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.
- package/README.md +57 -84
- package/dist/artifact-linter.d.ts +4 -0
- package/dist/artifact-linter.js +24 -3
- package/dist/cli.d.ts +1 -19
- package/dist/cli.js +49 -491
- package/dist/constants.d.ts +2 -13
- package/dist/constants.js +1 -43
- package/dist/content/closeout-guidance.d.ts +14 -0
- package/dist/content/closeout-guidance.js +42 -0
- package/dist/content/core-agents.js +55 -17
- package/dist/content/decision-protocol.d.ts +12 -0
- package/dist/content/decision-protocol.js +20 -0
- package/dist/content/diff-command.d.ts +1 -2
- package/dist/content/diff-command.js +8 -94
- package/dist/content/examples.d.ts +4 -10
- package/dist/content/examples.js +10 -20
- package/dist/content/hook-events.js +2 -2
- package/dist/content/hook-inline-snippets.d.ts +5 -2
- package/dist/content/hook-inline-snippets.js +33 -1
- package/dist/content/hook-manifest.d.ts +3 -4
- package/dist/content/hook-manifest.js +11 -12
- package/dist/content/hooks.js +44 -21
- package/dist/content/ideate-command.d.ts +2 -0
- package/dist/content/ideate-command.js +34 -25
- package/dist/content/iron-laws.d.ts +5 -5
- package/dist/content/iron-laws.js +5 -5
- package/dist/content/language-policy.d.ts +2 -0
- package/dist/content/language-policy.js +13 -0
- package/dist/content/learnings.d.ts +3 -4
- package/dist/content/learnings.js +26 -50
- package/dist/content/meta-skill.js +33 -22
- package/dist/content/next-command.js +41 -38
- package/dist/content/node-hooks.js +17 -345
- package/dist/content/opencode-plugin.js +5 -103
- package/dist/content/research-playbooks.js +14 -14
- package/dist/content/review-loop.d.ts +2 -0
- package/dist/content/review-loop.js +8 -0
- package/dist/content/session-hooks.js +15 -47
- package/dist/content/skills.d.ts +0 -5
- package/dist/content/skills.js +55 -128
- package/dist/content/stage-common-guidance.d.ts +0 -1
- package/dist/content/stage-common-guidance.js +17 -14
- package/dist/content/stage-schema.d.ts +26 -1
- package/dist/content/stage-schema.js +121 -40
- package/dist/content/stages/_lint-metadata/index.js +9 -15
- package/dist/content/stages/brainstorm.js +22 -43
- package/dist/content/stages/design.js +37 -57
- package/dist/content/stages/plan.js +22 -13
- package/dist/content/stages/review.js +24 -27
- package/dist/content/stages/scope.js +34 -46
- package/dist/content/stages/ship.js +7 -4
- package/dist/content/stages/spec.js +20 -9
- package/dist/content/stages/tdd.js +64 -44
- package/dist/content/start-command.js +13 -12
- package/dist/content/status-command.d.ts +2 -7
- package/dist/content/status-command.js +19 -146
- package/dist/content/subagents.d.ts +0 -5
- package/dist/content/subagents.js +51 -28
- package/dist/content/templates.d.ts +1 -1
- package/dist/content/templates.js +126 -135
- package/dist/content/track-render-context.d.ts +17 -0
- package/dist/content/track-render-context.js +44 -0
- package/dist/content/tree-command.d.ts +1 -2
- package/dist/content/tree-command.js +4 -87
- package/dist/content/utility-skills.d.ts +2 -29
- package/dist/content/utility-skills.js +2 -1534
- package/dist/content/view-command.js +31 -11
- package/dist/delegation.d.ts +1 -1
- package/dist/delegation.js +5 -15
- package/dist/doctor-registry.js +20 -21
- package/dist/doctor.js +88 -344
- package/dist/flow-state.d.ts +3 -0
- package/dist/flow-state.js +2 -0
- package/dist/harness-adapters.d.ts +1 -1
- package/dist/harness-adapters.js +51 -58
- package/dist/install.js +128 -358
- package/dist/internal/advance-stage.js +3 -9
- package/dist/internal/compound-readiness.d.ts +1 -1
- package/dist/internal/compound-readiness.js +1 -1
- package/dist/internal/tdd-loop-status.d.ts +1 -1
- package/dist/internal/tdd-loop-status.js +1 -1
- package/dist/knowledge-store.d.ts +16 -10
- package/dist/knowledge-store.js +51 -15
- package/dist/policy.js +16 -105
- package/dist/run-archive.d.ts +4 -6
- package/dist/run-archive.js +15 -20
- package/dist/run-persistence.d.ts +2 -2
- package/dist/run-persistence.js +3 -9
- package/package.json +1 -2
- package/dist/content/archive-command.d.ts +0 -2
- package/dist/content/archive-command.js +0 -124
- package/dist/content/compound-command.d.ts +0 -5
- package/dist/content/compound-command.js +0 -193
- package/dist/content/contexts.d.ts +0 -18
- package/dist/content/contexts.js +0 -24
- package/dist/content/contracts.d.ts +0 -2
- package/dist/content/contracts.js +0 -51
- package/dist/content/doctor-references.d.ts +0 -2
- package/dist/content/doctor-references.js +0 -150
- package/dist/content/eval-scaffold.d.ts +0 -15
- package/dist/content/eval-scaffold.js +0 -370
- package/dist/content/feature-command.d.ts +0 -2
- package/dist/content/feature-command.js +0 -123
- package/dist/content/flow-map.d.ts +0 -23
- package/dist/content/flow-map.js +0 -134
- package/dist/content/harness-doc.d.ts +0 -2
- package/dist/content/harness-doc.js +0 -202
- package/dist/content/harness-playbooks.d.ts +0 -24
- package/dist/content/harness-playbooks.js +0 -393
- package/dist/content/harness-tool-refs.d.ts +0 -20
- package/dist/content/harness-tool-refs.js +0 -268
- package/dist/content/ops-command.d.ts +0 -2
- package/dist/content/ops-command.js +0 -71
- package/dist/content/protocols.d.ts +0 -7
- package/dist/content/protocols.js +0 -215
- package/dist/content/retro-command.d.ts +0 -2
- package/dist/content/retro-command.js +0 -165
- package/dist/content/rewind-command.d.ts +0 -2
- package/dist/content/rewind-command.js +0 -106
- package/dist/content/tdd-log-command.d.ts +0 -2
- package/dist/content/tdd-log-command.js +0 -85
- package/dist/eval/agents/single-shot.d.ts +0 -27
- package/dist/eval/agents/single-shot.js +0 -79
- package/dist/eval/agents/with-tools.d.ts +0 -44
- package/dist/eval/agents/with-tools.js +0 -261
- package/dist/eval/agents/workflow.d.ts +0 -31
- package/dist/eval/agents/workflow.js +0 -155
- package/dist/eval/baseline.d.ts +0 -38
- package/dist/eval/baseline.js +0 -282
- package/dist/eval/config-loader.d.ts +0 -14
- package/dist/eval/config-loader.js +0 -395
- package/dist/eval/corpus.d.ts +0 -30
- package/dist/eval/corpus.js +0 -330
- package/dist/eval/cost-guard.d.ts +0 -102
- package/dist/eval/cost-guard.js +0 -190
- package/dist/eval/diff.d.ts +0 -64
- package/dist/eval/diff.js +0 -323
- package/dist/eval/llm-client.d.ts +0 -176
- package/dist/eval/llm-client.js +0 -267
- package/dist/eval/mode.d.ts +0 -28
- package/dist/eval/mode.js +0 -61
- package/dist/eval/progress.d.ts +0 -83
- package/dist/eval/progress.js +0 -59
- package/dist/eval/report.d.ts +0 -11
- package/dist/eval/report.js +0 -181
- package/dist/eval/rubric-loader.d.ts +0 -20
- package/dist/eval/rubric-loader.js +0 -143
- package/dist/eval/runner.d.ts +0 -81
- package/dist/eval/runner.js +0 -746
- package/dist/eval/runs.d.ts +0 -41
- package/dist/eval/runs.js +0 -114
- package/dist/eval/sandbox.d.ts +0 -38
- package/dist/eval/sandbox.js +0 -137
- package/dist/eval/tools/glob.d.ts +0 -2
- package/dist/eval/tools/glob.js +0 -163
- package/dist/eval/tools/grep.d.ts +0 -2
- package/dist/eval/tools/grep.js +0 -152
- package/dist/eval/tools/index.d.ts +0 -7
- package/dist/eval/tools/index.js +0 -35
- package/dist/eval/tools/read.d.ts +0 -2
- package/dist/eval/tools/read.js +0 -122
- package/dist/eval/tools/types.d.ts +0 -49
- package/dist/eval/tools/types.js +0 -41
- package/dist/eval/tools/write.d.ts +0 -2
- package/dist/eval/tools/write.js +0 -92
- package/dist/eval/types.d.ts +0 -561
- package/dist/eval/types.js +0 -47
- package/dist/eval/verifiers/judge.d.ts +0 -40
- package/dist/eval/verifiers/judge.js +0 -256
- package/dist/eval/verifiers/rules.d.ts +0 -24
- package/dist/eval/verifiers/rules.js +0 -218
- package/dist/eval/verifiers/structural.d.ts +0 -14
- package/dist/eval/verifiers/structural.js +0 -171
- package/dist/eval/verifiers/traceability.d.ts +0 -23
- package/dist/eval/verifiers/traceability.js +0 -84
- package/dist/eval/verifiers/workflow-consistency.d.ts +0 -21
- package/dist/eval/verifiers/workflow-consistency.js +0 -225
- package/dist/eval/workflow-corpus.d.ts +0 -7
- package/dist/eval/workflow-corpus.js +0 -207
- package/dist/feature-system.d.ts +0 -42
- package/dist/feature-system.js +0 -432
- package/dist/internal/knowledge-digest.d.ts +0 -7
- package/dist/internal/knowledge-digest.js +0 -93
package/dist/install.js
CHANGED
|
@@ -4,50 +4,28 @@ import path from "node:path";
|
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import { CCLAW_VERSION, FLOW_VERSION, REQUIRED_DIRS, RUNTIME_ROOT } from "./constants.js";
|
|
6
6
|
import { writeConfig, createDefaultConfig, readConfig, configPath, detectLanguageRulePacks, detectAdvancedKeys } from "./config.js";
|
|
7
|
-
import {
|
|
8
|
-
import { createInitialContextModeState } from "./content/contexts.js";
|
|
9
|
-
import { learnSkillMarkdown, learnCommandContract } from "./content/learnings.js";
|
|
7
|
+
import { learnSkillMarkdown } from "./content/learnings.js";
|
|
10
8
|
import { nextCommandContract, nextCommandSkillMarkdown } from "./content/next-command.js";
|
|
11
9
|
import { ideateCommandContract, ideateCommandSkillMarkdown } from "./content/ideate-command.js";
|
|
12
10
|
import { startCommandContract, startCommandSkillMarkdown } from "./content/start-command.js";
|
|
13
|
-
import { statusCommandContract, statusCommandSkillMarkdown } from "./content/status-command.js";
|
|
14
|
-
import { treeCommandContract, treeCommandSkillMarkdown } from "./content/tree-command.js";
|
|
15
|
-
import { diffCommandContract, diffCommandSkillMarkdown } from "./content/diff-command.js";
|
|
16
11
|
import { viewCommandContract, viewCommandSkillMarkdown } from "./content/view-command.js";
|
|
17
|
-
import { opsCommandContract, opsCommandSkillMarkdown } from "./content/ops-command.js";
|
|
18
|
-
import { featureCommandContract, featureCommandSkillMarkdown } from "./content/feature-command.js";
|
|
19
|
-
import { tddLogCommandContract, tddLogCommandSkillMarkdown } from "./content/tdd-log-command.js";
|
|
20
|
-
import { retroCommandContract, retroCommandSkillMarkdown } from "./content/retro-command.js";
|
|
21
|
-
import { compoundCommandContract, compoundCommandSkillMarkdown } from "./content/compound-command.js";
|
|
22
|
-
import { archiveCommandContract, archiveCommandSkillMarkdown } from "./content/archive-command.js";
|
|
23
|
-
import { rewindCommandContract, rewindCommandSkillMarkdown } from "./content/rewind-command.js";
|
|
24
12
|
import { subagentDrivenDevSkill, parallelAgentsSkill } from "./content/subagents.js";
|
|
25
13
|
import { sessionHooksSkillMarkdown } from "./content/session-hooks.js";
|
|
26
14
|
import { ironLawRuntimeDocument, ironLawsSkillMarkdown } from "./content/iron-laws.js";
|
|
27
15
|
import { stageCompleteScript, runHookCmdScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
|
|
28
16
|
import { nodeHookRuntimeScript } from "./content/node-hooks.js";
|
|
29
17
|
import { META_SKILL_NAME, usingCclawSkillMarkdown } from "./content/meta-skill.js";
|
|
30
|
-
import { decisionProtocolMarkdown, completionProtocolMarkdown, ethosProtocolMarkdown } from "./content/protocols.js";
|
|
31
|
-
import { flowMapMarkdown } from "./content/flow-map.js";
|
|
32
18
|
import { ARTIFACT_TEMPLATES, CURSOR_WORKFLOW_RULE_MDC, RULEBOOK_MARKDOWN, buildRulesJson } from "./content/templates.js";
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import { stageCommonGuidanceMarkdown } from "./content/stage-common-guidance.js";
|
|
36
|
-
import { STAGE_EXAMPLES_REFERENCE_DIR, stageExamplesReferenceMarkdown } from "./content/examples.js";
|
|
37
|
-
import { LANGUAGE_RULE_PACK_DIR, LANGUAGE_RULE_PACK_FILES, LANGUAGE_RULE_PACK_GENERATORS, LEGACY_LANGUAGE_RULE_PACK_FOLDERS, UTILITY_SKILL_FOLDERS, UTILITY_SKILL_MAP } from "./content/utility-skills.js";
|
|
19
|
+
import { stageSkillFolder, stageSkillMarkdown } from "./content/skills.js";
|
|
20
|
+
import { LANGUAGE_RULE_PACK_DIR, LANGUAGE_RULE_PACK_FILES, LANGUAGE_RULE_PACK_GENERATORS, LEGACY_LANGUAGE_RULE_PACK_FOLDERS } from "./content/utility-skills.js";
|
|
38
21
|
import { RESEARCH_PLAYBOOKS } from "./content/research-playbooks.js";
|
|
39
|
-
import { HARNESS_TOOL_REFS_DIR, HARNESS_TOOL_REFS_INDEX_MD, harnessToolRefMarkdown } from "./content/harness-tool-refs.js";
|
|
40
|
-
import { DOCTOR_REFERENCE_MARKDOWN } from "./content/doctor-references.js";
|
|
41
|
-
import { harnessDocsOverviewMarkdown, harnessIntegrationDocMarkdown } from "./content/harness-doc.js";
|
|
42
|
-
import { HARNESS_PLAYBOOKS_DIR, harnessPlaybookFileName, harnessPlaybookMarkdown, harnessPlaybooksIndexMarkdown } from "./content/harness-playbooks.js";
|
|
43
|
-
import { HOOK_EVENTS_BY_HARNESS, HOOK_SEMANTIC_EVENTS } from "./content/hook-events.js";
|
|
44
22
|
import { createInitialFlowState } from "./flow-state.js";
|
|
45
23
|
import { ensureDir, exists, writeFileSafe } from "./fs-utils.js";
|
|
46
24
|
import { ensureGitignore, removeGitignorePatterns } from "./gitignore.js";
|
|
47
|
-
import { HARNESS_ADAPTERS, harnessShimFileNames,
|
|
25
|
+
import { HARNESS_ADAPTERS, harnessShimFileNames, syncHarnessShims, removeCclawFromAgentsMd } from "./harness-adapters.js";
|
|
48
26
|
import { validateHookDocument } from "./hook-schema.js";
|
|
49
27
|
import { detectHarnesses } from "./init-detect.js";
|
|
50
|
-
import {
|
|
28
|
+
import { ensureRunSystem } from "./runs.js";
|
|
51
29
|
import { FLOW_STAGES } from "./types.js";
|
|
52
30
|
const OPENCODE_PLUGIN_REL_PATH = ".opencode/plugins/cclaw-plugin.mjs";
|
|
53
31
|
const CURSOR_RULE_REL_PATH = ".cursor/rules/cclaw-workflow.mdc";
|
|
@@ -57,6 +35,108 @@ const execFileAsync = promisify(execFile);
|
|
|
57
35
|
function runtimePath(projectRoot, ...segments) {
|
|
58
36
|
return path.join(projectRoot, RUNTIME_ROOT, ...segments);
|
|
59
37
|
}
|
|
38
|
+
async function removeBestEffort(targetPath, recursive = false) {
|
|
39
|
+
try {
|
|
40
|
+
await fs.rm(targetPath, { recursive, force: true });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// best-effort cleanup
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const DEPRECATED_UTILITY_SKILL_FOLDERS = [
|
|
47
|
+
"project-learnings",
|
|
48
|
+
"auto-orchestration",
|
|
49
|
+
"autoplan",
|
|
50
|
+
"red-first-testing",
|
|
51
|
+
"incremental-implementation",
|
|
52
|
+
"subagent-driven-development",
|
|
53
|
+
"dispatching-parallel-agents",
|
|
54
|
+
"session-guidelines",
|
|
55
|
+
"security-review",
|
|
56
|
+
"documentation",
|
|
57
|
+
"browser-qa-testing",
|
|
58
|
+
"feature-workspaces",
|
|
59
|
+
"security",
|
|
60
|
+
"debugging",
|
|
61
|
+
"performance",
|
|
62
|
+
"ci-cd",
|
|
63
|
+
"docs",
|
|
64
|
+
"executing-plans",
|
|
65
|
+
"verification-before-completion",
|
|
66
|
+
"finishing-a-development-branch",
|
|
67
|
+
"context-engineering",
|
|
68
|
+
"source-driven-development",
|
|
69
|
+
"frontend-accessibility",
|
|
70
|
+
"landscape-check",
|
|
71
|
+
"adversarial-review",
|
|
72
|
+
"security-audit",
|
|
73
|
+
"knowledge-curation",
|
|
74
|
+
"retrospective",
|
|
75
|
+
"document-review",
|
|
76
|
+
"receiving-code-review",
|
|
77
|
+
"flow-status",
|
|
78
|
+
"flow-tree",
|
|
79
|
+
"flow-diff"
|
|
80
|
+
];
|
|
81
|
+
const DEPRECATED_AGENT_FILES = [
|
|
82
|
+
"securityer.md",
|
|
83
|
+
"spec-reviewer.md",
|
|
84
|
+
"code-reviewer.md",
|
|
85
|
+
"repo-research-analyst.md",
|
|
86
|
+
"learnings-researcher.md",
|
|
87
|
+
"framework-docs-researcher.md",
|
|
88
|
+
"best-practices-researcher.md",
|
|
89
|
+
"git-history-analyzer.md"
|
|
90
|
+
];
|
|
91
|
+
const DEPRECATED_COMMAND_FILES = [
|
|
92
|
+
"learn.md",
|
|
93
|
+
"status.md",
|
|
94
|
+
"tree.md",
|
|
95
|
+
"diff.md",
|
|
96
|
+
"feature.md",
|
|
97
|
+
"ops.md",
|
|
98
|
+
"tdd-log.md",
|
|
99
|
+
"retro.md",
|
|
100
|
+
"compound.md",
|
|
101
|
+
"archive.md",
|
|
102
|
+
"rewind.md"
|
|
103
|
+
];
|
|
104
|
+
const DEPRECATED_SKILL_FILES = [
|
|
105
|
+
["flow-ops", "SKILL.md"],
|
|
106
|
+
["tdd-cycle-log", "SKILL.md"],
|
|
107
|
+
["flow-retro", "SKILL.md"],
|
|
108
|
+
["flow-compound", "SKILL.md"],
|
|
109
|
+
["flow-archive", "SKILL.md"],
|
|
110
|
+
["flow-rewind", "SKILL.md"],
|
|
111
|
+
["using-git-worktrees", "SKILL.md"]
|
|
112
|
+
];
|
|
113
|
+
const DEPRECATED_STATE_FILES = [
|
|
114
|
+
"checkpoint.json",
|
|
115
|
+
"flow-state.snapshot.json",
|
|
116
|
+
"stage-activity.jsonl",
|
|
117
|
+
"knowledge-digest.md",
|
|
118
|
+
"suggestion-memory.json",
|
|
119
|
+
"harness-gaps.json",
|
|
120
|
+
"context-mode.json",
|
|
121
|
+
"session-digest.md",
|
|
122
|
+
"context-warnings.jsonl"
|
|
123
|
+
];
|
|
124
|
+
const DEPRECATED_HOOK_FILES = [
|
|
125
|
+
"observe.sh",
|
|
126
|
+
"summarize-observations.sh",
|
|
127
|
+
"summarize-observations.mjs",
|
|
128
|
+
"_lib.sh",
|
|
129
|
+
"session-start.sh",
|
|
130
|
+
"stop-checkpoint.sh",
|
|
131
|
+
"run-hook.cmd",
|
|
132
|
+
"stage-complete.sh",
|
|
133
|
+
"pre-compact.sh",
|
|
134
|
+
"prompt-guard.sh",
|
|
135
|
+
"workflow-guard.sh",
|
|
136
|
+
"context-monitor.sh"
|
|
137
|
+
];
|
|
138
|
+
const DEPRECATED_RUNTIME_ROOT_FILES = ["learnings.jsonl", "observations.jsonl"];
|
|
139
|
+
const DEPRECATED_RUNTIME_DIRS = ["evals", "worktrees", "references", "contexts"];
|
|
60
140
|
async function resolveGitHooksDir(projectRoot) {
|
|
61
141
|
try {
|
|
62
142
|
const { stdout } = await execFileAsync("git", ["rev-parse", "--git-path", "hooks"], {
|
|
@@ -274,93 +354,28 @@ async function ensureStructure(projectRoot) {
|
|
|
274
354
|
await ensureDir(path.join(projectRoot, dir));
|
|
275
355
|
}
|
|
276
356
|
}
|
|
277
|
-
async function writeCommandContracts(projectRoot, track = "standard") {
|
|
278
|
-
await Promise.all(FLOW_STAGES.map(async (stage) => {
|
|
279
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", `${stage}.md`), stageCommandContract(stage, track));
|
|
280
|
-
}));
|
|
281
|
-
}
|
|
282
357
|
async function writeArtifactTemplates(projectRoot) {
|
|
283
358
|
await Promise.all(Object.entries(ARTIFACT_TEMPLATES).map(async ([fileName, content]) => {
|
|
284
359
|
await writeFileSafe(runtimePath(projectRoot, "templates", fileName), content);
|
|
285
360
|
}));
|
|
286
361
|
}
|
|
287
|
-
/**
|
|
288
|
-
* Seed the `.cclaw/evals/` scaffold. Only writes files that do not already
|
|
289
|
-
* exist so that user-authored config.yaml / corpus / rubrics / baselines are
|
|
290
|
-
* never clobbered by `cclaw sync`.
|
|
291
|
-
*/
|
|
292
|
-
async function writeEvalScaffold(projectRoot) {
|
|
293
|
-
const targets = [
|
|
294
|
-
{ rel: "evals/config.yaml", content: EVAL_CONFIG_YAML },
|
|
295
|
-
{ rel: "evals/corpus/README.md", content: EVAL_CORPUS_README },
|
|
296
|
-
{ rel: "evals/rubrics/README.md", content: EVAL_RUBRICS_README },
|
|
297
|
-
{ rel: "evals/baselines/README.md", content: EVAL_BASELINES_README },
|
|
298
|
-
{ rel: "evals/reports/README.md", content: EVAL_REPORTS_README }
|
|
299
|
-
];
|
|
300
|
-
for (const rubric of EVAL_RUBRIC_FILES) {
|
|
301
|
-
targets.push({
|
|
302
|
-
rel: `evals/rubrics/${rubric.stage}.yaml`,
|
|
303
|
-
content: rubric.contents
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
for (const target of targets) {
|
|
307
|
-
const absolute = runtimePath(projectRoot, ...target.rel.split("/"));
|
|
308
|
-
if (await exists(absolute))
|
|
309
|
-
continue;
|
|
310
|
-
await writeFileSafe(absolute, target.content);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
362
|
async function writeSkills(projectRoot, config) {
|
|
314
363
|
const skillTrack = config?.defaultTrack ?? "standard";
|
|
315
364
|
for (const stage of FLOW_STAGES) {
|
|
316
365
|
const folder = stageSkillFolder(stage);
|
|
317
366
|
await writeFileSafe(runtimePath(projectRoot, "skills", folder, "SKILL.md"), stageSkillMarkdown(stage, skillTrack));
|
|
318
|
-
// Progressive disclosure (A.2#8): materialize the full example artifact as
|
|
319
|
-
// a sibling reference file. The stage skill only links to it; agents load
|
|
320
|
-
// the reference on demand.
|
|
321
|
-
const referenceMarkdown = stageExamplesReferenceMarkdown(stage);
|
|
322
|
-
if (referenceMarkdown) {
|
|
323
|
-
const referenceDir = STAGE_EXAMPLES_REFERENCE_DIR.split("/");
|
|
324
|
-
await writeFileSafe(runtimePath(projectRoot, ...referenceDir, `${stage}-examples.md`), referenceMarkdown);
|
|
325
|
-
}
|
|
326
367
|
}
|
|
327
|
-
// Progressive disclosure for the TDD Batch Execution walkthrough (A.1#1).
|
|
328
|
-
// The detailed 3-task transcript lives next to stage examples so the
|
|
329
|
-
// always-rendered TDD skill stays under the line-budget and the reference
|
|
330
|
-
// is loaded on demand.
|
|
331
|
-
await writeFileSafe(runtimePath(projectRoot, ...STAGE_EXAMPLES_REFERENCE_DIR.split("/"), "tdd-batch-walkthrough.md"), TDD_BATCH_WALKTHROUGH_MARKDOWN);
|
|
332
|
-
await writeFileSafe(runtimePath(projectRoot, ...STAGE_EXAMPLES_REFERENCE_DIR.split("/"), "common-guidance.md"), stageCommonGuidanceMarkdown());
|
|
333
368
|
// Utility skills (not flow stages)
|
|
334
369
|
await writeFileSafe(runtimePath(projectRoot, "skills", "learnings", "SKILL.md"), learnSkillMarkdown());
|
|
335
370
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-next-step", "SKILL.md"), nextCommandSkillMarkdown());
|
|
336
371
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-ideate", "SKILL.md"), ideateCommandSkillMarkdown());
|
|
337
372
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-start", "SKILL.md"), startCommandSkillMarkdown());
|
|
338
373
|
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-view", "SKILL.md"), viewCommandSkillMarkdown());
|
|
339
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-status", "SKILL.md"), statusCommandSkillMarkdown());
|
|
340
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-tree", "SKILL.md"), treeCommandSkillMarkdown());
|
|
341
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-diff", "SKILL.md"), diffCommandSkillMarkdown());
|
|
342
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-ops", "SKILL.md"), opsCommandSkillMarkdown());
|
|
343
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "using-git-worktrees", "SKILL.md"), featureCommandSkillMarkdown());
|
|
344
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "tdd-cycle-log", "SKILL.md"), tddLogCommandSkillMarkdown());
|
|
345
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-retro", "SKILL.md"), retroCommandSkillMarkdown());
|
|
346
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-compound", "SKILL.md"), compoundCommandSkillMarkdown({
|
|
347
|
-
recurrenceThreshold: config?.compound?.recurrenceThreshold
|
|
348
|
-
}));
|
|
349
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-rewind", "SKILL.md"), rewindCommandSkillMarkdown());
|
|
350
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", "flow-archive", "SKILL.md"), archiveCommandSkillMarkdown());
|
|
351
374
|
await writeFileSafe(runtimePath(projectRoot, "skills", "subagent-dev", "SKILL.md"), subagentDrivenDevSkill());
|
|
352
375
|
await writeFileSafe(runtimePath(projectRoot, "skills", "parallel-dispatch", "SKILL.md"), parallelAgentsSkill());
|
|
353
376
|
await writeFileSafe(runtimePath(projectRoot, "skills", "session", "SKILL.md"), sessionHooksSkillMarkdown());
|
|
354
377
|
await writeFileSafe(runtimePath(projectRoot, "skills", "iron-laws", "SKILL.md"), ironLawsSkillMarkdown());
|
|
355
378
|
await writeFileSafe(runtimePath(projectRoot, "skills", META_SKILL_NAME, "SKILL.md"), usingCclawSkillMarkdown());
|
|
356
|
-
await writeFileSafe(runtimePath(projectRoot, "references", "protocols", "decision.md"), decisionProtocolMarkdown());
|
|
357
|
-
await writeFileSafe(runtimePath(projectRoot, "references", "protocols", "completion.md"), completionProtocolMarkdown());
|
|
358
|
-
await writeFileSafe(runtimePath(projectRoot, "references", "protocols", "ethos.md"), ethosProtocolMarkdown());
|
|
359
|
-
await writeFileSafe(runtimePath(projectRoot, "references", "flow-map.md"), flowMapMarkdown());
|
|
360
|
-
for (const folder of UTILITY_SKILL_FOLDERS) {
|
|
361
|
-
const generator = UTILITY_SKILL_MAP[folder];
|
|
362
|
-
await writeFileSafe(runtimePath(projectRoot, "skills", folder, "SKILL.md"), generator());
|
|
363
|
-
}
|
|
364
379
|
// In-thread research procedures (no YAML frontmatter, not delegated personas).
|
|
365
380
|
for (const [fileName, markdown] of Object.entries(RESEARCH_PLAYBOOKS)) {
|
|
366
381
|
await writeFileSafe(runtimePath(projectRoot, "skills", "research", fileName), markdown);
|
|
@@ -383,49 +398,12 @@ async function writeSkills(projectRoot, config) {
|
|
|
383
398
|
await fs.rm(legacyPath, { recursive: true, force: true });
|
|
384
399
|
}
|
|
385
400
|
}
|
|
386
|
-
// Per-harness tool maps (A.1#4). One reference file per supported harness
|
|
387
|
-
// plus an index; stage/utility skills cite these instead of hardcoding
|
|
388
|
-
// tool names inline.
|
|
389
|
-
const harnessIds = ["claude", "cursor", "opencode", "codex"];
|
|
390
|
-
const harnessRefsDir = HARNESS_TOOL_REFS_DIR.split("/");
|
|
391
|
-
await writeFileSafe(runtimePath(projectRoot, ...harnessRefsDir, "README.md"), HARNESS_TOOL_REFS_INDEX_MD);
|
|
392
|
-
for (const harness of harnessIds) {
|
|
393
|
-
await writeFileSafe(runtimePath(projectRoot, ...harnessRefsDir, `${harness}.md`), harnessToolRefMarkdown(harness));
|
|
394
|
-
}
|
|
395
|
-
const doctorRefsDir = ["references", "doctor"];
|
|
396
|
-
for (const [fileName, markdown] of Object.entries(DOCTOR_REFERENCE_MARKDOWN)) {
|
|
397
|
-
await writeFileSafe(runtimePath(projectRoot, ...doctorRefsDir, fileName), markdown);
|
|
398
|
-
}
|
|
399
|
-
await writeFileSafe(runtimePath(projectRoot, "references", "harnesses.md"), harnessIntegrationDocMarkdown());
|
|
400
|
-
await writeFileSafe(runtimePath(projectRoot, "references", "harnesses-overview.md"), harnessDocsOverviewMarkdown());
|
|
401
|
-
// Per-harness parity playbooks. Generated for every supported harness
|
|
402
|
-
// regardless of which harnesses the project installed — the index always
|
|
403
|
-
// resolves, and doctor only asserts presence of the installed harnesses'
|
|
404
|
-
// playbooks (see runtime-integrity checks).
|
|
405
|
-
const playbookDirSegments = HARNESS_PLAYBOOKS_DIR.split("/");
|
|
406
|
-
await writeFileSafe(runtimePath(projectRoot, ...playbookDirSegments, "README.md"), harnessPlaybooksIndexMarkdown());
|
|
407
|
-
for (const harness of harnessIds) {
|
|
408
|
-
await writeFileSafe(runtimePath(projectRoot, ...playbookDirSegments, harnessPlaybookFileName(harness)), harnessPlaybookMarkdown(harness));
|
|
409
|
-
}
|
|
410
401
|
}
|
|
411
|
-
async function
|
|
412
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "
|
|
402
|
+
async function writeEntryCommands(projectRoot) {
|
|
403
|
+
await writeFileSafe(runtimePath(projectRoot, "commands", "start.md"), startCommandContract());
|
|
413
404
|
await writeFileSafe(runtimePath(projectRoot, "commands", "next.md"), nextCommandContract());
|
|
414
405
|
await writeFileSafe(runtimePath(projectRoot, "commands", "ideate.md"), ideateCommandContract());
|
|
415
406
|
await writeFileSafe(runtimePath(projectRoot, "commands", "view.md"), viewCommandContract());
|
|
416
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "start.md"), startCommandContract());
|
|
417
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "status.md"), statusCommandContract());
|
|
418
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "tree.md"), treeCommandContract());
|
|
419
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "diff.md"), diffCommandContract());
|
|
420
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "ops.md"), opsCommandContract());
|
|
421
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "feature.md"), featureCommandContract());
|
|
422
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "tdd-log.md"), tddLogCommandContract());
|
|
423
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "retro.md"), retroCommandContract());
|
|
424
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "compound.md"), compoundCommandContract({
|
|
425
|
-
recurrenceThreshold: config.compound?.recurrenceThreshold
|
|
426
|
-
}));
|
|
427
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "archive.md"), archiveCommandContract());
|
|
428
|
-
await writeFileSafe(runtimePath(projectRoot, "commands", "rewind.md"), rewindCommandContract());
|
|
429
407
|
}
|
|
430
408
|
function toObject(value) {
|
|
431
409
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -799,78 +777,6 @@ async function ensureKnowledgeStore(projectRoot) {
|
|
|
799
777
|
await fs.rm(legacyMdPath, { force: true });
|
|
800
778
|
}
|
|
801
779
|
}
|
|
802
|
-
async function ensureSessionStateFiles(projectRoot) {
|
|
803
|
-
const stateDir = runtimePath(projectRoot, "state");
|
|
804
|
-
await ensureDir(stateDir);
|
|
805
|
-
// If flow-state.json is corrupt, `readFlowState` quarantines the bad
|
|
806
|
-
// file and throws. During install we'd rather continue than abort:
|
|
807
|
-
// the user just asked to set up cclaw, and the corrupt file is already
|
|
808
|
-
// preserved next to the original path. Fall back to a fresh initial
|
|
809
|
-
// state so the rest of install completes and the user can inspect the
|
|
810
|
-
// `.corrupt-<timestamp>.json` quarantine afterwards.
|
|
811
|
-
let flow;
|
|
812
|
-
try {
|
|
813
|
-
flow = await readFlowState(projectRoot);
|
|
814
|
-
}
|
|
815
|
-
catch (err) {
|
|
816
|
-
if (err instanceof CorruptFlowStateError) {
|
|
817
|
-
flow = createInitialFlowState();
|
|
818
|
-
}
|
|
819
|
-
else {
|
|
820
|
-
throw err;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
const activityPath = path.join(stateDir, "stage-activity.jsonl");
|
|
824
|
-
if (!(await exists(activityPath))) {
|
|
825
|
-
await writeFileSafe(activityPath, "", { mode: 0o600 });
|
|
826
|
-
}
|
|
827
|
-
const checkpointPath = path.join(stateDir, "checkpoint.json");
|
|
828
|
-
if (!(await exists(checkpointPath))) {
|
|
829
|
-
const initialCheckpoint = {
|
|
830
|
-
stage: flow.currentStage,
|
|
831
|
-
runId: flow.activeRunId,
|
|
832
|
-
status: "not_started",
|
|
833
|
-
lastCompletedStep: "",
|
|
834
|
-
remainingSteps: [],
|
|
835
|
-
blockers: [],
|
|
836
|
-
timestamp: new Date().toISOString()
|
|
837
|
-
};
|
|
838
|
-
await writeFileSafe(checkpointPath, `${JSON.stringify(initialCheckpoint, null, 2)}\n`, { mode: 0o600 });
|
|
839
|
-
}
|
|
840
|
-
const suggestionMemoryPath = path.join(stateDir, "suggestion-memory.json");
|
|
841
|
-
if (!(await exists(suggestionMemoryPath))) {
|
|
842
|
-
const suggestionMemory = {
|
|
843
|
-
enabled: true,
|
|
844
|
-
mutedStages: [],
|
|
845
|
-
lastSuggestedStage: "",
|
|
846
|
-
lastSuggestedAt: ""
|
|
847
|
-
};
|
|
848
|
-
await writeFileSafe(suggestionMemoryPath, `${JSON.stringify(suggestionMemory, null, 2)}\n`, { mode: 0o600 });
|
|
849
|
-
}
|
|
850
|
-
const contextModePath = path.join(stateDir, "context-mode.json");
|
|
851
|
-
if (!(await exists(contextModePath))) {
|
|
852
|
-
await writeFileSafe(contextModePath, `${JSON.stringify(createInitialContextModeState(), null, 2)}\n`, { mode: 0o600 });
|
|
853
|
-
}
|
|
854
|
-
const knowledgeDigestPath = path.join(stateDir, "knowledge-digest.md");
|
|
855
|
-
if (!(await exists(knowledgeDigestPath))) {
|
|
856
|
-
await writeFileSafe(knowledgeDigestPath, "# Knowledge digest (auto-generated)\n\n(no entries yet)\n");
|
|
857
|
-
}
|
|
858
|
-
const tddCycleLogPath = path.join(stateDir, "tdd-cycle-log.jsonl");
|
|
859
|
-
if (!(await exists(tddCycleLogPath))) {
|
|
860
|
-
await writeFileSafe(tddCycleLogPath, "", { mode: 0o600 });
|
|
861
|
-
}
|
|
862
|
-
const reconciliationNoticesPath = path.join(stateDir, "reconciliation-notices.json");
|
|
863
|
-
if (!(await exists(reconciliationNoticesPath))) {
|
|
864
|
-
await writeFileSafe(reconciliationNoticesPath, `${JSON.stringify({ schemaVersion: 1, notices: [] }, null, 2)}\n`, { mode: 0o600 });
|
|
865
|
-
}
|
|
866
|
-
const flowSnapshotPath = path.join(stateDir, "flow-state.snapshot.json");
|
|
867
|
-
if (!(await exists(flowSnapshotPath))) {
|
|
868
|
-
await writeFileSafe(flowSnapshotPath, `${JSON.stringify({
|
|
869
|
-
capturedAt: new Date().toISOString(),
|
|
870
|
-
state: flow
|
|
871
|
-
}, null, 2)}\n`, { mode: 0o600 });
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
780
|
async function writeRulebook(projectRoot) {
|
|
875
781
|
await writeFileSafe(runtimePath(projectRoot, "rules", "RULES.md"), RULEBOOK_MARKDOWN);
|
|
876
782
|
await writeFileSafe(runtimePath(projectRoot, "rules", "rules.json"), `${JSON.stringify(buildRulesJson(), null, 2)}\n`);
|
|
@@ -923,166 +829,34 @@ async function writeState(projectRoot, config, forceReset = false) {
|
|
|
923
829
|
const state = createInitialFlowState({ track: config.defaultTrack ?? "standard" });
|
|
924
830
|
await writeFileSafe(statePath, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
|
|
925
831
|
}
|
|
926
|
-
async function writeHarnessGapsState(projectRoot, harnesses) {
|
|
927
|
-
const report = harnesses.map((harness) => {
|
|
928
|
-
const capabilities = HARNESS_ADAPTERS[harness].capabilities;
|
|
929
|
-
const hookMap = HOOK_EVENTS_BY_HARNESS[harness];
|
|
930
|
-
const missingHookEvents = HOOK_SEMANTIC_EVENTS.filter((eventName) => !hookMap[eventName]);
|
|
931
|
-
const missingCapabilities = [];
|
|
932
|
-
if (capabilities.nativeSubagentDispatch !== "full") {
|
|
933
|
-
missingCapabilities.push(`nativeSubagentDispatch:${capabilities.nativeSubagentDispatch}`);
|
|
934
|
-
}
|
|
935
|
-
if (capabilities.hookSurface !== "full") {
|
|
936
|
-
missingCapabilities.push(`hookSurface:${capabilities.hookSurface}`);
|
|
937
|
-
}
|
|
938
|
-
if (capabilities.structuredAsk === "plain-text") {
|
|
939
|
-
missingCapabilities.push("structuredAsk:none");
|
|
940
|
-
}
|
|
941
|
-
const remediation = [];
|
|
942
|
-
switch (capabilities.subagentFallback) {
|
|
943
|
-
case "native":
|
|
944
|
-
// nothing to remediate — harness has first-class dispatch
|
|
945
|
-
break;
|
|
946
|
-
case "generic-dispatch":
|
|
947
|
-
remediation.push(`subagent dispatch → map named cclaw agents onto generic Task subagent_type per ${HARNESS_PLAYBOOKS_DIR}/${harness}-playbook.md`);
|
|
948
|
-
break;
|
|
949
|
-
case "role-switch":
|
|
950
|
-
remediation.push(`subagent dispatch → role-switch in-session with evidenceRefs per ${HARNESS_PLAYBOOKS_DIR}/${harness}-playbook.md`);
|
|
951
|
-
break;
|
|
952
|
-
case "waiver":
|
|
953
|
-
remediation.push(`subagent dispatch → record explicit harness_limitation waiver; no parity path available`);
|
|
954
|
-
break;
|
|
955
|
-
}
|
|
956
|
-
// Per-harness structuredAsk remediation: record either the fallback
|
|
957
|
-
// requirement (plain-text) or the gating / experimental status of the
|
|
958
|
-
// native primitive so `cclaw doctor` and harness-gaps.json stay
|
|
959
|
-
// honest about *why* a primitive might silently not fire.
|
|
960
|
-
switch (capabilities.structuredAsk) {
|
|
961
|
-
case "plain-text":
|
|
962
|
-
remediation.push("structured ask → fall back to a numbered plain-text list; first option is default");
|
|
963
|
-
break;
|
|
964
|
-
case "question":
|
|
965
|
-
remediation.push(`structured ask → OpenCode \`question\` tool; enable with \`permission.question: "allow"\` in \`opencode.json\` (ACP clients additionally need \`OPENCODE_ENABLE_QUESTION_TOOL=1\`). Fallback: shared plain-text lettered list.`);
|
|
966
|
-
break;
|
|
967
|
-
case "request_user_input":
|
|
968
|
-
remediation.push("structured ask → Codex `request_user_input` tool (experimental; surfaced in Plan / Collaboration mode). Fallback: shared plain-text lettered list when the tool is hidden.");
|
|
969
|
-
break;
|
|
970
|
-
case "AskUserQuestion":
|
|
971
|
-
case "AskQuestion":
|
|
972
|
-
// Native first-class ask — no remediation required.
|
|
973
|
-
break;
|
|
974
|
-
}
|
|
975
|
-
for (const event of missingHookEvents) {
|
|
976
|
-
if (harness === "codex" && event === "precompact_digest") {
|
|
977
|
-
// Codex CLI has no PreCompact event. Generic "schedule the script
|
|
978
|
-
// manually" copy doesn't help; instead, point the agent at the
|
|
979
|
-
// in-thread substitute that already exists in cclaw content
|
|
980
|
-
// (`/cc-ops retro` reads the same digest the hook would emit).
|
|
981
|
-
remediation.push("hook event precompact_digest → Codex has no PreCompact event; run `/cc-ops retro` in-thread before compaction instead of relying on a hook");
|
|
982
|
-
continue;
|
|
983
|
-
}
|
|
984
|
-
remediation.push(`hook event ${event} → schedule the corresponding script manually or accept reduced observability`);
|
|
985
|
-
}
|
|
986
|
-
return {
|
|
987
|
-
harness,
|
|
988
|
-
tier: harnessTier(harness),
|
|
989
|
-
subagentFallback: capabilities.subagentFallback,
|
|
990
|
-
playbookPath: `${RUNTIME_ROOT}/${HARNESS_PLAYBOOKS_DIR}/${harness}-playbook.md`,
|
|
991
|
-
missingCapabilities,
|
|
992
|
-
missingHookEvents,
|
|
993
|
-
remediation
|
|
994
|
-
};
|
|
995
|
-
});
|
|
996
|
-
await writeFileSafe(runtimePath(projectRoot, "state", "harness-gaps.json"), `${JSON.stringify({
|
|
997
|
-
generatedAt: new Date().toISOString(),
|
|
998
|
-
schemaVersion: 2,
|
|
999
|
-
harnesses: report
|
|
1000
|
-
}, null, 2)}\n`);
|
|
1001
|
-
}
|
|
1002
832
|
async function cleanLegacyArtifacts(projectRoot) {
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
"project-learnings",
|
|
1006
|
-
"auto-orchestration",
|
|
1007
|
-
"autoplan",
|
|
1008
|
-
"red-first-testing",
|
|
1009
|
-
"incremental-implementation",
|
|
1010
|
-
"subagent-driven-development",
|
|
1011
|
-
"dispatching-parallel-agents",
|
|
1012
|
-
"session-guidelines",
|
|
1013
|
-
"security-review",
|
|
1014
|
-
"documentation",
|
|
1015
|
-
"browser-qa-testing",
|
|
1016
|
-
"feature-workspaces"
|
|
1017
|
-
]) {
|
|
1018
|
-
try {
|
|
1019
|
-
await fs.rm(runtimePath(projectRoot, "skills", legacyFolder), {
|
|
1020
|
-
recursive: true,
|
|
1021
|
-
force: true
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
catch {
|
|
1025
|
-
// best-effort cleanup
|
|
1026
|
-
}
|
|
833
|
+
for (const legacyFolder of DEPRECATED_UTILITY_SKILL_FOLDERS) {
|
|
834
|
+
await removeBestEffort(runtimePath(projectRoot, "skills", legacyFolder), true);
|
|
1027
835
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
await fs.rm(runtimePath(projectRoot, "agents", "securityer.md"), { force: true });
|
|
1031
|
-
}
|
|
1032
|
-
catch {
|
|
1033
|
-
// best-effort cleanup
|
|
1034
|
-
}
|
|
1035
|
-
// Core-5 migration: remove deprecated generated agent personas.
|
|
1036
|
-
for (const legacyAgentFile of [
|
|
1037
|
-
"spec-reviewer.md",
|
|
1038
|
-
"code-reviewer.md",
|
|
1039
|
-
"repo-research-analyst.md",
|
|
1040
|
-
"learnings-researcher.md",
|
|
1041
|
-
"framework-docs-researcher.md",
|
|
1042
|
-
"best-practices-researcher.md",
|
|
1043
|
-
"git-history-analyzer.md"
|
|
1044
|
-
]) {
|
|
1045
|
-
try {
|
|
1046
|
-
await fs.rm(runtimePath(projectRoot, "agents", legacyAgentFile), { force: true });
|
|
1047
|
-
}
|
|
1048
|
-
catch {
|
|
1049
|
-
// best-effort cleanup
|
|
1050
|
-
}
|
|
836
|
+
for (const legacyAgentFile of DEPRECATED_AGENT_FILES) {
|
|
837
|
+
await removeBestEffort(runtimePath(projectRoot, "agents", legacyAgentFile));
|
|
1051
838
|
}
|
|
1052
839
|
for (const legacyPlugin of [
|
|
1053
840
|
path.join(projectRoot, ".opencode/plugins/viby-plugin.mjs"),
|
|
1054
841
|
path.join(projectRoot, ".opencode/plugins/opencode-plugin.mjs"),
|
|
1055
842
|
path.join(projectRoot, OPENCODE_PLUGIN_REL_PATH)
|
|
1056
843
|
]) {
|
|
1057
|
-
|
|
1058
|
-
await fs.rm(legacyPlugin, { force: true });
|
|
1059
|
-
}
|
|
1060
|
-
catch {
|
|
1061
|
-
// best-effort cleanup
|
|
1062
|
-
}
|
|
844
|
+
await removeBestEffort(legacyPlugin);
|
|
1063
845
|
}
|
|
1064
846
|
for (const legacyRuntimeFile of [
|
|
1065
|
-
runtimePath(projectRoot, "
|
|
1066
|
-
runtimePath(projectRoot, "
|
|
1067
|
-
runtimePath(projectRoot, "
|
|
1068
|
-
runtimePath(projectRoot, "
|
|
1069
|
-
runtimePath(projectRoot,
|
|
1070
|
-
runtimePath(projectRoot, "hooks",
|
|
1071
|
-
runtimePath(projectRoot, "hooks", "session-start.sh"),
|
|
1072
|
-
runtimePath(projectRoot, "hooks", "stop-checkpoint.sh"),
|
|
1073
|
-
runtimePath(projectRoot, "hooks", "run-hook.cmd"),
|
|
1074
|
-
runtimePath(projectRoot, "hooks", "stage-complete.sh"),
|
|
1075
|
-
runtimePath(projectRoot, "hooks", "pre-compact.sh"),
|
|
1076
|
-
runtimePath(projectRoot, "hooks", "prompt-guard.sh"),
|
|
1077
|
-
runtimePath(projectRoot, "hooks", "workflow-guard.sh"),
|
|
1078
|
-
runtimePath(projectRoot, "hooks", "context-monitor.sh")
|
|
847
|
+
...FLOW_STAGES.map((stage) => runtimePath(projectRoot, "commands", `${stage}.md`)),
|
|
848
|
+
...DEPRECATED_COMMAND_FILES.map((file) => runtimePath(projectRoot, "commands", file)),
|
|
849
|
+
...DEPRECATED_SKILL_FILES.map((segments) => runtimePath(projectRoot, "skills", ...segments)),
|
|
850
|
+
...DEPRECATED_STATE_FILES.map((file) => runtimePath(projectRoot, "state", file)),
|
|
851
|
+
...DEPRECATED_RUNTIME_ROOT_FILES.map((file) => runtimePath(projectRoot, file)),
|
|
852
|
+
...DEPRECATED_HOOK_FILES.map((file) => runtimePath(projectRoot, "hooks", file))
|
|
1079
853
|
]) {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
854
|
+
await removeBestEffort(legacyRuntimeFile);
|
|
855
|
+
}
|
|
856
|
+
// Runtime simplification cleanup: these folders were generated in older
|
|
857
|
+
// releases and are now intentionally removed from user projects.
|
|
858
|
+
for (const legacyRuntimeDir of DEPRECATED_RUNTIME_DIRS) {
|
|
859
|
+
await removeBestEffort(runtimePath(projectRoot, legacyRuntimeDir), true);
|
|
1086
860
|
}
|
|
1087
861
|
// D-4 terminology migration: rename historical ideation artifacts to the
|
|
1088
862
|
// canonical ideate-* naming without deleting user-authored content.
|
|
@@ -1142,17 +916,13 @@ async function materializeRuntime(projectRoot, config, forceStateReset) {
|
|
|
1142
916
|
await cleanLegacyArtifacts(projectRoot);
|
|
1143
917
|
await cleanStaleFiles(projectRoot);
|
|
1144
918
|
await Promise.all([
|
|
1145
|
-
|
|
1146
|
-
writeUtilityCommands(projectRoot, config),
|
|
919
|
+
writeEntryCommands(projectRoot),
|
|
1147
920
|
writeSkills(projectRoot, config),
|
|
1148
921
|
writeArtifactTemplates(projectRoot),
|
|
1149
|
-
writeEvalScaffold(projectRoot),
|
|
1150
922
|
writeRulebook(projectRoot)
|
|
1151
923
|
]);
|
|
1152
924
|
await writeState(projectRoot, config, forceStateReset);
|
|
1153
925
|
await ensureRunSystem(projectRoot, { createIfMissing: false });
|
|
1154
|
-
await ensureSessionStateFiles(projectRoot);
|
|
1155
|
-
await writeHarnessGapsState(projectRoot, harnesses);
|
|
1156
926
|
await ensureKnowledgeStore(projectRoot);
|
|
1157
927
|
await writeHooks(projectRoot, config);
|
|
1158
928
|
await syncDisabledHarnessArtifacts(projectRoot, harnesses);
|
|
@@ -1280,7 +1050,7 @@ function isManagedRuntimeHookCommand(command) {
|
|
|
1280
1050
|
// (e.g. `node .cclaw\hooks\run-hook.mjs ...`) still round-trip through
|
|
1281
1051
|
// sync without being duplicated alongside freshly generated entries.
|
|
1282
1052
|
const normalized = command.trim().replace(/\s+/gu, " ").replace(/\\/gu, "/");
|
|
1283
|
-
if (/(^|\s)(?:node\s+)?(?:"|')?(?:\.\/)?\.cclaw\/hooks\/run-hook\.(?:mjs|cmd)(?:"|')?\s+(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor|verify-current-state)(?:\s|$)/u.test(normalized)) {
|
|
1053
|
+
if (/(^|\s)(?:node\s+)?(?:"|')?(?:\.\/)?\.cclaw\/hooks\/run-hook\.(?:mjs|cmd)(?:"|')?\s+(?:session-start|stop-handoff|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor|verify-current-state)(?:\s|$)/u.test(normalized)) {
|
|
1284
1054
|
return true;
|
|
1285
1055
|
}
|
|
1286
1056
|
// Codex UserPromptSubmit non-blocking state nudge.
|
|
@@ -6,7 +6,6 @@ import { resolveArtifactPath } from "../artifact-paths.js";
|
|
|
6
6
|
import { RUNTIME_ROOT, SHIP_FINALIZATION_MODES } from "../constants.js";
|
|
7
7
|
import { stageSchema } from "../content/stage-schema.js";
|
|
8
8
|
import { appendDelegation, checkMandatoryDelegations } from "../delegation.js";
|
|
9
|
-
import { readActiveFeature } from "../feature-system.js";
|
|
10
9
|
import { verifyCompletedStagesGateClosure, verifyCurrentStageGateEvidence } from "../gate-evidence.js";
|
|
11
10
|
import { extractMarkdownSectionBody, parseLearningsSection } from "../artifact-linter.js";
|
|
12
11
|
import { getAvailableTransitions, getTransitionGuards, isFlowTrack } from "../flow-state.js";
|
|
@@ -16,7 +15,6 @@ import { FLOW_STAGES } from "../types.js";
|
|
|
16
15
|
import { runCompoundReadinessCommand } from "./compound-readiness.js";
|
|
17
16
|
import { runHookManifestCommand } from "./hook-manifest.js";
|
|
18
17
|
import { runEnvelopeValidateCommand } from "./envelope-validate.js";
|
|
19
|
-
import { runKnowledgeDigestCommand } from "./knowledge-digest.js";
|
|
20
18
|
import { runTddLoopStatusCommand } from "./tdd-loop-status.js";
|
|
21
19
|
import { runTddRedEvidenceCommand } from "./tdd-red-evidence.js";
|
|
22
20
|
import { extractReviewLoopEnvelopeFromArtifact } from "../content/review-loop.js";
|
|
@@ -550,11 +548,10 @@ async function harvestStageLearnings(projectRoot, stage, track) {
|
|
|
550
548
|
details: parsed.details
|
|
551
549
|
};
|
|
552
550
|
}
|
|
553
|
-
const activeFeature = await readActiveFeature(projectRoot).catch(() => null);
|
|
554
551
|
const appendResult = await appendKnowledge(projectRoot, parsed.entries, {
|
|
555
552
|
stage,
|
|
556
553
|
originStage: stage,
|
|
557
|
-
|
|
554
|
+
originRun: null,
|
|
558
555
|
project: path.basename(projectRoot)
|
|
559
556
|
});
|
|
560
557
|
if (appendResult.invalid > 0) {
|
|
@@ -823,7 +820,7 @@ async function runHookCommand(projectRoot, args, io) {
|
|
|
823
820
|
export async function runInternalCommand(projectRoot, argv, io) {
|
|
824
821
|
const [subcommand, ...tokens] = argv;
|
|
825
822
|
if (!subcommand) {
|
|
826
|
-
io.stderr.write("cclaw internal requires a subcommand: advance-stage | verify-flow-state-diff | verify-current-state |
|
|
823
|
+
io.stderr.write("cclaw internal requires a subcommand: advance-stage | verify-flow-state-diff | verify-current-state | envelope-validate | tdd-red-evidence | tdd-loop-status | compound-readiness | hook-manifest | hook\n");
|
|
827
824
|
return 1;
|
|
828
825
|
}
|
|
829
826
|
try {
|
|
@@ -836,9 +833,6 @@ export async function runInternalCommand(projectRoot, argv, io) {
|
|
|
836
833
|
if (subcommand === "verify-current-state") {
|
|
837
834
|
return await runVerifyCurrentState(projectRoot, parseVerifyCurrentStateArgs(tokens), io);
|
|
838
835
|
}
|
|
839
|
-
if (subcommand === "knowledge-digest") {
|
|
840
|
-
return await runKnowledgeDigestCommand(projectRoot, tokens, io);
|
|
841
|
-
}
|
|
842
836
|
if (subcommand === "envelope-validate") {
|
|
843
837
|
return await runEnvelopeValidateCommand(projectRoot, tokens, io);
|
|
844
838
|
}
|
|
@@ -857,7 +851,7 @@ export async function runInternalCommand(projectRoot, argv, io) {
|
|
|
857
851
|
if (subcommand === "hook") {
|
|
858
852
|
return await runHookCommand(projectRoot, parseHookArgs(tokens), io);
|
|
859
853
|
}
|
|
860
|
-
io.stderr.write(`Unknown internal subcommand: ${subcommand}. Expected advance-stage | verify-flow-state-diff | verify-current-state |
|
|
854
|
+
io.stderr.write(`Unknown internal subcommand: ${subcommand}. Expected advance-stage | verify-flow-state-diff | verify-current-state | envelope-validate | tdd-red-evidence | tdd-loop-status | compound-readiness | hook-manifest | hook\n`);
|
|
861
855
|
return 1;
|
|
862
856
|
}
|
|
863
857
|
catch (err) {
|