@cmmd-center/forge 0.10.7 → 0.10.9

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/bin.mjs CHANGED
@@ -16520,7 +16520,7 @@ function makeNetServiceShape(createServer = Net.createServer) {
16520
16520
  }
16521
16521
  //#endregion
16522
16522
  //#region ../../packages/shared/src/releaseInfo.generated.ts
16523
- const FORGE_RELEASE_VERSION = "0.10.4";
16523
+ const FORGE_RELEASE_VERSION = "0.10.6";
16524
16524
  //#endregion
16525
16525
  //#region ../../packages/shared/src/hostProcess.ts
16526
16526
  /**
@@ -65121,7 +65121,7 @@ function normalizeNumberish(value) {
65121
65121
  }
65122
65122
  //#endregion
65123
65123
  //#region package.json
65124
- var version$1 = "0.10.7";
65124
+ var version$1 = "0.10.9";
65125
65125
  //#endregion
65126
65126
  //#region src/sentry.ts
65127
65127
  const SERVER_APP_NAME = "forge-server";
@@ -93114,6 +93114,31 @@ function lifecycleIntentCommandId(runtimeId, threadId, requestedAt) {
93114
93114
  return CommandId.make("lifecycle-intent:" + stableReplicaDigest(runtimeId, threadId, requestedAt));
93115
93115
  }
93116
93116
  //#endregion
93117
+ //#region src/runtimeReplication/replicaHydrationProjects.ts
93118
+ function activePathMatchedProjects(projects, index, summary) {
93119
+ return projects.filter((project) => project.deletedAt === null && (project.id === summary.projectId || index.runtime.workspaceRoot !== null && project.workspaceRoot === index.runtime.workspaceRoot));
93120
+ }
93121
+ const resolveRepositoryMatchedProjects = fn$1("resolveRepositoryMatchedProjects")(function* (projects, replicaRepositoryFullName, dependencies) {
93122
+ if (replicaRepositoryFullName === null) return [];
93123
+ return yield* filter$1(projects.filter((project) => project.deletedAt === null), (project) => dependencies.resolveProjectRepositoryFullName(project.workspaceRoot).pipe(map$3((repositoryFullName) => repositoryFullName?.toLowerCase() === replicaRepositoryFullName)), { concurrency: 1 });
93124
+ });
93125
+ const resolveLocalReplicaProjects = fn$1("resolveLocalReplicaProjects")(function* (projects, index, summary, dependencies) {
93126
+ const pathMatches = activePathMatchedProjects(projects, index, summary);
93127
+ if (pathMatches.length > 0) return {
93128
+ projects: pathMatches,
93129
+ repositoryRemapped: false
93130
+ };
93131
+ return {
93132
+ projects: yield* resolveRepositoryMatchedProjects(projects, index.runtime.githubRepoFullName?.toLowerCase() ?? null, dependencies),
93133
+ repositoryRemapped: true
93134
+ };
93135
+ });
93136
+ function replicaWorkspaceMatchesLocalProject(input) {
93137
+ if (input.detail.runtime.workspaceRoot === input.localProject.workspaceRoot) return true;
93138
+ const localRepository = input.localProjectRepositoryFullName?.toLowerCase() ?? null;
93139
+ return localRepository !== null && input.detail.runtime.githubRepoFullName?.toLowerCase() === localRepository && input.detail.project.githubRepoFullName?.toLowerCase() === localRepository;
93140
+ }
93141
+ //#endregion
93117
93142
  //#region src/runtimeReplication/protocol.ts
93118
93143
  const EMPTY_RUNTIME_THREAD_HEAD_HASH = "sha256:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU";
93119
93144
  const REPLICA_MESSAGE_ID_PREFIX = "replica-source-v1:";
@@ -93308,25 +93333,6 @@ function replicaSummaryMatchesDetail(summary, detail) {
93308
93333
  [summary.lastActivityAt, detail.thread.lastActivityAt]
93309
93334
  ].every(([summaryValue, detailValue]) => summaryValue === detailValue);
93310
93335
  }
93311
- function replicaSummaryPayload(summary) {
93312
- return {
93313
- conversationId: summary.conversationId,
93314
- project: {
93315
- projectId: summary.projectId,
93316
- title: summary.projectTitle,
93317
- githubRepoFullName: summary.projectGithubRepoFullName,
93318
- branch: summary.projectBranch
93319
- },
93320
- thread: {
93321
- threadId: summary.threadId,
93322
- title: summary.title,
93323
- status: summary.status,
93324
- model: summary.model,
93325
- branch: summary.branch,
93326
- lastActivityAt: summary.lastActivityAt
93327
- }
93328
- };
93329
- }
93330
93336
  function hasValidReplicaGeneration(runtimeId, threadId, generationId, threadStatus, sourceEvents) {
93331
93337
  const streamKey = "thread:" + threadId;
93332
93338
  const base = runtimeThreadGenerationId(runtimeId, streamKey);
@@ -93467,30 +93473,11 @@ function threadDates(events, fallback) {
93467
93473
  updatedAt: events.at(-1).occurredAt
93468
93474
  };
93469
93475
  }
93470
- function replicaWorkspaceMatchesLocalProject(input) {
93471
- if (input.detail.runtime.workspaceRoot === input.localProject.workspaceRoot) return true;
93472
- const localRepository = input.localProjectRepositoryFullName?.toLowerCase() ?? null;
93473
- return localRepository !== null && input.detail.runtime.githubRepoFullName?.toLowerCase() === localRepository && input.detail.project.githubRepoFullName?.toLowerCase() === localRepository;
93474
- }
93475
93476
  function replicaToOrchestrationThread(input) {
93476
- const index = decodeReplicaThreadIndex({
93477
- data: {
93478
- runtime: input.indexRuntimePayload,
93479
- reachability: "unknown",
93480
- threads: [input.summaryPayload],
93481
- nextCursor: null
93482
- },
93483
- meta: {
93484
- domain: "runtimeThreadIndex",
93485
- version: "1.0",
93486
- timestamp: input.hydratedAt
93487
- }
93488
- });
93477
+ const { indexRuntime, summary } = input;
93489
93478
  const detail = decodeReplicaThreadDetail(input.replicaPayload);
93490
- if (index === null) return null;
93491
- const summary = index.threads[0];
93492
93479
  const sourceEvents = detail?.events.map(replicaSourceEvent) ?? [];
93493
- if (detail === null || summary === void 0 || index.runtime.id !== input.expectedRuntimeId || detail.runtime.id !== input.expectedRuntimeId || !replicaRuntimeMatches(index.runtime, detail.runtime) || !replicaSummaryMatchesDetail(summary, detail) || input.localProject.deletedAt !== null || input.localProject.defaultModelSelection === null || detail.runtime.workspaceRoot === null || !replicaWorkspaceMatchesLocalProject({
93480
+ if (detail === null || indexRuntime.id !== input.expectedRuntimeId || detail.runtime.id !== input.expectedRuntimeId || !replicaRuntimeMatches(indexRuntime, detail.runtime) || !replicaSummaryMatchesDetail(summary, detail) || input.localProject.deletedAt !== null || input.localProject.defaultModelSelection === null || detail.runtime.workspaceRoot === null || !replicaWorkspaceMatchesLocalProject({
93494
93481
  detail,
93495
93482
  localProject: input.localProject,
93496
93483
  localProjectRepositoryFullName: input.localProjectRepositoryFullName
@@ -93545,24 +93532,6 @@ function replicaHydrationFailure(detail, cause) {
93545
93532
  //#endregion
93546
93533
  //#region src/runtimeReplication/replicaHydration.ts
93547
93534
  const REPLICA_INDEX_PAGE_SIZE$1 = 100;
93548
- function activePathMatchedProjects(state, index, summary) {
93549
- return state.initialModel.projects.filter((project) => project.deletedAt === null && (project.id === summary.projectId || index.runtime.workspaceRoot !== null && project.workspaceRoot === index.runtime.workspaceRoot));
93550
- }
93551
- const resolveRepositoryMatchedProjects = fn$1("resolveRepositoryMatchedProjects")(function* (state, replicaRepositoryFullName, dependencies) {
93552
- if (replicaRepositoryFullName === null) return [];
93553
- return yield* filter$1(state.initialModel.projects.filter((project) => project.deletedAt === null), (project) => dependencies.resolveProjectRepositoryFullName(project.workspaceRoot).pipe(map$3((repositoryFullName) => repositoryFullName?.toLowerCase() === replicaRepositoryFullName)), { concurrency: 1 });
93554
- });
93555
- const resolveLocalReplicaProjects = fn$1("resolveLocalReplicaProjects")(function* (state, index, summary, dependencies) {
93556
- const pathMatches = activePathMatchedProjects(state, index, summary);
93557
- if (pathMatches.length > 0) return {
93558
- projects: pathMatches,
93559
- repositoryRemapped: false
93560
- };
93561
- return {
93562
- projects: yield* resolveRepositoryMatchedProjects(state, index.runtime.githubRepoFullName?.toLowerCase() ?? null, dependencies),
93563
- repositoryRemapped: true
93564
- };
93565
- });
93566
93535
  const readValidatedIndex = fn$1("readValidatedReplicaIndex")(function* (expectedRuntimeId, cursor, dependencies) {
93567
93536
  const rawIndex = yield* dependencies.readIndex({
93568
93537
  limit: REPLICA_INDEX_PAGE_SIZE$1,
@@ -93588,7 +93557,7 @@ const prepareReplicaSummary = fn$1("prepareReplicaSummary")(function* (expectedR
93588
93557
  state.skippedQuarantined += 1;
93589
93558
  return;
93590
93559
  }
93591
- const localResolution = yield* resolveLocalReplicaProjects(state, index, summary, dependencies);
93560
+ const localResolution = yield* resolveLocalReplicaProjects(state.initialModel.projects, index, summary, dependencies);
93592
93561
  const localProjects = localResolution.projects;
93593
93562
  if (localProjects.length !== 1) return yield* replicaHydrationFailure("replica project '" + summary.projectId + "' does not resolve to one active workspace");
93594
93563
  const detail = yield* dependencies.readThread({ threadId: summary.threadId });
@@ -93599,8 +93568,8 @@ const prepareReplicaSummary = fn$1("prepareReplicaSummary")(function* (expectedR
93599
93568
  localProject: localProjects[0],
93600
93569
  localProjectRepositoryFullName: localResolution.repositoryRemapped ? index.runtime.githubRepoFullName : null,
93601
93570
  replicaPayload: detail,
93602
- indexRuntimePayload: index.runtime,
93603
- summaryPayload: replicaSummaryPayload(summary)
93571
+ indexRuntime: index.runtime,
93572
+ summary
93604
93573
  });
93605
93574
  if (candidate === null) return yield* replicaHydrationFailure("thread '" + summary.threadId + "' failed identity or generation checks");
93606
93575
  state.prepared.push({
@@ -99472,6 +99441,316 @@ function claudeWriteToken(env = process.env) {
99472
99441
  return accessor.read(env);
99473
99442
  }
99474
99443
  //#endregion
99444
+ //#region src/egress/providerDeliveryReceipt.ts
99445
+ const PROVIDER_ACCOUNT_IDENTITY$2 = /^pai_v1_[A-Za-z0-9_-]{43}$/;
99446
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
99447
+ const RFC3339$1 = /^(\d{4})-(\d{2})-(\d{2})T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
99448
+ const RECEIPT_KEYS = new Set([
99449
+ "receiptId",
99450
+ "runtimeId",
99451
+ "machineId",
99452
+ "credentialEpoch",
99453
+ "identity",
99454
+ "issuedAt",
99455
+ "expiresAt"
99456
+ ]);
99457
+ const BINDING_KEYS = new Set([
99458
+ "runtimeId",
99459
+ "machineId",
99460
+ "credentialEpoch",
99461
+ "identity"
99462
+ ]);
99463
+ const CODEX_IDENTITY_KEYS = new Set([
99464
+ "kind",
99465
+ "provider",
99466
+ "providerAccountIdentity"
99467
+ ]);
99468
+ const CLAUDE_IDENTITY_KEYS = new Set([
99469
+ "kind",
99470
+ "provider",
99471
+ "credentialGenerationId"
99472
+ ]);
99473
+ function isRecord$13(value) {
99474
+ return typeof value === "object" && value !== null && !Array.isArray(value);
99475
+ }
99476
+ function isStrictRfc3339DateTime(value) {
99477
+ if (typeof value !== "string") return false;
99478
+ const match = RFC3339$1.exec(value);
99479
+ if (!match || !Number.isFinite(Date.parse(value))) return false;
99480
+ const year = Number(match[1]);
99481
+ const month = Number(match[2]);
99482
+ const day = Number(match[3]);
99483
+ return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth$1(year, month);
99484
+ }
99485
+ function daysInMonth$1(year, month) {
99486
+ if (month === 2) return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0 ? 29 : 28;
99487
+ return [
99488
+ 4,
99489
+ 6,
99490
+ 9,
99491
+ 11
99492
+ ].includes(month) ? 30 : 31;
99493
+ }
99494
+ function hasExactKeys$2(value, keys) {
99495
+ return Object.keys(value).every((key) => keys.has(key)) && Object.keys(value).length === keys.size;
99496
+ }
99497
+ function parseDeliveryIdentity(value, provider) {
99498
+ if (!isRecord$13(value)) return null;
99499
+ if (provider === "openai") return parseCodexDeliveryIdentity(value);
99500
+ if (provider === "anthropic") return parseClaudeDeliveryIdentity(value);
99501
+ return null;
99502
+ }
99503
+ function parseCodexDeliveryIdentity(value) {
99504
+ if (!hasExactKeys$2(value, CODEX_IDENTITY_KEYS) || value.kind !== "provider_account" || value.provider !== "codex" || typeof value.providerAccountIdentity !== "string" || !PROVIDER_ACCOUNT_IDENTITY$2.test(value.providerAccountIdentity)) return null;
99505
+ return {
99506
+ kind: "provider_account",
99507
+ provider: "codex",
99508
+ providerAccountIdentity: value.providerAccountIdentity
99509
+ };
99510
+ }
99511
+ function parseClaudeDeliveryIdentity(value) {
99512
+ if (!hasExactKeys$2(value, CLAUDE_IDENTITY_KEYS) || value.kind !== "credential_generation" || value.provider !== "claude" || typeof value.credentialGenerationId !== "string" || !UUID.test(value.credentialGenerationId)) return null;
99513
+ return {
99514
+ kind: "credential_generation",
99515
+ provider: "claude",
99516
+ credentialGenerationId: value.credentialGenerationId
99517
+ };
99518
+ }
99519
+ function parseProviderRuntimeDeliveryReceipt(value, expected) {
99520
+ if (!isRecord$13(value) || !hasExactKeys$2(value, RECEIPT_KEYS)) return null;
99521
+ const identity = parseDeliveryIdentity(value.identity, expected.provider);
99522
+ if (!identity || typeof value.receiptId !== "string" || value.receiptId.length === 0 || value.receiptId.length > 256 || value.runtimeId !== expected.runtimeId || value.machineId !== expected.machineId || value.credentialEpoch !== expected.credentialEpoch || !Number.isInteger(value.credentialEpoch) || value.credentialEpoch < 0 || !isStrictRfc3339DateTime(value.issuedAt) || value.expiresAt !== expected.expiresAt || value.expiresAt !== null && !isStrictRfc3339DateTime(value.expiresAt)) return null;
99523
+ return {
99524
+ receiptId: value.receiptId,
99525
+ runtimeId: expected.runtimeId,
99526
+ machineId: expected.machineId,
99527
+ credentialEpoch: expected.credentialEpoch,
99528
+ identity,
99529
+ issuedAt: value.issuedAt,
99530
+ expiresAt: value.expiresAt
99531
+ };
99532
+ }
99533
+ function providerDeliveryBindingFromReceipt(receipt) {
99534
+ return {
99535
+ runtimeId: receipt.runtimeId,
99536
+ machineId: receipt.machineId,
99537
+ credentialEpoch: receipt.credentialEpoch,
99538
+ identity: receipt.identity
99539
+ };
99540
+ }
99541
+ function readProviderDeliveryBinding(value) {
99542
+ if (!isRecord$13(value) || !hasExactKeys$2(value, BINDING_KEYS)) return null;
99543
+ const identityProvider = isRecord$13(value.identity) ? value.identity.provider : void 0;
99544
+ const tokenProvider = identityProvider === "codex" ? "openai" : identityProvider === "claude" ? "anthropic" : null;
99545
+ if (!tokenProvider) return null;
99546
+ const identity = parseDeliveryIdentity(value.identity, tokenProvider);
99547
+ if (!identity || typeof value.runtimeId !== "string" || value.runtimeId.length === 0 || typeof value.machineId !== "string" || value.machineId.length === 0 || !Number.isInteger(value.credentialEpoch) || value.credentialEpoch < 0) return null;
99548
+ return {
99549
+ runtimeId: value.runtimeId,
99550
+ machineId: value.machineId,
99551
+ credentialEpoch: value.credentialEpoch,
99552
+ identity
99553
+ };
99554
+ }
99555
+ function providerDeliveryBindingsEqual(left, right) {
99556
+ if (left.runtimeId !== right.runtimeId || left.machineId !== right.machineId || left.credentialEpoch !== right.credentialEpoch || left.identity.kind !== right.identity.kind || left.identity.provider !== right.identity.provider) return false;
99557
+ if (left.identity.kind === "provider_account" && right.identity.kind === "provider_account") return left.identity.providerAccountIdentity === right.identity.providerAccountIdentity;
99558
+ return left.identity.kind === "credential_generation" && right.identity.kind === "credential_generation" && left.identity.credentialGenerationId === right.identity.credentialGenerationId;
99559
+ }
99560
+ //#endregion
99561
+ //#region src/provider/claudeReadinessReason.ts
99562
+ /**
99563
+ * The reason literals Forge has copy for, confirmed against CMMD-36441's
99564
+ * readiness service. If the route renames one, the rename lands here as a
99565
+ * fall-through to the generic sentence, never as a wrong sentence.
99566
+ *
99567
+ * Reading the reason is what makes `stale` legible. CMMD-36441 answers
99568
+ * `credential_reconnect_required` on a `stale` answer that still reports
99569
+ * `connected: true`, and the older `credential_generation_not_applied` on a
99570
+ * `stale` answer that simply has not landed yet. Those want opposite
99571
+ * sentences, and both used to get "Reconnect Claude in Settings" because the
99572
+ * guard read only the delivery status.
99573
+ */
99574
+ const CODE_BY_UPSTREAM_REASON$1 = {
99575
+ credential_expired_refreshing: "CREDENTIAL_EXPIRED_REFRESHING",
99576
+ credential_reconnect_required: "CREDENTIAL_RECONNECT_REQUIRED",
99577
+ credential_not_connected: "CREDENTIAL_RECONNECT_REQUIRED",
99578
+ credential_generation_not_applied: "CREDENTIAL_GENERATION_NOT_APPLIED",
99579
+ runtime_unavailable: "RUNTIME_UNAVAILABLE"
99580
+ };
99581
+ const CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY = "The delivered Claude credential is unavailable or unusable in this runtime.";
99582
+ /**
99583
+ * An ISO 8601 instant, with or without fractional seconds, UTC or offset.
99584
+ * Anchored to nothing on purpose: CMMD wraps the time in a sentence, and the
99585
+ * time is the only part of that sentence Forge repeats.
99586
+ */
99587
+ const ISO_INSTANT_PATTERN = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})/;
99588
+ function claudeReadinessReasonCode(reason) {
99589
+ if (typeof reason !== "string" || !Object.hasOwn(CODE_BY_UPSTREAM_REASON$1, reason)) return null;
99590
+ return CODE_BY_UPSTREAM_REASON$1[reason] ?? null;
99591
+ }
99592
+ function expiredAtFromReadinessMessage(message) {
99593
+ if (typeof message !== "string") return null;
99594
+ return ISO_INSTANT_PATTERN.exec(message)?.[0] ?? null;
99595
+ }
99596
+ function claudeCredentialExpiredTurnCopy(expiredAt) {
99597
+ return `The delivered Claude credential expired at ${expiredAt}. CMMD is delivering a refreshed one, so retry this turn in a moment.`;
99598
+ }
99599
+ function claudeCredentialExpiredCardCopy(expiredAt) {
99600
+ return `The delivered Claude credential expired at ${expiredAt}. CMMD is delivering a refreshed one to this runtime.`;
99601
+ }
99602
+ /**
99603
+ * The last allowlisted readiness reason this process saw.
99604
+ *
99605
+ * A server process serves exactly one runtime, so one slot is the whole store.
99606
+ * It holds a reason code and a timestamp, never credential bytes. The provider
99607
+ * catalog reads a local credential file and cannot tell an expired snapshot
99608
+ * from a blank one, so without this the card can only offer the generic
99609
+ * sentence while the guard already knows better.
99610
+ */
99611
+ let latestVerdict = null;
99612
+ /**
99613
+ * Remember, or clear, what the readiness answer said.
99614
+ *
99615
+ * An answer carrying no allowlisted reason clears the slot, which is what makes
99616
+ * the card go back to the generic sentence the moment CMMD applies a
99617
+ * credential: an applied answer carries no reason.
99618
+ */
99619
+ function recordClaudeReadinessVerdict(readiness) {
99620
+ const code = claudeReadinessReasonCode(readiness.reason);
99621
+ latestVerdict = code === null ? null : {
99622
+ code,
99623
+ expiredAt: expiredAtFromReadinessMessage(readiness.lastErrorMessage)
99624
+ };
99625
+ }
99626
+ /**
99627
+ * What the provider status card says about a delivered credential it cannot
99628
+ * use. Names the expiry only when a readiness answer supplied the time; a
99629
+ * guessed time would be worse than the generic sentence.
99630
+ */
99631
+ function claudeNativeCredentialUnusableMessage() {
99632
+ const verdict = latestVerdict;
99633
+ if (verdict?.code === "CREDENTIAL_EXPIRED_REFRESHING" && verdict.expiredAt !== null) return claudeCredentialExpiredCardCopy(verdict.expiredAt);
99634
+ return CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY;
99635
+ }
99636
+ //#endregion
99637
+ //#region src/provider/providerReadiness.ts
99638
+ const GENERATION_HASH_PATTERN$1 = /^[a-f0-9]{64}$/;
99639
+ const STILL_APPLYING_STATUSES = new Set([
99640
+ "pending",
99641
+ "claimed",
99642
+ "activating"
99643
+ ]);
99644
+ const OAUTH_SECRET_FIELDS = ["accessToken", "refreshToken"];
99645
+ var ProviderReadinessFetchError = class extends Error {
99646
+ constructor(failure) {
99647
+ super(failure);
99648
+ this.failure = failure;
99649
+ this.name = "ProviderReadinessFetchError";
99650
+ }
99651
+ };
99652
+ async function queryProviderReadiness(input) {
99653
+ if (input.sprite !== null && input.environmentId !== input.sprite.environmentId) return {
99654
+ kind: "query_failed",
99655
+ failure: "wrong_environment"
99656
+ };
99657
+ if (input.provider !== "claudeAgent" || input.sprite === null) return {
99658
+ kind: "ready",
99659
+ binding: null
99660
+ };
99661
+ const sprite = input.sprite;
99662
+ if (!GENERATION_HASH_PATTERN$1.test(sprite.localGenerationHash)) return {
99663
+ kind: "not_ready",
99664
+ reason: "generation_mismatch"
99665
+ };
99666
+ let snapshot;
99667
+ try {
99668
+ snapshot = await input.claude.fetch(sprite.runtimeId);
99669
+ } catch (cause) {
99670
+ if (cause instanceof ProviderReadinessFetchError) return {
99671
+ kind: "query_failed",
99672
+ failure: cause.failure
99673
+ };
99674
+ return {
99675
+ kind: "query_failed",
99676
+ failure: "cmmd_unavailable"
99677
+ };
99678
+ }
99679
+ return classifyClaudeSnapshot(snapshot, sprite);
99680
+ }
99681
+ function isAppliedClaudeSnapshot(snapshot) {
99682
+ return snapshot.connected === true && snapshot.deliveryStatus === "applied" && snapshot.nativeExecutable === true && typeof snapshot.generationId === "string" && snapshot.generationId.trim().length > 0;
99683
+ }
99684
+ function classifyUnappliedClaudeSnapshot(snapshot) {
99685
+ const code = claudeReadinessReasonCode(snapshot.reason);
99686
+ if (code === "RUNTIME_UNAVAILABLE") return {
99687
+ kind: "not_ready",
99688
+ reason: "environment_unavailable"
99689
+ };
99690
+ if (code === "CREDENTIAL_EXPIRED_REFRESHING" || code === "CREDENTIAL_GENERATION_NOT_APPLIED") return {
99691
+ kind: "not_ready",
99692
+ reason: "still_applying"
99693
+ };
99694
+ if (code === "CREDENTIAL_RECONNECT_REQUIRED") return {
99695
+ kind: "not_ready",
99696
+ reason: "credential_unusable"
99697
+ };
99698
+ if (STILL_APPLYING_STATUSES.has(snapshot.deliveryStatus)) return {
99699
+ kind: "not_ready",
99700
+ reason: "still_applying"
99701
+ };
99702
+ if (snapshot.deliveryStatus === "failed") return {
99703
+ kind: "not_ready",
99704
+ reason: "apply_failed"
99705
+ };
99706
+ return {
99707
+ kind: "not_ready",
99708
+ reason: "credential_unusable"
99709
+ };
99710
+ }
99711
+ function classifyClaudeSnapshot(snapshot, sprite) {
99712
+ if (!isAppliedClaudeSnapshot(snapshot)) return classifyUnappliedClaudeSnapshot(snapshot);
99713
+ const generationId = snapshot.generationId.trim();
99714
+ if (createHash("sha256").update(generationId).digest("hex") !== sprite.localGenerationHash) return {
99715
+ kind: "not_ready",
99716
+ reason: "generation_mismatch"
99717
+ };
99718
+ const deliveryReceipt = parseProviderRuntimeDeliveryReceipt(snapshot.deliveryReceipt, {
99719
+ provider: "anthropic",
99720
+ runtimeId: sprite.runtimeId,
99721
+ machineId: sprite.machineId,
99722
+ credentialEpoch: sprite.credentialEpoch,
99723
+ expiresAt: snapshot.deliveryReceipt?.expiresAt ?? null
99724
+ });
99725
+ if (deliveryReceipt?.identity.kind !== "credential_generation" || deliveryReceipt.identity.credentialGenerationId !== generationId) return {
99726
+ kind: "not_ready",
99727
+ reason: "sprite_identity_drift"
99728
+ };
99729
+ return {
99730
+ kind: "ready",
99731
+ binding: providerDeliveryBindingFromReceipt(deliveryReceipt)
99732
+ };
99733
+ }
99734
+ /**
99735
+ * A Claude.ai subscription blob is usable when claudeAiOauth holds at least one
99736
+ * non-empty secret. Metadata without tokens is how production showed Connected
99737
+ * (max) for three days while every turn failed to refresh.
99738
+ */
99739
+ function hasUsableClaudeCredentialBlob(credentialJson) {
99740
+ try {
99741
+ const parsed = JSON.parse(credentialJson);
99742
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return false;
99743
+ const oauth = parsed.claudeAiOauth;
99744
+ if (typeof oauth !== "object" || oauth === null || Array.isArray(oauth)) return false;
99745
+ return OAUTH_SECRET_FIELDS.some((field) => {
99746
+ const value = oauth[field];
99747
+ return typeof value === "string" && value.trim().length > 0;
99748
+ });
99749
+ } catch {
99750
+ return false;
99751
+ }
99752
+ }
99753
+ //#endregion
99475
99754
  //#region src/providerAuth/ClaudeDeviceAuth.ts
99476
99755
  const AUTHORIZE_URL_PATTERN = /https:\/\/[^\s]*\/oauth\/authorize\?[^\s]+/u;
99477
99756
  const ANSI_ESCAPE_PATTERN$1 = new RegExp(String.raw`\x1B\[[0-?]*[ -/]*[@-~]`, "gu");
@@ -99753,21 +100032,7 @@ function resolveLocalClaudeCredentialPath(homePath) {
99753
100032
  * an API-key config. Claude Code stores the subscription OAuth under a
99754
100033
  * `claudeAiOauth` object; require that marker. Mirrors CMMD's
99755
100034
  * validateClaudeCredentialJson.
99756
- */
99757
- function isClaudeSubscriptionCredential(credentialJson) {
99758
- try {
99759
- const parsed = JSON.parse(credentialJson);
99760
- if (typeof parsed !== "object" || parsed === null) return false;
99761
- const oauth = parsed.claudeAiOauth;
99762
- if (typeof oauth !== "object" || oauth === null) return false;
99763
- return hasUsableOauthSecrets(oauth);
99764
- } catch {
99765
- return false;
99766
- }
99767
- }
99768
- /** Either of these alone is enough to authenticate. */
99769
- const OAUTH_SECRET_FIELDS = ["accessToken", "refreshToken"];
99770
- /**
100035
+ *
99771
100036
  * Require AT LEAST ONE usable token before uploading anything.
99772
100037
  *
99773
100038
  * This gate used to end at "claudeAiOauth is an object", and in production that
@@ -99794,11 +100059,8 @@ const OAUTH_SECRET_FIELDS = ["accessToken", "refreshToken"];
99794
100059
  * schema Anthropic might ship, and fields they add, rename or drop around these
99795
100060
  * two keep flowing through untouched.
99796
100061
  */
99797
- function hasUsableOauthSecrets(oauth) {
99798
- return OAUTH_SECRET_FIELDS.some((field) => {
99799
- const value = oauth[field];
99800
- return typeof value === "string" && value.trim().length > 0;
99801
- });
100062
+ function isClaudeSubscriptionCredential(credentialJson) {
100063
+ return hasUsableClaudeCredentialBlob(credentialJson);
99802
100064
  }
99803
100065
  const EMAIL_FIELD_NAMES = new Set([
99804
100066
  "email",
@@ -146345,12 +146607,12 @@ function decodeProviderKind(providerName, operation) {
146345
146607
  detail: `Unknown persisted provider '${providerName}'.`
146346
146608
  }));
146347
146609
  }
146348
- function isRecord$13(value) {
146610
+ function isRecord$12(value) {
146349
146611
  return value !== null && typeof value === "object" && !Array.isArray(value);
146350
146612
  }
146351
146613
  function mergeRuntimePayload(existing, next) {
146352
146614
  if (next === void 0) return existing ?? null;
146353
- if (isRecord$13(existing) && isRecord$13(next)) return {
146615
+ if (isRecord$12(existing) && isRecord$12(next)) return {
146354
146616
  ...existing,
146355
146617
  ...next
146356
146618
  };
@@ -147936,123 +148198,6 @@ function buildCodexCredentialModelScope(input) {
147936
148198
  return providerEgressModelScope(input.selectedModel, catalog);
147937
148199
  }
147938
148200
  //#endregion
147939
- //#region src/egress/providerDeliveryReceipt.ts
147940
- const PROVIDER_ACCOUNT_IDENTITY$2 = /^pai_v1_[A-Za-z0-9_-]{43}$/;
147941
- const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
147942
- const RFC3339$1 = /^(\d{4})-(\d{2})-(\d{2})T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
147943
- const RECEIPT_KEYS = new Set([
147944
- "receiptId",
147945
- "runtimeId",
147946
- "machineId",
147947
- "credentialEpoch",
147948
- "identity",
147949
- "issuedAt",
147950
- "expiresAt"
147951
- ]);
147952
- const BINDING_KEYS = new Set([
147953
- "runtimeId",
147954
- "machineId",
147955
- "credentialEpoch",
147956
- "identity"
147957
- ]);
147958
- const CODEX_IDENTITY_KEYS = new Set([
147959
- "kind",
147960
- "provider",
147961
- "providerAccountIdentity"
147962
- ]);
147963
- const CLAUDE_IDENTITY_KEYS = new Set([
147964
- "kind",
147965
- "provider",
147966
- "credentialGenerationId"
147967
- ]);
147968
- function isRecord$12(value) {
147969
- return typeof value === "object" && value !== null && !Array.isArray(value);
147970
- }
147971
- function isStrictRfc3339DateTime(value) {
147972
- if (typeof value !== "string") return false;
147973
- const match = RFC3339$1.exec(value);
147974
- if (!match || !Number.isFinite(Date.parse(value))) return false;
147975
- const year = Number(match[1]);
147976
- const month = Number(match[2]);
147977
- const day = Number(match[3]);
147978
- return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth$1(year, month);
147979
- }
147980
- function daysInMonth$1(year, month) {
147981
- if (month === 2) return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0 ? 29 : 28;
147982
- return [
147983
- 4,
147984
- 6,
147985
- 9,
147986
- 11
147987
- ].includes(month) ? 30 : 31;
147988
- }
147989
- function hasExactKeys$2(value, keys) {
147990
- return Object.keys(value).every((key) => keys.has(key)) && Object.keys(value).length === keys.size;
147991
- }
147992
- function parseDeliveryIdentity(value, provider) {
147993
- if (!isRecord$12(value)) return null;
147994
- if (provider === "openai") return parseCodexDeliveryIdentity(value);
147995
- if (provider === "anthropic") return parseClaudeDeliveryIdentity(value);
147996
- return null;
147997
- }
147998
- function parseCodexDeliveryIdentity(value) {
147999
- if (!hasExactKeys$2(value, CODEX_IDENTITY_KEYS) || value.kind !== "provider_account" || value.provider !== "codex" || typeof value.providerAccountIdentity !== "string" || !PROVIDER_ACCOUNT_IDENTITY$2.test(value.providerAccountIdentity)) return null;
148000
- return {
148001
- kind: "provider_account",
148002
- provider: "codex",
148003
- providerAccountIdentity: value.providerAccountIdentity
148004
- };
148005
- }
148006
- function parseClaudeDeliveryIdentity(value) {
148007
- if (!hasExactKeys$2(value, CLAUDE_IDENTITY_KEYS) || value.kind !== "credential_generation" || value.provider !== "claude" || typeof value.credentialGenerationId !== "string" || !UUID.test(value.credentialGenerationId)) return null;
148008
- return {
148009
- kind: "credential_generation",
148010
- provider: "claude",
148011
- credentialGenerationId: value.credentialGenerationId
148012
- };
148013
- }
148014
- function parseProviderRuntimeDeliveryReceipt(value, expected) {
148015
- if (!isRecord$12(value) || !hasExactKeys$2(value, RECEIPT_KEYS)) return null;
148016
- const identity = parseDeliveryIdentity(value.identity, expected.provider);
148017
- if (!identity || typeof value.receiptId !== "string" || value.receiptId.length === 0 || value.receiptId.length > 256 || value.runtimeId !== expected.runtimeId || value.machineId !== expected.machineId || value.credentialEpoch !== expected.credentialEpoch || !Number.isInteger(value.credentialEpoch) || value.credentialEpoch < 0 || !isStrictRfc3339DateTime(value.issuedAt) || value.expiresAt !== expected.expiresAt || value.expiresAt !== null && !isStrictRfc3339DateTime(value.expiresAt)) return null;
148018
- return {
148019
- receiptId: value.receiptId,
148020
- runtimeId: expected.runtimeId,
148021
- machineId: expected.machineId,
148022
- credentialEpoch: expected.credentialEpoch,
148023
- identity,
148024
- issuedAt: value.issuedAt,
148025
- expiresAt: value.expiresAt
148026
- };
148027
- }
148028
- function providerDeliveryBindingFromReceipt(receipt) {
148029
- return {
148030
- runtimeId: receipt.runtimeId,
148031
- machineId: receipt.machineId,
148032
- credentialEpoch: receipt.credentialEpoch,
148033
- identity: receipt.identity
148034
- };
148035
- }
148036
- function readProviderDeliveryBinding(value) {
148037
- if (!isRecord$12(value) || !hasExactKeys$2(value, BINDING_KEYS)) return null;
148038
- const identityProvider = isRecord$12(value.identity) ? value.identity.provider : void 0;
148039
- const tokenProvider = identityProvider === "codex" ? "openai" : identityProvider === "claude" ? "anthropic" : null;
148040
- if (!tokenProvider) return null;
148041
- const identity = parseDeliveryIdentity(value.identity, tokenProvider);
148042
- if (!identity || typeof value.runtimeId !== "string" || value.runtimeId.length === 0 || typeof value.machineId !== "string" || value.machineId.length === 0 || !Number.isInteger(value.credentialEpoch) || value.credentialEpoch < 0) return null;
148043
- return {
148044
- runtimeId: value.runtimeId,
148045
- machineId: value.machineId,
148046
- credentialEpoch: value.credentialEpoch,
148047
- identity
148048
- };
148049
- }
148050
- function providerDeliveryBindingsEqual(left, right) {
148051
- if (left.runtimeId !== right.runtimeId || left.machineId !== right.machineId || left.credentialEpoch !== right.credentialEpoch || left.identity.kind !== right.identity.kind || left.identity.provider !== right.identity.provider) return false;
148052
- if (left.identity.kind === "provider_account" && right.identity.kind === "provider_account") return left.identity.providerAccountIdentity === right.identity.providerAccountIdentity;
148053
- return left.identity.kind === "credential_generation" && right.identity.kind === "credential_generation" && left.identity.credentialGenerationId === right.identity.credentialGenerationId;
148054
- }
148055
- //#endregion
148056
148201
  //#region src/egress/providerEgressToken.ts
148057
148202
  var ProviderEgressTokenError = class extends TaggedError("ProviderEgressTokenError") {};
148058
148203
  const PROVIDER_EGRESS_TOKEN_TIMEOUT_MS = 1e4;
@@ -206978,6 +207123,7 @@ function toCanonicalItemType(raw) {
206978
207123
  if (type.includes("computer")) return "mcp_tool_call";
206979
207124
  if (type.includes("mcp")) return "mcp_tool_call";
206980
207125
  if (type.includes("dynamic tool")) return "dynamic_tool_call";
207126
+ if (type.includes("sub agent")) return "collab_agent_tool_call";
206981
207127
  if (type.includes("collab")) return "collab_agent_tool_call";
206982
207128
  if (type.includes("web search")) return "web_search";
206983
207129
  if (type.includes("image")) return "image_view";
@@ -207042,6 +207188,21 @@ function itemDetail(item, payload) {
207042
207188
  return trimmed;
207043
207189
  }
207044
207190
  }
207191
+ const SUB_AGENT_ACTIVITY_TITLE = "Subagent";
207192
+ /**
207193
+ * The text a subagent spawn shows in the timeline.
207194
+ *
207195
+ * A `SubAgentActivity` item carries only the agent path, the child thread id,
207196
+ * and whether the spawn started or completed. `itemDetail` reads none of those
207197
+ * fields, and both the started and the completed item arrive as `item/completed`,
207198
+ * so the lifecycle status cannot tell them apart either. Without this the row
207199
+ * renders as a bare title with no text under it. The app-server wire is
207200
+ * camelCase and the rollout file is snake_case, so read both.
207201
+ */
207202
+ function subAgentActivityDetail(item) {
207203
+ const parts = [asString$2(item.agentPath)?.trim() || asString$2(item.agent_path)?.trim(), asString$2(item.kind)?.trim()].filter((part) => part !== void 0 && part.length > 0);
207204
+ return parts.length > 0 ? parts.join(" ") : void 0;
207205
+ }
207045
207206
  function toRequestTypeFromMethod(method) {
207046
207207
  switch (method) {
207047
207208
  case "item/commandExecution/requestApproval": return "command_execution_approval";
@@ -207213,7 +207374,9 @@ function mapItemLifecycle(event, canonicalThreadId, lifecycle) {
207213
207374
  if ((itemType === "mcp_tool_call" || itemType === "dynamic_tool_call") && (isBrowserToolName(source.name) || isBrowserToolName(source.toolName) || isBrowserToolName(source.method) || isBrowserToolName(payload?.toolName) || isBrowserToolName(payload?.method))) itemType = "browser_automation";
207214
207375
  if ((itemType === "unknown" || itemType === "mcp_tool_call" || itemType === "dynamic_tool_call") && (isComputerToolName(source.name) || isComputerToolName(source.toolName) || isComputerToolName(source.method) || isComputerToolName(payload?.toolName) || isComputerToolName(payload?.method))) itemType = "mcp_tool_call";
207215
207376
  if (itemType === "unknown" && lifecycle !== "item.updated") return;
207216
- const detail = itemDetail(source, payload ?? {});
207377
+ const subAgentDetail = normalizeItemType(source.type).includes("sub agent") ? subAgentActivityDetail(source) : void 0;
207378
+ const detail = subAgentDetail ?? itemDetail(source, payload ?? {});
207379
+ const title = subAgentDetail ? SUB_AGENT_ACTIVITY_TITLE : itemTitle(itemType);
207217
207380
  const status = lifecycle === "item.started" ? "inProgress" : lifecycle === "item.completed" ? "completed" : void 0;
207218
207381
  return {
207219
207382
  ...runtimeEventBase(event, canonicalThreadId),
@@ -207221,7 +207384,7 @@ function mapItemLifecycle(event, canonicalThreadId, lifecycle) {
207221
207384
  payload: {
207222
207385
  itemType,
207223
207386
  ...status ? { status } : {},
207224
- ...itemTitle(itemType) ? { title: itemTitle(itemType) } : {},
207387
+ ...title ? { title } : {},
207225
207388
  ...detail ? { detail } : {},
207226
207389
  ...event.payload !== void 0 ? { data: event.payload } : {}
207227
207390
  }
@@ -208377,82 +208540,6 @@ const makeProviderAuthProvenance = (input) => {
208377
208540
  };
208378
208541
  };
208379
208542
  //#endregion
208380
- //#region src/provider/claudeReadinessReason.ts
208381
- /**
208382
- * The reason literals Forge has copy for, confirmed against CMMD-36441's
208383
- * readiness service. If the route renames one, the rename lands here as a
208384
- * fall-through to the generic sentence, never as a wrong sentence.
208385
- *
208386
- * Reading the reason is what makes `stale` legible. CMMD-36441 answers
208387
- * `credential_reconnect_required` on a `stale` answer that still reports
208388
- * `connected: true`, and the older `credential_generation_not_applied` on a
208389
- * `stale` answer that simply has not landed yet. Those want opposite
208390
- * sentences, and both used to get "Reconnect Claude in Settings" because the
208391
- * guard read only the delivery status.
208392
- */
208393
- const CODE_BY_UPSTREAM_REASON$1 = {
208394
- credential_expired_refreshing: "CREDENTIAL_EXPIRED_REFRESHING",
208395
- credential_reconnect_required: "CREDENTIAL_RECONNECT_REQUIRED",
208396
- credential_not_connected: "CREDENTIAL_RECONNECT_REQUIRED",
208397
- credential_generation_not_applied: "CREDENTIAL_GENERATION_NOT_APPLIED",
208398
- runtime_unavailable: "RUNTIME_UNAVAILABLE"
208399
- };
208400
- const CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY = "The delivered Claude credential is unavailable or unusable in this runtime.";
208401
- /**
208402
- * An ISO 8601 instant, with or without fractional seconds, UTC or offset.
208403
- * Anchored to nothing on purpose: CMMD wraps the time in a sentence, and the
208404
- * time is the only part of that sentence Forge repeats.
208405
- */
208406
- const ISO_INSTANT_PATTERN = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})/;
208407
- function claudeReadinessReasonCode(reason) {
208408
- if (typeof reason !== "string" || !Object.hasOwn(CODE_BY_UPSTREAM_REASON$1, reason)) return null;
208409
- return CODE_BY_UPSTREAM_REASON$1[reason] ?? null;
208410
- }
208411
- function expiredAtFromReadinessMessage(message) {
208412
- if (typeof message !== "string") return null;
208413
- return ISO_INSTANT_PATTERN.exec(message)?.[0] ?? null;
208414
- }
208415
- function claudeCredentialExpiredTurnCopy(expiredAt) {
208416
- return `The delivered Claude credential expired at ${expiredAt}. CMMD is delivering a refreshed one, so retry this turn in a moment.`;
208417
- }
208418
- function claudeCredentialExpiredCardCopy(expiredAt) {
208419
- return `The delivered Claude credential expired at ${expiredAt}. CMMD is delivering a refreshed one to this runtime.`;
208420
- }
208421
- /**
208422
- * The last allowlisted readiness reason this process saw.
208423
- *
208424
- * A server process serves exactly one runtime, so one slot is the whole store.
208425
- * It holds a reason code and a timestamp, never credential bytes. The provider
208426
- * catalog reads a local credential file and cannot tell an expired snapshot
208427
- * from a blank one, so without this the card can only offer the generic
208428
- * sentence while the guard already knows better.
208429
- */
208430
- let latestVerdict = null;
208431
- /**
208432
- * Remember, or clear, what the readiness answer said.
208433
- *
208434
- * An answer carrying no allowlisted reason clears the slot, which is what makes
208435
- * the card go back to the generic sentence the moment CMMD applies a
208436
- * credential: an applied answer carries no reason.
208437
- */
208438
- function recordClaudeReadinessVerdict(readiness) {
208439
- const code = claudeReadinessReasonCode(readiness.reason);
208440
- latestVerdict = code === null ? null : {
208441
- code,
208442
- expiredAt: expiredAtFromReadinessMessage(readiness.lastErrorMessage)
208443
- };
208444
- }
208445
- /**
208446
- * What the provider status card says about a delivered credential it cannot
208447
- * use. Names the expiry only when a readiness answer supplied the time; a
208448
- * guessed time would be worse than the generic sentence.
208449
- */
208450
- function claudeNativeCredentialUnusableMessage() {
208451
- const verdict = latestVerdict;
208452
- if (verdict?.code === "CREDENTIAL_EXPIRED_REFRESHING" && verdict.expiredAt !== null) return claudeCredentialExpiredCardCopy(verdict.expiredAt);
208453
- return CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY;
208454
- }
208455
- //#endregion
208456
208543
  //#region src/provider/personalClaudeInVm.ts
208457
208544
  /**
208458
208545
  * CMMD writes this marker when it activates a personal Claude subscription
@@ -208520,18 +208607,6 @@ function supportsFable51ClaudeCli(version) {
208520
208607
  function modelsForClaudeCliVersion(models, version) {
208521
208608
  return supportsFable51ClaudeCli(version) ? models : models.filter((model) => model.slug !== "claude-fable-5-1");
208522
208609
  }
208523
- function hasUsableNativeClaudeCredential(value) {
208524
- try {
208525
- const parsed = JSON.parse(value);
208526
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return false;
208527
- const oauth = parsed.claudeAiOauth;
208528
- if (typeof oauth !== "object" || oauth === null || Array.isArray(oauth)) return false;
208529
- const record = oauth;
208530
- return [record.accessToken, record.refreshToken].some((token) => typeof token === "string" && token.trim().length > 0);
208531
- } catch {
208532
- return false;
208533
- }
208534
- }
208535
208610
  function getClaudeModelCapabilities(model) {
208536
208611
  return getProviderModelCapabilities(PROVIDER$12, model) ?? DEFAULT_CLAUDE_MODEL_CAPABILITIES;
208537
208612
  }
@@ -208984,7 +209059,7 @@ function claudeVersionProbeTimeoutProvider(input) {
208984
209059
  const nativeClaudeProviderStatus = fn$1("nativeClaudeProviderStatus")(function* (input) {
208985
209060
  const nativeConfigPath = input.configPath ?? join(homedir(), ".claude");
208986
209061
  const nativeCredential = yield* tryPromise(() => readFile$1(join(nativeConfigPath, ".credentials.json"), "utf8")).pipe(option);
208987
- const usable = isSome(nativeCredential) ? hasUsableNativeClaudeCredential(nativeCredential.value) : false;
209062
+ const usable = isSome(nativeCredential) ? hasUsableClaudeCredentialBlob(nativeCredential.value) : false;
208988
209063
  return buildServerProvider({
208989
209064
  provider: PROVIDER$12,
208990
209065
  enabled: input.enabled,
@@ -227141,44 +227216,40 @@ function readinessFailureIssue(readiness) {
227141
227216
  if (readiness.connected === false || readiness.deliveryStatus === "stale" || readiness.deliveryStatus === "not_connected") return CLAUDE_READINESS_COPY.invalid;
227142
227217
  return CLAUDE_READINESS_COPY.unavailable;
227143
227218
  }
227144
- function generationHash(generationId) {
227145
- return createHash("sha256").update(generationId).digest("hex");
227146
- }
227147
227219
  async function assertNativeClaudeRuntimeReady(input) {
227148
227220
  if (!GENERATION_HASH_PATTERN.test(input.localGenerationHash)) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
227221
+ const environmentId = EnvironmentId.make(`cmmd-runtime:${input.runtimeId}`);
227222
+ const sprite = {
227223
+ environmentId,
227224
+ runtimeId: input.runtimeId,
227225
+ machineId: input.machineId,
227226
+ credentialEpoch: input.credentialEpoch,
227227
+ localGenerationHash: input.localGenerationHash
227228
+ };
227149
227229
  return await withReadinessRetry(async () => {
227150
227230
  const readiness = decodeClaudeRuntimeReadiness(await input.fetchReadiness(input.runtimeId));
227151
227231
  recordClaudeReadinessVerdict(readiness);
227152
- return verifiedClaudeDeliveryBinding(readiness, input);
227153
- });
227154
- }
227155
- function verifiedClaudeDeliveryBinding(readiness, authority) {
227156
- const generationId = appliedClaudeGeneration(readiness);
227157
- if (generationHash(generationId) !== authority.localGenerationHash) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.generationMismatch);
227158
- const deliveryReceipt = parseProviderRuntimeDeliveryReceipt(readiness.deliveryReceipt, {
227159
- provider: "anthropic",
227160
- runtimeId: authority.runtimeId,
227161
- machineId: authority.machineId,
227162
- credentialEpoch: authority.credentialEpoch,
227163
- expiresAt: readiness.deliveryReceipt?.expiresAt ?? null
227232
+ return bindingFromProviderReadiness(await queryProviderReadiness({
227233
+ environmentId,
227234
+ provider: "claudeAgent",
227235
+ sprite,
227236
+ claude: { fetch: async () => readiness }
227237
+ }), readiness);
227164
227238
  });
227165
- if (!isMatchingClaudeReceipt(deliveryReceipt, generationId)) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
227166
- return providerDeliveryBindingFromReceipt(deliveryReceipt);
227167
227239
  }
227168
- function appliedClaudeGeneration(readiness) {
227169
- if (readiness.connected !== true || readiness.deliveryStatus !== "applied" || readiness.nativeExecutable !== true || typeof readiness.generationId !== "string" || readiness.generationId.trim().length === 0) {
227170
- const refreshing = isCredentialRefreshInFlight(readiness);
227171
- const retryable = !isRuntimeUnavailable(readiness) && (refreshing || [
227172
- "pending",
227173
- "claimed",
227174
- "activating"
227175
- ].includes(readiness.deliveryStatus));
227176
- throw new ClaudeRuntimeReadinessError(readinessFailureIssue(readiness), retryable, refreshing ? "credentialRefresh" : "default");
227240
+ function bindingFromProviderReadiness(result, snapshot) {
227241
+ if (result.kind === "ready") {
227242
+ if (result.binding === null) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
227243
+ return result.binding;
227177
227244
  }
227178
- return readiness.generationId;
227179
- }
227180
- function isMatchingClaudeReceipt(receipt, generationId) {
227181
- return receipt?.identity.kind === "credential_generation" && receipt.identity.credentialGenerationId === generationId;
227245
+ if (result.kind === "query_failed") throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
227246
+ const refreshing = isCredentialRefreshInFlight(snapshot);
227247
+ const retryable = !isRuntimeUnavailable(snapshot) && (refreshing || [
227248
+ "pending",
227249
+ "claimed",
227250
+ "activating"
227251
+ ].includes(snapshot.deliveryStatus));
227252
+ throw new ClaudeRuntimeReadinessError(result.reason === "generation_mismatch" ? CLAUDE_READINESS_COPY.generationMismatch : result.reason === "sprite_identity_drift" ? CLAUDE_READINESS_COPY.unavailable : readinessFailureIssue(snapshot), retryable, refreshing ? "credentialRefresh" : "default");
227182
227253
  }
227183
227254
  function readinessData(value) {
227184
227255
  if (typeof value !== "object" || value === null || !("data" in value)) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
@@ -291492,7 +291563,7 @@ function resolveBuildCommitFromEnv(env) {
291492
291563
  * environment descriptor down instead of reporting an honest "unknown".
291493
291564
  */
291494
291565
  function readBakedBuildCommit() {
291495
- return "9e352ae66ea610fd1916726270fce8a1ab138a3b";
291566
+ return "e94d1f3729cdbbc5b3f87cc2368279c7ef20aec8";
291496
291567
  }
291497
291568
  async function resolveServerBuildCommit(input) {
291498
291569
  if (isFullCommitSha(input.baked)) return input.baked;