The paragraph arguing 'run the suite before concluding a docs change has no code consumers' carried a number: 'CI 2592 ran 1617 tests, 1 failed, 1616 passed'. That number is wrong and is withdrawn in place rather than deleted. Extracting per-test totals from these pipeline logs is not a reliable method: the same regex over the same log format returns 1003 for 2592, 1022 for 2593 and 3471 for 2594, which are runs of the same suite. Three irreconcilable answers from one method is proof the method does not measure what it claims, so no corrected count is substituted. The claim is restated in what the log carries reliably, the named FAIL list and the turbo task line. The count was decoration on a claim already carried by a specific name: one named failing spec is what refuted three hand-searches.
32 KiB
kind, status
| kind | status |
|---|---|
| tracking | active |
W4 — document contract worklist
Companion to 2026-08-20_stack-docs-flatten-and-alignment.md. That document proposes the
contract; this one records what was applied, what was held, and what still needs a decision.
Measured on origin/next at 63069149. Author: veronica. Review: fred (Gate-16, author is
not reviewer), then a pi seat for the adversarial pass.
What "live" means here
All *.md under docs/, minus docs/archive/, minus docs/_old_structure/. That is 127
files. The flatten plan says 130; the arithmetic does not close (318 total = 134 archive +
57 _old_structure + 127 live, not 130).
Applied
| bucket | count | note |
|---|---|---|
stamped kind + status |
107 | this pass |
| held, operator judgement | 17 | section "Needs a decision" below |
| held, cites the moving path | 3 | the three SUPERSEDED TASKS.md stamps |
| held, generated file | 1 | docs/fleet/NORTH_STAR.md, see below |
128 live .md under docs/, which is the 127 baseline plus this document. 107 + 17 + 3 + 1 = 128.
Kinds: 53 guide, 34 record, 13 spec, 7 tracking. Status: 105 active, 2 completed.
parent is not applied. It points at docs/fleet/NORTH_STAR.yaml, which the flatten moves
to docs/NORTH_STAR.yaml. Stamping it now means re-pointing 127 files by hand later. It lands
after the move, in one pass, with the post-move path.
Held: the three superseded stamps
docs/TASKS.md:5, docs/federation/TASKS.md:5, and docs/fleet/TASKS.md:5 each carry a W1
stamp of the form:
STATUS: SUPERSEDED — 2026-08-20. kind
tracking· superseded bydocs/fleet/NORTH_STAR.yaml
Two problems, both real:
- The tooling cannot read them. That line is a blockquote below the H1, not YAML front
matter. Plan section 6 check 5 ("every live document has a header; no document is
unclassified") parses front matter, so all three read as unclassified. The control that the
parse itself works is
docs/fleet/FLEET-DOCTRINE.md:3, which is genuine front matter. - They cite the moving path. Three of the six citations of
docs/fleet/NORTH_STAR.yamlare these stamps. Converting them before the flatten lands makes them stale on merge.
Converted after the flatten, not before.
Held: the one generated file
docs/fleet/NORTH_STAR.md is a projection and was stamped in the first pass. The stamp was
reverted before review, because stamping it is self-contradictory in a way that is not
merely theoretical:
- The contract says a
projectionis "Generated. Never hand-edited." Adding front matter by hand is a hand edit of a generated file, and the file's own banner says "Generated file — do not edit by hand." renderNorthStarMarkdown()atpackages/mosaic/src/commands/fleet.ts:373emits the H1 as its first line and no front matter at all.fleet-north-star.spec.ts:110-114asserts full-string equality between the renderer's output and the committed file:expect(rendered).toBe(committed). Before the stamp, line 1 of the committed file was# Mosaic Fleet — NORTH STAR, matching the renderer. After it, line 1 was---. The assertion fails.
So the header for a projection cannot live in the file. It has to be emitted by
renderNorthStarMarkdown(), which is a code change and belongs in the flatten PR alongside the
resolveNorthStarPaths() fix, not in a documentation pass.
This generalises: the contract as written cannot classify any generated document without a
matching change to its generator. NORTH_STAR.md is the only projection today, so the cost
is one function. It will not stay one.
Needs a decision
Nineteen rows. Seventeen are the plan's section 9 list, minus docs/fleet/north-star.md
(renamed to FLEET-DOCTRINE.md by W1, so the row is closed) and minus the two .yaml rows,
which are a different problem — see the next section. Two rows are new, found while
classifying.
Fill the kind column with a value from the contract, or superseded-by: <path>.
| path | proposed | why it is not mechanical |
|---|---|---|
docs/README.md |
guide |
It also prescribes the competing front-matter convention (see below). Whatever kind it gets, its body needs an edit. |
docs/SITEMAP.md |
guide or projection |
If it is generated from the tree it is a projection and needs a drift test. If hand-maintained it is a guide that goes stale silently. Nobody has said which. |
docs/federation/SETUP.md |
guide |
Reads as a guide. Federation tier status is the open part: if the tier is shelved this is superseded. |
docs/fleet/FLEET-CONFIG-DOCS-IA-CHECKLIST.md |
record |
An acceptance checklist is evidence of a past gate, which is record. But if it is still being checked against, it is tracking. |
docs/fleet/FLEET-LAUNCH.md |
guide |
Runbook. Depends on whether launch-seat.sh is deprecated in favour of mosaic fleet (campaign W3). If so, superseded. |
docs/fleet/LEGACY-EXAMPLE-PROFILE-DISPOSITION-INVENTORY.md |
record |
An inventory of dispositions taken. record unless dispositions are still pending, which the title implies they were once. |
docs/fleet/README.md |
guide |
Section index. Low risk; listed only because the plan lists it. |
docs/fleet/backlog-conventions.md |
guide |
Conventions decide things, and guide explicitly decides nothing. May be spec. |
docs/fleet/f4-matrix-connector.md |
spec |
F4 is a workstream. Whether it is live or abandoned decides spec versus superseded. |
docs/native-kanban-sot/DOCUMENTATION-CHECKLIST.md |
record |
Same question as the fleet IA checklist. |
docs/native-kanban-sot/INDEX.md |
guide |
Index of the canon. If it is generated from the canon it is a projection. |
docs/native-kanban-sot/KBN-010-THREAT-AUTH-CONSTRAINT-GATE.md |
spec |
415 lines of normative gate. spec fits; confirm it is not superseded by the shared contract. |
docs/native-kanban-sot/KBN-101-DB-ROLE-SPLIT.md |
spec |
As above. |
docs/native-kanban-sot/KBN-101-ENVELOPE-A.md |
spec |
Title says "v6, FINAL". If v6 supersedes v1-v5 elsewhere, those need superseded-by pointing here. |
docs/native-kanban-sot/SHARED-CONTRACT.md |
spec |
"Remediated Shared Contract v1". Same versioning question. |
docs/release-integrity/probe-inventory.md |
record |
An inventory. tracking if probes are still being added to it. |
docs/webui/PHASE-P-STRUCTURE.md |
spec |
Zero inbound references (plan section 5.4). Either wire it in or mark it superseded; the kind is the smaller question. |
docs/native-kanban-sot/TASKS.md |
conflict | The file says of itself: "This file is a build plan, not a task tracker, and is NOT superseded." The contract says tracking is "live state, single-writer (manifests, TASKS.md). Never a spec." The file claims to be the thing its name forbids. Either the file is wrong or the contract's TASKS.md shorthand is. |
docs/requirements/native-kanban-sot.md |
conflict | Plan section 5.2 says if it is hand-authored canon it is source-of-truth. The contract's own table says source-of-truth is machine-readable. This is prose markdown with normative MUST/MUST NOT, RATIFIED 2026-07-14, decision owner Jason. It cannot satisfy both rules. Either it is a spec or the machine-readable criterion is wrong. |
The last two are not slow rows, they are contradictions inside the contract. They want an answer about the contract, not about the file.
The contract collides with an existing one
docs/README.md lines 150-160 already document a front-matter convention, with its own
allowed values:
---
title: Human-readable page title
type: guide # guide | concept | reference | decision | rfc | runbook
audience: developer # user | admin | developer | all
status: current # current | draft | deprecated | historical
source_of_truth: false
---
Adoption is 4 of 127 files: docs/ADMIN-GUIDE/security/sso-providers.md,
docs/DEVELOPER-GUIDE/testing/lease-broker-operations.md,
docs/USER-GUIDE/getting-started/quickstart.md, docs/USER-GUIDE/product/web-dashboard.md.
status is in both schemas with disjoint vocabularies. type and kind are two names for
one idea with different value sets. source_of_truth: false is a boolean spelling of
kind: source-of-truth.
What this pass did, and it is a decision someone should ratify or reverse: the new contract
wins. Those 4 files had status: current rewritten to status: active and gained kind:.
Their title, type, audience and source_of_truth keys were left alone. Nothing reads any
of them — git grep source_of_truth outside docs/ returns zero hits — so no consumer broke.
docs/README.md still prescribes the old convention. It is an operator row above, so this pass
did not edit it. Until it is edited, the repository documents two conflicting header
conventions and points authors at the one being retired.
The contract has no form for a YAML document
Two of the plan's 20 rows are not markdown: docs/fleet/examples/roster-v2.yaml and
docs/openapi-tess.yaml. Front matter is a markdown convention. A .yaml file can carry a
leading --- document, but then it is two YAML documents and every existing parser of that
file sees a change.
This is not an edge case. It applies to docs/fleet/NORTH_STAR.yaml, the source of truth
itself, which is the one file the contract most needs to classify. Section 6 check 5 says no
document is unclassified. As written, the source of truth cannot comply.
Options, none of them chosen here: exclude .yaml from the contract and say so; carry their
metadata in a sidecar; or add a top-level kind: key inside the YAML body rather than as front
matter, which for NORTH_STAR.yaml is a schema change.
Method, and what it cannot tell you
Classification is per-file, by title and path, recorded with a confidence. It is not a regex sweep. The plan's own warning stands and is why the 19 rows above are held rather than guessed: the first classifier pass classed a RATIFIED requirements document as a projection.
Rows marked med in the working manifest and not listed above: the five docs/plans/* specs,
docs/fleet/migration/example-profile-disposition.md, the one ADR
(decisions/mos-runtime-portability-m1.md, called record because an ADR records a decision
taken), and the one RFC (rfcs/optional-ai-egress-gateways.md, called spec because it
proposes work not yet built). Those eight are stamped and are the most likely to be wrong.
Verification
- 103 of 103 files parse with the expected
kindandstatusin front matter. - The check was shown to reject a wrong kind before it was trusted (asserting
kind: recordon a file stampedguidefails). - The whole diff removes 4 lines, all of them
status: current. - 24 files untouched, matching 19 + 3 + 1 + 1.
Response to the W5 adversarial pass
vision ran a refute-first pass on this branch at 37cd00e from a fresh worktree. Three of its
points changed the branch. Everything is re-measured here before being acted on; where my
measurement disagrees with its stated evidence I say so.
1. docs/fleet/NORTH_STAR.md stamp reverted (bea47543)
vision raised this as latent and scoped to the flatten PR. It is live in this PR, so it could not wait.
fleet-north-star.spec.ts:110-114 is a drift test that reads the committed file from disk and
asserts full-string equality against renderNorthStarMarkdown(), whose first emitted line is the
H1 and which emits no front matter. Stamping changed line 1 from the H1 to ---.
CI 2589 confirms it directly, no longer by construction:
× renderNorthStarMarkdown > matches the committed NORTH_STAR.md projection (regenerate if this fails)
→ expected '# Mosaic Fleet — NORTH STAR\n\n> **Ge…' to be '---\nkind: projection\nstatus: active…'
Reverted to origin/next verbatim. git diff origin/next -- docs/fleet/NORTH_STAR.md is 0 lines;
control on docs/fleet/reference/cli.md returns 13, so the diff command does report differences.
The consequence is a contract-level one, recorded in the worklist: the contract as written
cannot classify any generated document without a matching change to its generator. A projection
is "Generated. Never hand-edited," so its header has to come out of the renderer. That is a code
change and belongs in the flatten PR beside the resolveNorthStarPaths() fix. vision's
recommendation, and I agree with it.
Counts: stamped 104 → 103. Untouched 23 → 24.
2. The docs/ qualifier (vision's C1)
Stated as asked. "127 live documentation files" is true for docs/ only. Definition: all
*.md under docs/, minus docs/archive/ and docs/_old_structure/. 318 total = 134 archive +
57 _old_structure + 127 live.
Repo-wide the phrase undercounts: 21 live markdown files sit outside docs/ and outside any named
exclusion (17 under guides/, plus README.md, AGENTS.md, CLAUDE.md, REPORT-A1207.md at
root). This PR does not stamp them and does not claim to.
3. format failure, and what it says about the header (8a55c041)
CI 2589 also failed prettier --check on exactly one file: the plan document I hand-wrote.
Reproduced locally, rc=1, same single file. Fixed; the diff is 31 lines in, 31 out, all table
column padding.
Worth stating for the review rather than burying: the other 103 stamped documents pass
prettier --check unchanged. The ---\nkind:\nstatus:\n--- block is prettier-clean as applied.
The formatting failure was in my prose, not in the contract header.
4. R1: the evidence inverts, the finding gets stronger
vision asks for a kind change on docs/DEVELOPER-GUIDE/architecture/channel-protocol.md, on the
grounds that it "carries 7 normative MUSTs" while the contract says guide "decides nothing."
The MUST count does not hold. Uppercase RFC2119 terms (MUST, MUST NOT, SHOULD,
SHOULD NOT, SHALL, MAY, REQUIRED) in that file: 0 lines. Control: the identical grep
returns 25 lines in docs/requirements/native-kanban-sot.md, so it finds them where they exist.
The seven lowercase "must" occurrences all disclaim authority rather than assert it: "must not be
used as instructions", "must not be treated as current behavior", "must remain planned work", "must
first specify", "before it can become architecture guidance." The file's own banner reads "it is
not a runtime registry, an API contract, a requirements document."
The citation half holds, and is larger than stated. vision's line numbers are exact. I restated them earlier with wrong directories, which is worth naming because it is the same method failure fred and I already wrote up as C3 in the flatten plan: I matched on basename and assumed the path. The real ones, plus the two vision did not list:
| citing document | line | words used |
|---|---|---|
docs/ADMIN-GUIDE/security/discord-ingress.md |
141 | "canonical shared-contract and parity boundary" |
docs/DEVELOPER-GUIDE/integrations/channel-adapters.md |
28 | "The canonical architecture summary is" |
docs/DEVELOPER-GUIDE/integrations/channel-adapters.md |
183 | "Canonical channel protocol architecture" |
docs/USER-GUIDE/workflows/discord-conversations.md |
127 | "current shared types ... explicit parity boundary" |
docs/SITEMAP.md |
54 | index entry |
docs/DEVELOPER-GUIDE/architecture/README.md |
18 | index entry |
So the tension is real. Three live documents outside the two indexes cite it, across four
citations, and three of those four use the word "canonical" for a document that spends its own
banner denying it is canonical. It is just not a MUST problem, and that
changes what the fix is. If the file is telling the truth about itself, the three "canonical"
citations are wrong and the edit belongs in those three files, not in this one's kind.
Left as kind: guide in this PR and flagged for the reviewer's call. Restamping on evidence
that inverts on reading would be worse than leaving it stamped and named.
Unchanged
vision's C2 (no consumer), C4 (holding parent blocks nothing) and C5 (a front-mattered .yaml
throws in YAML.parse) all reverified. C1's arithmetic closes at the stated ref.
fred's six decisions, applied
Ruled on PR #1350 as comment 23693. Each is applied here; each is his call, not mine, and any of them is one line to reverse.
| # | decision | applied as |
|---|---|---|
| A | New contract wins; docs/README.md is rewritten in this PR and the 4 old-schema files convert in the same pass |
docs/README.md:149-190 rewritten; type: dropped from the 4 files, title/audience/source_of_truth kept |
| B | source-of-truth leaves the kind enum and returns as an orthogonal boolean |
enum is now 6 values; docs/requirements/native-kanban-sot.md stamped kind: spec + source_of_truth: true |
| C | status gains a third value, completed |
the two executed plans take it (evidence below) |
| D | Kind follows content, never filename | docs/native-kanban-sot/TASKS.md stamped kind: spec, because its body says "a build plan, not a task tracker" |
| E | The contract covers .md only, stated as a decision rather than left as a gap |
written into docs/README.md with vision's YAML.parse measurement as the reason |
| F | channel-protocol.md becomes spec |
applied, with one correction and one consequence below |
C: evidence the two plans are complete
Neither plan self-declares completion, so this is measured from the artifacts rather than taken from the documents:
2026-08-10-ci-queue-purpose-implementation.md— the shipped guard carries the flag the plan specifies:ci-queue-wait.sh --purpose push|merge, exercised in this session at rc=0.2026-08-10-docs-structure-readme.md— every section the plan specifies exists indocs/README.mdtoday, including the Obsidian conventions and the source-of-truth precedence block. This PR is editing the artifact that plan produced.
F: the MUST count does not hold, and the fix changes shape
Applied as ruled. But the ruling's stated grounds are half wrong, and the half that survives points somewhere else, so this is the one to look at again.
Zero uppercase RFC2119 terms in channel-protocol.md, not seven. Control: the identical grep
returns 25 lines in docs/requirements/native-kanban-sot.md. The seven lowercase "must"
occurrences all disclaim authority: "must not be used as instructions", "must not be treated as
current behavior", "must remain planned work".
The citation half holds and is bigger than stated (table in the section above).
The consequence of applying F: the file is now stamped spec while its own banner says "it is
not a runtime registry, an API contract, a requirements document." Header and body now contradict
each other, which is the defect this pass exists to remove. Either the banner is edited in this PR,
or the three documents calling it canonical are the ones that are wrong. That is a content call and
it is left to the reviewer rather than folded into a stamping pass.
Q1 — the one question this pass cannot answer for itself
docs/README.md now prescribes the document contract, and it is the only live document under
docs/ with no kind. It is still on the operator-held list, so it is left unstamped.
By decision B it is arguably kind: spec with source_of_truth: true for the subject "document
contract". The reason this is not applied unilaterally: it decides which document outranks the
other when docs/README.md and docs/plans/2026-08-20_stack-docs-flatten-and-alignment.md disagree
about the contract, and they already differ (the plan's enum has 7 values, the README's now has 6).
That is an authority question, not a classification one.
The old schema DID have a consumer, and CI found it
vision's C2 concluded "no consumer found" after searching by parsing primitive rather than by key name. fred's decision A rested on "no installed base to protect." I accepted both. All three of us were wrong, and the full test suite is what proved it.
packages/mosaic/src/installation-documentation.spec.ts:39 asserted:
expect(markdown).toMatch(/^---\n[\s\S]*?\nstatus: current\n[\s\S]*?\n---\n/);
That is a raw regex over the markdown text, not a front-matter parse and not a key lookup, which is
exactly why a search organised around parsing primitives could not see it. It pins
docs/USER-GUIDE/getting-started/quickstart.md to the old vocabulary. Replacing status: current
with status: active turned it red.
Updated to status: active, the contract's value for "in force", with the reason in a comment
beside it. Verified by evaluating both regexes against the real file: old false, new true.
Control: a page carrying superseded-by still fails the new regex, so the assertion still asserts
something rather than matching anything with front matter.
The method point, which outlives this file. CI 2592 ran the whole suite against the stamped tree, 46 turbo tasks, and returned exactly one failing spec: this one. That is a stronger consumer search than any grep the three of us ran, because it does not depend on guessing how a consumer reads the file.
An earlier draft of this paragraph put a test count here, "1617 tests, 1 failed". That number was wrong and it is withdrawn. Extracting per-test totals from these pipeline logs is not reliable: the same regex over the same log format returns 1003 for 2592, 1022 for 2593 and 3471 for 2594, which are runs of the same suite. Three irreconcilable answers from one method is proof the method does not measure what it claims. What the log does carry reliably is the FAIL list and the turbo task line, so the claim is stated in those terms instead. The point never needed the count: one named failing spec is what refuted three hand-searches. Run the suite before concluding a documentation change has no code consumers. Two independent seats and a reviewer searching by hand missed the one that existed.
fred's second pass: F withdrawn, Q1 answered
Both changes below are fred's rulings, applied. Neither is my judgement and I record whose it is.
F is withdrawn: channel-protocol.md returns to kind: guide
Reverted. fred re-measured the file himself with a control and reached the count I reported: zero
uppercase RFC2119 terms case-sensitive, seven lowercase must, every one disclaiming authority,
under a banner that refuses requirements status. A page like that is a guide.
The reason this matters past one stamp is fred's own: F rested on "the doc graph outranks the page's own banner", which contradicts his decision D, "kind follows content, never the filename and never what other documents say about it". D is the rule. F was a counterexample to it, written in the same comment.
Neither rescue was taken. vision's adjective edit on the three citing docs and an edit to the page's banner would both have preserved a stamp that should not have been made. The three citing documents stay as they are: under vision's index-pointer reading, "canonical" claims the best page on a subject rather than normative force, so there is nothing to correct.
What this costs the contract: nothing, and that is the point. A kind that survives only by editing the evidence around it is not a classification.
Q1 answered: docs/README.md is stamped kind: spec, source_of_truth: true
Applied. By D, a document that prescribes the contract has spec content. By B, source_of_truth is
an orthogonal boolean and this is the authoritative statement of the contract, so it carries both.
The authority half of Q1 was whether stamping the README settles a conflict with the flatten plan, whose enum still has seven values against the README's six. fred's ruling: a plan never outranks the artifact it planned. The plan's enum is pre-decision-B staleness, not a competing authority. The plan is fred's file and he corrects it there.
The contract now applies to the document that states it. That was the only state in which it could be credible.
Verification arithmetic, re-closed
128 live .md under docs/ = 108 stamped + 16 operator-held + 3 supersede deferrals + 1
generated. The stamped count rose by one and the operator-held set fell by one, both because of the
README; every other row is unchanged. Control unchanged: the verifier reports valid=False when a
kind is corrupted to nonsense.
One consumer finding that is not a defect
A sweep of every spec reading a path under docs/ returns 10 files. Four read a live file:
fleet-north-star.spec.ts and installation-documentation.spec.ts (both already caught by CI),
mutator-gate.acceptance.spec.ts reading compaction-revocation.md, which passes under its guide
stamp, and roster-v2.spec.ts:366, which reads docs/fleet/reference/roster-v2.schema.json.
The fourth is a real read of a real live file under docs/ and is untouched only because decision E
scopes the contract to .md. Had the contract covered every file under docs/, front matter in
that JSON schema would have broken the spec, the same failure as the quickstart regex. E was
load-bearing beyond the YAML-parse grounds it was decided on. No action; recorded so the .md
boundary is not widened later without re-running this sweep.