Commit graph

3 commits

Author SHA1 Message Date
AgentSeal
dcd47e65f5 fix(act): refuse to apply a plan whose target changed since it was built
Plans serialize the full post-edit file content at build time, so a
target edited between the preview and the interactive confirm would be
silently overwritten with stale content (recoverable via backup, but a
silent violation of the dry-run-shows-exactly-what-changes principle).

- PlannedChange edit/create variants gain optional expectedHash: sha256
  of the raw on-disk bytes the plan was built from (hashed before the
  BOM strip), null when the plan expects the file to be absent,
  undefined to skip validation (framework back-compat).
- plans.ts sets it everywhere a target is read: ConfigDocs hashes the
  raw buffer it parses, and the marker builders hash the file behind a
  shared markerChange helper.
- runAction validates all expected hashes after snapshotting and before
  the first mutation; a mismatch throws "<path> changed since the plan
  was built; re-run codeburn optimize --apply", removes the backup dir,
  and journals nothing. No rollback is involved since nothing mutated.

Tests: stale edit target rejected with no journal record and no backup
dir left, expects-absent plan rejected when the file appeared, matching
hash still applies, and a hash-less change still applies unchecked.
2026-07-03 11:20:59 +02:00
AgentSeal
92d970196e fix(act): scope project-scope removals, --yes safety, --only validation (#604)
Review fixes plus one coordinator amendment on top of the initial
optimize --apply implementation.

- mcp-project-scope no longer strips a server from every projects[*]
  container in ~/.claude.json: only the top-level entry and the
  finding's cold projects lose it, and the cwd's own config files count
  as cold only when the cwd is in the cold list. The plan preview
  annotates ~/.claude.json with the project entries that lose the
  server.
- unused-mcp findings are now appliable (remove-everywhere mcp-remove
  plans, same as low-coverage).
- Notes are rendered under manual findings too, so an all-unparseable
  config surfaces its parse error instead of a bare "manual".
- ConfigDocs strips a leading UTF-8 BOM before JSON.parse.
- claude-md plans are excluded from --apply --yes (they write to
  cwd/CLAUDE.md); they apply via the interactive picker or an explicit
  --only selection, and --yes prints them as skipped with the reason.
- --only with an unknown or not-appliable id errors to stderr with the
  run's valid appliable ids and exit code 2.
- EOF at the interactive prompt prints "Nothing applied." and exits 0;
  an answer that arrives together with EOF is still honored.

Adds end-to-end tests driving runOptimizeApply over injected stdio and
a fixture home: --yes output with journal ids and undo hints, picker
parsing, --only filtering and validation, EOF, claude-md skip, the
projects[*] over-deletion regression, manual-note rendering, and BOM
configs.
2026-07-03 11:14:06 +02:00
AgentSeal
0dd54366b7 feat(act): optimize --apply for config-class fixes (#604)
Add stable kebab-case finding ids to every optimize detector and to the
JSON report, then route the config-class findings through the action
journal so they can be applied and undone.

- optimize.ts: id on every WasteFinding and OptimizeJsonReport entry;
  appliable findings also carry a machine-readable apply payload (mcp
  server list, project-scope keepers, archive names).
- act/plans.ts: planFor(finding) builds concrete, journaled file
  mutations for mcp-remove, mcp-project-scope, skill/agent/command
  archives, CLAUDE.md rule blocks, and the bash output cap. JSON edits
  preserve the rest of the document (2-space indent, trailing newline);
  unparseable config files are reported and skipped, not fatal.
- act/optimize-apply.ts: codeburn optimize --apply with a plain-readline
  confirm, plus --yes, --dry-run, and --only; prints each journal id and
  the undo hint. --apply with --json exits 2.

Tests cover mcp remove/undo, project-scope global-to-project move,
unparseable-file skip, archive collision suffixing, CLAUDE.md marker
idempotency, a byte-identical dry-run tree hash, and a finding-id guard.
2026-07-03 10:41:29 +02:00