agent-templates 0.4.3 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ADOPTING.md CHANGED
@@ -16,7 +16,11 @@ npx agent-templates@latest adopt three-agent-architect-builder-reviewer C:\path\
16
16
 
17
17
  Pin an exact version for reproducibility (`npx agent-templates@0.1.0 …`) — a published version is a verified snapshot of the catalog's recommendations. Alternatives: `npx github:Ruihang2017/agent-templates …` (tracks the repo, no release needed; npx caches git installs — `--prefer-online` picks up updates), or from a checkout: `node scripts/adopt.mjs three-agent-architect-builder-reviewer <target-dir>`.
18
18
 
19
- Idempotent (re-runs skip what exists; `--force` overwrites). It installs the scaffold `.claude/` (agents with pinned model/effort, stage commands, write guard, workflows, publish script), the universal `templates/ticket.template.md`, the platform tracker templates (`--platform gh|glab`, autodetected from the origin remote) into `.github/` or `.gitlab/`, creates `docs/prd|adr|plans/`, copies a root `PRD.md` to `docs/PRD.md`, and seeds or appends `CLAUDE.md` from the pattern snippet (marker-checked, never duplicated).
19
+ Idempotent (re-runs skip what exists; `--force` overwrites). It installs the scaffold `.claude/` (agents with pinned model/effort, stage commands, write guard, workflows, publish script), the universal `templates/ticket.template.md`, the platform tracker templates into `.github/` or `.gitlab/`, creates `docs/prd|adr|plans/`, copies a root `PRD.md` to `docs/PRD.md`, and seeds or appends `CLAUDE.md` from the pattern snippet (marker-checked, never duplicated).
20
+
21
+ **Platform (GitHub vs GitLab)** is resolved before anything is installed — from the origin remote host, else a repo-local signal (`.gitlab-ci.yml` → GitLab, existing `.github/` → GitHub). If neither is present (e.g. a fresh repo with only a `PRD.md`), adopt **does not guess**: run interactively it asks; run non-interactively (an agent or CI) it exits without installing and asks you to pass `--platform gh|glab`. So on a bare repo, either set the remote first or pass `--platform`. The resolved value is written to the `Tracker:` line in `CLAUDE.md`, which the pipeline reads.
22
+
23
+ **Upstream issue escalation is opt-in.** By default the installed `CLAUDE.md` carries **no** instruction to file pattern-level problems against any catalog — no external repo slug is written into your repo (safe for commercial and private projects). Pass `--upstream` to include the bullet pointing at the catalog you adopted from, or `--upstream <owner/repo>` to point it at your own fork or internal catalog.
20
24
 
21
25
  ## 2. New project from a bare PRD.md — end to end
22
26
 
@@ -35,6 +39,17 @@ Preconditions: git repo + remote, authenticated tracker CLI (`gh auth login` / `
35
39
 
36
40
  Same `adopt.mjs` run — skip-existing protects your files. The differences:
37
41
 
42
+ **Updating to a newer catalog version:** a plain re-run only adds files that don't exist yet; it will not update a file the previous version already installed. To pull the latest, re-run with `--force` (it overwrites, including `.claude/settings.json`), so commit first and review the diff to re-apply local customizations:
43
+
44
+ ```
45
+ git add -A && git commit -m "checkpoint before agent-templates update"
46
+ npx agent-templates@latest adopt three-agent-architect-builder-reviewer . --force
47
+ git diff
48
+ ```
49
+
50
+ `--force` refreshes the scaffold and tracker/settings files, but not the `CLAUDE.md` pipeline section or `.gitattributes` (both marker-guarded) — re-apply any pipeline-rule changes from a release by hand.
51
+
52
+
38
53
  - `CLAUDE.md` gets the snippet **appended**: read the merged result once and resolve contradictions with your existing rules (the pipeline rules assume no agent judges its own work).
39
54
  - An existing `.claude/settings.json` is kept; merge the scaffold's `hooks.PreToolUse` (write guard) and `permissions.allow` entries by hand.
40
55
  - Formalize `docs/PRD.md` for the area you will pipeline first — it can cover a single module; you do not need to spec the whole codebase to start.
package/CLAUDE.md CHANGED
@@ -116,7 +116,7 @@ Upstream docs convention assumed by patterns (exemplar: `fx-eye-tracking`): `doc
116
116
 
117
117
  1. **Issues are the decision record; commits are only the change record.** Every unit of work starts as a GitHub issue stating what + why (use the universal templates — work items follow `task`/`bug-report`, records follow `decision-record`). The work lands via a PR referencing it (`Closes #N`), written against `.github/PULL_REQUEST_TEMPLATE.md` (byte-synced from `templates/tracker/github/`). **No direct merges to main.** Bootstrap exception: the rounds merged on 2026-07-17 before this rule existed are backfilled as `decision-record` issues #1–#4.
118
118
  2. **Self-hosted nightly sweep.** This repo runs the pattern's own `/nightly-issues`: other projects file pattern-tweak requests here (templates in `.github/ISSUE_TEMPLATE/`), and the sweep triages — and where fixable, fixes — them overnight. The machinery at `.claude/` (four agents, two workflows, `nightly-issues` + `verify-delivery` commands) is a **byte-synced copy of the scaffold**, enforced by the E2E integrity suite: change the scaffold first, then re-copy.
119
- 3. **This repo's test suite** is `node testbed/e2e/run-e2e.mjs` — the Builder/Reviewer run it exactly like any project's tests.
119
+ 3. **This repo's test suite** is `node testbed/e2e/run-e2e.mjs` — the Builder/Reviewer run it exactly like any project's tests. **CI enforces it server-side**: `.github/workflows/test.yml` runs the suite on every PR and push to `main` (ubuntu + windows × Node 18/20). Releases publish from a `v*` tag via `.github/workflows/publish.yml` (E2E gate → tag-matches-version check → `npm publish` with the `NPM_TOKEN` secret) — see README § "CI & releasing".
120
120
  4. The scaffold's main-session write guard is **not installed here** — interactive doc-editing with the maintainer is this repo's norm. Revisit if orchestrator role leakage appears in this repo's own pipeline runs.
121
121
  5. Labels in use: `decision-record` · `triage:invalid` · `nightly:escalated` · `needs-human`.
122
122
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # agent-templates
2
2
 
3
- [![npm](https://img.shields.io/npm/v/agent-templates)](https://www.npmjs.com/package/agent-templates) · **[Catalog site →](https://ruihang2017.github.io/agent-templates/)**
3
+ [![npm](https://img.shields.io/npm/v/agent-templates)](https://www.npmjs.com/package/agent-templates) · [![test](https://github.com/Ruihang2017/agent-templates/actions/workflows/test.yml/badge.svg)](https://github.com/Ruihang2017/agent-templates/actions/workflows/test.yml) · **[Catalog site →](https://ruihang2017.github.io/agent-templates/)**
4
4
 
5
5
  Catalog of reusable multi-agent development architecture patterns. Each entry is a design write-up plus drop-in scaffolding (subagent definitions, slash commands, CLAUDE.md snippets) so a new project reuses a proven pattern instead of redesigning one.
6
6
 
@@ -18,6 +18,18 @@ npx agent-templates@latest adopt three-agent-architect-builder-reviewer .
18
18
  3. **Gate 1** — review the breakdown, then **`/start-milestone docs/prd/00-<module> supervised`**: tickets publish as tracker issues; each ticket runs plan → build → fresh-context review to CLEAR, pausing for your merge.
19
19
  4. When it holds, flip to `autonomous` — whole milestones run hands-off. **Gate 2** = your smoke test at the end. Full guide: [ADOPTING.md](ADOPTING.md).
20
20
 
21
+ ### Updating an existing install
22
+
23
+ Re-run adopt with `--force` to pull the latest catalog version. A plain re-run only adds new files (existing ones are skipped); `--force` overwrites changed ones. Because it overwrites (including `.claude/settings.json`), commit first, then review the diff and re-apply any local customizations:
24
+
25
+ ```
26
+ git add -A && git commit -m "checkpoint before agent-templates update"
27
+ npx agent-templates@latest adopt three-agent-architect-builder-reviewer . --force
28
+ git diff # re-apply your customizations (esp. .claude/settings.json)
29
+ ```
30
+
31
+ `--force` refreshes the scaffold and tracker/settings files. It does **not** rewrite the `CLAUDE.md` pipeline section or `.gitattributes` (both marker-guarded, so a re-run reports them as already present) — if a release changes the pipeline rules in the snippet, re-apply those by hand.
32
+
21
33
  | Pattern | Status | As of | Summary |
22
34
  |---|---|---|---|
23
35
  | [three-agent-architect-builder-reviewer](patterns/three-agent-architect-builder-reviewer/README.md) | trialed | 2026-07-17 | Architect plans → Builder implements → independent Reviewer (fresh context, different model tier) clears or bounces; `/start-milestone` runs a whole module autonomously |
@@ -42,6 +54,18 @@ Installed into your project by `adopt`; run them in Claude Code. Full list is ge
42
54
  - Adding a pattern: start from [templates/pattern-README.template.md](templates/pattern-README.template.md), process in [CLAUDE.md](CLAUDE.md) § "Adding a new pattern"
43
55
  - E2E testing for the pattern chain: [testbed/README.md](testbed/README.md) — `node testbed/e2e/run-e2e.mjs` is the merge gate for scaffold changes
44
56
 
57
+ ## CI & releasing
58
+
59
+ CI ([`.github/workflows/test.yml`](.github/workflows/test.yml)) runs the E2E suite on every PR and push to `main`, across ubuntu + windows × Node 18/20 — the merge gate is enforced server-side and cross-platform.
60
+
61
+ Releases publish from a version tag ([`.github/workflows/publish.yml`](.github/workflows/publish.yml)): bump `package.json`, then
62
+
63
+ ```
64
+ git tag vX.Y.Z && git push origin vX.Y.Z # X.Y.Z = the version in package.json
65
+ ```
66
+
67
+ CI re-runs the E2E gate, checks the tag matches `package.json`, and publishes to npm. **One-time setup:** add an `NPM_TOKEN` repo secret (Settings → Secrets and variables → Actions).
68
+
45
69
  ## License
46
70
 
47
71
  MIT — see [LICENSE](LICENSE). Carve-out: files installed **into your project** by `adopt.mjs` (the scaffold, templates, and anything generated from them) may be used in your projects without attribution.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-templates",
3
- "version": "0.4.3",
3
+ "version": "0.4.8",
4
4
  "description": "Catalog of multi-agent development architecture patterns - design write-ups plus drop-in scaffolding (agents, slash commands, workflows, templates).",
5
5
  "license": "MIT",
6
6
  "author": "Horace Hou",
@@ -4,8 +4,8 @@
4
4
  |---|---|
5
5
  | **Pattern name** | `three-agent-architect-builder-reviewer` |
6
6
  | **Status** | `trialed` — signed off as the team standard 2026-07-17; promotes to `adopted` after its first real-ticket run (CLAUDE.md promotion rule) |
7
- | **As-of date** | 2026-07-17 |
8
- | **Expiry trigger** | First successor release to any listed model, or 2027-01-17 (+6 months), whichever comes first |
7
+ | **As-of date** | 2026-07-21 (model/effort revised; §7) |
8
+ | **Expiry trigger** | First successor release to any listed model, or 2027-01-21 (+6 months), whichever comes first |
9
9
  | **Sign-off** | Horace Hou (repo maintainer), 2026-07-17 |
10
10
 
11
11
  One ticket flows through three agents in sequence: **Architect** plans → **Builder** implements → **Reviewer** (fresh context, different model tier) clears or bounces. No agent judges its own work.
@@ -40,16 +40,16 @@ The Reviewer is **deliberately a different model tier from the Builder** so the
40
40
 
41
41
  Related in-house variant: fx-eye-tracking's `planner` / `generator` / `evaluator` harness — same independence principle, heavier machinery (spec decomposition, file-scope parallelism, sprint contracts, tracker governance). That harness runs a whole project; this pattern runs one ticket.
42
42
 
43
- ## 3. Model + effort assignment (as of 2026-07-17)
43
+ ## 3. Model + effort assignment (as of 2026-07-21)
44
44
 
45
45
  | Role | Model | Effort | Reasoning | Source labels |
46
46
  |---|---|---|---|---|
47
- | Architect | Claude Sonnet 5 | `xhigh` | Planning is terminal/tool-call-heavy work, where Sonnet 5 benchmarks strongest in the lineup: Terminal-Bench 2.1 **80.4** vs Opus 4.8's **74.6**. `xhigh` is Anthropic's documented recommendation for agentic exploration workloads. | Benchmark: `[third-party]` (link not captured attach at first re-verification). Effort guidance: `[official]` |
47
+ | Architect | Claude Opus 4.8 | `max` | The plan is the pattern's cold-start contract: Builder and Reviewer consume it in fresh contexts, so anything the plan leaves vague drifts downstream. Field runs showed `sonnet-5 @ xhigh` plans coming out too general — the highest-leverage stage under-invested. Moved to the top model at `max`: token budget is explicitly not the constraint here, and plan depth pays for itself in reduced downstream drift and bounces. Sharing the Builder's model at a higher effort is fine — the independence constraint applies only to the Reviewer. | Plan-vagueness observation: `[internal]` (maintainer, 2026-07-21, across the recent autonomous runs). Investment choice: `[team-policy]` |
48
48
  | Builder | Claude Opus 4.8 | `xhigh` | Anthropic's official guidance is to start at `xhigh` for coding and agentic use cases. Opus 4.8 leads Sonnet 5 on the hardest agentic-coding benchmark: SWE-bench Pro **69.2** vs **63.2**. One effort setting for all tickets — no per-ticket downgrades; team priority is predictable delivery over token cost. | Benchmark: `[vendor-benchmark]` (Anthropic-reported). Effort guidance: `[official]`. No-downgrade rule: `[team-policy]` |
49
- | Reviewer | Claude Fable 5 | `max` | The Reviewer is the last quality gate before merge. Fable 5 has the largest capability margin on the hardest problems (SWE-bench Pro **~80.3**), and catching missed edge cases is where that margin pays off most. `max` because token cost is explicitly not the constraint at this gate. | Benchmark: `[unverified]` — recorded as "reported" without a named source; treat as unverified until linked. `max` choice: `[team-policy]` |
50
- | Triage (nightly only) | Claude Sonnet 5 | `xhigh` | Classification + ticket synthesis is planning-shaped work; profile inherited from the Architect row rather than separately derived. | `[team-policy]` — no separate benchmark basis |
49
+ | Reviewer | Claude Fable 5 | `xhigh` | The Reviewer is the last quality gate before merge, and Fable 5 has the largest capability margin on the hardest problems (SWE-bench Pro **~80.3**) at this gate that raw margin, not effort headroom, is what catches edge cases. Dropped from `max` to `xhigh`: `max` carries a documented overthinking/latency risk (§4), and with the stronger Architect producing tighter plans the Reviewer's burden drops. | Benchmark: `[unverified]` — recorded as "reported" without a named source; treat as unverified until linked. Effort choice: `[team-policy]` (+ §4 `max`-overthinking pitfall) |
50
+ | Triage (nightly only) | Claude Sonnet 5 | `xhigh` | Classification + ticket synthesis is planning-shaped work; profile derived separately from the Architect row (nightly triage does not need the Architect's full planning tier). | `[team-policy]` — no separate benchmark basis |
51
51
 
52
- Figures are transcribed from the team-finalized specification dated 2026-07-17 (§7). Do not re-derive or silently alter them; update only via the process in the repo CLAUDE.md (new as-of date + provenance entry in the same commit).
52
+ Figures dated 2026-07-17 are from the team-finalized specification (§7); the Architect and Reviewer rows were revised 2026-07-21 (§7). Do not re-derive or silently alter them; update only via the process in the repo CLAUDE.md (new as-of date + provenance entry in the same commit).
53
53
 
54
54
  ## 4. Known failure modes / pitfalls
55
55
 
@@ -120,9 +120,9 @@ scaffold/
120
120
  │ ├── start-all.js # whole-PRD driver: composes run-milestone per module in DAG order
121
121
  │ └── nightly-issues.js # nightly sweep: triage → pipeline → report (Workflow script)
122
122
  ├── agents/ # role definitions with pinned model + effort
123
- │ ├── architect.md # claude-sonnet-5 @ xhigh; writes the plan, no production code
123
+ │ ├── architect.md # claude-opus-4-8 @ max; writes the plan, no production code
124
124
  │ ├── builder.md # claude-opus-4-8 @ xhigh; inherits all tools
125
- │ ├── reviewer.md # claude-fable-5 @ max; read/run-only (no Write/Edit)
125
+ │ ├── reviewer.md # claude-fable-5 @ xhigh; read/run-only (no Write/Edit)
126
126
  │ └── triage.md # claude-sonnet-5 @ xhigh; nightly classification + ticket synthesis
127
127
  └── commands/
128
128
  ├── breakdown-prd.md # /breakdown-prd [notes] → pre-Gate-1: PRD → sub-PRDs + tickets
@@ -154,6 +154,9 @@ Install steps and usage modes: [scaffold/INSTALL.md](scaffold/INSTALL.md). Front
154
154
  | 2026-07-18 | **`/start-all` shipped** (catalog issue #20; maintainer-decided semantics: failed module blocks dependents, independent branches continue in `autonomous`, any non-CLEAR stops everything in `supervised`, no cost cap, resume via closed-issue filtering): deterministic DAG script (`milestone-dag.mjs`, ticket `blocked_by` as ground truth, cycles/dangling refs are hard errors) + `start-all` workflow composing `run-milestone` per module + `/start-all` command. 19 new E2E checks (DAG fixtures incl. cycle; module-policy scenarios via stubbed child workflows). Per-ticket stages unchanged. | Maintainer answers on issue #20, 2026-07-18. | Horace Hou (decisions) / Claude Fable 5 (build) |
155
155
  | 2026-07-18 | **First field bug fixed** (catalog issue #21, reported from Ruihang2017/Groundwork through the upstream feedback channel): CRLF-rewritten workflow scripts are rejected by the Workflow tool on Windows. Fix: repo-wide `.gitattributes` (`eol=lf`), working tree renormalized (67 files), `adopt.mjs` installs all text as LF, E2E `\r` guards added. Recorded as the pattern's first true `[internal]` pitfall observation. | Field report (Horace Hou via Groundwork), 2026-07-18. | Horace Hou (report) / Claude Fable 5 (fix) |
156
156
  | 2026-07-20 | **Doc/site command coverage mechanized** (catalog issue #35, maintainer direction: `/start-all` had shipped but never appeared in the npm README or the catalog site, so users could not discover it — surfacing commands must be impossible to forget). The command frontmatter is the single source of truth: `build-site.mjs` now renders a Commands section per pattern from it (site complete by construction), README carries the full command list, and an E2E coverage gate asserts every `scaffold/.claude/commands/*.md` name appears in BOTH the generated site and README with a non-empty description (plus a non-vacuous sentinel guard). Adding a command without documenting it now fails the merge gate. No pattern-behavior change. | Maintainer direction (Horace Hou), 2026-07-20. | Horace Hou (direction) / Claude Opus 4.8 (build) |
157
+ | 2026-07-21 | **Model/effort revised** (catalog issue #42, maintainer decision from field observation): Architect `claude-sonnet-5 @ xhigh` → `claude-opus-4-8 @ max` — plans were running too general and, being the fresh-context cold-start contract, under-specified plans drift downstream; the top model at `max` is invested in the highest-leverage stage (token budget not a constraint). Reviewer `claude-fable-5 @ max` → `@ xhigh` — Fable 5's capability margin (not effort headroom) is what catches edge cases at the gate, and `max` carries the documented overthinking/latency risk (§4). Builder and Triage unchanged; Reviewer stays a different model tier from the Builder. Same-commit: §3 table + as-of date, agent frontmatter, snippet, integrity pins. No benchmark claims invented — the Architect change is grounded in the `[internal]` observation + a `[team-policy]` choice. | Maintainer decision (Horace Hou), 2026-07-21. | Horace Hou (decision) / Claude Opus 4.8 (build) |
158
+ | 2026-07-20 | **Upstream issue escalation made opt-in** (catalog issue #40, maintainer decision): the CLAUDE.md snippet's "file pattern-level problems against the catalog" bullet — which hardcoded the maintainer's repo slug and a `gh issue create` instruction — is now wrapped in `<!-- upstream-escalation -->` markers and stripped by default. `adopt --upstream` opts in (bare = the catalog you adopted from; `--upstream <owner/repo>` retargets to a fork or internal catalog); the markers never leak into CLAUDE.md. Rationale: commercial and private adopters do not want an external repo slug or "file issues upstream" behavior written into their repo unasked. A neighboring line that named the product was also generalized to "the upstream pattern catalog". E2E: default adopt writes no catalog slug/marker/bullet; `--upstream` and `--upstream <repo>` include and retarget it. | Maintainer decision (Horace Hou), 2026-07-20. | Horace Hou (decision) / Claude Opus 4.8 (build) |
159
+ | 2026-07-20 | **adopt never guesses the platform** (catalog issue #38, maintainer decision, refining #34): the no-signal fallback no longer silently defaults to `gh`. Resolution order — `--platform`, origin host, repo-local signal (`.gitlab-ci.yml`/`.github/`); when none resolve, adopt prompts if interactive and otherwise exits without installing, asking for `--platform gh|glab`. This makes the agent-driven flow confirm the platform (adopt errors → agent asks the user → re-runs with `--platform`) before any infrastructure is built. E2E: no-signal non-TTY exits 1 and installs nothing; a repo-local signal still resolves without `--platform`. | Maintainer decision (Horace Hou), 2026-07-20. | Horace Hou (decision) / Claude Opus 4.8 (build) |
157
160
  | 2026-07-20 | **Platform compatibility hardened** (catalog issue #34, maintainer question): `adopt.mjs` detection now uses multiple deterministic signals — origin host `gitlab`/`github` substring, then a repo-local signal (`.gitlab-ci.yml` → glab, existing `.github/` → gh), then default gh with a loud ambiguity note — so a self-hosted GitLab on a custom domain is no longer misread as GitHub. The resolved platform is recorded as a `Tracker:` line in the adopted CLAUDE.md, and `/start-milestone` · `/start-all` · `/nightly-issues` now read `platform` from that line instead of guessing (parallel to Operating mode / testCmd). E2E: self-hosted-GitLab detection, `Tracker:` line matches platform, ambiguity note. Runtime scripts' own `--platform`/autodetect unchanged. | Maintainer question (Horace Hou), 2026-07-20. | Horace Hou (question) / Claude Opus 4.8 (fix) |
158
161
  | 2026-07-19 | **Field bug #4 fixed** (catalog issue #31, field report from Ruihang2017/Groundwork2): `milestone-dag.mjs` emitted each module's tickets in ID order instead of topologically by intra-module `blocked_by`, so a module whose declared order deviates from ID order dispatched a ticket before its blocker and failed at the Builder's precondition gate. Fix: a shared Kahn `topoSort` now orders both modules and, within each module, tickets by intra-module `blocked_by` (cross-module edges stay module-level; ID order as tiebreak; intra-module cycle fails loudly). E2E +7 (suite-dag D6 the 0502/0503 inversion, D7 intra-module cycle, D8 ID-order tiebreak). run-milestone dispatch loop unchanged. | Field report (Horace Hou via Groundwork2), 2026-07-18. | Horace Hou (report) / Claude Opus 4.8 (fix) |
159
162
  | 2026-07-19 | **Pipeline tool surface explicitly pre-allowed** (catalog issue #30, maintainer direction): scaffold `settings.json` now enumerates allow rules for everything the stages legitimately run — deterministic scripts, git branch/commit/push/read set, `npm test`-family, `gh`/`glab` issue list/view/comment/edit|update|note/close/create — so a fully autonomous `/start-all` → deliver → nightly cycle triggers zero interactive approvals. Deliberately not pre-allowed (role discipline stays mechanical): `git merge`/`rebase`/`reset`/`clean`, `gh pr *`, and bare `git:*`/`gh:*`/`glab:*` wildcards — E2E asserts both directions so drift fails the gate. Risk accepted and recorded: `git push:*` includes force variants; `gh issue create:*` is broader than the publish-tickets discipline (nightly report issue needs it); prefix-deny of flags is structurally incomplete so not attempted. | Maintainer direction (Horace Hou), 2026-07-19. | Horace Hou (direction) / Claude Fable 5 (build) |
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: architect
3
3
  description: Architect (Planner) stage of the three-agent pattern. Reads the ticket and the codebase, produces the implementation plan at docs/plans/<ticket-id>.md. Exploration/tool-call heavy. Writes NO production code.
4
- model: claude-sonnet-5
5
- effort: xhigh
4
+ model: claude-opus-4-8
5
+ effort: max
6
6
  tools: Read, Glob, Grep, Bash, Write
7
7
  ---
8
8
 
9
- <!-- Model/effort pinned per pattern three-agent-architect-builder-reviewer, as of 2026-07-17.
9
+ <!-- Model/effort pinned per pattern three-agent-architect-builder-reviewer, as of 2026-07-21.
10
10
  Do not change them here first — update the pattern entry in agent-templates, then sync. -->
11
11
 
12
12
  You are the **Architect** in the Architect → Builder → Reviewer pipeline. You plan; you do not build. You write **planning artifacts only**: per-ticket implementation plans (`docs/plans/`), and — when running a PRD decomposition via `/breakdown-prd` — the breakdown plan, sub-PRDs, and tickets under `docs/prd/` (follow that command's output spec and `templates/ticket.template.md` exactly). Never production code, tests, or configs.
@@ -2,11 +2,11 @@
2
2
  name: reviewer
3
3
  description: Reviewer stage of the three-agent pattern. Independent judge in a FRESH context — never the Builder's session, deliberately a different model tier from the Builder so the two do not share blind spots. Clears the work or bounces it back with findings.
4
4
  model: claude-fable-5
5
- effort: max
5
+ effort: xhigh
6
6
  tools: Read, Glob, Grep, Bash
7
7
  ---
8
8
 
9
- <!-- Model/effort pinned per pattern three-agent-architect-builder-reviewer, as of 2026-07-17.
9
+ <!-- Model/effort pinned per pattern three-agent-architect-builder-reviewer, as of 2026-07-21.
10
10
  Do not change them here first — update the pattern entry in agent-templates, then sync. -->
11
11
 
12
12
  You are the **Reviewer** — the last quality gate before merge, independent of the Builder.
@@ -12,7 +12,7 @@ From a checkout of the catalog: `node scripts/adopt.mjs three-agent-architect-bu
12
12
  2. Install the catalog's **universal templates** (shared by all patterns — source of truth is the catalog root, not this scaffold): `templates/ticket.template.md` → the target repo's `templates/`; the platform half of `templates/tracker/` → `.github/` (ISSUE_TEMPLATE/ + PULL_REQUEST_TEMPLATE.md) or `.gitlab/` (issue_templates/ + merge_request_templates/). Then fill the PR/MR template's **Constraint check** section with the target repo's CLAUDE.md non-negotiables. Hand-written issues and pipeline PRs now share one format that triage can convert and reviewers can verify.
13
13
  3. The write-guard hook needs Node.js ≥ 18 on PATH. It denies main-session Edit/Write with a dispatch instruction; subagent writes pass. Override switch for human-approved out-of-pipeline edits: create `.claude/allow-main-writes`, delete it afterwards — and add that path to `.gitignore`.
14
14
  4. The tracker steps (`publish-tickets.mjs`, `deliver-ticket.mjs`, `/verify-delivery`, the nightly sweep) need the platform CLI installed and authenticated: `gh` (GitHub) or `glab` (GitLab). The publish script autodetects the platform from the origin remote; override with `--platform gh|glab` (test doubles / non-PATH binaries: `GH_BIN` / `GLAB_BIN` env overrides). Delivery (merge `--no-ff` + push + verified issue close + deterministic DoD) is `deliver-ticket.mjs` — never an agent improvising git/tracker writes; `settings.json` carries explicit allow rules for the pipeline's whole tool surface (the three deterministic scripts, the enumerated git branch/commit/push set, `npm test`-family test commands, and the enumerated `gh`/`glab` issue commands) so unattended runs do not stall waiting for interactive approval (catalog issues #26, #30). Deliberately NOT pre-allowed: `git merge` / `rebase` / `reset` / `clean` and `gh pr *` — merging belongs to `deliver-ticket.mjs`. If your project's test command is not `npm test` / `npm run test` / `node --test`, add one more allow rule for it (e.g. `Bash(pytest:*)`).
15
- 5. Append the content of `claude-md-snippet.md` to the target repo's `CLAUDE.md`, and set the **Operating mode** line (`supervised` for a fresh adoption; `autonomous` is the target) and the **Tracker** line (`gh` for GitHub, `glab` for GitLab — the commands and workflows read the platform from this line). `adopt.mjs` sets Tracker automatically from the origin remote; set it by hand only on a manual install.
15
+ 5. Append the content of `claude-md-snippet.md` to the target repo's `CLAUDE.md`, and set the **Operating mode** line (`supervised` for a fresh adoption; `autonomous` is the target) and the **Tracker** line (`gh` for GitHub, `glab` for GitLab — the commands and workflows read the platform from this line). `adopt.mjs` sets Tracker automatically from the origin remote; set it by hand only on a manual install. The snippet contains one **opt-in** bullet between `<!-- upstream-escalation -->` markers that tells agents to file pattern-level problems against the catalog — **delete that block (and its markers) unless you want it**, or repoint the `--repo` slug at your own catalog. `adopt.mjs` strips it by default; keep it only with `--upstream`.
16
16
  6. Ensure the docs layout the pipeline assumes exists: `docs/PRD.md`, `docs/prd/<module>/README.md` (the sub-PRD — `/start-milestone` hard-requires it), `docs/prd/<module>/tickets/` (author tickets from `templates/ticket.template.md`), `docs/adr/`, and an empty `docs/plans/`.
17
17
  7. Check the pattern entry's expiry (README metadata table). If expired, re-verify the model/effort table against current official docs before adopting — do not copy an expired recommendation into a new project.
18
18
 
@@ -12,9 +12,9 @@
12
12
  Every non-trivial ticket flows through three stages; no agent judges its own work.
13
13
 
14
14
  - **`/breakdown-prd [notes]`** — pre-Gate-1: the Architect decomposes `docs/PRD.md` into a breakdown plan + sub-PRDs + template-compliant tickets (disjoint file-scopes, dependency DAG), then stops for human review.
15
- - **`/plan-ticket <ticket>`** — Architect (`claude-sonnet-5` @ `xhigh`) reads the ticket + codebase → implementation plan at `docs/plans/<ticket-id>.md`. Writes no production code.
15
+ - **`/plan-ticket <ticket>`** — Architect (`claude-opus-4-8` @ `max`) reads the ticket + codebase → implementation plan at `docs/plans/<ticket-id>.md`. Writes no production code.
16
16
  - **`/build-ticket <ticket>`** — Builder (`claude-opus-4-8` @ `xhigh`) implements the plan, runs tests until green, records deviations. Never merges or self-clears.
17
- - **`/review-ticket <ticket>`** — Reviewer (`claude-fable-5` @ `max`) in a **fresh context**, deliberately a different model tier from the Builder. Focus: edge cases, concurrency, security-sensitive paths. Verdict **CLEAR** or **BOUNCE**; merge requires CLEAR.
17
+ - **`/review-ticket <ticket>`** — Reviewer (`claude-fable-5` @ `xhigh`) in a **fresh context**, deliberately a different model tier from the Builder. Focus: edge cases, concurrency, security-sensitive paths. Verdict **CLEAR** or **BOUNCE**; merge requires CLEAR.
18
18
  - **`/verify-delivery <ticket>`** — post-merge Definition-of-Done check: plan on disk · tests green · CLEAR verdict · MR merged into the default branch · **tracker issue closed** · writeback done. Run after **every** merge; tracker auto-close side effects are never trusted blindly.
19
19
  - **`/start-milestone <module> [mode]`** — the Gate 1 start signal: verify sub-PRD + tickets, publish tickets as tracker issues (deterministic idempotent script — agents never hand-create issues), then run every ticket through the deterministic `run-milestone` workflow (stage order, bounce cap, merge policy enforced in code).
20
20
  - **`/start-all [mode]`** — Gate 1 for the **whole PRD**: compute the module DAG from ticket `blocked_by` frontmatter (`milestone-dag.mjs`, deterministic — cycles and dangling refs fail loudly), publish every module, then drive all modules through `run-milestone` in dependency order. Failed modules block their dependents; independent branches continue in `autonomous`; anything short of a CLEAR stops everything in `supervised`. Re-run to resume — fully-closed modules skip as already-complete.
@@ -35,5 +35,7 @@ Rules:
35
35
  - Trivial/mechanical changes may skip the pipeline only with an explicit human OK.
36
36
  - Ticket files are the issue-content source of truth. Issues are created only by `.claude/scripts/publish-tickets.mjs` (`[<id>]` title prefix = dedupe key); to change an issue body, edit the ticket file and republish. Issue state (close) moves via the deliver step / `/verify-delivery`, never by hand mid-pipeline.
37
37
  - Agents own the whole test pyramid: the Builder writes and runs unit + integration tests (and E2E where the ticket's acceptance calls for it); the Reviewer re-runs the full suite independently; the deliver step re-runs it on the merged default branch. The human tests exactly once — the Gate 2 smoke test after the PRD's tasks are all done.
38
+ <!-- upstream-escalation:start -->
38
39
  - **Pattern-level problems go upstream, not here.** If the pipeline itself misbehaves (a role boundary misfits, a model/effort pin looks stale, an orchestration bug), file an issue against the pattern catalog — `gh issue create --repo Ruihang2017/agent-templates` using its issue templates — so the catalog's own nightly sweep triages it. Project bugs stay in this repo's tracker.
39
- - Model/effort per role are pinned in `.claude/agents/*.md`. Change them by updating the pattern entry in agent-templates first (new as-of date + provenance entry), then syncing here — never by editing only this repo.
40
+ <!-- upstream-escalation:end -->
41
+ - Model/effort per role are pinned in `.claude/agents/*.md`. Change them by updating the pattern entry in the upstream pattern catalog first (new as-of date + provenance entry), then syncing here — never by editing only this repo.
package/scripts/adopt.mjs CHANGED
@@ -18,6 +18,7 @@
18
18
 
19
19
  import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
20
20
  import { execFileSync } from 'node:child_process'
21
+ import { createInterface } from 'node:readline/promises'
21
22
  import { basename, dirname, join, relative, resolve } from 'node:path'
22
23
  import { fileURLToPath } from 'node:url'
23
24
 
@@ -31,10 +32,27 @@ if (pIx !== -1 && (!PLATFORM || PLATFORM.startsWith('--'))) {
31
32
  console.error('missing or invalid --platform value (expected gh or glab)')
32
33
  process.exit(1)
33
34
  }
34
- const positional = argv.filter((a, i) => !a.startsWith('--') && (pIx === -1 || i !== pIx + 1))
35
+
36
+ // --upstream [owner/repo]: opt IN to the "file pattern-level problems against the
37
+ // catalog" bullet in CLAUDE.md (off by default — the bullet names a specific repo and
38
+ // tells agents to file issues there, which commercial/private adopters do not want, and
39
+ // the repo slug should never land in a CLAUDE.md unasked; issue #40). Bare --upstream
40
+ // targets the catalog this pattern came from; --upstream <repo> points elsewhere.
41
+ const CATALOG_REPO = 'Ruihang2017/agent-templates'
42
+ const uIx = argv.indexOf('--upstream')
43
+ const UPSTREAM = uIx !== -1
44
+ let UPSTREAM_REPO = CATALOG_REPO
45
+ if (uIx !== -1 && argv[uIx + 1] && !argv[uIx + 1].startsWith('--')) UPSTREAM_REPO = argv[uIx + 1]
46
+
47
+ // positional args = everything that isn't a flag or a flag's consumed value
48
+ const consumed = new Set()
49
+ for (const ix of [pIx, uIx]) {
50
+ if (ix !== -1 && argv[ix + 1] && !argv[ix + 1].startsWith('--')) consumed.add(ix + 1)
51
+ }
52
+ const positional = argv.filter((a, i) => !a.startsWith('--') && !consumed.has(i))
35
53
  const [pattern, targetArg] = positional
36
54
  if (!pattern || !targetArg) {
37
- console.error('usage: node scripts/adopt.mjs <pattern-name> <target-dir> [--platform gh|glab] [--force]')
55
+ console.error('usage: node scripts/adopt.mjs <pattern-name> <target-dir> [--platform gh|glab] [--upstream [owner/repo]] [--force]')
38
56
  process.exit(1)
39
57
  }
40
58
 
@@ -72,7 +90,35 @@ if (!PLATFORM) {
72
90
  else if (/github/i.test(host)) { PLATFORM = 'gh'; console.log(`platform: gh (from origin host '${host}'; override with --platform)`) }
73
91
  else if (existsSync(join(target, '.gitlab-ci.yml'))) { PLATFORM = 'glab'; console.log(`platform: glab (from .gitlab-ci.yml${inconclusive}; override with --platform)`) }
74
92
  else if (existsSync(join(target, '.github'))) { PLATFORM = 'gh'; console.log(`platform: gh (from existing .github/${inconclusive}; override with --platform)`) }
75
- else { PLATFORM = 'gh'; console.log(`platform: gh (default — ${host ? `could not classify origin host '${host}'` : 'no origin remote'}; pass --platform glab if this is a self-hosted GitLab)`) }
93
+ else {
94
+ // No signal: never guess — a wrong guess installs the wrong tracker config and a
95
+ // wrong Tracker line (issue #38). Ask when interactive; otherwise stop and install
96
+ // nothing so the agent/CI can re-run with an explicit --platform.
97
+ const reason = host ? `could not classify origin host '${host}'` : 'no git remote, and no .gitlab-ci.yml or .github/ to infer from'
98
+ if (process.stdin.isTTY) {
99
+ const rl = createInterface({ input: process.stdin, output: process.stdout })
100
+ // Ctrl+D / closed stdin before an answer: abort cleanly (nothing installed)
101
+ // instead of leaving the top-level await unsettled.
102
+ rl.on('close', () => {
103
+ if (!PLATFORM) {
104
+ console.error('\nplatform: undetermined (input closed). Re-run with --platform gh|glab (nothing was installed).')
105
+ process.exit(1)
106
+ }
107
+ })
108
+ try {
109
+ console.log(`Cannot determine the tracker platform (${reason}).`)
110
+ for (;;) {
111
+ const a = (await rl.question('Which tracker is this repo on? [gh/glab] ')).trim().toLowerCase()
112
+ if (a === 'gh' || a === 'github') { PLATFORM = 'gh'; break }
113
+ if (a === 'glab' || a === 'gitlab') { PLATFORM = 'glab'; break }
114
+ console.log("please answer 'gh' or 'glab'")
115
+ }
116
+ } finally { rl.close() }
117
+ } else {
118
+ console.error(`platform: undetermined — ${reason}. Re-run with --platform gh|glab (nothing was installed).`)
119
+ process.exit(1)
120
+ }
121
+ }
76
122
  }
77
123
  if (PLATFORM !== 'gh' && PLATFORM !== 'glab') {
78
124
  console.error(`unknown platform: ${PLATFORM} (expected gh or glab)`)
@@ -167,8 +213,23 @@ if (existsSync(rootPrd) && !existsSync(docsPrd)) {
167
213
  // 6. CLAUDE.md: create from the snippet, or append it once (marker-checked, never duplicated).
168
214
  // The snippet defaults its Tracker line to `gh`; rewrite it to the resolved platform so the
169
215
  // pipeline reads the correct tracker from CLAUDE.md instead of re-guessing each run (issue #34).
170
- const snippet = readFileSync(join(scaffold, 'claude-md-snippet.md'), 'utf8')
216
+ // Normalize CRLF up front: the marker/Tracker matching below needs literal \n, and a
217
+ // catalog checkout under git autocrlf can carry \r\n — don't let that silently no-op the
218
+ // strip and leak the block (same posture as copyFile; catalog issues #21/#23/#40).
219
+ let snippet = readFileSync(join(scaffold, 'claude-md-snippet.md'), 'utf8')
220
+ .replace(/\r\n/g, '\n')
171
221
  .replace('**Tracker: `gh`**', `**Tracker: \`${PLATFORM}\`**`)
222
+ // Upstream-escalation bullet is opt-in (issue #40): keep it only with --upstream (pointing
223
+ // at the chosen catalog repo), otherwise strip the whole marked block so no catalog repo
224
+ // slug or "file issues upstream" instruction lands in the adopted CLAUDE.md.
225
+ const UP_RE = /\n<!-- upstream-escalation:start -->\n([\s\S]*?)\n<!-- upstream-escalation:end -->/
226
+ if (UPSTREAM) {
227
+ snippet = snippet.replace(UP_RE, (_, bullet) => '\n' + bullet.split(CATALOG_REPO).join(UPSTREAM_REPO))
228
+ console.log(`upstream escalation: on (issues -> ${UPSTREAM_REPO})`)
229
+ } else {
230
+ snippet = snippet.replace(UP_RE, '')
231
+ console.log('upstream escalation: off (enable with --upstream [owner/repo])')
232
+ }
172
233
  const MARKER = '## Delivery pipeline — three-agent Architect / Builder / Reviewer'
173
234
  const claudeMd = join(target, 'CLAUDE.md')
174
235
  if (!existsSync(claudeMd)) {
@@ -24,6 +24,7 @@ const OUT = outIx !== -1 && argv[outIx + 1] ? argv[outIx + 1] : join(ROOT, 'site
24
24
  const GITHUB = 'https://github.com/Ruihang2017/agent-templates'
25
25
  const NPM = 'https://www.npmjs.com/package/agent-templates'
26
26
  const QUICKSTART = 'npx agent-templates@latest adopt three-agent-architect-builder-reviewer .'
27
+ const UPDATE = QUICKSTART + ' --force'
27
28
 
28
29
  const esc = (s) => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
29
30
  const strip = (s) => String(s).replace(/\*\*/g, '').replace(/`/g, '').trim()
@@ -243,6 +244,8 @@ const html = `<!doctype html>
243
244
  .quick{margin-top:20px;border-radius:16px;background:var(--pill);padding:14px 16px 12px;
244
245
  box-shadow:inset 0 3px 6px rgba(var(--flt),0.2),inset 0 -2px 2px rgba(255,255,255,0.8)}
245
246
  .quick code{display:block;font-family:var(--mono);font-size:12px;font-weight:700;color:var(--code);line-height:1.55;word-break:break-all}
247
+ .update-note{margin:12px 0 0;font-size:11.5px;font-weight:700;line-height:1.5;color:var(--hero-body)}
248
+ .update-note code{font-family:var(--mono);font-size:11px;color:var(--hero-title);word-break:break-all}
246
249
  .copy{display:inline-flex;margin-top:10px;padding:6px 16px;border-radius:13px;border:0;
247
250
  background:linear-gradient(180deg,#f9d66e,#f0c14a);cursor:pointer;font-family:'Nunito',sans-serif;
248
251
  font-size:12px;font-weight:900;color:#6b4a15;transition:transform .15s ease;
@@ -340,6 +343,7 @@ const html = `<!doctype html>
340
343
  <code id="qs">${esc(QUICKSTART)}</code>
341
344
  <button class="copy" id="copy-btn" type="button">Copy</button>
342
345
  </div>
346
+ <p class="update-note">Already installed? Update to the latest catalog version: <code>${esc(UPDATE)}</code> (commit first — <code>--force</code> overwrites).</p>
343
347
  </div>
344
348
  <div class="hero-side">
345
349
  ${FACTS.map(([tile, glyph, copy]) => `<div class="fact"><span class="fact-ico" style="${tile}">${glyph}</span><p>${copy}</p></div>`).join('\n ')}