Skip to content

v0.14.3 - a planted link can no longer redirect the project config

Choose a tag to compare

@github-actions github-actions released this 14 Oct 23:49
· 53 commits to main since this release
v0.14.3
efdd193

A planted link can no longer redirect the project config

Security

  • The project config is read and written only inside its own folder. A link planted at the config file or at a folder above it (a junction on Windows, a symlink on POSIX) made the conductor read a file outside the project, and made scripts/configure.mjs read, back up and write outside it. hooks/coalface-conductor.js now accepts a project config only when its real path is exactly its folder's real path plus the literal path the walk built; a refused file counts as absent and the report names it with the reason "it resolves outside its folder" (a permission-denied file keeps "unreadable"); the Antigravity adapter shares the read. scripts/configure.mjs pins the config it finds, the file it writes and the .bak copy before anything is read or written, and on a refusal prints one FAIL line and writes nothing. Witnesses: hook tests 71 to 85, configure tests 16 to 25. Named residue: check and use are two acts, a hard link cannot be told from a file, and a differently cased existing folder on a case-insensitive volume is refused.

Changed

  • The conductor is wired in exec form (CWK2-027): hooks/hooks.json now sets "command": "node" with the script path in "args" instead of a shell string with escaped quotes. Claude Code 2.1.299 takes this form; the vendor hooks reference (code.claude.com/docs/en/hooks, read 2026-10-15) says path placeholders such as ${CLAUDE_PLUGIN_ROOT} are substituted into command and into each args element as plain strings, with no shell, and that node plus a script path works on every platform. CoalWash ships the same shape in v1.12.2. scripts/verify.mjs now checks it; platform-configs/hooks.json is the Antigravity template with its own schema and is unchanged.
  • The wallet's dollar invariant is stated as conditional (skills/coalface/SKILL.md Wallet and description, README.md): the swarm fits inside the estimated solo dollar cost only when worker tiers are cheaper than main (CoalTipple delegate-down, or a cheaper model the user sets); with the default main-equivalent workers it can exceed solo dollars, and no budget stop exists. The benchmark figures are unchanged.
  • The release canon is adopted by blob id for three files (scripts/verify-release-shape.test.mjs, scripts/secret-gate.test.mjs, .coderabbit.yaml), with the git-spawn census pins re-pinned to the new blobs. Fixture git no longer waits on an editor, a prompt or a signer, and never signs with the operator's key (internal release tooling and tests; no shipped change).
  • The release canon is re-adopted at .github 690c2de (scripts/release-notes.mjs included, superseding its first adoption above), and the hold on scripts/release-notes.test.mjs is lifted. Adopted at the canon blob, scripts/release-notes.test.mjs (7e779ef8, canon, later than 690c2de), scripts/release-notes.mjs (f8d998d8), scripts/lib/release-shape.mjs (bfb29332), scripts/lib/release-shape.test.mjs (771a7e60) and .coderabbit.yaml (0d5a8860); scripts/verify-release-shape.test.mjs is fa8a730d. Neither release-notes file carries a census pin (internal release tooling and tests; no shipped change).
  • The secret scanner, the gate and both hooks are re-synced byte for byte: scripts/lib/secret-scan.mjs (270a21a2, unchanged) and scripts/secret-scan.test.mjs (a0319dcd) from Bankfire bd328f2, scripts/secret-gate.mjs (856956a1) and scripts/secret-gate.test.mjs (2f066650) from the .github canon, and .githooks/pre-commit and .githooks/pre-push whole at 1979bcaf. The gate and the hooks now state what the scan does not catch (a credential inside a URL or connection string, an HTTP authentication header whose token is not provider-shaped, a key split across lines), and SECURITY.md says the same (internal gate; no shipped change).
  • The git-spawn census is the flock's shared one, adopted by blob id (scripts/lib/git-env-census.mjs 13f8d95c, its test 972d9ca8 and its vectors file 8147dd7a, from .github), and the room's own lexer census is removed. gitTestEnv is re-exported from scripts/lib/git-env.mjs so the census trusts it by name; the room's one pin (scripts/secret-gate.mjs, which keeps GIT_INDEX_FILE on purpose) lives in scripts/lib/git-spawn-room.mjs and is measured by scripts/git-env-census-room.test.mjs (internal gate; no shipped change).
  • The claude.ai ZIP workflow is re-copied from the canon (.github/workflows/claude-ai-zips.yml, blob 686f200a): while no stable Release exists, a workflow_dispatch with the newer pre-release tag and launch_form=true re-points the one launch-form Release (draft, empty its assets, move its tag); a tag push alone re-points nothing (internal release tooling; no shipped change).
  • The test runner is the flock's wave runner and judges the suite by the TAP: each test file runs as its own node --test --test-reporter=tap child through scripts/lib/wave-run.mjs (3119cb7d, with its test fd578cfd and the scripts/lib/stdout-sync.mjs preload 27bd81af) and admits files by the live machine reading (scripts/lib/machine-reading.mjs, 1c550b66, byte-equal to the skill's own copy), all adopted by blob id, under the heap cap, a clock per test, a clock per file and a whole-run deadline, and a file that exits 0 before its tests register is VACUOUS and the run is red. scripts/test-expect.json holds a count floor for every roster file but one and, for scripts/git-env-census-room.test.mjs, the expected test names, so a test that vanishes from a file that still exits 0 turns the run red (scripts/lib/suite-run.mjs; testing.md's TAP-names rule). The unreleased single node --test child with --test-force-exit that preceded it is removed (internal gate; no shipped change).

Fixed

  • The pointer gate reads code fences with one shared scanner (tilde fences and indented fences included), and a vX.Y.Z:path citation in the top entry is checked with git cat-file -e against that tag (internal gate; no shipped change).
  • A vX.Y.Z:path citation in a clone without that tag is a named SKIP, not a FAIL (internal gate; no shipped change).