V5.5.0 beta - #205
Draft
mxriverlynn wants to merge 51 commits into
Draft
Conversation
Introduces han-ddd as an opt-in plugin carrying the ddd-analysis skill and seven specialist agents: domain-language-analyst, business-capability-analyst, domain-ownership-analyst, bounded-context-analyst, domain-map-synthesizer, bounded-context-modeler, and bounded-context-critic. The skill orchestrates a 12-step analysis flow: scope resolution, repository inventory, parallel discovery across five agents (domain-language-analyst, business-capability-analyst, domain-ownership-analyst, han-core:structural-analyst, han-core:behavioral-analyst), a bounded-context-modeler first pass, a bounded-context-critic evaluation, exactly one revision pass, and a synthesized report rendered from a references/ template into thirteen sections (Executive Summary, Domain Landscape, Ubiquitous Language, Business Capabilities, Current/Latent/Speculative contexts, Boundary Problems, Context Map, Context Details, Rejected Candidates, Questions for Domain Experts, Evidence Index). Registers han-ddd in both marketplace manifests and updates the agents and skills indexes. Depends on han-communication and han-core; not bundled by the han meta-plugin. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…used agents All seven agent role identities trimmed to under 50 tokens per agent-domain-focus guidance. domain-map-synthesizer description tightened to under 1024 characters. bounded-context-analyst and domain-map-synthesizer removed: every dimension of bounded-context-analyst is covered by the five specialized discovery agents, and domain-map-synthesizer's synthesis and output are fully covered by bounded-context-modeler, bounded-context-critic, and the skill's report rendering. All references updated across agent definitions, long-form docs, the agents index, the plugin README, and CLAUDE.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…analyst "evaluate" implied structural-analyst determines whether directories correspond to domain language boundaries — that inference belongs to bounded-context-modeler. Changed to "surface" to accurately describe what structural-analyst does: it surfaces S# structural findings. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The "What you get back" section claimed completeness ("these named sections")
but listed 9 of 13 sections, omitting Executive Summary, Domain Landscape,
Ubiquitous Language, and Business Capabilities. Also corrects "Rejected or
Weak Candidates" to match the template name "Rejected or Weak Context
Candidates".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, restrict closing section - Step 8.5 is now a hard gate: identifier-integrity and speculative-isolation errors stop the run before rendering; artifacts are preserved and validation failure is reported instead of "Analysis complete" - Speculative isolation now covers Owns, Consumes, Does not own, Responsibilities, and Relationships fields — not only Relationships and Consumes - DDD Strategic Relationship Overreach detection in the critic now scans every BCM# entry field (Purpose, Responsibilities, Capabilities, Owns, Consumes, Does not own, Relationships), not only Relationships fields - Step 12 closing message is restricted to discovery-only next steps; asserting that a boundary violation can be fixed, prescribing a correction, or recommending extraction or refactoring is prohibited - Report template Executive Summary and Boundary Problems sections carry matching prohibitions on remediation language and code-only strategic DDD assertions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds han-ddd:domain-visualizer, a presentation-only agent that translates a completed DDD analysis into evidence-backed visual artifacts: domain landscape, capability map, workflow swimlanes, state-machine diagrams, ownership map, language collision matrix, boundary friction map, domain question impact map, and scenario diagrams for competing interpretations. The agent runs as the final step of /ddd-analysis after both hard gates pass. It reads the eight persisted artifacts from the run folder and writes Mermaid diagrams and Markdown tables to $run_folder/visuals/. Visual generation failure is isolated — the DDD model and rendered report remain valid regardless. Step 12 (new) writes the rendered report to $run_folder/synthesis/ddd-analysis.md and dispatches the visualizer. The old Step 12 (present the report) becomes Step 13, with an Analysis Visuals line added to its closing summary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bumps the dev-tooling group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [actions/setup-node](https://github.com/actions/setup-node) and [actions/cache](https://github.com/actions/cache). Updates `actions/checkout` from 6.0.3 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v6.0.3...v7.0.1) Updates `actions/setup-node` from 6.4.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@v6.4.0...v7.0.0) Updates `actions/cache` from 5.0.5 to 6.1.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](actions/cache@v5.0.5...v6.1.0) chore(deps-dev): bump the dev-tooling group with 2 updates Bumps the dev-tooling group with 2 updates: [@j178/prek](https://github.com/j178/prek) and [prettier](https://github.com/prettier/prettier). Updates `@j178/prek` from 0.4.9 to 0.4.11 - [Release notes](https://github.com/j178/prek/releases) - [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md) - [Commits](j178/prek@v0.4.9...v0.4.11) Updates `prettier` from 3.9.5 to 3.9.6 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](prettier/prettier@3.9.5...3.9.6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: dev-tooling - dependency-name: actions/setup-node dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: dev-tooling - dependency-name: actions/cache dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: dev-tooling - dependency-name: "@j178/prek" dependency-version: 0.4.11 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: prettier dependency-version: 3.9.6 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling ... Signed-off-by: dependabot[bot] <support@github.com>
Closes #107. The planning chain had no checkpoint forcing an interface or data contract into concrete, buildable form before implementation, so a "trusted" plan could ship a shared contract as a to-be-authored deliverable and a builder would invent it mid-build. Two additive gaps: plan-implementation never required a contract in concrete form, and plan-work-items split one contract across items with no rule against it. Adds han-planning/references/contract-pinning-rule.md, owned by han-planning and consumed by four skills. It defines what counts as a contract, what counts as pinned, the phrases that never close one, and which stage owns pinning it. The rule is binary: there is no deferred-with-reason state, because an author who has one writes "TBD at build" and passes. plan-implementation pins it: a new operating principle, a Decision-field rule making the decision log treat a format grammar the way it already treats a key name, a specialist-brief directive so the finding is generated at all, and a binary aggregation check that raises an Open Question rather than touching the spec-maturity gate's counted trip conditions. plan-work-items keeps it whole: a shared contract is pinned in the item that introduces it with consumers sequenced behind it, and the passive "not draftable" flag gains an exception for a contract this breakdown itself authors. Step 4 now reads the plan's Open Items, including the non-blocking ones it previously never looked at. iterative-plan-review backstops it: five keywords added to both force-up lists and a Contract Check in the iteration checklist. plan-a-feature records the delegation: routing rule 3 gains one carve-out so a shared contract becomes an Open Item rather than vanishing. check-contract-pinning.sh gives the rule a mechanical proxy, reporting four failure classes separately and skipping fenced blocks so a worked example never reads as a deferral. Two tests guard it beyond behavior: the two per-skill copies stay byte-identical, and every phrase the script owns appears in the canonical rule.
…guidance Two conformance fixes plus one gap the contract-pinning work missed. Script calls were fenced code blocks in five skills. The authoring guidance (han-plugin-builder/skills/guidance/references/skill-building-guidance/script-execution-instructions.md) requires prose with an action verb, because Claude may read a fenced block as code to display rather than a command to run. Converted every remaining call site: plan-a-feature, plan-a-phased-build, plan-work-items, and han-reporting/html-summary. plan-a-feature/SKILL.md was 501 lines, one past the 500-line ceiling. The `T#` note lifecycle was split across Step 4 (capture) and Step 5 (flush), which is how the two halves drift apart. Both now live in one owned reference, references/t-note-protocol.md, carrying the qualifying tests, the in-message accumulator form, the flush procedure, and the no-candidate case. The file is 476 lines. The contract-pinning change updated both force-up keyword lists in iterative-plan-review but missed a third in plan-a-feature's finding-resolution.md. A finding that leaves a shared contract un-pinned now forces up to major there too, and the pure-implementation branch names the Open Item carve-out that mechanic-routing.md added.
The CLAUDE.md repository layout named only references/ under the han-planning skills directory, but every one of its five skills also carries scripts/. The plan-implementation long-form doc opened its "What you get back" section with "Four cross-referenced files" and then listed three, omitting artifacts/scope-boundary.md, and its summary bullet promised "All three file paths". The section also never named the two executed checks the skill runs before it summarizes, though the sibling planning docs name theirs.
## Summary - Adds a contract-pinning checkpoint to the planning chain so a shared interface or data contract reaches concrete, buildable form before implementation instead of being invented mid-build. Closes #107. - One new owned rule (`han-planning/references/contract-pinning-rule.md`) consumed by four skills, plus one executable check with 15 Bats tests. - Second commit is guidance conformance and is reviewable on its own: script invocations converted from fenced blocks to prose across five skills, and `plan-a-feature/SKILL.md` brought under the 500-line ceiling. ## Why The chain (`plan-a-feature` → `plan-implementation` → `plan-work-items`, with `iterative-plan-review` as backstop) had no checkpoint forcing a contract into concrete form, so a "trusted" implementation plan could ship one as a to-be-authored deliverable. In the grounding incident the ledger's entry types were named but its line grammar never was: the schema doc shipped without it, a scanner invented a parsing regex against the undefined format, and the real grammar was retrofitted a day later. Zero of 17 review findings raised the gap. Two additive gaps caused it. `plan-implementation` never required a contract in concrete form, and `plan-work-items` split one contract across items with no rule against it. Fixing either alone leaves the other live. ## What reviewers should look at closely **The rule is binary, with no deferred-with-reason state.** That was deliberate: an author who has an escape hatch writes "the grammar depends on the serialization library, TBD at build" and passes while leaving the same hole. **The new aggregation check stays out of the spec-maturity gate.** That gate counts findings from distinct specialists, and a binary condition bolted onto counted logic breaks it. An unpinned contract raises an `OQ-N` instead, which the Step 6 loop already knows how to settle. **`plan-work-items` now reads the plan's Open Items.** It previously never looked at that section at all, so a non-blocking open item vanished at the last stage that could see it. This came from a comment on the issue and generalizes past contracts. **The script is the only non-prose enforcement.** Nine of ten changes are instructions followed by the same class of agent that missed the gap. `check-contract-pinning.sh` reports four failure classes separately and skips fenced blocks so a worked example never reads as a deferral. Two tests guard it beyond behavior: the per-skill copies stay byte-identical, and every phrase the script owns appears in the canonical rule. ## How to verify - [ ] `npm run lint` - [ ] `npm test` (95 tests, 15 of them new) - [ ] `bash han-planning/skills/plan-implementation/scripts/check-contract-pinning.sh <a plan file> <its folder>` against a real plan folder - [ ] Read `han-planning/references/contract-pinning-rule.md` first; every other change cites it ## Risk / rollback Low. Nothing here changes an existing check's pass condition, and the one new executable check is additive. The largest behavioral change is that `plan-implementation` now treats an unpinned contract as reason to keep iterating rather than to ship, which can add a round on a plan that introduces a format. Revert with `git revert`. ## Not in this PR - No version bump and no CHANGELOG entry; both belong to `/han-release`. - `feature-implementation-plan-template.md` is 163 lines with no Contents list. It is a document skeleton, so a Contents list would be copied into every plan it generates. Left as-is deliberately.
Re-sync the vendored config, evidence, and YAGNI rule files with the han-core canonical copies. Add the han-config-dir.sh symlink every plugin carries and switch the ddd-analysis personal-config probe to it, with the matching allowed-tools grant, instead of a hardcoded ~/.claude. Trim the bounded-context-critic description under the 1024-character target by moving the failure-mode catalog into the body where it already lives, and align the Codex manifest capabilities with the other plugins.
…the agent docs Add han-ddd to the plugin table and opt-in lists in README, the plugin index, concepts, CONTRIBUTING, and CLAUDE.md, naming domain-visualizer where the other han-ddd agents are listed. Add a ddd-analysis chain to the workflows map. Correct the agent long-form docs against their sources: the critic's eighteen failure modes and legitimacy checks, the modeler's IBN# and DC# outputs, the artifact-path briefing every han-ddd agent receives, the visualizer's trigger conditions, and the language analyst's structural-layout boundary. Add the Domain Concerns report section to the ddd-analysis doc.
This PR adds `han-ddd`, an opt-in plugin that runs strategic Domain-Driven Design analysis over an existing codebase and produces a bounded-context and domain map, so that teams can discover where their real domain boundaries live without hand-tracing the code themselves. ## Behavior changes Running the new `ddd-analysis` skill dispatches five discovery agents in parallel (domain-language, business-capability, domain-ownership, structural, and behavioral analysts), then runs a modeling loop over their findings: a first bounded-context pass, a critique pass, and a revision pass. The result is rendered through a structured report template. Every candidate context is classified as CURRENT (the boundary is strongly expressed in the code today), LATENT (a real boundary that implementation currently obscures), or SPECULATIVE (meaningful evidence, but needs a domain expert to confirm), and each classification must pass a legitimacy test before it appears. The skill is deliberately conservative about speculation. A hard validation gate (Step 8.5) stops the run and reports failure rather than showing a report when it detects identifier-integrity errors or speculative claims leaking outside their isolation, and that isolation now covers the Owns, Consumes, Does not own, Responsibilities, and Relationships fields rather than Relationships alone. Overreach detection likewise scans every field of every modeled context. The closing message is limited to discovery-oriented next steps and will not prescribe fixes, recommend extraction or refactoring, or claim a boundary problem can be resolved. `han-ddd` is not bundled by the han meta-plugin, so it is installed on its own. It depends on `han-communication` and `han-core`, and ships the five domain agents the skill orchestrates.
#199) Bumps the dev-tooling group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [actions/setup-node](https://github.com/actions/setup-node) and [actions/cache](https://github.com/actions/cache). Updates `actions/checkout` from 6.0.3 to 7.0.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v7.0.1</h2> <h2>What's Changed</h2> <ul> <li>skip running unsafe pr check if input is default by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2518">actions/checkout#2518</a></li> <li>trim only ascii whitespace for branch by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2521">actions/checkout#2521</a></li> <li>escape values passed to --unset by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2530">actions/checkout#2530</a></li> <li>Various dependency updates</li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v7...v7.0.1">https://github.com/actions/checkout/compare/v7...v7.0.1</a></p> <h2>v7.0.0</h2> <h2>What's Changed</h2> <ul> <li>block checking out fork pr for pull_request_target and workflow_run by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li> <li>Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the minor-actions-dependencies group across 1 directory by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2458">actions/checkout#2458</a></li> <li>Bump flatted from 3.3.1 to 3.4.2 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2460">actions/checkout#2460</a></li> <li>Bump js-yaml from 4.1.0 to 4.2.0 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2461">actions/checkout#2461</a></li> <li>Bump <code>@actions/core</code> and <code>@actions/tool-cache</code> and Remove uuid by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2459">actions/checkout#2459</a></li> <li>upgrade module to esm and update dependencies by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2463">actions/checkout#2463</a></li> <li>Bump the minor-npm-dependencies group across 1 directory with 3 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2462">actions/checkout#2462</a></li> <li>getting ready for checkout v7 release by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2464">actions/checkout#2464</a></li> <li>update error wording by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2467">actions/checkout#2467</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v6.0.3...v7.0.0">https://github.com/actions/checkout/compare/v6.0.3...v7.0.0</a></p> <h2>v6.1.0</h2> <h2>What's Changed</h2> <ul> <li><strong>[BREAKING]</strong> backport <code>allow-unsafe-pr-checkout</code> to v6 by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2500">actions/checkout#2500</a></li> <li>backport fixes to releases-v6 by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2527">actions/checkout#2527</a></li> </ul> <p><a href="https://github.blog/changelog/2026-06-18-safer-pull_request_target-defaults-for-github-actions-checkout/">https://github.blog/changelog/2026-06-18-safer-pull_request_target-defaults-for-github-actions-checkout/</a> for more details about this breaking change</p> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v6.0.3...v6.1.0">https://github.com/actions/checkout/compare/v6.0.3...v6.1.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h2>v7.0.1</h2> <ul> <li>Skip running unsafe pr check if input is default by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2518">actions/checkout#2518</a></li> <li>Trim only ascii whitespace for branch by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2521">actions/checkout#2521</a></li> <li>Escape values passed to --unset by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2530">actions/checkout#2530</a></li> <li>Various dependency updates</li> </ul> <h2>v7.0.0</h2> <ul> <li>Block checking out fork PR for pull_request_target and workflow_run by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li> <li>Various dependency updates</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/3d3c42e5aac5ba805825da76410c181273ba90b1"><code>3d3c42e</code></a> prep v7.0.1 release (<a href="https://redirect.github.com/actions/checkout/issues/2531">#2531</a>)</li> <li><a href="https://github.com/actions/checkout/commit/28802689a136bfcdb721715abd713740beecbe07"><code>2880268</code></a> escape values passed to --unset (<a href="https://redirect.github.com/actions/checkout/issues/2530">#2530</a>)</li> <li><a href="https://github.com/actions/checkout/commit/12cd2235efa0937479335606d7c3ac9f6c0973b1"><code>12cd223</code></a> trim only ascii whitespace for branch (<a href="https://redirect.github.com/actions/checkout/issues/2521">#2521</a>)</li> <li><a href="https://github.com/actions/checkout/commit/62661c4e71a304b2823ed026347b8d34c3eac541"><code>62661c4</code></a> skip running unsafe pr check if input is default (<a href="https://redirect.github.com/actions/checkout/issues/2518">#2518</a>)</li> <li><a href="https://github.com/actions/checkout/commit/e8d4307400f9427dba7cb98e488d6ab85f1cec5f"><code>e8d4307</code></a> Bump the minor-actions-dependencies group with 2 updates (<a href="https://redirect.github.com/actions/checkout/issues/2499">#2499</a>)</li> <li><a href="https://github.com/actions/checkout/commit/631c942040754b6e095e929c1677c07e10ed4f87"><code>631c942</code></a> eslint 9 (<a href="https://redirect.github.com/actions/checkout/issues/2474">#2474</a>)</li> <li><a href="https://github.com/actions/checkout/commit/4f1f4aec02e41874fa0262ea8ff5172d7978ad1e"><code>4f1f4ae</code></a> Bump actions/upload-artifact from 4 to 7 (<a href="https://redirect.github.com/actions/checkout/issues/2476">#2476</a>)</li> <li><a href="https://github.com/actions/checkout/commit/ba097532fb203f7e88c9c3c0b899b49469908a92"><code>ba09753</code></a> Bump actions/checkout from 6 to 7 (<a href="https://redirect.github.com/actions/checkout/issues/2488">#2488</a>)</li> <li><a href="https://github.com/actions/checkout/commit/b9e0990d219a03df7633c93f6f005a8fecbcab22"><code>b9e0990</code></a> Bump docker/login-action from 3.3.0 to 4.2.0 (<a href="https://redirect.github.com/actions/checkout/issues/2479">#2479</a>)</li> <li><a href="https://github.com/actions/checkout/commit/e8cb398be4a550817e382abf69e4c12c76fce1f2"><code>e8cb398</code></a> Bump docker/build-push-action from 6.5.0 to 7.2.0 (<a href="https://redirect.github.com/actions/checkout/issues/2478">#2478</a>)</li> <li>Additional commits viewable in <a href="https://github.com/actions/checkout/compare/v6.0.3...v7.0.1">compare view</a></li> </ul> </details> <br /> Updates `actions/setup-node` from 6.4.0 to 7.0.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/setup-node/releases">actions/setup-node's releases</a>.</em></p> <blockquote> <h2>v7.0.0</h2> <h2>What's Changed</h2> <h3>Enhancements:</h3> <ul> <li>Add cache-primary-key and cache-matched-key as outputs by <a href="https://github.com/gowridurgad"><code>@gowridurgad</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1577">actions/setup-node#1577</a></li> <li>Migrate to ESM and upgrade dependencies by <a href="https://github.com/gowridurgad"><code>@gowridurgad</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1574">actions/setup-node#1574</a></li> </ul> <h3>Bug fixes:</h3> <ul> <li>Remove dummy NODE_AUTH_TOKEN export by <a href="https://github.com/gowridurgad"><code>@gowridurgad</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1558">actions/setup-node#1558</a></li> <li>Only use <code>mirrorToken</code> in <code>getManifest</code> if it's provided by <a href="https://github.com/deiga"><code>@deiga</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li> </ul> <h3>Documentation updates:</h3> <ul> <li>Add documentation for publishing to npm with Trusted Publisher (OIDC) by <a href="https://github.com/chiranjib-swain"><code>@chiranjib-swain</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li> <li>docs: Update restore-only cache documentation by <a href="https://github.com/priya-kinthali"><code>@priya-kinthali</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1550">actions/setup-node#1550</a></li> <li>docs: Update caching recommendations to mitigate cache poisoning risks by <a href="https://github.com/chiranjib-swain"><code>@chiranjib-swain</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1567">actions/setup-node#1567</a></li> </ul> <h3>Dependency update:</h3> <ul> <li>Upgrade <code>@actions/cache</code> to 5.1.0, log cache write denied by <a href="https://github.com/jasongin"><code>@jasongin</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/chiranjib-swain"><code>@chiranjib-swain</code></a> made their first contribution in <a href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li> <li><a href="https://github.com/deiga"><code>@deiga</code></a> made their first contribution in <a href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li> <li><a href="https://github.com/jasongin"><code>@jasongin</code></a> made their first contribution in <a href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/setup-node/compare/v6...v7.0.0">https://github.com/actions/setup-node/compare/v6...v7.0.0</a></p> <h2>v6.5.0</h2> <h2>What's Changed</h2> <ul> <li>Update <code>@actions/cache</code> to 5.1.0 and add security overrides for undici and fast-xml-parser by <a href="https://github.com/HarithaVattikuti"><code>@HarithaVattikuti</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1579">actions/setup-node#1579</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0">https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/setup-node/commit/820762786026740c76f36085b0efc47a31fe5020"><code>8207627</code></a> Migrate to ESM and upgrade dependencies (<a href="https://redirect.github.com/actions/setup-node/issues/1574">#1574</a>)</li> <li><a href="https://github.com/actions/setup-node/commit/04be95cf3511ea51ebf9f224ddfb99cc7ab87cd4"><code>04be95c</code></a> Add cache-primary-key and cache-matched-key as outputs (<a href="https://redirect.github.com/actions/setup-node/issues/1577">#1577</a>)</li> <li><a href="https://github.com/actions/setup-node/commit/7c2c68d20d402ed6a201ada70a81341941093140"><code>7c2c68d</code></a> docs: Update caching recommendations to mitigate cache poisoning risks (<a href="https://redirect.github.com/actions/setup-node/issues/1567">#1567</a>)</li> <li><a href="https://github.com/actions/setup-node/commit/6a61c0375d66246de94630495909f12cf8dac84d"><code>6a61c03</code></a> Merge pull request <a href="https://redirect.github.com/actions/setup-node/issues/1569">#1569</a> from jasongin/update-actions-cache-5.1.0</li> <li><a href="https://github.com/actions/setup-node/commit/30eb73b41ded577900c1ebf968ef95cdf8f7434f"><code>30eb73b</code></a> Resolve high-severity audit issues</li> <li><a href="https://github.com/actions/setup-node/commit/4e1a87a501d0302f99e30e2748568adcb388d09f"><code>4e1a87a</code></a> Update dist</li> <li><a href="https://github.com/actions/setup-node/commit/360237f0c01778d0c17291f75c56d6feae4f7574"><code>360237f</code></a> Strict equality</li> <li><a href="https://github.com/actions/setup-node/commit/4f8aac5beb2f0854bc79651567a18c67eb0b9de3"><code>4f8aac5</code></a> Bump <code>@actions/cache</code> to 5.1.0, log cache write denied</li> <li><a href="https://github.com/actions/setup-node/commit/f4a67bbeca970f103397d3d2b9462cf787cd2980"><code>f4a67bb</code></a> Only use <code>mirrorToken</code> in <code>getManifest</code> if it's provided (<a href="https://redirect.github.com/actions/setup-node/issues/1548">#1548</a>)</li> <li><a href="https://github.com/actions/setup-node/commit/0355742c943ddb13ca8a6b700f824231caa91e75"><code>0355742</code></a> Remove dummy NODE_AUTH_TOKEN export (<a href="https://redirect.github.com/actions/setup-node/issues/1558">#1558</a>)</li> <li>Additional commits viewable in <a href="https://github.com/actions/setup-node/compare/v6.4.0...v7.0.0">compare view</a></li> </ul> </details> <br /> Updates `actions/cache` from 5.0.5 to 6.1.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/cache/releases">actions/cache's releases</a>.</em></p> <blockquote> <h2>v6.1.0</h2> <h2>What's Changed</h2> <ul> <li>Bump <code>@actions/cache</code> to v6.1.0 - handle read-only cache access by <a href="https://github.com/jasongin"><code>@jasongin</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1768">actions/cache#1768</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v6...v6.1.0">https://github.com/actions/cache/compare/v6...v6.1.0</a></p> <h2>v6.0.0</h2> <h2>What's Changed</h2> <ul> <li>Update packages, migrate to ESM by <a href="https://github.com/Samirat"><code>@Samirat</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1760">actions/cache#1760</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v5...v6.0.0">https://github.com/actions/cache/compare/v5...v6.0.0</a></p> <h2>v5.1.0</h2> <h2>What's Changed</h2> <ul> <li>Bump <code>@actions/cache</code> to v5.1.0 - handle read-only cache access by <a href="https://github.com/jasongin"><code>@jasongin</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1775">actions/cache#1775</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v5...v5.1.0">https://github.com/actions/cache/compare/v5...v5.1.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/cache/blob/main/RELEASES.md">actions/cache's changelog</a>.</em></p> <blockquote> <h3>6.1.0</h3> <ul> <li>Bump <code>@actions/cache</code> to v6.1.0 to pick up <a href="https://redirect.github.com/actions/toolkit/pull/2435">actions/toolkit#2435 Handle cache write error due to read-only token</a></li> <li>Switch redundant "Cache save failed" warning to debug log in save-only</li> </ul> <h3>6.0.0</h3> <ul> <li>Updated <code>@actions/cache</code> to ^6.0.1, <code>@actions/core</code> to ^3.0.1, <code>@actions/exec</code> to ^3.0.0, <code>@actions/io</code> to ^3.0.2</li> <li>Migrated to ESM module system</li> <li>Upgraded Jest to v30 and test infrastructure to be ESM compatible</li> </ul> <h3>5.0.4</h3> <ul> <li>Bump <code>minimatch</code> to v3.1.5 (fixes ReDoS via globstar patterns)</li> <li>Bump <code>undici</code> to v6.24.1 (WebSocket decompression bomb protection, header validation fixes)</li> <li>Bump <code>fast-xml-parser</code> to v5.5.6</li> </ul> <h3>5.0.3</h3> <ul> <li>Bump <code>@actions/cache</code> to v5.0.5 (Resolves: <a href="https://github.com/actions/cache/security/dependabot/33">https://github.com/actions/cache/security/dependabot/33</a>)</li> <li>Bump <code>@actions/core</code> to v2.0.3</li> </ul> <h3>5.0.2</h3> <ul> <li>Bump <code>@actions/cache</code> to v5.0.3 <a href="https://redirect.github.com/actions/cache/pull/1692">#1692</a></li> </ul> <h3>5.0.1</h3> <ul> <li>Update <code>@azure/storage-blob</code> to <code>^12.29.1</code> via <code>@actions/cache@5.0.1</code> <a href="https://redirect.github.com/actions/cache/pull/1685">#1685</a></li> </ul> <h3>5.0.0</h3> <blockquote> <p>[!IMPORTANT] <code>actions/cache@v5</code> runs on the Node.js 24 runtime and requires a minimum Actions Runner version of <code>2.327.1</code>. If you are using self-hosted runners, ensure they are updated before upgrading.</p> </blockquote> <h3>4.3.0</h3> <ul> <li>Bump <code>@actions/cache</code> to <a href="https://redirect.github.com/actions/toolkit/pull/2132">v4.1.0</a></li> </ul> <h3>4.2.4</h3> <ul> <li>Bump <code>@actions/cache</code> to v4.0.5</li> </ul> <h3>4.2.3</h3> <ul> <li>Bump <code>@actions/cache</code> to v4.0.3 (obfuscates SAS token in debug logs for cache entries)</li> </ul> <h3>4.2.2</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/cache/commit/55cc8345863c7cc4c66a329aec7e433d2d1c52a9"><code>55cc834</code></a> Merge pull request <a href="https://redirect.github.com/actions/cache/issues/1768">#1768</a> from jasongin/readonly-cache</li> <li><a href="https://github.com/actions/cache/commit/d8cd72f230726cdf4457ebb61ec1b593a8d12337"><code>d8cd72f</code></a> Bump <code>@actions/cache</code> to v6.1.0 - handle cache write error due to RO token</li> <li><a href="https://github.com/actions/cache/commit/2c8a9bd7457de244a408f35966fab2fb45fda9c8"><code>2c8a9bd</code></a> Merge pull request <a href="https://redirect.github.com/actions/cache/issues/1760">#1760</a> from actions/samirat/esm_migration_and_package_update</li> <li><a href="https://github.com/actions/cache/commit/e9b91fdc3fea7d79165fceb79042ef45c2d51023"><code>e9b91fd</code></a> Prettier fixes</li> <li><a href="https://github.com/actions/cache/commit/e4884b8ff7f92ef6b52c79eda480bbc86e685adb"><code>e4884b8</code></a> Rebuild dist</li> <li><a href="https://github.com/actions/cache/commit/10baf0191a3c426ea0fa4a3253a5c04233b6e18f"><code>10baf01</code></a> Fixed licenses</li> <li><a href="https://github.com/actions/cache/commit/e39b386c9004d72a15d864ade8c0b3a702d47a37"><code>e39b386</code></a> Fix test mock return order</li> <li><a href="https://github.com/actions/cache/commit/b6928203372a8571ff984c0c883ef3a1adfb0c06"><code>b692820</code></a> PR feedback</li> <li><a href="https://github.com/actions/cache/commit/60749128a44d25d3c520a489e576380cf00ff3f1"><code>6074912</code></a> Rebuild dist bundles as ESM to match type:module</li> <li><a href="https://github.com/actions/cache/commit/5a912e8b4af820fa082a0e75cfd2c782f8fbfe0e"><code>5a912e8</code></a> Fix lint and jest issues</li> <li>Additional commits viewable in <a href="https://github.com/actions/cache/compare/v5.0.5...v6.1.0">compare view</a></li> </ul> </details> <br /> Bumps the dev-tooling group with 2 updates: [@j178/prek](https://github.com/j178/prek) and [prettier](https://github.com/prettier/prettier). Updates `@j178/prek` from 0.4.9 to 0.4.11 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/j178/prek/releases">@j178/prek's releases</a>.</em></p> <blockquote> <h2>0.4.11</h2> <h2>Release Notes</h2> <p>Released on 2026-07-25.</p> <h3>Highlights</h3> <ul> <li> <p>This release adds two new builtin hooks, <code>deny-pattern</code> and <code>require-pattern</code>, as native alternatives for <code>pygrep</code> use cases. <code>deny-pattern</code> fails when a configured pattern is found, while <code>require-pattern</code> ensures every selected file contains a match. By matching natively without spawning a Python subprocess, they run over 4x faster than <code>pygrep</code> in benchmarks. Note that they use <a href="https://docs.rs/regex/latest/regex/#syntax">Rust <code>regex</code> syntax</a>, which does not support look-around features such as negative lookbehind.</p> </li> <li> <p><code>prek run</code> now supports <code>--glob <PATTERN></code> to run hooks on tracked files matching a glob. It can be repeated or combined with <code>--files</code> and <code>--directory</code>.</p> </li> <li> <p>Hook priorities now support reusable aliases:</p> <pre lang="toml"><code>[priorities] checks = 10 <p>[[repos]] repo = "builtin" hooks = [ { id = "check-json", priority = "checks" }, { id = "check-yaml", priority = "checks" }, ] </code></pre></p> <p>This makes parallel scheduling easier to read and maintain.</p> </li> </ul> <h3>Enhancements</h3> <ul> <li>Add <code>deny-pattern</code> and <code>require-pattern</code> builtin hooks (<a href="https://redirect.github.com/j178/prek/pull/2359">#2359</a>)</li> <li>Support <code>--glob</code> patterns in <code>prek run</code> (<a href="https://redirect.github.com/j178/prek/pull/2381">#2381</a>)</li> <li>Support reusable aliases for hook priorities (<a href="https://redirect.github.com/j178/prek/pull/2331">#2331</a>)</li> <li>Implement <code>requirements-txt-fixer</code> as a builtin hook (<a href="https://redirect.github.com/j178/prek/pull/2390">#2390</a>)</li> <li>Improve user-facing warnings and errors (<a href="https://redirect.github.com/j178/prek/pull/2380">#2380</a>)</li> <li>Install Node hooks through git url (<a href="https://redirect.github.com/j178/prek/pull/2394">#2394</a>)</li> </ul> <h3>Performance</h3> <ul> <li>Reduce blocking-pool overhead in file hooks (<a href="https://redirect.github.com/j178/prek/pull/2384">#2384</a>)</li> <li>Speed up mixed-line-ending scans with memchr2 (<a href="https://redirect.github.com/j178/prek/pull/2391">#2391</a>)</li> </ul> <h3>Bug fixes</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/j178/prek/blob/master/CHANGELOG.md">@j178/prek's changelog</a>.</em></p> <blockquote> <h2>0.4.11</h2> <p>Released on 2026-07-25.</p> <h3>Highlights</h3> <ul> <li> <p>This release adds two new builtin hooks, <code>deny-pattern</code> and <code>require-pattern</code>, as native alternatives for <code>pygrep</code> use cases. <code>deny-pattern</code> fails when a configured pattern is found, while <code>require-pattern</code> ensures every selected file contains a match. By matching natively without spawning a Python subprocess, they run over 4x faster than <code>pygrep</code> in benchmarks. Note that they use <a href="https://docs.rs/regex/latest/regex/#syntax">Rust <code>regex</code> syntax</a>, which does not support look-around features such as negative lookbehind.</p> </li> <li> <p><code>prek run</code> now supports <code>--glob <PATTERN></code> to run hooks on tracked files matching a glob. It can be repeated or combined with <code>--files</code> and <code>--directory</code>.</p> </li> <li> <p>Hook priorities now support reusable aliases:</p> <pre lang="toml"><code>[priorities] checks = 10 <p>[[repos]] repo = "builtin" hooks = [ { id = "check-json", priority = "checks" }, { id = "check-yaml", priority = "checks" }, ] </code></pre></p> <p>This makes parallel scheduling easier to read and maintain.</p> </li> </ul> <h3>Enhancements</h3> <ul> <li>Add <code>deny-pattern</code> and <code>require-pattern</code> builtin hooks (<a href="https://redirect.github.com/j178/prek/pull/2359">#2359</a>)</li> <li>Support <code>--glob</code> patterns in <code>prek run</code> (<a href="https://redirect.github.com/j178/prek/pull/2381">#2381</a>)</li> <li>Support reusable aliases for hook priorities (<a href="https://redirect.github.com/j178/prek/pull/2331">#2331</a>)</li> <li>Implement <code>requirements-txt-fixer</code> as a builtin hook (<a href="https://redirect.github.com/j178/prek/pull/2390">#2390</a>)</li> <li>Improve user-facing warnings and errors (<a href="https://redirect.github.com/j178/prek/pull/2380">#2380</a>)</li> <li>Install Node hooks through git url (<a href="https://redirect.github.com/j178/prek/pull/2394">#2394</a>)</li> </ul> <h3>Performance</h3> <ul> <li>Reduce blocking-pool overhead in file hooks (<a href="https://redirect.github.com/j178/prek/pull/2384">#2384</a>)</li> <li>Speed up mixed-line-ending scans with memchr2 (<a href="https://redirect.github.com/j178/prek/pull/2391">#2391</a>)</li> </ul> <h3>Bug fixes</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/j178/prek/commit/92ba6c8c21e7acf5ce056b7c9b8dcba7325c3f5a"><code>92ba6c8</code></a> Bump version to 0.4.11 (<a href="https://redirect.github.com/j178/prek/issues/2402">#2402</a>)</li> <li><a href="https://github.com/j178/prek/commit/f575e428961414bc079060061bc570b71e553942"><code>f575e42</code></a> Bump quinn-proto from 0.11.14 to 0.11.16 (<a href="https://redirect.github.com/j178/prek/issues/2401">#2401</a>)</li> <li><a href="https://github.com/j178/prek/commit/c0ed56d92af1530e0acc98da2a8544bcf1dd01e7"><code>c0ed56d</code></a> Preserve system download policy when applying metadata (<a href="https://redirect.github.com/j178/prek/issues/2395">#2395</a>)</li> <li><a href="https://github.com/j178/prek/commit/3b8b5c53ea8ce674112e22f9f84addf3637ca9e0"><code>3b8b5c5</code></a> Install Node hooks through git url (<a href="https://redirect.github.com/j178/prek/issues/2394">#2394</a>)</li> <li><a href="https://github.com/j178/prek/commit/ff11cbb2d30478d9b2607dd1886cf90e33979365"><code>ff11cbb</code></a> Implement <code>requirements-txt-fixer</code> as a builtin hook (<a href="https://redirect.github.com/j178/prek/issues/2390">#2390</a>)</li> <li><a href="https://github.com/j178/prek/commit/c7dfc32c27f74ee04f9a4dc47b842fbb3e417631"><code>c7dfc32</code></a> Match identify tags across filename parts (<a href="https://redirect.github.com/j178/prek/issues/2399">#2399</a>)</li> <li><a href="https://github.com/j178/prek/commit/928dc5cf3b7c7486664d6a7e34ce8d89a603d7f1"><code>928dc5c</code></a> Speed up mixed-line-ending scans with memchr2 (<a href="https://redirect.github.com/j178/prek/issues/2391">#2391</a>)</li> <li><a href="https://github.com/j178/prek/commit/6c898499d8b7741f7e6b60cc42b195660e6d1afa"><code>6c89849</code></a> Honor filenames in builtin hook entry and args (<a href="https://redirect.github.com/j178/prek/issues/2389">#2389</a>)</li> <li><a href="https://github.com/j178/prek/commit/28bc3f013e0c97c39834f2f02a708355ed642462"><code>28bc3f0</code></a> Add description for no-commit-to-branch (<a href="https://redirect.github.com/j178/prek/issues/2388">#2388</a>)</li> <li><a href="https://github.com/j178/prek/commit/1d9adddb83df05770ea2a5562f141171be174d77"><code>1d9addd</code></a> Reduce blocking-pool overhead in file hooks (<a href="https://redirect.github.com/j178/prek/issues/2384">#2384</a>)</li> <li>Additional commits viewable in <a href="https://github.com/j178/prek/compare/v0.4.9...v0.4.11">compare view</a></li> </ul> </details> <br /> Updates `prettier` from 3.9.5 to 3.9.6 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/prettier/prettier/releases">prettier's releases</a>.</em></p> <blockquote> <h2>3.9.6</h2> <h2>What's Changed</h2> <ul> <li>Preserve quotes for methods named <code>new</code> (<a href="https://redirect.github.com/prettier/prettier/pull/19621">prettier/prettier#19621</a> by <a href="https://github.com/kovsu"><code>@kovsu</code></a>)</li> <li>Support <code>import defer</code> in <code>typescript</code> parser (<a href="https://redirect.github.com/prettier/prettier/pull/19624">prettier/prettier#19624</a>, <a href="https://redirect.github.com/prettier/prettier/pull/19675">prettier/prettier#19675</a> by <a href="https://github.com/fisker"><code>@fisker</code></a>)</li> <li>Added a new official plugin <a href="https://github.com/prettier/prettier/tree/3.9.6/packages/plugin-yuku"><code>@prettier/plugin-yuku</code> 🚀</a> (<a href="https://redirect.github.com/prettier/prettier/pull/19628">prettier/prettier#19628</a>, <a href="https://redirect.github.com/prettier/prettier/pull/19629">prettier/prettier#19629</a> by <a href="https://github.com/fisker"><code>@fisker</code></a>)</li> </ul> <p>🔗 <a href="https://github.com/prettier/prettier/blob/3.9.6/CHANGELOG.md#396">Changelog</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md">prettier's changelog</a>.</em></p> <blockquote> <h1>3.9.6</h1> <p><a href="https://github.com/prettier/prettier/compare/3.9.5...3.9.6">diff</a></p> <h4>TypeScript: Preserve quotes for methods named <code>new</code> (<a href="https://redirect.github.com/prettier/prettier/pull/19621">#19621</a> by <a href="https://github.com/kovsu"><code>@kovsu</code></a>)</h4> <!-- raw HTML omitted --> <pre lang="tsx"><code>// Input interface Container { "new"(id: string): number; } <p>// Prettier 3.9.5<br /> interface Container {<br /> new(id: string): number;<br /> }</p> <p>// Prettier 3.9.6<br /> interface Container {<br /> "new"(id: string): number;<br /> }<br /> </code></pre></p> <h4>TypeScript: Support <code>import defer</code> (<a href="https://redirect.github.com/prettier/prettier/pull/19624">#19624</a>, <a href="https://redirect.github.com/prettier/prettier/pull/19675">#19675</a> by <a href="https://github.com/fisker"><code>@fisker</code></a>)</h4> <!-- raw HTML omitted --> <pre lang="tsx"><code>// Input import defer * as foo from "foo"; <p>// Prettier 3.9.5<br /> import * as foo from "foo";</p> <p>// Prettier 3.9.6<br /> import defer * as foo from "foo";<br /> </code></pre></p> <h4>JavaScript: Added a new official plugin <code>@prettier/plugin-yuku</code> (<a href="https://redirect.github.com/prettier/prettier/pull/19628">#19628</a>, <a href="https://redirect.github.com/prettier/prettier/pull/19629">#19629</a> by <a href="https://github.com/fisker"><code>@fisker</code></a>)</h4> <p><code>@prettier/plugin-yuku</code> is powered by <a href="https://yuku.fyi/">Yuku</a> (A high-performance JavaScript/TypeScript compiler toolchain written in Zig).</p> <p>This plugin includes two new parsers: <code>yuku</code> (JavaScript syntax) and <code>yuku-ts</code> (TypeScript syntax).</p> <p><strong>To use this plugin:</strong></p> <ol> <li> <p>Install the plugin:</p> <pre lang="bash"><code>yarn add --dev prettier @prettier/plugin-yuku </code></pre> </li> </ol> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/prettier/prettier/commit/8f0c95057cc91d5836409466cd9d9af3bb901e84"><code>8f0c950</code></a> Release 3.9.6</li> <li><a href="https://github.com/prettier/prettier/commit/e9107647d0497d8ff1cacbb0f970d4543df77c1c"><code>e910764</code></a> Update changelog</li> <li><a href="https://github.com/prettier/prettier/commit/ec3f1c7bd74495992bc6954323a1a7fc8368808e"><code>ec3f1c7</code></a> Update typescript-eslint to v8.65.0 (<a href="https://redirect.github.com/prettier/prettier/issues/19675">#19675</a>)</li> <li><a href="https://github.com/prettier/prettier/commit/73d2efc2c6cba6f579585c88ef171132d90834ec"><code>73d2efc</code></a> Update Yuku parser to v0.7.0 (<a href="https://redirect.github.com/prettier/prettier/issues/19664">#19664</a>)</li> <li><a href="https://github.com/prettier/prettier/commit/dd5e24eabeab1f75ad573c79781e5fd408bcfad3"><code>dd5e24e</code></a> Preserve quotes for <code>TSMethodSignature</code> nodes named <code>new</code> (<a href="https://redirect.github.com/prettier/prettier/issues/19621">#19621</a>)</li> <li><a href="https://github.com/prettier/prettier/commit/c03ab4e71c23154d6b11537eee3c938f0d0f67d3"><code>c03ab4e</code></a> Update dependency eslint-plugin-unicorn to v72 (<a href="https://redirect.github.com/prettier/prettier/issues/19633">#19633</a>)</li> <li><a href="https://github.com/prettier/prettier/commit/b74dd53076c7208291a6b2e585c310844b41d35f"><code>b74dd53</code></a> Update Yuku parser to v0.6.5 (<a href="https://redirect.github.com/prettier/prettier/issues/19654">#19654</a>)</li> <li><a href="https://github.com/prettier/prettier/commit/f1b594ea1db1520c383d0e281d623551f671f824"><code>f1b594e</code></a> Update dependency eslint-plugin-simple-import-sort to v14 (<a href="https://redirect.github.com/prettier/prettier/issues/19655">#19655</a>)</li> <li><a href="https://github.com/prettier/prettier/commit/0d9dfb61530986373000dd107ea58ceebb79e233"><code>0d9dfb6</code></a> Update Yuku parser to v0.6.4 (<a href="https://redirect.github.com/prettier/prettier/issues/19650">#19650</a>)</li> <li><a href="https://github.com/prettier/prettier/commit/3bbb8159eb55575d4042653aa99f5f92a1416c19"><code>3bbb815</code></a> Remove <code>typescript-only</code> directory (<a href="https://redirect.github.com/prettier/prettier/issues/19636">#19636</a>)</li> <li>Additional commits viewable in <a href="https://github.com/prettier/prettier/compare/3.9.5...3.9.6">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details>
Records the evidence, root cause, and correction plan for the three findings in #148: automated-test-planning runs its full pipeline regardless of question scope, the test analysis agents can only argue a deferral from coverage location, and the readability editor does not check its own insertions against the voice blocklist. Carries 20 evidence items and 11 adversarial validation findings. Four of those findings corrected the plan before implementation.
…sked The skill classified nothing, so a narrow yes/no question ran the same pipeline as a whole-branch analysis: up to seven agent dispatches, a nine-section document, and two reviewers over it. Adds a size band with the same shape code-review and iterative-plan-review already use. Small defaults to focused mode: one agent, no conditional specialists, no reviewers, and a prose answer instead of the template. Medium and large are unchanged. Classification reads the user's request before Step 1's file list, because Step 1 falls back to the whole changed-files list when no scope is named, and that describes the branch rather than the question. Step 3's behavioral, prerequisite, and YAGNI sweeps run in both modes, so a focused answer is shorter without being less filtered. Registers the skill in docs/sizing.md alongside the other sizing-aware skills.
test-engineer could justify skipping a proposed test only by pointing at coverage elsewhere or at brittleness risk. Neither survives a reader who grants the path is reachable and asks what the new assertion would add. edge-case-explorer had the same gap, with "sufficient" left undefined. test-engineer gains a fifth evaluation axis: name a specific weakening of the code under test, predict which existing tests fail under it, and defer only when an existing test already catches everything the candidate would. Adds a Redundant Kill Set anti-pattern, a required Discriminating power field on every deferred item, and a rule against deferring on coverage location alone. edge-case-explorer now defines sufficient: a test is sufficient for an edge case only when it fails under a change that breaks that case. Neither agent has a test runner, so both state that the answer is a prediction from reading assertions and must name the test and assertion it came from. The canonical YAGNI rule is left untouched. It is written for committed items generally and is vendored byte-identically into five plugins, while this reasoning is test-specific.
The editor's only post-rewrite step confirmed facts survived. Its blocklist criterion governed the draft it audited, never the sentences it wrote, so the rewrite was the one place a fresh voice violation could originate and the one place with no voice check. Three planning skills tell the caller not to walk the self-check over the editor's output, and one skill runs no independent check at all, so a violation the editor introduces can reach the reader. Adds a step 4 that re-reads only the sentences the editor rewrote or inserted against the vocabulary blocklist and the em-dash positions, plus a line in the returned report. The pass corrects named violations only and leaves compliant wording alone, so a legal appositive em-dash survives it.
## Summary - Gives `automated-test-planning` a size band so a narrow question runs one agent and returns prose, instead of up to seven dispatches and a nine-section document. - Gives `test-engineer` and `edge-case-explorer` a discriminating-power test, so a deferral is argued from what an assertion would catch rather than from where coverage happens to sit. - Makes `readability-editor` check the sentences it writes against the voice blocklist it applies. - Leaves the canonical YAGNI rule and `manual-test-planning` untouched on purpose; both exclusions are argued in the investigation doc. ## Why Closes #148, a Han feedback report. It scored the run 5/5 on output accuracy and evidence discipline, and 2/5 on output length against decision count. The analysis quality was never in question; the cost and the durability of the reasoning were. Each fix copies a mechanism the suite already runs. The size band is `code-review`'s classifier plus `iterative-plan-review`'s lightweight mode, and the suite's own agent-economics guidance already says not to delegate work a skill can finish in a few tool calls, so that change is a conformance repair rather than a new idea. One part of the report is stale. The absolute em-dash ban it quotes was replaced six days after filing by a rule legalizing two positions, so two of its three flagged instances may no longer be violations. The structural gap behind it is unaffected and is what this PR fixes. Full evidence, root cause, and adversarial validation: `docs/plans/test-planning-feedback-issue-148/feedback-investigation.md` (20 evidence items, 11 validation findings). ## How to verify - [ ] `npm run lint` - [ ] Read `han-coding/skills/automated-test-planning/SKILL.md` Step 1.5 and confirm `arguments: size` is in the frontmatter. Without that key there is no `$size` to bind, which validation caught in the first draft. - [ ] Run `/automated-test-planning` with a narrow question on a branch with many changed files. It should announce a small band and answer in prose. Classification reads the request before the file list precisely so this case works. - [ ] Run `/automated-test-planning large` and confirm the full roster and template still run. - [ ] Dispatch `readability-editor` over a draft containing a legal appositive em-dash and confirm the new pass leaves it alone. ## Risk / rollback Low. Markdown instruction files only, no scripts and no behavior outside a Claude Code session. Medium and large runs of `automated-test-planning` are unchanged, so the blast radius is the small band and the two agents' deferral rationale. Revert with `git revert`; the four commits are independently revertable, one per correction plus the investigation doc. Three open risks are recorded in the investigation doc: the editor's new pass is unvalidated against false positives, `manual-test-planning` keeps an unconditional two-agent pipeline, and the discriminating-power answer is a prediction rather than an executed mutation test.
…anges Closes the gap issue #183 names between architectural-analysis, which produces findings and stops, and plan-a-feature, which specifies behavior a user observes and keeps symbol names out. Neither answers "these responsibilities are wrong, plan the fix". The skill takes whatever context is supplied, establishes the current state, settles a target state, and produces a change plan that is buildable directly by plan-work-items, tdd, or refactor. Three properties answer the issue's three complaints: - Code-level names are the subject rather than a leak. The plan names types, modules, and methods, because it plans a structure an engineer works in. - The surface delta is a target-state record, not a migration table. Every element removed, added, moved, renamed, or re-scoped carries a statement that would still be correct if every other entry were deleted, so a removal always says where the responsibility went. - Behavior preservation is a gate, not an assumption. Every delta entry is classified preserving, changing, or unknown, and the last two are escalated before they are committed. The run reads a prior findings report when one exists and dispatches its own structural, behavioral, and concurrency round when one does not. The output folder resolves through the config-rule precedence chain. Also adds reciprocal boundary clauses to architectural-analysis and plan-a-feature, registers the skill across the docs surfaces, and adds it to the four shared planning rules' consumer lists.
The branch added the plan-a-change skill and the han-ddd plugin but left several cross-plugin documentation surfaces pointing only one way. - Add /plan-a-change to the sizing-aware skill list, the per-skill table, and the per-skill Sizing links in docs/sizing.md. - Add /plan-a-change to the sizing, YAGNI, evidence, readability, and han-planning enumerations in docs/concepts.md, and add the missing /automated-test-planning to the sizing list there. - Add the missing Sizing section to the plan-a-change and ddd-analysis long-form docs, recording that ddd-analysis sizes analysis depth rather than team size and defaults to medium. - Add reverse boundary and Related documentation pointers to plan-a-change from architectural-analysis, plan-a-feature, plan-work-items, and refactor, including refactor's frontmatter. - Name /plan-a-change as a dispatcher in the fourteen agent long-form docs it dispatches. - Document the discriminating-power criterion in the test-engineer and edge-case-explorer Key concepts, matching their definitions. - Fix two wrong-depth docs/ links in the automated-test-planning doc. - Correct han-planning's plugin.json description, which claimed a han-core-only dependency while declaring han-communication too. Claude-Session: https://claude.ai/code/session_01UGo7ozwZcFKu2yVHtrGMMm
…anges (#207) ## Summary - Adds `/plan-a-change` to `han-planning`: a skill that plans an architecture-driven change to code that already exists, producing a plan `plan-work-items`, `tdd`, or `refactor` can build from directly. - Review the surface delta rule and the behavior-preservation gate closely. Those two carry the design. - No version bumps and no CHANGELOG entry. Adds reciprocal boundary clauses to `architectural-analysis` and `plan-a-feature` so disambiguation works in both directions. ## Why Issue #183 names a gap between two existing skills. `architectural-analysis` assesses an area and produces findings, then stops. `plan-a-feature` specifies behavior a user observes, and its content rule keeps symbol names out on purpose. Neither answers "these responsibilities are wrong, plan the fix", so the author of that issue hand-orchestrated `structural-analyst`, `behavioral-analyst`, and `software-architect` and synthesised the result themselves. The issue makes three asks. This PR answers all three in one skill: **Code-level names are the subject, not a leak.** The plan names types, modules, and methods, because it plans a structure an engineer works in rather than behavior a user observes. The altitude limit is different in kind: carry names, responsibilities, and contracts; never inline file bodies or prescribe line-level edits. **The surface delta is a target-state record, not a migration table.** Five verbs, and every entry states what is true after the change in its own right, written so it would still be correct if every other entry were deleted. A removal always says where the responsibility went, or that it went away and why. This is the fix for the issue's "one removal had no target-state statement anywhere". A migration table is written from the call site inward, so a responsibility moving between two internal collaborators produces no row at all and vanishes from a document built that way. **Behavior preservation is a gate, not an assumption.** Every delta entry is classified preserving, changing, or unknown. The last two are escalated before commit. An entry that cannot be classified is escalated rather than assumed safe. Closes #183. ## What it does Twelve steps: establish the reason, record the scope boundary, establish the current state, select the team, propose the target state, settle the delta, run the behavior gate, review, sweep for YAGNI and scope, write, readability, present. Two behaviors worth a reviewer's attention: - **The reason is recorded and not assumed.** Step 1 classifies why a change is being planned across six reason classes. A reported defect is one of them; a prior findings report is another. Neither is presumed to exist. A run with no recorded reason stops, because there is nothing for the YAGNI evidence test to test against. - **Discovery is conditional.** With a prior report, Step 2 reads it. Without one, Step 2 dispatches structural and behavioral analysts (plus concurrency on signal). That is the orchestration the issue describes doing by hand. The output folder resolves through the `config-rule` precedence chain, so `output-directory` from either `.han/config.md` governs it. ## How to verify - [ ] `npm run lint` and `npm test` (95 tests, all passing on this branch). - [ ] Read `han-planning/skills/plan-a-change/references/surface-delta-rule.md`, the file the issue's central complaint maps to. - [ ] Check the boundary clauses in three descriptions read correctly against each other: `plan-a-change`, `plan-a-feature`, and `architectural-analysis`. All three stay under the 1024-character target (765, 783, 843). - [ ] Confirm the docs coverage rule holds: long-form doc at `han-planning/docs/skills/plan-a-change.md`, scent line in the plugin README, entry in `docs/skills/README.md`, chain entry in `docs/workflows.md`. ## Risk / rollback Low. The change is additive: one new skill plus registration across the docs surfaces. The only edits to existing behavior are two description clauses and four consumer-list lines in the shared planning rules, none of which change what an existing skill does. `plan-a-change` uses the boundary record from `planning-boundary-rule` but not its visual-material convention, which is stated in the rule's consumer note. Revert with `git revert`.
Issue #193 reported six problems from a real plan-implementation run. Four are the same shape: a mechanic is written in one file and the file that must honor it never reads it back. One premise in the work item is wrong and it changed the fix. The issue says the orchestrating thread has execution tools; all three planning skills grant only find, git, mkdir, cp, and one config script. The measurement step works inside that grant and records what the grant cannot reach. Discovery ran structural and behavioral analysis over the area, then a review round of three specialists over the draft. That round found a critical defect in the plan itself: narrowing the editor's ledger while leaving four skills testing for the removed sentence would have sent every clean run down the degraded branch. Nine findings changed the plan.
Four of the six were the same shape: a mechanic written in one file that the file which must honor it never read back. Each now has a named reader, and the one whose failure is mechanical has a script. Synthesis writes the plan first, so both companion files write backward into a file that exists and a mid-run death leaves the primary artifact. A new check-plan-cross-references.sh resolves the links in both directions, and a shared synthesis-failure-rule.md stops either file-writing caller from running the readability pass against a plan that was never written. Specialists now cite a decision's field rather than the whole entry, and two findings citing one identifier with different figures no longer merge, since a genuine disagreement usually cites different evidence. The readability editor reports what it inserted with the source span it drew from, and its ledger stops asserting that everything survived. All four consuming skills had their branches rewritten, not only extended: each tested for the sentence the narrowed ledger removes, so leaving them would have sent every clean run down the degraded path. Discovery measures the figures its tools reach and records what they cannot, rather than passing a spec assertion through as fact. The premise that the orchestrator can run arbitrary commands was wrong; it holds find, git, glob and grep, and the permission grant is unchanged. Also repairs four in-area defects the discovery round found: two instruction sentences split across a file boundary, ten link labels a directory too shallow, a stale round cap, and a section missing from the write order that required it. The rule that would have prevented the split sentences now sits beside the ceiling that caused them. Run against the fourteen existing plan folders, the new check found the reported defect class in six of them.
Audit the entities this branch touched and fix five discrepancies between documentation and its source of truth. - CLAUDE.md: record synthesis-failure-rule.md, the new han-planning-owned reference file two skills cite, in both the repository layout and the shared planning conventions doc map. - readability-editor long-form doc: document the Insertions ledger the agent now returns, and correct the fact-preservation bullet, which described a blanket survival claim the agent explicitly no longer makes. - docs/sizing.md: add ddd-analysis, which binds $size and reads default-swarm-size but appeared in none of the three sizing-aware lists. Qualify the "default is small" claim, which ddd-analysis contradicts by defaulting to medium. - architectural-analysis: add the missing reverse boundary to ddd-analysis, in both the frontmatter description and the long-form doc, plus the pairing link. ddd-analysis names architectural-analysis three times as its alternative and nothing pointed back. Claude-Session: https://claude.ai/code/session_01HtgjM85z795Cd8oNC8J7do
) Closes #193. Feedback issue #193 reported six problems from a real `plan-implementation` run. Four were the same shape: a mechanic written in one file that the file which must honor it never read back. Each now has a named reader, and the one whose failure is mechanical has a script. The plan behind this change is in `docs/plans/plan-implementation-feedback-issue-193/`, with the discovery findings and the decision log beside it. ## One premise in the issue turned out to be wrong The issue says the orchestrating thread "does have execution tools." It does not. All three planning skills grant `find`, `git`, `mkdir`, `cp`, and one config script, with no general shell. So the measurement step works inside that grant and records what the grant cannot reach, rather than passing a specification's assertion through as fact. The permission grant is unchanged, and widening it is deferred with a trigger. ## What changed **The synthesis boundary is guarded on both sides.** The plan is written first, so both companion files write backward into a file that exists and a mid-run termination leaves the primary artifact rather than losing it. A new `check-plan-cross-references.sh` resolves the links in both directions, and a shared `synthesis-failure-rule.md` stops either file-writing caller from running the readability pass against a plan that was never written. **A citation names the field, not the entry.** A decision entry carries the committed option and the declined ones as sibling fields, and a bare identifier does not say which one a figure came from. Alongside it, two findings citing the same identifier with different figures no longer merge, because a genuine disagreement usually cites different evidence. **The readability editor reports what it wrote.** It names each sentence it inserted with the source span it drew from, and its ledger stops asserting that everything survived — an unfalsifiable claim that had already reported a figure the source never held. **All four consuming skills had their branches rewritten, not only extended.** Each tested for the exact sentence the narrowed ledger removes, so adding a fourth branch and leaving the first three would have sent every clean run down the path meaning "no usable report came back." The review round caught this; it is the defect the change exists to fix, reproduced inside the fix. **The deferral list got two readers**, one during the run and one at build time, where the reported run's deferred flag actually got built. ## Four in-area defects the discovery round found Two instruction sentences split across a file boundary, ten link labels a directory too shallow, a stale round cap contradicting the two files that own it, and a section required by an invariant but missing from the write order beside it. Both split sentences came from commits that moved body text under the 500-line ceiling, so the rule that would have prevented them now sits beside that ceiling. ## Verification - 23 new Bats tests for the script; 118 tests pass repo-wide; lint clean. - Run against the fourteen existing plan folders under `docs/plans/`, the new check found the reported defect class in six of them. Two were spot-verified as real: one plan cites `[D10]` against a log that stops at `D-8`, and another references a "Phase 2" section that does not exist. - All four `SKILL.md` files remain under the 500-line ceiling. ## Open, and deliberately not in this change Five dispatch points still consume a returned report with no failure branch. The Step 4 specialist fan-out is the one worth attention: a dead agent's absence is indistinguishable from a clean report with no findings, and a round that silently lost one of three specialists produces a plan that reads complete and is missing a domain. Units 7 and 8 change a report shape across a plugin boundary and must ship together, so the version bump is a release decision rather than a code one.
…ew and research
…research dispatch
…ew and research (#209) Feedback issue #194 reported four runs where a Han skill confirmed a reference existed without confirming it pointed at the right thing, or produced a complete-looking report without saying what it had not done. Three were in `code-review` and one in `research`. This change makes both skills say what they did not do, and check that a reference supports the thing it is attached to. What changed: - `code-review` gains a named **manual-only mode**, entered when the dispatch mechanism fails (not when an agent returns nothing). The manual review sweeps mapped checklist categories in the absent agents' place, the report gains a `## Review Coverage` section that renders only when coverage was absent, and the closing message names the cause and the count. The independent validation pass skips in that mode because it dispatches an agent. - A `Packaging (when applicable)` checklist category fires on diffs that change what gets packaged. It raises a Warning saying the review did not open the built artifact and what to check by hand. Its summary row opens with `Not checked —`. - A finding whose location came from a region read of a file over 1000 lines names its enclosing unit and the lines read to confirm it. Guarded twice: a fifth challenge axis in the validator brief, and a structural verification item that runs in every mode. - `research`'s traceability invariant is now two-part (resolvability and support), defined once in Operating Principles and cited elsewhere. The merge step records an old-to-new mapping across the renumbering, rewrites every citation surface through it including the evidence-status field, and labels a claim whose only source was dropped as no-evidence rather than single-source. Both inline column enumerations now name the one-line summary column. - `post-code-review-to-pr` carries Review Coverage across to the pull request and exempts it from the clarity pass's length-matching, so the disclosure survives to the widest audience. - Long-form docs for `code-review`, `research`, and `post-code-review-to-pr` updated to match. The plan and its artifacts are under `docs/plans/code-review-research-feedback-issue-194/`. Two departures from the issue are recorded there as the operator's decision: the packaging finding discloses the gap rather than inspecting the artifact, and the location rule fires on the region-read path rather than on disassembler output the skill never reads. Closes #194.
Three Han packages the README tells Codex users to install cannot be installed. han-documentation and han-research are absent from .agents/plugins/marketplace.json despite having valid Codex manifests; han-linear is absent from the catalog and has never had a manifest at all. The root cause is structural rather than a one-off slip. Four hand-maintained lists enumerate the Codex-installable packages (the directory tree, the manifests, the catalog, the README) and nothing checks that they agree. The drift entered on 2c09799, which scaffolded both plugins and updated only the Claude marketplace; the comparison case is 556b49e, which updated both marketplace files plus CLAUDE.md, which is why han-ddd installs. The plan names the directory tree as the authority and adds one Bats check enforcing it, in three units that each leave the repo green: register the two plugins that already have manifests; give han-linear a manifest, a catalog entry, and a corrected CLAUDE.md line; then add the check. Planned with plan-a-change. Discovery ran structural and behavioral analysts; the review round ran test-engineer, devops-engineer, and junior-developer, which found nine defects in the draft, including a verification step using git stash that cannot reach committed history and a worked JSON example that would have introduced permanent formatting drift.
han-plugin-builder's guidance is where every plugin-asset decision in this repo is supposed to route, and it has no document describing the Codex packaging surface. Its only Codex mentions are plugin-naming.md's dot rule and that file's rename checklist, which acknowledges .codex-plugin/plugin.json and a Codex marketplace exist as things to keep in step. Nothing states a plugin needs both to ship. Recorded as a deferral with a reopening trigger rather than pulled into this change: the consistency check answers the question mechanically, and a failing check is a stronger statement than a document nobody has to read.
Both plugins have carried a valid .codex-plugin/plugin.json since they were scaffolded in 2c09799, but that commit updated only the Claude marketplace, so neither name was ever resolvable: $ codex plugin add han-documentation@han Error: plugin `han-documentation` was not found in marketplace `han` A Codex install reads the catalog first and the per-plugin manifest second, so the lookup failed before reaching manifests that were correct all along. Adding the two entries is the whole fix for these two. Both entries take the four-key form every existing entry uses, and sit after han-core and before han-planning: the Codex catalog's order is the Claude marketplace's order with its omissions removed, so restoring the omitted names to their Claude positions is the placement consistent with the file. Unit 1 of 3 from docs/plans/codex-marketplace-catalog-consistency. Closes two of the three symptoms in #198.
han-linear failed one layer deeper than han-documentation and
han-research: it was absent from the catalog and had never carried a
.codex-plugin/plugin.json on any commit, so a catalog entry alone would
have resolved to a directory with no manifest to read. Both land here.
The manifest copies the nine fields that are byte-identical across all
twelve siblings (author, homepage, repository, license, skills, and the
four constant interface keys) and supplies the eight package-specific
ones from han-linear's README and skill description.
It ships at 1.0.0 rather than mirroring the Claude manifest's 1.1.1. The
release skill's own rule is that a brand-new plugin is not bumped by the
release that introduces it, and a Codex manifest that has never existed
is that case. The two version fields are separate lineages: the release
skill bumps {source}/.claude-plugin/plugin.json and the Claude
marketplace, and never opens a .codex-plugin file. Eleven of twelve
pairs already differ, so seeding 1.1.1 would manufacture a parity the
next release destroys.
CLAUDE.md line 83 recorded the missing manifest as intentional. This
change makes that false, and it is the file every agent reads before
scaffolding, so it is corrected here rather than left to drift. Same
shape as 556b49e, which added han-ddd and updated the Codex catalog, the
Claude marketplace, and the map together.
Unit 2 of 3 from docs/plans/codex-marketplace-catalog-consistency.
Closes the third symptom in #198.
Nothing in the test, lint, or CI chain read a manifest or a marketplace file, so the four data fixes above would not have stopped the next plugin repeating 2c09799. This adds the check that would have caught #198 when han-linear and han-ddd landed. The directory tree is the authority: every han-* directory needs a Codex manifest and a catalog entry. The han-* glob excludes the han/ meta-plugin structurally rather than by an exception list. Three assertions, bash and grep only: 1. the enumeration is non-empty, so the other two cannot pass over an empty set while looking identical to success 2. every package has a .codex-plugin/plugin.json 3. every package has a catalog entry whose name and path sit in the same entry, matched in a three-line window rather than tested for presence anywhere in the file Deliberately not asserted: version parity (false for eleven of twelve pairs) and description parity (false for all twelve). Both would fail the build the day they landed, and neither is a latent goal, since the release skill touches only the Claude side. Verified against a worktree on the commit before the data fixes: the check fails there and names han-documentation, han-research, and han-linear, with han-linear failing both assertions. A consistency check nobody has seen fail is a check nobody knows works. sanity.bats stated that test/ keeps only harness-level checks, which this file breaks. Widened to name the second category, keeping the clause that still decides most cases: a test covering one script sits beside that script. Unit 3 of 3 from docs/plans/codex-marketplace-catalog-consistency.
#210) Closes #198. Plans and implements the fix in five commits: two documentation commits carrying the change plan, then the three change units. ## What #198 reported Three Han packages the README tells Codex users to install could not be installed: ``` $ codex plugin add han-documentation@han Error: plugin `han-documentation` was not found in marketplace `han` ``` `han-research` failed identically. `han-linear` failed one layer deeper: absent from the catalog *and* never carrying a Codex manifest on any commit. ## Why it happened Four hand-maintained lists enumerate the Codex-installable packages — the `han-*` directory tree, the per-plugin manifests, `.agents/plugins/marketplace.json`, and the README — and nothing checked that they agreed. The drift is visible in the history. `2c09799` scaffolded `han-documentation` and `han-research` and updated only the Claude marketplace; its own message says "registered in the marketplace", singular. The comparison case is `556b49e`, which added `han-ddd` and updated both marketplace files plus `CLAUDE.md`, which is why `han-ddd` installs today. ## The three units | Unit | Commit | What it does | | --- | --- | --- | | 1 | `b83712f` | Two catalog entries for the plugins that already had manifests | | 2 | `1928de6` | `han-linear`'s manifest, its catalog entry, and the `CLAUDE.md` line that recorded its absence as intentional | | 3 | `f15663f` | The consistency check, plus the `sanity.bats` header it makes stale | Each unit leaves the repository green on its own. ## The check The directory tree is the authority: every `han-*` directory needs both files. The `han-*` glob excludes the `han` meta-plugin structurally rather than by an exception list. Three assertions, bash and grep only: 1. the enumeration is non-empty, so the other two cannot pass over an empty set while looking identical to success 2. every package has a `.codex-plugin/plugin.json` 3. every package has a catalog entry whose `name` and `path` sit in the **same** entry, matched in a three-line window rather than tested for presence anywhere in the file **Deliberately not asserted:** version parity (false for eleven of twelve pairs) and description parity (false for all twelve). Both would fail the build the day they landed, and neither is a latent goal — the release skill touches only the Claude side. ### Verified to actually fail Run against a worktree on the commit before Unit 1, with only the test file copied in: ``` not ok 2 every han-* package carries a Codex manifest # codex manifest missing: han-linear/.codex-plugin/plugin.json (copy han-ddd/... and edit the package-specific fields) not ok 3 every han-* package has a catalog entry naming it and pointing at it # catalog entry missing: add "name": "han-documentation" with "path": "./han-documentation" to .agents/plugins/marketplace.json # catalog entry missing: add "name": "han-linear" with "path": "./han-linear" to .agents/plugins/marketplace.json # catalog entry missing: add "name": "han-research" with "path": "./han-research" to .agents/plugins/marketplace.json ``` Exactly the three packages #198 names. On `HEAD`: 121 tests pass, 0 fail, every lint hook passes. ## Worth a reviewer's attention - **`han-linear`'s Codex manifest ships at `1.0.0`**, not the Claude manifest's `1.1.1`. The release skill's own rule is that a brand-new plugin is not bumped by the release that introduces it. The two version fields are separate lineages; seeding `1.1.1` would manufacture a parity the next release destroys. **No version is bumped by this PR.** - **The next release will classify `han-linear` as changed** on the strength of the new manifest alone, and the level buckets have no entry for "gained Codex installability." Worth deciding deliberately at release time. - **`CLAUDE.md` is edited**, and it was not in the area originally scoped. Brought in because this change makes line 83 false, on the `556b49e` precedent. Line 73 was cut for scope and is reinstatable. - **Nothing was verified against a running Codex.** No CLI was available. Every install-time claim traces to the repo's files and the error text in #198; the fix copies the shape of the ten entries that demonstrably work. - **`docs/choosing-a-han-plugin.md` still gives Codex readers Claude-only install commands.** Left alone as outside scope; recorded as a follow-up. ## Planning artifacts `docs/plans/codex-marketplace-catalog-consistency/` carries the change plan, 11 decisions, 18 current-state findings, and the scope boundary. Nine items are deferred with reopening triggers, including a reverse check on the catalog and a Codex packaging document for the `han-plugin-builder` guidance, which has none. Produced with `/han-planning:plan-a-change`. The review round (`test-engineer`, `devops-engineer`, `junior-developer`) found nine defects in the draft plan, including a verification step using `git stash` that cannot reach committed history, and a worked JSON example whose formatting would have diverged permanently from every sibling entry.
An outside reader reported that Han's docs contradict each other and the skill definitions (#200). This plans the fix and records the evidence. Verification widened the first of the three reported items. The quickstart is missing four size-accepting skills, not the one reported: it lists 9, the concepts page 12, and the skill frontmatter declares 14, of which 13 classify their own work. The cause is CONTRIBUTING.md step 6, which names the sizing and concepts catalogs and not the quickstart, so four skill additions between 2026-08-10 and 2026-09-09 updated the named pages and left the quickstart behind. The plan carries six delta entries in three units, each pinning the exact replacement text: the two list syncs plus the checklist step, the two han-reporting corrections, and the banner alt attribute. One entry is behavior-changing, and the operator approved widening scope to cover it. An automated catalog check is deferred under YAGNI with its reopening trigger named. Nothing was cut for scope.
…aims Closes #200. The quickstart listed 9 sizing-aware skills and the concepts page 12, where 13 skills classify their own work. Both now match docs/sizing.md, which was already correct. CONTRIBUTING.md step 6 now names the quickstart alongside the sizing and concepts catalogs, which is the reason it fell four months behind: four skill additions since 2026-05-29 updated the two pages the checklist named and left the third untouched. Two pages stated the han-reporting dependency exception correctly and then contradicted it a few lines later. On docs/choosing-a-han-plugin.md the correct half sat in a trailing parenthetical while the bold sentence under "The one thing that surprises people" erased it, so the exception now sits in the bold sentence a skimming reader stops on. docs/concepts.md listed reporting-only among installs that do not exist; it is the one layer plugin you can install without han-core, so the page now says what it gives you. The README banner gains alt text. It is the only image embed in the repo's prose, and it carries the project name and tagline that a screen-reader user previously got nothing of. Plan, decisions, and evidence in docs/plans/gh-200-docs-consistency/.
Branch-scoped documentation audit over the 14 skills and 22 agents this branch touched. - research: add Write and Edit to allowed-tools. Step 8 writes the report and applies the editor's rewrite, but neither tool was declared. - docs/readability.md: add /design-an-api, /plan-a-change, and /ddd-analysis to the per-skill table. All three dispatch readability-editor, and the table declares itself authoritative. - plan-a-change: document the Step 9.5 readability rewrite in Cost and latency and in Related documentation. - ddd-analysis: add the readability-editor bullet to Related documentation, matching the Step 10 dispatch its Cost section already described. - readability-editor: add /ddd-analysis to the dispatcher list. - risk-analyst: add /plan-a-change to the TL;DR dispatcher list and the Dispatch-when section; it was named in Related documentation only.
…aims (#211) Closes #200. An outside reader worked through the docs end to end and found pages that disagree with each other and with the skill definitions. All three of their findings were verified against the skill frontmatter and the plugin manifests before anything was changed, and the first one turned out larger than reported. ## The sizing-aware lists were three different lengths `docs/quickstart.md` listed 9 skills and `docs/concepts.md` listed 12. Thirteen skills classify their own work, which is what `docs/sizing.md` already said. Both pages now match it. The reporter found one missing skill. Four were missing, and the cause is one line: `CONTRIBUTING.md` step 6 told contributors to update the sizing and concepts catalogs and never mentioned the quickstart. Four skill additions between 2026-08-10 and 2026-09-09 updated the two named pages and left the third behind, so the quickstart's list had been stale since 2026-05-29. Step 6 now names all three. `plan-a-feature-to-confluence` declares `arguments: size` and stays out of all three catalogs on purpose. It forwards the argument to `plan-a-feature` rather than classifying anything, which step 6's own opening condition already excludes. ## Two pages denied the `han-reporting` exception they document `han-reporting` is the only layer plugin that does not declare `han-core`, and both pages said so correctly before contradicting themselves. On `docs/choosing-a-han-plugin.md` the correct half sat in a trailing parenthetical while the bold sentence two lines below it, under the heading "The one thing that surprises people", generalized over it. A skimming reader stops on the bold sentence, so the exception now lives there. `docs/concepts.md` listed reporting-only among installs that do not exist. It is exactly the install that does exist, so the page now says what it gives you: `/stakeholder-summary` and `/html-summary` plus `han-communication`, without the `han-core` agent roster. ## The banner has alt text `README.md` carries the only image embed in the repo's prose and had no `alt` attribute, so the project name and tagline reached a screen-reader user as the filename or as nothing. ## What is in this PR Two commits. The first adds the change plan, the decisions behind it, and the evidence, under `docs/plans/gh-200-docs-consistency/`. The second applies the six edits. Each edit was pinned to exact replacement text before being made, and each of the plan's three verification checks passes: all three pages now carry the same 13 names as `docs/sizing.md`, no page outside `docs/plans/` claims that every layer install brings the shared agents, and the banner announces the project rather than its filename. `npm run lint` and `npm test` pass. ## Deliberately not in this PR An automated check that a skill declaring `arguments: size` reaches every catalog. It would have caught this drift on the day it started, where the checklist edit only reminds a person. It is deferred with a reopening trigger recorded in the plan: a second drift incident, or a fourth page carrying the list. Two things the review surfaced and this PR leaves alone, both noted in the plan's Open Items. The plugin dependency graph is hand-copied across four files with nothing enforcing agreement, which is the same failure mode on a different fact. And `han-reporting/README.md` states no dependencies at all.
Issue #201 reports a pairing session that tucked the piece-3 pre-build ask under piece 2's stop, read "commit and next" as declining it, built piece 3 without the person's read, and wrote "ask declined" into the feedback record as the person's decision. The skill text permits it: the rule says the ask comes before the build and pairing Step 5 says "ask first", and neither forbids folding the ask into the previous stop. `docs/plans/gh-201-pre-build-ask-timing/` holds the change plan, its decision log, the current-state findings from a structural and behavioral discovery round, and the scope boundary. The plan re-scopes three sections of `collaborative-stop-rule.md` (and its two byte-identical copies), pairing Steps 5 and 6, and the pairing long-form doc, and pins every sentence the three files must agree on. Two behavior changes were put to the operator and accepted: the ask is a turn of its own that a stop never carries, and the record holds the person's words with the run's reading labeled as the run's. A review round with the junior developer, UX designer, and risk analyst extended the first change to a marked first piece, gave the ask's reply a recorded path, and named the run as the cause in the after-build message. Eight items sit under Deferred (YAGNI) with their reopening triggers.
Closes #201. The collaborative stop rule said the pre-build ask comes before the build and pairing Step 5 said "ask first", and neither forbade folding the ask into the tail of the previous piece's stop. A run did exactly that, read "commit and next" as declining the ask it had tucked under piece 2's stop, built piece 3 without the person's read, and wrote "ask declined" into the feedback record as the person's decision. `collaborative-stop-rule.md` now says a stop covers what just closed and asks nothing about a later piece; the ask is a turn of its own, opening the marked piece's turn after the person has replied to the previous stop or to the plan; a reply to a stop or the plan answers that alone and never counts as declining an ask the person has not answered; a question about the ask holds it open; a bundled ask was never posed and is presented on its own before building, and one found after the build is named with the run as the cause rather than re-asked. "Never require an answer before building" is gone, because the build now waits for a reply to the ask, though a decline is a full reply. The record's entry form is pinned: the person's words, the stop or ask they answered, and any reading the run adds labeled as the run's, with one worked example. The two vendored copies in `han-coding` and `han-planning` are byte-identical to the canonical file. Pairing Step 5 item 1 carries the same rule in the loop's terms and names what happens to the reply: recorded against the ask, then the build, with no pass through Step 6. Item 3 says naming the next concern is a report, never a question. Step 6 writes the response in the person's words against the stop or ask it answers. The long-form doc promises each of these to the person in the same terms and adds one turn per marked piece to its cost line. The change plan, decision log, and findings behind every sentence are under `docs/plans/gh-201-pre-build-ask-timing/`.
Closes #201. A pairing session tucked the piece-3 pre-build ask under piece 2's stop, read "commit and next" as declining it, built piece 3 without the person's read, and wrote "ask declined" into the feedback record as the person's decision. The skill text allowed it: the rule said the ask comes before the build and pairing Step 5 said "ask first", and nothing forbade folding the ask into the previous stop. ## The ask is a turn of its own, and a stop never carries it `collaborative-stop-rule.md` now says a stop covers what just closed and asks nothing about a later piece. The ask opens the marked piece's turn after the person has replied to the previous stop, or to the plan when the marked piece is the first, and it is the whole turn. A reply to a stop or the plan answers that alone and never counts as declining an ask the person has not answered. A question about the ask holds it open. The line "never require an answer before building" is gone. Read literally it licensed the build the issue reports. The build now waits for a reply to the ask, and a decline is a full reply: "I don't know" still advances the piece. ## A bundled ask is an unanswered ask When an earlier turn put the ask under a stop or the plan and the reply spoke only to that, the ask was never posed on its own, so the run presents it now, on its own, before building. If the piece was already built when that comes to light, the run says it put the ask under an earlier turn so it went unanswered, and continues from the stop in hand. It does not ask after the fact, because an ask after the build collects the cost and none of the benefit. ## The record holds the person's words The rule's "Recording what the person says" section pins the entry's form: the person's words, the stop or ask they answered, and any reading the run adds labeled as the run's, never written as what the person decided. One worked example pins the shape. An ask with no entry is an ask with no answer. This goes one step past the issue's suggested fix; the issue names the wrong record entry as a second effect, and the long-form doc already promised the record holds "which piece prompted it" with nothing delivering it. ## What is in this PR Two commits. The first adds the change plan, its decision log, the current-state findings from a structural and behavioral discovery round, and the scope boundary under `docs/plans/gh-201-pre-build-ask-timing/`. The second applies the plan: five paragraphs in the canonical rule with its two vendored copies kept byte-identical, three edits to `pairing/SKILL.md` (Step 5 item 1 rewritten with what happens to the ask's reply, one sentence on item 3, Step 6's opening sentence), and five edits to `han-core/docs/skills/pairing.md` so the doc promises exactly what the rule delivers, including one more turn per marked piece in its cost line. Every sentence the three files must agree on was pinned in the plan before it was written, and copied rather than paraphrased. `md5 -q` prints one hash for all three rule copies. `npm run lint` and `npm test` pass. The five backing skills are untouched: the one new clause they can act on sits in "What a stop presents", which they already read, and none of them poses an ask. ## Deliberately not in this PR Eight items sit under Deferred (YAGNI) in the plan with reopening triggers, among them a three-state ask marker in the record, ask behavior inside a "show me the next three" batch, a piece anchor on the ask turn, and an acknowledgment on a re-presented ask. None is implicated by the one incident on record. No ADR links the rule to the pairing plan's decision D7, which named the sentence this PR removes; the plan's decision D-3 records why it went. No version bump and no changelog edit; both belong to `/han-release`.
On a Claude Code install backed by Amazon Bedrock the WebSearch tool does not exist. The research-analyst agent declared it, the harness dropped the unmatched entry silently, and the agent ran on WebFetch alone while its report read as though a full survey had happened (#212). The analyst now notices when WebSearch is not offered to it or a call is refused, gathers by fetch alone, and opens its return with one fixed "Web search:" line. The research skill copies that line into the top of every report under Confidence, shields it from the readability rewrite, passes it to the validator, and on any run where the value is not "used" charters a completeness check and names the gap under Remaining Risks. The agent's tools line, the skill's allowed-tools line, and the source registry are unchanged. The long-form docs say what happens without search and that the shipped agent cannot be given another search tool. Closes #212
… report returns Claude-Session: https://claude.ai/code/session_0153G6yzMfYhMa4yWHnNcLJ9
#214) ## Summary - The research-analyst agent now notices when `WebSearch` is not offered to it (or a call is refused), gathers by fetch alone, and opens its return with one fixed `**Web search:**` line: `used`, or `not available. …`. - The `research` skill copies that line into every report's Summary directly under Confidence, protects it from the readability rewrite, passes it to the validator, and on any run where the value is not `used` adds a completeness check to the validator's charter and a fixed Remaining Risks entry. A missing line renders as `not reported. …` and gets the same treatment. - Nothing else moves: the agent's `tools:` line, the skill's `allowed-tools:` line, the `A#` registry shape, and `han-core/agents/adversarial-validator.md` are unchanged. The long-form docs say what happens without search and that the shipped agent cannot be given a different search tool (a plugin agent cannot carry its own MCP server, and its `tools:` list cannot name a server the plugin does not know). - The plan behind this, with the decision log and current-state findings, is in `docs/plans/gh-212-research-websearch-fallback/`. Three things were deferred with reopening triggers: the GitHub/npm/PyPI fetch fallback chain, named MCP search patterns in `tools:`, and a config setting naming a search tool. ## Why On a Claude Code install backed by Amazon Bedrock (confirmed by the official docs; the reporter says Vertex too) the `WebSearch` tool does not exist. A subagent's `tools:` list only narrows, so the unmatched entry was dropped silently and the analyst ran on `WebFetch` alone while its report read like a full survey. Nothing captured the fact at its origin and no downstream rule keyed on it. Fixes #212. ## How to verify - [ ] `npm run lint` passes. - [ ] With this branch as the local marketplace source, dispatch `han-research:research-analyst` directly on an Anthropic-backed install: the first line of its return is `**Web search:** used`. - [ ] Run `/research small` on the same install: the report's Summary shows `- **Web search:** used` directly under Confidence, byte-identical after the readability pass, and the closing chat message says nothing about web search. - [ ] Read Step 6 of `han-research/skills/research/SKILL.md` against an imagined analyst return with no line: it yields the `not reported` literal, and Step 7 then includes the completeness sentence. - [ ] Open item, non-blocking: on a Bedrock install, `/research small` should render the `not available` line. Nobody on this project has one; the issue's reporter does, and asking them to paste a Summary is the concrete check. ## Risk / rollback Low risk; markdown-only, revert via `git revert`. The one thing to watch for is a Bedrock report carrying `Web search: used`, which would mean the analyst did not take the no-search branch there (the protocol names both triggers, absent-from-list and refused-on-call, so it should hold under either observation).
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.
Consolidating changes for v5.5.0 release
Changes include: