@cmmd-center/forge 0.13.15 → 0.13.17

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.
Files changed (28) hide show
  1. package/dist/bin.cjs +258 -836
  2. package/dist/bin.mjs +228 -806
  3. package/dist/client/assets/{CanvasPanel-RpD9Eh_S.js → CanvasPanel-uofZ5KUR.js} +2 -2
  4. package/dist/client/assets/{CompositeItem-DEIBUHJR.js → CompositeItem-C5YSRi5B.js} +2 -2
  5. package/dist/client/assets/{DiffPanel-D-NIms_l.js → DiffPanel-DBxERq43.js} +3 -3
  6. package/dist/client/assets/{DiffPanel.logic-DwoeNGnH.js → DiffPanel.logic-CVvbOj4s.js} +2 -2
  7. package/dist/client/assets/DiffPanelShell-3FSe-Ixv.js +2533 -0
  8. package/dist/client/assets/{DiffWorkerPoolProvider-DHNvSWPo.js → DiffWorkerPoolProvider-DGz1EBXf.js} +9 -9
  9. package/dist/client/assets/PullRequestCodePanel-BsTzlXhi.js +5 -0
  10. package/dist/client/assets/{Virtualizer-Cm4G15Gy.js → Virtualizer-BABEZSz9.js} +2 -2
  11. package/dist/client/assets/{canvasStateStore-NrAxDqvM.js → canvasStateStore-IBP3QM_C.js} +2 -2
  12. package/dist/client/assets/{cmmdAuthRedirect-BahlX0gF.js → cmmdAuthRedirect-Ck1QfYaS.js} +2 -2
  13. package/dist/client/assets/index-DBkypII5.js +153 -0
  14. package/dist/client/assets/index-EZbGVDT4.css +1 -0
  15. package/dist/client/assets/{popover-Z8Tvl-OD.js → popover-BQaoSlk7.js} +2 -2
  16. package/dist/client/assets/{src-BU7yHzO9.js → src-Bj8vTcnP.js} +2 -2
  17. package/dist/client/assets/{toggle-CWYdWYBn.js → toggle-CE2NHkQL.js} +2 -2
  18. package/dist/client/index.html +11 -11
  19. package/dist/forge-build.json +1 -1
  20. package/dist/runtimeBootstrap.cjs +1 -1
  21. package/dist/runtimeBootstrap.mjs +1 -1
  22. package/dist/{runtimeControlAuthority-BkVB0uAA.cjs → runtimeControlAuthority-DCitZFTk.cjs} +3 -1
  23. package/dist/{runtimeControlAuthority-E_kdeD_P.mjs → runtimeControlAuthority-DpRIoWqP.mjs} +3 -1
  24. package/package.json +1 -1
  25. package/dist/client/assets/DiffPanelShell-BI5poBl7.js +0 -2532
  26. package/dist/client/assets/PullRequestCodePanel-apgvV8hi.js +0 -5
  27. package/dist/client/assets/index-C3pC5t1K.css +0 -1
  28. package/dist/client/assets/index-DdqgGbOQ.js +0 -154
package/dist/bin.mjs CHANGED
@@ -11,7 +11,7 @@ import { a as make$51, i as keys, n as getOption, o as makeWith$1, r as invalida
11
11
  import { S as layer$9, _ as defaultEscape, a as DeadlockError, b as makeCompiler$1, c as SqlError, d as UnknownError, g as custom, h as make$52, i as ConstraintError, l as SqlSyntaxError, m as SqlClient, n as AuthorizationError, o as LockTimeoutError, r as ConnectionError, s as SerializationError, t as AuthenticationError, u as StatementTimeoutError, v as defaultTransforms, y as fragment } from "./SqlError-BMBkezUO.mjs";
12
12
  import { r as wrapper_default, t as Mime_default } from "./Mime-Dq9IoNiV.mjs";
13
13
  import { a as diag, c as SpanKind$1, d as TraceFlags, f as ROOT_CONTEXT, i as propagation, l as isSpanContextValid, m as DiagLogLevel, n as init_esm$1, o as context$1, p as createContextKey, r as trace, s as SpanStatusCode, t as esm_exports$1 } from "./esm-wLIF-u3N.mjs";
14
- import { a as verifyCmmdAuthRuntimeTicket, c as verifyCmmdRuntimeTicket, d as runtimeGrantToken, f as setRuntimeGrantToken, i as sendRuntimeControlHeartbeat, l as verifyCmmdRuntimeTicketRefreshProof, n as bootstrapRuntimeControlAuthorityFromNarrowGrant, o as verifyCmmdClaudeReadinessTicket, p as createReadOnceFileTokenAccessor, r as readRuntimeControlAuthority, s as verifyCmmdClaudeUsageTicket, t as bootstrapRuntimeControlAuthority, u as verifyCmmdScopedRuntimePayload } from "./runtimeControlAuthority-E_kdeD_P.mjs";
14
+ import { a as verifyCmmdAuthRuntimeTicket, c as verifyCmmdRuntimeTicket, d as runtimeGrantToken, f as setRuntimeGrantToken, i as sendRuntimeControlHeartbeat, l as verifyCmmdRuntimeTicketRefreshProof, n as bootstrapRuntimeControlAuthorityFromNarrowGrant, o as verifyCmmdClaudeReadinessTicket, p as createReadOnceFileTokenAccessor, r as readRuntimeControlAuthority, s as verifyCmmdClaudeUsageTicket, t as bootstrapRuntimeControlAuthority, u as verifyCmmdScopedRuntimePayload } from "./runtimeControlAuthority-DpRIoWqP.mjs";
15
15
  import { n as PtySpawnError, t as PtyAdapter } from "./PTY-BzdbZ0Ym.mjs";
16
16
  import { createRequire } from "node:module";
17
17
  import * as HE from "node:child_process";
@@ -25521,160 +25521,6 @@ const WorkspaceEnsureScratchResult = Struct({
25521
25521
  workspaceRoot: String$1,
25522
25522
  title: String$1
25523
25523
  });
25524
- const CodeGraphRelation = Literals([
25525
- "contains",
25526
- "imports",
25527
- "calls",
25528
- "imports_from",
25529
- "method",
25530
- "references",
25531
- "re_exports",
25532
- "indirect_call",
25533
- "dynamic_import",
25534
- "inherits",
25535
- "rationale_for",
25536
- "implements",
25537
- "cites",
25538
- "triggers"
25539
- ]);
25540
- const CodeGraphConfidence = Literals(["EXTRACTED", "INFERRED"]);
25541
- const CodeGraphEdgeClass = Literals([
25542
- "containment",
25543
- "dependency",
25544
- "behavior"
25545
- ]);
25546
- /**
25547
- * Relation to drawn class. Exhaustive over CODE_GRAPH_RELATIONS by construction
25548
- * — `codeGraph.test.ts` fails if a relation is added without a class.
25549
- */
25550
- const CODE_GRAPH_RELATION_CLASS = {
25551
- contains: "containment",
25552
- method: "containment",
25553
- imports: "dependency",
25554
- imports_from: "dependency",
25555
- re_exports: "dependency",
25556
- dynamic_import: "dependency",
25557
- inherits: "dependency",
25558
- implements: "dependency",
25559
- calls: "behavior",
25560
- indirect_call: "behavior",
25561
- references: "behavior",
25562
- triggers: "behavior",
25563
- cites: "behavior",
25564
- rationale_for: "behavior"
25565
- };
25566
- const CodeGraphNodeKind = Literals(["file", "symbol"]);
25567
- /**
25568
- * One community, positioned.
25569
- *
25570
- * Positions are computed server-side and are stable for a given graph build, so
25571
- * the map does not rearrange itself between openings. A map you have to re-learn
25572
- * every time is not a map.
25573
- */
25574
- const CodeGraphRegion = Struct({
25575
- id: NonNegativeInt,
25576
- label: TrimmedNonEmptyString,
25577
- nodeCount: PositiveInt,
25578
- x: Number$1,
25579
- y: Number$1
25580
- });
25581
- /** An aggregated edge between two regions, weighted by how many edges cross. */
25582
- const CodeGraphRegionLink = Struct({
25583
- source: NonNegativeInt,
25584
- target: NonNegativeInt,
25585
- weight: PositiveInt
25586
- });
25587
- /**
25588
- * The default view: the whole repository as ~120 named regions.
25589
- *
25590
- * `truncatedRegions` is not decoration. When a graph has more regions than the
25591
- * map shows, the surface says so — a view that silently drops a third of the
25592
- * codebase while looking complete is the failure mode this field exists to
25593
- * prevent.
25594
- */
25595
- const CodeGraphSummary = Struct({
25596
- repoLabel: TrimmedNonEmptyString,
25597
- builtAtCommit: NullOr(String$1),
25598
- nodeCount: NonNegativeInt,
25599
- edgeCount: NonNegativeInt,
25600
- extractedEdgeCount: NonNegativeInt,
25601
- inferredEdgeCount: NonNegativeInt,
25602
- regionCount: NonNegativeInt,
25603
- regions: ArraySchema(CodeGraphRegion),
25604
- links: ArraySchema(CodeGraphRegionLink),
25605
- truncatedRegions: NonNegativeInt
25606
- });
25607
- /** A node as it appears in a list, a search result, or a neighborhood. */
25608
- const CodeGraphNodeSummary = Struct({
25609
- id: TrimmedNonEmptyString,
25610
- label: TrimmedNonEmptyString,
25611
- kind: CodeGraphNodeKind,
25612
- sourceFile: NullOr(String$1),
25613
- sourceLocation: NullOr(String$1),
25614
- regionId: NullOr(NonNegativeInt),
25615
- regionLabel: NullOr(String$1),
25616
- degree: NonNegativeInt
25617
- });
25618
- /** One edge, carrying both the exact relation and the class it is drawn as. */
25619
- const CodeGraphEdgeView = Struct({
25620
- source: TrimmedNonEmptyString,
25621
- target: TrimmedNonEmptyString,
25622
- relation: CodeGraphRelation,
25623
- edgeClass: CodeGraphEdgeClass,
25624
- confidence: CodeGraphConfidence,
25625
- confidenceScore: Number$1
25626
- });
25627
- /**
25628
- * One node and what surrounds it — the view a person actually works in.
25629
- *
25630
- * `truncated` fires when a hub's fan-out exceeds the cap. A god node with
25631
- * thousands of edges must degrade to "showing 150 of 2,310", never to a frozen
25632
- * tab or a quietly partial picture.
25633
- */
25634
- const CodeGraphNeighborhood = Struct({
25635
- root: CodeGraphNodeSummary,
25636
- nodes: ArraySchema(CodeGraphNodeSummary),
25637
- edges: ArraySchema(CodeGraphEdgeView),
25638
- depth: PositiveInt,
25639
- truncated: Boolean$1,
25640
- omittedCount: NonNegativeInt
25641
- });
25642
- const CodeGraphSearchResult = Struct({
25643
- nodes: ArraySchema(CodeGraphNodeSummary),
25644
- truncated: Boolean$1
25645
- });
25646
- const CodeGraphSummaryInput = Struct({ cwd: TrimmedNonEmptyString });
25647
- const CodeGraphNeighborhoodInput = Struct({
25648
- cwd: TrimmedNonEmptyString,
25649
- nodeId: TrimmedNonEmptyString,
25650
- depth: optional$4(PositiveInt)
25651
- });
25652
- const CodeGraphSearchInput = Struct({
25653
- cwd: TrimmedNonEmptyString,
25654
- query: TrimmedNonEmptyString,
25655
- limit: optional$4(PositiveInt)
25656
- });
25657
- /** Where the extractor writes, relative to the project root. */
25658
- const CODE_GRAPH_ARTIFACT_PATH = "graphify-out/graph.json";
25659
- /**
25660
- * No graph in this checkout, or one that cannot be read.
25661
- *
25662
- * Distinct from a read failure on purpose: "not indexed yet" is the normal
25663
- * first-run state and gets an action, while a malformed or unreadable artifact
25664
- * is a fault and gets an explanation. Collapsing them would tell a user with a
25665
- * corrupt file to run a build they have already run.
25666
- */
25667
- var CodeGraphUnavailableError = class extends TaggedErrorClass()("CodeGraphUnavailableError", {
25668
- reason: Literals([
25669
- "missing",
25670
- "unreadable",
25671
- "malformed",
25672
- "lfs-pointer"
25673
- ]),
25674
- message: String$1
25675
- }) {};
25676
- /** A node id that is not in this graph — usually a stale link into a rebuilt graph. */
25677
- var CodeGraphNodeNotFoundError = class extends TaggedErrorClass()("CodeGraphNodeNotFoundError", { nodeId: String$1 }) {};
25678
25524
  //#endregion
25679
25525
  //#region ../../packages/contracts/src/relay.ts
25680
25526
  const RELAY_PROTOCOL_FAMILY = "forge-relay";
@@ -26055,9 +25901,6 @@ const WS_METHODS = {
26055
25901
  projectsWriteFile: "projects.writeFile",
26056
25902
  projectCheckoutDeletionPreview: "projectCheckoutDeletion.preview",
26057
25903
  projectCheckoutDeletionExecute: "projectCheckoutDeletion.execute",
26058
- codeGraphSummary: "codeGraph.summary",
26059
- codeGraphNeighborhood: "codeGraph.neighborhood",
26060
- codeGraphSearch: "codeGraph.search",
26061
25904
  workspaceReadFile: "workspace.readFile",
26062
25905
  workspaceBeginWriteFile: "workspace.beginWriteFile",
26063
25906
  workspaceWriteFileChunk: "workspace.writeFileChunk",
@@ -26343,21 +26186,6 @@ const WsProjectCheckoutDeletionExecuteRpc = make$30(WS_METHODS.projectCheckoutDe
26343
26186
  payload: ProjectCheckoutDeletionExecuteInput,
26344
26187
  success: ProjectCheckoutDeletionResult
26345
26188
  });
26346
- const WsCodeGraphSummaryRpc = make$30(WS_METHODS.codeGraphSummary, {
26347
- payload: CodeGraphSummaryInput,
26348
- success: CodeGraphSummary,
26349
- error: CodeGraphUnavailableError
26350
- });
26351
- const WsCodeGraphNeighborhoodRpc = make$30(WS_METHODS.codeGraphNeighborhood, {
26352
- payload: CodeGraphNeighborhoodInput,
26353
- success: CodeGraphNeighborhood,
26354
- error: Union([CodeGraphUnavailableError, CodeGraphNodeNotFoundError])
26355
- });
26356
- const WsCodeGraphSearchRpc = make$30(WS_METHODS.codeGraphSearch, {
26357
- payload: CodeGraphSearchInput,
26358
- success: CodeGraphSearchResult,
26359
- error: CodeGraphUnavailableError
26360
- });
26361
26189
  const WsWorkspaceReadFileRpc = make$30(WS_METHODS.workspaceReadFile, {
26362
26190
  payload: BulkTransferReadFileInput,
26363
26191
  success: BulkTransferStreamEvent,
@@ -26807,7 +26635,7 @@ const WsRpcGroup = make$29(WsServerGetConfigRpc, WsServerRefreshProvidersRpc, Ws
26807
26635
  payload: UsageSummaryInput,
26808
26636
  success: UsageSummary,
26809
26637
  error: UsageReadError
26810
- }), WsPullRequestsListRpc, WsPullRequestsListStatsRpc, WsPullRequestsDetailRpc, WsPullRequestsActivityRpc, WsPullRequestsThreadCommentsRpc, WsPullRequestsDiffFileContentsRpc, WsPullRequestsRunActionRpc, WsPullRequestsUpdateRpc, WsPullRequestsCommentRpc, WsPullRequestsUpdateCommentRpc, WsPullRequestsSubmitReviewRpc, WsPullRequestsReplyToThreadRpc, WsPullRequestsSetThreadResolutionRpc, WsPullRequestsSetReactionRpc, WsPullRequestsInvalidateRpc, WsPullRequestsReviewerCandidatesRpc, WsPullRequestsRequestReviewersRpc, WsProjectsSearchContentsRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsProjectCheckoutDeletionPreviewRpc, WsProjectCheckoutDeletionExecuteRpc, WsCodeGraphSummaryRpc, WsCodeGraphNeighborhoodRpc, WsCodeGraphSearchRpc, WsWorkspaceReadFileRpc, WsWorkspaceBeginWriteFileRpc, WsWorkspaceWriteFileChunkRpc, WsWorkspaceCommitWriteFileRpc, WsWorkspaceCancelWriteFileRpc, WsShellOpenInEditorRpc, WsSubscribeGitStatusRpc, WsGitPullRpc, WsGitRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsGitListBranchesRpc, WsVcsListRefsRpc, WsVcsRefreshStatusRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsGitCreateWorktreeRpc, WsGitRemoveWorktreeRpc, WsGitCreateBranchRpc, WsGitCheckoutRpc, WsGitInitRpc, WsFilesystemBrowseRpc, WsProjectsReadFileRpc, WsReviewGetDiffPreviewRpc, WsCloudListRuntimesRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalSignalRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsBrowserOpenSessionRpc, WsBrowserListSessionsRpc, WsBrowserCloseSessionRpc, WsBrowserGetSessionRpc, WsBrowserCommandRpc, WsBrowserClearBrowsingDataRpc, WsBrowserAttachDisplayRpc, WsBrowserAddDisplayIceCandidateRpc, WsComputerInputRpc, WsDevTunnelRegisterRpc, WsDevTunnelUnregisterRpc, WsDevTunnelListRpc, WsThreadDevRuntimeGetRpc, WsThreadDevRuntimeAllocatePortRpc, WsThreadDevRuntimeReleaseRpc, WsWorkspaceEnvironmentPreflightRpc, WsWorkspaceEnsureScratchRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsProjectsListEntriesRpc, WsServerDiscoverSourceControlRpc, WsServerReportClientActivityRpc, WsSubscribeBrowserEventsRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsSubscribeWorkspaceReadinessRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationStreamTurnDiffRpc, WsOrchestrationStreamFullThreadDiffRpc, WsOrchestrationReplayEventsRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc, make$30(WS_METHODS.assetsCreateUrl, {
26638
+ }), WsPullRequestsListRpc, WsPullRequestsListStatsRpc, WsPullRequestsDetailRpc, WsPullRequestsActivityRpc, WsPullRequestsThreadCommentsRpc, WsPullRequestsDiffFileContentsRpc, WsPullRequestsRunActionRpc, WsPullRequestsUpdateRpc, WsPullRequestsCommentRpc, WsPullRequestsUpdateCommentRpc, WsPullRequestsSubmitReviewRpc, WsPullRequestsReplyToThreadRpc, WsPullRequestsSetThreadResolutionRpc, WsPullRequestsSetReactionRpc, WsPullRequestsInvalidateRpc, WsPullRequestsReviewerCandidatesRpc, WsPullRequestsRequestReviewersRpc, WsProjectsSearchContentsRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsProjectCheckoutDeletionPreviewRpc, WsProjectCheckoutDeletionExecuteRpc, WsWorkspaceReadFileRpc, WsWorkspaceBeginWriteFileRpc, WsWorkspaceWriteFileChunkRpc, WsWorkspaceCommitWriteFileRpc, WsWorkspaceCancelWriteFileRpc, WsShellOpenInEditorRpc, WsSubscribeGitStatusRpc, WsGitPullRpc, WsGitRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsGitListBranchesRpc, WsVcsListRefsRpc, WsVcsRefreshStatusRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsGitCreateWorktreeRpc, WsGitRemoveWorktreeRpc, WsGitCreateBranchRpc, WsGitCheckoutRpc, WsGitInitRpc, WsFilesystemBrowseRpc, WsProjectsReadFileRpc, WsReviewGetDiffPreviewRpc, WsCloudListRuntimesRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalSignalRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsBrowserOpenSessionRpc, WsBrowserListSessionsRpc, WsBrowserCloseSessionRpc, WsBrowserGetSessionRpc, WsBrowserCommandRpc, WsBrowserClearBrowsingDataRpc, WsBrowserAttachDisplayRpc, WsBrowserAddDisplayIceCandidateRpc, WsComputerInputRpc, WsDevTunnelRegisterRpc, WsDevTunnelUnregisterRpc, WsDevTunnelListRpc, WsThreadDevRuntimeGetRpc, WsThreadDevRuntimeAllocatePortRpc, WsThreadDevRuntimeReleaseRpc, WsWorkspaceEnvironmentPreflightRpc, WsWorkspaceEnsureScratchRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsProjectsListEntriesRpc, WsServerDiscoverSourceControlRpc, WsServerReportClientActivityRpc, WsSubscribeBrowserEventsRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsSubscribeWorkspaceReadinessRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationStreamTurnDiffRpc, WsOrchestrationStreamFullThreadDiffRpc, WsOrchestrationReplayEventsRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc, make$30(WS_METHODS.assetsCreateUrl, {
26811
26639
  payload: AssetsRpcSchemas.createUrl.input,
26812
26640
  success: AssetsRpcSchemas.createUrl.output,
26813
26641
  error: AssetAccessError
@@ -31496,21 +31324,6 @@ const RELAY_METHOD_POLICY_BASES = [
31496
31324
  requiredScope: "runtime.read",
31497
31325
  deliveryClass: "read"
31498
31326
  },
31499
- {
31500
- method: WS_METHODS.codeGraphSummary,
31501
- requiredScope: "workspace.read",
31502
- deliveryClass: "read"
31503
- },
31504
- {
31505
- method: WS_METHODS.codeGraphNeighborhood,
31506
- requiredScope: "workspace.read",
31507
- deliveryClass: "read"
31508
- },
31509
- {
31510
- method: WS_METHODS.codeGraphSearch,
31511
- requiredScope: "workspace.read",
31512
- deliveryClass: "read"
31513
- },
31514
31327
  {
31515
31328
  method: WS_METHODS.projectsWriteFile,
31516
31329
  requiredScope: "workspace.write",
@@ -66123,7 +65936,7 @@ function normalizeNumberish(value) {
66123
65936
  }
66124
65937
  //#endregion
66125
65938
  //#region package.json
66126
- var version$1 = "0.13.15";
65939
+ var version$1 = "0.13.17";
66127
65940
  //#endregion
66128
65941
  //#region src/sentry.ts
66129
65942
  const SERVER_APP_NAME = "forge-server";
@@ -67161,7 +66974,7 @@ function toPersistenceDecodeDefect(operation) {
67161
66974
  const isPersistenceError = (u) => is$1(PersistenceSqlError)(u) || is$1(PersistenceDecodeError)(u);
67162
66975
  //#endregion
67163
66976
  //#region src/cmmdConnection/CmmdConnectionStore.ts
67164
- const cache$1 = /* @__PURE__ */ new Map();
66977
+ const cache = /* @__PURE__ */ new Map();
67165
66978
  const jwtCache = /* @__PURE__ */ new Map();
67166
66979
  const jwtExpiryCache = /* @__PURE__ */ new Map();
67167
66980
  const refreshTokenCache = /* @__PURE__ */ new Map();
@@ -67302,7 +67115,7 @@ const hydrateCommandAccessTokenStore = gen(function* () {
67302
67115
  session_grant AS "sessionGrant"
67303
67116
  FROM command_access_tokens
67304
67117
  `.pipe(mapError(toPersistenceSqlError("CommandAccessTokenStore.hydrate:query")))).pipe(mapError(toPersistenceDecodeError("CommandAccessTokenStore.hydrate:decodeRows")));
67305
- cache$1.clear();
67118
+ cache.clear();
67306
67119
  jwtCache.clear();
67307
67120
  jwtExpiryCache.clear();
67308
67121
  refreshTokenCache.clear();
@@ -67312,7 +67125,7 @@ const hydrateCommandAccessTokenStore = gen(function* () {
67312
67125
  try: () => {
67313
67126
  for (const row of decoded) {
67314
67127
  const sessionId = row.sessionId;
67315
- cache$1.set(sessionId, decodeSensitiveValue(ACCESS_TOKEN_SCOPE, row.accessToken));
67128
+ cache.set(sessionId, decodeSensitiveValue(ACCESS_TOKEN_SCOPE, row.accessToken));
67316
67129
  const jwtToken = decryptNullable(JWT_TOKEN_SCOPE, row.jwtToken);
67317
67130
  if (jwtToken) jwtCache.set(sessionId, jwtToken);
67318
67131
  if (row.jwtExpiresAt) jwtExpiryCache.set(sessionId, row.jwtExpiresAt);
@@ -67332,7 +67145,7 @@ const hydrateCommandAccessTokenStore = gen(function* () {
67332
67145
  * Returns `null` when the session has no paired CMMD token.
67333
67146
  */
67334
67147
  function readCommandAccessTokenForSession(sessionId) {
67335
- return cache$1.get(sessionId) ?? null;
67148
+ return cache.get(sessionId) ?? null;
67336
67149
  }
67337
67150
  const threadSessions = /* @__PURE__ */ new Map();
67338
67151
  /**
@@ -67709,7 +67522,7 @@ const promoteMostRecentOwnerCommandAuthToSession = (sessionId) => gen(function*
67709
67522
  cmmd_user_identity = excluded.cmmd_user_identity,
67710
67523
  updated_at = excluded.updated_at
67711
67524
  `.pipe(mapError(toPersistenceSqlError("CommandAccessTokenStore.promoteLatestOwnerAuth:upsert")));
67712
- cache$1.set(sessionId, accessToken);
67525
+ cache.set(sessionId, accessToken);
67713
67526
  if (jwtToken) jwtCache.set(sessionId, jwtToken);
67714
67527
  else jwtCache.delete(sessionId);
67715
67528
  if (row.jwtExpiresAt) jwtExpiryCache.set(sessionId, row.jwtExpiresAt);
@@ -67754,7 +67567,7 @@ const setCommandAccessTokenForSession = (sessionId, accessToken) => gen(function
67754
67567
  access_token = excluded.access_token,
67755
67568
  updated_at = excluded.updated_at
67756
67569
  `.pipe(mapError(toPersistenceSqlError("CommandAccessTokenStore.set:query")));
67757
- cache$1.set(sessionId, token);
67570
+ cache.set(sessionId, token);
67758
67571
  });
67759
67572
  /**
67760
67573
  * Remove the PAT for a session from both durable persistence and the in-memory cache.
@@ -67767,7 +67580,7 @@ const clearCommandAccessTokenForSession = (sessionId) => gen(function* () {
67767
67580
  forgetCommandAccessTokenCachesForSession(sessionId);
67768
67581
  });
67769
67582
  function forgetCommandAccessTokenCachesForSession(sessionId) {
67770
- cache$1.delete(sessionId);
67583
+ cache.delete(sessionId);
67771
67584
  jwtCache.delete(sessionId);
67772
67585
  jwtExpiryCache.delete(sessionId);
67773
67586
  refreshTokenCache.delete(sessionId);
@@ -77318,500 +77131,6 @@ const makeSocketProtocol = /* @__PURE__ */ gen(function* () {
77318
77131
  };
77319
77132
  });
77320
77133
  //#endregion
77321
- //#region src/codeGraph/aggregate.ts
77322
- /**
77323
- * Turning a 26 MB graph into slices small enough to draw.
77324
- *
77325
- * Pure functions over an already-parsed graph, deliberately free of Effect, the
77326
- * filesystem and the RPC layer, so the interesting parts — capping, ranking,
77327
- * hub suppression — are testable without a runtime or a fixture file on disk.
77328
- *
77329
- * The whole module exists because of one number: this repo's graph is 34,102
77330
- * nodes and 86,347 edges. Nothing here ever returns more than a few hundred of
77331
- * either. A view that tries to show everything shows nothing.
77332
- */
77333
- function pushInto(map, key, link) {
77334
- const existing = map.get(key);
77335
- if (existing === void 0) {
77336
- map.set(key, [link]);
77337
- return;
77338
- }
77339
- existing.push(link);
77340
- }
77341
- function isKnownRelation(relation) {
77342
- return Object.hasOwn(CODE_GRAPH_RELATION_CLASS, relation);
77343
- }
77344
- /**
77345
- * Index a parsed graph once so every later query is a map lookup.
77346
- *
77347
- * Edges naming a node the artifact does not define are dropped rather than
77348
- * synthesised. Graphify does emit these — a call into a module outside the scan
77349
- * root — and inventing a placeholder node for one would put a file in the map
77350
- * that is not in the repository.
77351
- */
77352
- function indexGraph(raw, repoLabel) {
77353
- const nodes = /* @__PURE__ */ new Map();
77354
- for (const node of raw.nodes) nodes.set(node.id, node);
77355
- const outbound = /* @__PURE__ */ new Map();
77356
- const inbound = /* @__PURE__ */ new Map();
77357
- const degree = /* @__PURE__ */ new Map();
77358
- const unknownRelations = /* @__PURE__ */ new Set();
77359
- let extractedEdgeCount = 0;
77360
- let inferredEdgeCount = 0;
77361
- let edgeCount = 0;
77362
- for (const link of raw.links) {
77363
- if (!nodes.has(link.source) || !nodes.has(link.target)) continue;
77364
- const relation = link.relation ?? "";
77365
- if (relation !== "" && !isKnownRelation(relation)) {
77366
- unknownRelations.add(relation);
77367
- continue;
77368
- }
77369
- edgeCount += 1;
77370
- if (link.confidence === "INFERRED") inferredEdgeCount += 1;
77371
- else extractedEdgeCount += 1;
77372
- pushInto(outbound, link.source, link);
77373
- pushInto(inbound, link.target, link);
77374
- degree.set(link.source, (degree.get(link.source) ?? 0) + 1);
77375
- degree.set(link.target, (degree.get(link.target) ?? 0) + 1);
77376
- }
77377
- return {
77378
- repoLabel,
77379
- builtAtCommit: raw.built_at_commit ?? null,
77380
- nodes,
77381
- outbound,
77382
- inbound,
77383
- degree,
77384
- edgeCount,
77385
- extractedEdgeCount,
77386
- inferredEdgeCount,
77387
- unknownRelations: [...unknownRelations].toSorted()
77388
- };
77389
- }
77390
- /**
77391
- * Deterministic sunflower placement.
77392
- *
77393
- * A phyllotaxis spiral rather than a force simulation, for three reasons: it
77394
- * needs no dependency, it is O(n), and — the one that actually matters — it is
77395
- * *stable*. The same graph opens to the same picture every time, so the spatial
77396
- * memory a person builds up survives closing the panel. A force layout reshuffles
77397
- * on every mount and quietly costs them that.
77398
- *
77399
- * Index 0 lands nearest the centre, so ordering regions by size puts the
77400
- * architectural core where the eye starts.
77401
- */
77402
- function spiralPosition(index, total) {
77403
- const goldenAngle = Math.PI * (3 - Math.sqrt(5));
77404
- const radius = total <= 1 ? 0 : Math.sqrt(index / (total - 1));
77405
- const angle = index * goldenAngle;
77406
- return {
77407
- x: .5 + radius * Math.cos(angle) * .44,
77408
- y: .5 + radius * Math.sin(angle) * .44
77409
- };
77410
- }
77411
- /** Group nodes into their communities, and remember which community each is in. */
77412
- function accumulateRegions(graph) {
77413
- const accumulators = /* @__PURE__ */ new Map();
77414
- const regionOfNode = /* @__PURE__ */ new Map();
77415
- for (const node of graph.nodes.values()) {
77416
- const community = node.community;
77417
- if (community === void 0) continue;
77418
- regionOfNode.set(node.id, community);
77419
- const existing = accumulators.get(community);
77420
- if (existing === void 0) {
77421
- accumulators.set(community, {
77422
- id: community,
77423
- label: node.community_name ?? `Region ${String(community)}`,
77424
- nodeCount: 1
77425
- });
77426
- continue;
77427
- }
77428
- existing.nodeCount += 1;
77429
- }
77430
- return {
77431
- ordered: [...accumulators.values()].toSorted((a, b) => b.nodeCount - a.nodeCount || a.id - b.id),
77432
- regionOfNode
77433
- };
77434
- }
77435
- /**
77436
- * Collapse node-level edges into weighted links between drawn regions.
77437
- *
77438
- * Undirected: "these two areas talk" is the question at this altitude, and
77439
- * drawing both arcs doubles the ink for no added meaning.
77440
- */
77441
- function aggregateRegionLinks(graph, regionOfNode, shownIds) {
77442
- const linkWeights = /* @__PURE__ */ new Map();
77443
- for (const links of graph.outbound.values()) for (const link of links) {
77444
- const from = regionOfNode.get(link.source);
77445
- const to = regionOfNode.get(link.target);
77446
- if (from === void 0 || to === void 0 || from === to) continue;
77447
- if (!shownIds.has(from) || !shownIds.has(to)) continue;
77448
- const key = `${String(Math.min(from, to))}:${String(Math.max(from, to))}`;
77449
- linkWeights.set(key, (linkWeights.get(key) ?? 0) + 1);
77450
- }
77451
- return [...linkWeights.entries()].map(([key, weight]) => {
77452
- const [source, target] = key.split(":");
77453
- return {
77454
- source: Number(source),
77455
- target: Number(target),
77456
- weight
77457
- };
77458
- });
77459
- }
77460
- /**
77461
- * The default view: the repository as named regions.
77462
- *
77463
- * Regions come from graphify's own community detection, and their names come
77464
- * from the community's hub node — so a region is labelled `AIGateway.ts` or
77465
- * `IStorage`, something a person recognises, rather than "Community 469".
77466
- */
77467
- function buildSummary(graph) {
77468
- const { ordered, regionOfNode } = accumulateRegions(graph);
77469
- const shown = ordered.slice(0, 120);
77470
- const shownIds = new Set(shown.map((region) => region.id));
77471
- const regions = shown.map((region, index) => {
77472
- const position = spiralPosition(index, shown.length);
77473
- return {
77474
- id: region.id,
77475
- label: region.label,
77476
- nodeCount: region.nodeCount,
77477
- x: position.x,
77478
- y: position.y
77479
- };
77480
- });
77481
- return {
77482
- repoLabel: graph.repoLabel,
77483
- builtAtCommit: graph.builtAtCommit,
77484
- nodeCount: graph.nodes.size,
77485
- edgeCount: graph.edgeCount,
77486
- extractedEdgeCount: graph.extractedEdgeCount,
77487
- inferredEdgeCount: graph.inferredEdgeCount,
77488
- regionCount: ordered.length,
77489
- regions,
77490
- links: aggregateRegionLinks(graph, regionOfNode, shownIds),
77491
- truncatedRegions: Math.max(0, ordered.length - shown.length)
77492
- };
77493
- }
77494
- function summariseNode(graph, node) {
77495
- return {
77496
- id: node.id,
77497
- label: node.label ?? node.id,
77498
- kind: node._callable === true ? "symbol" : "file",
77499
- sourceFile: node.source_file ?? null,
77500
- sourceLocation: node.source_location ?? null,
77501
- regionId: node.community ?? null,
77502
- regionLabel: node.community_name ?? null,
77503
- degree: graph.degree.get(node.id) ?? 0
77504
- };
77505
- }
77506
- function toEdgeView(link) {
77507
- const relation = link.relation ?? "";
77508
- if (!isKnownRelation(relation)) return null;
77509
- const confidence = link.confidence === "INFERRED" ? "INFERRED" : "EXTRACTED";
77510
- return {
77511
- source: link.source,
77512
- target: link.target,
77513
- relation,
77514
- edgeClass: CODE_GRAPH_RELATION_CLASS[relation],
77515
- confidence,
77516
- confidenceScore: link.confidence_score ?? 1
77517
- };
77518
- }
77519
- /**
77520
- * Pull one node's neighbours into the result; return how many it had to drop.
77521
- *
77522
- * Split out of `buildNeighborhood` because the two read differently: the caller
77523
- * owns *how far to walk*, this owns *what one step collects*. Together they sat
77524
- * well past the repo's cognitive-complexity gate.
77525
- */
77526
- /** Links touching a node, most-connected neighbour first. */
77527
- function rankNeighbourLinks(graph, current) {
77528
- return [...graph.outbound.get(current) ?? [], ...graph.inbound.get(current) ?? []].toSorted((a, b) => {
77529
- const aOther = a.source === current ? a.target : a.source;
77530
- const bOther = b.source === current ? b.target : b.source;
77531
- return (graph.degree.get(bOther) ?? 0) - (graph.degree.get(aOther) ?? 0);
77532
- });
77533
- }
77534
- /** Take a neighbour into the result. False means the budget is spent. */
77535
- function admitNeighbour(state, id, node) {
77536
- if (state.included.has(id)) return true;
77537
- if (state.included.size >= 150) return false;
77538
- state.included.set(id, node);
77539
- state.next.push(id);
77540
- return true;
77541
- }
77542
- /** Record an edge once, dropping any relation this build cannot classify. */
77543
- function recordEdge(state, link) {
77544
- const edgeKey = `${link.source}>${link.target}:${link.relation ?? ""}`;
77545
- if (state.seenEdges.has(edgeKey)) return;
77546
- const view = toEdgeView(link);
77547
- if (view === null) return;
77548
- state.seenEdges.add(edgeKey);
77549
- state.edges.push(view);
77550
- }
77551
- /**
77552
- * Pull one node's neighbours into the result; return how many it had to drop.
77553
- *
77554
- * Split out of `buildNeighborhood` because the two read differently: the caller
77555
- * owns *how far to walk*, this owns *what one step collects*.
77556
- */
77557
- function expandNode(graph, current, state) {
77558
- let omitted = 0;
77559
- for (const link of rankNeighbourLinks(graph, current)) {
77560
- const other = link.source === current ? link.target : link.source;
77561
- const otherNode = graph.nodes.get(other);
77562
- if (otherNode === void 0) continue;
77563
- if (!admitNeighbour(state, other, otherNode)) {
77564
- omitted += 1;
77565
- continue;
77566
- }
77567
- recordEdge(state, link);
77568
- }
77569
- return omitted;
77570
- }
77571
- /**
77572
- * One node and what surrounds it.
77573
- *
77574
- * Two caps, and they do different jobs. `CODE_GRAPH_MAX_NEIGHBORS` bounds the
77575
- * answer so the canvas stays drawable. `CODE_GRAPH_MAX_FANOUT` bounds the
77576
- * *traversal*: a hub is included as a neighbor but never expanded through, so
77577
- * one `logger.ts` in the second ring cannot drag the entire repository in
77578
- * behind it. Without the second cap the first one is reached instantly and the
77579
- * result is 150 arbitrary nodes rather than the 150 nearest ones.
77580
- */
77581
- function buildNeighborhood(graph, nodeId, requestedDepth) {
77582
- const root = graph.nodes.get(nodeId);
77583
- if (root === void 0) return null;
77584
- const depth = Math.min(Math.max(1, requestedDepth), 2);
77585
- const included = new Map([[root.id, root]]);
77586
- const seenEdges = /* @__PURE__ */ new Set();
77587
- const edges = [];
77588
- let omittedCount = 0;
77589
- let frontier = [root.id];
77590
- for (let level = 0; level < depth; level += 1) {
77591
- const next = [];
77592
- for (const current of frontier) {
77593
- const fanout = graph.degree.get(current) ?? 0;
77594
- if (current !== root.id && fanout > 200) continue;
77595
- omittedCount += expandNode(graph, current, {
77596
- included,
77597
- seenEdges,
77598
- edges,
77599
- next
77600
- });
77601
- }
77602
- frontier = next;
77603
- if (frontier.length === 0) break;
77604
- }
77605
- const nodes = [...included.values()].filter((node) => node.id !== root.id).map((node) => summariseNode(graph, node)).toSorted((a, b) => b.degree - a.degree || a.label.localeCompare(b.label));
77606
- return {
77607
- root: summariseNode(graph, root),
77608
- nodes,
77609
- edges: edges.filter((edge) => included.has(edge.source) && included.has(edge.target)),
77610
- depth,
77611
- truncated: omittedCount > 0,
77612
- omittedCount
77613
- };
77614
- }
77615
- /**
77616
- * Rank one node against a query: lower is better, negative means no match.
77617
- *
77618
- * A file-path hit ranks last because "the query appears somewhere in this path"
77619
- * is much weaker evidence than "this thing is called that".
77620
- */
77621
- function matchScore(node, query) {
77622
- const label = (node.label ?? node.id).toLowerCase();
77623
- if (label === query) return 0;
77624
- if (label.startsWith(query)) return 1;
77625
- if (label.includes(query)) return 2;
77626
- return (node.source_file ?? "").toLowerCase().includes(query) ? 3 : -1;
77627
- }
77628
- /**
77629
- * Find a node by name or path.
77630
- *
77631
- * Entry to this surface is search, not the canvas — you usually arrive already
77632
- * knowing what you are looking for, and clicking around 34,000 nodes to find it
77633
- * is not a workflow. Ranking is exact, then prefix, then substring, with degree
77634
- * breaking ties so the `logger.ts` everything imports outranks a test fixture
77635
- * that merely shares the word.
77636
- */
77637
- function searchNodes(graph, rawQuery, limit = 40) {
77638
- const query = rawQuery.trim().toLowerCase();
77639
- if (query === "") return {
77640
- nodes: [],
77641
- truncated: false
77642
- };
77643
- const scored = [];
77644
- for (const node of graph.nodes.values()) {
77645
- const score = matchScore(node, query);
77646
- if (score < 0) continue;
77647
- scored.push({
77648
- node,
77649
- score
77650
- });
77651
- }
77652
- const ranked = scored.toSorted((a, b) => a.score - b.score || (graph.degree.get(b.node.id) ?? 0) - (graph.degree.get(a.node.id) ?? 0) || (a.node.label ?? a.node.id).localeCompare(b.node.label ?? b.node.id));
77653
- const capped = ranked.slice(0, limit);
77654
- return {
77655
- nodes: capped.map((entry) => summariseNode(graph, entry.node)),
77656
- truncated: ranked.length > capped.length
77657
- };
77658
- }
77659
- //#endregion
77660
- //#region src/codeGraph/graphArtifact.ts
77661
- /**
77662
- * Reading `graphify-out/graph.json` off disk, once.
77663
- *
77664
- * The artifact is 26 MB here and 40 MB for CMMD's server tree, and parsing it
77665
- * costs roughly a second. Every panel open would pay that again without a cache,
77666
- * so one indexed graph is held per project and reused until the file changes.
77667
- *
77668
- * Kept free of Effect on purpose: the failure modes worth distinguishing are all
77669
- * filesystem-shaped, and a plain promise keeps this unit-testable against real
77670
- * fixtures without constructing a runtime. `ws.ts` wraps it at the boundary.
77671
- */
77672
- const cache = /* @__PURE__ */ new Map();
77673
- /** Git LFS writes a pointer file that is valid text and useless as a graph. */
77674
- const LFS_POINTER_PREFIX = "version https://git-lfs.github.com/spec/v1";
77675
- function codeGraphArtifactPath(cwd) {
77676
- return path.join(cwd, CODE_GRAPH_ARTIFACT_PATH);
77677
- }
77678
- function isRawGraph(value) {
77679
- if (typeof value !== "object" || value === null) return false;
77680
- const candidate = value;
77681
- return Array.isArray(candidate.nodes) && Array.isArray(candidate.links);
77682
- }
77683
- /**
77684
- * Load and index the graph for one project checkout.
77685
- *
77686
- * The LFS-pointer case is called out separately rather than folded into
77687
- * "malformed" because it is the single most likely failure on a fresh clone —
77688
- * the file is present, tracked, and 133 bytes of metadata. Telling someone their
77689
- * graph is corrupt when they simply have not run `git lfs pull` sends them to
77690
- * rebuild something that is fine.
77691
- */
77692
- async function loadIndexedGraph(cwd) {
77693
- const artifactPath = codeGraphArtifactPath(cwd);
77694
- let stats;
77695
- try {
77696
- stats = await stat(artifactPath);
77697
- } catch {
77698
- return {
77699
- ok: false,
77700
- failure: {
77701
- kind: "missing",
77702
- artifactPath
77703
- }
77704
- };
77705
- }
77706
- if (!stats.isFile()) return {
77707
- ok: false,
77708
- failure: {
77709
- kind: "missing",
77710
- artifactPath
77711
- }
77712
- };
77713
- const cached = cache.get(artifactPath);
77714
- if (cached !== void 0 && cached.mtimeMs === stats.mtimeMs && cached.size === stats.size) return {
77715
- ok: true,
77716
- graph: cached.graph
77717
- };
77718
- let contents;
77719
- try {
77720
- contents = await readFile$1(artifactPath, "utf8");
77721
- } catch (error) {
77722
- return {
77723
- ok: false,
77724
- failure: {
77725
- kind: "unreadable",
77726
- artifactPath,
77727
- detail: error instanceof Error ? error.message : String(error)
77728
- }
77729
- };
77730
- }
77731
- if (contents.startsWith(LFS_POINTER_PREFIX)) return {
77732
- ok: false,
77733
- failure: {
77734
- kind: "lfs-pointer",
77735
- artifactPath
77736
- }
77737
- };
77738
- let parsed;
77739
- try {
77740
- parsed = JSON.parse(contents);
77741
- } catch (error) {
77742
- return {
77743
- ok: false,
77744
- failure: {
77745
- kind: "malformed",
77746
- artifactPath,
77747
- detail: error instanceof Error ? error.message : String(error)
77748
- }
77749
- };
77750
- }
77751
- if (!isRawGraph(parsed)) return {
77752
- ok: false,
77753
- failure: {
77754
- kind: "malformed",
77755
- artifactPath,
77756
- detail: "Expected an object with `nodes` and `links` arrays."
77757
- }
77758
- };
77759
- const graph = indexGraph(parsed, path.basename(cwd));
77760
- cache.set(artifactPath, {
77761
- mtimeMs: stats.mtimeMs,
77762
- size: stats.size,
77763
- graph
77764
- });
77765
- return {
77766
- ok: true,
77767
- graph
77768
- };
77769
- }
77770
- //#endregion
77771
- //#region src/codeGraph/service.ts
77772
- /**
77773
- * The code-graph RPC surface, as Effects.
77774
- *
77775
- * A thin seam between `ws.ts` and the pure aggregator: load the artifact, turn
77776
- * a filesystem failure into the tagged error the client can act on, and slice.
77777
- *
77778
- * The failure mapping is the substance here. Each reason produces different
77779
- * advice — pull LFS, run the extractor, report a corrupt file — so collapsing
77780
- * them into one "graph unavailable" would send people to fix the wrong thing.
77781
- */
77782
- function toUnavailable(failure) {
77783
- switch (failure.kind) {
77784
- case "missing": return new CodeGraphUnavailableError({
77785
- reason: "missing",
77786
- message: `No code graph in this checkout. Run \`graphify update .\` to build ${failure.artifactPath}.`
77787
- });
77788
- case "lfs-pointer": return new CodeGraphUnavailableError({
77789
- reason: "lfs-pointer",
77790
- message: `The graph is a Git LFS pointer, not the graph itself. Run \`git lfs pull\` to fetch it.`
77791
- });
77792
- case "malformed": return new CodeGraphUnavailableError({
77793
- reason: "malformed",
77794
- message: `The graph file could not be parsed: ${failure.detail}`
77795
- });
77796
- case "unreadable": return new CodeGraphUnavailableError({
77797
- reason: "unreadable",
77798
- message: `The graph file could not be read: ${failure.detail}`
77799
- });
77800
- }
77801
- }
77802
- function withGraph(cwd, use) {
77803
- return flatMap(promise(() => loadIndexedGraph(cwd)), (result) => result.ok ? succeed(use(result.graph)) : fail(toUnavailable(result.failure)));
77804
- }
77805
- function readCodeGraphSummary(input) {
77806
- return withGraph(input.cwd, buildSummary);
77807
- }
77808
- function readCodeGraphNeighborhood(input) {
77809
- return flatMap(withGraph(input.cwd, (graph) => buildNeighborhood(graph, input.nodeId, input.depth ?? 1)), (neighborhood) => neighborhood === null ? fail(new CodeGraphNodeNotFoundError({ nodeId: input.nodeId })) : succeed(neighborhood));
77810
- }
77811
- function readCodeGraphSearch(input) {
77812
- return withGraph(input.cwd, (graph) => searchNodes(graph, input.query, input.limit ?? 40));
77813
- }
77814
- //#endregion
77815
77134
  //#region src/checkpointing/Services/CheckpointDiffQuery.ts
77816
77135
  /**
77817
77136
  * CheckpointDiffQuery - Service tag for checkpoint diff queries.
@@ -96683,6 +96002,7 @@ const registerCloudRuntimeForReplicaHydration = gen(function* () {
96683
96002
  credentialEpoch,
96684
96003
  activeTurnCount: 0,
96685
96004
  activeSessionCount: 0,
96005
+ acceptingTurns: false,
96686
96006
  ...forgeGitCommit !== void 0 ? { forgeGitCommit } : {},
96687
96007
  forgeServerVersion: installedForgeServerVersion
96688
96008
  }),
@@ -96719,6 +96039,128 @@ const hydrateCloudRuntimeReplica = gen(function* () {
96719
96039
  return yield* hydrateRuntimeReplica({ expectedRuntimeId: grant.runtimeId }, dependencies);
96720
96040
  });
96721
96041
  //#endregion
96042
+ //#region src/runtimeDrain/RuntimeDrainState.ts
96043
+ /**
96044
+ * The positive facts this process must observe before it can claim a turn.
96045
+ *
96046
+ * Every entry is required, so adding one here is the whole change: the
96047
+ * derivation below reads this list rather than naming fields, and the record
96048
+ * it indexes cannot be built with a member missing.
96049
+ */
96050
+ const RUNTIME_EXECUTION_PRECONDITIONS = ["orchestrationEngine", "providerLayer"];
96051
+ /**
96052
+ * The single definition of the accepting-turns fact.
96053
+ *
96054
+ * Exported so test stubs of this service derive it exactly as the live state
96055
+ * does. A stub that recomputed it by hand could disagree with production and
96056
+ * still pass.
96057
+ */
96058
+ function deriveAcceptingTurns(input) {
96059
+ return RUNTIME_EXECUTION_PRECONDITIONS.every((precondition) => input.preconditions[precondition]) && !input.draining && !input.shutdownRequested;
96060
+ }
96061
+ const initialState = {
96062
+ activeTurns: /* @__PURE__ */ new Set(),
96063
+ activeTurnCount: 0,
96064
+ activeSessionCount: 0,
96065
+ draining: false,
96066
+ drainReason: null,
96067
+ drainTargetImageRef: null,
96068
+ drainTargetImageVersion: null,
96069
+ drainForceRequired: false,
96070
+ preconditions: {
96071
+ orchestrationEngine: false,
96072
+ providerLayer: false
96073
+ },
96074
+ shutdownRequested: false
96075
+ };
96076
+ function snapshotFromState(state) {
96077
+ return {
96078
+ activeTurnCount: state.activeTurnCount,
96079
+ activeSessionCount: state.activeSessionCount,
96080
+ draining: state.draining,
96081
+ drainReason: state.drainReason,
96082
+ drainTargetImageRef: state.drainTargetImageRef,
96083
+ drainTargetImageVersion: state.drainTargetImageVersion,
96084
+ drainForceRequired: state.drainForceRequired,
96085
+ acceptingTurns: deriveAcceptingTurns(state)
96086
+ };
96087
+ }
96088
+ function turnKey(input) {
96089
+ return `${input.threadId}:${input.turnId ?? "unknown"}`;
96090
+ }
96091
+ function normalizeCount(count) {
96092
+ return Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0;
96093
+ }
96094
+ const makeRuntimeDrainState = gen(function* () {
96095
+ const stateRef = yield* make$50(initialState);
96096
+ const update = (f) => updateAndGet(stateRef, f).pipe(map$3(snapshotFromState));
96097
+ return {
96098
+ beginTurn: (input) => update((state) => {
96099
+ const activeTurns = new Set(state.activeTurns);
96100
+ activeTurns.add(turnKey(input));
96101
+ return {
96102
+ ...state,
96103
+ activeTurns,
96104
+ activeTurnCount: activeTurns.size
96105
+ };
96106
+ }),
96107
+ completeTurn: (input) => update((state) => {
96108
+ const activeTurns = new Set(state.activeTurns);
96109
+ activeTurns.delete(turnKey(input));
96110
+ return {
96111
+ ...state,
96112
+ activeTurns,
96113
+ activeTurnCount: activeTurns.size
96114
+ };
96115
+ }),
96116
+ clearActiveTurns: update((state) => ({
96117
+ ...state,
96118
+ activeTurns: /* @__PURE__ */ new Set(),
96119
+ activeTurnCount: 0
96120
+ })),
96121
+ setActiveSessionCount: (count) => update((state) => ({
96122
+ ...state,
96123
+ activeSessionCount: normalizeCount(count)
96124
+ })),
96125
+ reconcileProviderSessions: (sessions) => update((state) => {
96126
+ const activeSessions = sessions.filter((session) => session.status !== "closed");
96127
+ const activeTurns = new Set(activeSessions.flatMap((session) => session.activeTurnId === void 0 ? [] : [turnKey({
96128
+ threadId: session.threadId,
96129
+ turnId: session.activeTurnId
96130
+ })]));
96131
+ return {
96132
+ ...state,
96133
+ activeTurns,
96134
+ activeTurnCount: activeTurns.size,
96135
+ activeSessionCount: activeSessions.length
96136
+ };
96137
+ }),
96138
+ applyControlPlaneState: (input) => update((state) => ({
96139
+ ...state,
96140
+ draining: input.draining ?? state.draining,
96141
+ drainReason: input.drainReason ?? state.drainReason,
96142
+ drainTargetImageRef: input.drainTargetImageRef ?? state.drainTargetImageRef,
96143
+ drainTargetImageVersion: input.drainTargetImageVersion ?? state.drainTargetImageVersion,
96144
+ drainForceRequired: input.drainForceRequired ?? state.drainForceRequired
96145
+ })),
96146
+ markExecutionPrecondition: (precondition) => update((state) => ({
96147
+ ...state,
96148
+ preconditions: {
96149
+ ...state.preconditions,
96150
+ [precondition]: true
96151
+ }
96152
+ })),
96153
+ requestShutdown: update((state) => ({
96154
+ ...state,
96155
+ shutdownRequested: true
96156
+ })),
96157
+ snapshot: get$6(stateRef).pipe(map$3(snapshotFromState)),
96158
+ isDraining: get$6(stateRef).pipe(map$3((state) => state.draining))
96159
+ };
96160
+ });
96161
+ var RuntimeDrainState = class extends Service$1()("forge/runtimeDrain/RuntimeDrainState") {};
96162
+ const RuntimeDrainStateLive = effect(RuntimeDrainState, makeRuntimeDrainState);
96163
+ //#endregion
96722
96164
  //#region src/persistence/Services/LocalAutomations.ts
96723
96165
  const LocalAutomationStatus = Literals([
96724
96166
  "active",
@@ -100352,6 +99794,30 @@ const makeCommandGate = gen(function* () {
100352
99794
  })
100353
99795
  };
100354
99796
  });
99797
+ /**
99798
+ * Settle the command gate for a finished startup, and report whether commands
99799
+ * are now accepted.
99800
+ *
99801
+ * The success branch is the moment the orchestration engine can take work, so
99802
+ * it is where the engine half of the accepting-turns fact is marked. A failed
99803
+ * startup accepts nothing and must leave the fact untouched: absent must not
99804
+ * read as healthy.
99805
+ */
99806
+ const settleCommandReadiness = (input) => gen(function* () {
99807
+ if (isFailure(input.startupExit)) {
99808
+ const error = new ServerRuntimeStartupError({
99809
+ message: startupFailureMessage(input.startupExit.cause),
99810
+ cause: input.startupExit.cause
99811
+ });
99812
+ yield* logError("server runtime startup failed", { cause: describeStartupFailure(input.startupExit.cause) });
99813
+ yield* input.commandGate.failCommandReady(error);
99814
+ return false;
99815
+ }
99816
+ yield* logDebug("Accepting commands");
99817
+ yield* input.commandGate.signalCommandReady;
99818
+ yield* input.drainState.markExecutionPrecondition("orchestrationEngine");
99819
+ return true;
99820
+ });
100355
99821
  const launchStartupHeartbeat = gen(function* () {
100356
99822
  const analytics = yield* AnalyticsService;
100357
99823
  const { threadCount, projectCount } = yield* (yield* ProjectionSnapshotQuery).getCounts().pipe(catch_((cause) => logWarning$1("failed to gather startup projection counts for telemetry", { cause }).pipe(as$3({
@@ -100532,6 +99998,7 @@ const ServerRuntimeStartupLive = effect(ServerRuntimeStartup, gen(function* () {
100532
99998
  const serverSettings = yield* ServerSettingsService;
100533
99999
  const serverEnvironment = yield* ServerEnvironment;
100534
100000
  const usage = yield* UsageService;
100001
+ const drainState = yield* RuntimeDrainState;
100535
100002
  const commandGate = yield* makeCommandGate;
100536
100003
  const httpListening = yield* make$39();
100537
100004
  const reactorScope = yield* make$37("sequential");
@@ -100614,18 +100081,11 @@ const ServerRuntimeStartupLive = effect(ServerRuntimeStartup, gen(function* () {
100614
100081
  root: true
100615
100082
  }));
100616
100083
  yield* forkScoped(gen(function* () {
100617
- const startupExit = yield* exit(startup);
100618
- if (isFailure(startupExit)) {
100619
- const error = new ServerRuntimeStartupError({
100620
- message: startupFailureMessage(startupExit.cause),
100621
- cause: startupExit.cause
100622
- });
100623
- yield* logError("server runtime startup failed", { cause: describeStartupFailure(startupExit.cause) });
100624
- yield* commandGate.failCommandReady(error);
100625
- return;
100626
- }
100627
- yield* logDebug("Accepting commands");
100628
- yield* commandGate.signalCommandReady;
100084
+ if (!(yield* settleCommandReadiness({
100085
+ startupExit: yield* exit(startup),
100086
+ commandGate,
100087
+ drainState
100088
+ }))) return;
100629
100089
  yield* logDebug("startup phase: starting the usage scan warm-up");
100630
100090
  yield* forkScoped(runUsageScanWarmup({ readSummary: usage.readSummary }));
100631
100091
  yield* logDebug("startup phase: waiting for http listener");
@@ -107173,9 +106633,6 @@ const makeWsRpcLayer = (currentSessionId, currentUserId) => WsRpcGroup.toLayer(g
107173
106633
  }))), { "rpc.aggregate": "workspace" }),
107174
106634
  [WS_METHODS.serverDiscoverSourceControl]: () => observeRpcEffect(WS_METHODS.serverDiscoverSourceControl, discoverSourceControl, { "rpc.aggregate": "server" }),
107175
106635
  [WS_METHODS.serverReportClientActivity]: () => observeRpcEffect(WS_METHODS.serverReportClientActivity, void_$1, { "rpc.aggregate": "server" }),
107176
- [WS_METHODS.codeGraphSummary]: (input) => observeRpcEffect(WS_METHODS.codeGraphSummary, readCodeGraphSummary(input), { "rpc.aggregate": "codeGraph" }),
107177
- [WS_METHODS.codeGraphNeighborhood]: (input) => observeRpcEffect(WS_METHODS.codeGraphNeighborhood, readCodeGraphNeighborhood(input), { "rpc.aggregate": "codeGraph" }),
107178
- [WS_METHODS.codeGraphSearch]: (input) => observeRpcEffect(WS_METHODS.codeGraphSearch, readCodeGraphSearch(input), { "rpc.aggregate": "codeGraph" }),
107179
106636
  [WS_METHODS.projectsWriteFile]: (input) => observeRpcEffect(WS_METHODS.projectsWriteFile, workspaceFileSystem.writeFile(input).pipe(mapError((cause) => {
107180
106637
  return new ProjectWriteFileError({
107181
106638
  message: is$1(WorkspacePathOutsideRootError)(cause) ? "Workspace file path must stay within the project root." : "Failed to write workspace file",
@@ -153208,7 +152665,9 @@ var CodexAppServerManager = class extends EventEmitter$1 {
153208
152665
  scheduleProviderEgressTokenRefresh(context, delayMs) {
153209
152666
  if (context.tokenRefreshTimer) clearTimeout(context.tokenRefreshTimer);
153210
152667
  const tokenRefreshTimer = setTimeout(() => {
153211
- this.handleProviderEgressTokenRefresh(context.session.threadId).catch(() => void 0);
152668
+ this.handleProviderEgressTokenRefresh(context.session.threadId).catch((error) => {
152669
+ this.emitErrorEvent(context, "session/tokenRefreshFailed", error instanceof Error ? error.message : String(error));
152670
+ });
153212
152671
  }, delayMs);
153213
152672
  tokenRefreshTimer.unref?.();
153214
152673
  context.tokenRefreshTimer = tokenRefreshTimer;
@@ -290471,93 +289930,6 @@ async function maybeRefreshRuntimeProvisioningGrant(input) {
290471
289930
  return "refreshed";
290472
289931
  }
290473
289932
  //#endregion
290474
- //#region src/runtimeDrain/RuntimeDrainState.ts
290475
- const initialState = {
290476
- activeTurns: /* @__PURE__ */ new Set(),
290477
- activeTurnCount: 0,
290478
- activeSessionCount: 0,
290479
- draining: false,
290480
- drainReason: null,
290481
- drainTargetImageRef: null,
290482
- drainTargetImageVersion: null,
290483
- drainForceRequired: false
290484
- };
290485
- function snapshotFromState(state) {
290486
- return {
290487
- activeTurnCount: state.activeTurnCount,
290488
- activeSessionCount: state.activeSessionCount,
290489
- draining: state.draining,
290490
- drainReason: state.drainReason,
290491
- drainTargetImageRef: state.drainTargetImageRef,
290492
- drainTargetImageVersion: state.drainTargetImageVersion,
290493
- drainForceRequired: state.drainForceRequired
290494
- };
290495
- }
290496
- function turnKey(input) {
290497
- return `${input.threadId}:${input.turnId ?? "unknown"}`;
290498
- }
290499
- function normalizeCount(count) {
290500
- return Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0;
290501
- }
290502
- const makeRuntimeDrainState = gen(function* () {
290503
- const stateRef = yield* make$50(initialState);
290504
- const update = (f) => updateAndGet(stateRef, f).pipe(map$3(snapshotFromState));
290505
- return {
290506
- beginTurn: (input) => update((state) => {
290507
- const activeTurns = new Set(state.activeTurns);
290508
- activeTurns.add(turnKey(input));
290509
- return {
290510
- ...state,
290511
- activeTurns,
290512
- activeTurnCount: activeTurns.size
290513
- };
290514
- }),
290515
- completeTurn: (input) => update((state) => {
290516
- const activeTurns = new Set(state.activeTurns);
290517
- activeTurns.delete(turnKey(input));
290518
- return {
290519
- ...state,
290520
- activeTurns,
290521
- activeTurnCount: activeTurns.size
290522
- };
290523
- }),
290524
- clearActiveTurns: update((state) => ({
290525
- ...state,
290526
- activeTurns: /* @__PURE__ */ new Set(),
290527
- activeTurnCount: 0
290528
- })),
290529
- setActiveSessionCount: (count) => update((state) => ({
290530
- ...state,
290531
- activeSessionCount: normalizeCount(count)
290532
- })),
290533
- reconcileProviderSessions: (sessions) => update((state) => {
290534
- const activeSessions = sessions.filter((session) => session.status !== "closed");
290535
- const activeTurns = new Set(activeSessions.flatMap((session) => session.activeTurnId === void 0 ? [] : [turnKey({
290536
- threadId: session.threadId,
290537
- turnId: session.activeTurnId
290538
- })]));
290539
- return {
290540
- ...state,
290541
- activeTurns,
290542
- activeTurnCount: activeTurns.size,
290543
- activeSessionCount: activeSessions.length
290544
- };
290545
- }),
290546
- applyControlPlaneState: (input) => update((state) => ({
290547
- ...state,
290548
- draining: input.draining ?? state.draining,
290549
- drainReason: input.drainReason ?? state.drainReason,
290550
- drainTargetImageRef: input.drainTargetImageRef ?? state.drainTargetImageRef,
290551
- drainTargetImageVersion: input.drainTargetImageVersion ?? state.drainTargetImageVersion,
290552
- drainForceRequired: input.drainForceRequired ?? state.drainForceRequired
290553
- })),
290554
- snapshot: get$6(stateRef).pipe(map$3(snapshotFromState)),
290555
- isDraining: get$6(stateRef).pipe(map$3((state) => state.draining))
290556
- };
290557
- });
290558
- var RuntimeDrainState = class extends Service$1()("forge/runtimeDrain/RuntimeDrainState") {};
290559
- const RuntimeDrainStateLive = effect(RuntimeDrainState, makeRuntimeDrainState);
290560
- //#endregion
290561
289933
  //#region src/runtimeDrain/RuntimeDrainReporter.ts
290562
289934
  const HEARTBEAT_INTERVAL = seconds(30);
290563
289935
  const HEARTBEAT_TICK_TIMEOUT = seconds(60);
@@ -290615,6 +289987,7 @@ const postRuntimeHeartbeat = (config, snapshot) => promise(async () => {
290615
289987
  ...config,
290616
289988
  activeTurnCount: snapshot.activeTurnCount,
290617
289989
  activeSessionCount: snapshot.activeSessionCount,
289990
+ acceptingTurns: snapshot.acceptingTurns,
290618
289991
  ...forgeGitCommit !== void 0 ? { forgeGitCommit } : {},
290619
289992
  forgeServerVersion: installedForgeServerVersion
290620
289993
  });
@@ -290723,6 +290096,7 @@ const makeRuntimeDrainReporter = gen(function* () {
290723
290096
  work: reportOnce,
290724
290097
  interval: HEARTBEAT_INTERVAL
290725
290098
  }));
290099
+ yield* addFinalizer$2(() => drainState.requestShutdown);
290726
290100
  })
290727
290101
  };
290728
290102
  });
@@ -290933,6 +290307,7 @@ function decodeCodexRateLimitWindows(raw) {
290933
290307
  function publicProviderRuntimeError(message) {
290934
290308
  return sanitizePublicProviderText(message, { fallback: DEFAULT_PUBLIC_PROVIDER_ERROR });
290935
290309
  }
290310
+ const processDomainEvent = (_event) => void_$1;
290936
290311
  function isAssistantTextDeltaEvent(event) {
290937
290312
  return event.type === "content.delta" && event.payload.streamKind === "assistant_text";
290938
290313
  }
@@ -291726,7 +291101,6 @@ const ProviderRuntimeIngestionLive = effect(ProviderRuntimeIngestionService, fn$
291726
291101
  yield* runtimeDrainReporter.reportOnce;
291727
291102
  }
291728
291103
  });
291729
- const processDomainEvent = (_event) => void_$1;
291730
291104
  const processInput = (input) => input.source === "runtime" ? processRuntimeEvent(input.event) : processDomainEvent(input.event);
291731
291105
  const processInputSafely = (input) => processInput(input).pipe(catchCause((cause) => {
291732
291106
  if (hasInterruptsOnly(cause)) return failCause$1(cause);
@@ -291777,6 +291151,7 @@ const ProviderRuntimeIngestionLive = effect(ProviderRuntimeIngestionService, fn$
291777
291151
  return {
291778
291152
  start: fn$1("start")(function* () {
291779
291153
  yield* reconcileOrphanedRunningSessions();
291154
+ yield* runtimeDrainState.markExecutionPrecondition("providerLayer");
291780
291155
  yield* runtimeDrainReporter.start;
291781
291156
  yield* forkScoped(runForEach(providerService.streamEvents, (event) => enqueueInput({
291782
291157
  source: "runtime",
@@ -292015,6 +291390,8 @@ const HANDLED_TURN_START_KEY_MAX = 1e4;
292015
291390
  const HANDLED_TURN_START_KEY_TTL = minutes(30);
292016
291391
  const DEFAULT_RUNTIME_MODE = "full-access";
292017
291392
  const DEFAULT_THREAD_TITLE = "New thread";
291393
+ const isProviderValidationError = is$1(ProviderValidationError);
291394
+ const isProviderKind = is$1(ProviderKind);
292018
291395
  function isPathInsideRoot(candidatePath, rootPath) {
292019
291396
  let resolvedCandidate;
292020
291397
  let resolvedRoot;
@@ -292051,6 +291428,38 @@ function resolveExistingWorkspaceCwd(input) {
292051
291428
  function publicProviderFailureDetail(detail) {
292052
291429
  return sanitizePublicProviderText(detail, { fallback: "CMMD is temporarily unavailable. Check the workspace AI connection and retry." }) ?? "CMMD is temporarily unavailable. Check the workspace AI connection and retry.";
292053
291430
  }
291431
+ /**
291432
+ * The failure detail a transcript shows, judged on the text and not the envelope.
291433
+ *
291434
+ * Forge writes its own validation copy, so `ProviderValidationError.issue` is
291435
+ * not raw provider output. Every envelope around it hides it, each in its own
291436
+ * way: `Cause.pretty` prints the error tag, and the sanitizer counts
291437
+ * "ProviderValidationError" as a provider leak, so a validation failure
291438
+ * rendered through `Cause.pretty` tripped the guard on its own wrapper. The
291439
+ * `message` getter spells the same tag out in prose. On 2026-09-16 the first of
291440
+ * those replaced "Reconnect the account and try again" with "CMMD is
291441
+ * temporarily unavailable" (#3337).
291442
+ *
291443
+ * The issue still goes through the sanitizer. `ProviderService` builds some
291444
+ * issues from a schema formatter, which echoes the decoded payload, so this is a
291445
+ * narrower input to the same guard rather than a way around it.
291446
+ */
291447
+ function publicProviderFailureDetailFromError(error) {
291448
+ if (isProviderValidationError(error)) return publicProviderFailureDetail(error.issue);
291449
+ return publicProviderFailureDetail(error instanceof Error ? error.message : String(error));
291450
+ }
291451
+ /**
291452
+ * The same judgement for a failure that arrives as a cause.
291453
+ *
291454
+ * Only the validation branch delegates. A cause carries what a bare error does
291455
+ * not: defects, interrupts, and more than one failure, all of which
291456
+ * `Cause.pretty` renders and `.message` would drop. Squashing every failure into
291457
+ * its message to reach one shared line would lose that.
291458
+ */
291459
+ function publicProviderFailureDetailFromCause(cause) {
291460
+ const error = squash(cause);
291461
+ return isProviderValidationError(error) ? publicProviderFailureDetailFromError(error) : publicProviderFailureDetail(pretty(cause));
291462
+ }
292054
291463
  function canReplaceThreadTitle(currentTitle, titleSeed) {
292055
291464
  const trimmedCurrentTitle = currentTitle.trim();
292056
291465
  if (trimmedCurrentTitle === DEFAULT_THREAD_TITLE) return true;
@@ -292206,7 +291615,7 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
292206
291615
  const thread = readModel.threads.find((entry) => entry.id === threadId);
292207
291616
  if (!thread) return yield* die$1(/* @__PURE__ */ new Error(`Thread '${threadId}' was not found in read model.`));
292208
291617
  const desiredRuntimeMode = thread.runtimeMode;
292209
- const currentProvider = thread.session?.status !== "stopped" && is$1(ProviderKind)(thread.session?.providerName) ? thread.session.providerName : void 0;
291618
+ const currentProvider = thread.session?.status !== "stopped" && isProviderKind(thread.session?.providerName) ? thread.session.providerName : void 0;
292210
291619
  const rawRequestedModelSelection = options?.modelSelection;
292211
291620
  const threadProvider = currentProvider ?? thread.modelSelection.provider;
292212
291621
  const isStaleRequestedProvider = rawRequestedModelSelection !== void 0 && rawRequestedModelSelection.provider !== threadProvider;
@@ -292584,7 +291993,7 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
292584
291993
  threadId: event.payload.threadId,
292585
291994
  kind: "provider.turn.start.failed",
292586
291995
  summary: "Provider turn start failed",
292587
- detail: publicProviderFailureDetail(pretty(cause)),
291996
+ detail: publicProviderFailureDetailFromCause(cause),
292588
291997
  turnId: null,
292589
291998
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
292590
291999
  })));
@@ -292600,7 +292009,14 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
292600
292009
  turnId: event.payload.turnId ?? null,
292601
292010
  createdAt: event.payload.createdAt
292602
292011
  });
292603
- yield* providerService.interruptTurn({ threadId: event.payload.threadId });
292012
+ yield* providerService.interruptTurn({ threadId: event.payload.threadId }).pipe(catchCause((cause) => appendProviderFailureActivity({
292013
+ threadId: event.payload.threadId,
292014
+ kind: "provider.turn.interrupt.failed",
292015
+ summary: "Provider turn interrupt failed",
292016
+ detail: publicProviderFailureDetail(pretty(cause)),
292017
+ turnId: event.payload.turnId ?? null,
292018
+ createdAt: event.payload.createdAt
292019
+ })));
292604
292020
  });
292605
292021
  const processApprovalResponseRequested = fn$1("processApprovalResponseRequested")(function* (event) {
292606
292022
  const staged = peekThreadContinuationSession(event.commandId);
@@ -292637,7 +292053,7 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
292637
292053
  threadId: event.payload.threadId,
292638
292054
  kind: "provider.approval.respond.failed",
292639
292055
  summary: "Provider approval response failed",
292640
- detail: isUnknownPendingApprovalRequestError(cause) ? stalePendingRequestDetail("approval", event.payload.requestId) : publicProviderFailureDetail(pretty(cause)),
292056
+ detail: isUnknownPendingApprovalRequestError(cause) ? stalePendingRequestDetail("approval", event.payload.requestId) : publicProviderFailureDetailFromCause(cause),
292641
292057
  turnId: null,
292642
292058
  createdAt: event.payload.createdAt,
292643
292059
  requestId: event.payload.requestId
@@ -292680,7 +292096,7 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
292680
292096
  threadId: event.payload.threadId,
292681
292097
  kind: "provider.user-input.respond.failed",
292682
292098
  summary: "Provider user input response failed",
292683
- detail: isUnknownPendingUserInputRequestError(cause) ? stalePendingRequestDetail("user-input", event.payload.requestId) : publicProviderFailureDetail(pretty(cause)),
292099
+ detail: isUnknownPendingUserInputRequestError(cause) ? stalePendingRequestDetail("user-input", event.payload.requestId) : publicProviderFailureDetailFromCause(cause),
292684
292100
  turnId: null,
292685
292101
  createdAt: event.payload.createdAt,
292686
292102
  requestId: event.payload.requestId
@@ -292693,8 +292109,7 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
292693
292109
  yield* providerService.stopSession({
292694
292110
  threadId: thread.id,
292695
292111
  ...event.payload.preserveResumeState === true ? { preserveResumeState: true } : {}
292696
- });
292697
- yield* setThreadSession({
292112
+ }).pipe(tap(() => setThreadSession({
292698
292113
  threadId: thread.id,
292699
292114
  session: {
292700
292115
  threadId: thread.id,
@@ -292706,7 +292121,14 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
292706
292121
  updatedAt: now
292707
292122
  },
292708
292123
  createdAt: now
292709
- });
292124
+ })), catchCause((cause) => appendProviderFailureActivity({
292125
+ threadId: event.payload.threadId,
292126
+ kind: "provider.session.stop.failed",
292127
+ summary: "Provider session stop failed",
292128
+ detail: publicProviderFailureDetail(pretty(cause)),
292129
+ turnId: null,
292130
+ createdAt: now
292131
+ })));
292710
292132
  });
292711
292133
  const processDomainEvent = fn$1("processDomainEvent")(function* (event) {
292712
292134
  yield* annotateCurrentSpan({
@@ -292801,7 +292223,7 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
292801
292223
  threadId: event.payload.threadId,
292802
292224
  kind: "provider.turn.start.failed",
292803
292225
  summary: "Provider turn start cleanup failed",
292804
- detail: publicProviderFailureDetail(cause instanceof Error ? cause.message : String(cause)),
292226
+ detail: publicProviderFailureDetailFromError(cause),
292805
292227
  turnId: null,
292806
292228
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
292807
292229
  })
@@ -298221,7 +297643,7 @@ function resolveBuildCommitFromEnv(env) {
298221
297643
  * environment descriptor down instead of reporting an honest "unknown".
298222
297644
  */
298223
297645
  function readBakedBuildCommit() {
298224
- return "78b0e072680ed734c4eb8337a6d38c87e7e34393";
297646
+ return "60c000d9c894e2ef04f90b602ddc8eb49c84980a";
298225
297647
  }
298226
297648
  async function resolveServerBuildCommit(input) {
298227
297649
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -321588,7 +321010,7 @@ const PlatformServicesLive = unwrap(gen(function* () {
321588
321010
  }));
321589
321011
  const RuntimeReplicationLayerLive = RuntimeReplicationLive.pipe(provideMerge(RuntimeReplicationClientLive), provideMerge(RuntimeReplicationOutboxLive), provideMerge(ActiveHourMeterLive.pipe(provide$1(RuntimeReplicationOutboxLive))));
321590
321012
  const RuntimeDrainLayerLive = RuntimeDrainReporterLive.pipe(provideMerge(RuntimeDrainStateLive));
321591
- const RuntimeAwareProviderReactorsLive = mergeAll(ProviderRuntimeIngestionLive, ProviderCommandReactorLive).pipe(provide$1(RuntimeDrainLayerLive), provide$1(ClaudeUsageTelemetryLive));
321013
+ const RuntimeAwareProviderReactorsLive = mergeAll(ProviderRuntimeIngestionLive, ProviderCommandReactorLive).pipe(provide$1(RuntimeDrainLayerLive), provideMerge(RuntimeDrainStateLive), provide$1(ClaudeUsageTelemetryLive));
321592
321014
  const PipelineWorkerCoordinatorLayerLive = PipelineWorkerCoordinatorLive.pipe(provideMerge(PipelineRunClientLive));
321593
321015
  const AgentProtocolReactorLayerLive = AgentProtocolReactorLive.pipe(provideMerge(PipelineRunStoreLive));
321594
321016
  const PipelineRunCoordinatorLayerLive = PipelineRunCoordinatorLive.pipe(provideMerge(PipelineProviderAuthorityInstallerLive), provideMerge(PipelineChangeInspectorLive), provideMerge(PipelineContextArtifactStoreLive), provideMerge(PipelineModelPolicyLive), provideMerge(PipelineRunClientLive), provideMerge(PipelineRunStoreLive), provideMerge(PipelineRunWorkspaceAllocatorLive), provideMerge(PipelineStagePolicyLive), provideMerge(PipelineWorkerCoordinatorLayerLive));