@izkac/forgekit 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/bin/forge.mjs +100 -0
- package/bin/forgekit.mjs +84 -0
- package/bin/review.mjs +82 -0
- package/package.json +46 -0
- package/scripts/prepack.mjs +78 -0
- package/scripts/run-tests.mjs +43 -0
- package/src/adr.mjs +236 -0
- package/src/adr.test.mjs +170 -0
- package/src/change.mjs +234 -0
- package/src/change.test.mjs +83 -0
- package/src/cleanup-sessions.mjs +70 -0
- package/src/config.mjs +103 -0
- package/src/defer.mjs +75 -0
- package/src/doctor.mjs +341 -0
- package/src/doctor.test.mjs +114 -0
- package/src/init.mjs +575 -0
- package/src/install.mjs +777 -0
- package/src/install.test.mjs +104 -0
- package/src/integrity-check.mjs +58 -0
- package/src/integrity.mjs +317 -0
- package/src/integrity.test.mjs +296 -0
- package/src/lib/workspaces.mjs +55 -0
- package/src/lib.mjs +138 -0
- package/src/models.defaults.json +41 -0
- package/src/new-session.mjs +82 -0
- package/src/openspec-overlays/README.md +19 -0
- package/src/openspec-overlays/openspec-apply-change-footer.md +14 -0
- package/src/openspec-overlays/opsx-apply-completion-step.md +1 -0
- package/src/openspec-overlays/opsx-apply-implement-step.md +11 -0
- package/src/paths.mjs +92 -0
- package/src/plan-engine.mjs +260 -0
- package/src/plan-engine.test.mjs +245 -0
- package/src/preferences.defaults.json +78 -0
- package/src/preferences.mjs +438 -0
- package/src/preferences.test.mjs +174 -0
- package/src/record-evidence.mjs +204 -0
- package/src/record-evidence.test.mjs +260 -0
- package/src/resolve-model.mjs +312 -0
- package/src/resolve-model.test.mjs +194 -0
- package/src/review/carryforward.mjs +413 -0
- package/src/review/carryforward.test.mjs +587 -0
- package/src/review/cli.test.mjs +117 -0
- package/src/review/export.mjs +172 -0
- package/src/review/export.test.mjs +197 -0
- package/src/review/fixtures/valid-review.json +42 -0
- package/src/review/lib.mjs +894 -0
- package/src/review/lib.test.mjs +266 -0
- package/src/review/merge-tentative.mjs +292 -0
- package/src/review/merge-tentative.test.mjs +363 -0
- package/src/review/new-review.mjs +200 -0
- package/src/review/render.mjs +108 -0
- package/src/review/schema-consistency.test.mjs +83 -0
- package/src/review/schema.json +196 -0
- package/src/review/signals.mjs +144 -0
- package/src/review/signals.test.mjs +62 -0
- package/src/score-cli.mjs +68 -0
- package/src/score.mjs +489 -0
- package/src/score.test.mjs +253 -0
- package/src/session-reminder.mjs +168 -0
- package/src/session-status.mjs +70 -0
- package/src/set-models.mjs +186 -0
- package/src/set-phase.mjs +177 -0
- package/src/set-phase.test.mjs +317 -0
- package/src/set-prefs.mjs +294 -0
- package/src/spine.mjs +91 -0
- package/src/triage-prompt.mjs +175 -0
- package/src/triage-prompt.test.mjs +50 -0
- package/src/vendor-openspec-overlays.mjs +176 -0
- package/src/vendor-openspec-overlays.test.mjs +62 -0
- package/vendor/skills/archive-to-adr/SKILL.md +149 -0
- package/vendor/skills/forge/SKILL.md +136 -0
- package/vendor/skills/forge/phases/brainstorm.md +23 -0
- package/vendor/skills/forge/phases/finish.md +87 -0
- package/vendor/skills/forge/phases/implement.md +76 -0
- package/vendor/skills/forge/phases/plan-openspec.md +40 -0
- package/vendor/skills/forge/phases/plan-specs.md +97 -0
- package/vendor/skills/forge/phases/review.md +25 -0
- package/vendor/skills/forge/phases/verify.md +120 -0
- package/vendor/skills/forge/references/forge-layout.md +85 -0
- package/vendor/skills/forge/references/pace.md +115 -0
- package/vendor/skills/forge/references/plan-routing.md +51 -0
- package/vendor/skills/forge/references/runtime-integrity.md +157 -0
- package/vendor/skills/forge/references/substantial-work.md +37 -0
- package/vendor/skills/forge/references/tdd-core.md +29 -0
- package/vendor/skills/forge/references/test-evidence.md +30 -0
- package/vendor/skills/forge/references/test-strategy.md +68 -0
- package/vendor/skills/forge/skills/NOTICE.md +17 -0
- package/vendor/skills/forge/skills/brainstorming/SKILL.md +120 -0
- package/vendor/skills/forge/skills/requesting-code-review/SKILL.md +67 -0
- package/vendor/skills/forge/skills/requesting-code-review/code-reviewer.md +146 -0
- package/vendor/skills/forge/skills/subagent-driven-development/SKILL.md +87 -0
- package/vendor/skills/forge/skills/systematic-debugging/SKILL.md +234 -0
- package/vendor/skills/forge/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/vendor/skills/forge/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/vendor/skills/forge/skills/systematic-debugging/find-polluter.sh +63 -0
- package/vendor/skills/forge/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/vendor/skills/forge/skills/test-driven-development/SKILL.md +290 -0
- package/vendor/skills/forge/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/vendor/skills/forge/skills/verification-before-completion/SKILL.md +59 -0
- package/vendor/skills/forge/subagents/final-reviewer-prompt.md +53 -0
- package/vendor/skills/forge/subagents/implementer-prompt.md +38 -0
- package/vendor/skills/forge/subagents/task-reviewer-prompt.md +61 -0
- package/vendor/skills/git-resolve-adr-conflict/SKILL.md +132 -0
- package/vendor/skills/thorough-code-review/SKILL.md +290 -0
- package/vendor/skills/thorough-code-review/examples/accepted-risks-janus.md +32 -0
- package/vendor/skills/thorough-code-review/examples.md +133 -0
- package/vendor/skills/thorough-code-review/reference/accepted-risks.md +26 -0
- package/vendor/skills/thorough-code-review/reference/lenses.md +96 -0
- package/vendor/skills/thorough-code-review/reference/phase1-scout.md +62 -0
- package/vendor/skills/thorough-code-review/reference/phase1c-coverage.md +44 -0
- package/vendor/skills/thorough-code-review/reference/phase2-skeptic.md +105 -0
- package/vendor/skills/thorough-code-review/reference/report-schema.json +222 -0
- package/vendor/skills/thorough-code-review/reference/report-template.md +115 -0
- package/vendor/skills/thorough-code-review/reference/severity-rubric.md +49 -0
- package/vendor/skills/thorough-code-review/reference/signals-preflight.md +55 -0
- package/vendor/templates/adr/README.md +7 -0
- package/vendor/templates/adr/decisions.md +141 -0
- package/vendor/templates/adr/hooks/check-pending-adrs.mjs +74 -0
- package/vendor/templates/adr/hooks/check-pending-adrs.sh +3 -0
- package/vendor/templates/adr/hooks/openspec-archive-agent-message.mjs +52 -0
- package/vendor/templates/adr/hooks/openspec-archive-agent-message.sh +3 -0
- package/vendor/templates/project/claude/commands/forge-apply.md +75 -0
- package/vendor/templates/project/claude/commands/forge-brainstorm.md +7 -0
- package/vendor/templates/project/claude/commands/forge-build.md +17 -0
- package/vendor/templates/project/claude/commands/forge-plan.md +12 -0
- package/vendor/templates/project/claude/commands/forge-skip.md +14 -0
- package/vendor/templates/project/claude/commands/forge-status.md +16 -0
- package/vendor/templates/project/claude/commands/forge.md +16 -0
- package/vendor/templates/project/claude/hooks/forge-prompt-hook.mjs +73 -0
- package/vendor/templates/project/claude/hooks/forge-session-start.mjs +19 -0
- package/vendor/templates/project/claude/hooks/forge-triage-hook.mjs +77 -0
- package/vendor/templates/project/claude/rules/forge.md +16 -0
- package/vendor/templates/project/codex/rules/forge.md +10 -0
- package/vendor/templates/project/cursor/commands/forge-apply.md +75 -0
- package/vendor/templates/project/cursor/commands/forge-brainstorm.md +10 -0
- package/vendor/templates/project/cursor/commands/forge-build.md +17 -0
- package/vendor/templates/project/cursor/commands/forge-plan.md +15 -0
- package/vendor/templates/project/cursor/commands/forge-skip.md +14 -0
- package/vendor/templates/project/cursor/commands/forge-status.md +16 -0
- package/vendor/templates/project/cursor/commands/forge.md +16 -0
- package/vendor/templates/project/cursor/hooks/forge-session-start.mjs +30 -0
- package/vendor/templates/project/cursor/hooks/forge-session-start.sh +3 -0
- package/vendor/templates/project/cursor/rules/forge.mdc +21 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# Testing Anti-Patterns
|
|
2
|
+
|
|
3
|
+
**Load this reference when:** writing or changing tests, adding mocks, or tempted to add test-only methods to production code.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Tests must verify real behavior, not mock behavior. Mocks are a means to isolate, not the thing being tested.
|
|
8
|
+
|
|
9
|
+
**Core principle:** Test what the code does, not what the mocks do.
|
|
10
|
+
|
|
11
|
+
**Following strict TDD prevents these anti-patterns.**
|
|
12
|
+
|
|
13
|
+
## The Iron Laws
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
1. NEVER test mock behavior
|
|
17
|
+
2. NEVER add test-only methods to production classes
|
|
18
|
+
3. NEVER mock without understanding dependencies
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Anti-Pattern 1: Testing Mock Behavior
|
|
22
|
+
|
|
23
|
+
**The violation:**
|
|
24
|
+
```typescript
|
|
25
|
+
// ❌ BAD: Testing that the mock exists
|
|
26
|
+
test('renders sidebar', () => {
|
|
27
|
+
render(<Page />);
|
|
28
|
+
expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Why this is wrong:**
|
|
33
|
+
- You're verifying the mock works, not that the component works
|
|
34
|
+
- Test passes when mock is present, fails when it's not
|
|
35
|
+
- Tells you nothing about real behavior
|
|
36
|
+
|
|
37
|
+
**your human partner's correction:** "Are we testing the behavior of a mock?"
|
|
38
|
+
|
|
39
|
+
**The fix:**
|
|
40
|
+
```typescript
|
|
41
|
+
// ✅ GOOD: Test real component or don't mock it
|
|
42
|
+
test('renders sidebar', () => {
|
|
43
|
+
render(<Page />); // Don't mock sidebar
|
|
44
|
+
expect(screen.getByRole('navigation')).toBeInTheDocument();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// OR if sidebar must be mocked for isolation:
|
|
48
|
+
// Don't assert on the mock - test Page's behavior with sidebar present
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Gate Function
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
BEFORE asserting on any mock element:
|
|
55
|
+
Ask: "Am I testing real component behavior or just mock existence?"
|
|
56
|
+
|
|
57
|
+
IF testing mock existence:
|
|
58
|
+
STOP - Delete the assertion or unmock the component
|
|
59
|
+
|
|
60
|
+
Test real behavior instead
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Anti-Pattern 2: Test-Only Methods in Production
|
|
64
|
+
|
|
65
|
+
**The violation:**
|
|
66
|
+
```typescript
|
|
67
|
+
// ❌ BAD: destroy() only used in tests
|
|
68
|
+
class Session {
|
|
69
|
+
async destroy() { // Looks like production API!
|
|
70
|
+
await this._workspaceManager?.destroyWorkspace(this.id);
|
|
71
|
+
// ... cleanup
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// In tests
|
|
76
|
+
afterEach(() => session.destroy());
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Why this is wrong:**
|
|
80
|
+
- Production class polluted with test-only code
|
|
81
|
+
- Dangerous if accidentally called in production
|
|
82
|
+
- Violates YAGNI and separation of concerns
|
|
83
|
+
- Confuses object lifecycle with entity lifecycle
|
|
84
|
+
|
|
85
|
+
**The fix:**
|
|
86
|
+
```typescript
|
|
87
|
+
// ✅ GOOD: Test utilities handle test cleanup
|
|
88
|
+
// Session has no destroy() - it's stateless in production
|
|
89
|
+
|
|
90
|
+
// In test-utils/
|
|
91
|
+
export async function cleanupSession(session: Session) {
|
|
92
|
+
const workspace = session.getWorkspaceInfo();
|
|
93
|
+
if (workspace) {
|
|
94
|
+
await workspaceManager.destroyWorkspace(workspace.id);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// In tests
|
|
99
|
+
afterEach(() => cleanupSession(session));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Gate Function
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
BEFORE adding any method to production class:
|
|
106
|
+
Ask: "Is this only used by tests?"
|
|
107
|
+
|
|
108
|
+
IF yes:
|
|
109
|
+
STOP - Don't add it
|
|
110
|
+
Put it in test utilities instead
|
|
111
|
+
|
|
112
|
+
Ask: "Does this class own this resource's lifecycle?"
|
|
113
|
+
|
|
114
|
+
IF no:
|
|
115
|
+
STOP - Wrong class for this method
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Anti-Pattern 3: Mocking Without Understanding
|
|
119
|
+
|
|
120
|
+
**The violation:**
|
|
121
|
+
```typescript
|
|
122
|
+
// ❌ BAD: Mock breaks test logic
|
|
123
|
+
test('detects duplicate server', () => {
|
|
124
|
+
// Mock prevents config write that test depends on!
|
|
125
|
+
vi.mock('ToolCatalog', () => ({
|
|
126
|
+
discoverAndCacheTools: vi.fn().mockResolvedValue(undefined)
|
|
127
|
+
}));
|
|
128
|
+
|
|
129
|
+
await addServer(config);
|
|
130
|
+
await addServer(config); // Should throw - but won't!
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Why this is wrong:**
|
|
135
|
+
- Mocked method had side effect test depended on (writing config)
|
|
136
|
+
- Over-mocking to "be safe" breaks actual behavior
|
|
137
|
+
- Test passes for wrong reason or fails mysteriously
|
|
138
|
+
|
|
139
|
+
**The fix:**
|
|
140
|
+
```typescript
|
|
141
|
+
// ✅ GOOD: Mock at correct level
|
|
142
|
+
test('detects duplicate server', () => {
|
|
143
|
+
// Mock the slow part, preserve behavior test needs
|
|
144
|
+
vi.mock('MCPServerManager'); // Just mock slow server startup
|
|
145
|
+
|
|
146
|
+
await addServer(config); // Config written
|
|
147
|
+
await addServer(config); // Duplicate detected ✓
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Gate Function
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
BEFORE mocking any method:
|
|
155
|
+
STOP - Don't mock yet
|
|
156
|
+
|
|
157
|
+
1. Ask: "What side effects does the real method have?"
|
|
158
|
+
2. Ask: "Does this test depend on any of those side effects?"
|
|
159
|
+
3. Ask: "Do I fully understand what this test needs?"
|
|
160
|
+
|
|
161
|
+
IF depends on side effects:
|
|
162
|
+
Mock at lower level (the actual slow/external operation)
|
|
163
|
+
OR use test doubles that preserve necessary behavior
|
|
164
|
+
NOT the high-level method the test depends on
|
|
165
|
+
|
|
166
|
+
IF unsure what test depends on:
|
|
167
|
+
Run test with real implementation FIRST
|
|
168
|
+
Observe what actually needs to happen
|
|
169
|
+
THEN add minimal mocking at the right level
|
|
170
|
+
|
|
171
|
+
Red flags:
|
|
172
|
+
- "I'll mock this to be safe"
|
|
173
|
+
- "This might be slow, better mock it"
|
|
174
|
+
- Mocking without understanding the dependency chain
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Anti-Pattern 4: Incomplete Mocks
|
|
178
|
+
|
|
179
|
+
**The violation:**
|
|
180
|
+
```typescript
|
|
181
|
+
// ❌ BAD: Partial mock - only fields you think you need
|
|
182
|
+
const mockResponse = {
|
|
183
|
+
status: 'success',
|
|
184
|
+
data: { userId: '123', name: 'Alice' }
|
|
185
|
+
// Missing: metadata that downstream code uses
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Later: breaks when code accesses response.metadata.requestId
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Why this is wrong:**
|
|
192
|
+
- **Partial mocks hide structural assumptions** - You only mocked fields you know about
|
|
193
|
+
- **Downstream code may depend on fields you didn't include** - Silent failures
|
|
194
|
+
- **Tests pass but integration fails** - Mock incomplete, real API complete
|
|
195
|
+
- **False confidence** - Test proves nothing about real behavior
|
|
196
|
+
|
|
197
|
+
**The Iron Rule:** Mock the COMPLETE data structure as it exists in reality, not just fields your immediate test uses.
|
|
198
|
+
|
|
199
|
+
**The fix:**
|
|
200
|
+
```typescript
|
|
201
|
+
// ✅ GOOD: Mirror real API completeness
|
|
202
|
+
const mockResponse = {
|
|
203
|
+
status: 'success',
|
|
204
|
+
data: { userId: '123', name: 'Alice' },
|
|
205
|
+
metadata: { requestId: 'req-789', timestamp: 1234567890 }
|
|
206
|
+
// All fields real API returns
|
|
207
|
+
};
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Gate Function
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
BEFORE creating mock responses:
|
|
214
|
+
Check: "What fields does the real API response contain?"
|
|
215
|
+
|
|
216
|
+
Actions:
|
|
217
|
+
1. Examine actual API response from docs/examples
|
|
218
|
+
2. Include ALL fields system might consume downstream
|
|
219
|
+
3. Verify mock matches real response schema completely
|
|
220
|
+
|
|
221
|
+
Critical:
|
|
222
|
+
If you're creating a mock, you must understand the ENTIRE structure
|
|
223
|
+
Partial mocks fail silently when code depends on omitted fields
|
|
224
|
+
|
|
225
|
+
If uncertain: Include all documented fields
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Anti-Pattern 5: Integration Tests as Afterthought
|
|
229
|
+
|
|
230
|
+
**The violation:**
|
|
231
|
+
```
|
|
232
|
+
✅ Implementation complete
|
|
233
|
+
❌ No tests written
|
|
234
|
+
"Ready for testing"
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Why this is wrong:**
|
|
238
|
+
- Testing is part of implementation, not optional follow-up
|
|
239
|
+
- TDD would have caught this
|
|
240
|
+
- Can't claim complete without tests
|
|
241
|
+
|
|
242
|
+
**The fix:**
|
|
243
|
+
```
|
|
244
|
+
TDD cycle:
|
|
245
|
+
1. Write failing test
|
|
246
|
+
2. Implement to pass
|
|
247
|
+
3. Refactor
|
|
248
|
+
4. THEN claim complete
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## When Mocks Become Too Complex
|
|
252
|
+
|
|
253
|
+
**Warning signs:**
|
|
254
|
+
- Mock setup longer than test logic
|
|
255
|
+
- Mocking everything to make test pass
|
|
256
|
+
- Mocks missing methods real components have
|
|
257
|
+
- Test breaks when mock changes
|
|
258
|
+
|
|
259
|
+
**your human partner's question:** "Do we need to be using a mock here?"
|
|
260
|
+
|
|
261
|
+
**Consider:** Integration tests with real components often simpler than complex mocks
|
|
262
|
+
|
|
263
|
+
## TDD Prevents These Anti-Patterns
|
|
264
|
+
|
|
265
|
+
**Why TDD helps:**
|
|
266
|
+
1. **Write test first** → Forces you to think about what you're actually testing
|
|
267
|
+
2. **Watch it fail** → Confirms test tests real behavior, not mocks
|
|
268
|
+
3. **Minimal implementation** → No test-only methods creep in
|
|
269
|
+
4. **Real dependencies** → You see what the test actually needs before mocking
|
|
270
|
+
|
|
271
|
+
**If you're testing mock behavior, you violated TDD** - you added mocks without watching test fail against real code first.
|
|
272
|
+
|
|
273
|
+
## Quick Reference
|
|
274
|
+
|
|
275
|
+
| Anti-Pattern | Fix |
|
|
276
|
+
|--------------|-----|
|
|
277
|
+
| Assert on mock elements | Test real component or unmock it |
|
|
278
|
+
| Test-only methods in production | Move to test utilities |
|
|
279
|
+
| Mock without understanding | Understand dependencies first, mock minimally |
|
|
280
|
+
| Incomplete mocks | Mirror real API completely |
|
|
281
|
+
| Tests as afterthought | TDD - tests first |
|
|
282
|
+
| Over-complex mocks | Consider integration tests |
|
|
283
|
+
|
|
284
|
+
## Red Flags
|
|
285
|
+
|
|
286
|
+
- Assertion checks for `*-mock` test IDs
|
|
287
|
+
- Methods only called in test files
|
|
288
|
+
- Mock setup is >50% of test
|
|
289
|
+
- Test fails when you remove mock
|
|
290
|
+
- Can't explain why mock is needed
|
|
291
|
+
- Mocking "just to be safe"
|
|
292
|
+
|
|
293
|
+
## The Bottom Line
|
|
294
|
+
|
|
295
|
+
**Mocks are tools to isolate, not things to test.**
|
|
296
|
+
|
|
297
|
+
If TDD reveals you're testing mock behavior, you've gone wrong.
|
|
298
|
+
|
|
299
|
+
Fix: Test real behavior or question why you're mocking at all.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verification-before-completion
|
|
3
|
+
description: Forge — verify before claiming done. Internal skill; read via forge orchestrator.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Verification Before Completion
|
|
7
|
+
|
|
8
|
+
Claiming work is complete without verification is dishonesty, not efficiency.
|
|
9
|
+
|
|
10
|
+
**Core principle:** Evidence before claims, always. Violating the letter of this rule is violating the spirit of this rule — it applies to exact phrases, paraphrases, and any wording implying success.
|
|
11
|
+
|
|
12
|
+
## Forge — coordinator verify phase
|
|
13
|
+
|
|
14
|
+
Three tiers: [test-strategy.md](../../references/test-strategy.md).
|
|
15
|
+
|
|
16
|
+
**During implement:** implementers use tier 1 (scoped TDD) and tier 2 (narrow task evidence in `test-evidence.md`).
|
|
17
|
+
|
|
18
|
+
**During verify:**
|
|
19
|
+
|
|
20
|
+
1. **Audit** tier 2 evidence per task — exit code, pass summary, reviewer approvals. Do **not** re-run tier 2 commands.
|
|
21
|
+
2. **Run tier 3 once** — fresh full workspace test per affected workspace (plus consumer workspaces if contracts changed). Save to `verify-evidence.md`.
|
|
22
|
+
3. **Runtime wiring audit** — for each capability requirement, name the production caller. Library-only / stub / false success → incomplete. See [runtime-integrity.md](../../references/runtime-integrity.md).
|
|
23
|
+
4. **E2E-or-BLOCKED** — one real fixture path through each critical live entry point, or an explicit `BLOCKED` list in `verify-evidence.md`. Do not claim complete while checkboxing around missing E2E.
|
|
24
|
+
5. Cite tier 3 + wiring/E2E evidence when claiming the implementation passes.
|
|
25
|
+
|
|
26
|
+
Re-run tier 3 only when it failed, coordinator edited code after verify evidence, reviewers flagged gaps, or the user asks. Per-task tier 2 runs **are** evidence for task-scoped claims; tier 3 **is** evidence for "full workspace passes." Do not duplicate tier 2 at verify; do not skip tier 3 because tier 2 passed; never run full workspace per implement task.
|
|
27
|
+
|
|
28
|
+
## The Iron Law
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Before claiming any status or expressing satisfaction ("Done!", "Great!", "should work"):
|
|
35
|
+
|
|
36
|
+
1. **IDENTIFY** the command that proves the claim
|
|
37
|
+
2. **RUN** it fresh and complete
|
|
38
|
+
3. **READ** full output — exit code, failure count
|
|
39
|
+
4. **VERIFY** the output confirms the claim; if not, state the actual status with evidence
|
|
40
|
+
5. Only then make the claim, **with** the evidence
|
|
41
|
+
|
|
42
|
+
Skip any step = lying, not verifying.
|
|
43
|
+
|
|
44
|
+
## What each claim requires
|
|
45
|
+
|
|
46
|
+
| Claim | Requires | Not sufficient |
|
|
47
|
+
|-------|----------|----------------|
|
|
48
|
+
| Tests pass | Test command output: 0 failures | Previous run, "should pass" |
|
|
49
|
+
| Linter clean | Linter output: 0 errors | Partial check, extrapolation |
|
|
50
|
+
| Build succeeds | Build command: exit 0 | Linter passing, logs look good |
|
|
51
|
+
| Bug fixed | Test of original symptom: passes | Code changed, assumed fixed |
|
|
52
|
+
| Regression test works | Red-green verified (revert fix → must fail → restore → pass) | Test passes once |
|
|
53
|
+
| Agent completed | VCS diff shows the changes | Agent reports "success" |
|
|
54
|
+
| Requirements met | Line-by-line checklist vs **capability specs** + named runtime owner per REQ | Tests passing; plan/task checkboxes alone |
|
|
55
|
+
| Change complete | Tier 3 + wiring audit + E2E fixture path (or explicit `BLOCKED`) | Green suite with stub handlers / unwired libraries |
|
|
56
|
+
|
|
57
|
+
## Red flags — stop and run the verification
|
|
58
|
+
|
|
59
|
+
"Should / probably / seems to" · satisfaction before evidence · committing or moving to the next task unverified · trusting an agent's success report · partial checks ("linter passed" ≠ build) · "I'm confident" (confidence ≠ evidence) · "just this once" · tired and wanting the work over.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Final implementation reviewer
|
|
2
|
+
|
|
3
|
+
Review the **entire** Forge session implementation against the plan **and**
|
|
4
|
+
the capability specs. See [references/runtime-integrity.md](../references/runtime-integrity.md).
|
|
5
|
+
|
|
6
|
+
## Plan source
|
|
7
|
+
|
|
8
|
+
{PLAN_REFERENCE}
|
|
9
|
+
|
|
10
|
+
## Capability specs (source of truth)
|
|
11
|
+
|
|
12
|
+
{CAPABILITY_SPECS_REFERENCE}
|
|
13
|
+
|
|
14
|
+
## Tasks completed
|
|
15
|
+
|
|
16
|
+
{TASK_SUMMARY}
|
|
17
|
+
|
|
18
|
+
## Scope
|
|
19
|
+
|
|
20
|
+
All files changed in this session (use git diff or explicit list):
|
|
21
|
+
|
|
22
|
+
{CHANGED_FILES}
|
|
23
|
+
|
|
24
|
+
## Spec-to-runtime trace (required)
|
|
25
|
+
|
|
26
|
+
For **each** requirement in the change's capability specs, name the
|
|
27
|
+
**production caller** (worker job kind, HTTP endpoint, CLI command, scheduled
|
|
28
|
+
job, …) that invokes the implementing code. Cross-check against `spine.json`
|
|
29
|
+
(`forge spine check`) — every capability row must be wired, not library-only.
|
|
30
|
+
|
|
31
|
+
- Library-only / no production caller → **`NOT READY`**
|
|
32
|
+
- Stub handler / false success / enqueueable-but-unhandled kind → **`NOT READY`**
|
|
33
|
+
- Job kind on the product surface that is neither wired end-to-end nor deleted → **`NOT READY`**
|
|
34
|
+
- UI/API reads a collection or artifact nothing in the production path writes → **`NOT READY`**
|
|
35
|
+
- Missing E2E fixture path with no explicit `BLOCKED` in `verify-evidence.md` → **`NOT READY`**
|
|
36
|
+
|
|
37
|
+
## Product-loop evidence (required)
|
|
38
|
+
|
|
39
|
+
`verify-evidence.md` must contain a `## Product loop` section proving the
|
|
40
|
+
**closed loop** (produce → consume → decision changes output), or an explicit
|
|
41
|
+
`BLOCKED` list. A single job slice (e.g. ingest→file) or a library-level E2E
|
|
42
|
+
does **not** count as platform E2E.
|
|
43
|
+
|
|
44
|
+
- No product-loop section and no `BLOCKED` → **`NOT READY`**
|
|
45
|
+
- `BLOCKED` present → **`NOT READY`** (honest, but not READY)
|
|
46
|
+
- Unresolved deferrals in `forge defer list` → **`NOT READY`**
|
|
47
|
+
|
|
48
|
+
## Verdict
|
|
49
|
+
|
|
50
|
+
- **READY** — every capability has a runtime owner, product loop evidenced, tests evidence real outcomes, no critical gaps
|
|
51
|
+
- **NOT READY** — list blockers (prefer runtime-integrity and missing wiring first)
|
|
52
|
+
|
|
53
|
+
Do not approve if tests were not run, **`test-evidence.md` is missing**, tasks remain unchecked, or any claimed capability is library-only / stubbed / false-succeeding. Task checkboxes at 100% do **not** override a broken spine.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Implementer subagent brief
|
|
2
|
+
|
|
3
|
+
You are the **implementer** for one Forge task. You receive only this brief — no chat history.
|
|
4
|
+
|
|
5
|
+
## Task
|
|
6
|
+
|
|
7
|
+
{TASK_TITLE}
|
|
8
|
+
|
|
9
|
+
{TASK_BODY}
|
|
10
|
+
|
|
11
|
+
## Files
|
|
12
|
+
|
|
13
|
+
{FILE_LIST}
|
|
14
|
+
|
|
15
|
+
## Requirements / spec excerpt
|
|
16
|
+
|
|
17
|
+
{SPEC_EXCERPT}
|
|
18
|
+
|
|
19
|
+
## Forge constraints
|
|
20
|
+
|
|
21
|
+
- Read and follow [references/tdd-core.md](./references/tdd-core.md) before any production code (full TDD skill only if stuck).
|
|
22
|
+
- **No** `git commit` or `git push` unless the user explicitly asked in the current message.
|
|
23
|
+
- **Testing tiers:** tier 1 = scoped test file/pattern per red/green cycle; tier 2 = narrowest command proving this task. **Do not** run the full workspace suite unless this task touches shared contracts or the brief says so — that is tier 3 and runs once at verify.
|
|
24
|
+
- Include **command, exit code, and pass/fail summary** for tier 2 in your report (coordinator saves to `test-evidence.md`).
|
|
25
|
+
- Minimal diff; match existing style; trace ecosystem consumers if contracts change.
|
|
26
|
+
|
|
27
|
+
## Runtime integrity (hard)
|
|
28
|
+
|
|
29
|
+
Read [references/runtime-integrity.md](../references/runtime-integrity.md). Honor these without exception:
|
|
30
|
+
|
|
31
|
+
- **No stub-with-success.** Do not implement a handler that only logs / bumps progress / marks succeeded. Unwired kinds must fail closed or not be exposed.
|
|
32
|
+
- **Name the runtime caller.** If you add library code, report which production path (job kind, endpoint, CLI) invokes it. If nothing calls it yet, end with `DONE_WITH_CONCERNS` and say so — do not pretend the capability is done.
|
|
33
|
+
- **Tests must fail on a no-op.** Assert domain side effects, not ceremony.
|
|
34
|
+
- If this brief tells you a stub is OK or to “wire later,” **reject the brief**: reply `NEEDS_CONTEXT` / `BLOCKED` and ask the coordinator to restore full scope or get user approval to shrink it.
|
|
35
|
+
|
|
36
|
+
## Report status
|
|
37
|
+
|
|
38
|
+
End with one of: `DONE`, `DONE_WITH_CONCERNS`, `NEEDS_CONTEXT`, `BLOCKED` plus details.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Task reviewer (spec compliance + code quality)
|
|
2
|
+
|
|
3
|
+
You review one Forge task in a single pass. No chat history — only this packet.
|
|
4
|
+
|
|
5
|
+
## What was requested (task / plan excerpt)
|
|
6
|
+
|
|
7
|
+
{PLAN_OR_SPEC_EXCERPT}
|
|
8
|
+
|
|
9
|
+
## Capability spec excerpt (source of truth)
|
|
10
|
+
|
|
11
|
+
{CAPABILITY_SPEC_EXCERPT}
|
|
12
|
+
|
|
13
|
+
Capability specs beat narrow task wording when they conflict. See
|
|
14
|
+
[references/runtime-integrity.md](../references/runtime-integrity.md).
|
|
15
|
+
|
|
16
|
+
## What was implemented (implementer's own summary)
|
|
17
|
+
|
|
18
|
+
{IMPLEMENTER_SUMMARY}
|
|
19
|
+
|
|
20
|
+
## Changed files / diff
|
|
21
|
+
|
|
22
|
+
{FILE_LIST}
|
|
23
|
+
|
|
24
|
+
Diff range: {DIFF_RANGE} <!-- e.g. `git diff` (uncommitted) or BASE..HEAD -->
|
|
25
|
+
|
|
26
|
+
**Read the actual code.** The summary above was written by the party under review — it is a map, not evidence. Read the changed files (or the diff range) before any verdict; verify each spec requirement against what the code does, not what the summary says it does.
|
|
27
|
+
|
|
28
|
+
## Check — spec compliance first, then quality
|
|
29
|
+
|
|
30
|
+
**Spec compliance** (gate — check before quality):
|
|
31
|
+
|
|
32
|
+
- Every requirement in the **capability** excerpt is implemented; nothing important missing
|
|
33
|
+
- No unrequested scope (extra flags, features, refactors not in the plan)
|
|
34
|
+
- Be strict on contract/API behaviour; pragmatic on internal refactors that match the plan
|
|
35
|
+
|
|
36
|
+
**Runtime integrity — REJECT if any of:**
|
|
37
|
+
|
|
38
|
+
- Success path has no domain side effects required by the capability
|
|
39
|
+
- Tests would still pass with a no-op handler (ceremony-only evidence)
|
|
40
|
+
- API / UI can enqueue or trigger a job kind / path the runtime cannot truly execute
|
|
41
|
+
- UI / consumers depend on data nothing in the production path writes
|
|
42
|
+
- Spec requirement has a library but no named runtime owner (job kind, endpoint, CLI, …)
|
|
43
|
+
- Brief authorized a stub / “wire later” for a path this change claims
|
|
44
|
+
- Wiring is deferred **without a registered open deferral** — the packet must show `forge defer list` output naming this task's deferral; "wiring in §9" with no registry entry is a REJECT
|
|
45
|
+
- The task claims a capability whose `spine.json` row is missing or library-only (empty runtimeOwner / writes / evidence)
|
|
46
|
+
|
|
47
|
+
**Code quality:**
|
|
48
|
+
|
|
49
|
+
- Simplicity — no over-engineering
|
|
50
|
+
- Surgical diff — no unrelated edits
|
|
51
|
+
- Error handling — no silent failures
|
|
52
|
+
- Tests — meaningful coverage for behaviour changes; **`test-evidence.md`** (tier 2) present with exit code `0` and pass summary; evidence is **narrow** unless task required full workspace
|
|
53
|
+
- Ecosystem — dependents updated if contracts changed
|
|
54
|
+
- AGENTS.md coding guidelines
|
|
55
|
+
|
|
56
|
+
## Verdict
|
|
57
|
+
|
|
58
|
+
- **APPROVED** — capability met, runtime owner present, quality acceptable
|
|
59
|
+
- **REJECTED** — list spec gaps and runtime-integrity failures first, then quality issues classified Critical / Important / Minor
|
|
60
|
+
|
|
61
|
+
Spec gaps, runtime-integrity failures, and Critical/Important quality issues must be fixed before the task is marked complete.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-resolve-adr-conflict
|
|
3
|
+
description: >-
|
|
4
|
+
Git-scoped resolution of duplicate ADR number collisions after a coworker
|
|
5
|
+
commits the same sequential number first. Renames the local ADR file to the
|
|
6
|
+
next free number, updates its internal ADR-NNNN references, merges the ADR
|
|
7
|
+
README by keeping all HEAD table rows, renumbering only the local row from the
|
|
8
|
+
======= side, and deleting every conflict marker, patches
|
|
9
|
+
openspec/changes/archive/**/proposal.md backlinks that still point at the old
|
|
10
|
+
ADR path, then git add to mark conflicts resolved. Git commands allowed are
|
|
11
|
+
git mv and git add (ADR dir and touched archive proposal.md only). Use when
|
|
12
|
+
the ADR README has merge conflict markers, two NNNN-*.md files share the same
|
|
13
|
+
prefix, or the user says git resolve ADR conflict / duplicate ADR number.
|
|
14
|
+
disable-model-invocation: true
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Git: resolve ADR number conflict
|
|
18
|
+
|
|
19
|
+
When two authors pick the same ADR number almost simultaneously, the remote
|
|
20
|
+
commit wins the number. **Renumber yours** — never recycle or overwrite a
|
|
21
|
+
committed ADR.
|
|
22
|
+
|
|
23
|
+
## Project config
|
|
24
|
+
|
|
25
|
+
Read **`.forge/config.json`**:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{ "adr": { "enabled": true, "dir": "docs/adr", "decisionsDoc": "docs/decisions.md" } }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Use **`{adrDir}`** = `adr.dir` (default `docs/adr`). If `adr.enabled` is `false`,
|
|
32
|
+
stop — this skill does not apply.
|
|
33
|
+
|
|
34
|
+
## Scope (strict)
|
|
35
|
+
|
|
36
|
+
| In scope | Out of scope |
|
|
37
|
+
| -------- | ------------ |
|
|
38
|
+
| Files under `{adrDir}/` | Implementation code, other docs |
|
|
39
|
+
| `openspec/changes/archive/**/proposal.md` — ADR backlink only | Other files under `openspec/` |
|
|
40
|
+
| `git mv` to rename the local ADR file | `git commit`, `git merge`, `git pull`, `git push` |
|
|
41
|
+
| `git add` on touched `{adrDir}/` and archive `proposal.md` paths | `git add` on any other path |
|
|
42
|
+
| Fix conflict markers in `{adrDir}/README.md` | Editing archive `design.md`, `tasks.md`, specs |
|
|
43
|
+
|
|
44
|
+
## When to run
|
|
45
|
+
|
|
46
|
+
- `{adrDir}/README.md` contains `<<<<<<<` / `=======` / `>>>>>>>` around table rows
|
|
47
|
+
- Two `{adrDir}/NNNN-*.md` files share the same four-digit prefix (different slugs)
|
|
48
|
+
- User reports "my ADR number was taken" after pulling or rebasing
|
|
49
|
+
|
|
50
|
+
## Workflow
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
Task progress:
|
|
54
|
+
- [ ] Detect collision and identify the local ADR
|
|
55
|
+
- [ ] Compute next free ADR number
|
|
56
|
+
- [ ] git mv rename local ADR file
|
|
57
|
+
- [ ] Update ADR body (title + ADR-NNNN references)
|
|
58
|
+
- [ ] Resolve {adrDir}/README.md — HEAD rows + your row renumbered; no markers left
|
|
59
|
+
- [ ] git add — mark README conflict resolved
|
|
60
|
+
- [ ] Patch archive proposal.md backlinks (old ADR number / path)
|
|
61
|
+
- [ ] git add — stage updated proposal.md files
|
|
62
|
+
- [ ] Verify
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 1. Detect collision and identify the local ADR
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git status --porcelain {adrDir}/
|
|
69
|
+
git ls-files {adrDir}/
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Local ADR (yours)** — untracked (`??`) / added (`A`), or the `>>>>>>>` side of a
|
|
73
|
+
README conflict. **Committed ADR (coworker's)** — tracked and HEAD side.
|
|
74
|
+
|
|
75
|
+
Record **`old_padded`** (four-digit prefix) and **`slug`** (filename after `NNNN-`).
|
|
76
|
+
|
|
77
|
+
### 2. Compute next free ADR number
|
|
78
|
+
|
|
79
|
+
Use the **higher** of HEAD README table max and on-disk `NNNN-*.md` max, then +1.
|
|
80
|
+
Zero-pad to 4 digits. Never reuse a number that already exists.
|
|
81
|
+
|
|
82
|
+
### 3. Rename with git mv
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git mv {adrDir}/<old_padded>-<slug>.md {adrDir}/<next_padded>-<slug>.md
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 4. Update the ADR file body
|
|
89
|
+
|
|
90
|
+
1. H1 `# NNNN.` → `# <next_padded>.`
|
|
91
|
+
2. Replace every `ADR-<old>` with `ADR-<next_padded>`
|
|
92
|
+
3. Do not change decision text unless it embeds the wrong number
|
|
93
|
+
|
|
94
|
+
### 5. Resolve `{adrDir}/README.md`
|
|
95
|
+
|
|
96
|
+
For each conflict block:
|
|
97
|
+
|
|
98
|
+
1. Keep every table row from the `<<<<<<< HEAD` side verbatim
|
|
99
|
+
2. Keep your row from the `=======` … `>>>>>>>` side, changing **only** the `#`
|
|
100
|
+
column to `<next_padded>`
|
|
101
|
+
3. Delete every conflict marker
|
|
102
|
+
4. Order: HEAD rows first, then your renumbered row(s)
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
rg '<<<<<<<|=======|>>>>>>>' {adrDir}/README.md
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Must print **no matches**.
|
|
109
|
+
|
|
110
|
+
### 6–8. Stage and patch backlinks
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
git add {adrDir}/README.md {adrDir}/<next_padded>-<slug>.md
|
|
114
|
+
rg -l "ADR-<old_padded>\\b|<old_padded>-<slug>\\.md" openspec/changes/archive/
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
In matching `proposal.md` files: update `ADR-NNNN` and filename segments only;
|
|
118
|
+
preserve the relative path prefix to `{adrDir}`. Then `git add` those proposals.
|
|
119
|
+
|
|
120
|
+
### 9. Verify
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git status {adrDir}/ openspec/changes/archive/
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Expect no unmerged README, no duplicate `NNNN-` prefixes, no stale
|
|
127
|
+
`ADR-<old_padded>` for your slug.
|
|
128
|
+
|
|
129
|
+
## Output
|
|
130
|
+
|
|
131
|
+
Report old → new path, new number, README merge summary, patched proposals.
|
|
132
|
+
Do **not** commit unless the user explicitly asks.
|