cclaw-cli 0.46.2 → 0.46.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.
@@ -43,7 +43,7 @@ const REQUIRED_GATE_IDS = {
43
43
  "tdd_red_test_written",
44
44
  "tdd_green_full_suite",
45
45
  "tdd_refactor_completed",
46
- "tdd_traceable_to_plan"
46
+ "tdd_verified_before_complete"
47
47
  ],
48
48
  review: [
49
49
  "review_layer1_spec_compliance",
@@ -27,6 +27,7 @@ export const TDD = {
27
27
  "Dispatch `test-author` subagent in `BUILD_GREEN_REFACTOR` mode — minimal implementation + full-suite GREEN + refactor notes.",
28
28
  "GREEN: Run full suite — execute ALL tests, not just the ones you wrote. The full suite must be GREEN.",
29
29
  "GREEN: Verify no regressions — if any existing test breaks, fix the regression before proceeding.",
30
+ "Run verification-before-completion discipline for the slice — capture a fresh test command, commit SHA, and explicit PASS/FAIL status before completion claims.",
30
31
  "REFACTOR: Improve code quality — without changing behavior. Document what you changed and why.",
31
32
  "Record evidence — capture RED failure, GREEN output, and REFACTOR notes in the TDD artifact.",
32
33
  "Annotate traceability — link to plan task ID and spec criterion.",
@@ -40,6 +41,7 @@ export const TDD = {
40
41
  "Capture and store failing output as RED evidence.",
41
42
  "Apply minimal change to satisfy RED tests (GREEN).",
42
43
  "Run full suite, not partial checks, for GREEN validation.",
44
+ "Before declaring the slice complete, run a fresh verification check and record command + commit SHA + PASS/FAIL.",
43
45
  "Refactor without changing behavior and document rationale (REFACTOR).",
44
46
  "Stop if regressions appear and fix before proceeding.",
45
47
  "If a test passes unexpectedly, investigate: does the behavior already exist, or is the test wrong?",
@@ -51,6 +53,7 @@ export const TDD = {
51
53
  "Run tests and capture failure output.",
52
54
  "Dispatch `test-author` in BUILD_GREEN_REFACTOR mode and implement smallest change needed for GREEN.",
53
55
  "Run full tests and build checks.",
56
+ "Run a fresh verification-before-completion check and capture command + commit SHA + PASS/FAIL in guard evidence.",
54
57
  "Perform refactor pass preserving behavior.",
55
58
  "Record RED, GREEN, and REFACTOR evidence in artifact.",
56
59
  "Annotate traceability to plan task and spec criterion; on `sliceReview` triggers, append a Per-Slice Review entry before closing the slice."
@@ -59,12 +62,14 @@ export const TDD = {
59
62
  { id: "tdd_red_test_written", description: "Failing tests exist before implementation changes." },
60
63
  { id: "tdd_green_full_suite", description: "Full relevant suite passes in GREEN state." },
61
64
  { id: "tdd_refactor_completed", description: "Refactor pass completed with behavior preservation verified." },
65
+ { id: "tdd_verified_before_complete", description: "Fresh verification evidence includes test command, commit SHA, and explicit pass/fail status." },
62
66
  { id: "tdd_traceable_to_plan", description: "Change traceability to plan slice is explicit." }
63
67
  ],
64
68
  requiredEvidence: [
65
69
  "Artifact updated at `.cclaw/artifacts/06-tdd.md` with RED, GREEN, and REFACTOR sections.",
66
70
  "Failing command output captured (RED).",
67
71
  "Full test/build output recorded (GREEN).",
72
+ "Fresh verification evidence recorded with command, commit SHA, and PASS/FAIL status before completion.",
68
73
  "Acceptance mapping documented.",
69
74
  "Failure reason analysis recorded.",
70
75
  "Refactor rationale captured.",
@@ -13,6 +13,25 @@ import { FLOW_STAGES } from "../types.js";
13
13
  function unique(values) {
14
14
  return [...new Set(values)];
15
15
  }
16
+ const TEST_COMMAND_HINT_PATTERN = /\b(?:npm test|pnpm test|yarn test|bun test|vitest|jest|pytest|go test|cargo test|mvn test|gradle test|dotnet test)\b/iu;
17
+ const SHA_WITH_LABEL_PATTERN = /\b(?:sha|commit)(?:\s*[:=]|\s+)\s*[0-9a-f]{7,40}\b/iu;
18
+ const PASS_STATUS_PATTERN = /\b(?:pass|passed|green|ok)\b/iu;
19
+ function validateGateEvidenceShape(stage, gateId, evidence) {
20
+ if (stage !== "tdd" || gateId !== "tdd_verified_before_complete") {
21
+ return null;
22
+ }
23
+ const trimmed = evidence.trim();
24
+ if (!TEST_COMMAND_HINT_PATTERN.test(trimmed)) {
25
+ return "must include the fresh verification command that was run (for example `npm test`, `pytest`, `go test`, or equivalent).";
26
+ }
27
+ if (!SHA_WITH_LABEL_PATTERN.test(trimmed)) {
28
+ return "must include a commit SHA token prefixed with `sha` or `commit` (for example `sha: abc1234`).";
29
+ }
30
+ if (!PASS_STATUS_PATTERN.test(trimmed)) {
31
+ return "must include explicit success status (for example `PASS` or `GREEN`).";
32
+ }
33
+ return null;
34
+ }
16
35
  function parseStringList(raw) {
17
36
  if (!Array.isArray(raw))
18
37
  return [];
@@ -392,6 +411,21 @@ async function runAdvanceStage(projectRoot, args, io) {
392
411
  io.stderr.write(`cclaw internal advance-stage: missing --evidence-json entries for passed gates: ${missingGuardEvidence.join(", ")}.\n`);
393
412
  return 1;
394
413
  }
414
+ const malformedGateEvidence = nextPassed.flatMap((gateId) => {
415
+ const provided = args.evidenceByGate[gateId];
416
+ const existing = flowState.guardEvidence[gateId];
417
+ const effectiveEvidence = typeof provided === "string" && provided.trim().length > 0
418
+ ? provided
419
+ : typeof existing === "string" && existing.trim().length > 0
420
+ ? existing
421
+ : "";
422
+ const issue = validateGateEvidenceShape(args.stage, gateId, effectiveEvidence);
423
+ return issue ? [`${gateId}: ${issue}`] : [];
424
+ });
425
+ if (malformedGateEvidence.length > 0) {
426
+ io.stderr.write(`cclaw internal advance-stage: gate evidence format check failed: ${malformedGateEvidence.join(" | ")}.\n`);
427
+ return 1;
428
+ }
395
429
  const nextGuardEvidence = { ...flowState.guardEvidence };
396
430
  for (const gateId of nextPassed) {
397
431
  const provided = args.evidenceByGate[gateId];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "0.46.2",
3
+ "version": "0.46.3",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {