Conversation
Bumps the mcp-dev-dependencies group in /mcp with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 26.1.0 to 26.1.1 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 26.1.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: mcp-dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…hestrate + reviews) Full exploration→plan spine for shrinking craft from a 115-command monolith into a native-first system (craft workflow core + folio docs/publishing): - docs/ideas/craft-refactor-proposal.html — adversarial Reviews #1 & #2 + Proposal v2 (native-first, workflow-based breakup) - docs/specs/GRILL-craft-refactor-2026-07-09.md — first-pass grill ledger (7 branches) - docs/specs/SPEC-craft-native-first-breakup-2026-07-09.md — 14 locked decisions, 4-phase plan, 4-axis verification gate - docs/plans/ORCHESTRATE-craft-native-first-breakup.md — executable plan (ORCHESTRATE-only; no worktree, no code) Planning artifacts only — no changes to craft's command/skill tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Commands with a stream redirect such as stderr-to-stdout passed the coarse redirect guard (any non-caret char after the redirect symbol qualifies, including an ampersand) but the fine extraction pattern excluded the ampersand, so grep -oE matched nothing and exited 1. Under this script's set -euo pipefail, a bare VAR=$(pipeline) assignment propagates that as a script-ending failure -- silently, no stderr, surfacing to users as 'PreToolUse:Bash hook error / No stderr output' on completely benign commands piping cat/head output. Appended '|| true' to all four BASH_TARGET extraction pipelines (redirect, tee, cp, touch) so a genuine no-match behaves like the empty-string fallback the existing -z BASH_TARGET checks already handle, instead of killing the hook. Detection is unchanged -- a real write-through target combined with a stderr redirect is still caught. 108/108 pre-existing tests still pass; 5 new tests added, 2 of which reproduce the exact crash against the pre-fix script (verified via git show) to prove they're real regression tests, not decoration.
… dead docs (115→94) (#279) * feat(prune)!: native-first Phase 1a — remove 21 dead-namespace commands (115→94) v3.0.0 increment. Recon-gated prune of deprecated commands with zero external callers, per SPEC-craft-native-first-breakup + Phase 0 recon. Deleted (21): workflow/ (5) + task/ (3) namespaces entirely, check/ (1), git/{init,git-recap,sync} + git/docs/{safety-rails,undo-guide,learning-guide} (true shims → skills/dev/git/references/), site/{nav,init,add,audit,consolidate, theme,create,preview}. Kept 15 as thin aliases (live flow-cli/tutorial/homebrew callers). site/docs/frameworks.md retained. HELD via ADR-002 rich-body gate (restored, NOT deleted): git/docs/refcard, check/gen-validator, workflow/insights — carry unique logic not preserved in their skills. Caught by test_skill_referenced_commands_exist during build. Fixes: bump-version --counts-only + swept 20 files 115→94; count-cascade (plugin.json breakdown, README, exclusions.txt historical README:42 entry); de-brittled test floors (hub >=100→59); OPT_IN drops deleted spec-review; removed obsolete test_git_init suite; repointed 3 true-shim refs in git SKILL.md. Tests: full suite 0 real failures (2676 passed; expected XFAIL/XPASS only); validate-counts 94/45/8 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG * docs(prune): exclude dead docs (specs/plans/archive) from built mkdocs site Phase 1b (v3.0.0). SPEC R1-B2/R1-B6: dead process-artifact dirs leave the PUBLISHED site but stay in-repo/git as live capture targets. No retention rule (C2). - exclude_docs EXTENDED (not overwritten): specs/ added; plans/+archive/ preserved - 12 inbound links into specs/_archive rewritten to GitHub blob URLs (R1-B6 sweep) - 29 stale nav entries + 2 parent headers pointing into excluded dirs removed - mkdocs build --strict exit 0; broken_links + doc-accuracy tests green Done via bounded Stage-2 workflow (docs-exclude agent), verified before commit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG * docs(spec): record native-first refutation — ship Phase 1, drop Phases 2-3 Stage-2 workflow (3 pilots + 4-axis gate + routing test) resolved the gating unknown NO-GO: router can't dispatch cross-plugin AND 3/3 pilots = thin-keep. Native-first thinning premise refuted for these commands; Phase 1 (prune + docs-exclude) is the banked, verified value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG * chore: drop tasks/ execution scaffolding before PR Working artifacts (agent-skills plan/todo + Phase-0 recon) don't belong on dev per merge-cleanup convention. The durable recon finding (delete 21 / hold 3 / native-first refuted) is recorded in the SPEC OUTCOME block. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG * test(git-shim): drop deleted sync.md + git-recap.md from shim-correctness array CI's "Validate Plugin Structure" job (branch-guard bash suites) asserted commands/git/{sync,git-recap}.md exist; Phase 1a deleted them (zero external callers). Removed from the SHIMS map; the 7 kept git aliases remain. This bash suite runs separately from pytest — missed in the pre-push pytest-only pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…irst Phase 1) - .STATUS: Phase 1 prune MERGED (115→94), native-first thinning refuted, Phases 2-3 dropped, verification-gap note (pytest ≠ CI bash suites) - ORCHESTRATE: marked CLOSED with outcome banner (not a live checklist) Durable lessons captured to memory: pytest-doesnt-cover-craft-ci-bash-suites, native-first-thinning-refuted-for-craft-dev-ops, + rich-body-trap refinement. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Completes the doc/website audit for the native-first Phase 1 prune (PR #279). Removes ~264 references to the 21 deleted commands across 40 files; archives 5 whole-doc-about-deleted-command files to docs/archive/deleted-commands-v3/ and drops their mkdocs nav entries. - Strip deleted-command refs: git/{init,sync,git-recap}, git:docs/{safety-rails, undo-guide,learning-guide}, workflow/{stuck,focus,recap,spec-review}, task/{status,output,cancel}, site/{init,add,audit,consolidate,nav,theme, create,preview} - Archive (git mv) + de-nav: git-init docs set + git/sync.md - Fix 5 broken links/anchors to archived/removed content (strict build now clean) - Counts left at 94/45/8 (managed by bump-version.sh); category subtotals are known YELLOW drift, not touched here mkdocs build --strict: clean (0 warnings). validate-counts: green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Fresh grill on the docs-authoring extraction (folio), standing on docs-maintenance merits only (native-first refuted in PR #279). Locks: B1 folio=tools+shared docs-standards (content per-project); B2 caller-based cut (docs:update/changelog stay in craft, authoring→folio); B3 drop DOCS from /do+/hub; B4 duplicate count tooling; B5 history-preserving subtree split, craft v4.0.0 + folio v1.0.0. Supersedes the dropped Phase 3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Tier-4 plan-orchestrator artifact built from GRILL-folio-split (B1–B5). Cross-repo (craft + new folio repo), ORCHESTRATE-only (no worktree yet): P0 caller-audit (gate) → P1 folio scaffold + docs-standards contract + dup count tooling → P2 history-preserving subtree extraction + folio CI → P3 craft amputation v4.0.0 (remove moved cmds, collapse site:deploy, drop DOCS from /do+/hub, MIGRATION-v4) → P4 /folio:do + coordinated 2-repo release. All 5 grill open questions mapped to phase tasks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
…terns branch-guard's HAS_HEREDOC guard only gated Pattern 1 (redirect). Since grep is line-oriented, a heredoc body line that happened to start with touch/tee, or match cp's two-word shape, was scanned as real shell syntax by Patterns 2-4 and could trigger a false bash_write_through confirm on plain commit-message prose. Gate all four patterns on HAS_HEREDOC, same as Pattern 1. 4 new regression tests (117/117 passing); reverting the fix alone (tests unchanged) makes the 3 new false-positive tests fail and leaves the real-detection regression test passing, confirming both the bug and that the fix doesn't weaken genuine write-through detection.
…ied, zero-CI mode pointer Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
…ion amendments Phase 0 OUTCOME recorded (Workflow wf_bf0549a1, adversarially verified, partition_sound): STAYS = docs:update + docs:changelog + site:deploy-as- shell; MOVES = 26; docs:claude-md:* trio = Phase 1 judgment call (leaning STAYS). Grill B2 open question resolved. Zero-CI impact amendments: folio repo must be PUBLIC (private CI would bill against the account pool — post-2026-03 self-hosted runners aren't free either); new Phase 1.5 protection-baseline task (protect-baseline, dev stays hook-guarded only). craft itself unaffected (public, free CI, protection unchanged). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Spec-driven artifacts for executing ORCHESTRATE-folio-split via dynamic Workflow(): W1 fan-out-inside-phases/parent-owns-gates + W2 parent-only- git/absolute-paths (grill-locked), W3 per-phase Workflow map, W4 schema+ adversarial-verify contracts, W5 budget envelope (~1.5-2.5M subagent tokens). Boundaries: agents never run git; every gate needs transcript + verifier sound=true; folio PUBLIC. tasks/plan.md + tasks/todo.md written as working artifacts (untracked, feature-branch bound). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
…er, folio launches ~15 Move-vs-kill pass over the 26-command moves-set (bounded; B1-B5/W1-W2 locked): 8 of 26 are already deprecated (all site:* + nav-update, replaced-by skills that move anyway) — kill at border with ADR-002 rich-body salvage (site-management router is 284 lines, NO references/, vs ~80KB of bodies); site:progress = teaching residue, pure kill. check-links merges into docs:check; site:docs:frameworks demotes to skill reference; claude-md trio RESOLVED: stays in craft as one unit (fixes review B5). Skills: 6 move / 3 stay (callers verified). Final shape: craft 69 / folio ~15+6+6 — 40% less extraction work. Feeds the single post-review amendment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
… ~22 cmds Adversarial-creative review of the post-split surface: classification shows 27 of 69 are ALREADY deprecated shims (v3 skill-migration debt), 2 more shims, 6 routers, 2 references — only 32 genuinely rich. Proposal: complete the shim-kill at v4 (ADR-002 salvage gate, ~12% rich-body base rate from PR #279), kill 2 teaching-residue utils, demote 1 internal ref, subcommand-consolidate ci (8 to 1), arch (4 to 1), code-audits (5 to 1), orch (3 to 1), plan (2 to 1) via savant's proven depth-1 pattern. Result: ~22 commands + ~40 skills. Does NOT re-run refuted native-first (own skills, not third-party). Rider on the v4.0.0 folio release: one major, one migration, one cascade. Self-attacked on 6 angles, all survive with gates (skill slash-invocability check per shim; nested skills excepted). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
…lls) Scoped integration of agent-skills' security-and-hardening, code-simplification, frontend-ui-engineering, and api-and-interface-design as optional content-injected gates inside workflow/drive/fanout — not a 4th orchestration engine, not a change to planning ownership. Avoids the subagent-nesting hazard documented in agent-skills' own AGENTS.md by never adopting its /ship-style persona fan-out inside craft's existing dispatch layers. Builds on SPEC-orchestrator-consolidation-2026-07-04.md.
…ngles recorded SPEC-D's section 6 targets (commands/orch/drive.md, orch.md, workflow-engine) collide with the v4 consolidation proposal (orch 3 to 1); the domain-gate concept is unaffected, only the paths go stale. Header note prevents a parallel session implementing against stale targets; adds two grill angles for when its turn comes (path staleness, external-content dependency policy). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
…ider Folds the 3-lens adversarial review (6 blockers, 9 majors) and the border-filter brainstorm into ORCHESTRATE + SPEC: - B1 mechanism: git filter-repo (subtree split cannot express the set) - B2 ci.yml:92 floor edit in the SAME amputation PR (86 to 60, then 18 at the 3.5 rider) - B3 folio release choreography scoped into Phase 2.4 (homebrew + aggregator workflows, App install, tap manifest, marketplace row) - B4/B5 counts corrected: craft 69 post-split (then ~22 via 3.5), folio 15/6/6; claude-md trio RESOLVED stays as one unit - B6 new docs-content sweep task with grep-zero gate (strict build is false-green for prose refs) - Majors: bare-protection-then-check bootstrap, folio floors retuned, release order folio-first/craft-tag-last + rollback runbook, commit-per-batch dirty-tree discipline, enumerated real test-breakage set, /folio:hub moved to Phase 2, hub DOCS section rebuilt (staying set + breadcrumb) instead of blanket drop, MIGRATION breadcrumbs - Border filter: 7 border kills w/ ADR-002 salvage, check-links merge, frameworks demotion, skills 6-move/3-stay - New Phase 3.5 rider (v4 surface, ~22 cmds) blocked on roster grill; folio site decision resolved (minimal folio-built site at v1.0.0) tasks/plan.md + todo.md slimmed to pointers (ORCHESTRATE is the single task source). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
R1-R4 locked (GRILL-craft-v4-roster): keep hot micro-shims next/done/ refine/brainstorm/check (check discovered as 315L dep shim during table review — 5th hot entry); salvage gate = every dying shim over 150L (12 jobs incl. the dist trio and claude-md trio); consolidation shape = thin router + verbatim bodies to skill references (ADR-002 line-conservation per migration); roster = 18 keep + 5 micro + 3 new routers (ci, arch, code:audit) = 26, tolerance plus-minus 2 with ledger-recorded deviations. Full 69-to-26 disposition in ROSTER-*.md. ORCHESTRATE Phase 3.5 unblocked: now 5 concrete tasks (salvage, kills, consolidations, cascade incl. hub regen + ci.yml floor to 18, suites). The entire v4.0.0 train is now spec-complete. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Planning chain complete: grill (B1-B5) + Phase 0 verified partition + 3-lens adversarial review amendment + border filter + v4 roster (R1-R4, 26 commands) + 33-task execution breakdown. All approved. Phases 1-4 await explicit go; nothing implemented yet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
T1.1 of the v4.0.0 train. Working artifacts (tasks/) ride the branch, deleted before final merge per CP-4. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PCmhbNUV6iSQrx1USQjACG
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ec-review, folio-split) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…assed Phase 2 complete (feature/extraction pushed, PR #1 CI green locally and on GitHub). Pre-Phase-3 gate cleared: T1.6 secrets confirmed real, folio plugin validates, branch protection set, all 15 commands/6 agents/6 skills verified present against the ORCHESTRATE disposition table. Phase 3 not started (user deferred). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
#280) Implements the 3-part fix proposed on the reopened craft#199: - verify-surfaces.sh: a mismatched Cowork leg now reports N releases behind (via git tag position), not just "mismatch" — both in the human report and --json's new releasesBehind field on the cowork leg. A bare WARN was easy to let ride silently; savant's own Cowork install sat 10 releases behind before anyone noticed. - scripts/cowork-recover.sh (new): one-shot diagnosis that reuses verify-surfaces.sh's JSON output and prints the actual working recovery path (uninstall -> reinstall -> full Cmd-Q relaunch) only when drift is found; no-ops cleanly when aligned or no Cowork store exists on the machine. - downstream-verification.md: explicit disambiguation note so a future release doesn't get closed against the wrong verification again — Code-registered (@Local-Plugins, CLI) and Cowork/Desktop (GUI) are different surfaces that share confusingly similar naming; that naming collision is exactly what caused craft#199's mis-closure. - TUTORIAL-dist-surfaces.md: corrected Step 4's guidance, which previously told readers to use in-app "Update" — the exact path that reliably no-ops. Now documents the real recovery steps and points at the new script. 12 new tests (82/82 total in test_verify_surfaces.sh); full targeted pytest wrappers green. doc-coverage-check.sh and markdownlint clean on all touched docs. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
CI verified real on GitHub (matched local replica), PR #1 squash-merged to folio dev via --admin (classifier blocked plain merge for unrelated reasons, not branch protection). Logged folio's actual release-readiness gap (no e2e/dogfood tests, thin docs, still 0.1.0) and the user's decision to defer that work until after Phase 3. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Records PR #280's merge and the feature/cowork-drift-recovery worktree/branch removal. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…287) * docs: add ORCHESTRATE plan for guard cd-target resolution Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(guard): cumulative cd-target resolution in no-switch-guard.sh Replace the single-hop `-C`-or-leading-`cd` git_dir extraction with a clause-walking resolver: each bare `cd <path>` retargets every subsequent clause (so `cd a && cd b && git switch x` resolves to b, not a), and a `git -C <path>` sets that invocation's target against the effective cwd. Last retarget wins. Phase 1.1 judgment call (per ORCHESTRATE): parallel-inline logic in each hook, NOT a shared sourced file. Two reasons: (1) the hooks derive their base cwd differently — no-switch from process $PWD, branch-guard from the JSON `.cwd` — a shared fn would be parameterized on that anyway; (2) a shared file would force both install scripts to deploy + source it, adding source-path-resolution fragility. Inline avoids both. Split uses `awk gsub` (real newline on BSD & GNU; BSD sed's `\n` does not). Paths containing `$`/backtick/quote are skipped (shell expansions / quoted mid-command `;cd` in commit messages we can't statically resolve). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(guard): name resolved cross-context repo in no-switch prompts Phase 2.2/2.3: is_dirty() already checks `git -C "$git_dir" status` against the resolver's target (verified). Add a [target repo: <name>] note to the dirty-tree confirm and clean-switch announce so a cross-context switch is unambiguous about which repo it acts on — mirrors branch-guard.sh's "name the resolved repo/branch explicitly" checklist item from #284. Note is empty when no cd/-C retarget occurred (same-repo switches unchanged). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(guard): cumulative cd-target resolution in branch-guard.sh §8d0 Phase 3: retrofit #284's single-hop §8d0 resolver to cumulative clause tracking. The old block resolved only ONE leading `cd`/`-C` (regex anchored `^cd`, structurally unable to match a second cd). Replace with the same left-to-right clause walk used in no-switch-guard.sh: each bare `cd <path>` retargets every subsequent clause (cd a && cd b && git push → b), a `git -C <path>` sets that invocation's target, last retarget wins. Downstream re-derivation (IS_CROSS_REPO_TARGET, BRANCH, PROJECT_ROOT, INTEGRATION_BRANCH, PROTECTION) fires against the LAST resolved target, guarded by the existing -d/git-repo/branch checks — a spurious target from a quoted mid-command separator that isn't a real git repo on a different branch is simply ignored. Scope comment updated (v1→v2); quote-bearing paths now also skipped. All #284 single-hop cross-context tests stay green (121/121, Phase 3.3 regression check). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test(guard): multi-hop cd + cross-context cases for both guards Phase 4. branch-guard: cd a && cd b && git push (last-wins → b), mixed cd + -C (b wins), and inverse cd feature && cd main (last-wins gates the protected target). no-switch: BRAINSTORM Context Scan scenarios — dirty session + clean worktree target (NOT blocked), clean session + dirty worktree target (blocked), and pure multi-hop cd dirty && cd clean (last-wins → NOT blocked). Verified the multi-hop cases FAIL against the base dev scripts (which pick the first cd) and PASS against the cumulative resolver — meaningful, failable coverage. Suites: branch-guard 124/124, no-switch 39/39. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs(guard): document cumulative cd-target resolution Phase 5. REFCARD-BRANCH-GUARD.md: new "Cross-Context Target Resolution" section (resolution table + cumulative note + documented quote-parsing limitation). CHANGELOG.md + docs/CHANGELOG.md: mirrored [Unreleased] Fixed entry. markdownlint clean; changelogs verified identical. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs(orchestrate): mark guard-cd-resolution phases 1-5 complete Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(guard): use awk char-class for clause split (cross-awk safe) Replace gsub(/&&|;|\|/) with gsub(/&&|[;|]/) in both hooks' cumulative resolvers. `\|`-as-literal-pipe is well-defined on BSD awk (dev box) but POSIX-underspecified for other awks; a character class is unambiguous across BSD/gawk/mawk and costs nothing — matters for the macOS + Ubuntu-CI portability constraint. Behavior identical; suites stay 124/124 + 39/39. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* docs: add ORCHESTRATE plan for guards.json write-race fix Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(guard): add shared mkdir-based lock helper for guards.json Phase 1 of the guards.json write-race fix. mkdir is atomic on both macOS and Linux (flock has no CLI on macOS, only the syscall), so it's used as the lock primitive with a staleness timeout so a crashed holder can't wedge the lock permanently. Standalone script (lib/guards-lock.sh), not a sourced function -- Operation 12's guards.json mutation is inline bash issued per-turn by the LLM with no backing script, so it can't share a shell process with install-guards.sh's separate invocation. * fix(guard): wire lock helper into Operation 12's guards.json mutation Phase 2 of the guards.json write-race fix. enable/disable/profile's jq-mutate step and the mute-expiry auto-sweep (when it actually clears a mute) now acquire lib/guards-lock.sh before the read-modify-write and release immediately after, with a trap EXIT cleanup so a mid-write failure can't leak the lock. * fix(guard): wire lock helper into install-guards.sh guards.json writes Phase 3 of the guards.json write-race fix -- the second writer found during adversarial review. Both the fresh-create branch and the per-guard merge loop now acquire lib/guards-lock.sh before their read-modify-write and release immediately after, with trap EXIT cleanup. The merge loop keeps a separate acquire/release per guard iteration rather than one lock held across the whole loop, so a concurrent Operation 12 mutation isn't blocked for the full duration. Verified against a scratch HOME (fresh-create + idempotent re-run). * test(guard): add guards.json concurrency regression suite Phase 4 of the guards.json write-race fix. Formalizes this session's ad hoc falsification test (2 concurrent jq-mutate loops, 40 writes each, scratch copy) as tests/test_guards_registry_concurrency.sh: - Case 1: two concurrent writers, distinct fields -- zero lost updates. - Case 2: an Operation-12-style writer concurrent with an install-guards.sh-style merge writer against the same scratch file -- proves the shared lock, not just per-writer self-consistency. - Case 3: a pre-staged stale lock dir is force-broken within the timeout rather than hanging. Every case runs against a mktemp -d scratch copy; a hard assert_not_real guard aborts the suite if any path ever matches the real ~/.claude/guards.json. Red-first verified: MODE=unlocked reproduces lost updates on the pre-fix code path across repeated runs; MODE=locked (default) passes 7/7 with zero lost updates. Also fixes a bug found while red-lining the suite: lib/guards-lock.sh logged a spurious "breaking stale lock" warning when a lock dir vanished between its existence check and its stat call (the holder releasing normally, not a crash) -- now retries immediately instead of misreporting staleness. * docs(guard): correct guards.json sole-mutator claim + CHANGELOG Phase 5 of the guards.json write-race fix. skills/dev/git/SKILL.md Operation 12 no longer claims to be the sole sanctioned mutator of guards.json -- corrected to name both writers (Operation 12 and install-guards.sh) and the shared lib/guards-lock.sh lock that now coordinates them, per the second-writer finding from adversarial review. Mirrored [Unreleased] Fixed entries added to CHANGELOG.md and docs/CHANGELOG.md. --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
… + docs (#289) Adversarially audited before implementation (background agent, read-only review of the proposal). Three of four proposed changes needed revision before landing: - Self-containment prompt gains a required absolute-path prefix (Agent tool has no cwd param) but drops an over-broad confinement clause that would have contradicted this skill's own Cross-Repo Detection feature. - New model-tier guidance reconciled against workflow-engine/SKILL.md's existing per-stage Model Routing rule (opposite instruction, different scope) with an explicit cross-reference instead of standing alone. - EnterWorktree guidance applied only to the STOP-new-session Session Instructions template, not to orchestrate-dispatch's intro — that mode dispatches a background Agent and doesn't need an interactive cwd switch; adding it there would have undermined the mode's own 2-concurrent-dispatch capability. - Resumability wording changed from a literal-string claim ("stays exactly X") to "identical between initial and resumed dispatch", since X now includes a path. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
All three guard-hardening PRs merged to dev with green CI: #287 (cd-target resolution), #288 (guards.json lock, no CHANGELOG conflict with #287 despite both touching it), #289 (orchestrate-dispatch hardening). Worktrees removed, local branches deleted via safe `-d` (squash-merge content recognized without needing force). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Three claims in GRILL-branch-guard-target-resolution-2026-07-14.md are now stale given this session's guard-hardening work: the disproven no-switch-guard "compound-string-match/worktree-cleanup" framing, the concurrency-safety item marked deferred (now fixed in #288, broader than originally scoped), and the cd/-C cumulative-tracking question marked unresolved (now locked and shipped in #287). Added forward pointers to the actual resolutions rather than leaving a future session to re-derive them from a stale doc. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…k-decision test A/B timing against branch-guard.sh at 3 historical commits (pre-guard-rewrites, pre-#284, pre-#287) all showed 207-360ms on this machine — the block-decision path was never reliably under 200ms, independent of today's cumulative-cwd work. Loosened the budget to 350ms with the evidence recorded inline; left the allow-decision budget at 200ms since it passes reliably.
Adversarial review of the deferred Phase 3.6 plan. Key finding: commands/orch.md already exists and already soft-routes to orch:drive/orch:workflow, so T3.6.2's "build a fresh router" premise was stale. 10 decisions locked, net effect: - 4 workstreams -> 2 (orch.md refactor, code:audit router); arch router dropped, plan:feature stays excluded per its pre-existing D2 lock - Reframed as organizational cleanup, not command-count reduction (invocability preserved for every subcommand, so 46->~26 was never reachable this way) - Split into 2 independent PRs instead of one bundled CP-3.6 gate - orch.md's launch logic moves to a new skill; orch.md itself becomes the router - Explicit discovery-cache regen step added to both workstreams' task lists See docs/specs/GRILL-phase-3-6-router-consolidation-2026-07-15.md for full ledger. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…streams Rewrites tasks/todo.md's stale Phase 3.6 section (T3.6.0-T3.6.7, planned as one bundled CP-3.6 gate at "craft@26") with the post-grill scope: 3 independently mergeable workstreams (orch.md refactor, code:audit router, ci router), each its own PR. arch router dropped (D6); plan:feature stays excluded (pre-existing D2 lock); framed as organizational cleanup, not command-count reduction, since D3 preserves slash-invocability for every absorbed subcommand. Also corrects a gap in the prior GRILL pass: the original Phase 3.6 plan had 5 target families, not 4 - `ci` (8 commands, 2117 lines, largest family) was missed in the first grill and is added back here as Workstream C (D10), with a real repo-flag format mismatch (short-name vs OWNER/NAME) found and scheduled as an explicit fix rather than left latent. Updates ORCHESTRATE-folio-split.md's Phase Overview rows for 3.5 (mark actually CLOSED, was showing unstarted) and 3.6 (point at the new scope). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Caught at the start of implementation, before any orch.md/drive.md/workflow.md change was made: D1/D7 were locked from line-counts and flag names alone, without reading drive.md/workflow.md in full. They're already thin command wrappers delegating to their own skills (drive-engine, workflow-engine) - the exact end-state the plan wanted to build - and the 3 commands document genuinely distinct execution engines with no real duplication. Same verdict as arch (D6): drop it. Phase 3.6 proceeds with 2 real workstreams (code:audit router, ci router). orch.md/drive.md/workflow.md are untouched by this branch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
D3 (preserve slash-invocability) cited "T3.5.1 kept commands invocable via skill, not deleted" as precedent -- factually wrong, T3.5.1 deleted the dist:pypi/curl-install/marketplace commands entirely (840e57d). The actual distinguishing factor: those 3 were already deprecated:true shims before T3.5.1 touched them, unlike Phase 3.6's targets which T3.6.0 confirmed are live and non-deprecated. Conclusion unchanged, citation fixed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Caught during implementation, before any file was changed: D8's "cohesive audit shape" verdict for all 5 code:audit-family commands was decided from line counts and a partial flag check. Full read of deps-audit.md/ deps-check.md/docs-check.md shows they're generic cross-project tools with incompatible flag surfaces (deps-check has no --format/--fix at all; docs-check has no formal arguments block and is really a generic docs+ deploy pipeline, not schema-audit-shaped). Workstream B shrinks to command-audit + skill-standards only (298 lines) -- the only 2 that genuinely share shape and verified-compatible --format/--fix semantics. deps-audit.md/deps-check.md/docs-check.md are untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…uter skill
Phase 3.6 Workstream B (docs/specs/GRILL-phase-3-6-router-consolidation-2026-07-15.md,
tasks/todo.md T3.6.B1-B5): the only 2 of the original 5 code:audit-family
commands that genuinely share shape and --format/--fix semantics
(both validate craft's own frontmatter/schema).
- New skills/code/audit-router/SKILL.md: shared --format/--fix vocabulary,
health-score formula, exit-code convention shared by both commands
- Salvaged both full bodies verbatim into references/{command-audit,
skill-standards}.md (ADR-002 line-conservation)
- commands/code/{command-audit,skill-standards}.md shrunk to thin shims:
frontmatter (arg surface) unchanged, both stay directly slash-invocable
- deps-audit.md/deps-check.md/docs-check.md untouched -- they're generic
cross-project tools with incompatible flag surfaces, not schema-audit-shaped
Count cascade: 39->40 skills (bump-version.sh + manual sweep of 6 files
outside its tracked list: commands/dist/homebrew.md, docs/MIGRATION-v4.md,
docs/QUICK-START.md, docs/architecture.md, docs/commands.md,
docs/guide/getting-started.md, docs/guide/hub-live-dashboard.md, docs/index.md,
docs/skills-agents.md, docs/tutorials/TUTORIAL-code-skill-standards.md,
README.md). Commands unchanged at 46 (no command added/removed, only 2
shrunk in place).
Full suite: 2561 passed / 4 failed (all confirmed pre-existing on this
branch via git stash: branch-guard hook-install drift + 3 known
test_v115_adhd_enhancements baseline failures) / 43 skipped.
mkdocs build --strict: clean (0 errors). validate-counts.sh + bump-version.sh
--verify: ALL CONSISTENT.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Both declared `category: code` while living in `commands/ci/`, which help_file_validator._check_category_mismatch flags as a real defect (expected category is derived from the parent directory). Found during Phase 3.6 Workstream C investigation. No router was built: a full read of all 8 commands/ci/*.md showed the family is genuinely heterogeneous (detect.md duplicates skills/ci/SKILL.md, triage.md's classify_failure() is extracted by tests/test_ci_triage_unit.py, generate.md is 731 lines of unique CI templates), so this metadata fix is the only real defect the investigation surfaced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both declared `category: orchestrate` while living in `commands/orch/`, and no `commands/orchestrate/` directory exists — so the category was unbacked. help_file_validator._check_category_mismatch derives the expected category from the parent directory and flags this. Pre-existing on dev; surfaced by a repo-wide validator sweep run while fixing the same defect class on commands/ci/. Repo-wide mismatch count is now 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 3.6 opened with 5 router workstreams and closes with 1 shipped: - plan:feature — excluded (pre-existing D2 lock, unchanged) - arch — dropped (D6), no real duplication - orch — dropped (D11), already delegates to engine skills - code:audit — SHIPPED, shrunk 5 commands -> 2 (D12), 204822a - ci — no router (D13); metadata fix only D13 records the ci full-body read: detect.md duplicates skills/ci/SKILL.md, triage.md's classify_failure() is regex-extracted and exec()'d by tests/test_ci_triage_unit.py (markdown IS the source of truth), generate.md is 730 lines of unique templates. No shared shape to route. Also withdraws D10's repo-flag normalization as a premise artifact: no validator enforces cross-family flag-shape consistency, so it was only a "defect" relative to a router vocabulary that no longer exists. Root cause across D11/D12/D13: the grill locked load-bearing decisions from line counts and flag names without reading the bodies. Every family that looked cohesive from surface metrics collapsed on a full read. Rule recorded for future consolidation phases: read every candidate body in full before locking a router decision. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 3.6 is closed and committed; the branch is deliberately parked, not abandoned. Records why it is not PR-ready so the next session does not re-derive the diagnosis. Scope reality: this branch is the whole v4 train (36 commits, Phases 3+3.5+3.6), 41 behind dev off a 2026-07-09 merge-base — not a small Workstream B+C PR. Three CI blockers with three unrelated causes: 1. test_branch_guard.sh — stale branch, NOT a regression. A characterization test encoding a known limitation that guard-hardening PRs #287-289 closed on dev; dev already renamed it `..._now_caught` expecting 2. The suite runs the INSTALLED hook at $HOME/.claude/hooks/, so its result is machine-global state, not branch state — which is why it passes on dev and fails here with identical code. Fixed free by a dev merge. 2. ci.yml:92 command floor 60 vs actual 46 — the open T3.4, stale a second time (targeted 86->60, then Phase 3.5 cut to 46). CI hard-fails. The new number is a decision (mass-deletion guardrail), not a mechanical edit. 3. test_git_shim_correctness.sh — the only true branch debt. T3.5.2 deleted commands/git/ but left the suite asserting those 7 shims exist. A dev merge does NOT fix it. Needs the suite updated/removed + its ci.yml:180 line. Root blind spot: these are bash suites (ci.yml:177-180); pytest does not run them. T3.5.2 cited "full pytest 2575 passed" as evidence and shipped this. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Brings 41 commits of dev (guard-hardening PRs #287-289, the cwd resolver, and /craft:git:issue-check from PR #283) onto the v4 folio-split branch. 34 conflicts resolved. Surface: 47 commands / 40 skills / 2 agents. Conflict resolution: - ~30 count-cascade conflicts (dev 95/45/8 vs branch 46/40/2) -> took the branch's post-split surface, then recomputed every tracked count mechanically via bump-version.sh --counts-only (14 files) rather than trusting hand-resolution. validate-counts.sh exits 0 at 47/40/2. - commands/docs/quickstart.md (modify/delete) -> kept deleted; folio owns it (verified present at folio/commands/docs/quickstart.md). dev's only change was a count bump inside an example template. - commands/git/issue-check.md -> KEPT AS A LIVE COMMAND, not folded into skills/dev/git/. Git's directory-rename detection had auto-relocated it to skills/dev/git/references/ (our side renamed commands/git/ -> skills/dev/git/references/ in T3.5.2), which would have broken tests/test_issue_check_unit.py: that test hardcodes commands/git/issue-check.md and exec()s the classify_issue() block out of it, so the command file is the single source of truth for the classifier. Same structural constraint recorded for commands/ci/triage.md in GRILL D13. Restored to commands/git/; its 12 unit tests pass. - skills/dev/git/SKILL.md -> kept the branch's reference-doc rows, dropped dev's stale commands/git/docs/refcard.md row. Operation 13 (Issue Premise Check) merged in cleanly from dev. - mkdocs.yml nav -> dropped dev's 7 deleted git command entries, kept the issue-check entry (blind --ours would have dropped it from the site). Also corrects two now-false claims in skills/dev/git/SKILL.md ("commands/git/ is now empty", "there is no explicit /craft:git:* invocation path anymore") — issue-check is a live command and the skill now says so, with the reason. Long-tail doc counts (46 -> 47) updated in 6 live user-facing files. Historical changelog entries, illustrative sample outputs, and spec/brainstorm records deliberately left at their original numbers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
T3.4 — command floor 60 -> 40. The floor is a mass-deletion guardrail and must sit BELOW the real surface. It went stale twice (86 -> 60) while the actual count fell 94 -> 70 -> 47, leaving the floor ABOVE the surface: CI hard-failed with "Expected at least 60 commands, found 47" on every run. 40 leaves ~15% headroom under the v4 surface of 47. Rationale is now a comment in ci.yml so the next surface change does not repeat this. test_git_shim_correctness.sh — inverted, not deleted. It asserted each commands/git/*.md was a genuine thin shim; T3.5.2 then COMPLETED that migration by deleting all 11 shims, making the assertions unsatisfiable (7 FAIL on this branch, 21/21 on dev where the files still exist). The shim-drift it guarded is now structurally impossible, so it instead guards the migration's end state: 1. the 11 former shims stay deleted (nobody silently re-adds one) 2. skills/dev/git/SKILL.md still carries Operations 1-12 3. issue-check stays live + non-deprecated (the one sanctioned exception) 4. no unsanctioned command reappears under commands/git/ Verified by planted defect, not just a green run: resurrecting status.md -> caught; renaming Operation 5 -> caught; marking issue-check deprecated -> caught; clean baseline 25/25 before and after. ci.yml needs no change — the suite keeps its filename. Root blind spot both share: these are bash suites (ci.yml), and pytest does not run them. T3.5.2 cited "full pytest 2575 passed" as its evidence and shipped the breakage behind a green check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extracts craft's docs-authoring surface into the standalone folio plugin. Phase 3.6 shipped 1 router of 5 planned: code:audit (5 cmds -> 2). orch, arch, and ci were all dropped after reading the command bodies in full — every family that looked cohesive from line counts and flag names collapsed on a full read. Also fixes 4 category: metadata defects (repo-wide mismatches now 0), T3.4's stale command floor (60 -> 40; it sat ABOVE the real surface of 47 and hard-failed CI), and inverts test_git_shim_correctness.sh to guard the completed git migration's end state rather than shims T3.5.2 deleted. /craft:git:issue-check stays a live command: tests/test_issue_check_unit.py extracts its classify_issue() block from commands/git/issue-check.md and exec()s it, so the command file is the classifier's single source of truth (same constraint as commands/ci/triage.md, GRILL D13). CI verified green: 2586 passed / 0 failed, all 4 bash suites pass, floor gate confirmed at 'Found 47 command files'.
Both were pre-existing errors, not off-by-one drift from the v4 merge — the
second was already false before it.
- Dry-run tip: "46 commands now support dry-run mode" -> 27. The 46 was the
old command TOTAL pasted into a dry-run claim; it contradicted the same
page's authoritative line ("27 of 47 commands support --dry-run").
- Documentation Commands section: "46 commands for documentation generation,
validation, and site management" -> "2 commands for documentation updates
and changelog automation". craft's commands/docs/ holds exactly 2 files
(update, changelog); the other 17 rows in that table are migration pointers
to folio, which now owns generation/validation/site-management. The old
sentence described a surface craft no longer has.
Verified: 0 remaining "46 commands" claims in this file, markdownlint clean,
mkdocs build --strict exit 0 (the added MIGRATION-v4.md link resolves).
NOT fixed, needs a decision: line 10's "17 Categories: arch, check, ci, code,
discovery-usage, dist, do, docs, git, hub, orchestrate, plan, site, smart-help,
test, utils, workflow" is stale (discovery-usage was demoted to docs in T3.5.2,
orchestrate is now orch, no workflow dir exists) — but "category" has two
defensible definitions here that disagree: frontmatter-declared categories give
10 (arch ci code dist docs git orch plan site smart) while directories give a
different 10 (... utils). The current list mixes in root-level commands as
pseudo-categories and matches neither. Left alone rather than guessed at.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… gap (#291) /craft:check never ran the shell suites CI invokes directly, because pytest does not collect them. The local gate and CI measured different things, and the local one reported green for a surface it never touched. Root cause behind two of the three CI blockers the v4 folio-split branch carried: T3.5.2 deleted commands/git/ citing 'full pytest 2575 passed' as evidence, while tests/test_git_shim_correctness.sh — a CI-required check — had been red for days asserting those exact files existed. Implemented as a hot-reload validator (the extension point /craft:check already scans), deriving the suite list from .github/workflows/*.yml rather than hardcoding it. craft has 22 tests/*.sh but CI runs 6; a hardcoded list is the drift this prevents. Advisory in default mode, blocking in release, per the documented release-gated validator contract. Verified by planted defect: replaying the real T3.5.2 bug (pre-fix suite restored from d41de18) is caught — WARN in default, exit 1 in release. Also catches a failing suite, a workflow referencing a missing suite, and skips cleanly in repos with no workflows. CI verified: pytest 2586 passed / 0 failed, all bash suites green, floor gate at 'Found 47 command files'.
…nce closed .STATUS still claimed "Counts unchanged 95/45/8" and last_session 2026-07-15, while dev is at 47/40/2 after today's two merges — the project's own state record contradicting the repo by ~48 commands. Records: PR #290 (v4 folio split, merge-commit 4af10f2, craft 94->47), PR #291 (ci-bash-suites validator, squash 88b221d), 5034aef (2 stale docs/commands.md count claims), and the local branch-guard hook re-sync that cleared the last known test failure. The session recap keeps the reusable part rather than just the outcome: the three CI blockers had three unrelated causes (stale branch / stale plan number / real debt) and triaging them as one bucket would have produced three wrong fixes. Also records the evidence discipline that paid off — planted defects over green runs, reading the CI log rather than the badge, baselining before blaming, and treating a recommendation refuted mid-execution as refuted rather than authorized. Open items carried forward: Phase 4, tasks/todo.md's nonexistent plan-of-record path, docs/commands.md:10's "17 Categories" definition question, and 2 branch-guard false positives. R09 status-drift verified back to its pre-existing baseline: my first draft said "preserved for the v4.0.0 tag", which tripped Check B — .STATUS's milestone is ONE line containing "SHIPPED", so every vX.Y.Z token on it must resolve to a real git tag, and v4.0.0 is not cut yet. Reworded to "the eventual v4 release tag". The 2 remaining warnings (v2.61.1, v1.16.0) are pre-existing historical prose, confirmed by running the checker against HEAD's .STATUS in the real repo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… positives (#292) * fix(guard): strip quoted spans + scope writes to PROJECT_ROOT branch-guard.sh's Bash write-through detection (Patterns 1-4) coarse-scanned the raw command string for shell metacharacters with plain grep, which has no notion of quoting. Three false positives fired live in one session, including during an audit of this exact bug class: awk 'NR>=203 && ...' -> '>' inside a single-quoted awk program read as a redirect grep -E '>[^=]' ... -> same, inside a grep pattern grep -n '...\"cp \|...' ... -> literal "cp " substring inside a quoted search pattern read as a cp invocation Same failure class Group 14c (2026-07-10) already fixed for heredoc bodies via HAS_HEREDOC; this generalizes it to any quoted span, not just heredoc bodies. COMMAND_SCAN strips quoted-span CONTENTS before the coarse `grep -q` presence checks; extraction (`grep -oE`) still runs against the ORIGINAL $COMMAND, so a real target quoted for spaces is unaffected. A fourth, unrelated bug fired alongside it: `cp <file> /tmp/...` was flagged as "creates a new code file on dev" even though /tmp is nowhere near the repo — only /dev/* was excluded. Added a PROJECT_ROOT prefix check on the resolved write target. PROJECT_ROOT is a realpath (`git rev-parse --show-toplevel`); $CWD often isn't (macOS's /tmp -> /private/tmp, and `mktemp -d` returns the /tmp form) — a naive literal-prefix compare broke 6 pre-existing in-repo-write tests during development. Fixed by canonicalizing the target's directory via `cd && pwd -P` (POSIX, avoids realpath/readlink -f, which aren't universally available) before comparing. Verified by planted defect AND by replaying the actual live false positives verbatim against the fixed hook (all resolve to exit=0), plus an isolated confirmation that a genuine redirect on a fresh dev-branch repo still returns exit=2 (blocked). New Group 22 (9 tests): 5 catch the false-positive class (including the 2 real historical commands), 4 are regression guards proving the fix doesn't weaken real detection (quoted target with spaces, cp inside the repo, a real touch alongside an unrelated quoted decoy). Full suite: 133/133 (was 124/133 mid-development, before the pwd -P fix). E2E: 30/30 (1 skipped, unrelated). Full pytest: 2601 passed / 1 failed (the 1 is the expected repo-vs-installed-hook divergence this branch itself causes, cleared by install-guards.sh — same pattern as PRs #290/#291). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(guard-audit): correct the skill's fictional config schema Discovered while running this skill to audit the false positives fixed in 7b51969. Step 5's documented config schema (nested "branches" object, "version": 2, allowed_extensions, pr_body_scan, force_push_allow, dev_allowed_extensions) is read ZERO times by scripts/branch-guard.sh — grepped for every one of those keys, all 0 matches. The real schema is a flat branch-name -> protection-level map, read via a single lookup, _json_get ".\"${BRANCH}\"" (branch-guard.sh:234). Following the skill's own instructions would have produced a config file the guard silently ignores. Also removed a fabricated "destructive git in PR body" rule (grepped the script for pr_body/PR body/--body: 0 matches — no such scanning exists) and replaced Step 4's fictional recommendations with the two real friction classes this session actually found: quoted-span misdetection and missing path scoping, neither fixable via any config key. Added a classification step (Step 4) splitting false positives into branch-policy (config-fixable) vs. detection-logic (requires a code PR to branch-guard.sh, not a config change) — the skill's "never modify branch-guard.sh" constraint was previously silent on what to do when the bug IS in branch-guard.sh; now it says so explicitly rather than implying a config workaround exists for everything. Verified: skill_standards_audit.py 100/100, markdownlint clean, description 400 chars (well under the 1536 cap). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * perf(guard): collapse COMMAND_SCAN to one sed invocation 7b51969's quote-stripping added printf | sed | sed (3 forks) to every Bash tool call on dev/main. dev's own dogfood perf budget (test_branch_guard_under_200ms) went from 207ms (pre-existing, already marginal on this machine — same class as the test_performance_cached_run xfail note re: unreliable wall-clock timing on shared runners) to 236ms. Collapsed to a single sed invocation (two -e expressions, here-string instead of printf|pipe) -> 3 forks to 1. Re-measured 0.80-0.90s per pytest invocation across 3 runs, consistently under budget. Full suite (133/133), E2E (30/30), and full pytest (2602 passed / 0 failed) all still green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(guard): correct cross-boundary quote-pairing regression in COMMAND_SCAN Adversarial review of PR #292's own Group 22 tests surfaced a real false negative the quote-stripping fix introduced: two independent sed passes (single-quote pass, then double-quote pass) let a single-quote-pair span across two unrelated double-quoted strings that each contain one apostrophe (e.g. "it's" ... "don't"), erasing a real redirect sitting between them from COMMAND_SCAN. Confirmed live: a genuine `> new_file.py` write-through on dev went completely undetected. Fix: combine both quote types into one alternation pattern (`'...'|"..."`) so quote-type resolves at the first quote character encountered and can never pair across a boundary of the other type. Verified via planted-defect replay: the new regression test fails against the reverted two-pass sed and passes against this fix; full suite 134/134. --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Written BEFORE any v4.0.0/folio-v1.0.0 tag exists, per the plan's own scheduling (T4.2 has no dependency on T4.0/T4.1/T4.1b/T4.1c and gates T4.3). Covers: - Path A: craft revert map (dev->main merge-commit revert, Homebrew re-point via craft.rb url+sha256, GitHub release annotated not deleted since a prior good version exists to point users to). - Path B: folio revert map (release+tag deletion appropriate here specifically because this is folio's FIRST release - no prior version exists, so nothing to annotate a "superseded" note toward; formula removed entirely, not downgraded, since it's created fresh in T4.3). - Explicit sequencing invariant: craft must not tag v4.0.0 before folio's release is confirmed fully live. - Path C: the partial-rollback question (folio ships, craft stalls) is deliberately left unresolved - stated as a question with arguments on both sides, not answered. This was flagged during Phase 4 planning as needing a human decision; the runbook's job is to make sure whoever hits this scenario sees the question, not to guess an answer for them. Homebrew automation detail confirmed by reading homebrew-release.yml: it pushes directly to homebrew-tap's main via a GitHub App token, no PR step - the runbook's revert commands reflect that (direct commit+push, not a PR-and-merge cycle, for the tap repo specifically; craft's and folio's own main branches DO go through a revert PR, per their branch protection).
T4.0-T4.2 complete (folio sync, /folio:do router+tests+docs, rollback runbook PR #293). T4.3 complete: folio v1.0.0 released, homebrew-tap manifest entry (PR #141) + test_paths audit fix (PR #142), brew install/audit verified clean. Adds the two /goal-ready SPEC files authored during Phase 4 planning.
Version bump from 2.61.2 to 4.0.0 via bump-version.sh (47 commands, 2 agents, 40 skills, 64 specs). Converts CHANGELOG.md/docs/CHANGELOG.md Unreleased section to 4.0.0, expanding docs/CHANGELOG.md with the full PR list since 2.61.1 (#279 through #293). Closes gaps surfaced by pre-release-check.sh's doc-coverage and docs-staleness gates: - Missing REFCARD rows (code:demo, git:issue-check) and mkdocs.yml nav entries (code:demo, site:deploy); new docs/commands/code/demo.md and docs/commands/site/deploy.md written (no prior site page existed for either command). - audit-router skill (T3.6) was never added to docs/skills-agents.md. - v4 rollback runbook added to mkdocs.yml nav. pre-release-check.sh 4.0.0: PASSED (remaining items are cross-repo or pre-existing advisories: homebrew-tap's craft.rb desc count, a pre-existing internal-doc nav gap, and .STATUS drift notes). Full pytest suite: 2637 passed, 0 failed. CI bash suites all green (branch_guard_e2e's sole failure is the documented runner-sensitive perf test, confirmed via SKIP_PERF).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Craft's biggest breaking release: the docs-authoring/publishing surface (24 commands, 6 agents, 6 skills) is extracted history-preserving into a new public plugin,
Data-Wise/folio(released as folio v1.0.0), alongside a v4 command-roster consolidation.Verification
python3 -m pytest tests/: 2637 passed, 0 failedSKIP_PERF=1)bash scripts/pre-release-check.sh 4.0.0: PASSEDbash scripts/doc-coverage-check.sh: PASSED (0 blocking gaps)brew install/brew auditclean) — this PR is the second half of the coordinated release train (folio-first, craft tag last, per the runbook)Test plan
homebrew-release.yml