fix: one Status column, not two names for the same thing - #87
Merged
kreneskyp merged 1 commit intoSep 12, 2026
Merged
Conversation
The TestMatrix contract declared `Coverage Status` on four tables and
`Status` on three, with byte-identical vocabularies:
Coverage Status: '^(✅|❌|🚧|⛔)(\s+.*)?$'
Status: '^(✅|❌|🚧|⛔)(\s+.*)?$'
and used them inconsistently across sibling tables of the same kind —
Functional Requirement Coverage took `Coverage Status`, Non-Functional
Requirement Coverage took `Status`. No distinction was being preserved. They
were two names for one thing.
The consequence was not cosmetic. `traceability.status.column` is a single
global selector reading `Status`, so on the four `Coverage Status` tables
quire reported `status-column-matches-nothing` and skipped status
classification entirely. `status_lies` then came back empty because nothing
ran, not because the rows were honest, and every consumer treating that
emptiness as a pass was certifying an unmeasured property.
This has been broken since the beginning. `Coverage Status` entered the shape
contract on 2026-08-04 (721baa0); the single global selector was added the
next day (9145ebb), whose own comment says it exists "so a contract and its
coverage computation cannot drift". It read one name from a contract that
already declared two.
Collapsing to one name is the root repair. The alternative under review
elsewhere — a per-declaration `status_column` override (quire-rs#410) — makes
the duplicate naming permanent and supported, and requires an engine release
nobody has shipped. This needs neither: the suite passes on the released
quire 0.32.0, whose engine has no `status_column` support.
Consumers renaming their own matrix headers is the intended breaking change;
modules are sha-pinned per machine, so nothing breaks until a consumer picks
this up. `reports/2026-08-04-tests-md-sweep.json` keeps the old name — it is a
record of a past sweep, not a live contract.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J4qKWaqT3xCXMbbtDqdDRY
This was referenced Sep 12, 2026
Closed
kreneskyp
added a commit
to agent-ix/spec-artifacts-iso
that referenced
this pull request
Sep 12, 2026
The TestMatrix contract collapsed `Coverage Status` and `Status` into a single `Status` column (agent-ix/spec-artifacts-process#87, 375fc2a). The two names carried byte-identical vocabularies and were applied inconsistently across sibling coverage tables, so the single global `traceability.status.column` selector matched only some of them and status classification was silently skipped on the rest — after which `status_lies` was empty because nothing ran, not because the rows were honest. This module's own matrix still used the old header, so its Functional Requirement Coverage table was one of the tables never classified. One line. Verified the pre-existing failure set is unchanged: 23 failed / 232 passed with and without this change, byte-identical lists. Claude-Session: https://claude.ai/code/session_01J4qKWaqT3xCXMbbtDqdDRY Co-authored-by: Agent IX <agent@agent-ix.dev> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kreneskyp
added a commit
that referenced
this pull request
Sep 12, 2026
Ports 375fc2a from the epic/264-assurance-integration cohort to main. The TestMatrix contract declared `Coverage Status` on four tables and `Status` on three, with byte-identical vocabularies, and used them inconsistently across sibling tables of the same kind — Functional Requirement Coverage took one, Non-Functional Requirement Coverage the other. No distinction was being preserved. The consequence was not cosmetic. `traceability.status.column` is a single global selector reading `Status`, so on the four `Coverage Status` tables quire reported `status-column-matches-nothing` and skipped status classification entirely. `status_lies` then came back empty because nothing ran, not because the rows were honest, and every consumer treating that emptiness as a pass was certifying an unmeasured property. Broken since the beginning: `Coverage Status` entered the shape contract on 2026-08-04 (721baa0); the single global selector was added the next day (9145ebb), whose own comment says it exists "so a contract and its coverage computation cannot drift". main carries surfaces the cohort does not, so the port reaches further than the original commit: `mappings.yaml`, the `TestMatrix`/`TestMatrixIndex` skeletons, `FunctionalCoverageRow.json`, the TypeSpec source, the negative fixtures, and the frozen `baseline-0.1.0` fixture. The two golden records pin a digest of their skeleton, so both digests are recomputed. Renaming a declared column is not additive, so this is a deliberate exception to NFR-001-AC-1's 0.1.0 baseline guarantee: the 0.1.0 baseline fixture is renamed with the contract rather than the guard being weakened, so it keeps comparing like with like and still catches every other drift. Verified: the failure set is byte-identical to main's — 8 failed, 246 passed, 42 errors before and after, all pre-existing. Closes #88 Claude-Session: https://claude.ai/code/session_01J4qKWaqT3xCXMbbtDqdDRY Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
The TestMatrix contract declared two column names with byte-identical vocabularies:
and used them inconsistently across sibling tables of the same kind:
Coverage StatusStatusTwo coverage tables, same purpose, different names. No distinction was being preserved.
Why it mattered
traceability.status.columnis a single global selector readingStatus. On the fourCoverage Statustables quire reportedstatus-column-matches-nothingand skipped status classification entirely.status_liesthen came back empty because nothing ran — not because the rows were honest. Every consumer reading that emptiness as a pass was certifying an unmeasured property.Engineering Assurance's release gate was doing exactly that.
Broken from the start
The selector landed the day after the contract that already declared two names. Its own comment says it exists "so a contract and its coverage computation cannot drift". It read one name from a two-named contract and has silently skipped four tables ever since.
Why the root fix, not the override
There is a per-declaration
status_columnoverride (quire-rs#410) with four PRs open against it — spec-artifacts-process #85/#77, spec-artifacts-iso #37/#33. It makes the duplicate naming permanent and supported, and it requires an engine release nobody has shipped: published quire 0.32.0's changelog claims to carry it but the tag pins an engine that predates it.This change needs none of that. The suite passes on released quire 0.32.0, whose engine has no
status_columnsupport:Those four PRs should be closed rather than landed.
Scope
manifest.yaml— 5 occurrences across 4 table contracts and one column patternspec/,tests/fixtures/,tests/test_manifest.py— 36 files, 51 linesreports/2026-08-04-tests-md-sweep.jsonkeeps the old name — it is a record of a past sweep, not a live contractConsumers renaming their own matrix headers is the intended breaking change. 116 repos carry
| Coverage Status |inspec/tests.md; modules are sha-pinned per machine, so nothing breaks until a consumer picks this up.make test92 passed,make lintclean.🤖 Generated with Claude Code
https://claude.ai/code/session_01J4qKWaqT3xCXMbbtDqdDRY