Skip to content

WP 1.3 · validator-spec-sheet — settle the ten §4 grammar gaps before #26, #28, #29 build #97

Description

Work package: WP 1.3 correction (WP 5.1 follow-up) · Phase: 5.0 · Traces: FR-8, FR-12, FR-18, NFR-3, NFR-6, R-2, AC-9.2, AC-9.4, AC-12.3, AC-13.1, US-12, US-13 · Precedes: #26 (quotation-symmetry), #28 (revision-row-immutability), #29 (tooling-shell-lint) · Related: #96 (the same class, for #25), #30 (role bindings), #27 (render-fidelity) · Owner document: docs/validator-spec-sheet.md §4

Problem statement

Two WP 5.1 checks have now shipped carrying a defect of one shape: §4 specifies an input envelope and a verdict table, but not the grammar the verdict ranges over, so the implementer invents one and the frozen fixture pack pins the invention.

Both were found after the code and its frozen fixtures existed, which is the expensive moment. #96 was then found by reading §4 against the seed before #25 built anything — the same class, a fraction of the cost.

This issue is the result of applying that same read to every remaining unbuilt check: #26, #27, #28, #29. It records ten findings. Nothing here is discovered by running code; all of it is settled by deciding.

Findings

revision-row-immutability (#28)

F1 — No row-correspondence rule. (Highest severity: this is the #91 hole verbatim, on the check's central condition.)

fail reads "Any byte of an existing row changed." Deciding which head row is a given base row requires a pairing rule, and §4 states none. The two available readings disagree on the case the check exists for:

Pairing A single row inserted mid-table
By index Every row below it re-indexes → reads as mass modification → fail
By key (e.g. the Version cell) Reads as an append landing out of order → warn

Both are defensible. An implementer must choose, and the fixture pack will pin the choice.

F2 — No version-ordering rule.

warn requires "a version that sorts below its predecessor." Nothing in the repository orders versions, and the one landed precedent runs the other way: scripts/validators/loose-pointer-drift.js compares by exact string equality after stripping one leading v and deliberately never orders. So v1.10 against v1.9 resolves however the implementer guesses — semver or lexical, with opposite results.

F3 — The table shape reaches a governed project through no channel.

options.table_heading defaults to "Appendix — Revision Record", and the warn condition needs a Version column and a Date column. That shape is stated only in CONTRIBUTING.md"columns | Version | Date | Change |" — which is this repository's contributor documentation and is not shipped to anyone who installs the plugin. skills/cadence-method/scaffold/ contains constitution.md, directives.md, gate-tiers.json, manifest.json, and registrations.md, and no governed-document template; references/gate-checks.md states the append-only rule with no table shape. The check's defaults therefore encode a convention consumers are never told.

F4 — #28's body over-claims relative to the sheet.

The issue requires failing on rows "modified, deleted, or reordered"; §4's fail covers only a byte change to an existing row. Deletion and reordering cannot be detected at all without F1's identity rule. Whichever way F1 resolves, the two texts must be reconciled.

quotation-symmetry (#26)

F5 — It re-implements a landed, fixture-pinned check, which §2 forbids in terms.

Its fail includes "a quotation whose evidence class names a date that the tag does not carry." Landed evidence-tag-grammar (#20) already fails "a class whose required date or parameter is missing or malformed", reading the same seeded references.evidence_classes. §2 states: "Nothing else in the repository re-implements a shipped check: a second, unfixtured implementation is exactly the divergence R-2 names."

This needs a scoping decision, not deletion by default: the section heading claims "pairing, attribution, and dating only", so quotation-scoped dating may be deliberate — but then the overlap with evidence-tag-grammar's broader claim scan must be recorded as deliberate rather than left to collide.

F6 — "Attribution" is defined nowhere in the repository.

fail fires on "a quotation with no attribution"; warn on "an attribution that names a source the artifact does not otherwise cite", which additionally needs a citation grammar and a name-matching rule. A repository-wide search finds the word only in prose about what a green gate proves (method §9, AC-9.4, SKILL.md, this sheet's own §8). No syntax, no position rule, no worked example. This is the purest instance of the #78/#91 class in the sweep.

F7 — A verdict depends on an input the section gives it no way to fail on.

Deciding "a date wherever its evidence class requires one" requires the seeded evidence-class reference, and §2 says a missing required key produces a skip. evidence-tag-grammar carries skipped: unavailable for exactly that condition. quotation-symmetry's table has four verdict rows and no unavailable, so a missing or unparseable reference has no legal verdict. Resolving F5 resolves this; if the dating clause stays, the fifth row is required (and §3's matrix cell moves from 4 rows to 5).

render-fidelity (#27)

F8 — skipped: not-applicable fires on a declaration mechanism that does not exist.

The condition is "The artifact declares no derived render" — the switch deciding whether the check runs at all. No declaration mechanism is defined anywhere: outside this sheet, the only mention of a derived render is AC-9.2's parenthetical. Meanwhile the input shape receives options.render_path from the caller, leaving it ambiguous whether the artifact declares anything at all.

The manifest row is the natural home, so this should be folded into #96's schema decision rather than decided twice.

F9 — The producer comparison is undefined, and the normalization deletes its input.

warn fires when "the committed render's recorded producer differs from the version preflight resolved." text-extract-v1 explicitly drops producer metadata, so the producer must be read on a separate path the sheet does not describe; and "differs" is undefined between a PDF Producer string and a preflight record of shape {binary, version}. Low severity — it only separates warn from pass — but it is a verdict resting on an unstated comparison.

tooling-shell-lint (#29)

F10a — A direct internal contradiction, already propagated into the issue.

The section's opening states the severity-to-verdict mapping is "pinned in the adapter, not inherited from the tool, so a tool upgrade cannot change a verdict without a recorded change (R-2)." The input shape places it in options.severity_map, caller-supplied — where any caller may flip "warning": "fail" to "warn" and change a verdict with no recorded change, which is exactly what the R-2 rationale claims is prevented.

#29 carries both readings in one body: its acceptance criteria say "pinned in options.severity_map", while its own correction note says "pinned in the adapter." One of the two is wrong and the issue cannot be built until it is settled.

F10b — The diagnostic vocabulary is implicitly bound to a tool the sheet declines to name.

The default map's keys — error | warning | info | style — are one specific linter's severity names, in a §5 that binds shell-lint as a role precisely so no binary enters by the side door. The normalized diagnostic shape the adapter hands the validator (path, line, code, severity) is undefined, so #30 and #29 have no contract between them.

What the sweep found clean

Recorded so a later reader knows these were checked rather than skipped:

Why this is a decision rather than an implementer's judgment

Every finding above sits on a verdict condition. An implementer handed any one of them must invent a rule, and the frozen fixture pack shipped alongside then pins the invention as though it were specified — which is precisely how #78 and #91 became expensive. F1 is the sharpest case: the two readings disagree on a mid-table insertion, which is the realistic FR-12 violation, so the check would be pinned to a behaviour nobody chose on the case it exists for.

None of the five is built yet. The whole set can be settled for the cost of reading and deciding.

Requested change

Amend docs/validator-spec-sheet.md §4 so that each finding above is answered in terms a second implementer could reproduce without reading a script, and reconcile #26, #28, and #29 with the result. Specifically:

  1. State the revision-row correspondence rule (F1) — index-paired or key-paired, with the key named if key-paired — and state the expected verdict for a mid-table insertion.
  2. State the version-ordering rule (F2), or rewrite the warn condition to need no ordering. If ordering is adopted, say explicitly how it relates to loose-pointer-drift's equality-only comparison, so two checks do not treat version tokens incompatibly.
  3. Give the revision-table shape a home a governed project actually receives (F3) — a scaffold template, a runtime reference, or an explicit statement that the shape is supplied per project through options and the defaults are this repository's own.
  4. Reconcile WP 5.1 · revision-row-immutability — Revision-row immutability validator #28's "modified, deleted, or reordered" with §4's fail (F4).
  5. Settle the quotation-symmetry / evidence-tag-grammar boundary (F5) — drop the evidence-class dating clause, or keep it scoped to quotations and record the overlap as deliberate.
  6. Define an attribution (F6) — its syntax, its position relative to the quotation it attributes, and the rule matching it against the artifact's other citations for the warn.
  7. Add quotation-symmetry's skipped: unavailable row if the dating clause is kept (F7), and update §3's matrix cell.
  8. Fold the derived-render declaration into WP 5.1 follow-up · Define the manifest document-row schema and artifact identity before #25 builds manifest-registry-consistency #96 (F8), so the manifest row schema decides it once; reflect the outcome in render-fidelity's skipped: not-applicable condition.
  9. State how the render producer is read and compared (F9), given that the normalization drops it.
  10. Resolve where the shell-lint severity map is pinned (F10a) — adapter or caller option — and update WP 5.1 · tooling-shell-lint — Tooling shell-lint validator #29's acceptance criteria and correction note to agree; specify the normalized diagnostic shape the adapter hands the validator (F10b), which is the WP 5.1 · adapters — External-tool adapters, role bindings + version preflight #30WP 5.1 · tooling-shell-lint — Tooling shell-lint validator #29 interface.

Non-goals

Sequencing

Before #26, #28, and #29. After any of them, that check's decision has a fixture pack voting against changing it — the position #78 and #91 are in now. #27 is additionally blocked on #30 regardless, and its F8 travels with #96.

The three findings that block a build outright are F1, F5, and F10a; the rest can land in the same amendment without gating anything further.

Acceptance criteria

Constraints

  • docs/validator-spec-sheet.md is not a governed document — its preamble states it carries no metadata table and no revision record — so no Revision Record row is required for editing it. (Triage note, unchanged from WP 5.1 follow-up · Define the manifest document-row schema and artifact identity before #25 builds manifest-registry-consistency #96: WP 1.3 · validator-spec-sheet — define the loose-pointer grammar §4 never states #91's acceptance criteria ask for one on this same file; that criterion is inconsistent with the sheet's preamble and is worth correcting there.)
  • The method governs the sheet (D-4). docs/reference/source/ is read-only.
  • Introduce no identifier without defining it in the authority document in the same change (FR-10). This issue introduces none; an amendment that needs one must carry its definition.
  • Any decision must leave the six landed checks and their frozen fixture packs valid. F2 in particular touches a surface loose-pointer-drift already pinned.
  • No new external tool without an NFR-3 entry, a pinned version, and a preflight check, in one change (NFR-1, NFR-3). F10b specifies an interface shape only and binds nothing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    blockedBlocked / deferreddoc-gapA governed or specification document omits something a build needsphase:5.0WBS Phase 5.0release-1Release 1 scope

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions