agent-templates 0.1.0
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 +57 -0
- package/CLAUDE.md +125 -0
- package/LICENSE +21 -0
- package/README.md +32 -0
- package/package.json +32 -0
- package/patterns/three-agent-architect-builder-reviewer/README.md +153 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/agents/architect.md +31 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/agents/builder.md +25 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/agents/reviewer.md +33 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/agents/triage.md +31 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/breakdown-prd.md +18 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/build-ticket.md +12 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/nightly-issues.md +14 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/plan-ticket.md +10 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/review-ticket.md +14 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/start-milestone.md +15 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/verify-delivery.md +20 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/hooks/guard-main-session-writes.mjs +53 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/scripts/publish-tickets.mjs +263 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/settings.json +15 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/workflows/nightly-issues.js +139 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/workflows/run-milestone.js +223 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/INSTALL.md +65 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/claude-md-snippet.md +37 -0
- package/scripts/adopt.mjs +177 -0
- package/scripts/build-site.mjs +264 -0
- package/scripts/cli.mjs +52 -0
- package/templates/pattern-README.template.md +65 -0
- package/templates/ticket.template.md +104 -0
- package/templates/tracker/github/ISSUE_TEMPLATE/bug-report.md +28 -0
- package/templates/tracker/github/ISSUE_TEMPLATE/decision-record.md +25 -0
- package/templates/tracker/github/ISSUE_TEMPLATE/task.md +36 -0
- package/templates/tracker/github/PULL_REQUEST_TEMPLATE.md +54 -0
- package/templates/tracker/gitlab/issue_templates/bug-report.md +23 -0
- package/templates/tracker/gitlab/issue_templates/decision-record.md +20 -0
- package/templates/tracker/gitlab/issue_templates/task.md +31 -0
- package/templates/tracker/gitlab/merge_request_templates/default.md +55 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// build-site.mjs — generates the catalog's GitHub Pages site from the catalog's own
|
|
3
|
+
// data (patterns/*/README.md + package.json). Never hand-edit the output: the page
|
|
4
|
+
// must not be able to drift from the pattern metadata.
|
|
5
|
+
//
|
|
6
|
+
// Usage: node scripts/build-site.mjs [--out <dir>] (default: site/)
|
|
7
|
+
// Output: <out>/index.html (self-contained) + <out>/.nojekyll
|
|
8
|
+
//
|
|
9
|
+
// Style: claymorphism per catalog issue #17 — cream background, pastel clay palette,
|
|
10
|
+
// puffy cards, soft extruded shadows, rounded chunky type, emoji as clay icons.
|
|
11
|
+
|
|
12
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
13
|
+
import { join } from 'node:path'
|
|
14
|
+
import { fileURLToPath } from 'node:url'
|
|
15
|
+
|
|
16
|
+
const ROOT = fileURLToPath(new URL('..', import.meta.url))
|
|
17
|
+
const argv = process.argv.slice(2)
|
|
18
|
+
const outIx = argv.indexOf('--out')
|
|
19
|
+
const OUT = outIx !== -1 && argv[outIx + 1] ? argv[outIx + 1] : join(ROOT, 'site')
|
|
20
|
+
|
|
21
|
+
const GITHUB = 'https://github.com/Ruihang2017/agent-templates'
|
|
22
|
+
const NPM = 'https://www.npmjs.com/package/agent-templates'
|
|
23
|
+
const QUICKSTART = 'npx agent-templates@latest adopt three-agent-architect-builder-reviewer .'
|
|
24
|
+
|
|
25
|
+
const esc = (s) => String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')
|
|
26
|
+
const strip = (s) => String(s).replace(/\*\*/g, '').replace(/`/g, '').trim()
|
|
27
|
+
|
|
28
|
+
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'))
|
|
29
|
+
|
|
30
|
+
function parsePattern(dir) {
|
|
31
|
+
const path = join(ROOT, 'patterns', dir, 'README.md')
|
|
32
|
+
if (!existsSync(path)) return null
|
|
33
|
+
const md = readFileSync(path, 'utf8')
|
|
34
|
+
const pick = (re) => (md.match(re) || [])[1] || ''
|
|
35
|
+
|
|
36
|
+
const title = strip(pick(/^# Pattern: (.+)$/m)) || dir
|
|
37
|
+
const statusRaw = strip(pick(/\|\s*\*\*Status\*\*\s*\|\s*([^|]+)\|/))
|
|
38
|
+
const status = (statusRaw.match(/[a-z]+/) || ['proposed'])[0]
|
|
39
|
+
const asOf = strip(pick(/\|\s*\*\*As-of date\*\*\s*\|\s*([^|]+)\|/))
|
|
40
|
+
|
|
41
|
+
// the one-line topology summary: first plain paragraph after the metadata table
|
|
42
|
+
let summary = ''
|
|
43
|
+
const lines = md.split('\n')
|
|
44
|
+
for (let i = 0; i < lines.length; i++) {
|
|
45
|
+
const l = lines[i].trim()
|
|
46
|
+
if (!l || l.startsWith('#') || l.startsWith('|') || l.startsWith('<!--')) continue
|
|
47
|
+
summary = strip(l)
|
|
48
|
+
break
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// model/effort rows from §3
|
|
52
|
+
const roles = []
|
|
53
|
+
const sec3 = md.split(/^## 3\. Model \+ effort[^\n]*$/m)[1]
|
|
54
|
+
if (sec3) {
|
|
55
|
+
for (const row of sec3.split(/^## /m)[0].split('\n')) {
|
|
56
|
+
const m = row.match(/^\|\s*([A-Z][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*`([^`]+)`\s*\|/)
|
|
57
|
+
if (m && !/^Role/.test(m[1])) roles.push({ role: strip(m[1]), model: strip(m[2]), effort: m[3] })
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// first three "Use when" bullets from §1
|
|
62
|
+
const useWhen = []
|
|
63
|
+
const sec1 = md.split(/\*\*Use when:\*\*/)[1]
|
|
64
|
+
if (sec1) {
|
|
65
|
+
for (const l of sec1.split(/\*\*Do not use when:\*\*/)[0].split('\n')) {
|
|
66
|
+
const m = l.match(/^- (.+)$/)
|
|
67
|
+
if (m && useWhen.length < 3) useWhen.push(strip(m[1]))
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return { dir, title, status, asOf, summary, roles, useWhen }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const patterns = readdirSync(join(ROOT, 'patterns'), { withFileTypes: true })
|
|
75
|
+
.filter((d) => d.isDirectory() && existsSync(join(ROOT, 'patterns', d.name, 'scaffold')))
|
|
76
|
+
.map((d) => parsePattern(d.name))
|
|
77
|
+
.filter(Boolean)
|
|
78
|
+
|
|
79
|
+
const STATUS_STYLE = {
|
|
80
|
+
proposed: ['var(--blue)', 'var(--blue-d)', '🧪'],
|
|
81
|
+
trialed: ['var(--butter)', 'var(--butter-d)', '🌱'],
|
|
82
|
+
adopted: ['var(--sage)', 'var(--sage-d)', '✅'],
|
|
83
|
+
deprecated: ['var(--pink)', 'var(--pink-d)', '🗄️'],
|
|
84
|
+
}
|
|
85
|
+
const ROLE_EMOJI = { Architect: '📐', Builder: '🔨', Reviewer: '🔍' }
|
|
86
|
+
const roleEmoji = (r) => ROLE_EMOJI[Object.keys(ROLE_EMOJI).find((k) => r.startsWith(k))] || '🌙'
|
|
87
|
+
|
|
88
|
+
const patternCards = patterns
|
|
89
|
+
.map((p) => {
|
|
90
|
+
const [bg, fg, ico] = STATUS_STYLE[p.status] || STATUS_STYLE.proposed
|
|
91
|
+
return `
|
|
92
|
+
<article class="card pattern">
|
|
93
|
+
<div class="pattern-head">
|
|
94
|
+
<h3>${esc(p.title)}</h3>
|
|
95
|
+
<span class="pill status" style="background:${bg};color:${fg}">${ico} ${esc(p.status)} · as of ${esc(p.asOf)}</span>
|
|
96
|
+
</div>
|
|
97
|
+
<p class="summary">${esc(p.summary)}</p>
|
|
98
|
+
<div class="roles">
|
|
99
|
+
${p.roles.map((r) => `<span class="pill role">${roleEmoji(r.role)} <b>${esc(r.role)}</b> · ${esc(r.model)} <code>@${esc(r.effort)}</code></span>`).join('\n ')}
|
|
100
|
+
</div>
|
|
101
|
+
${p.useWhen.length ? `<ul class="usewhen">${p.useWhen.map((u) => `<li>${esc(u)}</li>`).join('')}</ul>` : ''}
|
|
102
|
+
<div class="links">
|
|
103
|
+
<a class="btn small sage" href="${GITHUB}/tree/main/patterns/${esc(p.dir)}">📖 Pattern write-up</a>
|
|
104
|
+
<a class="btn small lav" href="${GITHUB}/tree/main/patterns/${esc(p.dir)}/scaffold">🧰 Scaffold</a>
|
|
105
|
+
</div>
|
|
106
|
+
</article>`
|
|
107
|
+
})
|
|
108
|
+
.join('\n')
|
|
109
|
+
|
|
110
|
+
const STEPS = [
|
|
111
|
+
['📦', 'Adopt', `<code>${esc(QUICKSTART)}</code> — scaffold, templates, docs skeleton, CLAUDE.md, in one idempotent command.`],
|
|
112
|
+
['🗺️', 'Break down', '<code>/breakdown-prd</code> — the Architect turns your PRD into sub-PRDs and cold-startable tickets, then stops.'],
|
|
113
|
+
['🚦', 'Gate 1 — you decide', 'Review the breakdown, then <code>/start-milestone</code>: tickets become tracker issues and the pipeline starts.'],
|
|
114
|
+
['🤖', 'Autonomous middle', 'Plan → build → fresh-context review (bounce-capped in code) → merge on CLEAR → issue closed → delivery verified.'],
|
|
115
|
+
['🔎', 'Gate 2 — smoke test', 'Agents own unit/integration/E2E all along; you test once, when the PRD is done. A nightly sweep fixes issues while you sleep.'],
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
const html = `<!doctype html>
|
|
119
|
+
<html lang="en">
|
|
120
|
+
<head>
|
|
121
|
+
<meta charset="utf-8">
|
|
122
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
123
|
+
<title>agent-templates — multi-agent patterns, ready to drop in</title>
|
|
124
|
+
<meta name="description" content="A catalog of multi-agent development architecture patterns: design write-ups plus drop-in scaffolding, E2E-tested, published on npm.">
|
|
125
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
126
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
127
|
+
<link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@600;700;800&family=Nunito:ital,wght@0,400;0,600;0,700;1,400&display=swap" rel="stylesheet">
|
|
128
|
+
<style>
|
|
129
|
+
:root{
|
|
130
|
+
--bg:#f7f0e6; --card:#fdf8f2; --ink:#5b4a3f; --muted:#96826f;
|
|
131
|
+
--sage:#cfe3d0; --sage-d:#5f9c6c; --peach:#f9d3b5; --peach-d:#d97f45;
|
|
132
|
+
--pink:#f7c6d0; --pink-d:#cf6d87; --butter:#f7e0a8; --butter-d:#a97e1c;
|
|
133
|
+
--blue:#c5d7ee; --blue-d:#5c82b6; --lav:#d9cdf0; --lav-d:#8266bd;
|
|
134
|
+
--clay:0 10px 24px rgba(91,74,63,.13), inset 0 3px 8px rgba(255,255,255,.95), inset 0 -4px 8px rgba(91,74,63,.07);
|
|
135
|
+
--clay-sm:0 6px 14px rgba(91,74,63,.12), inset 0 2px 5px rgba(255,255,255,.9), inset 0 -2px 5px rgba(91,74,63,.06);
|
|
136
|
+
}
|
|
137
|
+
*{box-sizing:border-box}
|
|
138
|
+
body{margin:0;background:var(--bg);color:var(--ink);font:16px/1.6 "Nunito",system-ui,sans-serif;
|
|
139
|
+
background-image:radial-gradient(600px 300px at 85% -50px, rgba(247,198,208,.35), transparent 70%),
|
|
140
|
+
radial-gradient(500px 260px at -60px 30%, rgba(207,227,208,.4), transparent 70%),
|
|
141
|
+
radial-gradient(520px 300px at 110% 75%, rgba(217,205,240,.32), transparent 70%);}
|
|
142
|
+
h1,h2,h3{font-family:"Baloo 2","Nunito",sans-serif;line-height:1.15;margin:0}
|
|
143
|
+
a{color:inherit;text-decoration:none}
|
|
144
|
+
.wrap{max-width:1060px;margin:0 auto;padding:28px 20px 60px}
|
|
145
|
+
header.nav{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:26px}
|
|
146
|
+
.logo{font-family:"Baloo 2",sans-serif;font-weight:800;font-size:1.35rem;background:var(--card);
|
|
147
|
+
padding:10px 20px;border-radius:999px;box-shadow:var(--clay-sm);border:1.5px solid #fff}
|
|
148
|
+
.nav .spacer{flex:1}
|
|
149
|
+
.btn{display:inline-flex;align-items:center;gap:8px;font-weight:700;padding:10px 20px;border-radius:999px;
|
|
150
|
+
box-shadow:var(--clay-sm);border:1.5px solid #fff;transition:transform .15s ease, box-shadow .15s ease;cursor:pointer}
|
|
151
|
+
.btn:hover{transform:translateY(-2px)}
|
|
152
|
+
.btn.small{padding:8px 14px;font-size:.9rem}
|
|
153
|
+
.btn.sage{background:var(--sage);color:var(--sage-d)} .btn.peach{background:var(--peach);color:var(--peach-d)}
|
|
154
|
+
.btn.blue{background:var(--blue);color:var(--blue-d)} .btn.lav{background:var(--lav);color:var(--lav-d)}
|
|
155
|
+
.card{background:var(--card);border-radius:28px;box-shadow:var(--clay);border:1.5px solid #fff;padding:26px 28px}
|
|
156
|
+
.hero{display:grid;grid-template-columns:1.5fr 1fr;gap:22px;align-items:stretch;margin-bottom:22px}
|
|
157
|
+
.hero .main{background:linear-gradient(145deg,#fbe3cd, #f9d3b5);}
|
|
158
|
+
.hero h1{font-size:clamp(1.9rem,4.5vw,2.9rem);color:#7a4b28;margin-bottom:10px}
|
|
159
|
+
.hero p.lede{color:#8a5a35;font-size:1.06rem;max-width:34em;margin:0 0 18px}
|
|
160
|
+
.cta{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:18px}
|
|
161
|
+
.quick{background:rgba(255,255,255,.75);border-radius:18px;box-shadow:var(--clay-sm);border:1.5px solid #fff;
|
|
162
|
+
padding:12px 16px;display:flex;gap:10px;align-items:center;flex-wrap:wrap}
|
|
163
|
+
.quick code{font:600 .85rem/1.4 ui-monospace,Consolas,monospace;color:#7a4b28;word-break:break-all}
|
|
164
|
+
.hero .side{display:flex;flex-direction:column;gap:14px;justify-content:center}
|
|
165
|
+
.side .fact{display:flex;gap:12px;align-items:center;background:var(--card);border-radius:20px;
|
|
166
|
+
box-shadow:var(--clay-sm);border:1.5px solid #fff;padding:12px 16px;font-weight:600}
|
|
167
|
+
.side .fact .ico{font-size:1.5rem}
|
|
168
|
+
.chips{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:16px;margin:22px 0}
|
|
169
|
+
.chip{border-radius:24px;padding:18px 20px;box-shadow:var(--clay);border:1.5px solid #fff}
|
|
170
|
+
.chip .big{font-family:"Baloo 2",sans-serif;font-weight:800;font-size:1.7rem;display:block}
|
|
171
|
+
.chip small{font-weight:700;opacity:.75}
|
|
172
|
+
.chip.c1{background:var(--sage);color:var(--sage-d)} .chip.c2{background:var(--peach);color:var(--peach-d)}
|
|
173
|
+
.chip.c3{background:var(--butter);color:var(--butter-d)} .chip.c4{background:var(--blue);color:var(--blue-d)}
|
|
174
|
+
section{margin-top:34px}
|
|
175
|
+
section > h2{font-size:1.6rem;margin-bottom:14px}
|
|
176
|
+
.pattern{margin-bottom:18px}
|
|
177
|
+
.pattern-head{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:8px}
|
|
178
|
+
.pattern h3{font-size:1.3rem}
|
|
179
|
+
.pill{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;border-radius:999px;font-weight:700;
|
|
180
|
+
font-size:.85rem;box-shadow:var(--clay-sm);border:1.5px solid #fff}
|
|
181
|
+
.summary{color:var(--muted);margin:6px 0 14px;font-weight:600}
|
|
182
|
+
.roles{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:12px}
|
|
183
|
+
.pill.role{background:#f3ece1;color:var(--ink)} .pill.role code{color:var(--lav-d)}
|
|
184
|
+
.usewhen{margin:0 0 14px;padding-left:22px;color:var(--muted)} .usewhen li{margin:4px 0}
|
|
185
|
+
.links{display:flex;gap:10px;flex-wrap:wrap}
|
|
186
|
+
.steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:16px}
|
|
187
|
+
.step{border-radius:24px;padding:20px;box-shadow:var(--clay);border:1.5px solid #fff;background:var(--card)}
|
|
188
|
+
.step .n{display:inline-flex;width:44px;height:44px;align-items:center;justify-content:center;font-size:1.4rem;
|
|
189
|
+
border-radius:16px;box-shadow:var(--clay-sm);border:1.5px solid #fff;margin-bottom:10px}
|
|
190
|
+
.step:nth-child(1) .n{background:var(--sage)} .step:nth-child(2) .n{background:var(--butter)}
|
|
191
|
+
.step:nth-child(3) .n{background:var(--peach)} .step:nth-child(4) .n{background:var(--lav)}
|
|
192
|
+
.step:nth-child(5) .n{background:var(--pink)}
|
|
193
|
+
.step h3{font-size:1.05rem;margin-bottom:6px} .step p{margin:0;font-size:.9rem;color:var(--muted)}
|
|
194
|
+
.step code{font-size:.8rem;color:var(--lav-d);word-break:break-all}
|
|
195
|
+
footer{margin-top:44px;text-align:center;color:var(--muted);font-weight:600;font-size:.9rem}
|
|
196
|
+
footer a{color:var(--lav-d)}
|
|
197
|
+
@media (max-width:760px){.hero{grid-template-columns:1fr}}
|
|
198
|
+
</style>
|
|
199
|
+
</head>
|
|
200
|
+
<body>
|
|
201
|
+
<div class="wrap">
|
|
202
|
+
<header class="nav">
|
|
203
|
+
<span class="logo">🏗️ agent-templates</span>
|
|
204
|
+
<span class="spacer"></span>
|
|
205
|
+
<a class="btn sage" href="${GITHUB}">⭐ GitHub</a>
|
|
206
|
+
<a class="btn peach" href="${NPM}">📦 npm <span data-npm-version>v${esc(pkg.version)}</span></a>
|
|
207
|
+
</header>
|
|
208
|
+
|
|
209
|
+
<div class="hero">
|
|
210
|
+
<div class="card main">
|
|
211
|
+
<h1>Multi-agent patterns,<br>ready to drop in.</h1>
|
|
212
|
+
<p class="lede">Field-proven architectures for AI-agent development — each one a design write-up <b>plus</b> working scaffolding. Humans decide at two gates; the agents do the rest.</p>
|
|
213
|
+
<div class="cta">
|
|
214
|
+
<a class="btn blue" href="${GITHUB}/blob/main/ADOPTING.md">🚀 Adoption guide</a>
|
|
215
|
+
<a class="btn lav" href="${GITHUB}/blob/main/CLAUDE.md">📜 Operating manual</a>
|
|
216
|
+
</div>
|
|
217
|
+
<div class="quick"><code id="qs">${esc(QUICKSTART)}</code><button class="btn small butter" style="background:var(--butter);color:var(--butter-d)" onclick="navigator.clipboard.writeText(document.getElementById('qs').textContent).then(()=>{this.textContent='Copied ✓'})">Copy</button></div>
|
|
218
|
+
</div>
|
|
219
|
+
<div class="side">
|
|
220
|
+
<div class="fact"><span class="ico">🧾</span> Every model/effort claim carries a source label and an expiry date</div>
|
|
221
|
+
<div class="fact"><span class="ico">🛡️</span> Role boundaries enforced by hooks, not prose</div>
|
|
222
|
+
<div class="fact"><span class="ico">🌙</span> Nightly sweep triages and fixes issues while you sleep</div>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<div class="chips">
|
|
227
|
+
<div class="chip c1"><span class="big">${patterns.length}</span><small>pattern${patterns.length === 1 ? '' : 's'} in the catalog</small></div>
|
|
228
|
+
<div class="chip c2"><span class="big" data-npm-version>v${esc(pkg.version)}</span><small>on npm · MIT</small></div>
|
|
229
|
+
<div class="chip c3"><span class="big">E2E</span><small>gated merges — deterministic, zero-token tests</small></div>
|
|
230
|
+
<div class="chip c4"><span class="big">2</span><small>human gates: sign-off & smoke test</small></div>
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
<section>
|
|
234
|
+
<h2>🧩 Patterns</h2>
|
|
235
|
+
${patternCards}
|
|
236
|
+
</section>
|
|
237
|
+
|
|
238
|
+
<section>
|
|
239
|
+
<h2>🛤️ From a bare PRD.md to shipped</h2>
|
|
240
|
+
<div class="steps">
|
|
241
|
+
${STEPS.map(([ico, t, d], i) => `<div class="step"><span class="n">${ico}</span><h3>${i + 1}. ${t}</h3><p>${d}</p></div>`).join('\n ')}
|
|
242
|
+
</div>
|
|
243
|
+
</section>
|
|
244
|
+
|
|
245
|
+
<footer>
|
|
246
|
+
Generated from the pattern catalog by <a href="${GITHUB}/blob/main/scripts/build-site.mjs">scripts/build-site.mjs</a>
|
|
247
|
+
· ${new Date().toISOString().slice(0, 10)} · <a href="${GITHUB}/blob/main/LICENSE">MIT</a>
|
|
248
|
+
· <a href="${GITHUB}/issues/new/choose">Feedback → issues</a>
|
|
249
|
+
</footer>
|
|
250
|
+
</div>
|
|
251
|
+
<script>
|
|
252
|
+
fetch('https://registry.npmjs.org/agent-templates').then(r=>r.json()).then(d=>{
|
|
253
|
+
var v=d['dist-tags']&&d['dist-tags'].latest;
|
|
254
|
+
if(v){document.querySelectorAll('[data-npm-version]').forEach(function(e){e.textContent='v'+v})}
|
|
255
|
+
}).catch(function(){})
|
|
256
|
+
</script>
|
|
257
|
+
</body>
|
|
258
|
+
</html>
|
|
259
|
+
`
|
|
260
|
+
|
|
261
|
+
mkdirSync(OUT, { recursive: true })
|
|
262
|
+
writeFileSync(join(OUT, 'index.html'), html)
|
|
263
|
+
writeFileSync(join(OUT, '.nojekyll'), '')
|
|
264
|
+
console.log(`site: ${join(OUT, 'index.html')} (${patterns.length} pattern(s), pkg v${pkg.version})`)
|
package/scripts/cli.mjs
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// agent-templates CLI — the npx entry point (package.json "bin").
|
|
3
|
+
// Dispatches to the catalog tooling; carries no logic of its own.
|
|
4
|
+
//
|
|
5
|
+
// agent-templates list show available patterns
|
|
6
|
+
// agent-templates adopt <pattern> <target-dir> [options] install a pattern (see adopt.mjs)
|
|
7
|
+
//
|
|
8
|
+
// Without cloning the catalog:
|
|
9
|
+
// npx github:Ruihang2017/agent-templates list
|
|
10
|
+
// npx github:Ruihang2017/agent-templates adopt three-agent-architect-builder-reviewer .
|
|
11
|
+
|
|
12
|
+
import { spawnSync } from 'node:child_process'
|
|
13
|
+
import { existsSync, readdirSync } from 'node:fs'
|
|
14
|
+
import { join } from 'node:path'
|
|
15
|
+
import { fileURLToPath } from 'node:url'
|
|
16
|
+
|
|
17
|
+
const ROOT = fileURLToPath(new URL('..', import.meta.url))
|
|
18
|
+
const [cmd, ...rest] = process.argv.slice(2)
|
|
19
|
+
|
|
20
|
+
if (cmd === 'adopt') {
|
|
21
|
+
const r = spawnSync(process.execPath, [join(ROOT, 'scripts', 'adopt.mjs'), ...rest], { stdio: 'inherit' })
|
|
22
|
+
process.exit(r.status === null ? 1 : r.status)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (cmd === 'list') {
|
|
26
|
+
const dir = join(ROOT, 'patterns')
|
|
27
|
+
const patterns = existsSync(dir)
|
|
28
|
+
? readdirSync(dir, { withFileTypes: true })
|
|
29
|
+
.filter((d) => d.isDirectory() && existsSync(join(dir, d.name, 'scaffold')))
|
|
30
|
+
.map((d) => d.name)
|
|
31
|
+
: []
|
|
32
|
+
console.log(patterns.length ? patterns.join('\n') : '(no patterns found)')
|
|
33
|
+
process.exit(0)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const usage = `agent-templates — multi-agent pattern catalog
|
|
37
|
+
|
|
38
|
+
usage:
|
|
39
|
+
agent-templates list
|
|
40
|
+
agent-templates adopt <pattern> <target-dir> [--platform gh|glab] [--force]
|
|
41
|
+
|
|
42
|
+
without cloning:
|
|
43
|
+
npx github:Ruihang2017/agent-templates list
|
|
44
|
+
npx github:Ruihang2017/agent-templates adopt three-agent-architect-builder-reviewer .
|
|
45
|
+
|
|
46
|
+
docs: ADOPTING.md in the catalog root`
|
|
47
|
+
if (!cmd) {
|
|
48
|
+
console.log(usage)
|
|
49
|
+
process.exit(0)
|
|
50
|
+
}
|
|
51
|
+
console.error(`unknown command: ${cmd}\n\n${usage}`)
|
|
52
|
+
process.exit(1)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Pattern: <Human-Readable Pattern Name>
|
|
2
|
+
|
|
3
|
+
<!-- Copy this file to patterns/<kebab-name>/README.md and fill EVERY section.
|
|
4
|
+
Format reference: patterns/three-agent-architect-builder-reviewer/README.md
|
|
5
|
+
Rules: CLAUDE.md "Grounding rules" — every model/effort claim carries a source label;
|
|
6
|
+
no training-data impressions; as-of date moves with every recommendation change. -->
|
|
7
|
+
|
|
8
|
+
| Field | Value |
|
|
9
|
+
|---|---|
|
|
10
|
+
| **Pattern name** | `<kebab-name>` (= directory name) |
|
|
11
|
+
| **Status** | `proposed` <!-- proposed → trialed → adopted → deprecated --> |
|
|
12
|
+
| **As-of date** | YYYY-MM-DD |
|
|
13
|
+
| **Expiry trigger** | First successor release to any listed model, or YYYY-MM-DD (+6 months), whichever comes first |
|
|
14
|
+
| **Sign-off** | <name, role, date> |
|
|
15
|
+
|
|
16
|
+
<One- or two-sentence summary of the agent topology: who does what, in what order.>
|
|
17
|
+
|
|
18
|
+
## 1. When to use / when not to use
|
|
19
|
+
|
|
20
|
+
**Use when:**
|
|
21
|
+
- <concrete task shape>
|
|
22
|
+
|
|
23
|
+
**Do not use when:**
|
|
24
|
+
- <concrete task shape — every pattern has a floor below which its overhead dominates>
|
|
25
|
+
|
|
26
|
+
## 2. Agent roles & boundaries
|
|
27
|
+
|
|
28
|
+
| Agent | Does | Never does |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| **<Role>** | <responsibility> | <hard boundary> |
|
|
31
|
+
|
|
32
|
+
<Who judges whom; which contexts must stay isolated; which boundaries are hard requirements vs tunable.
|
|
33
|
+
State which agent owns unit / integration / E2E tests — agents own all three levels (repo testing policy);
|
|
34
|
+
the human only smoke-tests at PRD completion.>
|
|
35
|
+
|
|
36
|
+
## 3. Model + effort assignment (as of YYYY-MM-DD)
|
|
37
|
+
|
|
38
|
+
| Role | Model | Effort | Reasoning | Source labels |
|
|
39
|
+
|---|---|---|---|---|
|
|
40
|
+
| <Role> | <exact model name> | <effort level> | <why this model/effort for this role> | <`[official]` / `[vendor-benchmark]` / `[third-party]` / `[internal]` / `[unverified]` / `[team-policy]` + link or "link not captured — attach at first re-verification"> |
|
|
41
|
+
|
|
42
|
+
## 4. Known failure modes / pitfalls
|
|
43
|
+
|
|
44
|
+
| Pitfall | Context | Mitigation | Recorded |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| <symptom> | <the specific harness/project/conditions it was observed in — or "design constraint (not a measured incident)"> | <mitigation> | YYYY-MM-DD |
|
|
47
|
+
| Harness-specific failures for these exact model+effort combinations | **None recorded yet** (as of YYYY-MM-DD) | Record here with harness name, conditions, and date when observed | — |
|
|
48
|
+
|
|
49
|
+
## 5. Upstream / downstream integration
|
|
50
|
+
|
|
51
|
+
**Upstream (work intake):** <how work enters — master PRD → sub-PRD → ticket; which docs each agent reads; where ADRs come in.>
|
|
52
|
+
|
|
53
|
+
**Downstream (deliverables):** <what leaves — PR, verdict, docs; what gates a merge.>
|
|
54
|
+
|
|
55
|
+
**Human gates:** <where humans decide (e.g. the start signal), where they must NOT be needed, and the exception path that pulls a human back in.>
|
|
56
|
+
|
|
57
|
+
## 6. Scaffold
|
|
58
|
+
|
|
59
|
+
<List of files under scaffold/ and what each is for. Point to scaffold/INSTALL.md for install steps. Note the date the scaffold's config keys were last verified against Claude Code docs.>
|
|
60
|
+
|
|
61
|
+
## 7. Provenance & change log
|
|
62
|
+
|
|
63
|
+
| Date | Change | Basis | Author |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| YYYY-MM-DD | Initial entry | <source record / doc links> | <who> |
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<!-- Universal ticket template — all patterns, plus the catalog repo itself.
|
|
2
|
+
Format distilled 2026-07-17 from the team's field-proven tickets: fx-eye-tracking
|
|
3
|
+
discipline, realtime-pilot PIL-15, MeritAI FND-9.
|
|
4
|
+
Copy to docs/prd/<NN-module>/tickets/<ID>-<slug>.md and fill every section.
|
|
5
|
+
Cold-start rule: a ticket is DEFECTIVE if executing it requires the planning
|
|
6
|
+
conversation. Inline the needed facts AND link their authoritative source.
|
|
7
|
+
The body below the frontmatter becomes the tracker issue body verbatim
|
|
8
|
+
(.claude/scripts/publish-tickets.mjs); the file stays the content source of truth. -->
|
|
9
|
+
---
|
|
10
|
+
id: MOD-NN # unique + stable; becomes the issue-title prefix "[MOD-NN]" (the dedupe key)
|
|
11
|
+
title: Short imperative title
|
|
12
|
+
module: NN-module # = parent directory name under docs/prd/
|
|
13
|
+
lane: NN-module # parallel lane; lanes may run concurrently ONLY with disjoint file-scopes
|
|
14
|
+
size: S # S | M | L
|
|
15
|
+
agent: builder # primary executing stage; justify in the "Why" line below
|
|
16
|
+
status: draft # draft -> ready -> done
|
|
17
|
+
date: YYYY-MM-DD
|
|
18
|
+
blocked_by: [] # ticket ids this one cannot start before (machine-readable dependency DAG)
|
|
19
|
+
blocks: [] # ticket ids waiting on this one
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# MOD-NN — Short imperative title
|
|
23
|
+
|
|
24
|
+
Implements <PRD §X FR-Y> per <ADR-NNNN (status, owner, date, via PR #N)> — or: "No ADR —
|
|
25
|
+
the decision is already made in <ref>; this is build ticket <n of m> against it."
|
|
26
|
+
Parent sub-PRD: [NN-module README](../README.md). Master spec: [PRD](../../../PRD.md).
|
|
27
|
+
Depends on: [MOD-NM — other ticket](MOD-NM-other-ticket.md) <!-- mirrors blocked_by; delete if none -->
|
|
28
|
+
**Why `builder`:** <one line — the basis for the agent assignment, e.g. "a narrowly-scoped
|
|
29
|
+
addition to an existing module, not a new subsystem">.
|
|
30
|
+
|
|
31
|
+
## Background + basis
|
|
32
|
+
|
|
33
|
+
<!-- Why this ticket exists. CITE every claim: PRD §, ADR section, stable decision ID, or a
|
|
34
|
+
merged PR — a conclusion may not appear from nowhere. QUOTE the load-bearing sentences
|
|
35
|
+
of the ADR/spec so the Builder does not re-derive intent.
|
|
36
|
+
Carry known caveats forward EXPLICITLY ("accepted for the pilot: X — documented, not
|
|
37
|
+
enforced, per PRD §Y") instead of re-litigating or silently dropping them. -->
|
|
38
|
+
|
|
39
|
+
## Goal
|
|
40
|
+
|
|
41
|
+
<!-- One paragraph: the artifact(s)/behavior to produce and where they land — stated so
|
|
42
|
+
completion is mechanically checkable. -->
|
|
43
|
+
|
|
44
|
+
## Non-goals
|
|
45
|
+
|
|
46
|
+
<!-- Bullet list. EACH exclusion names its owner or standing reason, so nobody guesses:
|
|
47
|
+
- No schema files — those are MOD-02.
|
|
48
|
+
- No init authentication — stays documented-not-enforced per PRD §9.4. Do not add it
|
|
49
|
+
as a side effect of this ticket. -->
|
|
50
|
+
|
|
51
|
+
## File-scope (write-owns)
|
|
52
|
+
|
|
53
|
+
<!-- Exact paths/globs this ticket may write, PLUS the explicit does-not-touch list.
|
|
54
|
+
State the serial-safety analysis: which tickets last touched these files, whether that
|
|
55
|
+
work is merged, and that no in-flight ticket contends for them. Must not overlap any
|
|
56
|
+
other in-flight ticket — disjoint file-scopes are what make parallel lanes safe.
|
|
57
|
+
Internal organization inside the scope is the Builder's choice. -->
|
|
58
|
+
|
|
59
|
+
- <paths this ticket owns>
|
|
60
|
+
- Does not touch: <paths owned elsewhere — name the owning ticket/module>
|
|
61
|
+
|
|
62
|
+
## Deliverables
|
|
63
|
+
|
|
64
|
+
<!-- Numbered, code-level precision: exact functions/exports, call sites, ordering
|
|
65
|
+
constraints ("directly after X and before Y"), naming conventions, and the behavioral
|
|
66
|
+
guarantee ("either fully visible or fully absent"). Fix the boundary AND the
|
|
67
|
+
load-bearing mechanics; leave internals free. -->
|
|
68
|
+
|
|
69
|
+
1. <deliverable>
|
|
70
|
+
|
|
71
|
+
## Acceptance checklist (classified)
|
|
72
|
+
|
|
73
|
+
<!-- Every criterion is a checkbox with exactly one class tag. The tag VOCABULARY is
|
|
74
|
+
project-defined in the target repo's CLAUDE.md — defaults: [machine] runnable
|
|
75
|
+
code/logic check · [fixture] replay of recorded data · [human] irreducibly human
|
|
76
|
+
judgment. Field vocabularies in use: [offline]/[live-model] (realtime pilot),
|
|
77
|
+
[machine]/[fixture]/[hardware-human] (fx-eye-tracking).
|
|
78
|
+
Rules: cover the pyramid where applicable — unit / integration / E2E; agents own all
|
|
79
|
+
three levels, the human only smoke-tests at PRD completion. Include the standing
|
|
80
|
+
suite-green item. If the ticket must conclude an open question, make the WRITEBACK
|
|
81
|
+
itself an acceptance item. Mark optional orchestrator-owned live checks "not required
|
|
82
|
+
to merge". Declare absent classes explicitly ("No [human] criteria — pure logic"). -->
|
|
83
|
+
|
|
84
|
+
- [ ] `[machine]` <criterion> (<cross-ref to AC/decision id>)
|
|
85
|
+
- [ ] `[machine]` <project test-suite command> green
|
|
86
|
+
|
|
87
|
+
## Test plan
|
|
88
|
+
|
|
89
|
+
<!-- The exact steps the Reviewer runs. NAME the harness/mocks/fixtures and the existing
|
|
90
|
+
test file whose construction pattern to copy. Say what is asserted, on what. Every
|
|
91
|
+
[machine]/[fixture] row must be reproducible offline. -->
|
|
92
|
+
|
|
93
|
+
## Feedback obligation
|
|
94
|
+
|
|
95
|
+
<!-- The writeback protocol, made concrete — three layers:
|
|
96
|
+
1. General rule: if implementation falsifies this spec, update this ticket / the
|
|
97
|
+
sub-PRD / the ADR first (version +0.1, changelog line), then change code. Silent
|
|
98
|
+
divergence = incomplete.
|
|
99
|
+
2. ENUMERATE the foreseeable frictions, each with its exact writeback target and path:
|
|
100
|
+
"if X cannot be expressed as Y → update docs/design-Z.md and ADR-NNNN's
|
|
101
|
+
consequences section FIRST, before touching src/W — a bigger surface than this
|
|
102
|
+
ticket's goal must not change silently."
|
|
103
|
+
3. If a decided protocol is outright falsified: that overturns a team decision —
|
|
104
|
+
escalate for re-review; never swap the approach silently inside the ticket. -->
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report a defect. Nightly triage reads this — the more mechanical the reproduction, the likelier an overnight fix.
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Symptom
|
|
10
|
+
|
|
11
|
+
<!-- What happens. Paste the exact error output / wrong value. -->
|
|
12
|
+
|
|
13
|
+
## Reproduction
|
|
14
|
+
|
|
15
|
+
<!-- Exact steps or commands; the smallest input that triggers it. -->
|
|
16
|
+
|
|
17
|
+
## Expected
|
|
18
|
+
|
|
19
|
+
<!-- What should happen instead, stated checkably. Cite the spec (PRD §/ADR) if you know it. -->
|
|
20
|
+
|
|
21
|
+
## Affected area (best guess)
|
|
22
|
+
|
|
23
|
+
<!-- Files/modules if you know them; leave empty if unsure — triage will trace it. -->
|
|
24
|
+
|
|
25
|
+
## Acceptance
|
|
26
|
+
|
|
27
|
+
<!-- What proves it fixed. Ideally a runnable check, e.g. "npm test stays green and f(x) returns y".
|
|
28
|
+
The pipeline turns this into the ticket's classified acceptance checklist. -->
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Decision record
|
|
3
|
+
about: Records what was done and why — the durable memory that commits cannot carry. Used by agents and humans alike.
|
|
4
|
+
title: 'Decision record: '
|
|
5
|
+
labels: decision-record
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**What** (merged in <commit/PR/MR>, YYYY-MM-DD): <one paragraph — the change as shipped.>
|
|
10
|
+
|
|
11
|
+
**Key decisions & why**
|
|
12
|
+
|
|
13
|
+
<!-- One bullet per decision: the decision, its reason, and the rejected alternative when
|
|
14
|
+
one was seriously considered. Cite sources — official docs, ADRs, maintainer direction
|
|
15
|
+
with date — the same grounding discipline as everything else. -->
|
|
16
|
+
|
|
17
|
+
-
|
|
18
|
+
|
|
19
|
+
**Evidence**
|
|
20
|
+
|
|
21
|
+
<!-- Test results, verification records, links to the docs where each decision landed. -->
|
|
22
|
+
|
|
23
|
+
**Links**
|
|
24
|
+
|
|
25
|
+
<!-- Related issues / PRs / ADRs / tickets. -->
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Task
|
|
3
|
+
about: Request a bounded piece of work. Mirrors the pipeline's ticket format so triage can convert it mechanically.
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Traceability
|
|
10
|
+
|
|
11
|
+
<!-- What this implements or follows from: PRD §/FR, an ADR, a discussion, an upstream
|
|
12
|
+
pattern — with links. If the decision is already made somewhere, say where. -->
|
|
13
|
+
|
|
14
|
+
## Background + basis
|
|
15
|
+
|
|
16
|
+
<!-- Why this is needed. Cite claims; quote the load-bearing sentences rather than
|
|
17
|
+
paraphrasing from memory. -->
|
|
18
|
+
|
|
19
|
+
## Goal
|
|
20
|
+
|
|
21
|
+
<!-- One paragraph: the artifact(s) to produce and where they land — checkable. -->
|
|
22
|
+
|
|
23
|
+
## Non-goals
|
|
24
|
+
|
|
25
|
+
<!-- Each exclusion names its owner or standing reason: "No X — that is MOD-02" /
|
|
26
|
+
"No Y — stays out of scope per PRD §Z; do not add it as a side effect." -->
|
|
27
|
+
|
|
28
|
+
## Affected area (best guess)
|
|
29
|
+
|
|
30
|
+
<!-- Files/modules if known; the Architect finalizes the file-scope and the
|
|
31
|
+
does-not-touch list. -->
|
|
32
|
+
|
|
33
|
+
## Acceptance
|
|
34
|
+
|
|
35
|
+
<!-- Checkable criteria, one per line, tagged with the repo's class vocabulary if you can
|
|
36
|
+
(defaults: [machine]/[fixture]/[human]). Prefer runnable checks ("command X exits 0"). -->
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do? One sentence. -->
|
|
4
|
+
|
|
5
|
+
## Related issue / ticket
|
|
6
|
+
|
|
7
|
+
<!-- Closes #N — plus the ticket id, e.g. [MOD-NN]. The ticket FILE stays the content
|
|
8
|
+
source of truth; the issue holds state. -->
|
|
9
|
+
|
|
10
|
+
## Type
|
|
11
|
+
|
|
12
|
+
<!-- Check one; matches conventional-commit prefixes. -->
|
|
13
|
+
|
|
14
|
+
- [ ] `feat` — new feature
|
|
15
|
+
- [ ] `fix` — bug fix
|
|
16
|
+
- [ ] `refactor` — restructuring, no behavior change
|
|
17
|
+
- [ ] `docs` — documentation / ADR only
|
|
18
|
+
- [ ] `test` — new or updated tests
|
|
19
|
+
- [ ] `ci` / `chore` — tooling, maintenance
|
|
20
|
+
|
|
21
|
+
## Changes
|
|
22
|
+
|
|
23
|
+
<!-- Bullets: what changed AND why. Include what was tried and rejected if it shaped the result. -->
|
|
24
|
+
|
|
25
|
+
-
|
|
26
|
+
|
|
27
|
+
## Design note
|
|
28
|
+
|
|
29
|
+
<!-- Hard-to-reverse or non-obvious changes: link the ADR (docs/adr/NNNN-*.md) — add one if
|
|
30
|
+
this is a durable decision. Otherwise summarize inline: problem · affected components ·
|
|
31
|
+
contract/schema changes · risks. -->
|
|
32
|
+
|
|
33
|
+
## Pipeline evidence
|
|
34
|
+
|
|
35
|
+
<!-- Assumes the installed pattern; the three-agent pattern's items are shown — adapt if
|
|
36
|
+
this repo runs a different pattern. -->
|
|
37
|
+
|
|
38
|
+
- [ ] Plan: `docs/plans/<ticket-id>.md` (link)
|
|
39
|
+
- [ ] Builder: REAL test output attached (unit / integration / E2E as the ticket requires) — never "should pass"
|
|
40
|
+
- [ ] Reviewer verdict: **CLEAR**, from a fresh context (link or paste the note; bounces: <n>)
|
|
41
|
+
- [ ] Deviations from the plan recorded (or "none")
|
|
42
|
+
- [ ] Post-merge: `/verify-delivery <ticket-id>` runs — the issue closes only after it passes
|
|
43
|
+
|
|
44
|
+
## Constraint check
|
|
45
|
+
|
|
46
|
+
<!-- At install time, copy this repo's non-negotiables from its CLAUDE.md here as
|
|
47
|
+
checkboxes. Tick what this PR touches; mark the rest N/A. Two universal items: -->
|
|
48
|
+
|
|
49
|
+
- [ ] No hardcoded secrets (keys, tokens, credentials) in code / config / logs / docs
|
|
50
|
+
- [ ] Docs / ADR / ticket updated if behavior or a decision changed (feedback obligation)
|
|
51
|
+
|
|
52
|
+
## Evidence
|
|
53
|
+
|
|
54
|
+
<!-- Test output, before/after screenshots (UI), command + output (CLI/API), or a short repro. -->
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!-- GitLab description template ("bug-report"). Nightly triage reads this —
|
|
2
|
+
the more mechanical the reproduction, the likelier an overnight fix. -->
|
|
3
|
+
|
|
4
|
+
## Symptom
|
|
5
|
+
|
|
6
|
+
<!-- What happens. Paste the exact error output / wrong value. -->
|
|
7
|
+
|
|
8
|
+
## Reproduction
|
|
9
|
+
|
|
10
|
+
<!-- Exact steps or commands; the smallest input that triggers it. -->
|
|
11
|
+
|
|
12
|
+
## Expected
|
|
13
|
+
|
|
14
|
+
<!-- What should happen instead, stated checkably. Cite the spec (PRD §/ADR) if you know it. -->
|
|
15
|
+
|
|
16
|
+
## Affected area (best guess)
|
|
17
|
+
|
|
18
|
+
<!-- Files/modules if you know them; leave empty if unsure — triage will trace it. -->
|
|
19
|
+
|
|
20
|
+
## Acceptance
|
|
21
|
+
|
|
22
|
+
<!-- What proves it fixed. Ideally a runnable check, e.g. "npm test stays green and f(x) returns y".
|
|
23
|
+
The pipeline turns this into the ticket's classified acceptance checklist. -->
|