Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD
across contents and paths, upstream package/repo coordinates -> @golem15/msd-core
and golem15com/msd-core. Deep links into upstream history, sibling upstream
packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is.
Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line,
package/plugin identity, regenerated lockfile, install-tree fixtures, derived
registries and benchmark baseline; migration checksum baseline re-locked
(MSD keeps its own install state, so no install had applied the old sums);
sort-order and regex-escaped expectations in tests adjusted.
* test(#4302): add failing regression test for deferral-window paragraph leak
RED: hasNearbyDeferralMarker's 500-char trailing window has no structural
boundary, so a compact citation-free restatement immediately followed by an
unrelated section that cites tdd.md borrows that neighbor's citation and
evades restatesCycleStructurally(). Reproduces the exact shape confirmed via
mutation testing against the real agents/gsd-executor.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix(#4302): bound the deferral window at the next heading, not a flat char count
hasNearbyDeferralMarker's 500-char trailing window had no structural
boundary, so a compact citation-free restatement immediately followed by an
unrelated section that cites tdd.md borrowed that neighbor's citation and
evaded restatesCycleStructurally() (confirmed on the real gsd-executor.md,
whose next section after the cycle pointer has its own independent citation
82 chars past the REFACTOR anchor).
First attempt bounded at the next blank line instead, and was rejected after
it broke a real case caught by direct execution before committing:
execute-plan.md's FIRST RED/GREEN/REFACTOR occurrence is a numbered list's
own intro sentence, separated by a genuine blank line from the list item
that actually carries the citation — a blank line is not reliably "still the
same statement" once list structure is involved.
Bounds at the next markdown heading (`\n#`) instead, capped at 500 chars as
before when no heading appears. Verified against both real files, the new
regression fixture, and every pre-existing #4268 fixture/property test.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix(#4302): close a narrower same-section evasion found by orthogonal review
The heading-only fix left a narrower gap: a citation-free restatement
followed by a blank line and an unrelated PROSE paragraph (no heading) that
cites tdd.md for an unrelated reason still evaded detection — confirmed by
the reviewer via execution.
Generalizes the boundary rule: any blank line whose following line is NOT a
markdown list continuation is now also a boundary (in addition to the
existing heading boundary), reconciling with the earlier-rejected flat
blank-line bound by adding the list-continuation exception that
execute-plan.md's real shape (a numbered list's intro sentence, then a
blank line, then the list item carrying the citation) needs. Verified
against both real files, all three restatement fixtures (heading-bounded,
prose-bounded, list-continuation negative-space), every pre-existing #4268
fixture, and the fast-check property test (200 runs).
Also restores an honest, updated limitation disclosure describing the one
narrower residual case not resolved by this design (a citation reachable via
exactly one list-item hop from an unrelated list) — matching this repo's
disclosed-not-silently-deferred practice from the original #4268 PR.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
---------
Co-authored-by: sim <sim@local>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* test(#4268): harden reworded-restatement and backend-predicate-divergence detection
tests/tdd-single-statement.test.cjs's restatesCycle() keyed on the exact
literal `commit: `test({phase}-{plan})`` substring, so a reworded restatement
of the RED/GREEN/REFACTOR procedure shipped green. Adds
restatesCycleStructurally(), a structural (span + list-marker) detector that
stays linear-scan (per the #4228 catastrophic-backtracking incident this must
not reintroduce) and is proven, empirically, to flag a paraphrased multi-step
fixture while not flagging the real compact citations in execute-plan.md and
gsd-executor.md (#4267's legitimate pointers).
tests/tdd-backend-wiring.test.cjs never compared the two dispatch backends'
`gsd_run query phase.tdd-applicable` calls against each other, so a one-word
divergence between them (e.g. a changed --pick flag in only one backend)
shipped green. Adds a byte-identity assertion on the command-substitution
content (normalized for the two backends' differing variable-name prefixes),
proven to have teeth via a RED-first mutation check before asserting it
against the real files.
The third gap in #4268 (nothing proves TDD_APPLICABLE has a real definition)
was already covered by this file's existing assertTddApplicableIsComputed
(epic #4272 Phase 2, #4266) — verified by inspection, no new test needed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* test(#4268): redesign restatement detector around deferral, not length
Standards+Spec review of the prior commit proved by execution that a
compact, no-list-marker restatement (under the 200-char span threshold)
sails past the span/list-marker-only signal. Redesigns the primary check:
the actual invariant is deferral, not length — a legitimate RED/GREEN/
REFACTOR mention always names tdd.md as the authority nearby, a restatement
never does. Flags when no tdd.md/canonical reference appears within a
500-char trailing window past the cycle mention, regardless of length or
list-marker shape; keeps span>200 and three-distinct-list-marker-lines as
secondary defense-in-depth OR-conditions. Verified independently against
both real files (execute-plan.md span=10, gsd-executor.md span=14, both with
a nearby deferral marker at +228/+82 chars) — no false positive, and the
reviewer's exact gap class (a 189-char no-citation paraphrase) is now
flagged.
Also fixes: boundary coverage at the span threshold (199/200/201, isolated
via a factored-out measureCycleSpan() helper), a fast-check property test
proving the fix holds for arbitrary filler text, and a fragile line-match in
tdd-backend-wiring.test.cjs that happened to work only because a FATAL echo
message containing the same substring came later in document order than the
real assignment line.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
---------
Co-authored-by: sim <sim@local>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* test(#3990): the RED/GREEN/REFACTOR cycle is stated once, embedded conditionally
* fix(#3990): state the cycle once — pointers in consumers, conditional tdd.md embeds
Emitted-Drift-Ack-Growth: execute-phase.md — #3990 conditions the tdd.md embed on the dispatch being TDD
* chore(#3990): changeset for the single-statement TDD cycle
* chore(#3990): backfill changeset pr number
* fix(#4228): linear cycle check — the lazy-span regex pinned a Windows core for the whole job cap
* test(#3990): allowlist pin tracks the rebased line
* fix(tests): npm-integrity gate names an empty audit output explicitly — empty stdout crashed the parse as a bare SyntaxError
* fix: name an empty npm-audit stdout explicitly — it crashed the parse as a bare SyntaxError
Observed on CI (several branches, all lanes): spawnSync npm ETIMEDOUT with
empty stdout; the empty string survived the recovery path and surfaced as
'SyntaxError: Unexpected end of JSON input', hiding the captured error. The
recovery path now requires non-empty stdout, and an empty result throws with
the captured stdout/stderr/message so the actual error is on the record.
Root cause of the ETIMEDOUT itself is NOT diagnosed here — this change only
stops masking it.
---------
Co-authored-by: sim <sim@local>