cclaw-cli 0.5.12 → 0.5.14
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 +26 -0
- package/dist/content/examples.js +62 -103
- package/dist/content/stage-schema.js +46 -10
- package/dist/content/templates.js +17 -2
- package/package.json +1 -1
package/dist/artifact-linter.js
CHANGED
|
@@ -199,6 +199,7 @@ function validateSectionBody(sectionBody, rule) {
|
|
|
199
199
|
details: `Rule expects exactly one selected token (${tokens.join(", ")}); found ${selected.size}.`
|
|
200
200
|
};
|
|
201
201
|
}
|
|
202
|
+
return { ok: true, details: "Exactly one token selected as expected." };
|
|
202
203
|
}
|
|
203
204
|
}
|
|
204
205
|
if (/Status:\s*pending\s+until/iu.test(rule)) {
|
|
@@ -419,9 +420,34 @@ export async function validateReviewArmy(projectRoot) {
|
|
|
419
420
|
if (!Array.isArray(rec.conflicts)) {
|
|
420
421
|
errors.push("reconciliation.conflicts must be an array.");
|
|
421
422
|
}
|
|
423
|
+
else {
|
|
424
|
+
rec.conflicts.forEach((c, ci) => {
|
|
425
|
+
if (c === null || typeof c !== "object" || Array.isArray(c)) {
|
|
426
|
+
errors.push(`reconciliation.conflicts[${ci}] must be an object.`);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const co = c;
|
|
430
|
+
if (!isNonEmptyString(co.findingId)) {
|
|
431
|
+
errors.push(`reconciliation.conflicts[${ci}].findingId must be a non-empty string.`);
|
|
432
|
+
}
|
|
433
|
+
else if (!findingIds.has(co.findingId)) {
|
|
434
|
+
errors.push(`reconciliation.conflicts[${ci}].findingId references unknown finding "${co.findingId}".`);
|
|
435
|
+
}
|
|
436
|
+
if (!isNonEmptyString(co.description)) {
|
|
437
|
+
errors.push(`reconciliation.conflicts[${ci}].description must be a non-empty string.`);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
}
|
|
422
441
|
if (!isStringArray(rec.multiSpecialistConfirmed)) {
|
|
423
442
|
errors.push("reconciliation.multiSpecialistConfirmed must be an array of finding ids.");
|
|
424
443
|
}
|
|
444
|
+
else {
|
|
445
|
+
for (const msId of rec.multiSpecialistConfirmed) {
|
|
446
|
+
if (!findingIds.has(msId)) {
|
|
447
|
+
errors.push(`reconciliation.multiSpecialistConfirmed references unknown finding id "${msId}".`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
425
451
|
if (!isStringArray(rec.shipBlockers)) {
|
|
426
452
|
errors.push("reconciliation.shipBlockers must be an array of finding ids.");
|
|
427
453
|
}
|
package/dist/content/examples.js
CHANGED
|
@@ -311,134 +311,93 @@ Execution rule: complete and verify each wave before starting the next wave.
|
|
|
311
311
|
| AC-2 (idempotency) | T-1, T-2 |
|
|
312
312
|
| AC-3 (failure visibility) | T-3 |
|
|
313
313
|
|
|
314
|
+
### Risk Assessment
|
|
315
|
+
|
|
316
|
+
| Task/Wave | Risk | Likelihood | Impact | Mitigation |
|
|
317
|
+
| --- | --- | --- | --- | --- |
|
|
318
|
+
| T-3 (Wave 3) | SSE reconnect logic complex | Medium | High | Spike reconnect in isolation before integrating with feed UI |
|
|
319
|
+
| Wave 2 → 3 | Publisher API contract may shift | Low | Medium | Pin contract in T-1 schema; T-2 integration test validates |
|
|
320
|
+
|
|
314
321
|
### WAIT_FOR_CONFIRM
|
|
315
322
|
- Status: pending
|
|
316
323
|
- Confirmed by:`,
|
|
317
|
-
tdd: `### RED
|
|
318
|
-
|
|
319
|
-
\`\`\`typescript
|
|
320
|
-
import { describe, it, expect } from "vitest";
|
|
321
|
-
import { summarizeDedupedFeed } from "../notificationFeed";
|
|
322
|
-
|
|
323
|
-
describe("summarizeDedupedFeed", () => {
|
|
324
|
-
it("counts unique keys and unread items", () => {
|
|
325
|
-
const summary = summarizeDedupedFeed([
|
|
326
|
-
{ dedupeKey: "a", read: false },
|
|
327
|
-
{ dedupeKey: "a", read: true },
|
|
328
|
-
{ dedupeKey: "b", read: false },
|
|
329
|
-
]);
|
|
330
|
-
|
|
331
|
-
expect(summary).toEqual({ uniqueKeys: 2, unread: 1 });
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
\`\`\`
|
|
335
|
-
|
|
336
|
-
### Expected output (FAIL)
|
|
337
|
-
|
|
338
|
-
\`\`\`bash
|
|
339
|
-
FAIL src/notificationFeed.test.ts
|
|
340
|
-
Error: Cannot find module '../notificationFeed' imported from src/notificationFeed.test.ts
|
|
341
|
-
\`\`\`
|
|
342
|
-
|
|
343
|
-
> **Annotation:** This test MUST fail before any production code is written.
|
|
344
|
-
|
|
345
|
-
### Iron Law verification
|
|
346
|
-
|
|
347
|
-
1. **Run** the test command (for example: \`pnpm vitest run src/notificationFeed.test.ts\`).
|
|
348
|
-
2. **Read output** and confirm the failure is due to the module/function not existing (or the function throwing “not implemented”), not due to a typo in assertions.
|
|
349
|
-
3. **Confirm** the failure reason matches the intentional gap: **missing implementation**, not a flaky environment or misconfigured test runner.
|
|
350
|
-
|
|
351
|
-
### Common mistakes to avoid
|
|
352
|
-
|
|
353
|
-
- “GREEN” that secretly imports a helper that already implements the behavior (that is skipping RED).
|
|
354
|
-
- Assertions that pass because the function returns \`undefined\` and the matcher is too loose.
|
|
355
|
-
|
|
356
|
-
### GREEN (minimal implementation to pass RED)
|
|
324
|
+
tdd: `### RED Evidence
|
|
357
325
|
|
|
358
|
-
|
|
359
|
-
|
|
326
|
+
| Slice | Test name | Command | Failure output summary |
|
|
327
|
+
| --- | --- | --- | --- |
|
|
328
|
+
| S-1 (event schema + dedupe) | counts unique keys and unread items | \`\`\`pnpm vitest run tests/unit/dedupe-feed.test.ts\`\`\` | Cannot find module '../notificationFeed' |
|
|
329
|
+
| S-2 (publisher outbox) | publishes event to outbox with dedupe key | \`\`\`pnpm vitest run tests/integration/publisher.test.ts\`\`\` | publishToOutbox is not a function |
|
|
330
|
+
| S-3 (client feed + fallback) | shows notification within 5s via SSE | \`\`\`pnpm playwright test tests/e2e/notification-feed.spec.ts\`\`\` | Element [data-testid="feed-item"] not found |
|
|
360
331
|
|
|
361
|
-
|
|
362
|
-
// Last write wins per dedupeKey (stable ordering: later items override earlier ones).
|
|
363
|
-
const latestReadByKey = new Map<string, boolean>();
|
|
332
|
+
### Acceptance Mapping
|
|
364
333
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
334
|
+
| Slice | Plan task ID | Spec criterion ID |
|
|
335
|
+
| --- | --- | --- |
|
|
336
|
+
| S-1 | T-1 | AC-1, AC-2 |
|
|
337
|
+
| S-2 | T-2 | AC-1 |
|
|
338
|
+
| S-3 | T-3 | AC-1, AC-2, AC-3 |
|
|
368
339
|
|
|
369
|
-
|
|
370
|
-
for (const read of latestReadByKey.values()) {
|
|
371
|
-
if (!read) unread += 1;
|
|
372
|
-
}
|
|
340
|
+
### Failure Analysis
|
|
373
341
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
342
|
+
| Slice | Expected missing behavior | Actual failure reason |
|
|
343
|
+
| --- | --- | --- |
|
|
344
|
+
| S-1 | notificationFeed module does not exist yet | Module import fails — correct: implementation missing |
|
|
345
|
+
| S-2 | publishToOutbox function not implemented | Function not found — correct: write path missing |
|
|
346
|
+
| S-3 | Feed UI not rendered, SSE not connected | DOM element missing — correct: client component not built |
|
|
377
347
|
|
|
378
|
-
###
|
|
348
|
+
### GREEN Evidence
|
|
379
349
|
|
|
380
|
-
|
|
350
|
+
- Full suite command: \`\`\`pnpm vitest run && pnpm playwright test\`\`\`
|
|
351
|
+
- Full suite result: 47 tests passed (3 new + 44 existing), 0 failed, 0 skipped
|
|
381
352
|
|
|
382
|
-
|
|
383
|
-
export type FeedItem = { dedupeKey: string; read: boolean };
|
|
353
|
+
### REFACTOR Notes
|
|
384
354
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
return latestReadByKey;
|
|
389
|
-
}
|
|
355
|
+
- What changed: Extracted \`\`\`mergeLatestByDedupeKey\`\`\` helper from inline loop in \`\`\`summarizeDedupedFeed\`\`\`; moved SSE reconnect logic into \`\`\`useSSEConnection\`\`\` hook.
|
|
356
|
+
- Why: Dedupe merge logic is reused by both publisher and client; reconnect logic was duplicated across components.
|
|
357
|
+
- Behavior preserved: Full suite re-run confirms 47/47 pass after refactor.
|
|
390
358
|
|
|
391
|
-
|
|
392
|
-
const latestReadByKey = mergeLatestByDedupeKey(items);
|
|
359
|
+
### Traceability
|
|
393
360
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
}
|
|
361
|
+
- Plan task IDs: T-1, T-2, T-3
|
|
362
|
+
- Spec criterion IDs: AC-1, AC-2, AC-3`,
|
|
363
|
+
review: `### Layer 1 Verdict
|
|
398
364
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
365
|
+
| Criterion | Verdict | Evidence |
|
|
366
|
+
| --- | --- | --- |
|
|
367
|
+
| AC-1: Delivery within 5s without reload | PASS | \`notification-feed.e2e.ts:44-88\` asserts SSE-to-UI timing under mock clock |
|
|
368
|
+
| AC-2: Dedupe — one visible item per key | PARTIAL | Unit tests cover publisher dedupe; UI merge path lacks test for race reordering (\`feedStore.test.ts\` missing case) |
|
|
369
|
+
| AC-3: Degraded mode + REST snapshot | PASS | \`NotificationsPanel.tsx:112-140\` renders banner + calls snapshot endpoint |
|
|
404
370
|
|
|
405
|
-
|
|
406
|
-
RUN v2.1.0 /Users/dev/app
|
|
371
|
+
### Layer 2 Findings
|
|
407
372
|
|
|
408
|
-
|
|
373
|
+
| ID | Severity | Category | Description | Status |
|
|
374
|
+
| --- | --- | --- | --- | --- |
|
|
375
|
+
| R-1 | Critical | correctness | Snapshot endpoint returns newest N rows but does not guarantee consistency with stream cursor — users can miss items between snapshot and subscribe. | open |
|
|
376
|
+
| R-2 | Important | performance | \`feedStore.merge()\` does full-array scan on every SSE event; O(n) per event where n is feed length. | open |
|
|
377
|
+
| R-3 | Suggestion | architecture | SSE reconnect logic duplicated across \`useNotifications\` and \`usePresence\`; extract shared hook. | open |
|
|
409
378
|
|
|
410
|
-
|
|
411
|
-
Tests 1 passed (1)
|
|
412
|
-
Tests: 1 passed.
|
|
413
|
-
\`\`\``,
|
|
414
|
-
review: `### Layer 1 — Spec compliance (per-criterion)
|
|
379
|
+
### Review Army Contract
|
|
415
380
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
| Delivery within 5s without reload | PASS | \`notification-feed.e2e.ts:44-88\` asserts SSE-to-UI timing under mock clock |
|
|
419
|
-
| Dedupe: one visible item per key | PARTIAL | Unit tests cover publisher dedupe; UI merge path lacks test for race reordering (\`feedStore.test.ts\` missing case) |
|
|
420
|
-
| Degraded mode + REST snapshot | PASS | \`NotificationsPanel.tsx:112-140\` renders banner + calls snapshot endpoint |
|
|
381
|
+
- See \`07-review-army.json\`
|
|
382
|
+
- Reconciliation summary: 1 duplicate collapsed (R-1 reported by spec-reviewer and code-reviewer), 0 conflicts
|
|
421
383
|
|
|
422
|
-
###
|
|
384
|
+
### Review Readiness Dashboard
|
|
423
385
|
|
|
424
|
-
-
|
|
425
|
-
-
|
|
426
|
-
-
|
|
427
|
-
-
|
|
428
|
-
-
|
|
429
|
-
1. Add cursor field + server-side reconciliation on subscribe (preferred).
|
|
430
|
-
2. Client-side “fetch since last seen id” merge pass (more complex, easier to get wrong).
|
|
431
|
-
3. Temporary mitigation: widen polling window when SSE is unhealthy (acceptable only as a short-term bridge).
|
|
386
|
+
- Layer 1 complete: yes (3/3 criteria)
|
|
387
|
+
- Layer 2 complete: yes (5 sections reviewed)
|
|
388
|
+
- Review army schema valid: yes
|
|
389
|
+
- Open critical blockers: 1 (R-1)
|
|
390
|
+
- Ship recommendation: BLOCKED until R-1 resolved
|
|
432
391
|
|
|
433
|
-
###
|
|
392
|
+
### Severity Summary
|
|
434
393
|
|
|
435
|
-
-
|
|
436
|
-
-
|
|
394
|
+
- Critical: 1
|
|
395
|
+
- Important: 1
|
|
396
|
+
- Suggestion: 1
|
|
437
397
|
|
|
438
|
-
###
|
|
398
|
+
### Final Verdict
|
|
439
399
|
|
|
440
|
-
-
|
|
441
|
-
- **PARTIAL** spec compliance items have a named owner and a test plan before ship.`,
|
|
400
|
+
- BLOCKED`,
|
|
442
401
|
ship: `### Preflight checklist (sample)
|
|
443
402
|
|
|
444
403
|
- tests ✅ (\`pnpm test\` green on main)
|
|
@@ -905,6 +905,7 @@ const PLAN = {
|
|
|
905
905
|
{ section: "Task List", required: true, validationRule: "Each task: ID, description, acceptance criterion link, verification command, and effort estimate (S/M/L)." },
|
|
906
906
|
{ section: "Acceptance Mapping", required: true, validationRule: "Every spec criterion is covered by at least one task." },
|
|
907
907
|
{ section: "Risk Assessment", required: false, validationRule: "If present: per-task or per-wave risk identification with likelihood, impact, and mitigation strategy." },
|
|
908
|
+
{ section: "Boundary Map", required: false, validationRule: "If present: per-wave or per-task interface contracts listing what each task produces (exports) and consumes (imports) from other tasks." },
|
|
908
909
|
{ section: "WAIT_FOR_CONFIRM", required: true, validationRule: "Explicit marker present. Status: pending until user approves." }
|
|
909
910
|
],
|
|
910
911
|
namedAntiPattern: {
|
|
@@ -1015,7 +1016,8 @@ const TDD = {
|
|
|
1015
1016
|
{ claim: "One broad integration test is enough.", reality: "Slice-level RED tests are required for precise failure signal." },
|
|
1016
1017
|
{ claim: "Refactor can be skipped for speed.", reality: "Skipping refactor accumulates debt and weakens maintainability." },
|
|
1017
1018
|
{ claim: "Only changed tests need to pass.", reality: "Full-suite checks are needed to detect regressions." },
|
|
1018
|
-
{ claim: "Traceability is implied by commit diff.", reality: "Explicit mapping avoids ambiguity in review and rollback." }
|
|
1019
|
+
{ claim: "Traceability is implied by commit diff.", reality: "Explicit mapping avoids ambiguity in review and rollback." },
|
|
1020
|
+
{ claim: "Tests written after implementation achieve the same goals.", reality: "Post-hoc tests confirm assumptions, not behavior. They test what you built, not what you should have built. TDD forces you to think about behavior before you have an implementation to be anchored by." }
|
|
1019
1021
|
],
|
|
1020
1022
|
redFlags: [
|
|
1021
1023
|
"No failing test output (RED missing)",
|
|
@@ -1033,14 +1035,39 @@ const TDD = {
|
|
|
1033
1035
|
{ name: "Failure-First Thinking", description: "The failing test IS the specification. Until you see the right failure, you do not understand what you are building. Wrong failures are information." },
|
|
1034
1036
|
{ name: "Minimal Viable Change", description: "The best implementation is the smallest one that passes all RED tests. Every extra line is risk. Resist the urge to 'improve while you are here.'" },
|
|
1035
1037
|
{ name: "Regression Paranoia", description: "Assume every change breaks something until the full suite proves otherwise. Partial test runs are lies of omission." },
|
|
1036
|
-
{ name: "Refactor-as-Hygiene", description: "Refactoring is not optional cleanup — it is the third leg of TDD. GREEN without REFACTOR accumulates mess. REFACTOR without GREEN breaks things." }
|
|
1038
|
+
{ name: "Refactor-as-Hygiene", description: "Refactoring is not optional cleanup — it is the third leg of TDD. GREEN without REFACTOR accumulates mess. REFACTOR without GREEN breaks things." },
|
|
1039
|
+
{ name: "Evidence Over Anecdote", description: "Every claim about test state must be backed by captured output. 'It passed' without terminal evidence is not evidence. 'I saw it fail' without the failure output is not RED. Capture commands, outputs, and results — not summaries from memory." },
|
|
1040
|
+
{ name: "Characterization First", description: "Before changing existing behavior, write characterization tests that capture current behavior as-is. These tests document what the system does today — even if that behavior is wrong. Only after the characterization suite is green do you add the new RED test for the desired change. This prevents accidental behavior destruction during refactoring." }
|
|
1041
|
+
],
|
|
1042
|
+
reviewSections: [
|
|
1043
|
+
{
|
|
1044
|
+
title: "RED Evidence Audit",
|
|
1045
|
+
evaluationPoints: [
|
|
1046
|
+
"Does every slice have a captured failing test output?",
|
|
1047
|
+
"Does each failure reason match the expected missing behavior (not a typo or config error)?",
|
|
1048
|
+
"Were tests written BEFORE any production code for that slice?",
|
|
1049
|
+
"Does each RED test assert observable behavior, not implementation details?",
|
|
1050
|
+
"Is there a test for each acceptance criterion mapped in the plan?"
|
|
1051
|
+
],
|
|
1052
|
+
stopGate: true
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
title: "GREEN/REFACTOR Audit",
|
|
1056
|
+
evaluationPoints: [
|
|
1057
|
+
"Does GREEN evidence show a FULL suite pass (not partial)?",
|
|
1058
|
+
"Is the GREEN implementation minimal — no features beyond what RED tests require?",
|
|
1059
|
+
"Does the REFACTOR step preserve all existing behavior (no new failures)?",
|
|
1060
|
+
"Are REFACTOR notes documented with rationale?",
|
|
1061
|
+
"Is traceability complete: every change links to plan task ID and spec criterion?"
|
|
1062
|
+
],
|
|
1063
|
+
stopGate: true
|
|
1064
|
+
}
|
|
1037
1065
|
],
|
|
1038
|
-
reviewSections: [],
|
|
1039
1066
|
completionStatus: ["DONE", "DONE_WITH_CONCERNS", "BLOCKED"],
|
|
1040
1067
|
crossStageTrace: {
|
|
1041
|
-
readsFrom: [".cclaw/artifacts/05-plan.md", ".cclaw/artifacts/04-spec.md"],
|
|
1068
|
+
readsFrom: [".cclaw/artifacts/05-plan.md", ".cclaw/artifacts/04-spec.md", ".cclaw/artifacts/03-design.md"],
|
|
1042
1069
|
writesTo: [".cclaw/artifacts/06-tdd.md"],
|
|
1043
|
-
traceabilityRule: "Every RED test traces to a plan task. Every GREEN change traces to a RED test. Every plan task traces to a spec criterion. Evidence chain must be unbroken."
|
|
1070
|
+
traceabilityRule: "Every RED test traces to a plan task. Every GREEN change traces to a RED test. Every plan task traces to a spec criterion. Design decisions inform test strategy. Evidence chain must be unbroken."
|
|
1044
1071
|
},
|
|
1045
1072
|
artifactValidation: [
|
|
1046
1073
|
{ section: "RED Evidence", required: true, validationRule: "Failing test output captured per slice." },
|
|
@@ -1048,8 +1075,14 @@ const TDD = {
|
|
|
1048
1075
|
{ section: "Failure Analysis", required: true, validationRule: "Failure reason matches expected missing behavior." },
|
|
1049
1076
|
{ section: "GREEN Evidence", required: true, validationRule: "Full suite pass output captured." },
|
|
1050
1077
|
{ section: "REFACTOR Notes", required: true, validationRule: "What changed, why, behavior preservation confirmed." },
|
|
1051
|
-
{ section: "Traceability", required: true, validationRule: "Plan task ID and spec criterion linked." }
|
|
1078
|
+
{ section: "Traceability", required: true, validationRule: "Plan task ID and spec criterion linked." },
|
|
1079
|
+
{ section: "Verification Ladder", required: false, validationRule: "If present: per-slice verification tier (static, command, behavioral, human) with evidence for highest tier reached." },
|
|
1080
|
+
{ section: "Coverage Targets", required: false, validationRule: "If present: per-module or per-code-type coverage thresholds with current values and measurement commands." }
|
|
1052
1081
|
],
|
|
1082
|
+
namedAntiPattern: {
|
|
1083
|
+
title: "Code Before Failing Test",
|
|
1084
|
+
description: "Production code written before a failing test is not TDD — it is guessing validated after the fact. Tests written after implementation confirm assumptions, not behavior. If you wrote code first, delete it and start with RED. Delete means delete — not 'keep as reference.' The failing test IS the specification."
|
|
1085
|
+
},
|
|
1053
1086
|
waveExecutionAllowed: true
|
|
1054
1087
|
};
|
|
1055
1088
|
// ---------------------------------------------------------------------------
|
|
@@ -1113,7 +1146,8 @@ const REVIEW = {
|
|
|
1113
1146
|
{ id: "review_layer2_performance", description: "Performance review completed." },
|
|
1114
1147
|
{ id: "review_layer2_architecture", description: "Architecture fit review completed." },
|
|
1115
1148
|
{ id: "review_severity_classified", description: "All findings are severity-tagged." },
|
|
1116
|
-
{ id: "review_criticals_resolved", description: "No unresolved critical blockers remain." }
|
|
1149
|
+
{ id: "review_criticals_resolved", description: "No unresolved critical blockers remain." },
|
|
1150
|
+
{ id: "review_army_json_valid", description: "07-review-army.json passes schema validation (validateReviewArmy)." }
|
|
1117
1151
|
],
|
|
1118
1152
|
requiredEvidence: [
|
|
1119
1153
|
"Artifact written to `.cclaw/artifacts/07-review.md`.",
|
|
@@ -1148,7 +1182,9 @@ const REVIEW = {
|
|
|
1148
1182
|
{ claim: "Passing tests mean spec compliance by default.", reality: "Tests can miss requirement mismatches; explicit spec review is mandatory." },
|
|
1149
1183
|
{ claim: "Severity labels are unnecessary.", reality: "Without severity, release decisions become inconsistent." },
|
|
1150
1184
|
{ claim: "Critical issues can be fixed after ship.", reality: "Critical blockers must be resolved before release handoff." },
|
|
1151
|
-
{ claim: "Security review is not needed for internal tools.", reality: "Internal tools become external surface area. Security is always in scope." }
|
|
1185
|
+
{ claim: "Security review is not needed for internal tools.", reality: "Internal tools become external surface area. Security is always in scope." },
|
|
1186
|
+
{ claim: "A quick skim is sufficient for small diffs.", reality: "Small diffs hide high-impact changes. A 3-line auth bypass is still critical. Every diff gets layered review regardless of size." },
|
|
1187
|
+
{ claim: "The author already reviewed their own code.", reality: "Self-review misses blind spots by definition. Independent review exists precisely because authors cannot objectively evaluate their own assumptions." }
|
|
1152
1188
|
],
|
|
1153
1189
|
redFlags: [
|
|
1154
1190
|
"No separate Layer 1/Layer 2 outcomes",
|
|
@@ -1245,7 +1281,7 @@ const REVIEW = {
|
|
|
1245
1281
|
completionStatus: ["APPROVED", "APPROVED_WITH_CONCERNS", "BLOCKED"],
|
|
1246
1282
|
crossStageTrace: {
|
|
1247
1283
|
readsFrom: [".cclaw/artifacts/06-tdd.md", ".cclaw/artifacts/04-spec.md", ".cclaw/artifacts/05-plan.md"],
|
|
1248
|
-
writesTo: [".cclaw/artifacts/07-review.md"],
|
|
1284
|
+
writesTo: [".cclaw/artifacts/07-review.md", ".cclaw/artifacts/07-review-army.json"],
|
|
1249
1285
|
traceabilityRule: "Review verdict must reference specific spec criteria and TDD evidence. Downstream ship stage must reference review verdict."
|
|
1250
1286
|
},
|
|
1251
1287
|
artifactValidation: [
|
|
@@ -1253,7 +1289,7 @@ const REVIEW = {
|
|
|
1253
1289
|
{ section: "Layer 2 Findings", required: true, validationRule: "Each finding has severity, description, and resolution status." },
|
|
1254
1290
|
{ section: "Review Army Contract", required: true, validationRule: "Structured findings include id/severity/confidence/fingerprint/reportedBy/status with dedup reconciliation summary." },
|
|
1255
1291
|
{ section: "Review Readiness Dashboard", required: true, validationRule: "At least 4 readiness checklist lines including blocker and recommendation status." },
|
|
1256
|
-
{ section: "Severity Summary", required: true, validationRule: "
|
|
1292
|
+
{ section: "Severity Summary", required: true, validationRule: "Per-severity count lines for critical, important, and suggestion buckets." },
|
|
1257
1293
|
{ section: "Final Verdict", required: true, validationRule: "Exactly one of: APPROVED, APPROVED_WITH_CONCERNS, BLOCKED." }
|
|
1258
1294
|
],
|
|
1259
1295
|
namedAntiPattern: {
|
|
@@ -278,6 +278,11 @@ Execution rule: complete and verify each wave before starting the next wave.
|
|
|
278
278
|
|---|---|---|---|---|
|
|
279
279
|
| | | | | |
|
|
280
280
|
|
|
281
|
+
## Boundary Map
|
|
282
|
+
| Task/Wave | Produces (exports) | Consumes (imports from) |
|
|
283
|
+
|---|---|---|
|
|
284
|
+
| | | |
|
|
285
|
+
|
|
281
286
|
## WAIT_FOR_CONFIRM
|
|
282
287
|
- Status: pending
|
|
283
288
|
- Confirmed by:
|
|
@@ -311,6 +316,17 @@ Execution rule: complete and verify each wave before starting the next wave.
|
|
|
311
316
|
## Traceability
|
|
312
317
|
- Plan task IDs:
|
|
313
318
|
- Spec criterion IDs:
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
## Verification Ladder
|
|
322
|
+
| Slice | Tier reached | Evidence |
|
|
323
|
+
|---|---|---|
|
|
324
|
+
| S-1 | | |
|
|
325
|
+
|
|
326
|
+
## Coverage Targets
|
|
327
|
+
| Code type | Target | Current | Command |
|
|
328
|
+
|---|---|---|---|
|
|
329
|
+
| | | | |
|
|
314
330
|
`,
|
|
315
331
|
"07-review.md": `# Review Artifact
|
|
316
332
|
|
|
@@ -359,8 +375,7 @@ Execution rule: complete and verify each wave before starting the next wave.
|
|
|
359
375
|
"confidence": 7,
|
|
360
376
|
"category": "correctness",
|
|
361
377
|
"location": {
|
|
362
|
-
"file": ""
|
|
363
|
-
"line": 0
|
|
378
|
+
"file": ""
|
|
364
379
|
},
|
|
365
380
|
"fingerprint": "",
|
|
366
381
|
"reportedBy": [],
|