ID |
|
|---|---|
Status |
Backlog |
Bucket |
Typed rejection chain |
Theme |
diagnostics |
Created |
2026-05-21 |
Updated |
2026-08-06 |
FieldRegistry classify-input trace loses typed Rejection payload
FieldRegistry.classifyInput at graphitron/src/main/java/no/sikt/graphitron/rewrite/FieldRegistry.java:108-110 emits the trace record for an InputFieldResolution.Unresolved outcome by defaulting to RejectionKind.AUTHOR_ERROR with u.reason() (a String), with the rationale comment "Unresolved carries no Rejection variant … default to AUTHOR_ERROR per the kind-of-thumb rule". This is the last place in the input-classification path where the typed-rejection chain breaks: the trace consumers (watch-mode formatter, LSP fix-its) lose the structured attempt + candidates payload they would otherwise consume on a column-miss Unresolved, and on non-column-miss Unresolved they get an AUTHOR_ERROR label that may not match the actual rejection kind. R205 closed the gap one layer up (InputFieldResolver.resolve now lifts to typed Rejection.unknownColumn / Rejection.structural); the corresponding lift inside FieldRegistry.classifyInput was flagged in the R205 self-review and deferred. Two design forks worth thinking through during Spec: (a) widen InputFieldResolution.Unresolved to carry a Rejection (touches every Unresolved construction site in the classifier; some sites lack catalog/candidates context to build unknownColumn), or (b) thread TableRef rt into FieldRegistry.classifyInput and lift to Rejection there. (a) keeps the lift co-located with classification; (b) keeps Unresolved transient by design. Either way the deliverable is removing the RejectionKind.AUTHOR_ERROR default arm and emitting RejectionKind.of(rejection) consistently with traceOutput at FieldRegistry.java:127-130.
Cross-reference (2026-07-15): fork (a) is verbatim R66’s Phase A2 (rejection-string-carrier-widening, item 2: widen InputFieldResolution.Unresolved.reason: String to rejection: Rejection). If R66 A2 ships first this item collapses to the consumer-side update (remove the default arm, emit RejectionKind.of(rejection)); if this item ships first it carries A2’s record change. R213 (input-field-rejection-attribution) grows the same record a SourceLocation; co-design so the record widening happens once. Prefer fork (a) sequenced against R66 A2 over duplicating the record change here.
Fact-base note (2026-08-06)
Under the claim relations the trace this item types is replaced: FieldRegistry.classify’s same-coordinate conflict handling is the key constraint in embryonic form (R589’s words), and claim plus violation rows carry what the trace carries. Fork (b), threading `TableRef into classifyInput, is a dead end; the item collapses to the record widening or retires with the registry.
Context and the whole-board picture: roadmap/audits/2026-08-06-fact-base-impact-sweep.md.