@cmmd-center/forge 0.13.89 → 0.13.91

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 (21) hide show
  1. package/dist/bin.cjs +377 -50
  2. package/dist/bin.mjs +398 -74
  3. package/dist/client/assets/{CanvasPanel-D9NzolmF.js → CanvasPanel-By1TNSCJ.js} +2 -2
  4. package/dist/client/assets/{CompositeItem-DU4kdAw6.js → CompositeItem-B4KFI6uM.js} +2 -2
  5. package/dist/client/assets/{DiffPanel-Dx1AY0mg.js → DiffPanel-BiNw2LQH.js} +2 -2
  6. package/dist/client/assets/{DiffPanel.logic-BiyBXIja.js → DiffPanel.logic-w5A538H2.js} +2 -2
  7. package/dist/client/assets/{DiffWorkerPoolProvider-jDqu6eJj.js → DiffWorkerPoolProvider-NwR6dTfX.js} +2 -2
  8. package/dist/client/assets/{PullRequestCodePanel-CqrN4lB_.js → PullRequestCodePanel-CkPd76Ea.js} +2 -2
  9. package/dist/client/assets/{Virtualizer-D-5QCW79.js → Virtualizer-BBvJHcYh.js} +2 -2
  10. package/dist/client/assets/{WorkerPoolContext-BxfSg7K_.js → WorkerPoolContext-BAaHKB2s.js} +3 -3
  11. package/dist/client/assets/{canvasStateStore-CBQkAlnK.js → canvasStateStore-DoXLRnB-.js} +2 -2
  12. package/dist/client/assets/{cmmdAuthRedirect-CCwq2L-I.js → cmmdAuthRedirect-Bx5ApJLL.js} +2 -2
  13. package/dist/client/assets/{index-BrOo-A0J.js → index-kD30f58L.js} +6 -6
  14. package/dist/client/assets/{popover-DJpPSHsy.js → popover-DlZTqPIV.js} +2 -2
  15. package/dist/client/assets/src-1F7f5y9L.js +3 -0
  16. package/dist/client/assets/{toggle-Bv2GfLGu.js → toggle-BwedUJ-z.js} +2 -2
  17. package/dist/client/index.html +10 -10
  18. package/dist/forge-build.json +1 -1
  19. package/dist/{open-yHTUkd2Y.mjs → open-2-reBrpv.mjs} +3 -3
  20. package/package.json +1 -1
  21. package/dist/client/assets/src-CF8xm6xH.js +0 -3
package/dist/bin.cjs CHANGED
@@ -17845,6 +17845,7 @@ const OrchestrationThread = require_Schema$1.Struct({
17845
17845
  parentThreadId: require_Schema$1.NullOr(ThreadId).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
17846
17846
  status: ThreadStatus.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("idle"))),
17847
17847
  workerRole: require_Schema$1.NullOr(WorkerRole).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
17848
+ workSessionId: require_Schema$1.optionalKey(require_Schema$1.NullOr(require_Schema$1.String)),
17848
17849
  pendingAutoCreatePrompt: require_Schema$1.optional(require_Schema$1.NullOr(AutoCreateTaskPrompt)).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
17849
17850
  goal: require_Schema$1.NullOr(TrimmedNonEmptyString).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
17850
17851
  titleRegeneration: require_Schema$1.NullOr(ThreadTitleRegeneration).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
@@ -18000,6 +18001,15 @@ const ProjectDeleteCommand = require_Schema$1.Struct({
18000
18001
  commandId: CommandId,
18001
18002
  projectId: ProjectId
18002
18003
  });
18004
+ /**
18005
+ * The CMMD Work Session id a command may carry (forge#3466 review, nit 9).
18006
+ * CMMD's capability broker requires 1 to 256 characters; bounding it here
18007
+ * rejects a malformed id at the door instead of letting decide-time code find
18008
+ * out. Command-only: the read model and its events keep decoding a plain
18009
+ * string so a row or a journaled event written before this bound existed
18010
+ * still loads.
18011
+ */
18012
+ const CommandWorkSessionId = TrimmedNonEmptyString.check(require_Schema$1.isMaxLength(256));
18003
18013
  const ThreadCreateCommand = require_Schema$1.Struct({
18004
18014
  type: require_Schema$1.Literal("thread.create"),
18005
18015
  commandId: CommandId,
@@ -18013,6 +18023,7 @@ const ThreadCreateCommand = require_Schema$1.Struct({
18013
18023
  worktreePath: require_Schema$1.NullOr(TrimmedNonEmptyString),
18014
18024
  anchorKind: require_Schema$1.optional(CmmdAnchorKind),
18015
18025
  anchorCmmdId: require_Schema$1.optional(require_Schema$1.NullOr(require_Schema$1.String)),
18026
+ workSessionId: require_Schema$1.optional(require_Schema$1.NullOr(CommandWorkSessionId)),
18016
18027
  goal: require_Schema$1.optional(require_Schema$1.NullOr(TrimmedNonEmptyString)),
18017
18028
  linkedPullRequest: require_Schema$1.optional(require_Schema$1.NullOr(LinkedPullRequest)),
18018
18029
  kind: require_Schema$1.optional(ThreadKind),
@@ -18122,7 +18133,8 @@ const ThreadTurnStartCommand = require_Schema$1.Struct({
18122
18133
  anchorCmmdId: require_Schema$1.optional(require_Schema$1.NullOr(require_Schema$1.String)),
18123
18134
  kind: require_Schema$1.optional(ThreadKind),
18124
18135
  parentThreadId: require_Schema$1.optional(require_Schema$1.NullOr(ThreadId)),
18125
- createdAt: IsoDateTime
18136
+ createdAt: IsoDateTime,
18137
+ workSessionId: require_Schema$1.optional(require_Schema$1.NullOr(CommandWorkSessionId))
18126
18138
  });
18127
18139
  const ClientThreadTurnStartCommand = require_Schema$1.Struct({
18128
18140
  type: require_Schema$1.Literal("thread.turn.start"),
@@ -18145,7 +18157,8 @@ const ClientThreadTurnStartCommand = require_Schema$1.Struct({
18145
18157
  anchorCmmdId: require_Schema$1.optional(require_Schema$1.NullOr(require_Schema$1.String)),
18146
18158
  kind: require_Schema$1.optional(ThreadKind),
18147
18159
  parentThreadId: require_Schema$1.optional(require_Schema$1.NullOr(ThreadId)),
18148
- createdAt: IsoDateTime
18160
+ createdAt: IsoDateTime,
18161
+ workSessionId: require_Schema$1.optional(require_Schema$1.NullOr(CommandWorkSessionId))
18149
18162
  });
18150
18163
  const ThreadTurnInterruptCommand = require_Schema$1.Struct({
18151
18164
  type: require_Schema$1.Literal("thread.turn.interrupt"),
@@ -18441,6 +18454,7 @@ const ThreadCreatedPayload$1 = require_Schema$1.Struct({
18441
18454
  settledOverride: require_Schema$1.optional(SettledOverride),
18442
18455
  anchorKind: CmmdAnchorKind.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("scratch"))),
18443
18456
  anchorCmmdId: require_Schema$1.NullOr(require_Schema$1.String).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
18457
+ workSessionId: require_Schema$1.optionalKey(require_Schema$1.NullOr(require_Schema$1.String)),
18444
18458
  goal: require_Schema$1.optionalKey(require_Schema$1.NullOr(TrimmedNonEmptyString)),
18445
18459
  linkedPullRequest: require_Schema$1.optionalKey(require_Schema$1.NullOr(LinkedPullRequest)),
18446
18460
  kind: ThreadKind.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("master"))),
@@ -18482,6 +18496,7 @@ const ThreadMetaUpdatedPayload$1 = require_Schema$1.Struct({
18482
18496
  status: require_Schema$1.optional(ThreadStatus),
18483
18497
  parentThreadId: require_Schema$1.optional(require_Schema$1.NullOr(ThreadId)),
18484
18498
  workerRole: require_Schema$1.optional(require_Schema$1.NullOr(WorkerRole)),
18499
+ workSessionId: require_Schema$1.optional(require_Schema$1.NullOr(require_Schema$1.String)),
18485
18500
  goal: require_Schema$1.optional(require_Schema$1.NullOr(TrimmedNonEmptyString)),
18486
18501
  linkedPullRequest: require_Schema$1.optional(require_Schema$1.NullOr(LinkedPullRequest)),
18487
18502
  regenerateTitle: require_Schema$1.optional(require_Schema$1.Literal(true)),
@@ -66296,7 +66311,7 @@ function normalizeNumberish(value) {
66296
66311
  }
66297
66312
  //#endregion
66298
66313
  //#region package.json
66299
- var version$1 = "0.13.89";
66314
+ var version$1 = "0.13.91";
66300
66315
  //#endregion
66301
66316
  //#region src/sentry.ts
66302
66317
  const SERVER_APP_NAME = "forge-server";
@@ -87937,7 +87952,8 @@ const brokerScopes = new Set([
87937
87952
  "github",
87938
87953
  "provider",
87939
87954
  "package",
87940
- "scm"
87955
+ "scm",
87956
+ "sidekick"
87941
87957
  ]);
87942
87958
  const defaultOwnerId = "interactive";
87943
87959
  const authorities = /* @__PURE__ */ new Map();
@@ -88091,6 +88107,19 @@ function readRuntimeBrokerAuthorityForRuntime(input) {
88091
88107
  }
88092
88108
  //#endregion
88093
88109
  //#region src/runtimeAuth/runtimeBrokerIdentity.ts
88110
+ /**
88111
+ * Whether this process is a CMMD-managed per-project cloud runtime (a
88112
+ * sprite), never a local Forge desktop or dev process. Shared by
88113
+ * `GitHubBroker.resolveRuntimeGrant` and
88114
+ * `cmmdWorkSessionCapabilityBroker.resolveWorkSessionSidekickRuntimeGrant`
88115
+ * (forge#3466 review, should-fix 4) so the two runtime-grant resolvers gate
88116
+ * on the same runtime-role signal instead of each inferring it separately.
88117
+ * Mirrors the env parsing `providerEgressToken.ts` and `ServerEnvironment.ts`
88118
+ * already use for the same signal.
88119
+ */
88120
+ function isCmmdCloudRuntimeModeEnv() {
88121
+ return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
88122
+ }
88094
88123
  function classifyRuntimeBrokerIdentity(input) {
88095
88124
  const machineId = input.machineId?.trim();
88096
88125
  const credentialEpoch = input.credentialEpoch;
@@ -91115,9 +91144,6 @@ var GitHubBroker = class {
91115
91144
  return validateGitBranchName(branch) ?? branch;
91116
91145
  }
91117
91146
  };
91118
- function isCmmdCloudRuntimeModeEnv() {
91119
- return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
91120
- }
91121
91147
  function inferGitHubBrokerRuntimeRole() {
91122
91148
  if (isCmmdCloudRuntimeModeEnv()) return "user-vm";
91123
91149
  return "local";
@@ -115686,7 +115712,7 @@ const postgresSchemaStatements = [
115686
115712
  "CREATE TABLE IF NOT EXISTS checkpoint_diff_blobs (\n thread_id TEXT NOT NULL,\n from_turn_count INTEGER NOT NULL,\n to_turn_count INTEGER NOT NULL,\n diff TEXT NOT NULL,\n created_at TEXT NOT NULL,\n UNIQUE (thread_id, from_turn_count, to_turn_count)\n )",
115687
115713
  "CREATE TABLE IF NOT EXISTS provider_session_runtime (\n thread_id TEXT PRIMARY KEY,\n provider_name TEXT NOT NULL,\n adapter_key TEXT NOT NULL,\n runtime_mode TEXT NOT NULL DEFAULT 'full-access',\n status TEXT NOT NULL,\n last_seen_at TEXT NOT NULL,\n resume_cursor_json TEXT,\n runtime_payload_json TEXT\n )",
115688
115714
  "CREATE TABLE IF NOT EXISTS projection_projects (\n project_id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n workspace_root TEXT NOT NULL,\n scripts_json TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT\n , default_model_selection_json TEXT, default_thread_env_mode TEXT, cmmd_registration_json TEXT)",
115689
- "CREATE TABLE IF NOT EXISTS projection_threads (\n thread_id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL,\n title TEXT NOT NULL,\n branch TEXT,\n worktree_path TEXT,\n latest_turn_id TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT\n , runtime_mode TEXT NOT NULL DEFAULT 'full-access', interaction_mode TEXT NOT NULL DEFAULT 'default', model_selection_json TEXT, archived_at TEXT, latest_user_message_at TEXT, pending_approval_count INTEGER NOT NULL DEFAULT 0, pending_user_input_count INTEGER NOT NULL DEFAULT 0, has_actionable_proposed_plan INTEGER NOT NULL DEFAULT 0, kind TEXT NOT NULL DEFAULT 'master', parent_thread_id TEXT, status TEXT NOT NULL DEFAULT 'idle', anchor_kind TEXT NOT NULL DEFAULT 'scratch', anchor_cmmd_id TEXT, worker_role TEXT DEFAULT NULL, goal TEXT, pending_auto_create_prompt_json TEXT, title_regeneration_json TEXT, rate_limit_status_json TEXT, linked_pull_request_json TEXT, settled_at TEXT, settled_override TEXT)",
115715
+ "CREATE TABLE IF NOT EXISTS projection_threads (\n thread_id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL,\n title TEXT NOT NULL,\n branch TEXT,\n worktree_path TEXT,\n latest_turn_id TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT\n , runtime_mode TEXT NOT NULL DEFAULT 'full-access', interaction_mode TEXT NOT NULL DEFAULT 'default', model_selection_json TEXT, archived_at TEXT, latest_user_message_at TEXT, pending_approval_count INTEGER NOT NULL DEFAULT 0, pending_user_input_count INTEGER NOT NULL DEFAULT 0, has_actionable_proposed_plan INTEGER NOT NULL DEFAULT 0, kind TEXT NOT NULL DEFAULT 'master', parent_thread_id TEXT, status TEXT NOT NULL DEFAULT 'idle', anchor_kind TEXT NOT NULL DEFAULT 'scratch', anchor_cmmd_id TEXT, worker_role TEXT DEFAULT NULL, goal TEXT, pending_auto_create_prompt_json TEXT, title_regeneration_json TEXT, rate_limit_status_json TEXT, linked_pull_request_json TEXT, settled_at TEXT, settled_override TEXT, work_session_id TEXT)",
115690
115716
  "CREATE TABLE IF NOT EXISTS projection_thread_messages (\n message_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n role TEXT NOT NULL,\n text TEXT NOT NULL,\n is_streaming INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n , attachments_json TEXT)",
115691
115717
  "CREATE TABLE IF NOT EXISTS projection_thread_activities (\n activity_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n tone TEXT NOT NULL,\n kind TEXT NOT NULL,\n summary TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n created_at TEXT NOT NULL\n , sequence INTEGER)",
115692
115718
  "CREATE TABLE IF NOT EXISTS projection_thread_sessions (\n thread_id TEXT PRIMARY KEY,\n status TEXT NOT NULL,\n provider_name TEXT,\n provider_session_id TEXT,\n provider_thread_id TEXT,\n active_turn_id TEXT,\n last_error TEXT,\n updated_at TEXT NOT NULL\n , runtime_mode TEXT NOT NULL DEFAULT 'full-access')",
@@ -116007,7 +116033,8 @@ const postgresUpgradeMigrations = new Map([
116007
116033
  LIMIT 1
116008
116034
  )
116009
116035
  WHERE model_selection_json IS NULL`
116010
- ]]
116036
+ ]],
116037
+ [77, [`ALTER TABLE projection_threads ADD COLUMN IF NOT EXISTS work_session_id TEXT`]]
116011
116038
  ]);
116012
116039
  function requirePostgresUpgradeStatements(version) {
116013
116040
  const statements = postgresUpgradeMigrations.get(version);
@@ -116033,15 +116060,15 @@ const runPostgresMigrations = require_Schema$1.fn("runPostgresMigrations")(funct
116033
116060
  ORDER BY version DESC
116034
116061
  LIMIT 1
116035
116062
  `)[0]?.version ?? 0;
116036
- if (currentVersion > 76) return yield* require_Schema$1.die(/* @__PURE__ */ new Error(`Forge Postgres schema ${currentVersion} is newer than server schema 76.`));
116063
+ if (currentVersion > 77) return yield* require_Schema$1.die(/* @__PURE__ */ new Error(`Forge Postgres schema ${currentVersion} is newer than server schema 77.`));
116037
116064
  if (currentVersion === 0) {
116038
116065
  for (const statement of postgresSchemaStatements) yield* sql.unsafe(statement);
116039
116066
  yield* sql`
116040
116067
  INSERT INTO forge_schema_migrations (version)
116041
- VALUES (${76})
116068
+ VALUES (${77})
116042
116069
  ON CONFLICT (version) DO NOTHING
116043
116070
  `;
116044
- } else for (let version = currentVersion + 1; version <= 76; version += 1) {
116071
+ } else for (let version = currentVersion + 1; version <= 77; version += 1) {
116045
116072
  const statements = yield* require_Schema$1.sync(() => requirePostgresUpgradeStatements(version));
116046
116073
  for (const statement of statements) yield* sql.unsafe(statement);
116047
116074
  yield* sql`
@@ -118826,6 +118853,18 @@ var _076_ProjectionTurnsModelSelection_default = require_Schema$1.gen(function*
118826
118853
  `;
118827
118854
  });
118828
118855
  //#endregion
118856
+ //#region src/persistence/Migrations/077_ProjectionThreadWorkSessionId.ts
118857
+ /** Stores the CMMD Work Session id a kicked thread's root turn belongs to (forge#3466). */
118858
+ var _077_ProjectionThreadWorkSessionId_default = require_Schema$1.gen(function* () {
118859
+ const sql = yield* require_SqlError.SqlClient;
118860
+ if (!(yield* sql`
118861
+ PRAGMA table_info(projection_threads)
118862
+ `).some((column) => column.name === "work_session_id")) yield* sql`
118863
+ ALTER TABLE projection_threads
118864
+ ADD COLUMN work_session_id TEXT
118865
+ `;
118866
+ });
118867
+ //#endregion
118829
118868
  //#region src/persistence/Migrations.ts
118830
118869
  /**
118831
118870
  * MigrationsLive - Migration runner with inline loader
@@ -119226,6 +119265,11 @@ const migrationEntries = [
119226
119265
  76,
119227
119266
  "ProjectionTurnsModelSelection",
119228
119267
  _076_ProjectionTurnsModelSelection_default
119268
+ ],
119269
+ [
119270
+ 77,
119271
+ "ProjectionThreadWorkSessionId",
119272
+ _077_ProjectionThreadWorkSessionId_default
119229
119273
  ]
119230
119274
  ];
119231
119275
  const makeMigrationLoader = (throughId) => fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
@@ -152591,10 +152635,10 @@ function getOpenAiProviderEgressProxyConfig(input) {
152591
152635
  message: `Workspace OpenAI provider egress is configured, but OPENAI_BASE_URL does not point at ${OPENAI_PROVIDER_EGRESS_PATH}. Refusing to start Codex with a stale or raw OPENAI_API_KEY.`
152592
152636
  };
152593
152637
  }
152594
- function configuredRuntimeMachineId() {
152638
+ function configuredRuntimeMachineId$1() {
152595
152639
  return process.env.FORGE_CMMD_RUNTIME_MACHINE_ID?.trim() || null;
152596
152640
  }
152597
- function configuredRuntimeCredentialEpoch() {
152641
+ function configuredRuntimeCredentialEpoch$1() {
152598
152642
  const raw = process.env.FORGE_CMMD_RUNTIME_CREDENTIAL_EPOCH?.trim();
152599
152643
  return raw === void 0 ? void 0 : Number(raw);
152600
152644
  }
@@ -152665,15 +152709,15 @@ function resolveBrokerTicketOutcome(input) {
152665
152709
  function providerEgressRequiresOwnerSession() {
152666
152710
  if (!canIssueCmmdRuntimeProviderEgressToken()) return false;
152667
152711
  return classifyRuntimeBrokerIdentity({
152668
- machineId: configuredRuntimeMachineId() ?? void 0,
152669
- credentialEpoch: configuredRuntimeCredentialEpoch(),
152712
+ machineId: configuredRuntimeMachineId$1() ?? void 0,
152713
+ credentialEpoch: configuredRuntimeCredentialEpoch$1(),
152670
152714
  brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
152671
152715
  }).mode === "exact";
152672
152716
  }
152673
152717
  function runtimeProviderBrokerToken(input) {
152674
152718
  const identity = classifyRuntimeBrokerIdentity({
152675
- machineId: configuredRuntimeMachineId() ?? void 0,
152676
- credentialEpoch: configuredRuntimeCredentialEpoch(),
152719
+ machineId: configuredRuntimeMachineId$1() ?? void 0,
152720
+ credentialEpoch: configuredRuntimeCredentialEpoch$1(),
152677
152721
  brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
152678
152722
  });
152679
152723
  if (identity.mode !== "exact") return resolveBrokerTicketOutcome({
@@ -152788,7 +152832,8 @@ async function issueCmmdRuntimeProviderEgressCredential(input) {
152788
152832
  body: JSON.stringify({
152789
152833
  provider: input.provider,
152790
152834
  ...providerEgressModelBodyFields(input),
152791
- ...input.provider === "openai" && input.providerAccountId ? { provider_account_id: input.providerAccountId } : {}
152835
+ ...input.provider === "openai" && input.providerAccountId ? { provider_account_id: input.providerAccountId } : {},
152836
+ ...input.threadId ? { thread_id: input.threadId } : {}
152792
152837
  })
152793
152838
  });
152794
152839
  if (!response.ok) throw new Error(await describeProviderTokenFailure(response));
@@ -152813,8 +152858,8 @@ function runtimeCredentialFromGrant(provider, payload, controlPlaneUrl) {
152813
152858
  return deliveryBoundRuntimeCredential(provider, payload, controlPlaneUrl);
152814
152859
  }
152815
152860
  function deliveryBoundRuntimeCredential(provider, payload, controlPlaneUrl) {
152816
- const runtimeMachineId = configuredRuntimeMachineId();
152817
- const runtimeCredentialEpoch = configuredRuntimeCredentialEpoch();
152861
+ const runtimeMachineId = configuredRuntimeMachineId$1();
152862
+ const runtimeCredentialEpoch = configuredRuntimeCredentialEpoch$1();
152818
152863
  if (!runtimeMachineId || runtimeCredentialEpoch === void 0) throw new Error("Provider proxy token response was missing exact runtime authority.");
152819
152864
  const deliveryReceipt = parseProviderRuntimeDeliveryReceipt(payload.deliveryReceipt, {
152820
152865
  provider,
@@ -211956,7 +212001,7 @@ function createCodexCmmdSidekickDynamicToolHandler(session) {
211956
212001
  //#region src/cmmdData/cmmdDelegatedToolCatalog.ts
211957
212002
  const CATALOG_PATH = "/api/forge/context/sidekick/tools/catalog";
211958
212003
  const EXECUTE_PATH = "/api/forge/context/sidekick/tools/execute";
211959
- const AUTH_REQUIRED = {
212004
+ const AUTH_REQUIRED$1 = {
211960
212005
  ok: false,
211961
212006
  code: "CMMD_AUTH_REQUIRED"
211962
212007
  };
@@ -211964,11 +212009,32 @@ function upstreamErrorCode(error) {
211964
212009
  if (error && typeof error === "object" && "code" in error && typeof error.code === "string") return error.code;
211965
212010
  return "CMMD_REST_ERROR";
211966
212011
  }
211967
- async function listCatalog(resolveJwt, scope) {
212012
+ /**
212013
+ * The Work Session lane, tried before the owner-JWT lane ever runs
212014
+ * (forge#3466 review, should-fix 3). A headless sprite's Work Session thread
212015
+ * never carries an owner JWT (CMMD ADR-015), so trying that lane first only
212016
+ * spends a lookup before falling through to the same broker call every time
212017
+ * — and on a sprite in runtime mode, the owner's browser and CMMD's kick
212018
+ * authenticate into the same synthetic session, so a resolved JWT there is
212019
+ * never legitimately this Work Session's own. Reading fresh on every call,
212020
+ * not once at construction, is what makes blocker 1's fix work: session
212021
+ * start, the ~30-second renewal, and a post-`capability_invalid` re-mint all
212022
+ * land here, so a Retry that rebinds the thread mid-session is picked up on
212023
+ * its very next mint instead of being stuck asking for the session that just
212024
+ * failed. Returns null (not a failure) for a person-started thread, which
212025
+ * supplies no `readWorkSessionId` and keeps today's owner lane byte for byte.
212026
+ */
212027
+ async function resolveViaWorkSession(workSessionCapability, scope) {
212028
+ const workSessionId = workSessionCapability.readWorkSessionId ? await workSessionCapability.readWorkSessionId() : null;
212029
+ if (workSessionId === null) return null;
212030
+ return workSessionCapability.requestCapability ? workSessionCapability.requestCapability(workSessionId, scope.threadId) : AUTH_REQUIRED$1;
212031
+ }
212032
+ async function listCatalog(resolveJwt, workSessionCapability, scope) {
212033
+ const viaWorkSession = await resolveViaWorkSession(workSessionCapability, scope);
212034
+ if (viaWorkSession !== null) return viaWorkSession;
211968
212035
  const sessionId = readThreadSessionId(scope.threadId);
211969
- if (!sessionId) return AUTH_REQUIRED;
211970
- const jwt = await resolveJwt(sessionId);
211971
- if (!jwt) return AUTH_REQUIRED;
212036
+ const jwt = sessionId ? await resolveJwt(sessionId) : null;
212037
+ if (!jwt) return AUTH_REQUIRED$1;
211972
212038
  const body = { forgeThreadId: scope.threadId };
211973
212039
  if (scope.projectId !== void 0) body["projectId"] = scope.projectId;
211974
212040
  if (scope.forgeAgentId !== void 0) body["forgeAgentId"] = scope.forgeAgentId;
@@ -212018,9 +212084,9 @@ async function execute(request) {
212018
212084
  };
212019
212085
  }
212020
212086
  }
212021
- function createCmmdDelegatedToolCatalogClient(resolveJwt) {
212087
+ function createCmmdDelegatedToolCatalogClient(resolveJwt, workSessionCapability = {}) {
212022
212088
  return {
212023
- listCatalog: (scope) => listCatalog(resolveJwt, scope),
212089
+ listCatalog: (scope) => listCatalog(resolveJwt, workSessionCapability, scope),
212024
212090
  execute
212025
212091
  };
212026
212092
  }
@@ -212075,9 +212141,144 @@ function createCmmdSidekickToolSession(client, scope) {
212075
212141
  };
212076
212142
  }
212077
212143
  //#endregion
212144
+ //#region src/cmmdData/cmmdWorkSessionCapabilityBroker.ts
212145
+ /**
212146
+ * CMMD's Work Session Sidekick-capability broker client (forge#3466,
212147
+ * CMMD#5026).
212148
+ *
212149
+ * A headless sprite runs a Work Session's root thread with no owner JWT or
212150
+ * PAT: nobody signed in. `cmmdDelegatedToolCatalog.ts`'s owner-JWT lane falls
212151
+ * through to this one instead, presenting the runtime's OWN grant (never a
212152
+ * JWT, per CMMD ADR-015) plus the Work Session id CMMD stamped on the thread,
212153
+ * and getting back the same delegated Sidekick capability shape the owner
212154
+ * lane mints.
212155
+ */
212156
+ const SIDEKICK_CAPABILITY_TIMEOUT_MS = 1e4;
212157
+ const AUTH_REQUIRED = {
212158
+ ok: false,
212159
+ code: "CMMD_AUTH_REQUIRED"
212160
+ };
212161
+ function configuredRuntimeMachineId() {
212162
+ return process.env.FORGE_CMMD_RUNTIME_MACHINE_ID?.trim() || void 0;
212163
+ }
212164
+ function configuredRuntimeCredentialEpoch() {
212165
+ const raw = process.env.FORGE_CMMD_RUNTIME_CREDENTIAL_EPOCH?.trim();
212166
+ return raw === void 0 ? void 0 : Number(raw);
212167
+ }
212168
+ /**
212169
+ * The runtime's own bearer for the "sidekick" broker scope.
212170
+ *
212171
+ * Follows the same exact-machine / legacy split as
212172
+ * `GitHubBroker.resolveRuntimeGrant`, including its `runtimeRole !== "user-vm"`
212173
+ * gate (forge#3466 review, should-fix 4, via the resolver both share:
212174
+ * `isCmmdCloudRuntimeModeEnv`): an exact-machine runtime presents whatever
212175
+ * ticket CMMD already delivered into the broker-authority cache for this
212176
+ * scope (an inbound request installs it as a side effect of authenticating;
212177
+ * CMMD's runtime ticket carries `sidekick` alongside `provider`/`github`/etc,
212178
+ * so it lands there the same way). A legacy runtime presents its one
212179
+ * portable grant token. A runtime with no id, an identity that is neither
212180
+ * exact nor legacy, or a role that isn't a managed CMMD cloud runtime at
212181
+ * all, has nothing to present — a local Forge with a stray
212182
+ * `FORGE_CMMD_RUNTIME_ID` left over from a legacy config must never present
212183
+ * its portable grant token as though it were a sprite.
212184
+ */
212185
+ function resolveWorkSessionSidekickRuntimeGrant() {
212186
+ if (!isCmmdCloudRuntimeModeEnv()) return null;
212187
+ const runtimeId = process.env.FORGE_CMMD_RUNTIME_ID?.trim();
212188
+ if (!runtimeId) return null;
212189
+ const identity = classifyRuntimeBrokerIdentity({
212190
+ machineId: configuredRuntimeMachineId(),
212191
+ credentialEpoch: configuredRuntimeCredentialEpoch(),
212192
+ brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
212193
+ });
212194
+ if (identity.mode === "exact") {
212195
+ const authority = readRuntimeBrokerAuthorityForRuntime({
212196
+ runtimeId,
212197
+ machineId: identity.machineId,
212198
+ credentialEpoch: identity.credentialEpoch,
212199
+ requiredScope: "sidekick"
212200
+ });
212201
+ return authority ? {
212202
+ runtimeId,
212203
+ token: authority.token
212204
+ } : null;
212205
+ }
212206
+ if (identity.mode === "invalid") return null;
212207
+ const legacyToken = require_runtimeControlAuthority.runtimeGrantToken();
212208
+ return legacyToken ? {
212209
+ runtimeId,
212210
+ token: legacyToken
212211
+ } : null;
212212
+ }
212213
+ function isRawSidekickCapabilityResponse(value) {
212214
+ if (typeof value !== "object" || value === null) return false;
212215
+ const record = value;
212216
+ return Array.isArray(record.tools) && typeof record.catalogVersion === "string" && typeof record.capabilitySessionId === "number" && typeof record.capabilityToken === "string" && typeof record.expiresAt === "string";
212217
+ }
212218
+ /**
212219
+ * Mints a Work Session Sidekick capability straight from CMMD, for a thread
212220
+ * whose owner JWT never resolved.
212221
+ *
212222
+ * The mint route answers a bare JSON body, never CMMD's forge-context
212223
+ * `{ data: ... }` envelope the owner-JWT catalog route uses, so this never
212224
+ * unwraps `.data`. Always resolves, never throws: a missing runtime grant, a
212225
+ * network failure, and a refusal from CMMD (the broker feature flag is off,
212226
+ * the Work Session ended, this runtime is not its starter, ...) all fold to
212227
+ * the same `CMMD_AUTH_REQUIRED` the owner-JWT lane already returns on any
212228
+ * auth failure, so callers need exactly one failure branch. The refusal's
212229
+ * own code is logged, not returned, so an operator can still tell the cases
212230
+ * apart.
212231
+ */
212232
+ async function requestWorkSessionSidekickCapability(workSessionId, threadId, deps = {}) {
212233
+ const grant = (deps.resolveRuntimeGrant ?? resolveWorkSessionSidekickRuntimeGrant)();
212234
+ if (!grant) {
212235
+ console.warn(`[cmmd-work-session-capability] no runtime grant for the sidekick scope (thread ${threadId}, work session ${workSessionId})`);
212236
+ return AUTH_REQUIRED;
212237
+ }
212238
+ const fetchImpl = deps.fetch ?? fetch;
212239
+ const url = resolveCommandAppEndpoint(`/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/sidekick-capability`);
212240
+ let response;
212241
+ try {
212242
+ response = await fetchImpl(url, {
212243
+ method: "POST",
212244
+ headers: {
212245
+ Authorization: `Bearer ${grant.token}`,
212246
+ "Content-Type": "application/json"
212247
+ },
212248
+ body: JSON.stringify({ workSessionId }),
212249
+ signal: AbortSignal.timeout(SIDEKICK_CAPABILITY_TIMEOUT_MS)
212250
+ });
212251
+ } catch (error) {
212252
+ console.warn("[cmmd-work-session-capability] broker request failed:", error instanceof Error ? error.message : String(error));
212253
+ return AUTH_REQUIRED;
212254
+ }
212255
+ if (!response.ok) {
212256
+ const body = await response.json().catch(() => null);
212257
+ const code = body && typeof body === "object" && typeof body.code === "string" ? body.code : `HTTP_${response.status}`;
212258
+ console.warn(`[cmmd-work-session-capability] broker refused the mint (${code})`);
212259
+ return AUTH_REQUIRED;
212260
+ }
212261
+ const data = await response.json().catch(() => null);
212262
+ if (!isRawSidekickCapabilityResponse(data)) {
212263
+ console.warn("[cmmd-work-session-capability] broker returned an unexpected mint response");
212264
+ return AUTH_REQUIRED;
212265
+ }
212266
+ return {
212267
+ ok: true,
212268
+ tools: data.tools,
212269
+ catalogVersion: data.catalogVersion,
212270
+ capabilitySessionId: data.capabilitySessionId,
212271
+ capabilityToken: data.capabilityToken,
212272
+ expiresAt: data.expiresAt
212273
+ };
212274
+ }
212275
+ //#endregion
212078
212276
  //#region src/cmmdData/resolveCmmdSidekickToolCatalog.ts
212079
- async function resolveCmmdSidekickToolCatalog(resolveJwt, threadId) {
212080
- const session = createCmmdSidekickToolSession(createCmmdDelegatedToolCatalogClient(resolveJwt), { threadId });
212277
+ async function resolveCmmdSidekickToolCatalog(resolveJwt, threadId, options = {}) {
212278
+ const session = createCmmdSidekickToolSession(createCmmdDelegatedToolCatalogClient(resolveJwt, {
212279
+ ...options.readWorkSessionId !== void 0 ? { readWorkSessionId: options.readWorkSessionId } : {},
212280
+ requestCapability: options.requestWorkSessionCapability ?? requestWorkSessionSidekickCapability
212281
+ }), { threadId });
212081
212282
  const catalog = await session.getCatalog();
212082
212283
  return {
212083
212284
  session,
@@ -212097,6 +212298,36 @@ async function resolveCmmdSidekickJwt(input) {
212097
212298
  });
212098
212299
  }
212099
212300
  //#endregion
212301
+ //#region src/cmmdData/cmmdWorkSessionThreadLookup.ts
212302
+ const WorkSessionIdRow = require_Schema$1.Struct({ workSessionId: require_Schema$1.NullOr(require_Schema$1.String) });
212303
+ const decodeWorkSessionIdRows = require_Schema$1.decodeUnknownEffect(require_Schema$1.ArraySchema(WorkSessionIdRow));
212304
+ /**
212305
+ * Reads the CMMD Work Session id CMMD stamped on a thread's `thread.create`,
212306
+ * straight from the projected thread row (forge#3466). Null for a
212307
+ * person-started thread, for a thread projected before this field existed,
212308
+ * and for a thread id with no projected row at all.
212309
+ *
212310
+ * A minimal raw-SQL read against `projection_threads`, deliberately not
212311
+ * routed through `ProjectionThreadRepository`: the adapters that need this
212312
+ * (`ClaudeAdapter.ts`, `CodexAdapter.ts`) already capture only
212313
+ * `SqlClient.SqlClient` at session-build time (see `readThreadAuthSession`
212314
+ * in `GitHubAgentToolStore.ts` for the established pattern this follows), and
212315
+ * widening that capture to a second service for one column is not worth the
212316
+ * risk to every other call sharing it.
212317
+ */
212318
+ function readThreadWorkSessionId(threadId) {
212319
+ return require_Schema$1.gen(function* () {
212320
+ return (yield* decodeWorkSessionIdRows(yield* (yield* require_SqlError.SqlClient)`
212321
+ SELECT work_session_id AS "workSessionId"
212322
+ FROM projection_threads
212323
+ WHERE thread_id = ${threadId}
212324
+ LIMIT 1
212325
+ `))[0]?.workSessionId ?? null;
212326
+ }).pipe(require_Schema$1.tapError((error) => require_Schema$1.sync(() => {
212327
+ console.warn(`[cmmd-work-session-thread-lookup] failed to read work_session_id for thread ${threadId}:`, error instanceof Error ? error.message : String(error));
212328
+ })), require_Schema$1.orElseSucceed(() => null));
212329
+ }
212330
+ //#endregion
212100
212331
  //#region ../../packages/shared/src/computerUsePermission.ts
212101
212332
  /**
212102
212333
  * Single source of truth for the computer-use permission default.
@@ -213687,13 +213918,14 @@ const makeCodexAdapter = require_Schema$1.fn("makeCodexAdapter")(function* (opti
213687
213918
  const jwt = readCommandJwtForSession(binding.sessionId);
213688
213919
  return jwt ? { jwt } : null;
213689
213920
  } });
213921
+ const readCmmdWorkSessionId = () => runWithRuntimeContext(readThreadWorkSessionId(input.threadId));
213690
213922
  const { session: cmmdSidekickToolSession, tools: cmmdSidekickTools } = yield* require_Schema$1.promise(() => resolveCmmdSidekickToolCatalog((sessionId) => resolveCmmdSidekickJwt({
213691
213923
  threadId: input.threadId,
213692
213924
  sessionId,
213693
213925
  logPrefix: "codex-cmmd-sidekick",
213694
213926
  readThreadAuth: (threadId) => runWithRuntimeContext(readThreadAuthSession(threadId)),
213695
213927
  resolveJwt: (options) => runWithRuntimeContext(resolveCmmdJwtForSession(options))
213696
- }), input.threadId));
213928
+ }), input.threadId, { readWorkSessionId: readCmmdWorkSessionId }));
213697
213929
  const cmmdSidekickToolNames = new Set(cmmdSidekickTools.map((tool) => tool.name));
213698
213930
  const devServerToolDeps = {
213699
213931
  threadDevRuntime,
@@ -215808,6 +216040,21 @@ const SIGNIN_REQUIRED = {
215808
216040
  action: "notify_human",
215809
216041
  message: "Not signed in to CMMD for this session. Continue from repository evidence and tell the user to sign in to CMMD to enable project context."
215810
216042
  };
216043
+ /**
216044
+ * Same failure as {@link SIGNIN_REQUIRED} (no CMMD sign-in exists for this
216045
+ * session), but for a headless Work Session runtime that was never going to
216046
+ * have one: nobody is present to sign in (CMMD ADR-015). Telling the agent
216047
+ * to ask a human to sign in is wrong there. When CMMD's Sidekick capability
216048
+ * broker minted delegated tools for this Work Session (forge#3466,
216049
+ * CMMD#5026), point at them instead of dead-ending.
216050
+ */
216051
+ const WORK_SESSION_CONTEXT_VIA_DELEGATED_TOOLS = {
216052
+ ok: false,
216053
+ code: "signin_required",
216054
+ retryable: false,
216055
+ action: "skip",
216056
+ message: "No CMMD sign-in for this session, but this Work Session has delegated Sidekick tools. Call cmmd_get_agent_plan (or get_task) from cmmd-sidekick-tools for the task packet and current context, then continue from there."
216057
+ };
215811
216058
  /** Map a thrown CMMD client error to a recoverable envelope. */
215812
216059
  function errorEnvelope(err) {
215813
216060
  if (isCmmdMcpAuthError$2(err)) return {
@@ -215870,12 +216117,13 @@ function projectIdToToolArg(projectId) {
215870
216117
  * mutation arg. The `action` arg of CMMD's multiplexed tools is hardcoded to a
215871
216118
  * read inside contextBuilder and never surfaced to the LLM.
215872
216119
  */
215873
- function makeCmmdContextHandlers(resolvePat) {
216120
+ function makeCmmdContextHandlers(resolvePat, options = {}) {
216121
+ const noPatEnvelope = options.hasWorkSessionPacketTool ? WORK_SESSION_CONTEXT_VIA_DELEGATED_TOOLS : SIGNIN_REQUIRED;
215874
216122
  return {
215875
216123
  getCurrentContext: async () => {
215876
216124
  try {
215877
216125
  const pat = await resolvePat();
215878
- if (!pat) return envelope(SIGNIN_REQUIRED);
216126
+ if (!pat) return envelope(noPatEnvelope);
215879
216127
  const snapshot = await buildCurrentContextSnapshot(pat, {
215880
216128
  maxCampaigns: 3,
215881
216129
  maxProjects: 5,
@@ -215908,7 +216156,7 @@ function makeCmmdContextHandlers(resolvePat) {
215908
216156
  message: "Provide a non-empty `query` to search the CMMD knowledge base."
215909
216157
  });
215910
216158
  const pat = await resolvePat();
215911
- if (!pat) return envelope(SIGNIN_REQUIRED);
216159
+ if (!pat) return envelope(noPatEnvelope);
215912
216160
  const effectiveLimit = clampLimit(limit, DEFAULT_BRAIN_LIMIT, MAX_BRAIN_LIMIT);
215913
216161
  const result = await callCmmdTool$2(pat, "search_brain_documents", {
215914
216162
  query: trimmedQuery,
@@ -215962,7 +216210,7 @@ function makeCmmdContextHandlers(resolvePat) {
215962
216210
  message: "Provide a `projectId` (from cmmd_get_current_context data.projects[].id)."
215963
216211
  });
215964
216212
  const pat = await resolvePat();
215965
- if (!pat) return envelope(SIGNIN_REQUIRED);
216213
+ if (!pat) return envelope(noPatEnvelope);
215966
216214
  const result = await callCmmdTool$2(pat, "list_board_tasks", { project_id: projectIdToToolArg(trimmedId) });
215967
216215
  if (result.isError) return envelope(isErrorEnvelope(result));
215968
216216
  const text = extractMcpToolText$2(result);
@@ -215991,8 +216239,8 @@ function makeCmmdContextHandlers(resolvePat) {
215991
216239
  * when the user is not authenticated with CMMD. Called per
215992
216240
  * tool invocation so a mid-session token refresh is picked up.
215993
216241
  */
215994
- function createCmmdContextMcpServer(threadId, resolvePat) {
215995
- const handlers = makeCmmdContextHandlers(resolvePat);
216242
+ function createCmmdContextMcpServer(threadId, resolvePat, options = {}) {
216243
+ const handlers = makeCmmdContextHandlers(resolvePat, options);
215996
216244
  return z1e({
215997
216245
  name: "cmmd-context",
215998
216246
  tools: [
@@ -216515,7 +216763,7 @@ function buildClaudeMcpServers(input) {
216515
216763
  return {
216516
216764
  "forge-browser": createBrowserMcpServer(input.browserManager, input.threadId, browserToolScope(input.browserToolEnvironmentId)),
216517
216765
  "forge-dev-server": createDevServerMcpServer(input.devServerToolDeps, input.threadId),
216518
- "cmmd-context": createCmmdContextMcpServer(input.threadId, input.resolveCmmdPat),
216766
+ "cmmd-context": createCmmdContextMcpServer(input.threadId, input.resolveCmmdPat, { hasWorkSessionPacketTool: input.hasWorkSessionPacketTool }),
216519
216767
  [GITHUB_MCP_SERVER_NAME]: createGitHubMcpServer(input.runBrokeredGitHubTool, input.threadId, input.serverSettings),
216520
216768
  ...input.computerManager ? { [COMPUTER_MCP_SERVER_NAME]: createComputerMcpServer(input.computerManager, input.threadId) } : {},
216521
216769
  ...input.cmmdSidekickTools ? { "cmmd-sidekick-tools": createCmmdSidekickToolsMcpServer(input.cmmdSidekickTools.session, input.cmmdSidekickTools.tools) } : {},
@@ -216559,19 +216807,47 @@ function claudePermissionQueryOptions(permissionMode) {
216559
216807
  function createClaudePromptStream(promptQueue) {
216560
216808
  return require_Path.fromQueue(promptQueue).pipe(require_Path.filter((item) => item.type === "message"), require_Path.map((item) => item.message), require_Path.catchCause((cause) => require_Schema$1.hasInterruptsOnly(cause) ? require_Path.empty : require_Path.failCause(cause)), require_Path.toAsyncIterable);
216561
216809
  }
216562
- function createCmmdPatResolver(threadId) {
216810
+ function createCmmdPatResolver(threadId, readWorkSessionId) {
216563
216811
  return async () => {
216812
+ if (await readWorkSessionId() !== null) return null;
216564
216813
  const ownerSessionId = readThreadSessionId(threadId);
216565
216814
  if (!ownerSessionId) return null;
216566
216815
  return readCommandAccessTokenForSession(ownerSessionId);
216567
216816
  };
216568
216817
  }
216569
- function resolveCmmdSidekickTools(resolveJwt, threadId) {
216570
- return require_Schema$1.promise(() => resolveCmmdSidekickToolCatalog(resolveJwt, threadId)).pipe(require_Schema$1.map((resolved) => ({
216818
+ function resolveCmmdSidekickTools(resolveJwt, threadId, readWorkSessionId) {
216819
+ return require_Schema$1.promise(() => resolveCmmdSidekickToolCatalog(resolveJwt, threadId, { readWorkSessionId })).pipe(require_Schema$1.map((resolved) => ({
216571
216820
  registration: resolved.tools.length > 0 ? resolved : null,
216572
216821
  codewebMcpGrant: resolved.codewebMcp
216573
216822
  })));
216574
216823
  }
216824
+ /**
216825
+ * Name of the delegated tool that returns a Work Session's task packet
216826
+ * (CMMD's Agent Plan family, ADR-029). Forge's Sidekick capability broker
216827
+ * always mounts this for a Work Session (CMMD's `forge-surface.ts` curated
216828
+ * allowlist, verified 2026-09-26), so its presence in the granted catalog is
216829
+ * exactly "a Work Session capability exists for this thread". See
216830
+ * `cmmdContextMcpServer.ts`'s no-PAT branch (forge#3466).
216831
+ */
216832
+ const WORK_SESSION_PACKET_TOOL_NAME = "cmmd_get_agent_plan";
216833
+ /**
216834
+ * Whether `cmmd-context`'s no-PAT branch should point at delegated tools
216835
+ * instead of asking the user to sign in (forge#3466 review, should-fix 5).
216836
+ *
216837
+ * Gating on `workSessionId !== null` alone, without a separate "which lane
216838
+ * minted this" tag, is sound because `cmmdDelegatedToolCatalog.ts`'s
216839
+ * `listCatalog` (should-fix 3) structurally never calls the owner-JWT lane
216840
+ * once a Work Session id is present — it returns straight from the broker
216841
+ * call or `AUTH_REQUIRED`. So a non-null `workSessionId` here can only ever
216842
+ * pair with a broker-minted registration. Before that reorder, the owner-JWT
216843
+ * catalog (the full, unnarrowed Sidekick catalog) also contains
216844
+ * `cmmd_get_agent_plan`, so checking the tool name alone told a
216845
+ * person-started thread with a resolved JWT but no PAT that it had Work
216846
+ * Session tools when it never did.
216847
+ */
216848
+ function hasWorkSessionPacketTool(workSessionId, registration) {
216849
+ return workSessionId !== null && (registration?.tools.some((tool) => tool.name === WORK_SESSION_PACKET_TOOL_NAME) ?? false);
216850
+ }
216575
216851
  function buildDevServerToolDeps(input) {
216576
216852
  return {
216577
216853
  threadDevRuntime: input.threadDevRuntime,
@@ -218748,7 +219024,8 @@ const makeClaudeAdapter = require_Schema$1.fn("makeClaudeAdapter")(function* (op
218748
219024
  const runPromise = require_Schema$1.runPromiseWith(runtimeContext);
218749
219025
  const browserToolEnvironmentId = yield* resolveBrowserToolEnvironmentId();
218750
219026
  const computerManager = resolveComputerManager(serverConfig);
218751
- const resolveCmmdPat = createCmmdPatResolver(threadId);
219027
+ const readWorkSessionId = () => runWithSqlRuntimeContext(readThreadWorkSessionId(threadId));
219028
+ const resolveCmmdPat = createCmmdPatResolver(threadId, readWorkSessionId);
218752
219029
  const resolveCmmdSidekickJwtForSession = (sessionId) => resolveCmmdSidekickJwt({
218753
219030
  threadId,
218754
219031
  sessionId,
@@ -218756,7 +219033,8 @@ const makeClaudeAdapter = require_Schema$1.fn("makeClaudeAdapter")(function* (op
218756
219033
  readThreadAuth: (targetThreadId) => runWithSqlRuntimeContext(readThreadAuthSession(targetThreadId)),
218757
219034
  resolveJwt: (options) => runWithSqlRuntimeContext(resolveCmmdJwtForSession(options))
218758
219035
  });
218759
- const cmmdSidekickResolution = yield* resolveCmmdSidekickTools(resolveCmmdSidekickJwtForSession, threadId);
219036
+ const workSessionId = yield* require_Schema$1.promise(readWorkSessionId);
219037
+ const cmmdSidekickResolution = yield* resolveCmmdSidekickTools(resolveCmmdSidekickJwtForSession, threadId, readWorkSessionId);
218760
219038
  const devServerToolDeps = buildDevServerToolDeps({
218761
219039
  threadDevRuntime,
218762
219040
  devTunnel,
@@ -218841,6 +219119,7 @@ const makeClaudeAdapter = require_Schema$1.fn("makeClaudeAdapter")(function* (op
218841
219119
  resolveCmmdPat,
218842
219120
  devServerToolDeps,
218843
219121
  cmmdSidekickTools: cmmdSidekickResolution.registration,
219122
+ hasWorkSessionPacketTool: hasWorkSessionPacketTool(workSessionId, cmmdSidekickResolution.registration),
218844
219123
  codewebMcpInjection,
218845
219124
  runBrokeredGitHubTool,
218846
219125
  serverSettings
@@ -288304,6 +288583,7 @@ const ProjectionThread = require_Schema$1.Struct({
288304
288583
  parentThreadId: require_Schema$1.NullOr(ThreadId).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
288305
288584
  anchorKind: CmmdAnchorKind.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("scratch"))),
288306
288585
  anchorCmmdId: require_Schema$1.NullOr(require_Schema$1.String).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
288586
+ workSessionId: require_Schema$1.optionalKey(require_Schema$1.NullOr(require_Schema$1.String)),
288307
288587
  linkedPullRequest: require_Schema$1.optionalKey(require_Schema$1.NullOr(LinkedPullRequest)),
288308
288588
  status: ThreadStatus.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("idle"))),
288309
288589
  workerRole: require_Schema$1.NullOr(WorkerRole).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
@@ -299478,7 +299758,7 @@ function resolveBuildCommitFromEnv(env) {
299478
299758
  * environment descriptor down instead of reporting an honest "unknown".
299479
299759
  */
299480
299760
  function readBakedBuildCommit() {
299481
- return "394b2a7cd449282f2845ec5fa3bd9093f20b8bb8";
299761
+ return "6a8d2900640fafdaeaeaf45ddfa1f1cf70c212d7";
299482
299762
  }
299483
299763
  async function resolveServerBuildCommit(input) {
299484
299764
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -303128,6 +303408,7 @@ const decideOrchestrationCommand = require_Schema$1.fn("decideOrchestrationComma
303128
303408
  updatedAt: command.createdAt,
303129
303409
  anchorKind: anchor.anchorKind,
303130
303410
  anchorCmmdId: anchor.anchorCmmdId,
303411
+ workSessionId: command.workSessionId ?? null,
303131
303412
  goal: command.goal ?? null,
303132
303413
  linkedPullRequest: command.linkedPullRequest ?? null,
303133
303414
  kind,
@@ -303437,7 +303718,8 @@ const decideOrchestrationCommand = require_Schema$1.fn("decideOrchestrationComma
303437
303718
  const providerSwitchSelection = command.modelSelection !== void 0 && command.modelSelection.provider !== targetThread.modelSelection.provider ? command.modelSelection : void 0;
303438
303719
  const accountSelection = turnAccountSelection(targetThread.modelSelection, command.modelSelection);
303439
303720
  const turnModelSelection = providerSwitchSelection ?? accountSelection;
303440
- if (!shouldUpdateAnchor && !turnModelSelection) return [userMessageEvent, turnStartRequestedEvent];
303721
+ const shouldRebindWorkSession = command.workSessionId !== void 0 && command.workSessionId !== null && command.workSessionId !== targetThread.workSessionId;
303722
+ if (!shouldUpdateAnchor && !turnModelSelection && !shouldRebindWorkSession) return [userMessageEvent, turnStartRequestedEvent];
303441
303723
  return [
303442
303724
  {
303443
303725
  ...withEventBase({
@@ -303452,6 +303734,7 @@ const decideOrchestrationCommand = require_Schema$1.fn("decideOrchestrationComma
303452
303734
  anchorKind: nextAnchor.anchorKind,
303453
303735
  anchorCmmdId: nextAnchor.anchorCmmdId,
303454
303736
  ...turnModelSelection ? { modelSelection: turnModelSelection } : {},
303737
+ ...shouldRebindWorkSession ? { workSessionId: command.workSessionId } : {},
303455
303738
  updatedAt: command.createdAt
303456
303739
  }
303457
303740
  },
@@ -303975,12 +304258,22 @@ function retainThreadActivitiesAfterRevert(activities, retainedTurnIds) {
303975
304258
  function retainThreadProposedPlansAfterRevert(proposedPlans, retainedTurnIds) {
303976
304259
  return proposedPlans.filter((proposedPlan) => proposedPlan.turnId === null || retainedTurnIds.has(proposedPlan.turnId));
303977
304260
  }
304261
+ /**
304262
+ * Orders an unsequenced activity before a sequenced one, matching the SQL
304263
+ * projection's own `ORDER BY CASE WHEN sequence IS NULL THEN 0 ELSE 1 END
304264
+ * ASC, sequence ASC`. Zero means neither operand settles the order (both
304265
+ * missing, or both present and equal), so the caller falls back to a
304266
+ * timestamp/id tiebreak.
304267
+ */
304268
+ function compareOptionalActivitySequence(left, right) {
304269
+ const leftHasSequence = left !== void 0;
304270
+ const rightHasSequence = right !== void 0;
304271
+ if (leftHasSequence !== rightHasSequence) return leftHasSequence ? 1 : -1;
304272
+ return leftHasSequence && rightHasSequence ? left - right : 0;
304273
+ }
303978
304274
  function compareThreadActivities(left, right) {
303979
- if (left.sequence !== void 0 && right.sequence !== void 0) {
303980
- if (left.sequence !== right.sequence) return left.sequence - right.sequence;
303981
- } else if (left.sequence !== void 0) return 1;
303982
- else if (right.sequence !== void 0) return -1;
303983
- return left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id);
304275
+ const bySequence = compareOptionalActivitySequence(left.sequence, right.sequence);
304276
+ return bySequence !== 0 ? bySequence : left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id);
303984
304277
  }
303985
304278
  function createEmptyReadModel(nowIso) {
303986
304279
  return {
@@ -304011,6 +304304,7 @@ function projectEvent(model, event) {
304011
304304
  worktreePath: payload.worktreePath,
304012
304305
  anchorKind: payload.anchorKind,
304013
304306
  anchorCmmdId: payload.anchorCmmdId,
304307
+ workSessionId: payload.workSessionId ?? null,
304014
304308
  goal: payload.goal ?? null,
304015
304309
  linkedPullRequest: payload.linkedPullRequest ?? null,
304016
304310
  titleRegeneration: null,
@@ -304091,6 +304385,7 @@ function projectEvent(model, event) {
304091
304385
  ...payload.goal !== void 0 ? { goal: payload.goal } : {},
304092
304386
  ...payload.linkedPullRequest !== void 0 ? { linkedPullRequest: payload.linkedPullRequest } : {},
304093
304387
  ...payload.titleRegeneration !== void 0 ? { titleRegeneration: payload.titleRegeneration } : {},
304388
+ ...payload.workSessionId !== void 0 ? { workSessionId: payload.workSessionId } : {},
304094
304389
  updatedAt: payload.updatedAt
304095
304390
  })
304096
304391
  })));
@@ -305155,6 +305450,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
305155
305450
  parent_thread_id,
305156
305451
  anchor_kind,
305157
305452
  anchor_cmmd_id,
305453
+ work_session_id,
305158
305454
  linked_pull_request_json,
305159
305455
  status,
305160
305456
  worker_role,
@@ -305187,6 +305483,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
305187
305483
  ${row.parentThreadId},
305188
305484
  ${row.anchorKind},
305189
305485
  ${row.anchorCmmdId},
305486
+ ${row.workSessionId ?? null},
305190
305487
  ${row.linkedPullRequest == null ? null : JSON.stringify(row.linkedPullRequest)},
305191
305488
  ${row.status},
305192
305489
  ${row.workerRole},
@@ -305219,6 +305516,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
305219
305516
  parent_thread_id = excluded.parent_thread_id,
305220
305517
  anchor_kind = excluded.anchor_kind,
305221
305518
  anchor_cmmd_id = excluded.anchor_cmmd_id,
305519
+ work_session_id = excluded.work_session_id,
305222
305520
  linked_pull_request_json = excluded.linked_pull_request_json,
305223
305521
  status = excluded.status,
305224
305522
  worker_role = excluded.worker_role,
@@ -305256,6 +305554,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
305256
305554
  parent_thread_id AS "parentThreadId",
305257
305555
  anchor_kind AS "anchorKind",
305258
305556
  anchor_cmmd_id AS "anchorCmmdId",
305557
+ work_session_id AS "workSessionId",
305259
305558
  linked_pull_request_json AS "linkedPullRequest",
305260
305559
  status,
305261
305560
  worker_role AS "workerRole",
@@ -305295,6 +305594,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
305295
305594
  parent_thread_id AS "parentThreadId",
305296
305595
  anchor_kind AS "anchorKind",
305297
305596
  anchor_cmmd_id AS "anchorCmmdId",
305597
+ work_session_id AS "workSessionId",
305298
305598
  linked_pull_request_json AS "linkedPullRequest",
305299
305599
  status,
305300
305600
  worker_role AS "workerRole",
@@ -305477,6 +305777,14 @@ function collectThreadUserInputAttachmentRelativePaths(threadId, events) {
305477
305777
  }
305478
305778
  return relativePaths;
305479
305779
  }
305780
+ /**
305781
+ * Coalesces an optional Work Session id to the persisted default. Top-level
305782
+ * so the `??` here does not count against `applyThreadsProjection`'s own
305783
+ * complexity budget. See forge#3466.
305784
+ */
305785
+ function projectedWorkSessionId(workSessionId) {
305786
+ return workSessionId ?? null;
305787
+ }
305480
305788
  const runAttachmentSideEffects = require_Schema$1.fn("runAttachmentSideEffects")(function* (sideEffects) {
305481
305789
  const serverConfig = yield* require_Schema$1.service(ServerConfig);
305482
305790
  const fileSystem = yield* require_Schema$1.service(require_Path.FileSystem);
@@ -305642,6 +305950,7 @@ const makeOrchestrationProjectionPipeline = require_Schema$1.fn("makeOrchestrati
305642
305950
  parentThreadId: event.payload.parentThreadId,
305643
305951
  anchorKind: event.payload.anchorKind,
305644
305952
  anchorCmmdId: event.payload.anchorCmmdId,
305953
+ workSessionId: projectedWorkSessionId(event.payload.workSessionId),
305645
305954
  linkedPullRequest: event.payload.linkedPullRequest ?? null,
305646
305955
  status: event.payload.status,
305647
305956
  workerRole: event.payload.workerRole,
@@ -305680,6 +305989,7 @@ const makeOrchestrationProjectionPipeline = require_Schema$1.fn("makeOrchestrati
305680
305989
  parentThreadId: thread.parentThreadId,
305681
305990
  anchorKind: thread.anchorKind,
305682
305991
  anchorCmmdId: thread.anchorCmmdId,
305992
+ workSessionId: projectedWorkSessionId(thread.workSessionId),
305683
305993
  linkedPullRequest: thread.linkedPullRequest ?? null,
305684
305994
  status: thread.status,
305685
305995
  workerRole: thread.workerRole,
@@ -305748,6 +306058,7 @@ const makeOrchestrationProjectionPipeline = require_Schema$1.fn("makeOrchestrati
305748
306058
  ...event.payload.goal !== void 0 ? { goal: event.payload.goal } : {},
305749
306059
  ...event.payload.linkedPullRequest !== void 0 ? { linkedPullRequest: event.payload.linkedPullRequest } : {},
305750
306060
  ...event.payload.titleRegeneration !== void 0 ? { titleRegeneration: event.payload.titleRegeneration } : {},
306061
+ ...event.payload.workSessionId !== void 0 ? { workSessionId: projectedWorkSessionId(event.payload.workSessionId) } : {},
305751
306062
  updatedAt: event.payload.updatedAt
305752
306063
  });
305753
306064
  return;
@@ -306748,6 +307059,16 @@ function probeProjectAvailability(fs, workspaceRoot) {
306748
307059
  function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation) {
306749
307060
  return (cause) => require_Schema$1.isSchemaError(cause) ? toPersistenceDecodeError(decodeOperation)(cause) : toPersistenceSqlError(sqlOperation)(cause);
306750
307061
  }
307062
+ /**
307063
+ * `{ workSessionId }` when the row carries one, an empty object when absent,
307064
+ * so the built thread's optionalKey field round-trips without ever getting
307065
+ * assigned an explicit `undefined` (exactOptionalPropertyTypes). Pulled out
307066
+ * of the two thread builders that call it so this file's already-flagged
307067
+ * high-complexity functions do not pick up the branch. See forge#3466.
307068
+ */
307069
+ function workSessionIdField(workSessionId) {
307070
+ return workSessionId !== void 0 ? { workSessionId } : {};
307071
+ }
306751
307072
  const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
306752
307073
  const sql = yield* require_SqlError.SqlClient;
306753
307074
  const repositoryIdentityResolver = yield* RepositoryIdentityResolver;
@@ -306800,6 +307121,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
306800
307121
  parent_thread_id AS "parentThreadId",
306801
307122
  anchor_kind AS "anchorKind",
306802
307123
  anchor_cmmd_id AS "anchorCmmdId",
307124
+ work_session_id AS "workSessionId",
306803
307125
  linked_pull_request_json AS "linkedPullRequest",
306804
307126
  status,
306805
307127
  worker_role AS "workerRole",
@@ -306838,6 +307160,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
306838
307160
  parent_thread_id AS "parentThreadId",
306839
307161
  anchor_kind AS "anchorKind",
306840
307162
  anchor_cmmd_id AS "anchorCmmdId",
307163
+ work_session_id AS "workSessionId",
306841
307164
  linked_pull_request_json AS "linkedPullRequest",
306842
307165
  status,
306843
307166
  worker_role AS "workerRole",
@@ -306942,6 +307265,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
306942
307265
  parent_thread_id AS "parentThreadId",
306943
307266
  anchor_kind AS "anchorKind",
306944
307267
  anchor_cmmd_id AS "anchorCmmdId",
307268
+ work_session_id AS "workSessionId",
306945
307269
  linked_pull_request_json AS "linkedPullRequest",
306946
307270
  status,
306947
307271
  worker_role AS "workerRole",
@@ -307274,6 +307598,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
307274
307598
  parent_thread_id AS "parentThreadId",
307275
307599
  anchor_kind AS "anchorKind",
307276
307600
  anchor_cmmd_id AS "anchorCmmdId",
307601
+ work_session_id AS "workSessionId",
307277
307602
  linked_pull_request_json AS "linkedPullRequest",
307278
307603
  status,
307279
307604
  worker_role AS "workerRole",
@@ -307586,6 +307911,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
307586
307911
  session: sessionsByThread.get(row.threadId) ?? null,
307587
307912
  anchorKind: row.anchorKind,
307588
307913
  anchorCmmdId: row.anchorCmmdId,
307914
+ ...workSessionIdField(row.workSessionId),
307589
307915
  linkedPullRequest: row.linkedPullRequest,
307590
307916
  kind: row.kind,
307591
307917
  parentThreadId: row.parentThreadId,
@@ -307835,6 +308161,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
307835
308161
  session: require_Schema$1.isSome(sessionRow) ? mapSessionRow(sessionRow.value) : null,
307836
308162
  anchorKind: threadRow.value.anchorKind,
307837
308163
  anchorCmmdId: threadRow.value.anchorCmmdId,
308164
+ ...workSessionIdField(threadRow.value.workSessionId),
307838
308165
  linkedPullRequest: threadRow.value.linkedPullRequest,
307839
308166
  kind: threadRow.value.kind,
307840
308167
  parentThreadId: threadRow.value.parentThreadId,