cclaw-cli 0.5.10 → 0.5.12
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/dist/artifact-linter.js
CHANGED
|
@@ -201,6 +201,22 @@ function validateSectionBody(sectionBody, rule) {
|
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
|
+
if (/Status:\s*pending\s+until/iu.test(rule)) {
|
|
205
|
+
const statusLine = bodyLines.find((l) => /^\s*-?\s*Status\s*:/iu.test(l));
|
|
206
|
+
if (!statusLine) {
|
|
207
|
+
return { ok: false, details: "WAIT_FOR_CONFIRM section must contain a 'Status:' line." };
|
|
208
|
+
}
|
|
209
|
+
const validStatuses = ["pending", "approved"];
|
|
210
|
+
const statusMatch = /Status\s*:\s*(\S+)/iu.exec(statusLine);
|
|
211
|
+
const statusValue = statusMatch?.[1]?.toLowerCase();
|
|
212
|
+
if (!statusValue || !validStatuses.includes(statusValue)) {
|
|
213
|
+
const foundLabel = statusValue || "(empty)";
|
|
214
|
+
return {
|
|
215
|
+
ok: false,
|
|
216
|
+
details: "WAIT_FOR_CONFIRM Status must be exactly one of: " + validStatuses.join(", ") + ". Found: " + foundLabel + "."
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
204
220
|
const keywords = extractRequiredKeywords(rule);
|
|
205
221
|
if (keywords.length > 0) {
|
|
206
222
|
const bodyLower = sectionBody.toLowerCase();
|
|
@@ -242,7 +258,16 @@ export async function lintArtifact(projectRoot, stage) {
|
|
|
242
258
|
}
|
|
243
259
|
const raw = await fs.readFile(absFile, "utf8");
|
|
244
260
|
const sections = extractH2Sections(raw);
|
|
261
|
+
const isTrivialOverride = schema.trivialOverrideSections &&
|
|
262
|
+
schema.trivialOverrideSections.length > 0 &&
|
|
263
|
+
/trivial.change|mini.design|escape.hatch/iu.test(raw);
|
|
264
|
+
const overrideSet = isTrivialOverride
|
|
265
|
+
? new Set(schema.trivialOverrideSections.map((s) => normalizeHeadingTitle(s).toLowerCase()))
|
|
266
|
+
: null;
|
|
245
267
|
for (const v of schema.artifactValidation) {
|
|
268
|
+
const effectiveRequired = overrideSet
|
|
269
|
+
? overrideSet.has(normalizeHeadingTitle(v.section).toLowerCase()) ? true : false
|
|
270
|
+
: v.required;
|
|
246
271
|
const hasHeading = headingPresent(sections, v.section);
|
|
247
272
|
const body = hasHeading ? sectionBodyByName(sections, v.section) : null;
|
|
248
273
|
const validation = body === null
|
|
@@ -251,7 +276,7 @@ export async function lintArtifact(projectRoot, stage) {
|
|
|
251
276
|
const found = hasHeading && validation.ok;
|
|
252
277
|
findings.push({
|
|
253
278
|
section: v.section,
|
|
254
|
-
required:
|
|
279
|
+
required: effectiveRequired,
|
|
255
280
|
rule: v.validationRule,
|
|
256
281
|
found,
|
|
257
282
|
details: found
|
package/dist/content/examples.js
CHANGED
|
@@ -180,12 +180,34 @@ Data flow: Gateway → Service (validate + enrich) → Publisher (fan-out) → Q
|
|
|
180
180
|
| Duplicate publish | Retry after timeout | Dedupe key check in outbox | Upsert with idempotency key | None (transparent) |
|
|
181
181
|
| Queue backpressure | Spike >1000 events/s | Queue depth metric alarm | Back-pressure signal to publisher, shed non-critical events | Delayed delivery of low-priority notifications |
|
|
182
182
|
|
|
183
|
+
### Test Strategy
|
|
184
|
+
|
|
185
|
+
- **Unit:** validator functions, dedupe-key logic, event schema factories — target 90%+ line coverage.
|
|
186
|
+
- **Integration:** publisher → outbox → read-model pipeline via in-memory DB; SSE reconnect with simulated drops.
|
|
187
|
+
- **E2E:** one happy-path browser test (publish → feed visible) and one degraded-path test (SSE down → REST fallback + banner).
|
|
188
|
+
|
|
189
|
+
### Performance Budget
|
|
190
|
+
|
|
191
|
+
| Critical path | Metric | Target | Measurement method |
|
|
192
|
+
| --- | --- | --- | --- |
|
|
193
|
+
| Publish → visible in feed | p95 latency | ≤ 5 s | Integration test with deterministic clock + production Datadog SLO |
|
|
194
|
+
| Feed snapshot load | p99 response time | ≤ 200 ms | Load test with 1 000 items per user |
|
|
195
|
+
| SSE reconnect | Time to first event after drop | ≤ 3 s | Simulated disconnect in integration suite |
|
|
196
|
+
|
|
183
197
|
### NOT in scope
|
|
184
198
|
|
|
185
199
|
- Outbound channels (email, push, SMS) — deferred to v2.
|
|
186
200
|
- Admin notification management UI — separate workstream.
|
|
187
201
|
- Notification preferences / mute rules — requires user settings redesign.
|
|
188
202
|
|
|
203
|
+
### Parallelization Strategy
|
|
204
|
+
|
|
205
|
+
| Module | Depends on | Parallel lane | Conflict risk |
|
|
206
|
+
| --- | --- | --- | --- |
|
|
207
|
+
| Notification schema (T1) | — | Lane A | None |
|
|
208
|
+
| Publisher + outbox (T2) | T1 | Lane A | None |
|
|
209
|
+
| Client feed + SSE (T3) | T1, T2 | Lane B (after T1) | Shared event type definitions |
|
|
210
|
+
|
|
189
211
|
### Unresolved Decisions
|
|
190
212
|
|
|
191
213
|
| Decision | Status | Options | Missing info | Default if unanswered |
|
|
@@ -212,75 +234,86 @@ Data flow: Gateway → Service (validate + enrich) → Publisher (fan-out) → Q
|
|
|
212
234
|
### Quality bar for this stage
|
|
213
235
|
|
|
214
236
|
Design output should be **reviewable by someone who did not attend brainstorming**: they can trace from constraints → components → open decisions without reading code.`,
|
|
215
|
-
spec: `### Acceptance
|
|
237
|
+
spec: `### Acceptance Criteria
|
|
216
238
|
|
|
217
|
-
|
|
239
|
+
| ID | Criterion (observable/measurable/falsifiable) | Design Decision Ref |
|
|
240
|
+
| --- | --- | --- |
|
|
241
|
+
| AC-1 | Given a signed-in user with an active session, when the server publishes a new notification event for that user, the client feed shows the new item within 5 seconds without a full page reload. | Architecture: SSE delivery path |
|
|
242
|
+
| AC-2 | Given the same logical notification is published twice with the same dedupe key, when the client processes the stream, the feed contains exactly one visible item for that key. | Architecture: dedupe-key in event schema |
|
|
243
|
+
| AC-3 | Given the live connection is unavailable, when the user opens the notifications panel, the UI shows a non-blocking "live updates paused" banner and loads the latest snapshot via REST within 2 seconds. | Architecture: REST fallback + degraded UX |
|
|
218
244
|
|
|
219
|
-
|
|
220
|
-
- **When** the server publishes a new notification event for that user
|
|
221
|
-
- **Then** the client feed shows the new item within 5 seconds without a full page reload
|
|
245
|
+
### Edge Cases
|
|
222
246
|
|
|
223
|
-
|
|
247
|
+
| Criterion ID | Boundary case | Error case |
|
|
248
|
+
| --- | --- | --- |
|
|
249
|
+
| AC-1 | Notification published during client reconnect window (boundary: \u2264 5 s delivery still holds after reconnect). | Server publish fails mid-write — client never receives event; REST snapshot fills gap. |
|
|
250
|
+
| AC-2 | Two events with identical dedupe key arrive within same SSE frame (boundary: only one row rendered). | Dedupe-key field missing — reject event at publisher and log error. |
|
|
251
|
+
| AC-3 | SSE disconnects after exactly 30 s heartbeat timeout (boundary: banner appears within 1 s of timeout). | REST snapshot endpoint returns 500 — panel shows "unable to load" with retry button. |
|
|
224
252
|
|
|
225
|
-
|
|
226
|
-
- **When** the client processes the stream
|
|
227
|
-
- **Then** the feed contains exactly one visible item for that key
|
|
253
|
+
### Constraints and Assumptions
|
|
228
254
|
|
|
229
|
-
**
|
|
255
|
+
- **Constraints:** Max feed size 1 000 items per user. SSE heartbeat interval 30 s (server-side). REST snapshot p99 \u2264 200 ms. No new runtime dependencies.
|
|
256
|
+
- **Assumptions:** Users have a single active session at a time for v1. Existing auth middleware provides user context. Event publisher is single-writer per user.
|
|
230
257
|
|
|
231
|
-
|
|
232
|
-
- **When** the user opens the notifications panel
|
|
233
|
-
- **Then** the UI shows a non-blocking degraded state and still loads the latest snapshot via REST
|
|
258
|
+
### Testability Map
|
|
234
259
|
|
|
235
|
-
|
|
260
|
+
| Criterion ID | Verification approach | Command/manual steps |
|
|
261
|
+
| --- | --- | --- |
|
|
262
|
+
| AC-1 | Integration test: publish event \u2192 assert feed contains item within 5 s (deterministic clock). | \`pnpm vitest run tests/integration/notification-delivery.test.ts\` |
|
|
263
|
+
| AC-2 | Unit test: publish same dedupe key twice \u2192 assert single row in feed store. | \`pnpm vitest run tests/unit/dedupe-feed.test.ts\` |
|
|
264
|
+
| AC-3 | E2E test: kill SSE transport \u2192 assert banner visible + REST snapshot loads. | \`pnpm playwright test tests/e2e/degraded-mode.spec.ts\` |
|
|
236
265
|
|
|
237
|
-
|
|
238
|
-
| --- | --- |
|
|
239
|
-
| “Notifications should be fast.” | “p95 time from publish to visible feed update ≤ 5s under steady load.” |
|
|
240
|
-
| “The system should handle errors gracefully.” | “If SSE is down, panel renders REST snapshot within 2s and shows ‘live updates paused’.” |
|
|
241
|
-
| “Users should not see duplicates.” | “For dedupe key K, repeated publishes produce exactly one row with key K.” |
|
|
266
|
+
### Approval
|
|
242
267
|
|
|
243
|
-
|
|
268
|
+
- Approved by: user
|
|
269
|
+
- Date: 2026-04-14`,
|
|
270
|
+
plan: `### Dependency Graph
|
|
244
271
|
|
|
245
|
-
|
|
246
|
-
-
|
|
272
|
+
\`\`\`
|
|
273
|
+
T-1 ──▶ T-2 ──▶ T-3
|
|
274
|
+
│ ▲
|
|
275
|
+
└───────────────┘
|
|
276
|
+
\`\`\`
|
|
247
277
|
|
|
248
|
-
|
|
278
|
+
Parallel opportunity: T-1 is a prerequisite for both T-2 and T-3 (T-3 also needs T-2).
|
|
249
279
|
|
|
250
|
-
|
|
251
|
-
plan: `### Task breakdown (sample)
|
|
280
|
+
### Dependency Waves
|
|
252
281
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
| T2 | Implement publisher + outbox write path | T1 | Spec criterion 1 satisfied in integration test (happy path) | M |
|
|
257
|
-
| T3 | Implement client feed + SSE subscribe + REST fallback | T1, T2 | Spec criteria 1–3 satisfied in e2e-style tests (including degraded mode) | L |
|
|
282
|
+
#### Wave 1 (foundation)
|
|
283
|
+
- Task IDs: T-1
|
|
284
|
+
- Verification gate: schema tests pass, dedupe key fixtures validated
|
|
258
285
|
|
|
259
|
-
|
|
286
|
+
#### Wave 2 (core logic)
|
|
287
|
+
- Task IDs: T-2
|
|
288
|
+
- Depends on: Wave 1 (T-1 complete)
|
|
289
|
+
- Verification gate: integration test proves publish-to-outbox path
|
|
260
290
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
\`\`\`
|
|
291
|
+
#### Wave 3 (integration)
|
|
292
|
+
- Task IDs: T-3
|
|
293
|
+
- Depends on: Wave 2 (T-2 complete)
|
|
294
|
+
- Verification gate: e2e tests pass for delivery, dedupe, and degraded mode
|
|
266
295
|
|
|
267
|
-
|
|
296
|
+
Execution rule: complete and verify each wave before starting the next wave.
|
|
268
297
|
|
|
269
|
-
|
|
270
|
-
| --- | --- | --- |
|
|
271
|
-
| Criterion 1 (delivery) | T2, T3 | T2 proves publish path; T3 proves UI subscription path |
|
|
272
|
-
| Criterion 2 (idempotency) | T1, T2 | Schema + publisher tests must include dedupe cases |
|
|
273
|
-
| Criterion 3 (failure visibility) | T3 | Explicit degraded-mode test case |
|
|
298
|
+
### Task List
|
|
274
299
|
|
|
275
|
-
|
|
300
|
+
| Task ID | Description | Acceptance criterion | Verification command | Effort |
|
|
301
|
+
| --- | --- | --- | --- | --- |
|
|
302
|
+
| T-1 | Define notification event schema + dedupe key rules | AC-1, AC-2: schema contract + fixtures | \`\`\`pnpm vitest run tests/unit/notification-schema.test.ts\`\`\` |
|
|
303
|
+
| T-2 | Implement publisher + outbox write path | AC-1: integration test (happy path publish) | \`\`\`pnpm vitest run tests/integration/publisher.test.ts\`\`\` |
|
|
304
|
+
| T-3 | Implement client feed + SSE subscribe + REST fallback | AC-1, AC-2, AC-3: e2e tests including degraded mode | \`\`\`pnpm playwright test tests/e2e/notification-feed.spec.ts\`\`\` |
|
|
276
305
|
|
|
277
|
-
|
|
278
|
-
- **T2 before T3** ensures the UI is not built on a mocked publisher that will not match production semantics.
|
|
279
|
-
- **T3 last** integrates transport concerns once contracts are stable.
|
|
306
|
+
### Acceptance Mapping
|
|
280
307
|
|
|
281
|
-
|
|
308
|
+
| Criterion ID | Task IDs |
|
|
309
|
+
| --- | --- |
|
|
310
|
+
| AC-1 (delivery within 5s) | T-2, T-3 |
|
|
311
|
+
| AC-2 (idempotency) | T-1, T-2 |
|
|
312
|
+
| AC-3 (failure visibility) | T-3 |
|
|
282
313
|
|
|
283
|
-
|
|
314
|
+
### WAIT_FOR_CONFIRM
|
|
315
|
+
- Status: pending
|
|
316
|
+
- Confirmed by:`,
|
|
284
317
|
tdd: `### RED test (Vitest) — written before production code
|
|
285
318
|
|
|
286
319
|
\`\`\`typescript
|
|
@@ -71,6 +71,8 @@ export interface StageSchema {
|
|
|
71
71
|
decisionRecordFormat?: string;
|
|
72
72
|
/** When true, stage skill includes wave auto-execute guidance (tdd). */
|
|
73
73
|
waveExecutionAllowed?: boolean;
|
|
74
|
+
/** Sections that remain required even when the trivial-change escape hatch is active (design only). */
|
|
75
|
+
trivialOverrideSections?: string[];
|
|
74
76
|
/** Agent names that MUST be dispatched (or waived) before stage transition — derived from mandatory auto-subagent rows. */
|
|
75
77
|
mandatoryDelegations: string[];
|
|
76
78
|
}
|
|
@@ -412,7 +412,8 @@ const DESIGN = {
|
|
|
412
412
|
"For design baseline approval: present the full baseline. **STOP.** Do NOT proceed until user explicitly approves the design.",
|
|
413
413
|
"Take a firm position on every recommendation. Do NOT hedge with 'it depends' or 'you could do either'. State your opinion, then justify it.",
|
|
414
414
|
"Use pushback patterns for weak framing: if the user says 'it's just a small change', respond with 'small changes to shared interfaces have outsized blast radius — let's map it'. If 'we'll refactor later', respond with 'later never comes — show me the refactor ticket or do it now'.",
|
|
415
|
-
"When the user's proposed architecture is suboptimal, say so directly. Offer the alternative with concrete trade-offs, do not bury criticism in praise."
|
|
415
|
+
"When the user's proposed architecture is suboptimal, say so directly. Offer the alternative with concrete trade-offs, do not bury criticism in praise.",
|
|
416
|
+
"When encountering ambiguity, classify it before acting: (A) ask user for missing info, (B) enumerate interpretations and pick one with justification, (C) propose hypothesis with validation path. Do NOT silently resolve ambiguity."
|
|
416
417
|
],
|
|
417
418
|
process: [
|
|
418
419
|
"Read upstream artifacts (brainstorm, scope).",
|
|
@@ -514,7 +515,8 @@ const DESIGN = {
|
|
|
514
515
|
{ name: "Owner Preference Alignment", description: "Every recommendation must align with project conventions (DRY, test style, minimal diff, edge-case rigor). Read existing patterns before recommending new ones." },
|
|
515
516
|
{ name: "Failure Is Information", description: "A design that fails fast and visibly is better than one that silently degrades. Map every failure mode and make it observable. Undetected failures compound." },
|
|
516
517
|
{ name: "Search Breadth Before Depth", description: "Before committing to a design path, survey the full solution space: stdlib, existing code, open-source, prior art. A 30-minute search can save a 30-hour custom build." },
|
|
517
|
-
{ name: "Outside Voice", description: "When confidence is high and options seem obvious, that is exactly when to seek contradiction. Ask: what would a skeptical reviewer challenge here? What assumption am I not questioning?" }
|
|
518
|
+
{ name: "Outside Voice", description: "When confidence is high and options seem obvious, that is exactly when to seek contradiction. Ask: what would a skeptical reviewer challenge here? What assumption am I not questioning?" },
|
|
519
|
+
{ name: "Ambiguity Classification", description: "Before resolving any unclear requirement, classify it: (A) Insufficient information — ask the user. (B) Multiple valid interpretations — enumerate and pick with justification. (C) Genuinely unknown — propose hypothesis and validation path. Never treat all ambiguity the same way." }
|
|
518
520
|
],
|
|
519
521
|
reviewSections: [
|
|
520
522
|
{
|
|
@@ -578,17 +580,23 @@ const DESIGN = {
|
|
|
578
580
|
traceabilityRule: "Every architecture decision must trace to a scope boundary. Every downstream spec requirement must trace to a design decision."
|
|
579
581
|
},
|
|
580
582
|
artifactValidation: [
|
|
583
|
+
{ section: "Codebase Investigation", required: true, validationRule: "Must list blast-radius files with current responsibilities and discovered patterns." },
|
|
584
|
+
{ section: "Search Before Building", required: true, validationRule: "For each technical choice: Layer 1 (exact match), Layer 2 (partial match), Layer 3 (inspiration), EUREKA labels with reuse-first default." },
|
|
581
585
|
{ section: "Architecture Boundaries", required: true, validationRule: "Must list component boundaries with ownership." },
|
|
582
586
|
{ section: "Architecture Diagram", required: true, validationRule: "At least one diagram (ASCII, Mermaid, or image) showing component boundaries and data flow direction." },
|
|
583
587
|
{ section: "Data Flow", required: true, validationRule: "Must include happy path, nil input, empty input, upstream error paths." },
|
|
584
588
|
{ section: "Failure Mode Table", required: true, validationRule: "Each failure mode has: trigger, detection, mitigation, user impact." },
|
|
585
589
|
{ section: "Test Strategy", required: true, validationRule: "Must define unit/integration/e2e expectations with coverage targets." },
|
|
590
|
+
{ section: "Performance Budget", required: true, validationRule: "For each critical path: metric name, target threshold, and measurement method." },
|
|
586
591
|
{ section: "What Already Exists", required: true, validationRule: "For each sub-problem: existing code/library found (Layer 1-3/EUREKA label), reuse decision, and adaptation needed." },
|
|
587
592
|
{ section: "NOT in scope", required: true, validationRule: "Work considered and explicitly deferred with one-line rationale." },
|
|
588
593
|
{ section: "Parallelization Strategy", required: false, validationRule: "If multi-module: dependency table, parallel lanes, conflict flags." },
|
|
589
594
|
{ section: "Unresolved Decisions", required: false, validationRule: "If any: what info is missing, who provides it, default if unanswered." },
|
|
595
|
+
{ section: "Interface Contracts", required: false, validationRule: "If present: for each module boundary list produces (outputs) and consumes (inputs) with data types." },
|
|
596
|
+
{ section: "Patterns to Mirror", required: false, validationRule: "If present: list discovered codebase patterns to follow, with file references and rationale for each." },
|
|
590
597
|
{ section: "Completion Dashboard", required: true, validationRule: "Lists every review section with status (clear / issues-found-resolved / issues-open), decision count, and unresolved items (or 'None')." }
|
|
591
598
|
],
|
|
599
|
+
trivialOverrideSections: ["Architecture Boundaries", "NOT in scope", "Completion Dashboard"],
|
|
592
600
|
namedAntiPattern: {
|
|
593
601
|
title: "Architecture Will Emerge While Coding",
|
|
594
602
|
description: "Emergent architecture is a myth for non-trivial systems. What actually emerges is accidental complexity, incompatible module boundaries, and tech debt that costs 10x to fix later. Lock architecture explicitly before writing code."
|
|
@@ -636,7 +644,8 @@ const SPEC = {
|
|
|
636
644
|
"Resolve ambiguity before moving to plan. Challenge vague language.",
|
|
637
645
|
"Capture assumptions explicitly, not implicitly.",
|
|
638
646
|
"Require user confirmation on the written spec. **STOP.** Do NOT proceed to plan until user approves.",
|
|
639
|
-
"For each criterion, ask: how would you test this? If the answer is unclear, rewrite."
|
|
647
|
+
"For each criterion, ask: how would you test this? If the answer is unclear, rewrite.",
|
|
648
|
+
"When encountering ambiguity, classify it before acting: (A) ask user for missing info, (B) enumerate interpretations and pick one with justification, (C) propose hypothesis with validation path. Do NOT silently resolve ambiguity."
|
|
640
649
|
],
|
|
641
650
|
process: [
|
|
642
651
|
"Define measurable acceptance criteria.",
|
|
@@ -705,9 +714,33 @@ const SPEC = {
|
|
|
705
714
|
cognitivePatterns: [
|
|
706
715
|
{ name: "Observable Over Descriptive", description: "Requirements describe what can be observed, not what should feel like. Replace every adjective with a measurement." },
|
|
707
716
|
{ name: "Boundary Precision", description: "Every acceptance criterion has boundary conditions. What is the minimum valid input? Maximum? What happens at the edges?" },
|
|
708
|
-
{ name: "Assumption Surfacing", description: "Implicit assumptions are invisible requirements. Force every assumption into an explicit statement. If you cannot name the assumption, you have not found it yet." }
|
|
717
|
+
{ name: "Assumption Surfacing", description: "Implicit assumptions are invisible requirements. Force every assumption into an explicit statement. If you cannot name the assumption, you have not found it yet." },
|
|
718
|
+
{ name: "Ambiguity Classification", description: "Before resolving any unclear requirement, classify it: (A) Insufficient information — ask the user. (B) Multiple valid interpretations — enumerate and pick with justification. (C) Genuinely unknown — propose hypothesis and validation path. Never treat all ambiguity the same way." }
|
|
719
|
+
],
|
|
720
|
+
reviewSections: [
|
|
721
|
+
{
|
|
722
|
+
title: "Acceptance Criteria Audit",
|
|
723
|
+
evaluationPoints: [
|
|
724
|
+
"Is every criterion observable (can you point to evidence of pass/fail)?",
|
|
725
|
+
"Is every criterion measurable (numeric threshold or boolean outcome)?",
|
|
726
|
+
"Is every criterion falsifiable (can you describe what failure looks like)?",
|
|
727
|
+
"Does every criterion trace to a design decision (Design Decision Ref)?",
|
|
728
|
+
"Are there any vague adjectives (fast, intuitive, robust) without thresholds?"
|
|
729
|
+
],
|
|
730
|
+
stopGate: true
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
title: "Testability Audit",
|
|
734
|
+
evaluationPoints: [
|
|
735
|
+
"Does every criterion have a concrete test description in the Testability Map?",
|
|
736
|
+
"Does every test specify a verification approach (unit, integration, e2e, manual)?",
|
|
737
|
+
"Does every test include a runnable command or manual steps?",
|
|
738
|
+
"Are edge cases (boundary + error) defined for every criterion?",
|
|
739
|
+
"Can you run every verification command right now and get a meaningful result?"
|
|
740
|
+
],
|
|
741
|
+
stopGate: true
|
|
742
|
+
}
|
|
709
743
|
],
|
|
710
|
-
reviewSections: [],
|
|
711
744
|
completionStatus: ["DONE", "DONE_WITH_CONCERNS", "BLOCKED"],
|
|
712
745
|
crossStageTrace: {
|
|
713
746
|
readsFrom: [".cclaw/artifacts/03-design.md", ".cclaw/artifacts/02-scope.md"],
|
|
@@ -715,12 +748,19 @@ const SPEC = {
|
|
|
715
748
|
traceabilityRule: "Every acceptance criterion must trace to a design decision. Every downstream plan task must trace to a spec criterion."
|
|
716
749
|
},
|
|
717
750
|
artifactValidation: [
|
|
718
|
-
{ section: "Acceptance Criteria", required: true, validationRule: "Each criterion is observable, measurable, and falsifiable." },
|
|
751
|
+
{ section: "Acceptance Criteria", required: true, validationRule: "Each criterion is observable, measurable, and falsifiable. Table should include a Design Decision Ref column tracing back to design artifact." },
|
|
719
752
|
{ section: "Edge Cases", required: true, validationRule: "At least one boundary and one error condition per criterion." },
|
|
720
753
|
{ section: "Constraints and Assumptions", required: true, validationRule: "All implicit assumptions surfaced. Constraints have sources." },
|
|
721
|
-
{ section: "Testability Map", required: true, validationRule: "Each criterion maps to a concrete test description." },
|
|
754
|
+
{ section: "Testability Map", required: true, validationRule: "Each criterion maps to a concrete test description with verification approach (unit, integration, e2e, manual) and command or manual steps." },
|
|
755
|
+
{ section: "Vague to Fixed", required: false, validationRule: "If present: table with original vague wording and rewritten observable/testable version for each ambiguous requirement." },
|
|
756
|
+
{ section: "Non-Functional Requirements", required: false, validationRule: "If present: performance thresholds, security constraints, scalability limits, reliability targets with measurable values." },
|
|
757
|
+
{ section: "Interface Contracts", required: false, validationRule: "If present: for each module boundary list produces (outputs) and consumes (inputs) with data types." },
|
|
722
758
|
{ section: "Approval", required: true, validationRule: "Explicit user approval marker present." }
|
|
723
|
-
]
|
|
759
|
+
],
|
|
760
|
+
namedAntiPattern: {
|
|
761
|
+
title: "Implementation Will Clarify Requirements",
|
|
762
|
+
description: "Unclear specs do not become clear during coding — they become contradictory implementations, rework, and scope creep. If a requirement cannot be stated in observable, testable terms right now, it is not ready for implementation. Rewrite it until it is falsifiable."
|
|
763
|
+
}
|
|
724
764
|
};
|
|
725
765
|
// ---------------------------------------------------------------------------
|
|
726
766
|
// PLAN
|
|
@@ -824,9 +864,35 @@ const PLAN = {
|
|
|
824
864
|
cognitivePatterns: [
|
|
825
865
|
{ name: "Vertical Slice Thinking", description: "Each task delivers one thin end-to-end slice of value. Horizontal layers (all models, then all controllers) create integration risk. Vertical slices (one feature through all layers) reduce it." },
|
|
826
866
|
{ name: "Two-Minute Smell Test", description: "If a competent engineer cannot understand and start a task in two minutes, the task is too large or too vague. Break it down further." },
|
|
827
|
-
{ name: "Make the Change Easy, Then Make the Easy Change", description: "Refactor first, implement second. Never structural + behavioral changes simultaneously. Sequence tasks accordingly." }
|
|
867
|
+
{ name: "Make the Change Easy, Then Make the Easy Change", description: "Refactor first, implement second. Never structural + behavioral changes simultaneously. Sequence tasks accordingly." },
|
|
868
|
+
{ name: "Diagnose Before Fix", description: "Before decomposing work, understand the current state of the codebase. Read existing code, tests, and conventions. Tasks should reference what exists, not assume a blank slate." },
|
|
869
|
+
{ name: "Scrap Signals", description: "If a task description is vague, the acceptance criterion is missing, or the verification command is a placeholder — it is scrap. Either rewrite it or remove it. Half-specified tasks waste more time than no tasks." },
|
|
870
|
+
{ name: "Risk-First Exploration", description: "Sequence the highest-risk or most uncertain tasks first. If wave 1 proves the risky assumption wrong, the rest of the plan can adapt. If the risk is buried in wave 3, you discover failure late." }
|
|
871
|
+
],
|
|
872
|
+
reviewSections: [
|
|
873
|
+
{
|
|
874
|
+
title: "Task Decomposition Audit",
|
|
875
|
+
evaluationPoints: [
|
|
876
|
+
"Does every task target a single coherent area (vertical slice)?",
|
|
877
|
+
"Can each task be completed in 2-5 minutes?",
|
|
878
|
+
"Does every task have an acceptance criterion link and verification command?",
|
|
879
|
+
"Are there tasks that touch multiple unrelated areas?",
|
|
880
|
+
"Would a new engineer understand and start each task within two minutes?"
|
|
881
|
+
],
|
|
882
|
+
stopGate: true
|
|
883
|
+
},
|
|
884
|
+
{
|
|
885
|
+
title: "Wave Completeness Audit",
|
|
886
|
+
evaluationPoints: [
|
|
887
|
+
"Does every task belong to exactly one wave?",
|
|
888
|
+
"Does each wave have a verification gate?",
|
|
889
|
+
"Are wave dependencies explicit and acyclic?",
|
|
890
|
+
"Is the acceptance mapping complete — every spec criterion covered?",
|
|
891
|
+
"Are there hidden dependencies between tasks in different waves?"
|
|
892
|
+
],
|
|
893
|
+
stopGate: true
|
|
894
|
+
}
|
|
828
895
|
],
|
|
829
|
-
reviewSections: [],
|
|
830
896
|
completionStatus: ["DONE", "DONE_WITH_CONCERNS", "BLOCKED"],
|
|
831
897
|
crossStageTrace: {
|
|
832
898
|
readsFrom: [".cclaw/artifacts/04-spec.md", ".cclaw/artifacts/03-design.md", ".cclaw/artifacts/02-scope.md"],
|
|
@@ -836,10 +902,15 @@ const PLAN = {
|
|
|
836
902
|
artifactValidation: [
|
|
837
903
|
{ section: "Dependency Graph", required: true, validationRule: "Ordering and parallel opportunities explicit. No circular dependencies." },
|
|
838
904
|
{ section: "Dependency Waves", required: true, validationRule: "Every task belongs to a wave. Each wave has an exit gate and dependency statement." },
|
|
839
|
-
{ section: "Task List", required: true, validationRule: "Each task: ID, description, acceptance criterion link, verification command." },
|
|
905
|
+
{ section: "Task List", required: true, validationRule: "Each task: ID, description, acceptance criterion link, verification command, and effort estimate (S/M/L)." },
|
|
840
906
|
{ section: "Acceptance Mapping", required: true, validationRule: "Every spec criterion is covered by at least one task." },
|
|
907
|
+
{ section: "Risk Assessment", required: false, validationRule: "If present: per-task or per-wave risk identification with likelihood, impact, and mitigation strategy." },
|
|
841
908
|
{ section: "WAIT_FOR_CONFIRM", required: true, validationRule: "Explicit marker present. Status: pending until user approves." }
|
|
842
|
-
]
|
|
909
|
+
],
|
|
910
|
+
namedAntiPattern: {
|
|
911
|
+
title: "Task Details Can Be Finalized During Coding",
|
|
912
|
+
description: "Underspecified tasks do not become clear during implementation — they become context thrash, broken sequencing, and rework. Every task needs an acceptance criterion, a verification command, and a wave assignment before execution starts. If you cannot describe what 'done' looks like for a task, the task is not ready."
|
|
913
|
+
}
|
|
843
914
|
};
|
|
844
915
|
// ---------------------------------------------------------------------------
|
|
845
916
|
// TDD — RED → GREEN → REFACTOR cycle (merged test + build)
|
|
@@ -162,6 +162,11 @@ export const ARTIFACT_TEMPLATES = {
|
|
|
162
162
|
- Integration:
|
|
163
163
|
- E2E:
|
|
164
164
|
|
|
165
|
+
## Performance Budget
|
|
166
|
+
| Critical path | Metric | Target | Measurement method |
|
|
167
|
+
|---|---|---|---|
|
|
168
|
+
| | | | |
|
|
169
|
+
|
|
165
170
|
## NOT in scope
|
|
166
171
|
-
|
|
167
172
|
|
|
@@ -169,6 +174,16 @@ export const ARTIFACT_TEMPLATES = {
|
|
|
169
174
|
- Parallel lanes:
|
|
170
175
|
- Conflict risks:
|
|
171
176
|
|
|
177
|
+
## Patterns to Mirror
|
|
178
|
+
| Pattern | Source file | Rationale |
|
|
179
|
+
|---|---|---|
|
|
180
|
+
| | | |
|
|
181
|
+
|
|
182
|
+
## Interface Contracts
|
|
183
|
+
| Module | Produces | Consumes |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| | | |
|
|
186
|
+
|
|
172
187
|
## Unresolved Decisions
|
|
173
188
|
| Decision | Missing info | Owner | Default |
|
|
174
189
|
|---|---|---|---|
|
|
@@ -188,9 +203,9 @@ export const ARTIFACT_TEMPLATES = {
|
|
|
188
203
|
"04-spec.md": `# Specification Artifact
|
|
189
204
|
|
|
190
205
|
## Acceptance Criteria
|
|
191
|
-
| ID | Criterion (observable/measurable/falsifiable) |
|
|
192
|
-
|
|
193
|
-
| AC-1 | |
|
|
206
|
+
| ID | Criterion (observable/measurable/falsifiable) | Design Decision Ref |
|
|
207
|
+
|---|---|---|
|
|
208
|
+
| AC-1 | | |
|
|
194
209
|
|
|
195
210
|
## Edge Cases
|
|
196
211
|
| Criterion ID | Boundary case | Error case |
|
|
@@ -206,6 +221,21 @@ export const ARTIFACT_TEMPLATES = {
|
|
|
206
221
|
|---|---|---|
|
|
207
222
|
| AC-1 | | |
|
|
208
223
|
|
|
224
|
+
## Vague to Fixed
|
|
225
|
+
| Original (vague) | Rewritten (observable/testable) |
|
|
226
|
+
|---|---|
|
|
227
|
+
| | |
|
|
228
|
+
|
|
229
|
+
## Non-Functional Requirements
|
|
230
|
+
| Category | Requirement | Threshold | Measurement |
|
|
231
|
+
|---|---|---|---|
|
|
232
|
+
| | | | |
|
|
233
|
+
|
|
234
|
+
## Interface Contracts
|
|
235
|
+
| Module | Produces | Consumes |
|
|
236
|
+
|---|---|---|
|
|
237
|
+
| | | |
|
|
238
|
+
|
|
209
239
|
## Approval
|
|
210
240
|
- Approved by:
|
|
211
241
|
- Date:
|
|
@@ -234,15 +264,20 @@ export const ARTIFACT_TEMPLATES = {
|
|
|
234
264
|
Execution rule: complete and verify each wave before starting the next wave.
|
|
235
265
|
|
|
236
266
|
## Task List
|
|
237
|
-
| Task ID | Description | Acceptance criterion | Verification command |
|
|
238
|
-
|
|
239
|
-
| T-1 | | | |
|
|
267
|
+
| Task ID | Description | Acceptance criterion | Verification command | Effort |
|
|
268
|
+
|---|---|---|---|---|
|
|
269
|
+
| T-1 | | | | |
|
|
240
270
|
|
|
241
271
|
## Acceptance Mapping
|
|
242
272
|
| Criterion ID | Task IDs |
|
|
243
273
|
|---|---|
|
|
244
274
|
| AC-1 | T-1 |
|
|
245
275
|
|
|
276
|
+
## Risk Assessment
|
|
277
|
+
| Task/Wave | Risk | Likelihood | Impact | Mitigation |
|
|
278
|
+
|---|---|---|---|---|
|
|
279
|
+
| | | | | |
|
|
280
|
+
|
|
246
281
|
## WAIT_FOR_CONFIRM
|
|
247
282
|
- Status: pending
|
|
248
283
|
- Confirmed by:
|