cclaw-cli 0.51.1 → 0.51.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.
@@ -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
- - Use the completion helper instead of raw \`flow-state.json\` edits (legacy direct edits trigger workflow-guard warnings or strict-mode blocks).
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) {
@@ -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
- if (typeof value !== "string")
329
- continue;
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] = trimmed;
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 (const token of flagTokens) {
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.replace("--evidence-json=", "");
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.replace("--passed=", ""))];
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.replace("--waive-delegation=", ""))
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.replace("--waiver-reason=", "").trim();
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}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "0.51.1",
3
+ "version": "0.51.2",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {