From 28c91f2565309269beeb8875d9dd423ca4e5e447 Mon Sep 17 00:00:00 2001 From: River Bailey Date: Thu, 15 Oct 2026 13:28:17 -0600 Subject: [PATCH 1/9] docs(research): draft cross-plugin config discovery report --- .../research/cross-plugin-config-discovery.md | 230 ++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 docs/research/cross-plugin-config-discovery.md diff --git a/docs/research/cross-plugin-config-discovery.md b/docs/research/cross-plugin-config-discovery.md new file mode 100644 index 00000000..d71c4dc6 --- /dev/null +++ b/docs/research/cross-plugin-config-discovery.md @@ -0,0 +1,230 @@ +# Research: Discovering Configuration Contributed by Other Installed Han Plugins + +The question: how can each installed Han plugin ship configuration that other Han plugins discover and load +automatically, so that, for example, `test-engineer` can move from `han-core` into `han-coding`, and `han-planning` +skills use it when `han-coding` is installed and run without it when it is not? + +Evidence mode: strict. + +## Summary + +Han can do this, but Claude Code gives it no built-in way to. Claude Code dependencies are all-or-nothing. A plugin that +lists another as a dependency gets it installed automatically and stops loading without it, and there is no "optional" +or "contributes to" setting. So the discovery has to be built from parts Claude Code already has. + +The shape of the contract matters more than the transport. Every established plugin system studied puts the contract +with the consumer: the planning plugin names a slot, such as "test-planning specialist", and the coding plugin says "my +`test-engineer` fills that slot." None has the provider list the consumer's individual features. Han should follow that +pattern, so renaming a planning skill never breaks the coding plugin. When nothing fills a slot, the planning skill +simply runs without it, the same way Han already skips an extra agent that is not installed. + +For the transport, the best-supported route is a small startup hook in each providing plugin. The hook prints that +plugin's contribution file into the session when the session starts, and only enabled plugins run hooks. As a safety +net, a planning skill checks that the agent actually appears in the session's list of available agents before +dispatching it. This works today with no new machinery, and it keeps the skill safe if the hook does not run. Two other +routes exist: asking the Claude Code command line which plugins are installed, and reading Claude Code's plugin folders +directly. Both are less stable. + +How solid it is: the contract shape is well-corroborated; the startup-hook transport rests on one documentation page +and needs a quick live check before you commit to it. + +- **Confidence:** Medium +- **Web search:** used + +## Research Results + +### Claude Code has no optional-dependency or contribution mechanism + +A plugin's `dependencies` are hard requirements. They are installed automatically, and the dependent plugin is disabled +when one is missing or out of version range (A1, A2). Claude Code strips any manifest key it does not recognize, and it +documents no `contributes`, `extends`, or optional-dependency field (A1). One search turned up no proposal for one +[single-source] (A11). The free-form `metadata` object is ignored by Claude Code itself (A1), so a custom manifest field +cannot carry the declaration. + +This rules out the obvious design of having `han-planning` depend on `han-coding`. That edge would auto-install +`han-coding` and disable `han-planning` without it (A2). Han's own past investigation reached the same conclusion: a +dependency only affects installation, not what a skill can see (A31). + +### Prior art puts the contract with the consumer + +Every plugin system surveyed has the consuming side, or a neutral host, define the named slot. Providers register +against that slot. + +- IntelliJ: the defining plugin declares an extension point, and other plugins contribute into its namespace (A13). +- Eclipse: the declaring plug-in owns the contract (A20). +- Python entry points: the consumer owns the group and its interface (A15). +- pluggy and pytest: the host owns the hook specs, and plugins implement them (A16, A17). +- Java ServiceLoader: the service owner defines the interface (A18). + +No surveyed system has a provider list the consumer's internal features [negative result, bounded survey]. The nearest +cases, VS Code `contributes` and IntelliJ optional ``, name a host-defined slot or id, not the consumer's +private parts (A14, A19). In your example, `han-coding`'s file saying "`test-engineer` is usable by `plan-a-feature` +and `plan-implementation`" is the push shape that prior art avoids. Saying "`test-engineer` fills `han-planning`'s +test-planning role" is the pull shape it supports. + +### The consumer always owns what happens when nothing is installed + +The systems agree that absence is the consumer's problem to handle. ServiceLoader returns an empty result and the caller +supplies a default (A18). npm says handling a missing optional dependency "is still your program's responsibility" +(A21). IntelliJ isolates optional code so the core never touches it [single-source] (A14). + +Han already has this rule for user-configured extra agents. An entry that does not resolve to a dispatchable agent is +skipped with a one-line note, and a bad config never fails a run (A23). A contributed agent can reuse those semantics +unchanged. + +### The known failure mode is a silent no-op + +Pluggy accepts an implementation whose hook name matches nothing, unless the host runs an explicit check (A16). For Han, +the same thing happens if `han-coding` names a role `han-planning` renamed or never had: the contribution is silently +ignored. Han has no test today that checks an agent reference resolves or that a role name exists (A33), so nothing +would catch it. + +### Four ways a skill could learn what another plugin contributes + +No environment variable or substitution exposes another plugin's install location. `${CLAUDE_PLUGIN_ROOT}` and +`${CLAUDE_PLUGIN_DATA}` point only at the plugin itself (A1). Han uses nothing beyond `${CLAUDE_PLUGIN_ROOT}` today, and +has no code that finds sibling plugins (A24). Han's earlier research also found that a plugin cannot hand configuration to +a project through a CLAUDE.md at its root or through `userConfig` [single-source] (A30). What remains: + +- **Startup hook.** A plugin's SessionStart hook can print text into the session's context before the first prompt. It + re-fires on resume, clear, and compaction, and only enabled plugins run hooks [single-source] (A5). Hook processes + receive the plugin's own `${CLAUDE_PLUGIN_ROOT}`, so the hook can read its own contribution file (A1). This is the + only documented channel where a provider pushes content another plugin's skill can see. Han ships no hooks today. +- **Command-line listing.** `claude plugin list --json` reports every installation with its id, enabled state, scope, + version, and install path (A4). Calling it from a skill's load-time shell probe is unverified for speed and safety. A + failing probe aborts the whole skill unless guarded (A6), and in-place plugins may report no install path (A3, A4). +- **Reading Claude Code's plugin folders.** `installed_plugins.json` and the versioned cache folder are documented, but + as a loading reference, not a published schema (A3). The cache path changes on every update, a setting can move the + root (A3, A10), and the file does not reflect which plugins are enabled for this project (A3). +- **The session's own agent list.** Plugin agents register as `plugin:agent`, and the model sees every available + agent's description (A7). This session's own Agent tool listing shows agents from six different plugins with their + descriptions (A34). Han already uses prose-level "check it is installed, else fall back" logic for skills (A32). + What the Agent tool does when handed an unknown agent name is undocumented. Two user reports disagree on whether the + error lists the valid names [single-source each] (A8, A9). + +### Codex has no equivalent + +Codex plugins have no documented dependency field or plugin-to-plugin reference (A12). Han ships Codex manifests for +every plugin, so any design that leans on a Claude Code hook has no confirmed Codex counterpart. + +### The move itself reverses a recorded decision + +Han's current rule keeps an agent in `han-core` unless a single skill family in one plugin dispatches it exclusively +(A29). `test-engineer` is dispatched from four `han-planning` skills (A25) and two `han-coding` skills (A26). A recorded +decision rejected splitting the roster between `han-planning` and `han-coding`, because their dispatch sets overlap +heavily (A28). Moving `test-engineer` with this mechanism means amending both. It also means `han-planning` deliberately +loses `test-engineer` when `han-coding` is absent, which is the behavior you described. Both plugins depend today only +on `han-communication` and `han-core` (A27), so nothing new is needed on the dependency side. + +## Options to Consider + +### O1: Provider startup hook prints a role-shaped contribution file + +- **What it is:** `han-coding` ships a contribution file in the same markdown shape as `.han/config.md`, saying which + of its agents fill which named consumer roles, plus a SessionStart hook that prints that file. `han-planning`'s roster + tables name roles. A skill uses any agent a contribution in context names for its role, and skips the role when none + does. It matches what you asked for: the configuration lives in the providing plugin and is found automatically. +- **Trade-offs:** It uses only documented parts (A1, A5) and only enabled plugins contribute (A5). A small amount of + context is spent every session, and the model reads it rather than a parser. It does nothing where hooks are + disabled, and has no confirmed Codex path (A12). It adds the first hook to Han. +- **Rests on:** (A1), (A5), (A13), (A15), (A16), (A23) +- **Evidence status:** single-source (caveated) for the hook injection (A5); corroborated for the role contract. + +### O2: Skill probe calls the command-line plugin listing + +- **What it is:** Each consuming skill's load-time probe runs `claude plugin list --json`, finds enabled Han plugins, + and reads each one's contribution file from its install path. +- **Trade-offs:** It is machine-parsed and reports enabled state (A4). It also nests a CLI call inside every skill load + with unverified latency and safety, and a failure aborts the skill unless guarded (A6). In-place plugins may lack an + install path (A4). It needs a new `allowed-tools` grant on every consuming skill (A6, A24). +- **Rests on:** (A3), (A4), (A6) +- **Evidence status:** corroborated for the output format; single-source (caveated) that it is safe to run from a probe. + +### O3: Skill probe reads Claude Code's plugin folders directly + +- **What it is:** A shared script, symlinked like the config-dir resolver (A24), reads `installed_plugins.json` or + globs sibling folders in the plugin cache for contribution files. +- **Trade-offs:** It is fast and needs no CLI. But it reads files that are not a published schema, it misses the + project-level enabled state, and the path moves with versions and settings (A3, A10). It is the most fragile option. +- **Rests on:** (A3), (A10), (A24) +- **Evidence status:** single-source (caveated) + +### O4: Consumer roster names the optional agent and checks the session list + +- **What it is:** `han-planning`'s roster names `han-coding:test-engineer` directly as optional: dispatch it if it + appears in the session's available agents, skip the role if it does not. No contribution file and no transport. +- **Trade-offs:** It needs no new machinery and works anywhere agents register (A7, A34). It reuses Han's existing skip + semantics (A23). But the mapping lives in `han-planning`, not `han-coding`, which is the opposite of what you asked + for, and the consumer must know the provider's agent name. It covers agents only. +- **Rests on:** (A7), (A23), (A32), (A34) +- **Evidence status:** corroborated (A7 with A34 on agent visibility); unknown-agent behavior is unresolved (A8, A9). + +### O5: Keep the shared roster in `han-core` + +- **What it is:** The status quo. Every agent either plugin dispatches stays in `han-core`. +- **Trade-offs:** It is proven and needs no new mechanism (A28, A29). It leaves `han-core` carrying agents only one + plugin family really needs, which is the problem you want to solve. +- **Rests on:** (A28), (A29) +- **Evidence status:** corroborated (codebase) + +## Recommendation + +- **Recommendation:** Adopt a role-shaped (pull) contract, delivered by O1's startup hook, with O4's session-list check + as the guard in every consuming skill. `han-planning` names the roles in its rosters. `han-coding` ships the file + saying `test-engineer` fills the test-planning role. A planning skill dispatches a contributed agent only when it also + appears among the session's available agents, and otherwise skips the role with Han's existing one-line note. Add a + test that every role a contribution names exists in some consumer roster, to catch the silent no-op. Before + committing, run one live check: install `han-coding` with a SessionStart hook in a local marketplace, confirm a + `han-planning` skill sees the printed text, and confirm it survives a compaction. If that check fails, fall back to O4 + alone and accept that the mapping lives in `han-planning`. +- **Evidence basis:** + - Corroborated: the consumer owns the contract and the degradation (A13, A15, A16, A18, A20, A21); Claude Code has no + optional or contributes field, and dependencies are hard (A1, A2); plugin agents are visible to the model by name + (A7, A34); Han already skips unresolved extra agents (A23). + - Single-source: a SessionStart hook's output reaches skills in other plugins and survives compaction (A5). This is + why the live check comes first, and why the O4 guard keeps the design safe if A5 is wrong. + - Single-source: what the Agent tool does with an unknown agent name (A8, A9). The guard avoids relying on it. + - Codebase: the move amends the agent-placement rule (A29) and decision D1 (A28). + +## Validation + + + +## Sources + +| ID | Source | Link / location | Retrieved | Trust class | Summary (one line) | Evidence status | +| --- | ------ | --------------- | --------- | ----------- | ------------------ | --------------- | +| A1 | Claude Code plugin manifest reference | https://code.claude.com/docs/en/plugins-reference | 2026-10-15 | web | Only per-plugin path variables exist; `dependencies` are required; unknown manifest keys are stripped; no contributes field; `metadata` unread | corroborated by A2, A3, A5 | +| A2 | Claude Code plugin dependencies | https://code.claude.com/docs/en/plugin-dependencies | 2026-10-15 | web | Dependencies auto-install and the dependent plugin is disabled when one is missing or out of range; no optional form | corroborated by A1 | +| A3 | Claude Code plugin loading reference | https://code.claude.com/docs/en/plugins/loading | 2026-10-15 | web | Plugin cache layout, `installed_plugins.json`, versioned paths, six-source `enabledPlugins`, in-place loading | corroborated by A4 | +| A4 | Claude Code plugin CLI reference | https://code.claude.com/docs/en/plugins/cli-reference | 2026-10-15 | web | `claude plugin list --json` reports id, enabled, scope, version, installPath per installation | corroborated by A3 | +| A5 | Claude Code hooks reference | https://code.claude.com/docs/en/hooks | 2026-10-15 | web | SessionStart output is added to context before the first prompt, re-fires on resume/clear/compact; only enabled plugins run hooks | single source (caveated); hook environment corroborated by A1 | +| A6 | Claude Code skills reference | https://code.claude.com/docs/en/skills | 2026-10-15 | web | A failing load-time `!` command aborts the skill unless guarded; needs `allowed-tools`; can be disabled by a setting | single source (caveated) | +| A7 | Claude Code subagents reference | https://code.claude.com/docs/en/sub-agents | 2026-10-15 | web | Plugin agents register as `plugin:agent` and the model sees their descriptions; unknown-name error undocumented | corroborated by A34 on visibility | +| A8 | Mirror of anthropics/claude-code issue #32975 | https://claudeissues.com/issue/32975-bug-agent-tool-accepts-invalid-subagent-type-without-validation-error | 2026-10-15 | web | User report: an invalid `subagent_type` fails ambiguously without listing valid types | single source (caveated); contradicted by A9 | +| A9 | Mirror digest of issues #38964 and #45043 | https://claudeissues.com/issue/45043-subagent-type-with-custom-agents-from-claude-agents-returns-agent-type-not-found | 2026-10-15 | web | Snippets: unknown agent returns "Agent type '' not found" with an available-agents list | single source (caveated); contradicted by A8 | +| A10 | Claude Code environment variables reference | https://code.claude.com/docs/en/env-vars | 2026-10-15 | web | `CLAUDE_CODE_PLUGIN_CACHE_DIR` moves the plugins root; `CLAUDE_CONFIG_DIR` effect on it unverified | single source (caveated) | +| A11 | Web search for optional dependency / contributes proposals | https://github.com/anthropics/claude-code/issues/48864, https://github.com/anthropics/claude-code/issues/51370 | 2026-10-15 | web | One search found only dependency doc-gap issues, no optional or contributes proposal | negative result, single search | +| A12 | Codex plugin build docs | https://developers.openai.com/codex/plugins/build | 2026-10-15 | web | Codex cache and enabled state under `~/.codex/`; no dependency or plugin-to-plugin reference documented | single source (caveated) | +| A13 | IntelliJ Platform extension points | https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html | 2026-10-15 | web | Defining plugin declares the extension point; contributors fill it in its namespace | corroborated by A15, A16, A20 | +| A14 | IntelliJ Platform optional plugin dependencies | https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html | 2026-10-15 | web | Optional `` isolates optional code in a separate config file so the plugin loads without the other | single source (caveated) | +| A15 | Python packaging entry points specification | https://packaging.python.org/en/latest/specifications/entry-points/ | 2026-10-15 | web | The consuming project defines the group's interface; prefix group names to avoid clashes | corroborated by A13, A16, A17 | +| A16 | pluggy documentation | https://pluggy.readthedocs.io/en/latest/ | 2026-10-15 | web | Host defines hookspecs, plugins implement; an impl matching no spec is accepted unless the host validates | corroborated by A15, A17 | +| A17 | pytest: writing plugins | https://docs.pytest.org/en/stable/how-to/writing_plugins.html | 2026-10-15 | web | Plugins auto-discovered via the pytest-owned `pytest11` entry-point group | corroborated by A15, A16 | +| A18 | Java ServiceLoader (Java 21) | https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/ServiceLoader.html | 2026-10-15 | web | Service owner defines the interface; no provider yields an empty result and the caller supplies a default | corroborated by A15, A16 | +| A19 | VS Code extension manifest | https://code.visualstudio.com/api/references/extension-manifest | 2026-10-15 | web | `contributes` declarations key on ids; `extensionPack` bundles members that must work independently | single source (caveated) | +| A20 | Eclipse FAQ: extensions and extension points | https://wiki.eclipse.org/FAQ_What_are_extensions_and_extension_points%3F | 2026-10-15 | web | Declaring plug-in defines the contract (socket); extensions are plugs | corroborated by A13 | +| A21 | npm package.json docs | https://docs.npmjs.com/cli/v10/configuring-npm/package-json | 2026-10-15 | web | Handling a missing optional dependency is the program's responsibility | corroborated by A18 | +| A22 | OSGi whiteboard pattern (search snippets) | https://enroute.osgi.org/FAQ/400-patterns.html | 2026-10-15 | web | Providers register services; consumer looks them all up; absence need not block | single source (caveated); pages not opened | +| A23 | Han config rule: extra agents and degradation | `han-core/references/config-rule.md:111-134` | n/a | codebase | Extra agents join the candidate pool; an unresolvable entry is skipped with a one-line note; bad config never fails a run | codebase anchor | +| A24 | Han config probe and resolver | `han-research/skills/research/SKILL.md:15-23`, `scripts/han-config-dir.sh`, `scripts/han-config-dir.bats:46-76` | n/a | codebase | Skills use only `${CLAUDE_PLUGIN_ROOT}` and a symlinked resolver script; no sibling-plugin lookup exists | codebase anchor | +| A25 | test-engineer dispatch in han-planning | `han-planning/skills/plan-a-feature/references/review-team-briefs.md:26`, `han-planning/skills/plan-implementation/references/team-selection.md:74-75`, `han-planning/skills/plan-a-change/references/team-selection.md:53`, `han-planning/skills/iterative-plan-review/references/team-selection.md:55-56` | n/a | codebase | Four han-planning skills select `han-core:test-engineer` by domain match, with no installed check | codebase anchor | +| A26 | test-engineer dispatch in han-coding | `han-coding/skills/automated-test-planning/SKILL.md:124,142`, `han-coding/skills/code-review/references/agent-dispatch.md:31-32`, `han-coding/skills/code-review/references/types/testing.md:9` | n/a | codebase | Two han-coding skills dispatch `han-core:test-engineer` | codebase anchor | +| A27 | Plugin manifests | `han-planning/.claude-plugin/plugin.json:5`, `han-coding/.claude-plugin/plugin.json:5`, `han/.claude-plugin/plugin.json:5-14` | n/a | codebase | han-planning and han-coding each depend only on han-communication and han-core | codebase anchor | +| A28 | han-core restructure decision D1 | `docs/plans/han-core-restructure/artifacts/decision-log.md:19-30` | n/a | codebase | Kept the shared roster in han-core; rejected splitting it between han-planning and han-coding over heavy overlap | codebase anchor | +| A29 | Agent placement rule | `CONTRIBUTING.md:203-207` | n/a | codebase | Agents live in han-core unless one skill family in one plugin dispatches them exclusively | codebase anchor | +| A30 | Earlier config extensibility research | `docs/research/han-config-extensibility.md:65-71` | n/a | codebase | A plugin cannot ship project config: plugin-root CLAUDE.md is not loaded and `userConfig` is user-scope only | single source (caveated) in that report | +| A31 | Namespace-qualified dispatch investigation | `docs/plans/namespace-qualified-agent-dispatch/investigation.md:25-26,62-70` | n/a | codebase | `dependencies` is install-only; bare agent names can collide across installed plugins | corroborated by A2 | +| A32 | Installed-skill detection prose | `han-planning/skills/plan-work-items/references/deliverable-skill-catalog.md:64` | n/a | codebase | A han-planning skill already checks a skill is installed and falls back to a best fit, in prose | codebase anchor | +| A33 | Absence of reference checks | `test/`, `han-planning/skills/*/scripts/check-*.sh` | n/a | codebase | No test checks that a dispatched agent exists or that config-rule copies match | codebase negative result | +| A34 | This session's available-agent listing | provided: Agent tool roster in the research session, 2026-10-15 | n/a | provided | The model's agent list shows plugin agents from six plugins as `plugin:agent` with descriptions | corroborated by A7 | From fe6400d028442a1ff54871b14994cbb4bf3c6ecd Mon Sep 17 00:00:00 2001 From: River Bailey Date: Thu, 15 Oct 2026 13:32:04 -0600 Subject: [PATCH 2/9] docs(research): apply adversarial validation to cross-plugin config report --- .../research/cross-plugin-config-discovery.md | 395 ++++++++++++++---- 1 file changed, 304 insertions(+), 91 deletions(-) diff --git a/docs/research/cross-plugin-config-discovery.md b/docs/research/cross-plugin-config-discovery.md index d71c4dc6..e23bbb23 100644 --- a/docs/research/cross-plugin-config-discovery.md +++ b/docs/research/cross-plugin-config-discovery.md @@ -8,25 +8,25 @@ Evidence mode: strict. ## Summary -Han can do this, but Claude Code gives it no built-in way to. Claude Code dependencies are all-or-nothing. A plugin that -lists another as a dependency gets it installed automatically and stops loading without it, and there is no "optional" -or "contributes to" setting. So the discovery has to be built from parts Claude Code already has. - -The shape of the contract matters more than the transport. Every established plugin system studied puts the contract -with the consumer: the planning plugin names a slot, such as "test-planning specialist", and the coding plugin says "my -`test-engineer` fills that slot." None has the provider list the consumer's individual features. Han should follow that -pattern, so renaming a planning skill never breaks the coding plugin. When nothing fills a slot, the planning skill -simply runs without it, the same way Han already skips an extra agent that is not installed. - -For the transport, the best-supported route is a small startup hook in each providing plugin. The hook prints that -plugin's contribution file into the session when the session starts, and only enabled plugins run hooks. As a safety -net, a planning skill checks that the agent actually appears in the session's list of available agents before -dispatching it. This works today with no new machinery, and it keeps the skill safe if the hook does not run. Two other -routes exist: asking the Claude Code command line which plugins are installed, and reading Claude Code's plugin folders -directly. Both are less stable. - -How solid it is: the contract shape is well-corroborated; the startup-hook transport rests on one documentation page -and needs a quick live check before you commit to it. +You can move `test-engineer` into `han-coding` and keep `han-planning` working without it, and the simplest way needs no +new machinery. Put the declaration in the agent itself. `test-engineer`'s description says it fills planning's +test-planning role. `han-planning` names that role in its team lists and uses whichever available agent claims it. When +`han-coding` is not installed, no agent claims the role and the planning skill runs without it. + +This works because Claude Code already shows the model every installed agent and its description. It also follows the +pattern every established plugin system studied uses. The consuming side names a slot, and the providing side says it +fills that slot. The provider never lists the consumer's individual features, so renaming a planning skill never breaks +the coding plugin. + +Claude Code has no built-in "optional dependency" or "contributes to" setting. A plugin that lists another as a +dependency gets it installed automatically and stops loading without it. So a general system for one plugin to hand +configuration to another has to be built. The best-supported way is a small hook in each providing plugin that prints +its contribution file when a session starts. Build that only when a plugin needs to contribute something other than an +agent. It adds Han's first hook, costs a little context in every session, and rests on one documentation page that has +not been checked in a live session. + +How solid it is: the slot-and-filler pattern is well-corroborated; the agent-description route rests on how Claude Code +shows agents to the model, confirmed by its docs and by direct observation; the hook route rests on a single source. - **Confidence:** Medium - **Web search:** used @@ -38,12 +38,12 @@ and needs a quick live check before you commit to it. A plugin's `dependencies` are hard requirements. They are installed automatically, and the dependent plugin is disabled when one is missing or out of version range (A1, A2). Claude Code strips any manifest key it does not recognize, and it documents no `contributes`, `extends`, or optional-dependency field (A1). One search turned up no proposal for one -[single-source] (A11). The free-form `metadata` object is ignored by Claude Code itself (A1), so a custom manifest field -cannot carry the declaration. +[single-source] (A11). Claude Code ignores the free-form `metadata` object (A1), so a custom manifest field cannot carry +the declaration. -This rules out the obvious design of having `han-planning` depend on `han-coding`. That edge would auto-install -`han-coding` and disable `han-planning` without it (A2). Han's own past investigation reached the same conclusion: a -dependency only affects installation, not what a skill can see (A31). +This rules out having `han-planning` depend on `han-coding`. That edge would auto-install `han-coding` and disable +`han-planning` without it (A2). Han's own earlier investigation reached the same conclusion: a dependency controls what +gets installed, not what a skill can see (A31). ### Prior art puts the contract with the consumer @@ -55,12 +55,14 @@ against that slot. - Python entry points: the consumer owns the group and its interface (A15). - pluggy and pytest: the host owns the hook specs, and plugins implement them (A16, A17). - Java ServiceLoader: the service owner defines the interface (A18). +- OSGi whiteboard: providers register themselves, and the consumer looks them all up [single-source] (A22). -No surveyed system has a provider list the consumer's internal features [negative result, bounded survey]. The nearest -cases, VS Code `contributes` and IntelliJ optional ``, name a host-defined slot or id, not the consumer's -private parts (A14, A19). In your example, `han-coding`'s file saying "`test-engineer` is usable by `plan-a-feature` -and `plan-implementation`" is the push shape that prior art avoids. Saying "`test-engineer` fills `han-planning`'s -test-planning role" is the pull shape it supports. +The surveyed systems do not have a provider list the consumer's internal features. This is a bounded survey of about +ten systems, not proof that none does. The nearest cases, VS Code `contributes` and IntelliJ optional ``, have +the provider name a host-defined slot or id (A14, A19). Applied to your example, "`test-engineer` is usable by +`plan-a-feature` and `plan-implementation`" names consumer skills. "`test-engineer` fills `han-planning`'s +test-planning role" names a slot. Both keep the declaration inside `han-coding`, which is what you asked for. Only the +second matches the surveyed pattern. ### The consumer always owns what happens when nothing is installed @@ -75,120 +77,295 @@ unchanged. ### The known failure mode is a silent no-op Pluggy accepts an implementation whose hook name matches nothing, unless the host runs an explicit check (A16). For Han, -the same thing happens if `han-coding` names a role `han-planning` renamed or never had: the contribution is silently -ignored. Han has no test today that checks an agent reference resolves or that a role name exists (A33), so nothing -would catch it. +the same thing happens if `han-coding` names a role `han-planning` renamed or never had: the contribution is ignored and +nobody is told. No check in `test/` or the planning scripts verifies that an agent reference resolves (A33), so nothing +would catch it today. ### Four ways a skill could learn what another plugin contributes No environment variable or substitution exposes another plugin's install location. `${CLAUDE_PLUGIN_ROOT}` and -`${CLAUDE_PLUGIN_DATA}` point only at the plugin itself (A1). Han uses nothing beyond `${CLAUDE_PLUGIN_ROOT}` today, and -has no code that finds sibling plugins (A24). Han's earlier research also found that a plugin cannot hand configuration to -a project through a CLAUDE.md at its root or through `userConfig` [single-source] (A30). What remains: +`${CLAUDE_PLUGIN_DATA}` point only at the plugin itself (A1). Han reaches files only through its own plugin and skill +roots and has no code that finds sibling plugins (A24). Han's earlier research also found that a plugin cannot hand +configuration to a project through a CLAUDE.md at its root or through `userConfig` [single-source] (A30). What remains: +- **The session's own agent list.** Plugin agents register as `plugin:agent`, and the model sees every available + agent's description (A7). This session's own agent list shows agents from six plugins with their descriptions (A34). + Han already uses prose-level "check it is installed, else fall back" logic for skills (A32). What the Agent tool does + when handed an unknown agent name is undocumented. Two user reports disagree on whether the error lists the valid + names [single-source each] (A8, A9). - **Startup hook.** A plugin's SessionStart hook can print text into the session's context before the first prompt. It - re-fires on resume, clear, and compaction, and only enabled plugins run hooks [single-source] (A5). Hook processes - receive the plugin's own `${CLAUDE_PLUGIN_ROOT}`, so the hook can read its own contribution file (A1). This is the - only documented channel where a provider pushes content another plugin's skill can see. Han ships no hooks today. + re-fires on resume, clear, and compaction, and only enabled plugins run hooks [single-source] (A5). Hook processes get + only the plugin's own path variables, so the hook can read its own contribution file (A1). This is the only + documented channel where a provider pushes content into the session. The docs do not say outright that a skill in a + different plugin then reads it, or that subagents see it. No Han plugin ships a hook today (A35). - **Command-line listing.** `claude plugin list --json` reports every installation with its id, enabled state, scope, version, and install path (A4). Calling it from a skill's load-time shell probe is unverified for speed and safety. A failing probe aborts the whole skill unless guarded (A6), and in-place plugins may report no install path (A3, A4). - **Reading Claude Code's plugin folders.** `installed_plugins.json` and the versioned cache folder are documented, but as a loading reference, not a published schema (A3). The cache path changes on every update, a setting can move the root (A3, A10), and the file does not reflect which plugins are enabled for this project (A3). -- **The session's own agent list.** Plugin agents register as `plugin:agent`, and the model sees every available - agent's description (A7). This session's own Agent tool listing shows agents from six different plugins with their - descriptions (A34). Han already uses prose-level "check it is installed, else fall back" logic for skills (A32). - What the Agent tool does when handed an unknown agent name is undocumented. Two user reports disagree on whether the - error lists the valid names [single-source each] (A8, A9). ### Codex has no equivalent Codex plugins have no documented dependency field or plugin-to-plugin reference (A12). Han ships Codex manifests for every plugin, so any design that leans on a Claude Code hook has no confirmed Codex counterpart. -### The move itself reverses a recorded decision +### The move reaches further than the planning rosters Han's current rule keeps an agent in `han-core` unless a single skill family in one plugin dispatches it exclusively (A29). `test-engineer` is dispatched from four `han-planning` skills (A25) and two `han-coding` skills (A26). A recorded decision rejected splitting the roster between `han-planning` and `han-coding`, because their dispatch sets overlap -heavily (A28). Moving `test-engineer` with this mechanism means amending both. It also means `han-planning` deliberately -loses `test-engineer` when `han-coding` is absent, which is the behavior you described. Both plugins depend today only -on `han-communication` and `han-core` (A27), so nothing new is needed on the dependency side. +heavily (A28). Moving `test-engineer` means amending both, whichever discovery route you pick. + +The move also touches files beyond the dispatch rosters: + +- Two `han-core` agents and one `han-planning` agent route test-planning questions to `test-engineer` by name (A36). + After the move, `han-core` would name an agent that lives in a plugin above it and may not be installed. +- The evals name `han-core:test-engineer` 13 times (A36). +- `han-coding`'s own calls change namespace from `han-core:` to `han-coding:` (A26). + +Neither plugin needs a new dependency. Both depend today only on `han-communication` and `han-core` (A27). + +### Checking the general mechanism against Han's YAGNI rule + +Han's YAGNI rule asks for evidence that an item is needed now, then prefers the strictly simpler version that meets it +(A37). The evidence you gave covers moving agents out of `han-core` with `test-engineer` as the first case. It does not +yet show a plugin needing to contribute anything other than an agent. The `han` meta-plugin installs both +`han-planning` and `han-coding` (A27), so most people get both today. The planning-without-coding install is your stated +requirement, which is evidence for the move. It is not evidence for a general configuration channel. ## Options to Consider ### O1: Provider startup hook prints a role-shaped contribution file -- **What it is:** `han-coding` ships a contribution file in the same markdown shape as `.han/config.md`, saying which - of its agents fill which named consumer roles, plus a SessionStart hook that prints that file. `han-planning`'s roster - tables name roles. A skill uses any agent a contribution in context names for its role, and skips the role when none - does. It matches what you asked for: the configuration lives in the providing plugin and is found automatically. -- **Trade-offs:** It uses only documented parts (A1, A5) and only enabled plugins contribute (A5). A small amount of - context is spent every session, and the model reads it rather than a parser. It does nothing where hooks are - disabled, and has no confirmed Codex path (A12). It adds the first hook to Han. -- **Rests on:** (A1), (A5), (A13), (A15), (A16), (A23) -- **Evidence status:** single-source (caveated) for the hook injection (A5); corroborated for the role contract. +- **What it is:** `han-coding` ships a contribution file and a SessionStart hook that prints it. The file uses the same + markdown shape as `.han/config.md`, with frontmatter and named sections (A38). It says which agents fill which named + consumer roles, and could carry other settings later. `han-planning`'s team lists name roles. A skill uses any agent a + contribution in context names for its role, and skips the role when none does. It is the general configuration + channel you described. +- **Trade-offs:** It uses only documented parts (A1, A5), and only enabled plugins contribute (A5). It costs a small + amount of context every session, including sessions that never run a planning skill, and the model reads it rather + than a parser. If the hook does not run, the role is skipped without notice even though `han-coding` is installed. It + is Han's first hook (A35), and has no confirmed Codex path (A12). +- **Rests on:** (A1), (A5), (A15), (A16), (A23), (A38) +- **Evidence status:** single-source (caveated) for the hook transport (A5); corroborated for the role contract. ### O2: Skill probe calls the command-line plugin listing - **What it is:** Each consuming skill's load-time probe runs `claude plugin list --json`, finds enabled Han plugins, and reads each one's contribution file from its install path. -- **Trade-offs:** It is machine-parsed and reports enabled state (A4). It also nests a CLI call inside every skill load +- **Trade-offs:** It is machine-parsed and reports enabled state (A4). But it nests a CLI call inside every skill load, with unverified latency and safety, and a failure aborts the skill unless guarded (A6). In-place plugins may lack an - install path (A4). It needs a new `allowed-tools` grant on every consuming skill (A6, A24). + install path (A4). Every consuming skill needs a new `allowed-tools` grant (A6, A24). - **Rests on:** (A3), (A4), (A6) - **Evidence status:** corroborated for the output format; single-source (caveated) that it is safe to run from a probe. ### O3: Skill probe reads Claude Code's plugin folders directly -- **What it is:** A shared script, symlinked like the config-dir resolver (A24), reads `installed_plugins.json` or - globs sibling folders in the plugin cache for contribution files. -- **Trade-offs:** It is fast and needs no CLI. But it reads files that are not a published schema, it misses the +- **What it is:** A shared script, symlinked into each plugin like the config-dir resolver (A24), reads + `installed_plugins.json` or searches sibling folders in the plugin cache for contribution files. +- **Trade-offs:** It is fast and needs no CLI. But the files it reads are not a published schema, it misses the project-level enabled state, and the path moves with versions and settings (A3, A10). It is the most fragile option. - **Rests on:** (A3), (A10), (A24) - **Evidence status:** single-source (caveated) -### O4: Consumer roster names the optional agent and checks the session list +### O4: Consumer team list names the optional agent -- **What it is:** `han-planning`'s roster names `han-coding:test-engineer` directly as optional: dispatch it if it - appears in the session's available agents, skip the role if it does not. No contribution file and no transport. +- **What it is:** `han-planning`'s team list names `han-coding:test-engineer` as optional. A skill dispatches it if it + appears among the session's available agents and skips the role if it does not. No contribution file and no + transport. - **Trade-offs:** It needs no new machinery and works anywhere agents register (A7, A34). It reuses Han's existing skip - semantics (A23). But the mapping lives in `han-planning`, not `han-coding`, which is the opposite of what you asked - for, and the consumer must know the provider's agent name. It covers agents only. -- **Rests on:** (A7), (A23), (A32), (A34) -- **Evidence status:** corroborated (A7 with A34 on agent visibility); unknown-agent behavior is unresolved (A8, A9). - -### O5: Keep the shared roster in `han-core` + rule (A23). But the mapping lives in `han-planning`, which is the opposite of what you asked for, and `han-planning` + must know `han-coding`'s agent name. It covers agents only. +- **Rests on:** (A7), (A23), (A34) +- **Evidence status:** corroborated for agent visibility (A7, consistent with A34); unknown-agent behavior unresolved + (A8, A9). + +### O5: The agent declares its role in its own description + +- **What it is:** The O4 mechanism with the declaration moved into `han-coding`. `test-engineer`'s description states + that it fills planning's test-planning role. `han-planning`'s team list names the role, not the agent, and uses any + available agent whose description claims it. +- **Trade-offs:** The declaration lives in the providing plugin, as you asked, with no hook, no file, and no Codex gap + beyond whether Codex shows agents to the model (A7, A12). The cost: descriptions also drive Claude Code's automatic + delegation and count against a shared context budget (A7), so role text has to stay short. A role claimed in prose + cannot be checked by a parser, though a test can search descriptions for role names to catch the silent no-op (A16, + A33). It covers agents only. +- **Rests on:** (A7), (A13), (A15), (A23), (A34) +- **Evidence status:** corroborated for agent visibility and the role contract; no source documents role-matching on + descriptions specifically. + +### O6: Delegate to a han-coding skill when it is installed + +- **What it is:** Move the agent, and have the planning skill invoke `han-coding`'s `automated-test-planning` skill, + which dispatches `test-engineer` alone in its focused mode (A39), when that skill is installed. Otherwise skip. +- **Trade-offs:** It uses Han's existing "check the skill is installed, else fall back" prose (A32) and needs no hook. + The skill's own description is the declaration. But it runs a whole skill, with its own output and steps, where the + planning roster wanted one specialist's input on a plan. It covers only capabilities that already have a skill. +- **Rests on:** (A32), (A39) +- **Evidence status:** codebase only; untested as a cross-plugin delegation. + +### O7: Keep the shared roster in `han-core` - **What it is:** The status quo. Every agent either plugin dispatches stays in `han-core`. -- **Trade-offs:** It is proven and needs no new mechanism (A28, A29). It leaves `han-core` carrying agents only one - plugin family really needs, which is the problem you want to solve. +- **Trade-offs:** It is proven and needs no new mechanism (A28, A29). It leaves `han-core` carrying agents that only one + plugin family needs, which is the problem you want to solve. - **Rests on:** (A28), (A29) - **Evidence status:** corroborated (codebase) +A registry file in `han-core` that each provider edits is not listed. It puts `han-core` back in the middle, and +`han-core` would have to know about every provider, which is the coupling the move is meant to remove. + ## Recommendation -- **Recommendation:** Adopt a role-shaped (pull) contract, delivered by O1's startup hook, with O4's session-list check - as the guard in every consuming skill. `han-planning` names the roles in its rosters. `han-coding` ships the file - saying `test-engineer` fills the test-planning role. A planning skill dispatches a contributed agent only when it also - appears among the session's available agents, and otherwise skips the role with Han's existing one-line note. Add a - test that every role a contribution names exists in some consumer roster, to catch the silent no-op. Before - committing, run one live check: install `han-coding` with a SessionStart hook in a local marketplace, confirm a - `han-planning` skill sees the printed text, and confirm it survives a compaction. If that check fails, fall back to O4 - alone and accept that the mapping lives in `han-planning`. +- **Recommendation:** Adopt O5 for `test-engineer`. Name roles, not agents, in `han-planning`'s team lists, and have the + moved agent's description claim its role. A planning skill uses an available agent that claims the role and otherwise + skips it with Han's existing one-line note. Add a test that every role an agent description claims appears in some + consumer team list. Amend the agent-placement rule and decision D1, and update the `han-core` agents, the evals, and + the docs that name `test-engineer`. Hold O1 until a plugin needs to contribute something other than an agent. At + that point, first run one live check: install `han-coding` with a SessionStart hook from a local marketplace and + confirm a `han-planning` skill and its subagents see the printed text after a compaction. If you would rather keep + descriptions free of planning concepts, O4 is the plainer fallback, at the cost of the mapping living in + `han-planning`. - **Evidence basis:** - - Corroborated: the consumer owns the contract and the degradation (A13, A15, A16, A18, A20, A21); Claude Code has no - optional or contributes field, and dependencies are hard (A1, A2); plugin agents are visible to the model by name - (A7, A34); Han already skips unresolved extra agents (A23). - - Single-source: a SessionStart hook's output reaches skills in other plugins and survives compaction (A5). This is - why the live check comes first, and why the O4 guard keeps the design safe if A5 is wrong. - - Single-source: what the Agent tool does with an unknown agent name (A8, A9). The guard avoids relying on it. - - Codebase: the move amends the agent-placement rule (A29) and decision D1 (A28). + - Corroborated: the consumer owns the slot and the handling of absence (A13, A15, A16, A18, A20, A21); Claude Code + has no optional or contributes field, and dependencies are hard (A1, A2); the model sees each plugin agent's name + and description (A7, consistent with A34); Han already skips unresolved extra agents (A23). + - Codebase: the move amends the placement rule (A29) and D1 (A28) and touches routing text and evals (A36); YAGNI + favors the smallest version that meets the stated need (A37). + - Not documented anywhere found: matching a role named in an agent's description. It follows from agent visibility + (A7) and is how Han already selects agents by stated specialty, but no source tests it as a contract. + - Single-source, and deferred for that reason: the hook transport (A5). The unknown-agent error behavior (A8, A9) is + avoided by checking the available-agent list first. ## Validation - +The adversarial validator challenged the evidence, the options framing, the recommendation, and how the evidence was +gathered. The first draft recommended the hook (O1) as the primary transport. Validation changed that. + +### V1: Codebase anchors are accurate + +- **Strategy:** Challenge the Evidence +- **Investigation:** Read every cited codebase range (A23 to A29, A31, A32, A33). +- **Result:** Confirmed. Line offsets are within a line or two. +- **Impact:** None. + +### V2: "Han uses nothing beyond `${CLAUDE_PLUGIN_ROOT}`" overreached + +- **Strategy:** Challenge the Evidence +- **Investigation:** A repository search found `${CLAUDE_SKILL_DIR}` in two `han-coding` skills. It also confirmed that + no plugin ships hooks. +- **Result:** Partially Refuted. +- **Impact:** Reworded to "its own plugin and skill roots". Added A35 for the no-hooks claim. + +### V3: The no-test claim was broader than the search + +- **Strategy:** Challenge the Evidence +- **Investigation:** Listed `test/` and the planning scripts, and found the evals reference `han-core:test-engineer`. +- **Result:** Confirmed, with a narrower scope. +- **Impact:** A33 now says "no check found in `test/` or the planning scripts". The evals joined the list of files the + move touches (A36). + +### V4: A skill-delegation option was missing + +- **Strategy:** Challenge the Options Framing +- **Investigation:** `han-planning` already has installed-skill fallback prose (A32), and `automated-test-planning` can + dispatch `test-engineer` alone (A39). +- **Result:** Refuted. The option set was incomplete. +- **Impact:** Added O6. + +### V5: Agent self-description and a registry file were not considered + +- **Strategy:** Challenge the Options Framing +- **Investigation:** The model already sees each agent's description (A7, A34), so the agent can carry its own role + claim. A `han-core` registry would put `han-core` back in the middle. +- **Result:** Partially Refuted. +- **Impact:** Added O5, and a one-line rejection of the registry. + +### V6: The push-versus-pull framing was stated too strongly + +- **Strategy:** Challenge the Options Framing +- **Investigation:** The prior-art claim rests on a bounded survey. Your requested shape keeps the declaration in + `han-coding`, which O1 and O5 both honor. +- **Result:** Partially Refuted. +- **Impact:** Softened to "the surveyed systems do not do this". The report now says which options keep the declaration + in the provider. + +### V7: The availability guard does not cover a hook that never runs + +- **Strategy:** Challenge the Recommendation +- **Investigation:** Checking the available-agent list prevents dispatching a missing agent. If the hook never runs, + the contribution never reaches context, and an installed `test-engineer` is skipped without notice. +- **Result:** Partially Refuted. +- **Impact:** Removed the claim that the guard makes O1 safe if A5 is wrong. Named the silent skip as an O1 trade-off. + +### V8: The move touches agents and evals the draft did not list + +- **Strategy:** Challenge the Recommendation +- **Investigation:** `plan-synthesizer`, `junior-developer`, and `discussion-facilitator` route to `test-engineer` by + name. The evals and `han-coding`'s own calls name it under `han-core:` (A36, A26). +- **Result:** Partially Refuted. +- **Impact:** Added the section on how far the move reaches. The recommendation now includes those updates. + +### V9: The general mechanism was not checked against YAGNI + +- **Strategy:** Challenge the Recommendation +- **Investigation:** Applied Han's YAGNI rule (A37). The meta-plugin installs both plugins (A27). The stated need is + agents. The hook adds Han's first hook, per-session context cost, and a Codex gap. +- **Result:** Partially Refuted. +- **Impact:** Added the YAGNI section. O1 moved from recommended to deferred. + +### V10: Several citations fit loosely + +- **Strategy:** Challenge the Evidence +- **Investigation:** Traced every inline citation against its registry summary. +- **Problems found:** + - The config-file shape claim had no source. + - A34 was labeled as corroborating A7, but it is one session's observation. + - A22 was never cited. + - O1 cited prior-art sources for its hook. +- **Result:** Partially Refuted. +- **Impact:** Fixed each one: + - Added A38 for the config-file shape. + - Relabeled A34 as consistent with A7. + - Cited A22 in the prior-art list. + - Trimmed O1's sources to those that bear on it. + +### V11: The recommended transport rested on one source + +- **Strategy:** Challenge the Evidence-Gathering Integrity +- **Investigation:** Checked how many sources each piece of the recommendation rests on, and how independent they are: + - A5 alone supports the hook. + - "Re-fires on compaction" is not the same claim as "a skill in another plugin can read it". + - A8 and A9 are third-party copies of user bug reports. + - A22 is search snippets only. + - The summaries showed no planted or directive text. +- **Result:** Partially Refuted. +- **Impact:** The recommendation no longer depends on A5. Removing A8, A9, or A22 changes nothing. + +### V12: The hook-first ordering was not supported + +- **Strategy:** Challenge the Recommendation +- **Investigation:** Compared what O1 adds over the agent-list options once V7, V8, and V9 are applied. +- **Result:** Partially Refuted. +- **Impact:** The recommendation now leads with an option that needs no hook. + +### Adjustments Made + +The recommendation was rewritten. The first draft led with O1, the startup hook, and treated the agent-list check as a +guard. The final version leads with O5, which keeps the declaration in `han-coding` with no new machinery, and defers O1 +until a non-agent contribution is needed and a live check passes. O5 and O6 were added, the move's full reach and a +YAGNI check were added, and the citation problems were fixed. + +### Confidence Assessment + +- **Confidence:** Medium +- **Remaining Risks:** + - Role-matching on agent descriptions has no source that tests it as a contract. + - The SessionStart hook route rests on one documentation page and has not been run in a live session. + - What the Agent tool returns for an unknown agent name is unresolved (A8 and A9 conflict). + - Codex behavior is untested for every option. + - The validator did not re-fetch any web source. ## Sources @@ -217,7 +394,7 @@ on `han-communication` and `han-core` (A27), so nothing new is needed on the dep | A21 | npm package.json docs | https://docs.npmjs.com/cli/v10/configuring-npm/package-json | 2026-10-15 | web | Handling a missing optional dependency is the program's responsibility | corroborated by A18 | | A22 | OSGi whiteboard pattern (search snippets) | https://enroute.osgi.org/FAQ/400-patterns.html | 2026-10-15 | web | Providers register services; consumer looks them all up; absence need not block | single source (caveated); pages not opened | | A23 | Han config rule: extra agents and degradation | `han-core/references/config-rule.md:111-134` | n/a | codebase | Extra agents join the candidate pool; an unresolvable entry is skipped with a one-line note; bad config never fails a run | codebase anchor | -| A24 | Han config probe and resolver | `han-research/skills/research/SKILL.md:15-23`, `scripts/han-config-dir.sh`, `scripts/han-config-dir.bats:46-76` | n/a | codebase | Skills use only `${CLAUDE_PLUGIN_ROOT}` and a symlinked resolver script; no sibling-plugin lookup exists | codebase anchor | +| A24 | Han config probe and resolver | `han-research/skills/research/SKILL.md:15-23`, `scripts/han-config-dir.sh`, `scripts/han-config-dir.bats:46-76` | n/a | codebase | Skills reach files through their own plugin and skill roots and a symlinked resolver script; no sibling-plugin lookup exists | codebase anchor | | A25 | test-engineer dispatch in han-planning | `han-planning/skills/plan-a-feature/references/review-team-briefs.md:26`, `han-planning/skills/plan-implementation/references/team-selection.md:74-75`, `han-planning/skills/plan-a-change/references/team-selection.md:53`, `han-planning/skills/iterative-plan-review/references/team-selection.md:55-56` | n/a | codebase | Four han-planning skills select `han-core:test-engineer` by domain match, with no installed check | codebase anchor | | A26 | test-engineer dispatch in han-coding | `han-coding/skills/automated-test-planning/SKILL.md:124,142`, `han-coding/skills/code-review/references/agent-dispatch.md:31-32`, `han-coding/skills/code-review/references/types/testing.md:9` | n/a | codebase | Two han-coding skills dispatch `han-core:test-engineer` | codebase anchor | | A27 | Plugin manifests | `han-planning/.claude-plugin/plugin.json:5`, `han-coding/.claude-plugin/plugin.json:5`, `han/.claude-plugin/plugin.json:5-14` | n/a | codebase | han-planning and han-coding each depend only on han-communication and han-core | codebase anchor | @@ -226,5 +403,41 @@ on `han-communication` and `han-core` (A27), so nothing new is needed on the dep | A30 | Earlier config extensibility research | `docs/research/han-config-extensibility.md:65-71` | n/a | codebase | A plugin cannot ship project config: plugin-root CLAUDE.md is not loaded and `userConfig` is user-scope only | single source (caveated) in that report | | A31 | Namespace-qualified dispatch investigation | `docs/plans/namespace-qualified-agent-dispatch/investigation.md:25-26,62-70` | n/a | codebase | `dependencies` is install-only; bare agent names can collide across installed plugins | corroborated by A2 | | A32 | Installed-skill detection prose | `han-planning/skills/plan-work-items/references/deliverable-skill-catalog.md:64` | n/a | codebase | A han-planning skill already checks a skill is installed and falls back to a best fit, in prose | codebase anchor | -| A33 | Absence of reference checks | `test/`, `han-planning/skills/*/scripts/check-*.sh` | n/a | codebase | No test checks that a dispatched agent exists or that config-rule copies match | codebase negative result | -| A34 | This session's available-agent listing | provided: Agent tool roster in the research session, 2026-10-15 | n/a | provided | The model's agent list shows plugin agents from six plugins as `plugin:agent` with descriptions | corroborated by A7 | +| A33 | Absence of reference checks | `test/`, `han-planning/skills/*/scripts/check-*.sh` | n/a | codebase | No check found in `test/` or the planning scripts that a dispatched agent exists or that config-rule copies match | codebase negative result, bounded search | +| A34 | This session's available-agent listing | provided: Agent tool roster in the research session, 2026-10-15 | n/a | provided | The model's agent list shows plugin agents from six plugins as `plugin:agent` with descriptions | consistent with A7; direct observation of one session | +| A35 | Absence of hooks in Han plugins | `*/.claude-plugin/plugin.json`, plugin directories | n/a | codebase | No Han plugin ships a hooks directory or a `hooks` manifest key | codebase negative result | +| A36 | test-engineer references outside the dispatch rosters | `han-core/agents/plan-synthesizer.md:153`, `han-core/agents/junior-developer.md:241`, `han-planning/agents/discussion-facilitator.md:143`, `evals/test-engineer/tests.json` | n/a | codebase | Two han-core agents and one han-planning agent route test planning to `test-engineer` by name; the evals name `han-core:test-engineer` 13 times | codebase anchor | +| A37 | Han YAGNI rule | `han-core/references/yagni-rule.md:24-46` | n/a | codebase | Gate 1 needs evidence an item is needed now; Gate 2 prefers the strictly simpler version that meets it | codebase anchor | +| A38 | Han config file schema | `han-core/references/config-rule.md:49-76` | n/a | codebase | Config files are markdown: frontmatter for scalar settings, named sections such as `## Extra Agents` for lists | codebase anchor | +| A39 | han-coding automated-test-planning focused mode | `han-coding/skills/automated-test-planning/SKILL.md:124` | n/a | codebase | The skill's focused mode dispatches `test-engineer` alone | codebase anchor | + +### A7: Claude Code subagents reference — recommendation-bearing + +- **Link / location:** https://code.claude.com/docs/en/sub-agents +- **Retrieved:** 2026-10-15 +- **Trust class:** web (outside the trust boundary) +- **Summary:** Plugin agents register under a `plugin:agent` name. Claude Code decides when to delegate to an agent from + its `description`, so every available agent's description is loaded into the model's context, and the combined + descriptions count against a context budget that warns at about 15,000 tokens. The page does not document what the + Agent tool returns when asked for an agent name that does not exist. +- **Evidence status:** consistent with A34 + +### A15: Python packaging entry points specification — recommendation-bearing + +- **Link / location:** https://packaging.python.org/en/latest/specifications/entry-points/ +- **Retrieved:** 2026-10-15 +- **Trust class:** web (outside the trust boundary) +- **Summary:** An entry-point group names a kind of object that installed packages can provide. The consuming project + typically defines the group's interface, and a new group should be prefixed with a project name the author controls + to avoid clashes. This is the clearest statement of the slot-and-filler pattern the recommendation follows. +- **Evidence status:** corroborated by A13, A16, A17 + +### A23: Han config rule, extra agents and degradation — recommendation-bearing + +- **Link / location:** `han-core/references/config-rule.md:111-134` +- **Retrieved:** n/a +- **Trust class:** codebase (trusted current-state anchor) +- **Summary:** Extra agents named in `.han/config.md` join a skill's candidate pool and compete under its own selection + rules and size caps. An entry that does not resolve to a dispatchable agent is skipped with a one-line note, and a bad + config never fails a run. A contributed agent can follow the same rules unchanged. +- **Evidence status:** codebase anchor From 1de07d00a5b67d176d1bfcc32e2cfbc66240a509 Mon Sep 17 00:00:00 2001 From: River Bailey Date: Thu, 15 Oct 2026 13:32:36 -0600 Subject: [PATCH 3/9] docs(research): readability pass on cross-plugin config report --- docs/research/cross-plugin-config-discovery.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/research/cross-plugin-config-discovery.md b/docs/research/cross-plugin-config-discovery.md index e23bbb23..498e4ed9 100644 --- a/docs/research/cross-plugin-config-discovery.md +++ b/docs/research/cross-plugin-config-discovery.md @@ -57,7 +57,7 @@ against that slot. - Java ServiceLoader: the service owner defines the interface (A18). - OSGi whiteboard: providers register themselves, and the consumer looks them all up [single-source] (A22). -The surveyed systems do not have a provider list the consumer's internal features. This is a bounded survey of about +None of the surveyed systems has a provider list the consumer's internal features. This is a bounded survey of about ten systems, not proof that none does. The nearest cases, VS Code `contributes` and IntelliJ optional ``, have the provider name a host-defined slot or id (A14, A19). Applied to your example, "`test-engineer` is usable by `plan-a-feature` and `plan-implementation`" names consumer skills. "`test-engineer` fills `han-planning`'s @@ -220,13 +220,15 @@ A registry file in `han-core` that each provider edits is not listed. It puts `h - **Recommendation:** Adopt O5 for `test-engineer`. Name roles, not agents, in `han-planning`'s team lists, and have the moved agent's description claim its role. A planning skill uses an available agent that claims the role and otherwise - skips it with Han's existing one-line note. Add a test that every role an agent description claims appears in some - consumer team list. Amend the agent-placement rule and decision D1, and update the `han-core` agents, the evals, and - the docs that name `test-engineer`. Hold O1 until a plugin needs to contribute something other than an agent. At - that point, first run one live check: install `han-coding` with a SessionStart hook from a local marketplace and - confirm a `han-planning` skill and its subagents see the printed text after a compaction. If you would rather keep - descriptions free of planning concepts, O4 is the plainer fallback, at the cost of the mapping living in - `han-planning`. + skips it with Han's existing one-line note. + - Add a test that every role an agent description claims appears in some consumer team list. + - Amend the agent-placement rule and decision D1, and update the `han-core` agents, the evals, and the docs that name + `test-engineer`. + - Hold O1 until a plugin needs to contribute something other than an agent. At that point, first run one live check: + install `han-coding` with a SessionStart hook from a local marketplace and confirm a `han-planning` skill and its + subagents see the printed text after a compaction. + - If you would rather keep descriptions free of planning concepts, O4 is the plainer fallback, at the cost of the + mapping living in `han-planning`. - **Evidence basis:** - Corroborated: the consumer owns the slot and the handling of absence (A13, A15, A16, A18, A20, A21); Claude Code has no optional or contributes field, and dependencies are hard (A1, A2); the model sees each plugin agent's name From 1ea9d0cef89b6bf319928aa590c85f9e925e8630 Mon Sep 17 00:00:00 2001 From: River Bailey Date: Thu, 15 Oct 2026 13:48:21 -0600 Subject: [PATCH 4/9] spike: move test-engineer agent from han-core into han-coding --- evals/test-engineer/tests.json | 26 +++++++++---------- .../agents/test-engineer.md | 2 +- .../docs/agents/test-engineer.md | 2 +- .../skills/automated-test-planning/SKILL.md | 8 +++--- han-coding/skills/code-review/SKILL.md | 2 +- .../code-review/references/agent-dispatch.md | 6 ++--- .../references/output-verification.md | 2 +- .../code-review/references/types/testing.md | 2 +- .../references/types/work-ticket.md | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) rename {han-core => han-coding}/agents/test-engineer.md (99%) rename {han-core => han-coding}/docs/agents/test-engineer.md (99%) diff --git a/evals/test-engineer/tests.json b/evals/test-engineer/tests.json index cff13cfc..d7043424 100644 --- a/evals/test-engineer/tests.json +++ b/evals/test-engineer/tests.json @@ -4,7 +4,7 @@ { "name": "Agent Call: plan tests for auth module", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-plan-tests-for-auth-module.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -12,7 +12,7 @@ { "name": "Agent Call: find untested behaviors in user service", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-find-untested-behaviors.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -20,7 +20,7 @@ { "name": "Agent Call: identify test coverage gaps in handlers", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-test-coverage-gaps.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -28,7 +28,7 @@ { "name": "Agent Call: prioritize test cases by risk", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-prioritize-test-cases.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -36,7 +36,7 @@ { "name": "Agent Call: behavioral test plan for API endpoints", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-behavioral-test-plan.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -44,7 +44,7 @@ { "name": "Agent Call: negative — sports test results", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-negative-sports-test.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -52,7 +52,7 @@ { "name": "Agent Call: negative — sprint planning", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-negative-engineering-plan.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -60,7 +60,7 @@ { "name": "Agent Call: negative — behavioral psychology", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-negative-behavior-psychology.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -68,7 +68,7 @@ { "name": "Agent Call: sibling — edge case exploration", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-sibling-edge-cases.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -76,7 +76,7 @@ { "name": "Agent Call: sibling — code review", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-sibling-code-review.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -84,7 +84,7 @@ { "name": "Agent Call: sibling — investigate production bug", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-sibling-investigate-bug.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -92,7 +92,7 @@ { "name": "Agent Call: sibling — architectural analysis", "type": "agent-call", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-call-sibling-architecture.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -100,7 +100,7 @@ { "name": "Agent Prompt: test plan for go-security-project", "type": "agent-prompt", - "agentFile": "han-core:test-engineer", + "agentFile": "han-coding:test-engineer", "promptFile": "agent-prompt-go-security-test-plan.md", "scaffold": "go-security-project", "model": "opus", diff --git a/han-core/agents/test-engineer.md b/han-coding/agents/test-engineer.md similarity index 99% rename from han-core/agents/test-engineer.md rename to han-coding/agents/test-engineer.md index 746f7da1..4621ddd0 100644 --- a/han-core/agents/test-engineer.md +++ b/han-coding/agents/test-engineer.md @@ -6,7 +6,7 @@ description: expectations for commands) for isolation, and produces a prioritized test plan with recommended test levels. Use when thorough, multi-angle test planning is needed for new or existing code. Does not write test code — produces a plan only. Does not do deep edge case exploration or boundary analysis — use edge-case-explorer for exhaustive boundary - value and failure mode discovery." + value and failure mode discovery. Fills the han-planning `test-planning` role." tools: Read, Glob, Grep, Bash(git *), Bash(find *), Write model: sonnet --- diff --git a/han-core/docs/agents/test-engineer.md b/han-coding/docs/agents/test-engineer.md similarity index 99% rename from han-core/docs/agents/test-engineer.md rename to han-coding/docs/agents/test-engineer.md index a2ac4339..6423f41e 100644 --- a/han-core/docs/agents/test-engineer.md +++ b/han-coding/docs/agents/test-engineer.md @@ -62,7 +62,7 @@ to dispatch the agent. For what the agent does internally, read the agent defini ## How to invoke it -Dispatch via the `Agent` tool with `subagent_type: han-core:test-engineer`. Give it: +Dispatch via the `Agent` tool with `subagent_type: han-coding:test-engineer`. Give it: 1. **A focus area.** Files, a directory, or a feature description. The narrower the scope, the sharper the plan. 2. **Project context, optional.** If the project's test framework and conventions are not obvious from the existing diff --git a/han-coding/skills/automated-test-planning/SKILL.md b/han-coding/skills/automated-test-planning/SKILL.md index b9b4062d..628cfd32 100644 --- a/han-coding/skills/automated-test-planning/SKILL.md +++ b/han-coding/skills/automated-test-planning/SKILL.md @@ -121,7 +121,7 @@ State the chosen band and mode in one line with the justification before dispatc `Medium: from the project .han/config.md default-swarm-size`, naming whichever file supplied it). Accept the user's override of the band, the mode, or both. -In **focused mode**, dispatch only `han-core:test-engineer` in Step 2, skip the conditional specialists, answer in prose +In **focused mode**, dispatch only `han-coding:test-engineer` in Step 2, skip the conditional specialists, answer in prose per Step 4's focused-mode rules, and skip the two reviewers in Step 5. **Step 3 runs in full either way.** Its behavioral, prerequisite, and YAGNI sweeps decide what may be recommended at all, so skipping them would let a focused answer recommend a test that cannot be written without an out-of-scope production change. In **full mode**, run every @@ -139,7 +139,7 @@ other than `none provided`, include it in every agent prompt so they can focus t ### Always dispatch -1. **Launch han-core:test-engineer agent** — prompt: "Analyze test coverage for the following files{on branch {branch} +1. **Launch han-coding:test-engineer agent** — prompt: "Analyze test coverage for the following files{on branch {branch} if applicable}: {file list}. Recommend tests only at the public API: the inputs a real caller supplies, the outputs and side effects they observe, and the interactions the unit has with the objects and services it collaborates with. Do not recommend tests that reach into private methods, internal state, or implementation structure — if two @@ -189,7 +189,7 @@ Wait for every dispatched agent to complete and collect full output for processi Combine findings from every dispatched agent into a unified, prioritized test plan: 1. **Classify findings** — - - **han-core:test-engineer items** (T1, T2, ...): map High to CRIT or HIGH depending on the code path (security, data + - **han-coding:test-engineer items** (T1, T2, ...): map High to CRIT or HIGH depending on the code path (security, data integrity, auth = CRIT; business logic, error handling = HIGH), Medium to MED, Low to LOW. - **han-core:edge-case-explorer items** (EC1, EC2, ...): map directly — Critical to CRIT, High to HIGH, Medium to MED, Low to LOW. @@ -278,7 +278,7 @@ Lead with behavior. These rules make the plan a human-readable overview first an 4. **Technical Reference → Test Plan** — All items from Step 3, grouped by priority tier. Every test plan item should include file:line references from the agent output, and preserve agent detail — carry through the test approach, code paths, and risk assessments into the merged output. -5. **Technical Reference → Deferred Tests** — Items the han-core:test-engineer excluded due to brittleness risk. +5. **Technical Reference → Deferred Tests** — Items the han-coding:test-engineer excluded due to brittleness risk. 6. **Technical Reference → Dropped Edge Cases** — Items the han-core:edge-case-explorer intentionally excluded. 7. **Technical Reference → Blocked by a Production Change** — Items the prerequisite sweep moved out of the priority tiers, each with the production change it would need, the file that would carry it, and that file's other consumers. diff --git a/han-coding/skills/code-review/SKILL.md b/han-coding/skills/code-review/SKILL.md index 657ed312..292bf216 100644 --- a/han-coding/skills/code-review/SKILL.md +++ b/han-coding/skills/code-review/SKILL.md @@ -606,7 +606,7 @@ escalate to those bands. Continue task ID numbering sequentially from Steps 4-6 ### Deferred tests -If the han-core:test-engineer produced Deferred/Skipped items, include them as a note after the testing findings (not +If the han-coding:test-engineer produced Deferred/Skipped items, include them as a note after the testing findings (not counted toward the cap): > **Deferred tests:** The following test cases were considered but excluded because brittleness risk outweighs value: diff --git a/han-coding/skills/code-review/references/agent-dispatch.md b/han-coding/skills/code-review/references/agent-dispatch.md index 82ab2391..b1500f55 100644 --- a/han-coding/skills/code-review/references/agent-dispatch.md +++ b/han-coding/skills/code-review/references/agent-dispatch.md @@ -28,7 +28,7 @@ team's own agent outside Han. Its series carries the agent's name, so two such a | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ---------------------------------------- | | `han-core:junior-developer` | any change (generalist) | full file list (generalist) | junior-developer-review.md | JD | | `han-core:adversarial-security-analyst` | any change | full file list plus dependency manifests | security-analysis.md | SEC | -| `han-core:test-engineer` | source files with logic or behavior were added or modified (skip for docs-only or pure config changes) | source files plus their related test files | test-plan.md | T | +| `han-coding:test-engineer` | source files with logic or behavior were added or modified (skip for docs-only or pure config changes) | source files plus their related test files | test-plan.md | T | | `han-core:edge-case-explorer` | code processes inputs with boundaries, parses external data, or handles multiple states (skip for trivial edits, renames, or docs-only changes) | source files containing logic or input handling | edge-case-analysis.md | EC | | `han-core:structural-analyst` | the change introduces new files, new modules, or modifies dependency direction across modules (skip for single-file in-place edits) | source files only (skip configs, schemas, docs) | structural-analysis.md | S | | `han-core:behavioral-analyst` | the change modifies runtime data flow across module boundaries, error propagation paths, or state management (skip for self-contained changes within a single function or class) | source files containing runtime logic | behavioral-analysis.md | B | @@ -170,7 +170,7 @@ from earlier steps; `{the change}` names the change the way Step 1 resolved it: (`git diff {default-branch}...HEAD`) on branch {branch} in Mode A, the uncommitted diff in Mode B, and the listed files read in full in Mode C): -1. `han-core:test-engineer` — "Analyze test coverage for the following files{if branch available: ' on branch +1. `han-coding:test-engineer` — "Analyze test coverage for the following files{if branch available: ' on branch {branch}'}: {file list}. Focus your analysis on these files and their related test files." 2. `han-core:edge-case-explorer` — "Explore edge cases for the following files{if branch available: ' on branch @@ -319,7 +319,7 @@ visible rather than implied: - `han-core:junior-developer` → Code Maintainability, Documentation, Code Style & Patterns, Architecture Decision Records. - `han-core:adversarial-security-analyst` → Data Isolation, Error Handling, API Design. Partial: nothing substitutes for an exploit path demonstrated against the code. -- `han-core:test-engineer` → Testing, Correctness. +- `han-coding:test-engineer` → Testing, Correctness. - `han-core:edge-case-explorer` → Correctness, Error Handling. Partial: the checklist asks whether edge cases are handled, not which ones exist. - `han-core:structural-analyst` → Code Organization, Code Maintainability. - `han-core:behavioral-analyst` → Error Handling, Correctness. diff --git a/han-coding/skills/code-review/references/output-verification.md b/han-coding/skills/code-review/references/output-verification.md index 26197f6f..3a1c74cf 100644 --- a/han-coding/skills/code-review/references/output-verification.md +++ b/han-coding/skills/code-review/references/output-verification.md @@ -41,7 +41,7 @@ Then verify: selected) have valid task IDs continuing from manual review IDs. Findings from agents that were not dispatched in Step 3 must not appear. 3. Agent findings have valid `file_path:line_number` references -4. Deferred tests note is present if the han-core:test-engineer produced skipped items +4. Deferred tests note is present if the han-coding:test-engineer produced skipped items 5. The Review Summary table includes every corrective finding (CRIT/WARN/SUGG) and every security finding, and matches the sections that are present. YAGNI findings are excluded from the table (see rule 12). For findings whose block omits the category, the table is the only place that category appears. Every CRIT/WARN/SUGG row carries its fix route diff --git a/han-coding/skills/code-review/references/types/testing.md b/han-coding/skills/code-review/references/types/testing.md index 0a1f0b55..b8e5612c 100644 --- a/han-coding/skills/code-review/references/types/testing.md +++ b/han-coding/skills/code-review/references/types/testing.md @@ -6,7 +6,7 @@ Check the test coverage and edge cases of the change. ## Roster -- Always: han-core:test-engineer, han-core:edge-case-explorer +- Always: han-coding:test-engineer, han-core:edge-case-explorer - When relevant: none ## Checklist categories diff --git a/han-coding/skills/code-review/references/types/work-ticket.md b/han-coding/skills/code-review/references/types/work-ticket.md index 02e6561e..c9490662 100644 --- a/han-coding/skills/code-review/references/types/work-ticket.md +++ b/han-coding/skills/code-review/references/types/work-ticket.md @@ -7,7 +7,7 @@ Verify that the change on this branch resolves the named work ticket. ## Roster - Always: han-core:gap-analyzer -- When relevant: han-core:test-engineer +- When relevant: han-coding:test-engineer ## Checklist categories From 24e3ccdbfb3d57640511a7f1429b22954f3ee975 Mon Sep 17 00:00:00 2001 From: River Bailey Date: Thu, 15 Oct 2026 13:48:52 -0600 Subject: [PATCH 5/9] spike: han-planning fills a test-planning role instead of naming test-engineer --- han-planning/references/agent-roles.md | 60 +++++++++++++++++++ .../skills/iterative-plan-review/SKILL.md | 2 +- .../references/team-selection.md | 5 +- .../references/team-selection.md | 7 ++- .../references/review-team-briefs.md | 4 +- .../references/team-selection.md | 5 +- 6 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 han-planning/references/agent-roles.md diff --git a/han-planning/references/agent-roles.md b/han-planning/references/agent-roles.md new file mode 100644 index 00000000..a78a3e71 --- /dev/null +++ b/han-planning/references/agent-roles.md @@ -0,0 +1,60 @@ +# Agent Roles (Slots Another Plugin's Agent Can Fill) + +## Contents + +- What a role is +- How an agent claims a role +- How a skill fills a role +- The roles +- Related rules + +**Owned by `han-planning`.** This file is authored here and is not a vendored copy of a shared rule. Do not overwrite it +from another plugin's `references/` folder during a re-sync sweep, and do not treat a difference between it and any +similarly-named file elsewhere as drift to correct. + +## What a role is + +A role is a named slot on a `han-planning` team list that an agent from another plugin can fill. It lets a planning skill +use a specialist without `han-planning` depending on the plugin that ships it. When that plugin is installed, its agent +fills the role. When it is not, the role stays empty and the skill runs without it. + +`han-planning` owns the role names and what each one is for. A plugin that ships an agent says which role the agent +fills. The providing plugin never names `han-planning`'s skills, so renaming or adding a planning skill never breaks it. + +## How an agent claims a role + +An agent claims a role with one sentence at the end of its frontmatter `description`, in this exact form: + +```markdown +Fills the han-planning `test-planning` role. +``` + +The description is the claim because Claude Code loads every installed agent's description into the session. A skill +reading its team list can see which agents are available and which roles they claim, with no extra lookup. The role name +is in backticks and matches a heading under "The roles" below exactly. A test checks that every claimed role exists here. + +## How a skill fills a role + +When a team list names a role and the skill selects it, fill it this way: + +1. Look through the agents available in this session for any whose description claims the role. +2. If one agent claims it, dispatch that agent by its qualified `plugin:agent` name, exactly as the session lists it. +3. If more than one claims it, dispatch the one whose description best fits the selection reason. It is one candidate, + counted once against the team's size cap. +4. If none claims it, skip the role and add one line to the team announcement, for example: "Skipped the + `test-planning` role: no installed agent fills it." This is not an error, and the run continues. + +Never dispatch an agent for a role by guessing its name. Use only a name the session lists. + +## The roles + +### `test-planning` + +Plans tests around observable behavior: inputs, outputs, and collaborator interactions, with the test doubles that +isolate them. Select it when a plan or spec commits to behavior that has to be verified, or when a change must preserve +behavior that existing tests pin. Today `han-coding` ships the agent that fills it. + +## Related rules + +- [`config-rule.md`](./config-rule.md): extra agents a project names join the same pool and use the same skip-with-a-note + handling. diff --git a/han-planning/skills/iterative-plan-review/SKILL.md b/han-planning/skills/iterative-plan-review/SKILL.md index 1032ed07..882aca34 100644 --- a/han-planning/skills/iterative-plan-review/SKILL.md +++ b/han-planning/skills/iterative-plan-review/SKILL.md @@ -272,7 +272,7 @@ loop earlier whenever a round goes quiet, so the cap is a ceiling rather than a | `han-core:concurrency-analyst` | Sections touching concurrent access, race conditions, async coordination | | `han-core:software-architect` / `han-core:system-architect` | Architecture / topology / context-map sections | | `han-core:risk-analyst` | Architectural and delivery risks; depends on upstream specialist findings | - | `han-core:test-engineer` / `han-core:edge-case-explorer` | Sections describing observable behavior, boundary cases, failure modes | + | `test-planning` role / `han-core:edge-case-explorer` | Sections describing observable behavior, boundary cases, failure modes | | `han-core:data-engineer` | Sections touching schema, migration, data movement, analytics | | `han-core:gap-analyzer` | Source PRD/spec + the plan under review | | `han-core:content-auditor` | Documentation sections being updated | diff --git a/han-planning/skills/iterative-plan-review/references/team-selection.md b/han-planning/skills/iterative-plan-review/references/team-selection.md index 8a15642c..493402d5 100644 --- a/han-planning/skills/iterative-plan-review/references/team-selection.md +++ b/han-planning/skills/iterative-plan-review/references/team-selection.md @@ -52,7 +52,8 @@ review. Draw from: - `han-core:system-architect` — cross-service / bounded-context topology, context-map relationships, integration patterns, data ownership, failure-domain containment. - `han-core:risk-analyst` — prioritization of architectural and delivery risks. -- `han-core:test-engineer` — observable-behavior test planning, test doubles. +- The [`test-planning` role](../../../references/agent-roles.md) — observable-behavior test planning, test doubles. Filled by whichever installed agent + claims it; skipped with a one-line note when none does. - `han-core:edge-case-explorer` — boundary values, input messiness, state-dependent failures. - `han-core:data-engineer` — schema changes, migrations, data movement, analytics implications. - `han-core:gap-analyzer` — spec-vs-implementation gap checks when a source spec exists. @@ -90,7 +91,7 @@ review. Draw from: `han-core:adversarial-security-analyst`, `han-core:devops-engineer`, `han-core:on-call-engineer` (scoped to spec-level resilience commitments — idempotency, retry behavior, kill switches, graceful degradation — not file-and-line mechanics), `han-core:observability-engineer` (scoped to the telemetry the spec commits to — which signals a flow - emits and what they must let someone answer — not instrument or pipeline mechanics), `han-core:edge-case-explorer`, `han-core:test-engineer`, `han-core:gap-analyzer`, `han-core:risk-analyst` + emits and what they must let someone answer — not instrument or pipeline mechanics), `han-core:edge-case-explorer`, the `test-planning` role, `han-core:gap-analyzer`, `han-core:risk-analyst` (no structural/behavioral/concurrency upstream dependency), `han-core:content-auditor`, `han-core:codebase-explorer`. Present the proposed team to the user briefly — the required agents (and whether `han-core:evidence-based-investigator` diff --git a/han-planning/skills/plan-a-change/references/team-selection.md b/han-planning/skills/plan-a-change/references/team-selection.md index df86ddd7..98e3a661 100644 --- a/han-planning/skills/plan-a-change/references/team-selection.md +++ b/han-planning/skills/plan-a-change/references/team-selection.md @@ -50,8 +50,9 @@ Select additional specialists up to the cap, based on what the area actually con - `han-core:risk-analyst` — prioritization across the findings the discovery round and the review produced. The most common first pick, because a change plan's failure mode is carrying every finding at equal weight. -- `han-core:test-engineer` — how the change is verified, and which existing tests pin behavior the delta must preserve. - Include whenever a behavior-preservation claim needs something to rest on. +- The [`test-planning` role](../../../references/agent-roles.md) — how the change is verified, and which existing tests pin behavior the delta must + preserve. Include whenever a behavior-preservation claim needs something to rest on. Filled by whichever installed + agent claims it; skipped with a one-line note when none does. - `han-core:on-call-engineer` — code-level resilience the change moves or removes: timeouts, retries, idempotency, queue handling, kill switches, and the failure paths a responsibility shift can quietly relocate. - `han-core:adversarial-security-analyst` — the area handles authentication, authorization, PII, secrets, or untrusted @@ -83,7 +84,7 @@ Pass each specialist only what its domain needs, plus the pointers below. Do not | Specialist | Plan sections to include in the brief | | --------------------------------------- | --------------------------------------------------------------------------------- | | `han-core:risk-analyst` | Target State, the full delta with behavior classifications, Change Units | -| `han-core:test-engineer` | Current State, the delta entries classified Preserving, Change Units | +| `test-planning` role | Current State, the delta entries classified Preserving, Change Units | | `han-core:on-call-engineer` | Delta entries touching error paths, retries, timeouts, queues, or lifecycle order | | `han-core:adversarial-security-analyst` | Delta entries moving a trust boundary, plus Current State on those paths | | `han-core:data-engineer` | Delta entries touching a schema, persisted format, or data-access path | diff --git a/han-planning/skills/plan-a-feature/references/review-team-briefs.md b/han-planning/skills/plan-a-feature/references/review-team-briefs.md index a5d27e60..454f51f2 100644 --- a/han-planning/skills/plan-a-feature/references/review-team-briefs.md +++ b/han-planning/skills/plan-a-feature/references/review-team-briefs.md @@ -23,7 +23,7 @@ Select the remaining specialists by matching domain to feature, under the size c | `han-core:on-call-engineer` | Resilience commitments the spec must make: idempotency on retried operations, timeout and deadline behavior, graceful degradation when a dependency is down, kill switches, named failure-mode coverage. Spec level only. | | `han-core:observability-engineer` | Telemetry design the spec commits to: metric instruments or labels, span attributes, log schemas, OpenTelemetry SDK setup (samplers, exporters, resource attributes), telemetry pipeline configuration, or telemetry volume and cost. Spec level only. SLO definitions, alert rules, and dashboards stay with `han-core:devops-engineer`; source-line debuggability, correlation-ID propagation, and PII in individual log statements stay with `han-core:on-call-engineer`. Brief it not to recommend tail sampling, a Collector tier, or retention tiers for volume the project does not have. | | `han-core:edge-case-explorer` | Boundary values, input messiness, or state-dependent failures. | -| `han-core:test-engineer` | What observable behaviors the spec commits to making testable. Test-double and collaborator-boundary framing is deferred to `plan-implementation`. | +| `test-planning` role | What observable behaviors the spec commits to making testable. Test-double and collaborator-boundary framing is deferred to `plan-implementation`. Fill it per [`agent-roles.md`](../../../references/agent-roles.md); skip it with a one-line note when no installed agent claims it. | | `han-core:gap-analyzer` | A PRD or reference spec exists to compare the draft against. | | `han-core:risk-analyst` | Significant blast radius, where risks need prioritizing. | @@ -57,7 +57,7 @@ set. | `han-core:on-call-engineer` | Outcome, Primary Flow, Alternate Flows, Edge Cases, Coordinations (sections touching idempotency, retries, timeouts, kill switches, graceful degradation) | | `han-core:observability-engineer` | Outcome, Primary Flow, Coordinations, Open Items (sections touching which signals a flow emits, telemetry volume or cost, or a telemetry pipeline) | | `han-core:edge-case-explorer` | Outcome, Primary Flow, Alternate Flows, Edge Cases | -| `han-core:test-engineer` | Outcome, Primary Flow, Alternate Flows, Edge Cases | +| `test-planning` role | Outcome, Primary Flow, Alternate Flows, Edge Cases | | `han-core:gap-analyzer` | Source PRD or reference spec, plus the draft spec under review | | `han-core:risk-analyst` | Outcome, Coordinations, Edge Cases (risk-relevant rows only) | | `han-core:junior-developer` | Outcome, plus the first paragraph of every section | diff --git a/han-planning/skills/plan-implementation/references/team-selection.md b/han-planning/skills/plan-implementation/references/team-selection.md index 870998f8..c3f3f322 100644 --- a/han-planning/skills/plan-implementation/references/team-selection.md +++ b/han-planning/skills/plan-implementation/references/team-selection.md @@ -71,7 +71,8 @@ specialist rather than discovering a gap late. Unless the user specified a team the feature crosses a service boundary, introduces a new integration, changes a context-map relationship, or shifts data ownership. Include both when the feature does both. - `han-core:risk-analyst` — prioritization of architectural and delivery risks. -- `han-core:test-engineer` — observable-behavior test planning and test doubles. +- The [`test-planning` role](../../../references/agent-roles.md) — observable-behavior test planning and test doubles. Filled by whichever installed agent claims it; skipped + with a one-line note when none does. - `han-core:edge-case-explorer` — boundary values, input messiness, state-dependent failures. - `han-core:data-engineer` — schema changes, migrations, data movement, analytics implications. @@ -100,7 +101,7 @@ Pass each selected specialist only the sections relevant to its domain, plus the | `han-core:concurrency-analyst` | Sections touching concurrent access, race conditions, async coordination | | `han-core:software-architect` / `han-core:system-architect` | Architecture / topology / context-map sections | | `han-core:risk-analyst` | Architectural and delivery risks; depends on upstream specialist findings | -| `han-core:test-engineer` / `han-core:edge-case-explorer` | Outcome, Primary Flow, Alternate Flows, Edge Cases | +| `test-planning` role / `han-core:edge-case-explorer` | Outcome, Primary Flow, Alternate Flows, Edge Cases | | `han-core:data-engineer` | Sections touching schema, migration, data movement, analytics | | `han-core:junior-developer` | Outcome + first paragraph of every section (plain-language overview) | From abdb80a8193a34e8e3299192d5f9022ba9fbca77 Mon Sep 17 00:00:00 2001 From: River Bailey Date: Thu, 15 Oct 2026 13:49:57 -0600 Subject: [PATCH 6/9] spike: test that agent role claims match han-planning's role list --- test/agent-roles.bats | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 test/agent-roles.bats diff --git a/test/agent-roles.bats b/test/agent-roles.bats new file mode 100644 index 00000000..d65d3688 --- /dev/null +++ b/test/agent-roles.bats @@ -0,0 +1,56 @@ +#!/usr/bin/env bats +# +# Guards the agent-role contract in han-planning/references/agent-roles.md. +# An agent in any plugin claims a han-planning role with one sentence in its +# description, and a planning skill fills the role from whichever installed +# agent claims it. Nothing at runtime notices a claim for a role that does not +# exist: the agent is never selected, and the role is skipped as if the plugin +# were not installed. These checks catch that drift in the repo instead. +# +# Portability: keep to bash 3.2, and grep one named file at a time, never -r +# (see test/codex-packaging.bats for why). + +REPO_ROOT="${BATS_TEST_DIRNAME}/.." +ROLES='han-planning/references/agent-roles.md' + +# Every role defined in the roles file, one per line. +defined_roles() { + cd "$REPO_ROOT" || return 1 + sed -n 's/^### `\([a-z0-9-]*\)`$/\1/p' "$ROLES" +} + +# Every "file role" pair claimed by an agent description, one per line. +claimed_roles() { + cd "$REPO_ROOT" || return 1 + for f in han-*/agents/*.md; do + sed -n 's/.*Fills the han-planning `\([a-z0-9-]*\)` role\..*/\1/p' "$f" | + while read -r role; do printf '%s %s\n' "$f" "$role"; done + done +} + +@test "the roles file defines at least one role" { + run defined_roles + [ "$status" -eq 0 ] + [ -n "$output" ] +} + +@test "every role an agent claims is defined in the roles file" { + roles="$(defined_roles)" + missing='' + while read -r file role; do + [ -z "$file" ] && continue + printf '%s\n' "$roles" | grep -qx "$role" || missing="${missing}${file} claims undefined role '${role}'"$'\n' + done < Date: Thu, 15 Oct 2026 13:51:20 -0600 Subject: [PATCH 7/9] spike: update docs, indexes, and routing text for the moved test-engineer --- CLAUDE.md | 22 ++++++++++++------- CONTRIBUTING.md | 5 ++++- docs/agents/README.md | 2 +- han-coding/README.md | 8 ++++++- han-coding/docs/agents/test-engineer.md | 6 +++-- .../code-review/references/agent-dispatch.md | 2 +- han-core/README.md | 2 -- han-core/agents/junior-developer.md | 2 +- han-core/agents/plan-synthesizer.md | 2 +- han-core/docs/agents/edge-case-explorer.md | 2 +- han-planning/agents/discussion-facilitator.md | 2 +- 11 files changed, 35 insertions(+), 20 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 92fc49c0..97cf43ca 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ surfaces the first two, the inline `explanation-guidance` skill that surfaces th the `readability-editor` agent, and the `han-readability` and `han-concise` output styles that apply the first two to every turn of a session; it depends on nothing and every prose-producing plugin depends on it), `han-core` (the shared foundation: the specialist agent roster the rest of the suite dispatches — every shared agent except the `readability-editor`, the -`research-analyst`, and the `discussion-facilitator` — plus the `project-discovery` skill, the `pairing` collaborative working mode, and the canonical rule files; depends on no other Han plugin), +`research-analyst`, the `discussion-facilitator`, and the `test-engineer` — plus the `project-discovery` skill, the `pairing` collaborative working mode, and the canonical rule files; depends on no other Han plugin), `han-documentation` (the documentation skills: `project-documentation`, `architectural-decision-record`, and `runbook`; depends on `han-communication` and `han-core` and is bundled by the `han` meta-plugin), `han-research` (the pre-planning knowledge-work skills — `research`, `gap-analysis`, and `issue-triage` — plus the `research-analyst` @@ -117,13 +117,14 @@ han-plugin-builder skill: │ ├── agents/ # discussion-facilitator agent definition │ ├── skills/ # Planning skill directories, each with SKILL.md + references/ + scripts/ │ ├── docs/ # In-plugin long-form docs: docs/skills/{name}.md + docs/agents/discussion-facilitator.md -│ └── references/ # Both kinds: han-planning-owned canonical files (planning-boundary-rule.md, scope-justification-rule.md, operator-escalation-rule.md, contract-pinning-rule.md, synthesis-failure-rule.md) beside vendored copies (yagni-rule.md, evidence-rule.md, config-rule.md, collaborative-stop-rule.md). Each owned file opens by saying so; do not overwrite one in a re-sync sweep -├── han-coding/ # Coding plugin: tdd, refactor, design-an-api, code-review, code-overview, code-walkthrough, architectural-analysis, automated-test-planning, manual-test-planning, investigate, coding-standard (the skills for working in code; depends on han-communication and han-core; bundled by the han meta-plugin) -│ ├── README.md # Light front door + scent-line skills list +│ └── references/ # Both kinds: han-planning-owned canonical files (planning-boundary-rule.md, scope-justification-rule.md, operator-escalation-rule.md, contract-pinning-rule.md, synthesis-failure-rule.md, agent-roles.md) beside vendored copies (yagni-rule.md, evidence-rule.md, config-rule.md, collaborative-stop-rule.md). Each owned file opens by saying so; do not overwrite one in a re-sync sweep +├── han-coding/ # Coding plugin: tdd, refactor, design-an-api, code-review, code-overview, code-walkthrough, architectural-analysis, automated-test-planning, manual-test-planning, investigate, coding-standard (the skills for working in code) + the test-engineer agent, which fills han-planning's test-planning role (depends on han-communication and han-core; bundled by the han meta-plugin) +│ ├── README.md # Light front door + scent-line skills and agent lists │ ├── .claude-plugin/ │ │ └── plugin.json +│ ├── agents/ # test-engineer agent definition │ ├── skills/ # Coding-facing skill directories, each with SKILL.md + references/ (+ scripts/ where used) -│ ├── docs/ # In-plugin long-form docs: docs/skills/{name}.md +│ ├── docs/ # In-plugin long-form docs: docs/skills/{name}.md + docs/agents/test-engineer.md │ └── references/ # Cross-skill reference files vendored for han-coding skills (yagni-rule.md, evidence-rule.md, config-rule.md, collaborative-stop-rule.md) ├── han-github/ # GitHub plugin: post-code-review-to-pr, update-pr-description, work-items-to-issues (depends on han-communication, han-core, and han-coding, whose code-review skill post-code-review-to-pr wraps) │ ├── README.md # Light front door + scent-line skills list @@ -221,7 +222,7 @@ The same plugin also ships those two interview-driven builder skills, `skill-bui design tree for a new skill or agent decision-by-decision and then review the finished artifact against that guidance. Documentation is plugin-first: each plugin carries a light front-door `README.md` and its own long-form docs. Long-form docs in `{plugin}/docs/skills/{name}.md` and `{plugin}/docs/agents/{name}.md` (agents only in `han-core`, -`han-communication`, `han-research`, `han-planning`, and `han-ddd`) are the canonical operator-facing source for every skill and every agent, +`han-communication`, `han-research`, `han-planning`, `han-coding`, and `han-ddd`) are the canonical operator-facing source for every skill and every agent, sitting beside that plugin's README. The cross-plugin surfaces stay under repo-root `docs/`: the alphabetized skills and agents indexes (`docs/skills/README.md`, `docs/agents/README.md`), the plugin index (`docs/choosing-a-han-plugin.md`), and the workflows composition map (`docs/workflows.md`). The underlying definition @@ -231,7 +232,7 @@ and agents indexes (`docs/skills/README.md`, `docs/agents/README.md`), the plugi `han-reporting/skills/{name}/SKILL.md`, `han-feedback/skills/{name}/SKILL.md`, `han-atlassian/skills/{name}/SKILL.md`, `han-linear/skills/{name}/SKILL.md`, `han-ddd/skills/{name}/SKILL.md`, `han-core/agents/{name}.md`, `han-communication/agents/{name}.md`, `han-research/agents/research-analyst.md`, -`han-planning/agents/discussion-facilitator.md`, or `han-ddd/agents/{name}.md`) is the implementation. +`han-planning/agents/discussion-facilitator.md`, `han-coding/agents/test-engineer.md`, or `han-ddd/agents/{name}.md`) is the implementation. ## When to use which doc @@ -305,6 +306,11 @@ such as Claude, should be referenced here. one, and which stage of the chain owns pinning it. Consumed by `plan-a-feature`, `plan-a-change`, `plan-implementation`, `plan-work-items`, and `iterative-plan-review`. The phrase list is mirrored by `check-contract-pinning.sh`; the rule is canonical, so edit it first. +- **[han-planning/references/agent-roles.md](./han-planning/references/agent-roles.md).** The named roles on + `han-planning` team lists that an agent from another plugin can fill, how an agent claims one in its description, and + how a skill fills a role or skips it when no installed agent claims it. Lets `han-planning` use an agent such as + `han-coding`'s `test-engineer` without depending on that plugin. `test/agent-roles.bats` checks every claim names a + defined role. - **[han-planning/references/synthesis-failure-rule.md](./han-planning/references/synthesis-failure-rule.md).** The check a caller runs after `han-core:plan-synthesizer` returns, to confirm the plan file exists and holds content before any later step reads it, plus the three things the stop says when it does not: what did not happen, what @@ -340,7 +346,7 @@ Every file in this section is owned by `han-planning`, not vendored. Each opens `han-github/skills/`, `han-reporting/skills/`, `han-feedback/skills/`, `han-atlassian/skills/`, `han-linear/skills/`, `han-ddd/skills/`, and `han-plugin-builder/skills/` has a long-form doc in its plugin's `docs/skills/`, a scent line in its plugin's `README.md`, and an entry in the skills index (`docs/skills/README.md`); same for agents in `han-core/agents/`, - `han-communication/agents/`, `han-research/agents/`, `han-planning/agents/`, and `han-ddd/agents/` (long-form docs in + `han-communication/agents/`, `han-research/agents/`, `han-planning/agents/`, `han-coding/agents/`, and `han-ddd/agents/` (long-form docs in `{plugin}/docs/agents/`, indexed in `docs/agents/README.md`). Verify the indexes list every entity when editing them, rather than tracking a running total. An output style in `han-communication/output-styles/` gets a long-form doc in diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc64b956..b70f0a87 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -206,7 +206,10 @@ Long-form docs always live under `docs/` regardless of which plugin the entity s agents live in `han-core` by default; an agent moves out only when a single skill family in one plugin above `han-core` dispatches it exclusively. Today that is the readability-editor, living in `han-communication` with the readability skills it serves; the research-analyst, living in `han-research` with the research skill that - dispatches it; and the discussion-facilitator, living in `han-planning` with `plan-implementation`. See + dispatches it; and the discussion-facilitator, living in `han-planning` with `plan-implementation`. An agent that one + plugin dispatches directly and `han-planning` uses only through a role can also move out: today that is the + test-engineer, living in `han-coding` and filling `han-planning`'s `test-planning` role. See + [agent-roles.md](./han-planning/references/agent-roles.md) for how an agent claims a role. See [agent-domain-focus.md](./han-plugin-builder/skills/guidance/references/agent-building-guidelines/agent-domain-focus.md) for how narrow and named the domain vocabulary should be. 2. Copy [the agent template](./docs/templates/agent-long-form-template.md) into `{plugin}/docs/agents/{name}.md` diff --git a/docs/agents/README.md b/docs/agents/README.md index b8217578..38782e9b 100644 --- a/docs/agents/README.md +++ b/docs/agents/README.md @@ -93,7 +93,7 @@ domain-language-analyst, domain-ownership-analyst, and domain-visualizer, which dependency direction, abstractions, and duplication. - [`system-architect`](../../han-core/docs/agents/system-architect.md) — Synthesize boundary-crossing findings into context-map relationships, integration patterns, data ownership, and failure-domain containment across services. -- [`test-engineer`](../../han-core/docs/agents/test-engineer.md) — Plan tests focused on observable behavior and +- [`test-engineer`](../../han-coding/docs/agents/test-engineer.md) — Plan tests focused on observable behavior and recommend test doubles for isolation, producing a prioritized test plan. - [`user-experience-designer`](../../han-core/docs/agents/user-experience-designer.md) — Review a UI adversarially against Nielsen's heuristics, WCAG 2.2, universal design, and dark-pattern detection. diff --git a/han-coding/README.md b/han-coding/README.md index f2a2f782..35323512 100644 --- a/han-coding/README.md +++ b/han-coding/README.md @@ -30,7 +30,13 @@ it, dispatching specialist agents to cover each dimension in parallel. Reach for - [`/coding-standard`](docs/skills/coding-standard.md) — Create and update coding standards from existing patterns or evidence-based research. -Its skills dispatch shared agents that live in `han-core` (and, for the readability-editor, in `han-communication`). +## Agents + +- [`test-engineer`](docs/agents/test-engineer.md) — Plan tests focused on observable behavior and recommend test + doubles for isolation, producing a prioritized test plan. + +The other agents its skills dispatch are the shared specialists that live in `han-core` (and, for the +readability-editor, in `han-communication`). ## Installation diff --git a/han-coding/docs/agents/test-engineer.md b/han-coding/docs/agents/test-engineer.md index 6423f41e..43695c45 100644 --- a/han-coding/docs/agents/test-engineer.md +++ b/han-coding/docs/agents/test-engineer.md @@ -1,8 +1,10 @@ # test-engineer -Operator documentation for the `test-engineer` agent in the han plugin. This document helps you decide _when_ and _how_ +Operator documentation for the `test-engineer` agent in the `han-coding` plugin. This document helps you decide _when_ and _how_ to dispatch the agent. For what the agent does internally, read the agent definition at -[`han-core/agents/test-engineer.md`](../../agents/test-engineer.md). +[`han-coding/agents/test-engineer.md`](../../agents/test-engineer.md). The agent fills `han-planning`'s +`test-planning` role, so planning skills use it when `han-coding` is installed and skip the role when it is not; see +[`agent-roles.md`](../../../han-planning/references/agent-roles.md). > See also: [Plugin README](../../README.md) · [Repo root](../../../README.md) · [All agents](../../../docs/agents/README.md) · > [All skills](../../../docs/skills/README.md) · [YAGNI](../../../docs/yagni.md) diff --git a/han-coding/skills/code-review/references/agent-dispatch.md b/han-coding/skills/code-review/references/agent-dispatch.md index b1500f55..c8f6a83e 100644 --- a/han-coding/skills/code-review/references/agent-dispatch.md +++ b/han-coding/skills/code-review/references/agent-dispatch.md @@ -28,7 +28,7 @@ team's own agent outside Han. Its series carries the agent's name, so two such a | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ---------------------------------------- | | `han-core:junior-developer` | any change (generalist) | full file list (generalist) | junior-developer-review.md | JD | | `han-core:adversarial-security-analyst` | any change | full file list plus dependency manifests | security-analysis.md | SEC | -| `han-coding:test-engineer` | source files with logic or behavior were added or modified (skip for docs-only or pure config changes) | source files plus their related test files | test-plan.md | T | +| `han-coding:test-engineer` | source files with logic or behavior were added or modified (skip for docs-only or pure config changes) | source files plus their related test files | test-plan.md | T | | `han-core:edge-case-explorer` | code processes inputs with boundaries, parses external data, or handles multiple states (skip for trivial edits, renames, or docs-only changes) | source files containing logic or input handling | edge-case-analysis.md | EC | | `han-core:structural-analyst` | the change introduces new files, new modules, or modifies dependency direction across modules (skip for single-file in-place edits) | source files only (skip configs, schemas, docs) | structural-analysis.md | S | | `han-core:behavioral-analyst` | the change modifies runtime data flow across module boundaries, error propagation paths, or state management (skip for self-contained changes within a single function or class) | source files containing runtime logic | behavioral-analysis.md | B | diff --git a/han-core/README.md b/han-core/README.md index 726e017e..525fc486 100644 --- a/han-core/README.md +++ b/han-core/README.md @@ -83,8 +83,6 @@ Most agents are dispatched for you by skills; you rarely invoke them directly. G ### Testing -- [`test-engineer`](docs/agents/test-engineer.md) — Plan tests focused on observable behavior and recommend test - doubles for isolation, producing a prioritized test plan. - [`edge-case-explorer`](docs/agents/edge-case-explorer.md) — Systematically discover and catalog edge cases: boundary values, type-coercion traps, and state-dependent failures. diff --git a/han-core/agents/junior-developer.md b/han-core/agents/junior-developer.md index c5895041..b3d97d43 100644 --- a/han-core/agents/junior-developer.md +++ b/han-core/agents/junior-developer.md @@ -238,7 +238,7 @@ Domain handoffs: `software-architect` - **Cross-service / bounded-context topology, context-map relationships, integration patterns, data ownership across services, failure-domain containment** → `system-architect` -- **Test planning depth, behavior-focused tests, test doubles** → `test-engineer` +- **Test planning depth, behavior-focused tests, test doubles** → the `test-planning` role (`test-engineer`, when `han-coding` is installed) - **Edge-case discovery for tests** → `edge-case-explorer` - **Bug root-cause investigation** → `evidence-based-investigator` - **Spec / PRD vs implementation gap** → `gap-analyzer` diff --git a/han-core/agents/plan-synthesizer.md b/han-core/agents/plan-synthesizer.md index 4a964432..f09260a1 100644 --- a/han-core/agents/plan-synthesizer.md +++ b/han-core/agents/plan-synthesizer.md @@ -150,7 +150,7 @@ Specialists available on this team: `software-architect` - **Cross-service / bounded-context topology, context-map relationships, integration patterns, data ownership across services, failure-domain containment** → `system-architect` -- **Test planning for observable behavior** → `test-engineer` +- **Test planning for observable behavior** → the `test-planning` role (`test-engineer`, when `han-coding` is installed) - **Edge-case discovery for tests** → `edge-case-explorer` - **Bug root-cause investigation** → `evidence-based-investigator` - **Spec vs. implementation gap** → `gap-analyzer` diff --git a/han-core/docs/agents/edge-case-explorer.md b/han-core/docs/agents/edge-case-explorer.md index cb52c850..2ffb0804 100644 --- a/han-core/docs/agents/edge-case-explorer.md +++ b/han-core/docs/agents/edge-case-explorer.md @@ -165,7 +165,7 @@ https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-de - [Repo root README](../../../README.md). The Han suite landing page. Start here if you arrived from outside the docs tree. - [YAGNI](../../../docs/yagni.md). The Speculative Edge Case rule. - [Agents Index](../../../docs/agents/README.md). All agents, grouped by role. -- [`test-engineer`](./test-engineer.md). Sibling agent. `/automated-test-planning` runs both in parallel. +- [`test-engineer`](../../../han-coding/docs/agents/test-engineer.md). Sibling agent. `/automated-test-planning` runs both in parallel. - [`/automated-test-planning`](../../../han-coding/docs/skills/automated-test-planning.md). Always dispatches this agent. - [`/code-review`](../../../han-coding/docs/skills/code-review.md). Conditionally dispatches this agent. - [`/plan-a-feature`](../../../han-planning/docs/skills/plan-a-feature.md). Dispatches this agent as part of the spec-stage diff --git a/han-planning/agents/discussion-facilitator.md b/han-planning/agents/discussion-facilitator.md index af2940a2..00fc5ccb 100644 --- a/han-planning/agents/discussion-facilitator.md +++ b/han-planning/agents/discussion-facilitator.md @@ -140,7 +140,7 @@ Specialists available on this team: `software-architect` - **Cross-service / bounded-context topology, context-map relationships, integration patterns, data ownership across services, failure-domain containment** → `system-architect` -- **Test planning for observable behavior** → `test-engineer` +- **Test planning for observable behavior** → the `test-planning` role (`test-engineer`, when `han-coding` is installed) - **Edge-case discovery for tests** → `edge-case-explorer` - **Bug root-cause investigation** → `evidence-based-investigator` - **Spec vs. implementation gap** → `gap-analyzer` From 2b733057f92bab6ffcbe1adfe4e4ec67f08a36e3 Mon Sep 17 00:00:00 2001 From: River Bailey Date: Thu, 15 Oct 2026 15:02:23 -0600 Subject: [PATCH 8/9] revert: roll back the test-engineer move spike Reverts 1ea9d0c, 24e3ccd, abdb80a, and 3e276b8 so the change can be planned in full with plan-a-change against the cross-plugin config discovery research. --- CLAUDE.md | 22 +++---- CONTRIBUTING.md | 5 +- docs/agents/README.md | 2 +- evals/test-engineer/tests.json | 26 ++++---- han-coding/README.md | 8 +-- .../skills/automated-test-planning/SKILL.md | 8 +-- han-coding/skills/code-review/SKILL.md | 2 +- .../code-review/references/agent-dispatch.md | 6 +- .../references/output-verification.md | 2 +- .../code-review/references/types/testing.md | 2 +- .../references/types/work-ticket.md | 2 +- han-core/README.md | 2 + han-core/agents/junior-developer.md | 2 +- han-core/agents/plan-synthesizer.md | 2 +- .../agents/test-engineer.md | 2 +- han-core/docs/agents/edge-case-explorer.md | 2 +- .../docs/agents/test-engineer.md | 8 +-- han-planning/agents/discussion-facilitator.md | 2 +- han-planning/references/agent-roles.md | 60 ------------------- .../skills/iterative-plan-review/SKILL.md | 2 +- .../references/team-selection.md | 5 +- .../references/team-selection.md | 7 +-- .../references/review-team-briefs.md | 4 +- .../references/team-selection.md | 5 +- test/agent-roles.bats | 56 ----------------- 25 files changed, 55 insertions(+), 189 deletions(-) rename {han-coding => han-core}/agents/test-engineer.md (99%) rename {han-coding => han-core}/docs/agents/test-engineer.md (95%) delete mode 100644 han-planning/references/agent-roles.md delete mode 100644 test/agent-roles.bats diff --git a/CLAUDE.md b/CLAUDE.md index 97cf43ca..92fc49c0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ surfaces the first two, the inline `explanation-guidance` skill that surfaces th the `readability-editor` agent, and the `han-readability` and `han-concise` output styles that apply the first two to every turn of a session; it depends on nothing and every prose-producing plugin depends on it), `han-core` (the shared foundation: the specialist agent roster the rest of the suite dispatches — every shared agent except the `readability-editor`, the -`research-analyst`, the `discussion-facilitator`, and the `test-engineer` — plus the `project-discovery` skill, the `pairing` collaborative working mode, and the canonical rule files; depends on no other Han plugin), +`research-analyst`, and the `discussion-facilitator` — plus the `project-discovery` skill, the `pairing` collaborative working mode, and the canonical rule files; depends on no other Han plugin), `han-documentation` (the documentation skills: `project-documentation`, `architectural-decision-record`, and `runbook`; depends on `han-communication` and `han-core` and is bundled by the `han` meta-plugin), `han-research` (the pre-planning knowledge-work skills — `research`, `gap-analysis`, and `issue-triage` — plus the `research-analyst` @@ -117,14 +117,13 @@ han-plugin-builder skill: │ ├── agents/ # discussion-facilitator agent definition │ ├── skills/ # Planning skill directories, each with SKILL.md + references/ + scripts/ │ ├── docs/ # In-plugin long-form docs: docs/skills/{name}.md + docs/agents/discussion-facilitator.md -│ └── references/ # Both kinds: han-planning-owned canonical files (planning-boundary-rule.md, scope-justification-rule.md, operator-escalation-rule.md, contract-pinning-rule.md, synthesis-failure-rule.md, agent-roles.md) beside vendored copies (yagni-rule.md, evidence-rule.md, config-rule.md, collaborative-stop-rule.md). Each owned file opens by saying so; do not overwrite one in a re-sync sweep -├── han-coding/ # Coding plugin: tdd, refactor, design-an-api, code-review, code-overview, code-walkthrough, architectural-analysis, automated-test-planning, manual-test-planning, investigate, coding-standard (the skills for working in code) + the test-engineer agent, which fills han-planning's test-planning role (depends on han-communication and han-core; bundled by the han meta-plugin) -│ ├── README.md # Light front door + scent-line skills and agent lists +│ └── references/ # Both kinds: han-planning-owned canonical files (planning-boundary-rule.md, scope-justification-rule.md, operator-escalation-rule.md, contract-pinning-rule.md, synthesis-failure-rule.md) beside vendored copies (yagni-rule.md, evidence-rule.md, config-rule.md, collaborative-stop-rule.md). Each owned file opens by saying so; do not overwrite one in a re-sync sweep +├── han-coding/ # Coding plugin: tdd, refactor, design-an-api, code-review, code-overview, code-walkthrough, architectural-analysis, automated-test-planning, manual-test-planning, investigate, coding-standard (the skills for working in code; depends on han-communication and han-core; bundled by the han meta-plugin) +│ ├── README.md # Light front door + scent-line skills list │ ├── .claude-plugin/ │ │ └── plugin.json -│ ├── agents/ # test-engineer agent definition │ ├── skills/ # Coding-facing skill directories, each with SKILL.md + references/ (+ scripts/ where used) -│ ├── docs/ # In-plugin long-form docs: docs/skills/{name}.md + docs/agents/test-engineer.md +│ ├── docs/ # In-plugin long-form docs: docs/skills/{name}.md │ └── references/ # Cross-skill reference files vendored for han-coding skills (yagni-rule.md, evidence-rule.md, config-rule.md, collaborative-stop-rule.md) ├── han-github/ # GitHub plugin: post-code-review-to-pr, update-pr-description, work-items-to-issues (depends on han-communication, han-core, and han-coding, whose code-review skill post-code-review-to-pr wraps) │ ├── README.md # Light front door + scent-line skills list @@ -222,7 +221,7 @@ The same plugin also ships those two interview-driven builder skills, `skill-bui design tree for a new skill or agent decision-by-decision and then review the finished artifact against that guidance. Documentation is plugin-first: each plugin carries a light front-door `README.md` and its own long-form docs. Long-form docs in `{plugin}/docs/skills/{name}.md` and `{plugin}/docs/agents/{name}.md` (agents only in `han-core`, -`han-communication`, `han-research`, `han-planning`, `han-coding`, and `han-ddd`) are the canonical operator-facing source for every skill and every agent, +`han-communication`, `han-research`, `han-planning`, and `han-ddd`) are the canonical operator-facing source for every skill and every agent, sitting beside that plugin's README. The cross-plugin surfaces stay under repo-root `docs/`: the alphabetized skills and agents indexes (`docs/skills/README.md`, `docs/agents/README.md`), the plugin index (`docs/choosing-a-han-plugin.md`), and the workflows composition map (`docs/workflows.md`). The underlying definition @@ -232,7 +231,7 @@ and agents indexes (`docs/skills/README.md`, `docs/agents/README.md`), the plugi `han-reporting/skills/{name}/SKILL.md`, `han-feedback/skills/{name}/SKILL.md`, `han-atlassian/skills/{name}/SKILL.md`, `han-linear/skills/{name}/SKILL.md`, `han-ddd/skills/{name}/SKILL.md`, `han-core/agents/{name}.md`, `han-communication/agents/{name}.md`, `han-research/agents/research-analyst.md`, -`han-planning/agents/discussion-facilitator.md`, `han-coding/agents/test-engineer.md`, or `han-ddd/agents/{name}.md`) is the implementation. +`han-planning/agents/discussion-facilitator.md`, or `han-ddd/agents/{name}.md`) is the implementation. ## When to use which doc @@ -306,11 +305,6 @@ such as Claude, should be referenced here. one, and which stage of the chain owns pinning it. Consumed by `plan-a-feature`, `plan-a-change`, `plan-implementation`, `plan-work-items`, and `iterative-plan-review`. The phrase list is mirrored by `check-contract-pinning.sh`; the rule is canonical, so edit it first. -- **[han-planning/references/agent-roles.md](./han-planning/references/agent-roles.md).** The named roles on - `han-planning` team lists that an agent from another plugin can fill, how an agent claims one in its description, and - how a skill fills a role or skips it when no installed agent claims it. Lets `han-planning` use an agent such as - `han-coding`'s `test-engineer` without depending on that plugin. `test/agent-roles.bats` checks every claim names a - defined role. - **[han-planning/references/synthesis-failure-rule.md](./han-planning/references/synthesis-failure-rule.md).** The check a caller runs after `han-core:plan-synthesizer` returns, to confirm the plan file exists and holds content before any later step reads it, plus the three things the stop says when it does not: what did not happen, what @@ -346,7 +340,7 @@ Every file in this section is owned by `han-planning`, not vendored. Each opens `han-github/skills/`, `han-reporting/skills/`, `han-feedback/skills/`, `han-atlassian/skills/`, `han-linear/skills/`, `han-ddd/skills/`, and `han-plugin-builder/skills/` has a long-form doc in its plugin's `docs/skills/`, a scent line in its plugin's `README.md`, and an entry in the skills index (`docs/skills/README.md`); same for agents in `han-core/agents/`, - `han-communication/agents/`, `han-research/agents/`, `han-planning/agents/`, `han-coding/agents/`, and `han-ddd/agents/` (long-form docs in + `han-communication/agents/`, `han-research/agents/`, `han-planning/agents/`, and `han-ddd/agents/` (long-form docs in `{plugin}/docs/agents/`, indexed in `docs/agents/README.md`). Verify the indexes list every entity when editing them, rather than tracking a running total. An output style in `han-communication/output-styles/` gets a long-form doc in diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b70f0a87..fc64b956 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -206,10 +206,7 @@ Long-form docs always live under `docs/` regardless of which plugin the entity s agents live in `han-core` by default; an agent moves out only when a single skill family in one plugin above `han-core` dispatches it exclusively. Today that is the readability-editor, living in `han-communication` with the readability skills it serves; the research-analyst, living in `han-research` with the research skill that - dispatches it; and the discussion-facilitator, living in `han-planning` with `plan-implementation`. An agent that one - plugin dispatches directly and `han-planning` uses only through a role can also move out: today that is the - test-engineer, living in `han-coding` and filling `han-planning`'s `test-planning` role. See - [agent-roles.md](./han-planning/references/agent-roles.md) for how an agent claims a role. See + dispatches it; and the discussion-facilitator, living in `han-planning` with `plan-implementation`. See [agent-domain-focus.md](./han-plugin-builder/skills/guidance/references/agent-building-guidelines/agent-domain-focus.md) for how narrow and named the domain vocabulary should be. 2. Copy [the agent template](./docs/templates/agent-long-form-template.md) into `{plugin}/docs/agents/{name}.md` diff --git a/docs/agents/README.md b/docs/agents/README.md index 38782e9b..b8217578 100644 --- a/docs/agents/README.md +++ b/docs/agents/README.md @@ -93,7 +93,7 @@ domain-language-analyst, domain-ownership-analyst, and domain-visualizer, which dependency direction, abstractions, and duplication. - [`system-architect`](../../han-core/docs/agents/system-architect.md) — Synthesize boundary-crossing findings into context-map relationships, integration patterns, data ownership, and failure-domain containment across services. -- [`test-engineer`](../../han-coding/docs/agents/test-engineer.md) — Plan tests focused on observable behavior and +- [`test-engineer`](../../han-core/docs/agents/test-engineer.md) — Plan tests focused on observable behavior and recommend test doubles for isolation, producing a prioritized test plan. - [`user-experience-designer`](../../han-core/docs/agents/user-experience-designer.md) — Review a UI adversarially against Nielsen's heuristics, WCAG 2.2, universal design, and dark-pattern detection. diff --git a/evals/test-engineer/tests.json b/evals/test-engineer/tests.json index d7043424..cff13cfc 100644 --- a/evals/test-engineer/tests.json +++ b/evals/test-engineer/tests.json @@ -4,7 +4,7 @@ { "name": "Agent Call: plan tests for auth module", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-plan-tests-for-auth-module.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -12,7 +12,7 @@ { "name": "Agent Call: find untested behaviors in user service", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-find-untested-behaviors.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -20,7 +20,7 @@ { "name": "Agent Call: identify test coverage gaps in handlers", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-test-coverage-gaps.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -28,7 +28,7 @@ { "name": "Agent Call: prioritize test cases by risk", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-prioritize-test-cases.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -36,7 +36,7 @@ { "name": "Agent Call: behavioral test plan for API endpoints", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-behavioral-test-plan.md", "model": "opus", "expect": [{ "agent-call": true }] @@ -44,7 +44,7 @@ { "name": "Agent Call: negative — sports test results", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-negative-sports-test.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -52,7 +52,7 @@ { "name": "Agent Call: negative — sprint planning", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-negative-engineering-plan.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -60,7 +60,7 @@ { "name": "Agent Call: negative — behavioral psychology", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-negative-behavior-psychology.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -68,7 +68,7 @@ { "name": "Agent Call: sibling — edge case exploration", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-sibling-edge-cases.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -76,7 +76,7 @@ { "name": "Agent Call: sibling — code review", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-sibling-code-review.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -84,7 +84,7 @@ { "name": "Agent Call: sibling — investigate production bug", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-sibling-investigate-bug.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -92,7 +92,7 @@ { "name": "Agent Call: sibling — architectural analysis", "type": "agent-call", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-call-sibling-architecture.md", "model": "sonnet", "expect": [{ "agent-call": false }] @@ -100,7 +100,7 @@ { "name": "Agent Prompt: test plan for go-security-project", "type": "agent-prompt", - "agentFile": "han-coding:test-engineer", + "agentFile": "han-core:test-engineer", "promptFile": "agent-prompt-go-security-test-plan.md", "scaffold": "go-security-project", "model": "opus", diff --git a/han-coding/README.md b/han-coding/README.md index 35323512..f2a2f782 100644 --- a/han-coding/README.md +++ b/han-coding/README.md @@ -30,13 +30,7 @@ it, dispatching specialist agents to cover each dimension in parallel. Reach for - [`/coding-standard`](docs/skills/coding-standard.md) — Create and update coding standards from existing patterns or evidence-based research. -## Agents - -- [`test-engineer`](docs/agents/test-engineer.md) — Plan tests focused on observable behavior and recommend test - doubles for isolation, producing a prioritized test plan. - -The other agents its skills dispatch are the shared specialists that live in `han-core` (and, for the -readability-editor, in `han-communication`). +Its skills dispatch shared agents that live in `han-core` (and, for the readability-editor, in `han-communication`). ## Installation diff --git a/han-coding/skills/automated-test-planning/SKILL.md b/han-coding/skills/automated-test-planning/SKILL.md index 628cfd32..b9b4062d 100644 --- a/han-coding/skills/automated-test-planning/SKILL.md +++ b/han-coding/skills/automated-test-planning/SKILL.md @@ -121,7 +121,7 @@ State the chosen band and mode in one line with the justification before dispatc `Medium: from the project .han/config.md default-swarm-size`, naming whichever file supplied it). Accept the user's override of the band, the mode, or both. -In **focused mode**, dispatch only `han-coding:test-engineer` in Step 2, skip the conditional specialists, answer in prose +In **focused mode**, dispatch only `han-core:test-engineer` in Step 2, skip the conditional specialists, answer in prose per Step 4's focused-mode rules, and skip the two reviewers in Step 5. **Step 3 runs in full either way.** Its behavioral, prerequisite, and YAGNI sweeps decide what may be recommended at all, so skipping them would let a focused answer recommend a test that cannot be written without an out-of-scope production change. In **full mode**, run every @@ -139,7 +139,7 @@ other than `none provided`, include it in every agent prompt so they can focus t ### Always dispatch -1. **Launch han-coding:test-engineer agent** — prompt: "Analyze test coverage for the following files{on branch {branch} +1. **Launch han-core:test-engineer agent** — prompt: "Analyze test coverage for the following files{on branch {branch} if applicable}: {file list}. Recommend tests only at the public API: the inputs a real caller supplies, the outputs and side effects they observe, and the interactions the unit has with the objects and services it collaborates with. Do not recommend tests that reach into private methods, internal state, or implementation structure — if two @@ -189,7 +189,7 @@ Wait for every dispatched agent to complete and collect full output for processi Combine findings from every dispatched agent into a unified, prioritized test plan: 1. **Classify findings** — - - **han-coding:test-engineer items** (T1, T2, ...): map High to CRIT or HIGH depending on the code path (security, data + - **han-core:test-engineer items** (T1, T2, ...): map High to CRIT or HIGH depending on the code path (security, data integrity, auth = CRIT; business logic, error handling = HIGH), Medium to MED, Low to LOW. - **han-core:edge-case-explorer items** (EC1, EC2, ...): map directly — Critical to CRIT, High to HIGH, Medium to MED, Low to LOW. @@ -278,7 +278,7 @@ Lead with behavior. These rules make the plan a human-readable overview first an 4. **Technical Reference → Test Plan** — All items from Step 3, grouped by priority tier. Every test plan item should include file:line references from the agent output, and preserve agent detail — carry through the test approach, code paths, and risk assessments into the merged output. -5. **Technical Reference → Deferred Tests** — Items the han-coding:test-engineer excluded due to brittleness risk. +5. **Technical Reference → Deferred Tests** — Items the han-core:test-engineer excluded due to brittleness risk. 6. **Technical Reference → Dropped Edge Cases** — Items the han-core:edge-case-explorer intentionally excluded. 7. **Technical Reference → Blocked by a Production Change** — Items the prerequisite sweep moved out of the priority tiers, each with the production change it would need, the file that would carry it, and that file's other consumers. diff --git a/han-coding/skills/code-review/SKILL.md b/han-coding/skills/code-review/SKILL.md index 292bf216..657ed312 100644 --- a/han-coding/skills/code-review/SKILL.md +++ b/han-coding/skills/code-review/SKILL.md @@ -606,7 +606,7 @@ escalate to those bands. Continue task ID numbering sequentially from Steps 4-6 ### Deferred tests -If the han-coding:test-engineer produced Deferred/Skipped items, include them as a note after the testing findings (not +If the han-core:test-engineer produced Deferred/Skipped items, include them as a note after the testing findings (not counted toward the cap): > **Deferred tests:** The following test cases were considered but excluded because brittleness risk outweighs value: diff --git a/han-coding/skills/code-review/references/agent-dispatch.md b/han-coding/skills/code-review/references/agent-dispatch.md index c8f6a83e..82ab2391 100644 --- a/han-coding/skills/code-review/references/agent-dispatch.md +++ b/han-coding/skills/code-review/references/agent-dispatch.md @@ -28,7 +28,7 @@ team's own agent outside Han. Its series carries the agent's name, so two such a | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ---------------------------------------- | | `han-core:junior-developer` | any change (generalist) | full file list (generalist) | junior-developer-review.md | JD | | `han-core:adversarial-security-analyst` | any change | full file list plus dependency manifests | security-analysis.md | SEC | -| `han-coding:test-engineer` | source files with logic or behavior were added or modified (skip for docs-only or pure config changes) | source files plus their related test files | test-plan.md | T | +| `han-core:test-engineer` | source files with logic or behavior were added or modified (skip for docs-only or pure config changes) | source files plus their related test files | test-plan.md | T | | `han-core:edge-case-explorer` | code processes inputs with boundaries, parses external data, or handles multiple states (skip for trivial edits, renames, or docs-only changes) | source files containing logic or input handling | edge-case-analysis.md | EC | | `han-core:structural-analyst` | the change introduces new files, new modules, or modifies dependency direction across modules (skip for single-file in-place edits) | source files only (skip configs, schemas, docs) | structural-analysis.md | S | | `han-core:behavioral-analyst` | the change modifies runtime data flow across module boundaries, error propagation paths, or state management (skip for self-contained changes within a single function or class) | source files containing runtime logic | behavioral-analysis.md | B | @@ -170,7 +170,7 @@ from earlier steps; `{the change}` names the change the way Step 1 resolved it: (`git diff {default-branch}...HEAD`) on branch {branch} in Mode A, the uncommitted diff in Mode B, and the listed files read in full in Mode C): -1. `han-coding:test-engineer` — "Analyze test coverage for the following files{if branch available: ' on branch +1. `han-core:test-engineer` — "Analyze test coverage for the following files{if branch available: ' on branch {branch}'}: {file list}. Focus your analysis on these files and their related test files." 2. `han-core:edge-case-explorer` — "Explore edge cases for the following files{if branch available: ' on branch @@ -319,7 +319,7 @@ visible rather than implied: - `han-core:junior-developer` → Code Maintainability, Documentation, Code Style & Patterns, Architecture Decision Records. - `han-core:adversarial-security-analyst` → Data Isolation, Error Handling, API Design. Partial: nothing substitutes for an exploit path demonstrated against the code. -- `han-coding:test-engineer` → Testing, Correctness. +- `han-core:test-engineer` → Testing, Correctness. - `han-core:edge-case-explorer` → Correctness, Error Handling. Partial: the checklist asks whether edge cases are handled, not which ones exist. - `han-core:structural-analyst` → Code Organization, Code Maintainability. - `han-core:behavioral-analyst` → Error Handling, Correctness. diff --git a/han-coding/skills/code-review/references/output-verification.md b/han-coding/skills/code-review/references/output-verification.md index 3a1c74cf..26197f6f 100644 --- a/han-coding/skills/code-review/references/output-verification.md +++ b/han-coding/skills/code-review/references/output-verification.md @@ -41,7 +41,7 @@ Then verify: selected) have valid task IDs continuing from manual review IDs. Findings from agents that were not dispatched in Step 3 must not appear. 3. Agent findings have valid `file_path:line_number` references -4. Deferred tests note is present if the han-coding:test-engineer produced skipped items +4. Deferred tests note is present if the han-core:test-engineer produced skipped items 5. The Review Summary table includes every corrective finding (CRIT/WARN/SUGG) and every security finding, and matches the sections that are present. YAGNI findings are excluded from the table (see rule 12). For findings whose block omits the category, the table is the only place that category appears. Every CRIT/WARN/SUGG row carries its fix route diff --git a/han-coding/skills/code-review/references/types/testing.md b/han-coding/skills/code-review/references/types/testing.md index b8e5612c..0a1f0b55 100644 --- a/han-coding/skills/code-review/references/types/testing.md +++ b/han-coding/skills/code-review/references/types/testing.md @@ -6,7 +6,7 @@ Check the test coverage and edge cases of the change. ## Roster -- Always: han-coding:test-engineer, han-core:edge-case-explorer +- Always: han-core:test-engineer, han-core:edge-case-explorer - When relevant: none ## Checklist categories diff --git a/han-coding/skills/code-review/references/types/work-ticket.md b/han-coding/skills/code-review/references/types/work-ticket.md index c9490662..02e6561e 100644 --- a/han-coding/skills/code-review/references/types/work-ticket.md +++ b/han-coding/skills/code-review/references/types/work-ticket.md @@ -7,7 +7,7 @@ Verify that the change on this branch resolves the named work ticket. ## Roster - Always: han-core:gap-analyzer -- When relevant: han-coding:test-engineer +- When relevant: han-core:test-engineer ## Checklist categories diff --git a/han-core/README.md b/han-core/README.md index 525fc486..726e017e 100644 --- a/han-core/README.md +++ b/han-core/README.md @@ -83,6 +83,8 @@ Most agents are dispatched for you by skills; you rarely invoke them directly. G ### Testing +- [`test-engineer`](docs/agents/test-engineer.md) — Plan tests focused on observable behavior and recommend test + doubles for isolation, producing a prioritized test plan. - [`edge-case-explorer`](docs/agents/edge-case-explorer.md) — Systematically discover and catalog edge cases: boundary values, type-coercion traps, and state-dependent failures. diff --git a/han-core/agents/junior-developer.md b/han-core/agents/junior-developer.md index b3d97d43..c5895041 100644 --- a/han-core/agents/junior-developer.md +++ b/han-core/agents/junior-developer.md @@ -238,7 +238,7 @@ Domain handoffs: `software-architect` - **Cross-service / bounded-context topology, context-map relationships, integration patterns, data ownership across services, failure-domain containment** → `system-architect` -- **Test planning depth, behavior-focused tests, test doubles** → the `test-planning` role (`test-engineer`, when `han-coding` is installed) +- **Test planning depth, behavior-focused tests, test doubles** → `test-engineer` - **Edge-case discovery for tests** → `edge-case-explorer` - **Bug root-cause investigation** → `evidence-based-investigator` - **Spec / PRD vs implementation gap** → `gap-analyzer` diff --git a/han-core/agents/plan-synthesizer.md b/han-core/agents/plan-synthesizer.md index f09260a1..4a964432 100644 --- a/han-core/agents/plan-synthesizer.md +++ b/han-core/agents/plan-synthesizer.md @@ -150,7 +150,7 @@ Specialists available on this team: `software-architect` - **Cross-service / bounded-context topology, context-map relationships, integration patterns, data ownership across services, failure-domain containment** → `system-architect` -- **Test planning for observable behavior** → the `test-planning` role (`test-engineer`, when `han-coding` is installed) +- **Test planning for observable behavior** → `test-engineer` - **Edge-case discovery for tests** → `edge-case-explorer` - **Bug root-cause investigation** → `evidence-based-investigator` - **Spec vs. implementation gap** → `gap-analyzer` diff --git a/han-coding/agents/test-engineer.md b/han-core/agents/test-engineer.md similarity index 99% rename from han-coding/agents/test-engineer.md rename to han-core/agents/test-engineer.md index 4621ddd0..746f7da1 100644 --- a/han-coding/agents/test-engineer.md +++ b/han-core/agents/test-engineer.md @@ -6,7 +6,7 @@ description: expectations for commands) for isolation, and produces a prioritized test plan with recommended test levels. Use when thorough, multi-angle test planning is needed for new or existing code. Does not write test code — produces a plan only. Does not do deep edge case exploration or boundary analysis — use edge-case-explorer for exhaustive boundary - value and failure mode discovery. Fills the han-planning `test-planning` role." + value and failure mode discovery." tools: Read, Glob, Grep, Bash(git *), Bash(find *), Write model: sonnet --- diff --git a/han-core/docs/agents/edge-case-explorer.md b/han-core/docs/agents/edge-case-explorer.md index 2ffb0804..cb52c850 100644 --- a/han-core/docs/agents/edge-case-explorer.md +++ b/han-core/docs/agents/edge-case-explorer.md @@ -165,7 +165,7 @@ https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-de - [Repo root README](../../../README.md). The Han suite landing page. Start here if you arrived from outside the docs tree. - [YAGNI](../../../docs/yagni.md). The Speculative Edge Case rule. - [Agents Index](../../../docs/agents/README.md). All agents, grouped by role. -- [`test-engineer`](../../../han-coding/docs/agents/test-engineer.md). Sibling agent. `/automated-test-planning` runs both in parallel. +- [`test-engineer`](./test-engineer.md). Sibling agent. `/automated-test-planning` runs both in parallel. - [`/automated-test-planning`](../../../han-coding/docs/skills/automated-test-planning.md). Always dispatches this agent. - [`/code-review`](../../../han-coding/docs/skills/code-review.md). Conditionally dispatches this agent. - [`/plan-a-feature`](../../../han-planning/docs/skills/plan-a-feature.md). Dispatches this agent as part of the spec-stage diff --git a/han-coding/docs/agents/test-engineer.md b/han-core/docs/agents/test-engineer.md similarity index 95% rename from han-coding/docs/agents/test-engineer.md rename to han-core/docs/agents/test-engineer.md index 43695c45..a2ac4339 100644 --- a/han-coding/docs/agents/test-engineer.md +++ b/han-core/docs/agents/test-engineer.md @@ -1,10 +1,8 @@ # test-engineer -Operator documentation for the `test-engineer` agent in the `han-coding` plugin. This document helps you decide _when_ and _how_ +Operator documentation for the `test-engineer` agent in the han plugin. This document helps you decide _when_ and _how_ to dispatch the agent. For what the agent does internally, read the agent definition at -[`han-coding/agents/test-engineer.md`](../../agents/test-engineer.md). The agent fills `han-planning`'s -`test-planning` role, so planning skills use it when `han-coding` is installed and skip the role when it is not; see -[`agent-roles.md`](../../../han-planning/references/agent-roles.md). +[`han-core/agents/test-engineer.md`](../../agents/test-engineer.md). > See also: [Plugin README](../../README.md) · [Repo root](../../../README.md) · [All agents](../../../docs/agents/README.md) · > [All skills](../../../docs/skills/README.md) · [YAGNI](../../../docs/yagni.md) @@ -64,7 +62,7 @@ to dispatch the agent. For what the agent does internally, read the agent defini ## How to invoke it -Dispatch via the `Agent` tool with `subagent_type: han-coding:test-engineer`. Give it: +Dispatch via the `Agent` tool with `subagent_type: han-core:test-engineer`. Give it: 1. **A focus area.** Files, a directory, or a feature description. The narrower the scope, the sharper the plan. 2. **Project context, optional.** If the project's test framework and conventions are not obvious from the existing diff --git a/han-planning/agents/discussion-facilitator.md b/han-planning/agents/discussion-facilitator.md index 00fc5ccb..af2940a2 100644 --- a/han-planning/agents/discussion-facilitator.md +++ b/han-planning/agents/discussion-facilitator.md @@ -140,7 +140,7 @@ Specialists available on this team: `software-architect` - **Cross-service / bounded-context topology, context-map relationships, integration patterns, data ownership across services, failure-domain containment** → `system-architect` -- **Test planning for observable behavior** → the `test-planning` role (`test-engineer`, when `han-coding` is installed) +- **Test planning for observable behavior** → `test-engineer` - **Edge-case discovery for tests** → `edge-case-explorer` - **Bug root-cause investigation** → `evidence-based-investigator` - **Spec vs. implementation gap** → `gap-analyzer` diff --git a/han-planning/references/agent-roles.md b/han-planning/references/agent-roles.md deleted file mode 100644 index a78a3e71..00000000 --- a/han-planning/references/agent-roles.md +++ /dev/null @@ -1,60 +0,0 @@ -# Agent Roles (Slots Another Plugin's Agent Can Fill) - -## Contents - -- What a role is -- How an agent claims a role -- How a skill fills a role -- The roles -- Related rules - -**Owned by `han-planning`.** This file is authored here and is not a vendored copy of a shared rule. Do not overwrite it -from another plugin's `references/` folder during a re-sync sweep, and do not treat a difference between it and any -similarly-named file elsewhere as drift to correct. - -## What a role is - -A role is a named slot on a `han-planning` team list that an agent from another plugin can fill. It lets a planning skill -use a specialist without `han-planning` depending on the plugin that ships it. When that plugin is installed, its agent -fills the role. When it is not, the role stays empty and the skill runs without it. - -`han-planning` owns the role names and what each one is for. A plugin that ships an agent says which role the agent -fills. The providing plugin never names `han-planning`'s skills, so renaming or adding a planning skill never breaks it. - -## How an agent claims a role - -An agent claims a role with one sentence at the end of its frontmatter `description`, in this exact form: - -```markdown -Fills the han-planning `test-planning` role. -``` - -The description is the claim because Claude Code loads every installed agent's description into the session. A skill -reading its team list can see which agents are available and which roles they claim, with no extra lookup. The role name -is in backticks and matches a heading under "The roles" below exactly. A test checks that every claimed role exists here. - -## How a skill fills a role - -When a team list names a role and the skill selects it, fill it this way: - -1. Look through the agents available in this session for any whose description claims the role. -2. If one agent claims it, dispatch that agent by its qualified `plugin:agent` name, exactly as the session lists it. -3. If more than one claims it, dispatch the one whose description best fits the selection reason. It is one candidate, - counted once against the team's size cap. -4. If none claims it, skip the role and add one line to the team announcement, for example: "Skipped the - `test-planning` role: no installed agent fills it." This is not an error, and the run continues. - -Never dispatch an agent for a role by guessing its name. Use only a name the session lists. - -## The roles - -### `test-planning` - -Plans tests around observable behavior: inputs, outputs, and collaborator interactions, with the test doubles that -isolate them. Select it when a plan or spec commits to behavior that has to be verified, or when a change must preserve -behavior that existing tests pin. Today `han-coding` ships the agent that fills it. - -## Related rules - -- [`config-rule.md`](./config-rule.md): extra agents a project names join the same pool and use the same skip-with-a-note - handling. diff --git a/han-planning/skills/iterative-plan-review/SKILL.md b/han-planning/skills/iterative-plan-review/SKILL.md index 882aca34..1032ed07 100644 --- a/han-planning/skills/iterative-plan-review/SKILL.md +++ b/han-planning/skills/iterative-plan-review/SKILL.md @@ -272,7 +272,7 @@ loop earlier whenever a round goes quiet, so the cap is a ceiling rather than a | `han-core:concurrency-analyst` | Sections touching concurrent access, race conditions, async coordination | | `han-core:software-architect` / `han-core:system-architect` | Architecture / topology / context-map sections | | `han-core:risk-analyst` | Architectural and delivery risks; depends on upstream specialist findings | - | `test-planning` role / `han-core:edge-case-explorer` | Sections describing observable behavior, boundary cases, failure modes | + | `han-core:test-engineer` / `han-core:edge-case-explorer` | Sections describing observable behavior, boundary cases, failure modes | | `han-core:data-engineer` | Sections touching schema, migration, data movement, analytics | | `han-core:gap-analyzer` | Source PRD/spec + the plan under review | | `han-core:content-auditor` | Documentation sections being updated | diff --git a/han-planning/skills/iterative-plan-review/references/team-selection.md b/han-planning/skills/iterative-plan-review/references/team-selection.md index 493402d5..8a15642c 100644 --- a/han-planning/skills/iterative-plan-review/references/team-selection.md +++ b/han-planning/skills/iterative-plan-review/references/team-selection.md @@ -52,8 +52,7 @@ review. Draw from: - `han-core:system-architect` — cross-service / bounded-context topology, context-map relationships, integration patterns, data ownership, failure-domain containment. - `han-core:risk-analyst` — prioritization of architectural and delivery risks. -- The [`test-planning` role](../../../references/agent-roles.md) — observable-behavior test planning, test doubles. Filled by whichever installed agent - claims it; skipped with a one-line note when none does. +- `han-core:test-engineer` — observable-behavior test planning, test doubles. - `han-core:edge-case-explorer` — boundary values, input messiness, state-dependent failures. - `han-core:data-engineer` — schema changes, migrations, data movement, analytics implications. - `han-core:gap-analyzer` — spec-vs-implementation gap checks when a source spec exists. @@ -91,7 +90,7 @@ review. Draw from: `han-core:adversarial-security-analyst`, `han-core:devops-engineer`, `han-core:on-call-engineer` (scoped to spec-level resilience commitments — idempotency, retry behavior, kill switches, graceful degradation — not file-and-line mechanics), `han-core:observability-engineer` (scoped to the telemetry the spec commits to — which signals a flow - emits and what they must let someone answer — not instrument or pipeline mechanics), `han-core:edge-case-explorer`, the `test-planning` role, `han-core:gap-analyzer`, `han-core:risk-analyst` + emits and what they must let someone answer — not instrument or pipeline mechanics), `han-core:edge-case-explorer`, `han-core:test-engineer`, `han-core:gap-analyzer`, `han-core:risk-analyst` (no structural/behavioral/concurrency upstream dependency), `han-core:content-auditor`, `han-core:codebase-explorer`. Present the proposed team to the user briefly — the required agents (and whether `han-core:evidence-based-investigator` diff --git a/han-planning/skills/plan-a-change/references/team-selection.md b/han-planning/skills/plan-a-change/references/team-selection.md index 98e3a661..df86ddd7 100644 --- a/han-planning/skills/plan-a-change/references/team-selection.md +++ b/han-planning/skills/plan-a-change/references/team-selection.md @@ -50,9 +50,8 @@ Select additional specialists up to the cap, based on what the area actually con - `han-core:risk-analyst` — prioritization across the findings the discovery round and the review produced. The most common first pick, because a change plan's failure mode is carrying every finding at equal weight. -- The [`test-planning` role](../../../references/agent-roles.md) — how the change is verified, and which existing tests pin behavior the delta must - preserve. Include whenever a behavior-preservation claim needs something to rest on. Filled by whichever installed - agent claims it; skipped with a one-line note when none does. +- `han-core:test-engineer` — how the change is verified, and which existing tests pin behavior the delta must preserve. + Include whenever a behavior-preservation claim needs something to rest on. - `han-core:on-call-engineer` — code-level resilience the change moves or removes: timeouts, retries, idempotency, queue handling, kill switches, and the failure paths a responsibility shift can quietly relocate. - `han-core:adversarial-security-analyst` — the area handles authentication, authorization, PII, secrets, or untrusted @@ -84,7 +83,7 @@ Pass each specialist only what its domain needs, plus the pointers below. Do not | Specialist | Plan sections to include in the brief | | --------------------------------------- | --------------------------------------------------------------------------------- | | `han-core:risk-analyst` | Target State, the full delta with behavior classifications, Change Units | -| `test-planning` role | Current State, the delta entries classified Preserving, Change Units | +| `han-core:test-engineer` | Current State, the delta entries classified Preserving, Change Units | | `han-core:on-call-engineer` | Delta entries touching error paths, retries, timeouts, queues, or lifecycle order | | `han-core:adversarial-security-analyst` | Delta entries moving a trust boundary, plus Current State on those paths | | `han-core:data-engineer` | Delta entries touching a schema, persisted format, or data-access path | diff --git a/han-planning/skills/plan-a-feature/references/review-team-briefs.md b/han-planning/skills/plan-a-feature/references/review-team-briefs.md index 454f51f2..a5d27e60 100644 --- a/han-planning/skills/plan-a-feature/references/review-team-briefs.md +++ b/han-planning/skills/plan-a-feature/references/review-team-briefs.md @@ -23,7 +23,7 @@ Select the remaining specialists by matching domain to feature, under the size c | `han-core:on-call-engineer` | Resilience commitments the spec must make: idempotency on retried operations, timeout and deadline behavior, graceful degradation when a dependency is down, kill switches, named failure-mode coverage. Spec level only. | | `han-core:observability-engineer` | Telemetry design the spec commits to: metric instruments or labels, span attributes, log schemas, OpenTelemetry SDK setup (samplers, exporters, resource attributes), telemetry pipeline configuration, or telemetry volume and cost. Spec level only. SLO definitions, alert rules, and dashboards stay with `han-core:devops-engineer`; source-line debuggability, correlation-ID propagation, and PII in individual log statements stay with `han-core:on-call-engineer`. Brief it not to recommend tail sampling, a Collector tier, or retention tiers for volume the project does not have. | | `han-core:edge-case-explorer` | Boundary values, input messiness, or state-dependent failures. | -| `test-planning` role | What observable behaviors the spec commits to making testable. Test-double and collaborator-boundary framing is deferred to `plan-implementation`. Fill it per [`agent-roles.md`](../../../references/agent-roles.md); skip it with a one-line note when no installed agent claims it. | +| `han-core:test-engineer` | What observable behaviors the spec commits to making testable. Test-double and collaborator-boundary framing is deferred to `plan-implementation`. | | `han-core:gap-analyzer` | A PRD or reference spec exists to compare the draft against. | | `han-core:risk-analyst` | Significant blast radius, where risks need prioritizing. | @@ -57,7 +57,7 @@ set. | `han-core:on-call-engineer` | Outcome, Primary Flow, Alternate Flows, Edge Cases, Coordinations (sections touching idempotency, retries, timeouts, kill switches, graceful degradation) | | `han-core:observability-engineer` | Outcome, Primary Flow, Coordinations, Open Items (sections touching which signals a flow emits, telemetry volume or cost, or a telemetry pipeline) | | `han-core:edge-case-explorer` | Outcome, Primary Flow, Alternate Flows, Edge Cases | -| `test-planning` role | Outcome, Primary Flow, Alternate Flows, Edge Cases | +| `han-core:test-engineer` | Outcome, Primary Flow, Alternate Flows, Edge Cases | | `han-core:gap-analyzer` | Source PRD or reference spec, plus the draft spec under review | | `han-core:risk-analyst` | Outcome, Coordinations, Edge Cases (risk-relevant rows only) | | `han-core:junior-developer` | Outcome, plus the first paragraph of every section | diff --git a/han-planning/skills/plan-implementation/references/team-selection.md b/han-planning/skills/plan-implementation/references/team-selection.md index c3f3f322..870998f8 100644 --- a/han-planning/skills/plan-implementation/references/team-selection.md +++ b/han-planning/skills/plan-implementation/references/team-selection.md @@ -71,8 +71,7 @@ specialist rather than discovering a gap late. Unless the user specified a team the feature crosses a service boundary, introduces a new integration, changes a context-map relationship, or shifts data ownership. Include both when the feature does both. - `han-core:risk-analyst` — prioritization of architectural and delivery risks. -- The [`test-planning` role](../../../references/agent-roles.md) — observable-behavior test planning and test doubles. Filled by whichever installed agent claims it; skipped - with a one-line note when none does. +- `han-core:test-engineer` — observable-behavior test planning and test doubles. - `han-core:edge-case-explorer` — boundary values, input messiness, state-dependent failures. - `han-core:data-engineer` — schema changes, migrations, data movement, analytics implications. @@ -101,7 +100,7 @@ Pass each selected specialist only the sections relevant to its domain, plus the | `han-core:concurrency-analyst` | Sections touching concurrent access, race conditions, async coordination | | `han-core:software-architect` / `han-core:system-architect` | Architecture / topology / context-map sections | | `han-core:risk-analyst` | Architectural and delivery risks; depends on upstream specialist findings | -| `test-planning` role / `han-core:edge-case-explorer` | Outcome, Primary Flow, Alternate Flows, Edge Cases | +| `han-core:test-engineer` / `han-core:edge-case-explorer` | Outcome, Primary Flow, Alternate Flows, Edge Cases | | `han-core:data-engineer` | Sections touching schema, migration, data movement, analytics | | `han-core:junior-developer` | Outcome + first paragraph of every section (plain-language overview) | diff --git a/test/agent-roles.bats b/test/agent-roles.bats deleted file mode 100644 index d65d3688..00000000 --- a/test/agent-roles.bats +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bats -# -# Guards the agent-role contract in han-planning/references/agent-roles.md. -# An agent in any plugin claims a han-planning role with one sentence in its -# description, and a planning skill fills the role from whichever installed -# agent claims it. Nothing at runtime notices a claim for a role that does not -# exist: the agent is never selected, and the role is skipped as if the plugin -# were not installed. These checks catch that drift in the repo instead. -# -# Portability: keep to bash 3.2, and grep one named file at a time, never -r -# (see test/codex-packaging.bats for why). - -REPO_ROOT="${BATS_TEST_DIRNAME}/.." -ROLES='han-planning/references/agent-roles.md' - -# Every role defined in the roles file, one per line. -defined_roles() { - cd "$REPO_ROOT" || return 1 - sed -n 's/^### `\([a-z0-9-]*\)`$/\1/p' "$ROLES" -} - -# Every "file role" pair claimed by an agent description, one per line. -claimed_roles() { - cd "$REPO_ROOT" || return 1 - for f in han-*/agents/*.md; do - sed -n 's/.*Fills the han-planning `\([a-z0-9-]*\)` role\..*/\1/p' "$f" | - while read -r role; do printf '%s %s\n' "$f" "$role"; done - done -} - -@test "the roles file defines at least one role" { - run defined_roles - [ "$status" -eq 0 ] - [ -n "$output" ] -} - -@test "every role an agent claims is defined in the roles file" { - roles="$(defined_roles)" - missing='' - while read -r file role; do - [ -z "$file" ] && continue - printf '%s\n' "$roles" | grep -qx "$role" || missing="${missing}${file} claims undefined role '${role}'"$'\n' - done < Date: Fri, 16 Oct 2026 10:05:37 -0600 Subject: [PATCH 9/9] halfway planned implementation, but likely going to throw all of this away --- .../artifacts/change-decision-log.md | 43 ++ .../artifacts/current-state-findings.md | 408 ++++++++++++++++++ .../artifacts/scope-boundary.md | 47 ++ 3 files changed, 498 insertions(+) create mode 100644 docs/plans/han-core-agent-redistribution/artifacts/change-decision-log.md create mode 100644 docs/plans/han-core-agent-redistribution/artifacts/current-state-findings.md create mode 100644 docs/plans/han-core-agent-redistribution/artifacts/scope-boundary.md diff --git a/docs/plans/han-core-agent-redistribution/artifacts/change-decision-log.md b/docs/plans/han-core-agent-redistribution/artifacts/change-decision-log.md new file mode 100644 index 00000000..d2e7d54b --- /dev/null +++ b/docs/plans/han-core-agent-redistribution/artifacts/change-decision-log.md @@ -0,0 +1,43 @@ +# Change Decision Log: han-core Agent Redistribution + + + +## Trivial decisions + +## Full decisions + +### D-1: The user-experience-designer moves to han-planning + +- **Question:** Where does `user-experience-designer` live, given that one `han-coding` review type requires it and + five planning and research skills use it optionally? +- **Decision:** `han-core:user-experience-designer` becomes `han-planning:user-experience-designer` and claims the + `ux-review` role. `han-coding`'s code-review fills that role in its default-run dispatch table and in the `ux` review + type. When no installed agent fills it, the default run marks usability `not swept` through the existing + manual-only coverage disclosure, and `/code-review ux` states that the type has no reviewer installed rather than + reporting a clean pass. The placement rule gains an exception: a reviewer lives where most of the skills that use it + live, provided every other consumer can name what is missing when it is absent. +- **Rationale:** UX review is mostly pre-build work on specs and plans. Five consumers (plan-a-feature, + plan-a-change, plan-implementation, iterative-plan-review, gap-analysis) against one (code-review, through two entry + points) means a partial install loses fewer skills' coverage this way. Code-review already discloses an absent + reviewer as `not swept`, so its degraded path exists. +- **Evidence:** C-13 (code-review `ux` type: Always `user-experience-designer`); C-14 (manual-only substitution list, + `han-coding/skills/code-review/references/agent-dispatch.md:334`: "nothing substitutes. No checklist category covers + usability or accessibility"); C-19 and C-20 (dispatch map); user input. +- **Behavior impact:** Changing. With `han-coding` installed but not `han-planning`, `/code-review` on a UI change + reports usability as `not swept`, and `/code-review ux` reports that no reviewer is installed. With `han-planning` + installed but not `han-coding`, planning skills keep UX review. User's answer, verbatim: "move it to han-planning". +- **Rejected alternatives:** + - Move to han-coding, as the software architect proposed — rejected because planning-only installs would lose UX + review in five skills to keep it in one. + - Stay in han-core — rejected by the operator; it keeps an agent in the foundation that no core skill uses. +- **Revisit criterion:** If a `han-coding` skill other than code-review comes to require UX review, or code-review's + `ux` type gains a second reviewer. +- **Dissent (if any):** The software architect's proposal placed it in han-coding under the strict "plugin that + requires it" rule. +- **Settles delta entry:** pending +- **Dependent decisions:** pending (the content-auditor deferral reason weakens, since `han-coding` now fills a role) +- **Referenced in plan:** pending diff --git a/docs/plans/han-core-agent-redistribution/artifacts/current-state-findings.md b/docs/plans/han-core-agent-redistribution/artifacts/current-state-findings.md new file mode 100644 index 00000000..0ba9edee --- /dev/null +++ b/docs/plans/han-core-agent-redistribution/artifacts/current-state-findings.md @@ -0,0 +1,408 @@ +# Current State Findings: han-core Agent Redistribution + +## Provenance + +Produced by this run's own discovery round on 2026-10-15. Nothing in the area had a prior findings report. The research +report `docs/research/cross-plugin-config-discovery.md` is the reason for the change and is cited where it carries a +codebase fact (its A-numbered sources). + +- `han-core:structural-analyst` covered the reference map, routing text between agents, roster copies, and the places + outside skills that hard-code agent namespaces. Its findings were S-1 to S-17. +- `han-core:behavioral-analyst` covered how skills select and dispatch agents, what each dispatch site does when an agent + is missing, fixed pipelines, and cap counting. Its findings were B-1 to B-22. +- `han-core:concurrency-analyst` was not dispatched. The area is markdown and has no concurrent access. +- The run's own sweep added the project context, the git history of earlier agent moves, the plugin manifests, and a + correction to S-14 (C-17). + +Both specialists worked by grep and excerpt reads. They did not read every one of about 650 hits individually. The +structural pass spot-checked about 12 reference-file classifications. + +## Project Context + +- **Stack:** Markdown skill, agent, and doc content, plus Bash scripts. npm manages dev tooling only. `npm test` runs Bats + over every `*.bats` file. `npm run lint` runs prek (Prettier, ShellCheck, file hygiene). +- **Conventions source:** `CLAUDE.md` (project map and `## Project Discovery`), `CONTRIBUTING.md`. +- **ADRs found:** `docs/adr/0001-project-configurable-default-swarm-size.md`, which does not bear on agent placement. The + placement decision of record is D1 in `docs/plans/han-core-restructure/artifacts/decision-log.md:19-30`, which is a + plan decision and not an ADR. +- **Coding standards found:** the agent placement rule in `CONTRIBUTING.md:203-211`, the namespacing rule in + `han-plugin-builder/skills/guidance/references/skill-building-guidance/agent-dispatch-namespacing.md`, and + `docs/semantic-versioning.md`. +- **Recent churn:** the most-touched agents in `han-core/agents/` over the last 90 days are `test-engineer`, + `on-call-engineer`, `junior-developer`, and `data-engineer` (6 touches each). The `test-engineer` count includes the + reverted spike. Commit messages were not classified. + +## Gaps + +- No ADR records where agents live or why. D1 is a plan decision only. +- No test checks that a dispatched agent name resolves, that the duplicated roster copies agree, or that vendored rule + copies match (research A33, structural S-11). +- No mechanism exists anywhere for a skill to dispatch a shipped agent conditionally on its being installed (C-9). +- Nothing documents what the Agent tool returns for an unknown agent name (research A7, A8, A9). See Findings No Agent + Could Audit. + +## Findings + +### C-1: Every han-core agent except project-scanner is dispatched by two or more plugins + +- **Claim:** No `han-core` agent other than `project-scanner` meets the current placement rule's "one plugin dispatches + it exclusively" test. +- **Location:** dispatch sites across `han-coding/`, `han-planning/`, `han-research/`, `han-documentation/`, + `han-ddd/`, and `han-github/`. The full table is in C-19. +- **Evidence:** distinct dispatching plugins per agent: + ``` + 1: project-scanner (han-core only) + 2: concurrency-analyst, edge-case-explorer, test-engineer (coding, planning); plan-synthesizer (planning, research) + 3: adversarial-security-analyst, adversarial-validator, data-engineer, devops-engineer, + evidence-based-investigator, gap-analyzer, observability-engineer, on-call-engineer, + user-experience-designer (coding, planning, research); behavioral-analyst, structural-analyst + (coding, planning, ddd); risk-analyst (coding, planning, documentation) + 4: content-auditor, information-architect, software-architect (coding, planning, documentation, research) + 5: codebase-explorer (atlassian-by-wrapper, coding, documentation, planning, research); + junior-developer (coding, planning, documentation, github, research); + system-architect (coding, planning, documentation, ddd, research) + ``` +- **Raised by:** structural-analyst S-1, S-2. +- **Confidence:** Verified. +- **Bears on:** — + +### C-2: The current placement rule keeps agents in han-core unless one plugin's skill family dispatches them exclusively + +- **Claim:** Agents default to `han-core`. Three have moved out under the exclusivity test, and restructure decision D1 + rejected splitting the roster between `han-planning` and `han-coding`. +- **Location:** `CONTRIBUTING.md:203-211`. `docs/plans/han-core-restructure/artifacts/decision-log.md:19-30`. +- **Evidence:** + ``` + New agents live in `han-core` by default; an agent moves out only when a single skill family in one plugin above + `han-core` dispatches it exclusively. Today that is the readability-editor, ... the research-analyst, ... and the + discussion-facilitator, living in `han-planning` with `plan-implementation`. + ``` + D1: "Split the roster between han-planning and han-coding — rejected because their dispatch sets overlap heavily and + the union covers nearly every agent (E1, E2)." +- **Raised by:** structural-analyst S-2. Behavioral-analyst B-21. Research A28, A29. +- **Confidence:** Verified. `CONTRIBUTING.md:25` says "four exceptions" while line 205 names three, a small internal + mismatch. +- **Bears on:** — + +### C-3: Every existing cross-plugin agent dispatch is a qualified name backed by a hard dependency + +- **Claim:** Every dispatching plugin already declares `han-core`. Nothing in the suite dispatches a shipped agent + through a role or conditionally on installation. +- **Location:** `*/.claude-plugin/plugin.json`. Dispatch prose, for example + `han-planning/skills/plan-a-change/SKILL.md:198`. +- **Evidence:** + ``` + han-coding, han-ddd, han-documentation, han-planning, han-research: [han-communication, han-core] + han-github: [han-communication, han-core, han-coding] + han-atlassian: [han-communication, han-core, han-documentation, han-planning, han-coding] + han-feedback, han-linear, han-plugin-builder, han-communication: [] han-reporting: [han-communication] + ``` + "Dispatch `han-core:software-architect` with the current-state findings…" (no absence handling nearby). +- **Raised by:** structural-analyst S-1. Behavioral-analyst B-1, B-21. +- **Confidence:** Verified. +- **Bears on:** — + +### C-4: Plugins without a han-core dependency only mention agents and never dispatch them + +- **Claim:** `han-feedback` parses `subagent_type` strings from session logs as data. `han-plugin-builder` uses agent + names as illustrative examples (`example-plugin:structural-analyst`). `han-atlassian` names `han-core:codebase-explorer` + only in prose describing what the `han-coding` skill it wraps does. +- **Location:** `han-feedback/skills/han-feedback/SKILL.md:57,101,193`; + `han-plugin-builder/skills/guidance/references/skill-building-guidance/agent-dispatch-namespacing.md:20-64`; + `han-atlassian/skills/code-overview-to-confluence/SKILL.md:74`. +- **Evidence:** "`subagent_type` is `han-core:adversarial-security-analyst`, or skill output naming a Han agent it + launched". +- **Raised by:** structural-analyst S-3. Behavioral-analyst B-20. +- **Confidence:** Verified. +- **Bears on:** — + +### C-5: Agents name their siblings by bare name in their descriptions, in two dense clusters + +- **Claim:** "Does not X — use Y" routing lives in agent `description:` frontmatter and names siblings without a + namespace. The architecture sextet and the operations quintet each name nearly every other member. +- **Location:** `han-core/agents/*.md` frontmatter, lines 5-12. +- **Evidence:** + ``` + Architecture: structural-analyst, behavioral-analyst, concurrency-analyst, risk-analyst, + software-architect, system-architect + Operations: devops-engineer, on-call-engineer, observability-engineer, data-engineer, + adversarial-security-analyst + Pairs: test-engineer <-> edge-case-explorer; + content-auditor <-> information-architect <-> gap-analyzer; + user-experience-designer -> information-architect + ``` + Upward edges that already cross a plugin boundary: `codebase-explorer` and `evidence-based-investigator` say "use + research-analyst" (`han-research`), and `plan-synthesizer` names `discussion-facilitator` (`han-planning`). +- **Raised by:** structural-analyst S-4. +- **Confidence:** Verified. +- **Bears on:** — + +### C-6: Agents cannot dispatch, so routing text is advice to the caller and never fails at runtime + +- **Claim:** No agent's `tools:` line includes `Agent`. A sibling name in an agent body is a record entry for the human + or the calling skill, not a dispatch. +- **Location:** `han-core/agents/plan-synthesizer.md:11`, `han-planning/agents/discussion-facilitator.md:12`, and every + other agent's frontmatter. +- **Evidence:** `tools: Read, Glob, Grep, Bash(git *), Bash(find *), Write` +- **Raised by:** behavioral-analyst B-18. +- **Confidence:** Verified. +- **Bears on:** — + +### C-7: Three agents carry hand-copied roster lists that assume every specialist is present + +- **Claim:** `plan-synthesizer`, `junior-developer`, and `discussion-facilitator` each carry a "specialists available on + this team" list by bare name. Each one tells its reader to record whether each specialist "must still be brought in". + None of them can tell which specialists are installed. The `plan-synthesizer` list omits `data-engineer`, + `on-call-engineer`, and `observability-engineer`, all three of which planning dispatches. +- **Location:** `han-core/agents/plan-synthesizer.md:136-159` (repeated as a `Domain:` enum at :354); + `han-core/agents/junior-developer.md:227-248`; `han-planning/agents/discussion-facilitator.md:135-150`. +- **Evidence:** `**Test planning for observable behavior** → `test-engineer`` (plan-synthesizer :153); + `**Test planning depth, behavior-focused tests, test doubles** → `test-engineer`` (junior-developer :241). +- **Raised by:** structural-analyst S-5, S-6. Behavioral-analyst B-18, B-22. +- **Confidence:** Verified for the lists. Exact line ranges for `junior-developer` and `discussion-facilitator` came from + excerpts. +- **Bears on:** — + +### C-8: Selection-condition prose for the same agent is duplicated across five consumer files in three plugins + +- **Claim:** Each consumer writes its own "select X when…" trigger text, often near-verbatim. Example: the + `observability-engineer` trigger appears in code-review, plan-a-feature, and gap-analysis. +- **Location:** `han-coding/skills/code-review/references/agent-dispatch.md:28-43`; + `han-planning/skills/plan-a-feature/references/review-team-briefs.md:18-30`; + `han-planning/skills/iterative-plan-review/references/team-selection.md:8-96`; + `han-planning/skills/plan-implementation/references/team-selection.md:22-157`; + `han-research/skills/gap-analysis/SKILL.md:173-195`. +- **Evidence:** "metric instruments or labels, span attributes, log schemas, OpenTelemetry SDK setup (samplers, + exporters, resource…" appears at `agent-dispatch.md:39` and `review-team-briefs.md:24`. +- **Raised by:** structural-analyst S-12, S-13. +- **Confidence:** Verified for the cited pair. Not checked across every agent. +- **Bears on:** — + +### C-9: The only skip-with-a-note rule covers config-named extra agents, not shipped agents + +- **Claim:** `config-rule.md` skips an extra agent that does not resolve, with a one-line note. Its degradation rule + confines notes to "content that attempts a recognized override", so an unfilled role is not covered as written. The + extras clause is repeated at 11 call sites. +- **Location:** `han-core/references/config-rule.md:111-139`. The call sites include + `han-planning/skills/*/references/team-selection.md`, `han-coding/skills/code-review/references/agent-dispatch.md:63-66`, + `han-coding/skills/{architectural-analysis,investigate,automated-test-planning,design-an-api}/SKILL.md`, and + `han-research/skills/research/SKILL.md:177-181`. +- **Evidence:** + ``` + An entry that does not resolve to a dispatchable agent is skipped with the one-line note naming it. + ... + Show a one-line note only when content that attempts a recognized override cannot be used; pass over + everything else silently. + ``` +- **Raised by:** behavioral-analyst B-3. Research A23. +- **Confidence:** Verified. +- **Bears on:** — + +### C-10: Some dispatches are required producers and others are optional pool members, and only the second can go unfilled safely + +- **Claim:** An agent that a skill always dispatches as the sole producer of a section cannot be an optional role + without breaking that skill. Pool members chosen by signal under a cap can go unfilled with fewer reviewers as the + only cost. +- **Location:** the table in C-20. +- **Evidence:** "`han-core:structural-analyst`, `han-core:behavioral-analyst`, `han-core:risk-analyst`, and + `han-core:software-architect` run at every size BECAUSE structure, runtime behavior, risk-of-inaction, and SOLID + synthesis are the irreducible core of an architectural read." (`han-coding/skills/architectural-analysis/SKILL.md:39-44`) +- **Raised by:** behavioral-analyst B-2, B-12 to B-15. +- **Confidence:** Verified. +- **Bears on:** — + +### C-11: Two "absent agent" precedents already exist, system-architect's deferral note and plan-synthesizer's band skip + +- **Claim:** `architectural-analysis` and `plan-a-change` already render a no-`system-architect` state as a one-line + deferral. `gap-analysis` already consolidates without `plan-synthesizer` at small size. Code-review prints a named + coverage gap when the security analyst is absent from a typed run, and marks per-agent "Not covered". +- **Location:** `han-coding/skills/architectural-analysis/SKILL.md:270-273`; + `han-planning/skills/plan-a-change/SKILL.md:203`; `han-research/skills/gap-analysis/SKILL.md:58-61,315`; + `han-coding/skills/code-review/SKILL.md:131-134`; `han-coding/skills/code-review/references/agent-dispatch.md:275-277`. +- **Evidence:** "If `han-core:plan-synthesizer` is not on the team, skip to Step 6." / "`Security analysis did not run on + this review.`" +- **Raised by:** behavioral-analyst B-6, B-11, B-12, B-14. +- **Confidence:** Verified. +- **Bears on:** — + +### C-12: Skills count team caps in two incompatible ways + +- **Claim:** `plan-implementation`, `plan-a-change`, and `iterative-plan-review` count chosen specialists only. + `plan-a-feature`, `architectural-analysis`, `design-an-api`, `research`, and `gap-analysis` count total seats. + Code-review has no numeric cap. The spike's "counted once against the team's size cap" presumed a single model. +- **Location:** `han-planning/skills/plan-implementation/references/team-selection.md:18-19`; + `han-planning/skills/plan-a-feature/SKILL.md:296-302`; `han-coding/skills/architectural-analysis/SKILL.md:158-162`; + `han-coding/skills/code-review/references/agent-dispatch.md:69`. +- **Evidence:** "The cap is counted in **chosen specialists**, not in total seats." vs. "Small | 2 + (han-core:junior-developer + 1 chosen specialist)". +- **Raised by:** behavioral-analyst B-10. +- **Confidence:** Verified. +- **Bears on:** — + +### C-13: Code-review uses the same agent as required in one review type and optional in another + +- **Claim:** Each typed review has `Always:` and `When relevant:` agents. A default run always dispatches only + `junior-developer` and `adversarial-security-analyst`. +- **Location:** `han-coding/skills/code-review/references/types/*.md:9-10`; + `han-coding/skills/code-review/SKILL.md:116-120`. +- **Evidence:** + ``` + architecture: Always structural, behavioral | data: Always data-engineer; relevant on-call + observability: Always observability | release: Always devops; relevant data-engineer + testing: Always test-engineer, edge-case-explorer | resilience: Always on-call; relevant concurrency + ux: Always user-experience-designer | maintainability: Always junior-developer + docs: Always information-architect; relevant content-auditor + work-ticket: Always gap-analyzer; relevant test-engineer | security: Always adversarial-security-analyst + ``` +- **Raised by:** behavioral-analyst B-7. +- **Confidence:** Verified. +- **Bears on:** — + +### C-14: Code-review's manual-only mode might fire for a single missing agent + +- **Claim:** Code-review switches the whole run to manual-only when a dispatch call "is made and denied". Whether an + unknown agent name lands there, or in the per-agent "Not covered" path, is undetermined. +- **Location:** `han-coding/skills/code-review/references/agent-dispatch.md:282-311`. +- **Evidence:** "Do not probe for availability before dispatching; the attempt is the detection." +- **Raised by:** behavioral-analyst B-5. +- **Confidence:** Unverified. The Agent tool's error for an unknown name could not be inspected. +- **Bears on:** — + +### C-15: Agent bodies cite no han-core reference files, and long-form docs link to their agent by relative path + +- **Claim:** Moving an agent file breaks no reference-file path inside it. Its long-form doc in `han-core/docs/agents/` + links `../../agents/{name}.md` and has to move with it. `han-research/docs/skills/gap-analysis.md:371` links + `../../../han-core/agents/gap-analyzer.md` directly. +- **Location:** `han-core/agents/*.md`; `han-core/docs/agents/*.md:5`; `docs/agents/README.md` (23 links). +- **Evidence:** a grep of agent bodies for `references/`, `han-core/`, `evidence-rule`, `yagni`, `config-rule`, and + `readability` returned no hits. +- **Raised by:** structural-analyst S-10, S-11. +- **Confidence:** Verified. +- **Bears on:** — + +### C-16: Tooling and evals hard-code han-core as the agent home + +- **Claim:** Three eval suites dispatch agents by `han-core:` name. The repo's own doc-update skill treats + `han-core/agents` as the single agent root. The plugin-builder guidance teaches `han-core:agent-name` qualified + dispatch. +- **Location:** `evals/{test-engineer,edge-case-explorer,gap-analyzer}/tests.json` (`"agentFile": "han-core:{name}"`, + `"plugins": ["han-core"]`); `.claude/skills/han-update-documentation/scripts/detect-doc-update-context.sh:18`, `SKILL.md:89`, + `references/scope-mapping.md:12,56`, and `references/audit-checklist.md:19,81,93`; + `han-plugin-builder/skills/guidance/assets/rule-index-body.md:97`. +- **Evidence:** `# agent-root the single directory that holds agents (han-core/agents),` +- **Raised by:** structural-analyst S-11. Run sweep (script header read). +- **Confidence:** Verified for the header. Whether the script body already walks more than one agent directory is + Unverified. Agents already live in four plugins, so it likely misses three today. +- **Bears on:** — + +### C-17: CLAUDE.md on disk matches the reverted state, which corrects S-14 + +- **Claim:** The structural pass reported that CLAUDE.md still describes `agent-roles.md` and a moved `test-engineer`. + It read the instructions loaded at session start, before the revert. On disk, CLAUDE.md has zero `agent-roles` + mentions, and the revert's diff against `1de07d0` is empty. +- **Location:** `CLAUDE.md`. +- **Evidence:** `grep -c "agent-roles" CLAUDE.md` → `0`; `git diff 1de07d0 --stat` → no output. +- **Raised by:** run sweep, correcting structural-analyst S-14. +- **Confidence:** Verified. +- **Bears on:** — + +### C-18: The reverted spike is the only worked example of the role mechanism + +- **Claim:** The spike defined a `han-planning`-owned `agent-roles.md` that holds the claim sentence, a four-step fill + procedure, and one role. It added a Bats test that checks claim syntax, not runtime fill. It edited only planning + consumers, so it never exercised the total-seat cap skills or code-review. It moved the long-form doc, rewrote the + `han-coding` dispatch namespace, rewrote routing text in three agents, and changed 13 eval references. +- **Location:** `git show 24e3ccd:han-planning/references/agent-roles.md`; `git show abdb80a:test/agent-roles.bats`; + commit stats for `1ea9d0c` and `3e276b8`. +- **Evidence:** + ``` + Fills the han-planning `test-planning` role. + ... + 4. If none claims it, skip the role and add one line to the team announcement, for example: "Skipped the + `test-planning` role: no installed agent fills it." This is not an error, and the run continues. + ``` +- **Raised by:** behavioral-analyst B-10, B-17. Structural-analyst S-14. Run sweep. +- **Confidence:** Verified. It was never run end to end, which is Unverified (B-11). +- **Bears on:** — + +### C-19: Per-agent dispatch map + +- **Claim:** Where each agent is dispatched. Routing-only and mention-only references are excluded. Details and line + numbers are in the structural pass's table, preserved in summary here. +- **Location:** see each row. +- **Evidence:** + + | Agent | Dispatching plugins and skills | + | --- | --- | + | adversarial-security-analyst | coding: architectural-analysis, automated-test-planning, code-review (default always), design-an-api; planning: iterative-plan-review, plan-a-change, plan-a-feature, plan-implementation; research: gap-analysis | + | adversarial-validator | coding: code-overview, code-review (7.4), design-an-api, investigate, manual-test-planning; planning: iterative-plan-review; research: gap-analysis, research | + | behavioral-analyst | coding: architectural-analysis, code-review, design-an-api, investigate; ddd: ddd-analysis; planning: 4 skills | + | codebase-explorer | coding: architectural-analysis, code-overview, code-walkthrough, coding-standard, design-an-api; documentation: adr, project-documentation; planning: iterative-plan-review; research: gap-analysis, research | + | concurrency-analyst | coding: architectural-analysis, automated-test-planning, code-review, design-an-api, investigate; planning: 4 skills | + | content-auditor | coding: code-review (docs, relevant); documentation: project-documentation; planning: iterative-plan-review; research: gap-analysis | + | data-engineer | coding: architectural-analysis, code-review, design-an-api, investigate; planning: iterative-plan-review, plan-a-change, plan-implementation; research: gap-analysis | + | devops-engineer | coding: architectural-analysis, code-review; planning: 4 skills; research: gap-analysis | + | edge-case-explorer | coding: automated-test-planning, code-review; planning: iterative-plan-review, plan-a-feature, plan-implementation | + | evidence-based-investigator | coding: investigate; planning: iterative-plan-review; research: gap-analysis | + | gap-analyzer | coding: code-review (work-ticket); planning: iterative-plan-review, plan-a-feature; research: gap-analysis | + | information-architect | coding: automated-test-planning, code-review, coding-standard; documentation: project-documentation; planning: plan-a-phased-build (plan-work-items names it in a catalog only); research: gap-analysis | + | junior-developer | coding: automated-test-planning, code-review, coding-standard, design-an-api; documentation: adr; github: post-code-review-to-pr, update-pr-description; planning: 4 skills + round aggregation; research: gap-analysis | + | observability-engineer | coding: architectural-analysis, code-review; planning: 4 skills; research: gap-analysis | + | on-call-engineer | coding: architectural-analysis, code-review, code-walkthrough, design-an-api; planning: 4 skills; research: gap-analysis | + | plan-synthesizer | planning: plan-a-feature, plan-implementation, plan-work-items; research: gap-analysis | + | project-scanner | core: project-discovery | + | risk-analyst | coding: architectural-analysis; documentation: adr; planning: 4 skills | + | software-architect | coding: architectural-analysis, design-an-api; documentation: adr; planning: 4 skills; research: gap-analysis | + | structural-analyst | coding: architectural-analysis, code-review, design-an-api; ddd: ddd-analysis; planning: 4 skills | + | system-architect | coding: architectural-analysis, design-an-api; documentation: adr; planning: 4 skills; research: gap-analysis; ddd: named as a next step only | + | test-engineer | coding: automated-test-planning, code-review; planning: iterative-plan-review, plan-a-change, plan-a-feature, plan-implementation | + | user-experience-designer | coding: code-review (ux type); planning: 4 skills; research: gap-analysis | + +- **Raised by:** structural-analyst S-9, corrected for `research` dispatching `adversarial-validator` and + `codebase-explorer`. +- **Confidence:** Verified for plugin membership. The skill lists rest on a grep plus spot-checks. +- **Bears on:** — + +### C-20: Required versus optional, per plugin, for every agent + +- **Claim:** Which plugins *require* each agent, meaning an always-dispatched sole producer or a fixed seat whose absence + breaks the skill's output. Every other dispatch is optional. +- **Location:** the behavioral pass's table, which follows B-14. +- **Evidence:** + + | Agent | Required in | Optional in | + | --- | --- | --- | + | junior-developer | coding, planning, documentation, github, research | — | + | codebase-explorer | coding, documentation | research (conditional), planning | + | adversarial-validator | coding, planning (iterative-plan-review), research | — | + | structural-analyst, behavioral-analyst | coding, planning (plan-a-change discovery), ddd | — | + | software-architect | coding, planning (plan-a-change), documentation (adr) | research | + | risk-analyst | coding, documentation (adr) | planning | + | system-architect | — (conditional with a documented absent state everywhere) | coding, planning, documentation, research | + | concurrency-analyst | — (conditional everywhere; in architectural-analysis's small band) | coding, planning | + | information-architect | coding (coding-standard, code-review docs), planning (plan-a-phased-build), documentation | research | + | gap-analyzer | research (sole analyzer), coding (work-ticket type) | planning | + | plan-synthesizer | planning (3 skills) | research (medium and large only, with a fallback) | + | evidence-based-investigator | coding (investigate) | planning (iterative-plan-review, conditionally mandatory), research | + | test-engineer, edge-case-explorer | coding | planning | + | adversarial-security-analyst | coding (code-review default run) | planning, research | + | devops, on-call, observability, data-engineer | coding (typed code-review runs) | planning, research, coding's other skills | + | user-experience-designer | coding (ux type) | planning, research | + | content-auditor | documentation (conditional, Step 6 flag) | coding, planning, research | + | project-scanner | core | — | + +- **Raised by:** behavioral-analyst B-2, B-7, B-12 to B-16, synthesized by this run. +- **Confidence:** Verified for the sites the behavioral pass read. The "required" label is this run's synthesis of its + always/optional table. +- **Bears on:** — + +## Findings No Agent Could Audit + +- **What the Agent tool returns for an unknown agent name.** This is host runtime, not in the repo, and the research + sources conflict (A8, A9). Closing it takes a live session that dispatches a non-existent `plugin:agent` name. It + decides whether a role fill can safely try a dispatch, or must check the session's agent list first. +- **Whether every installed agent's description reaches a skill's context, including after compaction.** Research A7 + documents it, and this session's own agent list shows it directly (A34). Nobody tested it as a contract the model + reliably matches role claims against. Closing it takes one live run of a planning skill with and without the providing + plugin installed. +- **Codex.** Whether Codex shows agents and their descriptions to the model is undocumented (A12). diff --git a/docs/plans/han-core-agent-redistribution/artifacts/scope-boundary.md b/docs/plans/han-core-agent-redistribution/artifacts/scope-boundary.md new file mode 100644 index 00000000..e909f267 --- /dev/null +++ b/docs/plans/han-core-agent-redistribution/artifacts/scope-boundary.md @@ -0,0 +1,47 @@ +# Scope Boundary: han-core Agent Redistribution + +## Work Item + +No work item exists. The operator's request in the session on 2026-10-15 is the only boundary this run has. It points +at the research report `docs/research/cross-plugin-config-discovery.md` as the reason for the change. + +## Stated Scope + +The operator's request, quoted: + +> pick up the cross-plugin config work research again. let's roll back the spike, and do a full /plan-a-change against +> the research. i want you to do some analysis on the current agents in han-core, and provide recommendations for where +> each agent should live with justification, along with what role should be named and used by these agents + +The area confirmed in the confirmation turn: the 23 agents in `han-core/agents/`, plus everything that names them. +That covers skills in every plugin, other agents, evals, long-form docs, the skills and agents indexes, the agent +placement rule in `CONTRIBUTING.md`, `CLAUDE.md`, plugin manifests, and tests. + +## Stated Exclusions + +None stated in the request. + +## Operator-Stated Scope + +Stated in the confirmation turn: + +- "let's leave out the startup hook." The research report's option O1, a SessionStart hook in a providing plugin that + prints a contribution file into the session, is out of scope. +- "everything else looks good." The operator accepted that the plan may add or change plugin dependencies where a + placement calls for it, and accepted the output folder `docs/plans/han-core-agent-redistribution/`. +- The reverted `test-engineer` spike (commits `1ea9d0c`, `24e3ccd`, `abdb80a`, `3e276b8`, reverted in `2b73305`) is + evidence, not a decided outcome. + +## Direction of Travel + +Agents move out of `han-core` toward the plugins whose skills use them, wherever a named role lets a consumer run +without the providing plugin installed. The current placement rule (agents stay in `han-core` unless one skill family +in one plugin dispatches them exclusively) and restructure decision D1 are being revisited, not preserved. + +## Visual Material Received + +None received + +## Record Provenance + +Established by `plan-a-change` in this run. No earlier record existed in this folder or beside the research report.