Commit Graph

15 Commits

Author SHA1 Message Date
j2h4u
f850952332 fix(state): preserve frontmatter status when body Status field is missing
syncStateFrontmatter() rebuilds YAML frontmatter from the body on every
writeStateMd() call. If an agent removes or omits the Status: field from
the body, buildStateFrontmatter() defaults to 'unknown', overwriting a
previously valid status (e.g., 'executing').

Fix: read existing frontmatter before stripping, and preserve its status
value when the body-derived status would be 'unknown'. This makes
frontmatter self-healing — once a status is set, it persists even if the
body loses the field.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:33:13 +05:00
Tom Boucher
3e2c85e6fd refactor: consolidate STATE.md field helpers, fix command injection in isGitIgnored
Refactoring:
- Extract stateReplaceFieldWithFallback() to state.cjs as single source of truth
  for the try-primary-then-fallback pattern that was duplicated inline across
  phase.cjs, milestone.cjs, and state.cjs
- Replace all inline bold-only regex patterns in cmdPhaseComplete with shared
  stateReplaceField/stateExtractField helpers — now supports both **Bold:**
  and plain Field: STATE.md formats (fixes the same bug as #924)
- Replace inline bold-only regex patterns in cmdMilestoneComplete with shared helpers
- Replace inline bold-only regex for Completed Phases/Total Phases/Progress
  counters in cmdPhaseComplete with stateExtractField/stateReplaceField
- Replace inline bold-only Total Phases regex in cmdPhaseRemove with shared helpers

Security:
- Fix command injection surface in isGitIgnored (core.cjs): replace execSync with
  string concatenation with execFileSync using array arguments — prevents shell
  interpretation of special characters in file paths

Tests (7 new):
- 5 tests for stateReplaceFieldWithFallback: primary field, fallback, neither,
  preference, and plain format
- 1 regression test: phase complete with plain-format STATE.md fields
- 1 regression test: milestone complete with plain-format STATE.md fields

854 tests pass (was 847). No behavioral regressions.
2026-03-19 15:05:20 -04:00
j2h4u
85a65fd384 fix(state): parse compound Plan field in advance-plan command
`cmdStateAdvancePlan` expected separate `Current Plan` and
`Total Plans in Phase` fields, but the current STATE.md template
uses a single compound field: `Plan: X of Y in current phase`.

Now tries legacy separate fields first, then falls back to parsing
the compound format. Preserves the compound format when writing back
(replaces only the plan number). Also handles `Last activity`
(lowercase) field name from current template.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 21:28:26 +05:00
j2h4u
e1b3277869 fix(state): derive total_phases from ROADMAP when phases lack directories
Phases listed in ROADMAP.md but not yet planned (no directory on disk)
were excluded from total_phases, causing premature milestone completion.
Now uses Math.max(diskDirs, roadmapCount) via filter.phaseCount.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:07:53 -06:00
j2h4u
b863ed6de5 fix(state): scope phase counting to current milestone
Extract getMilestonePhaseFilter() from milestone.cjs closure into core.cjs
as a shared helper. Apply it in buildStateFrontmatter and cmdPhaseComplete
so multi-milestone projects count only current milestone's phases instead
of all directories on disk.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:07:49 -06:00
Lex Christopherson
9c27da0261 fix(windows): cross-platform path separators, JSON quoting, and dollar signs
- Add toPosixPath() helper to normalize output paths to forward slashes
- Use string concatenation for relative base paths instead of path.join()
- Apply toPosixPath() to all user-facing file paths in init.cjs output
- Use array-based execFileSync in test helpers to bypass shell quoting
  issues with JSON args and dollar signs on Windows cmd.exe

Fixes 7 test failures on Windows: frontmatter set/merge (3), init
path assertions (2), and state dollar-amount corruption (2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:34:36 -06:00
Ethan Hurst
c9e73e9c94 fix(quick-1): remove HIGH severity test overfitting in 4 test files
- frontmatter.test.cjs: delete FRONTMATTER_SCHEMAS describe block (4 tests asserting on lookup table shape)
- core.test.cjs: replace 12 per-profile per-agent matrix tests with 1 structural validation test
- commands.test.cjs: URL test uses URL.searchParams.get() instead of raw string includes
- state.test.cjs: date assertion uses before/after window to handle midnight boundary safely
2026-02-26 05:49:31 +10:00
Ethan Hurst
d5ef3b4f1f test(09-02): add cmdStateResolveBlocker and cmdStateRecordSession tests
- 5 tests for cmdStateResolveBlocker: case-insensitive removal, None placeholder on empty, missing text error, missing STATE.md, no-match succeeds
- 5 tests for cmdStateRecordSession: update all fields, timestamp-only update, None default resume-file, missing STATE.md, no session fields returns false
2026-02-26 05:49:31 +10:00
Ethan Hurst
763ff97764 test(09-02): add cmdStateAdvancePlan, cmdStateRecordMetric, cmdStateUpdateProgress tests
- 4 tests for cmdStateAdvancePlan: advance, last-plan complete, missing STATE.md, unparseable fields
- 4 tests for cmdStateRecordMetric: append row, None-yet placeholder, missing fields error, missing STATE.md
- 4 tests for cmdStateUpdateProgress: percent calculation, zero plans, missing Progress field, missing STATE.md
2026-02-26 05:49:31 +10:00
Ethan Hurst
29a87cba7c test(09-01): add cmdStateLoad, cmdStateGet, cmdStatePatch, cmdStateUpdate CLI tests
- 3 cmdStateLoad tests: state+config+roadmap detection, missing STATE.md, --raw flag output
- 5 cmdStateGet tests: full content, bold field extraction, section extraction, missing field error, missing file error
- 5 cmdStatePatch/cmdStateUpdate tests: batch update, failed fields reporting, single field update, field not found, missing STATE.md
2026-02-26 05:49:31 +10:00
Ethan Hurst
1ca7df13a0 test(09-01): add stateExtractField and stateReplaceField unit tests
- 4 stateExtractField tests: simple extraction, colon-in-value, null on missing, case-insensitive
- 4 stateReplaceField tests: replace value, null on missing, preserves surrounding content, round-trip
2026-02-26 05:49:31 +10:00
Lex Christopherson
0ca1a59ab3 feat: add YAML frontmatter sync to STATE.md for machine readability 2026-02-25 07:20:14 -06:00
Colin Johnson
77d434709d Fix STATE.md decision corruption and dollar handling (#701) 2026-02-23 09:55:54 -06:00
Lex Christopherson
3a56a207a5 fix(gsd-tools): support --cwd override for state-snapshot
Add --cwd <path> / --cwd=<path> support so sandboxed subagents running
outside the project root can target a specific directory. Invalid paths
return a clear error. Tests ported to tests/state.test.cjs (the old
monolithic test file was split into domain files on main).

Closes #622

Co-Authored-By: Colin Johnson <colin@solvely.net>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:31:06 -06:00
Tyler Satre
fa2e156887 refactor: split gsd-tools.test.cjs into domain test files
Move 81 tests (18 describe blocks) from single monolithic test file
into 7 domain-specific test files under tests/ with shared helpers.
Test parity verified: 81/81 pass before and after split.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:30:54 -05:00