ralph-prd 1.0.4 → 1.0.6
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/README.md +16 -2
- package/bin/install.mjs +42 -29
- package/package.json +1 -2
- package/ralph/lib/config.mjs +9 -8
- package/ralph/lib/ship-checker.mjs +319 -0
- package/ralph/lib/verifier.mjs +1 -1
- package/ralph/ralph-claude.mjs +70 -2
- package/ralph/ralph.config.sample.yaml +10 -5
- package/ralph/test/ship-checker.test.mjs +268 -0
- package/skills/grill-me/SKILL.md +0 -10
- package/skills/grill-me/agents/openai.yaml +0 -4
- package/skills/prd-to-plan/SKILL.md +0 -107
- package/skills/prd-to-plan/agents/openai.yaml +0 -4
- package/skills/repo-doc-maintainer/SKILL.md +0 -101
- package/skills/repo-doc-maintainer/agents/openai.yaml +0 -4
- package/skills/repo-doc-maintainer/references/doc-update-criteria.md +0 -32
- package/skills/review-changes/SKILL.md +0 -90
- package/skills/review-changes/agents/openai.yaml +0 -4
- package/skills/review-changes/references/review-checklist.md +0 -37
- package/skills/ship-check/SKILL.md +0 -80
- package/skills/ship-check/agents/openai.yaml +0 -4
- package/skills/ship-check/references/validation-flow.md +0 -26
- package/skills/write-a-prd/SKILL.md +0 -74
- package/skills/write-a-prd/agents/openai.yaml +0 -4
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { test, describe } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
5
|
+
import { runShipCheck, ShipCheckError } from '../lib/ship-checker.mjs';
|
|
6
|
+
import { LogWriter } from '../lib/log-writer.mjs';
|
|
7
|
+
import { makeTempDir, makeFakeSend } from './helpers.mjs';
|
|
8
|
+
|
|
9
|
+
const PHASE = {
|
|
10
|
+
index: 0,
|
|
11
|
+
title: 'Phase 1: CLI Shell',
|
|
12
|
+
body: '### What to build\nBuild CLI.\n\n### Acceptance criteria\n\n- [ ] Dry-run works',
|
|
13
|
+
acceptanceCriteria: ['Dry-run works'],
|
|
14
|
+
hasVerification: true,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const REPO_STATE = '`git status --short`:\n(no changes)';
|
|
18
|
+
|
|
19
|
+
const SKILL_BODY = 'Review the phase implementation and emit VERDICT: APPROVED or VERDICT: REMARKS.';
|
|
20
|
+
|
|
21
|
+
/** Write a minimal SKILL.md (with frontmatter) to a temp base dir and return the base dir. */
|
|
22
|
+
function makeSkillDir(body = SKILL_BODY) {
|
|
23
|
+
const base = makeTempDir();
|
|
24
|
+
const skillDir = join(base, '.claude', 'skills', 'ship-check');
|
|
25
|
+
mkdirSync(skillDir, { recursive: true });
|
|
26
|
+
writeFileSync(
|
|
27
|
+
join(skillDir, 'SKILL.md'),
|
|
28
|
+
`---\nname: ship-check\n---\n\n${body}`,
|
|
29
|
+
'utf8'
|
|
30
|
+
);
|
|
31
|
+
return base;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function makeSetup() {
|
|
35
|
+
const logsDir = makeTempDir();
|
|
36
|
+
const lw = new LogWriter(logsDir, 'dump');
|
|
37
|
+
const skillsBase = makeSkillDir();
|
|
38
|
+
return { logsDir, lw, skillsBase };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('runShipCheck', () => {
|
|
42
|
+
|
|
43
|
+
test('APPROVED on first check → returns nextTaskNum = startTaskNum + 1', async () => {
|
|
44
|
+
const { lw, skillsBase } = makeSetup();
|
|
45
|
+
const send = makeFakeSend(['All looks good.\n\nVERDICT: APPROVED']);
|
|
46
|
+
|
|
47
|
+
const { nextTaskNum } = await runShipCheck({
|
|
48
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
49
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 2, send,
|
|
50
|
+
_skillsBase: skillsBase,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
assert.equal(nextTaskNum, 3); // startTaskNum=2, one session => 3
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('REMARKS → repair → APPROVED: 3 sessions, nextTaskNum = startTaskNum + 3', async () => {
|
|
57
|
+
const { lw, skillsBase } = makeSetup();
|
|
58
|
+
const send = makeFakeSend([
|
|
59
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- Missing tests\nFINDINGS_END',
|
|
60
|
+
'Fixed the tests.',
|
|
61
|
+
'VERDICT: APPROVED',
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
const { nextTaskNum } = await runShipCheck({
|
|
65
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
66
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
67
|
+
_skillsBase: skillsBase,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
assert.equal(nextTaskNum, 4); // 1 + 3 sessions
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('REMARKS → repair → APPROVED: repair prompt includes findings', async () => {
|
|
74
|
+
const { lw, skillsBase } = makeSetup();
|
|
75
|
+
let repairPrompt = '';
|
|
76
|
+
let call = 0;
|
|
77
|
+
const send = async (prompt, { onChunk } = {}) => {
|
|
78
|
+
call++;
|
|
79
|
+
let resp;
|
|
80
|
+
if (call === 1) {
|
|
81
|
+
resp = 'VERDICT: REMARKS\nFINDINGS_START\n- Need more error handling\nFINDINGS_END';
|
|
82
|
+
} else if (call === 2) {
|
|
83
|
+
repairPrompt = prompt;
|
|
84
|
+
resp = 'Fixed.';
|
|
85
|
+
} else {
|
|
86
|
+
resp = 'VERDICT: APPROVED';
|
|
87
|
+
}
|
|
88
|
+
onChunk?.(resp);
|
|
89
|
+
return resp;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
await runShipCheck({
|
|
93
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
94
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
95
|
+
_skillsBase: skillsBase,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
assert.ok(repairPrompt.includes('Need more error handling'), 'repair prompt should contain findings');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('REMARKS → repair → REMARKS: throws ShipCheckError', async () => {
|
|
102
|
+
const { lw, skillsBase } = makeSetup();
|
|
103
|
+
const send = makeFakeSend([
|
|
104
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- Still broken\nFINDINGS_END',
|
|
105
|
+
'Tried to fix.',
|
|
106
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- Still broken after repair\nFINDINGS_END',
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
await assert.rejects(
|
|
110
|
+
() => runShipCheck({
|
|
111
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
112
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
113
|
+
_skillsBase: skillsBase,
|
|
114
|
+
}),
|
|
115
|
+
(err) => {
|
|
116
|
+
assert.ok(err instanceof ShipCheckError);
|
|
117
|
+
assert.equal(err.phaseName, 'Phase 1: CLI Shell');
|
|
118
|
+
assert.ok(err.findings.length > 0);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('REMARKS → repair → REMARKS: ShipCheckError is distinct from VerificationError', async () => {
|
|
125
|
+
const { lw, skillsBase } = makeSetup();
|
|
126
|
+
const send = makeFakeSend([
|
|
127
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- Bad\nFINDINGS_END',
|
|
128
|
+
'Fix attempt.',
|
|
129
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- Still bad\nFINDINGS_END',
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
await assert.rejects(
|
|
133
|
+
() => runShipCheck({
|
|
134
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
135
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
136
|
+
_skillsBase: skillsBase,
|
|
137
|
+
}),
|
|
138
|
+
(err) => {
|
|
139
|
+
assert.equal(err.name, 'ShipCheckError');
|
|
140
|
+
assert.ok(!(err.constructor.name === 'VerificationError'));
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('double-REMARKS: exactly 3 sessions total', async () => {
|
|
147
|
+
const { lw, skillsBase } = makeSetup();
|
|
148
|
+
let calls = 0;
|
|
149
|
+
const send = async (prompt, { onChunk } = {}) => {
|
|
150
|
+
calls++;
|
|
151
|
+
const resp = calls === 2
|
|
152
|
+
? 'Fixed.'
|
|
153
|
+
: 'VERDICT: REMARKS\nFINDINGS_START\n- Problem\nFINDINGS_END';
|
|
154
|
+
onChunk?.(resp);
|
|
155
|
+
return resp;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
await runShipCheck({
|
|
160
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
161
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
162
|
+
_skillsBase: skillsBase,
|
|
163
|
+
});
|
|
164
|
+
} catch { /* expected */ }
|
|
165
|
+
|
|
166
|
+
assert.equal(calls, 3, 'exactly 3 sessions: ship-check + repair + re-check');
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('all sessions write individual step logs', async () => {
|
|
170
|
+
const { logsDir, lw, skillsBase } = makeSetup();
|
|
171
|
+
const send = makeFakeSend([
|
|
172
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- X\nFINDINGS_END',
|
|
173
|
+
'Fixed.',
|
|
174
|
+
'VERDICT: APPROVED',
|
|
175
|
+
]);
|
|
176
|
+
|
|
177
|
+
await runShipCheck({
|
|
178
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
179
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
180
|
+
_skillsBase: skillsBase,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
assert.ok(existsSync(join(logsDir, 'phase-1-ship-check.log')));
|
|
184
|
+
assert.ok(existsSync(join(logsDir, 'phase-1-ship-check-repair.log')));
|
|
185
|
+
assert.ok(existsSync(join(logsDir, 'phase-1-ship-check-re.log')));
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test('logs preserved after double-REMARKS', async () => {
|
|
189
|
+
const { logsDir, lw, skillsBase } = makeSetup();
|
|
190
|
+
const send = makeFakeSend([
|
|
191
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- Bad\nFINDINGS_END',
|
|
192
|
+
'Tried to fix.',
|
|
193
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- Still bad\nFINDINGS_END',
|
|
194
|
+
]);
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
await runShipCheck({
|
|
198
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
199
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
200
|
+
_skillsBase: skillsBase,
|
|
201
|
+
});
|
|
202
|
+
} catch { /* expected */ }
|
|
203
|
+
|
|
204
|
+
assert.ok(existsSync(join(logsDir, 'phase-1-ship-check.log')));
|
|
205
|
+
assert.ok(existsSync(join(logsDir, 'phase-1-ship-check-repair.log')));
|
|
206
|
+
assert.ok(existsSync(join(logsDir, 'phase-1-ship-check-re.log')));
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test('SKILL.md frontmatter is stripped before sending as prompt', async () => {
|
|
210
|
+
const logsDir = makeTempDir();
|
|
211
|
+
const lw = new LogWriter(logsDir, 'dump');
|
|
212
|
+
const skillsBase = makeSkillDir('Actual skill instructions here.');
|
|
213
|
+
let capturedPrompt = '';
|
|
214
|
+
const send = async (prompt, { onChunk } = {}) => {
|
|
215
|
+
capturedPrompt = prompt;
|
|
216
|
+
const resp = 'VERDICT: APPROVED';
|
|
217
|
+
onChunk?.(resp);
|
|
218
|
+
return resp;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
await runShipCheck({
|
|
222
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
223
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
224
|
+
_skillsBase: skillsBase,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
assert.ok(capturedPrompt.includes('Actual skill instructions here.'));
|
|
228
|
+
assert.ok(!capturedPrompt.includes('name: ship-check'), 'frontmatter should be stripped');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test('missing SKILL.md throws a clear configuration error', async () => {
|
|
232
|
+
const { lw } = makeSetup();
|
|
233
|
+
const emptyBase = makeTempDir(); // no SKILL.md here
|
|
234
|
+
const send = makeFakeSend(['VERDICT: APPROVED']);
|
|
235
|
+
|
|
236
|
+
await assert.rejects(
|
|
237
|
+
() => runShipCheck({
|
|
238
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
239
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 1, send,
|
|
240
|
+
_skillsBase: emptyBase,
|
|
241
|
+
}),
|
|
242
|
+
(err) => {
|
|
243
|
+
assert.ok(err.message.includes('ship-check'), 'error should mention ship-check');
|
|
244
|
+
assert.ok(err.message.includes('SKILL.md'), 'error should mention SKILL.md');
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test('APPROVED on re-check: findings from first REMARKS are not propagated to error', async () => {
|
|
251
|
+
const { lw, skillsBase } = makeSetup();
|
|
252
|
+
const send = makeFakeSend([
|
|
253
|
+
'VERDICT: REMARKS\nFINDINGS_START\n- Minor issue\nFINDINGS_END',
|
|
254
|
+
'Fixed the minor issue.',
|
|
255
|
+
'VERDICT: APPROVED',
|
|
256
|
+
]);
|
|
257
|
+
|
|
258
|
+
// Should resolve without throwing
|
|
259
|
+
const result = await runShipCheck({
|
|
260
|
+
phase: PHASE, repoState: REPO_STATE,
|
|
261
|
+
logWriter: lw, phaseNum: 1, startTaskNum: 5, send,
|
|
262
|
+
_skillsBase: skillsBase,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
assert.equal(result.nextTaskNum, 8); // 5 + 3 sessions
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
});
|
package/skills/grill-me/SKILL.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: grill-me
|
|
3
|
-
description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
|
|
7
|
-
|
|
8
|
-
Ask the questions one at a time.
|
|
9
|
-
|
|
10
|
-
If a question can be answered by exploring the codebase, explore the codebase instead.
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: prd-to-plan
|
|
3
|
-
description: Turn a PRD into a multi-phase implementation plan using tracer-bullet vertical slices, saved as a local Markdown file in ./plans/. Use when user wants to break down a PRD, create an implementation plan, plan phases from a PRD, or mentions "tracer bullets".
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# PRD to Plan
|
|
7
|
-
|
|
8
|
-
Break a PRD into a phased implementation plan using vertical slices (tracer bullets). Output is a Markdown file in `./docs/<feature-name>/plan.md`.
|
|
9
|
-
|
|
10
|
-
## Process
|
|
11
|
-
|
|
12
|
-
### 1. Confirm the PRD is in context
|
|
13
|
-
|
|
14
|
-
The PRD should already be in the conversation. If it isn't, ask the user to paste it or point you to the file.
|
|
15
|
-
|
|
16
|
-
### 2. Explore the codebase
|
|
17
|
-
|
|
18
|
-
If you have not already explored the codebase, do so to understand the current architecture, existing patterns, and integration layers.
|
|
19
|
-
|
|
20
|
-
### 3. Identify durable architectural decisions
|
|
21
|
-
|
|
22
|
-
Before slicing, identify high-level decisions that are unlikely to change throughout implementation:
|
|
23
|
-
|
|
24
|
-
- Route structures / URL patterns
|
|
25
|
-
- Database schema shape
|
|
26
|
-
- Key data models
|
|
27
|
-
- Authentication / authorization approach
|
|
28
|
-
- Third-party service boundaries
|
|
29
|
-
|
|
30
|
-
These go in the plan header so every phase can reference them.
|
|
31
|
-
|
|
32
|
-
### 4. Draft vertical slices
|
|
33
|
-
|
|
34
|
-
Break the PRD into **tracer bullet** phases. Each phase is a thin vertical slice that cuts through ALL integration layers end-to-end, NOT a horizontal slice of one layer.
|
|
35
|
-
|
|
36
|
-
<vertical-slice-rules>
|
|
37
|
-
- Each slice delivers a narrow but COMPLETE path through every layer (schema, API, UI, tests)
|
|
38
|
-
- A completed slice is demoable or verifiable on its own
|
|
39
|
-
- Prefer many thin slices over few thick ones
|
|
40
|
-
- Do NOT include specific file names, function names, or implementation details that are likely to change as later phases are built
|
|
41
|
-
- DO include durable decisions: route paths, schema shapes, data model names
|
|
42
|
-
</vertical-slice-rules>
|
|
43
|
-
|
|
44
|
-
### 5. Quiz the user
|
|
45
|
-
|
|
46
|
-
Present the proposed breakdown as a numbered list. For each phase show:
|
|
47
|
-
|
|
48
|
-
- **Title**: short descriptive name
|
|
49
|
-
- **User stories covered**: which user stories from the PRD this addresses
|
|
50
|
-
|
|
51
|
-
Ask the user:
|
|
52
|
-
|
|
53
|
-
- Does the granularity feel right? (too coarse / too fine)
|
|
54
|
-
- Should any phases be merged or split further?
|
|
55
|
-
|
|
56
|
-
Iterate until the user approves the breakdown.
|
|
57
|
-
|
|
58
|
-
### 6. Write the plan file
|
|
59
|
-
|
|
60
|
-
Create `./docs/<feature-name>/` if it doesn't exist. Write the plan as a Markdown file named after the feature (e.g. `./docs/meta-direct-whatsapp/plan.md`). Use the template below.
|
|
61
|
-
|
|
62
|
-
<plan-template>
|
|
63
|
-
# Plan: <Feature Name>
|
|
64
|
-
|
|
65
|
-
> Source PRD: <brief identifier or link>
|
|
66
|
-
|
|
67
|
-
## Architectural decisions
|
|
68
|
-
|
|
69
|
-
Durable decisions that apply across all phases:
|
|
70
|
-
|
|
71
|
-
- **Routes**: ...
|
|
72
|
-
- **Schema**: ...
|
|
73
|
-
- **Key models**: ...
|
|
74
|
-
- (add/remove sections as appropriate)
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## Phase 1: <Title>
|
|
79
|
-
|
|
80
|
-
**User stories**: <list from PRD>
|
|
81
|
-
|
|
82
|
-
### What to build
|
|
83
|
-
|
|
84
|
-
A concise description of this vertical slice. Describe the end-to-end behavior, not layer-by-layer implementation.
|
|
85
|
-
|
|
86
|
-
### Acceptance criteria
|
|
87
|
-
|
|
88
|
-
- [ ] Criterion 1
|
|
89
|
-
- [ ] Criterion 2
|
|
90
|
-
- [ ] Criterion 3
|
|
91
|
-
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
## Phase 2: <Title>
|
|
95
|
-
|
|
96
|
-
**User stories**: <list from PRD>
|
|
97
|
-
|
|
98
|
-
### What to build
|
|
99
|
-
|
|
100
|
-
...
|
|
101
|
-
|
|
102
|
-
### Acceptance criteria
|
|
103
|
-
|
|
104
|
-
- [ ] ...
|
|
105
|
-
|
|
106
|
-
<!-- Repeat for each phase -->
|
|
107
|
-
</plan-template>
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: repo-doc-maintainer
|
|
3
|
-
description: Review recent repository changes and decide whether AGENTS.md or other project-level documentation needs a high-level update. Use when finishing a feature, fix, refactor, or architectural change and you need to preserve repo-shaping guidance such as new patterns, constraints, workflows, validation rules, or onboarding-relevant gotchas without adding low-level implementation detail.
|
|
4
|
-
disable-model-invocation: true
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Repo Doc Maintainer
|
|
8
|
-
|
|
9
|
-
## Overview
|
|
10
|
-
|
|
11
|
-
Review the latest local changes, classify whether they introduced stable repo-shaping knowledge, and update project-level documentation (AGENTS.md, CLAUDE.md, or equivalent) only when that knowledge would help the next contributor work safely.
|
|
12
|
-
|
|
13
|
-
Keep docs compact and high signal. Do not turn any file into a changelog, feature walkthrough, or implementation dump.
|
|
14
|
-
|
|
15
|
-
## Workflow
|
|
16
|
-
|
|
17
|
-
1. Inspect the latest change set.
|
|
18
|
-
2. Compare the change against the current guidance in the project's documentation files.
|
|
19
|
-
3. Decide whether the change introduced new high-level knowledge that future contributors need.
|
|
20
|
-
4. Update only the appropriate document and only at the correct level of abstraction.
|
|
21
|
-
5. Summarize what changed or explicitly say no doc update is needed.
|
|
22
|
-
|
|
23
|
-
## Inspect The Change Set
|
|
24
|
-
|
|
25
|
-
Check the local diff first. Prefer the smallest scope that answers the question:
|
|
26
|
-
|
|
27
|
-
- `git status --short`
|
|
28
|
-
- `git diff --stat`
|
|
29
|
-
- `git diff -- <path>`
|
|
30
|
-
- `git log -1 --stat`
|
|
31
|
-
|
|
32
|
-
If the user asks about merged or already committed work, inspect the relevant commit or commit range instead.
|
|
33
|
-
|
|
34
|
-
Read the affected code before editing docs. Do not infer a new rule from filenames alone.
|
|
35
|
-
|
|
36
|
-
## Decide Whether Docs Should Change
|
|
37
|
-
|
|
38
|
-
Update docs only for durable, reusable guidance such as:
|
|
39
|
-
|
|
40
|
-
- a new architectural pattern or layering rule
|
|
41
|
-
- a new dependency or repo-wide technology choice
|
|
42
|
-
- a new required validation or workflow step
|
|
43
|
-
- a new DI, routing, state, API, persistence, or testing convention
|
|
44
|
-
- a new gotcha that is subtle, repeatable, and likely to cause regressions
|
|
45
|
-
- a new location of truth for important behavior
|
|
46
|
-
|
|
47
|
-
Do not update docs for:
|
|
48
|
-
|
|
49
|
-
- one-off feature details
|
|
50
|
-
- temporary workarounds unless they are active repo constraints
|
|
51
|
-
- file-by-file summaries
|
|
52
|
-
- naming trivia
|
|
53
|
-
- low-level implementation mechanics that are obvious from code
|
|
54
|
-
- changes that are already captured adequately in existing docs
|
|
55
|
-
|
|
56
|
-
Use this test: if the next competent contributor would likely make a mistake without knowing this, and the guidance remains useful beyond one feature, document it.
|
|
57
|
-
|
|
58
|
-
## Choose The Right File
|
|
59
|
-
|
|
60
|
-
Update `AGENTS.md` (or `CLAUDE.md`) when the guidance should be visible in the fastest possible repo brief:
|
|
61
|
-
|
|
62
|
-
- stable architectural constraints
|
|
63
|
-
- repo-wide rules
|
|
64
|
-
- mandatory validation commands
|
|
65
|
-
- short "what matters" reminders
|
|
66
|
-
|
|
67
|
-
Keep additions terse. Prefer a single bullet or short sentence.
|
|
68
|
-
|
|
69
|
-
Update onboarding or developer docs when the guidance needs more explanation:
|
|
70
|
-
|
|
71
|
-
- decision rules
|
|
72
|
-
- examples
|
|
73
|
-
- gotchas
|
|
74
|
-
- workflow detail
|
|
75
|
-
- rationale that helps a new contributor apply the rule correctly
|
|
76
|
-
|
|
77
|
-
If a rule belongs in both files, put the shortest possible reminder in AGENTS.md and the fuller explanation in the onboarding doc.
|
|
78
|
-
|
|
79
|
-
## Editing Rules
|
|
80
|
-
|
|
81
|
-
- Keep docs high level and DRY.
|
|
82
|
-
- Preserve existing tone and structure.
|
|
83
|
-
- Integrate new guidance into the most relevant existing section instead of appending random notes.
|
|
84
|
-
- Prefer editing or tightening an existing bullet before adding a new one when the concept already exists.
|
|
85
|
-
- Avoid repeating the same rule in multiple sections of the same file.
|
|
86
|
-
- Do not document speculative patterns. The rule should already exist in code or workflow.
|
|
87
|
-
|
|
88
|
-
## Output Expectations
|
|
89
|
-
|
|
90
|
-
After review, report one of these outcomes:
|
|
91
|
-
|
|
92
|
-
- no doc update needed, with a brief reason
|
|
93
|
-
- updated AGENTS.md / CLAUDE.md
|
|
94
|
-
- updated onboarding docs
|
|
95
|
-
- updated both
|
|
96
|
-
|
|
97
|
-
When you update docs, describe the repo-shaping guidance you added, not a file-by-file diff dump.
|
|
98
|
-
|
|
99
|
-
## Reference
|
|
100
|
-
|
|
101
|
-
Read [references/doc-update-criteria.md](references/doc-update-criteria.md) when you need a tighter rubric for deciding whether a change is repo-shaping enough to document.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Doc Update Criteria
|
|
2
|
-
|
|
3
|
-
Use this rubric when deciding whether a recent change deserves documentation in project-level docs.
|
|
4
|
-
|
|
5
|
-
## Good Candidates
|
|
6
|
-
|
|
7
|
-
- New repo-wide API or data-access pattern
|
|
8
|
-
- New state-management rule that affects multiple features
|
|
9
|
-
- New dependency-injection registration requirement
|
|
10
|
-
- New routing or bootstrap constraint
|
|
11
|
-
- New persistence, localization, or testing convention
|
|
12
|
-
- New validation command, CI expectation, or test convention
|
|
13
|
-
- New subtle regression trap discovered through real work
|
|
14
|
-
|
|
15
|
-
## Weak Candidates
|
|
16
|
-
|
|
17
|
-
- Single-screen implementation detail
|
|
18
|
-
- Private helper extraction
|
|
19
|
-
- Renaming or code movement with no behavior change
|
|
20
|
-
- Temporary experiment
|
|
21
|
-
- Feature-specific copy or asset changes
|
|
22
|
-
- Test-only detail that does not represent a broader repo convention
|
|
23
|
-
|
|
24
|
-
## Questions To Ask
|
|
25
|
-
|
|
26
|
-
1. Would this still matter in a month?
|
|
27
|
-
2. Does this affect more than one file, feature, or future task?
|
|
28
|
-
3. Would a contributor who skips this guidance likely make a real mistake?
|
|
29
|
-
4. Is the rule already captured clearly in one of the docs?
|
|
30
|
-
5. Can this be stated at a high level without teaching the implementation?
|
|
31
|
-
|
|
32
|
-
If the answer to the first three is mostly yes, document it. If the last two are no, document it carefully and concisely.
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: review-changes
|
|
3
|
-
description: Review the latest changes and check whether they comply with the project's documented guidelines (AGENTS.md, CLAUDE.md, or equivalent). Use when reviewing local diffs, recent commits, or feature work and you need a findings-first assessment of architecture, reuse, testing, and repo-specific rules.
|
|
4
|
-
disable-model-invocation: true
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Review Changes
|
|
8
|
-
|
|
9
|
-
## Overview
|
|
10
|
-
|
|
11
|
-
Review recent code changes against the repo's documented guidelines.
|
|
12
|
-
|
|
13
|
-
Default to review mode: identify concrete violations, risks, regressions, and missing tests first. Only give a brief clean bill of health when no meaningful findings exist.
|
|
14
|
-
|
|
15
|
-
## Workflow
|
|
16
|
-
|
|
17
|
-
1. Inspect the latest change set.
|
|
18
|
-
2. Read the relevant parts of the project's guidelines (AGENTS.md, CLAUDE.md, or any onboarding doc referenced there).
|
|
19
|
-
3. Read the changed code directly.
|
|
20
|
-
4. Compare the implementation against repo rules, not generic style opinions.
|
|
21
|
-
5. Report findings first, ordered by severity, with file references.
|
|
22
|
-
6. If no findings exist, say that explicitly and note any residual risk or verification gap.
|
|
23
|
-
|
|
24
|
-
## Inspect The Change Set
|
|
25
|
-
|
|
26
|
-
Prefer the smallest source of truth that answers the review request:
|
|
27
|
-
|
|
28
|
-
- `git status --short`
|
|
29
|
-
- `git diff --stat`
|
|
30
|
-
- `git diff -- <path>`
|
|
31
|
-
- `git log -1 --stat`
|
|
32
|
-
- `git show <commit>`
|
|
33
|
-
|
|
34
|
-
If the user asks about committed work, review the relevant commit or commit range instead of the working tree.
|
|
35
|
-
|
|
36
|
-
Do not review from summaries alone. Read the affected files.
|
|
37
|
-
|
|
38
|
-
## Review Focus
|
|
39
|
-
|
|
40
|
-
Use the project's documented guidelines as the review standard. Focus especially on:
|
|
41
|
-
|
|
42
|
-
- correct file and feature placement per the project's directory conventions
|
|
43
|
-
- DRY and reuse of logic, components, and flows
|
|
44
|
-
- state management following the project's chosen patterns
|
|
45
|
-
- dependency injection and service resolution following project conventions
|
|
46
|
-
- repository and data access contracts matching established patterns
|
|
47
|
-
- tests added or updated when behavior changes
|
|
48
|
-
- files growing beyond roughly 800 lines without being split
|
|
49
|
-
|
|
50
|
-
Do not invent standards beyond what the repo documents unless a change is obviously broken on its own terms.
|
|
51
|
-
|
|
52
|
-
## Repo-Specific Checks
|
|
53
|
-
|
|
54
|
-
Treat these as high-value checks:
|
|
55
|
-
|
|
56
|
-
- duplicated components or near-identical UI that should be shared or parameterized
|
|
57
|
-
- new services or repositories instantiated ad hoc inside views/components
|
|
58
|
-
- raw exceptions escaping into state management or UI layers
|
|
59
|
-
- hardcoded user-facing text that should be localized (if the project uses i18n)
|
|
60
|
-
- behavior changes without matching test updates
|
|
61
|
-
- large files that should be split into focused files
|
|
62
|
-
|
|
63
|
-
Read [references/review-checklist.md](references/review-checklist.md) for the compact checklist when you need to scan quickly.
|
|
64
|
-
|
|
65
|
-
## Output Format
|
|
66
|
-
|
|
67
|
-
Findings are the primary output.
|
|
68
|
-
|
|
69
|
-
For each finding:
|
|
70
|
-
|
|
71
|
-
- state the severity
|
|
72
|
-
- state the problem
|
|
73
|
-
- explain why it violates the project's guidelines or creates a concrete risk
|
|
74
|
-
- include a file reference
|
|
75
|
-
- suggest the fix direction briefly
|
|
76
|
-
|
|
77
|
-
After findings, optionally include:
|
|
78
|
-
|
|
79
|
-
- open questions or assumptions
|
|
80
|
-
- a short summary if needed
|
|
81
|
-
|
|
82
|
-
If there are no findings, say that explicitly. Mention residual risks such as unrun tests, incomplete diff scope, or unverified runtime behavior.
|
|
83
|
-
|
|
84
|
-
## Review Discipline
|
|
85
|
-
|
|
86
|
-
- Prefer repo-specific reasoning over generic best-practice language.
|
|
87
|
-
- Do not request documentation updates unless the user asks for doc maintenance separately.
|
|
88
|
-
- Do not suggest broad rewrites when a focused fix would satisfy the repo rule.
|
|
89
|
-
- Be strict about architectural drift, duplication, and missing tests.
|
|
90
|
-
- Be careful with false positives: confirm the code actually violates the rule before flagging it.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# Review Checklist
|
|
2
|
-
|
|
3
|
-
Use this checklist while reviewing recent changes against the project's documented guidelines.
|
|
4
|
-
|
|
5
|
-
## Architecture
|
|
6
|
-
|
|
7
|
-
- Does the code belong in the shared/core layer or in the feature that owns it?
|
|
8
|
-
- Did the change duplicate a shared concern instead of reusing existing code?
|
|
9
|
-
- Did any file grow beyond roughly 800 lines without being split?
|
|
10
|
-
|
|
11
|
-
## State Management
|
|
12
|
-
|
|
13
|
-
- Does the state management approach follow the project's chosen pattern?
|
|
14
|
-
- If a new pattern was introduced, is there real complexity to justify it?
|
|
15
|
-
|
|
16
|
-
## Data And DI
|
|
17
|
-
|
|
18
|
-
- Are dependencies resolved via the project's DI system instead of ad hoc construction?
|
|
19
|
-
- Do repositories and data access layers follow the established contracts?
|
|
20
|
-
- Do mock or test implementations still match the real contract?
|
|
21
|
-
|
|
22
|
-
## UI And Reuse
|
|
23
|
-
|
|
24
|
-
- Is there an existing component that should have been reused?
|
|
25
|
-
- Could the new UI be parameterized instead of cloned?
|
|
26
|
-
- Should the component live in shared code because multiple features can use it?
|
|
27
|
-
|
|
28
|
-
## User-Facing Behavior
|
|
29
|
-
|
|
30
|
-
- Is all visible text localized (if the project uses i18n)?
|
|
31
|
-
- Were any persistence changes made in a way that could create partial or inconsistent state?
|
|
32
|
-
|
|
33
|
-
## Tests
|
|
34
|
-
|
|
35
|
-
- Did behavior change without test updates?
|
|
36
|
-
- If a reusable abstraction changed, were existing callers protected with tests?
|
|
37
|
-
- Is there any residual risk because validation was not run?
|