cclaw-cli 0.48.31 → 0.48.32
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 +609 -10
- package/dist/config.d.ts +1 -1
- package/dist/config.js +82 -4
- package/dist/content/examples.js +23 -6
- package/dist/content/ideate-command.d.ts +6 -2
- package/dist/content/ideate-command.js +43 -16
- package/dist/content/ideate-frames.d.ts +31 -0
- package/dist/content/ideate-frames.js +140 -0
- package/dist/content/ideate-ranking.d.ts +25 -0
- package/dist/content/ideate-ranking.js +65 -0
- package/dist/content/review-loop.d.ts +192 -0
- package/dist/content/review-loop.js +689 -0
- package/dist/content/seed-shelf.d.ts +36 -0
- package/dist/content/seed-shelf.js +236 -0
- package/dist/content/skills.js +14 -1
- package/dist/content/stage-schema.d.ts +1 -1
- package/dist/content/stage-schema.js +14 -2
- package/dist/content/stages/brainstorm.js +15 -4
- package/dist/content/stages/design.js +31 -8
- package/dist/content/stages/schema-types.d.ts +10 -0
- package/dist/content/stages/scope.js +17 -6
- package/dist/content/start-command.js +24 -18
- package/dist/content/templates.js +108 -4
- package/dist/internal/advance-stage.js +143 -1
- package/dist/trace-matrix.d.ts +14 -0
- package/dist/trace-matrix.js +55 -1
- package/dist/types.d.ts +27 -0
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface SeedShelfEntry {
|
|
2
|
+
fileName: string;
|
|
3
|
+
absPath: string;
|
|
4
|
+
relPath: string;
|
|
5
|
+
createdOn: string;
|
|
6
|
+
title: string;
|
|
7
|
+
triggerWhen: string[];
|
|
8
|
+
sourceStage: string | null;
|
|
9
|
+
sourceArtifact: string | null;
|
|
10
|
+
hypothesis: string | null;
|
|
11
|
+
action: string | null;
|
|
12
|
+
summary: string;
|
|
13
|
+
raw: string;
|
|
14
|
+
}
|
|
15
|
+
export interface SeedTemplateInput {
|
|
16
|
+
title: string;
|
|
17
|
+
triggerWhen: readonly string[];
|
|
18
|
+
hypothesis: string;
|
|
19
|
+
action: string;
|
|
20
|
+
sourceStage?: string;
|
|
21
|
+
sourceArtifact?: string;
|
|
22
|
+
createdAt?: Date;
|
|
23
|
+
}
|
|
24
|
+
export interface ResolvedSeedPath {
|
|
25
|
+
fileName: string;
|
|
26
|
+
absPath: string;
|
|
27
|
+
relPath: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function seedShelfDir(projectRoot: string): string;
|
|
30
|
+
export declare function seedSlug(title: string): string;
|
|
31
|
+
export declare function seedFileName(title: string, createdAt?: Date): string;
|
|
32
|
+
export declare function resolveSeedPathForWrite(projectRoot: string, title: string, createdAt?: Date): Promise<ResolvedSeedPath>;
|
|
33
|
+
export declare function readSeedShelf(projectRoot: string): Promise<SeedShelfEntry[]>;
|
|
34
|
+
export declare function seedMatchesPrompt(seed: SeedShelfEntry, prompt: string): boolean;
|
|
35
|
+
export declare function findMatchingSeeds(projectRoot: string, prompt: string, maxMatches?: number): Promise<SeedShelfEntry[]>;
|
|
36
|
+
export declare function renderSeedTemplate(input: SeedTemplateInput): string;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parse } from "yaml";
|
|
4
|
+
import { RUNTIME_ROOT } from "../constants.js";
|
|
5
|
+
const SEED_FILE_NAME_PATTERN = /^SEED-(\d{4}-\d{2}-\d{2})-([a-z0-9]+(?:-[a-z0-9]+)*)(?:-(\d+))?\.md$/u;
|
|
6
|
+
const DEFAULT_MAX_MATCHES = 3;
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function normalizeTriggerList(value) {
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
return value
|
|
13
|
+
.map((item) => typeof item === "string" || typeof item === "number" ? String(item).trim() : "")
|
|
14
|
+
.filter((item) => item.length > 0);
|
|
15
|
+
}
|
|
16
|
+
if (typeof value === "string") {
|
|
17
|
+
return value
|
|
18
|
+
.split(/,\s*/u)
|
|
19
|
+
.map((item) => item.trim())
|
|
20
|
+
.filter((item) => item.length > 0);
|
|
21
|
+
}
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
function parseSeedFrontmatter(raw) {
|
|
25
|
+
if (!raw.startsWith("---")) {
|
|
26
|
+
return { values: {}, body: raw };
|
|
27
|
+
}
|
|
28
|
+
const lines = raw.split(/\r?\n/u);
|
|
29
|
+
let closingIndex = -1;
|
|
30
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
31
|
+
if (lines[index]?.trim() === "---") {
|
|
32
|
+
closingIndex = index;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (closingIndex < 0) {
|
|
37
|
+
return { values: {}, body: raw };
|
|
38
|
+
}
|
|
39
|
+
const frontmatterRaw = lines.slice(1, closingIndex).join("\n");
|
|
40
|
+
const body = lines.slice(closingIndex + 1).join("\n");
|
|
41
|
+
try {
|
|
42
|
+
const parsed = parse(frontmatterRaw);
|
|
43
|
+
if (isRecord(parsed)) {
|
|
44
|
+
return { values: parsed, body };
|
|
45
|
+
}
|
|
46
|
+
return { values: {}, body };
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return { values: {}, body };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function firstHeading(body) {
|
|
53
|
+
const match = /^#\s+(.+)$/mu.exec(body);
|
|
54
|
+
if (!match)
|
|
55
|
+
return null;
|
|
56
|
+
const title = match[1]?.trim() ?? "";
|
|
57
|
+
return title.length > 0 ? title : null;
|
|
58
|
+
}
|
|
59
|
+
function firstNonEmptyParagraph(body) {
|
|
60
|
+
const lines = body.split(/\r?\n/u);
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
if (trimmed.length === 0)
|
|
64
|
+
continue;
|
|
65
|
+
if (/^#\s+/u.test(trimmed))
|
|
66
|
+
continue;
|
|
67
|
+
if (/^[-*]\s+/u.test(trimmed))
|
|
68
|
+
continue;
|
|
69
|
+
return trimmed;
|
|
70
|
+
}
|
|
71
|
+
return "";
|
|
72
|
+
}
|
|
73
|
+
function fromFileNameFallbackTitle(fileName) {
|
|
74
|
+
const stem = fileName.replace(/\.md$/u, "");
|
|
75
|
+
const withoutPrefix = stem.replace(/^SEED-\d{4}-\d{2}-\d{2}-/u, "");
|
|
76
|
+
return withoutPrefix
|
|
77
|
+
.split("-")
|
|
78
|
+
.filter((part) => part.length > 0 && !/^\d+$/u.test(part))
|
|
79
|
+
.map((part) => part[0]?.toUpperCase() + part.slice(1))
|
|
80
|
+
.join(" ")
|
|
81
|
+
.trim();
|
|
82
|
+
}
|
|
83
|
+
export function seedShelfDir(projectRoot) {
|
|
84
|
+
return path.join(projectRoot, RUNTIME_ROOT, "seeds");
|
|
85
|
+
}
|
|
86
|
+
export function seedSlug(title) {
|
|
87
|
+
const normalized = title
|
|
88
|
+
.toLowerCase()
|
|
89
|
+
.trim()
|
|
90
|
+
.replace(/[`"'“”‘’()[\]{}<>]/gu, " ")
|
|
91
|
+
.replace(/[^a-z0-9]+/gu, "-")
|
|
92
|
+
.replace(/^-+/u, "")
|
|
93
|
+
.replace(/-+$/u, "");
|
|
94
|
+
if (normalized.length === 0) {
|
|
95
|
+
return "seed";
|
|
96
|
+
}
|
|
97
|
+
return normalized.slice(0, 48);
|
|
98
|
+
}
|
|
99
|
+
function isoDate(value) {
|
|
100
|
+
return value.toISOString().slice(0, 10);
|
|
101
|
+
}
|
|
102
|
+
export function seedFileName(title, createdAt = new Date()) {
|
|
103
|
+
return `SEED-${isoDate(createdAt)}-${seedSlug(title)}.md`;
|
|
104
|
+
}
|
|
105
|
+
async function pathExists(absPath) {
|
|
106
|
+
try {
|
|
107
|
+
await fs.stat(absPath);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export async function resolveSeedPathForWrite(projectRoot, title, createdAt = new Date()) {
|
|
115
|
+
const seedsDir = seedShelfDir(projectRoot);
|
|
116
|
+
await fs.mkdir(seedsDir, { recursive: true });
|
|
117
|
+
const baseFile = seedFileName(title, createdAt);
|
|
118
|
+
const baseStem = baseFile.replace(/\.md$/u, "");
|
|
119
|
+
let candidate = baseFile;
|
|
120
|
+
let index = 2;
|
|
121
|
+
while (await pathExists(path.join(seedsDir, candidate))) {
|
|
122
|
+
candidate = `${baseStem}-${index}.md`;
|
|
123
|
+
index += 1;
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
fileName: candidate,
|
|
127
|
+
absPath: path.join(seedsDir, candidate),
|
|
128
|
+
relPath: path.join(RUNTIME_ROOT, "seeds", candidate)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export async function readSeedShelf(projectRoot) {
|
|
132
|
+
const dir = seedShelfDir(projectRoot);
|
|
133
|
+
let names = [];
|
|
134
|
+
try {
|
|
135
|
+
names = await fs.readdir(dir);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
const entries = [];
|
|
141
|
+
for (const fileName of names) {
|
|
142
|
+
if (!SEED_FILE_NAME_PATTERN.test(fileName))
|
|
143
|
+
continue;
|
|
144
|
+
const absPath = path.join(dir, fileName);
|
|
145
|
+
let raw = "";
|
|
146
|
+
try {
|
|
147
|
+
raw = await fs.readFile(absPath, "utf8");
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const frontmatter = parseSeedFrontmatter(raw);
|
|
153
|
+
const title = (typeof frontmatter.values.title === "string" && frontmatter.values.title.trim().length > 0
|
|
154
|
+
? frontmatter.values.title.trim()
|
|
155
|
+
: null) ??
|
|
156
|
+
firstHeading(frontmatter.body) ??
|
|
157
|
+
fromFileNameFallbackTitle(fileName) ??
|
|
158
|
+
"Untitled seed";
|
|
159
|
+
const triggerWhen = normalizeTriggerList(frontmatter.values.trigger_when ?? frontmatter.values.triggerWhen);
|
|
160
|
+
const sourceStage = typeof frontmatter.values.source_stage === "string"
|
|
161
|
+
? frontmatter.values.source_stage
|
|
162
|
+
: typeof frontmatter.values.sourceStage === "string"
|
|
163
|
+
? frontmatter.values.sourceStage
|
|
164
|
+
: null;
|
|
165
|
+
const sourceArtifact = typeof frontmatter.values.source_artifact === "string"
|
|
166
|
+
? frontmatter.values.source_artifact
|
|
167
|
+
: typeof frontmatter.values.sourceArtifact === "string"
|
|
168
|
+
? frontmatter.values.sourceArtifact
|
|
169
|
+
: null;
|
|
170
|
+
const hypothesis = typeof frontmatter.values.hypothesis === "string" ? frontmatter.values.hypothesis : null;
|
|
171
|
+
const action = typeof frontmatter.values.action === "string" ? frontmatter.values.action : null;
|
|
172
|
+
const createdOn = SEED_FILE_NAME_PATTERN.exec(fileName)?.[1] ?? "1970-01-01";
|
|
173
|
+
const summary = firstNonEmptyParagraph(frontmatter.body);
|
|
174
|
+
entries.push({
|
|
175
|
+
fileName,
|
|
176
|
+
absPath,
|
|
177
|
+
relPath: path.join(RUNTIME_ROOT, "seeds", fileName),
|
|
178
|
+
createdOn,
|
|
179
|
+
title,
|
|
180
|
+
triggerWhen,
|
|
181
|
+
sourceStage,
|
|
182
|
+
sourceArtifact,
|
|
183
|
+
hypothesis,
|
|
184
|
+
action,
|
|
185
|
+
summary,
|
|
186
|
+
raw
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
entries.sort((a, b) => b.fileName.localeCompare(a.fileName));
|
|
190
|
+
return entries;
|
|
191
|
+
}
|
|
192
|
+
export function seedMatchesPrompt(seed, prompt) {
|
|
193
|
+
const normalizedPrompt = prompt.toLowerCase().trim();
|
|
194
|
+
if (normalizedPrompt.length === 0)
|
|
195
|
+
return false;
|
|
196
|
+
if (seed.triggerWhen.length === 0)
|
|
197
|
+
return false;
|
|
198
|
+
return seed.triggerWhen.some((trigger) => normalizedPrompt.includes(trigger.toLowerCase()));
|
|
199
|
+
}
|
|
200
|
+
export async function findMatchingSeeds(projectRoot, prompt, maxMatches = DEFAULT_MAX_MATCHES) {
|
|
201
|
+
const seeds = await readSeedShelf(projectRoot);
|
|
202
|
+
const matches = seeds.filter((seed) => seedMatchesPrompt(seed, prompt));
|
|
203
|
+
return matches.slice(0, Math.max(1, maxMatches));
|
|
204
|
+
}
|
|
205
|
+
export function renderSeedTemplate(input) {
|
|
206
|
+
const triggerWhen = [...input.triggerWhen].map((item) => item.trim()).filter((item) => item.length > 0);
|
|
207
|
+
const createdAt = input.createdAt ?? new Date();
|
|
208
|
+
const sourceStage = input.sourceStage?.trim() || "unknown";
|
|
209
|
+
const sourceArtifact = input.sourceArtifact?.trim() || "unknown";
|
|
210
|
+
return `---
|
|
211
|
+
title: ${input.title.trim()}
|
|
212
|
+
created_at: ${createdAt.toISOString()}
|
|
213
|
+
source_stage: ${sourceStage}
|
|
214
|
+
source_artifact: ${sourceArtifact}
|
|
215
|
+
trigger_when:
|
|
216
|
+
${triggerWhen.length > 0 ? triggerWhen.map((trigger) => ` - ${trigger}`).join("\n") : " - <trigger token>"}
|
|
217
|
+
hypothesis: ${input.hypothesis.trim()}
|
|
218
|
+
action: ${input.action.trim()}
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
# ${input.title.trim()}
|
|
222
|
+
|
|
223
|
+
## Why capture this seed
|
|
224
|
+
${input.hypothesis.trim()}
|
|
225
|
+
|
|
226
|
+
## Trigger when
|
|
227
|
+
${triggerWhen.length > 0 ? triggerWhen.map((trigger) => `- ${trigger}`).join("\n") : "- <trigger token>"}
|
|
228
|
+
|
|
229
|
+
## Suggested action
|
|
230
|
+
${input.action.trim()}
|
|
231
|
+
|
|
232
|
+
## Notes
|
|
233
|
+
- Expected payoff:
|
|
234
|
+
- Risks:
|
|
235
|
+
`;
|
|
236
|
+
}
|
package/dist/content/skills.js
CHANGED
|
@@ -82,6 +82,18 @@ function reviewSectionsBlock(sectionsInput) {
|
|
|
82
82
|
${sections}
|
|
83
83
|
`;
|
|
84
84
|
}
|
|
85
|
+
function reviewLoopBlock(reviewLoop) {
|
|
86
|
+
if (!reviewLoop)
|
|
87
|
+
return "";
|
|
88
|
+
const checklist = reviewLoop.checklist.map((item) => `- \`${item}\``).join("\n");
|
|
89
|
+
return `## Outside Voice Review Loop
|
|
90
|
+
- Stage: \`${reviewLoop.stage}\`
|
|
91
|
+
- Target score: \`${reviewLoop.targetScore}\`
|
|
92
|
+
- Max iterations: \`${reviewLoop.maxIterations}\`
|
|
93
|
+
- Checklist dimensions:
|
|
94
|
+
${checklist}
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
85
97
|
function verificationBlock(stage) {
|
|
86
98
|
if (!VERIFICATION_STAGES.includes(stage))
|
|
87
99
|
return "";
|
|
@@ -335,6 +347,7 @@ export function stageSkillMarkdown(stage, track = "standard") {
|
|
|
335
347
|
const interactionFocus = dedupeGuidance(executionModel.interactionProtocol, [...executionModel.checklist, ...executionModel.process]).slice(0, 5);
|
|
336
348
|
const processSummary = dedupeGuidance(executionModel.process, executionModel.checklist).slice(0, 5);
|
|
337
349
|
const stageRefs = stageSpecificSeeAlso(stage);
|
|
350
|
+
const reviewLoopSection = reviewLoopBlock(reviewLens.reviewLoop);
|
|
338
351
|
const mandatoryDelegationSummary = mandatoryDelegations.length > 0
|
|
339
352
|
? mandatoryDelegations.map((name) => `\`${name}\``).join(", ")
|
|
340
353
|
: "none";
|
|
@@ -418,7 +431,7 @@ ${crossStageTraceBlock(artifactRules.crossStageTrace)}
|
|
|
418
431
|
${artifactValidationBlock(artifactRules.artifactValidation)}
|
|
419
432
|
|
|
420
433
|
## Review Lens
|
|
421
|
-
## Outputs
|
|
434
|
+
${reviewLoopSection ? `${reviewLoopSection}\n` : ""}## Outputs
|
|
422
435
|
${reviewLens.outputs.map((item) => `- ${item}`).join("\n")}
|
|
423
436
|
|
|
424
437
|
${reviewSectionsBlock(reviewLens.reviewSections)}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FlowStage, FlowTrack, TransitionRule } from "../types.js";
|
|
2
2
|
import type { StageComplexityTier, StageAutoSubagentDispatch, StageSchema } from "./stages/schema-types.js";
|
|
3
|
-
export type { ArtifactValidation, CrossStageTrace, ReviewSection, StageComplexityTier, StageExecutionModel, StagePhilosophy, StageArtifactRules, StageReviewLens, StageAutoSubagentDispatch, StageGate, StageSchemaLegacyInput, StageSchema, StageSchemaInput, StageSchemaV2Input } from "./stages/schema-types.js";
|
|
3
|
+
export type { ArtifactValidation, CrossStageTrace, ReviewSection, StageComplexityTier, StageExecutionModel, StagePhilosophy, StageArtifactRules, StageReviewLoop, StageReviewLens, StageAutoSubagentDispatch, StageGate, StageSchemaLegacyInput, StageSchema, StageSchemaInput, StageSchemaV2Input } from "./stages/schema-types.js";
|
|
4
4
|
export declare const SKILL_ENVELOPE_KINDS: readonly ["stage-output", "gate-result", "delegation-record"];
|
|
5
5
|
export type SkillEnvelopeKind = (typeof SKILL_ENVELOPE_KINDS)[number];
|
|
6
6
|
export interface SkillEnvelope {
|
|
@@ -145,13 +145,23 @@ const REQUIRED_GATE_IDS = {
|
|
|
145
145
|
]
|
|
146
146
|
};
|
|
147
147
|
const REQUIRED_ARTIFACT_SECTIONS = {
|
|
148
|
-
brainstorm: [
|
|
148
|
+
brainstorm: [
|
|
149
|
+
"Context",
|
|
150
|
+
"Problem",
|
|
151
|
+
"Approach Tier",
|
|
152
|
+
"Approaches",
|
|
153
|
+
"Approach Reaction",
|
|
154
|
+
"Selected Direction"
|
|
155
|
+
],
|
|
149
156
|
scope: ["Scope Mode", "In Scope / Out of Scope", "Completion Dashboard", "Scope Summary"],
|
|
150
157
|
design: [
|
|
151
158
|
"Research Fleet Synthesis",
|
|
152
159
|
"Architecture Boundaries",
|
|
153
160
|
"Architecture Diagram",
|
|
154
161
|
"Failure Mode Table",
|
|
162
|
+
"Security & Threat Model",
|
|
163
|
+
"Observability & Debuggability",
|
|
164
|
+
"Deployment & Rollout",
|
|
155
165
|
"Completion Dashboard"
|
|
156
166
|
],
|
|
157
167
|
spec: ["Acceptance Criteria", "Edge Cases", "Testability Map", "Approval"],
|
|
@@ -227,6 +237,7 @@ function normalizeStageSchemaInput(value) {
|
|
|
227
237
|
next: value.next,
|
|
228
238
|
checklist: value.executionModel.checklist,
|
|
229
239
|
reviewSections: value.reviewLens.reviewSections,
|
|
240
|
+
reviewLoop: value.reviewLens.reviewLoop,
|
|
230
241
|
completionStatus: value.artifactRules.completionStatus,
|
|
231
242
|
crossStageTrace: value.artifactRules.crossStageTrace,
|
|
232
243
|
artifactValidation: value.artifactRules.artifactValidation,
|
|
@@ -453,7 +464,8 @@ export function stageSchema(stage, track = "standard") {
|
|
|
453
464
|
const reviewLens = {
|
|
454
465
|
outputs: base.outputs,
|
|
455
466
|
reviewSections: base.reviewSections,
|
|
456
|
-
mandatoryDelegations
|
|
467
|
+
mandatoryDelegations,
|
|
468
|
+
reviewLoop: base.reviewLoop
|
|
457
469
|
};
|
|
458
470
|
return {
|
|
459
471
|
...base,
|
|
@@ -44,6 +44,7 @@ export const BRAINSTORM = {
|
|
|
44
44
|
"**Propose 2-3 architecturally distinct approaches** — with real trade-offs and no recommendation yet. At least one option must be a higher-upside challenger that raises ambition vs the user's initial ask.",
|
|
45
45
|
"**Collect user reaction** — ask which approach feels closest and what concerns remain before stating your recommendation.",
|
|
46
46
|
"**Recommend only after reaction** — present final recommendation with rationale that explicitly references user feedback.",
|
|
47
|
+
"**Plant-seed shelf (optional)** — when a non-selected approach is still promising, capture it as `.cclaw/seeds/SEED-<YYYY-MM-DD>-<slug>.md` with `trigger_when`, hypothesis, and suggested action instead of losing it.",
|
|
47
48
|
"**Present design by sections** — scale each section to its complexity. Ask after each section whether it looks right so far. Cover: architecture, key components, data flow.",
|
|
48
49
|
"**Optional visual companion** — when architecture/data flow complexity is medium+ offer a compact diagram (ASCII or Mermaid) before artifact write-up.",
|
|
49
50
|
"**Write artifact** to `.cclaw/artifacts/01-brainstorm-<slug>.md`.",
|
|
@@ -74,6 +75,7 @@ export const BRAINSTORM = {
|
|
|
74
75
|
"Propose 2-3 architecturally distinct approaches with trade-offs (one must be higher-upside challenger).",
|
|
75
76
|
"Collect user reaction before giving your recommendation.",
|
|
76
77
|
"Recommend after reaction and explain how feedback changed the recommendation.",
|
|
78
|
+
"Optionally plant promising non-selected approaches into `.cclaw/seeds/SEED-<YYYY-MM-DD>-<slug>.md` with trigger_when/action notes.",
|
|
77
79
|
"Present design sections incrementally, get approval after each.",
|
|
78
80
|
"Write approved direction to `.cclaw/artifacts/01-brainstorm-<slug>.md`.",
|
|
79
81
|
"Run document-quality pass to close contradictions and weak trade-off reasoning.",
|
|
@@ -93,6 +95,7 @@ export const BRAINSTORM = {
|
|
|
93
95
|
"2-3 approaches with trade-offs are recorded, including one higher-upside challenger option.",
|
|
94
96
|
"User reaction to approaches is captured before final recommendation.",
|
|
95
97
|
"Final recommendation explicitly reflects user reaction.",
|
|
98
|
+
"When a promising option is parked, a seed file is created under `.cclaw/seeds/` and referenced in the artifact.",
|
|
96
99
|
"Approved direction and approval marker are present.",
|
|
97
100
|
"Assumptions and open questions are captured (or explicitly marked as none)."
|
|
98
101
|
],
|
|
@@ -130,13 +133,21 @@ export const BRAINSTORM = {
|
|
|
130
133
|
{ section: "Context", required: true, validationRule: "Must reference project state and relevant existing code or patterns." },
|
|
131
134
|
{ section: "Problem", required: true, validationRule: "Must define what we're solving, success criteria, and constraints." },
|
|
132
135
|
{ section: "Clarifying Questions", required: false, validationRule: "Must capture question, answer, and decision impact for each clarifying question." },
|
|
133
|
-
{ section: "Approach Tier", required:
|
|
134
|
-
{ section: "
|
|
135
|
-
{ section: "
|
|
136
|
-
{ section: "
|
|
136
|
+
{ section: "Approach Tier", required: true, validationRule: "Must classify depth as Lightweight/Standard/Deep and explain why." },
|
|
137
|
+
{ section: "Short-Circuit Decision", required: false, validationRule: "Must include Status/Why/Scope handoff lines when short-circuit is discussed." },
|
|
138
|
+
{ section: "Approaches", required: true, validationRule: "Must compare 2-3 architecturally distinct options with real trade-offs and include one row labeled `challenger: higher-upside`." },
|
|
139
|
+
{ section: "Approach Reaction", required: true, validationRule: "Must summarize user reaction before recommendation, including concerns that changed direction." },
|
|
140
|
+
{ section: "Selected Direction", required: true, validationRule: "Must include the selected approach, rationale tied to user reaction/feedback, and explicit approval marker." },
|
|
137
141
|
{ section: "Design", required: false, validationRule: "Must cover architecture, key components, and data flow scaled to complexity." },
|
|
138
142
|
{ section: "Visual Companion", required: false, validationRule: "If architecture/data-flow complexity is medium+, include compact ASCII/Mermaid diagram or explicitly justify omission." },
|
|
139
143
|
{ section: "Assumptions and Open Questions", required: false, validationRule: "Must capture unresolved assumptions/open questions, or explicitly state none." }
|
|
144
|
+
],
|
|
145
|
+
trivialOverrideSections: [
|
|
146
|
+
"Context",
|
|
147
|
+
"Problem",
|
|
148
|
+
"Approach Tier",
|
|
149
|
+
"Short-Circuit Decision",
|
|
150
|
+
"Selected Direction"
|
|
140
151
|
]
|
|
141
152
|
},
|
|
142
153
|
reviewLens: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { REVIEW_LOOP_CHECKLISTS } from "../review-loop.js";
|
|
1
2
|
// ---------------------------------------------------------------------------
|
|
2
3
|
// DESIGN — reference: gstack Eng review
|
|
3
4
|
// ---------------------------------------------------------------------------
|
|
@@ -44,7 +45,7 @@ export const DESIGN = {
|
|
|
44
45
|
"Codebase Investigation — Before any design decision, read the actual code in the blast radius. List every file that will be touched, its current responsibilities, and existing patterns (error handling, naming, test style). Design must conform to discovered patterns, not impose new ones without justification.",
|
|
45
46
|
"Step 0: Scope Challenge — what existing code solves sub-problems? Minimum change set? Complexity check: 8+ files or 2+ new services = complexity smell → flag for possible scope reduction.",
|
|
46
47
|
"Search Before Building — For each technical choice (library, pattern, architecture), search for existing solutions. Label findings: Layer 1 (exact match), Layer 2 (partial match, needs adaptation), Layer 3 (inspiration only), EUREKA (unexpected perfect solution). Default to existing before custom.",
|
|
47
|
-
"Architecture Review — lock component boundaries and one realistic failure scenario per new codepath. **Mandatory diagrams
|
|
48
|
+
"Architecture Review — lock component boundaries and one realistic failure scenario per new codepath. **Mandatory diagrams by tier:** Lightweight=Architecture Diagram, Standard=+Data-Flow Shadow Paths + Error Flow Diagram, Deep=+State Machine Diagram + Rollback Flowchart + Deployment Sequence Diagram.",
|
|
48
49
|
"Security & Threat Model Review — trust boundaries, authn/authz, input validation, secrets handling, data exposure risks, abuse cases, and mitigation ownership.",
|
|
49
50
|
"Code Quality Review — code organization, DRY violations, error handling patterns, over/under-engineering assessment. Include stale-diagram audit for touched files.",
|
|
50
51
|
"Test Review — diagram every new flow, data path, error path. For each: what test type covers it? Does one exist? What is the gap? Produce test plan artifact.",
|
|
@@ -52,7 +53,9 @@ export const DESIGN = {
|
|
|
52
53
|
"Observability & Debuggability Review — logging, metrics, traces, alerts, and on-call diagnosis path for each critical failure mode.",
|
|
53
54
|
"Deployment & Rollout Review — migration sequencing, flag strategy, rollback plan, compatibility window, and post-deploy verification steps.",
|
|
54
55
|
"Parallelization Strategy — If multiple independent modules, produce dependency table: which can be built in parallel? Where are conflict risks? Flag shared-state modules.",
|
|
55
|
-
"Outside Voice + Spec Review Loop — run adversarial second-opinion review, reconcile findings, and iterate up to 3 cycles or until quality score >= 0.8.",
|
|
56
|
+
"Outside Voice + Spec Review Loop — run adversarial second-opinion review, reconcile findings, and iterate up to 3 cycles or until quality score >= 0.8. When `.cclaw/config.yaml::reviewLoop.externalSecondOpinion.enabled` is true, run an additional external-model pass and explicitly resolve score/finding disagreements.",
|
|
57
|
+
"Stale Diagram Audit (opt-in) — when `.cclaw/config.yaml::optInAudits.staleDiagramAudit` is true, compare blast-radius file mtimes against diagram-marker freshness and flag stale diagrams before design lock.",
|
|
58
|
+
"Plant-seed shelf (optional) — when an unresolved/deferred design idea has upside, capture it as `.cclaw/seeds/SEED-<YYYY-MM-DD>-<slug>.md` with trigger_when and action so it can be recalled on future `/cc` starts.",
|
|
56
59
|
"Unresolved Decisions — List any design decisions that could not be resolved in this session. For each: what information is missing? Who can provide it? What is the default if no answer comes?",
|
|
57
60
|
"Distribution Check — If the plan creates new artifact types (packages, CLI tools, configs), document the build/publish story. How does it reach the user?",
|
|
58
61
|
"Deferred Items Cross-Reference — Collect every item explicitly deferred during design review. Each must appear in the Unresolved Decisions table or in the upstream scope artifact's deferred list. No deferred item may exist only in conversation — it must be written down."
|
|
@@ -86,8 +89,9 @@ export const DESIGN = {
|
|
|
86
89
|
"Add security, observability, and deployment reviews for Standard+ changes.",
|
|
87
90
|
"Run stale-diagram audit in touched files and reconcile drift.",
|
|
88
91
|
"Define test coverage strategy and performance budget.",
|
|
89
|
-
"Produce required outputs: NOT-in-scope section, What-already-exists section,
|
|
90
|
-
"
|
|
92
|
+
"Produce required outputs: NOT-in-scope section, What-already-exists section, tier-required diagrams with markers, failure mode table.",
|
|
93
|
+
"Optionally plant unresolved high-upside ideas into `.cclaw/seeds/SEED-<YYYY-MM-DD>-<slug>.md` with trigger_when/action notes.",
|
|
94
|
+
"Run outside-voice spec review loop (up to 3 iterations, quality score target >= 0.8). If configured, include external second opinion and reconcile deltas.",
|
|
91
95
|
"Produce completion dashboard: status per review section, critical/open gap counts, decision count, unresolved items.",
|
|
92
96
|
"Write design lock artifact for downstream spec/plan."
|
|
93
97
|
],
|
|
@@ -102,12 +106,15 @@ export const DESIGN = {
|
|
|
102
106
|
"Research artifact written to `.cclaw/artifacts/02a-research.md` with stack/features/architecture/pitfalls sections plus synthesis.",
|
|
103
107
|
"Artifact written to `.cclaw/artifacts/03-design-<slug>.md`.",
|
|
104
108
|
"Failure-mode table exists in Method/Exception/Rescue/UserSees format.",
|
|
105
|
-
"
|
|
109
|
+
"Tier-required diagram markers are present: architecture (all tiers), +shadow/error (Standard+), +state-machine/rollback/deployment-sequence (Deep).",
|
|
110
|
+
"When `.cclaw/config.yaml::optInAudits.staleDiagramAudit` is true, stale diagram audit finding is clear (no blast-radius file newer than diagram markers without explicit update).",
|
|
106
111
|
"Security & threat model findings are documented with mitigations.",
|
|
107
112
|
"Observability and deployment plans are explicit for critical flows.",
|
|
108
113
|
"Outside-voice findings and dispositions are recorded (accept/reject/defer).",
|
|
109
114
|
"Spec review loop summary includes iteration count and quality score trajectory.",
|
|
115
|
+
"When `.cclaw/config.yaml::reviewLoop.externalSecondOpinion.enabled` is true, external second-opinion disposition is captured.",
|
|
110
116
|
"Test strategy includes unit/integration/e2e expectations.",
|
|
117
|
+
"When a high-upside idea is deferred, a seed file is created under `.cclaw/seeds/` and referenced in the artifact.",
|
|
111
118
|
"NOT-in-scope section produced.",
|
|
112
119
|
"What-already-exists section produced.",
|
|
113
120
|
"Completion dashboard lists review section status, critical/open gap counts, decision count, and unresolved items (or 'None')."
|
|
@@ -154,13 +161,23 @@ export const DESIGN = {
|
|
|
154
161
|
{ section: "Codebase Investigation", required: false, validationRule: "Must list blast-radius files with current responsibilities and discovered patterns." },
|
|
155
162
|
{ section: "Search Before Building", required: false, validationRule: "For each technical choice: Layer 1 (exact match), Layer 2 (partial match), Layer 3 (inspiration), EUREKA labels with reuse-first default." },
|
|
156
163
|
{ section: "Architecture Boundaries", required: true, validationRule: "Must list component boundaries with ownership." },
|
|
157
|
-
{ section: "Architecture Diagram", required: true, validationRule: "
|
|
158
|
-
{ section: "Data
|
|
164
|
+
{ section: "Architecture Diagram", required: true, validationRule: "Must include `<!-- diagram: architecture -->` marker. Diagram must label concrete nodes, label arrows, mark direction, distinguish sync/async edges, and include at least one failure/degraded edge." },
|
|
165
|
+
{ section: "Data-Flow Shadow Paths", required: false, validationRule: "Standard/Deep: include `<!-- diagram: data-flow-shadow-paths -->` marker and path table with trigger plus fallback/degrade behavior." },
|
|
166
|
+
{ section: "Error Flow Diagram", required: false, validationRule: "Standard/Deep: include `<!-- diagram: error-flow -->` marker and failure-detection -> rescue -> user-visible outcome flow." },
|
|
167
|
+
{ section: "State Machine Diagram", required: false, validationRule: "Deep: include `<!-- diagram: state-machine -->` marker and state transitions for critical flow lifecycle." },
|
|
168
|
+
{ section: "Rollback Flowchart", required: false, validationRule: "Deep: include `<!-- diagram: rollback-flowchart -->` marker with trigger -> rollback actions -> verification." },
|
|
169
|
+
{ section: "Deployment Sequence Diagram", required: false, validationRule: "Deep: include `<!-- diagram: deployment-sequence -->` marker with rollout order and guard checks." },
|
|
170
|
+
{ section: "Data Flow", required: false, validationRule: "Must include happy path, nil input, empty input, upstream error paths, plus Interaction Edge Case matrix rows for: double-click, nav-away-mid-request, 10K-result dataset, background-job abandonment, zombie connection. Each row must declare handled yes/no and deferred item when not handled." },
|
|
171
|
+
{ section: "Stale Diagram Audit", required: false, validationRule: "When `.cclaw/config.yaml::optInAudits.staleDiagramAudit` is true: blast-radius files from Codebase Investigation must not be newer than the current design diagram-marker baseline unless explicitly refreshed." },
|
|
159
172
|
{ section: "Failure Mode Table", required: true, validationRule: "Use Method/Exception/Rescue/UserSees columns and treat silent user impact without rescue as critical." },
|
|
160
|
-
{ section: "Security & Threat Model", required:
|
|
173
|
+
{ section: "Security & Threat Model", required: true, validationRule: "Must list trust boundaries, abuse/failure scenarios, mitigations, and residual risks." },
|
|
161
174
|
{ section: "Test Strategy", required: false, validationRule: "Must define unit/integration/e2e expectations with coverage targets." },
|
|
162
175
|
{ section: "Performance Budget", required: false, validationRule: "For each critical path: metric name, target threshold, and measurement method." },
|
|
176
|
+
{ section: "Observability & Debuggability", required: true, validationRule: "Must define logs/metrics/traces plus alerting/debug path for critical failure modes." },
|
|
177
|
+
{ section: "Deployment & Rollout", required: true, validationRule: "Must define migration/flag strategy, rollback plan, and post-deploy verification steps." },
|
|
163
178
|
{ section: "What Already Exists", required: false, validationRule: "For each sub-problem: existing code/library found (Layer 1-3/EUREKA label), reuse decision, and adaptation needed." },
|
|
179
|
+
{ section: "Outside Voice Findings", required: false, validationRule: "List adversarial findings and disposition (accept/reject/defer) with rationale per finding." },
|
|
180
|
+
{ section: "Spec Review Loop", required: false, validationRule: "Record iteration table (max 3) with quality score per iteration, stop reason, and unresolved concerns." },
|
|
164
181
|
{ section: "NOT in scope", required: false, validationRule: "Work considered and explicitly deferred with one-line rationale." },
|
|
165
182
|
{ section: "Parallelization Strategy", required: false, validationRule: "If multi-module: dependency table, parallel lanes, conflict flags." },
|
|
166
183
|
{ section: "Unresolved Decisions", required: false, validationRule: "If any: what info is missing, who provides it, default if unanswered." },
|
|
@@ -178,6 +195,12 @@ export const DESIGN = {
|
|
|
178
195
|
"What-already-exists section",
|
|
179
196
|
"design completion dashboard"
|
|
180
197
|
],
|
|
198
|
+
reviewLoop: {
|
|
199
|
+
stage: "design",
|
|
200
|
+
checklist: REVIEW_LOOP_CHECKLISTS.design.map((dimension) => dimension.id),
|
|
201
|
+
maxIterations: 3,
|
|
202
|
+
targetScore: 0.8
|
|
203
|
+
},
|
|
181
204
|
reviewSections: [
|
|
182
205
|
{
|
|
183
206
|
title: "Architecture Review",
|
|
@@ -70,10 +70,18 @@ export interface StageReviewLens {
|
|
|
70
70
|
outputs: string[];
|
|
71
71
|
reviewSections: ReviewSection[];
|
|
72
72
|
mandatoryDelegations: string[];
|
|
73
|
+
reviewLoop?: StageReviewLoop;
|
|
73
74
|
}
|
|
74
75
|
export interface StageReviewLensInput {
|
|
75
76
|
outputs: string[];
|
|
76
77
|
reviewSections: ReviewSection[];
|
|
78
|
+
reviewLoop?: StageReviewLoop;
|
|
79
|
+
}
|
|
80
|
+
export interface StageReviewLoop {
|
|
81
|
+
stage: "scope" | "design";
|
|
82
|
+
checklist: string[];
|
|
83
|
+
maxIterations: number;
|
|
84
|
+
targetScore: number;
|
|
77
85
|
}
|
|
78
86
|
export interface StageSchema {
|
|
79
87
|
schemaShape: "v2";
|
|
@@ -130,6 +138,8 @@ export interface StageSchema {
|
|
|
130
138
|
trivialOverrideSections?: string[];
|
|
131
139
|
/** Agent names that MUST be dispatched (or waived) before stage transition — derived from mandatory auto-subagent rows. */
|
|
132
140
|
mandatoryDelegations: string[];
|
|
141
|
+
/** Optional shared outside-voice loop config for scope/design stages. */
|
|
142
|
+
reviewLoop?: StageReviewLoop;
|
|
133
143
|
}
|
|
134
144
|
export type StageSchemaLegacyInput = Omit<StageSchema, "schemaShape" | "philosophy" | "executionModel" | "artifactRules" | "reviewLens" | "mandatoryDelegations" | "complexityTier"> & {
|
|
135
145
|
schemaShape?: "legacy";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { REVIEW_LOOP_CHECKLISTS } from "../review-loop.js";
|
|
1
2
|
// ---------------------------------------------------------------------------
|
|
2
3
|
// SCOPE — reference: gstack CEO review
|
|
3
4
|
// ---------------------------------------------------------------------------
|
|
@@ -43,7 +44,7 @@ export const SCOPE = {
|
|
|
43
44
|
},
|
|
44
45
|
executionModel: {
|
|
45
46
|
checklist: [
|
|
46
|
-
"**Pre-Scope System Audit** — before premise challenge
|
|
47
|
+
"**Pre-Scope System Audit (opt-in)** — when `.cclaw/config.yaml::optInAudits.scopePreAudit` is true, before premise challenge gather reality snapshot: recent commits (`git log -30 --oneline`), current diff (`git diff --stat`), stash state (`git stash list`), and deferred debt markers (`rg -n 'TODO|FIXME|XXX|HACK'`). Record findings in scope artifact.",
|
|
47
48
|
"**Assess complexity** — Read the brainstorm artifact. If project is simple (single component, clear architecture, personal/prototype), run light-touch scope: mode selection, 3-5 key in/out boundaries, deferred items. Skip Dream State Mapping and Temporal Interrogation. If project is complex (multi-component, team delivery, production), run the full checklist.",
|
|
48
49
|
"**Prime Directives** — Zero silent failures. For each in-scope capability, name concrete failure modes, the exact error surface, and trace all four data-flow paths (happy, nil, empty, upstream error). Include interaction edge cases (double-click, navigate-away, stale state), observability commitments, and explicit deferred-item logging.",
|
|
49
50
|
"**Premise Challenge** — Is this the right problem? What if we do nothing? What are we optimizing for?",
|
|
@@ -55,7 +56,8 @@ export const SCOPE = {
|
|
|
55
56
|
"**Temporal Interrogation** — (complex projects only) simulate implementation timeline: HOUR 1 foundations, HOUR 2-3 core logic, HOUR 4-5 integration surprises, HOUR 6+ polish/tests. Decide what must be locked now vs safely deferred.",
|
|
56
57
|
"**Mode Selection** — Present expand/selective/hold/reduce with recommendation and default heuristic: greenfield -> expand, feature enhancement -> selective, bugfix/hotfix/refactor -> hold, broad blast radius (>15 files or multi-team impact) -> reduce.",
|
|
57
58
|
"**Mode-Specific Analysis** — After mode is selected, run the matching analysis: EXPAND (10x and delight opportunities), SELECTIVE (hold-scope rigor then cherry-picked expansions), HOLD (minimum-change-set hardening), REDUCE (ruthless cuts and follow-up split).",
|
|
58
|
-
"**
|
|
59
|
+
"**Plant-seed shelf (optional)** — when a deferred/out-of-scope idea still has upside, capture it as `.cclaw/seeds/SEED-<YYYY-MM-DD>-<slug>.md` with trigger_when and action instead of losing it in prose-only notes.",
|
|
60
|
+
"**Outside Voice + Spec Review Loop** — run an adversarial second-opinion pass on the scope artifact, reconcile findings, and iterate up to 3 cycles or until quality score >= 0.8. When `.cclaw/config.yaml::reviewLoop.externalSecondOpinion.enabled` is true, run an additional external-model pass and explicitly resolve score/finding disagreements.",
|
|
59
61
|
"**Error and Rescue Registry** — For each capability: what breaks, how detected, what fallback."
|
|
60
62
|
],
|
|
61
63
|
interactionProtocol: [
|
|
@@ -74,15 +76,16 @@ export const SCOPE = {
|
|
|
74
76
|
"**STOP BEFORE ADVANCE.** Mandatory delegation `planner` must be marked completed or explicitly waived in `.cclaw/state/delegation-log.json`. Then close the stage via `node .cclaw/hooks/stage-complete.mjs scope` (do not hand-edit `.cclaw/state/flow-state.json`)."
|
|
75
77
|
],
|
|
76
78
|
process: [
|
|
77
|
-
"
|
|
79
|
+
"When `.cclaw/config.yaml::optInAudits.scopePreAudit` is true, run pre-scope system audit (git log/diff/stash/debt markers).",
|
|
78
80
|
"Run premise challenge and existing-solution leverage check.",
|
|
79
81
|
"When mode is EXPAND/SELECTIVE, run brief landscape check before final scope lock.",
|
|
80
82
|
"Calibrate quality bar against 2-3 strong existing modules/files.",
|
|
81
83
|
"Produce 2-3 scope alternatives in a structured format (Name, Summary, Effort, Risk, Pros, Cons, Reuses) with minimum viable and ideal architecture options included.",
|
|
82
84
|
"Choose scope mode with user approval.",
|
|
83
85
|
"Run mode-specific analysis that matches the selected scope mode.",
|
|
86
|
+
"Optionally plant high-upside deferred ideas into `.cclaw/seeds/SEED-<YYYY-MM-DD>-<slug>.md` with trigger_when/action notes.",
|
|
84
87
|
"Walk through scope review sections one at a time.",
|
|
85
|
-
"Run outside-voice spec review loop (up to 3 iterations, quality score target >= 0.8).",
|
|
88
|
+
"Run outside-voice spec review loop (up to 3 iterations, quality score target >= 0.8). If configured, include external second opinion and reconcile deltas.",
|
|
86
89
|
"Write explicit scope contract, discretion areas, and deferred items.",
|
|
87
90
|
"Freeze non-negotiable boundaries as stable Locked Decisions (D-XX IDs).",
|
|
88
91
|
"Produce scope summary plus completion dashboard (section status, critical gaps, resolved decisions, unresolved items or `None`)."
|
|
@@ -94,7 +97,7 @@ export const SCOPE = {
|
|
|
94
97
|
],
|
|
95
98
|
requiredEvidence: [
|
|
96
99
|
"Artifact written to `.cclaw/artifacts/02-scope-<slug>.md`.",
|
|
97
|
-
"Pre-Scope System Audit findings are captured (git log/diff/stash/debt markers).",
|
|
100
|
+
"When `.cclaw/config.yaml::optInAudits.scopePreAudit` is true, Pre-Scope System Audit findings are captured (git log/diff/stash/debt markers).",
|
|
98
101
|
"In-scope and out-of-scope lists are explicit.",
|
|
99
102
|
"Discretion areas are explicit (or marked as `None`).",
|
|
100
103
|
"Selected mode and rationale are documented.",
|
|
@@ -102,7 +105,9 @@ export const SCOPE = {
|
|
|
102
105
|
"Premise challenge findings documented.",
|
|
103
106
|
"Outside Voice findings and dispositions are recorded (accept/reject/defer with rationale).",
|
|
104
107
|
"Spec review loop summary includes iteration count and quality score trajectory.",
|
|
108
|
+
"When `.cclaw/config.yaml::reviewLoop.externalSecondOpinion.enabled` is true, external second-opinion disposition is captured.",
|
|
105
109
|
"Deferred items list with one-line rationale for each.",
|
|
110
|
+
"When an upside deferred idea is parked, a seed file is created under `.cclaw/seeds/` and referenced in the artifact.",
|
|
106
111
|
"Completion dashboard lists per-section status, critical/open gaps, decision count, and unresolved items (or `None`)."
|
|
107
112
|
],
|
|
108
113
|
inputs: ["brainstorm artifact", "timeline constraints", "product priorities"],
|
|
@@ -139,7 +144,7 @@ export const SCOPE = {
|
|
|
139
144
|
traceabilityRule: "Every scope boundary must be traceable to a brainstorm decision. Every downstream design choice must stay within the scope contract."
|
|
140
145
|
},
|
|
141
146
|
artifactValidation: [
|
|
142
|
-
{ section: "Pre-Scope System Audit", required: false, validationRule: "
|
|
147
|
+
{ section: "Pre-Scope System Audit", required: false, validationRule: "When `.cclaw/config.yaml::optInAudits.scopePreAudit` is true: must capture git log -30, git diff --stat, git stash list, and debt-marker scan (TODO/FIXME/XXX/HACK) before premise challenge." },
|
|
143
148
|
{ section: "Prime Directives", required: false, validationRule: "For each scoped capability: named failure modes, explicit error surface, four data-flow paths, interaction edge cases, observability expectations, and deferred-item handling." },
|
|
144
149
|
{ section: "Premise Challenge", required: false, validationRule: "Must contain explicit answers to: right problem? direct path? what if nothing?" },
|
|
145
150
|
{ section: "Landscape Check", required: false, validationRule: "When mode is EXPAND/SELECTIVE, include at least one external reference insight and its impact on scope." },
|
|
@@ -163,6 +168,12 @@ export const SCOPE = {
|
|
|
163
168
|
},
|
|
164
169
|
reviewLens: {
|
|
165
170
|
outputs: ["scope mode decision", "scope contract", "discretion areas list", "deferred scope list", "scope summary", "scope completion dashboard"],
|
|
171
|
+
reviewLoop: {
|
|
172
|
+
stage: "scope",
|
|
173
|
+
checklist: REVIEW_LOOP_CHECKLISTS.scope.map((dimension) => dimension.id),
|
|
174
|
+
maxIterations: 3,
|
|
175
|
+
targetScore: 0.8
|
|
176
|
+
},
|
|
166
177
|
reviewSections: [
|
|
167
178
|
{
|
|
168
179
|
title: "Scope Boundary Audit",
|