cclaw-cli 0.51.1 → 0.51.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/content/skills.js
CHANGED
|
@@ -216,10 +216,11 @@ function completionParametersBlock(schema, track) {
|
|
|
216
216
|
- \`artifact\`: \`${RUNTIME_ROOT}/artifacts/${schema.artifactRules.artifactFile}\`
|
|
217
217
|
- \`mandatory delegations\`: ${mandatory}
|
|
218
218
|
- \`completion helper\`: \`node .cclaw/hooks/stage-complete.mjs ${schema.stage}\`
|
|
219
|
+
- \`completion helper with evidence\`: \`node .cclaw/hooks/stage-complete.mjs ${schema.stage} --evidence-json '{"<gate_id>":"<evidence note>"}' --passed=<gate_id>[,<gate_id>]\`
|
|
219
220
|
- Fill \`## Learnings\` before closeout: either \`- None this stage.\` or JSON bullets with required keys \`type\`, \`trigger\`, \`action\`, \`confidence\` (knowledge-schema compatible).
|
|
220
221
|
- Record mandatory delegation completion/waiver in \`${RUNTIME_ROOT}/state/delegation-log.json\` with rationale as needed.
|
|
221
|
-
-
|
|
222
|
-
- Completion protocol: verify required gates, update the artifact, then use the completion helper.
|
|
222
|
+
- Never edit raw \`flow-state.json\` to complete a stage, even in advisory mode; that bypasses validation, gate evidence, and Learnings harvest. If the helper fails, stop and report the exact command/output instead of applying a manual state workaround.
|
|
223
|
+
- Completion protocol: verify required gates, update the artifact, then use the completion helper with \`--evidence-json\` and \`--passed\` for every satisfied gate.
|
|
223
224
|
`;
|
|
224
225
|
}
|
|
225
226
|
function quickStartBlock(stage, track) {
|
|
@@ -48,7 +48,7 @@ export const BRAINSTORM = {
|
|
|
48
48
|
],
|
|
49
49
|
interactionProtocol: [
|
|
50
50
|
"Start from observed project context; if the idea is vague, first narrow the project type.",
|
|
51
|
-
"Ask at most one question per turn, only when decision-changing;
|
|
51
|
+
"Ask at most one question per turn, only when decision-changing; if using a structured question tool, send exactly one question object, not a multi-question form.",
|
|
52
52
|
"If likely answers do not change architecture or scope boundaries, choose the default and state the assumption.",
|
|
53
53
|
"Show approaches before the recommendation; include a higher-upside challenger and gather reaction first.",
|
|
54
54
|
"State exactly what is being approved, then **STOP** until the user explicitly approves the artifact."
|
|
@@ -119,9 +119,9 @@ export const BRAINSTORM = {
|
|
|
119
119
|
{ section: "Clarifying Questions", required: false, validationRule: "Must capture question, answer, and decision impact for each clarifying question." },
|
|
120
120
|
{ section: "Approach Tier", required: true, validationRule: "Must classify depth as Lightweight/Standard/Deep and explain why." },
|
|
121
121
|
{ section: "Short-Circuit Decision", required: false, validationRule: "Must include Status/Why/Scope handoff lines when short-circuit is discussed; compact stubs are valid for concrete asks." },
|
|
122
|
-
{ section: "Approaches", required: true, validationRule: "Must compare 2-3 architecturally distinct options with real trade-offs
|
|
123
|
-
{ section: "Approach Reaction", required: true, validationRule: "Must summarize user reaction before recommendation, including
|
|
124
|
-
{ section: "Selected Direction", required: true, validationRule: "Must include the selected approach, rationale tied to user reaction/feedback
|
|
122
|
+
{ section: "Approaches", required: true, validationRule: "Must compare 2-3 architecturally distinct options with real trade-offs; include at least one table/bullet row containing both `challenger` and `higher-upside`." },
|
|
123
|
+
{ section: "Approach Reaction", required: true, validationRule: "Must appear before Selected Direction and summarize user reaction before recommendation, including `Closest option`, `Concerns`, and what changed after reaction." },
|
|
124
|
+
{ section: "Selected Direction", required: true, validationRule: "Must include the selected approach, an explicit approval marker, and rationale tied to user reaction/feedback/concerns so the recommendation traces to the user response." },
|
|
125
125
|
{ section: "Design", required: false, validationRule: "Must cover architecture, key components, and data flow scaled to complexity." },
|
|
126
126
|
{ section: "Visual Companion", required: false, validationRule: "If architecture/data-flow complexity is medium+, include compact ASCII/Mermaid diagram or explicitly justify omission." },
|
|
127
127
|
{ section: "Assumptions and Open Questions", required: false, validationRule: "Must capture unresolved assumptions/open questions, or explicitly state none." }
|
package/dist/gate-evidence.js
CHANGED
|
@@ -215,11 +215,21 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState) {
|
|
|
215
215
|
if (shouldValidateArtifact) {
|
|
216
216
|
const lint = await lintArtifact(projectRoot, stage, flowState.track);
|
|
217
217
|
if (!lint.passed) {
|
|
218
|
-
const
|
|
219
|
-
.filter((finding) => finding.required && !finding.found)
|
|
220
|
-
|
|
218
|
+
const failedRequiredFindings = lint.findings
|
|
219
|
+
.filter((finding) => finding.required && !finding.found);
|
|
220
|
+
const failedRequired = failedRequiredFindings.map((finding) => finding.section);
|
|
221
221
|
if (failedRequired.length > 0) {
|
|
222
|
-
|
|
222
|
+
const failureDetails = failedRequiredFindings
|
|
223
|
+
.map((finding) => {
|
|
224
|
+
const details = finding.details?.trim();
|
|
225
|
+
const rule = finding.rule?.trim();
|
|
226
|
+
const explanation = details && details.length > 0 ? details : rule;
|
|
227
|
+
return explanation && explanation.length > 0
|
|
228
|
+
? `${finding.section}: ${explanation}`
|
|
229
|
+
: finding.section;
|
|
230
|
+
})
|
|
231
|
+
.join("; ");
|
|
232
|
+
issues.push(`artifact validation failed for required sections: ${failedRequired.join(", ")}. ${failureDetails}`);
|
|
223
233
|
}
|
|
224
234
|
}
|
|
225
235
|
if (stage === "review") {
|
|
@@ -309,6 +309,19 @@ function coerceCandidateFlowState(raw, fallback) {
|
|
|
309
309
|
stageGateCatalog: parseCandidateGateCatalog(typed.stageGateCatalog, fallback.stageGateCatalog)
|
|
310
310
|
};
|
|
311
311
|
}
|
|
312
|
+
function stringifyGateEvidenceValue(value) {
|
|
313
|
+
if (typeof value === "string")
|
|
314
|
+
return value;
|
|
315
|
+
if (typeof value === "boolean")
|
|
316
|
+
return value ? "passed" : "failed";
|
|
317
|
+
if (typeof value === "number" || typeof value === "bigint")
|
|
318
|
+
return String(value);
|
|
319
|
+
if (value === null || value === undefined)
|
|
320
|
+
return "";
|
|
321
|
+
if (typeof value === "object")
|
|
322
|
+
return JSON.stringify(value);
|
|
323
|
+
return String(value);
|
|
324
|
+
}
|
|
312
325
|
function parseEvidenceByGate(raw) {
|
|
313
326
|
if (!raw || raw.trim().length === 0) {
|
|
314
327
|
return {};
|
|
@@ -325,12 +338,10 @@ function parseEvidenceByGate(raw) {
|
|
|
325
338
|
}
|
|
326
339
|
const next = {};
|
|
327
340
|
for (const [key, value] of Object.entries(parsed)) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const trimmed = value.trim();
|
|
331
|
-
if (trimmed.length === 0)
|
|
341
|
+
const normalized = stringifyGateEvidenceValue(value).trim();
|
|
342
|
+
if (normalized.length === 0)
|
|
332
343
|
continue;
|
|
333
|
-
next[key] =
|
|
344
|
+
next[key] = normalized;
|
|
334
345
|
}
|
|
335
346
|
return next;
|
|
336
347
|
}
|
|
@@ -381,28 +392,62 @@ function parseAdvanceStageArgs(tokens) {
|
|
|
381
392
|
let waiveDelegations = [];
|
|
382
393
|
let waiverReason;
|
|
383
394
|
let quiet = false;
|
|
384
|
-
for (
|
|
395
|
+
for (let i = 0; i < flagTokens.length; i += 1) {
|
|
396
|
+
const token = flagTokens[i];
|
|
397
|
+
const nextToken = flagTokens[i + 1];
|
|
385
398
|
if (token === "--quiet") {
|
|
386
399
|
quiet = true;
|
|
387
400
|
continue;
|
|
388
401
|
}
|
|
402
|
+
if (token === "--evidence-json") {
|
|
403
|
+
if (!nextToken || nextToken.startsWith("--")) {
|
|
404
|
+
throw new Error("--evidence-json requires a JSON object value.");
|
|
405
|
+
}
|
|
406
|
+
evidenceJson = nextToken;
|
|
407
|
+
i += 1;
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
389
410
|
if (token.startsWith("--evidence-json=")) {
|
|
390
|
-
evidenceJson = token.
|
|
411
|
+
evidenceJson = token.slice("--evidence-json=".length);
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (token === "--passed") {
|
|
415
|
+
if (!nextToken || nextToken.startsWith("--")) {
|
|
416
|
+
throw new Error("--passed requires a comma-separated gate list.");
|
|
417
|
+
}
|
|
418
|
+
passed = [...passed, ...parseCsv(nextToken)];
|
|
419
|
+
i += 1;
|
|
391
420
|
continue;
|
|
392
421
|
}
|
|
393
422
|
if (token.startsWith("--passed=")) {
|
|
394
|
-
passed = [...passed, ...parseCsv(token.
|
|
423
|
+
passed = [...passed, ...parseCsv(token.slice("--passed=".length))];
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
if (token === "--waive-delegation") {
|
|
427
|
+
if (!nextToken || nextToken.startsWith("--")) {
|
|
428
|
+
throw new Error("--waive-delegation requires a comma-separated agent list.");
|
|
429
|
+
}
|
|
430
|
+
waiveDelegations = [...waiveDelegations, ...parseCsv(nextToken)];
|
|
431
|
+
i += 1;
|
|
395
432
|
continue;
|
|
396
433
|
}
|
|
397
434
|
if (token.startsWith("--waive-delegation=")) {
|
|
398
435
|
waiveDelegations = [
|
|
399
436
|
...waiveDelegations,
|
|
400
|
-
...parseCsv(token.
|
|
437
|
+
...parseCsv(token.slice("--waive-delegation=".length))
|
|
401
438
|
];
|
|
402
439
|
continue;
|
|
403
440
|
}
|
|
441
|
+
if (token === "--waiver-reason") {
|
|
442
|
+
if (!nextToken || nextToken.startsWith("--")) {
|
|
443
|
+
throw new Error("--waiver-reason requires a text value.");
|
|
444
|
+
}
|
|
445
|
+
waiverReason = nextToken.trim();
|
|
446
|
+
i += 1;
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
404
449
|
if (token.startsWith("--waiver-reason=")) {
|
|
405
|
-
waiverReason = token.
|
|
450
|
+
waiverReason = token.slice("--waiver-reason=".length).trim();
|
|
406
451
|
continue;
|
|
407
452
|
}
|
|
408
453
|
throw new Error(`Unknown flag for internal advance-stage: ${token}`);
|