cclaw-cli 0.5.10 → 0.5.11
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
|
@@ -242,7 +242,16 @@ export async function lintArtifact(projectRoot, stage) {
|
|
|
242
242
|
}
|
|
243
243
|
const raw = await fs.readFile(absFile, "utf8");
|
|
244
244
|
const sections = extractH2Sections(raw);
|
|
245
|
+
const isTrivialOverride = schema.trivialOverrideSections &&
|
|
246
|
+
schema.trivialOverrideSections.length > 0 &&
|
|
247
|
+
/trivial.change|mini.design|escape.hatch/iu.test(raw);
|
|
248
|
+
const overrideSet = isTrivialOverride
|
|
249
|
+
? new Set(schema.trivialOverrideSections.map((s) => normalizeHeadingTitle(s).toLowerCase()))
|
|
250
|
+
: null;
|
|
245
251
|
for (const v of schema.artifactValidation) {
|
|
252
|
+
const effectiveRequired = overrideSet
|
|
253
|
+
? overrideSet.has(normalizeHeadingTitle(v.section).toLowerCase()) ? true : false
|
|
254
|
+
: v.required;
|
|
246
255
|
const hasHeading = headingPresent(sections, v.section);
|
|
247
256
|
const body = hasHeading ? sectionBodyByName(sections, v.section) : null;
|
|
248
257
|
const validation = body === null
|
|
@@ -251,7 +260,7 @@ export async function lintArtifact(projectRoot, stage) {
|
|
|
251
260
|
const found = hasHeading && validation.ok;
|
|
252
261
|
findings.push({
|
|
253
262
|
section: v.section,
|
|
254
|
-
required:
|
|
263
|
+
required: effectiveRequired,
|
|
255
264
|
rule: v.validationRule,
|
|
256
265
|
found,
|
|
257
266
|
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,42 +234,39 @@ 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
|
-
|
|
218
|
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
-
|
|
222
|
-
|
|
223
|
-
**Criterion 2 — idempotency**
|
|
224
|
-
|
|
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
|
|
239
|
+
| ID | Criterion (observable/measurable/falsifiable) |
|
|
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. |
|
|
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. |
|
|
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. |
|
|
228
244
|
|
|
229
|
-
|
|
245
|
+
### Edge Cases
|
|
230
246
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
-
|
|
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. |
|
|
234
252
|
|
|
235
|
-
###
|
|
253
|
+
### Constraints and Assumptions
|
|
236
254
|
|
|
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.” |
|
|
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.
|
|
242
257
|
|
|
243
|
-
###
|
|
258
|
+
### Testability Map
|
|
244
259
|
|
|
245
|
-
|
|
246
|
-
|
|
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\` |
|
|
247
265
|
|
|
248
|
-
###
|
|
266
|
+
### Approval
|
|
249
267
|
|
|
250
|
-
|
|
268
|
+
- Approved by: user
|
|
269
|
+
- Date: 2026-04-14`,
|
|
251
270
|
plan: `### Task breakdown (sample)
|
|
252
271
|
|
|
253
272
|
| ID | Title | depends_on | acceptance_criteria | estimated_effort |
|
|
@@ -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,7 +714,8 @@ 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." }
|
|
709
719
|
],
|
|
710
720
|
reviewSections: [],
|
|
711
721
|
completionStatus: ["DONE", "DONE_WITH_CONCERNS", "BLOCKED"],
|
|
@@ -715,12 +725,17 @@ const SPEC = {
|
|
|
715
725
|
traceabilityRule: "Every acceptance criterion must trace to a design decision. Every downstream plan task must trace to a spec criterion."
|
|
716
726
|
},
|
|
717
727
|
artifactValidation: [
|
|
718
|
-
{ section: "Acceptance Criteria", required: true, validationRule: "Each criterion is observable, measurable, and falsifiable." },
|
|
728
|
+
{ 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
729
|
{ section: "Edge Cases", required: true, validationRule: "At least one boundary and one error condition per criterion." },
|
|
720
730
|
{ 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." },
|
|
731
|
+
{ 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." },
|
|
732
|
+
{ section: "Interface Contracts", required: false, validationRule: "If present: for each module boundary list produces (outputs) and consumes (inputs) with data types." },
|
|
722
733
|
{ section: "Approval", required: true, validationRule: "Explicit user approval marker present." }
|
|
723
|
-
]
|
|
734
|
+
],
|
|
735
|
+
namedAntiPattern: {
|
|
736
|
+
title: "Implementation Will Clarify Requirements",
|
|
737
|
+
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."
|
|
738
|
+
}
|
|
724
739
|
};
|
|
725
740
|
// ---------------------------------------------------------------------------
|
|
726
741
|
// PLAN
|
|
@@ -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,11 @@ export const ARTIFACT_TEMPLATES = {
|
|
|
206
221
|
|---|---|---|
|
|
207
222
|
| AC-1 | | |
|
|
208
223
|
|
|
224
|
+
## Interface Contracts
|
|
225
|
+
| Module | Produces | Consumes |
|
|
226
|
+
|---|---|---|
|
|
227
|
+
| | | |
|
|
228
|
+
|
|
209
229
|
## Approval
|
|
210
230
|
- Approved by:
|
|
211
231
|
- Date:
|