dc139b38e052d1b8cd8cb98d3f53fa47b4df9c9c
16 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d12809985e |
fix(#905): preserve STATE.md frontmatter scalars in syncStateFrontmatter (#907)
syncStateFrontmatter was silently dropping current_phase, current_phase_name, current_plan, and progress when body annotations were absent (e.g. after an agent or tool rewrote the body). These scalars can only be derived from body annotations — when absent, buildStateFrontmatter returns nothing for those keys. Added existingFm fallbacks mirroring the same pattern already applied in cmdStateJson, so every writeStateMd call preserves the existing values instead of stripping them. Also extended cmdStateJson with the same fallbacks for the three non-progress scalars. Adds regression test (7 cases) + lint-test-file-count allowlist entry. Closes #905 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
808df9110c |
fix(#892): parse checklist-style roadmap phases in validate/verify (#908)
buildRoadmapPhaseVariants() only matched heading-style phases (## Phase N:), silently skipping the supported checklist format (- [x] **Phase N: name**). This caused W007 false-positives for every on-disk phase dir when the project uses a checklist ROADMAP. Fix adds a second regex pass (mirroring the existing buildNotStartedPhaseVariants() approach). Also refactors the duplicate inline heading-only regex in cmdValidateConsistency() to delegate to buildRoadmapPhaseVariants() (DRY). Regression test in tests/bug-892-validate-checklist-roadmap-phases.test.cjs covers both paths. Closes #892 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
0a11d361ca |
feat(#69): nest concrete skills under namespace routers at install (#883)
Emit the 6 gsd-ns-* routers as the only top-level skill bundles and nest the ~61 concrete skills under <router>/skills/<name>/SKILL.md on runtimes with confirmed non-recursive skill loaders (claude global, cline, qwen, hermes, augment, trae, antigravity). Router bodies rewrite their routing tables from Skill-tool dispatch to a Read skills/<name>/SKILL.md pattern. Recursive/unconfirmed loaders (cursor, codex, copilot, windsurf, codebuddy, opencode, kilo) keep the flat layout. Completes the v1.40 namespace architecture (#2792) so the eager skill listing drops to ~6 entries. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e04e757672 |
feat(#776): Gemini hook events (BeforeAgent/AfterAgent/BeforeModel) + hooksConfig.enabled check (#829)
* feat(#776): Gemini hook events (BeforeAgent/AfterAgent/BeforeModel) + hooksConfig.enabled check Register three new Gemini-CLI hook events on install: - BeforeAgent: fires before agent planning; wired to gsd-context-monitor - AfterAgent: fires after final response generation; wired to gsd-context-monitor - BeforeModel: fires before each LLM call (per-turn); wired to gsd-context-monitor All three reuse gsd-context-monitor.js (no new hook files). Uninstall cleanup loop extended to remove the new events. Non-array guard added for robustness against malformed settings. Also detect hooksConfig.enabled:false in Gemini settings and emit a clear warning — without this check, all registered hooks silently do nothing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: update changeset pr: 829 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(#776): document Gemini hook events Add hook coverage table to the Gemini CLI section of install-on-your-runtime.md, covering the three new events (BeforeAgent/AfterAgent/BeforeModel wired to gsd-context-monitor) plus a callout for the hooksConfig.enabled:false silent failure mode detected by the installer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
edd3c6c332 |
fix(#730): scope current-milestone Phase Details section in roadmap parser (#748)
`extractCurrentMilestone()` scoped the current-milestone window to its `## Phases` checklist subsection and terminated at the milestone's own `## Milestone … (Phase Details)` heading, so the `### Phase N:` detail headers fell outside scope. Every parser-backed command — `init.phase-op` (and thus `/gsd:discuss-phase`, `/gsd:plan-phase`), `state`, `roadmap list`, and `validate health` (W006) — therefore could not resolve phases of any milestone after the first until a `.planning/phases/` directory already existed, blocking discuss/plan. The parser now additionally includes the current milestone's `(Phase Details)` section in scope, located via the already-computed version matches and anchored (boundary-aware) to the selected milestone's version token so sibling sub-milestones sharing a version prefix do not cross-pollinate. The existing heading selection and primary window are unchanged. Adds tests/bug-730-milestone-phase-details-scope.test.cjs covering the two-milestone reproduction, first-milestone non-regression, direct getRoadmapPhaseInternal resolution, validate-health W006 visibility, a three-milestone roadmap, and the closed-sibling sub-milestone case. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
de7d6add15 |
fix(#622): make graph.html copy optional in /gsd-graphify build chain (#634)
* fix(#622): make graph.html copy optional in /gsd-graphify build chain The Step 3 shell chain in commands/gsd/graphify.md copied graphify-out/graph.html with an unconditional `cp` linked by `&&`. When a graph exceeds graphify's HTML viz node limit (default 5000), `graphify update .` deliberately omits graph.html, so the `cp` failed with "cannot stat" and aborted the chain — skipping the GRAPH_REPORT.md copy, the diff-snapshot write, and the status report, and reporting BUILD FAILED even though the graph data was rebuilt successfully. Guard the graph.html copy with `{ [ -f graphify-out/graph.html ] && cp ... || true; }`, mirroring the already-correct tolerant copy in hooks/lib/gsd-graphify-rebuild.sh. A skipped optional HTML artifact no longer aborts the chain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#622): add changeset for graph.html optional-copy fix Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(#622): CRLF-tolerant fence regex + allowlist the new graphify test Two CI guards flagged the new regression test: - windows-test-parity (fenceRegexLiteralNewline): the block-extraction regex matched ```bash with a literal \n, which breaks on Windows CRLF checkouts. Use ```bash\r?\n per the guard's sanctioned fix. - lint-test-file-count: the new file is a 5th test in the grapify bucket (cap 2, grandfathered at 4). Add it to the graphify allowlist files array and give the entry a real tracking issue (TBD -> 622). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
54a4e34b47 |
fix(#623): make release Verify-publish tolerant of npm propagation lag (#624)
* fix(#623): make release Verify-publish tolerant of npm propagation lag The rc and latest Verify-publish steps used a single `sleep 10` + one `npm view`, which false-failed the whole release job when npm's registry read lagged the publish write — observed on the v1.3.0-rc.1 RC run, where publish/tag/GitHub-release all succeeded but verification reported NOT_FOUND. Extract the check into scripts/verify-npm-publish.cjs: a testable module with a bounded retry/poll loop, a frozen REASON enum, and a --json mode (mirrors verify-reapply-patches.cjs). Both workflow steps now call it. dist-tag reporting stays informational and never fails the step, matching prior behavior. Adds tests/verify-npm-publish.test.cjs covering retry, exhaustion, and dist-tag reporting via injected lookups (no network). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#623): allowlist verify-npm-publish.test.cjs in the verify cluster The test-file-count linter groups test files by production-module prefix. scripts/verify-npm-publish.cjs lives under scripts/ (not a scanned prod dir), so its test collapses into the existing `verify` module via the startsWith(prefix + '-') rule — same as scripts/verify-reapply-patches.cjs, whose tests are already allowlisted under `verify`. Add the new test to that cluster's allowlisted set to satisfy the identity ratchet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
a28dcec981 |
chore(#597): replace count-based ratchet guards with AST lint + named-set allowlists (#603)
The windows-test-parity ratchet greps test source for fs.rmSync-without-
maxRetries (and six other Windows-portability anti-patterns), failing when an
integer offender COUNT exceeds a frozen baseline (rmSync: 95). A count ratchet
is a Goodhart metric: fixing one offender and adding another keeps the count
constant, so a new defect slips through green. Replace it — and every other
count ratchet in the repo — with a layered, masking-proof design.
Behavioral seam test
- tests/helpers-cleanup.test.cjs proves helpers.cleanup() carries the Windows
EBUSY retry budget. cleanup() delegates retries to Node's fs.rmSync via
maxRetries (it owns no loop), so the test asserts the option contract
(recursive/force/maxRetries>0/retryDelay>0) + real-FS removal + the cwd-guard,
rather than a loop that does not exist. The EBUSY risk is now tested ONCE at
the helper, not approximated textually at every call site.
Write-time ESLint rule (AST-accurate, replaces the grep)
- eslint-rules/no-raw-rmsync-in-tests.cjs (error in tests/**/*.test.cjs) bans
raw fs.rmSync, steering to cleanup(). Catches member, computed (fs['rmSync']),
destructured and aliased forms; escape hatch is inline
`// eslint-disable-next-line local/no-raw-rmsync-in-tests -- <reason>` only.
- Migrated 336 raw fs.rmSync teardown calls across ~116 test files to cleanup().
~18 genuinely load-bearing sites (mid-test SUT/fault-injection removals,
error-swallowing or name-colliding local teardown helpers) keep the raw call
with an inline eslint-disable + reason.
Shared anti-ratchet primitive
- scripts/lib/allowlist-ratchet.cjs:
- assertWithinAllowlist: fails on NOVEL ids (new offender introduced) AND on
STALE ids (a known offender was fixed but not pruned) — identity, not count,
and a ratchet DOWN toward zero.
- assertTightCeiling: a size/length budget whose ceiling must stay within a
grace band of the high-water mark, so budgets may only tighten, never creep.
Ratchets converted onto the primitive
- windows-test-parity-guard.test.cjs: rmSync rule deleted (now ESLint-enforced);
the remaining six patterns moved from integer baselines to named-set
allowlists with ratchet-down.
- scripts/lint-test-file-count.{cjs,allowlist.json}: per-module integer counts →
named filename sets (closes the swap-a-file-keep-the-count blind spot); a
module dropping under cap now FAILS to force pruning its allowlist entry.
- enh-2790 skill-count `<= 63` → named skill allowlist (ratchets toward ~58).
Size budgets hardened (tighten-only)
- agent-size / workflow-size / feat-3039 help-tiered: ceilings lowered to the
current high-water mark and an assertTightCeiling anti-creep check added per
tier. Fixed external-contract limits (description ≤100 chars, agent ≤100 KB)
are intentionally left as-is — they are not grandfathered creeping budgets.
No user-facing behavior change (tests + tooling only); no USER_FACING_PREFIXES
touched, so no changeset fragment is required.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
8c7ef76e25 | test(#192): ratchet audit prefix test-file-count allowlist | ||
|
|
59bcdf03b6 |
refactor(#180): migrate STATE.md Document Module to sdk/src/state (#249)
* refactor(#180): migrate state document module to sdk/src/state * test(#180): ratchet lint allowlists for state module relocation |
||
|
|
d8b432da1e |
fix(#14): wire --auto flag through progress→next handoff (#148)
* fix(#14): document --auto in progress.md and wire chaining logic in next.md The --auto flag was accepted by /gsd:progress --next --auto but silently ignored: it was not documented in the <flags> section of progress.md and had no handling in the next.md show_and_execute step, so it was dropped at the handoff boundary and never produced step chaining. - Add --auto and --next --auto entries to progress.md <flags> - Update progress.md <process> to explicitly list --auto as a passthrough arg - Add --auto chaining logic to next.md show_and_execute: after each step completes, re-invoke /gsd:progress --next --auto until milestone complete or a blocking decision is required - Add regression test (4 assertions) covering all three fix points Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(#14): bump lint-test-file-count progress ceiling for bug-14 test bug-14-progress-auto-flag-dropped.test.cjs resolves to the "progress" effective prefix and legitimately grows the cluster to 6. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(#14): add changeset fragment Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(#14): address review feedback — differentiate duplicate tests, scope assertions to specific blocks Test 2 now extracts the <process> block and asserts --auto within it, distinguishing it from test 1's <flags>-level check. Remaining assertions use semantic token matches (--auto, --next --auto) that are robust to benign reformatting. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
3f9eb43054 |
fix(#21): add YAML frontmatter to STATE.md template (#151)
* fix(#21): add YAML frontmatter to STATE.md File Template sections Both template files (get-shit-done/templates/state.md and sdk/prompts/templates/state.md) lacked a YAML frontmatter block in their File Template section. When an AI agent creates .planning/STATE.md from the template, the file had no frontmatter until the first state.* mutation ran syncStateFrontmatter — leaving the init→first-write window with nothing for frontmatter consumers (current_phase, status, progress.*) to read. Adds a minimal frontmatter block with gsd_state_version, status, and a zeroed progress skeleton matching the shape buildStateFrontmatter produces. syncStateFrontmatter will replace these placeholders on the first state write. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(#21): bump lint-test-file-count state ceiling for bug-21 test Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(#21): add changeset fragment for STATE.md template frontmatter fix Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(#21): address review — dual-template equality guard, progress schema assertion, version annotation - Add inline comment to gsd_state_version in both templates documenting that syncStateFrontmatter overwrites the value on first state.* call - Sync sdk/prompts/templates/state.md File Template block to match get-shit-done/templates/state.md (add Deferred Items section, fix Pending Todos blurb) — templates were diverged - Add parseFrontmatter() helper to test file for value-aware parsing - Add per-template test: progress.total_plans === 0 and progress.completed_plans === 0 - Add cross-template byte-equality assertion to catch future drift - Add note to parseFrontmatterKeys that it does not handle list-valued fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
b533f71857 |
chore: introduce CommandRoutingHub and migrate phase-command-router (PoC) (#3828)
* feat(routing): add CommandRoutingHub with behavioral test suite (#3788) Introduces createHub({ mode, sdkLoader, cjsRegistry, manifest }) and hub.dispatch({ family, subcommand, args, cwd, raw }) -> Result with a closed 6-value ERROR_KINDS frozen enum. Hub never throws, never prints, and enforces no transparent fallback between sdk/cjs modes. 34 behavioral tests cover all errorKind values, mode fixation, and the no-throw contract. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(routing): migrate phase-command-router to CommandRoutingHub (#3788) Rewrites phase-command-router.cjs to dispatch through CommandRoutingHub. Public entry point routePhaseCommand({ phase, args, cwd, raw, error }) is unchanged. The adapter determines mode (sdk/cjs) from env + tryLoadSdk(), constructs a hub, dispatches, and translates the pure Result back to output()/error() calls. New behavioral test suite (23 tests) replaces the old mock-heavy approach and includes two integration tests through the real hub. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(routing): ADR + glossary + changeset for CommandRoutingHub (#3788) Adds ADR-3788 documenting the hub's design contract (pure result, fixed mode, closed 6-value errorKind enum, no transparent fallback). Adds Command Routing Hub glossary entry to CONTEXT.md and a one-paragraph reference to ARCHITECTURE.md. Changeset fragment records the Changed entry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(docs): rename ADR to sequential convention 0012 (#3788) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(inventory): register CommandRoutingHub in INVENTORY (#3788) Add command-routing-hub.cjs row to docs/INVENTORY.md CLI Modules table, bump headline count from 72 to 73, and regenerate INVENTORY-MANIFEST.json via scripts/gen-inventory-manifest.cjs --write. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(adr): add 0012 to ADR index (#3788) Add entry for 0012-command-routing-hub.md to the index table in docs/adr/README.md so the enh-3271-sdk-adr-structure lint passes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(lint): bump phase test-file ceiling to accommodate command-router suite (#3788) phase-command-router.test.cjs added by the CommandRoutingHub migration pushes the phase prefix cluster from 4 to 5 test files. Bump the allowlist ceiling from 4 to 5 (issue 3788) so lint-test-file-count passes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(routing): preserve phase.mvp-mode JSON error and ROADMAP scan through hub (#3788) mvp-mode was never registered in the SDK; the pre-#3788 CJS router always dispatched it via the CJS handler even when sdkAvailable was true. After the hub migration, SDK-mode hubs (Docker, where the SDK build exists) sent mvp-mode to the SDK bridge, which returned SdkDispatchFailed with reason 'unknown' instead of the expected 'usage' code, and failed ROADMAP lookups. Fix by short-circuiting mvp-mode to the CJS handler before hub construction, matching the pre-migration observable behaviour. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(adr): note SDK-incomplete subcommand limitation in ADR-0012 (#3788) * fix(inventory): bump CLI Modules headline to 74 after rebase onto main (#3788) Upstream added code-review-flags.cjs (72→73) at the same time our branch added command-routing-hub.cjs. After rebase both modules exist (74 total) but the headline stayed at 73; bump to 74. * fix(routing): remove dead mvp-mode handler from cjsRegistry (#3788) The cjsRegistry['phase']['mvp-mode'] handler (previously lines 65–68) was unreachable: the early-return bypass at line 56 intercepts mvp-mode before hub construction in CJS mode, and in SDK mode cjsRegistry is passed as undefined. Remove the dead handler; all 57 tests still pass. * docs(adr): correct router count in ADR-0012 (#3788) The context section cited "eight" routers including "frontmatter" but there is no frontmatter-command-router.cjs. The actual count is seven: phase, phases, roadmap, state, verify, validate, init. * fix(routing): guard missing subcommand + use ERROR_KINDS constant (#3788) Two fixes in phase-command-router.cjs: 1. Add early-return for missing subcommand before hub construction. Pre-#3788 the routeCjsCommandFamily fell through to error() for undefined args[1]; post-#3788 the hub's manifest check skips falsy subcommands, which would have sent bare 'phase' into SDK dispatch in SDK mode instead of the expected "Available: ..." error message. 2. Switch on ERROR_KINDS.UnknownCommand instead of bare 'UnknownCommand' string, per ADR-0012's closed-enum contract ("callers switch on ERROR_KINDS values, not bare string literals"). * docs(routing): fix factual errors in ARCHITECTURE, ADR-0012, changeset (#3788) Three corrections: 1. ARCHITECTURE.md: softened "All CJS command family routers dispatch through CommandRoutingHub" — only phase-command-router.cjs is migrated in this PR; remaining routers still use routeCjsCommandFamily and migrate in follow-up issues. 2. ADR-0012: corrected the SDK mvp-mode claim. The ADR said "the SDK has no equivalent entry" but sdk/src/query/command-static-catalog- domain.ts:104-105 registers phase.mvp-mode. The actual reason for the early-return bypass is divergent ROADMAP scan behaviour and error reason codes, not SDK absence. 3. .changeset/mellow-tigers-gather.md: corrected pr: 1 → pr: 3828. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
a7abc6df2f |
fix(3657): skip false-fail when pristine hash drifts after GSD update (#3767)
* test(3657): RED+shape-lock for verify-reapply-patches pristine-drift Adds tests/bug-3657-verify-reapply-patches-pristine-drift.test.cjs: - Core regression: exits 0 with reason=OK_PRISTINE_DRIFT_DETECTED when on-disk gsd-pristine/ hash does not match backup-meta.json.pristine_hashes - Counter-tests: real FAIL_USER_LINES_MISSING still caught when hashes match; over-broad mode unchanged when backup-meta.json is absent; clean run reports 0 failures when everything matches - Multi-file: drift + real-failure handled independently per file Updates tests/bug-2969-verify-reapply-patches.test.cjs REASON shape-lock to include OK_PRISTINE_DRIFT_DETECTED (added by the #3657 fix). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(3657): verify-reapply-patches skips pristine when hash drifts When gsd-pristine/ is refreshed to a newer GSD version after a backup is captured, the on-disk pristine's SHA-256 no longer matches the hash recorded in backup-meta.json.pristine_hashes. Using the wrong-version pristine as the diff baseline inverts the delta: every line the upstream removed between the two versions appears as a "user-added line that must survive", producing spurious FAIL_USER_LINES_MISSING false positives (Bug #3657). Fix: - Add sha256() and readPristineHashes() helpers to verify-reapply-patches.cjs - In verifyFile(), when a pristine_hashes entry exists for the file, compare the on-disk pristine's SHA-256 against it before accepting the baseline - On hash mismatch, return immediately with status=ok and the new REASON.OK_PRISTINE_DRIFT_DETECTED code, skipping the diff rather than false-failing - When no pristine_hashes entry exists (older installer / absent backup-meta), fall through to the pre-fix behaviour (use on-disk pristine as-is) - Export sha256, readPristineHashes, and OK_PRISTINE_DRIFT_DETECTED New REASON code OK_PRISTINE_DRIFT_DETECTED is added to the frozen enum. Exit code contract is unchanged: 0 for gate pass (including skipped-due-drift files), 1 for real user-content failures, 2 for structural errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(3657): update changeset to reference PR #3767 * fix(3657): surface drifted_files in verify-reapply-patches JSON report Extend the top-level JSON report shape with two additive fields: - `drifted: N` — count of files skipped due to pristine-snapshot drift - `drifted_files: [...]` — relative paths of those files Per-file shape is unchanged (status:'ok' + reason:OK_PRISTINE_DRIFT_DETECTED) for backward compat. Drift still exits 0; `failures` count is unaffected. This gives workflow Step 5a structured data to gate on so drifted files are no longer silently treated as a full PASS (codex adversarial-review finding 1). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(3657): reapply-patches workflow halts on drifted files instead of silent pass Insert a "Step 5a: drift check" block between the exit-code check and the failures check in workflows/reapply-patches.md Step 5a. The new block: 1. Parses `drifted` + `drifted_files` from the JSON report (added in the companion prod-code commit). 2. When DRIFTED_COUNT > 0, emits a formatted HALT message naming each drifted file and instructs the user to re-baseline before re-running. 3. Sets DRIFT_DETECTED=true and exits non-zero so subsequent steps cannot execute while drift is unresolved. Drift is a distinct third state: it is not a failure (no missing user lines were proven) but it is also not a clean pass (the diff was skipped entirely). Existing pass/fail logic for VERIFY_STATUS and failures count is unchanged. Closes the silent-skip gap identified in codex adversarial-review finding 1. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(3657): assert drifted_files report shape + workflow Step 5a drift check Finding 1 (BLOCKER) — three new tests in bug-3657 test file: - Single drifted file: drifted=1, drifted_files contains the file path, failures=0, per-file shape unchanged (backward compat). - Multi-file drift: drifted=2, drifted_files lists both paths, clean file absent from array. - No-drift baseline: drifted=0, drifted_files=[] always present in output. Finding 2 (WARNING) — structural test on workflow source: - Asserts Step 5a contains "Step 5a: drift check" heading. - Asserts DRIFTED_COUNT, drifted_files, and DRIFT_DETECTED are referenced (confirming the gate exists and uses the structured report fields). - Asserts drift-check block appears before VERIFY_STATUS check (exit-code is 0 for drift, so the drift check must precede the non-zero gate). Also updates bug-2969 shape-lock to include the two new additive fields (drifted, drifted_files) per the contract change in the prod-code commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(3657): address pr-review-toolkit + codex review + CI failures - lint-tests: add // allow-test-rule: source-text-is-the-product at file top of bug-3657 test file; the inline comment at line 477 was a prose sentence, not a file-level annotation, so the lint scanner did not recognise it as the bypass token - Windows test failures (4 subtests): normalize relPath to forward slashes before pristineHashes key lookup in verifyFile(); on Windows path.join produces backslash-separated relPath values but backup-meta.json stores keys with forward slashes, causing the hash lookup to silently return undefined, falling through to use-as-is mode and producing the same false FAIL_USER_LINES_MISSING that the fix was meant to prevent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tests): bump verify allowlist ceiling 9→10 for bug-3657 test file Adding tests/bug-3657-verify-reapply-patches-pristine-drift.test.cjs in the previous commit pushed the verify module from 9 to 10 test files. The lint-test-file-count gate (added in #6313baad on main) enforces that modules cannot exceed their allowlist ceiling, so all 6 test platforms plus lint-tests and coverage failed with: FAIL_EXCEEDS_ALLOWLIST: verify count=10 ceiling=9 The fix is to raise the ceiling from 9 to 10 and set issue=3767. This file does not exist on this branch yet (introduced on main after the branch diverged) so we add it here. The merged CI state will see the bumped ceiling and pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
aab01f43e9 |
refactor(tests): consolidate Phase Lifecycle Module — 20 files → 4 (#3741)
* chore(tests): lint rule — cap test files per production module at 2 Adds scripts/lint-test-file-count.cjs with a ratcheted allowlist (scripts/lint-test-file-count.allowlist.json) capturing today's 30 violating clusters as a ceiling. New entries blocked at PR time; reductions ratchet automatically. Wires into .github/workflows/test.yml as a new step in lint-tests. Refs #3737 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(tests): consolidate Phase Lifecycle Module — 20 files → 4 - Merge 10 CJS bug-fix test files into tests/phase.test.cjs - Merge sdk/src/phase-runner-types.test.ts + sdk/src/phase-prompt.test.ts into sdk/src/phase-runner.test.ts (97 → 152 tests, 0 failures) - Rename 4 mis-attributed test files out of phase cluster: phase-researcher-app-aware → gsd-researcher-app-aware phase-researcher-flow-diagram → gsd-researcher-flow-diagram feat-3023-phase-type-models → feat-3023-model-phase-types phase-6-cjs-sdk-seam-contracts → cjs-sdk-bridge-seam-contracts - Fix phasePlanIndex (#3430): non-canonical plan filename warning now surfaces in data.warnings[] as "Ignored noncanonical plan files: ..." instead of a separate singular data.warning field - Update allowlist: phase ceiling 20 → 4 (closes #3740) - Add Phase Lifecycle Module glossary entry to CONTEXT.md Closes #3740 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(phase-roadmap-mutation): replaceInCurrentMilestone handles active milestone inside <details> block When the active milestone is wrapped in a <details> block (e.g. user collapsed it, or milestone transition), the after-</details> slice is empty or contains only footer text — the pattern never matches and the replacement is silently dropped. Fix: when after.replace() produces no change, fall back to replacing inside the last <details>...</details> block. Shipped-milestone blocks are untouched because only the last <details> block is targeted. Closes #2641 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(changeset): add required type/pr frontmatter to 3740 fragment Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
6313baad63 |
chore(tests): lint rule — cap test files per production module at 2 (#3738)
* chore(tests): lint rule — cap test files per production module at 2 Adds scripts/lint-test-file-count.cjs with a ratcheted allowlist (scripts/lint-test-file-count.allowlist.json) capturing today's 30 violating clusters as a ceiling. New entries blocked at PR time; reductions ratchet automatically. Wires into .github/workflows/test.yml as a new step in lint-tests. Refs #3737 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(tests): add docs-exempt to changeset fragment Internal CI lint rule — no user-facing docs impact. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |