cclaw-cli 6.9.0 → 6.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/artifact-linter/plan.js +37 -0
- package/dist/artifact-linter/shared.d.ts +51 -2
- package/dist/artifact-linter/shared.js +52 -4
- package/dist/artifact-linter/tdd.d.ts +42 -1
- package/dist/artifact-linter/tdd.js +443 -31
- package/dist/artifact-linter.js +93 -2
- package/dist/content/core-agents.d.ts +14 -0
- package/dist/content/core-agents.js +35 -0
- package/dist/content/examples.js +9 -9
- package/dist/content/hooks.js +202 -4
- package/dist/content/reference-patterns.js +2 -2
- package/dist/content/skills.js +1 -1
- package/dist/content/stage-schema.js +0 -3
- package/dist/content/stages/tdd.js +22 -23
- package/dist/content/subagents.js +12 -3
- package/dist/content/templates.d.ts +6 -0
- package/dist/content/templates.js +42 -34
- package/dist/delegation.d.ts +119 -0
- package/dist/delegation.js +171 -10
- package/dist/install.js +9 -0
- package/dist/internal/advance-stage.js +15 -3
- package/dist/internal/plan-split-waves.d.ts +66 -0
- package/dist/internal/plan-split-waves.js +249 -0
- package/package.json +1 -1
|
@@ -207,6 +207,20 @@ export declare const CCLAW_AGENTS: readonly [{
|
|
|
207
207
|
readonly relatedStages: ["tdd"];
|
|
208
208
|
readonly returnSchema: AgentReturnSchema;
|
|
209
209
|
readonly body: string;
|
|
210
|
+
}, {
|
|
211
|
+
readonly name: "slice-documenter";
|
|
212
|
+
readonly description: "PARALLEL with slice-implementer in TDD GREEN. Writes per-slice prose summary to `<artifacts-dir>/tdd-slices/S-<id>.md`. Does NOT implement, does NOT write tests. Mandatory on discoveryMode=deep, opt-in elsewhere.";
|
|
213
|
+
readonly tools: ["Read", "Write", "Edit", "Grep", "Glob"];
|
|
214
|
+
readonly model: "fast";
|
|
215
|
+
readonly activation: "on-demand";
|
|
216
|
+
readonly relatedStages: ["tdd"];
|
|
217
|
+
readonly returnSchema: {
|
|
218
|
+
readonly statusField: "status";
|
|
219
|
+
readonly allowedStatuses: ["DONE", "DONE_WITH_CONCERNS", "NEEDS_CONTEXT", "BLOCKED"];
|
|
220
|
+
readonly requiredFields: ["status", "summaryMd", "learnings", "evidenceRefs", "blockers"];
|
|
221
|
+
readonly evidenceFields: ["summaryMd", "evidenceRefs"];
|
|
222
|
+
};
|
|
223
|
+
readonly body: string;
|
|
210
224
|
}, {
|
|
211
225
|
readonly name: "fixer";
|
|
212
226
|
readonly description: "ON-DEMAND fresh worker after review FAIL/PARTIAL evidence. Must fix only the cited criterion within explicit allowed files.";
|
|
@@ -544,6 +544,41 @@ export const CCLAW_AGENTS = [
|
|
|
544
544
|
"**Role boundary:** do not broaden scope, do not review your own work as final approval, and do not spawn subagents."
|
|
545
545
|
].join("\n")
|
|
546
546
|
},
|
|
547
|
+
{
|
|
548
|
+
name: "slice-documenter",
|
|
549
|
+
description: "PARALLEL with slice-implementer in TDD GREEN. Writes per-slice prose summary to `<artifacts-dir>/tdd-slices/S-<id>.md`. Does NOT implement, does NOT write tests. Mandatory on discoveryMode=deep, opt-in elsewhere.",
|
|
550
|
+
tools: ["Read", "Write", "Edit", "Grep", "Glob"],
|
|
551
|
+
model: "fast",
|
|
552
|
+
activation: "on-demand",
|
|
553
|
+
relatedStages: ["tdd"],
|
|
554
|
+
returnSchema: {
|
|
555
|
+
statusField: "status",
|
|
556
|
+
allowedStatuses: ["DONE", "DONE_WITH_CONCERNS", "NEEDS_CONTEXT", "BLOCKED"],
|
|
557
|
+
requiredFields: ["status", "summaryMd", "learnings", "evidenceRefs", "blockers"],
|
|
558
|
+
evidenceFields: ["summaryMd", "evidenceRefs"]
|
|
559
|
+
},
|
|
560
|
+
body: [
|
|
561
|
+
"You are a **slice-documenter** dispatched in PARALLEL with `slice-implementer` for the same slice.",
|
|
562
|
+
"",
|
|
563
|
+
"**Mission:** capture per-slice prose summary while production code is being written.",
|
|
564
|
+
"Because your only `claimedPath` is `<artifacts-dir>/tdd-slices/S-<id>.md` and the implementer's `claimedPaths` are production code, the file-overlap scheduler auto-allows the parallel dispatch.",
|
|
565
|
+
"",
|
|
566
|
+
"When invoked:",
|
|
567
|
+
"1. Read the active plan unit, acceptance criterion, and the failing RED test for this slice.",
|
|
568
|
+
"2. Write a thin per-slice file at `<artifacts-dir>/tdd-slices/S-<id>.md` with the headings:",
|
|
569
|
+
" - `# Slice S-<id>`",
|
|
570
|
+
" - `## Plan unit` (T-... pointer)",
|
|
571
|
+
" - `## Acceptance criteria` (AC-... ids)",
|
|
572
|
+
" - `## Why this slice`",
|
|
573
|
+
" - `## What was tested`",
|
|
574
|
+
" - `## What was implemented`",
|
|
575
|
+
" - `## REFACTOR notes`",
|
|
576
|
+
" - `## Learnings`",
|
|
577
|
+
"3. Return JSON: `{ status, summaryMd, learnings: string[], evidenceRefs: [\"<artifacts-dir>/tdd-slices/S-<id>.md\"], blockers: [] }`.",
|
|
578
|
+
"",
|
|
579
|
+
"**Forbidden:** edit `06-tdd.md`, test files, or production code. Edit ONLY your slice file."
|
|
580
|
+
].join("\n")
|
|
581
|
+
},
|
|
547
582
|
{
|
|
548
583
|
name: "fixer",
|
|
549
584
|
description: "ON-DEMAND fresh worker after review FAIL/PARTIAL evidence. Must fix only the cited criterion within explicit allowed files.",
|
package/dist/content/examples.js
CHANGED
|
@@ -36,10 +36,10 @@ export const BEHAVIOR_ANCHORS = [
|
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
stage: "tdd",
|
|
39
|
-
section: "RED
|
|
40
|
-
bad: "RED
|
|
41
|
-
good: "
|
|
42
|
-
ruleHint: "
|
|
39
|
+
section: "Watched-RED Proof",
|
|
40
|
+
bad: "Hand-edit Watched-RED Proof rows directly in the TDD artifact; the next lint overwrites the auto-rendered region and the slice still lacks a provable RED in delegation events.",
|
|
41
|
+
good: "Dispatch `test-author --slice S-1 --phase red`, then `slice-implementer --slice S-1 --phase green`. The linter auto-renders the slice cycle from `delegation-events.jsonl`.",
|
|
42
|
+
ruleHint: "RED/GREEN/REFACTOR transitions are recorded as `delegation-events.jsonl` rows via slice-tagged dispatches; the markdown tables are auto-rendered between `auto-start: tdd-slice-summary` markers from v6.11.0 onward."
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
stage: "review",
|
|
@@ -247,12 +247,12 @@ Plan is ready to execute after user confirmation.
|
|
|
247
247
|
| S-1 feed window | expected 30d window, got 7d |
|
|
248
248
|
| S-2 degraded banner | banner absent after forced disconnect |
|
|
249
249
|
|
|
250
|
-
## Acceptance
|
|
250
|
+
## Acceptance & Failure Map
|
|
251
251
|
|
|
252
|
-
| Slice | AC
|
|
253
|
-
| --- | --- |
|
|
254
|
-
| S-1 | AC-1 |
|
|
255
|
-
| S-2 | AC-3 |
|
|
252
|
+
| Slice | Source ID | AC ID | Expected behavior | RED-link |
|
|
253
|
+
| --- | --- | --- | --- | --- |
|
|
254
|
+
| S-1 | SRC-1 | AC-1 | feed window honors 30d cap | spanId:tdd-feed-window-red |
|
|
255
|
+
| S-2 | SRC-2 | AC-3 | degraded banner appears on disconnect | spanId:tdd-banner-red (auto-derived from delegation-events.jsonl) |
|
|
256
256
|
|
|
257
257
|
## GREEN
|
|
258
258
|
|
package/dist/content/hooks.js
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { RUNTIME_ROOT } from "../constants.js";
|
|
5
|
-
import { DELEGATION_DISPATCH_SURFACES, DELEGATION_DISPATCH_SURFACE_PATH_PREFIXES } from "../delegation.js";
|
|
5
|
+
import { DELEGATION_DISPATCH_SURFACES, DELEGATION_DISPATCH_SURFACE_PATH_PREFIXES, DELEGATION_PHASES } from "../delegation.js";
|
|
6
6
|
function resolveCliRuntimeForGeneratedHook() {
|
|
7
7
|
const here = fileURLToPath(import.meta.url);
|
|
8
8
|
// Vitest runs init/sync from src/ and expects helpers to execute the same
|
|
@@ -210,6 +210,8 @@ const TERMINAL = new Set(["completed", "failed", "waived", "stale"]);
|
|
|
210
210
|
const VALID_DISPATCH_SURFACES = ${JSON.stringify([...DELEGATION_DISPATCH_SURFACES])};
|
|
211
211
|
const VALID_DISPATCH_SURFACES_SET = new Set(VALID_DISPATCH_SURFACES);
|
|
212
212
|
const SURFACE_PATH_PREFIXES = ${JSON.stringify(DELEGATION_DISPATCH_SURFACE_PATH_PREFIXES)};
|
|
213
|
+
const VALID_DELEGATION_PHASES = ${JSON.stringify([...DELEGATION_PHASES])};
|
|
214
|
+
const VALID_DELEGATION_PHASES_SET = new Set(VALID_DELEGATION_PHASES);
|
|
213
215
|
const LEDGER_SCHEMA_VERSION = 3;
|
|
214
216
|
const FLOW_STATE_GUARD_REL_PATH = RUNTIME_ROOT + "/.flow-state.guard.json";
|
|
215
217
|
|
|
@@ -326,7 +328,7 @@ function hasPriorAck(events, args, runId) {
|
|
|
326
328
|
function usage() {
|
|
327
329
|
process.stderr.write([
|
|
328
330
|
"Usage:",
|
|
329
|
-
" node .cclaw/hooks/delegation-record.mjs --stage=<stage> --agent=<agent> --mode=<mandatory|proactive> --status=<scheduled|launched|acknowledged|completed|failed|waived|stale> --span-id=<id> [--dispatch-id=<id>] [--worker-run-id=<id>] [--dispatch-surface=<surface>] [--agent-definition-path=<path>] [--ack-ts=<iso>] [--launched-ts=<iso>] [--completed-ts=<iso>] [--evidence-ref=<ref>] [--waiver-reason=<text>] [--supersede=<prevSpanId>] [--allow-parallel] [--json]",
|
|
331
|
+
" node .cclaw/hooks/delegation-record.mjs --stage=<stage> --agent=<agent> --mode=<mandatory|proactive> --status=<scheduled|launched|acknowledged|completed|failed|waived|stale> --span-id=<id> [--dispatch-id=<id>] [--worker-run-id=<id>] [--dispatch-surface=<surface>] [--agent-definition-path=<path>] [--ack-ts=<iso>] [--launched-ts=<iso>] [--completed-ts=<iso>] [--evidence-ref=<ref>] [--waiver-reason=<text>] [--supersede=<prevSpanId>] [--allow-parallel] [--paths=<comma-separated>] [--override-cap=<int>] [--json]",
|
|
330
332
|
" node .cclaw/hooks/delegation-record.mjs --rerecord --span-id=<id> --dispatch-id=<id> --dispatch-surface=<surface> --agent-definition-path=<path> [--ack-ts=<iso>] [--completed-ts=<iso>] [--evidence-ref=<ref>] [--json]",
|
|
331
333
|
" node .cclaw/hooks/delegation-record.mjs --repair --span-id=<id> --repair-reason=\"<why>\" [--json]",
|
|
332
334
|
"",
|
|
@@ -339,6 +341,15 @@ function usage() {
|
|
|
339
341
|
"Dispatch dedup (v6.8.0):",
|
|
340
342
|
" --supersede=<prevSpanId> close the previous active span on this (stage, agent) as 'stale' before recording the new scheduled row",
|
|
341
343
|
" --allow-parallel record both spans as concurrent; new row is tagged allowParallel: true",
|
|
344
|
+
"",
|
|
345
|
+
"TDD parallel scheduler (v6.10.0):",
|
|
346
|
+
" --paths=<a,b,c> repo-relative paths the slice-implementer will edit; disjoint sets auto-promote to allowParallel, overlap throws DispatchOverlapError",
|
|
347
|
+
" --override-cap=<int> raise the slice-implementer fan-out cap once for this dispatch (default cap " + String(5) + ", env CCLAW_MAX_PARALLEL_SLICE_IMPLEMENTERS overrides globally)",
|
|
348
|
+
"",
|
|
349
|
+
"TDD slice phase tagging (v6.11.0):",
|
|
350
|
+
" --slice=<id> TDD slice identifier (e.g. S-1) used by the linter to auto-derive the Watched-RED + Vertical Slice Cycle tables.",
|
|
351
|
+
" --phase=<phase> one of " + VALID_DELEGATION_PHASES.join(", ") + ". Pair with --slice to record a TDD slice phase event.",
|
|
352
|
+
" --refactor-rationale=<t> required when --phase=refactor-deferred unless --evidence-ref carries the rationale text.",
|
|
342
353
|
""
|
|
343
354
|
].join("\\n") + "\\n");
|
|
344
355
|
}
|
|
@@ -440,6 +451,39 @@ function buildRow(args, status, runId, now, options) {
|
|
|
440
451
|
// Inherit the span's startTs from prior rows so monotonic validation
|
|
441
452
|
// can compare against the original schedule, not the row write time.
|
|
442
453
|
const startTs = (options && options.spanStartTs) || now;
|
|
454
|
+
// v6.10.0 (P1): claimedPaths from --paths=<comma-separated>. Empty
|
|
455
|
+
// arrays are dropped so the row stays compatible with v6.9 readers.
|
|
456
|
+
const claimedPathsRaw = typeof args.paths === "string" ? args.paths : "";
|
|
457
|
+
const claimedPaths = claimedPathsRaw
|
|
458
|
+
.split(",")
|
|
459
|
+
.map((value) => value.trim())
|
|
460
|
+
.filter((value) => value.length > 0);
|
|
461
|
+
// v6.11.0 (D1+D2): TDD slice tagging via --slice / --phase. Phase
|
|
462
|
+
// must be one of the canonical enum values; the inline validator
|
|
463
|
+
// rejects unknown phases before the row hits the ledger.
|
|
464
|
+
const sliceId =
|
|
465
|
+
typeof args.slice === "string" && args.slice.trim().length > 0
|
|
466
|
+
? args.slice.trim()
|
|
467
|
+
: undefined;
|
|
468
|
+
const phase =
|
|
469
|
+
typeof args.phase === "string" && args.phase.trim().length > 0
|
|
470
|
+
? args.phase.trim()
|
|
471
|
+
: undefined;
|
|
472
|
+
// v6.11.0 (D2): when --refactor-rationale is supplied it is folded
|
|
473
|
+
// into evidenceRefs[0] so the linter (which reads evidenceRefs only)
|
|
474
|
+
// can surface the rationale without touching new fields. The user
|
|
475
|
+
// may also pass --evidence-ref containing the rationale text.
|
|
476
|
+
let resolvedEvidenceRefs = normalizeEvidenceRefs(args);
|
|
477
|
+
if (
|
|
478
|
+
phase === "refactor-deferred" &&
|
|
479
|
+
typeof args["refactor-rationale"] === "string" &&
|
|
480
|
+
args["refactor-rationale"].trim().length > 0
|
|
481
|
+
) {
|
|
482
|
+
const rationale = args["refactor-rationale"].trim();
|
|
483
|
+
if (!resolvedEvidenceRefs.includes(rationale)) {
|
|
484
|
+
resolvedEvidenceRefs = [rationale, ...resolvedEvidenceRefs];
|
|
485
|
+
}
|
|
486
|
+
}
|
|
443
487
|
return {
|
|
444
488
|
stage: args.stage,
|
|
445
489
|
agent: args.agent,
|
|
@@ -452,7 +496,7 @@ function buildRow(args, status, runId, now, options) {
|
|
|
452
496
|
agentDefinitionPath: args["agent-definition-path"],
|
|
453
497
|
fulfillmentMode,
|
|
454
498
|
waiverReason: args["waiver-reason"],
|
|
455
|
-
evidenceRefs:
|
|
499
|
+
evidenceRefs: resolvedEvidenceRefs,
|
|
456
500
|
runId,
|
|
457
501
|
startTs,
|
|
458
502
|
ts: now,
|
|
@@ -461,7 +505,10 @@ function buildRow(args, status, runId, now, options) {
|
|
|
461
505
|
completedTs: args["completed-ts"] || (status === "completed" ? now : undefined),
|
|
462
506
|
endTs: TERMINAL.has(status) ? now : undefined,
|
|
463
507
|
schemaVersion: LEDGER_SCHEMA_VERSION,
|
|
464
|
-
allowParallel: args["allow-parallel"] === true ? true : undefined
|
|
508
|
+
allowParallel: args["allow-parallel"] === true ? true : undefined,
|
|
509
|
+
claimedPaths: claimedPaths.length > 0 ? claimedPaths : undefined,
|
|
510
|
+
sliceId,
|
|
511
|
+
phase
|
|
465
512
|
};
|
|
466
513
|
}
|
|
467
514
|
|
|
@@ -502,6 +549,102 @@ function findActiveSpanForPairInline(stage, agent, runId, entries) {
|
|
|
502
549
|
return null;
|
|
503
550
|
}
|
|
504
551
|
|
|
552
|
+
// keep in sync with computeActiveSubagents in src/delegation.ts
|
|
553
|
+
function computeActiveSubagentsInline(entries) {
|
|
554
|
+
const ACTIVE_STATUSES = new Set(["scheduled", "launched", "acknowledged"]);
|
|
555
|
+
const effectiveTs = (entry) =>
|
|
556
|
+
entry.completedTs || entry.ackTs || entry.launchedTs || entry.endTs || entry.startTs || entry.ts || "";
|
|
557
|
+
const latestBySpan = new Map();
|
|
558
|
+
for (const entry of entries) {
|
|
559
|
+
if (!entry || typeof entry !== "object") continue;
|
|
560
|
+
if (typeof entry.spanId !== "string" || entry.spanId.length === 0) continue;
|
|
561
|
+
const existing = latestBySpan.get(entry.spanId);
|
|
562
|
+
if (!existing || effectiveTs(entry) >= effectiveTs(existing)) {
|
|
563
|
+
latestBySpan.set(entry.spanId, entry);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
const active = [];
|
|
567
|
+
for (const entry of latestBySpan.values()) {
|
|
568
|
+
if (ACTIVE_STATUSES.has(entry.status)) active.push(entry);
|
|
569
|
+
}
|
|
570
|
+
return active;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// keep in sync with validateFileOverlap in src/delegation.ts
|
|
574
|
+
function validateFileOverlapInline(stamped, activeEntries) {
|
|
575
|
+
if (stamped.agent !== "slice-implementer" || stamped.stage !== "tdd") {
|
|
576
|
+
return { autoParallel: false, conflict: null };
|
|
577
|
+
}
|
|
578
|
+
const newPaths = Array.isArray(stamped.claimedPaths) ? stamped.claimedPaths : [];
|
|
579
|
+
if (newPaths.length === 0) {
|
|
580
|
+
return { autoParallel: false, conflict: null };
|
|
581
|
+
}
|
|
582
|
+
const sameLane = activeEntries.filter(
|
|
583
|
+
(entry) =>
|
|
584
|
+
entry.stage === stamped.stage &&
|
|
585
|
+
entry.agent === stamped.agent &&
|
|
586
|
+
entry.spanId !== stamped.spanId
|
|
587
|
+
);
|
|
588
|
+
if (sameLane.length === 0) {
|
|
589
|
+
return { autoParallel: true, conflict: null };
|
|
590
|
+
}
|
|
591
|
+
for (const existing of sameLane) {
|
|
592
|
+
const existingPaths = Array.isArray(existing.claimedPaths) ? existing.claimedPaths : [];
|
|
593
|
+
if (existingPaths.length === 0) {
|
|
594
|
+
return { autoParallel: false, conflict: null };
|
|
595
|
+
}
|
|
596
|
+
const overlap = newPaths.filter((p) => existingPaths.includes(p));
|
|
597
|
+
if (overlap.length > 0) {
|
|
598
|
+
return {
|
|
599
|
+
autoParallel: false,
|
|
600
|
+
conflict: {
|
|
601
|
+
existingSpanId: existing.spanId || "unknown",
|
|
602
|
+
newSpanId: stamped.spanId || "unknown",
|
|
603
|
+
pair: { stage: stamped.stage, agent: stamped.agent },
|
|
604
|
+
conflictingPaths: overlap
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return { autoParallel: true, conflict: null };
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
const MAX_PARALLEL_SLICE_IMPLEMENTERS_INLINE = 5;
|
|
613
|
+
|
|
614
|
+
function readMaxParallelOverrideFromEnvInline() {
|
|
615
|
+
const raw = process.env.CCLAW_MAX_PARALLEL_SLICE_IMPLEMENTERS;
|
|
616
|
+
if (typeof raw !== "string" || raw.trim().length === 0) return null;
|
|
617
|
+
const parsed = Number(raw);
|
|
618
|
+
if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed < 1) return null;
|
|
619
|
+
return parsed;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// keep in sync with validateFanOutCap in src/delegation.ts
|
|
623
|
+
function validateFanOutCapInline(stamped, activeEntries, override) {
|
|
624
|
+
if (stamped.agent !== "slice-implementer" || stamped.stage !== "tdd") return null;
|
|
625
|
+
if (stamped.status !== "scheduled") return null;
|
|
626
|
+
let cap;
|
|
627
|
+
if (override !== null && override !== undefined && Number.isInteger(override) && override >= 1) {
|
|
628
|
+
cap = override;
|
|
629
|
+
} else {
|
|
630
|
+
cap = readMaxParallelOverrideFromEnvInline() || MAX_PARALLEL_SLICE_IMPLEMENTERS_INLINE;
|
|
631
|
+
}
|
|
632
|
+
const sameLaneActive = activeEntries.filter(
|
|
633
|
+
(entry) =>
|
|
634
|
+
entry.stage === stamped.stage &&
|
|
635
|
+
entry.agent === stamped.agent &&
|
|
636
|
+
entry.spanId !== stamped.spanId
|
|
637
|
+
);
|
|
638
|
+
if (sameLaneActive.length + 1 > cap) {
|
|
639
|
+
return {
|
|
640
|
+
cap,
|
|
641
|
+
active: sameLaneActive.length,
|
|
642
|
+
pair: { stage: stamped.stage, agent: stamped.agent }
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
|
|
505
648
|
function enforceDispatchDedupInline(stamped, priorEntries, args) {
|
|
506
649
|
if (stamped.status !== "scheduled") return null;
|
|
507
650
|
if (args["allow-parallel"] === true) return null;
|
|
@@ -906,6 +1049,36 @@ async function main() {
|
|
|
906
1049
|
return;
|
|
907
1050
|
}
|
|
908
1051
|
|
|
1052
|
+
// v6.11.0 (D2) — TDD slice phase tagging validation. --phase is
|
|
1053
|
+
// strictly enum-bound; --slice must be a non-empty string when
|
|
1054
|
+
// provided; --phase=refactor-deferred requires either an explicit
|
|
1055
|
+
// --refactor-rationale or an --evidence-ref with rationale text so
|
|
1056
|
+
// the linter has something to render.
|
|
1057
|
+
if (args.phase !== undefined && !VALID_DELEGATION_PHASES_SET.has(args.phase)) {
|
|
1058
|
+
problems.push("invalid --phase (allowed: " + VALID_DELEGATION_PHASES.join(", ") + ")");
|
|
1059
|
+
emitProblems(problems, json, 2);
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
if (args.slice !== undefined && (typeof args.slice !== "string" || args.slice.trim().length === 0)) {
|
|
1063
|
+
problems.push("--slice requires a non-empty value");
|
|
1064
|
+
emitProblems(problems, json, 2);
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
if (args.phase === "refactor-deferred") {
|
|
1068
|
+
const rationaleProvided =
|
|
1069
|
+
typeof args["refactor-rationale"] === "string" && args["refactor-rationale"].trim().length > 0;
|
|
1070
|
+
const evidenceProvided =
|
|
1071
|
+
(typeof args["evidence-ref"] === "string" && args["evidence-ref"].trim().length > 0) ||
|
|
1072
|
+
(Array.isArray(args["evidence-refs"]) && args["evidence-refs"].some(
|
|
1073
|
+
(ref) => typeof ref === "string" && ref.trim().length > 0
|
|
1074
|
+
));
|
|
1075
|
+
if (!rationaleProvided && !evidenceProvided) {
|
|
1076
|
+
problems.push("--phase=refactor-deferred requires --refactor-rationale=<text> or --evidence-ref=<text>");
|
|
1077
|
+
emitProblems(problems, json, 2);
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
909
1082
|
if (args.status === "completed" && args["dispatch-surface"] !== "role-switch") {
|
|
910
1083
|
for (const key of ["dispatch-id", "dispatch-surface", "agent-definition-path"]) {
|
|
911
1084
|
if (!args[key]) problems.push("completed isolated/generic status requires --" + key);
|
|
@@ -992,6 +1165,31 @@ async function main() {
|
|
|
992
1165
|
emitErrorJson("delegation_timestamp_non_monotonic", violation, json);
|
|
993
1166
|
return;
|
|
994
1167
|
}
|
|
1168
|
+
|
|
1169
|
+
// v6.10.0 (P1+P2): file-overlap scheduler + fan-out cap. Run before
|
|
1170
|
+
// the legacy dispatch dedup so disjoint claimedPaths can auto-promote
|
|
1171
|
+
// to allowParallel and bypass the duplicate guard.
|
|
1172
|
+
if (status === "scheduled") {
|
|
1173
|
+
const sameRunPrior = priorLedger.filter((entry) => entry.runId === runId);
|
|
1174
|
+
const activeForRun = computeActiveSubagentsInline(sameRunPrior);
|
|
1175
|
+
const overlap = validateFileOverlapInline(clean, activeForRun);
|
|
1176
|
+
if (overlap.conflict) {
|
|
1177
|
+
emitErrorJson("dispatch_overlap", overlap.conflict, json);
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
if (overlap.autoParallel && clean.allowParallel !== true) {
|
|
1181
|
+
clean.allowParallel = true;
|
|
1182
|
+
args["allow-parallel"] = true;
|
|
1183
|
+
event.allowParallel = true;
|
|
1184
|
+
}
|
|
1185
|
+
const overrideRaw = typeof args["override-cap"] === "string" ? args["override-cap"] : null;
|
|
1186
|
+
const override = overrideRaw !== null ? Number(overrideRaw) : null;
|
|
1187
|
+
const capViolation = validateFanOutCapInline(clean, activeForRun, override);
|
|
1188
|
+
if (capViolation) {
|
|
1189
|
+
emitErrorJson("dispatch_cap", capViolation, json);
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
995
1193
|
const dedupViolation = enforceDispatchDedupInline(clean, priorLedger, args);
|
|
996
1194
|
if (dedupViolation) {
|
|
997
1195
|
if (dedupViolation.kind === "supersede") {
|
|
@@ -36,7 +36,7 @@ export const REFERENCE_PATTERNS = [
|
|
|
36
36
|
"Discover tests and affected contracts before opening a RED vertical slice.",
|
|
37
37
|
"Map the slice to the active source item before editing production code."
|
|
38
38
|
],
|
|
39
|
-
artifactSections: ["Test Discovery", "System-Wide Impact Check", "Acceptance
|
|
39
|
+
artifactSections: ["Test Discovery", "System-Wide Impact Check", "Acceptance & Failure Map"]
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
stage: "review",
|
|
@@ -143,7 +143,7 @@ export const REFERENCE_PATTERNS = [
|
|
|
143
143
|
"Open one packet as one vertical slice; do not mix unrelated packet evidence.",
|
|
144
144
|
"Close packet only when RED, GREEN, REFACTOR, and verification evidence align."
|
|
145
145
|
],
|
|
146
|
-
artifactSections: ["Acceptance
|
|
146
|
+
artifactSections: ["Acceptance & Failure Map", "RED Evidence", "GREEN Evidence", "REFACTOR Notes"]
|
|
147
147
|
}
|
|
148
148
|
]
|
|
149
149
|
},
|
package/dist/content/skills.js
CHANGED
|
@@ -102,7 +102,7 @@ Any "the failure is real" claim (failing test, broken build, regression catch, d
|
|
|
102
102
|
|
|
103
103
|
\`proof: <iso-ts> | <observed snippet — first 200 chars> | source: <command or log path>\`
|
|
104
104
|
|
|
105
|
-
For TDD specifically, this is the watched-RED proof and is required per new test before \`stage-complete\` accepts the stage.
|
|
105
|
+
For TDD specifically, this is the watched-RED proof and is required per new test before \`stage-complete\` accepts the stage. From v6.11.0 onward, the controller dispatches \`test-author --slice S-<id> --phase red\` (and later \`slice-implementer --phase green\`, \`--phase refactor\` or \`--phase refactor-deferred --refactor-rationale "<why>"\`) and the linter auto-derives the \`Watched-RED Proof\` and \`Vertical Slice Cycle\` tables in \`06-tdd.md\` from \`.cclaw/state/delegation-events.jsonl\`. Do NOT hand-edit those tables. v6.10.0 sidecar (\`06-tdd-slices.jsonl\`) is removed; \`cclaw-cli sync\` cleans the file from existing installs.
|
|
106
106
|
`;
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
@@ -357,15 +357,12 @@ const REQUIRED_ARTIFACT_SECTIONS = {
|
|
|
357
357
|
],
|
|
358
358
|
plan: ["Task List", "Dependency Batches", "Acceptance Mapping", "Execution Posture", "WAIT_FOR_CONFIRM"],
|
|
359
359
|
tdd: [
|
|
360
|
-
"Test Discovery",
|
|
361
360
|
"System-Wide Impact Check",
|
|
362
361
|
"RED Evidence",
|
|
363
362
|
"GREEN Evidence",
|
|
364
363
|
"REFACTOR Notes",
|
|
365
364
|
"Traceability",
|
|
366
365
|
"Iron Law Acknowledgement",
|
|
367
|
-
"Watched-RED Proof",
|
|
368
|
-
"Vertical Slice Cycle",
|
|
369
366
|
"Verification Ladder"
|
|
370
367
|
],
|
|
371
368
|
review: ["Review Evidence Scope", "Changed-File Coverage", "Layer 1 Verdict", "Review Findings Contract", "Severity Summary", "Final Verdict"],
|
|
@@ -42,14 +42,14 @@ export const TDD = {
|
|
|
42
42
|
"Discover the test surface — inspect existing tests, fixtures, helpers, test commands, and nearby assertions before authoring RED. Reuse the local test style unless the slice genuinely needs a new pattern.",
|
|
43
43
|
"Run a system-wide impact check — name callbacks, state transitions, interfaces, schemas, CLI/config/API contracts, persistence, or event boundaries that this slice can affect. Add RED coverage for each affected public contract or record why it is out of scope.",
|
|
44
44
|
"Source/test preflight — before production edits, classify planned paths using test-path patterns; verify the RED touches a test path and the GREEN touches only source paths needed for the failing behavior.",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"Continue the same `test-author` delegation intent for GREEN — minimal implementation plus full-suite GREEN evidence. Set `CCLAW_ACTIVE_AGENT=tdd-green` when the harness supports phase labels.",
|
|
45
|
+
"Use the mandatory `test-author` delegation for RED — after discovery and impact check, dispatch with `--slice S-<id> --phase red`. Produce failing behavior tests only (no production edits) and let the harness record the dispatch via the generated `delegation-record` hook. Set `CCLAW_ACTIVE_AGENT=tdd-red` when the harness supports phase labels.",
|
|
46
|
+
"RED: do NOT hand-edit `## Watched-RED Proof`, `## Vertical Slice Cycle`, or `## RED Evidence` markdown tables. The linter auto-renders them from `delegation-events.jsonl` slice phase rows; manual edits inside the auto-render markers are overwritten on the next lint.",
|
|
47
|
+
"Dispatch the `slice-implementer` for GREEN with `--slice S-<id> --phase green` and explicit `--paths` so the file-overlap scheduler can auto-allow parallel slices. Attach an evidence ref (test path, span ref, or pasted-output pointer) so the Vertical Slice Cycle row is well-formed. Set `CCLAW_ACTIVE_AGENT=tdd-green` when the harness supports phase labels.",
|
|
49
48
|
"GREEN: Run full suite — execute ALL tests, not just the ones you wrote. The full suite must be GREEN.",
|
|
50
49
|
"GREEN: Verify no regressions — if any existing test breaks, fix the regression before proceeding.",
|
|
51
50
|
"Run verification-before-completion discipline for the slice — capture a fresh test command, explicit PASS/FAIL status, and a config-aware ref (commit SHA when VCS is present/required, or no-vcs attestation when allowed).",
|
|
52
|
-
"REFACTOR:
|
|
51
|
+
"REFACTOR: re-dispatch the `slice-implementer` (or `test-author`) with `--phase refactor` once GREEN holds, OR `--phase refactor-deferred --refactor-rationale \"<why>\"` to close the slice without a refactor pass. Both options are recorded as a delegation event; the linter accepts either as REFACTOR coverage. Set `CCLAW_ACTIVE_AGENT=tdd-refactor` when the harness supports phase labels.",
|
|
52
|
+
"DOC (parallel): when `discoveryMode === \"deep\"` is active, dispatch `slice-documenter --slice S-<id> --phase doc` IN PARALLEL with `slice-implementer` for the same slice. The documenter only writes `<artifacts-dir>/tdd-slices/S-<id>.md`, so its `--paths` are disjoint from the implementer's production code and the file-overlap scheduler auto-allows the parallel dispatch.",
|
|
53
53
|
"Record evidence — capture test discovery, system-wide impact check, RED failure, GREEN output, and REFACTOR notes in the TDD artifact. When logging a `green` row, attach the closed acceptance-criterion IDs in `acIds` so Ralph Loop status counts them.",
|
|
54
54
|
"Annotate traceability — link to the active track's source: plan task ID + spec criterion on standard/medium, or spec acceptance item / bug reproduction slice on quick.",
|
|
55
55
|
"**Boundary with review (do NOT escalate single-slice findings to whole-diff review).** `tdd.Per-Slice Review` OWNS severity-classified findings WITHIN one slice (correctness, edge cases, regression). `review` OWNS whole-diff Layer 1 (spec compliance) plus Layer 2 (cross-slice integration, security sweep, dependency/version audit, observability). When a single-slice finding genuinely needs whole-diff escalation, surface it in `06-tdd.md > Per-Slice Review` first; review will cite it (not re-classify) and the cross-artifact-duplication linter requires matching severity/disposition.",
|
|
@@ -58,10 +58,11 @@ export const TDD = {
|
|
|
58
58
|
],
|
|
59
59
|
interactionProtocol: [
|
|
60
60
|
"Pick one vertical slice at a time: source item, RED test, GREEN implementation, REFACTOR, and verification evidence move together.",
|
|
61
|
-
"Slice implementers are sequential by default. Parallel implementers are allowed only when (a) lanes touch non-overlapping files
|
|
62
|
-
"Controller owns orchestration
|
|
61
|
+
"Slice implementers are sequential by default. Parallel implementers are allowed only when (a) lanes touch non-overlapping files (the file-overlap scheduler auto-allows parallel when `--paths` are disjoint), and (b) an `integration-overseer` is dispatched after the parallel lanes and writes cohesion-evidence into the artifact before the gate is marked passed.",
|
|
62
|
+
"Controller owns orchestration. For each slice S-<id>, dispatch in this order: (1) `test-author --slice S-<id> --phase red` (RED-only, no production edits), (2) `slice-implementer --slice S-<id> --phase green --paths <comma-separated>` for GREEN, (3) re-dispatch `--phase refactor` or `--phase refactor-deferred --refactor-rationale \"<why>\"` to close REFACTOR. Each dispatch records a row in `delegation-events.jsonl` and the linter auto-derives the Watched-RED + Vertical Slice Cycle tables from those rows. Do NOT hand-edit those tables.",
|
|
63
63
|
"Before writing RED tests, discover relevant existing tests and commands so the new test extends the suite instead of fighting it.",
|
|
64
64
|
"Before implementation, perform a system-wide impact check across callbacks, state, interfaces, schemas, and external contracts touched by the slice.",
|
|
65
|
+
"Slice-documenter (Phase C, opt-in / mandatory on discoveryMode=deep): in parallel with `slice-implementer --phase green`, dispatch `slice-documenter --slice S-<id> --phase doc` whose only `claimedPaths` is `<artifacts-dir>/tdd-slices/S-<id>.md`. The two dispatches run concurrently because their paths are disjoint. The documenter writes per-slice prose so the main `06-tdd.md` stays thin.",
|
|
65
66
|
"Run source/test preflight using configured TDD path patterns where feasible; if path classification is impossible (generated files, non-file side effect), record why.",
|
|
66
67
|
"Write behavior-focused tests before changing implementation (RED).",
|
|
67
68
|
"Capture and store failing output as RED evidence.",
|
|
@@ -104,20 +105,20 @@ export const TDD = {
|
|
|
104
105
|
{ id: "tdd_docs_drift_check", description: "When public API/config/CLI surfaces change, docs drift is addressed via a completed doc-updater pass." }
|
|
105
106
|
],
|
|
106
107
|
requiredEvidence: [
|
|
107
|
-
"Artifact updated at `.cclaw/artifacts/06-tdd.md` with
|
|
108
|
+
"Artifact updated at `.cclaw/artifacts/06-tdd.md` with System-Wide Impact Check, Acceptance & Failure Map, REFACTOR Notes, Iron Law Acknowledgement, Verification Ladder, and Learnings.",
|
|
108
109
|
"Relevant existing test files, helpers, fixtures, and exact commands identified before RED.",
|
|
109
110
|
"Callbacks, state transitions, interfaces, schemas, and contracts checked for impact before implementation.",
|
|
110
111
|
"Execution posture and vertical-slice RED/GREEN/REFACTOR checkpoint plan recorded, including commit boundaries when the repo workflow supports them.",
|
|
111
|
-
"
|
|
112
|
-
"
|
|
112
|
+
"RED observability: a `phase=red` event in `delegation-events.jsonl` for each slice with non-empty evidenceRefs (test path, span ref, or pasted-output pointer). Legacy `## Watched-RED Proof` / `## RED Evidence` markdown tables remain valid as a fallback.",
|
|
113
|
+
"GREEN observability: a `phase=green` event in `delegation-events.jsonl` per slice whose `completedTs` >= the matching `phase=red` `completedTs` and whose evidenceRefs name the failing-now-passing test. Legacy `## GREEN Evidence` block remains valid as a fallback.",
|
|
114
|
+
"REFACTOR observability: per slice, a `phase=refactor` event OR a `phase=refactor-deferred` event whose evidenceRefs / refactor rationale captures why refactor was deferred.",
|
|
113
115
|
"Fresh verification evidence recorded with command, PASS/FAIL status, and commit SHA or no-VCS reason plus content/artifact hash before completion.",
|
|
114
116
|
"Iron Law Acknowledgement section explicitly states `Acknowledged: yes`.",
|
|
115
|
-
"Watched-RED Proof includes at least one populated row with an ISO timestamp.",
|
|
116
|
-
"Vertical Slice Cycle records RED, GREEN, and REFACTOR per active slice.",
|
|
117
117
|
"Acceptance mapping documented.",
|
|
118
118
|
"Failure reason analysis recorded.",
|
|
119
119
|
"Refactor rationale captured.",
|
|
120
|
-
"Traceability to task identifier is documented."
|
|
120
|
+
"Traceability to task identifier is documented.",
|
|
121
|
+
"On discoveryMode=deep: per slice, a `phase=doc` event from `slice-documenter` whose evidenceRefs name `<artifacts-dir>/tdd-slices/S-<id>.md`. On other discovery modes the documenter event is advisory."
|
|
121
122
|
],
|
|
122
123
|
inputs: ["approved plan slice", "spec acceptance criterion", "test harness configuration", "coding standards and constraints"],
|
|
123
124
|
requiredContext: ["plan artifact", "spec artifact", "existing test patterns", "affected contracts and state boundaries"],
|
|
@@ -156,18 +157,16 @@ export const TDD = {
|
|
|
156
157
|
},
|
|
157
158
|
artifactValidation: [
|
|
158
159
|
{ section: "Upstream Handoff", required: false, validationRule: "Summarizes plan/spec/design decisions, constraints, open questions, and explicit drift before RED work." },
|
|
159
|
-
{ section: "Test Discovery", required:
|
|
160
|
+
{ section: "Test Discovery", required: false, validationRule: "Overall narrative for how the stage discovered the existing test surface. Per-slice details live under `tdd-slices/S-<id>.md` from v6.11.0; the `## Test Discovery` heading is optional/advisory." },
|
|
160
161
|
{ section: "System-Wide Impact Check", required: true, validationRule: "Before implementation: names affected callbacks, state transitions, interfaces, schemas, public APIs/config/CLI, persistence, or event contracts, with coverage or explicit out-of-scope notes." },
|
|
161
|
-
{ section: "
|
|
162
|
-
{ section: "
|
|
163
|
-
{ section: "
|
|
164
|
-
{ section: "Failure Analysis", required: false, validationRule: "Failure reason matches expected missing behavior." },
|
|
165
|
-
{ section: "GREEN Evidence", required: true, validationRule: "Full suite pass output captured." },
|
|
162
|
+
{ section: "RED Evidence", required: true, validationRule: "Failing test output per slice. From v6.11.0 this section is auto-satisfied by a `phase=red` event in `delegation-events.jsonl` with non-empty evidenceRefs; the markdown block remains required as a legacy fallback when phase events are absent." },
|
|
163
|
+
{ section: "Acceptance & Failure Map", required: false, validationRule: "Each slice row carries Source ID, AC ID, expected behavior, and a RED-link (delegation spanId or evidence path). From v6.11.0 the column is auto-derivable from `phase=red` events." },
|
|
164
|
+
{ section: "GREEN Evidence", required: true, validationRule: "Full suite pass output. From v6.11.0 this section is auto-satisfied by a `phase=green` event in `delegation-events.jsonl` with non-empty evidenceRefs; the markdown block remains required as a legacy fallback when phase events are absent." },
|
|
166
165
|
{ section: "REFACTOR Notes", required: true, validationRule: "What changed, why, behavior preservation confirmed." },
|
|
167
166
|
{ section: "Traceability", required: true, validationRule: "Plan task ID and spec criterion linked." },
|
|
168
167
|
{ section: "Iron Law Acknowledgement", required: true, validationRule: "Must include `Acknowledged: yes` and list exceptions (or `None`)." },
|
|
169
|
-
{ section: "Watched-RED Proof", required:
|
|
170
|
-
{ section: "Vertical Slice Cycle", required:
|
|
168
|
+
{ section: "Watched-RED Proof", required: false, validationRule: "From v6.11.0 the Watched-RED summary is auto-rendered from `delegation-events.jsonl` slice phase events (see auto-start: tdd-slice-summary marker). Legacy markdown tables continue to validate via the fallback path." },
|
|
169
|
+
{ section: "Vertical Slice Cycle", required: false, validationRule: "From v6.11.0 the Vertical Slice Cycle table is auto-rendered between `auto-start: tdd-slice-summary` markers. Legacy markdown tables continue to validate via the fallback path." },
|
|
171
170
|
{ section: "Verification Ladder", required: true, validationRule: "Per-slice verification tier (static, command, behavioral, human) with evidence captured for the highest tier reached this turn. Must include command + PASS/FAIL + commit SHA when VCS is present, or explicit no-vcs reason plus content/artifact hash/config override." },
|
|
172
171
|
{ section: "TDD Blocker Taxonomy", required: false, validationRule: "When blocked, classify as NO_SOURCE_CONTEXT, NO_TEST_SURFACE, NO_IMPLEMENTABLE_SLICE, RED_NOT_EXPRESSIBLE, or NO_VCS_MODE; include blockedBecause, missingInputs, recommendedRoute, nextCommand, and resumeCriteria." },
|
|
173
172
|
{ section: "Coverage Targets", required: false, validationRule: "If present: per-module or per-code-type coverage thresholds with current values and measurement commands." },
|
|
@@ -302,11 +301,11 @@ function tddStageVariantForTrack(track) {
|
|
|
302
301
|
traceabilityRule: "Every RED test traces to an acceptance criterion. Every GREEN change traces to a RED test. Evidence chain must be unbroken."
|
|
303
302
|
},
|
|
304
303
|
artifactValidation: TDD.artifactRules.artifactValidation.map((row) => {
|
|
305
|
-
if (row.section === "Acceptance
|
|
304
|
+
if (row.section === "Acceptance & Failure Map") {
|
|
306
305
|
return {
|
|
307
306
|
...row,
|
|
308
307
|
required: true,
|
|
309
|
-
validationRule: "Each
|
|
308
|
+
validationRule: "Each slice row carries Source ID, AC ID (spec acceptance criterion ID, for example AC-1), expected behavior, and a RED-link (delegation spanId or evidence path). From v6.11.0 a `phase=red` event in `delegation-events.jsonl` with non-empty evidenceRefs satisfies the row."
|
|
310
309
|
};
|
|
311
310
|
}
|
|
312
311
|
if (row.section === "Traceability") {
|
|
@@ -676,9 +676,9 @@ function sliceImplementerEnhancedBody() {
|
|
|
676
676
|
${MARKDOWN_CODE_FENCE}
|
|
677
677
|
You are a slice-implementer subagent.
|
|
678
678
|
|
|
679
|
-
SLICE: {single vertical slice}
|
|
679
|
+
SLICE: {single vertical slice — controller MUST dispatch you with --slice S-<id> --phase green --paths <comma-separated>}
|
|
680
680
|
RED_EVIDENCE: {failing test and expected failure}
|
|
681
|
-
ALLOWED_FILES: {explicit file boundaries}
|
|
681
|
+
ALLOWED_FILES: {explicit file boundaries — surfaced to scheduler as Files: <paths>}
|
|
682
682
|
FORBIDDEN_CHANGES: {scope/compatibility limits}
|
|
683
683
|
VERIFICATION: {commands expected}
|
|
684
684
|
|
|
@@ -686,6 +686,12 @@ Rules:
|
|
|
686
686
|
- Implement only the minimal GREEN change for the existing RED evidence.
|
|
687
687
|
- Keep REFACTOR behavior-preserving.
|
|
688
688
|
- Return the strict worker JSON schema first.
|
|
689
|
+
|
|
690
|
+
Slice phase-event contract (v6.11.0):
|
|
691
|
+
- Do NOT hand-edit \`## Watched-RED Proof\`, \`## Vertical Slice Cycle\`, \`## RED Evidence\`, or \`## GREEN Evidence\` markdown tables in 06-tdd.md. The linter auto-renders them between \`<!-- auto-start: tdd-slice-summary -->\` markers from \`delegation-events.jsonl\` slice phase rows.
|
|
692
|
+
- Your dispatch row IS the evidence: the harness-generated delegation-record hook stamps \`sliceId=S-<id>\`, \`phase=green\`, and \`completedTs\` automatically. Attach evidenceRefs (test path, span ref, or pasted-output pointer) so the linter validates the row.
|
|
693
|
+
- After REFACTOR, ask the controller to re-dispatch you with \`--phase refactor\` (or \`--phase refactor-deferred --refactor-rationale "<why>"\`); each call appends a new ledger row.
|
|
694
|
+
- Per-slice prose summary lives in \`<artifacts-dir>/tdd-slices/S-<id>.md\` and is owned by the parallel \`slice-documenter\` (or the controller). You do NOT touch that file.
|
|
689
695
|
${MARKDOWN_CODE_FENCE}
|
|
690
696
|
|
|
691
697
|
`;
|
|
@@ -929,12 +935,15 @@ FIXTURES / PATTERNS: {links to helper modules by path + naming conventions}
|
|
|
929
935
|
|
|
930
936
|
Process (mandatory):
|
|
931
937
|
1) If STAGE_MODE=TEST_RED_ONLY:
|
|
932
|
-
-
|
|
938
|
+
- Controller dispatched you with \`--slice S-<id> --phase red\`. Add failing tests proving the gap (show failing output excerpt).
|
|
933
939
|
- Do NOT edit production code.
|
|
940
|
+
- Do NOT hand-edit \`## Watched-RED Proof\` / \`## RED Evidence\` markdown tables in 06-tdd.md — the linter auto-renders them from your dispatch row in \`delegation-events.jsonl\`. Just ensure your worker return includes evidenceRefs (test path, span ref, or pasted-output pointer) so the harness can stamp them on the ledger row.
|
|
934
941
|
- Report: TESTS_ADDED, RED_COMMAND_RUN, RED_EVIDENCE, STATUS: DONE|BLOCKED.
|
|
935
942
|
2) If STAGE_MODE=BUILD_GREEN_REFACTOR:
|
|
943
|
+
- Controller dispatched you with \`--slice S-<id> --phase green\` (and later \`--phase refactor\` or \`--phase refactor-deferred --refactor-rationale "<why>"\`).
|
|
936
944
|
- GREEN — minimal production code to satisfy existing RED tests, rerun full suite.
|
|
937
945
|
- REFACTOR — only after full suite is green; preserve behavior.
|
|
946
|
+
- Do NOT hand-edit \`## Vertical Slice Cycle\` / \`## GREEN Evidence\` markdown tables — auto-rendered from your dispatch row.
|
|
938
947
|
- Report: FILES_EDITED, GREEN_COMMAND_RUN, REFACTOR_NOTES, STATUS: DONE|BLOCKED.
|
|
939
948
|
${MARKDOWN_CODE_FENCE}
|
|
940
949
|
|
|
@@ -17,4 +17,10 @@ export declare const RULEBOOK_MARKDOWN = "# Cclaw Rulebook\n\n## MUST_ALWAYS\n-
|
|
|
17
17
|
*/
|
|
18
18
|
export declare const CURSOR_GUIDELINES_RULE_MDC = "---\ndescription: cclaw zero-install behavior baseline (always-on)\nglobs:\n - \"**/*\"\nalwaysApply: true\n---\n\n<!-- cclaw-managed-cursor-guidelines-rule -->\n\n# Cclaw Baseline Guidelines\n\nThese three rules apply to every Cursor agent session in this project,\nregardless of whether stage skills loaded.\n\n## 1. Q&A floor before drafting (brainstorm/scope/design)\n\nBefore drafting any `.cclaw/artifacts/01-brainstorm-*.md`,\n`02-scope-*.md`, or `03-design-*.md`, verify that the artifact's\n`## Q&A Log` table demonstrates Ralph-Loop convergence: every\nforcing-question topic id is tagged `[topic:<id>]` on at least one row\n(see the stage's forcing-questions checklist for the id list), the last\n2 turns produce no new decision-changing impact, OR an explicit user\nstop-signal row is recorded. Walk the stage forcing questions one at a\ntime via the `AskQuestion` tool. If you find yourself proposing a\ndraft after 1-2 questions while forcing topic ids remain untagged, STOP\nand continue the loop.\n\nThe `qa_log_unconverged` linter rule will block `stage-complete` when\nconvergence has not been reached. Wave 24 (v6.0.0) made `[topic:<id>]`\ntagging mandatory; the English keyword fallback was removed because it\nmis-reported convergence on RU/UA Q&A logs.\n\n## 2. Mandatory subagents run after Q&A approval\n\nFor brainstorm / scope / design, mandatory subagents (\n`product-discovery`, `critic`, `planner`, `architect`,\n`test-author`) run **only AFTER the user approves the elicitation\noutcome**, never before the Q&A loop converges. Dispatching them early\npreempts the user dialogue and violates the elicitation contract \u2014 the\nlinter will block stage-complete.\n\nSee each stage's \"Run Phase: post-elicitation\" rows in the materialized\nAutomatic Subagent Dispatch table.\n\n## 3. Never echo cclaw command lines to chat\n\nThe user does not run cclaw helpers (`node .cclaw/hooks/...`) manually.\nNEVER paste full command lines, `--evidence-json '{...}'` payloads,\n`--waive-delegation=...`, or shell hash commands (`shasum`,\n`sha256sum`, `Get-FileHash`, `certutil`, etc.) into chat. Run the\nhelper via the tool layer and report only the resulting summary. On\nfailure, report a compact human-readable summary plus the helper JSON in\na single fenced `json` block.\n";
|
|
19
19
|
export declare const CURSOR_WORKFLOW_RULE_MDC = "---\ndescription: cclaw workflow guardrails for Cursor agent sessions\nglobs:\n - \"**/*\"\nalwaysApply: true\n---\n\n<!-- cclaw-managed-cursor-workflow-rule -->\n\n# Cclaw Workflow Guardrails\n\n## Activation Rule\n\nBefore responding to coding work:\n1. Read `.cclaw/state/flow-state.json`.\n2. Start with `/cc` or continue with `/cc`.\n3. If no software-stage flow applies, respond normally.\n\n## Stage Order\n\n`brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship`\n\nTrack-specific skips are allowed only when `flow-state.track` + `skippedStages` explicitly say so.\n\n## Task Classification\n\n| Class | Route |\n|---|---|\n| non-trivial software work | `/cc <idea>` |\n| trivial software fix | `/cc <idea>` (quick track) |\n| bugfix with repro | `/cc <idea>` and enforce RED-first in tdd |\n| pure question / non-software | direct answer (no stage flow) |\n\n## Command Surface\n\n- `/cc` = entry and resume.\n- `/cc` = only progression path.\n- Knowledge capture and recall use the `learnings` skill when requested.\n\n## Verification Discipline\n\n- No completion claim without fresh command evidence in this turn.\n- Stage completion claim requires `stage-complete` exit 0 in the current turn. Quote the single-line success JSON printed to stdout (e.g. `{\"ok\":true,\"command\":\"stage-complete\",...}`); do not paraphrase, do not infer success from empty stdout or from skipped retries.\n\n## Protocol label hygiene\n\n`skip` wording means different things depending on phase: brainstorm/scope/design Q&A stop-signals may still literal **skip**/enough/move-on wording; structured ship closeout retros and compound clustering prompts should expose **no changes** (or accept-as-is language) rather than labeling the passive path as skip. Keep the verbs aligned with the harness question copy you present to the human.\n- Do not mark gates passed from memory.\n- Keep evidence in `.cclaw/artifacts/`; archive through closeout via `/cc` or cancel early via `node .cclaw/hooks/cancel-run.mjs`.\n\n## Delegation And Approvals\n\n- Machine-only checks in design/plan/tdd/review/ship should auto-dispatch when tooling supports it.\n- **For brainstorm / scope / design stages**: ask user input continuously via adaptive elicitation (one question per turn through the harness-native question tool \u2014 `AskQuestion` in Cursor). Walk the stage forcing-questions list one-by-one. **Tag each Q&A Log row's `Decision impact` cell with `[topic:<id>]`** (the id is given in the stage's forcing-questions checklist) so the linter can verify coverage in any natural language. Do NOT batch and do NOT defer to a single approval gate at the end. The `qa_log_unconverged` linter rule will block `stage-complete` when convergence is not reached (forcing topic ids untagged AND last 2 turns still produce decision-changing rows AND no stop-signal).\n- **For other stages** (spec/plan/tdd/build/review/ship): ask user input only at explicit approval gates (scope mode, plan approval, challenge resolution, ship finalization), not for routine progress updates.\n- If you find yourself proposing a draft after 1-2 questions in brainstorm/scope/design, STOP \u2014 go back to the forcing-questions list and continue.\n- Mandatory subagents in brainstorm/scope/design run only AFTER the user approves the elicitation outcome (see each stage's \"Run Phase: post-elicitation\" rows). Dispatching them before the Q&A loop converges violates the contract.\n- Never echo cclaw command lines (`node .cclaw/hooks/...`, `--evidence-json '{...}'`) to chat \u2014 the user does not run cclaw manually. Run helpers via the tool layer; report only the resulting summary.\n- If harness capabilities are partial, record waiver reasons in delegation logs.\n\n## Routing Source Of Truth\n\n- Primary router: `.cclaw/skills/using-cclaw/SKILL.md`.\n- Stage behavior: current stage skill plus `.cclaw/state/flow-state.json`.\n- Preamble budget: keep role/status announcements brief and avoid repeating\n them unless the stage or role changes.\n";
|
|
20
|
+
/**
|
|
21
|
+
* v6.11.0 (S2) — per-slice prose file written by `slice-documenter`
|
|
22
|
+
* (or the controller) to `<artifacts-dir>/tdd-slices/S-<id>.md`. The
|
|
23
|
+
* main `06-tdd.md` is auto-indexed via `## Slices Index`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function tddSliceFileTemplate(sliceId: string): string;
|
|
20
26
|
export declare function buildRulesJson(): Record<string, unknown>;
|