cclaw-cli 0.49.0 → 0.51.1

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.
Files changed (183) hide show
  1. package/README.md +57 -84
  2. package/dist/artifact-linter.d.ts +4 -0
  3. package/dist/artifact-linter.js +24 -3
  4. package/dist/cli.d.ts +1 -19
  5. package/dist/cli.js +49 -491
  6. package/dist/constants.d.ts +2 -13
  7. package/dist/constants.js +1 -43
  8. package/dist/content/closeout-guidance.d.ts +14 -0
  9. package/dist/content/closeout-guidance.js +42 -0
  10. package/dist/content/core-agents.js +55 -17
  11. package/dist/content/decision-protocol.d.ts +12 -0
  12. package/dist/content/decision-protocol.js +20 -0
  13. package/dist/content/diff-command.d.ts +1 -2
  14. package/dist/content/diff-command.js +8 -94
  15. package/dist/content/examples.d.ts +4 -10
  16. package/dist/content/examples.js +10 -20
  17. package/dist/content/hook-events.js +2 -2
  18. package/dist/content/hook-inline-snippets.d.ts +5 -2
  19. package/dist/content/hook-inline-snippets.js +33 -1
  20. package/dist/content/hook-manifest.d.ts +3 -4
  21. package/dist/content/hook-manifest.js +11 -12
  22. package/dist/content/hooks.js +44 -21
  23. package/dist/content/ideate-command.d.ts +2 -0
  24. package/dist/content/ideate-command.js +34 -25
  25. package/dist/content/iron-laws.d.ts +5 -5
  26. package/dist/content/iron-laws.js +5 -5
  27. package/dist/content/language-policy.d.ts +2 -0
  28. package/dist/content/language-policy.js +13 -0
  29. package/dist/content/learnings.d.ts +3 -4
  30. package/dist/content/learnings.js +26 -50
  31. package/dist/content/meta-skill.js +33 -22
  32. package/dist/content/next-command.js +41 -38
  33. package/dist/content/node-hooks.js +17 -345
  34. package/dist/content/opencode-plugin.js +5 -103
  35. package/dist/content/research-playbooks.js +14 -14
  36. package/dist/content/review-loop.d.ts +2 -0
  37. package/dist/content/review-loop.js +8 -0
  38. package/dist/content/session-hooks.js +15 -47
  39. package/dist/content/skills.d.ts +0 -5
  40. package/dist/content/skills.js +55 -128
  41. package/dist/content/stage-common-guidance.d.ts +0 -1
  42. package/dist/content/stage-common-guidance.js +17 -14
  43. package/dist/content/stage-schema.d.ts +26 -1
  44. package/dist/content/stage-schema.js +121 -40
  45. package/dist/content/stages/_lint-metadata/index.js +9 -15
  46. package/dist/content/stages/brainstorm.js +22 -43
  47. package/dist/content/stages/design.js +37 -57
  48. package/dist/content/stages/plan.js +22 -13
  49. package/dist/content/stages/review.js +24 -27
  50. package/dist/content/stages/scope.js +34 -46
  51. package/dist/content/stages/ship.js +7 -4
  52. package/dist/content/stages/spec.js +20 -9
  53. package/dist/content/stages/tdd.js +64 -44
  54. package/dist/content/start-command.js +13 -12
  55. package/dist/content/status-command.d.ts +2 -7
  56. package/dist/content/status-command.js +19 -146
  57. package/dist/content/subagents.d.ts +0 -5
  58. package/dist/content/subagents.js +51 -28
  59. package/dist/content/templates.d.ts +1 -1
  60. package/dist/content/templates.js +126 -135
  61. package/dist/content/track-render-context.d.ts +17 -0
  62. package/dist/content/track-render-context.js +44 -0
  63. package/dist/content/tree-command.d.ts +1 -2
  64. package/dist/content/tree-command.js +4 -87
  65. package/dist/content/utility-skills.d.ts +2 -29
  66. package/dist/content/utility-skills.js +2 -1534
  67. package/dist/content/view-command.js +31 -11
  68. package/dist/delegation.d.ts +1 -1
  69. package/dist/delegation.js +5 -15
  70. package/dist/doctor-registry.js +20 -21
  71. package/dist/doctor.js +88 -344
  72. package/dist/flow-state.d.ts +3 -0
  73. package/dist/flow-state.js +2 -0
  74. package/dist/harness-adapters.d.ts +1 -1
  75. package/dist/harness-adapters.js +51 -58
  76. package/dist/install.js +128 -358
  77. package/dist/internal/advance-stage.js +3 -9
  78. package/dist/internal/compound-readiness.d.ts +1 -1
  79. package/dist/internal/compound-readiness.js +1 -1
  80. package/dist/internal/tdd-loop-status.d.ts +1 -1
  81. package/dist/internal/tdd-loop-status.js +1 -1
  82. package/dist/knowledge-store.d.ts +16 -10
  83. package/dist/knowledge-store.js +51 -15
  84. package/dist/policy.js +16 -105
  85. package/dist/run-archive.d.ts +4 -6
  86. package/dist/run-archive.js +15 -20
  87. package/dist/run-persistence.d.ts +2 -2
  88. package/dist/run-persistence.js +3 -9
  89. package/package.json +1 -2
  90. package/dist/content/archive-command.d.ts +0 -2
  91. package/dist/content/archive-command.js +0 -124
  92. package/dist/content/compound-command.d.ts +0 -5
  93. package/dist/content/compound-command.js +0 -193
  94. package/dist/content/contexts.d.ts +0 -18
  95. package/dist/content/contexts.js +0 -24
  96. package/dist/content/contracts.d.ts +0 -2
  97. package/dist/content/contracts.js +0 -51
  98. package/dist/content/doctor-references.d.ts +0 -2
  99. package/dist/content/doctor-references.js +0 -150
  100. package/dist/content/eval-scaffold.d.ts +0 -15
  101. package/dist/content/eval-scaffold.js +0 -370
  102. package/dist/content/feature-command.d.ts +0 -2
  103. package/dist/content/feature-command.js +0 -123
  104. package/dist/content/flow-map.d.ts +0 -23
  105. package/dist/content/flow-map.js +0 -134
  106. package/dist/content/harness-doc.d.ts +0 -2
  107. package/dist/content/harness-doc.js +0 -202
  108. package/dist/content/harness-playbooks.d.ts +0 -24
  109. package/dist/content/harness-playbooks.js +0 -393
  110. package/dist/content/harness-tool-refs.d.ts +0 -20
  111. package/dist/content/harness-tool-refs.js +0 -268
  112. package/dist/content/ops-command.d.ts +0 -2
  113. package/dist/content/ops-command.js +0 -71
  114. package/dist/content/protocols.d.ts +0 -7
  115. package/dist/content/protocols.js +0 -215
  116. package/dist/content/retro-command.d.ts +0 -2
  117. package/dist/content/retro-command.js +0 -165
  118. package/dist/content/rewind-command.d.ts +0 -2
  119. package/dist/content/rewind-command.js +0 -106
  120. package/dist/content/tdd-log-command.d.ts +0 -2
  121. package/dist/content/tdd-log-command.js +0 -85
  122. package/dist/eval/agents/single-shot.d.ts +0 -27
  123. package/dist/eval/agents/single-shot.js +0 -79
  124. package/dist/eval/agents/with-tools.d.ts +0 -44
  125. package/dist/eval/agents/with-tools.js +0 -261
  126. package/dist/eval/agents/workflow.d.ts +0 -31
  127. package/dist/eval/agents/workflow.js +0 -155
  128. package/dist/eval/baseline.d.ts +0 -38
  129. package/dist/eval/baseline.js +0 -282
  130. package/dist/eval/config-loader.d.ts +0 -14
  131. package/dist/eval/config-loader.js +0 -395
  132. package/dist/eval/corpus.d.ts +0 -30
  133. package/dist/eval/corpus.js +0 -330
  134. package/dist/eval/cost-guard.d.ts +0 -102
  135. package/dist/eval/cost-guard.js +0 -190
  136. package/dist/eval/diff.d.ts +0 -64
  137. package/dist/eval/diff.js +0 -323
  138. package/dist/eval/llm-client.d.ts +0 -176
  139. package/dist/eval/llm-client.js +0 -267
  140. package/dist/eval/mode.d.ts +0 -28
  141. package/dist/eval/mode.js +0 -61
  142. package/dist/eval/progress.d.ts +0 -83
  143. package/dist/eval/progress.js +0 -59
  144. package/dist/eval/report.d.ts +0 -11
  145. package/dist/eval/report.js +0 -181
  146. package/dist/eval/rubric-loader.d.ts +0 -20
  147. package/dist/eval/rubric-loader.js +0 -143
  148. package/dist/eval/runner.d.ts +0 -81
  149. package/dist/eval/runner.js +0 -746
  150. package/dist/eval/runs.d.ts +0 -41
  151. package/dist/eval/runs.js +0 -114
  152. package/dist/eval/sandbox.d.ts +0 -38
  153. package/dist/eval/sandbox.js +0 -137
  154. package/dist/eval/tools/glob.d.ts +0 -2
  155. package/dist/eval/tools/glob.js +0 -163
  156. package/dist/eval/tools/grep.d.ts +0 -2
  157. package/dist/eval/tools/grep.js +0 -152
  158. package/dist/eval/tools/index.d.ts +0 -7
  159. package/dist/eval/tools/index.js +0 -35
  160. package/dist/eval/tools/read.d.ts +0 -2
  161. package/dist/eval/tools/read.js +0 -122
  162. package/dist/eval/tools/types.d.ts +0 -49
  163. package/dist/eval/tools/types.js +0 -41
  164. package/dist/eval/tools/write.d.ts +0 -2
  165. package/dist/eval/tools/write.js +0 -92
  166. package/dist/eval/types.d.ts +0 -561
  167. package/dist/eval/types.js +0 -47
  168. package/dist/eval/verifiers/judge.d.ts +0 -40
  169. package/dist/eval/verifiers/judge.js +0 -256
  170. package/dist/eval/verifiers/rules.d.ts +0 -24
  171. package/dist/eval/verifiers/rules.js +0 -218
  172. package/dist/eval/verifiers/structural.d.ts +0 -14
  173. package/dist/eval/verifiers/structural.js +0 -171
  174. package/dist/eval/verifiers/traceability.d.ts +0 -23
  175. package/dist/eval/verifiers/traceability.js +0 -84
  176. package/dist/eval/verifiers/workflow-consistency.d.ts +0 -21
  177. package/dist/eval/verifiers/workflow-consistency.js +0 -225
  178. package/dist/eval/workflow-corpus.d.ts +0 -7
  179. package/dist/eval/workflow-corpus.js +0 -207
  180. package/dist/feature-system.d.ts +0 -42
  181. package/dist/feature-system.js +0 -432
  182. package/dist/internal/knowledge-digest.d.ts +0 -7
  183. package/dist/internal/knowledge-digest.js +0 -93
@@ -1,8 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { RUNTIME_ROOT } from "./constants.js";
4
- import { canTransition, createInitialCloseoutState, createInitialFlowState, isFlowTrack, skippedStagesForTrack, SHIP_SUBSTATES } from "./flow-state.js";
5
- import { ensureFeatureSystem, syncActiveFeatureSnapshot } from "./feature-system.js";
4
+ import { canTransition, createInitialCloseoutState, createInitialFlowState, FLOW_STATE_SCHEMA_VERSION, isFlowTrack, skippedStagesForTrack, SHIP_SUBSTATES } from "./flow-state.js";
6
5
  import { ensureDir, exists, withDirectoryLock, writeFileSafe } from "./fs-utils.js";
7
6
  import { FLOW_STAGES } from "./types.js";
8
7
  export class InvalidStageTransitionError extends Error {
@@ -283,6 +282,7 @@ function coerceFlowState(parsed) {
283
282
  ? activeRunIdRaw.trim()
284
283
  : next.activeRunId;
285
284
  return {
285
+ schemaVersion: FLOW_STATE_SCHEMA_VERSION,
286
286
  activeRunId,
287
287
  currentStage: isFlowStage(parsed.currentStage) ? parsed.currentStage : next.currentStage,
288
288
  completedStages: sanitizeCompletedStages(parsed.completedStages),
@@ -334,9 +334,7 @@ async function quarantineCorruptState(statePath, cause) {
334
334
  throw new CorruptFlowStateError(statePath, quarantinedPath, cause);
335
335
  }
336
336
  export async function readFlowState(projectRoot, options = {}) {
337
- if (options.repairFeatureSystem !== false) {
338
- await ensureFeatureSystem(projectRoot);
339
- }
337
+ void options;
340
338
  const statePath = flowStatePath(projectRoot);
341
339
  if (!(await exists(statePath))) {
342
340
  return createInitialFlowState();
@@ -361,7 +359,6 @@ export async function readFlowState(projectRoot, options = {}) {
361
359
  return coerceFlowState(parsed);
362
360
  }
363
361
  export async function writeFlowState(projectRoot, state, options = {}) {
364
- await ensureFeatureSystem(projectRoot);
365
362
  const doWrite = async () => {
366
363
  const statePath = flowStatePath(projectRoot);
367
364
  if (!options.allowReset && (await exists(statePath))) {
@@ -389,7 +386,6 @@ export async function writeFlowState(projectRoot, state, options = {}) {
389
386
  else {
390
387
  await withDirectoryLock(flowStateLockPath(projectRoot), doWrite);
391
388
  }
392
- await syncActiveFeatureSnapshot(projectRoot);
393
389
  }
394
390
  /**
395
391
  * Exposed path helper so callers that need to serialize a multi-step
@@ -400,7 +396,6 @@ export function flowStateLockPathFor(projectRoot) {
400
396
  return flowStateLockPath(projectRoot);
401
397
  }
402
398
  export async function ensureRunSystem(projectRoot, _options = {}) {
403
- await ensureFeatureSystem(projectRoot);
404
399
  await ensureDir(runsRoot(projectRoot));
405
400
  await ensureDir(activeArtifactsPath(projectRoot));
406
401
  const statePath = flowStatePath(projectRoot);
@@ -408,6 +403,5 @@ export async function ensureRunSystem(projectRoot, _options = {}) {
408
403
  if (!(await exists(statePath))) {
409
404
  await writeFlowState(projectRoot, state, { allowReset: true });
410
405
  }
411
- await syncActiveFeatureSnapshot(projectRoot);
412
406
  return state;
413
407
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "0.49.0",
3
+ "version": "0.51.1",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,7 +40,6 @@
40
40
  "node": ">=20.0.0"
41
41
  },
42
42
  "dependencies": {
43
- "openai": "^4.104.0",
44
43
  "yaml": "^2.8.1"
45
44
  },
46
45
  "devDependencies": {
@@ -1,2 +0,0 @@
1
- export declare function archiveCommandContract(): string;
2
- export declare function archiveCommandSkillMarkdown(): string;
@@ -1,124 +0,0 @@
1
- import { RUNTIME_ROOT } from "../constants.js";
2
- const ARCHIVE_SKILL_FOLDER = "flow-archive";
3
- const ARCHIVE_SKILL_NAME = "flow-archive";
4
- function flowStatePath() {
5
- return `${RUNTIME_ROOT}/state/flow-state.json`;
6
- }
7
- function runsPath() {
8
- return `${RUNTIME_ROOT}/runs`;
9
- }
10
- function activeArtifactsPath() {
11
- return `${RUNTIME_ROOT}/artifacts`;
12
- }
13
- export function archiveCommandContract() {
14
- return `# /cc-ops archive
15
-
16
- ## Purpose
17
-
18
- Finalize the active cclaw run: move artifacts to \`${runsPath()}/<archive-id>\`,
19
- snapshot state, write a manifest, and reset runtime for the next run.
20
-
21
- Auto-triggered by \`/cc-next\` when \`closeout.shipSubstate === "ready_to_archive"\`.
22
- Direct invocation from a harness command is supported but rarely needed.
23
-
24
- ## HARD-GATE
25
-
26
- - Do not archive with \`closeout.shipSubstate !== "ready_to_archive"\`.
27
- - Do not archive a shipped run when \`retro.completedAt\` is missing and
28
- \`closeout.retroSkipped !== true\`.
29
- - Never hand-move files between \`${activeArtifactsPath()}\` and \`${runsPath()}\`.
30
- Always run the archive runtime command so the snapshot+manifest stay
31
- atomic.
32
-
33
- ## Inputs
34
-
35
- \`/cc-ops archive [--name=<slug>]\`
36
-
37
- (Legacy flags \`--skip-retro --retro-reason=<text>\` still exist for CLI
38
- invocations; in-harness the skip path is driven by \`closeout.retroSkipped\`
39
- set during retro.)
40
-
41
- ## Algorithm
42
-
43
- 1. Read \`${flowStatePath()}\`.
44
- 2. Verify \`closeout.shipSubstate === "ready_to_archive"\`. If not, report
45
- \`closeout not ready (state=<substate>) | run: /cc-next\` and stop.
46
- 3. Build archive command:
47
- - base: \`npx cclaw archive\`,
48
- - optional: \`--name=<slug>\`,
49
- - legacy override: \`--skip-retro --retro-reason=<text>\` (only when user
50
- explicitly wants the CLI skip path).
51
- 4. Execute the archive command in project root.
52
- 5. On success, flow-state is reset to the initial stage for the default
53
- track; \`closeout.shipSubstate\` returns to \`"idle"\` on reset.
54
- 6. Surface:
55
- - archive id/path,
56
- - reset stage,
57
- - knowledge curation hint when \`activeEntryCount >= softThreshold\`.
58
-
59
- ## Output format
60
-
61
- \`\`\`
62
- cclaw archive
63
- status: archived
64
- run: <archive-id>
65
- path: .cclaw/runs/<archive-id>
66
- next: /cc <new-idea>
67
- \`\`\`
68
-
69
- ## Primary skill
70
-
71
- **${RUNTIME_ROOT}/skills/${ARCHIVE_SKILL_FOLDER}/SKILL.md**
72
- `;
73
- }
74
- export function archiveCommandSkillMarkdown() {
75
- return `---
76
- name: ${ARCHIVE_SKILL_NAME}
77
- description: "Finalize the active cclaw run. Auto-triggered by /cc-next when shipSubstate=ready_to_archive."
78
- ---
79
-
80
- # /cc-ops archive
81
-
82
- ## HARD-GATE
83
-
84
- Never simulate archive by hand-editing runtime files. Always execute the
85
- archive runtime command so state snapshots and manifest generation stay
86
- atomic. Never bypass the substate check — if retro/compound haven't
87
- advanced the substate to \`ready_to_archive\`, stop and surface the
88
- mismatch.
89
-
90
- ## Protocol
91
-
92
- 1. Read \`${flowStatePath()}\`:
93
- - if \`closeout.shipSubstate !== "ready_to_archive"\`, stop and route
94
- the user back to \`/cc-next\` (it will resume at the correct step),
95
- - sanity-check: \`completedStages\` must include \`"ship"\`,
96
- - sanity-check: \`retro.completedAt\` is set **or**
97
- \`closeout.retroSkipped === true\` with a reason.
98
- 2. Build shell command:
99
- - \`npx cclaw archive\`,
100
- - append \`--name=<slug>\` when provided,
101
- - append legacy \`--skip-retro --retro-reason=<text>\` only when the user
102
- explicitly requests the CLI skip path (normally not needed — skip is
103
- captured in \`closeout\` during retro).
104
- 3. Run command from repo root.
105
- 4. Relay key lines from output:
106
- - archive destination under \`${runsPath()}\`,
107
- - flow reset confirmation,
108
- - knowledge curation recommendation if \`activeEntryCount >= 50\`.
109
-
110
- ## Resume semantics
111
-
112
- Archive is idempotent on a per-run basis. If a previous session ran
113
- archive successfully, the active artifacts directory is empty and
114
- \`closeout.shipSubstate\` is \`"idle"\`; \`/cc-next\` will simply report
115
- "Flow complete" or prompt for a new \`/cc\` input.
116
-
117
- ## Validation
118
-
119
- - \`${runsPath()}\` contains a new archive folder for this run.
120
- - \`${activeArtifactsPath()}\` is reset for the next run.
121
- - \`${flowStatePath()}\` is valid JSON and points to the initial stage.
122
- - \`closeout.shipSubstate === "idle"\` after reset.
123
- `;
124
- }
@@ -1,5 +0,0 @@
1
- export interface CompoundCommandOptions {
2
- recurrenceThreshold?: number;
3
- }
4
- export declare function compoundCommandContract(options?: CompoundCommandOptions): string;
5
- export declare function compoundCommandSkillMarkdown(options?: CompoundCommandOptions): string;
@@ -1,193 +0,0 @@
1
- import { RUNTIME_ROOT } from "../constants.js";
2
- const COMPOUND_SKILL_FOLDER = "flow-compound";
3
- const COMPOUND_SKILL_NAME = "flow-compound";
4
- const DEFAULT_RECURRENCE_THRESHOLD = 3;
5
- const SMALL_PROJECT_ARCHIVE_RUNS_THRESHOLD = 5;
6
- const SMALL_PROJECT_RECURRENCE_THRESHOLD = 2;
7
- function resolveRecurrenceThreshold(options) {
8
- const threshold = options.recurrenceThreshold;
9
- if (typeof threshold === "number" && Number.isInteger(threshold) && threshold >= 1) {
10
- return threshold;
11
- }
12
- return DEFAULT_RECURRENCE_THRESHOLD;
13
- }
14
- export function compoundCommandContract(options = {}) {
15
- const recurrenceThreshold = resolveRecurrenceThreshold(options);
16
- return `# /cc-ops compound
17
-
18
- ## Purpose
19
-
20
- Lift repeated lessons from \`${RUNTIME_ROOT}/knowledge.jsonl\` into durable
21
- project assets (rules, protocols, skills) so the next run is easier and safer.
22
-
23
- Auto-triggered by \`/cc-next\` when \`closeout.shipSubstate === "compound_review"\`.
24
- Direct invocation is supported but rarely needed.
25
-
26
- ## HARD-GATE
27
-
28
- - Do not mutate rules/skills/protocols without explicit user approval.
29
- - Every proposal must cite concrete knowledge evidence (line refs or IDs).
30
- - Keep scope focused: one compound change set per run.
31
- - Do not block the archive step if no clusters qualify — record an empty
32
- compound pass and advance.
33
-
34
- ## Inputs
35
-
36
- \`/cc-ops compound\` (no flags). The structured ask presents candidates;
37
- the user can approve individual lifts, accept-all, or skip.
38
-
39
- ## Algorithm
40
-
41
- 1. Read \`${RUNTIME_ROOT}/knowledge.jsonl\` (strict JSONL, one entry per line).
42
- 2. Cluster entries by \`trigger\` + \`action\` similarity.
43
- 3. Resolve recurrence policy:
44
- - base threshold = \`${recurrenceThreshold}\` (from \`config.compound.recurrenceThreshold\`),
45
- - count archived runs under \`${RUNTIME_ROOT}/runs/\`,
46
- - if archived run count is < ${SMALL_PROJECT_ARCHIVE_RUNS_THRESHOLD}, use
47
- effective threshold = \`min(base threshold, ${SMALL_PROJECT_RECURRENCE_THRESHOLD})\` for this pass.
48
- 4. Filter candidates that satisfy at least one trigger:
49
- - recurrence count >= effective threshold, or
50
- - any knowledge entry in the cluster has \`severity: "critical"\`
51
- (critical override, recurrence can be 1).
52
- 5. If **no candidates** exist:
53
- - set \`closeout.compoundCompletedAt = <ISO>\`,
54
- - set \`closeout.compoundPromoted = 0\`,
55
- - set \`closeout.shipSubstate = "ready_to_archive"\`,
56
- - emit \`compound: no candidates | next: /cc-next\` and stop.
57
- 6. **Drift check** each surviving candidate before presenting it (see
58
- "Drift check" section in the skill): confirm the lift target file is
59
- current, spot-check the repo for contradictions, demote stale clusters
60
- into a new superseding entry instead of a lift.
61
- 7. Otherwise, present **one** structured ask via the harness's native ask
62
- tool (\`AskUserQuestion\` / \`AskQuestion\` / \`question\` /
63
- \`request_user_input\`; plain-text lettered list as fallback) summarising
64
- all candidates at once:
65
- - \`apply-all\` (default) — apply every listed lift,
66
- - \`apply-selected\` — prompt per-candidate,
67
- - \`skip\` — record a skip reason and advance without changes.
68
- 8. Apply approved lifts to the target file(s). Each lift also appends a
69
- \`type: "compound"\` entry back to \`${RUNTIME_ROOT}/knowledge.jsonl\`
70
- summarising what was lifted.
71
- 9. Update flow-state:
72
- - \`closeout.compoundCompletedAt = <ISO>\`,
73
- - \`closeout.compoundPromoted = <count>\`,
74
- - \`closeout.compoundSkipped = true\` if user picked skip,
75
- - \`closeout.shipSubstate = "ready_to_archive"\`.
76
- 10. Emit one-line summary: \`compound: promoted=<N> skipped=<bool> | next: /cc-next\`.
77
-
78
- ## Primary skill
79
-
80
- **${RUNTIME_ROOT}/skills/${COMPOUND_SKILL_FOLDER}/SKILL.md**
81
- `;
82
- }
83
- export function compoundCommandSkillMarkdown(options = {}) {
84
- const recurrenceThreshold = resolveRecurrenceThreshold(options);
85
- return `---
86
- name: ${COMPOUND_SKILL_NAME}
87
- description: "Lift repeated learnings into durable rules/protocols/skills. Auto-triggered after retro accept."
88
- ---
89
-
90
- # /cc-ops compound
91
-
92
- ## Announce at start
93
-
94
- "Using flow-compound to lift repeated learnings into durable workflow assets."
95
-
96
- ## HARD-GATE
97
-
98
- No silent codification. Every lift requires explicit user approval. An
99
- empty pass is allowed and must advance \`closeout.shipSubstate\` to
100
- \`"ready_to_archive"\`.
101
-
102
- ## Protocol
103
-
104
- 1. Parse \`.cclaw/knowledge.jsonl\` and group repeated lessons by
105
- trigger+action similarity.
106
- 2. Resolve recurrence policy:
107
- - base threshold = \`${recurrenceThreshold}\` from \`config.compound.recurrenceThreshold\`,
108
- - count archived runs under \`.cclaw/runs/\`,
109
- - if archived run count is < ${SMALL_PROJECT_ARCHIVE_RUNS_THRESHOLD}, use
110
- effective threshold = \`min(base threshold, ${SMALL_PROJECT_RECURRENCE_THRESHOLD})\` for this pass.
111
- 3. Keep only candidates that meet at least one trigger:
112
- - recurrence >= effective threshold and actionable lift path, or
113
- - a cluster entry with \`severity: critical\` (critical override, recurrence can be 1).
114
- 4. If none qualify, record an empty pass:
115
- - \`closeout.compoundCompletedAt = <ISO>\`,
116
- - \`closeout.compoundPromoted = 0\`,
117
- - \`closeout.shipSubstate = "ready_to_archive"\`,
118
- - announce \`compound: no candidates\` and stop.
119
- 5. **Drift check — run before presenting any candidate.** Knowledge lines
120
- are append-only, so textual repetition alone does not prove the rule is
121
- still true. For every cluster that survives the recurrence filter:
122
-
123
- - **Read the lift target.** Open the rule/protocol/skill file you would
124
- edit. If the current contents already encode a stronger version of
125
- the cluster's \`action\`, drop the candidate (nothing to lift).
126
- - **Grep for contradictions.** Run a quick repo search on the cluster's
127
- \`trigger\` keywords. If recent code or docs contradict the cluster,
128
- treat the cluster as stale.
129
- - **Check age.** Inspect \`last_seen_ts\` across the cluster's lines. If
130
- every contributing line is older than ~90 days with no fresh
131
- observation, treat the cluster as stale.
132
- - **Handle stale clusters correctly.** Do **not** silently skip them.
133
- Append a new superseding \`type: "lesson"\` line to
134
- \`.cclaw/knowledge.jsonl\` whose \`trigger\` explicitly references the
135
- old pattern (e.g. \`"when previous rule about X no longer holds: ..."\`)
136
- and whose \`action\` documents the replacement or archive reason.
137
- Then drop the candidate from the lift list.
138
- - **Cite line IDs.** Every surviving candidate must list the concrete
139
- knowledge line indices (1-based) that back it, not just a
140
- summary string. This is what makes the lift auditable.
141
- - **Include qualification reason.** Mark each candidate as
142
- \`recurrence\` or \`critical_override\` so reviewers can see why it passed
143
- the filter.
144
- - Optionally invoke the \`knowledge-curation\` utility skill's
145
- stale/duplicate/supersede heuristics if you want a second pass.
146
-
147
- 6. Otherwise, render each candidate as:
148
-
149
- \`\`\`
150
- Candidate: <short title>
151
- Qualification: <recurrence|critical_override>
152
- Evidence: <knowledge line-ids>
153
- Freshness: <newest last_seen_ts among evidence lines>
154
- Lift target: <rule/protocol/skill file>
155
- Change type: <add/update/remove>
156
- Expected benefit: <what regressions this prevents>
157
- \`\`\`
158
-
159
- 7. Present **one** structured question with three options:
160
- - \`apply-all\` (default) — apply every candidate,
161
- - \`apply-selected\` — prompt per-candidate approval next,
162
- - \`skip\` — record a skip reason and advance.
163
-
164
- 8. For approved candidates:
165
- - edit the target file(s) with the lift,
166
- - append a \`type: "compound"\` entry to \`.cclaw/knowledge.jsonl\`
167
- describing what was promoted, including the source line IDs.
168
-
169
- 9. Update flow-state \`closeout\`:
170
- - \`compoundCompletedAt\`,
171
- - \`compoundPromoted\` (count),
172
- - \`compoundSkipped\` (boolean) + \`compoundSkipReason\` when applicable,
173
- - \`shipSubstate = "ready_to_archive"\`.
174
-
175
- ## Resume semantics
176
-
177
- A new session with \`shipSubstate === "compound_review"\` re-runs the scan
178
- and re-asks the structured question. If the user already applied lifts in
179
- a previous session but the state file was not updated, they should pick
180
- \`skip\` with reason \`already-applied\` — compound is idempotent from the
181
- closeout chain's perspective.
182
-
183
- ## Validation
184
-
185
- - \`closeout.compoundCompletedAt\` is set.
186
- - \`closeout.shipSubstate === "ready_to_archive"\`.
187
- - If lifts were applied, the target files show the edit and at least one
188
- new \`compound\` line exists in \`.cclaw/knowledge.jsonl\`, and the new
189
- line references the source knowledge line IDs.
190
- - If drift check demoted any cluster, a new superseding \`lesson\` line
191
- exists on the same run documenting the replacement.
192
- `;
193
- }
@@ -1,18 +0,0 @@
1
- export declare const DEFAULT_CONTEXT_MODE = "default";
2
- /**
3
- * Valid context mode identifiers used by the session hooks and the
4
- * `context-engineering` skill. Mode bodies no longer live as separate
5
- * `.cclaw/contexts/<mode>.md` files — the guidance was merged into the
6
- * `context-engineering` skill. This list only exists so `doctor` can
7
- * validate that `state/context-mode.json#activeMode` references a known
8
- * mode name.
9
- */
10
- export declare const AVAILABLE_CONTEXT_MODES: readonly ["default", "execution", "review", "incident"];
11
- /** Legacy alias: kept so existing imports keep typechecking. */
12
- export declare const CONTEXT_MODES: Record<string, true>;
13
- export interface ContextModeState {
14
- activeMode: string;
15
- updatedAt: string;
16
- availableModes: string[];
17
- }
18
- export declare function createInitialContextModeState(nowIso?: string): ContextModeState;
@@ -1,24 +0,0 @@
1
- export const DEFAULT_CONTEXT_MODE = "default";
2
- /**
3
- * Valid context mode identifiers used by the session hooks and the
4
- * `context-engineering` skill. Mode bodies no longer live as separate
5
- * `.cclaw/contexts/<mode>.md` files — the guidance was merged into the
6
- * `context-engineering` skill. This list only exists so `doctor` can
7
- * validate that `state/context-mode.json#activeMode` references a known
8
- * mode name.
9
- */
10
- export const AVAILABLE_CONTEXT_MODES = [
11
- "default",
12
- "execution",
13
- "review",
14
- "incident"
15
- ];
16
- /** Legacy alias: kept so existing imports keep typechecking. */
17
- export const CONTEXT_MODES = Object.fromEntries(AVAILABLE_CONTEXT_MODES.map((mode) => [mode, true]));
18
- export function createInitialContextModeState(nowIso = new Date().toISOString()) {
19
- return {
20
- activeMode: DEFAULT_CONTEXT_MODE,
21
- updatedAt: nowIso,
22
- availableModes: [...AVAILABLE_CONTEXT_MODES]
23
- };
24
- }
@@ -1,2 +0,0 @@
1
- import type { FlowStage, FlowTrack } from "../types.js";
2
- export declare function stageCommandContract(stage: FlowStage, track?: FlowTrack): string;
@@ -1,51 +0,0 @@
1
- import { stagePolicyNeedles, stageSchema } from "./stage-schema.js";
2
- import { stageSkillFolder } from "./skills.js";
3
- export function stageCommandContract(stage, track = "standard") {
4
- const schema = stageSchema(stage, track);
5
- const skillPath = `.cclaw/skills/${stageSkillFolder(stage)}/SKILL.md`;
6
- const reads = schema.crossStageTrace.readsFrom;
7
- const readsLine = reads.length > 0 ? reads.join(", ") : "(first stage)";
8
- const hydrationLines = reads.length > 0
9
- ? reads.map((readPath) => `- \`${readPath}\``).join("\n")
10
- : "- (first stage — no upstream artifacts)";
11
- const gateIds = schema.requiredGates
12
- .map((g) => `\`${g.id}\``)
13
- .join(", ");
14
- const writes = schema.crossStageTrace.writesTo;
15
- const writesLine = writes.map((w) => `\`${w}\``).join(", ");
16
- const primaryArtifact = `.cclaw/artifacts/${schema.artifactFile}`;
17
- const writeStepPaths = writes.length > 1
18
- ? writes.map((w) => `\`${w}\``).join(" and ")
19
- : `\`${primaryArtifact}\``;
20
- const policyNeedles = stagePolicyNeedles(stage, track);
21
- return `# /cc-${stage}
22
-
23
- Load and follow **${skillPath}** — it contains the full checklist, examples, interaction protocol, and verification discipline.
24
-
25
- ## HARD-GATE
26
- ${schema.hardGate}
27
-
28
- ## In / Out
29
- - **Reads:** ${readsLine}
30
- - **Writes:** ${writesLine}
31
- - **Next:** \`/cc-next\` (updates flow-state and loads the next stage)
32
-
33
- ## Context Hydration (mandatory before stage work)
34
- 1. Read \`.cclaw/state/flow-state.json\`.
35
- 2. Resolve active artifact root: \`.cclaw/artifacts/\`.
36
- 3. Load required upstream artifacts for this stage:
37
- ${hydrationLines}
38
- 4. Stream \`.cclaw/knowledge.jsonl\` and apply relevant JSON-line entries (strict schema: type, trigger, action, confidence, domain, stage, origin_stage, origin_feature, frequency, universality, maturity, created, first_seen_ts, last_seen_ts, project; optional: source, severity).
39
- 5. Write stage output to ${writeStepPaths}.
40
- 6. Do NOT copy artifacts into \`.cclaw/runs/\`; archival is handled by \`/cc-ops archive\` (agent-facing wrapper over archive runtime).
41
-
42
- ## Gates
43
- ${gateIds}
44
-
45
- ## Exit
46
- ${schema.exitCriteria.map((v) => `- ${v}`).join("\n")}
47
-
48
- ## Anchors
49
- ${policyNeedles.map((v) => `- ${v}`).join("\n")}
50
- `;
51
- }
@@ -1,2 +0,0 @@
1
- export declare const DOCTOR_REFERENCE_DIR = ".cclaw/references/doctor";
2
- export declare const DOCTOR_REFERENCE_MARKDOWN: Record<string, string>;
@@ -1,150 +0,0 @@
1
- import { RUNTIME_ROOT } from "../constants.js";
2
- export const DOCTOR_REFERENCE_DIR = `${RUNTIME_ROOT}/references/doctor`;
3
- export const DOCTOR_REFERENCE_MARKDOWN = {
4
- "README.md": `# Doctor Reference Index
5
-
6
- Reference docs for \`cclaw doctor\` checks.
7
-
8
- ## Categories
9
-
10
- - \`runtime-layout.md\` - runtime directories, generated commands, and skill files
11
- - \`hooks-and-lifecycle.md\` - hook wiring and harness lifecycle integration
12
- - \`harness-and-routing.md\` - harness shims, AGENTS/CLAUDE routing blocks, cursor rule
13
- - \`state-and-gates.md\` - flow-state integrity and gate evidence contracts
14
- - \`delegation-and-preamble.md\` - mandatory delegations and lightweight announce discipline
15
- - \`traceability.md\` - spec/plan/tdd trace matrix expectations
16
- - \`tooling-capabilities.md\` - local runtime prerequisites (node only)
17
- - \`config-and-policy.md\` - config schema, rules policy, and validation references
18
- `,
19
- "runtime-layout.md": `# Runtime Layout
20
-
21
- ## Expected surfaces
22
-
23
- - \`.cclaw/\` root and generated subdirectories
24
- - stage command contracts under \`.cclaw/commands/\`
25
- - stage skills under \`.cclaw/skills/\`
26
- - utility command contracts (\`start\`, \`next\`, \`learn\`, \`status\`)
27
- - state files under \`.cclaw/state/\`
28
-
29
- ## Typical fixes
30
-
31
- 1. Run \`cclaw sync\` to re-materialize generated assets.
32
- 2. If runtime is severely drifted, run \`cclaw upgrade\`.
33
- 3. Avoid manual edits under generated runtime paths unless explicitly supported.
34
- `,
35
- "hooks-and-lifecycle.md": `# Hooks And Lifecycle
36
-
37
- ## Expected behavior
38
-
39
- - session start rehydrates flow + knowledge digest
40
- - pre-tool hooks run prompt/workflow guards
41
- - post-tool hooks run context monitor
42
- - stop hooks checkpoint progress
43
- - OpenCode uses plugin-based lifecycle integration
44
-
45
- ## Typical fixes
46
-
47
- 1. Re-run \`cclaw sync\` after harness config changes.
48
- 2. Ensure harness is enabled in \`.cclaw/config.yaml\`.
49
- 3. Validate hook JSON shape and remove malformed manual edits.
50
- `,
51
- "harness-and-routing.md": `# Harness And Routing
52
-
53
- ## Expected behavior
54
-
55
- - command shims exist for every enabled harness
56
- - managed routing block is present in \`AGENTS.md\` (and \`CLAUDE.md\` when applicable)
57
- - cursor rule mirrors workflow activation guidance
58
- - opencode plugin path is registered in opencode config
59
-
60
- ## Typical fixes
61
-
62
- 1. Confirm \`harnesses\` list in \`.cclaw/config.yaml\`.
63
- 2. Run \`cclaw sync\` to re-generate shims/routing files.
64
- 3. Remove stale harness artifacts for disabled harnesses via \`cclaw sync\`.
65
- `,
66
- "state-and-gates.md": `# State And Gates
67
-
68
- ## Expected behavior
69
-
70
- - \`flow-state.json\` has activeRunId, current stage, and consistent track/skippedStages
71
- - current-stage gate evidence is internally consistent
72
- - completed stages only include passed required gates
73
-
74
- ## Typical fixes
75
-
76
- 1. Run \`cclaw doctor --reconcile-gates\` to refresh current-stage gate catalog.
77
- 2. Repair inconsistent stage artifacts, then re-run doctor.
78
- 3. Do not manually mutate gate arrays without matching artifact evidence.
79
- `,
80
- "delegation-and-preamble.md": `# Delegation And Preamble
81
-
82
- ## Delegation contract
83
-
84
- - mandatory delegations for the current stage must be completed or waived
85
- - waivers should include an explicit reason
86
- - stale entries from previous runs are ignored by current-run checks
87
- - delegation entries use span-compatible fields (\`spanId\`, \`startTs\`, \`endTs\`, \`retryCount\`, \`evidenceRefs\`)
88
-
89
- ## Announce discipline contract
90
-
91
- - no dedicated preamble runtime log is required
92
- - substantial turns should still start with a concise announce (stage + goal + next action)
93
- - do not spam repeated announces when intent did not change
94
-
95
- ## Typical fixes
96
-
97
- 1. Append missing delegation records with \`completed\` or \`waived\` status.
98
- 2. Record harness-limitation waivers when native delegation is unavailable.
99
- 3. Keep announces concise and only refresh when plan/risk materially changes.
100
- `,
101
- "traceability.md": `# Traceability
102
-
103
- ## Expected behavior
104
-
105
- - spec criteria map to plan tasks
106
- - plan tasks map to tdd slices/tests
107
- - no orphaned criteria/tasks/tests when downstream artifacts exist
108
-
109
- ## Typical fixes
110
-
111
- 1. Add stable IDs to spec/plan/tdd sections.
112
- 2. Ensure mapping tables include every active criterion/task/slice.
113
- 3. Re-run \`cclaw doctor\` after artifact updates.
114
- `,
115
- "tooling-capabilities.md": `# Tooling Capabilities
116
-
117
- ## Required
118
-
119
- - \`node\` (>=20) — the only runtime dependency. All hooks, git-hook relays, and the
120
- \`cclaw\` CLI itself run on Node.js. No \`bash\`, \`python3\`, or \`jq\` required.
121
- - \`git\` — needed for worktree and pre-commit/pre-push relays.
122
-
123
- ## Not required (removed)
124
-
125
- Earlier releases relied on \`bash\` to execute generated shell hooks and on
126
- \`python3\`/\`jq\` as JSON fallback parsers. Node-only mode removes both: hooks
127
- dispatch through \`.cclaw/hooks/run-hook.cmd <hook-name>\` (which forwards to
128
- Node), so these tools
129
- are no longer part of the supported runtime contract.
130
-
131
- ## Typical fixes
132
-
133
- 1. Install Node.js 20 or newer (matches \`package.json\` \`engines\`) and ensure \`node\` is on \`PATH\`.
134
- 2. Re-run \`cclaw sync\` to regenerate hook configs after upgrading Node.
135
- `,
136
- "config-and-policy.md": `# Config And Policy
137
-
138
- ## Expected behavior
139
-
140
- - \`.cclaw/config.yaml\` parses and uses supported keys/values
141
- - \`.cclaw/rules/rules.json\` matches generated policy schema
142
- - policy needles and required sections remain present in generated contracts
143
-
144
- ## Typical fixes
145
-
146
- 1. Repair invalid config values and run \`cclaw sync\`.
147
- 2. Re-generate policy files via \`cclaw sync\` if drift is detected.
148
- 3. Keep generated contracts aligned with stage schemas and policy needles.
149
- `
150
- };