refactor(#3469): one composition for the STATE.md write seam (#3501)

* docs(#3469): amend ADR-3408 section 8.3 — the pipeline has sanctioned exceptions

Section 8.3 read 'Every STATE.md write applies the pipeline.' That is false by
design for two commands, and acting on it would have inverted a shipped
feature.

Preservation makes curated frontmatter win over a re-derived body value.
state sync exists to do the opposite — #905's 'body annotation beats existing
frontmatter when both are present'; it re-derives frontmatter FROM the body.
REGENERATE_STATE is a factory reset that rebuilds STATE.md from scratch.
Applying the pipeline to either would re-lock exactly what the command was
invoked to replace.

This issue's own scope line, inherited from the epic, said to route the direct
writeStateMd callers through the pipeline. For cmdStateSync that would have
shipped silently, with every gate green, because no test asserts that sync
LETS the body win. Caught by reading the helper's docstring and then verifying
the claim against the code — a stale comment had already misdirected this epic
once.

Both commands are now named in a closed exception list and are permanent
ratchet entries.

Consequence recorded rather than left to bite Phase 4: the 'drive the ratchet
to 0 and delete the file' target in this ADR and in #3471 is wrong. Two
entries are permanent, so the correct end state is 2, and the honest report is
'0 removable bypasses, 2 sanctioned'. A guard reaching 0 here would only do so
by having stopped looking at two real writers.

* refactor(#3469): one composition for the write seam, not one per caller

Implements ADR-3408 section 8.3 as amended.

syncAndPreserveStateMd is now the single composition of syncStateFrontmatter
and applyPostSyncPreservation. readModifyWriteStateMd and cmdPhaseComplete
both CALL it instead of each assembling the two steps themselves.
cmdPhaseComplete keeps its own writePlanningFileSet envelope — the
composition returns content, it does not take over the write, so STATE.md
still commits atomically with ROADMAP and REQUIREMENTS.

Assembling the stages at a call site is a re-derivation even when every step
calls an owner. Upstream's fix(#3374) routed cmdPhaseComplete through
applyPostSyncPreservation but left it calling syncStateFrontmatter directly
first, so the composition was duplicated and free to diverge with both guards
green. That is ADR-3180 Amendment 2's finding repeating on the write side.

cmdMilestoneComplete gains preservation. It wrote through writeStateMd, so it
got sync and no preservation — the identical shape #3374 reported for
phase.complete, and flagged upstream as a follow-up in the helper's own
docstring. This is that follow-up.

Divergence is now visible: preservation_warnings names each field restored
over a disagreeing derived value. Deliberately NOT named warnings —
cmdPhaseComplete already exposes warnings as a prose string array, and two
sibling commands carrying that name with different element types is
Generative Fix Divergence, the class this epic exists to remove.

patchCore stops running stateReplaceField over the whole document. One
observable consequence, intended per design row 9: a frontmatter-shaped patch
key with no body counterpart now reports failed instead of silently
succeeding, because the old whole-document match was literally hitting the
YAML line case-insensitively.

The guard closes Phase 1's DECLARED KNOWN GAP as promised rather than
re-deferring it: section 8.3(b) detection is tractable now the composition
exists. Scoped by two factors to avoid Phase 1's measured 29-to-1 false
positive rate — a variable field-name argument AND a content argument whose
nearest preceding assignment is not stripFrontmatter. Verified 0 findings and
0 false positives across all 33 call sites, plus 5 synthetic shapes. It also
detects the re-assembly shape above.

Ratchet: 4 entries to 2, both sanctioned-permanent. cmdStateSync's owner
changes from #3471 to sanctioned-permanent per Amendment 2 — routing it
through preservation would invert the #905 contract.

Also fixed inline rather than deferred: cmdMilestoneComplete's STATE.md read
now happens inside withStateLock. It previously read outside any lock before
writeStateMd took its own, leaving a TOCTOU window under concurrent writers.

* test(#3469): characterization coverage for the single write seam

Matrix sections A-E. Criterion 6 was amended by maintainer decision — all five
instances closed by point fixes while Phase 1 was in flight — so these are
characterization tests at the consumer's output per ADR-3180 Decision 4(b)/(c),
paired with the drift guard's count, never either alone.

Section C is the one that earns its keep. cmdStateSync is a sanctioned
permanent exception: state sync exists to re-derive frontmatter FROM the body,
so preservation there re-locks exactly what the command was invoked to
replace. C1 pins that the body wins; C4 pins that this phase left the command
byte-identical. Nothing else in the suite would notice if a future change made
sync start preserving, and the natural reading of 'one write seam' is to make
precisely that change.

Section E pins the guard's false-positive scoping. E4 (updateCore's
strip-then-replace) and E5 (sectionBody-scoped calls) must NOT be reported —
the naive detector measured 29 false positives to 1 true positive in Phase 1.
E7 is the inverse: a sanctioned-permanent entry disappearing must FAIL,
because a guard reaching zero here would only do so by having stopped looking
at two real writers.

Also corrects a stale test that asserted patchCore's old whole-document
behavior, which this phase deliberately changes.

One honest limitation, flagged rather than papered over: A1's 'byte-identical
to pre-refactor' cannot be diffed against real pre-refactor bytes from inside
the suite. It is implemented as the seeded fast-check property that
cmdPhaseComplete's composed output equals readModifyWriteStateMd's for the
same inputs — the strongest available proxy, not the literal claim.

* docs(#3469): refresh the seam glossary entry and add the changeset

Two spec-review gaps, both real.

CONTEXT.md's STATE.md Transition Module entry named three direct writeStateMd
callers including cmdMilestoneComplete. This phase routed that one through the
composition, so the line was false the moment the refactor landed.

Worth recording plainly: I wrote that sentence in Phase 0, correcting an
older stale pointer in it, and my own Phase 2 change invalidated it again
within the same epic. That is the exact drift this epic exists to remove,
demonstrated on the epic's own documentation — and it is why the entry now
ends by saying the whole-repo drift guard, not this line, is the authoritative
count.

The entry now records the composition (syncAndPreserveStateMd) and states that
exactly two direct callers remain, both SANCTIONED PERMANENT rather than debt.

Changeset: type Changed, because milestone complete's observable output moves.
Tier-2 per ADR-3180 Decision 3 — a stale body line no longer wins over fresher
frontmatter, and the command gains preservation_warnings. Docs requirement is
met by the ADR amendment already in this diff.

* test(#3469): register property-test temp-dir cleanup at creation time

Standards review, minor but real: the new fast-check property cleaned up its
temp dirs in a loop AFTER fc.assert returned. A genuine property failure
throws, so that line never ran and every dir from the failing run — including
all of fast-check's shrinking iterations — leaked.

The failure path is exactly when a littered machine hurts most, and a failing
property test is the case the test exists for.

Cleanup is now registered with t.after() at dir-creation time, so teardown
happens however the test exits. Not try/finally — CONTRIBUTING.md:356 bans it
inside test bodies, which is why the after-the-assertion shape existed in the
first place.

Swept the rest of the branch's test diff for the same shape; phase.test.cjs
already uses registered teardown and nothing else matched.

* fix(#3469): patchCore routes frontmatter writes instead of dropping them

Checkpoint returned 10 failures of 33880. One implementation defect, three
test defects, one stale test — all fixed, and the implementation defect is the
one that matters.

patchCore stripped frontmatter and then reconstructed it VERBATIM, applying no
patches to it. An arbitrary custom frontmatter key with no body counterpart and
no FIELD_CLASSIFICATION row — risk_level in the upstream fix(#3351) test —
therefore always reported failed and silently never wrote. It worked before,
via the old whole-document match on the raw YAML line.

That is a regression against this phase's own design row 9, which requires
frontmatter changes to ROUTE THROUGH the seam — still work, policy-governed —
not to stop working. Removing a capability is not routing it. An upstream test
caught it, which is the argument for running the checkpoint before believing
the refactor.

patchCore now partitions by frontmatter shape, decided structurally from the
parsed frontmatter's own keys rather than a naming heuristic:
  - classified keys still report failed — policy owns them and a raw patch may
    not bypass it;
  - unclassified keys apply to the frontmatter object and report updated —
    Phase 1's behavior-table row 19, a field with no row is not this contract's
    business;
  - body-shaped keys are unchanged.

The property 'failure' was my own test breaking the repo's Clock Seams rule.
The two paths agree byte-for-byte; the only difference was last_updated,
stamped from the wall clock on two invocations milliseconds apart, so it could
never pass. Time is now frozen with mock.timers across both — not by excluding
last_updated from the comparison, which would have silently stopped comparing
a field the composition writes.

B4's fixture could not discriminate: normalizeStateStatus maps any text
containing 'complete' to 'completed', and milestone complete's own new body
value derives to exactly that — which was also the fixture's stale value. The
stale value is now 'executing' so the assertion can tell 'body correctly won'
from 'stale survived'.

B5's fixture tripped a pre-existing unstarted-phase guard before reaching any
write-seam code; it now has the matching phase directory.

D9 asserted the old exempt set. readModifyWriteStateMd now calls one symbol
rather than assembling two, so it needs no exemption; syncAndPreserveStateMd
is the sole legitimate composition site.

* fix(#3469): patchCore resolves body-first, so the body wins a name collision

Re-verification returned 2 failures of 33880, both D4 — the hostile row for a
key that exists as BOTH a frontmatter key and a body field.

The partition checked frontmatter first, so 'status' — classified in
FIELD_CLASSIFICATION and also present as a body 'Status:' line — routed to the
frontmatter branch, was rejected as classified, and reported failed.

Wrong order. Patching 'status' means the body field, and upstream fix(#3351)
says so in its own comment: 'the legitimate working case for state.patch is
display-cased BODY fields — Status, Current Plan, Phase.' The body is
authoritative in this model; frontmatter is the projection. D4 asserted
exactly that and was right.

Resolution order is now body, then frontmatter:
  1. resolves to a body field -> apply to body, updated
  2. else an own key of the frontmatter:
       classified   -> failed  (policy owns it)
       unclassified -> apply to frontmatter, updated
  3. else -> failed

Verified by probe against the compiled lib for all four cases rather than
asserted: risk_level (frontmatter-only, unclassified) still lands;
current_phase still fails; display-cased Status unchanged; D4's lower-cased
status now lands via the body with the frontmatter untouched.

The current_phase case was the one that could have regressed silently, so its
fixture was read rather than assumed — D1's body carries 'Phase: 3 (alpha)'
and no 'Current Phase:' line, so body-first cannot reach it.

* chore(#3469): backfill pr number in changeset fragment

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-14 16:04:09 -04:00
committed by GitHub
parent 71180983a0
commit e2f4c16d9e
15 changed files with 1443 additions and 152 deletions

View File

@@ -62,35 +62,33 @@
* to prevent. `stripComments` does not track quoted strings for exactly
* this reason — see its own header.
*
* DECLARED KNOWN GAP — §8.3(b) `patchCore` frontmatter-write shape is NOT
* detected by this guard. `patchCore` runs `stateReplaceField(` over the
* WHOLE document (body + frontmatter) instead of stripping frontmatter
* first, the way `updateCore` does — a real defect, but this guard does not
* catch it.
* AXIS 3 — FRONTMATTER-SHAPED WRITE (§8.3(b)), CLOSED IN PHASE 2 (#3469).
* Phase 1 left this as a DECLARED KNOWN GAP: `patchCore` ran
* `stateReplaceField(` over the WHOLE document (body + frontmatter) instead
* of stripping frontmatter first, the way `updateCore` does, and a naive
* co-occurrence approximation ("does the enclosing function also call
* `stripFrontmatter(`?") measured at 33 occurrences of `stateReplaceField(`,
* of which only 4 were genuine write-seam bypasses and 29 were noise — the
* definition of `stateReplaceField` itself, ~20 calls on `sectionBody` (a
* body slice that is frontmatter-free by construction), and several calls
* inside `readModifyWriteStateMd` callbacks. 29 false positives to 1 true
* positive would have buried the signal.
*
* Why: catching it needs genuine DATAFLOW ("is this argument a variable
* holding the full document, or a body slice?"), not function-scoped
* co-occurrence. A co-occurrence approximation (does the enclosing function
* also call `stripFrontmatter(`?) was implemented and measured directly
* against this repo: 33 occurrences of `stateReplaceField(`, of which only
* 4 are genuine write-seam bypasses and 29 are noise — the definition of
* `stateReplaceField` itself (matched as a call), ~20 calls on `sectionBody`
* (a body slice that is frontmatter-free by construction), and several
* calls inside `readModifyWriteStateMd` callbacks (correct, because the RMW
* envelope applies preservation after the callback returns). 29 false
* positives to 1 true positive buries the signal and makes the ratchet's
* shrink-rate meaningless as a Phase 2 progress indicator — recorded here,
* with these numbers, so the next reader does not re-attempt the same
* approximation.
*
* Who owns closing it: Phase 2 (#3469), which also FIXES the defect by
* consolidating on the single write seam — after which detection becomes
* tractable, because once the pure pipeline exists the invariant simplifies
* to "no transition core calls `stateReplaceField` on unstripped content".
*
* This is a DECLARED gap with a named owner, not a silent omission — a
* guard that quietly does not look somewhere is the failure ADR-3180
* Decision 4(d) records.
* Phase 2 fixes `patchCore` (it now strips frontmatter first, matching
* `updateCore`) AND closes the gap, using a narrower, two-factor shape that
* does not reproduce that ratio: `findUnstrippedContentWrites` below flags a
* `stateReplaceField(` call only when BOTH (a) its field-name argument is a
* VARIABLE, not a fixed string literal — every OTHER call site in
* `EXECUTOR_FILE` passes a fixed Title-Case literal (`'Phase'`, `'Total
* Plans in Phase'`, ...) that can never collide with a lowercase/snake_case
* YAML frontmatter key, so a literal field name is never a candidate
* regardless of whether its content argument is stripped — and (b) its
* content argument has not been run through `stripFrontmatter` first,
* checked by a simple backward scan (within the same function) for the
* nearest preceding assignment to that argument's variable name. This is
* deliberately NOT full alias/dataflow tracking — see the function's own
* docstring for the narrow, documented limitation this trades for
* tractability.
*/
const fs = require('node:fs');
@@ -108,6 +106,10 @@ const BASELINE_PATH = path.join(__dirname, 'state-write-path-drift-baseline.json
const REASON = Object.freeze({
FIELD_NAME_DISPATCH: 'field_name_dispatch',
UNIMPLEMENTED_POLICY: 'unimplemented_policy',
// Axis 3 (§8.3(b), closed Phase 2 / #3469): a `stateReplaceField(` call
// with a variable field-name argument whose content argument was not run
// through `stripFrontmatter` first — see `findUnstrippedContentWrites`.
UNSTRIPPED_CONTENT_WRITE: 'unstripped_content_write',
SEAM_BYPASS_UNRECORDED: 'seam_bypass_unrecorded',
SEAM_BYPASS_COUNT_GREW: 'seam_bypass_count_grew',
SEAM_BYPASS_COUNT_SHRANK: 'seam_bypass_count_shrank',
@@ -132,12 +134,22 @@ const EXECUTOR_FILE = 'src/state-transition.cts';
const SEAM_OWNER_FILE = 'src/state.cts';
// Per Decision 4(d)'s "owner FILE is not exempt, only its named canonical
// FUNCTIONS are": a `writeStateMd(`/`syncStateFrontmatter(` call inside one
// of these two functions, in `SEAM_OWNER_FILE` only, is the seam's own
// internal plumbing (the I/O wrapper calling the pure sync stage), not a
// bypass. Every OTHER function in `state.cts` — and every function in every
// OTHER file — is still scanned and still flagged.
const SEAM_OWNER_EXEMPT_FUNCTIONS = ['writeStateMd', 'readModifyWriteStateMd'];
// FUNCTIONS are": a `writeStateMd(`/`syncStateFrontmatter(`/
// `applyPostSyncPreservation(` call inside one of these two functions, in
// `SEAM_OWNER_FILE` only, is the seam's own internal plumbing, not a bypass.
// `writeStateMd` is the `cmdStateSync`/`REGENERATE_STATE` path's own I/O
// wrapper calling `syncStateFrontmatter` directly (no preservation, by
// design — §8.3's closed exception list). `syncAndPreserveStateMd` (#3469)
// is the ONE write-seam composition — `syncStateFrontmatter` then
// `applyPostSyncPreservation` — every OTHER caller needing a non-standard
// I/O envelope routes through. Every OTHER function in `state.cts` — and
// every function in every OTHER file — is still scanned and still flagged;
// in particular, `readModifyWriteStateMd` is NOT exempt: after #3469 it no
// longer contains a direct `syncStateFrontmatter(`/`applyPostSyncPreservation(`
// call at all (it calls `syncAndPreserveStateMd` like everyone else), so if
// one reappeared there it would be exactly the re-assembly shape this axis
// exists to catch.
const SEAM_OWNER_EXEMPT_FUNCTIONS = ['writeStateMd', 'syncAndPreserveStateMd'];
// Unconditional path-separator normalization (never gated on
// `process.platform` — a Windows-authored fork PR must be judged by the
@@ -395,20 +407,128 @@ function findUnimplementedPolicies(text, rel) {
return out;
}
// The two write-seam functions, matched only as CALLS (`\(` immediately
// after, modulo whitespace) — never as bare mentions of the name.
const SEAM_CALL_RE = /\b(writeStateMd|syncStateFrontmatter)\s*\(/g;
// A line that IS one of the two seam functions' own definitions — skipped
// outright, never counted as a call to itself.
const SEAM_DEF_LINE_RE = /^\s*(?:export\s+)?(?:async\s+)?function\s+(?:writeStateMd|syncStateFrontmatter)\b/;
// AXIS 3 (§8.3(b), closed Phase 2 / #3469): `stateReplaceField(<contentArg>,
// <fieldArg>, ...)` on a single line, capturing both argument expressions.
// `contentArg` must be a bare identifier (a call expression or property
// access as the first argument is not matched — silently out of scope, per
// this axis's own narrow-limitation note below) so its assignments can be
// tracked; `fieldArg` is everything up to the next comma, trimmed, so its
// literal-vs-variable shape can be read off directly.
const STATE_REPLACE_FIELD_CALL_RE = /\bstateReplaceField\s*\(\s*([A-Za-z_$][\w$]*)\s*,\s*([^,()]+),/g;
// True when `arg` (already trimmed) is a fixed string/template literal —
// the safe shape, since every literal field name this codebase actually
// uses is a Title-Case body label that cannot collide with a lowercase/
// snake_case YAML frontmatter key.
function isQuotedLiteralArg(arg) {
const t = arg.trim();
return t.startsWith("'") || t.startsWith('"') || t.startsWith('`');
}
/**
* AXIS 2a: every direct `writeStateMd(`/`syncStateFrontmatter(` call in
* `text`, outside the two functions' own definitions and (only inside
* `SEAM_OWNER_FILE`) outside `SEAM_OWNER_EXEMPT_FUNCTIONS`'s own bodies. No
* `reason` on these findings — `applyRatchet` assigns one, since the same
* observed call site is a different failure shape depending on whether the
* baseline already knows about it.
* The nearest assignment to `varName` (`varName = <expr>` or
* `const|let|var varName = <expr>`), scanning `lines` BACKWARD from `index`
* (inclusive) and stopping at the nearest preceding named-function
* declaration (mirrors `enclosingFunction`'s own boundary, so the scan
* cannot walk into an unrelated function above the one containing the
* call). Returns the assigned expression's trimmed text, or `null` when no
* such assignment is found before the boundary — meaning `varName` is the
* enclosing function's own untouched parameter.
*
* Deliberately single-hop: this reports whatever the NEAREST assignment's
* right-hand side literally is, and does not itself follow a further alias
* (`let body = someOtherVar;` is reported as `"someOtherVar"`, not resolved
* further). Every real call site in this file assigns its body variable
* directly from `stripFrontmatter(content)` with no intermediate alias
* (`updateCore`, `patchCore`, `beginPhaseCore`'s `tryField` helper) — a
* future call site that introduces one extra hop of aliasing would evade
* this check. A declared, narrow limitation, not a silent one — mirrors
* this file's existing precedent (`FIELD_VAR_EQ_LITERAL_RE`'s own
* documented scope) of accepting a bounded risk in trade for not chasing
* full dataflow, which is exactly what made the Phase 1 approximation
* unusable (29 false positives to 1 true positive).
*/
function nearestPrecedingAssignment(lines, index, varName) {
const assignRe = new RegExp(`(?:^|[^.\\w$])(?:const|let|var)?\\s*${escapeRegex(varName)}\\s*=\\s*([^=].*)$`);
for (let i = index; i >= 0; i--) {
if (FUNCTION_DECL_LINE_RE.test(lines[i])) return null;
const m = assignRe.exec(lines[i]);
if (m) return m[1].trim();
}
return null;
}
/**
* AXIS 3: every `stateReplaceField(` call in `EXECUTOR_FILE` whose field-name
* argument is a VARIABLE (not a quoted literal) — the only shape that can
* ever rewrite YAML frontmatter, since `stateReplaceField`'s `^field:` line
* pattern is case-insensitive and matches any line starting with that name,
* literal or not — AND whose content argument was not assigned from
* `stripFrontmatter(` at the nearest preceding assignment. A literal
* field-name argument is never flagged regardless of stripping: every fixed
* string this file's `stateReplaceField` calls use is a Title-Case body
* label (`'Phase'`, `'Total Plans in Phase'`, ...) that cannot collide with
* a lowercase/snake_case frontmatter key by construction, so checking its
* content argument would only add false positives on the ~20 already-safe
* `sectionBody`-scoped calls this axis must NOT report (mirrors
* `updateCore`'s strip-then-replace shape, and `beginPhaseCore`'s
* `stateReplaceField(body, name, value)`, both legitimately unflagged).
*/
function findUnstrippedContentWrites(rel, text) {
const rawLines = text.split('\n');
const stripped = stripComments(text);
const out = [];
for (let i = 0; i < stripped.length; i++) {
const line = stripped[i];
if (!line.trim()) continue;
STATE_REPLACE_FIELD_CALL_RE.lastIndex = 0;
let m;
while ((m = STATE_REPLACE_FIELD_CALL_RE.exec(line)) !== null) {
const contentArg = m[1];
const fieldArg = m[2];
if (isQuotedLiteralArg(fieldArg)) continue;
const assignment = nearestPrecedingAssignment(stripped, i - 1, contentArg);
const isStripped = assignment !== null && /^stripFrontmatter\s*\(/.test(assignment);
if (isStripped) continue;
// `file`/`source` sanitized for the same fork-PR reason as every other
// finding in this guard; `contentArg` is captured out of repo source
// (an identifier name), attacker-controlled on the same basis.
out.push({
reason: REASON.UNSTRIPPED_CONTENT_WRITE,
axis: 'frontmatter-write',
file: sanitizeForReport(rel),
line: i + 1,
field: sanitizeForReport(contentArg),
source: sanitizeForReport(rawLines[i].trim()),
});
}
}
return out;
}
// The three write-seam functions, matched only as CALLS (`\(` immediately
// after, modulo whitespace) — never as bare mentions of the name.
// `applyPostSyncPreservation` (#3469) is included alongside
// `writeStateMd`/`syncStateFrontmatter`: after Phase 2, it is ONLY ever
// legitimately called from inside `syncAndPreserveStateMd` (the seam
// composition), so any OTHER call to it is either a re-assembly of the pair
// (Phase 2's Finding 3 shape — a call site invoking both
// `syncStateFrontmatter` and `applyPostSyncPreservation` itself instead of
// the composition) or a bypass calling it alone; either way it belongs on
// this axis.
const SEAM_CALL_RE = /\b(writeStateMd|syncStateFrontmatter|applyPostSyncPreservation)\s*\(/g;
// A line that IS one of the three seam functions' own definitions — skipped
// outright, never counted as a call to itself.
const SEAM_DEF_LINE_RE = /^\s*(?:export\s+)?(?:async\s+)?function\s+(?:writeStateMd|syncStateFrontmatter|applyPostSyncPreservation)\b/;
/**
* AXIS 2a: every direct `writeStateMd(`/`syncStateFrontmatter(`/
* `applyPostSyncPreservation(` call in `text`, outside the three functions'
* own definitions and (only inside `SEAM_OWNER_FILE`) outside
* `SEAM_OWNER_EXEMPT_FUNCTIONS`'s own bodies. No `reason` on these
* findings — `applyRatchet` assigns one, since the same observed call site
* is a different failure shape depending on whether the baseline already
* knows about it.
*/
function findSeamBypasses(rel, text) {
const rawLines = text.split('\n');
@@ -654,11 +774,13 @@ function applyRatchet(observed, baseline) {
}
/**
* Run both scan passes (the `src/` tree for Axis 1 + Axis 2a, the prompt
* layer for Axis 2b) and split the combined findings by `axis` into
* Run both scan passes (the `src/` tree for Axis 1 + Axis 2a + Axis 3, the
* prompt layer for Axis 2b) and split the combined findings by `axis` into
* `{ policyFindings, seamFindings }`. `policyFindings` are already terminal
* (each carries its own `reason`); `seamFindings` are raw observations —
* `applyRatchet` is what turns them into (or clears them of) a finding.
* (each carries its own `reason`) — this bucket is every axis EXCEPT
* `write-seam` (Axis 2), which alone is ratcheted; `seamFindings` are raw
* write-seam observations — `applyRatchet` is what turns them into (or
* clears them of) a finding.
*/
function collect() {
const srcFindings = scanTree({
@@ -671,6 +793,7 @@ function collect() {
if (relPosix === EXECUTOR_FILE) {
found.push(...findPolicyDispatchDrift(relPosix, text));
found.push(...findUnimplementedPolicies(text, relPosix));
found.push(...findUnstrippedContentWrites(relPosix, text));
}
found.push(...findSeamBypasses(relPosix, text));
return found;
@@ -688,7 +811,7 @@ function collect() {
const all = [...srcFindings, ...promptFindings];
return {
policyFindings: all.filter((f) => f.axis === 'policy-dispatch'),
policyFindings: all.filter((f) => f.axis !== 'write-seam'),
seamFindings: all.filter((f) => f.axis === 'write-seam'),
};
}
@@ -745,18 +868,23 @@ function buildBaselineEntries(seamFindings, existingEntries) {
}
const BASELINE_COMMENT =
'ADR-3408 Decision 5 write-seam ratchet baseline (issue #3468, Phase 1). Every entry here is a ' +
'`writeStateMd(`/`syncStateFrontmatter(` bypass this guard found by a whole-repo scan (Decision ' +
'4(a)) — it is ACKNOWLEDGED, not endorsed: acknowledgment is in writing (this file), with the ' +
'issue owning its removal recorded in the entry\'s "owner" field. This baseline is SHRINK-ONLY — ' +
'an entry that stops firing goes STALE and fails the plain run until `--baseline` is re-run to ' +
'drop it (ADR-3180 Decision 4(e)\'s "the baseline may only shrink", adopted verbatim by ADR-3408). ' +
'Phase 2 (#3469) removes the `cmdPhaseComplete` and `patchCore` entries when it lands the single ' +
'write seam. Phase 4 (#3471) drives this baseline to empty and deletes this file. ' +
'`REGENERATE_STATE` (`src/health-diagnostic.cts`) is a SANCTIONED PERMANENT exception, not debt — ' +
'it is `/gsd-health --repair`\'s factory reset, which rebuilds STATE.md from scratch, so ' +
'preservation would restore exactly the values it was invoked to discard; do not "consolidate" ' +
'its entry away.';
'ADR-3408 Decision 5 write-seam ratchet baseline (issue #3468, Phase 1; Phase 2 / #3469 lands the ' +
'single write seam and Amendment 2). Every entry here is a `writeStateMd(`/`syncStateFrontmatter(`/' +
'`applyPostSyncPreservation(` bypass this guard found by a whole-repo scan (Decision 4(a)) — it is ' +
'ACKNOWLEDGED, not endorsed: acknowledgment is in writing (this file), with the issue owning its ' +
'removal recorded in the entry\'s "owner" field. This baseline is SHRINK-ONLY — an entry that stops ' +
'firing goes STALE and fails the plain run until `--baseline` is re-run to drop it (ADR-3180 ' +
'Decision 4(e)\'s "the baseline may only shrink", adopted verbatim by ADR-3408). Phase 2 (#3469) ' +
'removed the `cmdPhaseComplete` (`src/phase.cts`) and `cmdMilestoneComplete` (`src/milestone.cts`) ' +
'entries by routing both through the single write-seam composition (`syncAndPreserveStateMd`, ' +
'`src/state.cts`). ADR-3408 Amendment 2: "0 bypasses" was never this baseline\'s target — TWO ' +
'entries are SANCTIONED PERMANENT, not debt, and Phase 4 (#3471) does NOT drive this file to empty: ' +
'`cmdStateSync` (`src/state.cts`) exists precisely to let the body win (#905 — `state sync` ' +
're-derives frontmatter FROM the body), so routing it through preservation would invert the command ' +
'rather than fix a bug; `REGENERATE_STATE` (`src/health-diagnostic.cts`) is `/gsd-health --repair`\'s ' +
'factory reset, which rebuilds STATE.md from scratch, so preservation would restore exactly the ' +
'values it was invoked to discard. Neither entry may be "consolidated" away — a guard reporting them ' +
'is reporting correctly, and a change that removes one is a regression, not progress.';
function writeBaseline(seamFindings) {
const priorBaseline = loadBaseline();
@@ -902,6 +1030,9 @@ module.exports = {
readPolicyUnion,
findPolicyDispatchDrift,
findUnimplementedPolicies,
findUnstrippedContentWrites,
isQuotedLiteralArg,
nearestPrecedingAssignment,
findSeamBypasses,
findPromptSeamUses,
isInsideCodeSpan,

View File

@@ -1,5 +1,5 @@
{
"_comment": "ADR-3408 Decision 5 write-seam ratchet baseline (issue #3468, Phase 1). Every entry here is a `writeStateMd(`/`syncStateFrontmatter(` bypass this guard found by a whole-repo scan (Decision 4(a)) — it is ACKNOWLEDGED, not endorsed: acknowledgment is in writing (this file), with the issue owning its removal recorded in the entry's \"owner\" field. This baseline is SHRINK-ONLY — an entry that stops firing goes STALE and fails the plain run until `--baseline` is re-run to drop it (ADR-3180 Decision 4(e)'s \"the baseline may only shrink\", adopted verbatim by ADR-3408). Phase 2 (#3469) removes the `cmdPhaseComplete` and `patchCore` entries when it lands the single write seam. Phase 4 (#3471) drives this baseline to empty and deletes this file. `REGENERATE_STATE` (`src/health-diagnostic.cts`) is a SANCTIONED PERMANENT exception, not debt — it is `/gsd-health --repair`'s factory reset, which rebuilds STATE.md from scratch, so preservation would restore exactly the values it was invoked to discard; do not \"consolidate\" its entry away.",
"_comment": "ADR-3408 Decision 5 write-seam ratchet baseline (issue #3468, Phase 1; Phase 2 / #3469 lands the single write seam and Amendment 2). Every entry here is a `writeStateMd(`/`syncStateFrontmatter(`/`applyPostSyncPreservation(` bypass this guard found by a whole-repo scan (Decision 4(a)) — it is ACKNOWLEDGED, not endorsed: acknowledgment is in writing (this file), with the issue owning its removal recorded in the entry's \"owner\" field. This baseline is SHRINK-ONLY — an entry that stops firing goes STALE and fails the plain run until `--baseline` is re-run to drop it (ADR-3180 Decision 4(e)'s \"the baseline may only shrink\", adopted verbatim by ADR-3408). Phase 2 (#3469) removed the `cmdPhaseComplete` (`src/phase.cts`) and `cmdMilestoneComplete` (`src/milestone.cts`) entries by routing both through the single write-seam composition (`syncAndPreserveStateMd`, `src/state.cts`). ADR-3408 Amendment 2: \"0 bypasses\" was never this baseline's target — TWO entries are SANCTIONED PERMANENT, not debt, and Phase 4 (#3471) does NOT drive this file to empty: `cmdStateSync` (`src/state.cts`) exists precisely to let the body win (#905 — `state sync` re-derives frontmatter FROM the body), so routing it through preservation would invert the command rather than fix a bug; `REGENERATE_STATE` (`src/health-diagnostic.cts`) is `/gsd-health --repair`'s factory reset, which rebuilds STATE.md from scratch, so preservation would restore exactly the values it was invoked to discard. Neither entry may be \"consolidated\" away — a guard reporting them is reporting correctly, and a change that removes one is a regression, not progress.",
"entries": [
{
"file": "src/health-diagnostic.cts",
@@ -8,26 +8,12 @@
"count": 1,
"owner": "sanctioned-permanent"
},
{
"file": "src/milestone.cts",
"source": "writeStateMd(statePath, result.content, cwd);",
"symbol": "writeStateMd",
"count": 1,
"owner": "#3471"
},
{
"file": "src/phase.cts",
"source": "const synced = syncStateFrontmatter(stateContent, cwd, authoritativeFm);",
"symbol": "syncStateFrontmatter",
"count": 1,
"owner": "#3469"
},
{
"file": "src/state.cts",
"source": "writeStateMd(statePath, modified, cwd);",
"symbol": "writeStateMd",
"count": 1,
"owner": "#3471"
"owner": "sanctioned-permanent"
}
]
}