cclaw-cli 6.13.1 → 6.14.1

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/install.js CHANGED
@@ -1003,6 +1003,90 @@ async function applyPlanLegacyContinuationIfNeeded(projectRoot) {
1003
1003
  // Best-effort: corrupt/missing state is handled elsewhere on sync.
1004
1004
  }
1005
1005
  }
1006
+ /**
1007
+ * v6.14.0 — set stream-style defaults on `cclaw-cli sync` and print a
1008
+ * one-line hint when defaults change. Strategy:
1009
+ *
1010
+ * - When `legacyContinuation: true` and `tddCheckpointMode` is unset, force
1011
+ * `tddCheckpointMode: "global-red"` (preserves hox wave protocol).
1012
+ * - When `legacyContinuation: true` and `integrationOverseerMode` is unset,
1013
+ * force `integrationOverseerMode: "always"` (preserves v6.13 behavior).
1014
+ * - When `legacyContinuation` is NOT true (new / standard projects) and
1015
+ * neither field is set, default to `tddCheckpointMode: "per-slice"`,
1016
+ * `integrationOverseerMode: "conditional"`. Also default
1017
+ * `worktreeExecutionMode: "worktree-first"` if unset.
1018
+ *
1019
+ * Returns a one-line hint string (or `null` if nothing changed) so callers
1020
+ * can print it through the standard sync hint surface.
1021
+ */
1022
+ async function applyV614DefaultsIfNeeded(projectRoot) {
1023
+ // Defensive read — match `applyTddCutoverIfNeeded`'s pattern (raw +
1024
+ // JSON.parse) so corrupt state is left untouched for the downstream
1025
+ // fail-fast check in `materializeRuntime` (which expects to see the
1026
+ // CorruptFlowStateError surfaced via `ensureRunSystem`). Calling
1027
+ // `readFlowState` directly would quarantine the corrupt file and hide
1028
+ // the failure from the caller.
1029
+ const flowStatePath = runtimePath(projectRoot, "state", "flow-state.json");
1030
+ let flowStateRaw;
1031
+ try {
1032
+ flowStateRaw = await fs.readFile(flowStatePath, "utf8");
1033
+ }
1034
+ catch {
1035
+ return null;
1036
+ }
1037
+ let parsed;
1038
+ try {
1039
+ parsed = JSON.parse(flowStateRaw);
1040
+ }
1041
+ catch {
1042
+ return null;
1043
+ }
1044
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1045
+ return null;
1046
+ }
1047
+ const obj = parsed;
1048
+ const updates = {};
1049
+ const summary = [];
1050
+ const tddCheckpointModeSet = obj.tddCheckpointMode === "per-slice" || obj.tddCheckpointMode === "global-red";
1051
+ const integrationOverseerModeSet = obj.integrationOverseerMode === "conditional" || obj.integrationOverseerMode === "always";
1052
+ const worktreeExecutionModeSet = obj.worktreeExecutionMode === "worktree-first" || obj.worktreeExecutionMode === "single-tree";
1053
+ const legacyContinuation = obj.legacyContinuation === true;
1054
+ if (legacyContinuation) {
1055
+ if (!tddCheckpointModeSet) {
1056
+ updates.tddCheckpointMode = "global-red";
1057
+ summary.push("tddCheckpointMode=global-red (legacyContinuation)");
1058
+ }
1059
+ if (!integrationOverseerModeSet) {
1060
+ updates.integrationOverseerMode = "always";
1061
+ summary.push("integrationOverseerMode=always (legacyContinuation)");
1062
+ }
1063
+ }
1064
+ else {
1065
+ if (!tddCheckpointModeSet) {
1066
+ updates.tddCheckpointMode = "per-slice";
1067
+ summary.push("tddCheckpointMode=per-slice");
1068
+ }
1069
+ if (!integrationOverseerModeSet) {
1070
+ updates.integrationOverseerMode = "conditional";
1071
+ summary.push("integrationOverseerMode=conditional");
1072
+ }
1073
+ if (!worktreeExecutionModeSet) {
1074
+ updates.worktreeExecutionMode = "worktree-first";
1075
+ summary.push("worktreeExecutionMode=worktree-first");
1076
+ }
1077
+ }
1078
+ if (summary.length === 0) {
1079
+ return null;
1080
+ }
1081
+ const merged = { ...obj, ...updates };
1082
+ try {
1083
+ await writeFileSafe(flowStatePath, `${JSON.stringify(merged, null, 2)}\n`, { mode: 0o600 });
1084
+ }
1085
+ catch {
1086
+ return null;
1087
+ }
1088
+ return `v6.14.0 stream-style defaults applied: ${summary.join(", ")}. To opt out, edit .cclaw/state/flow-state.json directly or pin the legacy mode (tddCheckpointMode="global-red", integrationOverseerMode="always").`;
1089
+ }
1006
1090
  async function cleanLegacyArtifacts(projectRoot) {
1007
1091
  for (const legacyFolder of DEPRECATED_UTILITY_SKILL_FOLDERS) {
1008
1092
  await removeBestEffort(runtimePath(projectRoot, "skills", legacyFolder), true);
@@ -1178,6 +1262,10 @@ async function materializeRuntime(projectRoot, config, forceStateReset, operatio
1178
1262
  if (operation === "sync" || operation === "upgrade") {
1179
1263
  await applyTddCutoverIfNeeded(projectRoot);
1180
1264
  await applyPlanLegacyContinuationIfNeeded(projectRoot);
1265
+ const v614Hint = await applyV614DefaultsIfNeeded(projectRoot);
1266
+ if (v614Hint) {
1267
+ process.stdout.write(`cclaw: ${v614Hint}\n`);
1268
+ }
1181
1269
  }
1182
1270
  try {
1183
1271
  await ensureRunSystem(projectRoot, { createIfMissing: false });
@@ -473,6 +473,8 @@ function coerceFlowState(parsed) {
473
473
  const completedStageMeta = sanitizeCompletedStageMeta(parsed.completedStageMeta);
474
474
  const tddCutoverSliceId = coerceTddCutoverSliceId(parsed.tddCutoverSliceId);
475
475
  const worktreeExecutionMode = coerceWorktreeExecutionMode(parsed.worktreeExecutionMode);
476
+ const tddCheckpointMode = coerceTddCheckpointMode(parsed.tddCheckpointMode);
477
+ const integrationOverseerMode = coerceIntegrationOverseerMode(parsed.integrationOverseerMode);
476
478
  const legacyContinuation = typeof parsed.legacyContinuation === "boolean" ? parsed.legacyContinuation : undefined;
477
479
  const state = {
478
480
  schemaVersion: FLOW_STATE_SCHEMA_VERSION,
@@ -488,6 +490,8 @@ function coerceFlowState(parsed) {
488
490
  ...(completedStageMeta ? { completedStageMeta } : {}),
489
491
  ...(tddCutoverSliceId ? { tddCutoverSliceId } : {}),
490
492
  ...(worktreeExecutionMode !== undefined ? { worktreeExecutionMode } : {}),
493
+ ...(tddCheckpointMode !== undefined ? { tddCheckpointMode } : {}),
494
+ ...(integrationOverseerMode !== undefined ? { integrationOverseerMode } : {}),
491
495
  ...(legacyContinuation !== undefined ? { legacyContinuation } : {}),
492
496
  skippedStages: sanitizeSkippedStages(parsed.skippedStages, track),
493
497
  staleStages: sanitizeStaleStages(parsed.staleStages),
@@ -514,6 +518,16 @@ function coerceWorktreeExecutionMode(value) {
514
518
  return value;
515
519
  return undefined;
516
520
  }
521
+ function coerceTddCheckpointMode(value) {
522
+ if (value === "per-slice" || value === "global-red")
523
+ return value;
524
+ return undefined;
525
+ }
526
+ function coerceIntegrationOverseerMode(value) {
527
+ if (value === "conditional" || value === "always")
528
+ return value;
529
+ return undefined;
530
+ }
517
531
  export class CorruptFlowStateError extends Error {
518
532
  statePath;
519
533
  quarantinedPath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "6.13.1",
3
+ "version": "6.14.1",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {