authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-06-19 23:27:15-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-06-19 23:27:15-07:00
log2fbbe68c24892c4de9bd50450e7363376475ad7d
tree8df878ccac4226b4ea41cc5969cf592d931910d3
parent65385c028169da7e18d0f25124f0e3f6a1208567
signature Signed by PGP key B5690EEEBB952194

Clarify Effect error discriminator modeling (#3217)

Co-authored-by: codex <codex@users.noreply.github.com>

1 files changed, 1 insertions(+), 0 deletions(-)

.macroscope/check-run-agents/effect-service-conventions.md+1
...@@ -50,6 +50,7 @@ Review changed TypeScript and directly affected call sites for the conventions b...@@ -50,6 +50,7 @@ Review changed TypeScript and directly affected call sites for the conventions b
50- Capture stable, serializable domain context such as the operation or stage, resource/path or entity identifier, and normalized category/status. Map failures where that context is known instead of wrapping an entire multi-step pipeline in one generic error. Do not add a `detail` field that merely copies `cause.message` and then use it to construct the wrapper message.50- Capture stable, serializable domain context such as the operation or stage, resource/path or entity identifier, and normalized category/status. Map failures where that context is known instead of wrapping an entire multi-step pipeline in one generic error. Do not add a `detail` field that merely copies `cause.message` and then use it to construct the wrapper message.
51- When translating or wrapping a real failure, preserve the immediate underlying error itself as `cause` alongside the structural fields so the complete error chain and stack remain available. If every construction wraps a failure, `cause` should be required; make it optional only when the same error can legitimately originate without an underlying failure.51- When translating or wrapping a real failure, preserve the immediate underlying error itself as `cause` alongside the structural fields so the complete error chain and stack remain available. If every construction wraps a failure, `cause` should be required; make it optional only when the same error can legitimately originate without an underlying failure.
52- Derive the wrapper's `message` exclusively from its stable structural attributes, never from `cause`, `cause.message`, or a stringified defect. Do not replace the immediate error with only `error.cause`, erase a structured upstream error into a string, or manufacture an `Error` merely to populate `cause`. Pure validation/domain errors created without an underlying failure do not need a cause.52- Derive the wrapper's `message` exclusively from its stable structural attributes, never from `cause`, `cause.message`, or a stringified defect. Do not replace the immediate error with only `error.cause`, erase a structured upstream error into a string, or manufacture an `Error` merely to populate `cause`. Pure validation/domain errors created without an underlying failure do not need a cause.
53- Do not encode the same distinction twice with both a specific error tag and a single-value `operation`, `reason`, `kind`, or `phase` literal. Choose one coherent model: use distinct error classes and omit the redundant discriminator when callers or messages treat the failures as genuinely different, or use one service-level error with a multi-value operation discriminator and a generic message derived from that operation when the failures share the same semantics.
53- Split semantically distinct failures into separate error classes when a `reason`, `kind`, `phase`, or similar discriminator is used to choose the user-facing message or drive caller control flow. A discriminator used only for internal diagnostics may remain a field.54- Split semantically distinct failures into separate error classes when a `reason`, `kind`, `phase`, or similar discriminator is used to choose the user-facing message or drive caller control flow. A discriminator used only for internal diagnostics may remain a field.
54- Use `Schema.Union` of error classes when a shared schema, predicate, or helper type is useful.55- Use `Schema.Union` of error classes when a shared schema, predicate, or helper type is useful.
55- Export direct schema predicates such as `export const isFoo = Schema.is(Foo)`. Flag a private `Schema.is` constant wrapped by a redundant function with the same signature.56- Export direct schema predicates such as `export const isFoo = Schema.is(Foo)`. Flag a private `Schema.is` constant wrapped by a redundant function with the same signature.