There is one diagnostic currency. Extraction, contract generation, and graph validation all report in the one finding shape, and no surface introduces a parallel report shape of its own.
A finding's location lives in its own structured file and line fields, never baked into its message text, so a location is composed once by whoever renders it and is never rendered twice.
The command-line rendering is the path and line, the severity in brackets, the validator id, and the message, in that order and separated by the same one-line punctuation for every finding.
The location degrades by field rather than by placeholder: a file with a line renders both, a file without a line renders the path alone, and a finding carrying no file renders no location prefix at all.
The Design Review renders the same currency in its findings table under the same composition rule, and shows an em dash where a finding carries no file, because a table cell cannot be absent the way a prefix can.
Given a finding naming the validator {validatorId: "honesty/readiness-floor"} at severity {severity: "error"} carrying the message {message: "The stated rung is not earned."}
When the {renderer: "command-line"} renderer formats that finding once per location shape
Then the finding carrying the file {file: "specs/probe.sdp.md"} and the line {line: 7} renders {withLocation: "specs/probe.sdp.md:7 — [error] honesty/readiness-floor — The stated rung is not earned."}
Then the same finding carrying the file alone renders {fileOnly: "specs/probe.sdp.md — [error] honesty/readiness-floor — The stated rung is not earned."}
Then the same finding carrying neither renders {bare: "[error] honesty/readiness-floor — The stated rung is not earned."}
Given
a finding naming the validator {validatorId: "honesty/readiness-floor"} at severity {severity: "error"} carrying the message {message: "The stated rung is not earned."}
When
the {renderer: "command-line"} renderer formats that finding once per location shape
Then
the finding carrying the file {file: "specs/probe.sdp.md"} and the line {line: 7} renders {withLocation: "specs/probe.sdp.md:7 — [error] honesty/readiness-floor — The stated rung is not earned."}
the same finding carrying the file alone renders {fileOnly: "specs/probe.sdp.md — [error] honesty/readiness-floor — The stated rung is not earned."}
the same finding carrying neither renders {bare: "[error] honesty/readiness-floor — The stated rung is not earned."}
Given a finding naming the validator {validatorId: "honesty/readiness-floor"} at severity {severity: "error"} carrying the message {message: "The stated rung is not earned | its floor refused it."}
When the {renderer: "Design Review"} renderer formats that finding once per location shape
Then the findings row carrying the file {file: "specs/probe.sdp.md"} and the line {line: 7} renders {locationRow: "| error | `honesty/readiness-floor` | The stated rung is not earned \| its floor refused it. | `specs/probe.sdp.md:7` |"}
Then the same row carrying the file alone renders {fileOnlyRow: "| error | `honesty/readiness-floor` | The stated rung is not earned \| its floor refused it. | `specs/probe.sdp.md` |"}
Then the same row carrying neither renders {absentRow: "| error | `honesty/readiness-floor` | The stated rung is not earned \| its floor refused it. | — |"}
Given
a finding naming the validator {validatorId: "honesty/readiness-floor"} at severity {severity: "error"} carrying the message {message: "The stated rung is not earned | its floor refused it."}
When
the {renderer: "Design Review"} renderer formats that finding once per location shape
Then
the findings row carrying the file {file: "specs/probe.sdp.md"} and the line {line: 7} renders {locationRow: "| error | `honesty/readiness-floor` | The stated rung is not earned \| its floor refused it. | `specs/probe.sdp.md:7` |"}
the same row carrying the file alone renders {fileOnlyRow: "| error | `honesty/readiness-floor` | The stated rung is not earned \| its floor refused it. | `specs/probe.sdp.md` |"}
the same row carrying neither renders {absentRow: "| error | `honesty/readiness-floor` | The stated rung is not earned \| its floor refused it. | — |"}
Given a finding naming the validator {validatorId:string} at severity {severity:"warning"|"error"} carrying the message {message:string}
When the {renderer:"command-line"|"Design Review"} renderer formats that finding once per location shape
Then the finding carrying the file {file:string} and the line {line:number} renders {withLocation:string}
Then the same finding carrying the file alone renders {fileOnly:string}
Then the same finding carrying neither renders {bare:string}
Then the findings row carrying the file {file:string} and the line {line:number} renders {locationRow:string}
Then the same row carrying the file alone renders {fileOnlyRow:string}
Then the same row carrying neither renders {absentRow:string}
validate: <errors> errors · <warnings> warnings (conformance + honesty over the one graph), written once to standard output after all findings have been written to standard error.
a finding naming the validator {validatorId:string} at severity {severity:"warning"|"error"} carrying the message {message:string}
When
the {renderer:"command-line"|"Design Review"} renderer formats that finding once per location shape
Then
the finding carrying the file {file:string} and the line {line:number} renders {withLocation:string}
the same finding carrying the file alone renders {fileOnly:string}
the same finding carrying neither renders {bare:string}
the findings row carrying the file {file:string} and the line {line:number} renders {locationRow:string}
the same row carrying the file alone renders {fileOnlyRow:string}
the same row carrying neither renders {absentRow:string}
Composing needs the script.
Design view
Requirement drawing
Requirement drawing for spec:validation.diagnostic-renderingThe diagram as text
spec:validation.diagnostic-rendering: One diagnostic currency, its location composed from structured fields · declared Spec
spec:validation.diagnostic-rendering.composed-location: One finding, three location shapes, one composition rule · declared Spec
spec:validation.diagnostic-rendering.table-cell-location: The same three location shapes, rendered as table cells · declared Spec
spec:validation.two-check-families: Validation separates well-formedness from non-pretending · declared Spec
impl:protocol.diagnostic-rendering-cli: composes structured finding fields into the one command-line diagnostic form · anchored code · src/cli/output.ts:23
impl:protocol.diagnostic-rendering-design-review: renders structured finding locations in the Design Review table · anchored code · src/projections/design-review-context.ts:208
impl:protocol.validate-summary: prints validate's findings and its summary line · anchored code · src/cli/validate-view-command.ts:23
impl:protocol.validation-contracts: conformance/honesty family currency and finding shapes · anchored code · src/validate/contracts.ts:5
test:protocol.diagnostic-rendering.composed-location: the composed-location point verifies the one rendering rule and both degradations · anchored test binding · binding present · test/self-hosting-projections.test.ts:1277
test:protocol.diagnostic-rendering.table-cell-location: the table-cell point verifies the same composition rule on the Design Review's twin · anchored test binding · binding present · test/self-hosting-projections.test.ts:1292
impl:protocol.diagnostic-rendering-cli · composes structured finding fields into the one command-line diagnostic form · src/cli/output.ts:23 · role codec · component component:protocol.cli · layer edge · context protocol
impl:protocol.diagnostic-rendering-design-review · renders structured finding locations in the Design Review table · src/projections/design-review-context.ts:208 · role projection · component component:protocol.projections · layer edge · context protocol
impl:protocol.validate-summary · prints validate's findings and its summary line · src/cli/validate-view-command.ts:23 · role codec · component component:protocol.cli · layer edge · context protocol
impl:protocol.validation-contracts · conformance/honesty family currency and finding shapes · src/validate/contracts.ts:5 · role contract · component component:protocol.validate · layer domain · context protocol