cclaw-cli 0.47.0 → 0.48.0

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/policy.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { COMMAND_FILE_ORDER, RUNTIME_ROOT } from "./constants.js";
3
+ import { RUNTIME_ROOT } from "./constants.js";
4
+ import { FLOW_STAGES } from "./types.js";
4
5
  import { stageSchema, stagePolicyNeedles } from "./content/stage-schema.js";
5
6
  import { stageSkillFolder } from "./content/skills.js";
6
7
  import { exists } from "./fs-utils.js";
@@ -10,7 +11,7 @@ export async function policyChecks(projectRoot, options = {}) {
10
11
  const checks = [];
11
12
  const rules = [...POLICY_RULES];
12
13
  const activeHarnesses = new Set(options.harnesses && options.harnesses.length > 0 ? options.harnesses : ALL_HARNESSES);
13
- for (const stage of COMMAND_FILE_ORDER) {
14
+ for (const stage of FLOW_STAGES) {
14
15
  const folder = stageSkillFolder(stage);
15
16
  const schema = stageSchema(stage);
16
17
  const commandFile = `${RUNTIME_ROOT}/commands/${stage}.md`;
@@ -8,6 +8,7 @@ function activeArtifactsPath(projectRoot) {
8
8
  function retroArtifactPath(projectRoot) {
9
9
  return path.join(activeArtifactsPath(projectRoot), "09-retro.md");
10
10
  }
11
+ const RETRO_ARTIFACT_MTIME_FALLBACK_WINDOW_MS = 24 * 60 * 60 * 1000;
11
12
  function parseIsoTimestamp(value) {
12
13
  if (!value || value.trim().length === 0)
13
14
  return null;
@@ -35,8 +36,24 @@ export async function evaluateRetroGate(projectRoot, state) {
35
36
  }
36
37
  }
37
38
  let compoundEntries = state.retro.compoundEntries;
38
- const windowStartMs = parseIsoTimestamp(state.closeout.retroDraftedAt);
39
- const windowEndMs = parseIsoTimestamp(state.closeout.retroAcceptedAt) ?? parseIsoTimestamp(state.retro.completedAt);
39
+ let windowStartMs = parseIsoTimestamp(state.closeout.retroDraftedAt);
40
+ let windowEndMs = parseIsoTimestamp(state.closeout.retroAcceptedAt) ?? parseIsoTimestamp(state.retro.completedAt);
41
+ if (compoundEntries <= 0 &&
42
+ hasRetroArtifact &&
43
+ windowStartMs === null &&
44
+ windowEndMs === null) {
45
+ try {
46
+ const stats = await fs.stat(artifactFile);
47
+ const anchor = stats.mtimeMs;
48
+ if (Number.isFinite(anchor) && anchor > 0) {
49
+ windowStartMs = anchor - RETRO_ARTIFACT_MTIME_FALLBACK_WINDOW_MS;
50
+ windowEndMs = anchor + RETRO_ARTIFACT_MTIME_FALLBACK_WINDOW_MS;
51
+ }
52
+ }
53
+ catch {
54
+ // fallback scan remains disabled when mtime cannot be read
55
+ }
56
+ }
40
57
  const shouldFallbackScan = compoundEntries <= 0 && (windowStartMs !== null || windowEndMs !== null);
41
58
  const knowledgeFile = path.join(projectRoot, RUNTIME_ROOT, "knowledge.jsonl");
42
59
  if (shouldFallbackScan && (await exists(knowledgeFile))) {
@@ -1,9 +1,10 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { COMMAND_FILE_ORDER, RUNTIME_ROOT } from "./constants.js";
3
+ import { RUNTIME_ROOT } from "./constants.js";
4
4
  import { canTransition, createInitialCloseoutState, createInitialFlowState, isFlowTrack, skippedStagesForTrack, SHIP_SUBSTATES } from "./flow-state.js";
5
5
  import { ensureFeatureSystem, syncActiveFeatureSnapshot } from "./feature-system.js";
6
6
  import { ensureDir, exists, withDirectoryLock, writeFileSafe } from "./fs-utils.js";
7
+ import { FLOW_STAGES } from "./types.js";
7
8
  export class InvalidStageTransitionError extends Error {
8
9
  from;
9
10
  to;
@@ -17,7 +18,7 @@ export class InvalidStageTransitionError extends Error {
17
18
  const FLOW_STATE_REL_PATH = `${RUNTIME_ROOT}/state/flow-state.json`;
18
19
  const RUNS_DIR_REL_PATH = `${RUNTIME_ROOT}/runs`;
19
20
  const ACTIVE_ARTIFACTS_REL_PATH = `${RUNTIME_ROOT}/artifacts`;
20
- const FLOW_STAGE_SET = new Set(COMMAND_FILE_ORDER);
21
+ const FLOW_STAGE_SET = new Set(FLOW_STAGES);
21
22
  function validateFlowTransition(prev, next) {
22
23
  if (prev.activeRunId !== next.activeRunId) {
23
24
  // New run — only reset paths may change the runId, but those set allowReset.
@@ -85,7 +86,7 @@ function sanitizeGuardEvidence(value) {
85
86
  function sanitizeStageGateCatalog(value, fallback) {
86
87
  const uniqueStrings = (items) => [...new Set(items)];
87
88
  const next = {};
88
- for (const stage of COMMAND_FILE_ORDER) {
89
+ for (const stage of FLOW_STAGES) {
89
90
  const base = fallback[stage];
90
91
  next[stage] = {
91
92
  required: [...base.required],
@@ -100,7 +101,7 @@ function sanitizeStageGateCatalog(value, fallback) {
100
101
  return next;
101
102
  }
102
103
  const rawCatalog = value;
103
- for (const stage of COMMAND_FILE_ORDER) {
104
+ for (const stage of FLOW_STAGES) {
104
105
  const rawStage = rawCatalog[stage];
105
106
  if (!rawStage || typeof rawStage !== "object" || Array.isArray(rawStage)) {
106
107
  continue;
package/dist/types.d.ts CHANGED
@@ -109,7 +109,7 @@ export interface TddPathConfig {
109
109
  export interface CompoundConfig {
110
110
  recurrenceThreshold?: number;
111
111
  }
112
- export interface VibyConfig {
112
+ export interface CclawConfig {
113
113
  version: string;
114
114
  flowVersion: string;
115
115
  harnesses: HarnessId[];
@@ -141,6 +141,7 @@ export interface VibyConfig {
141
141
  /**
142
142
  * Legacy alias for test-side path detection in workflow-guard.
143
143
  * Prefer `tdd.testPathPatterns` in new configs.
144
+ * @deprecated Use `tdd.testPathPatterns` instead.
144
145
  */
145
146
  tddTestGlobs?: string[];
146
147
  /** Path-pattern routing for TDD test/production write classification. */
@@ -173,6 +174,10 @@ export interface VibyConfig {
173
174
  */
174
175
  sliceReview?: SliceReviewConfig;
175
176
  }
177
+ /**
178
+ * @deprecated Use `CclawConfig` instead.
179
+ */
180
+ export type VibyConfig = CclawConfig;
176
181
  export interface TransitionRule {
177
182
  from: FlowStage;
178
183
  to: FlowStage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,6 +21,7 @@
21
21
  "test": "vitest run",
22
22
  "test:watch": "vitest",
23
23
  "test:coverage": "vitest run --coverage",
24
+ "test:mutation": "stryker run",
24
25
  "smoke:runtime": "npm run build && node scripts/smoke-init.mjs",
25
26
  "lint:hooks": "npm run build && node scripts/lint-generated-hooks.mjs",
26
27
  "build:harness-docs": "npm run build && node scripts/build-harness-docs.mjs",
@@ -44,6 +45,8 @@
44
45
  "yaml": "^2.8.1"
45
46
  },
46
47
  "devDependencies": {
48
+ "@stryker-mutator/core": "^9.6.1",
49
+ "@stryker-mutator/vitest-runner": "^9.6.1",
47
50
  "@types/node": "^24.7.2",
48
51
  "@vitest/coverage-v8": "^3.2.4",
49
52
  "typescript": "^5.9.3",