cclaw-cli 6.14.2 → 6.14.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/artifact-linter/tdd.js +20 -39
- package/dist/install.js +34 -7
- package/package.json +1 -1
|
@@ -285,13 +285,25 @@ export async function lintTddStage(ctx) {
|
|
|
285
285
|
"refactor-deferred",
|
|
286
286
|
"resolve-conflict"
|
|
287
287
|
]);
|
|
288
|
-
// v6.14.
|
|
289
|
-
// boundary, exempt
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
//
|
|
293
|
-
// the
|
|
294
|
-
|
|
288
|
+
// v6.14.3 — under `legacyContinuation: true` AND a stamped
|
|
289
|
+
// boundary, exempt every slice closed at or before
|
|
290
|
+
// `tddWorktreeCutoverSliceId`. The cutover boundary itself is the
|
|
291
|
+
// contract: slices ≤ boundary were closed before the
|
|
292
|
+
// worktree-first metadata mandate took effect, so we trust the
|
|
293
|
+
// boundary as authoritative and do not require the slice to have
|
|
294
|
+
// recorded zero metadata across all rows.
|
|
295
|
+
//
|
|
296
|
+
// The earlier v6.14.2 "all-or-nothing" rule rejected the common
|
|
297
|
+
// hox-shape pattern where the GREEN row carries claim/lane/lease
|
|
298
|
+
// (added on the v6.14.x worktree-first flip) but a later
|
|
299
|
+
// `refactor-deferred` terminal row does not. That partial-
|
|
300
|
+
// metadata layout is the operator-visible signature of the
|
|
301
|
+
// failure mode this exemption was introduced to fix; flagging it
|
|
302
|
+
// again under a different code defeated the entire migration.
|
|
303
|
+
//
|
|
304
|
+
// Operators who want a strict gate can opt out by clearing
|
|
305
|
+
// `legacyContinuation` (or omitting `tddWorktreeCutoverSliceId`)
|
|
306
|
+
// — both fields are explicit, persisted, and operator-editable.
|
|
295
307
|
const isExemptLegacySlice = (sliceId) => {
|
|
296
308
|
if (!legacyContinuation)
|
|
297
309
|
return false;
|
|
@@ -300,14 +312,7 @@ export async function lintTddStage(ctx) {
|
|
|
300
312
|
const n = parseSliceNumber(sliceId);
|
|
301
313
|
if (n === null)
|
|
302
314
|
return false;
|
|
303
|
-
|
|
304
|
-
return false;
|
|
305
|
-
const meta = sliceWorktreeMetaState.get(sliceId);
|
|
306
|
-
if (!meta)
|
|
307
|
-
return true; // no slice-implementer rows at all → fully legacy
|
|
308
|
-
// Exempt only when the slice carries ZERO worktree fields across
|
|
309
|
-
// all rows. Partial metadata stays flagged.
|
|
310
|
-
return !meta.anyMeta;
|
|
315
|
+
return n <= worktreeCutoverBoundary;
|
|
311
316
|
};
|
|
312
317
|
const missingGreenMeta = new Set();
|
|
313
318
|
const exemptedGreenMeta = new Set();
|
|
@@ -1333,30 +1338,6 @@ function pickEventTs(rows) {
|
|
|
1333
1338
|
}
|
|
1334
1339
|
return undefined;
|
|
1335
1340
|
}
|
|
1336
|
-
/**
|
|
1337
|
-
* v6.14.2 — for each slice id appearing in `slice-implementer` rows of
|
|
1338
|
-
* the active run, record whether ANY row carried at least one of the
|
|
1339
|
-
* three worktree-first metadata fields (`claimToken`, `ownerLaneId`,
|
|
1340
|
-
* `leasedUntil`). Used by `isExemptLegacySlice` to enforce the "all-or-
|
|
1341
|
-
* nothing legacy" rule: only slices with NO worktree fields anywhere
|
|
1342
|
-
* in their rows qualify for the legacyContinuation amnesty.
|
|
1343
|
-
*/
|
|
1344
|
-
function computeSliceWorktreeMetaState(events) {
|
|
1345
|
-
const out = new Map();
|
|
1346
|
-
for (const ev of events) {
|
|
1347
|
-
if (ev.stage !== "tdd" || ev.agent !== "slice-implementer")
|
|
1348
|
-
continue;
|
|
1349
|
-
if (typeof ev.sliceId !== "string")
|
|
1350
|
-
continue;
|
|
1351
|
-
const tok = ev.claimToken?.trim() ?? "";
|
|
1352
|
-
const lane = ev.ownerLaneId?.trim() ?? "";
|
|
1353
|
-
const lease = ev.leasedUntil?.trim() ?? "";
|
|
1354
|
-
const anyHere = tok.length > 0 || lane.length > 0 || lease.length > 0;
|
|
1355
|
-
const prev = out.get(ev.sliceId) ?? { anyMeta: false };
|
|
1356
|
-
out.set(ev.sliceId, { anyMeta: prev.anyMeta || anyHere });
|
|
1357
|
-
}
|
|
1358
|
-
return out;
|
|
1359
|
-
}
|
|
1360
1341
|
/**
|
|
1361
1342
|
* v6.14.2 — slices whose terminal `refactor` / `refactor-deferred` /
|
|
1362
1343
|
* `resolve-conflict` row recorded a `completedTs` that PRECEDES the
|
package/dist/install.js
CHANGED
|
@@ -939,8 +939,20 @@ async function applyTddCutoverIfNeeded(projectRoot) {
|
|
|
939
939
|
if (typeof obj.tddCutoverSliceId === "string" && obj.tddCutoverSliceId.length > 0) {
|
|
940
940
|
return;
|
|
941
941
|
}
|
|
942
|
-
|
|
943
|
-
|
|
942
|
+
// v6.14.3 — refresh the SHA256 sidecar by writing through
|
|
943
|
+
// `writeFlowState`. The previous direct `writeFileSafe` invocation
|
|
944
|
+
// left the sidecar stale, so the very next guarded hook on a synced
|
|
945
|
+
// legacy project rejected its own `tddCutoverSliceId` stamp.
|
|
946
|
+
try {
|
|
947
|
+
const state = await readFlowState(projectRoot);
|
|
948
|
+
await writeFlowState(projectRoot, { ...state, tddCutoverSliceId: cutoverSliceId }, {
|
|
949
|
+
allowReset: true,
|
|
950
|
+
writerSubsystem: "sync-v6.12-tdd-cutover-stamp"
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
catch {
|
|
954
|
+
// Best-effort: corrupt/missing state is handled elsewhere on sync.
|
|
955
|
+
}
|
|
944
956
|
}
|
|
945
957
|
const V613_LEGACY_PLAN_BANNER = "<!-- legacy-continuation: predates v6.13 parallel metadata. New units MAY add dependsOn/claimedPaths/parallelizable; existing units treated as best-effort serial. -->";
|
|
946
958
|
/**
|
|
@@ -1091,9 +1103,16 @@ async function applyV614DefaultsIfNeeded(projectRoot) {
|
|
|
1091
1103
|
if (summary.length === 0) {
|
|
1092
1104
|
return null;
|
|
1093
1105
|
}
|
|
1094
|
-
|
|
1106
|
+
// v6.14.3 — refresh the SHA256 sidecar in lockstep so guarded reads
|
|
1107
|
+
// (verify-current-state, advance-stage, etc.) don't trip a guard
|
|
1108
|
+
// mismatch immediately after `cclaw-cli sync`/`upgrade` writes the
|
|
1109
|
+
// v6.14.2 stream-style defaults.
|
|
1095
1110
|
try {
|
|
1096
|
-
|
|
1111
|
+
const state = await readFlowState(projectRoot);
|
|
1112
|
+
await writeFlowState(projectRoot, { ...state, ...updates }, {
|
|
1113
|
+
allowReset: true,
|
|
1114
|
+
writerSubsystem: "sync-v6.14.2-stream-defaults"
|
|
1115
|
+
});
|
|
1097
1116
|
}
|
|
1098
1117
|
catch {
|
|
1099
1118
|
return null;
|
|
@@ -1204,10 +1223,18 @@ async function applyV6142WorktreeCutoverIfNeeded(projectRoot) {
|
|
|
1204
1223
|
}
|
|
1205
1224
|
if (!stamped)
|
|
1206
1225
|
return null;
|
|
1207
|
-
|
|
1226
|
+
// v6.14.3 — go through `writeFlowState` so the SHA256 sidecar
|
|
1227
|
+
// (`.cclaw/.flow-state.guard.json`) is refreshed in lockstep with
|
|
1228
|
+
// the on-disk flow-state.json. The previous v6.14.2 implementation
|
|
1229
|
+
// wrote the field via `writeFileSafe` directly, which left the
|
|
1230
|
+
// sidecar pointing at the pre-stamp digest; the next guarded hook
|
|
1231
|
+
// (e.g. `cclaw internal verify-current-state`) then failed with
|
|
1232
|
+
// `flow-state guard mismatch` and demanded a manual repair.
|
|
1208
1233
|
try {
|
|
1209
|
-
|
|
1210
|
-
|
|
1234
|
+
const state = await readFlowState(projectRoot);
|
|
1235
|
+
await writeFlowState(projectRoot, { ...state, tddWorktreeCutoverSliceId: stamped }, {
|
|
1236
|
+
allowReset: true,
|
|
1237
|
+
writerSubsystem: "sync-v6.14.2-worktree-cutover-stamp"
|
|
1211
1238
|
});
|
|
1212
1239
|
}
|
|
1213
1240
|
catch {
|