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.
@@ -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: v.required,
279
+ required: effectiveRequired,
255
280
  rule: v.validationRule,
256
281
  found,
257
282
  details: found
@@ -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 criteria (Given / When / Then)
237
+ spec: `### Acceptance Criteria
216
238
 
217
- **Criterion 1 delivery**
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
- - **Given** a signed-in user with an active session
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
- **Criterion 2 idempotency**
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
- - **Given** the same logical notification is published twice with the same dedupe key
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
- **Criterion 3 failure visibility**
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
- - **Given** the live connection is unavailable
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
- ### Non-testable fixed (comparison)
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
- | Vague (non-testable) | Fixed (observable + testable) |
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
- ### Test doubles / fixtures (planning notes)
268
+ - Approved by: user
269
+ - Date: 2026-04-14`,
270
+ plan: `### Dependency Graph
244
271
 
245
- - Use a deterministic clock for the “within 5 seconds” criterion in automated tests.
246
- - Use a fake transport for SSE in unit tests; reserve browser-level tests for one happy path + one degraded path.
272
+ \`\`\`
273
+ T-1 ──▶ T-2 ──▶ T-3
274
+ │ ▲
275
+ └───────────────┘
276
+ \`\`\`
247
277
 
248
- ### Traceability reminder
278
+ Parallel opportunity: T-1 is a prerequisite for both T-2 and T-3 (T-3 also needs T-2).
249
279
 
250
- Every criterion should map to **at least one automated check** (unit/integration/e2e) before the work is considered “specified enough” to start TDD in earnest.`,
251
- plan: `### Task breakdown (sample)
280
+ ### Dependency Waves
252
281
 
253
- | ID | Title | depends_on | acceptance_criteria | estimated_effort |
254
- | --- | --- | --- | --- | --- |
255
- | T1 | Define notification event schema + dedupe key rules | — | Spec criteria 2 satisfied in a written contract + fixtures | S |
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
- ### Dependency graph (ASCII)
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
- T1 ──▶ T2 ──▶ T3
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
- ### Acceptance mapping (sample)
296
+ Execution rule: complete and verify each wave before starting the next wave.
268
297
 
269
- | Spec criterion | Tasks that cover it | Notes |
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
- ### Sequencing rationale (sample)
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
- - **T1 first** prevents rework when event keys change mid-build.
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
- ### Risk note
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
- If T3 grows too large, split “transport” vs “UI state machine” into two tasks while keeping the dependency graph acyclic.`,
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:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "0.5.10",
3
+ "version": "0.5.12",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {