cclaw-cli 0.51.29 → 0.55.2
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 +22 -16
- package/dist/artifact-linter/brainstorm.d.ts +2 -0
- package/dist/artifact-linter/brainstorm.js +245 -0
- package/dist/artifact-linter/design.d.ts +2 -0
- package/dist/artifact-linter/design.js +323 -0
- package/dist/artifact-linter/plan.d.ts +2 -0
- package/dist/artifact-linter/plan.js +162 -0
- package/dist/artifact-linter/review-army.d.ts +24 -0
- package/dist/artifact-linter/review-army.js +365 -0
- package/dist/artifact-linter/review.d.ts +2 -0
- package/dist/artifact-linter/review.js +65 -0
- package/dist/artifact-linter/scope.d.ts +2 -0
- package/dist/artifact-linter/scope.js +115 -0
- package/dist/artifact-linter/shared.d.ts +246 -0
- package/dist/artifact-linter/shared.js +1488 -0
- package/dist/artifact-linter/ship.d.ts +2 -0
- package/dist/artifact-linter/ship.js +46 -0
- package/dist/artifact-linter/spec.d.ts +2 -0
- package/dist/artifact-linter/spec.js +108 -0
- package/dist/artifact-linter/tdd.d.ts +2 -0
- package/dist/artifact-linter/tdd.js +124 -0
- package/dist/artifact-linter.d.ts +4 -76
- package/dist/artifact-linter.js +56 -2949
- package/dist/cli.d.ts +2 -18
- package/dist/cli.js +8 -246
- package/dist/codex-feature-flag.d.ts +1 -1
- package/dist/codex-feature-flag.js +1 -1
- package/dist/config.d.ts +3 -2
- package/dist/config.js +67 -3
- package/dist/constants.d.ts +1 -7
- package/dist/constants.js +9 -15
- package/dist/content/cancel-command.js +2 -2
- package/dist/content/closeout-guidance.js +13 -10
- package/dist/content/core-agents.d.ts +18 -0
- package/dist/content/core-agents.js +51 -7
- package/dist/content/decision-protocol.d.ts +1 -1
- package/dist/content/decision-protocol.js +1 -1
- package/dist/content/examples.js +6 -6
- package/dist/content/harness-doc.js +20 -2
- package/dist/content/hook-inline-snippets.d.ts +17 -4
- package/dist/content/hook-inline-snippets.js +218 -5
- package/dist/content/hook-manifest.d.ts +2 -2
- package/dist/content/hook-manifest.js +2 -2
- package/dist/content/hooks.d.ts +1 -0
- package/dist/content/hooks.js +32 -137
- package/dist/content/idea-command.d.ts +8 -0
- package/dist/content/{ideate-command.js → idea-command.js} +57 -50
- package/dist/content/idea-frames.d.ts +31 -0
- package/dist/content/{ideate-frames.js → idea-frames.js} +9 -9
- package/dist/content/idea-ranking.d.ts +25 -0
- package/dist/content/{ideate-ranking.js → idea-ranking.js} +5 -5
- package/dist/content/iron-laws.d.ts +0 -1
- package/dist/content/iron-laws.js +31 -16
- package/dist/content/learnings.js +1 -1
- package/dist/content/meta-skill.js +11 -13
- package/dist/content/node-hooks.d.ts +10 -0
- package/dist/content/node-hooks.js +45 -11
- package/dist/content/opencode-plugin.js +3 -3
- package/dist/content/session-hooks.js +1 -1
- package/dist/content/skills.js +19 -7
- package/dist/content/stage-command.js +1 -1
- package/dist/content/stage-schema.js +44 -2
- package/dist/content/stages/_lint-metadata/index.js +26 -2
- package/dist/content/stages/brainstorm.js +13 -7
- package/dist/content/stages/design.js +16 -11
- package/dist/content/stages/plan.js +9 -6
- package/dist/content/stages/review.js +4 -4
- package/dist/content/stages/schema-types.d.ts +1 -1
- package/dist/content/stages/scope.js +15 -12
- package/dist/content/stages/ship.js +2 -2
- package/dist/content/stages/spec.js +9 -3
- package/dist/content/stages/tdd.js +14 -4
- package/dist/content/start-command.d.ts +2 -2
- package/dist/content/start-command.js +24 -21
- package/dist/content/status-command.js +8 -8
- package/dist/content/subagents.js +61 -7
- package/dist/content/templates.d.ts +1 -1
- package/dist/content/templates.js +104 -152
- package/dist/content/tree-command.js +2 -2
- package/dist/content/utility-skills.d.ts +2 -2
- package/dist/content/utility-skills.js +2 -2
- package/dist/content/view-command.js +4 -2
- package/dist/delegation.d.ts +2 -0
- package/dist/delegation.js +2 -1
- package/dist/early-loop.d.ts +66 -0
- package/dist/early-loop.js +275 -0
- package/dist/flow-state.d.ts +1 -1
- package/dist/flow-state.js +1 -1
- package/dist/gate-evidence.d.ts +8 -0
- package/dist/gate-evidence.js +141 -5
- package/dist/harness-adapters.d.ts +2 -2
- package/dist/harness-adapters.js +54 -122
- package/dist/harness-selection.d.ts +31 -0
- package/dist/harness-selection.js +214 -0
- package/dist/install.js +166 -38
- package/dist/internal/advance-stage/advance.d.ts +50 -0
- package/dist/internal/advance-stage/advance.js +480 -0
- package/dist/internal/advance-stage/cancel-run.d.ts +8 -0
- package/dist/internal/advance-stage/cancel-run.js +19 -0
- package/dist/internal/advance-stage/flow-state-coercion.d.ts +3 -0
- package/dist/internal/advance-stage/flow-state-coercion.js +81 -0
- package/dist/internal/advance-stage/helpers.d.ts +14 -0
- package/dist/internal/advance-stage/helpers.js +145 -0
- package/dist/internal/advance-stage/hook.d.ts +8 -0
- package/dist/internal/advance-stage/hook.js +40 -0
- package/dist/internal/advance-stage/parsers.d.ts +54 -0
- package/dist/internal/advance-stage/parsers.js +307 -0
- package/dist/internal/advance-stage/review-loop.d.ts +7 -0
- package/dist/internal/advance-stage/review-loop.js +170 -0
- package/dist/internal/advance-stage/rewind.d.ts +14 -0
- package/dist/internal/advance-stage/rewind.js +108 -0
- package/dist/internal/advance-stage/start-flow.d.ts +11 -0
- package/dist/internal/advance-stage/start-flow.js +136 -0
- package/dist/internal/advance-stage/verify.d.ts +29 -0
- package/dist/internal/advance-stage/verify.js +225 -0
- package/dist/internal/advance-stage.js +21 -1470
- package/dist/internal/compound-readiness.d.ts +1 -1
- package/dist/internal/compound-readiness.js +2 -2
- package/dist/internal/early-loop-status.d.ts +7 -0
- package/dist/internal/early-loop-status.js +90 -0
- package/dist/internal/runtime-integrity.d.ts +7 -0
- package/dist/internal/runtime-integrity.js +288 -0
- package/dist/internal/tdd-red-evidence.js +1 -1
- package/dist/knowledge-store.d.ts +3 -8
- package/dist/knowledge-store.js +16 -29
- package/dist/managed-resources.js +24 -2
- package/dist/policy.js +5 -7
- package/dist/run-archive.d.ts +1 -1
- package/dist/run-archive.js +16 -16
- package/dist/run-persistence.js +112 -12
- package/dist/tdd-cycle.d.ts +3 -3
- package/dist/tdd-cycle.js +1 -1
- package/dist/types.d.ts +18 -10
- package/package.json +1 -1
- package/dist/content/finish-command.d.ts +0 -2
- package/dist/content/finish-command.js +0 -26
- package/dist/content/ideate-command.d.ts +0 -8
- package/dist/content/ideate-frames.d.ts +0 -31
- package/dist/content/ideate-ranking.d.ts +0 -25
- package/dist/content/next-command.d.ts +0 -20
- package/dist/content/next-command.js +0 -298
- package/dist/content/seed-shelf.d.ts +0 -36
- package/dist/content/seed-shelf.js +0 -301
- package/dist/content/stage-common-guidance.d.ts +0 -1
- package/dist/content/stage-common-guidance.js +0 -106
- package/dist/doctor-registry.d.ts +0 -10
- package/dist/doctor-registry.js +0 -186
- package/dist/doctor.d.ts +0 -17
- package/dist/doctor.js +0 -2206
- package/dist/internal/hook-manifest.d.ts +0 -16
- package/dist/internal/hook-manifest.js +0 -77
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { RUNTIME_ROOT } from "../../constants.js";
|
|
3
|
+
import { stageAutoSubagentDispatch, stageSchema } from "../../content/stage-schema.js";
|
|
4
|
+
import { appendDelegation, readDelegationLedger } from "../../delegation.js";
|
|
5
|
+
import { readFlowState } from "../../runs.js";
|
|
6
|
+
import { TRACK_STAGES } from "../../types.js";
|
|
7
|
+
import { coerceCandidateFlowState } from "./flow-state-coercion.js";
|
|
8
|
+
import { buildValidationReport } from "./advance.js";
|
|
9
|
+
import fs from "node:fs/promises";
|
|
10
|
+
export async function runVerifyFlowStateDiff(projectRoot, args, io) {
|
|
11
|
+
let raw = args.afterJson;
|
|
12
|
+
if (!raw && args.afterFile) {
|
|
13
|
+
raw = await fs.readFile(args.afterFile, "utf8");
|
|
14
|
+
}
|
|
15
|
+
if (!raw) {
|
|
16
|
+
io.stderr.write("cclaw internal verify-flow-state-diff: no candidate state payload.\n");
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
let parsed;
|
|
20
|
+
try {
|
|
21
|
+
parsed = JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
io.stderr.write(`cclaw internal verify-flow-state-diff: invalid JSON payload (${err instanceof Error ? err.message : String(err)}).\n`);
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
const current = await readFlowState(projectRoot);
|
|
28
|
+
const candidate = coerceCandidateFlowState(parsed, current);
|
|
29
|
+
const validation = await buildValidationReport(projectRoot, candidate);
|
|
30
|
+
if (!args.quiet) {
|
|
31
|
+
io.stdout.write(`${JSON.stringify(validation, null, 2)}\n`);
|
|
32
|
+
}
|
|
33
|
+
if (!validation.ok) {
|
|
34
|
+
io.stderr.write(`cclaw internal verify-flow-state-diff: candidate state is invalid for stage "${validation.stage}".\n`);
|
|
35
|
+
}
|
|
36
|
+
return validation.ok ? 0 : 1;
|
|
37
|
+
}
|
|
38
|
+
export async function runVerifyCurrentState(projectRoot, args, io) {
|
|
39
|
+
const current = await readFlowState(projectRoot);
|
|
40
|
+
const validation = await buildValidationReport(projectRoot, current);
|
|
41
|
+
if (!args.quiet) {
|
|
42
|
+
io.stdout.write(`${JSON.stringify(validation, null, 2)}\n`);
|
|
43
|
+
}
|
|
44
|
+
if (!validation.ok) {
|
|
45
|
+
const unmetDelegations = validation.delegation.missing.length + validation.delegation.missingEvidence.length;
|
|
46
|
+
const gatesWithoutEvidence = validation.gates.issues.filter((issue) => issue.includes("missing guardEvidence entry")).length;
|
|
47
|
+
io.stderr.write(`cclaw: current stage has ${unmetDelegations} unmet mandatory delegations and ${gatesWithoutEvidence} gates without evidence.\n`);
|
|
48
|
+
io.stderr.write(`cclaw internal verify-current-state: unresolved stage constraints for "${validation.stage}".\n`);
|
|
49
|
+
}
|
|
50
|
+
return validation.ok ? 0 : 1;
|
|
51
|
+
}
|
|
52
|
+
export function firstIncompleteStageForTrack(track, completedStages) {
|
|
53
|
+
const completed = new Set(completedStages);
|
|
54
|
+
const stages = TRACK_STAGES[track];
|
|
55
|
+
return stages.find((stage) => !completed.has(stage)) ?? stages[stages.length - 1] ?? "brainstorm";
|
|
56
|
+
}
|
|
57
|
+
export function carriedCompletedStageCatalog(current, fresh, stage) {
|
|
58
|
+
const previousCatalog = current.stageGateCatalog[stage];
|
|
59
|
+
const freshCatalog = fresh.stageGateCatalog[stage];
|
|
60
|
+
const allowed = new Set([...freshCatalog.required, ...freshCatalog.recommended]);
|
|
61
|
+
const previousPassed = new Set(previousCatalog.passed.filter((gateId) => allowed.has(gateId)));
|
|
62
|
+
const previousBlocked = new Set(previousCatalog.blocked.filter((gateId) => allowed.has(gateId)));
|
|
63
|
+
const orderedAllowed = [...freshCatalog.required, ...freshCatalog.recommended];
|
|
64
|
+
const evidence = {};
|
|
65
|
+
const passed = orderedAllowed.filter((gateId) => {
|
|
66
|
+
if (!previousPassed.has(gateId))
|
|
67
|
+
return false;
|
|
68
|
+
const note = current.guardEvidence[gateId];
|
|
69
|
+
if (typeof note !== "string" || note.trim().length === 0)
|
|
70
|
+
return false;
|
|
71
|
+
evidence[gateId] = note.trim();
|
|
72
|
+
return true;
|
|
73
|
+
});
|
|
74
|
+
const passedSet = new Set(passed);
|
|
75
|
+
return {
|
|
76
|
+
catalog: {
|
|
77
|
+
required: [...freshCatalog.required],
|
|
78
|
+
recommended: [...freshCatalog.recommended],
|
|
79
|
+
conditional: [],
|
|
80
|
+
triggered: [],
|
|
81
|
+
passed,
|
|
82
|
+
blocked: orderedAllowed.filter((gateId) => previousBlocked.has(gateId) && !passedSet.has(gateId))
|
|
83
|
+
},
|
|
84
|
+
evidence
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export function completedStageClosureEvidenceIssues(flowState) {
|
|
88
|
+
const issues = [];
|
|
89
|
+
for (const stage of flowState.completedStages) {
|
|
90
|
+
const schema = stageSchema(stage, flowState.track);
|
|
91
|
+
const catalog = flowState.stageGateCatalog[stage];
|
|
92
|
+
const required = schema.requiredGates
|
|
93
|
+
.filter((gate) => gate.tier === "required")
|
|
94
|
+
.map((gate) => gate.id);
|
|
95
|
+
for (const gateId of required) {
|
|
96
|
+
if (!catalog.passed.includes(gateId))
|
|
97
|
+
continue;
|
|
98
|
+
const note = flowState.guardEvidence[gateId];
|
|
99
|
+
if (typeof note !== "string" || note.trim().length === 0) {
|
|
100
|
+
issues.push(`completed stage "${stage}" passed gate "${gateId}" is missing guardEvidence.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return issues;
|
|
105
|
+
}
|
|
106
|
+
export async function ensureProactiveDelegationTrace(projectRoot, stage, options) {
|
|
107
|
+
const proactiveRules = stageAutoSubagentDispatch(stage).filter((rule) => rule.mode === "proactive");
|
|
108
|
+
if (proactiveRules.length === 0)
|
|
109
|
+
return { missingRules: [] };
|
|
110
|
+
const ledger = await readDelegationLedger(projectRoot);
|
|
111
|
+
const currentRunEntries = ledger.entries.filter((entry) => entry.runId === ledger.runId);
|
|
112
|
+
const missingRules = proactiveRules.filter((rule) => !currentRunEntries.some((entry) => entry.stage === stage && entry.agent === rule.agent && entry.mode === "proactive"));
|
|
113
|
+
if (missingRules.length === 0)
|
|
114
|
+
return { missingRules: [] };
|
|
115
|
+
if (!options.acceptWaiver)
|
|
116
|
+
return { missingRules };
|
|
117
|
+
const waiverReason = options.waiverReason?.trim() || "accepted via --accept-proactive-waiver";
|
|
118
|
+
for (const rule of missingRules) {
|
|
119
|
+
await appendDelegation(projectRoot, {
|
|
120
|
+
stage,
|
|
121
|
+
agent: rule.agent,
|
|
122
|
+
mode: "proactive",
|
|
123
|
+
status: "waived",
|
|
124
|
+
waiverReason,
|
|
125
|
+
acceptedBy: "user-flag",
|
|
126
|
+
conditionTrigger: rule.when,
|
|
127
|
+
skill: rule.skill,
|
|
128
|
+
ts: new Date().toISOString()
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return { missingRules: [] };
|
|
132
|
+
}
|
|
133
|
+
export async function pathExists(projectRoot, relPath) {
|
|
134
|
+
try {
|
|
135
|
+
await fs.stat(path.join(projectRoot, relPath));
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export async function listExistingFiles(projectRoot, relPaths) {
|
|
143
|
+
const matches = [];
|
|
144
|
+
for (const relPath of relPaths) {
|
|
145
|
+
try {
|
|
146
|
+
const stat = await fs.stat(path.join(projectRoot, relPath));
|
|
147
|
+
if (stat.isFile())
|
|
148
|
+
matches.push(relPath);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// continue
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return matches;
|
|
155
|
+
}
|
|
156
|
+
export async function listFilesUnder(projectRoot, relDir, limit = 20) {
|
|
157
|
+
const root = path.join(projectRoot, relDir);
|
|
158
|
+
const out = [];
|
|
159
|
+
async function walk(absDir) {
|
|
160
|
+
if (out.length >= limit)
|
|
161
|
+
return;
|
|
162
|
+
let entries;
|
|
163
|
+
try {
|
|
164
|
+
entries = await fs.readdir(absDir, { withFileTypes: true });
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
if (out.length >= limit)
|
|
171
|
+
return;
|
|
172
|
+
if (entry.name.startsWith("."))
|
|
173
|
+
continue;
|
|
174
|
+
const abs = path.join(absDir, entry.name);
|
|
175
|
+
if (entry.isDirectory()) {
|
|
176
|
+
await walk(abs);
|
|
177
|
+
}
|
|
178
|
+
else if (entry.isFile()) {
|
|
179
|
+
out.push(path.relative(projectRoot, abs).split(path.sep).join("/"));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
await walk(root);
|
|
184
|
+
return out;
|
|
185
|
+
}
|
|
186
|
+
export async function discoverStartFlowContext(projectRoot) {
|
|
187
|
+
const lines = [];
|
|
188
|
+
const seedFiles = (await listFilesUnder(projectRoot, path.join(RUNTIME_ROOT, "seeds"), 10))
|
|
189
|
+
.filter((relPath) => /^\.cclaw\/seeds\/SEED-.*\.md$/u.test(relPath));
|
|
190
|
+
lines.push(seedFiles.length > 0
|
|
191
|
+
? `- Seed shelf scanned: ${seedFiles.join(", ")}.`
|
|
192
|
+
: "- Seed shelf scanned: no `.cclaw/seeds/SEED-*.md` files found.");
|
|
193
|
+
const originDirs = ["docs/prd", "docs/rfcs", "docs/adr", "docs/design", "specs", "prd", "rfc", "design"];
|
|
194
|
+
const originRootFiles = ["PRD.md", "SPEC.md", "DESIGN.md", "REQUIREMENTS.md", "ROADMAP.md"];
|
|
195
|
+
const originFiles = [
|
|
196
|
+
...(await listExistingFiles(projectRoot, originRootFiles)),
|
|
197
|
+
...(await Promise.all(originDirs.map((dir) => listFilesUnder(projectRoot, dir, 6)))).flat()
|
|
198
|
+
].slice(0, 20);
|
|
199
|
+
lines.push(originFiles.length > 0
|
|
200
|
+
? `- Origin docs scanned: found ${originFiles.join(", ")}.`
|
|
201
|
+
: "- Origin docs scanned: no PRD/RFC/ADR/design/spec files found in configured locations.");
|
|
202
|
+
const stackMarkers = await listExistingFiles(projectRoot, [
|
|
203
|
+
"package.json",
|
|
204
|
+
"pyproject.toml",
|
|
205
|
+
"requirements.txt",
|
|
206
|
+
"requirements-dev.txt",
|
|
207
|
+
".python-version",
|
|
208
|
+
"go.mod",
|
|
209
|
+
"Cargo.toml",
|
|
210
|
+
"pom.xml",
|
|
211
|
+
"build.gradle",
|
|
212
|
+
"build.gradle.kts",
|
|
213
|
+
"Dockerfile",
|
|
214
|
+
"docker-compose.yml",
|
|
215
|
+
"docker-compose.yaml",
|
|
216
|
+
".gitlab-ci.yml"
|
|
217
|
+
]);
|
|
218
|
+
if (await pathExists(projectRoot, ".github/workflows")) {
|
|
219
|
+
stackMarkers.push(".github/workflows/");
|
|
220
|
+
}
|
|
221
|
+
lines.push(stackMarkers.length > 0
|
|
222
|
+
? `- Stack markers scanned: found ${stackMarkers.join(", ")}.`
|
|
223
|
+
: "- Stack markers scanned: no root stack markers found.");
|
|
224
|
+
return lines;
|
|
225
|
+
}
|