@quantiya/codevibe-codex-plugin 2.0.22 → 2.0.24

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.
@@ -294,6 +294,8 @@ export interface ShadowEnv {
294
294
  afterQuotaReferenceMarkerEntry?: (filePath: string) => Promise<void> | void;
295
295
  /** @internal deterministic replacement seam after a quota-reference marker is opened. */
296
296
  afterQuotaReferenceMarkerStat?: (filePath: string) => Promise<void> | void;
297
+ /** @internal deterministic replacement seam after the final target lifecycle scan. */
298
+ afterQuotaRetirementTargetProof?: (shadowRoot: string) => Promise<void> | void;
297
299
  /** @internal fail initial/retry shadow-root durability before acknowledgement. */
298
300
  failShadowRootDirectorySyncStage?: 'target-child' | 'target-parent';
299
301
  /** @internal fail initial/retry state-root durability before acknowledgement. */
@@ -255,7 +255,17 @@ interface RegisteredShadowRoot extends AnchoredFsIdentity {
255
255
  * physical shadow root before copying, so the aggregate scan cannot be split by
256
256
  * different temp-root configuration.
257
257
  */
258
- export declare function registerAndListQuotaShadowRoots(stateRoot: string, stateRootIdentity: WorkspaceRootAuthority, currentShadowRoot: string, currentShadowRootIdentity: WorkspaceRootAuthority, publicationOwnerKey: string, maxStateMarkerBytes: number, afterQuotaReferenceTaskEntry?: (stateDir: string) => Promise<void> | void, afterQuotaReferenceMarkerEntry?: (filePath: string) => Promise<void> | void, afterQuotaReferenceMarkerStat?: (filePath: string) => Promise<void> | void, failDirectorySync?: boolean): Promise<RegisteredShadowRoot[]>;
258
+ export declare function registerAndListQuotaShadowRoots(stateRoot: string, stateRootIdentity: WorkspaceRootAuthority, currentShadowRoot: string, currentShadowRootIdentity: WorkspaceRootAuthority, publicationOwnerKey: string, maxStateMarkerBytes: number, afterQuotaReferenceTaskEntry?: (stateDir: string) => Promise<void> | void, afterQuotaReferenceMarkerEntry?: (filePath: string) => Promise<void> | void, afterQuotaReferenceMarkerStat?: (filePath: string) => Promise<void> | void, failDirectorySync?: boolean, mode?: 'register-current' | 'retire-current-if-unused', afterQuotaRetirementTargetProof?: (shadowRoot: string) => Promise<void> | void): Promise<RegisteredShadowRoot[]>;
259
+ /**
260
+ * Retire the exact current shadow-root authority after terminal cleanup.
261
+ *
262
+ * Registration and retirement share the same cross-process quota fence. The
263
+ * current root is removed only when the exact registered directory still
264
+ * exists, contains no generated snapshot/staging/tombstone, and is not named
265
+ * by any durable state or exposure marker. A missing, replaced, renamed, or
266
+ * referenced authority remains fail-closed in `registerAndListQuotaShadowRoots`.
267
+ */
268
+ export declare function retireQuotaShadowRootIfUnused(stateRoot: string, stateRootIdentity: WorkspaceRootAuthority, currentShadowRoot: string, currentShadowRootIdentity: WorkspaceRootAuthority, publicationOwnerKey: string, maxStateMarkerBytes: number, afterQuotaReferenceTaskEntry?: (stateDir: string) => Promise<void> | void, afterQuotaReferenceMarkerEntry?: (filePath: string) => Promise<void> | void, afterQuotaReferenceMarkerStat?: (filePath: string) => Promise<void> | void, failDirectorySync?: boolean, afterQuotaRetirementTargetProof?: (shadowRoot: string) => Promise<void> | void): Promise<boolean>;
259
269
  interface CleanupBlockAnchorRead {
260
270
  present: boolean;
261
271
  cleanupOwners: ProcessCleanupOwner[];
@@ -229,6 +229,7 @@ export declare class WorkspaceShadow {
229
229
  */
230
230
  applyingAuthorityRetired?: boolean;
231
231
  }): Promise<void>;
232
+ private retirePhysicalCopyRootIfUnused;
232
233
  private retainExposureWriteAuthority;
233
234
  private runOwnedStateFileWrite;
234
235
  private acceptExposureSnapshot;
@@ -8410,9 +8410,10 @@ function reduceSessionTaskTerminal(state, event) {
8410
8410
  if (terminal === null) return state;
8411
8411
  let taskId = "taskId" in event ? event.taskId : void 0;
8412
8412
  if (!taskId) return state;
8413
- let existing = state.sessionTasks.get(taskId), sessionTasks = new Map(state.sessionTasks);
8413
+ let runningTasks = new Map(state.runningTasks), evictedRunningTask = runningTasks.delete(taskId), existing = state.sessionTasks.get(taskId), sessionTasks = new Map(state.sessionTasks);
8414
8414
  if (existing) {
8415
- if (existing.origin !== "single" || existing.status !== "running") return state;
8415
+ if (existing.origin !== "single" || existing.status !== "running")
8416
+ return evictedRunningTask ? { ...state, runningTasks } : state;
8416
8417
  sessionTasks.set(taskId, { ...existing, status: terminal });
8417
8418
  } else
8418
8419
  sessionTasks.set(taskId, {
@@ -8421,7 +8422,7 @@ function reduceSessionTaskTerminal(state, event) {
8421
8422
  status: terminal,
8422
8423
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
8423
8424
  });
8424
- return { ...state, sessionTasks };
8425
+ return { ...state, runningTasks, sessionTasks };
8425
8426
  }
8426
8427
  var REVIEWER_STATUS_PHASES = /* @__PURE__ */ new Set([
8427
8428
  "reviewers_dispatched",
@@ -8724,9 +8725,9 @@ function reduceClarificationAnswered(state, answer) {
8724
8725
  };
8725
8726
  }
8726
8727
  function reduceTaskLifecycle(state, task) {
8727
- let next = new Map(state.runningTasks);
8728
- task.status === "completed" || task.status === "cancelled" || task.status === "failed" ? next.delete(task.taskId) : next.set(task.taskId, task);
8729
- let history = new Map(state.sessionTasks), existing = state.sessionTasks.get(task.taskId), existingIsTerminal = existing?.origin === "single" && (existing.status === "completed" || existing.status === "cancelled" || existing.status === "failed"), incomingIsTerminal = task.status === "completed" || task.status === "cancelled" || task.status === "failed";
8728
+ let existing = state.sessionTasks.get(task.taskId), existingIsTerminal = existing?.origin === "single" && (existing.status === "completed" || existing.status === "cancelled" || existing.status === "failed"), incomingIsTerminal = task.status === "completed" || task.status === "cancelled" || task.status === "failed", next = new Map(state.runningTasks);
8729
+ incomingIsTerminal || existingIsTerminal && !incomingIsTerminal ? next.delete(task.taskId) : next.set(task.taskId, task);
8730
+ let history = new Map(state.sessionTasks);
8730
8731
  return history.set(task.taskId, {
8731
8732
  taskId: task.taskId,
8732
8733
  agentKind: task.agentKind,
@@ -33076,8 +33077,13 @@ function isSameRegisteredRootAuthority(prior, current) {
33076
33077
  function isSameRootAfterDeviceReincarnation(prior, current) {
33077
33078
  return prior.dev !== current.dev && prior.ino === current.ino && prior.version === current.version && prior.canonicalPath === current.canonicalPath && prior.birthtimeNs === current.birthtimeNs;
33078
33079
  }
33079
- async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority, maxStateMarkerBytes, registeredShadowRoots, afterTaskEntry, afterMarkerEntry, afterMarkerStat) {
33080
- let referenced = /* @__PURE__ */ new Set(), budget = createPathBudget(), taskEntries = await readDirectoryBounded(
33080
+ async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority, maxStateMarkerBytes, registeredShadowRoots, afterTaskEntry, afterMarkerEntry, afterMarkerStat, allowUnrecognizedRegularFiles = !1, allowUnregisteredReferences = !1, allowConcurrentSiblingTeardown = !1) {
33081
+ let retryConcurrentSiblingTeardown = (error, target) => {
33082
+ let code = error?.code, message = error instanceof Error ? error.message : String(error), isSiblingChurn = code === "ENOENT" || message.includes("workspace root changed while opening") || message.includes("workspace root cwd identity mismatch") || message.includes("workspace root changed during authority capture") || message.includes("bounded-directory target identity mismatch") || message.includes("bounded-directory parent changed while opening") || message.includes("bounded-directory parent changed while descending") || message.includes("anchored read root authority unavailable") || message.includes("anchored read root identity mismatch") || message.includes("anchored read root incarnation mismatch") || message.includes("anchored read directory chain changed") || message.includes("anchored read directory changed while descending") || message.includes("anchored read cwd identity mismatch") || message.includes("anchored read file identity mismatch") || message.includes("anchored read file changed during read") || message.includes("anchored read file path changed") || message.includes("anchored read file changed after read");
33083
+ throw allowConcurrentSiblingTeardown && isSiblingChurn ? new Error(
33084
+ `bounded-directory target changed during enumeration: ${target}; ${message}`
33085
+ ) : error;
33086
+ }, referenced = /* @__PURE__ */ new Set(), budget = createPathBudget(), taskEntries = await readDirectoryBounded(
33081
33087
  stateRoot,
33082
33088
  budget,
33083
33089
  "physical-copy root reference enumeration",
@@ -33090,15 +33096,24 @@ async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority
33090
33096
  );
33091
33097
  for (let taskEntry of taskEntries) {
33092
33098
  if (isStateRootInfrastructureDirectory(taskEntry.name) || taskEntry.name === SHADOW_ROOT_REGISTRY_FILE) continue;
33093
- if (!taskEntry.isDirectory() || taskEntry.isSymbolicLink())
33099
+ if (!taskEntry.isDirectory() || taskEntry.isSymbolicLink()) {
33100
+ if (allowUnrecognizedRegularFiles && taskEntry.isFile() && !taskEntry.isSymbolicLink()) continue;
33094
33101
  throw new Error("physical-copy root reference state entry changed type");
33102
+ }
33095
33103
  let taskId = taskEntry.name, stateDir = path38.join(stateRoot, taskId), enumeratedStateDir = boundedDirectoryStat(taskEntry);
33096
33104
  if (!enumeratedStateDir)
33097
33105
  throw new Error("physical-copy root reference state entry lacks authority");
33098
33106
  await afterTaskEntry?.(stateDir);
33099
- let stateDirAuthority = await captureWorkspaceRootAuthority(stateDir);
33107
+ let stateDirAuthority = await captureWorkspaceRootAuthority(stateDir).catch(
33108
+ (error) => retryConcurrentSiblingTeardown(
33109
+ error,
33110
+ `sibling state directory ${taskId}`
33111
+ )
33112
+ );
33100
33113
  if (stateDirAuthority.dev !== enumeratedStateDir.dev || stateDirAuthority.ino !== enumeratedStateDir.ino || stateDirAuthority.birthtimeNs !== enumeratedStateDir.birthtimeNs || stateDirAuthority.canonicalPath !== enumeratedStateDir.canonicalPath || path38.dirname(stateDirAuthority.canonicalPath) !== stateRoot || path38.basename(stateDirAuthority.canonicalPath) !== taskId)
33101
- throw new Error("physical-copy root reference state directory changed after enumeration");
33114
+ throw allowConcurrentSiblingTeardown ? new Error(
33115
+ `bounded-directory target changed during enumeration: sibling state directory ${taskId}`
33116
+ ) : new Error("physical-copy root reference state directory changed after enumeration");
33102
33117
  let markerEntries = await readDirectoryBounded(
33103
33118
  stateDir,
33104
33119
  budget,
@@ -33110,7 +33125,10 @@ async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority
33110
33125
  rootAuthority: stateRootAuthority,
33111
33126
  relativeDirectory: taskId
33112
33127
  }
33113
- );
33128
+ ).catch((error) => retryConcurrentSiblingTeardown(
33129
+ error,
33130
+ `sibling state contents ${taskId}`
33131
+ ));
33114
33132
  for (let markerEntry of markerEntries) {
33115
33133
  let isStateMarker = SHADOW_STATE_FILE_RE.test(markerEntry.name), isExposureRetention = SHADOW_EXPOSURE_RETENTION_FILE_RE.test(markerEntry.name);
33116
33134
  if (!isStateMarker && !isExposureRetention) continue;
@@ -33120,38 +33138,55 @@ async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority
33120
33138
  if (!enumeratedMarker)
33121
33139
  throw new Error("physical-copy root reference marker lacks authority");
33122
33140
  await afterMarkerEntry?.(stateFile);
33123
- let read = await anchoredReadFileWithinRoot(stateDir, markerEntry.name, {
33124
- maxBytes: maxStateMarkerBytes,
33125
- expectedRoot: stateDirAuthority,
33126
- expectedFile: enumeratedMarker,
33127
- requireSingleLink: !0,
33128
- afterStat: () => afterMarkerStat?.(stateFile)
33129
- });
33130
- if (!read) throw new Error("physical-copy root reference marker disappeared");
33141
+ let read;
33142
+ try {
33143
+ read = await anchoredReadFileWithinRoot(stateDir, markerEntry.name, {
33144
+ maxBytes: maxStateMarkerBytes,
33145
+ expectedRoot: stateDirAuthority,
33146
+ expectedFile: enumeratedMarker,
33147
+ requireSingleLink: !0,
33148
+ afterStat: () => afterMarkerStat?.(stateFile)
33149
+ });
33150
+ } catch (error) {
33151
+ retryConcurrentSiblingTeardown(
33152
+ error,
33153
+ `sibling marker ${taskId}/${markerEntry.name}`
33154
+ );
33155
+ }
33156
+ if (!read)
33157
+ throw allowConcurrentSiblingTeardown ? new Error(
33158
+ `bounded-directory target changed during enumeration: sibling marker ${taskId}/${markerEntry.name}`
33159
+ ) : new Error("physical-copy root reference marker disappeared");
33131
33160
  let decoded = read.bytes.toString("utf8");
33132
33161
  if (!Buffer.from(decoded, "utf8").equals(read.bytes))
33133
33162
  throw new Error("physical-copy root reference marker is not strict UTF-8");
33134
33163
  let value = JSON.parse(decoded);
33135
33164
  if (isStateMarker) {
33136
33165
  let marker = validateMarkerShape(value, taskId), markerRoot2 = path38.dirname(marker.shadowDir);
33137
- if (!registeredShadowRoots.has(markerRoot2))
33166
+ if (validateStateMarkerPlacement(marker, stateFile, stateDir, markerRoot2, stateRoot), !registeredShadowRoots.has(markerRoot2)) {
33167
+ if (allowUnregisteredReferences) continue;
33138
33168
  throw new Error("physical-copy root reference marker names an unregistered root");
33139
- validateStateMarkerPlacement(marker, stateFile, stateDir, markerRoot2, stateRoot), referenced.add(markerRoot2);
33169
+ }
33170
+ referenced.add(markerRoot2);
33140
33171
  continue;
33141
33172
  }
33142
33173
  let preliminary = value;
33143
33174
  if (typeof preliminary.finalShadowDir != "string")
33144
33175
  throw new Error("physical-copy root exposure marker lacks a shadow path");
33145
33176
  let markerRoot = path38.dirname(preliminary.finalShadowDir);
33146
- if (!registeredShadowRoots.has(markerRoot))
33177
+ if (assertExposureRetentionMarker(value, taskId, stateFile, markerRoot, stateRoot), !registeredShadowRoots.has(markerRoot)) {
33178
+ if (allowUnregisteredReferences) continue;
33147
33179
  throw new Error("physical-copy root exposure marker names an unregistered root");
33148
- assertExposureRetentionMarker(value, taskId, stateFile, markerRoot, stateRoot), referenced.add(markerRoot);
33180
+ }
33181
+ referenced.add(markerRoot);
33149
33182
  }
33150
33183
  }
33151
33184
  return referenced;
33152
33185
  }
33153
- async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, currentShadowRoot, currentShadowRootIdentity, publicationOwnerKey, maxStateMarkerBytes, afterQuotaReferenceTaskEntry, afterQuotaReferenceMarkerEntry, afterQuotaReferenceMarkerStat, failDirectorySync = !1) {
33154
- let registryPath = path38.join(stateRoot, SHADOW_ROOT_REGISTRY_FILE), expected = await captureAnchoredWritePrecondition(registryPath, 1024 * 1024), roots = [];
33186
+ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, currentShadowRoot, currentShadowRootIdentity, publicationOwnerKey, maxStateMarkerBytes, afterQuotaReferenceTaskEntry, afterQuotaReferenceMarkerEntry, afterQuotaReferenceMarkerStat, failDirectorySync = !1, mode = "register-current", afterQuotaRetirementTargetProof) {
33187
+ let registryPath = path38.join(stateRoot, SHADOW_ROOT_REGISTRY_FILE), expected = await captureAnchoredWritePrecondition(registryPath, 1024 * 1024);
33188
+ if (mode === "retire-current-if-unused" && expected.kind === "absent") return [];
33189
+ let roots = [];
33155
33190
  if (expected.kind === "existing") {
33156
33191
  let read = await anchoredReadFileWithinRoot(stateRoot, SHADOW_ROOT_REGISTRY_FILE, {
33157
33192
  maxBytes: 1048576
@@ -33171,13 +33206,16 @@ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, cur
33171
33206
  if (consumeMetadataPath(registryBudget, root.path, "physical-copy root registry"), byPath.has(root.path)) throw new Error("physical-copy root registry contains duplicates");
33172
33207
  byPath.set(root.path, root);
33173
33208
  }
33174
- let priorCurrent = byPath.get(currentShadowRoot), reincarnatedDevice = null;
33209
+ let priorCurrent = byPath.get(currentShadowRoot);
33210
+ if (mode === "retire-current-if-unused" && !priorCurrent)
33211
+ return roots;
33212
+ let reincarnatedDevice = null;
33175
33213
  if (priorCurrent && !isSameRegisteredRootAuthority(priorCurrent, currentShadowRootIdentity))
33176
33214
  if (isSameRootAfterDeviceReincarnation(priorCurrent, currentShadowRootIdentity))
33177
33215
  reincarnatedDevice = priorCurrent.dev;
33178
33216
  else
33179
33217
  throw new Error("physical-copy root changed identity while quota authority is retained");
33180
- if (priorCurrent || consumeMetadataPath(registryBudget, currentShadowRoot, "physical-copy root registry"), byPath.set(currentShadowRoot, { path: currentShadowRoot, ...currentShadowRootIdentity }), byPath.size > 256) throw new Error("physical-copy root registry exceeds 256 roots");
33218
+ if (!priorCurrent && mode === "register-current" && consumeMetadataPath(registryBudget, currentShadowRoot, "physical-copy root registry"), mode === "register-current" && byPath.set(currentShadowRoot, { path: currentShadowRoot, ...currentShadowRootIdentity }), byPath.size > 256) throw new Error("physical-copy root registry exceeds 256 roots");
33181
33219
  let retained = [], scanBudget = createPathBudget(), referencedShadowRoots = null, hasPhysicalCopyEntry = async (candidate) => {
33182
33220
  let liveRoot;
33183
33221
  try {
@@ -33192,7 +33230,7 @@ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, cur
33192
33230
  "physical-copy root retirement enumeration",
33193
33231
  candidate.path,
33194
33232
  { rootAuthority: liveRoot, relativeDirectory: "" }
33195
- )).some((entry) => entry.isDirectory() && !entry.isSymbolicLink() && (SHADOW_DIR_RE.test(entry.name) || SHADOW_STAGING_DIR_RE.test(entry.name) || SHADOW_TREE_TOMBSTONE_RE.test(entry.name)));
33233
+ )).some((entry) => SHADOW_DIR_RE.test(entry.name) || SHADOW_STAGING_DIR_RE.test(entry.name) || SHADOW_TREE_TOMBSTONE_RE.test(entry.name));
33196
33234
  return await assertWorkspaceRootAuthority(
33197
33235
  liveRoot.canonicalPath,
33198
33236
  liveRoot,
@@ -33207,6 +33245,42 @@ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, cur
33207
33245
  afterQuotaReferenceMarkerEntry,
33208
33246
  afterQuotaReferenceMarkerStat
33209
33247
  ), !referencedShadowRoots.has(candidate.path));
33248
+ if (mode === "retire-current-if-unused") {
33249
+ let candidate = priorCurrent;
33250
+ if (await assertWorkspaceRootAuthority(
33251
+ currentShadowRoot,
33252
+ currentShadowRootIdentity,
33253
+ "physical-copy current-root retirement preflight"
33254
+ ), await hasPhysicalCopyEntry(candidate) || (referencedShadowRoots = await collectDurablyReferencedShadowRoots(
33255
+ stateRoot,
33256
+ stateRootIdentity,
33257
+ maxStateMarkerBytes,
33258
+ new Set(byPath.keys()),
33259
+ afterQuotaReferenceTaskEntry,
33260
+ afterQuotaReferenceMarkerEntry,
33261
+ afterQuotaReferenceMarkerStat,
33262
+ !0,
33263
+ !0,
33264
+ !0
33265
+ ), referencedShadowRoots.has(candidate.path))) return roots;
33266
+ let retirementPostimage = roots.filter((root) => root.path !== currentShadowRoot);
33267
+ return await hasPhysicalCopyEntry(candidate) ? roots : (await afterQuotaRetirementTargetProof?.(currentShadowRoot), await assertWorkspaceRootAuthority(
33268
+ currentShadowRoot,
33269
+ currentShadowRootIdentity,
33270
+ "physical-copy current-root retirement commit"
33271
+ ), await anchoredAtomicWrite(
33272
+ registryPath,
33273
+ JSON.stringify({ version: 2, roots: retirementPostimage }),
33274
+ {
33275
+ expected,
33276
+ expectedParent: stateRootIdentity,
33277
+ mode: 384,
33278
+ maxTargetBytes: 1024 * 1024,
33279
+ failDirectorySync,
33280
+ publicationOwnerKey
33281
+ }
33282
+ ), retirementPostimage);
33283
+ }
33210
33284
  for (let candidate of byPath.values()) {
33211
33285
  if (candidate.path === currentShadowRoot) {
33212
33286
  retained.push(candidate);
@@ -33254,6 +33328,41 @@ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, cur
33254
33328
  }
33255
33329
  ), retained;
33256
33330
  }
33331
+ async function retireQuotaShadowRootIfUnused(stateRoot, stateRootIdentity, currentShadowRoot, currentShadowRootIdentity, publicationOwnerKey, maxStateMarkerBytes, afterQuotaReferenceTaskEntry, afterQuotaReferenceMarkerEntry, afterQuotaReferenceMarkerStat, failDirectorySync = !1, afterQuotaRetirementTargetProof) {
33332
+ await assertWorkspaceRootAuthority(
33333
+ stateRoot,
33334
+ stateRootIdentity,
33335
+ "physical-copy root retirement state root"
33336
+ ), await assertWorkspaceRootAuthority(
33337
+ currentShadowRoot,
33338
+ currentShadowRootIdentity,
33339
+ "physical-copy root retirement current root"
33340
+ );
33341
+ let quotaLockDir = path38.join(stateRoot, SHADOW_QUOTA_LOCK_DIR), quotaLockRootAuthority = await captureWorkspaceRootAuthority(quotaLockDir);
33342
+ if (path38.dirname(quotaLockRootAuthority.canonicalPath) !== stateRootIdentity.canonicalPath || path38.basename(quotaLockRootAuthority.canonicalPath) !== SHADOW_QUOTA_LOCK_DIR)
33343
+ throw new Error("physical-copy quota-lock directory escaped its state-root authority");
33344
+ return withAnchoredExclusiveLock(
33345
+ path38.join(quotaLockRootAuthority.canonicalPath, SHADOW_QUOTA_LOCK_FILE),
33346
+ async () => !(await withTransientDirectoryEnumerationRetry(() => registerAndListQuotaShadowRoots(
33347
+ stateRoot,
33348
+ stateRootIdentity,
33349
+ currentShadowRoot,
33350
+ currentShadowRootIdentity,
33351
+ publicationOwnerKey,
33352
+ maxStateMarkerBytes,
33353
+ afterQuotaReferenceTaskEntry,
33354
+ afterQuotaReferenceMarkerEntry,
33355
+ afterQuotaReferenceMarkerStat,
33356
+ failDirectorySync,
33357
+ "retire-current-if-unused",
33358
+ afterQuotaRetirementTargetProof
33359
+ ), {
33360
+ maxAttempts: 8,
33361
+ retryDelaysMs: [10, 25, 50, 100, 200, 400, 800]
33362
+ })).some((candidate) => candidate.path === currentShadowRoot),
33363
+ { expectedParent: quotaLockRootAuthority }
33364
+ );
33365
+ }
33257
33366
  async function readCleanupBlockAnchor(shadowDir, expected) {
33258
33367
  try {
33259
33368
  if (shadowDir !== expected.snapshotRootAuthority.canonicalPath)
@@ -33792,6 +33901,24 @@ var WorkspaceShadow = class _WorkspaceShadow {
33792
33901
  stateRootAuthority,
33793
33902
  resolveStateMarkerByteLimit(env)
33794
33903
  ).catch(() => {
33904
+ }), await registerAndListQuotaShadowRoots(
33905
+ stateRoot,
33906
+ stateRootIdentity,
33907
+ shadowRoot,
33908
+ shadowRootIdentity,
33909
+ publicationOwnerKey,
33910
+ resolveStateMarkerByteLimit(env),
33911
+ env.afterQuotaReferenceTaskEntry,
33912
+ env.afterQuotaReferenceMarkerEntry,
33913
+ env.afterQuotaReferenceMarkerStat,
33914
+ env.failQuotaRegistryDirectorySync === !0,
33915
+ "retire-current-if-unused"
33916
+ ).catch((retirementErr) => {
33917
+ logger.warn("[WorkspaceShadow] failed-create root retirement deferred", {
33918
+ taskId,
33919
+ shadowRoot,
33920
+ err: retirementErr instanceof Error ? retirementErr.message : String(retirementErr)
33921
+ });
33795
33922
  }), err;
33796
33923
  }
33797
33924
  },
@@ -34300,12 +34427,15 @@ var WorkspaceShadow = class _WorkspaceShadow {
34300
34427
  this.snapshotRootAuthority
34301
34428
  );
34302
34429
  if (displaced && displaced.canonicalPath !== this.shadowDir) {
34303
- await this.discardDisplacedSnapshot(opts);
34430
+ await this.discardDisplacedSnapshot(opts), await this.retirePhysicalCopyRootIfUnused();
34304
34431
  return;
34305
34432
  }
34306
34433
  if (snapshotPathError.code === "ENOENT") {
34307
- if (await this.exactStateResourcesAreRetired()) return;
34308
- await this.discardDisplacedSnapshot(opts);
34434
+ if (await this.exactStateResourcesAreRetired()) {
34435
+ await this.retirePhysicalCopyRootIfUnused();
34436
+ return;
34437
+ }
34438
+ await this.discardDisplacedSnapshot(opts), await this.retirePhysicalCopyRootIfUnused();
34309
34439
  return;
34310
34440
  }
34311
34441
  if (snapshotPathError.code !== "ENOENT")
@@ -34341,7 +34471,10 @@ var WorkspaceShadow = class _WorkspaceShadow {
34341
34471
  opts.applyingAuthorityRetired === !0,
34342
34472
  snapshotAuthority
34343
34473
  );
34344
- if (!disposalSnapshot) return;
34474
+ if (!disposalSnapshot) {
34475
+ await this.retirePhysicalCopyRootIfUnused();
34476
+ return;
34477
+ }
34345
34478
  let stateFileIdentity = disposalSnapshot.stateFileIdentity, exposureFile = path39.join(
34346
34479
  this.stateDir,
34347
34480
  exposureRetentionFileNameForShadow(this.shadowDir)
@@ -34453,6 +34586,35 @@ var WorkspaceShadow = class _WorkspaceShadow {
34453
34586
  expectedParent: disposalSnapshot.stateRootAuthority
34454
34587
  }).catch(() => {
34455
34588
  })), treeRemoved && releasePhysicalCopyBytes(this.physicalCopyScope, this.shadowDir), removeError) throw removeError;
34589
+ await this.retirePhysicalCopyRootIfUnused();
34590
+ }
34591
+ async retirePhysicalCopyRootIfUnused() {
34592
+ let shadowRoot = path39.dirname(this.shadowDir);
34593
+ try {
34594
+ let shadowRootAuthority = await captureWorkspaceRootAuthority(shadowRoot);
34595
+ await retireQuotaShadowRootIfUnused(
34596
+ this.stateRootAuthority.canonicalPath,
34597
+ this.stateRootAuthority,
34598
+ shadowRootAuthority.canonicalPath,
34599
+ shadowRootAuthority,
34600
+ workspacePublicationAuthorityOwnerKey(
34601
+ this.stateRootAuthority.canonicalPath,
34602
+ this.taskId
34603
+ ),
34604
+ this.maxStateMarkerBytes,
34605
+ this.env.afterQuotaReferenceTaskEntry,
34606
+ this.env.afterQuotaReferenceMarkerEntry,
34607
+ this.env.afterQuotaReferenceMarkerStat,
34608
+ this.env.failQuotaRegistryDirectorySync === !0,
34609
+ this.env.afterQuotaRetirementTargetProof
34610
+ );
34611
+ } catch (err) {
34612
+ logger.warn("[WorkspaceShadow] physical-copy root retirement deferred", {
34613
+ taskId: this.taskId,
34614
+ shadowRoot,
34615
+ err: err instanceof Error ? err.message : String(err)
34616
+ });
34617
+ }
34456
34618
  }
34457
34619
  retainExposureWriteAuthority(fileAuthority, stateDirAuthority) {
34458
34620
  if (!sameWorkspaceRootAuthority(stateDirAuthority, this.stateDirAuthority))
@@ -53232,12 +53394,17 @@ var QuorumLoop = class _QuorumLoop {
53232
53394
  err: err.message
53233
53395
  });
53234
53396
  let reason = classifyImplementorRoundFailure(err);
53235
- this.surfaceHalt(`The task could not proceed \u2014 ${reason}.`), this.emitProgress(
53236
- { phase: "round_failed", round: args.roundNumber, reason, taskId: args.taskId },
53237
- originEpoch
53238
- );
53397
+ this.surfaceHalt(`The task could not proceed \u2014 ${reason}.`);
53239
53398
  let reviseFeedbackId = args.reviseFeedbackId, preserveResetForRetry = submissionStarted && args.reviewScopeReset === !0 && reviseFeedbackId !== void 0 && this.reviewScopeResetTasks.has(args.taskId);
53240
- preserveResetForRetry && this.seenReviseFeedbackIds.delete(reviseFeedbackId), await this.discardShadow(args.taskId, void 0, {
53399
+ this.emitProgress(
53400
+ {
53401
+ phase: "round_failed",
53402
+ round: args.roundNumber,
53403
+ reason,
53404
+ ...preserveResetForRetry ? {} : { taskId: args.taskId }
53405
+ },
53406
+ originEpoch
53407
+ ), preserveResetForRetry && this.seenReviseFeedbackIds.delete(reviseFeedbackId), await this.discardShadow(args.taskId, void 0, {
53241
53408
  preserveReviseContext: preserveResetForRetry
53242
53409
  });
53243
53410
  } finally {
@@ -8,10 +8,9 @@ export declare const CONVERSATION_BUFFER_MAX = 500;
8
8
  export declare function reducer(state: OrchestrationState, action: OrchestrationAction): OrchestrationState;
9
9
  /**
10
10
  * P10 E3 r6/r8 — "is a single-implementor task actually running?" from the
11
- * TRUTHFUL `sessionTasks` lifecycle (the task-end closers terminalize it;
12
- * `runningTasks` never terminalizes in production and is kept ONLY for the
13
- * decision-spawned-a-task size heuristic). Shared by the `/status` running
14
- * line, `deriveCurrentTaskState` (the planner packet), and the reviewer-line
15
- * SET guard below.
11
+ * TRUTHFUL `sessionTasks` lifecycle. Shared by the `/status` running line,
12
+ * `deriveCurrentTaskState` (the planner packet), and the reviewer-line SET
13
+ * guard below. `runningTasks` is terminalized in parallel for its independent
14
+ * task-start size heuristic.
16
15
  */
17
16
  export declare function hasRunningSingleTask(state: OrchestrationState): boolean;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.16",
3
+ "version": "2.0.18",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -332,7 +332,7 @@ endif
332
332
 
333
333
  quiet_cmd_regen_makefile = ACTION Regenerating $@
334
334
  cmd_regen_makefile = cd $(srcdir); /opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/hendryyeh/Library/Caches/node-gyp/24.4.0" "-Dnode_gyp_dir=/opt/homebrew/lib/node_modules/npm/node_modules/node-gyp" "-Dnode_lib_file=/Users/hendryyeh/Library/Caches/node-gyp/24.4.0/<(target_arch)/node.lib" "-Dmodule_root_dir=/Users/hendryyeh/Workspace/CodeVibe/codevibe-codex-plugin/node_modules/fs-ext" "-Dnode_engine=v8" "--depth=." "-Goutput_dir=." "--generator-output=build" -I/Users/hendryyeh/Workspace/CodeVibe/codevibe-codex-plugin/node_modules/fs-ext/build/config.gypi -I/opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/hendryyeh/Library/Caches/node-gyp/24.4.0/include/node/common.gypi "--toplevel-dir=." binding.gyp
335
- Makefile: $(srcdir)/binding.gyp $(srcdir)/../../../../../Library/Caches/node-gyp/24.4.0/include/node/common.gypi $(srcdir)/../../../../../../../opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi
335
+ Makefile: $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../Library/Caches/node-gyp/24.4.0/include/node/common.gypi $(srcdir)/../../../../../../../opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi
336
336
  $(call do_cmd,regen_makefile)
337
337
 
338
338
  # "all" is a concatenation of the "all" targets from all the included
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-codex-plugin",
3
- "version": "2.0.22",
3
+ "version": "2.0.24",
4
4
  "description": "Control OpenAI Codex CLI from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
5
5
  "main": "dist/server.js",
6
6
  "codevibe": {
@@ -47,7 +47,7 @@
47
47
  "node": ">=22.0.0"
48
48
  },
49
49
  "dependencies": {
50
- "@quantiya/codevibe-core": "2.0.16",
50
+ "@quantiya/codevibe-core": "2.0.18",
51
51
  "@quantiya/quorum-core": "^1.0.1",
52
52
  "chokidar": "^4.0.0",
53
53
  "dotenv": "^16.6.1",