* 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>
18 KiB
18 KiB