cclaw-cli 0.18.0 → 0.21.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/constants.d.ts +1 -1
- package/dist/constants.js +2 -0
- package/dist/content/compound-command.d.ts +2 -0
- package/dist/content/compound-command.js +72 -0
- package/dist/content/harnesses-doc.js +3 -1
- package/dist/content/ideate-command.d.ts +2 -0
- package/dist/content/ideate-command.js +73 -0
- package/dist/content/meta-skill.js +5 -2
- package/dist/content/next-command.js +3 -3
- package/dist/content/ops-command.js +4 -2
- package/dist/content/protocols.js +28 -11
- package/dist/content/retro-command.js +2 -1
- package/dist/content/skills.js +12 -5
- package/dist/content/stages/review.js +20 -0
- package/dist/content/stages/ship.js +1 -0
- package/dist/content/utility-skills.d.ts +3 -1
- package/dist/content/utility-skills.js +90 -0
- package/dist/doctor.js +123 -1
- package/dist/harness-adapters.js +17 -1
- package/dist/install.js +6 -0
- package/dist/policy.js +10 -0
- package/package.json +1 -1
package/dist/constants.d.ts
CHANGED
|
@@ -7,6 +7,6 @@ export declare const DEFAULT_HARNESSES: HarnessId[];
|
|
|
7
7
|
export declare const REQUIRED_DIRS: readonly [".cclaw", ".cclaw/commands", ".cclaw/skills", ".cclaw/contexts", ".cclaw/templates", ".cclaw/artifacts", ".cclaw/worktrees", ".cclaw/state", ".cclaw/runs", ".cclaw/rules", ".cclaw/adapters", ".cclaw/agents", ".cclaw/hooks", ".cclaw/custom-skills"];
|
|
8
8
|
export declare const REQUIRED_GITIGNORE_PATTERNS: readonly ["# cclaw generated artifacts", ".cclaw/", ".claude/commands/cc-*.md", ".claude/commands/cc.md", ".cursor/commands/cc-*.md", ".cursor/commands/cc.md", ".opencode/commands/cc-*.md", ".opencode/commands/cc.md", ".codex/commands/cc-*.md", ".codex/commands/cc.md", ".claude/hooks/hooks.json", ".cursor/hooks.json", ".codex/hooks.json", ".opencode/plugins/cclaw-plugin.mjs", ".cursor/rules/cclaw-workflow.mdc"];
|
|
9
9
|
export declare const COMMAND_FILE_ORDER: FlowStage[];
|
|
10
|
-
export declare const UTILITY_COMMANDS: readonly ["learn", "next", "view", "status", "tree", "diff", "ops", "feature", "tdd-log", "retro", "archive", "rewind"];
|
|
10
|
+
export declare const UTILITY_COMMANDS: readonly ["learn", "next", "ideate", "view", "status", "tree", "diff", "ops", "feature", "tdd-log", "retro", "compound", "archive", "rewind"];
|
|
11
11
|
export declare const SUBAGENT_SKILL_FOLDERS: readonly ["subagent-dev", "parallel-dispatch"];
|
|
12
12
|
export type UtilityCommand = (typeof UTILITY_COMMANDS)[number];
|
package/dist/constants.js
CHANGED
|
@@ -54,6 +54,7 @@ export const COMMAND_FILE_ORDER = [
|
|
|
54
54
|
export const UTILITY_COMMANDS = [
|
|
55
55
|
"learn",
|
|
56
56
|
"next",
|
|
57
|
+
"ideate",
|
|
57
58
|
"view",
|
|
58
59
|
"status",
|
|
59
60
|
"tree",
|
|
@@ -62,6 +63,7 @@ export const UTILITY_COMMANDS = [
|
|
|
62
63
|
"feature",
|
|
63
64
|
"tdd-log",
|
|
64
65
|
"retro",
|
|
66
|
+
"compound",
|
|
65
67
|
"archive",
|
|
66
68
|
"rewind"
|
|
67
69
|
];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { RUNTIME_ROOT } from "../constants.js";
|
|
2
|
+
const COMPOUND_SKILL_FOLDER = "flow-compound";
|
|
3
|
+
const COMPOUND_SKILL_NAME = "flow-compound";
|
|
4
|
+
export function compoundCommandContract() {
|
|
5
|
+
return `# /cc-ops compound
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Lift repeated lessons into durable project assets (rules, protocols, skills)
|
|
10
|
+
so the next run is easier and safer.
|
|
11
|
+
|
|
12
|
+
## HARD-GATE
|
|
13
|
+
|
|
14
|
+
- Do not mutate rules/skills without explicit user approval.
|
|
15
|
+
- Every proposal must cite concrete knowledge evidence (line references or IDs).
|
|
16
|
+
- Keep scope focused: one compound change set per run.
|
|
17
|
+
|
|
18
|
+
## Algorithm
|
|
19
|
+
|
|
20
|
+
1. Read \`${RUNTIME_ROOT}/knowledge.jsonl\`.
|
|
21
|
+
2. Cluster repeated trigger/action pairs.
|
|
22
|
+
3. For clusters with frequency >= 3, propose one lift action:
|
|
23
|
+
- rule update
|
|
24
|
+
- protocol update
|
|
25
|
+
- utility skill update
|
|
26
|
+
4. For each proposal include:
|
|
27
|
+
- why now
|
|
28
|
+
- target file(s)
|
|
29
|
+
- expected risk reduction
|
|
30
|
+
5. Ask user approval for each proposal before writing.
|
|
31
|
+
6. Apply approved lifts and record completion in retro artifact.
|
|
32
|
+
|
|
33
|
+
## Primary skill
|
|
34
|
+
|
|
35
|
+
**${RUNTIME_ROOT}/skills/${COMPOUND_SKILL_FOLDER}/SKILL.md**
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
export function compoundCommandSkillMarkdown() {
|
|
39
|
+
return `---
|
|
40
|
+
name: ${COMPOUND_SKILL_NAME}
|
|
41
|
+
description: "Compound mode: convert repeated learnings into durable rules/protocols/skills."
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
# /cc-ops compound
|
|
45
|
+
|
|
46
|
+
## Announce at start
|
|
47
|
+
|
|
48
|
+
"Using flow-compound to lift repeated learnings into durable workflow assets."
|
|
49
|
+
|
|
50
|
+
## HARD-GATE
|
|
51
|
+
|
|
52
|
+
No silent codification. Every lift requires explicit user approval.
|
|
53
|
+
|
|
54
|
+
## Protocol
|
|
55
|
+
|
|
56
|
+
1. Parse \`.cclaw/knowledge.jsonl\` and group repeated lessons.
|
|
57
|
+
2. Keep only candidates with clear recurrence and actionable lift path.
|
|
58
|
+
3. Propose each candidate using this template:
|
|
59
|
+
|
|
60
|
+
\`\`\`
|
|
61
|
+
Candidate: <short title>
|
|
62
|
+
Evidence: <knowledge refs>
|
|
63
|
+
Lift target: <rule/protocol/skill file>
|
|
64
|
+
Change type: <add/update/remove>
|
|
65
|
+
Expected benefit: <what regressions this prevents>
|
|
66
|
+
\`\`\`
|
|
67
|
+
|
|
68
|
+
4. Ask user to approve/reject per candidate.
|
|
69
|
+
5. Apply only approved candidates.
|
|
70
|
+
6. Append a \`compound\` learning entry summarizing what was lifted.
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
@@ -65,9 +65,10 @@ All harnesses receive the same utility commands:
|
|
|
65
65
|
|
|
66
66
|
- \`/cc\` - flow entry and resume
|
|
67
67
|
- \`/cc-next\` - stage progression
|
|
68
|
+
- \`/cc-ideate\` - discovery mode for ranked repo-improvement backlog
|
|
68
69
|
- \`/cc-view\` - read-only router for status/tree/diff
|
|
69
70
|
- \`/cc-learn\` - knowledge capture/lookup
|
|
70
|
-
- \`/cc-ops\` - operations router for feature/tdd-log/retro/archive/rewind
|
|
71
|
+
- \`/cc-ops\` - operations router for feature/tdd-log/retro/compound/archive/rewind
|
|
71
72
|
|
|
72
73
|
Read-only subcommands:
|
|
73
74
|
- \`/cc-view status\` - visual flow snapshot
|
|
@@ -78,6 +79,7 @@ Operations subcommands:
|
|
|
78
79
|
- \`/cc-ops feature ...\` - git-worktree feature isolation and routing
|
|
79
80
|
- \`/cc-ops tdd-log ...\` - explicit RED/GREEN/REFACTOR evidence log
|
|
80
81
|
- \`/cc-ops retro\` - mandatory retrospective gate before archive
|
|
82
|
+
- \`/cc-ops compound\` - lift repeated learnings into durable rules/skills
|
|
81
83
|
- \`/cc-ops archive\` - archive active run from harness flow
|
|
82
84
|
- \`/cc-ops rewind ...\` - rewind flow and invalidate downstream stages
|
|
83
85
|
- \`/cc-ops rewind --ack ...\` - clear stale stage markers after redo
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { RUNTIME_ROOT } from "../constants.js";
|
|
2
|
+
const IDEATE_SKILL_FOLDER = "flow-ideate";
|
|
3
|
+
const IDEATE_SKILL_NAME = "flow-ideate";
|
|
4
|
+
export function ideateCommandContract() {
|
|
5
|
+
return `# /cc-ideate
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Repository-improvement discovery mode. Generate a ranked backlog of high-value
|
|
10
|
+
improvements before committing to a specific feature request.
|
|
11
|
+
|
|
12
|
+
## HARD-GATE
|
|
13
|
+
|
|
14
|
+
- This is discovery mode only. Do not start implementation automatically.
|
|
15
|
+
- Every recommendation must include evidence from the current repository.
|
|
16
|
+
- End with a decision prompt: pick one candidate or cancel.
|
|
17
|
+
|
|
18
|
+
## Algorithm
|
|
19
|
+
|
|
20
|
+
1. Scan repo signals:
|
|
21
|
+
- open TODO/backlog notes
|
|
22
|
+
- flaky or failing tests
|
|
23
|
+
- oversized modules / complexity hotspots
|
|
24
|
+
- docs drift vs changed code
|
|
25
|
+
- repeated learnings from \`.cclaw/knowledge.jsonl\`
|
|
26
|
+
2. Produce 5-10 candidates with:
|
|
27
|
+
- impact (High/Medium/Low)
|
|
28
|
+
- effort (S/M/L)
|
|
29
|
+
- confidence (High/Medium/Low)
|
|
30
|
+
- evidence path(s)
|
|
31
|
+
3. Rank candidates by impact/effort ratio.
|
|
32
|
+
4. Present one recommendation as default.
|
|
33
|
+
5. Ask user to choose:
|
|
34
|
+
- (A) start with recommended item
|
|
35
|
+
- (B) choose another candidate
|
|
36
|
+
- (C) cancel
|
|
37
|
+
|
|
38
|
+
## Primary skill
|
|
39
|
+
|
|
40
|
+
**${RUNTIME_ROOT}/skills/${IDEATE_SKILL_FOLDER}/SKILL.md**
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
export function ideateCommandSkillMarkdown() {
|
|
44
|
+
return `---
|
|
45
|
+
name: ${IDEATE_SKILL_NAME}
|
|
46
|
+
description: "Repository ideation mode: detect and rank high-leverage improvements before implementation."
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
# /cc-ideate
|
|
50
|
+
|
|
51
|
+
## Announce at start
|
|
52
|
+
|
|
53
|
+
"Using flow-ideate to identify highest-leverage improvements in this repository."
|
|
54
|
+
|
|
55
|
+
## HARD-GATE
|
|
56
|
+
|
|
57
|
+
Do not start coding in ideate mode. End with an explicit user choice.
|
|
58
|
+
|
|
59
|
+
## Protocol
|
|
60
|
+
|
|
61
|
+
1. Collect evidence from the current repo state.
|
|
62
|
+
2. Build candidate improvements with impact/effort/confidence.
|
|
63
|
+
3. Rank and recommend one candidate.
|
|
64
|
+
4. Ask for explicit selection.
|
|
65
|
+
5. If user selects a candidate, hand off to \`/cc <selected idea>\`.
|
|
66
|
+
|
|
67
|
+
## Candidate format
|
|
68
|
+
|
|
69
|
+
| ID | Improvement | Impact | Effort | Confidence | Evidence |
|
|
70
|
+
|---|---|---|---|---|---|
|
|
71
|
+
| I-1 | | High/Medium/Low | S/M/L | High/Medium/Low | path or command evidence |
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
@@ -3,7 +3,7 @@ export const META_SKILL_NAME = "using-cclaw";
|
|
|
3
3
|
export function usingCclawSkillMarkdown() {
|
|
4
4
|
return `---
|
|
5
5
|
name: using-cclaw
|
|
6
|
-
description: "Routing brain for cclaw. Decide whether to start/resume a stage, answer directly, or use utility commands like /cc-learn, /cc-view, and /cc-ops."
|
|
6
|
+
description: "Routing brain for cclaw. Decide whether to start/resume a stage, answer directly, or use utility commands like /cc-learn, /cc-ideate, /cc-view, and /cc-ops."
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Using Cclaw
|
|
@@ -25,10 +25,11 @@ Task arrives
|
|
|
25
25
|
├─ Running as spawned subagent? -> obey parent prompt only; do not run cclaw routing
|
|
26
26
|
├─ Pure question / non-software ask? -> answer directly (no stage)
|
|
27
27
|
├─ New software work? -> /cc <idea>
|
|
28
|
+
├─ Repo-improvement discovery? -> /cc-ideate
|
|
28
29
|
├─ Resume existing flow? -> /cc or /cc-next
|
|
29
30
|
├─ Knowledge operation? -> /cc-learn
|
|
30
31
|
├─ Read-only workspace view? -> /cc-view [status|tree|diff]
|
|
31
|
-
└─ Workspace operation? -> /cc-ops [feature|tdd-log|retro|archive|rewind]
|
|
32
|
+
└─ Workspace operation? -> /cc-ops [feature|tdd-log|retro|compound|archive|rewind]
|
|
32
33
|
\`\`\`
|
|
33
34
|
|
|
34
35
|
## Task classification
|
|
@@ -60,6 +61,8 @@ Tracks may skip stages via \`flow-state.track\` + \`skippedStages\`.
|
|
|
60
61
|
Load utility skills only when triggered by the current task:
|
|
61
62
|
|
|
62
63
|
- security, performance, debugging, docs, ci-cd
|
|
64
|
+
- verification-before-completion before completion claims
|
|
65
|
+
- finishing-a-development-branch during ship/finalization
|
|
63
66
|
- document-review and execution context skills
|
|
64
67
|
- language rule packs from \`.cclaw/config.yaml\` when enabled
|
|
65
68
|
|
|
@@ -33,7 +33,7 @@ This is the only progression command the user needs to drive the entire flow. St
|
|
|
33
33
|
|
|
34
34
|
- **Do not** invent gate completion: use only \`${flowPath}\` plus observable evidence in repo artifacts.
|
|
35
35
|
- **Do not** skip stages: advance only from \`currentStage\` to its configured successor.
|
|
36
|
-
- If the flow reaches terminal ship completion, route closeout in order: **/cc-ops retro -> /cc-ops archive**.
|
|
36
|
+
- If the flow reaches terminal ship completion, route closeout in order: **/cc-ops retro -> /cc-ops compound (optional) -> /cc-ops archive**.
|
|
37
37
|
|
|
38
38
|
## Algorithm (mandatory)
|
|
39
39
|
|
|
@@ -56,7 +56,7 @@ This is the only progression command the user needs to drive the entire flow. St
|
|
|
56
56
|
|
|
57
57
|
→ If current stage's \`next\` is **\`done\`**:
|
|
58
58
|
- if \`currentStage === "ship"\` and \`retro.completedAt\` is missing -> route to \`/cc-ops retro\`,
|
|
59
|
-
- if \`currentStage === "ship"\` and \`retro.completedAt\` is present -> route to \`/cc-ops archive\`,
|
|
59
|
+
- if \`currentStage === "ship"\` and \`retro.completedAt\` is present -> suggest \`/cc-ops compound\` then route to \`/cc-ops archive\`,
|
|
60
60
|
- otherwise report **"Flow complete. All stages finished."** and stop.
|
|
61
61
|
→ Otherwise: load **\`${RUNTIME_ROOT}/skills/<skillFolder>/SKILL.md\`** and **\`${RUNTIME_ROOT}/commands/<nextStage>.md\`** for the successor stage. Execute that stage's protocol.
|
|
62
62
|
|
|
@@ -150,7 +150,7 @@ Execute the stage protocol. The stage skill handles interaction, STOP points, ga
|
|
|
150
150
|
If \`next\` is \`done\`:
|
|
151
151
|
|
|
152
152
|
- If \`currentStage\` is \`ship\` and \`retro.completedAt\` is missing -> route to \`/cc-ops retro\`.
|
|
153
|
-
- If \`currentStage\` is \`ship\` and \`retro.completedAt\` exists -> route to \`/cc-ops archive\`.
|
|
153
|
+
- If \`currentStage\` is \`ship\` and \`retro.completedAt\` exists -> suggest \`/cc-ops compound\`, then route to \`/cc-ops archive\`.
|
|
154
154
|
- Otherwise report **"Flow complete. All stages finished."** and stop.
|
|
155
155
|
|
|
156
156
|
Otherwise load the next stage's skill and command contract, begin execution.
|
|
@@ -12,6 +12,7 @@ Subcommands:
|
|
|
12
12
|
- \`feature\` -> \`/cc-ops feature\`
|
|
13
13
|
- \`tdd-log\` -> \`/cc-ops tdd-log\`
|
|
14
14
|
- \`retro\` -> \`/cc-ops retro\`
|
|
15
|
+
- \`compound\` -> \`/cc-ops compound\`
|
|
15
16
|
- \`archive\` -> \`/cc-ops archive\`
|
|
16
17
|
- \`rewind\` -> \`/cc-ops rewind\`
|
|
17
18
|
|
|
@@ -27,6 +28,7 @@ Subcommands:
|
|
|
27
28
|
- \`feature\` -> \`${RUNTIME_ROOT}/commands/feature.md\`
|
|
28
29
|
- \`tdd-log\` -> \`${RUNTIME_ROOT}/commands/tdd-log.md\`
|
|
29
30
|
- \`retro\` -> \`${RUNTIME_ROOT}/commands/retro.md\`
|
|
31
|
+
- \`compound\` -> \`${RUNTIME_ROOT}/commands/compound.md\`
|
|
30
32
|
- \`archive\` -> \`${RUNTIME_ROOT}/commands/archive.md\`
|
|
31
33
|
- \`rewind\` -> \`${RUNTIME_ROOT}/commands/rewind.md\`
|
|
32
34
|
3. Unknown subcommand -> print supported values and stop.
|
|
@@ -39,7 +41,7 @@ Subcommands:
|
|
|
39
41
|
export function opsCommandSkillMarkdown() {
|
|
40
42
|
return `---
|
|
41
43
|
name: ${OPS_SKILL_NAME}
|
|
42
|
-
description: "Unified operational router for feature/tdd-log/retro/archive/rewind commands."
|
|
44
|
+
description: "Unified operational router for feature/tdd-log/retro/compound/archive/rewind commands."
|
|
43
45
|
---
|
|
44
46
|
|
|
45
47
|
# /cc-ops
|
|
@@ -50,7 +52,7 @@ This wrapper only dispatches. It must not apply state mutations itself.
|
|
|
50
52
|
|
|
51
53
|
## Protocol
|
|
52
54
|
|
|
53
|
-
1. Require a subcommand (\`feature|tdd-log|retro|archive|rewind\`).
|
|
55
|
+
1. Require a subcommand (\`feature|tdd-log|retro|compound|archive|rewind\`).
|
|
54
56
|
2. Route to the matching command contract + skill pair.
|
|
55
57
|
3. Preserve pass-through args after the subcommand (e.g. \`/cc-ops rewind design\`).
|
|
56
58
|
4. Echo which subcommand was dispatched for auditability.
|
|
@@ -75,7 +75,12 @@ export function ethosProtocolMarkdown() {
|
|
|
75
75
|
|
|
76
76
|
Shared operating principles across all stages.
|
|
77
77
|
|
|
78
|
-
##
|
|
78
|
+
## 1) Boil the Lake
|
|
79
|
+
|
|
80
|
+
When the "complete version" costs only slightly more than a shortcut, prefer the
|
|
81
|
+
complete version. Do not leave obvious quality gaps for hypothetical follow-ups.
|
|
82
|
+
|
|
83
|
+
## 2) Search Before Building
|
|
79
84
|
|
|
80
85
|
Before adding new code/templates/rules:
|
|
81
86
|
|
|
@@ -84,13 +89,30 @@ Before adding new code/templates/rules:
|
|
|
84
89
|
3. Search codebase for reusable implementations.
|
|
85
90
|
4. Prefer built-in/library primitives over custom helpers.
|
|
86
91
|
|
|
87
|
-
##
|
|
92
|
+
## 3) User Sovereignty
|
|
93
|
+
|
|
94
|
+
AI recommends. User decides. If your recommendation changes the user's stated
|
|
95
|
+
direction, ask first and wait for explicit approval.
|
|
96
|
+
|
|
97
|
+
## 4) Iron-Law Discipline
|
|
98
|
+
|
|
99
|
+
Every stage has a non-negotiable Iron Law. If a proposed action violates it,
|
|
100
|
+
stop and escalate via Decision Protocol instead of rationalizing exceptions.
|
|
101
|
+
|
|
102
|
+
## 5) Complete Before Ship
|
|
88
103
|
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
104
|
+
No release shortcuts:
|
|
105
|
+
- review verdict must be explicit,
|
|
106
|
+
- preflight evidence must be fresh,
|
|
107
|
+
- rollback must be written before finalization.
|
|
92
108
|
|
|
93
|
-
##
|
|
109
|
+
## 6) Compound, Don't Repeat
|
|
110
|
+
|
|
111
|
+
When a reusable lesson appears, add one strict-schema JSONL entry via
|
|
112
|
+
\`/cc-learn add\`. Repeated lessons should be lifted into stable rules/skills so
|
|
113
|
+
the same class of mistake gets harder to repeat.
|
|
114
|
+
|
|
115
|
+
## Turn Announce Discipline
|
|
94
116
|
|
|
95
117
|
Keep orchestration visible without maintaining a dedicated preamble runtime log.
|
|
96
118
|
|
|
@@ -98,10 +120,5 @@ Keep orchestration visible without maintaining a dedicated preamble runtime log.
|
|
|
98
120
|
- Skip announce for trivial single-command actions.
|
|
99
121
|
- Never repeat boilerplate announces when the intent did not change.
|
|
100
122
|
- If plan or risk changes materially, post a fresh announce before executing.
|
|
101
|
-
|
|
102
|
-
## Operational learning
|
|
103
|
-
|
|
104
|
-
When a reusable lesson appears, add one strict-schema JSONL entry via
|
|
105
|
-
\`/cc-learn add\`. Keep the knowledge store append-only.
|
|
106
123
|
`;
|
|
107
124
|
}
|
|
@@ -36,7 +36,7 @@ Mandatory retrospective gate before archive once ship is complete.
|
|
|
36
36
|
- \`required: true\`
|
|
37
37
|
- \`completedAt: <ISO>\`
|
|
38
38
|
- \`compoundEntries: <count>\`
|
|
39
|
-
5. Report completion summary and remind user that \`/cc-ops
|
|
39
|
+
5. Report completion summary and remind user that \`/cc-ops compound\` (optional) can lift repeated learnings before \`/cc-ops archive\`.
|
|
40
40
|
|
|
41
41
|
## Primary skill
|
|
42
42
|
|
|
@@ -67,6 +67,7 @@ Archive must remain blocked until retro artifact exists and compound knowledge w
|
|
|
67
67
|
5. Print explicit completion line:
|
|
68
68
|
- \`retro gate: complete\`
|
|
69
69
|
- \`compound entries added: <N>\`
|
|
70
|
+
- \`next: /cc-ops compound (optional) -> /cc-ops archive\`
|
|
70
71
|
|
|
71
72
|
## Validation
|
|
72
73
|
|
package/dist/content/skills.js
CHANGED
|
@@ -98,6 +98,9 @@ Provide fresh, stage-local verification evidence from this turn:
|
|
|
98
98
|
1. Run verification commands (tests/build/lint/type-check) for the changed scope.
|
|
99
99
|
2. Confirm output, do not infer success from prior runs.
|
|
100
100
|
3. If this is a bug fix, capture RED -> GREEN evidence for the regression path.
|
|
101
|
+
|
|
102
|
+
Reference utility skill:
|
|
103
|
+
\`.cclaw/skills/verification-before-completion/SKILL.md\`
|
|
101
104
|
`;
|
|
102
105
|
}
|
|
103
106
|
function waveExecutionModeBlock(stage) {
|
|
@@ -191,11 +194,14 @@ function stageSpecificSeeAlso(stage) {
|
|
|
191
194
|
],
|
|
192
195
|
review: [
|
|
193
196
|
`- \`${RUNTIME_ROOT}/skills/security/SKILL.md\``,
|
|
194
|
-
`- \`${RUNTIME_ROOT}/skills/parallel-dispatch/SKILL.md
|
|
197
|
+
`- \`${RUNTIME_ROOT}/skills/parallel-dispatch/SKILL.md\``,
|
|
198
|
+
`- \`${RUNTIME_ROOT}/skills/verification-before-completion/SKILL.md\``
|
|
195
199
|
],
|
|
196
200
|
ship: [
|
|
197
201
|
`- \`${RUNTIME_ROOT}/skills/ci-cd/SKILL.md\``,
|
|
198
|
-
`- \`${RUNTIME_ROOT}/skills/docs/SKILL.md
|
|
202
|
+
`- \`${RUNTIME_ROOT}/skills/docs/SKILL.md\``,
|
|
203
|
+
`- \`${RUNTIME_ROOT}/skills/verification-before-completion/SKILL.md\``,
|
|
204
|
+
`- \`${RUNTIME_ROOT}/skills/finishing-a-development-branch/SKILL.md\``
|
|
199
205
|
]
|
|
200
206
|
};
|
|
201
207
|
return refs[stage];
|
|
@@ -226,9 +232,10 @@ function quickStartBlock(stage) {
|
|
|
226
232
|
const gatePreview = schema.requiredGates.slice(0, 3).map((g) => `\`${g.id}\``).join(", ");
|
|
227
233
|
return `## Quick Start
|
|
228
234
|
|
|
229
|
-
1.
|
|
230
|
-
2.
|
|
231
|
-
3.
|
|
235
|
+
1. Announce at start: "Using \`${schema.skillName}\` to ${schema.purpose}".
|
|
236
|
+
2. Obey HARD-GATE and Iron Law.
|
|
237
|
+
3. Execute checklist in order and persist \`${RUNTIME_ROOT}/artifacts/${schema.artifactFile}\`.
|
|
238
|
+
4. Satisfy gates (${gatePreview}${schema.requiredGates.length > 3 ? ` +${schema.requiredGates.length - 3}` : ""}).
|
|
232
239
|
`;
|
|
233
240
|
}
|
|
234
241
|
/**
|
|
@@ -168,6 +168,26 @@ export const REVIEW = {
|
|
|
168
168
|
],
|
|
169
169
|
stopGate: true
|
|
170
170
|
},
|
|
171
|
+
{
|
|
172
|
+
title: "Specialist Lens: Data & Migration Safety",
|
|
173
|
+
evaluationPoints: [
|
|
174
|
+
"Schema/data migrations are reversible and include backfill/rollback strategy",
|
|
175
|
+
"Idempotency expectations are explicit for retryable flows",
|
|
176
|
+
"Data-loss scenarios (truncate/overwrite/drop) are guarded by checks or dry-runs",
|
|
177
|
+
"Boundary contracts (API/schema/event payload) maintain backward compatibility or are versioned"
|
|
178
|
+
],
|
|
179
|
+
stopGate: false
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
title: "Specialist Lens: Developer Experience",
|
|
183
|
+
evaluationPoints: [
|
|
184
|
+
"New behavior includes discoverable docs/usage notes where needed",
|
|
185
|
+
"Error messages are actionable for on-call and local debugging",
|
|
186
|
+
"Default configuration remains safe and unsurprising",
|
|
187
|
+
"Change footprint stays minimal and avoids hidden coupling"
|
|
188
|
+
],
|
|
189
|
+
stopGate: false
|
|
190
|
+
},
|
|
171
191
|
{
|
|
172
192
|
title: "Meta-Review: Verify the Verification",
|
|
173
193
|
evaluationPoints: [
|
|
@@ -26,6 +26,7 @@ export const SHIP = {
|
|
|
26
26
|
"Re-run tests on merged result — if merging locally, run the full test suite AFTER the merge, not just before. Post-merge failures are common.",
|
|
27
27
|
"Generate release notes — summarize what changed, why, and what it affects. Reference spec criteria. Include: breaking changes, new dependencies, migration steps if any.",
|
|
28
28
|
"Write rollback plan — trigger conditions (what tells you it is broken), rollback steps (exact commands/git operations), and verification (how to confirm rollback worked).",
|
|
29
|
+
"Load utility skills — `verification-before-completion` for fresh evidence and `finishing-a-development-branch` for finalization workflow.",
|
|
29
30
|
"Monitoring checklist — what should be watched after deploy? Error rates, latency, key business metrics. If no monitoring exists, flag it as a risk.",
|
|
30
31
|
"Select finalization mode — exactly ONE enum: (A) FINALIZE_MERGE_LOCAL, (B) FINALIZE_OPEN_PR, (C) FINALIZE_KEEP_BRANCH, (D) FINALIZE_DISCARD_BRANCH. For discard: list what will be deleted, require typed confirmation.",
|
|
31
32
|
"Execute finalization — perform the selected action. For merge: verify clean merge. For PR: include structured body (summary, test plan, rollback). For discard: verify deletion.",
|
|
@@ -10,6 +10,8 @@ export declare function ciCdSkill(): string;
|
|
|
10
10
|
export declare function docsSkill(): string;
|
|
11
11
|
export declare function executingPlansSkill(): string;
|
|
12
12
|
export declare function contextEngineeringSkill(): string;
|
|
13
|
+
export declare function verificationBeforeCompletionSkill(): string;
|
|
14
|
+
export declare function finishingDevelopmentBranchSkill(): string;
|
|
13
15
|
export declare function sourceDrivenDevelopmentSkill(): string;
|
|
14
16
|
export declare function frontendAccessibilitySkill(): string;
|
|
15
17
|
export declare function landscapeCheckSkill(): string;
|
|
@@ -44,5 +46,5 @@ export declare const LANGUAGE_RULE_PACK_GENERATORS: Record<string, () => string>
|
|
|
44
46
|
* clean them up after the move to `.cclaw/rules/lang/`.
|
|
45
47
|
*/
|
|
46
48
|
export declare const LEGACY_LANGUAGE_RULE_PACK_FOLDERS: readonly ["language-typescript", "language-python", "language-go"];
|
|
47
|
-
export declare const UTILITY_SKILL_FOLDERS: readonly ["security", "debugging", "performance", "ci-cd", "docs", "executing-plans", "context-engineering", "source-driven-development", "frontend-accessibility", "landscape-check", "adversarial-review", "security-audit", "knowledge-curation", "retrospective", "document-review"];
|
|
49
|
+
export declare const UTILITY_SKILL_FOLDERS: readonly ["security", "debugging", "performance", "ci-cd", "docs", "executing-plans", "verification-before-completion", "finishing-a-development-branch", "context-engineering", "source-driven-development", "frontend-accessibility", "landscape-check", "adversarial-review", "security-audit", "knowledge-curation", "retrospective", "document-review"];
|
|
48
50
|
export declare const UTILITY_SKILL_MAP: Record<string, () => string>;
|
|
@@ -594,6 +594,92 @@ Modes are stored in \`.cclaw/contexts/\`:
|
|
|
594
594
|
- Shipping decisions based on stale pre-compaction context.
|
|
595
595
|
`;
|
|
596
596
|
}
|
|
597
|
+
export function verificationBeforeCompletionSkill() {
|
|
598
|
+
return `---
|
|
599
|
+
name: verification-before-completion
|
|
600
|
+
description: "Final verification discipline before stage closeout or ship. Use when preparing a completion claim."
|
|
601
|
+
---
|
|
602
|
+
|
|
603
|
+
# Verification Before Completion
|
|
604
|
+
|
|
605
|
+
## Announce at start
|
|
606
|
+
|
|
607
|
+
"Using verification-before-completion to validate fresh evidence before completion."
|
|
608
|
+
|
|
609
|
+
## HARD-GATE
|
|
610
|
+
|
|
611
|
+
Do not claim completion from memory. Every pass claim requires fresh, in-turn evidence.
|
|
612
|
+
|
|
613
|
+
## Protocol
|
|
614
|
+
|
|
615
|
+
1. Identify changed scope (files, modules, user-facing behaviors).
|
|
616
|
+
2. Run the smallest command set that still proves the scope:
|
|
617
|
+
- tests for changed area
|
|
618
|
+
- typecheck/build/lint if the stack requires it
|
|
619
|
+
3. Capture exact command + pass/fail output in the artifact.
|
|
620
|
+
4. If this is a bug fix, include RED -> GREEN regression evidence.
|
|
621
|
+
5. If any check fails, stop completion and return to fix loop.
|
|
622
|
+
|
|
623
|
+
## Completion claim checklist
|
|
624
|
+
|
|
625
|
+
- [ ] Commands were run in this turn (not reused from earlier output).
|
|
626
|
+
- [ ] Output corresponds to the actual changed scope.
|
|
627
|
+
- [ ] Failures (if any) are resolved or explicitly escalated.
|
|
628
|
+
- [ ] Artifact includes evidence references.
|
|
629
|
+
- [ ] Completion status reflects evidence (DONE / DONE_WITH_CONCERNS / BLOCKED).
|
|
630
|
+
|
|
631
|
+
## Anti-patterns
|
|
632
|
+
|
|
633
|
+
- "Tests passed earlier today" without rerunning.
|
|
634
|
+
- Reporting only "PASS" without command context.
|
|
635
|
+
- Running unrelated checks while skipping changed scope checks.
|
|
636
|
+
- Marking DONE while blockers still fail.
|
|
637
|
+
`;
|
|
638
|
+
}
|
|
639
|
+
export function finishingDevelopmentBranchSkill() {
|
|
640
|
+
return `---
|
|
641
|
+
name: finishing-a-development-branch
|
|
642
|
+
description: "Finalize implementation branch after review: verify, choose integration mode, execute safely, and clean up."
|
|
643
|
+
---
|
|
644
|
+
|
|
645
|
+
# Finishing a Development Branch
|
|
646
|
+
|
|
647
|
+
## Announce at start
|
|
648
|
+
|
|
649
|
+
"Using finishing-a-development-branch to complete this branch safely."
|
|
650
|
+
|
|
651
|
+
## HARD-GATE
|
|
652
|
+
|
|
653
|
+
Do not merge, open PR, or discard branch until verification and rollback notes are explicit.
|
|
654
|
+
|
|
655
|
+
## Protocol
|
|
656
|
+
|
|
657
|
+
1. Verify readiness:
|
|
658
|
+
- review verdict is APPROVED or APPROVED_WITH_CONCERNS
|
|
659
|
+
- verification-before-completion checklist is satisfied
|
|
660
|
+
2. Choose one finalization mode:
|
|
661
|
+
- FINALIZE_MERGE_LOCAL
|
|
662
|
+
- FINALIZE_OPEN_PR
|
|
663
|
+
- FINALIZE_KEEP_BRANCH
|
|
664
|
+
- FINALIZE_DISCARD_BRANCH
|
|
665
|
+
3. Execute only the chosen mode and record exact result.
|
|
666
|
+
4. If merge or discard happened in a feature worktree, clean the worktree.
|
|
667
|
+
5. Update ship artifact with release notes, rollback, and finalization evidence.
|
|
668
|
+
|
|
669
|
+
## Rollback minimum
|
|
670
|
+
|
|
671
|
+
- Trigger: what tells us release is wrong.
|
|
672
|
+
- Steps: exact revert/reset/rollback commands.
|
|
673
|
+
- Verification: how we confirm rollback worked.
|
|
674
|
+
|
|
675
|
+
## Anti-patterns
|
|
676
|
+
|
|
677
|
+
- Multiple finalization modes in one run.
|
|
678
|
+
- Merge without rollback section.
|
|
679
|
+
- PR without test/verification summary.
|
|
680
|
+
- Discarding branch without explicit user confirmation.
|
|
681
|
+
`;
|
|
682
|
+
}
|
|
597
683
|
export function sourceDrivenDevelopmentSkill() {
|
|
598
684
|
return `---
|
|
599
685
|
name: source-driven-development
|
|
@@ -1524,6 +1610,8 @@ export const UTILITY_SKILL_FOLDERS = [
|
|
|
1524
1610
|
"ci-cd",
|
|
1525
1611
|
"docs",
|
|
1526
1612
|
"executing-plans",
|
|
1613
|
+
"verification-before-completion",
|
|
1614
|
+
"finishing-a-development-branch",
|
|
1527
1615
|
"context-engineering",
|
|
1528
1616
|
"source-driven-development",
|
|
1529
1617
|
"frontend-accessibility",
|
|
@@ -1541,6 +1629,8 @@ export const UTILITY_SKILL_MAP = {
|
|
|
1541
1629
|
"ci-cd": ciCdSkill,
|
|
1542
1630
|
docs: docsSkill,
|
|
1543
1631
|
"executing-plans": executingPlansSkill,
|
|
1632
|
+
"verification-before-completion": verificationBeforeCompletionSkill,
|
|
1633
|
+
"finishing-a-development-branch": finishingDevelopmentBranchSkill,
|
|
1544
1634
|
"context-engineering": contextEngineeringSkill,
|
|
1545
1635
|
"source-driven-development": sourceDrivenDevelopmentSkill,
|
|
1546
1636
|
"frontend-accessibility": frontendAccessibilitySkill,
|
package/dist/doctor.js
CHANGED
|
@@ -34,6 +34,27 @@ async function isGitRepo(projectRoot) {
|
|
|
34
34
|
return false;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
async function gitWorktreePaths(projectRoot) {
|
|
38
|
+
try {
|
|
39
|
+
const { stdout } = await execFileAsync("git", ["worktree", "list", "--porcelain"], {
|
|
40
|
+
cwd: projectRoot
|
|
41
|
+
});
|
|
42
|
+
const out = new Set();
|
|
43
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
44
|
+
const trimmed = line.trim();
|
|
45
|
+
if (!trimmed.startsWith("worktree "))
|
|
46
|
+
continue;
|
|
47
|
+
const rawPath = trimmed.slice("worktree ".length).trim();
|
|
48
|
+
if (!rawPath)
|
|
49
|
+
continue;
|
|
50
|
+
out.add(path.resolve(rawPath));
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return new Set();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
37
58
|
async function resolveGitHooksDir(projectRoot) {
|
|
38
59
|
try {
|
|
39
60
|
const { stdout } = await execFileAsync("git", ["rev-parse", "--git-path", "hooks"], { cwd: projectRoot });
|
|
@@ -462,6 +483,7 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
462
483
|
const hasMarkers = content.includes(CCLAW_MARKER_START) && content.includes(CCLAW_MARKER_END);
|
|
463
484
|
const hasCcCommand = content.includes("/cc");
|
|
464
485
|
const hasCcNext = content.includes("/cc-next");
|
|
486
|
+
const hasCcIdeate = content.includes("/cc-ideate");
|
|
465
487
|
const hasCcLearn = content.includes("/cc-learn");
|
|
466
488
|
const hasCcView = content.includes("/cc-view");
|
|
467
489
|
const hasCcOps = content.includes("/cc-ops");
|
|
@@ -471,6 +493,7 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
471
493
|
agentsBlockOk = hasMarkers
|
|
472
494
|
&& hasCcCommand
|
|
473
495
|
&& hasCcNext
|
|
496
|
+
&& hasCcIdeate
|
|
474
497
|
&& hasCcLearn
|
|
475
498
|
&& hasCcView
|
|
476
499
|
&& hasCcOps
|
|
@@ -484,7 +507,7 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
484
507
|
details: `${agentsFile} must contain the managed cclaw marker block with routing, verification, and minimal detail pointer`
|
|
485
508
|
});
|
|
486
509
|
// Utility commands
|
|
487
|
-
for (const cmd of ["learn", "next", "status", "tree", "diff", "feature", "tdd-log", "retro", "rewind"]) {
|
|
510
|
+
for (const cmd of ["learn", "next", "ideate", "status", "tree", "diff", "feature", "tdd-log", "retro", "compound", "rewind"]) {
|
|
488
511
|
const cmdPath = path.join(projectRoot, RUNTIME_ROOT, "commands", `${cmd}.md`);
|
|
489
512
|
checks.push({
|
|
490
513
|
name: `utility_command:${cmd}`,
|
|
@@ -495,12 +518,16 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
495
518
|
// Utility skills
|
|
496
519
|
for (const [folder, label] of [
|
|
497
520
|
["learnings", "learnings"],
|
|
521
|
+
["flow-ideate", "flow-ideate"],
|
|
498
522
|
["flow-tree", "flow-tree"],
|
|
499
523
|
["flow-diff", "flow-diff"],
|
|
500
524
|
["using-git-worktrees", "using-git-worktrees"],
|
|
501
525
|
["tdd-cycle-log", "tdd-cycle-log"],
|
|
502
526
|
["flow-retro", "flow-retro"],
|
|
527
|
+
["flow-compound", "flow-compound"],
|
|
503
528
|
["flow-rewind", "flow-rewind"],
|
|
529
|
+
["verification-before-completion", "verification-before-completion"],
|
|
530
|
+
["finishing-a-development-branch", "finishing-a-development-branch"],
|
|
504
531
|
["subagent-dev", "sdd"],
|
|
505
532
|
["parallel-dispatch", "parallel-agents"],
|
|
506
533
|
["session", "session"],
|
|
@@ -834,6 +861,8 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
834
861
|
let malformedKnowledgeLines = 0;
|
|
835
862
|
let missingSchemaV2Fields = 0;
|
|
836
863
|
let parsedKnowledgeLines = 0;
|
|
864
|
+
let lowConfidenceLines = 0;
|
|
865
|
+
const triggerActionCounts = new Map();
|
|
837
866
|
const requiredV2Fields = [
|
|
838
867
|
"type",
|
|
839
868
|
"trigger",
|
|
@@ -865,6 +894,16 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
865
894
|
continue;
|
|
866
895
|
}
|
|
867
896
|
parsedKnowledgeLines += 1;
|
|
897
|
+
const confidence = typeof parsed.confidence === "string" ? parsed.confidence.toLowerCase() : "";
|
|
898
|
+
if (confidence === "low") {
|
|
899
|
+
lowConfidenceLines += 1;
|
|
900
|
+
}
|
|
901
|
+
const trigger = typeof parsed.trigger === "string" ? parsed.trigger.trim().toLowerCase() : "";
|
|
902
|
+
const action = typeof parsed.action === "string" ? parsed.action.trim().toLowerCase() : "";
|
|
903
|
+
if (trigger.length > 0 && action.length > 0) {
|
|
904
|
+
const key = `${trigger} => ${action}`;
|
|
905
|
+
triggerActionCounts.set(key, (triggerActionCounts.get(key) ?? 0) + 1);
|
|
906
|
+
}
|
|
868
907
|
const missing = requiredV2Fields.some((field) => !Object.prototype.hasOwnProperty.call(parsed, field));
|
|
869
908
|
if (missing) {
|
|
870
909
|
missingSchemaV2Fields += 1;
|
|
@@ -894,6 +933,24 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
894
933
|
? `all ${parsedKnowledgeLines} knowledge line(s) include schema v2 fields`
|
|
895
934
|
: `warning: ${missingSchemaV2Fields}/${parsedKnowledgeLines} knowledge line(s) miss schema v2 fields (origin/maturity/frequency metadata)`
|
|
896
935
|
});
|
|
936
|
+
const lowConfidenceRatio = parsedKnowledgeLines === 0 ? 0 : lowConfidenceLines / parsedKnowledgeLines;
|
|
937
|
+
checks.push({
|
|
938
|
+
name: "warning:knowledge:low_confidence_density",
|
|
939
|
+
ok: true,
|
|
940
|
+
details: parsedKnowledgeLines === 0
|
|
941
|
+
? "knowledge.jsonl is empty"
|
|
942
|
+
: lowConfidenceRatio <= 0.35
|
|
943
|
+
? `low-confidence entries: ${lowConfidenceLines}/${parsedKnowledgeLines}`
|
|
944
|
+
: `warning: low-confidence entries are high (${lowConfidenceLines}/${parsedKnowledgeLines}, ${(lowConfidenceRatio * 100).toFixed(1)}%). Consider /cc-learn curate before adding more.`
|
|
945
|
+
});
|
|
946
|
+
const repeatedClusters = [...triggerActionCounts.entries()].filter(([, count]) => count >= 3);
|
|
947
|
+
checks.push({
|
|
948
|
+
name: "warning:knowledge:repeat_clusters",
|
|
949
|
+
ok: true,
|
|
950
|
+
details: repeatedClusters.length === 0
|
|
951
|
+
? "no high-frequency repeated trigger/action clusters detected"
|
|
952
|
+
: `warning: ${repeatedClusters.length} repeated learning cluster(s) detected (>=3 repeats). Consider /cc-ops compound to lift them into rules/skills.`
|
|
953
|
+
});
|
|
897
954
|
}
|
|
898
955
|
checks.push({
|
|
899
956
|
name: "state:checkpoint_exists",
|
|
@@ -1049,6 +1106,34 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
1049
1106
|
ok: await exists(path.join(projectRoot, RUNTIME_ROOT, "artifacts")),
|
|
1050
1107
|
details: `${RUNTIME_ROOT}/artifacts must exist as the active artifact root`
|
|
1051
1108
|
});
|
|
1109
|
+
const artifactsRoot = path.join(projectRoot, RUNTIME_ROOT, "artifacts");
|
|
1110
|
+
let artifactPlaceholderHits = [];
|
|
1111
|
+
if (await exists(artifactsRoot)) {
|
|
1112
|
+
try {
|
|
1113
|
+
const entries = await fs.readdir(artifactsRoot, { withFileTypes: true });
|
|
1114
|
+
const placeholderPattern = /\b(?:TODO|TBD|FIXME)\b|<fill-in>|<your-.*-here>/giu;
|
|
1115
|
+
for (const entry of entries) {
|
|
1116
|
+
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
1117
|
+
continue;
|
|
1118
|
+
const filePath = path.join(artifactsRoot, entry.name);
|
|
1119
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
1120
|
+
const matchCount = (content.match(placeholderPattern) ?? []).length;
|
|
1121
|
+
if (matchCount > 0) {
|
|
1122
|
+
artifactPlaceholderHits.push(`${entry.name}:${matchCount}`);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
catch {
|
|
1127
|
+
artifactPlaceholderHits = [];
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
checks.push({
|
|
1131
|
+
name: "warning:artifacts:stale_placeholders",
|
|
1132
|
+
ok: true,
|
|
1133
|
+
details: artifactPlaceholderHits.length === 0
|
|
1134
|
+
? "no TODO/TBD/FIXME placeholder markers found in active artifacts"
|
|
1135
|
+
: `warning: placeholder markers detected in active artifacts (${artifactPlaceholderHits.join(", ")}). Clear before marking completion.`
|
|
1136
|
+
});
|
|
1052
1137
|
const features = await listFeatures(projectRoot);
|
|
1053
1138
|
const worktreeRegistry = await readFeatureWorktreeRegistry(projectRoot);
|
|
1054
1139
|
const activeFeatureEntry = worktreeRegistry.entries.find((entry) => entry.featureId === activeFeature);
|
|
@@ -1086,6 +1171,43 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
1086
1171
|
? `active feature "${activeFeature}" maps to workspace path ${activeFeatureEntry.path} (${activeFeatureEntry.source})`
|
|
1087
1172
|
: `active feature "${activeFeature}" has no worktree registry entry`
|
|
1088
1173
|
});
|
|
1174
|
+
const missingRegistryPaths = [];
|
|
1175
|
+
for (const entry of worktreeRegistry.entries) {
|
|
1176
|
+
const workspacePath = resolveFeatureWorkspacePath(projectRoot, entry);
|
|
1177
|
+
if (!(await exists(workspacePath))) {
|
|
1178
|
+
missingRegistryPaths.push(`${entry.featureId}:${entry.path}`);
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
checks.push({
|
|
1182
|
+
name: "state:worktree_registry_paths_exist",
|
|
1183
|
+
ok: missingRegistryPaths.length === 0,
|
|
1184
|
+
details: missingRegistryPaths.length === 0
|
|
1185
|
+
? "all worktree registry entries resolve to existing paths"
|
|
1186
|
+
: `missing worktree paths for registry entries: ${missingRegistryPaths.join(", ")}`
|
|
1187
|
+
});
|
|
1188
|
+
const gitTrackedPaths = await gitWorktreePaths(projectRoot);
|
|
1189
|
+
const registryGitPaths = worktreeRegistry.entries
|
|
1190
|
+
.filter((entry) => entry.source === "git-worktree")
|
|
1191
|
+
.map((entry) => resolveFeatureWorkspacePath(projectRoot, entry));
|
|
1192
|
+
const missingFromGitList = registryGitPaths.filter((workspacePath) => !gitTrackedPaths.has(path.resolve(workspacePath)));
|
|
1193
|
+
checks.push({
|
|
1194
|
+
name: "warning:state:worktree_registry_git_drift",
|
|
1195
|
+
ok: true,
|
|
1196
|
+
details: missingFromGitList.length === 0
|
|
1197
|
+
? "git-worktree registry entries align with `git worktree list`"
|
|
1198
|
+
: `warning: ${missingFromGitList.length} registry worktree path(s) are missing from \`git worktree list\`: ${missingFromGitList.join(", ")}`
|
|
1199
|
+
});
|
|
1200
|
+
const managedWorktreeRoot = path.join(projectRoot, RUNTIME_ROOT, "worktrees");
|
|
1201
|
+
const unregisteredManagedWorktrees = [...gitTrackedPaths]
|
|
1202
|
+
.filter((workspacePath) => workspacePath.startsWith(path.resolve(managedWorktreeRoot)))
|
|
1203
|
+
.filter((workspacePath) => !registryGitPaths.some((registeredPath) => path.resolve(registeredPath) === workspacePath));
|
|
1204
|
+
checks.push({
|
|
1205
|
+
name: "warning:state:worktree_unregistered_paths",
|
|
1206
|
+
ok: true,
|
|
1207
|
+
details: unregisteredManagedWorktrees.length === 0
|
|
1208
|
+
? "no unmanaged git worktrees under .cclaw/worktrees"
|
|
1209
|
+
: `warning: unregistered git worktree paths detected: ${unregisteredManagedWorktrees.map((value) => path.relative(projectRoot, value)).join(", ")}`
|
|
1210
|
+
});
|
|
1089
1211
|
const legacyWorkspaceEntries = worktreeRegistry.entries
|
|
1090
1212
|
.filter((entry) => entry.source === "legacy-snapshot")
|
|
1091
1213
|
.map((entry) => entry.featureId);
|
package/dist/harness-adapters.js
CHANGED
|
@@ -18,6 +18,12 @@ const UTILITY_SHIMS = [
|
|
|
18
18
|
skillFolder: "flow-next-step",
|
|
19
19
|
commandFile: "next.md"
|
|
20
20
|
},
|
|
21
|
+
{
|
|
22
|
+
fileName: "cc-ideate.md",
|
|
23
|
+
command: "ideate",
|
|
24
|
+
skillFolder: "flow-ideate",
|
|
25
|
+
commandFile: "ideate.md"
|
|
26
|
+
},
|
|
21
27
|
{
|
|
22
28
|
fileName: "cc-view.md",
|
|
23
29
|
command: "view",
|
|
@@ -99,6 +105,15 @@ function agentsMdBlock() {
|
|
|
99
105
|
> Auto-generated by \`cclaw sync\`. Do not edit this managed block manually.
|
|
100
106
|
> Existing project rules in this repository take precedence over cclaw defaults.
|
|
101
107
|
|
|
108
|
+
## Anti-Slop Guard
|
|
109
|
+
|
|
110
|
+
Treat quality as a hard requirement, not style preference:
|
|
111
|
+
|
|
112
|
+
1. Confirm there is a real problem statement before proposing broad changes.
|
|
113
|
+
2. Prefer one focused change over bundled unrelated edits.
|
|
114
|
+
3. Verify claims with fresh evidence in this turn.
|
|
115
|
+
4. If uncertain, escalate with options instead of fabricating certainty.
|
|
116
|
+
|
|
102
117
|
### Activation Rule
|
|
103
118
|
|
|
104
119
|
Before responding to a coding request:
|
|
@@ -133,9 +148,10 @@ When in doubt, prefer **non-trivial** — the quick track is opt-in and only saf
|
|
|
133
148
|
|---|---|
|
|
134
149
|
| \`/cc\` | **Entry point.** No args = resume current stage. With prompt = classify task and start the right flow. |
|
|
135
150
|
| \`/cc-next\` | **Progression.** Advances to the next stage when current is complete. |
|
|
151
|
+
| \`/cc-ideate\` | **Discovery mode.** Generates a ranked repo-improvement backlog before implementation. |
|
|
136
152
|
| \`/cc-view\` | **Read-only router.** Unified entry for status/tree/diff views. |
|
|
137
153
|
| \`/cc-learn\` | **Cross-cutting.** Capture or review project knowledge (append-only JSONL). |
|
|
138
|
-
| \`/cc-ops\` | **Operations router.** Unified entry for feature/tdd-log/retro/archive/rewind actions. |
|
|
154
|
+
| \`/cc-ops\` | **Operations router.** Unified entry for feature/tdd-log/retro/compound/archive/rewind actions. |
|
|
139
155
|
|
|
140
156
|
**Stage order:** brainstorm > scope > design > spec > plan > tdd > review > ship.
|
|
141
157
|
\`/cc-next\` loads the right stage skill automatically. Gates must pass before handoff.
|
package/dist/install.js
CHANGED
|
@@ -8,6 +8,7 @@ import { commandContract } from "./content/contracts.js";
|
|
|
8
8
|
import { contextModeFiles, createInitialContextModeState } from "./content/contexts.js";
|
|
9
9
|
import { learnSkillMarkdown, learnCommandContract } from "./content/learnings.js";
|
|
10
10
|
import { nextCommandContract, nextCommandSkillMarkdown } from "./content/next-command.js";
|
|
11
|
+
import { ideateCommandContract, ideateCommandSkillMarkdown } from "./content/ideate-command.js";
|
|
11
12
|
import { startCommandContract, startCommandSkillMarkdown } from "./content/start-command.js";
|
|
12
13
|
import { statusCommandContract, statusCommandSkillMarkdown } from "./content/status-command.js";
|
|
13
14
|
import { treeCommandContract, treeCommandSkillMarkdown } from "./content/tree-command.js";
|
|
@@ -17,6 +18,7 @@ import { opsCommandContract, opsCommandSkillMarkdown } from "./content/ops-comma
|
|
|
17
18
|
import { featureCommandContract, featureCommandSkillMarkdown } from "./content/feature-command.js";
|
|
18
19
|
import { tddLogCommandContract, tddLogCommandSkillMarkdown } from "./content/tdd-log-command.js";
|
|
19
20
|
import { retroCommandContract, retroCommandSkillMarkdown } from "./content/retro-command.js";
|
|
21
|
+
import { compoundCommandContract, compoundCommandSkillMarkdown } from "./content/compound-command.js";
|
|
20
22
|
import { archiveCommandContract, archiveCommandSkillMarkdown } from "./content/archive-command.js";
|
|
21
23
|
import { rewindCommandContract, rewindCommandSkillMarkdown } from "./content/rewind-command.js";
|
|
22
24
|
import { subagentDrivenDevSkill, parallelAgentsSkill } from "./content/subagents.js";
|
|
@@ -204,6 +206,7 @@ async function writeSkills(projectRoot, config) {
|
|
|
204
206
|
// Utility skills (not flow stages)
|
|
205
207
|
await writeFileSafe(runtimePath(projectRoot, "skills", "learnings", "SKILL.md"), learnSkillMarkdown());
|
|
206
208
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-next-step", "SKILL.md"), nextCommandSkillMarkdown());
|
|
209
|
+
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-ideate", "SKILL.md"), ideateCommandSkillMarkdown());
|
|
207
210
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-start", "SKILL.md"), startCommandSkillMarkdown());
|
|
208
211
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-view", "SKILL.md"), viewCommandSkillMarkdown());
|
|
209
212
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-status", "SKILL.md"), statusCommandSkillMarkdown());
|
|
@@ -213,6 +216,7 @@ async function writeSkills(projectRoot, config) {
|
|
|
213
216
|
await writeFileSafe(runtimePath(projectRoot, "skills", "using-git-worktrees", "SKILL.md"), featureCommandSkillMarkdown());
|
|
214
217
|
await writeFileSafe(runtimePath(projectRoot, "skills", "tdd-cycle-log", "SKILL.md"), tddLogCommandSkillMarkdown());
|
|
215
218
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-retro", "SKILL.md"), retroCommandSkillMarkdown());
|
|
219
|
+
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-compound", "SKILL.md"), compoundCommandSkillMarkdown());
|
|
216
220
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-rewind", "SKILL.md"), rewindCommandSkillMarkdown());
|
|
217
221
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-archive", "SKILL.md"), archiveCommandSkillMarkdown());
|
|
218
222
|
await writeFileSafe(runtimePath(projectRoot, "skills", "subagent-dev", "SKILL.md"), subagentDrivenDevSkill());
|
|
@@ -266,6 +270,7 @@ async function writeSkills(projectRoot, config) {
|
|
|
266
270
|
async function writeUtilityCommands(projectRoot) {
|
|
267
271
|
await writeFileSafe(runtimePath(projectRoot, "commands", "learn.md"), learnCommandContract());
|
|
268
272
|
await writeFileSafe(runtimePath(projectRoot, "commands", "next.md"), nextCommandContract());
|
|
273
|
+
await writeFileSafe(runtimePath(projectRoot, "commands", "ideate.md"), ideateCommandContract());
|
|
269
274
|
await writeFileSafe(runtimePath(projectRoot, "commands", "view.md"), viewCommandContract());
|
|
270
275
|
await writeFileSafe(runtimePath(projectRoot, "commands", "start.md"), startCommandContract());
|
|
271
276
|
await writeFileSafe(runtimePath(projectRoot, "commands", "status.md"), statusCommandContract());
|
|
@@ -275,6 +280,7 @@ async function writeUtilityCommands(projectRoot) {
|
|
|
275
280
|
await writeFileSafe(runtimePath(projectRoot, "commands", "feature.md"), featureCommandContract());
|
|
276
281
|
await writeFileSafe(runtimePath(projectRoot, "commands", "tdd-log.md"), tddLogCommandContract());
|
|
277
282
|
await writeFileSafe(runtimePath(projectRoot, "commands", "retro.md"), retroCommandContract());
|
|
283
|
+
await writeFileSafe(runtimePath(projectRoot, "commands", "compound.md"), compoundCommandContract());
|
|
278
284
|
await writeFileSafe(runtimePath(projectRoot, "commands", "archive.md"), archiveCommandContract());
|
|
279
285
|
await writeFileSafe(runtimePath(projectRoot, "commands", "rewind.md"), rewindCommandContract());
|
|
280
286
|
}
|
package/dist/policy.js
CHANGED
|
@@ -90,6 +90,9 @@ export async function policyChecks(projectRoot, options = {}) {
|
|
|
90
90
|
{ file: runtimeFile("skills/learnings/SKILL.md"), needle: "## Subcommands", name: "utility_skill:learnings:subcommands" },
|
|
91
91
|
{ file: runtimeFile("skills/learnings/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:learnings:hard_gate" },
|
|
92
92
|
{ file: runtimeFile("commands/learn.md"), needle: "## Subcommands", name: "utility_command:learn:subcommands" },
|
|
93
|
+
{ file: runtimeFile("commands/ideate.md"), needle: "## Algorithm", name: "utility_command:ideate:algorithm" },
|
|
94
|
+
{ file: runtimeFile("skills/flow-ideate/SKILL.md"), needle: "## Protocol", name: "utility_skill:ideate:protocol" },
|
|
95
|
+
{ file: runtimeFile("skills/flow-ideate/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:ideate:hard_gate" },
|
|
93
96
|
{ file: runtimeFile("commands/status.md"), needle: "bar:", name: "utility_command:status:visual_bar" },
|
|
94
97
|
{ file: runtimeFile("commands/status.md"), needle: "/cc-view tree · /cc-view diff", name: "utility_command:status:tree_diff_link" },
|
|
95
98
|
{ file: runtimeFile("commands/tree.md"), needle: "## Algorithm", name: "utility_command:tree:algorithm" },
|
|
@@ -107,6 +110,9 @@ export async function policyChecks(projectRoot, options = {}) {
|
|
|
107
110
|
{ file: runtimeFile("commands/retro.md"), needle: "## Algorithm", name: "utility_command:retro:algorithm" },
|
|
108
111
|
{ file: runtimeFile("skills/flow-retro/SKILL.md"), needle: "## Protocol", name: "utility_skill:retro:protocol" },
|
|
109
112
|
{ file: runtimeFile("skills/flow-retro/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:retro:hard_gate" },
|
|
113
|
+
{ file: runtimeFile("commands/compound.md"), needle: "## Algorithm", name: "utility_command:compound:algorithm" },
|
|
114
|
+
{ file: runtimeFile("skills/flow-compound/SKILL.md"), needle: "## Protocol", name: "utility_skill:compound:protocol" },
|
|
115
|
+
{ file: runtimeFile("skills/flow-compound/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:compound:hard_gate" },
|
|
110
116
|
{ file: runtimeFile("commands/rewind.md"), needle: "## Algorithm", name: "utility_command:rewind:algorithm" },
|
|
111
117
|
{ file: runtimeFile("skills/flow-rewind/SKILL.md"), needle: "## Protocol", name: "utility_skill:rewind:protocol" },
|
|
112
118
|
{ file: runtimeFile("skills/flow-rewind/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:rewind:hard_gate" },
|
|
@@ -156,6 +162,10 @@ export async function policyChecks(projectRoot, options = {}) {
|
|
|
156
162
|
{ file: runtimeFile("skills/executing-plans/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:executing_plans:hard_gate" },
|
|
157
163
|
{ file: runtimeFile("skills/executing-plans/SKILL.md"), needle: "## Execution Protocol", name: "utility_skill:executing_plans:protocol" },
|
|
158
164
|
{ file: runtimeFile("skills/executing-plans/SKILL.md"), needle: "## Wave Checklist", name: "utility_skill:executing_plans:waves" },
|
|
165
|
+
{ file: runtimeFile("skills/verification-before-completion/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:verification_before_completion:hard_gate" },
|
|
166
|
+
{ file: runtimeFile("skills/verification-before-completion/SKILL.md"), needle: "## Protocol", name: "utility_skill:verification_before_completion:protocol" },
|
|
167
|
+
{ file: runtimeFile("skills/finishing-a-development-branch/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:finishing_branch:hard_gate" },
|
|
168
|
+
{ file: runtimeFile("skills/finishing-a-development-branch/SKILL.md"), needle: "## Protocol", name: "utility_skill:finishing_branch:protocol" },
|
|
159
169
|
{ file: runtimeFile("skills/context-engineering/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:context_engineering:hard_gate" },
|
|
160
170
|
{ file: runtimeFile("skills/context-engineering/SKILL.md"), needle: "## Context Modes", name: "utility_skill:context_engineering:modes" },
|
|
161
171
|
{ file: runtimeFile("skills/context-engineering/SKILL.md"), needle: "## Mode Switching Protocol", name: "utility_skill:context_engineering:switch" },
|