* test(#948): add regression tests for no-op write guard and record-session auto-create (#944) Red before fix: 11/15 tests fail. Green after: 15/15. Covers zero-match patch byte-identity, milestone_name preservation, stopped_at frontmatter-wins, record-session auto-create fallback, and adversarial fixtures (CRLF, empty body, non-canonical labels). Also registers bug-948-state-noop-write-guard.test.cjs in the state bucket of lint-test-file-count.allowlist.json. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#948): guard STATE.md no-op writes; preserve milestone_name/stopped_at (closes #944) Shared root cause: `readModifyWriteStateMd` wrote STATE.md unconditionally even when the transform produced no change, and `syncStateFrontmatter` re-derived frontmatter from the possibly-stale body on every write. Three coordinated fixes in src/state.cts: 1. readModifyWriteStateMd: add no-op guard — when transform result === input content, skip the write entirely (no platformWriteSync, no last_updated bump, no frontmatter re-derive). Fixes #948 zero-match phantom write and the #944 phantom last_updated bump. 2. syncStateFrontmatter: extend existing-frontmatter preserve logic — fall back to existingFm['milestone_name'] / existingFm['milestone'] when the derived value is the template placeholder 'milestone' (getMilestoneInfo returns this literal when it cannot match the version in ROADMAP.md); prefer existingFm['stopped_at'] / existingFm['paused_at'] over a body-derived value (the frontmatter value, written by the canonical record-session path, wins over stale historical body lines). Mirrors the fallback already in cmdStateJson. 3. cmdStateRecordSession: when --stopped-at / --resume-file are supplied but body labels are absent, DWIM auto-create a canonical ## Session section (mirroring how add-decision / add-blocker / record-metric auto-create their sections). Never return a silent recorded:false when the caller supplied values. SDK check: no sdk/src/state.ts exists in this repo (the comment in cmdStateSnapshot references a sibling concern in the TypeScript SDK codebase, which is a separate repo not present here). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: add changeset for PR #952 (fix #948/#944) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#948): correct stopped_at preserve rule; adjust test for sync behaviour The "always prefer frontmatter stopped_at" rule in syncStateFrontmatter was too aggressive — it broke phase.complete which intentionally updates stopped_at in the body and expects syncStateFrontmatter to pick it up. The primary fix (no-op guard in readModifyWriteStateMd) already prevents the stale-body-overwrites-frontmatter scenario from #948: the file is not written when the transform produces no change, so syncStateFrontmatter never runs on a zero-match patch. The body-derived value can only win when an actual write occurs, which means the body was legitimately updated. Reverted to the original #905 rule for stopped_at/paused_at: fall back to existing frontmatter only when the derived value is absent (empty/null). Also adjusted the sync-suite test to assert what state sync actually does (milestone_name preservation) rather than a stopped_at-wins property that state sync does not have by design. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#944): update existing session block in place (adversarial review) HIGH finding: the DWIM auto-create in cmdStateRecordSession was appending a second ## Session block unconditionally, even when one already existed with non-canonical content (e.g. a markdown table). Both buildStateFrontmatter and cmdStateSnapshot read only the FIRST ## Session block via regex, so the newly-written Stopped at / Resume file values landed in the second, invisible block — frontmatter stopped_at stayed stale and state-snapshot returned nulls. Fix: check for an existing ## Session heading. When one is present, normalize that section in place by replacing its body with canonical **Last session:** / **Stopped at:** / **Resume file:** bold-label lines. Only append a brand-new section when NO ## Session heading exists. LOW finding: the auto-create scaffold emits **Last session:** but cmdStateSnapshot only matched **Last Date:**, so session.last_date was null after auto-create despite a valid timestamp being written. Fix: extend the lastDateMatch regex in cmdStateSnapshot to also accept **Last session:** / Last session: (the form the scaffold writes). Tests: 3 new tests added to bug-948-state-noop-write-guard.test.cjs that confirmed failure against the previous HEAD and pass after this fix: - exactly one ## Session block after record-session with non-canonical existing block - state-snapshot sees correct stopped_at via first Session block (not a duplicate) - state-snapshot session.last_date is non-null after auto-create on body-less file Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#944): improve in-place section replace to cleanly remove old body content The previous regex `/(^## Session[ \t]*$)([\s\S]*?)(?=\n^## |\n*$)/im` with a lazy match consumed nothing after the heading, so old non-canonical body content (e.g. table rows) remained after the new canonical lines. While functionally correct (parsers found the canonical lines first in the FIRST ## Session block), it left stale content in the section. Replace with a negative-lookahead per-line pattern that consumes all content from the heading up to (but not including) the next ## heading, producing a clean section with only the canonical bold-label lines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
147 lines
4.8 KiB
JSON
147 lines
4.8 KiB
JSON
{
|
|
"_doc": "Baseline of modules currently exceeding the 2-test-file limit. Each entry locks in TODAY's exact test filenames as the allowlisted set (identity ratchet). Adding a NEW test file to a capped module fails (novel). Removing one requires pruning this list (stale, ratchet-down). When a cluster drops to ≤ 2, remove its entry entirely. New entries require justification in PR description.",
|
|
"modules": {
|
|
"audit": {
|
|
"files": [
|
|
"audit-fix-command.test.cjs",
|
|
"bug-2659-audit-open-crash.test.cjs",
|
|
"bug-2836-audit-open-summary-uat-drift.test.cjs",
|
|
"bug-2911-audit-open-output-shape.test.cjs"
|
|
],
|
|
"issue": "192"
|
|
},
|
|
"config": {
|
|
"files": [
|
|
"bug-2943-config-get-context-window-default.test.cjs",
|
|
"bug-321-config-defaults-clone-strategy.test.cjs",
|
|
"bug-3227-config-set-model-overrides.test.cjs",
|
|
"bug-442-config-dir-equals-in-path.test.cjs",
|
|
"config-field-docs.test.cjs",
|
|
"config-get-default.test.cjs",
|
|
"config-schema.property.test.cjs",
|
|
"config.test.cjs"
|
|
],
|
|
"issue": "TBD"
|
|
},
|
|
"graphify": {
|
|
"files": [
|
|
"bug-622-graphify-optional-graph-html.test.cjs",
|
|
"graphify-auto-update.slow.test.cjs",
|
|
"graphify-query.test.cjs",
|
|
"graphify-visualization.test.cjs",
|
|
"graphify.test.cjs"
|
|
],
|
|
"issue": "622"
|
|
},
|
|
"intel": {
|
|
"files": [
|
|
"bug-2351-intel-kilo-layout.test.cjs",
|
|
"bug-3290-intel-updater-layout-block.test.cjs",
|
|
"intel.test.cjs"
|
|
],
|
|
"issue": "TBD"
|
|
},
|
|
"milestone": {
|
|
"files": [
|
|
"bug-730-milestone-phase-details-scope.test.cjs",
|
|
"milestone-archive.test.cjs",
|
|
"milestone-helper.test.cjs",
|
|
"milestone-prefixed-convention.test.cjs",
|
|
"milestone-summary.test.cjs",
|
|
"milestone.test.cjs"
|
|
],
|
|
"issue": "TBD"
|
|
},
|
|
"phase": {
|
|
"files": [
|
|
"bug-214-phase-researcher-write-truncation-contract.test.cjs",
|
|
"phase-dependency-levels.test.cjs",
|
|
"phase.test.cjs"
|
|
],
|
|
"issue": "597"
|
|
},
|
|
"roadmap": {
|
|
"files": [
|
|
"bug-2661-roadmap-sync-parallel.test.cjs",
|
|
"bug-3128-roadmap-plan-count-slug-layout.test.cjs",
|
|
"bug-3599-roadmap-get-phase-project-code-prefix.test.cjs",
|
|
"enh-2447-roadmap-wave-deps.test.cjs",
|
|
"roadmap-mode-field.test.cjs",
|
|
"roadmap-phase-fallback.test.cjs",
|
|
"roadmap.test.cjs"
|
|
],
|
|
"issue": "TBD"
|
|
},
|
|
"runtime-artifact-layout": {
|
|
"files": [
|
|
"runtime-artifact-layout-install-profiles.test.cjs",
|
|
"runtime-artifact-layout-surface.test.cjs",
|
|
"runtime-artifact-layout.test.cjs"
|
|
],
|
|
"issue": "TBD"
|
|
},
|
|
"security": {
|
|
"files": [
|
|
"security-prompt-injection.security.test.cjs",
|
|
"security-scan.security.test.cjs",
|
|
"security.test.cjs"
|
|
],
|
|
"issue": "TBD"
|
|
},
|
|
"state": {
|
|
"files": [
|
|
"bug-21-state-md-template-frontmatter.test.cjs",
|
|
"bug-2630-state-frontmatter-milestone-switch.test.cjs",
|
|
"bug-3127-state-begin-phase-idempotent.test.cjs",
|
|
"bug-3242-state-update-progress-trample.test.cjs",
|
|
"bug-3286-state-write-routing.test.cjs",
|
|
"bug-3454-state-dollar-backreference-growth.test.cjs",
|
|
"bug-397-state-preserve-executor-authored.test.cjs",
|
|
"bug-905-state-syncstatefrontmatter-preserve-scalars.test.cjs",
|
|
"bug-948-state-noop-write-guard.test.cjs",
|
|
"state-acquirestatelock-non-eexist.test.cjs",
|
|
"state-prune.test.cjs",
|
|
"state.test.cjs"
|
|
],
|
|
"issue": "180"
|
|
},
|
|
"verify": {
|
|
"files": [
|
|
"bug-2969-verify-reapply-patches.test.cjs",
|
|
"bug-2994-verify-reapply-patches-installed-path.test.cjs",
|
|
"bug-3381-verify-work-workstream.test.cjs",
|
|
"bug-3657-verify-reapply-patches-pristine-drift.test.cjs",
|
|
"verify-health.test.cjs",
|
|
"verify-mvp-uat.test.cjs",
|
|
"verify-npm-publish.test.cjs",
|
|
"verify-test-quality.test.cjs",
|
|
"verify-work-auto-transition.test.cjs",
|
|
"verify.test.cjs"
|
|
],
|
|
"issue": "3767"
|
|
},
|
|
"install": {
|
|
"files": [
|
|
"bug-410-install-defaults-test-mode-guard.test.cjs",
|
|
"enh-776-install-gemini-hook-events.test.cjs",
|
|
"install-minimal-hooks.test.cjs",
|
|
"install-nested-layout.test.cjs",
|
|
"install-path-detection.test.cjs",
|
|
"install-regressions.test.cjs",
|
|
"install-runtime-artifacts.test.cjs",
|
|
"install-update-marker.test.cjs",
|
|
"install.test.cjs"
|
|
],
|
|
"issue": "TBD"
|
|
},
|
|
"validate": {
|
|
"files": [
|
|
"bug-3129-validate-commit-git-bypass.test.cjs",
|
|
"bug-892-validate-checklist-roadmap-phases.test.cjs",
|
|
"validate-context.test.cjs"
|
|
],
|
|
"issue": "892"
|
|
}
|
|
}
|
|
}
|