Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .agents/commands/build.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
description: Implement the current feature one phase at a time, ticking tasks.md and running the verification gate at each phase boundary
argument-hint: <spec-dir-name> (optional; defaults to the most recent work/* directory)
argument-hint: <spec-dir-name> (optional; defaults to the most recent development/work/* directory)
---

You are carrying out the implementation phase of a feature.

1. Identify the target spec directory.
- If `$ARGUMENTS` is provided, use `work/$ARGUMENTS/`.
- If `$ARGUMENTS` is provided, use `development/work/$ARGUMENTS/`.
- Otherwise, use the most recently modified directory under
`work/`.
`development/work/`.
2. Read `spec.md`, `plan.md`, and `tasks.md` in full. If `plan.md` is
missing or empty, stop and tell the user to run `/plan` first.
3. If the plan touches an unfamiliar area of the codebase, run an
Expand All @@ -25,6 +25,8 @@ You are carrying out the implementation phase of a feature.
- Work one phase at a time, writing tests first where the plan
calls for behaviour change.
- Tick `tasks.md` checkboxes in the same commit as the code change.
- Keep `report.md` current: deviations, abandoned approaches, and
`DECISION-PENDING:` escalations are recorded when they happen.
- Run `make verify` at every phase boundary.
- Stop at the end of each phase and hand off to `/verify`
(Reviewer) before starting the next.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] correctness — ⏭️ Not fixed here

/build forwards only the developer subagent's "phase complete" hand-back; the developer's other documented stop (a scratch.md note requesting an explorer pass, developer.md:80) has no servicing step, unlike /plan's explicit SPIKE-REQUEST round-trip.

Failure scenario

The developer hits a search it cannot summarise inline, follows developer.md:78-81, writes "requesting an explorer pass" into scratch.md and stops mid-phase with tasks.md boxes unticked. build.md step 5 has exactly one branch — "When the developer reports a phase complete, stop and ask the user to run /verify" — so the parent reports the stop as a completed phase and routes the user to /verify. The reviewer then reviews half-implemented work and returns NEEDS-WORK (unticked tasks, missing tests), /build re-delegates to a fresh developer that hits the same wall, and the explorer request is never serviced: the phase ping-pongs between /build and /verify with no progress until the user reads scratch.md by hand.

Left for upstream: this is a gap in the template's role protocol rather than something this migration introduced, and fixing it here would deepen the divergence that every future copier update has to re-merge.

Expand Down
18 changes: 15 additions & 3 deletions .agents/commands/plan.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
---
description: Expand spec.md into a numbered, testable plan.md for the current feature
argument-hint: <spec-dir-name> (optional; defaults to the most recent work/* directory)
argument-hint: <spec-dir-name> (optional; defaults to the most recent development/work/* directory)
---

You are expanding a feature spec into an implementation plan.

1. Identify the target spec directory.
- If `$ARGUMENTS` is provided, use `work/$ARGUMENTS/`.
- If `$ARGUMENTS` is provided, use `development/work/$ARGUMENTS/`.
- Otherwise, use the most recently modified directory under
`work/`.
`development/work/`.
2. Confirm `spec.md` exists and has been reviewed. If it's missing or
empty, stop and tell the user to run `/spec` first.
3. Delegate the planning to the **architect** subagent
(`.agents/subagents/architect.md`). It owns the phased-plan format,
the architecture-decisions block, the "each phase has tests"
contract, and the "stop and ask before coding" boundary.
4. If the architect hands back a **spike request** — a
`SPIKE-REQUEST:` line in `scratch.md` naming one question (it cannot
run code itself) — run the smallest throwaway experiment that answers
it, in a temp dir or scratch space, never left in the source tree.
Append the result to `scratch.md` on a `SPIKE-FINDING:` line
(question → method → answer → evidence), then re-invoke the
architect; it starts with fresh context and reads `scratch.md` to
pick the answer up. Spike code is disposable; only the findings
survive, in the plan's **Spike findings** section.
Cap this at **three rounds per plan**. A fourth request means the
uncertainty is not a design experiment — stop and put the question
to the user.

The architect subagent will write `plan.md` and mirror it into
`tasks.md`, then stop for user review. Once the user confirms the
Expand Down
31 changes: 25 additions & 6 deletions .agents/commands/spec.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: Create a new feature spec directory under work/<YYYY-MM>-<slug>/
description: Create a new feature spec directory under development/work/<YYYY-MM>-<slug>/
argument-hint: <kebab-case-slug>
---

Expand All @@ -8,17 +8,36 @@ You are creating a new feature spec.
1. If `$ARGUMENTS` is empty, ask the user for a slug before creating
anything.
2. Compute today's date as `YYYY-MM`. The directory is
`work/<YYYY-MM>-$ARGUMENTS/`.
`development/work/<YYYY-MM>-$ARGUMENTS/`.
3. Create the directory if it doesn't exist. **Do not** pre-create
`plan.md`, `tasks.md`, or `scratch.md` — each role creates the
artifacts it owns (Architect: `plan.md`/`tasks.md`; Developer:
`scratch.md`), and pre-creating them would force those roles to
`edit` files they should be able to `write` from scratch.
`plan.md`, `tasks.md`, `report.md`, or `scratch.md` — each role
creates the deliverables it owns (Architect: `plan.md`/`tasks.md`;
Developer: `report.md`), and pre-creating them would force those
roles to `edit` files they should be able to `write` from scratch.
`scratch.md` is not a deliverable but the feature's shared channel:
whoever needs it first creates it, and everyone after that appends.
4. Delegate the actual spec authoring to the **product-owner** subagent
(`.agents/subagents/product-owner.md`). It owns the spec format,
the testable-criteria rule, the non-goals requirement, and the
"stop and ask before planning" boundary.
5. If the product-owner hands back a **clarifying question** instead of
`spec.md`, put it to the user, then re-invoke the product-owner
subagent with the question and the user's answer included in the
prompt — it starts each invocation with fresh context and cannot see
the exchange otherwise. Repeat until it produces the spec. Cap this
at **five rounds**: if the questions have not converged by then, stop
and ask the user to settle the scope directly.

The product-owner subagent will write `spec.md` and then stop for user
review. Once the user confirms the spec, the next step is `/plan`
(Architect role). Do not start implementing yet.

If the reviewed spec's **Glossary** section pins down new domain terms,
promote them to `development/glossary.md` as part of the review wrap-up
(the product-owner subagent cannot write outside the feature
directory). The glossary is a **register**: promotion from a reviewed
spec is its one sanctioned mid-feature channel (see Document liveness
in `development/harness-usage.md`), and the Reviewer checks each
promoted entry against the spec's Glossary section — so promote the
reviewed terms verbatim, and don't fold in renames or meaning changes
of existing entries (those are trunk-gated, a dedicated PR).
23 changes: 15 additions & 8 deletions .agents/commands/verify.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,25 @@ You are running the review phase for the current feature.
Delegate the work to the **reviewer** subagent
(`.agents/subagents/reviewer.md`). It will:

- Read `spec.md`, `plan.md`, `tasks.md`, and the current diff.
- Run `make verify`.
- Check spec conformance, plan conformance, and implementation
quality.
- Read `spec.md`, `plan.md` (including its **Review checklist**
section, if present), `tasks.md`, `report.md` (if the Developer has
started it — expected by the final phase), and the current diff.
- Run `make verify` itself — it never takes the Developer's
word for the gate.
- Check spec conformance, plan conformance, implementation quality,
and report honesty (undeclared deviations are defects).
- Produce a `GO` or `NEEDS-WORK` verdict with a citation-rich defect
list (`path/to/file.ext:LINE`) when work remains.
list (`path/to/file.ext:LINE`), ranked MAJOR / MINOR / INFO. Any
MAJOR means NEEDS-WORK.

Hand the reviewer's verdict back to the user verbatim. If
`NEEDS-WORK`, the next step is `/build` (Developer role) to address
the defects. If `GO`, summarise what changed since the last verify
(use `git diff --stat` and `git log -1`) and stop.
the defects. If `GO` on the feature's final phase, confirm `report.md`
is complete (what was built, deviations, negative results, follow-ups,
gate result) before the feature is declared mergeable — it freezes at
merge. Then summarise what changed since the last verify (use
`git diff --stat` and `git log -1`) and stop.

Never silently skip, disable, or `@ignore` a failing test. If a test
must be skipped, draft an ADR under `docs/adr/` and ask for
must be skipped, draft an ADR under `development/adr/` and ask for
confirmation.
10 changes: 9 additions & 1 deletion .agents/hooks/block-destructive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,12 @@
# .opencode/opencode.jsonc restate these patterns by hand — keep in sync.
#
# See .agents/README.md for the single-source-of-truth rationale.
grep -qE 'rm -rf|push --force|reset --hard|DROP TABLE' && exit 2 || exit 0
# The matched pattern goes to stderr: a bare `exit 2` reaches the agent as an
# unexplained refusal, which it answers by rewording and retrying the same
# command. Naming the pattern makes the refusal actionable in one turn.
match=$(grep -oE 'rm -rf|push --force|reset --hard|DROP TABLE' | head -n 1)
if [ -n "$match" ]; then
echo "block-destructive: refused — matches the deny-list pattern '$match'." >&2
exit 2
fi
exit 0
12 changes: 10 additions & 2 deletions .agents/hooks/ensure-toolchain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# - Any other agent / CI / devcontainer may call it too.
#
# The install command and URL come from the toolchain_install_* macros in
# _macros.jinja (the single source; docs/tool-bootstrap.md renders the same
# _macros.jinja (the single source; development/tool-bootstrap.md renders the same
# macro for its manual fallback). The installer appends $HOME/.local/bin to the
# shell profile, so the binary is on PATH for *new* shells (e.g. an agent's
# subsequent tool calls), not the current one. A caller that needs it within its
Expand All @@ -18,6 +18,14 @@
#
# See .agents/README.md for the single-source-of-truth rationale.

# jq is a hard requirement of the PreToolUse Bash guard, not a convenience: it
# parses the tool input, and the guard fails closed, so without jq every Bash
# call is denied — including the one that would install it. Report that here, at
# session start, instead of letting the first tool call fail opaquely. Warn only:
# a missing jq must not abort the uv bootstrap below.
command -v jq >/dev/null 2>&1 || \
echo "ensure-toolchain: WARNING — jq not found. The PreToolUse Bash guard denies every command without it; install jq (apt-get install jq / brew install jq). See development/tool-bootstrap.md." >&2

command -v uv >/dev/null 2>&1 && exit 0

# A prior install may sit in $HOME/.local/bin without being on this shell's PATH yet.
Expand All @@ -33,5 +41,5 @@ if curl -LsSf https://astral.sh/uv/install.sh | sh >&2 && [ -x "$HOME/.local/bin
fi

echo "ensure-toolchain: ERROR — could not install uv automatically (offline or restricted network?)." >&2
echo "ensure-toolchain: install it manually, then retry. See docs/tool-bootstrap.md." >&2
echo "ensure-toolchain: install it manually, then retry. See development/tool-bootstrap.md." >&2
exit 1
80 changes: 80 additions & 0 deletions .agents/skills/architect-playbook/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
name: architect-playbook
description: |
How the Architect turns an approved spec into a plan. Use when writing
or revising plan.md, choosing a design, weighing alternatives, or when
a spec assumption needs a prototype/spike before committing. Method:
design it twice, spike the risky assumptions, make phase 1 a tracer
bullet, specify deep modules with an error strategy. Companion to the
architect subagent and the /plan command.
---

# Architect playbook

The plan is written for an executor with less context than you: fresh
session, weaker model, no access to this conversation. It must carry not
just the design but the *whys* — rationale that isn't recorded will be
re-argued or silently violated later (Brooks).

Shared ground rules: `.agents/skills/design-principles/SKILL.md`.

## Method

1. **Study exemplars first.** Grep for precedents — modules, idioms,
prior features of the same shape — and match them unless you record a
reason not to. Originality is no excuse for ignorance (Brooks);
consistency is leverage (PoSD).
2. **Design it twice.** Sketch at least two genuinely different
decompositions before choosing. Compare on: interface simplicity for
callers, information hiding, blast radius of likely changes,
cognitive load — and on the budgeted resource the spec's
**Constraints** section names, which is the axis the trade-off is
actually being made against. Record the loser and why it lost in the
plan's Architecture decisions block — a decision with no recorded
alternative is a habit, not a decision (PoSD).
3. **Spike before you commit.** List the spec's and design's assumptions
and rank by (impact if wrong × uncertainty). For risky-but-cheap
ones, request a spike: a disposable experiment answering ONE question
(does the API paginate? is the parser fast enough?). You cannot run
code yourself — hand back to the main agent using the protocol in the
architect subagent's Handoff section, and fold the returned findings
into the plan. Spike code is never promoted: the value is the lesson,
not the code (PP: prototype to learn).
4. **Phase 1 is a tracer bullet.** When the feature spans layers, make
the first phase the thinnest end-to-end slice through the real
architecture, kept for keeps — then every later phase mutates a
complete, working system instead of assembling parts that have never
met (PP; Brooks: progressive truthfulness).
5. **Specify deep modules.** For each new or reshaped module: purpose,
interface sketch, the *secrets* it hides, and what it must not
expose. Minimal implementation, slightly general interface. Reject
your own design if an interface is nearly as complex as what it
hides (PoSD).
6. **Design the error strategy, don't inherit it.** Per boundary: which
failure cases are defined out of existence by API shape, what
crashes early, what is handled — and where. "Wrap it in try/catch"
is not a strategy (PoSD; PP).
7. **Name in the ubiquitous language.** Take names from
`development/glossary.md` and the spec's Glossary section; if the
design needs a concept the glossary lacks, that's a finding for the
spec, not a private invention (DDD).
8. **Tests are part of the design.** Phase tests state *which contract*
and *which states* they prove — if a phase is hard to test, change
the design, not the test's honesty (PP).
9. **Flag the irreversible.** Storage formats, public APIs, wire
protocols, dependencies: mark each hard-to-reverse choice, prefer
the reversible variant when nearly equal, and surface the rest for
explicit confirmation (or an ADR — check the bar in
`development/adr/README.md`).

## Gotchas

- Spike findings that contradict the spec go back to the Product Owner
as spec feedback — don't quietly plan around a broken assumption.
- Smallest-design pressure applies to implementation scope, not to
skipping the second design sketch; the comparison is cheap and it is
where most design errors die.
- Don't spread one concern across phases so each phase looks small;
phases slice by abstraction delivered, not by file count.
- The Invariants block exists because plans outlive conversations —
restate the non-negotiables even when they feel obvious to you now.
Loading
Loading