diff --git a/CLAUDE.md b/CLAUDE.md index 3908a2a0..0144cde5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,7 +20,8 @@ implementation: specifying with `plan-a-feature`, planning the build with `plan- `iterative-plan-review`, plus the `discussion-facilitator` agent that audits a planning discussion in progress; depends on `han-communication` and `han-core` and is bundled by the `han` meta-plugin), `han-coding` (the coding skills -you reach for while working in code: writing it with `tdd` and `refactor`, plus reviewing, overviewing, analyzing, +you reach for while working in code: writing it with `tdd` and `refactor`, designing an interface contract with +`design-an-api`, plus reviewing, overviewing, analyzing, testing, investigating, and standardizing it with `code-review`, `code-overview`, `architectural-analysis`, `automated-test-planning`, `manual-test-planning`, `investigate`, and `coding-standard`; depends on `han-communication` and `han-core` and is bundled by the `han` meta-plugin), @@ -109,7 +110,7 @@ han-plugin-builder skill: │ ├── skills/ # Planning skill directories, each with SKILL.md + references/ │ ├── 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) beside vendored copies (yagni-rule.md, evidence-rule.md, config-rule.md). Each owned file opens by saying so; do not overwrite one in a re-sync sweep -├── han-coding/ # Coding plugin: tdd, refactor, code-review, code-overview, 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) +├── han-coding/ # Coding plugin: tdd, refactor, design-an-api, code-review, code-overview, 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 diff --git a/docs/skills/README.md b/docs/skills/README.md index aeada121..9eab0342 100644 --- a/docs/skills/README.md +++ b/docs/skills/README.md @@ -31,6 +31,9 @@ skill-and-agent split is fuzzy, read [Concepts](../concepts.md) first. or specified files, with a size-scaled roster of specialist agents. - [`/coding-standard`](../../han-coding/docs/skills/coding-standard.md) — Create and update coding standards from existing patterns or evidence-based research. +- [`/design-an-api`](../../han-coding/docs/skills/design-an-api.md) — Design the contract for an API change inside one + codebase, with every element justified from one stated goal and the design run past a question round and an + adversarial validation round. - [`/edit-for-readability`](../../han-communication/docs/skills/edit-for-readability.md) — Rewrite the prose of a target you already have against the shared readability standard, preserving every fact. - [`/explanation-guidance`](../../han-communication/docs/skills/explanation-guidance.md) — Surface the shared standard diff --git a/docs/workflows.md b/docs/workflows.md index 1d7bf029..2ba8441b 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -80,8 +80,10 @@ prepare the ground for a test-first build. flowchart TD review["/code-review"] --> refactor["/refactor"] arch["/architectural-analysis"] --> refactor + arch --> design["/design-an-api"] + design --> tdd["/tdd"] review --> pr["/post-code-review-to-pr"] - refactor --> tdd["/tdd"] + refactor --> tdd tdd --> prdesc["/update-pr-description"] investigate["/investigate"] --> iterate["/iterative-plan-review"] ``` @@ -95,6 +97,10 @@ flowchart TD work orders. - **[`/refactor`](../han-coding/docs/skills/refactor.md) → [`/tdd`](../han-coding/docs/skills/tdd.md).** Preparatory refactoring makes the change easy, then `/tdd` makes the easy change. +- **[`/architectural-analysis`](../han-coding/docs/skills/architectural-analysis.md) → + [`/design-an-api`](../han-coding/docs/skills/design-an-api.md) → [`/tdd`](../han-coding/docs/skills/tdd.md).** Judge + the structure you are designing into, shape the contract against one stated goal, then implement it test-first. The + analysis step is optional; `/design-an-api` runs its own discovery wave when you start there. - **[`/investigate`](../han-coding/docs/skills/investigate.md) → [`/iterative-plan-review`](../han-planning/docs/skills/iterative-plan-review.md).** Root-cause the bug, then stress-test the proposed fix. diff --git a/han-coding/.claude-plugin/plugin.json b/han-coding/.claude-plugin/plugin.json index 81ffd308..6875f924 100644 --- a/han-coding/.claude-plugin/plugin.json +++ b/han-coding/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "han-coding", - "description": "Coding-facing skills for the Han suite: writing, reviewing, testing, investigating, and standardizing code. Home of the tdd skill, which drives a feature or behavior through a BDD-framed red-green-refactor loop with an enforced observed-failure gate, and the refactor skill, which restructures existing code without changing its behavior through a test-gated refactoring loop, plus code-review (comprehensive review of local changes), code-overview (a progressive-disclosure, understand-now overview of unfamiliar code or a PR's changes), architectural-analysis (module-level coupling, data flow, concurrency, risk, and SOLID assessment), automated-test-planning (coverage-gap and edge-case test plans), manual-test-planning (plain-language manual test plans a person runs by hand), investigate (evidence-based root-cause debugging), and coding-standard (creating and updating coding standards). Depends on han-core and han-communication; bundled by the han meta-plugin.", + "description": "Coding-facing skills for the Han suite: writing, reviewing, testing, investigating, and standardizing code. Home of the tdd skill, which drives a feature or behavior through a BDD-framed red-green-refactor loop with an enforced observed-failure gate, and the refactor skill, which restructures existing code without changing its behavior through a test-gated refactoring loop, plus design-an-api (designing an interface contract for one stated goal through an options round, a question round, and an adversarial validation round), code-review (comprehensive review of local changes), code-overview (a progressive-disclosure, understand-now overview of unfamiliar code or a PR's changes), architectural-analysis (module-level coupling, data flow, concurrency, risk, and SOLID assessment), automated-test-planning (coverage-gap and edge-case test plans), manual-test-planning (plain-language manual test plans a person runs by hand), investigate (evidence-based root-cause debugging), and coding-standard (creating and updating coding standards). Depends on han-core and han-communication; bundled by the han meta-plugin.", "version": "3.0.0", "dependencies": ["han-communication", "han-core"] } diff --git a/han-coding/README.md b/han-coding/README.md index 107af3cf..c719c66a 100644 --- a/han-coding/README.md +++ b/han-coding/README.md @@ -12,6 +12,9 @@ specialist agents to cover each dimension in parallel. Reach for it once there i enforced observed-failure gate; it writes code, not a document. - [`/refactor`](docs/skills/refactor.md) — Restructure existing code without changing its behavior through a test-gated loop that re-runs the full suite after every small step. +- [`/design-an-api`](docs/skills/design-an-api.md) — Design the contract for an API change inside one codebase, with + every element justified from one stated goal and the design run past a question round and an adversarial validation + round. - [`/code-review`](docs/skills/code-review.md) — Run a comprehensive code review on the current branch or specified files, with a size-scaled roster of specialist agents. - [`/code-overview`](docs/skills/code-overview.md) — Produce a human-readable, progressive-disclosure overview of diff --git a/han-coding/docs/skills/design-an-api.md b/han-coding/docs/skills/design-an-api.md new file mode 100644 index 00000000..78a72785 --- /dev/null +++ b/han-coding/docs/skills/design-an-api.md @@ -0,0 +1,154 @@ +# /design-an-api + +Operator documentation for the `/design-an-api` skill in the han plugin. This document helps you decide _when_ and _how_ +to use the skill. For what the skill does internally, read the skill definition at +[`han-coding/skills/design-an-api/SKILL.md`](../../skills/design-an-api/SKILL.md). + +> See also: [Plugin README](../../README.md) · [Repo root](../../../README.md) · +> [All skills](../../../docs/skills/README.md) · [All agents](../../../docs/agents/README.md) · +> [YAGNI](../../../docs/yagni.md) + +## TL;DR + +- **What it does.** Designs the contract for an API change inside one codebase, running the design past a question round + and an adversarial validation round before you commit to it. +- **When to use it.** You know what the capability should do, and you need to decide the shape of the interface that + delivers it, sized for roughly one pull request. +- **What you get back.** A run folder holding a context brief, a design-options document, and the final design document + that a `/tdd` run implements against. + +## Key concepts + +- **The stated goal.** One ticket, issue, or written requirement the whole design answers to. The skill will not run + without one, because it is the only thing the design can be justified against. +- **The justification field.** Every parameter, field, type, default, precedence rule, and failure behavior names either + the goal language it descends from or the asked-for behavior it is a necessity of. +- **The cut list.** Anything the interface could plausibly carry that the goal never asks for, recorded with what it + would have done so you can put it back. +- **The two gates.** You pick the design option, and later you answer each open item one at a time. Everything else + runs unattended. + +## When to use it + +**Invoke when:** + +- A ticket asks for a capability and the real work is deciding the interface: a component's props, a function surface, + URL or query parameters, an event payload, or a module boundary. +- You are about to change a shared surface and want the consumer audit and the failure behavior settled before anyone + writes code. +- A branch already carries a half-built attempt and you want the contract redesigned from the merge base instead. + +**Do not invoke for:** + +- **Deciding what a feature should do.** Use [`/plan-a-feature`](../../../han-planning/docs/skills/plan-a-feature.md) + instead; it settles behavior, this settles contract shape. +- **Planning how to deliver the work.** Use + [`/plan-implementation`](../../../han-planning/docs/skills/plan-implementation.md) instead. +- **Judging the architecture already in the codebase.** Use + [`/architectural-analysis`](./architectural-analysis.md) instead; it assesses what exists rather than designing what + comes next. +- **Writing the code.** Use [`/tdd`](./tdd.md) to implement the design, or [`/refactor`](./refactor.md) to restructure + existing code without changing its behavior. + +## How to invoke it + +Run `/design-an-api` in Claude Code. + +Give it: + +1. **The goal.** A ticket reference, issue URL, file path, or one paragraph describing what this change is for. A sharp + goal names the user-visible outcome ("a link can prefill the first two steps of the signup flow"). A thin goal names + only the mechanism ("add query param support"), which gives the justification field nothing to cite. +2. **The interface.** Which component, function, module, route, or payload is being designed, and where it lives. A new + surface with no file yet is fine; name the module it will live in. +3. **A size, optionally.** `small`, `medium`, `large`, or `dynamic` as the first argument. Leave it off and the skill + classifies from signals it detects in the interface and its consumers. + +Example prompts: + +- `/design-an-api`. _"Design the change to FlowProvider that lets URL query values prefill a flow's steps, per + ticket ABC-142."_ +- `/design-an-api medium https://github.com/acme/app/issues/88 the exported cache client surface in src/cache/`. + +## What you get back + +Three files in one run folder, placed under your configured `output-directory` or a folder named for the interface +under the project's documentation root: + +- **`context-brief.md`.** Numbered findings `F1`, `F2`, `F3`, … from the discovery wave. Each finding carries a + `file:line` citation or the label `inferred`, plus the agent that reported it. Conflicting findings stay as separate + entries with both citations rather than being resolved silently. +- **`design-options.md`.** The two or three options the architect produced, with one recommendation, the rejected + alternatives and why, and pseudocode sketches of each option's signatures. +- **`api-design.md`.** The deliverable. It holds the designed contract in three parts (surface, invariants, failure + behavior), the justification table, the options considered, the questions resolved (`Q1`, `Q2`, … each with its + answer's source), the validation findings (`V1`, `V2`, … each accepted or rejected), the cut list, and the open + risks. + +If any of the three files already exists in the folder, the run date-suffixes all three so one run's files stay +together, and tells you which names it wrote. It never overwrites. + +## How to get the most out of it + +- **Paste the ticket, do not paraphrase it.** The justification field quotes the goal. A paraphrase you wrote from + memory becomes the scope authority, and it drifts. +- **Answer the open items with the consequence in mind.** Each one is surfaced with candidate answers and what changes + in the contract; the answer you give becomes the recorded justification for those elements. +- **Read the cut list before you approve.** It is the only place the design tells you what it deliberately left out. + Reinstating an entry is one sentence, and your direction becomes its justification. +- **Re-run larger when the closing summary names an omitted domain.** The band cap can drop a signalled specialist. The + summary says which one. +- **Pair with `/tdd` next.** The design document is written to be the input to a test-first implementation run. + +## YAGNI + +This skill is enforcing, not advisory. An element that cannot fill its justification field does not enter the design at +all; it moves to the cut list with what it would have done and why it was cut. The cut list appears in the closing +message as well as the document, so a wrong cut is visible in the turn rather than buried in a file you have no reason +to open. + +One floor bounds that discipline: silence never cuts a necessity. A goal that never mentions a caching layer justifies +cutting one, but the same goal's silence about invalid input, error behavior, and types cuts nothing, because those are +necessities of the surface it did ask for. See [YAGNI](../../../docs/yagni.md) for the shared evidence and +simpler-version gates this sits beside. + +## Cost and latency + +A small run dispatches four agents in sequence-with-one-parallel-wave: the discovery wave, then the architect, the +junior developer, and the adversarial validator. A large run adds as many as four signalled specialists to the discovery +wave, for up to eight agents total. Only signalled specialists are added, so a run at a size you set by hand can sit +under its band's ceiling. The architect is the most expensive single participant, because it runs up to four times: once +for options and once after each of the question round, the open items, and the validation round. + +This is an infrequent, high-signal run. It sits before implementation, not inside a tight loop. + +## In more detail + +The skill exists because the arrangement it packages was already working by hand. A session documented in +[issue #173](https://github.com/testdouble/han/issues/173) dispatched `han-core:software-architect`, +`han-core:junior-developer`, and `han-core:adversarial-validator` directly, against a hand-assembled context brief, to +design a query-parameter prefill contract on a shared React flow provider. The designed API shipped essentially as +specified and survived a later code review. One junior-developer question reversed a naming decision before any code +existed. + +What the skill adds to that arrangement is the discovery step the session assembled ad hoc, the size band that scales +the roster, and the two gates in fixed positions. What it deliberately does not add is the full analyst fan-out that +`/architectural-analysis` runs: that roster is built to assess an existing module across every dimension, and it is +oversized for shaping one contract. + +## Related documentation + +- [Plugin README](../../README.md). The plugin's front door: its skills, agents, and how they fit together. +- [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 evidence-based "You Aren't Gonna Need It" rule: the two gates, the + acceptable-evidence list, the named anti-patterns, and the deferral format. +- [`/tdd`](./tdd.md). The implementation run this design document feeds. +- [`/architectural-analysis`](./architectural-analysis.md). Assesses the module you are about to change, when you want + the existing structure judged before designing into it. +- [`software-architect`](../../../han-core/docs/agents/software-architect.md). Produces the options and every + amendment. +- [`junior-developer`](../../../han-core/docs/agents/junior-developer.md). Questions the chosen option as a generalist + who was not in the room. +- [`adversarial-validator`](../../../han-core/docs/agents/adversarial-validator.md). Attacks the amended design and the + evidence under it. diff --git a/han-coding/skills/architectural-analysis/SKILL.md b/han-coding/skills/architectural-analysis/SKILL.md index 1cf7fc8b..bc4a044c 100644 --- a/han-coding/skills/architectural-analysis/SKILL.md +++ b/han-coding/skills/architectural-analysis/SKILL.md @@ -6,8 +6,8 @@ description: review the architecture, design quality, dependency structure, coupling, cohesion, or technical debt of an existing part of the codebase. Not for investigating specific bugs, runtime errors, or failures — use investigate. Not for test planning — use automated-test-planning. Not for file-level code review — use code-review. Not for researching open-ended - options, prior art, or how something works — use research. Not for writing documentation or architectural decision - records." + options, prior art, or how something works — use research. Not for designing a new interface or contract — use + design-an-api. Not for writing documentation or architectural decision records." arguments: size argument-hint: "[size: small | medium | large | dynamic] [focus area: module, directory, or feature to analyze]" allowed-tools: Read, Glob, Grep, Agent, Bash(find *) diff --git a/han-coding/skills/design-an-api/SKILL.md b/han-coding/skills/design-an-api/SKILL.md new file mode 100644 index 00000000..8b25c234 --- /dev/null +++ b/han-coding/skills/design-an-api/SKILL.md @@ -0,0 +1,371 @@ +--- +name: design-an-api +description: > + Designs the contract for an API change inside one codebase — a component's props, a function surface, URL or query + parameters, an event payload, or a module boundary — through a discovery pass, an options document with one + recommendation, a question round, and an adversarial validation round, with every element of the contract justified + from one stated goal. Use when you want to design, shape, decide, or nail down an interface, contract, signature, or + API change for a capability you can already describe, sized for roughly one pull request. Produces a design document + and changes no code. Does not specify what a feature should do — use plan-a-feature. Does not plan delivery or + sequencing — use plan-implementation. Does not assess the architecture of existing code — use + architectural-analysis. Does not write the code — use tdd. Does not restructure existing code — use refactor. +arguments: size +argument-hint: + "[size: small | medium | large | dynamic] [the goal or ticket this serves, and the interface to design]" +allowed-tools: Read, Write, Glob, Grep, Agent, Bash(git *), Bash(find *), Bash(mkdir *) +--- + +## Project Context + +- git installed: !`which git 2>/dev/null || echo "not installed"` +- current branch: !`git branch --show-current 2>/dev/null || echo "no git branch"` +- default branch: !`git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null || echo unknown` +- CLAUDE.md: !`find . -maxdepth 1 -name "CLAUDE.md" -type f` +- project-discovery.md: !`find . -maxdepth 3 -name "project-discovery.md" -type f` +- personal config directory: !`echo "${CLAUDE_CONFIG_DIR:-$HOME/.claude}"` +- project .han/config.md: !`cat .han/config.md 2>/dev/null || echo ""` + +As your first action, use the Read tool on `.han/config.md` inside the `personal config directory` path above. A read +that returns no file is no personal configuration: continue silently. When that file or the `project .han/config.md` +probe supplies content, apply it per [config-rule.md](../../references/config-rule.md), which governs precedence +between the two files, relative-path resolution, and what to do with a file that reads but cannot be used. + +## Operating Principles + +Read these before dispatching anything. They constrain every step below. + +- **A stated goal is required, and it is the scope governor.** This skill designs a contract in service of one named + goal: a ticket, an issue, a written requirement, or a described capability. If no goal resolves, stop and ask for one + BECAUSE without a goal there is nothing to justify the design against, and the run degrades into designing a + general-purpose framework for a single consumer. +- **Every element of the contract carries a justification.** Each named parameter, field, type, default, precedence + rule, and failure behavior states exactly one of two things: the part of the stated goal it descends from, quoted or + named; or the asked-for behavior it is a necessity of. An element that can fill neither does not enter the design. It + moves to the cut list with what it would have done and why it was cut. +- **Silence never cuts a necessity.** The goal is short and does not enumerate what it depends on. A goal that never + mentions a caching layer justifies cutting one. The same goal's silence about invalid input, error behavior, and + types does not cut those, because they are necessities of the surface it did ask for. +- **The agents own the judgment; the skill orchestrates.** The skill resolves the goal and the interface, classifies + size, selects the roster, fans agents out and in, runs the two human gates, and renders the design document. It + produces no design content of its own. +- **The four-agent spine always runs; specialists are signal-selected.** `han-core:codebase-explorer`, + `han-core:software-architect`, `han-core:junior-developer`, and `han-core:adversarial-validator` run at every size + BECAUSE evidence, design, questioning, and attack are the irreducible core of a contract that survives contact. Every + other specialist is added only when the interface's signals warrant it and the band allows it, BECAUSE dispatching an + agent whose domain the contract never touches burns tokens and pulls the design toward concerns the goal did not ask + for. +- **Default to small.** Start classification at small and escalate only when a higher-band signal is clearly present. + Borderline signals stay at the smaller band. Under-dispatching is recoverable by re-running at a larger size; + over-dispatching is not. +- **This skill changes no code.** It produces a design document. Implementation is a separate, later step, normally a + `tdd` run against this document. +- **Options before commitment.** The architect produces two or three real options with one recommendation, not a single + design with alternatives invented afterward to justify it. The user picks before three further agent rounds are spent + refining one. +- **The design document template lives at + [references/api-design-template.md](./references/api-design-template.md).** The skill renders that template by filling + its sections. It does not invent a structure inline. +- **The document is written for a named reader.** As the skill writes the design document's synthesized prose, it + sources the shared standard by invoking `han-communication:readability-guidance` and applies it, holding one audience + above the writing: the engineer who will implement this contract and the reviewer who will approve it. Scope that + frame per section so the specifics that reader needs — exact signatures, types, precedence rules, file paths — are + preserved, never simplified away. + +# Design an API + +## Step 1: Resolve the Goal, the Interface, and the Starting Point + +**Bind `$size`.** If the user passed `small`, `medium`, `large`, or `dynamic` as the first positional argument, bind +`$size` to it. Anything else is part of the goal-and-interface context, not a size; bind `$size` to the literal +`none provided`. + +**Resolve the goal.** Take the remaining argument and conversation context as the goal this design serves. A ticket +reference, issue URL, file path, or a described capability all qualify. Read the referenced material if it names a file +or is fetchable from the conversation. Record the goal verbatim where it is quotable — the justification field in every +later step cites it. If no goal resolves, stop and ask the user for the ticket, issue, or one-paragraph statement of +what this change is for. Do not proceed without it. + +**Resolve the interface.** Identify what is being designed: which component, function, module, route, or payload, and +where it lives. Confirm it resolves to real files using `Glob` and `Read`. If the interface is genuinely new and has no +file yet, resolve instead the module or directory it will live in and the consumers that will call it. If neither +resolves, ask the user to name the surface before going further. + +**Resolve the starting point.** Read the `current branch` and `default branch` values from Project Context. When +`default branch` reads `unknown`, `origin/HEAD` is unset and there is no base to compare against: the working tree is +the starting point, no question is asked, and the run continues. Otherwise run +`git diff --name-only {default branch}...HEAD` and check whether any interface file resolved above appears in the +output. Only when one does, ask the user in one short message whether to design from the branch as it stands or from +the merge base, ignoring the branch's changes; read the merge-base state with `git show` when they choose the merge +base. In every other case — no interface file changed on the branch, git unavailable, or the command fails — the +working tree is the starting point and no question is asked. State the chosen starting point in one line. + +**Resolve project context.** If `CLAUDE.md` is present, read its `## Project Discovery` section for conventions. Fall +back to `project-discovery.md`. These resolve language, framework, and convention questions so the agents infer less. If +neither exists, the agents fall back to surrounding-code inference — note this in the briefs. + +**Resolve the output folder.** The run writes three files: `{folder}/context-brief.md`, `{folder}/design-options.md`, +and `{folder}/api-design.md`. Resolve `{folder}` in this order: + +1. If the user specified an output folder, use it. +2. If the project or personal config sets an `output-directory`, place the run folder under it, per + [config-rule.md](../../references/config-rule.md). +3. Otherwise, choose a 2-to-4-word kebab-case folder named for the interface, under a documentation root surfaced via + `CLAUDE.md`, `project-discovery.md`, or a Glob fallback (`docs/plans/`, `docs/`). + +Create the folder with `mkdir -p`. Check all three names with `Glob` before writing anything. If any of the three +already exists there, write every file this run produces to a date-suffixed name (for example `api-design-2026-08-07.md` +alongside `context-brief-2026-08-07.md` and `design-options-2026-08-07.md`) so one run's files stay together, and state +which files were written; never silently overwrite. State the chosen folder in one short line and proceed without +waiting for confirmation. + +## Step 2: Detect Signals and Classify Size + +Run targeted `Grep` and `Glob` over the interface and its consumers to detect which domains the contract actually +touches. These signals drive both the band and the roster: + +- **Consumer-spread signal:** the interface has call sites beyond the module being changed — several components, several + routes, or an exported surface other packages import. +- **Ordering signal:** async, lifecycle, mount-order, retry-order, or event-order behavior is part of the contract, not + an implementation detail behind it. +- **Data-contract signal:** the interface carries persisted data, a schema or migration, a wire or event payload, or a + document shape that another system reads. +- **Trust-boundary signal:** the interface accepts untrusted input (URL and query parameters, request bodies, uploads) + or carries auth, tokens, secrets, or PII across the surface. +- **Failure-path signal:** the contract has to state what happens on failure — outbound calls, timeouts, retries, + idempotency, partial writes, or a failure that would page someone. +- **Boundary-data signal:** the contract moves data across a module boundary, or how errors propagate across that + boundary is itself part of what the design has to decide. +- **System-seam signal:** the interface crosses a deployable unit or bounded-context boundary — an RPC or HTTP contract + with a sibling service, a message broker topic, or a shared store across services. + +**Classify the size.** Default to small. Escalate only when a band's signal is clearly present; when a signal is +borderline, stay at the smaller band. + +- **Small** _(default)_ — one interface with a contained consumer set inside one module, and none of the ordering, + data-contract, trust-boundary, failure-path, boundary-data, or system-seam signals. +- **Medium** — a consumer-spread signal, OR exactly one of the ordering, data-contract, trust-boundary, failure-path, + or boundary-data signals. +- **Large** — two or more of those cross-cutting signals together, OR a system-seam signal is present, OR `$size` is + `large`. + +**Apply the size override.** If `$size` is not `none provided`, use it: a band value is the band and skips the +signal-based classification above, while `dynamic` forces the signal-based classification even when the project config +sets a default band. If `$size` is `none provided` and the project config supplies a band via `default-swarm-size` (per +[config-rule.md](../../references/config-rule.md)), use that band, skip the signal-based classification, and announce +the config as the source. In every case still select specialists by signal: a `large` band does not dispatch agents +whose domain the contract never touches. A conversational override ("design this large") is equivalent to `$size`. + +## Step 3: Build the Roster and Announce It + +**Spine — dispatched at every size:** + +- `han-core:codebase-explorer` — discovers the current surface, its consumers, and the constraints the design has to + live inside. Feeds the context brief. Runs in Step 4. +- `han-core:software-architect` — produces the options document and every later amendment. Runs in Steps 5, 7, 8, and 9. +- `han-core:junior-developer` — questions the chosen option as a generalist who was not in the room. Runs in Step 7. +- `han-core:adversarial-validator` — attacks the amended design and the evidence under it. Runs in Step 9. + +**Signal-selected specialists — added to the discovery wave when the signal is present and the band allows:** + +| Specialist | Add when | Min band | +| --------------------------------------- | ---------------------- | -------- | +| `han-core:structural-analyst` | Consumer-spread signal | Medium | +| `han-core:behavioral-analyst` | Boundary-data signal | Medium | +| `han-core:concurrency-analyst` | Ordering signal | Medium | +| `han-core:data-engineer` | Data-contract signal | Medium | +| `han-core:on-call-engineer` | Failure-path signal | Medium | +| `han-core:system-architect` | System-seam signal | Large | +| `han-core:adversarial-security-analyst` | Trust-boundary signal | Medium | + +Roster caps by band are ceilings, not quotas: **small** runs the spine only (4 agents); **medium** adds at most two +signalled specialists (up to 6 agents); **large** adds at most four, including `han-core:system-architect` when a +system-seam signal is present (up to 8 agents). A band reached by override rather than by signal can sit well under its +ceiling; add no specialist whose signal is absent just to fill the band. If more specialists are signalled than the cap +allows, keep the band's count, prefer the specialists covering the strongest signals, and name the omitted domains in +the design document's summary so the user can re-run larger. + +Extra agents named in the project config's `## Extra Agents` list join the signal-selected pool and compete under the +same signals and band caps, per [config-rule.md](../../references/config-rule.md): add one only when a signal in the +interface matches its stated specialty, count it against the band's cap, and skip an entry that does not resolve to a +dispatchable agent with a one-line note. + +**Announce the decision in one line before dispatching**, with per-specialist justification — for example: + +> **Size: medium.** Designing the query-parameter prefill contract on `FlowProvider`; consumer-spread signal (7 call +> sites) and a trust-boundary signal (values arrive from the URL). **Roster (6):** `han-core:codebase-explorer`, +> `han-core:structural-analyst` (consumer audit), `han-core:adversarial-security-analyst` (untrusted URL input), then +> `han-core:software-architect`, `han-core:junior-developer`, and `han-core:adversarial-validator`. + +State git availability in the same message if git is absent. Proceed without a blocking confirmation; discovery is +read-only and re-runnable, so a gate here would gate a reversible operation. If the user objects to the roster, honor +the adjustment. + +## Step 4: Dispatch the Discovery Wave and Write the Context Brief + +Launch `han-core:codebase-explorer` and every signalled specialist in a single message with one `Agent` call per agent +so they run concurrently. Each brief must contain: + +- The stated goal, verbatim. +- The resolved interface, its file paths, and its known consumers. +- The starting point from Step 1, so an agent reading a branch-modified file knows whether those changes count. +- The resolved project-context conventions, or a note that none were found and surrounding-code inference applies. +- The instruction to report findings with provenance: every finding carries a file path and line number, or is labelled + as an inference. + +Wait for the whole wave to return. Then write `{folder}/context-brief.md`: a numbered list of findings (F1, F2, F3, …), +each carrying the finding, its provenance (a `file:line` citation, or the label `inferred`), and the agent that reported +it. Merge duplicates and keep conflicting findings as separate numbered entries with both citations, rather than +picking a winner. Apply the evidence rule from [../../references/evidence-rule.md](../../references/evidence-rule.md) to +every finding. When a question the design depends on has no evidence at any tier, record it as an open item rather than +guessing, and carry it into Step 8 alongside the open items the question round produces. + +If a specialist returns nothing usable or fails, record a one-line note in the context brief naming the agent and the +domain left uncovered, and continue. A missing specialist narrows the design's evidence; it does not stop the run. If +`han-core:codebase-explorer` returns nothing usable, relaunch it once with the interface's file paths spelled out. If +the second attempt also returns nothing, stop and tell the user the interface could not be discovered, naming the paths +that were searched. + +## Step 5: Dispatch the Architect for Options + +Launch `han-core:software-architect` with one `Agent` call. Pass it the stated goal verbatim, the full context brief, +and the resolved project conventions. Its brief must ask for: + +1. **Two or three real options** for the contract, each one a design someone could implement, not a strawman. +2. **One recommendation** with the reasoning that selects it over the others. +3. **The rejected alternatives** with the reason each was rejected. +4. **For every element of every option** — each parameter, field, type, default, precedence rule, lifecycle rule, and + failure behavior — the justification defined in the Operating Principles: the part of the goal it descends from, or + the asked-for behavior it is a necessity of. +5. **A cut list** of anything the interface could plausibly carry but the goal does not ask for, with what it would have + done and why it was cut. +6. **Pseudocode sketches** of each option's signatures and types. + +Write the returned options to `{folder}/design-options.md`. + +If the architect returns one option, or returns options whose elements carry no justification, relaunch it once with the +missing requirement restated. If the second attempt still returns one option, carry that option forward and record in +the design document that only one viable option was produced, with the architect's stated reason. If the second attempt +still leaves elements unjustified, do not carry those elements: move each one to the cut list with what it would have +done and the note that no justification was produced for it, so the gap reaches the user in Step 6 rather than passing +as designed. + +## Step 6: Human Gate — The User Picks an Option + +Before writing the question, invoke `han-communication:explanation-guidance` to source the shared explanation standard +into your context. After that skill returns, proceed immediately to the question below — do not stop there. The +standard stays in context for Step 8, so do not invoke it a second time. + +Present the options to the user with `AskUserQuestion`: one option per choice, the recommendation named first and +labelled as recommended, each with its one-line reasoning. Apply the explanation standard to the wording, so each option +reads as an outcome the user could observe rather than a mechanism. Include the cut list in the surrounding message so +the user sees what the design is giving up. + +Handle the response: + +- **User picks the recommendation or another option** — carry it forward as the chosen design. +- **User picks a rejected alternative or amends an option** — carry their choice forward, and record their direction as + the justification for the elements it changes. Operator direction is itself a valid justification. +- **User asks for a different option entirely** — return to Step 5 with their feedback, once. If a second round still + does not produce an acceptable option, present what exists and ask for the constraint that is missing. + +## Step 7: Dispatch the Question Round and Amend + +Launch `han-core:junior-developer` with one `Agent` call. Pass it the stated goal verbatim, the context brief, and the +chosen option in full. Its brief must ask it to reframe the contract in simpler terms and raise the clarifying questions +a generalist who was not in the room would ask: unstated prerequisites, conflicts with the project's own conventions, +names that do not say what they hold, and behavior the contract leaves undefined. Ask for numbered questions. + +Sort the returned questions into three buckets: + +1. **Settled by the goal** — the stated goal already answers it. Answer it, cite the goal, and do not escalate. + Re-deciding a question the goal already decided wastes the user's turn. +2. **Settled by the context brief** — a finding answers it. Answer it, cite the finding number. +3. **Open** — neither the goal nor the brief settles it, and the answer changes the contract. These go to Step 8. + +Then relaunch `han-core:software-architect` with one `Agent` call, passing the chosen option, every question, and the +answers from buckets 1 and 2, and ask it to amend the design accordingly. Hold the open items until Step 8 answers +them. + +## Step 8: Human Gate — Open Items, One at a Time + +If Step 7 and Step 4 left no open item, say so in one line, skip this gate, and go straight to Step 9. The gate exists +to settle open items; with none to settle it has nothing to ask and no answer to fold in. + +Otherwise surface the open items — those the question round produced in Step 7, plus any no-evidence item recorded in +Step 4 — **one at a time**, each as its own `AskUserQuestion` call. Never batch them BECAUSE +each answer routinely settles or reshapes the ones behind it, and a batch asks the user to decide in an order the design +does not follow. + +Apply the explanation standard already in your context from Step 6 to each question's wording. Each question leads with +the plain-language consequence of the choice, names two to four candidate answers, and says what changes in the contract +depending on the answer. After each answer, re-check the remaining open items: drop the ones the answer just settled, +and re-word the ones it changed. + +When every open item is answered, relaunch `han-core:software-architect` with one `Agent` call carrying the answers, and +have it fold them into the amended design. Record each answer in the design document as the justification for the +elements it settles. + +## Step 9: Dispatch the Adversarial Validation Round + +Launch `han-core:adversarial-validator` with one `Agent` call. Pass it, verbatim and unsummarized, the stated goal, the +full context brief with every finding and its citation, the amended design with its justifications, and the cut list. +Do not summarize — the validator needs the detail to attack effectively. Its job is to try to break the contract: find +the consumer the design forgets, the input state it does not define behavior for, the invariant a caller can violate, +the justification that does not actually follow from the goal, and the finding whose evidence does not support what the +design built on it. + +Record its output as numbered validation findings (V1, V2, V3, …), and mark each one: + +- **Rejected** — the finding does not hold. Record why, citing the goal, a context-brief finding, or a user decision + from Step 6 or Step 8. +- **Accepted** — the finding holds. Once every finding is marked, relaunch `han-core:software-architect` a single time + carrying all accepted findings together, and record what changed for each. + +If the validator finds nothing, record what it checked and why that supports the design. A clean validation round is a +result, not an empty section. + +Cap the revision at one round. If the revised design would open new open items, list them in the design document's Open +Risks section rather than starting another gate cycle. + +## Step 10: Render the Design Document and Rewrite It for Readability + +Read [references/api-design-template.md](./references/api-design-template.md) and render it into +`{folder}/api-design.md`. Render rules: + +1. **Fill the front matter.** The goal and where it came from, the interface, the chosen size and its one-line + justification, the dispatched roster, the starting point, and git availability. +2. **Carry the justification for every element.** The justification table is the section that makes the scope discipline + auditable; an element with an empty justification is a rendering bug, not a formatting choice. +3. **Keep the cut list.** Render it even when short. It is what tells the reader what the design deliberately does not + carry. +4. **Omit sections that have no content**, keeping the remaining sections in the template's order. Never emit a heading + with placeholder or "N/A" content. A clean validation round is content, not an empty section. +5. **Write the Summary last**, after every other section is filled: the contract in two or three sentences, the option + chosen and what it was chosen over, the decisions the user made at each gate that ran, the validation outcome, and + any signalled domain the band cap omitted. + +Then invoke `han-communication:readability-guidance` to source the shared readability standard into your context. After +that skill returns, proceed immediately to the rewrite below — do not stop there. Dispatch +`han-communication:readability-editor` with one `Agent` call to audit and rewrite the document. Pass it the +file path and the named audience: the engineer who will implement this contract and the reviewer who will approve it. +The editor reads han-communication's own canonical rule, so pass no rule path. It preserves every fact and edits prose +regions only — never inside code fences, pseudocode sketches, type signatures in code blocks, or finding-ID and +`file:line` citation identifiers. Apply its rewrite to the file. + +Then run the readability rule's standardized six-point self-check, which is in your context from the +`readability-guidance` invocation above, over the document's prose regions only. Correct every failure before +presenting. Its fidelity criterion is not optional: the standard governs how the content is said, never whether a +required fact appears. + +## Step 11: Present the Design + +Present the design to the user in a short closing message covering: + +- The three file paths written. +- The contract in two or three sentences. +- The size band and roster used, and git availability if git was absent. +- The cut list, in the same plain language the design document uses, so the user can reinstate anything they disagree + with. Any entry they reinstate re-enters the design with their direction as its justification. +- The open risks the validation round left standing, and any signalled domain the band cap omitted that would justify a + re-run at a larger size. +- The next step: this document is the input to a `tdd` run that implements the contract. diff --git a/han-coding/skills/design-an-api/references/api-design-template.md b/han-coding/skills/design-an-api/references/api-design-template.md new file mode 100644 index 00000000..e2eeb2cd --- /dev/null +++ b/han-coding/skills/design-an-api/references/api-design-template.md @@ -0,0 +1,117 @@ +# API Design Document Template + +The `design-an-api` skill renders this template into `{folder}/api-design.md`. Fill every section that has content and +omit the ones that do not, keeping the remaining sections in the order below. Never emit a heading with placeholder or +"N/A" content. + +Replace every `{placeholder}` with the resolved value. Text in _italics_ under a heading describes what the section +holds and is not written into the rendered document. + +--- + +```yaml +--- +goal: "{the stated goal, quoted}" +goal_source: "{ticket reference, issue URL, file path, or 'described in conversation'}" +interface: "{what is being designed, and where it lives}" +size: "{small | medium | large}" +size_reason: "{one line: which signals put it in this band}" +roster: "{the dispatched agents, comma-separated}" +starting_point: "{working tree | merge base with {branch}}" +git_available: "{yes | no}" +--- +``` + +# API Design: {interface} + +## Summary + +_Two or three sentences stating the contract, then one line each for: the option chosen and what it was chosen over, +the decisions the user made at each gate that ran, the validation outcome, and any signalled domain the band cap +omitted. Written last, after every other section is filled._ + +## The Goal This Serves + +_The stated goal, quoted verbatim, with its source. Every justification in this document cites back to this section._ + +## The Designed Contract + +_The contract itself, in three parts:_ + +### Surface + +_The signatures, parameters, fields, and types, in a code fence. Pseudocode is fine; this is a design, not an +implementation._ + +### Invariants + +_The rules a caller can rely on and cannot violate: precedence between sources of a value, what persists and what does +not, lifecycle and ordering guarantees, and idempotency where the contract states one._ + +### Failure Behavior + +_What the contract does with invalid, missing, malformed, or hostile input, and what a caller observes when an +underlying operation fails._ + +## Why Each Element Is Here + +_One row per named element of the contract. The justification names the part of the goal the element descends from, or +the asked-for behavior it is a necessity of. An empty justification is a rendering bug._ + +| Element | What it does | Justification | +| -------- | ------------ | ---------------------------------------------------------------------- | +| `{name}` | {behavior} | {goal language it descends from, or the behavior it is a necessity of} | + +## Options Considered + +_Each option the architect produced, with its surface sketch and the reason it was chosen or rejected. The chosen +option is named first and marked as chosen._ + +### {Option name} — chosen + +_What it does differently, and the reasoning that selected it._ + +### {Option name} — rejected + +_What it does differently, and why it was rejected._ + +## Questions Resolved + +_Every question from the question round, numbered, each with its answer and the source of the answer: the goal, a +context-brief finding (F#), or the user's decision at a gate._ + +| # | Question | Answer | Source | +| --- | ---------- | -------- | --------------------------- | +| Q1 | {question} | {answer} | {goal / F# / user decision} | + +## Validation Findings + +_Every finding from the adversarial validation round, numbered V1, V2, V3, …, each marked accepted or rejected. An +accepted finding records what changed in the design. A rejected finding records why it does not hold, with its +citation. A validation round that found nothing records what it checked and why that supports the design._ + +| # | Finding | Disposition | What changed or why it does not hold | +| --- | --------- | --------------------- | ----------------------------------------- | +| V1 | {finding} | {accepted / rejected} | {change, or the citation that rejects it} | + +## Cut List + +_Everything this interface could plausibly carry that the goal does not ask for. Each entry names what it would have +done, in the same plain language the closing summary uses, and why it was cut. Rendered even when short. The reader can +reinstate any entry; their direction becomes its justification._ + +- **{What it would have done}** — cut because {reason, with the citation that supports the cut}. + +## Open Risks + +_What the validation round left standing, what the design depends on but could not verify, and any signalled domain the +band cap omitted. Each entry names the condition that would make it matter._ + +## Evidence + +_A pointer to `context-brief.md` for the numbered findings this design was built on, plus any finding this document +cites directly._ + +## Next Step + +_This document is the input to a `tdd` run that implements the contract._ diff --git a/han-planning/skills/plan-a-feature/SKILL.md b/han-planning/skills/plan-a-feature/SKILL.md index 65881a1a..eaf14195 100644 --- a/han-planning/skills/plan-a-feature/SKILL.md +++ b/han-planning/skills/plan-a-feature/SKILL.md @@ -5,8 +5,9 @@ description: > decision-by-decision, resolving dependencies as it goes. Use when the user wants to plan, design, scope, specify, or flesh out a new feature, capability, or system behavior before implementation. Produces a feature specification focused on system behaviors, not implementation detail. Does not refine or stress-test an existing plan — use - iterative-plan-review. Does not document already-built features — use project-documentation. Does not research - open-ended options before there is a feature to specify — use research. + iterative-plan-review. Does not document already-built features — use project-documentation. Does not design the + contract for an interface — use design-an-api. Does not research open-ended options before there is a feature to + specify — use research. arguments: size argument-hint: "[size: small | medium | large | dynamic] [feature description, optional: output folder path]" allowed-tools: Read, Write, Edit, Glob, Grep, Agent, Bash(find *), Bash(mkdir *), Bash(cp *) diff --git a/han-planning/skills/plan-implementation/SKILL.md b/han-planning/skills/plan-implementation/SKILL.md index afe4564a..446370c2 100644 --- a/han-planning/skills/plan-implementation/SKILL.md +++ b/han-planning/skills/plan-implementation/SKILL.md @@ -4,7 +4,8 @@ description: > Builds a feature implementation plan from an existing feature specification (or equivalent context) through a facilitated team conversation. Use when the user wants to plan how to implement, build, deliver, or ship a feature that has already been specified. Does not specify what the feature should do — use plan-a-feature first. Does - not refine or stress-test an already-written plan — use iterative-plan-review. + not design the contract for an interface — use design-an-api. Does not refine or stress-test an already-written plan — + use iterative-plan-review. arguments: size argument-hint: "[size: small | medium | large | dynamic] [feature specification path, optional: additional context]" allowed-tools: Read, Write, Edit, Glob, Grep, Agent, Bash(find *), Bash(git *), Bash(mkdir *), Bash(cp *)