Skip to content

v3.23.4 - a project config can no longer turn on automatic fixes

Choose a tag to compare

@github-actions github-actions released this 16 Oct 22:24
· 106 commits to main since this release
v3.23.4
eec6e15

A project config can no longer turn on automatic fixes

A cloned repository's config could set autoFixMode: safe and make rot-canary edit files without showing the menu; safe now counts only from your own global config. plugin/ moved (the three hooks, the rot-canary skill), so this is a PATCH release.

Security

  • autoFixMode from a project config may only lower it. The order is off < interactive < safe: a project value can keep the mode or lower it, never raise it, and safe counts only when it comes from the user's global config (~/.claude/.coalmine.json); with no global safe, a project safe reads as interactive (CR row 17, CWK2-044). The hooks apply the clamp on every run (all three Node hooks, and the PowerShell fallbacks' config merge, which emit nothing); the conductor and the stop hook say what is in effect: [CoalMine] autoFixMode in effect: <mode> (<why>) on the session-start context and on the session-end scan report, only when a config sets the key. A manual /rot-canary run has no hook in front of it: there the same rule comes from the skill text, which is a mitigation an agent follows, not a clamp a machine enforces, so it is not claimed as closed. This reverses on purpose the 3.22.3 sentence that a project config you did not write can set the key to safe: a cloned repository could turn on automatic edits. — test: scripts/lib/autofix-clamp.test.mjs, scripts/lib/ps-config.test.ps1

Fixed

  • The touch hook's marker append is bounded by MARKER_MAX_BYTES. An entry that would take the marker past 1 MiB is dropped silently (Phoenix #4) instead of written, because the reader treats a marker over the bound as absent and the stop hook would lose the whole touched-file list; an entry landing exactly on the bound is written. Not covered: two hooks of one session appending in parallel, each under the bound by less than one entry, can still land one entry past it. — test: scripts/lib/marker-append-bound.test.mjs
  • The Antigravity Stop hook resolves the project from workspacePaths. In Antigravity mode it took the git root of its own working folder, which is the plugin folder when the plugin is registered outside the project, while the touch hook and the conductor already used the workspace; it now uses workspacePaths[0] for the config, the language probe and the MEMORY.md probe. Claude Code is unchanged. — test: scripts/lib/ag-plugin.test.mjs

Changed

  • Internal — the release workflow .github/workflows/claude-ai-zips.yml builds reproducible ZIPs and lists a Release's assets before it downloads, as the org canon does (CR row 7, thread t129 (4)): the stage step takes the tag commit's time as SOURCE_DATE_EPOCH, the zip step runs under TZ=UTC as find | LC_ALL=C sort | zip -X -D -@, and the step that reads the Release's existing assets fails on an API error instead of treating it as a first run. The first real run is this release's tag push. This ships nothing in plugin/.
  • Internal — four front-door-links files are adopted from the org canon by blob (the outward half of the link check): .github/workflows/front-door-links.yml f0cc9ec0 (its job is named front-door-links), scripts/front-door-links.mjs 3793a056, scripts/lib/front-door-links.mjs 7df59db6 and scripts/front-door-links.test.mjs 3cff2b30 (blob ids as git hash-object reads them). This ships nothing in plugin/.