cclaw-cli 0.55.2 → 2.0.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/README.md +3 -3
- package/dist/artifact-linter/brainstorm.js +59 -1
- package/dist/artifact-linter/design.js +46 -1
- package/dist/artifact-linter/plan.js +22 -1
- package/dist/artifact-linter/review.js +35 -1
- package/dist/artifact-linter/scope.js +33 -9
- package/dist/artifact-linter/shared.d.ts +12 -10
- package/dist/artifact-linter/shared.js +102 -41
- package/dist/artifact-linter/ship.js +36 -0
- package/dist/artifact-linter/spec.js +23 -1
- package/dist/artifact-linter/tdd.js +74 -0
- package/dist/artifact-linter.d.ts +1 -1
- package/dist/artifact-linter.js +11 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -0
- package/dist/content/closeout-guidance.d.ts +1 -1
- package/dist/content/closeout-guidance.js +10 -11
- package/dist/content/core-agents.d.ts +35 -36
- package/dist/content/core-agents.js +189 -99
- package/dist/content/diff-command.js +1 -1
- package/dist/content/examples.d.ts +0 -3
- package/dist/content/examples.js +197 -752
- package/dist/content/hook-events.js +1 -2
- package/dist/content/hook-manifest.d.ts +3 -4
- package/dist/content/hook-manifest.js +22 -25
- package/dist/content/hooks.js +54 -14
- package/dist/content/idea.d.ts +60 -0
- package/dist/content/idea.js +404 -0
- package/dist/content/learnings.d.ts +2 -4
- package/dist/content/learnings.js +10 -26
- package/dist/content/meta-skill.js +4 -3
- package/dist/content/node-hooks.js +368 -164
- package/dist/content/observe.js +3 -3
- package/dist/content/opencode-plugin.js +12 -32
- package/dist/content/reference-patterns.js +2 -2
- package/dist/content/runtime-shared-snippets.d.ts +8 -0
- package/dist/content/runtime-shared-snippets.js +80 -0
- package/dist/content/session-hooks.js +1 -1
- package/dist/content/skills-elicitation.d.ts +1 -0
- package/dist/content/skills-elicitation.js +123 -0
- package/dist/content/skills.d.ts +1 -0
- package/dist/content/skills.js +54 -2
- package/dist/content/stage-schema.js +107 -63
- package/dist/content/stages/brainstorm.js +7 -3
- package/dist/content/stages/design.js +4 -0
- package/dist/content/stages/review.js +8 -8
- package/dist/content/stages/schema-types.d.ts +2 -2
- package/dist/content/stages/scope.js +7 -3
- package/dist/content/stages/ship.js +1 -1
- package/dist/content/start-command.js +4 -4
- package/dist/content/status-command.js +3 -3
- package/dist/content/subagent-context-skills.js +156 -1
- package/dist/content/subagents.d.ts +0 -5
- package/dist/content/subagents.js +12 -82
- package/dist/content/templates.js +108 -6
- package/dist/content/utility-skills.js +26 -97
- package/dist/flow-state.d.ts +12 -6
- package/dist/flow-state.js +5 -6
- package/dist/gate-evidence.d.ts +0 -31
- package/dist/gate-evidence.js +3 -181
- package/dist/harness-adapters.js +1 -1
- package/dist/hook-schemas/claude-hooks.v1.json +2 -3
- package/dist/hook-schemas/codex-hooks.v1.json +1 -1
- package/dist/hook-schemas/cursor-hooks.v1.json +1 -1
- package/dist/install.js +50 -7
- package/dist/internal/advance-stage/advance.js +22 -2
- package/dist/internal/advance-stage/parsers.d.ts +1 -0
- package/dist/internal/advance-stage/parsers.js +6 -0
- package/dist/internal/advance-stage/review-loop.js +1 -10
- package/dist/knowledge-store.d.ts +2 -20
- package/dist/knowledge-store.js +43 -57
- package/dist/policy.js +3 -3
- package/dist/retro-gate.js +8 -90
- package/dist/run-archive.js +1 -4
- package/dist/run-persistence.d.ts +1 -1
- package/dist/run-persistence.js +43 -111
- package/dist/runtime/run-hook.entry.d.ts +3 -0
- package/dist/runtime/run-hook.entry.js +5 -0
- package/dist/runtime/run-hook.mjs +9647 -0
- package/dist/track-heuristics.d.ts +7 -1
- package/dist/track-heuristics.js +12 -0
- package/package.json +4 -2
- package/dist/content/hook-inline-snippets.d.ts +0 -96
- package/dist/content/hook-inline-snippets.js +0 -515
- package/dist/content/idea-command.d.ts +0 -8
- package/dist/content/idea-command.js +0 -322
- package/dist/content/idea-frames.d.ts +0 -31
- package/dist/content/idea-frames.js +0 -140
- package/dist/content/idea-ranking.d.ts +0 -25
- package/dist/content/idea-ranking.js +0 -65
- package/dist/trace-matrix.d.ts +0 -27
- package/dist/trace-matrix.js +0 -226
package/dist/content/observe.js
CHANGED
|
@@ -56,20 +56,20 @@ function buildCursorEvents() {
|
|
|
56
56
|
}
|
|
57
57
|
export function claudeHooksJsonWithObservation() {
|
|
58
58
|
return JSON.stringify({
|
|
59
|
-
cclawHookSchemaVersion:
|
|
59
|
+
cclawHookSchemaVersion: 2,
|
|
60
60
|
hooks: buildClaudeLikeEvents("claude")
|
|
61
61
|
}, null, 2);
|
|
62
62
|
}
|
|
63
63
|
export function cursorHooksJsonWithObservation() {
|
|
64
64
|
return JSON.stringify({
|
|
65
|
-
cclawHookSchemaVersion:
|
|
65
|
+
cclawHookSchemaVersion: 2,
|
|
66
66
|
version: 1,
|
|
67
67
|
hooks: buildCursorEvents()
|
|
68
68
|
}, null, 2);
|
|
69
69
|
}
|
|
70
70
|
export function codexHooksJsonWithObservation() {
|
|
71
71
|
return JSON.stringify({
|
|
72
|
-
cclawHookSchemaVersion:
|
|
72
|
+
cclawHookSchemaVersion: 2,
|
|
73
73
|
hooks: buildClaudeLikeEvents("codex")
|
|
74
74
|
}, null, 2);
|
|
75
75
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RUNTIME_ROOT } from "../constants.js";
|
|
2
2
|
import { META_SKILL_NAME } from "./meta-skill.js";
|
|
3
|
+
import { SHARED_FLOW_AND_KNOWLEDGE_SNIPPETS, SHARED_STAGE_SUPPORT_SNIPPETS } from "./runtime-shared-snippets.js";
|
|
3
4
|
export function opencodePluginJs(_options = {}) {
|
|
4
5
|
return `// cclaw OpenCode plugin — generated by npx cclaw-cli sync
|
|
5
6
|
import { appendFileSync, existsSync, mkdirSync } from "node:fs";
|
|
@@ -16,13 +17,8 @@ export default function cclawPlugin(ctx) {
|
|
|
16
17
|
const flowStatePath = join(stateDir, "flow-state.json");
|
|
17
18
|
const knowledgePath = join(runtimeDir, "knowledge.jsonl");
|
|
18
19
|
const metaSkillPath = join(runtimeDir, "skills/${META_SKILL_NAME}/SKILL.md");
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
brainstorm: "brainstorm-self-review.md",
|
|
22
|
-
scope: "scope-ceo-review.md",
|
|
23
|
-
design: "design-eng-review.md"
|
|
24
|
-
};
|
|
25
|
-
const REVIEW_PROMPT_FILES = Object.values(REVIEW_PROMPT_BY_STAGE);
|
|
20
|
+
${SHARED_FLOW_AND_KNOWLEDGE_SNIPPETS}
|
|
21
|
+
${SHARED_STAGE_SUPPORT_SNIPPETS}
|
|
26
22
|
|
|
27
23
|
function ensureRuntimeDirs() {
|
|
28
24
|
try {
|
|
@@ -61,14 +57,9 @@ export default function cclawPlugin(ctx) {
|
|
|
61
57
|
async function readFlowState() {
|
|
62
58
|
try {
|
|
63
59
|
const raw = await readFile(flowStatePath, "utf8");
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
stage: typeof state.currentStage === "string" ? state.currentStage : "none",
|
|
67
|
-
completed: Array.isArray(state.completedStages) ? state.completedStages.length : 0,
|
|
68
|
-
activeRunId: typeof state.activeRunId === "string" ? state.activeRunId : "none"
|
|
69
|
-
};
|
|
60
|
+
return summarizeFlowState(JSON.parse(raw));
|
|
70
61
|
} catch {
|
|
71
|
-
return {
|
|
62
|
+
return summarizeFlowState({});
|
|
72
63
|
}
|
|
73
64
|
}
|
|
74
65
|
|
|
@@ -80,18 +71,13 @@ export default function cclawPlugin(ctx) {
|
|
|
80
71
|
}
|
|
81
72
|
}
|
|
82
73
|
|
|
83
|
-
async function
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
return text.split(/\\r?\\n/).slice(-maxLines);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async function readKnowledgeDigest() {
|
|
90
|
-
return readTailLines(knowledgePath, 12);
|
|
74
|
+
async function readKnowledgeDigest(stage) {
|
|
75
|
+
const raw = await readFileText(knowledgePath);
|
|
76
|
+
return parseKnowledgeDigest(raw, stage, 6).lines;
|
|
91
77
|
}
|
|
92
78
|
|
|
93
79
|
async function readStageSupportContext(stage) {
|
|
94
|
-
if (
|
|
80
|
+
if (!isKnownStageId(stage)) return [];
|
|
95
81
|
const parts = [];
|
|
96
82
|
const contract = (await readFileText(join(runtimeDir, "templates/state-contracts", stage + ".json"))).trim();
|
|
97
83
|
if (contract.length > 0) {
|
|
@@ -100,7 +86,7 @@ export default function cclawPlugin(ctx) {
|
|
|
100
86
|
contract
|
|
101
87
|
);
|
|
102
88
|
}
|
|
103
|
-
const reviewPromptName =
|
|
89
|
+
const reviewPromptName = reviewPromptFileName(stage);
|
|
104
90
|
if (reviewPromptName) {
|
|
105
91
|
const prompt = (await readFileText(join(runtimeDir, "skills/review-prompts", reviewPromptName))).trim();
|
|
106
92
|
if (prompt.length > 0) {
|
|
@@ -119,12 +105,12 @@ export default function cclawPlugin(ctx) {
|
|
|
119
105
|
const flow = await readFlowState();
|
|
120
106
|
const parts = [
|
|
121
107
|
BOOTSTRAP_MARKER,
|
|
122
|
-
\`cclaw loaded. Flow: stage=\${flow.stage} (\${flow.completed}/8 completed, run=\${flow.activeRunId}). Active artifacts: ${RUNTIME_ROOT}
|
|
108
|
+
\`cclaw loaded. Flow: stage=\${flow.stage} (\${flow.completed}/8 completed, run=\${flow.activeRunId}). Active artifacts: \${activeArtifactsPathLabel("${RUNTIME_ROOT}")}\`
|
|
123
109
|
];
|
|
124
110
|
|
|
125
111
|
|
|
126
112
|
|
|
127
|
-
const knowledge = await readKnowledgeDigest();
|
|
113
|
+
const knowledge = await readKnowledgeDigest(flow.stage);
|
|
128
114
|
if (knowledge.length > 0) parts.push("Knowledge digest (top relevant entries):", ...knowledge);
|
|
129
115
|
|
|
130
116
|
const stageSupport = await readStageSupportContext(flow.stage);
|
|
@@ -621,12 +607,6 @@ export default function cclawPlugin(ctx) {
|
|
|
621
607
|
eventType === "session.compacted" ||
|
|
622
608
|
eventType === "session.cleared" ||
|
|
623
609
|
eventType === "session.updated";
|
|
624
|
-
// session.compacted must run pre-compact BEFORE canonical rehydration,
|
|
625
|
-
// otherwise the injected system prompt can show the pre-compact
|
|
626
|
-
// digest/state until the next lifecycle event.
|
|
627
|
-
if (eventType === "session.compacted") {
|
|
628
|
-
await runHookScript("pre-compact", eventData ?? {});
|
|
629
|
-
}
|
|
630
610
|
if (isSessionLifecycle) {
|
|
631
611
|
// Keep OpenCode aligned with Claude/Cursor/Codex: session-start is
|
|
632
612
|
// the canonical rehydrate path that refreshes derived state such as
|
|
@@ -201,7 +201,7 @@ export const REFERENCE_PATTERNS = [
|
|
|
201
201
|
"Review source-item coverage by vertical slice, not by file count alone.",
|
|
202
202
|
"A slice is review-ready only when RED, GREEN, REFACTOR, and verification evidence all line up."
|
|
203
203
|
],
|
|
204
|
-
artifactSections: ["Completeness Snapshot", "
|
|
204
|
+
artifactSections: ["Completeness Snapshot", "Coverage Check"]
|
|
205
205
|
}
|
|
206
206
|
]
|
|
207
207
|
},
|
|
@@ -348,7 +348,7 @@ export const REFERENCE_PATTERNS = [
|
|
|
348
348
|
{
|
|
349
349
|
stage: "review",
|
|
350
350
|
guidance: [
|
|
351
|
-
"Victory Detector: Layer 1, Layer 2, security sweep, structured findings, and
|
|
351
|
+
"Victory Detector: Layer 1, Layer 2, security sweep, structured findings, and acceptance/reproduction coverage evidence are complete with no unresolved criticals unless verdict is BLOCKED.",
|
|
352
352
|
"If the detector fails, iterate findings or route back to TDD; do not say LGTM."
|
|
353
353
|
],
|
|
354
354
|
artifactSections: ["Review Readiness Snapshot", "Final Verdict"]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared runtime snippets interpolated into generated hook/plugin scripts.
|
|
3
|
+
*
|
|
4
|
+
* Keep these string helpers minimal and dependency-free so both runtimes
|
|
5
|
+
* (node hooks and OpenCode plugin) stay in sync without duplicating constants.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SHARED_FLOW_AND_KNOWLEDGE_SNIPPETS = "\nfunction summarizeFlowState(rawState) {\n const state =\n rawState && typeof rawState === \"object\" && !Array.isArray(rawState)\n ? rawState\n : {};\n return {\n stage: typeof state.currentStage === \"string\" ? state.currentStage : \"none\",\n completed: Array.isArray(state.completedStages) ? state.completedStages.length : 0,\n activeRunId: typeof state.activeRunId === \"string\" ? state.activeRunId : \"none\"\n };\n}\n\nfunction parseKnowledgeDigest(rawKnowledge, currentStage, maxRows = 6) {\n const text = typeof rawKnowledge === \"string\" ? rawKnowledge : \"\";\n if (text.trim().length === 0) {\n return { learningsCount: 0, lines: [] };\n }\n const rows = text\n .split(/\\r?\\n/gu)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n let learningsCount = 0;\n const parsedRows = [];\n for (const line of rows) {\n if (line.startsWith(\"{\")) learningsCount += 1;\n try {\n const parsed = JSON.parse(line);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) continue;\n parsedRows.push(parsed);\n } catch {\n // ignore malformed knowledge line in digest\n }\n }\n const lines = parsedRows\n .filter((row) => {\n const stage = typeof row.stage === \"string\" ? row.stage : null;\n return stage === null || stage === currentStage;\n })\n .slice(-maxRows)\n .reverse()\n .map((row) => {\n const confidence = typeof row.confidence === \"string\" ? row.confidence : \"unknown\";\n const stage = typeof row.stage === \"string\" ? row.stage : \"global\";\n const trigger = typeof row.trigger === \"string\" ? row.trigger : \"trigger\";\n const action = typeof row.action === \"string\" ? row.action : \"action\";\n return \"- [\" + confidence + \" \u2022 \" + stage + \"] \" + trigger + \" -> \" + action;\n });\n return { learningsCount, lines };\n}\n\nfunction activeArtifactsPathLabel(runtimeRoot) {\n return String(runtimeRoot || \".cclaw\") + \"/artifacts/\";\n}\n";
|
|
8
|
+
export declare const SHARED_STAGE_SUPPORT_SNIPPETS = "\nconst STAGE_IDS = [\"brainstorm\", \"scope\", \"design\", \"spec\", \"plan\", \"tdd\", \"review\", \"ship\"];\nconst REVIEW_PROMPT_BY_STAGE = {\n brainstorm: \"brainstorm-self-review.md\",\n scope: \"scope-ceo-review.md\",\n design: \"design-eng-review.md\"\n};\nconst REVIEW_PROMPT_FILES = Object.values(REVIEW_PROMPT_BY_STAGE);\n\nfunction isKnownStageId(stage) {\n return typeof stage === \"string\" && STAGE_IDS.includes(stage);\n}\n\nfunction reviewPromptFileName(stage) {\n if (!isKnownStageId(stage)) return null;\n const name = REVIEW_PROMPT_BY_STAGE[stage];\n return typeof name === \"string\" ? name : null;\n}\n";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared runtime snippets interpolated into generated hook/plugin scripts.
|
|
3
|
+
*
|
|
4
|
+
* Keep these string helpers minimal and dependency-free so both runtimes
|
|
5
|
+
* (node hooks and OpenCode plugin) stay in sync without duplicating constants.
|
|
6
|
+
*/
|
|
7
|
+
export const SHARED_FLOW_AND_KNOWLEDGE_SNIPPETS = `
|
|
8
|
+
function summarizeFlowState(rawState) {
|
|
9
|
+
const state =
|
|
10
|
+
rawState && typeof rawState === "object" && !Array.isArray(rawState)
|
|
11
|
+
? rawState
|
|
12
|
+
: {};
|
|
13
|
+
return {
|
|
14
|
+
stage: typeof state.currentStage === "string" ? state.currentStage : "none",
|
|
15
|
+
completed: Array.isArray(state.completedStages) ? state.completedStages.length : 0,
|
|
16
|
+
activeRunId: typeof state.activeRunId === "string" ? state.activeRunId : "none"
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseKnowledgeDigest(rawKnowledge, currentStage, maxRows = 6) {
|
|
21
|
+
const text = typeof rawKnowledge === "string" ? rawKnowledge : "";
|
|
22
|
+
if (text.trim().length === 0) {
|
|
23
|
+
return { learningsCount: 0, lines: [] };
|
|
24
|
+
}
|
|
25
|
+
const rows = text
|
|
26
|
+
.split(/\\r?\\n/gu)
|
|
27
|
+
.map((line) => line.trim())
|
|
28
|
+
.filter((line) => line.length > 0);
|
|
29
|
+
let learningsCount = 0;
|
|
30
|
+
const parsedRows = [];
|
|
31
|
+
for (const line of rows) {
|
|
32
|
+
if (line.startsWith("{")) learningsCount += 1;
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(line);
|
|
35
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
|
|
36
|
+
parsedRows.push(parsed);
|
|
37
|
+
} catch {
|
|
38
|
+
// ignore malformed knowledge line in digest
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const lines = parsedRows
|
|
42
|
+
.filter((row) => {
|
|
43
|
+
const stage = typeof row.stage === "string" ? row.stage : null;
|
|
44
|
+
return stage === null || stage === currentStage;
|
|
45
|
+
})
|
|
46
|
+
.slice(-maxRows)
|
|
47
|
+
.reverse()
|
|
48
|
+
.map((row) => {
|
|
49
|
+
const confidence = typeof row.confidence === "string" ? row.confidence : "unknown";
|
|
50
|
+
const stage = typeof row.stage === "string" ? row.stage : "global";
|
|
51
|
+
const trigger = typeof row.trigger === "string" ? row.trigger : "trigger";
|
|
52
|
+
const action = typeof row.action === "string" ? row.action : "action";
|
|
53
|
+
return "- [" + confidence + " • " + stage + "] " + trigger + " -> " + action;
|
|
54
|
+
});
|
|
55
|
+
return { learningsCount, lines };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function activeArtifactsPathLabel(runtimeRoot) {
|
|
59
|
+
return String(runtimeRoot || ".cclaw") + "/artifacts/";
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
export const SHARED_STAGE_SUPPORT_SNIPPETS = `
|
|
63
|
+
const STAGE_IDS = ["brainstorm", "scope", "design", "spec", "plan", "tdd", "review", "ship"];
|
|
64
|
+
const REVIEW_PROMPT_BY_STAGE = {
|
|
65
|
+
brainstorm: "brainstorm-self-review.md",
|
|
66
|
+
scope: "scope-ceo-review.md",
|
|
67
|
+
design: "design-eng-review.md"
|
|
68
|
+
};
|
|
69
|
+
const REVIEW_PROMPT_FILES = Object.values(REVIEW_PROMPT_BY_STAGE);
|
|
70
|
+
|
|
71
|
+
function isKnownStageId(stage) {
|
|
72
|
+
return typeof stage === "string" && STAGE_IDS.includes(stage);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function reviewPromptFileName(stage) {
|
|
76
|
+
if (!isKnownStageId(stage)) return null;
|
|
77
|
+
const name = REVIEW_PROMPT_BY_STAGE[stage];
|
|
78
|
+
return typeof name === "string" ? name : null;
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
@@ -66,7 +66,7 @@ When resuming work after a break:
|
|
|
66
66
|
|
|
67
67
|
### Optional session-history scan for compound
|
|
68
68
|
|
|
69
|
-
During post-ship \`
|
|
69
|
+
During post-ship \`post_ship_review\`, ask before scanning external session history. If the user opts in, inspect only relevant Cursor/Claude/Codex transcripts for repeated failures or process lessons, summarize matches, and then apply the same overlap/refresh/supersede rules before touching \`.cclaw/knowledge.jsonl\`.
|
|
70
70
|
|
|
71
71
|
## Context Management
|
|
72
72
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function adaptiveElicitationSkillMarkdown(): string;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { RUNTIME_ROOT } from "../constants.js";
|
|
2
|
+
import { questionBudgetHint } from "../track-heuristics.js";
|
|
3
|
+
import { FLOW_TRACKS } from "../types.js";
|
|
4
|
+
const ELICITATION_STAGES = ["brainstorm", "scope", "design"];
|
|
5
|
+
function renderQuestionBudgetHintTable() {
|
|
6
|
+
const rows = [];
|
|
7
|
+
for (const track of FLOW_TRACKS) {
|
|
8
|
+
for (const stage of ELICITATION_STAGES) {
|
|
9
|
+
const hint = questionBudgetHint(track, stage);
|
|
10
|
+
rows.push(`| \`${track}\` | \`${stage}\` | ${hint.min} | ${hint.recommended} | ${hint.hardCapWarning} |`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return `| Track | Stage | Min | Recommended | Hard cap warning |
|
|
14
|
+
|---|---|---|---|---|
|
|
15
|
+
${rows.join("\n")}`;
|
|
16
|
+
}
|
|
17
|
+
export function adaptiveElicitationSkillMarkdown() {
|
|
18
|
+
const budgetTable = renderQuestionBudgetHintTable();
|
|
19
|
+
return `---
|
|
20
|
+
name: adaptive-elicitation
|
|
21
|
+
description: "Harness-native one-question-at-a-time dialogue for brainstorm/scope/design with stop signals, smart-skip, and append-only Q&A logging."
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Adaptive Elicitation
|
|
25
|
+
|
|
26
|
+
Pinned anchor: "Don't tell it what to do, give it success criteria and watch it go."
|
|
27
|
+
|
|
28
|
+
## HARD-GATE
|
|
29
|
+
- User does not run cclaw manually. Do not tell the user to run CLI commands for answers.
|
|
30
|
+
- Ask exactly one question per turn and wait for the answer before asking the next one.
|
|
31
|
+
- Use harness-native question tools first; prose fallback is allowed only when the tool is unavailable.
|
|
32
|
+
- Keep a running Q&A trace in the active artifact under \`## Q&A Log\` in \`${RUNTIME_ROOT}/artifacts/\` as append-only rows.
|
|
33
|
+
|
|
34
|
+
## Harness Question Surface
|
|
35
|
+
|
|
36
|
+
Preferred native tool names:
|
|
37
|
+
- Claude Code: \`AskUserQuestion\`
|
|
38
|
+
- Codex: \`request_user_input\`
|
|
39
|
+
- Gemini: \`ask_user\`
|
|
40
|
+
- Cursor: \`AskQuestion\`
|
|
41
|
+
|
|
42
|
+
If unavailable, ask one concise prose question and explicitly wait for chat answer.
|
|
43
|
+
|
|
44
|
+
## Core Protocol
|
|
45
|
+
|
|
46
|
+
1. Ask one decision-changing question.
|
|
47
|
+
2. Wait for the answer.
|
|
48
|
+
3. Append one row to \`## Q&A Log\`: \`Turn | Question | User answer (1-line) | Decision impact\`.
|
|
49
|
+
4. Self-evaluate:
|
|
50
|
+
- What did I learn?
|
|
51
|
+
- Is context enough to draft now? (yes/no + reason)
|
|
52
|
+
- If no, what is the next most decision-changing question?
|
|
53
|
+
5. Repeat until context is clear OR user asks to proceed.
|
|
54
|
+
|
|
55
|
+
## Question Shape Rules
|
|
56
|
+
|
|
57
|
+
- Prefer single-select multiple choice when one direction/priority/next step must be chosen.
|
|
58
|
+
- Use multi-select only for compatible sets (goals, constraints, non-goals).
|
|
59
|
+
- Smart-skip questions already answered earlier (directly or implicitly) and log "skipped (already covered)" when relevant.
|
|
60
|
+
|
|
61
|
+
## Stop Signals (Natural Language)
|
|
62
|
+
|
|
63
|
+
Treat these as stop-and-draft signals:
|
|
64
|
+
- RU: "достаточно", "хватит", "давай драфт"
|
|
65
|
+
- EN: "enough", "skip", "just draft it", "stop asking", "move on"
|
|
66
|
+
- UA: "досить", "вистачить", "давай драфт", "рухаємось далі"
|
|
67
|
+
|
|
68
|
+
When detected:
|
|
69
|
+
- Do not ask another question in this stage loop.
|
|
70
|
+
- Move to drafting with available context.
|
|
71
|
+
- For internal agent calls only, pass \`--skip-questions\` on the next advance helper call.
|
|
72
|
+
|
|
73
|
+
## Conditional Grilling (Only On Risk Triggers)
|
|
74
|
+
|
|
75
|
+
Ask an extra 3-5 sharp questions only when one of these triggers appears:
|
|
76
|
+
- Irreversibility (data deletion, schema migration, breaking API/contract)
|
|
77
|
+
- Security/auth boundary changes
|
|
78
|
+
- Domain-model ambiguity with multiple plausible invariants
|
|
79
|
+
|
|
80
|
+
Do not ask extra questions "for theater" on simple low-risk work.
|
|
81
|
+
|
|
82
|
+
## Question Budget Hint (Soft Guidance)
|
|
83
|
+
|
|
84
|
+
Use as orientation, never as a hard stop. Source of truth is \`questionBudgetHint(track, stage)\`:
|
|
85
|
+
|
|
86
|
+
${budgetTable}
|
|
87
|
+
|
|
88
|
+
Track mapping note: \`quick\` ~= lightweight, \`medium\` ~= standard, \`standard\` ~= deep.
|
|
89
|
+
Stop based on clarity/user signal, not raw count.
|
|
90
|
+
|
|
91
|
+
## Stage Forcing Questions
|
|
92
|
+
|
|
93
|
+
Always keep at least one unresolved forcing question in play until answered or explicitly waived:
|
|
94
|
+
|
|
95
|
+
- Brainstorm:
|
|
96
|
+
- What pain are we solving?
|
|
97
|
+
- What is the most direct path?
|
|
98
|
+
- What happens if we do nothing?
|
|
99
|
+
- Who is the operator/user impacted first?
|
|
100
|
+
- What are non-negotiable no-go boundaries?
|
|
101
|
+
- Scope:
|
|
102
|
+
- What is definitely in and definitely out?
|
|
103
|
+
- Which decisions are already locked upstream?
|
|
104
|
+
- What is the rollback path if this fails?
|
|
105
|
+
- What are the top failure modes we must design for?
|
|
106
|
+
- Design:
|
|
107
|
+
- What is the data flow end-to-end?
|
|
108
|
+
- Where are the seams/interfaces and ownership boundaries?
|
|
109
|
+
- Which invariants must always hold?
|
|
110
|
+
- What will we explicitly NOT refactor now?
|
|
111
|
+
|
|
112
|
+
## One-Way Override (Irreversible Decisions)
|
|
113
|
+
|
|
114
|
+
For irreversible moves (deletion, schema migration, breaking API):
|
|
115
|
+
- Ask for explicit confirmation even if user asked to stop questions.
|
|
116
|
+
- Proceed only after explicit override ("I understand the irreversible risk; proceed").
|
|
117
|
+
- Record the override in \`## Q&A Log\` and in the stage artifact decision section.
|
|
118
|
+
|
|
119
|
+
## Completion Rule
|
|
120
|
+
|
|
121
|
+
"Continue until clear OR user wants to proceed."
|
|
122
|
+
Never force a fixed N-question script.`;
|
|
123
|
+
}
|
package/dist/content/skills.d.ts
CHANGED
|
@@ -10,3 +10,4 @@ export declare function noPlaceholdersBlock(): string;
|
|
|
10
10
|
export declare function watchedFailProofBlock(): string;
|
|
11
11
|
export declare function stageSkillFolder(stage: FlowStage): string;
|
|
12
12
|
export declare function stageSkillMarkdown(stage: FlowStage, track?: FlowTrack): string;
|
|
13
|
+
export declare function executingWavesSkillMarkdown(): string;
|
package/dist/content/skills.js
CHANGED
|
@@ -148,11 +148,12 @@ function contextLoadingBlock(stage, trace, executionModel) {
|
|
|
148
148
|
|
|
149
149
|
Before execution:
|
|
150
150
|
1. Read \`.cclaw/state/flow-state.json\`.
|
|
151
|
+
- If the file is missing, do **not** invent an active run — this is normal for fresh init. Route to \`/cc <idea>\` first.
|
|
151
152
|
2. Load active artifacts from \`.cclaw/artifacts/\`.
|
|
152
153
|
3. Load upstream artifacts required by this stage:
|
|
153
154
|
${readLines}
|
|
154
155
|
4. Read the state contract from \`.cclaw/templates/state-contracts/<stage>.json\` for required fields, taxonomies, and derived markdown path.
|
|
155
|
-
5. Read the canonical artifact template at \`${artifactTemplatePath}\`
|
|
156
|
+
5. Read the canonical artifact template at \`${artifactTemplatePath}\` to preserve heading/per-row tables contracts (stable section names and column order) plus calibrated review block scaffolding. Preserve existing substantive bullets/rows already in the artifact; never overwrite the artifact wholesale from the template — patch only sections you author this turn.
|
|
156
157
|
6. Extract upstream decisions, constraints, and open questions into the current artifact's \`Upstream Handoff\` section when present.
|
|
157
158
|
7. Confirm context readiness: upstream artifact freshness, required context, canonical template shape, relevant in-repo/reference patterns, and unresolved blockers are known. If any item is missing, load it or stop before drafting.
|
|
158
159
|
8. Before doing stage work, give a compact user-facing drift preamble: "Carrying forward: <1-3 bullets>. Drift since upstream: None / <specific drift>. Recommendation: continue / re-scope."
|
|
@@ -376,7 +377,7 @@ function completionParametersBlock(schema, track) {
|
|
|
376
377
|
- \`delegation lifecycle proof\`: use the delegation helper recipe in this section with explicit lifecycle rows: \`--status=scheduled\` -> \`--status=launched\` -> \`--status=acknowledged\` -> \`--status=completed\` (completed isolated/generic requires prior ACK for the same span or \`--ack-ts=<iso>\`).
|
|
377
378
|
- Fill \`## Learnings\` before closeout: either \`- None this stage.\` or JSON bullets with required keys \`type\`, \`trigger\`, \`action\`, \`confidence\` (knowledge-schema compatible).
|
|
378
379
|
- Record mandatory delegation lifecycle in \`${RUNTIME_ROOT}/state/delegation-log.json\` and append proof events to \`${RUNTIME_ROOT}/state/delegation-events.jsonl\`; the ledger is current state, the event log is audit proof.${mandatoryAgents.length > 0 ? ` If a mandatory delegation cannot run in this harness, use \`--waive-delegation=${mandatoryAgents.join(",")} --waiver-reason="<why safe>"\` on the completion helper.` : ""} If proactive delegations were intentionally skipped, rerun only with \`--accept-proactive-waiver\` (optionally \`--accept-proactive-waiver-reason="<why safe>"\`) after explicit user approval.
|
|
379
|
-
- Never edit raw \`flow-state.json\` to complete a stage, even in advisory mode; that bypasses validation, gate evidence, and Learnings harvest. If
|
|
380
|
+
- Never edit raw \`flow-state.json\` to complete a stage, even in advisory mode; that bypasses validation, gate evidence, and Learnings harvest. If a helper fails, report a one-line human-readable failure plus fenced JSON diagnostics; never echo the invoking command line or apply a manual state workaround.
|
|
380
381
|
- Completion protocol: verify required gates, update the artifact, then use the completion helper with \`--evidence-json\` and \`--passed\` for every satisfied gate.
|
|
381
382
|
`;
|
|
382
383
|
}
|
|
@@ -607,3 +608,54 @@ ${reviewSectionsBlock(reviewLens.reviewSections)}
|
|
|
607
608
|
- Keep decisions explicit: context, options, chosen option, rationale, risk, and rollback.
|
|
608
609
|
`;
|
|
609
610
|
}
|
|
611
|
+
export function executingWavesSkillMarkdown() {
|
|
612
|
+
return `---
|
|
613
|
+
name: executing-waves
|
|
614
|
+
description: "Execute multi-wave work using existing cclaw run resume + verify-current-state — no new CLI needed."
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
# Executing Waves (Persistent Multi-Wave Work)
|
|
618
|
+
|
|
619
|
+
## Overview
|
|
620
|
+
|
|
621
|
+
Long-form work (large refactors, multi-stage uplifts) often spans many waves.
|
|
622
|
+
This skill documents how the controller persists work across waves WITHOUT new
|
|
623
|
+
CLI commands, using existing \`cclaw run resume\` and \`internal verify-current-state\`.
|
|
624
|
+
|
|
625
|
+
## When to Use
|
|
626
|
+
|
|
627
|
+
- Work spans 2+ commits / waves with cohesion concerns between waves.
|
|
628
|
+
- Each wave has its own stage cycle (brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship).
|
|
629
|
+
- User wants explicit per-wave verification before the next wave starts.
|
|
630
|
+
- Risk of cross-wave drift exists.
|
|
631
|
+
|
|
632
|
+
## Anti-Pattern
|
|
633
|
+
|
|
634
|
+
- Running many waves linearly without verification between them, accumulating drift.
|
|
635
|
+
- Treating a wave as only a commit boundary without re-verifying upstream decisions.
|
|
636
|
+
|
|
637
|
+
## Process
|
|
638
|
+
|
|
639
|
+
1. **Wave Start**: author wave plan as \`.cclaw/wave-plans/<wave-n>.md\` referencing previous wave's ship artifact.
|
|
640
|
+
2. **Carry-forward Audit**: at brainstorm of the next wave, re-read previous wave ship artifact and explicitly record in the existing \`## Wave Carry-forward\` section:
|
|
641
|
+
- Carrying forward: <scope LD# hash references still valid>
|
|
642
|
+
- Drift detected: <decisions no longer valid + reason>
|
|
643
|
+
- Re-scope needed: <yes/no>
|
|
644
|
+
- Never create a second \`## Locked Decisions\` heading in brainstorm; reference prior LD# hashes inline.
|
|
645
|
+
3. **Resume Path**: if a wave was interrupted mid-stage, \`cclaw run resume\` restores state. Run \`internal verify-current-state\` before continuing.
|
|
646
|
+
4. **Wave End**: at ship, architect cross-stage verification runs from dispatch matrix. If \`DRIFT_DETECTED\`, fix before ship.
|
|
647
|
+
5. **Next Wave Trigger**: launch new \`/cc <topic>\` for next wave and reference previous wave ship artifact in upstream handoff.
|
|
648
|
+
|
|
649
|
+
## Status Markers
|
|
650
|
+
|
|
651
|
+
- \`wave-status: in-progress\` — current stage incomplete.
|
|
652
|
+
- \`wave-status: blocked-by-prev\` — waiting on previous wave verification.
|
|
653
|
+
- \`wave-status: shipped\` — wave shipped, next wave can start.
|
|
654
|
+
- \`wave-status: rolled-back\` — previous wave invalidated, current wave needs rebase.
|
|
655
|
+
|
|
656
|
+
## Linter Hooks
|
|
657
|
+
|
|
658
|
+
- If multi-wave work is detected (>1 wave-plan files in \`.cclaw/wave-plans/\`), current brainstorm artifact MUST contain \`## Wave Carry-forward\` section with drift audit.
|
|
659
|
+
- If carry-forward drift is missing in multi-wave context, emit \`[P1] wave.drift_unaddressed\`.
|
|
660
|
+
`;
|
|
661
|
+
}
|