cclaw-cli 7.7.1 → 8.1.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 +211 -134
- package/dist/artifact-frontmatter.d.ts +51 -0
- package/dist/artifact-frontmatter.js +131 -0
- package/dist/artifact-paths.d.ts +7 -27
- package/dist/artifact-paths.js +20 -249
- package/dist/cancel.d.ts +16 -0
- package/dist/cancel.js +66 -0
- package/dist/cli.d.ts +2 -27
- package/dist/cli.js +107 -511
- package/dist/compound.d.ts +26 -0
- package/dist/compound.js +96 -0
- package/dist/config.d.ts +14 -51
- package/dist/config.js +23 -359
- package/dist/constants.d.ts +11 -18
- package/dist/constants.js +19 -106
- package/dist/content/antipatterns.d.ts +1 -0
- package/dist/content/antipatterns.js +109 -0
- package/dist/content/artifact-templates.d.ts +10 -0
- package/dist/content/artifact-templates.js +550 -0
- package/dist/content/cancel-command.d.ts +2 -2
- package/dist/content/cancel-command.js +25 -17
- package/dist/content/core-agents.d.ts +9 -233
- package/dist/content/core-agents.js +39 -768
- package/dist/content/decision-protocol.d.ts +1 -12
- package/dist/content/decision-protocol.js +27 -20
- package/dist/content/examples.d.ts +8 -42
- package/dist/content/examples.js +293 -425
- package/dist/content/idea-command.d.ts +2 -0
- package/dist/content/idea-command.js +38 -0
- package/dist/content/iron-laws.d.ts +4 -138
- package/dist/content/iron-laws.js +18 -197
- package/dist/content/meta-skill.d.ts +1 -3
- package/dist/content/meta-skill.js +57 -134
- package/dist/content/node-hooks.d.ts +12 -8
- package/dist/content/node-hooks.js +188 -838
- package/dist/content/recovery.d.ts +8 -0
- package/dist/content/recovery.js +179 -0
- package/dist/content/reference-patterns.d.ts +4 -13
- package/dist/content/reference-patterns.js +260 -389
- package/dist/content/research-playbooks.d.ts +8 -8
- package/dist/content/research-playbooks.js +108 -121
- package/dist/content/review-loop.d.ts +6 -192
- package/dist/content/review-loop.js +29 -731
- package/dist/content/skills.d.ts +8 -38
- package/dist/content/skills.js +681 -732
- package/dist/content/specialist-prompts/architect.d.ts +1 -0
- package/dist/content/specialist-prompts/architect.js +225 -0
- package/dist/content/specialist-prompts/brainstormer.d.ts +1 -0
- package/dist/content/specialist-prompts/brainstormer.js +168 -0
- package/dist/content/specialist-prompts/index.d.ts +2 -0
- package/dist/content/specialist-prompts/index.js +14 -0
- package/dist/content/specialist-prompts/planner.d.ts +1 -0
- package/dist/content/specialist-prompts/planner.js +182 -0
- package/dist/content/specialist-prompts/reviewer.d.ts +1 -0
- package/dist/content/specialist-prompts/reviewer.js +193 -0
- package/dist/content/specialist-prompts/security-reviewer.d.ts +1 -0
- package/dist/content/specialist-prompts/security-reviewer.js +133 -0
- package/dist/content/specialist-prompts/slice-builder.d.ts +1 -0
- package/dist/content/specialist-prompts/slice-builder.js +232 -0
- package/dist/content/stage-playbooks.d.ts +8 -0
- package/dist/content/stage-playbooks.js +404 -0
- package/dist/content/start-command.d.ts +2 -12
- package/dist/content/start-command.js +221 -207
- package/dist/flow-state.d.ts +21 -178
- package/dist/flow-state.js +67 -170
- package/dist/fs-utils.d.ts +6 -26
- package/dist/fs-utils.js +29 -162
- package/dist/gitignore.d.ts +2 -1
- package/dist/gitignore.js +51 -34
- package/dist/harness-detect.d.ts +10 -0
- package/dist/harness-detect.js +29 -0
- package/dist/harness-prompt.d.ts +26 -0
- package/dist/harness-prompt.js +142 -0
- package/dist/install.d.ts +35 -15
- package/dist/install.js +238 -1347
- package/dist/knowledge-store.d.ts +19 -163
- package/dist/knowledge-store.js +56 -590
- package/dist/logger.d.ts +8 -3
- package/dist/logger.js +13 -4
- package/dist/orchestrator-routing.d.ts +29 -0
- package/dist/orchestrator-routing.js +156 -0
- package/dist/run-persistence.d.ts +7 -118
- package/dist/run-persistence.js +29 -845
- package/dist/runtime/run-hook.entry.d.ts +1 -3
- package/dist/runtime/run-hook.entry.js +19 -4
- package/dist/runtime/run-hook.mjs +13 -1024
- package/dist/types.d.ts +25 -261
- package/dist/types.js +8 -36
- package/package.json +6 -3
- package/dist/artifact-linter/brainstorm.d.ts +0 -2
- package/dist/artifact-linter/brainstorm.js +0 -353
- package/dist/artifact-linter/design.d.ts +0 -18
- package/dist/artifact-linter/design.js +0 -444
- package/dist/artifact-linter/findings-dedup.d.ts +0 -56
- package/dist/artifact-linter/findings-dedup.js +0 -232
- package/dist/artifact-linter/plan.d.ts +0 -2
- package/dist/artifact-linter/plan.js +0 -826
- package/dist/artifact-linter/review-army.d.ts +0 -49
- package/dist/artifact-linter/review-army.js +0 -520
- package/dist/artifact-linter/review.d.ts +0 -2
- package/dist/artifact-linter/review.js +0 -113
- package/dist/artifact-linter/scope.d.ts +0 -2
- package/dist/artifact-linter/scope.js +0 -158
- package/dist/artifact-linter/shared.d.ts +0 -637
- package/dist/artifact-linter/shared.js +0 -2163
- package/dist/artifact-linter/ship.d.ts +0 -2
- package/dist/artifact-linter/ship.js +0 -250
- package/dist/artifact-linter/spec.d.ts +0 -2
- package/dist/artifact-linter/spec.js +0 -176
- package/dist/artifact-linter/tdd.d.ts +0 -118
- package/dist/artifact-linter/tdd.js +0 -1404
- package/dist/artifact-linter.d.ts +0 -15
- package/dist/artifact-linter.js +0 -517
- package/dist/codex-feature-flag.d.ts +0 -58
- package/dist/codex-feature-flag.js +0 -193
- package/dist/content/closeout-guidance.d.ts +0 -14
- package/dist/content/closeout-guidance.js +0 -44
- package/dist/content/diff-command.d.ts +0 -1
- package/dist/content/diff-command.js +0 -43
- package/dist/content/harness-doc.d.ts +0 -1
- package/dist/content/harness-doc.js +0 -65
- package/dist/content/hook-events.d.ts +0 -9
- package/dist/content/hook-events.js +0 -23
- package/dist/content/hook-manifest.d.ts +0 -81
- package/dist/content/hook-manifest.js +0 -156
- package/dist/content/hooks.d.ts +0 -11
- package/dist/content/hooks.js +0 -1972
- package/dist/content/idea.d.ts +0 -60
- package/dist/content/idea.js +0 -416
- package/dist/content/language-policy.d.ts +0 -2
- package/dist/content/language-policy.js +0 -13
- package/dist/content/learnings.d.ts +0 -6
- package/dist/content/learnings.js +0 -141
- package/dist/content/observe.d.ts +0 -19
- package/dist/content/observe.js +0 -86
- package/dist/content/opencode-plugin.d.ts +0 -1
- package/dist/content/opencode-plugin.js +0 -635
- package/dist/content/review-prompts.d.ts +0 -1
- package/dist/content/review-prompts.js +0 -104
- package/dist/content/runtime-shared-snippets.d.ts +0 -8
- package/dist/content/runtime-shared-snippets.js +0 -80
- package/dist/content/session-hooks.d.ts +0 -7
- package/dist/content/session-hooks.js +0 -107
- package/dist/content/skills-elicitation.d.ts +0 -1
- package/dist/content/skills-elicitation.js +0 -167
- package/dist/content/stage-command.d.ts +0 -2
- package/dist/content/stage-command.js +0 -17
- package/dist/content/stage-schema.d.ts +0 -117
- package/dist/content/stage-schema.js +0 -955
- package/dist/content/stages/_lint-metadata/index.d.ts +0 -2
- package/dist/content/stages/_lint-metadata/index.js +0 -97
- package/dist/content/stages/brainstorm.d.ts +0 -2
- package/dist/content/stages/brainstorm.js +0 -184
- package/dist/content/stages/design.d.ts +0 -2
- package/dist/content/stages/design.js +0 -288
- package/dist/content/stages/index.d.ts +0 -8
- package/dist/content/stages/index.js +0 -11
- package/dist/content/stages/plan.d.ts +0 -2
- package/dist/content/stages/plan.js +0 -191
- package/dist/content/stages/review.d.ts +0 -2
- package/dist/content/stages/review.js +0 -240
- package/dist/content/stages/schema-types.d.ts +0 -203
- package/dist/content/stages/schema-types.js +0 -1
- package/dist/content/stages/scope.d.ts +0 -2
- package/dist/content/stages/scope.js +0 -254
- package/dist/content/stages/ship.d.ts +0 -2
- package/dist/content/stages/ship.js +0 -159
- package/dist/content/stages/spec.d.ts +0 -2
- package/dist/content/stages/spec.js +0 -170
- package/dist/content/stages/tdd.d.ts +0 -4
- package/dist/content/stages/tdd.js +0 -273
- package/dist/content/state-contracts.d.ts +0 -1
- package/dist/content/state-contracts.js +0 -63
- package/dist/content/status-command.d.ts +0 -4
- package/dist/content/status-command.js +0 -109
- package/dist/content/subagent-context-skills.d.ts +0 -4
- package/dist/content/subagent-context-skills.js +0 -279
- package/dist/content/subagents.d.ts +0 -3
- package/dist/content/subagents.js +0 -997
- package/dist/content/templates.d.ts +0 -26
- package/dist/content/templates.js +0 -1692
- package/dist/content/track-render-context.d.ts +0 -18
- package/dist/content/track-render-context.js +0 -53
- package/dist/content/tree-command.d.ts +0 -1
- package/dist/content/tree-command.js +0 -64
- package/dist/content/utility-skills.d.ts +0 -30
- package/dist/content/utility-skills.js +0 -160
- package/dist/content/view-command.d.ts +0 -2
- package/dist/content/view-command.js +0 -92
- package/dist/delegation.d.ts +0 -649
- package/dist/delegation.js +0 -1539
- package/dist/early-loop.d.ts +0 -70
- package/dist/early-loop.js +0 -302
- package/dist/execution-topology.d.ts +0 -44
- package/dist/execution-topology.js +0 -95
- package/dist/gate-evidence.d.ts +0 -85
- package/dist/gate-evidence.js +0 -631
- package/dist/harness-adapters.d.ts +0 -151
- package/dist/harness-adapters.js +0 -756
- package/dist/harness-selection.d.ts +0 -31
- package/dist/harness-selection.js +0 -214
- package/dist/hook-schema.d.ts +0 -6
- package/dist/hook-schema.js +0 -114
- package/dist/hook-schemas/claude-hooks.v1.json +0 -10
- package/dist/hook-schemas/codex-hooks.v1.json +0 -10
- package/dist/hook-schemas/cursor-hooks.v1.json +0 -13
- package/dist/init-detect.d.ts +0 -2
- package/dist/init-detect.js +0 -50
- package/dist/internal/advance-stage/advance.d.ts +0 -89
- package/dist/internal/advance-stage/advance.js +0 -655
- package/dist/internal/advance-stage/cancel-run.d.ts +0 -8
- package/dist/internal/advance-stage/cancel-run.js +0 -19
- package/dist/internal/advance-stage/flow-state-coercion.d.ts +0 -3
- package/dist/internal/advance-stage/flow-state-coercion.js +0 -81
- package/dist/internal/advance-stage/helpers.d.ts +0 -14
- package/dist/internal/advance-stage/helpers.js +0 -145
- package/dist/internal/advance-stage/hook.d.ts +0 -8
- package/dist/internal/advance-stage/hook.js +0 -40
- package/dist/internal/advance-stage/parsers.d.ts +0 -72
- package/dist/internal/advance-stage/parsers.js +0 -357
- package/dist/internal/advance-stage/proactive-delegation-trace.d.ts +0 -24
- package/dist/internal/advance-stage/proactive-delegation-trace.js +0 -56
- package/dist/internal/advance-stage/review-loop.d.ts +0 -16
- package/dist/internal/advance-stage/review-loop.js +0 -199
- package/dist/internal/advance-stage/rewind.d.ts +0 -14
- package/dist/internal/advance-stage/rewind.js +0 -108
- package/dist/internal/advance-stage/start-flow.d.ts +0 -13
- package/dist/internal/advance-stage/start-flow.js +0 -241
- package/dist/internal/advance-stage/verify.d.ts +0 -21
- package/dist/internal/advance-stage/verify.js +0 -185
- package/dist/internal/advance-stage.d.ts +0 -7
- package/dist/internal/advance-stage.js +0 -138
- package/dist/internal/cohesion-contract-stub.d.ts +0 -24
- package/dist/internal/cohesion-contract-stub.js +0 -148
- package/dist/internal/compound-readiness.d.ts +0 -23
- package/dist/internal/compound-readiness.js +0 -102
- package/dist/internal/detect-public-api-changes.d.ts +0 -5
- package/dist/internal/detect-public-api-changes.js +0 -45
- package/dist/internal/detect-supply-chain-changes.d.ts +0 -6
- package/dist/internal/detect-supply-chain-changes.js +0 -138
- package/dist/internal/early-loop-status.d.ts +0 -7
- package/dist/internal/early-loop-status.js +0 -93
- package/dist/internal/envelope-validate.d.ts +0 -7
- package/dist/internal/envelope-validate.js +0 -66
- package/dist/internal/flow-state-repair.d.ts +0 -20
- package/dist/internal/flow-state-repair.js +0 -104
- package/dist/internal/plan-split-waves.d.ts +0 -190
- package/dist/internal/plan-split-waves.js +0 -764
- package/dist/internal/runtime-integrity.d.ts +0 -7
- package/dist/internal/runtime-integrity.js +0 -268
- package/dist/internal/slice-commit.d.ts +0 -7
- package/dist/internal/slice-commit.js +0 -619
- package/dist/internal/tdd-loop-status.d.ts +0 -14
- package/dist/internal/tdd-loop-status.js +0 -68
- package/dist/internal/tdd-red-evidence.d.ts +0 -7
- package/dist/internal/tdd-red-evidence.js +0 -153
- package/dist/internal/waiver-grant.d.ts +0 -62
- package/dist/internal/waiver-grant.js +0 -294
- package/dist/internal/wave-status.d.ts +0 -74
- package/dist/internal/wave-status.js +0 -506
- package/dist/managed-resources.d.ts +0 -53
- package/dist/managed-resources.js +0 -313
- package/dist/policy.d.ts +0 -10
- package/dist/policy.js +0 -167
- package/dist/retro-gate.d.ts +0 -9
- package/dist/retro-gate.js +0 -47
- package/dist/run-archive.d.ts +0 -61
- package/dist/run-archive.js +0 -391
- package/dist/runs.d.ts +0 -2
- package/dist/runs.js +0 -2
- package/dist/stack-detection.d.ts +0 -116
- package/dist/stack-detection.js +0 -489
- package/dist/streaming/event-stream.d.ts +0 -31
- package/dist/streaming/event-stream.js +0 -114
- package/dist/tdd-cycle.d.ts +0 -107
- package/dist/tdd-cycle.js +0 -289
- package/dist/tdd-verification-evidence.d.ts +0 -17
- package/dist/tdd-verification-evidence.js +0 -122
- package/dist/track-heuristics.d.ts +0 -27
- package/dist/track-heuristics.js +0 -154
- package/dist/util/slice-id.d.ts +0 -58
- package/dist/util/slice-id.js +0 -89
- package/dist/worktree-manager.d.ts +0 -20
- package/dist/worktree-manager.js +0 -108
package/dist/artifact-paths.js
CHANGED
|
@@ -1,261 +1,32 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const ext = path.extname(fileName);
|
|
13
|
-
if (!ext) {
|
|
14
|
-
return { stem: fileName, ext: "" };
|
|
15
|
-
}
|
|
16
|
-
return { stem: fileName.slice(0, -ext.length), ext };
|
|
17
|
-
}
|
|
18
|
-
function appendCollisionSuffix(fileName, index) {
|
|
19
|
-
const { stem, ext } = splitExt(fileName);
|
|
20
|
-
return `${stem}-${index}${ext}`;
|
|
21
|
-
}
|
|
22
|
-
export function isSlugArtifactPattern(filePattern) {
|
|
23
|
-
return filePattern.includes("<slug>");
|
|
24
|
-
}
|
|
25
|
-
export function legacyArtifactFileName(filePattern) {
|
|
26
|
-
if (!isSlugArtifactPattern(filePattern)) {
|
|
27
|
-
return filePattern;
|
|
28
|
-
}
|
|
29
|
-
return filePattern.replace(/-<slug>/gu, "");
|
|
30
|
-
}
|
|
2
|
+
import { FLOWS_ROOT, SHIPPED_DIR_REL_PATH } from "./constants.js";
|
|
3
|
+
export const ARTIFACT_FILE_NAMES = {
|
|
4
|
+
plan: "plan.md",
|
|
5
|
+
build: "build.md",
|
|
6
|
+
review: "review.md",
|
|
7
|
+
ship: "ship.md",
|
|
8
|
+
decisions: "decisions.md",
|
|
9
|
+
learnings: "learnings.md"
|
|
10
|
+
};
|
|
31
11
|
export function slugifyArtifactTopic(topic) {
|
|
32
|
-
const
|
|
12
|
+
const slug = topic
|
|
33
13
|
.toLowerCase()
|
|
34
14
|
.trim()
|
|
35
|
-
.replace(/[`"'
|
|
15
|
+
.replace(/[`"'()[\]{}<>]/gu, " ")
|
|
36
16
|
.replace(/[^a-z0-9]+/gu, "-")
|
|
37
17
|
.replace(/^-+/u, "")
|
|
38
18
|
.replace(/-+$/u, "");
|
|
39
|
-
|
|
40
|
-
return DEFAULT_TOPIC_SLUG;
|
|
41
|
-
}
|
|
42
|
-
return normalized.slice(0, 48);
|
|
43
|
-
}
|
|
44
|
-
function slugPatternRegex(filePattern) {
|
|
45
|
-
const [left, right] = filePattern.split("<slug>");
|
|
46
|
-
return new RegExp(`^${escapeRegExp(left ?? "")}[a-z0-9]+(?:-[a-z0-9]+)*(?:-\\d+)?${escapeRegExp(right ?? "")}$`, "u");
|
|
47
|
-
}
|
|
48
|
-
function searchRoots(projectRoot) {
|
|
49
|
-
return [
|
|
50
|
-
{
|
|
51
|
-
absDir: path.join(projectRoot, RUNTIME_ROOT, "artifacts"),
|
|
52
|
-
relPrefix: path.join(RUNTIME_ROOT, "artifacts")
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
absDir: projectRoot,
|
|
56
|
-
relPrefix: ""
|
|
57
|
-
}
|
|
58
|
-
];
|
|
59
|
-
}
|
|
60
|
-
function candidateFromRoot(root, fileName) {
|
|
61
|
-
return {
|
|
62
|
-
relPath: root.relPrefix ? path.join(root.relPrefix, fileName) : fileName,
|
|
63
|
-
absPath: path.join(root.absDir, fileName)
|
|
64
|
-
};
|
|
19
|
+
return (slug || "task").slice(0, 64);
|
|
65
20
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (!(await exists(ideaPath))) {
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
const raw = await fs.readFile(ideaPath, "utf8");
|
|
73
|
-
const lines = raw.split(/\r?\n/gu);
|
|
74
|
-
const userPromptHeading = lines.findIndex((line) => /^##\s+user prompt\b/iu.test(line.trim()));
|
|
75
|
-
if (userPromptHeading >= 0) {
|
|
76
|
-
for (let i = userPromptHeading + 1; i < lines.length; i += 1) {
|
|
77
|
-
const line = lines[i].trim();
|
|
78
|
-
if (line.length === 0)
|
|
79
|
-
continue;
|
|
80
|
-
if (/^##\s+/u.test(line))
|
|
81
|
-
break;
|
|
82
|
-
const candidate = line.replace(/^[-*>\s#]+/u, "").trim();
|
|
83
|
-
if (candidate.length > 0) {
|
|
84
|
-
return candidate;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const metadataLine = /^(?:class|track|stack|reclassification)\s*:/iu;
|
|
89
|
-
for (const line of lines) {
|
|
90
|
-
const trimmed = line.trim();
|
|
91
|
-
if (trimmed.length === 0)
|
|
92
|
-
continue;
|
|
93
|
-
if (metadataLine.test(trimmed))
|
|
94
|
-
continue;
|
|
95
|
-
if (/^##\s+/u.test(trimmed))
|
|
96
|
-
continue;
|
|
97
|
-
const candidate = trimmed.replace(/^[-*>\s#]+/u, "").trim();
|
|
98
|
-
if (candidate.length > 0) {
|
|
99
|
-
return candidate;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
21
|
+
export function activeArtifactDir(projectRoot, slug) {
|
|
22
|
+
return path.join(projectRoot, FLOWS_ROOT, slug);
|
|
107
23
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return slugifyArtifactTopic(explicitTopic);
|
|
111
|
-
}
|
|
112
|
-
const inferred = await inferTopicFromIdeaArtifact(projectRoot);
|
|
113
|
-
if (inferred && inferred.trim().length > 0) {
|
|
114
|
-
return slugifyArtifactTopic(inferred);
|
|
115
|
-
}
|
|
116
|
-
return slugifyArtifactTopic(stage);
|
|
24
|
+
export function activeArtifactPath(projectRoot, stage, slug) {
|
|
25
|
+
return path.join(activeArtifactDir(projectRoot, slug), ARTIFACT_FILE_NAMES[stage]);
|
|
117
26
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const candidates = [];
|
|
121
|
-
const hasSlugPattern = isSlugArtifactPattern(filePattern);
|
|
122
|
-
const matcher = hasSlugPattern ? slugPatternRegex(filePattern) : null;
|
|
123
|
-
for (const root of roots) {
|
|
124
|
-
if (hasSlugPattern && matcher) {
|
|
125
|
-
let entries = [];
|
|
126
|
-
try {
|
|
127
|
-
entries = await fs.readdir(root.absDir);
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
entries = [];
|
|
131
|
-
}
|
|
132
|
-
for (const entry of entries) {
|
|
133
|
-
if (!matcher.test(entry))
|
|
134
|
-
continue;
|
|
135
|
-
const { relPath, absPath } = candidateFromRoot(root, entry);
|
|
136
|
-
let mtimeMs = 0;
|
|
137
|
-
try {
|
|
138
|
-
const stat = await fs.stat(absPath);
|
|
139
|
-
mtimeMs = stat.mtimeMs;
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
candidates.push({
|
|
145
|
-
fileName: entry,
|
|
146
|
-
relPath,
|
|
147
|
-
absPath,
|
|
148
|
-
mtimeMs,
|
|
149
|
-
legacy: false
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
const { relPath, absPath } = candidateFromRoot(root, filePattern);
|
|
155
|
-
if (await exists(absPath)) {
|
|
156
|
-
let mtimeMs = 0;
|
|
157
|
-
try {
|
|
158
|
-
const stat = await fs.stat(absPath);
|
|
159
|
-
mtimeMs = stat.mtimeMs;
|
|
160
|
-
}
|
|
161
|
-
catch {
|
|
162
|
-
mtimeMs = 0;
|
|
163
|
-
}
|
|
164
|
-
candidates.push({
|
|
165
|
-
fileName: filePattern,
|
|
166
|
-
relPath,
|
|
167
|
-
absPath,
|
|
168
|
-
mtimeMs,
|
|
169
|
-
legacy: false
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (legacyFile && LEGACY_ARTIFACT_GRACE_CYCLES > 0) {
|
|
174
|
-
const { relPath, absPath } = candidateFromRoot(root, legacyFile);
|
|
175
|
-
if (await exists(absPath)) {
|
|
176
|
-
let mtimeMs = 0;
|
|
177
|
-
try {
|
|
178
|
-
const stat = await fs.stat(absPath);
|
|
179
|
-
mtimeMs = stat.mtimeMs;
|
|
180
|
-
}
|
|
181
|
-
catch {
|
|
182
|
-
mtimeMs = 0;
|
|
183
|
-
}
|
|
184
|
-
candidates.push({
|
|
185
|
-
fileName: legacyFile,
|
|
186
|
-
relPath,
|
|
187
|
-
absPath,
|
|
188
|
-
mtimeMs,
|
|
189
|
-
legacy: true
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
candidates.sort((a, b) => {
|
|
195
|
-
if (b.mtimeMs !== a.mtimeMs) {
|
|
196
|
-
return b.mtimeMs - a.mtimeMs;
|
|
197
|
-
}
|
|
198
|
-
if (a.legacy !== b.legacy) {
|
|
199
|
-
return a.legacy ? 1 : -1;
|
|
200
|
-
}
|
|
201
|
-
return a.fileName.localeCompare(b.fileName);
|
|
202
|
-
});
|
|
203
|
-
return candidates;
|
|
27
|
+
export function shippedArtifactDir(projectRoot, slug) {
|
|
28
|
+
return path.join(projectRoot, SHIPPED_DIR_REL_PATH, slug);
|
|
204
29
|
}
|
|
205
|
-
export
|
|
206
|
-
|
|
207
|
-
const intent = context.intent ?? "read";
|
|
208
|
-
const filePattern = stageSchema(stage, track).artifactFile;
|
|
209
|
-
const hasSlugPattern = isSlugArtifactPattern(filePattern);
|
|
210
|
-
const legacyFile = hasSlugPattern ? legacyArtifactFileName(filePattern) : null;
|
|
211
|
-
const existing = await collectExistingCandidates(context.projectRoot, filePattern, legacyFile);
|
|
212
|
-
if (intent === "read" && existing.length > 0) {
|
|
213
|
-
const picked = existing[0];
|
|
214
|
-
return {
|
|
215
|
-
stage,
|
|
216
|
-
fileName: picked.fileName,
|
|
217
|
-
relPath: picked.relPath,
|
|
218
|
-
absPath: picked.absPath,
|
|
219
|
-
source: "existing",
|
|
220
|
-
legacy: picked.legacy
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
const artifactRoot = path.join(context.projectRoot, RUNTIME_ROOT, "artifacts");
|
|
224
|
-
if (!hasSlugPattern) {
|
|
225
|
-
return {
|
|
226
|
-
stage,
|
|
227
|
-
fileName: filePattern,
|
|
228
|
-
relPath: path.join(RUNTIME_ROOT, "artifacts", filePattern),
|
|
229
|
-
absPath: path.join(artifactRoot, filePattern),
|
|
230
|
-
source: "generated",
|
|
231
|
-
legacy: false
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
const topicSlug = await resolvedTopicSlug(context.projectRoot, stage, context.topic);
|
|
235
|
-
const baseFileName = filePattern.replace("<slug>", topicSlug);
|
|
236
|
-
if (intent === "read") {
|
|
237
|
-
return {
|
|
238
|
-
stage,
|
|
239
|
-
fileName: baseFileName,
|
|
240
|
-
relPath: path.join(RUNTIME_ROOT, "artifacts", baseFileName),
|
|
241
|
-
absPath: path.join(artifactRoot, baseFileName),
|
|
242
|
-
source: "generated",
|
|
243
|
-
legacy: false
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
let candidate = baseFileName;
|
|
247
|
-
let index = 2;
|
|
248
|
-
// Keep incrementing while a matching file exists under active artifacts root.
|
|
249
|
-
while (await exists(path.join(artifactRoot, candidate))) {
|
|
250
|
-
candidate = appendCollisionSuffix(baseFileName, index);
|
|
251
|
-
index += 1;
|
|
252
|
-
}
|
|
253
|
-
return {
|
|
254
|
-
stage,
|
|
255
|
-
fileName: candidate,
|
|
256
|
-
relPath: path.join(RUNTIME_ROOT, "artifacts", candidate),
|
|
257
|
-
absPath: path.join(artifactRoot, candidate),
|
|
258
|
-
source: "generated",
|
|
259
|
-
legacy: false
|
|
260
|
-
};
|
|
30
|
+
export function shippedArtifactPath(projectRoot, slug, stage) {
|
|
31
|
+
return path.join(shippedArtifactDir(projectRoot, slug), ARTIFACT_FILE_NAMES[stage]);
|
|
261
32
|
}
|
package/dist/cancel.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ArtifactStage } from "./artifact-paths.js";
|
|
2
|
+
export interface CancelOptions {
|
|
3
|
+
reason?: string;
|
|
4
|
+
cancelledAt?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CancelResult {
|
|
7
|
+
slug: string;
|
|
8
|
+
cancelledDir: string;
|
|
9
|
+
movedArtifacts: ArtifactStage[];
|
|
10
|
+
reason: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class CancelError extends Error {
|
|
13
|
+
}
|
|
14
|
+
export declare function cancelledArtifactDir(projectRoot: string, slug: string): string;
|
|
15
|
+
export declare function cancelActiveRun(projectRoot: string, options?: CancelOptions): Promise<CancelResult>;
|
|
16
|
+
export declare function listCancelled(projectRoot: string): Promise<string[]>;
|
package/dist/cancel.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { ARTIFACT_FILE_NAMES, activeArtifactDir, activeArtifactPath } from "./artifact-paths.js";
|
|
4
|
+
import { CANCELLED_DIR_REL_PATH } from "./constants.js";
|
|
5
|
+
import { ensureDir, exists, removePath, writeFileSafe } from "./fs-utils.js";
|
|
6
|
+
import { syncFrontmatter } from "./artifact-frontmatter.js";
|
|
7
|
+
import { readFlowState, resetFlowState } from "./run-persistence.js";
|
|
8
|
+
export class CancelError extends Error {
|
|
9
|
+
}
|
|
10
|
+
export function cancelledArtifactDir(projectRoot, slug) {
|
|
11
|
+
return path.join(projectRoot, CANCELLED_DIR_REL_PATH, slug);
|
|
12
|
+
}
|
|
13
|
+
async function moveIfExists(source, destination) {
|
|
14
|
+
if (!(await exists(source)))
|
|
15
|
+
return false;
|
|
16
|
+
await ensureDir(path.dirname(destination));
|
|
17
|
+
await fs.rename(source, destination);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
const ALL_STAGES = ["plan", "build", "review", "ship", "decisions", "learnings"];
|
|
21
|
+
export async function cancelActiveRun(projectRoot, options = {}) {
|
|
22
|
+
const state = await readFlowState(projectRoot);
|
|
23
|
+
if (!state.currentSlug) {
|
|
24
|
+
throw new CancelError("No active slug; nothing to cancel.");
|
|
25
|
+
}
|
|
26
|
+
const slug = state.currentSlug;
|
|
27
|
+
const reason = options.reason?.trim() || "user cancelled";
|
|
28
|
+
const cancelledAt = options.cancelledAt ?? new Date().toISOString();
|
|
29
|
+
for (const stage of ["plan", "build", "review", "ship"]) {
|
|
30
|
+
const filePath = activeArtifactPath(projectRoot, stage, slug);
|
|
31
|
+
if (await exists(filePath)) {
|
|
32
|
+
try {
|
|
33
|
+
await syncFrontmatter(projectRoot, slug, stage, {});
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// ignore frontmatter parse errors during cancel; we still move the file
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const target = cancelledArtifactDir(projectRoot, slug);
|
|
41
|
+
await ensureDir(target);
|
|
42
|
+
const moved = [];
|
|
43
|
+
for (const stage of ALL_STAGES) {
|
|
44
|
+
const source = activeArtifactPath(projectRoot, stage, slug);
|
|
45
|
+
const destination = path.join(target, ARTIFACT_FILE_NAMES[stage]);
|
|
46
|
+
if (await moveIfExists(source, destination))
|
|
47
|
+
moved.push(stage);
|
|
48
|
+
}
|
|
49
|
+
const manifest = `---\nslug: ${slug}\nstage: cancelled\nstatus: cancelled\ncancelled_at: ${cancelledAt}\nreason: ${JSON.stringify(reason)}\n---\n\n# ${slug} — cancelled\n\n${reason}\n\n## Artifacts\n\n${moved.map((stage) => `- ${ARTIFACT_FILE_NAMES[stage]}`).join("\n") || "_No artifacts were active at cancel time._"}\n`;
|
|
50
|
+
await writeFileSafe(path.join(target, "manifest.md"), manifest);
|
|
51
|
+
const activeDir = activeArtifactDir(projectRoot, slug);
|
|
52
|
+
if (await exists(activeDir)) {
|
|
53
|
+
const remaining = await fs.readdir(activeDir);
|
|
54
|
+
if (remaining.length === 0)
|
|
55
|
+
await removePath(activeDir);
|
|
56
|
+
}
|
|
57
|
+
await resetFlowState(projectRoot);
|
|
58
|
+
return { slug, cancelledDir: target, movedArtifacts: moved, reason };
|
|
59
|
+
}
|
|
60
|
+
export async function listCancelled(projectRoot) {
|
|
61
|
+
const dir = path.join(projectRoot, CANCELLED_DIR_REL_PATH);
|
|
62
|
+
if (!(await exists(dir)))
|
|
63
|
+
return [];
|
|
64
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
65
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
66
|
+
}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,28 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
export { parseHarnessSelectionAnswer } from "./harness-selection.js";
|
|
5
|
-
type CommandName = "init" | "sync" | "upgrade" | "uninstall" | "archive" | "internal";
|
|
6
|
-
interface ParsedArgs {
|
|
7
|
-
command?: CommandName;
|
|
8
|
-
harnesses?: HarnessId[];
|
|
9
|
-
track?: FlowTrack;
|
|
10
|
-
dryRun?: boolean;
|
|
11
|
-
interactive?: boolean;
|
|
12
|
-
syncCheck?: boolean;
|
|
13
|
-
archiveName?: string;
|
|
14
|
-
archiveSkipRetro?: boolean;
|
|
15
|
-
archiveSkipRetroReason?: string;
|
|
16
|
-
archiveDisposition?: ArchiveDisposition;
|
|
17
|
-
archiveDispositionReason?: string;
|
|
18
|
-
/** Hidden plumbing command (`cclaw internal ...`) arguments. */
|
|
19
|
-
internalArgs?: string[];
|
|
20
|
-
showHelp?: boolean;
|
|
21
|
-
showVersion?: boolean;
|
|
22
|
-
}
|
|
23
|
-
export declare function usage(): string;
|
|
24
|
-
declare function parseHarnesses(raw: string): HarnessId[];
|
|
25
|
-
declare function parseTrack(raw: string): FlowTrack;
|
|
26
|
-
declare function parseArchiveDisposition(raw: string): ArchiveDisposition;
|
|
27
|
-
declare function parseArgs(argv: string[]): ParsedArgs;
|
|
28
|
-
export { parseArgs, parseArchiveDisposition, parseHarnesses, parseTrack };
|
|
2
|
+
import { type CliContext } from "./types.js";
|
|
3
|
+
export declare function runCli(argv: string[], context: CliContext): Promise<number>;
|