@quantiya/codevibe-claude-plugin 2.0.19 → 2.0.20

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;
@@ -33076,8 +33076,13 @@ function isSameRegisteredRootAuthority(prior, current) {
33076
33076
  function isSameRootAfterDeviceReincarnation(prior, current) {
33077
33077
  return prior.dev !== current.dev && prior.ino === current.ino && prior.version === current.version && prior.canonicalPath === current.canonicalPath && prior.birthtimeNs === current.birthtimeNs;
33078
33078
  }
33079
- async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority, maxStateMarkerBytes, registeredShadowRoots, afterTaskEntry, afterMarkerEntry, afterMarkerStat) {
33080
- let referenced = /* @__PURE__ */ new Set(), budget = createPathBudget(), taskEntries = await readDirectoryBounded(
33079
+ async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority, maxStateMarkerBytes, registeredShadowRoots, afterTaskEntry, afterMarkerEntry, afterMarkerStat, allowUnrecognizedRegularFiles = !1, allowUnregisteredReferences = !1, allowConcurrentSiblingTeardown = !1) {
33080
+ let retryConcurrentSiblingTeardown = (error, target) => {
33081
+ 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");
33082
+ throw allowConcurrentSiblingTeardown && isSiblingChurn ? new Error(
33083
+ `bounded-directory target changed during enumeration: ${target}; ${message}`
33084
+ ) : error;
33085
+ }, referenced = /* @__PURE__ */ new Set(), budget = createPathBudget(), taskEntries = await readDirectoryBounded(
33081
33086
  stateRoot,
33082
33087
  budget,
33083
33088
  "physical-copy root reference enumeration",
@@ -33090,15 +33095,24 @@ async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority
33090
33095
  );
33091
33096
  for (let taskEntry of taskEntries) {
33092
33097
  if (isStateRootInfrastructureDirectory(taskEntry.name) || taskEntry.name === SHADOW_ROOT_REGISTRY_FILE) continue;
33093
- if (!taskEntry.isDirectory() || taskEntry.isSymbolicLink())
33098
+ if (!taskEntry.isDirectory() || taskEntry.isSymbolicLink()) {
33099
+ if (allowUnrecognizedRegularFiles && taskEntry.isFile() && !taskEntry.isSymbolicLink()) continue;
33094
33100
  throw new Error("physical-copy root reference state entry changed type");
33101
+ }
33095
33102
  let taskId = taskEntry.name, stateDir = path38.join(stateRoot, taskId), enumeratedStateDir = boundedDirectoryStat(taskEntry);
33096
33103
  if (!enumeratedStateDir)
33097
33104
  throw new Error("physical-copy root reference state entry lacks authority");
33098
33105
  await afterTaskEntry?.(stateDir);
33099
- let stateDirAuthority = await captureWorkspaceRootAuthority(stateDir);
33106
+ let stateDirAuthority = await captureWorkspaceRootAuthority(stateDir).catch(
33107
+ (error) => retryConcurrentSiblingTeardown(
33108
+ error,
33109
+ `sibling state directory ${taskId}`
33110
+ )
33111
+ );
33100
33112
  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");
33113
+ throw allowConcurrentSiblingTeardown ? new Error(
33114
+ `bounded-directory target changed during enumeration: sibling state directory ${taskId}`
33115
+ ) : new Error("physical-copy root reference state directory changed after enumeration");
33102
33116
  let markerEntries = await readDirectoryBounded(
33103
33117
  stateDir,
33104
33118
  budget,
@@ -33110,7 +33124,10 @@ async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority
33110
33124
  rootAuthority: stateRootAuthority,
33111
33125
  relativeDirectory: taskId
33112
33126
  }
33113
- );
33127
+ ).catch((error) => retryConcurrentSiblingTeardown(
33128
+ error,
33129
+ `sibling state contents ${taskId}`
33130
+ ));
33114
33131
  for (let markerEntry of markerEntries) {
33115
33132
  let isStateMarker = SHADOW_STATE_FILE_RE.test(markerEntry.name), isExposureRetention = SHADOW_EXPOSURE_RETENTION_FILE_RE.test(markerEntry.name);
33116
33133
  if (!isStateMarker && !isExposureRetention) continue;
@@ -33120,38 +33137,55 @@ async function collectDurablyReferencedShadowRoots(stateRoot, stateRootAuthority
33120
33137
  if (!enumeratedMarker)
33121
33138
  throw new Error("physical-copy root reference marker lacks authority");
33122
33139
  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");
33140
+ let read;
33141
+ try {
33142
+ read = await anchoredReadFileWithinRoot(stateDir, markerEntry.name, {
33143
+ maxBytes: maxStateMarkerBytes,
33144
+ expectedRoot: stateDirAuthority,
33145
+ expectedFile: enumeratedMarker,
33146
+ requireSingleLink: !0,
33147
+ afterStat: () => afterMarkerStat?.(stateFile)
33148
+ });
33149
+ } catch (error) {
33150
+ retryConcurrentSiblingTeardown(
33151
+ error,
33152
+ `sibling marker ${taskId}/${markerEntry.name}`
33153
+ );
33154
+ }
33155
+ if (!read)
33156
+ throw allowConcurrentSiblingTeardown ? new Error(
33157
+ `bounded-directory target changed during enumeration: sibling marker ${taskId}/${markerEntry.name}`
33158
+ ) : new Error("physical-copy root reference marker disappeared");
33131
33159
  let decoded = read.bytes.toString("utf8");
33132
33160
  if (!Buffer.from(decoded, "utf8").equals(read.bytes))
33133
33161
  throw new Error("physical-copy root reference marker is not strict UTF-8");
33134
33162
  let value = JSON.parse(decoded);
33135
33163
  if (isStateMarker) {
33136
33164
  let marker = validateMarkerShape(value, taskId), markerRoot2 = path38.dirname(marker.shadowDir);
33137
- if (!registeredShadowRoots.has(markerRoot2))
33165
+ if (validateStateMarkerPlacement(marker, stateFile, stateDir, markerRoot2, stateRoot), !registeredShadowRoots.has(markerRoot2)) {
33166
+ if (allowUnregisteredReferences) continue;
33138
33167
  throw new Error("physical-copy root reference marker names an unregistered root");
33139
- validateStateMarkerPlacement(marker, stateFile, stateDir, markerRoot2, stateRoot), referenced.add(markerRoot2);
33168
+ }
33169
+ referenced.add(markerRoot2);
33140
33170
  continue;
33141
33171
  }
33142
33172
  let preliminary = value;
33143
33173
  if (typeof preliminary.finalShadowDir != "string")
33144
33174
  throw new Error("physical-copy root exposure marker lacks a shadow path");
33145
33175
  let markerRoot = path38.dirname(preliminary.finalShadowDir);
33146
- if (!registeredShadowRoots.has(markerRoot))
33176
+ if (assertExposureRetentionMarker(value, taskId, stateFile, markerRoot, stateRoot), !registeredShadowRoots.has(markerRoot)) {
33177
+ if (allowUnregisteredReferences) continue;
33147
33178
  throw new Error("physical-copy root exposure marker names an unregistered root");
33148
- assertExposureRetentionMarker(value, taskId, stateFile, markerRoot, stateRoot), referenced.add(markerRoot);
33179
+ }
33180
+ referenced.add(markerRoot);
33149
33181
  }
33150
33182
  }
33151
33183
  return referenced;
33152
33184
  }
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 = [];
33185
+ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, currentShadowRoot, currentShadowRootIdentity, publicationOwnerKey, maxStateMarkerBytes, afterQuotaReferenceTaskEntry, afterQuotaReferenceMarkerEntry, afterQuotaReferenceMarkerStat, failDirectorySync = !1, mode = "register-current", afterQuotaRetirementTargetProof) {
33186
+ let registryPath = path38.join(stateRoot, SHADOW_ROOT_REGISTRY_FILE), expected = await captureAnchoredWritePrecondition(registryPath, 1024 * 1024);
33187
+ if (mode === "retire-current-if-unused" && expected.kind === "absent") return [];
33188
+ let roots = [];
33155
33189
  if (expected.kind === "existing") {
33156
33190
  let read = await anchoredReadFileWithinRoot(stateRoot, SHADOW_ROOT_REGISTRY_FILE, {
33157
33191
  maxBytes: 1048576
@@ -33171,13 +33205,16 @@ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, cur
33171
33205
  if (consumeMetadataPath(registryBudget, root.path, "physical-copy root registry"), byPath.has(root.path)) throw new Error("physical-copy root registry contains duplicates");
33172
33206
  byPath.set(root.path, root);
33173
33207
  }
33174
- let priorCurrent = byPath.get(currentShadowRoot), reincarnatedDevice = null;
33208
+ let priorCurrent = byPath.get(currentShadowRoot);
33209
+ if (mode === "retire-current-if-unused" && !priorCurrent)
33210
+ return roots;
33211
+ let reincarnatedDevice = null;
33175
33212
  if (priorCurrent && !isSameRegisteredRootAuthority(priorCurrent, currentShadowRootIdentity))
33176
33213
  if (isSameRootAfterDeviceReincarnation(priorCurrent, currentShadowRootIdentity))
33177
33214
  reincarnatedDevice = priorCurrent.dev;
33178
33215
  else
33179
33216
  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");
33217
+ 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
33218
  let retained = [], scanBudget = createPathBudget(), referencedShadowRoots = null, hasPhysicalCopyEntry = async (candidate) => {
33182
33219
  let liveRoot;
33183
33220
  try {
@@ -33192,7 +33229,7 @@ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, cur
33192
33229
  "physical-copy root retirement enumeration",
33193
33230
  candidate.path,
33194
33231
  { 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)));
33232
+ )).some((entry) => SHADOW_DIR_RE.test(entry.name) || SHADOW_STAGING_DIR_RE.test(entry.name) || SHADOW_TREE_TOMBSTONE_RE.test(entry.name));
33196
33233
  return await assertWorkspaceRootAuthority(
33197
33234
  liveRoot.canonicalPath,
33198
33235
  liveRoot,
@@ -33207,6 +33244,42 @@ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, cur
33207
33244
  afterQuotaReferenceMarkerEntry,
33208
33245
  afterQuotaReferenceMarkerStat
33209
33246
  ), !referencedShadowRoots.has(candidate.path));
33247
+ if (mode === "retire-current-if-unused") {
33248
+ let candidate = priorCurrent;
33249
+ if (await assertWorkspaceRootAuthority(
33250
+ currentShadowRoot,
33251
+ currentShadowRootIdentity,
33252
+ "physical-copy current-root retirement preflight"
33253
+ ), await hasPhysicalCopyEntry(candidate) || (referencedShadowRoots = await collectDurablyReferencedShadowRoots(
33254
+ stateRoot,
33255
+ stateRootIdentity,
33256
+ maxStateMarkerBytes,
33257
+ new Set(byPath.keys()),
33258
+ afterQuotaReferenceTaskEntry,
33259
+ afterQuotaReferenceMarkerEntry,
33260
+ afterQuotaReferenceMarkerStat,
33261
+ !0,
33262
+ !0,
33263
+ !0
33264
+ ), referencedShadowRoots.has(candidate.path))) return roots;
33265
+ let retirementPostimage = roots.filter((root) => root.path !== currentShadowRoot);
33266
+ return await hasPhysicalCopyEntry(candidate) ? roots : (await afterQuotaRetirementTargetProof?.(currentShadowRoot), await assertWorkspaceRootAuthority(
33267
+ currentShadowRoot,
33268
+ currentShadowRootIdentity,
33269
+ "physical-copy current-root retirement commit"
33270
+ ), await anchoredAtomicWrite(
33271
+ registryPath,
33272
+ JSON.stringify({ version: 2, roots: retirementPostimage }),
33273
+ {
33274
+ expected,
33275
+ expectedParent: stateRootIdentity,
33276
+ mode: 384,
33277
+ maxTargetBytes: 1024 * 1024,
33278
+ failDirectorySync,
33279
+ publicationOwnerKey
33280
+ }
33281
+ ), retirementPostimage);
33282
+ }
33210
33283
  for (let candidate of byPath.values()) {
33211
33284
  if (candidate.path === currentShadowRoot) {
33212
33285
  retained.push(candidate);
@@ -33254,6 +33327,41 @@ async function registerAndListQuotaShadowRoots(stateRoot, stateRootIdentity, cur
33254
33327
  }
33255
33328
  ), retained;
33256
33329
  }
33330
+ async function retireQuotaShadowRootIfUnused(stateRoot, stateRootIdentity, currentShadowRoot, currentShadowRootIdentity, publicationOwnerKey, maxStateMarkerBytes, afterQuotaReferenceTaskEntry, afterQuotaReferenceMarkerEntry, afterQuotaReferenceMarkerStat, failDirectorySync = !1, afterQuotaRetirementTargetProof) {
33331
+ await assertWorkspaceRootAuthority(
33332
+ stateRoot,
33333
+ stateRootIdentity,
33334
+ "physical-copy root retirement state root"
33335
+ ), await assertWorkspaceRootAuthority(
33336
+ currentShadowRoot,
33337
+ currentShadowRootIdentity,
33338
+ "physical-copy root retirement current root"
33339
+ );
33340
+ let quotaLockDir = path38.join(stateRoot, SHADOW_QUOTA_LOCK_DIR), quotaLockRootAuthority = await captureWorkspaceRootAuthority(quotaLockDir);
33341
+ if (path38.dirname(quotaLockRootAuthority.canonicalPath) !== stateRootIdentity.canonicalPath || path38.basename(quotaLockRootAuthority.canonicalPath) !== SHADOW_QUOTA_LOCK_DIR)
33342
+ throw new Error("physical-copy quota-lock directory escaped its state-root authority");
33343
+ return withAnchoredExclusiveLock(
33344
+ path38.join(quotaLockRootAuthority.canonicalPath, SHADOW_QUOTA_LOCK_FILE),
33345
+ async () => !(await withTransientDirectoryEnumerationRetry(() => registerAndListQuotaShadowRoots(
33346
+ stateRoot,
33347
+ stateRootIdentity,
33348
+ currentShadowRoot,
33349
+ currentShadowRootIdentity,
33350
+ publicationOwnerKey,
33351
+ maxStateMarkerBytes,
33352
+ afterQuotaReferenceTaskEntry,
33353
+ afterQuotaReferenceMarkerEntry,
33354
+ afterQuotaReferenceMarkerStat,
33355
+ failDirectorySync,
33356
+ "retire-current-if-unused",
33357
+ afterQuotaRetirementTargetProof
33358
+ ), {
33359
+ maxAttempts: 8,
33360
+ retryDelaysMs: [10, 25, 50, 100, 200, 400, 800]
33361
+ })).some((candidate) => candidate.path === currentShadowRoot),
33362
+ { expectedParent: quotaLockRootAuthority }
33363
+ );
33364
+ }
33257
33365
  async function readCleanupBlockAnchor(shadowDir, expected) {
33258
33366
  try {
33259
33367
  if (shadowDir !== expected.snapshotRootAuthority.canonicalPath)
@@ -33792,6 +33900,24 @@ var WorkspaceShadow = class _WorkspaceShadow {
33792
33900
  stateRootAuthority,
33793
33901
  resolveStateMarkerByteLimit(env)
33794
33902
  ).catch(() => {
33903
+ }), await registerAndListQuotaShadowRoots(
33904
+ stateRoot,
33905
+ stateRootIdentity,
33906
+ shadowRoot,
33907
+ shadowRootIdentity,
33908
+ publicationOwnerKey,
33909
+ resolveStateMarkerByteLimit(env),
33910
+ env.afterQuotaReferenceTaskEntry,
33911
+ env.afterQuotaReferenceMarkerEntry,
33912
+ env.afterQuotaReferenceMarkerStat,
33913
+ env.failQuotaRegistryDirectorySync === !0,
33914
+ "retire-current-if-unused"
33915
+ ).catch((retirementErr) => {
33916
+ logger.warn("[WorkspaceShadow] failed-create root retirement deferred", {
33917
+ taskId,
33918
+ shadowRoot,
33919
+ err: retirementErr instanceof Error ? retirementErr.message : String(retirementErr)
33920
+ });
33795
33921
  }), err;
33796
33922
  }
33797
33923
  },
@@ -34300,12 +34426,15 @@ var WorkspaceShadow = class _WorkspaceShadow {
34300
34426
  this.snapshotRootAuthority
34301
34427
  );
34302
34428
  if (displaced && displaced.canonicalPath !== this.shadowDir) {
34303
- await this.discardDisplacedSnapshot(opts);
34429
+ await this.discardDisplacedSnapshot(opts), await this.retirePhysicalCopyRootIfUnused();
34304
34430
  return;
34305
34431
  }
34306
34432
  if (snapshotPathError.code === "ENOENT") {
34307
- if (await this.exactStateResourcesAreRetired()) return;
34308
- await this.discardDisplacedSnapshot(opts);
34433
+ if (await this.exactStateResourcesAreRetired()) {
34434
+ await this.retirePhysicalCopyRootIfUnused();
34435
+ return;
34436
+ }
34437
+ await this.discardDisplacedSnapshot(opts), await this.retirePhysicalCopyRootIfUnused();
34309
34438
  return;
34310
34439
  }
34311
34440
  if (snapshotPathError.code !== "ENOENT")
@@ -34341,7 +34470,10 @@ var WorkspaceShadow = class _WorkspaceShadow {
34341
34470
  opts.applyingAuthorityRetired === !0,
34342
34471
  snapshotAuthority
34343
34472
  );
34344
- if (!disposalSnapshot) return;
34473
+ if (!disposalSnapshot) {
34474
+ await this.retirePhysicalCopyRootIfUnused();
34475
+ return;
34476
+ }
34345
34477
  let stateFileIdentity = disposalSnapshot.stateFileIdentity, exposureFile = path39.join(
34346
34478
  this.stateDir,
34347
34479
  exposureRetentionFileNameForShadow(this.shadowDir)
@@ -34453,6 +34585,35 @@ var WorkspaceShadow = class _WorkspaceShadow {
34453
34585
  expectedParent: disposalSnapshot.stateRootAuthority
34454
34586
  }).catch(() => {
34455
34587
  })), treeRemoved && releasePhysicalCopyBytes(this.physicalCopyScope, this.shadowDir), removeError) throw removeError;
34588
+ await this.retirePhysicalCopyRootIfUnused();
34589
+ }
34590
+ async retirePhysicalCopyRootIfUnused() {
34591
+ let shadowRoot = path39.dirname(this.shadowDir);
34592
+ try {
34593
+ let shadowRootAuthority = await captureWorkspaceRootAuthority(shadowRoot);
34594
+ await retireQuotaShadowRootIfUnused(
34595
+ this.stateRootAuthority.canonicalPath,
34596
+ this.stateRootAuthority,
34597
+ shadowRootAuthority.canonicalPath,
34598
+ shadowRootAuthority,
34599
+ workspacePublicationAuthorityOwnerKey(
34600
+ this.stateRootAuthority.canonicalPath,
34601
+ this.taskId
34602
+ ),
34603
+ this.maxStateMarkerBytes,
34604
+ this.env.afterQuotaReferenceTaskEntry,
34605
+ this.env.afterQuotaReferenceMarkerEntry,
34606
+ this.env.afterQuotaReferenceMarkerStat,
34607
+ this.env.failQuotaRegistryDirectorySync === !0,
34608
+ this.env.afterQuotaRetirementTargetProof
34609
+ );
34610
+ } catch (err) {
34611
+ logger.warn("[WorkspaceShadow] physical-copy root retirement deferred", {
34612
+ taskId: this.taskId,
34613
+ shadowRoot,
34614
+ err: err instanceof Error ? err.message : String(err)
34615
+ });
34616
+ }
34456
34617
  }
34457
34618
  retainExposureWriteAuthority(fileAuthority, stateDirAuthority) {
34458
34619
  if (!sameWorkspaceRootAuthority(stateDirAuthority, this.stateDirAuthority))
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.16",
3
+ "version": "2.0.17",
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-claude-plugin",
3
- "version": "2.0.19",
3
+ "version": "2.0.20",
4
4
  "description": "Control Claude Code 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.17",
51
51
  "@quantiya/quorum-core": "^1.0.1",
52
52
  "dotenv": "^16.6.1",
53
53
  "express": "^5.1.0",