Conversation
Records the v4.5.0 release (repo-triage skill, 8 ecosystem tutorials, nav fix) in .STATUS milestone narrative; archives the two completed specs that drove this release. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes the one content gap left after the v4.5.0 docs sync: repo-triage had SKILL.md/REFCARD/getting-started coverage but no task-focused cookbook recipe, unlike triage-a-red-pr's equivalent workflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ncy gate) REFCARD.md's quick-reference box had the right version NUMBER (4.5.0, bump-version.sh's literal-string target) but stale content around it: release date (2026-07-17, actually v4.1.0's) and highlight line (still describing v4.1.0's /craft:restore, not v4.5.0's repo-triage skill) — same bump-version.sh blind-spot pattern as the docs/index.md fix earlier this release. Skill count also read 40, not 41. skills-agents.md's TL;DR line said "8 specialized agents" two lines above its own correct "2 specialized agents" — stale since the v4.0.0 folio split (8→2 agents), never caught because count-consistency only anchors on specific badge/count patterns, not every prose mention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Captures today's REFCARD.md/skills-agents.md incident (correct version numbers, stale surrounding prose) as 3 concrete Phase 7 checks to add to docs-staleness-check.sh: release-date claims, agent/skill count prose, and version-highlight staleness proxy. External research (fiberplane/drift, Vale, dosu.dev freshness scoring) confirmed no existing tool fits craft's count/version-anchored staleness model — extending the existing gate with targeted patterns, no new dependency. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…check 2) 3 blocking findings from adversarial review, all fixed: - Check 3 (version-highlight staleness proxy) was falsified by its own target: bump-version.sh touches REFCARD.md's version line every release, so the whole-file git-log-touch proxy would never flag the exact file that caused this SPEC to exist. Dropped rather than built as a per-line proxy — not worth the complexity for an advisory-only signal until checks 1-2 prove insufficient alone. - Check 2 (agent/skill count prose) false-positived on 90+ legitimate matches (orchestration mode-limit prose, a fictional-plugin tutorial, an intentional-bug troubleshooting example) when scoped as a blanket regex. Rescoped to structured line shapes only (TL;DR lines, version boxes, badge/count-summary lines). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Quick Start only documented the dev-only local-plugins symlink path, with no real install instructions for external users. Added the two actual install paths (Homebrew, Data-Wise marketplace) and moved the symlink instructions under a "developing craft itself" note. Also fixed 5 stale "47 commands" mentions (current: 48) scattered through prose/callouts — the exact class of bug docs-staleness-check.sh doesn't catch (free prose, not a structured badge/count line); see SPEC-doc-staleness-prose-gaps-2026-08-07.md for the planned gate fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ly edits homebrew-tap#211 (craft's stale unprotect-caveat fix) tripped the Formula Drift Guard CI check on first push — content changed with no version/revision bump, so brew upgrade would never have detected it. Documents the rule in /craft:dist:homebrew and the release skill's homebrew reference so it doesn't have to be rediscovered by trial and error next time a tap formula gets a content-only fix outside a version release. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same blind spot as this SPEC's craft-side checks (fixed number, stale surrounding prose) exists in homebrew-tap's manifest.json caveats_extra text — confirmed live via the /craft:git:unprotect caveat bug fixed in homebrew-tap#211. Out of scope here (D2: craft only) — recorded so it isn't silently forgotten. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Records this session's continuation work: 3 stale-prose doc bugs found and fixed, a cookbook recipe added, SPEC-doc-staleness-prose-gaps brainstormed/spec'd/adversarially reviewed (not yet built), and homebrew-tap#211 merged (stale caveat text + required revision bump). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New OpenCode MCP bridge cheat sheet (opencode + opencode-async), routing table and mandatory-monitor guidance in both delegation tutorials, and a brainstorm -> dual-review -> grill -> spec chain scoping delegation to two use cases (arch:review adversarial review, brainstorm research escalation) with the rest parked. Both docs were adversarially reviewed by codex and opencode/deepseek-v4-pro themselves before this commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The 📚 Teaching mkdocs nav section, README's Teaching Mode section, and
the underlying commands/utils/{teach_config,teaching_validation,
semester_progress}.py + utils/detect_teaching_mode.py all documented
/craft:site:{progress,validate,publish} — deleted in the v4 command-prune
(commands/site/ now has only deploy.md). A prior SPEC's "keep the utils,
they're consumed by 4 files" rationale is dead: all 4 consuming files are
gone. Confirmed via background audit this session; verdict was REMOVE.
Removed: 7 docs/teaching-* pages, 4 dead utils, 10 dead test files
(including tests testing modules that no longer import), 1 pytest marker,
1 test.md domain row. Fixed 6 resulting dead links across REFCARD.md,
tutorials/index.md, getting-started/choose-path.md, guide/
claude-code-2.1-integration.md, guide/integration-testing.md (trimmed its
whole "Category 3: Teaching Workflow" section + renumbered), and
cookbook/common/deploy-course-website.md (kept — it's actually about
folio's live site:build/check commands, only its teaching cross-links
were dead).
Verified: full suite 2462 passed / 20 failed (both failure classes
pre-existing and unrelated — test_branch_guard_dogfood.py's documented
cross-repo symlink baseline, and a pre-existing broken link in
REVIEW-repo-triage-2026-08-07.md dated 2026-08-07, untouched tonight).
markdownlint + mkdocs build --strict clean. Command/skill/agent counts
unaffected (48/41/2) — teaching was never a real command/skill/agent.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… teaching removal
Bumps the mcp-dev-dependencies group in /mcp with 2 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [esbuild](https://github.com/evanw/esbuild). Updates `@types/node` from 26.1.2 to 26.2.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `esbuild` from 0.28.1 to 0.28.2 - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md) - [Commits](evanw/esbuild@v0.28.1...v0.28.2) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 26.2.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: mcp-dev-dependencies - dependency-name: esbuild dependency-version: 0.28.2 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>
CLAUDE.md's Project Structure table still claimed 8 agent definitions; the real count has been 2 since v4.0.0. The row sits outside the bump-version.sh count cascade, whose CLAUDE.md pattern only matches the bold "**N agents**" form, so it survived every version bump since. README.md's tagline claimed "1994 tests passing" — stale, unguarded by any validator, and unbackable next to a suite with known pre-existing failures. Dropped the hard number rather than substituting another one that will drift the same way. Verified: docs-staleness-check.sh GREEN, validate-counts.sh 4/4, markdownlint 0 errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… harness README's highlight block still advertised v2.36.0's Deterministic Workflow Engine five minors after v4.5.0 shipped. Replaced with the v4.5.0 headline from docs/NEWS.md (repo-triage skill + 8 ecosystem-tool tutorials). SPEC-doc-staleness-prose-gaps amended with: - Amendment section recording two live findings from a currency read on 7db7b56. E1: Phase 7's scan pattern is strictly plural, so CLAUDE.md's "8 agent definitions" went unseen for five minors -- the singular form must fold into the shared matcher, not sit on top of it. E2: NEWS.md and .STATUS disagree on the v4.5.0 release date because the GitHub release crossed the UTC boundary, so check 1 needs a single authority plus a one-day window or it flags a correct repo on first run. - ADR-007 requirement: records the commitment to pattern-scoped prose gating over Vale/semantic/LLM-in-CI, the rejected whole-file git-touch proxy and why it was falsified, the severity posture, and the revisit trigger. - Test-harness design: 9 fixtures across clean/defect/falsepos, a table-driven runner asserting on --json output, and a rule that a check without a defect fixture is a rejected change. Acceptance criteria extended by 5 items to cover all of the above. Verified: markdownlint 0 errors, docs-staleness-check.sh GREEN. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…aps live The repo-triage row still read DISPATCHED 2026-08-07 after that work shipped in v4.5.0 and its worktree was removed. Marked merged with its PR links and added the feature/doc-staleness-prose-gaps worktree created this session. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… lines (#334) * feat(docs-staleness): prose checks for release dates and shaped count lines Implements SPEC-doc-staleness-prose-gaps-2026-08-07 and records the approach as ADR-007. Phase 7 anchored on structured tokens only, so four real bugs shipped while it reported GREEN: REFCARD.md's wrong release date beside a right version number, skills-agents.md's "8 specialized agents" two lines above its own correct "2", CLAUDE.md's "8 agent definitions" for five minors, and README.md headlining v2.36.0 at v4.5.0. Two checks, both severity warning: - Release-date claims within 4 lines of the current version token must fall within a day of that version's git tag date. The window is not slack: the GitHub release for v4.5.0 published 2026-08-08T03:44Z against a 2026-08-07 tag, so a stricter check would flag a correct repo on its first run. - Count prose is checked inside four structured line shapes only (version box, TL;DR opener, bolded count-summary badge, structure-table row), where the singular noun form is safe to match. The broad scan stays plural-only and unscoped -- widening it would reopen the 90+ false positives the adversarial review closed. Harness: 11 fixtures across clean / planted-defect / known-false-positive, plus a table-driven runner asserting on --json findings. Positive controls verified by mutation rather than assumed -- removing the 40% floor fails 3 tests, dropping the singular alternation fails exactly the E1 defect test. Three findings from the build itself, all folded back into the SPEC: - The 40%-of-expected floor must apply to shaped lines too. Without it the first build flagged five legitimate counts on dev: category subtotals in reference boxes, a bolded subset count, a narrative count about another plugin. All five are now falsepos fixtures. - Matching TL;DR anywhere on a line flagged ADR-007's own context table, which quotes the line the ADR exists to explain. The shape now requires the line to open with TL;DR. - The first build ran the script at 36s against a dev baseline of 8.0s, blowing the 30s timeout in test_pre_release_check_runs. Cause was ~1300 per-file awk spawns plus ~21000 greps over every line of every box block. Now one awk pass over the file list, an in-awk pre-filter so only count-bearing lines reach bash, and the date window computed once. 8.7s. Full suite in-tree: 1 failed / 2460 passed / 49 skipped. The one failure is a pre-existing broken link in REVIEW-repo-triage-2026-08-07.md, reproduced on the dev baseline (20 failed / 2462 passed; dev's 19 branch-guard failures are skips on a feature branch). docs-staleness GREEN, validate-counts 4/4, markdownlint 0 errors, mkdocs build --strict clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): unparseable release-date authority must be vacuous Self-review of #334 found it. compute_release_date_window exits silently when the tag date will not parse, leaving an empty accept-window -- and an empty window matches nothing, so every release-date claim in the repo was flagged at once. One bad input became a repo-wide false-positive storm. The no-tag case was already handled (skip); an unparseable tag was not. Both now take the same path: the check is vacuous unless the authority actually parsed. Regression test uses the clean/ fixture, which is correct against a real tag date, so any finding it sees comes from the broken authority alone. Positive control verified by reverting the guard: the test fails with "release date '2026-08-08' for v4.5.0 (tag: not-a-date)". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(specs): repoint REVIEW-repo-triage at the archived GRILL b1c4426 archived GRILL-repo-triage-2026-08-07.md to docs/specs/_archive/ without updating its one referrer, so test_no_broken_links has failed on every branch since. It is the sole failure in the dev baseline and the only thing red on this PR. Unrelated to this branch's subject, fixed here because a dev-side fix would not reach this PR's CI run. The other file archived in the same commit (SPEC-ecosystem-tool-tutorials) has no referrers -- checked, nothing to fix. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): release-date window was one line short of its contract Found by /code-review on #334, confirmed empirically before acting. The win-- decrement runs on the version-mention line itself, so win = 4 scanned that line plus only 3 more. Both the inline comment and docs/reference/REFCARD-DOCS-STALENESS.md advertise 4 following lines, and the gap silently reads GREEN rather than flagging -- a layout as ordinary as heading / blank / Type / blank / Released fell straight through it. win = 5 restores the documented window. New defect fixture places a stale date at exactly that far edge; positive control verified by reverting to 4, which fails only that case: FAILED test_prose_staleness_fixture[defect-release-date-far-edge] - planted defect went undetected 1 failed, 14 passed Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): pass 2 [f]ix applied nothing while reporting success pass2_interactive_review's [f]ix branch printed "-> Fixed" and incremented TOTAL_FIXED without touching the file. It is the same reports-success-changes-nothing bug pass 1 was fixed for earlier (see the BSD-sed note now on apply_line_fix), left behind in the other pass. Extracted pass 1's python applier into apply_line_fix and pointed both passes at it, so the two cannot drift apart again. It echoes "true" only when the file actually changed, and "false" for a non-substitution fix_detail, a pattern that matches nothing, or an out-of-range line -- Phase 8's doc-coverage findings carry a `doc-coverage:surface:cmd` marker rather than a substitution and must never be executed. Both prose checks now emit a real substitution as their fix_detail instead of a human-readable "old -> new" note, so confirming one in pass 2 actually edits the file. They stay routed to pass 2 rather than pass 1: the surrounding prose is hand-authored, so a human should see the line before the number changes under it. The substitution swaps only the digits, leaving "agent definitions" intact. Two tests pin the applier's contract, including that a "false" result leaves the file byte-identical. Positive control verified by mutating apply_line_fix to report success without writing -- the truthfulness test fails. The pass 2 branch itself is not directly covered: it requires a TTY. Its 8 lines of fix_detail parsing mirror pass 1's. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: sync SPEC, ADR-007, REFCARD and changelogs with the four post-build fixes All four planning/internal docs were written in bd95723 and none was updated for the fixes that landed after it, so each described the first build rather than what ships. SPEC: new "Post-build findings" table recording all four bugs and, for each, which mechanism caught it -- the existing suite's timeout, self-review, /code-review, and reading adjacent code. No single review mechanism found more than one, which is the point of recording it. Notes that two of the four are the same failure mode (reporting a result never established) and that the pass-2 bug is a recurrence of one pass 1 was already fixed for. Adds the fix-routing decision, the 11th fixture, and 4 acceptance criteria. ADR-007: two architectural rules the fixes established, both stated generally for checks added later. A failed authority makes a check vacuous, never universal -- absence of a usable comparison is not evidence of drift, and the failure modes are not symmetric (a skipped check costs one missed bug; a check that fires on every document costs the gate its credibility). And fixes must be applied, not announced -- one shared applier, because patching the second site would have left a third. REFCARD: corrects the window to "the version line or the 4 lines below it", documents the vacuous-on-unusable-authority rule, and records that choosing [f]ix now really edits the file, including when it will decline. CHANGELOG (both): the three script fixes plus the archived-GRILL link repoint. Verified: markdownlint 0 errors, docs-staleness GREEN, validate-counts 4/4, mkdocs build --strict clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(specs): spec the 9 prose-check defects found reviewing #334 Every finding reproduced against the real script before being written down -- F1/F2/F6 by constructing input, F5/F7 by reading the consuming code. Two are verified as changing the design rather than just the code: F5: ADR-007 justified `warning` over `error` by claiming both severities fail the release gate identically. pre-release-check.sh:280 is headed "warn-only, does not block release" and swallows the exit code, and docs-quality.yml sets continue-on-error -- while skills/release/SKILL.md:143 says RED blocks and YELLOW proceeds. The label is the only gate, so the severity choice IS the block decision the ADR said it was not. F7: docs-quality.yml checks out without fetch-tags, so no tag exists and check 1 silently skips on every CI run; and release writes the NEWS/REFCARD dates before the tag is created. The check may only ever fire on a dev machine that already pulled the tag. Groups the nine into four root causes rather than listing them flat, because patching nine sites individually leaves the classes open -- notably C3, where the pass-2 [e] branch is the third instance of the same reports-success-changes-nothing bug, introduced by #334's own change of the finding's `file` field to path:lineno. Nine decisions left open with tradeoffs rather than pre-resolved, for grilling. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(specs): grill the prose-check hardening spec — 5 branches locked Two branches were reframed by evidence gathered during the grill, not argument. D1 (authority): dropped the git tag for cross-file consistency. The tag is absent in both environments the check exists to protect -- release runs Step 3b (write doc dates) -> Step 3b.5 (staleness gate) -> Step 8 (create tag), so the tag does not exist when the gate runs; and docs-quality.yml checks out without fetch-tags. As built, check 1 fires only on a dev machine that already pulled the tag. Comparing claims against each other needs no authority and works in both places. D2 (severity): split, check 1 RED and check 2 YELLOW. Verified that no consumer reads the exit status -- pre-release-check.sh swallows it with || true, docs-quality.yml sets continue-on-error -- while skills/release/SKILL.md:143 blocks on the RED label. The label is the only gate, so severity IS the block decision ADR-007 claimed it was not. Severity now follows demonstrated precision per-check rather than per-phase. D3: fix the noun boundary, anchor the substitution on the full matched span, and floor at max(2, 40%) -- all three, because F1's agent half is caused by the floor being 0 for agents, and a prose-corrupting fix is worse than a false warning. D4: fix the [e]xclude no-op at the record level across Phase 7 and Phase 9. Correction: this was relayed as a regression from #334 and is not -- dev already has add_finding with "${file}:${lineno}" at 341, 497 and 548. Pre-existing, two phases wide, and a live violation of the rule ADR-007 states. D5: amend #334 rather than merge-then-harden. craft's docs are hyphen-heavy, so shipping first means dev carries a --fix that can rewrite prose. Spec updated where the grill overtook it: status, the C3 correction, and scope (Phase 9 in, tag/fetch-tags out). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(plan): ORCHESTRATE for prose-check hardening + 6th grill branch Routed by /craft:plan tier detection: SPEC present, GRILL present, no ORCHESTRATE -> plan-orchestrator (tier 4). Worktree already exists, so no new one was created. Six phases mapped to the locked decisions, sequential, one commit each: matcher/payload/floor (D3), check 1 to cross-file consistency (D1, D6), severity split and the ADR correction (D2), exclusion round-trip at the record level (D4), the two low findings plus doc sync, then verify and update PR #334 (D5). Authoring the plan surfaced a gap the grill left: the spec listed 9 decisions and the grill locked 5, so the release-date window discipline (spec D4 / finding F3) was never resolved. D1 settled where the authority comes from, not how claims are collected -- so prose like "Upgrading to v4.5.0 is a drop-in change" would still open a window and turn a nearby unrelated date into a claim for that version. The false positive survived the redesign in a new place. Resolved as ledger D6: the window opens only when the version token appears in a heading or a version-box line. Structural rather than numeric -- shrinking the window narrows the class without closing it, and requiring version and date on one line would miss the real NEWS.md layout the check exists for. D2 raises the stakes, since check 1 is now RED and every surviving false positive blocks a release. Friction Prevention records the traps this work already hit once: the awk pre-filter and bash matcher are two regexes expressing one rule and must move together, and the 30s test_pre_release_check_runs budget is the only thing that caught the last perf regression. No implementation this session -- plan artifact only, per the confirm gate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(plan): grill the ORCHESTRATE — 5 plan-level branches, 4 found defects Grilling the plan rather than the design. Four of the five branches found something wrong with the plan; only one confirmed it. D7 phase order: the record change moves to FIRST. As written, Phases 1-3 authored add_finding calls and tests against the old signature and Phase 4 then rewrote all 12 call sites (Phase 6 x2, 7 x3, 8 x3, 9 x4) -- every prose finding written twice, and the mechanical 12-site sweep landing last, where a missed site is hardest to spot against three phases of other changes. D8 fixtures: "delete ... or rewrite" narrowed to rewrite-only. D6 keeps a window, so the off-by-one class is still live and defect/release-date-far-edge.md is its only positive control -- the exact bug /code-review caught. The plan permitted deleting it with an "or". Generalized into Friction Prevention: never delete a positive control to make a redesign easier. D9 normalize the claim sites. Evidence gathered while grilling: craft has exactly two release-date claims for the current version and they already disagree -- NEWS.md 2026-08-08 (UTC) vs REFCARD.md 2026-08-07 (tag-local). Both reachable under D6, so check 1 fires on craft today and only the one-day tolerance keeps it GREEN. With D2 making it RED, the repo would sit permanently one day from a blocked release with no prior warning. D10: Phase 6 gains the .STATUS refresh and the at-merge ORCHESTRATE deletion. Both required by craft's CLAUDE.md, neither enforced -- not gitignored, not in exclusions.txt, no test. D11: RED promotion is evidence-gated. Check 1 is redesigned and promoted to release-blocking in the same PR, so it ships as warning and is promoted in Phase 6 only after running clean over the real docs with the transcript quoted. Does not reverse D2 -- makes RED earned rather than assumed. Estimate corrected 2h -> ~3h; the original was wishful about Phase 1. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e row ORCHESTRATE-*.md files are feature-branch working artifacts, not dev content (craft CLAUDE.md, grill decision D10). Nothing enforces this — the file is not gitignored, not in exclusions.txt, and no test guards it. .STATUS row flipped to MERGED and rewritten to say what actually shipped, including what did not: a high-effort review found 9 further defects, 2 of them HIGH, and the hardening is spec'd and grilled but not implemented. Recorded plainly rather than left implicit, since check 2's --fix can corrupt prose until that work lands. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Recreated rather than reused. After #334's squash-merge the old worktree's branch no longer descended from dev, so `git diff origin/dev...HEAD` re-proposed 24 files / +1666 lines already merged, against 2 files of real difference -- the ahead/behind counts read "dev ahead 3, branch ahead 10" and meant nothing. Continuing there would have made the next PR unreviewable. The branch name was also wrong: doc-staleness-prose-gaps shipped, this is the hardening. Deletion gated on the PR head matching the local tip (nothing added after the merge) and the merge commit being an ancestor of dev, per the squash-merge footgun -- `git cherry` misreports squash-merged branches as unmerged. Nothing lost: SPEC and GRILL are on dev; the ORCHESTRATE was restored into the new worktree from b5de1ae. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Full docs-staleness-check.sh (all 4 gating phases) and post-release-sweep.sh already read GREEN/CLEAN. This is the advisory-only pass on top --audit-exclusions plus real content review, per the project's doc-currency check. REFCARD.md:9 claimed "2632+ passing" -- unguarded (no script owns this box line; claude_md_sync.py only tracks CLAUDE.md's bold **Tests:** form), and already wrong against the measured dev baseline (2462 passed / 20 failed). Same class as the README fix earlier this session -- swapped the hard number for the command that produces it, so it can't drift again. Also removed a duplicate "All 1432 tests passing" claim further down the same file, equally unguarded. Re-padded the box borders to the file's existing 63-char width. Pruned 6 exclusions.txt entries, all dead for one of two reasons: - docs/commands/orchestrate.md:4 agents -- file deleted (orch rename, v2.60.0) - The other 5 sat under docs/cookbook/ or docs/examples/, both already whole-directory excluded (lines 27-28) -- the per-pattern entries were redundant from the start, and their target numbers have since drifted further (94 -> 115), so they matched nothing either way. Verified: docs-staleness-check.sh GREEN (0 issues), --audit-exclusions "All exclusions valid" (was 6 stale), validate-counts.sh 4/4, markdownlint 0 errors, mkdocs build --strict clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
) * fix(docs-staleness): carry finding location as its own field (D4/F4) add_finding glued file+lineno into one string ("path:lineno"). Pass 2's [e]xclude writes an entry against $file expecting a bare path, so every Phase 7/9 exclusion request wrote a pattern that could never match is_pattern_excluded's path:pattern parse -- it printed "Excluded" and the finding came back on the next run. Predates PR #334; not a regression it introduced (git show dev: confirms the same glued shape at lines 341/497/548 before this PR). Splits the record into file + locator, threading the change through all 12 add_finding call sites, both consumers (pass1_auto_fix, pass2_interactive_review), and findings_to_json -- JSON output shape is unchanged (still emits "file":"path:locator" via a shared finding_location() helper). New test drives the real interactive [e] keystroke through a pty (pexpect), not a Python reimplementation of pass 2's write logic -- verifies the exclusion actually suppresses the finding on a second run. Phase 1 of 6 in the prose-check hardening (SPEC/GRILL-prose-check- hardening-2026-08-15.md, decision D4). Adds the ORCHESTRATE plan file, restored from the pre-merge worktree per handoff. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): matcher boundary, span-anchored fix, real floor (D3/F1/F2/F6) Check 2's noun trailer, `([^a-z]|$)`, treats `-` as a valid boundary character, so hyphenated compounds read as counts: "30 command-line entry points" matched as "30 command" (expected 48), "3 agent-facing surfaces" as "3 agent" (expected 2). Replaced with PROSE_COUNT_TRAILER (whitespace, closing punctuation, or end-of-line), shared by the awk pre-filter and the bash matcher so the two can't drift apart again -- independent tuning of that pair already caused a 4x perf regression once. Accepting the offered [f]ix on a genuine match corrupted the surrounding prose: the substitution was built from a second, un-anchored "N noun" regex with no trailer at all, so it could match a different (shorter) span than detection did. Detection and the fix anchor now derive from one captured span. The 40%-of-expected floor is 0 for agents (`2 * 40 / 100 == 0`), so the guard ADR-007 and two code comments cite as what makes shaped-line counts safe did not exist for the smallest count type -- any "N agent(s)" mention, however small, read as a stale-total candidate. Floored at max(2, 40%). New fixtures are positive controls, not just happy-path coverage: reverted the source change and confirmed both new falsepos cases fail (docs/ architecture.md flags '30 command'/'3 agent'; docs/migration.md flags '1 agent') before restoring the fix. A new pty-driven [f]ix test asserts the surrounding prose ("agent definitions") survives the substitution. E1 pin (defect/structure-table-singular.md, clean/structure-table- correct.md) and the release-date off-by-one guard (defect/release-date-far-edge.md) both still pass unchanged. 21/21 tests, ~10s raw script run (well under the 30s pre-release-check timeout). Phase 2 of 6 in the prose-check hardening (SPEC/GRILL-prose-check- hardening-2026-08-15.md, decision D3). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): check 1 -> cross-file consistency, heading-scoped window (D1/D6/F3/F7) Check 1 compared every release-date claim against the current version's git tag, but the tag doesn't exist at either point this check actually runs: the release pipeline writes NEWS/REFCARD dates in Step 3b, before Step 8 creates the tag, and docs-quality.yml's checkout has no fetch-tags. As built, the check only ever fired on a developer machine that had already pulled a tag that isn't the one being released -- not a gate anywhere it runs (F7). Dropped the external authority. Every release-date claim for the current version is now compared against every other one via a new majority_date() helper: most claims wins, ties break to the LATER date (a stale-date bug is a forgotten update, so the wrong claim is normally older than the correct one, never newer -- with the common case of exactly two claims, NEWS.md and a REFCARD-style box, every tie is 1-1, so this is what decides which one is "authority"). The one-day tolerance survives as the agreement window between claims, still absorbing the real UTC-boundary case (v4.5.0: NEWS.md 2026-08-08, REFCARD 2026-08-07). Vacuous with 0-1 claims, same posture as the old missing-tag case -- accepted cost, cannot catch a date uniformly wrong in every file. Separately, the claim-collection window opened on ANY line containing the version token, including running prose ("Upgrading to v4.5.0 is a drop-in change") -- a nearby unrelated date then got collected as though it were this version's release date (F3). Now requires the version token sit in a markdown heading or a version-box content line (D6). Test harness changed shape to match: check 1 needs a peer claim to agree or disagree with, so its fixtures now pair via a new build_repo_multi() helper instead of the single-fixture harness every other check uses. Reverted the source change and confirmed the 4 new/changed release-date tests fail against the pre-fix code (2 real assertion failures on the redesigned checks, 2 "command not found" for the not-yet-existing majority_date) before restoring the fix. 25/25 tests, ~12s raw script run. Phase 3 of 6 in the prose-check hardening (SPEC/GRILL-prose-check- hardening-2026-08-15.md, decisions D1 and D6). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): severity split -- check 1 error, check 2 warning (D2/F5) Check 1 (release-date consistency) now emits `error`; check 2 (count prose) stays `warning`. Not cosmetic: pre-release-check.sh:280 runs this whole script as `... || true`, discarding the exit code, and docs-quality.yml sets continue-on-error -- no consumer reads the process exit status. skills/release/SKILL.md:143 blocks on the RED label alone. The severity string IS the block decision, not a secondary label on top of one. Check 1 earns error: after the D1 cross-file redesign it's near-binary, two claims either agree or they don't. Check 2 stays warning: it matches free-form prose patterns and produced three false-positive defects in the PR that introduced it (a hyphenated-compound false match, a zero-floor for the smallest count type, five sub-threshold counts caught pre-merge) -- it hasn't earned a blocker yet. Rewrote ADR-007's Severity section, which had asserted "both severities already block the gate, so the label doesn't matter" -- checked during this review and found false per the citations above. Removed the claim, not softened it, per this branch's own rule (docs/adr's "reports success, changes nothing" posture applies to a doc's claims as much as a script's [f]ix). Also updated the ADR's authority description, still describing release dates as checked against a git tag from before the D1 rewrite. New test reverts the severity change and confirms it fails (check 1's finding comes back "warning" instead of "error") before restoring the fix. 26/26 tests. Phase 4 of 6 in the prose-check hardening (SPEC/GRILL-prose-check- hardening-2026-08-15.md, decision D2). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): un-promote check 1 to warning, gate error on evidence (D11) The previous commit shipped check 1 at severity error directly, skipping D11's evidence gate: "Check 1 ships as warning in this phase. Promotion to error happens in Phase 6, gated on evidence -- the check is being redesigned and promoted in one PR, and the only evidence it is sound would otherwise be tests written alongside it by the same author in the same sitting." (ORCHESTRATE-prose-check-hardening.md Phase 4.) Reverted check 1 to warning. Promotion to error belongs in Phase 6, after a clean run across every tracked doc and both real claim sites (docs/NEWS.md, docs/REFCARD.md) with the transcript quoted -- not on a passing unit suite alone. Rewrote ADR-007's Severity section to describe the gate rather than an unconditional split: check 1 is *designed* to block (D2) but ships warning until it earns error. Replaced the severity test, which had pinned the premature promotion, with two: one confirming both checks still ship warning pending the gate, and a second (test_phase_status_goes_red_on_any_error_finding) that pins the underlying mixed-severity mechanism directly against phase_status_label -- an error finding among warnings goes RED, an all-warning phase stays YELLOW -- independent of which check is promoted when, since neither check emits error yet. 27/27 tests. Still Phase 4 of 6 (SPEC/GRILL-prose-check-hardening-2026-08-15.md, decisions D2 and D11) -- this corrects the previous commit rather than starting Phase 5. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): box-close discipline, doc/regex sync, date normalization (D9/F8/F9) F8: an unclosed version-box (opening box character with no matching closing one) leaked `inbox` mode into the rest of the file, so a later structure-table row lost its own-type restriction. Closed at the FIRST line carrying no box-drawing character at all, not only on an explicit closing character. Discovered while planting F8's fixture: the broad, unscoped plural-only count scan shares check 2's F1 hyphen-boundary bug -- "7 agents-only" matched as "7 agents" (expected 2), and this scan's findings are auto-fixable, so it's worse than F2 (no human in the loop under `--fix --non-interactive`). Not a separately enumerated finding; surfaced by the hardening SPEC's own hyphenated-compound acceptance criterion (command-line, agent-facing, skill-authoring, agents-only). Fixed with the same PROSE_COUNT_TRAILER and span-anchored substitution as check 2. F9: REFCARD-DOCS-STALENESS.md described `tldr` as "a line containing TL;DR"; the regex requires the line to open with it (deliberate, so a doc describing this bug isn't itself flagged for the example it quotes). Fixed the doc. D9: normalized the two real release-date claim sites. docs/NEWS.md's v4.5.0 entry moved from 2026-08-08 (GitHub release UTC) to 2026-08-07 (tag-local); docs/REFCARD.md's box line gained the `v4.5.0` prefix it was missing -- without it, the line sat 4 lines before the box's other "v4.5.0" mention, so D6's forward-only window never reached it, and REFCARD contributed zero claims regardless of date value. Both CHANGELOGs' v4.5.0 headings synced to match. Recorded the convention in skills/release/references/pipeline-steps.md so it doesn't drift again. Verified live: injected a temporary mismatch into REFCARD.md's date and confirmed check 1 caught it ("disagrees with other claims (majority: 2026-08-07)") before reverting the injection. Added a "Superseded" pointer to the parent SPEC-doc-staleness-prose-gaps -2026-08-07.md rather than rewriting its historical acceptance criteria, and marked the hardening SPEC's own acceptance criteria against verified evidence gathered across all five phases so far. New/changed fixtures verified as positive controls by reverting each fix and re-testing: falsepos/unclosed-box-leaks-into-table.md (uses the singular noun form so it isolates the shape-classification bug from the unrelated broad scan) and the broadened hyphenated-compound-tldr.md (now covers skill-authoring, agents-only). 28/28 tests, ~11s raw script run. Phase 5 of 6 in the prose-check hardening (SPEC/GRILL-prose-check- hardening-2026-08-15.md, decision D9). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(docs-staleness): Phase 6 verify + promote check 1 to error (D11) Full-suite run surfaced 2 regressions not in the original F1-F9 list, both introduced by earlier phases in this branch: - PROSE_COUNT_TRAILER was missing `*` from its boundary-char class, so the broad plural-only count scan never matched markdown-bold badges like README's `**777 commands**` -- the char after "commands" is `*`, not whitespace/punctuation/EOL. Added `*` to the trailer and both noun-trim sed patterns that must stay in sync with it. - bump-version.sh --verify's literal `Version: X.Y.Z` grep broke against Phase 5's REFCARD.md wording (`v4.5.0 (released ...)`, added to satisfy D6's window). Reworded to `Version: 4.5.0 (v4.5.0, released ...)`, satisfying both the grep and D6's same-line version-token requirement. Both verified via revert-and-retest positive control before restoring. Full suite: 2476 passed / 0 failed (dev baseline: 2462 passed / 20 failed). D11 promotion gate cleared: docs-staleness-check.sh --json returned 0 count_consistency findings across every tracked doc, reaching both real claim sites (docs/NEWS.md, docs/REFCARD.md). Live-fire transcript: injecting 2020-01-01 into docs/REFCARD.md:7 produced "release date '2020-01-01' for v4.5.0 disagrees with other claims (majority: 2026-08-07)", reverted after confirming. Check 1 promoted warning->error; check 2 stays warning. ADR-007 and REFCARD-DOCS-STALENESS.md updated to match (the latter also had stale pre-redesign prose describing the old git-tag authority and the now-deleted CRAFT_RELEASE_DATE override). .STATUS worktree row refreshed (D10); ORCHESTRATE Phase 6 + Acceptance Criteria checkboxes marked with evidence. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test(docs-staleness): drop dead CRAFT_RELEASE_DATE env var from fixtures Flagged by an independent architecture review of PR #335: the only consumer, resolve_release_date(), was deleted in this branch's Phase 3 redesign (check 1 moved from a single external authority to cross-file consistency), but 3 test call sites still set the env var. Harmless (unread by the script) but stale -- a future reader would assume it still did something. FIXTURE_TAG_DATE itself stays; it still documents the date fixtures are authored against (e.g. clean/release-date-companion.md's literal "2026-08-07"). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Consolidated the prose-check-hardening worktree row into a MERGED entry (squash 7d79228) with the D11 promotion, arch-review, and mid-flight rebase-conflict evidence; cross-referenced the superseded #334 row. Also deletes ORCHESTRATE-prose-check-hardening.md, which the squash-merge carried onto dev -- a feature-branch working artifact per craft's own CLAUDE.md convention, not dev content. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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
docs-staleness-check.shPhase 7 — release-date consistency and count-prose scoped to 4 structured line shapes, closing a blind spot where stale counts read GREEN for multiple releases.erroronce a clean live-repo run confirmed it. Count-prose boundary handling fixed for hyphenated compounds and markdown-bold badges.scholar.[4.6.0]section inCHANGELOG.md/docs/CHANGELOG.md.Test plan
test_branch_guard_dogfood.py, pre-existing/environmental (installed hook symlinks to the siblingcc-configrepo, out of scope per cross-repo permission boundary — same documented issue as v4.5.0's own release notes). Not caused by this release's diff.pre-release-check.sh 4.6.0— PASSED, all 10 checks greendocs-staleness-check.sh— GREEN (0 issues), including a live catch-and-fix mid-release:bump-version.shleftdocs/REFCARD.md's embedded date/headline stale (still describing v4.5.0), fixed and re-verified GREENmarkdownlint— 0 errors across all changed files./scripts/bump-version.sh --verify— ALL CONSISTENT🤖 Generated with Claude Code