@p4code/cli 0.1.29 → 0.1.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.mjs CHANGED
@@ -236,7 +236,7 @@ const make$76 = () => {
236
236
  const layer$72 = Layer.sync(NetService, make$76);
237
237
  //#endregion
238
238
  //#region package.json
239
- var version = "0.1.29";
239
+ var version = "0.1.31";
240
240
  //#endregion
241
241
  //#region src/config.ts
242
242
  /**
@@ -1422,11 +1422,20 @@ const ProviderInstanceEnvironment = Schema$1.Array(ProviderInstanceEnvironmentVa
1422
1422
  * each driver registers its own decoder with the runtime registry, and
1423
1423
  * envelopes for unknown drivers are preserved verbatim so they round-trip
1424
1424
  * across version changes without data loss.
1425
+ *
1426
+ * `defaultModel` sits on the envelope rather than inside the driver blob
1427
+ * because it is a routing preference the app resolves, not something a
1428
+ * driver interprets: it names the model a new thread, task, or project
1429
+ * starts on when the user has no more recent pick of their own. An
1430
+ * unrecognized slug (model removed, custom entry deleted) is ignored by
1431
+ * the resolver rather than validated away here, so a temporarily absent
1432
+ * provider does not lose the preference.
1425
1433
  */
1426
1434
  const ProviderInstanceConfig = Schema$1.Struct({
1427
1435
  driver: ProviderDriverKind,
1428
1436
  displayName: Schema$1.optional(TrimmedNonEmptyString),
1429
1437
  accentColor: Schema$1.optional(TrimmedNonEmptyString),
1438
+ defaultModel: Schema$1.optional(TrimmedNonEmptyString),
1430
1439
  environment: Schema$1.optionalKey(ProviderInstanceEnvironment),
1431
1440
  enabled: Schema$1.optionalKey(Schema$1.Boolean),
1432
1441
  config: Schema$1.optionalKey(Schema$1.Unknown)
@@ -7374,20 +7383,24 @@ const RepositoryKeyField = TrimmedNonEmptyString.pipe(Schema$1.annotateEncoded({
7374
7383
  */
7375
7384
  const OrderKeyField = TrimmedNonEmptyString.pipe(Schema$1.annotateEncoded({ description: "Manual board position key. Lexicographic: smaller sorts higher in the column. Null means no manual position." }));
7376
7385
  /**
7377
- * Where a task came from when it did not originate on this board.
7386
+ * Which tracker issue a row *is*, for a row read out of a tracker.
7378
7387
  *
7379
7388
  * The identifier is the tracker's own, not ours: `MOBILE-12262` reads the same
7380
7389
  * in p4code as it does in Linear, in a commit message, and in conversation,
7381
7390
  * which is the whole point of carrying it. `url` is what the tracker itself
7382
7391
  * reported, never a guess assembled from the identifier - a Linear URL embeds
7383
7392
  * the workspace slug, so a constructed one would 404.
7393
+ *
7394
+ * Read-only, and only ever set by the `linear` source. p4code's own board does
7395
+ * not copy tracker issues into rows of its own: a ticket is read where it lives
7396
+ * and shown under the id its tracker gave it, which is why nothing here appears
7397
+ * in a create or update input.
7384
7398
  */
7385
7399
  const TaskExternalRef = Schema$1.Struct({
7386
7400
  source: Schema$1.Literals(["linear"]),
7387
7401
  identifier: TrimmedNonEmptyString,
7388
7402
  url: TrimmedNonEmptyString
7389
7403
  });
7390
- const ExternalRefField = TaskExternalRef.pipe(Schema$1.annotateEncoded({ description: "The tracker issue this task mirrors, e.g. a Linear ticket. Null for a task that originated on this board." }));
7391
7404
  /**
7392
7405
  * The task this one was split out of.
7393
7406
  *
@@ -7445,10 +7458,10 @@ const Task = Schema$1.Struct({
7445
7458
  */
7446
7459
  threadId: Schema$1.NullOr(ThreadId),
7447
7460
  /**
7448
- * The tracker issue this task mirrors, or `null` for a task that was filed
7449
- * here. Nullable-with-default for the same version-skew reason as
7450
- * `readableId` above: a row from a store without the migration decodes to
7451
- * `null` rather than failing the whole board.
7461
+ * The tracker issue this row is, for a row read from a tracker, and `null`
7462
+ * for every row on p4code's own board. Nullable-with-default because the
7463
+ * board's own store has no such column at all - a row read from SQLite
7464
+ * decodes to `null` rather than failing the whole board.
7452
7465
  */
7453
7466
  externalRef: Schema$1.NullOr(TaskExternalRef).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
7454
7467
  /**
@@ -7471,7 +7484,6 @@ const TaskCreateInput = Schema$1.Struct({
7471
7484
  projectId: Schema$1.optional(ProjectIdField),
7472
7485
  repositoryKey: Schema$1.optional(RepositoryKeyField),
7473
7486
  threadId: Schema$1.optional(ThreadIdField),
7474
- externalRef: Schema$1.optional(ExternalRefField),
7475
7487
  parentTaskId: Schema$1.optional(ParentTaskIdField),
7476
7488
  title: TitleField,
7477
7489
  body: Schema$1.optional(BodyField),
@@ -7522,7 +7534,6 @@ const HubTaskPutInput = Schema$1.Struct({
7522
7534
  projectId: Schema$1.NullOr(ProjectIdField),
7523
7535
  repositoryKey: Schema$1.NullOr(RepositoryKeyField),
7524
7536
  threadId: Schema$1.NullOr(ThreadIdField),
7525
- externalRef: Schema$1.NullOr(ExternalRefField),
7526
7537
  parentTaskId: Schema$1.NullOr(ParentTaskIdField),
7527
7538
  title: TitleField,
7528
7539
  body: BodyField,
@@ -7544,7 +7555,6 @@ const TaskUpdateInput = Schema$1.Struct({
7544
7555
  projectId: Schema$1.optional(Schema$1.NullOr(ProjectIdField)),
7545
7556
  repositoryKey: Schema$1.optional(Schema$1.NullOr(RepositoryKeyField)),
7546
7557
  threadId: Schema$1.optional(Schema$1.NullOr(ThreadIdField)),
7547
- externalRef: Schema$1.optional(Schema$1.NullOr(ExternalRefField)),
7548
7558
  parentTaskId: Schema$1.optional(Schema$1.NullOr(ParentTaskIdField)),
7549
7559
  title: Schema$1.optional(TitleField),
7550
7560
  body: Schema$1.optional(BodyField),
@@ -7921,8 +7931,9 @@ var ProjectWriteFileError = class extends Schema$1.TaggedErrorClass()("ProjectWr
7921
7931
  * Reading an issue out of an external tracker.
7922
7932
  *
7923
7933
  * One call, deliberately: p4code does not sync trackers, it recognizes a ticket
7924
- * somebody pasted and asks the tracker what it is called. Everything durable
7925
- * that comes back is stored on a task as its {@link TaskExternalRef}.
7934
+ * somebody pasted and asks the tracker what it is called. Nothing is stored:
7935
+ * the ticket stays in its tracker, under the id the tracker gave it, and the
7936
+ * caller renders the answer.
7926
7937
  *
7927
7938
  * The tracker is reached through the MCP server the user already registered for
7928
7939
  * it, so there is no second place to configure credentials and no p4code-owned
@@ -7942,7 +7953,7 @@ var ProjectWriteFileError = class extends Schema$1.TaggedErrorClass()("ProjectWr
7942
7953
  const TicketResolveInput = Schema$1.Struct({ reference: TrimmedNonEmptyString.pipe(Schema$1.annotateEncoded({ description: "The ticket as it was written: an identifier like MOBILE-12241, or a tracker URL. Pass it through verbatim rather than reformatting it." })) });
7943
7954
  const TicketResolveResult = Schema$1.Struct({
7944
7955
  externalRef: TaskExternalRef,
7945
- /** The issue title as the tracker reports it, for the task that mirrors it. */
7956
+ /** The issue title as the tracker reports it. */
7946
7957
  title: TrimmedNonEmptyString,
7947
7958
  /**
7948
7959
  * The issue body, when the tracker reports one.
@@ -9225,8 +9236,6 @@ const WS_METHODS = {
9225
9236
  tasksUpdate: "tasks.update",
9226
9237
  tasksDelete: "tasks.delete",
9227
9238
  tasksStartThread: "tasks.startThread",
9228
- tasksRefreshExternal: "tasks.refreshExternal",
9229
- ticketsResolve: "tickets.resolve",
9230
9239
  hubGetSyncStatus: "hub.getSyncStatus",
9231
9240
  hubConnect: "hub.connect",
9232
9241
  hubDisconnect: "hub.disconnect",
@@ -9358,29 +9367,6 @@ const WsTasksStartThreadRpc = Rpc.make(WS_METHODS.tasksStartThread, {
9358
9367
  ])
9359
9368
  });
9360
9369
  /**
9361
- * Bring a task that mirrors a tracker issue back in line with the tracker.
9362
- *
9363
- * One direction only: the tracker's copy is the original, and the local row is
9364
- * a cache of it that exists so the board and the task panel can render the work
9365
- * without a network call in the way. Nothing here writes to the tracker.
9366
- *
9367
- * Answers with the whole task rather than an acknowledgement, for the same
9368
- * reason every other task RPC does - the caller renders the row it asked about
9369
- * and never has to follow this with a read. A task that mirrors nothing is
9370
- * returned untouched rather than refused: "refresh this" on a locally filed
9371
- * task is a no-op, not a mistake.
9372
- */
9373
- const WsTasksRefreshExternalRpc = Rpc.make(WS_METHODS.tasksRefreshExternal, {
9374
- payload: TaskGetInput,
9375
- success: TaskResult,
9376
- error: Schema$1.Union([
9377
- TaskNotFoundError,
9378
- TaskStoreError,
9379
- TicketResolveError,
9380
- EnvironmentAuthorizationError
9381
- ])
9382
- });
9383
- /**
9384
9370
  * Hub link and skill sync.
9385
9371
  *
9386
9372
  * Every one of these answers with the whole status rather than an
@@ -9584,17 +9570,6 @@ const WsMcpOAuthDisconnectRpc = Rpc.make(WS_METHODS.mcpOAuthDisconnect, {
9584
9570
  error: Schema$1.Union([McpRegistryError, EnvironmentAuthorizationError])
9585
9571
  });
9586
9572
  /**
9587
- * Asks the tracker what a pasted reference is, without writing anything.
9588
- *
9589
- * Read-only on purpose: the caller decides whether the answer becomes a task.
9590
- * A resolve that filed a row would make an accidental paste a board entry.
9591
- */
9592
- const WsTicketsResolveRpc = Rpc.make(WS_METHODS.ticketsResolve, {
9593
- payload: TicketResolveInput,
9594
- success: TicketResolveResult,
9595
- error: Schema$1.Union([TicketResolveError, EnvironmentAuthorizationError])
9596
- });
9597
- /**
9598
9573
  * The board, then every change to it, for as long as the client stays
9599
9574
  * subscribed. The leading snapshot is what makes this sufficient on its own —
9600
9575
  * a client does not list first, so there is no window between the two in which
@@ -9972,7 +9947,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
9972
9947
  error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
9973
9948
  stream: true
9974
9949
  });
9975
- const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsShellOpenInEditorRpc, WsFilesystemBrowseRpc, WsAssetsCreateUrlRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsVcsListRefsRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsReviewGetDiffPreviewRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsPreviewOpenRpc, WsPreviewNavigateRpc, WsPreviewResizeRpc, WsPreviewRefreshRpc, WsPreviewCloseRpc, WsPreviewListRpc, WsPreviewReportStatusRpc, WsPreviewAutomationConnectRpc, WsPreviewAutomationRespondRpc, WsPreviewAutomationFocusHostRpc, WsSubscribePreviewEventsRpc, WsSubscribeDiscoveredLocalServersRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsTasksListRpc, WsTasksGetRpc, WsTasksCreateRpc, WsTasksUpdateRpc, WsTasksDeleteRpc, WsTasksStartThreadRpc, WsTasksRefreshExternalRpc, WsSubscribeTasksRpc, WsHubGetSyncStatusRpc, WsHubConnectRpc, WsHubDisconnectRpc, WsHubSetSyncModeRpc, WsHubSetShareModeRpc, WsHubMintTokenRpc, WsSkillsSyncRpc, WsSkillsPublishRpc, WsSkillsPublishAllRpc, WsSkillsUnpublishRpc, WsAssetsReadRpc, WsAssetsSaveRpc, WsAssetsDeleteRpc, WsAssetsCreateLocalRpc, WsAssetsRemoveLocalRpc, WsSkillRegistrySearchRpc, WsSkillRegistryFetchRpc, WsMcpListRpc, WsMcpSaveRpc, WsMcpRemoveRpc, WsMcpSetSecretRpc, WsMcpOAuthBeginRpc, WsMcpOAuthDisconnectRpc, WsTicketsResolveRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
9950
+ const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsShellOpenInEditorRpc, WsFilesystemBrowseRpc, WsAssetsCreateUrlRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsVcsListRefsRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsReviewGetDiffPreviewRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsPreviewOpenRpc, WsPreviewNavigateRpc, WsPreviewResizeRpc, WsPreviewRefreshRpc, WsPreviewCloseRpc, WsPreviewListRpc, WsPreviewReportStatusRpc, WsPreviewAutomationConnectRpc, WsPreviewAutomationRespondRpc, WsPreviewAutomationFocusHostRpc, WsSubscribePreviewEventsRpc, WsSubscribeDiscoveredLocalServersRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsTasksListRpc, WsTasksGetRpc, WsTasksCreateRpc, WsTasksUpdateRpc, WsTasksDeleteRpc, WsTasksStartThreadRpc, WsSubscribeTasksRpc, WsHubGetSyncStatusRpc, WsHubConnectRpc, WsHubDisconnectRpc, WsHubSetSyncModeRpc, WsHubSetShareModeRpc, WsHubMintTokenRpc, WsSkillsSyncRpc, WsSkillsPublishRpc, WsSkillsPublishAllRpc, WsSkillsUnpublishRpc, WsAssetsReadRpc, WsAssetsSaveRpc, WsAssetsDeleteRpc, WsAssetsCreateLocalRpc, WsAssetsRemoveLocalRpc, WsSkillRegistrySearchRpc, WsSkillRegistryFetchRpc, WsMcpListRpc, WsMcpSaveRpc, WsMcpRemoveRpc, WsMcpSetSecretRpc, WsMcpOAuthBeginRpc, WsMcpOAuthDisconnectRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
9976
9951
  //#endregion
9977
9952
  //#region ../../packages/shared/src/oauthScope.ts
9978
9953
  const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
@@ -13207,6 +13182,29 @@ var _043_TaskSync_default = Effect.gen(function* () {
13207
13182
  `;
13208
13183
  });
13209
13184
  //#endregion
13185
+ //#region src/persistence/Migrations/044_TaskExternalRefRemoved.ts
13186
+ /**
13187
+ * The end of mirroring: p4code's board holds p4code's own rows only.
13188
+ *
13189
+ * Migration 040 added `external_ref_json` so a Linear ticket could be filed
13190
+ * here as a local task that cached the issue. That arrangement gave every
13191
+ * ticket two names - the tracker's and a `P4-n` this board minted beside it -
13192
+ * and put work nobody filed here on the board. A ticket is now read where it
13193
+ * lives, through the Linear board source, and shown under the tracker's own id.
13194
+ *
13195
+ * The rows that were mirrors are deliberately left alone. They are ordinary
13196
+ * tasks once the column is gone, and deleting somebody's board rows to complete
13197
+ * a schema change is not this migration's call to make; the identifier they
13198
+ * mirrored is usually still quoted in their title or body.
13199
+ *
13200
+ * @module Migrations/044_TaskExternalRefRemoved
13201
+ */
13202
+ var _044_TaskExternalRefRemoved_default = Effect.gen(function* () {
13203
+ const sql = yield* SqlClient.SqlClient;
13204
+ yield* sql`DROP INDEX IF EXISTS idx_tasks_external_ref_identifier`;
13205
+ yield* sql`ALTER TABLE tasks DROP COLUMN external_ref_json`;
13206
+ });
13207
+ //#endregion
13210
13208
  //#region src/persistence/Migrations.ts
13211
13209
  /**
13212
13210
  * MigrationsLive - Migration runner with inline loader
@@ -13442,6 +13440,11 @@ const migrationEntries = [
13442
13440
  43,
13443
13441
  "TaskSync",
13444
13442
  _043_TaskSync_default
13443
+ ],
13444
+ [
13445
+ 44,
13446
+ "TaskExternalRefRemoved",
13447
+ _044_TaskExternalRefRemoved_default
13445
13448
  ]
13446
13449
  ];
13447
13450
  const makeMigrationLoader = (throughId) => Migrator.fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
@@ -15049,10 +15052,7 @@ const DeleteTaskInput = Schema$1.Struct({ taskId: TaskId });
15049
15052
  var TaskRepository = class extends Context.Service()("@p4code/cli/persistence/Services/Tasks/TaskRepository") {};
15050
15053
  //#endregion
15051
15054
  //#region src/persistence/Layers/Tasks.ts
15052
- const TaskDbRow$1 = Task.mapFields(Struct.assign({
15053
- labels: Schema$1.fromJsonString(Schema$1.Array(TaskLabel)),
15054
- externalRef: Schema$1.NullOr(Schema$1.fromJsonString(TaskExternalRef))
15055
- }));
15055
+ const TaskDbRow$1 = Task.mapFields(Struct.assign({ labels: Schema$1.fromJsonString(Schema$1.Array(TaskLabel)) }));
15056
15056
  /**
15057
15057
  * The `list` filter with every field normalized to a bound `null` rather than
15058
15058
  * an absent key. Each predicate is then `(:param IS NULL OR column = :param)`,
@@ -15072,7 +15072,6 @@ const TASK_COLUMNS$1 = `
15072
15072
  project_id AS "projectId",
15073
15073
  repository_key AS "repositoryKey",
15074
15074
  thread_id AS "threadId",
15075
- external_ref_json AS "externalRef",
15076
15075
  parent_task_id AS "parentTaskId",
15077
15076
  title,
15078
15077
  body,
@@ -15097,7 +15096,6 @@ const makeTaskRepository = Effect.gen(function* () {
15097
15096
  project_id,
15098
15097
  repository_key,
15099
15098
  thread_id,
15100
- external_ref_json,
15101
15099
  parent_task_id,
15102
15100
  title,
15103
15101
  body,
@@ -15115,7 +15113,6 @@ const makeTaskRepository = Effect.gen(function* () {
15115
15113
  ${row.projectId},
15116
15114
  ${row.repositoryKey},
15117
15115
  ${row.threadId},
15118
- ${row.externalRef === null ? null : JSON.stringify(row.externalRef)},
15119
15116
  ${row.parentTaskId},
15120
15117
  ${row.title},
15121
15118
  ${row.body},
@@ -15133,7 +15130,6 @@ const makeTaskRepository = Effect.gen(function* () {
15133
15130
  project_id = excluded.project_id,
15134
15131
  repository_key = excluded.repository_key,
15135
15132
  thread_id = excluded.thread_id,
15136
- external_ref_json = excluded.external_ref_json,
15137
15133
  parent_task_id = excluded.parent_task_id,
15138
15134
  title = excluded.title,
15139
15135
  body = excluded.body,
@@ -15233,7 +15229,6 @@ const makeTaskRepository = Effect.gen(function* () {
15233
15229
  ...input.projectId !== void 0 ? { projectId: input.projectId } : {},
15234
15230
  ...input.repositoryKey !== void 0 ? { repositoryKey: input.repositoryKey } : {},
15235
15231
  ...input.threadId !== void 0 ? { threadId: input.threadId } : {},
15236
- ...input.externalRef !== void 0 ? { externalRef: input.externalRef } : {},
15237
15232
  ...input.parentTaskId !== void 0 ? { parentTaskId: input.parentTaskId } : {},
15238
15233
  ...input.title !== void 0 ? { title: input.title } : {},
15239
15234
  ...input.body !== void 0 ? { body: input.body } : {},
@@ -15273,7 +15268,6 @@ const makeTaskRepository = Effect.gen(function* () {
15273
15268
  ...input.patch.projectId !== void 0 ? { projectId: input.patch.projectId } : {},
15274
15269
  ...input.patch.repositoryKey !== void 0 ? { repositoryKey: input.patch.repositoryKey } : {},
15275
15270
  ...input.patch.threadId !== void 0 ? { threadId: input.patch.threadId } : {},
15276
- ...input.patch.externalRef !== void 0 ? { externalRef: input.patch.externalRef } : {},
15277
15271
  ...input.patch.parentTaskId !== void 0 ? { parentTaskId: input.patch.parentTaskId } : {},
15278
15272
  ...input.patch.title !== void 0 ? { title: input.patch.title } : {},
15279
15273
  ...input.patch.body !== void 0 ? { body: input.patch.body } : {},
@@ -15408,7 +15402,7 @@ const createTaskRoute = HttpRouter.add("POST", "/tasks", respondToHubFailures(Ef
15408
15402
  projectId: input.projectId ?? null,
15409
15403
  repositoryKey: input.repositoryKey ?? null,
15410
15404
  threadId: input.threadId ?? null,
15411
- externalRef: input.externalRef ?? null,
15405
+ externalRef: null,
15412
15406
  parentTaskId: input.parentTaskId ?? null,
15413
15407
  title: input.title,
15414
15408
  body: input.body ?? "",
@@ -15449,7 +15443,7 @@ const putTaskRoute = HttpRouter.add("PUT", "/tasks/:taskId", respondToHubFailure
15449
15443
  projectId: input.projectId,
15450
15444
  repositoryKey: input.repositoryKey,
15451
15445
  threadId: input.threadId,
15452
- externalRef: input.externalRef,
15446
+ externalRef: null,
15453
15447
  parentTaskId: input.parentTaskId,
15454
15448
  title: input.title,
15455
15449
  body: input.body,
@@ -15799,6 +15793,18 @@ var _007_TaskParentTaskId_default = Effect.gen(function* () {
15799
15793
  `;
15800
15794
  });
15801
15795
  //#endregion
15796
+ //#region src/hub/Migrations/008_TaskExternalRefRemoved.ts
15797
+ /**
15798
+ * Drops the mirror column, mirroring the environment server's migration 044.
15799
+ * The hub carried it so a mirrored ticket read the same on a second machine;
15800
+ * with nothing filing mirrors, there is nothing for it to carry.
15801
+ */
15802
+ var _008_TaskExternalRefRemoved_default = Effect.gen(function* () {
15803
+ const sql = yield* SqlClient.SqlClient;
15804
+ yield* sql`DROP INDEX IF EXISTS idx_tasks_external_ref_identifier`;
15805
+ yield* sql`ALTER TABLE tasks DROP COLUMN external_ref_json`;
15806
+ });
15807
+ //#endregion
15802
15808
  //#region src/hub/Migrations.ts
15803
15809
  /**
15804
15810
  * Hub migrations.
@@ -15844,6 +15850,11 @@ const hubMigrationEntries = [
15844
15850
  7,
15845
15851
  "TaskParentTaskId",
15846
15852
  _007_TaskParentTaskId_default
15853
+ ],
15854
+ [
15855
+ 8,
15856
+ "TaskExternalRefRemoved",
15857
+ _008_TaskExternalRefRemoved_default
15847
15858
  ]
15848
15859
  ];
15849
15860
  const hubMigrationLoader = Migrator.fromRecord(Object.fromEntries(hubMigrationEntries.map(([id, name, migration]) => [`${id}_${name}`, migration])));
@@ -36325,14 +36336,6 @@ const callMcpTool = Effect.fn("McpToolClient.callMcpTool")(function* (input) {
36325
36336
  text
36326
36337
  };
36327
36338
  });
36328
- /**
36329
- * Linear's own tool for reading one issue.
36330
- *
36331
- * Named here rather than at each call site because two of them are now in
36332
- * different modules - the board's store and the mirror refresh - and a tool
36333
- * name that drifts between them fails at runtime with a shrug from the server.
36334
- */
36335
- const LINEAR_GET_ISSUE_TOOL$1 = "get_issue";
36336
36339
  /** Why a Linear call could not be made, in terms a person can act on. */
36337
36340
  var LinearUnavailable = class extends Schema$1.TaggedErrorClass()("LinearUnavailable", {
36338
36341
  reason: Schema$1.Literals([
@@ -36509,6 +36512,9 @@ function parseTicketReference(text) {
36509
36512
  * in the `linear_task_links` sidecar instead. Everything Linear carries has a
36510
36513
  * home here.
36511
36514
  *
36515
+ * An issue becomes a card the board renders while it is on screen, and never a
36516
+ * row on p4code's own board: nothing here is a copy that can fall behind.
36517
+ *
36512
36518
  * @module persistence/Layers/linearTaskMapping
36513
36519
  */
36514
36520
  /**
@@ -36660,25 +36666,6 @@ const taskFromLinearIssue = (issue, link = EMPTY_LINEAR_TASK_LINK) => {
36660
36666
  };
36661
36667
  };
36662
36668
  /**
36663
- * What a refresh writes onto the local row.
36664
- *
36665
- * `undefined` for an issue Linear reported nothing usable for, on the same
36666
- * reading as {@link taskFromLinearIssue}: a blank title is a caller that asked
36667
- * for the wrong fields, and blanking the mirror is the worse answer.
36668
- */
36669
- const linearMirrorFields = (issue) => {
36670
- const task = taskFromLinearIssue(issue);
36671
- if (task === void 0) return;
36672
- return {
36673
- title: task.title,
36674
- body: task.body,
36675
- status: task.status,
36676
- priority: task.priority,
36677
- assignee: task.assignee,
36678
- labels: task.labels
36679
- };
36680
- };
36681
- /**
36682
36669
  * The fields `list_issues` has to return for a card to be complete.
36683
36670
  *
36684
36671
  * Named here rather than at the call site because `taskFromLinearIssue` reads
@@ -37056,7 +37043,6 @@ const makeHubTaskClient = Effect.gen(function* () {
37056
37043
  projectId: row.projectId,
37057
37044
  repositoryKey: row.repositoryKey,
37058
37045
  threadId: row.threadId,
37059
- externalRef: row.externalRef,
37060
37046
  parentTaskId: row.parentTaskId,
37061
37047
  title: row.title,
37062
37048
  body: row.body,
@@ -37122,17 +37108,13 @@ Layer.effect(HubTaskClient, makeHubTaskClient);
37122
37108
  *
37123
37109
  * @module persistence/Layers/TaskSyncStore
37124
37110
  */
37125
- const TaskDbRow = Task.mapFields(Struct.assign({
37126
- labels: Schema$1.fromJsonString(Schema$1.Array(TaskLabel)),
37127
- externalRef: Schema$1.NullOr(Schema$1.fromJsonString(TaskExternalRef))
37128
- }));
37111
+ const TaskDbRow = Task.mapFields(Struct.assign({ labels: Schema$1.fromJsonString(Schema$1.Array(TaskLabel)) }));
37129
37112
  const TASK_COLUMNS = `
37130
37113
  task_id AS "taskId",
37131
37114
  readable_id AS "readableId",
37132
37115
  project_id AS "projectId",
37133
37116
  repository_key AS "repositoryKey",
37134
37117
  thread_id AS "threadId",
37135
- external_ref_json AS "externalRef",
37136
37118
  parent_task_id AS "parentTaskId",
37137
37119
  title,
37138
37120
  body,
@@ -37511,7 +37493,7 @@ const buildTaskRow = (input, taskId, timestamp, repositoryKey = null) => ({
37511
37493
  projectId: input.projectId ?? null,
37512
37494
  repositoryKey: repositoryKey ?? input.repositoryKey ?? null,
37513
37495
  threadId: input.threadId ?? null,
37514
- externalRef: input.externalRef ?? null,
37496
+ externalRef: null,
37515
37497
  parentTaskId: input.parentTaskId ?? null,
37516
37498
  title: input.title,
37517
37499
  body: input.body ?? "",
@@ -37559,6 +37541,38 @@ const resolveTaskReadableIdPrefix = Effect.fn("taskBoard.resolveReadableIdPrefix
37559
37541
  if (Option.isNone(file) || file.value.taskPrefix === void 0) return "T";
37560
37542
  return file.value.taskPrefix.toUpperCase();
37561
37543
  });
37544
+ /** Project settings + live snapshots into the two lookups a start needs. */
37545
+ const buildTaskStartProviderDefaults = (input) => ({
37546
+ defaultModelByInstance: new Map(Object.entries(input.providerInstances).flatMap(([instanceId, instance]) => instance?.defaultModel === void 0 ? [] : [[instanceId, instance.defaultModel]])),
37547
+ modelsByInstance: new Map(input.providers.map((provider) => [provider.instanceId, provider.models.map((model) => model.slug)]))
37548
+ });
37549
+ /**
37550
+ * The model a start should use: the instance's pinned default from settings
37551
+ * when it names something that instance can serve, otherwise the selection
37552
+ * stored on the project.
37553
+ *
37554
+ * The pin outranks the stored selection because a project's
37555
+ * `defaultModelSelection` is written once, when the project is created, and
37556
+ * never revisited — without this, every project created before the user picked
37557
+ * a default would keep starting tasks on whatever model its provider happened
37558
+ * to list first at the time.
37559
+ *
37560
+ * Only the model moves; the instance does not. A project bound to Claude keeps
37561
+ * running on Claude, because a per-instance pin says nothing about which
37562
+ * provider the work belongs on. Stored `options` are dropped along with the old
37563
+ * model — reasoning effort and context-window ids belong to the model that
37564
+ * declared them.
37565
+ */
37566
+ const applyPinnedDefaultModel = (selection, defaults) => {
37567
+ const pinned = defaults?.defaultModelByInstance.get(selection.instanceId);
37568
+ if (pinned === void 0 || pinned === selection.model) return selection;
37569
+ const models = defaults?.modelsByInstance.get(selection.instanceId);
37570
+ if (models !== void 0 && models.length > 0 && !models.includes(pinned)) return selection;
37571
+ return {
37572
+ instanceId: selection.instanceId,
37573
+ model: pinned
37574
+ };
37575
+ };
37562
37576
  /**
37563
37577
  * Everything that decides whether a task can be started, as one pure function.
37564
37578
  *
@@ -37572,7 +37586,7 @@ const resolveTaskReadableIdPrefix = Effect.fn("taskBoard.resolveReadableIdPrefix
37572
37586
  * The project is passed in as the repository returns it — including soft-deleted
37573
37587
  * rows, which is why `deletedAt` is checked here rather than assumed away.
37574
37588
  */
37575
- const resolveTaskStart = (task, project) => {
37589
+ const resolveTaskStart = (task, project, providerDefaults) => {
37576
37590
  if (task.projectId === null) return {
37577
37591
  startable: false,
37578
37592
  reason: "no-project"
@@ -37589,7 +37603,7 @@ const resolveTaskStart = (task, project) => {
37589
37603
  return {
37590
37604
  startable: true,
37591
37605
  projectId: task.projectId,
37592
- model
37606
+ model: applyPinnedDefaultModel(model, providerDefaults)
37593
37607
  };
37594
37608
  };
37595
37609
  /**
@@ -38467,106 +38481,6 @@ const make$37 = Effect.gen(function* () {
38467
38481
  });
38468
38482
  const layer$32 = Layer.effect(SkillRegistry, make$37);
38469
38483
  //#endregion
38470
- //#region src/mcp/TicketResolver.ts
38471
- /**
38472
- * The registered server name a Linear ticket is resolved through.
38473
- *
38474
- * Matched by name rather than by URL: the name is what the user typed in
38475
- * Settings and what every other surface calls it, and a workspace may reach
38476
- * Linear through a proxy URL that no pattern here would recognize.
38477
- */
38478
- const LINEAR_SERVER_NAME = "linear";
38479
- /** Linear's own tool for reading one issue. */
38480
- const LINEAR_GET_ISSUE_TOOL = "get_issue";
38481
- var TicketResolver = class extends Context.Service()("@p4code/cli/mcp/TicketResolver") {};
38482
- const stringField$1 = (record, key) => {
38483
- const value = record[key];
38484
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
38485
- };
38486
- const asRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
38487
- /**
38488
- * Find the issue inside whatever the tool returned.
38489
- *
38490
- * MCP leaves the shape of a tool result to the tool, so this accepts the three
38491
- * arrangements in the wild - the structured payload itself, that payload with
38492
- * the issue nested one level down, or a text block that happens to be JSON -
38493
- * rather than assuming the one Linear happens to send today.
38494
- */
38495
- const readIssue = (result) => {
38496
- const structured = asRecord$1(result.structuredContent);
38497
- if (structured !== void 0) {
38498
- const nested = asRecord$1(structured["issue"]);
38499
- if (nested !== void 0) return nested;
38500
- if (stringField$1(structured, "url") !== void 0) return structured;
38501
- }
38502
- try {
38503
- const parsed = JSON.parse(result.text);
38504
- const record = asRecord$1(parsed);
38505
- if (record === void 0) return structured;
38506
- return asRecord$1(record["issue"]) ?? record;
38507
- } catch {
38508
- return structured;
38509
- }
38510
- };
38511
- const make$36 = Effect.gen(function* () {
38512
- const registry = yield* McpRegistry;
38513
- const oauth = yield* McpOAuth;
38514
- const http = yield* HttpClient$1.HttpClient;
38515
- return { resolve: Effect.fn("TicketResolver.resolve")(function* (reference) {
38516
- const identifier = parseTicketReference(reference);
38517
- if (identifier === null) return yield* new TicketResolveError({
38518
- reason: "not_found",
38519
- detail: `"${reference}" does not look like a ticket reference.`
38520
- });
38521
- const server = (yield* registry.list).find((candidate) => candidate.registration.name.toLowerCase() === LINEAR_SERVER_NAME && candidate.registration.enabled);
38522
- if (server === void 0 || server.registration.transport === "stdio") return yield* new TicketResolveError({
38523
- reason: "not_configured",
38524
- detail: "No Linear MCP server is registered on this machine. Add it in Settings to link tickets."
38525
- });
38526
- const registration = server.registration;
38527
- const token = yield* oauth.accessTokenFor(registration);
38528
- const headers = {
38529
- ...registration.headers,
38530
- ...Option.isSome(token) ? { authorization: `Bearer ${token.value}` } : {}
38531
- };
38532
- if (Option.isNone(token) && Object.keys(registration.headers ?? {}).length === 0) return yield* new TicketResolveError({
38533
- reason: "not_authorized",
38534
- detail: "Linear is registered but not signed in on this machine. Sign in from Settings."
38535
- });
38536
- const result = yield* callMcpTool({
38537
- url: registration.url,
38538
- headers,
38539
- toolName: LINEAR_GET_ISSUE_TOOL,
38540
- arguments: { id: identifier }
38541
- }).pipe(Effect.provideService(HttpClient$1.HttpClient, http), Effect.mapError((error) => error.status === 401 || error.status === 403 ? new TicketResolveError({
38542
- reason: "not_authorized",
38543
- detail: "Linear rejected p4code's sign-in. Sign in again from Settings."
38544
- }) : new TicketResolveError({
38545
- reason: "unavailable",
38546
- detail: error.detail
38547
- })));
38548
- const issue = readIssue(result);
38549
- const url = issue === void 0 ? void 0 : stringField$1(issue, "url");
38550
- const title = issue === void 0 ? void 0 : stringField$1(issue, "title");
38551
- if (issue === void 0 || url === void 0 || title === void 0) return yield* new TicketResolveError({
38552
- reason: "not_found",
38553
- detail: `Linear returned nothing usable for ${identifier}.`
38554
- });
38555
- const externalRef = {
38556
- source: "linear",
38557
- identifier: stringField$1(issue, "identifier") ?? identifier,
38558
- url
38559
- };
38560
- const description = stringField$1(issue, "description");
38561
- return {
38562
- externalRef,
38563
- title,
38564
- ...description === void 0 ? {} : { description }
38565
- };
38566
- }) };
38567
- });
38568
- const layer$31 = Layer.effect(TicketResolver, make$36);
38569
- //#endregion
38570
38484
  //#region ../../packages/shared/src/KeyedCoalescingWorker.ts
38571
38485
  const makeKeyedCoalescingWorker = (options) => Effect.gen(function* () {
38572
38486
  const queue = yield* Effect.acquireRelease(TxQueue.unbounded(), TxQueue.shutdown);
@@ -38864,7 +38778,7 @@ const serversEqual = (left, right) => {
38864
38778
  }
38865
38779
  return true;
38866
38780
  };
38867
- const make$35 = Effect.gen(function* PortDiscoveryMake() {
38781
+ const make$36 = Effect.gen(function* PortDiscoveryMake() {
38868
38782
  const net = yield* NetService;
38869
38783
  const processRunner = yield* ProcessRunner;
38870
38784
  const hostPlatform = yield* HostProcessPlatform;
@@ -39015,7 +38929,7 @@ const make$35 = Effect.gen(function* PortDiscoveryMake() {
39015
38929
  unregisterTerminal
39016
38930
  });
39017
38931
  }).pipe(Effect.withSpan("PortDiscovery.make"));
39018
- const layer$30 = Layer.effect(PortDiscovery, make$35);
38932
+ const layer$31 = Layer.effect(PortDiscovery, make$36);
39019
38933
  //#endregion
39020
38934
  //#region src/terminal/Manager.ts
39021
38935
  /**
@@ -39693,7 +39607,7 @@ function normalizedRuntimeEnv(env) {
39693
39607
  if (entries.length === 0) return null;
39694
39608
  return Object.fromEntries(entries.toSorted(([left], [right]) => left.localeCompare(right)));
39695
39609
  }
39696
- const make$34 = Effect.fn("TerminalManager.make")(function* () {
39610
+ const make$35 = Effect.fn("TerminalManager.make")(function* () {
39697
39611
  const { terminalLogsDir } = yield* ServerConfig$1;
39698
39612
  const ptyAdapter = yield* PtyAdapter;
39699
39613
  const portDiscovery = yield* PortDiscovery;
@@ -40655,7 +40569,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
40655
40569
  subscribeMetadata
40656
40570
  });
40657
40571
  });
40658
- const layer$29 = Layer.effect(TerminalManager, make$34()).pipe(Layer.provide(layer$54));
40572
+ const layer$30 = Layer.effect(TerminalManager, make$35()).pipe(Layer.provide(layer$54));
40659
40573
  //#endregion
40660
40574
  //#region src/mcp/McpInvocationContext.ts
40661
40575
  var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
@@ -40865,7 +40779,7 @@ const classifyResponseError = (context, error) => {
40865
40779
  });
40866
40780
  }
40867
40781
  };
40868
- const make$33 = Effect.gen(function* PreviewAutomationBrokerMake() {
40782
+ const make$34 = Effect.gen(function* PreviewAutomationBrokerMake() {
40869
40783
  const crypto = yield* Crypto.Crypto;
40870
40784
  const state = yield* SynchronizedRef.make({
40871
40785
  clients: /* @__PURE__ */ new Map(),
@@ -41099,7 +41013,7 @@ const make$33 = Effect.gen(function* PreviewAutomationBrokerMake() {
41099
41013
  invoke
41100
41014
  });
41101
41015
  }).pipe(Effect.withSpan("PreviewAutomationBroker.make"));
41102
- const layer$28 = Layer.effect(PreviewAutomationBroker, make$33);
41016
+ const layer$29 = Layer.effect(PreviewAutomationBroker, make$34);
41103
41017
  //#endregion
41104
41018
  //#region src/preview/Manager.ts
41105
41019
  /**
@@ -41163,7 +41077,7 @@ const buildIdleSnapshot = (input) => ({
41163
41077
  viewport: FILL_PREVIEW_VIEWPORT,
41164
41078
  updatedAt: input.updatedAt
41165
41079
  });
41166
- const make$32 = Effect.gen(function* PreviewManagerMake() {
41080
+ const make$33 = Effect.gen(function* PreviewManagerMake() {
41167
41081
  const serverEpoch = NodeCrypto.randomUUID();
41168
41082
  const stateRef = yield* SynchronizedRef.make(initialState);
41169
41083
  const eventsPubSub = yield* PubSub.unbounded();
@@ -41394,7 +41308,7 @@ const make$32 = Effect.gen(function* PreviewManagerMake() {
41394
41308
  subscribeEvents: PubSub.subscribe(eventsPubSub)
41395
41309
  });
41396
41310
  }).pipe(Effect.withSpan("PreviewManager.make"));
41397
- const layer$27 = Layer.effect(PreviewManager, make$32);
41311
+ const layer$28 = Layer.effect(PreviewManager, make$33);
41398
41312
  //#endregion
41399
41313
  //#region src/workspace/WorkspaceSearchIndex.ts
41400
41314
  const WORKSPACE_INDEX_MAX_ENTRIES = 25e3;
@@ -41528,7 +41442,7 @@ const waitForScan = (cwd, finder, onFailure) => Effect.try({
41528
41442
  timeout: WORKSPACE_INDEX_SCAN_TIMEOUT
41529
41443
  })
41530
41444
  }), Effect.withSpan("WorkspaceSearchIndex.waitForScan"));
41531
- const make$31 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
41445
+ const make$32 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
41532
41446
  const finder = yield* Effect.acquireRelease(createFinder(cwd), (finder) => Effect.try({
41533
41447
  try: () => finder.destroy(),
41534
41448
  catch: (cause) => new WorkspaceSearchIndexDestroyFailed({
@@ -41602,9 +41516,9 @@ const make$31 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
41602
41516
  * workspace root. WorkspaceSearchIndexMap owns memoization and idle cleanup;
41603
41517
  * using a default cwd here would mix resources from different workspaces.
41604
41518
  */
41605
- const layer$26 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$31(cwd));
41519
+ const layer$27 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$32(cwd));
41606
41520
  var WorkspaceSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceSearchIndexMap", {
41607
- lookup: layer$26,
41521
+ lookup: layer$27,
41608
41522
  idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
41609
41523
  }) {};
41610
41524
  //#endregion
@@ -41666,7 +41580,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu
41666
41580
  if (!input.cwd) return yield* new WorkspaceEntriesCurrentProjectRequiredError({ partialPath: input.partialPath });
41667
41581
  return path.resolve(expandHomePath$1(input.cwd, path), input.partialPath);
41668
41582
  });
41669
- const make$30 = Effect.gen(function* () {
41583
+ const make$31 = Effect.gen(function* () {
41670
41584
  const path = yield* Path.Path;
41671
41585
  const workspacePaths = yield* WorkspacePaths;
41672
41586
  const workspaceSearchIndexes = yield* WorkspaceSearchIndexMap;
@@ -41740,7 +41654,7 @@ const make$30 = Effect.gen(function* () {
41740
41654
  search
41741
41655
  });
41742
41656
  });
41743
- const layer$25 = Layer.effect(WorkspaceEntries, make$30).pipe(Layer.provide(WorkspaceSearchIndexMap.layer));
41657
+ const layer$26 = Layer.effect(WorkspaceEntries, make$31).pipe(Layer.provide(WorkspaceSearchIndexMap.layer));
41744
41658
  //#endregion
41745
41659
  //#region src/workspace/WorkspaceFileSystem.ts
41746
41660
  /**
@@ -41799,7 +41713,7 @@ Schema$1.Union([
41799
41713
  ]);
41800
41714
  /** Service tag for workspace file operations. */
41801
41715
  var WorkspaceFileSystem = class extends Context.Service()("@p4code/cli/workspace/WorkspaceFileSystem") {};
41802
- const make$29 = Effect.gen(function* () {
41716
+ const make$30 = Effect.gen(function* () {
41803
41717
  const fileSystem = yield* FileSystem.FileSystem;
41804
41718
  const path = yield* Path.Path;
41805
41719
  const workspacePaths = yield* WorkspacePaths;
@@ -41934,7 +41848,7 @@ const make$29 = Effect.gen(function* () {
41934
41848
  writeFile
41935
41849
  });
41936
41850
  });
41937
- const layer$24 = Layer.effect(WorkspaceFileSystem, make$29);
41851
+ const layer$25 = Layer.effect(WorkspaceFileSystem, make$30);
41938
41852
  //#endregion
41939
41853
  //#region src/textGeneration/TextGenerationPresets.ts
41940
41854
  const conventionalCommitsTextGenerationPolicy = {
@@ -41998,7 +41912,7 @@ var ProjectSetupScriptProjectNotFoundError = class extends Schema$1.TaggedErrorC
41998
41912
  };
41999
41913
  Schema$1.Union([ProjectSetupScriptOperationError, ProjectSetupScriptProjectNotFoundError]);
42000
41914
  var ProjectSetupScriptRunner = class extends Context.Service()("@p4code/cli/project/ProjectSetupScriptRunner") {};
42001
- const make$28 = Effect.gen(function* () {
41915
+ const make$29 = Effect.gen(function* () {
42002
41916
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
42003
41917
  const terminalManager = yield* TerminalManager;
42004
41918
  const runForThread = Effect.fn("ProjectSetupScriptRunner.runForThread")(function* (input) {
@@ -42056,7 +41970,7 @@ const make$28 = Effect.gen(function* () {
42056
41970
  });
42057
41971
  return ProjectSetupScriptRunner.of({ runForThread });
42058
41972
  });
42059
- const layer$23 = Layer.effect(ProjectSetupScriptRunner, make$28);
41973
+ const layer$24 = Layer.effect(ProjectSetupScriptRunner, make$29);
42060
41974
  //#endregion
42061
41975
  //#region src/sourceControl/azureDevOpsPullRequests.ts
42062
41976
  const AzureDevOpsPullRequestSchema = Schema$1.Struct({
@@ -42359,7 +42273,7 @@ function decodeAzureDevOpsJson(raw, schema, operation, cwd) {
42359
42273
  cause
42360
42274
  })));
42361
42275
  }
42362
- const make$27 = Effect.gen(function* () {
42276
+ const make$28 = Effect.gen(function* () {
42363
42277
  const process = yield* VcsProcess;
42364
42278
  const execute = (input) => process.run({
42365
42279
  operation: "AzureDevOpsCli.execute",
@@ -42501,7 +42415,7 @@ const make$27 = Effect.gen(function* () {
42501
42415
  }).pipe(Effect.asVoid)
42502
42416
  });
42503
42417
  });
42504
- const layer$22 = Layer.effect(AzureDevOpsCli, make$27);
42418
+ const layer$23 = Layer.effect(AzureDevOpsCli, make$28);
42505
42419
  //#endregion
42506
42420
  //#region src/sourceControl/SourceControlProviderDiscovery.ts
42507
42421
  function firstNonEmptyLine(text) {
@@ -42704,7 +42618,7 @@ function toChangeRequest$3(summary) {
42704
42618
  isCrossRepository: false
42705
42619
  };
42706
42620
  }
42707
- const make$26 = Effect.gen(function* () {
42621
+ const make$27 = Effect.gen(function* () {
42708
42622
  const azure = yield* AzureDevOpsCli;
42709
42623
  return SourceControlProvider.of({
42710
42624
  kind: "azure-devops",
@@ -42796,7 +42710,7 @@ const make$26 = Effect.gen(function* () {
42796
42710
  })))
42797
42711
  });
42798
42712
  });
42799
- Layer.effect(SourceControlProvider, make$26);
42713
+ Layer.effect(SourceControlProvider, make$27);
42800
42714
  //#endregion
42801
42715
  //#region src/sourceControl/bitbucketPullRequests.ts
42802
42716
  const BitbucketRepositoryRefSchema = Schema$1.Struct({
@@ -43110,7 +43024,7 @@ function responseError(operation, response) {
43110
43024
  responseBodyLength: body.length
43111
43025
  }))));
43112
43026
  }
43113
- const make$25 = Effect.gen(function* () {
43027
+ const make$26 = Effect.gen(function* () {
43114
43028
  const config = yield* BitbucketApiEnvConfig;
43115
43029
  const httpClient = yield* HttpClient.HttpClient;
43116
43030
  const fileSystem = yield* FileSystem.FileSystem;
@@ -43274,7 +43188,7 @@ const make$25 = Effect.gen(function* () {
43274
43188
  })))
43275
43189
  });
43276
43190
  });
43277
- const layer$20 = Layer.effect(BitbucketApi, make$25);
43191
+ const layer$21 = Layer.effect(BitbucketApi, make$26);
43278
43192
  //#endregion
43279
43193
  //#region src/sourceControl/BitbucketSourceControlProvider.ts
43280
43194
  function toChangeRequest$2(summary) {
@@ -43292,7 +43206,7 @@ function toChangeRequest$2(summary) {
43292
43206
  ...summary.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin } : {}
43293
43207
  };
43294
43208
  }
43295
- const make$24 = Effect.gen(function* () {
43209
+ const make$25 = Effect.gen(function* () {
43296
43210
  const bitbucket = yield* BitbucketApi;
43297
43211
  return SourceControlProvider.of({
43298
43212
  kind: "bitbucket",
@@ -43383,7 +43297,7 @@ const make$24 = Effect.gen(function* () {
43383
43297
  })))
43384
43298
  });
43385
43299
  });
43386
- Layer.effect(SourceControlProvider, make$24);
43300
+ Layer.effect(SourceControlProvider, make$25);
43387
43301
  const makeDiscovery = Effect.gen(function* () {
43388
43302
  return {
43389
43303
  type: "api",
@@ -43612,7 +43526,7 @@ function deriveRepositoryCloneUrlsFromCreateOutput(stdout, repository) {
43612
43526
  sshUrl: `git@${fallbackHost}:${repository}.git`
43613
43527
  };
43614
43528
  }
43615
- const make$23 = Effect.gen(function* () {
43529
+ const make$24 = Effect.gen(function* () {
43616
43530
  const process = yield* VcsProcess;
43617
43531
  const execute = (input) => process.run({
43618
43532
  operation: "GitHubCli.execute",
@@ -43728,7 +43642,7 @@ const make$23 = Effect.gen(function* () {
43728
43642
  }).pipe(Effect.asVoid)
43729
43643
  });
43730
43644
  });
43731
- const layer$18 = Layer.effect(GitHubCli, make$23);
43645
+ const layer$19 = Layer.effect(GitHubCli, make$24);
43732
43646
  //#endregion
43733
43647
  //#region src/sourceControl/gitHubAuthStatus.ts
43734
43648
  const GitHubAuthStatusAccountSchema = Schema$1.Struct({
@@ -43829,7 +43743,7 @@ const discovery$1 = {
43829
43743
  parseAuth: parseGitHubAuth,
43830
43744
  installHint: "Install the GitHub command-line tool (`gh`) via https://cli.github.com/ or your package manager (for example `brew install gh`)."
43831
43745
  };
43832
- const make$22 = Effect.gen(function* () {
43746
+ const make$23 = Effect.gen(function* () {
43833
43747
  const github = yield* GitHubCli;
43834
43748
  const listChangeRequests = (input) => {
43835
43749
  if (input.state === "open") return github.listOpenPullRequests({
@@ -43945,7 +43859,7 @@ const make$22 = Effect.gen(function* () {
43945
43859
  })))
43946
43860
  });
43947
43861
  });
43948
- Layer.effect(SourceControlProvider, make$22);
43862
+ Layer.effect(SourceControlProvider, make$23);
43949
43863
  //#endregion
43950
43864
  //#region src/sourceControl/gitLabMergeRequests.ts
43951
43865
  const GitLabProjectReferenceSchema = Schema$1.Struct({
@@ -44256,7 +44170,7 @@ function parseRepositoryPath(repository) {
44256
44170
  projectPath
44257
44171
  };
44258
44172
  }
44259
- const make$21 = Effect.gen(function* () {
44173
+ const make$22 = Effect.gen(function* () {
44260
44174
  const process = yield* VcsProcess;
44261
44175
  const run = (input, mapError) => process.run({
44262
44176
  operation: "GitLabCli.execute",
@@ -44405,7 +44319,7 @@ const make$21 = Effect.gen(function* () {
44405
44319
  }).pipe(Effect.asVoid)
44406
44320
  });
44407
44321
  });
44408
- const layer$16 = Layer.effect(GitLabCli, make$21);
44322
+ const layer$17 = Layer.effect(GitLabCli, make$22);
44409
44323
  //#endregion
44410
44324
  //#region src/sourceControl/gitLabAuthStatus.ts
44411
44325
  const HOST_LINE_PATTERN = /^(?:[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?|\[[a-f0-9:.]+\])(?::\d+)?$/iu;
@@ -44502,7 +44416,7 @@ const discovery = {
44502
44416
  refineUnknownRemote: refineUnknownGitLabRemote,
44503
44417
  installHint: "Install the GitLab command-line tool (`glab`) from https://gitlab.com/gitlab-org/cli or your package manager (for example `brew install glab`)."
44504
44418
  };
44505
- const make$20 = Effect.gen(function* () {
44419
+ const make$21 = Effect.gen(function* () {
44506
44420
  const gitlab = yield* GitLabCli;
44507
44421
  return SourceControlProvider.of({
44508
44422
  kind: "gitlab",
@@ -44590,7 +44504,7 @@ const make$20 = Effect.gen(function* () {
44590
44504
  })))
44591
44505
  });
44592
44506
  });
44593
- Layer.effect(SourceControlProvider, make$20);
44507
+ Layer.effect(SourceControlProvider, make$21);
44594
44508
  //#endregion
44595
44509
  //#region src/sourceControl/SourceControlProviderRegistry.ts
44596
44510
  const PROVIDER_DETECTION_CACHE_CAPACITY = 2048;
@@ -44741,12 +44655,12 @@ const makeWithProviders = Effect.fn("makeSourceControlProviderRegistryWithProvid
44741
44655
  })), { concurrency: "unbounded" })
44742
44656
  });
44743
44657
  });
44744
- const make$19 = Effect.gen(function* () {
44745
- const github = yield* make$22;
44746
- const gitlab = yield* make$20;
44747
- const bitbucket = yield* make$24;
44658
+ const make$20 = Effect.gen(function* () {
44659
+ const github = yield* make$23;
44660
+ const gitlab = yield* make$21;
44661
+ const bitbucket = yield* make$25;
44748
44662
  const bitbucketDiscovery = yield* makeDiscovery;
44749
- const azureDevOps = yield* make$26;
44663
+ const azureDevOps = yield* make$27;
44750
44664
  return yield* makeWithProviders([
44751
44665
  {
44752
44666
  kind: "github",
@@ -44770,7 +44684,7 @@ const make$19 = Effect.gen(function* () {
44770
44684
  }
44771
44685
  ]);
44772
44686
  });
44773
- const layer$14 = Layer.effect(SourceControlProviderRegistry, make$19);
44687
+ const layer$15 = Layer.effect(SourceControlProviderRegistry, make$20);
44774
44688
  //#endregion
44775
44689
  //#region src/sourceControl/PrTemplateDetection.ts
44776
44690
  const TEMPLATE_MAX_BYTES = 8e3;
@@ -45140,7 +45054,7 @@ function toPullRequestHeadRemoteInfo(pr) {
45140
45054
  ...pr.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: pr.headRepositoryOwnerLogin } : {}
45141
45055
  };
45142
45056
  }
45143
- const make$18 = Effect.gen(function* () {
45057
+ const make$19 = Effect.gen(function* () {
45144
45058
  const gitCore = yield* GitVcsDriver;
45145
45059
  const sourceControlProviders = yield* SourceControlProviderRegistry;
45146
45060
  const textGeneration = yield* TextGeneration;
@@ -46058,7 +45972,7 @@ const make$18 = Effect.gen(function* () {
46058
45972
  runStackedAction
46059
45973
  });
46060
45974
  });
46061
- const layer$13 = Layer.effect(GitManager, make$18);
45975
+ const layer$14 = Layer.effect(GitManager, make$19);
46062
45976
  //#endregion
46063
45977
  //#region src/git/GitWorkflowService.ts
46064
45978
  var GitWorkflowService = class extends Context.Service()("@p4code/cli/git/GitWorkflowService") {};
@@ -46095,7 +46009,7 @@ function nonRepositoryListRefs() {
46095
46009
  totalCount: 0
46096
46010
  };
46097
46011
  }
46098
- const make$17 = Effect.gen(function* () {
46012
+ const make$18 = Effect.gen(function* () {
46099
46013
  const registry = yield* VcsDriverRegistry;
46100
46014
  const git = yield* GitVcsDriver;
46101
46015
  const gitManager = yield* GitManager;
@@ -46181,7 +46095,7 @@ const make$17 = Effect.gen(function* () {
46181
46095
  renameBranch: (input) => ensureGit("GitWorkflowService.renameBranch", input.cwd).pipe(Effect.andThen(git.renameBranch(input)))
46182
46096
  });
46183
46097
  });
46184
- const layer$12 = Layer.effect(GitWorkflowService, make$17);
46098
+ const layer$13 = Layer.effect(GitWorkflowService, make$18);
46185
46099
  //#endregion
46186
46100
  //#region src/vcs/VcsStatusBroadcaster.ts
46187
46101
  const DEFAULT_VCS_STATUS_REFRESH_INTERVAL = Duration.seconds(30);
@@ -46253,7 +46167,7 @@ function fingerprintStatusPart(status) {
46253
46167
  return JSON.stringify(status);
46254
46168
  }
46255
46169
  const normalizeCwd = (cwd) => Effect.service(FileSystem.FileSystem).pipe(Effect.flatMap((fs) => fs.realPath(cwd)), Effect.orElseSucceed(() => cwd));
46256
- const make$16 = Effect.gen(function* () {
46170
+ const make$17 = Effect.gen(function* () {
46257
46171
  const workflow = yield* GitWorkflowService;
46258
46172
  const fs = yield* FileSystem.FileSystem;
46259
46173
  const changesPubSub = yield* Effect.acquireRelease(PubSub.unbounded(), (pubsub) => PubSub.shutdown(pubsub));
@@ -46477,7 +46391,7 @@ const make$16 = Effect.gen(function* () {
46477
46391
  streamStatus
46478
46392
  });
46479
46393
  });
46480
- const layer$11 = Layer.effect(VcsStatusBroadcaster, make$16);
46394
+ const layer$12 = Layer.effect(VcsStatusBroadcaster, make$17);
46481
46395
  //#endregion
46482
46396
  //#region src/vcs/VcsProvisioningService.ts
46483
46397
  var VcsProvisioningService = class extends Context.Service()("@p4code/cli/vcs/VcsProvisioningService") {};
@@ -46490,7 +46404,7 @@ function resolveRequestedKind(kind) {
46490
46404
  }));
46491
46405
  return Effect.succeed(kind);
46492
46406
  }
46493
- const make$15 = Effect.gen(function* () {
46407
+ const make$16 = Effect.gen(function* () {
46494
46408
  const registry = yield* VcsDriverRegistry;
46495
46409
  const initRepository = Effect.fn("VcsProvisioningService.initRepository")(function* (input) {
46496
46410
  const kind = yield* resolveRequestedKind(input.kind);
@@ -46498,11 +46412,11 @@ const make$15 = Effect.gen(function* () {
46498
46412
  });
46499
46413
  return VcsProvisioningService.of({ initRepository });
46500
46414
  });
46501
- const layer$10 = Layer.effect(VcsProvisioningService, make$15);
46415
+ const layer$11 = Layer.effect(VcsProvisioningService, make$16);
46502
46416
  //#endregion
46503
46417
  //#region src/review/ReviewService.ts
46504
46418
  var ReviewService = class extends Context.Service()("@p4code/cli/review/ReviewService") {};
46505
- const make$14 = Effect.gen(function* () {
46419
+ const make$15 = Effect.gen(function* () {
46506
46420
  const config = yield* ServerConfig$1;
46507
46421
  const fileSystem = yield* FileSystem.FileSystem;
46508
46422
  const path = yield* Path.Path;
@@ -46558,7 +46472,7 @@ const make$14 = Effect.gen(function* () {
46558
46472
  });
46559
46473
  return ReviewService.of({ getDiffPreview });
46560
46474
  });
46561
- const layer$9 = Layer.effect(ReviewService, make$14);
46475
+ const layer$10 = Layer.effect(ReviewService, make$15);
46562
46476
  //#endregion
46563
46477
  //#region src/diagnostics/ProcessDiagnostics.ts
46564
46478
  const PROCESS_QUERY_TIMEOUT_MS = 1e3;
@@ -46853,7 +46767,7 @@ function assertDescendantPid(pid) {
46853
46767
  }));
46854
46768
  }));
46855
46769
  }
46856
- const make$13 = Effect.gen(function* () {
46770
+ const make$14 = Effect.gen(function* () {
46857
46771
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
46858
46772
  const read = Effect.gen(function* () {
46859
46773
  const readAt = yield* DateTime.now;
@@ -46897,7 +46811,7 @@ const make$13 = Effect.gen(function* () {
46897
46811
  signal
46898
46812
  });
46899
46813
  });
46900
- const layer$8 = Layer.effect(ProcessDiagnostics, make$13);
46814
+ const layer$9 = Layer.effect(ProcessDiagnostics, make$14);
46901
46815
  //#endregion
46902
46816
  //#region src/diagnostics/ProcessResourceMonitor.ts
46903
46817
  const SAMPLE_INTERVAL_MS = 5e3;
@@ -47048,7 +46962,7 @@ function aggregateProcessResourceHistory(input) {
47048
46962
  }) : Option.none()
47049
46963
  };
47050
46964
  }
47051
- const make$12 = Effect.gen(function* () {
46965
+ const make$13 = Effect.gen(function* () {
47052
46966
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
47053
46967
  const state = yield* Ref.make({
47054
46968
  samples: [],
@@ -47097,7 +47011,7 @@ const make$12 = Effect.gen(function* () {
47097
47011
  });
47098
47012
  return ProcessResourceMonitor.of({ readHistory });
47099
47013
  });
47100
- const layer$7 = Layer.effect(ProcessResourceMonitor, make$12);
47014
+ const layer$8 = Layer.effect(ProcessResourceMonitor, make$13);
47101
47015
  //#endregion
47102
47016
  //#region src/diagnostics/TraceDiagnostics.ts
47103
47017
  var TraceFileReadError = class extends Schema$1.TaggedErrorClass()("TraceFileReadError", {
@@ -47345,7 +47259,7 @@ function readTraceFile(fileSystem, path) {
47345
47259
  cause
47346
47260
  })) }));
47347
47261
  }
47348
- const make$11 = Effect.gen(function* () {
47262
+ const make$12 = Effect.gen(function* () {
47349
47263
  const fileSystem = yield* FileSystem.FileSystem;
47350
47264
  const read = Effect.fn("TraceDiagnostics.read")(function* (options) {
47351
47265
  const readAt = options.readAt ?? (yield* DateTime.now);
@@ -47389,7 +47303,7 @@ const make$11 = Effect.gen(function* () {
47389
47303
  });
47390
47304
  return TraceDiagnostics.of({ read });
47391
47305
  });
47392
- const layer$6 = Layer.effect(TraceDiagnostics, make$11);
47306
+ const layer$7 = Layer.effect(TraceDiagnostics, make$12);
47393
47307
  function readTraceDiagnostics(options) {
47394
47308
  return Effect.gen(function* () {
47395
47309
  return yield* (yield* TraceDiagnostics).read(options);
@@ -47413,7 +47327,7 @@ const VCS_PROBES = [{
47413
47327
  installHint: "Install Jujutsu with `brew install jj` or from https://github.com/jj-vcs/jj."
47414
47328
  }];
47415
47329
  var SourceControlDiscovery = class extends Context.Service()("@p4code/cli/sourceControl/SourceControlDiscovery") {};
47416
- const make$10 = Effect.gen(function* () {
47330
+ const make$11 = Effect.gen(function* () {
47417
47331
  const config = yield* ServerConfig$1;
47418
47332
  const process = yield* VcsProcess;
47419
47333
  const sourceControlProviders = yield* SourceControlProviderRegistry;
@@ -47462,7 +47376,7 @@ const make$10 = Effect.gen(function* () {
47462
47376
  sourceControlProviders: sourceControlProviders.discover
47463
47377
  }) });
47464
47378
  });
47465
- const layer$5 = Layer.effect(SourceControlDiscovery, make$10);
47379
+ const layer$6 = Layer.effect(SourceControlDiscovery, make$11);
47466
47380
  //#endregion
47467
47381
  //#region src/sourceControl/SourceControlRepositoryService.ts
47468
47382
  const isSourceControlRepositoryError = Schema$1.is(SourceControlRepositoryError);
@@ -47495,7 +47409,7 @@ function expandHomePath(input, path) {
47495
47409
  if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
47496
47410
  return input;
47497
47411
  }
47498
- const make$9 = Effect.gen(function* () {
47412
+ const make$10 = Effect.gen(function* () {
47499
47413
  const config = yield* ServerConfig$1;
47500
47414
  const fileSystem = yield* FileSystem.FileSystem;
47501
47415
  const git = yield* GitVcsDriver;
@@ -47634,7 +47548,7 @@ const make$9 = Effect.gen(function* () {
47634
47548
  publishRepository: (input) => publishRepository(input).pipe(mapRepositoryError("publishRepository", input.provider))
47635
47549
  });
47636
47550
  });
47637
- const layer$4 = Layer.effect(SourceControlRepositoryService, make$9);
47551
+ const layer$5 = Layer.effect(SourceControlRepositoryService, make$10);
47638
47552
  //#endregion
47639
47553
  //#region src/ws.ts
47640
47554
  /** Matches `p4c hub token add`, so a token minted here and one minted there are the same thing. */
@@ -47756,8 +47670,6 @@ const RPC_REQUIRED_SCOPE = /* @__PURE__ */ new Map([
47756
47670
  [WS_METHODS.tasksUpdate, AuthOrchestrationOperateScope],
47757
47671
  [WS_METHODS.tasksDelete, AuthOrchestrationOperateScope],
47758
47672
  [WS_METHODS.tasksStartThread, AuthOrchestrationOperateScope],
47759
- [WS_METHODS.tasksRefreshExternal, AuthOrchestrationOperateScope],
47760
- [WS_METHODS.ticketsResolve, AuthOrchestrationReadScope],
47761
47673
  [WS_METHODS.subscribeTasks, AuthOrchestrationReadScope],
47762
47674
  [WS_METHODS.hubGetSyncStatus, AuthOrchestrationReadScope],
47763
47675
  [WS_METHODS.hubConnect, AuthOrchestrationOperateScope],
@@ -47912,8 +47824,6 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
47912
47824
  const mcpOAuth = yield* McpOAuth;
47913
47825
  const claudeMcpFiles = yield* ClaudeMcpFiles;
47914
47826
  const skillRegistry = yield* SkillRegistry;
47915
- const ticketResolver = yield* TicketResolver;
47916
- const linearClient = yield* LinearMcpClient;
47917
47827
  const listMcpServersEverywhere = Effect.gen(function* () {
47918
47828
  const servers = [...yield* mcpRegistry.list];
47919
47829
  const projectRows = yield* projectionProjects.listAll().pipe(Effect.map((rows) => rows.filter((row) => row.deletedAt === null)), Effect.orElseSucceed(() => []));
@@ -48406,7 +48316,12 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
48406
48316
  const found = yield* tasks.getById({ taskId }).pipe(Effect.catch(toTaskStoreError("tasks.startThread")));
48407
48317
  if (Option.isNone(found)) return yield* new TaskNotFoundError({ taskId });
48408
48318
  const task = found.value;
48409
- const plan = resolveTaskStart(task, task.projectId === null ? Option.none() : yield* projectionProjects.getById({ projectId: task.projectId }).pipe(Effect.catch(toTaskStoreError("tasks.startThread.project"))));
48319
+ const plan = resolveTaskStart(task, task.projectId === null ? Option.none() : yield* projectionProjects.getById({ projectId: task.projectId }).pipe(Effect.catch(toTaskStoreError("tasks.startThread.project"))), yield* Effect.gen(function* () {
48320
+ return buildTaskStartProviderDefaults({
48321
+ providerInstances: (yield* serverSettings.getSettings).providerInstances,
48322
+ providers: yield* providerRegistry.getProviders
48323
+ });
48324
+ }).pipe(Effect.tapError((cause) => Effect.logWarning("task start could not read provider defaults", { cause })), Effect.orElseSucceed(() => void 0)));
48410
48325
  if (!plan.startable) return yield* new TaskNotStartableError({
48411
48326
  taskId,
48412
48327
  reason: plan.reason
@@ -48464,48 +48379,6 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
48464
48379
  threadId
48465
48380
  };
48466
48381
  }), { "rpc.aggregate": "tasks" }),
48467
- /**
48468
- * Bring a mirror back in line with the tracker issue it mirrors.
48469
- *
48470
- * The local row is the cache. Everything Linear owns - title, body,
48471
- * status, priority, assignee, labels - is overwritten from the issue,
48472
- * and everything p4code owns - the thread, the project, the readable
48473
- * id, the board position - is left exactly as it was. Nothing is
48474
- * written back to Linear, so a refresh can never lose work there.
48475
- *
48476
- * Always against the board source, never `linear`: refreshing a row
48477
- * that *is* the Linear issue would be copying it onto itself.
48478
- */
48479
- [WS_METHODS.tasksRefreshExternal]: ({ taskId }) => observeRpcEffect$1(WS_METHODS.tasksRefreshExternal, Effect.gen(function* () {
48480
- const tasks = taskRepositories.forSource(DEFAULT_TASK_SOURCE);
48481
- const found = yield* tasks.getById({ taskId }).pipe(Effect.catch(toTaskStoreError("tasks.refreshExternal")));
48482
- if (Option.isNone(found)) return yield* new TaskNotFoundError({ taskId });
48483
- const task = found.value;
48484
- if (task.externalRef === null) return { task };
48485
- const payload = yield* linearClient.call(LINEAR_GET_ISSUE_TOOL$1, { id: task.externalRef.identifier }).pipe(Effect.mapError((cause) => new TicketResolveError({
48486
- reason: cause.reason === "failed" ? "unavailable" : cause.reason,
48487
- detail: cause.detail
48488
- })));
48489
- const issue = readOne(payload);
48490
- const fields = issue === void 0 ? void 0 : linearMirrorFields(issue);
48491
- if (fields === void 0) return yield* new TicketResolveError({
48492
- reason: "not_found",
48493
- detail: `Linear returned nothing usable for ${task.externalRef.identifier}.`
48494
- });
48495
- const patched = yield* tasks.patch({
48496
- taskId,
48497
- ...fields
48498
- }, yield* nowIso$5).pipe(Effect.catch(toTaskStoreError("tasks.refreshExternal.patch")));
48499
- if (Option.isNone(patched)) return yield* new TaskNotFoundError({ taskId });
48500
- return { task: patched.value };
48501
- }), { "rpc.aggregate": "tasks" }),
48502
- /**
48503
- * What a pasted reference is, straight from the tracker.
48504
- *
48505
- * Nothing is written here: the client decides whether the answer
48506
- * becomes a task, so an accidental paste costs one request and no row.
48507
- */
48508
- [WS_METHODS.ticketsResolve]: ({ reference }) => observeRpcEffect$1(WS_METHODS.ticketsResolve, ticketResolver.resolve(reference), { "rpc.aggregate": "tickets" }),
48509
48382
  [WS_METHODS.subscribeTasks]: ({ source }) => observeRpcStreamEffect$1(WS_METHODS.subscribeTasks, Effect.succeed(taskRepositories.forSource(source).streamWithSnapshot.pipe(Stream.catch((cause) => Stream.fromEffect(toTaskStoreError("tasks.subscribe")(cause))))), { "rpc.aggregate": "tasks" }),
48510
48383
  [WS_METHODS.hubGetSyncStatus]: (_input) => observeRpcEffect$1(WS_METHODS.hubGetSyncStatus, assetSync.status, { "rpc.aggregate": "hub" }),
48511
48384
  [WS_METHODS.hubConnect]: (input) => observeRpcEffect$1(WS_METHODS.hubConnect, hubLink.connect(input).pipe(Effect.mapError((cause) => new HubLinkError({ detail: cause.message })), Effect.andThen(assetSync.status)), { "rpc.aggregate": "hub" }),
@@ -48773,7 +48646,7 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
48773
48646
  const serverAuth = yield* EnvironmentAuth;
48774
48647
  const sessions = yield* SessionStore;
48775
48648
  const session = yield* serverAuth.authenticateWebSocketUpgrade(request).pipe(Effect.catchIf(isServerAuthCredentialError, (error) => failEnvironmentAuthInvalid(serverAuthCredentialReason(error))), Effect.catchIf(isServerAuthInternalError, (error) => failEnvironmentInternal("internal_error", error)));
48776
- const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$34), Layer.provide(Layer.succeed(ServerSelfUpdate, serverSelfUpdate)), Layer.provide(Layer.succeed(TaskRepositoryRegistry, taskRepositories)), Layer.provide(Layer.succeed(ProjectionProjectRepository, projectionProjects)), Layer.provide(Layer.succeed(P4ProjectFileLoader, p4ProjectFileLoader)), Layer.provide(layer$5.pipe(Layer.provide(layer$14.pipe(Layer.provide(Layer.mergeAll(layer$22, layer$20, layer$18, layer$16)), Layer.provideMerge(layer$39), Layer.provide(layer$37.pipe(Layer.provide(layer$38))))), Layer.provide(layer$40))))));
48649
+ const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$34), Layer.provide(Layer.succeed(ServerSelfUpdate, serverSelfUpdate)), Layer.provide(Layer.succeed(TaskRepositoryRegistry, taskRepositories)), Layer.provide(Layer.succeed(ProjectionProjectRepository, projectionProjects)), Layer.provide(Layer.succeed(P4ProjectFileLoader, p4ProjectFileLoader)), Layer.provide(layer$6.pipe(Layer.provide(layer$15.pipe(Layer.provide(Layer.mergeAll(layer$23, layer$21, layer$19, layer$17)), Layer.provideMerge(layer$39), Layer.provide(layer$37.pipe(Layer.provide(layer$38))))), Layer.provide(layer$40))))));
48777
48650
  return yield* Effect.acquireUseRelease(sessions.markConnected(session.sessionId), () => rpcWebSocketHttpEffect, () => sessions.markDisconnected(session.sessionId));
48778
48651
  }).pipe(Effect.catchTags({
48779
48652
  EnvironmentAuthInvalidError: HttpServerRespondable.toResponse,
@@ -48838,7 +48711,7 @@ function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation, correlatio
48838
48711
  cause
48839
48712
  });
48840
48713
  }
48841
- const make$8 = Effect.gen(function* () {
48714
+ const make$9 = Effect.gen(function* () {
48842
48715
  const sql = yield* SqlClient.SqlClient;
48843
48716
  const upsertRuntimeRow = SqlSchema.void({
48844
48717
  Request: ProviderSessionRuntimeDbRowSchema,
@@ -48941,7 +48814,7 @@ const make$8 = Effect.gen(function* () {
48941
48814
  deleteByThreadId
48942
48815
  };
48943
48816
  });
48944
- const layer$3 = Layer.effect(ProviderSessionRuntimeRepository, make$8);
48817
+ const layer$4 = Layer.effect(ProviderSessionRuntimeRepository, make$9);
48945
48818
  //#endregion
48946
48819
  //#region src/provider/Errors.ts
48947
48820
  /**
@@ -49636,12 +49509,12 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
49636
49509
  });
49637
49510
  });
49638
49511
  let activeMcpSessionRegistry;
49639
- const make$7 = Effect.acquireRelease(makeWithOptions().pipe(Effect.tap((registry) => Effect.sync(() => {
49512
+ const make$8 = Effect.acquireRelease(makeWithOptions().pipe(Effect.tap((registry) => Effect.sync(() => {
49640
49513
  activeMcpSessionRegistry = registry;
49641
49514
  }))), (registry) => Effect.sync(() => {
49642
49515
  if (activeMcpSessionRegistry === registry) activeMcpSessionRegistry = void 0;
49643
49516
  }));
49644
- const layer$2 = Layer.effect(McpSessionRegistry, make$7);
49517
+ const layer$3 = Layer.effect(McpSessionRegistry, make$8);
49645
49518
  const issueActiveMcpCredential = (request) => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeThread(request.threadId).pipe(Effect.andThen(activeMcpSessionRegistry.issue(request))) : Effect.sync(() => void 0);
49646
49519
  /**
49647
49520
  * Refreshes the liveness of a thread's MCP credential. Called on every provider
@@ -73609,7 +73482,7 @@ const makeTerminationError$1 = (handle) => Effect.match(handle.exitCode, {
73609
73482
  //#endregion
73610
73483
  //#region ../../packages/effect-codex-app-server/src/client.ts
73611
73484
  var CodexAppServerClient = class extends Context.Service()("effect-codex-app-server/client/CodexAppServerClient") {};
73612
- const make$6 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
73485
+ const make$7 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
73613
73486
  const requestHandlers = /* @__PURE__ */ new Map();
73614
73487
  const notificationHandlers = /* @__PURE__ */ new Map();
73615
73488
  let unknownRequestHandler;
@@ -73676,7 +73549,7 @@ const make$6 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(fu
73676
73549
  const layerChildProcess$1 = (handle, options = {}) => Layer.effect(CodexAppServerClient, makeChildProcessClient(handle, options));
73677
73550
  const makeChildProcessClient = Effect.fn("effect-codex-app-server/CodexAppServerClient.makeChildProcessClient")(function* (handle, options) {
73678
73551
  yield* Stream.runDrain(handle.stderr).pipe(Effect.ignore, Effect.forkScoped);
73679
- return yield* make$6(makeChildStdio$1(handle), options, makeTerminationError$1(handle));
73552
+ return yield* make$7(makeChildStdio$1(handle), options, makeTerminationError$1(handle));
73680
73553
  });
73681
73554
  //#endregion
73682
73555
  //#region src/provider/Layers/CodexProvider.ts
@@ -79978,7 +79851,7 @@ const makeTerminationError = (handle) => Effect.match(handle.exitCode, {
79978
79851
  //#endregion
79979
79852
  //#region ../../packages/effect-acp/src/client.ts
79980
79853
  var AcpClient = class extends Context.Service()("effect-acp/client/AcpClient") {};
79981
- const make$5 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options = {}, terminationError) {
79854
+ const make$6 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options = {}, terminationError) {
79982
79855
  const coreHandlers = {};
79983
79856
  const notificationHandlers = {
79984
79857
  sessionUpdate: {
@@ -80136,11 +80009,11 @@ const make$5 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options
80136
80009
  const layerChildProcess = (handle, options = {}) => {
80137
80010
  const stdio = makeChildStdio(handle);
80138
80011
  const terminationError = makeTerminationError(handle);
80139
- return Layer.effect(AcpClient, make$5(stdio, options, terminationError));
80012
+ return Layer.effect(AcpClient, make$6(stdio, options, terminationError));
80140
80013
  };
80141
80014
  //#endregion
80142
80015
  //#region ../../packages/shared/src/toolActivity.ts
80143
- function asRecord(value) {
80016
+ function asRecord$1(value) {
80144
80017
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
80145
80018
  }
80146
80019
  function asTrimmedString(value) {
@@ -80170,10 +80043,10 @@ function extractCommandFromTitle$1(title) {
80170
80043
  return /`([^`]+)`/u.exec(title)?.[1]?.trim() || void 0;
80171
80044
  }
80172
80045
  function extractToolCommand(data, title) {
80173
- const item = asRecord(data?.item);
80174
- const itemInput = asRecord(item?.input);
80175
- const itemResult = asRecord(item?.result);
80176
- const rawInput = asRecord(data?.rawInput);
80046
+ const item = asRecord$1(data?.item);
80047
+ const itemInput = asRecord$1(item?.input);
80048
+ const itemResult = asRecord$1(item?.result);
80049
+ const rawInput = asRecord$1(data?.rawInput);
80177
80050
  const direct = [
80178
80051
  normalizeCommandValue$1(item?.command),
80179
80052
  normalizeCommandValue$1(itemInput?.command),
@@ -80201,7 +80074,7 @@ function collectPaths(value, paths, seen, depth) {
80201
80074
  }
80202
80075
  return;
80203
80076
  }
80204
- const record = asRecord(value);
80077
+ const record = asRecord$1(value);
80205
80078
  if (!record) return;
80206
80079
  for (const key of [
80207
80080
  "path",
@@ -80260,7 +80133,7 @@ function deriveToolActivityPresentation(input) {
80260
80133
  const title = asTrimmedString(input.title);
80261
80134
  const detail = stripTrailingExitCode(asTrimmedString(input.detail));
80262
80135
  const fallbackSummary = asTrimmedString(input.fallbackSummary) ?? "Tool";
80263
- const data = asRecord(input.data);
80136
+ const data = asRecord$1(input.data);
80264
80137
  const command = extractToolCommand(data, title);
80265
80138
  const primaryPath = extractPrimaryPath(data);
80266
80139
  const action = classifyToolAction({
@@ -80284,7 +80157,7 @@ function deriveToolActivityPresentation(input) {
80284
80157
  ...primaryPath ? { detail: primaryPath } : {}
80285
80158
  };
80286
80159
  if (action === "search") {
80287
- const query = asTrimmedString(asRecord(data?.rawInput)?.query) ?? asTrimmedString(asRecord(data?.rawInput)?.pattern) ?? asTrimmedString(asRecord(data?.rawInput)?.searchTerm);
80160
+ const query = asTrimmedString(asRecord$1(data?.rawInput)?.query) ?? asTrimmedString(asRecord$1(data?.rawInput)?.pattern) ?? asTrimmedString(asRecord$1(data?.rawInput)?.searchTerm);
80288
80161
  return {
80289
80162
  summary: "Searched files",
80290
80163
  ...query ? { detail: query } : {}
@@ -80596,7 +80469,7 @@ function formatConfigOptionValue(value) {
80596
80469
  const defaultSessionLoadTimeout = Duration.seconds(90);
80597
80470
  const defaultSessionLoadReplayIdleGap = Duration.seconds(2);
80598
80471
  var AcpSessionRuntime = class extends Context.Service()("@p4code/cli/provider/acp/AcpSessionRuntime") {};
80599
- const make$4 = (options) => Effect.gen(function* () {
80472
+ const make$5 = (options) => Effect.gen(function* () {
80600
80473
  const crypto = yield* Crypto.Crypto;
80601
80474
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
80602
80475
  const runtimeScope = yield* Scope.Scope;
@@ -80905,7 +80778,7 @@ const make$4 = (options) => Effect.gen(function* () {
80905
80778
  notify: acp.raw.notify
80906
80779
  };
80907
80780
  });
80908
- const layer$1 = (options) => Layer.effect(AcpSessionRuntime, make$4(options));
80781
+ const layer$2 = (options) => Layer.effect(AcpSessionRuntime, make$5(options));
80909
80782
  function sessionConfigOptionsFromSetup(response) {
80910
80783
  return response?.configOptions ?? [];
80911
80784
  }
@@ -81272,7 +81145,7 @@ function buildCursorDiscoveredModelsFromAvailableModelsResponse(response) {
81272
81145
  }
81273
81146
  const makeCursorAcpProbeRuntime = (cursorSettings, environment) => Effect.gen(function* () {
81274
81147
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
81275
- const acpContext = yield* Layer.build(layer$1({
81148
+ const acpContext = yield* Layer.build(layer$2({
81276
81149
  spawn: {
81277
81150
  command: cursorSettings.binaryPath,
81278
81151
  args: [...cursorSettings.apiEndpoint ? ["-e", cursorSettings.apiEndpoint] : [], "acp"],
@@ -81722,7 +81595,7 @@ function buildCursorAcpSpawnInput(cursorSettings, cwd, environment) {
81722
81595
  };
81723
81596
  }
81724
81597
  const makeCursorAcpRuntime = (input) => Effect.gen(function* () {
81725
- const acpContext = yield* Layer.build(layer$1({
81598
+ const acpContext = yield* Layer.build(layer$2({
81726
81599
  ...input,
81727
81600
  spawn: buildCursorAcpSpawnInput(input.cursorSettings, input.cwd, input.environment),
81728
81601
  authMethodId: "cursor_login",
@@ -83176,7 +83049,7 @@ function resolveGrokAuthMethodId(environment) {
83176
83049
  return environment?.[GROK_API_KEY_ENV]?.trim() ? GROK_AUTH_METHOD_API_KEY : GROK_AUTH_METHOD_CACHED_TOKEN;
83177
83050
  }
83178
83051
  const makeGrokAcpRuntime = (input) => Effect.gen(function* () {
83179
- const acpContext = yield* Layer.build(layer$1({
83052
+ const acpContext = yield* Layer.build(layer$2({
83180
83053
  ...input,
83181
83054
  spawn: buildGrokAcpSpawnInput(input.grokSettings, input.cwd, input.environment),
83182
83055
  authMethodId: resolveGrokAuthMethodId(input.environment)
@@ -84621,7 +84494,7 @@ function mapMuseExecRecord(input) {
84621
84494
  const payload = record.payload;
84622
84495
  switch (record.payloadType) {
84623
84496
  case "run.model.configured": {
84624
- const modelId = stringField(payload, "model_id");
84497
+ const modelId = stringField$1(payload, "model_id");
84625
84498
  if (modelId) state.modelId = modelId;
84626
84499
  return [(stamp) => ({
84627
84500
  type: "session.configured",
@@ -84639,7 +84512,7 @@ function mapMuseExecRecord(input) {
84639
84512
  raw: rawFrom(record)
84640
84513
  })];
84641
84514
  case "run.output.delta": {
84642
- const text = stringField(payload, "text");
84515
+ const text = stringField$1(payload, "text");
84643
84516
  if (text === void 0 || text.length === 0) return [];
84644
84517
  return appendAssistantText({
84645
84518
  text,
@@ -84650,8 +84523,8 @@ function mapMuseExecRecord(input) {
84650
84523
  }
84651
84524
  case "task.lifecycle.proposed": {
84652
84525
  const event = eventField(payload);
84653
- const taskId = stringField(event, "task_id");
84654
- const toolName = toolNameFromTaskKind(stringField(event, "task_kind"));
84526
+ const taskId = stringField$1(event, "task_id");
84527
+ const toolName = toolNameFromTaskKind(stringField$1(event, "task_kind"));
84655
84528
  if (!taskId || !toolName) return [];
84656
84529
  state.toolNameByTaskId.set(taskId, toolName);
84657
84530
  return [(stamp) => ({
@@ -84669,15 +84542,15 @@ function mapMuseExecRecord(input) {
84669
84542
  }
84670
84543
  case "task.lifecycle.side_effect_intent": {
84671
84544
  const event = eventField(payload);
84672
- const taskId = stringField(event, "task_id");
84673
- const callId = toolCallIdFromIdempotencyKey(stringField(event, "idempotency_key"));
84545
+ const taskId = stringField$1(event, "task_id");
84546
+ const callId = toolCallIdFromIdempotencyKey(stringField$1(event, "idempotency_key"));
84674
84547
  if (taskId && callId) state.taskIdByCallId.set(callId, taskId);
84675
84548
  return [];
84676
84549
  }
84677
84550
  case "task.lifecycle.output": {
84678
84551
  const event = eventField(payload);
84679
- const taskId = stringField(event, "task_id");
84680
- const chunk = stringField(event, "chunk");
84552
+ const taskId = stringField$1(event, "task_id");
84553
+ const chunk = stringField$1(event, "chunk");
84681
84554
  if (!taskId || !chunk) return [];
84682
84555
  const toolName = state.toolNameByTaskId.get(taskId);
84683
84556
  if (!toolName) return [];
@@ -84695,13 +84568,13 @@ function mapMuseExecRecord(input) {
84695
84568
  })];
84696
84569
  }
84697
84570
  case "tool.result": {
84698
- const callId = stringField(payload, "call_id");
84571
+ const callId = stringField$1(payload, "call_id");
84699
84572
  const taskId = callId ? state.taskIdByCallId.get(callId) : void 0;
84700
84573
  if (!taskId) return [];
84701
84574
  const toolName = state.toolNameByTaskId.get(taskId);
84702
84575
  state.settledToolTaskIds.add(taskId);
84703
- const failed = stringField(recordField(payload, "correlation_facts"), "outcome") === "error";
84704
- const detail = truncate(stringField(payload, "text"), MAX_TOOL_DETAIL_CHARS);
84576
+ const failed = stringField$1(recordField(payload, "correlation_facts"), "outcome") === "error";
84577
+ const detail = truncate(stringField$1(payload, "text"), MAX_TOOL_DETAIL_CHARS);
84705
84578
  const editFacts = recordField(payload, "edit_facts");
84706
84579
  return [(stamp) => ({
84707
84580
  type: "item.completed",
@@ -84720,12 +84593,12 @@ function mapMuseExecRecord(input) {
84720
84593
  }
84721
84594
  case "task.lifecycle.failed": {
84722
84595
  const event = eventField(payload);
84723
- const taskId = stringField(event, "task_id");
84596
+ const taskId = stringField$1(event, "task_id");
84724
84597
  if (!taskId) return [];
84725
84598
  const toolName = state.toolNameByTaskId.get(taskId);
84726
84599
  if (!toolName || state.settledToolTaskIds.has(taskId)) return [];
84727
84600
  state.settledToolTaskIds.add(taskId);
84728
- const detail = truncate(stringField(event, "reason"), MAX_TOOL_DETAIL_CHARS);
84601
+ const detail = truncate(stringField$1(event, "reason"), MAX_TOOL_DETAIL_CHARS);
84729
84602
  return [(stamp) => ({
84730
84603
  type: "item.completed",
84731
84604
  ...stamp,
@@ -84757,10 +84630,10 @@ function mapMuseExecRecord(input) {
84757
84630
  */
84758
84631
  function mapTerminalRecord(input) {
84759
84632
  const { record, state, context } = input;
84760
- const terminalState = turnStateFromTerminal(stringField(record.payload, "terminal") ?? record.payloadType.slice(13));
84633
+ const terminalState = turnStateFromTerminal(stringField$1(record.payload, "terminal") ?? record.payloadType.slice(13));
84761
84634
  state.terminal = terminalState;
84762
84635
  const drafts = [];
84763
- const remainder = assistantTextRemainder(state.assistantText, stringField(record.payload, "text"));
84636
+ const remainder = assistantTextRemainder(state.assistantText, stringField$1(record.payload, "text"));
84764
84637
  if (remainder) drafts.push(...appendAssistantText({
84765
84638
  text: remainder,
84766
84639
  state,
@@ -84777,7 +84650,7 @@ function mapTerminalRecord(input) {
84777
84650
  status: "completed"
84778
84651
  }
84779
84652
  }));
84780
- const reason = stringField(record.payload, "reason");
84653
+ const reason = stringField$1(record.payload, "reason");
84781
84654
  drafts.push((stamp) => ({
84782
84655
  type: "turn.completed",
84783
84656
  ...stamp,
@@ -84893,7 +84766,7 @@ function rawFrom(record) {
84893
84766
  function isRecord$1(value) {
84894
84767
  return typeof value === "object" && value !== null && !Array.isArray(value);
84895
84768
  }
84896
- function stringField(source, key) {
84769
+ function stringField$1(source, key) {
84897
84770
  const value = source?.[key];
84898
84771
  return typeof value === "string" && value.length > 0 ? value : void 0;
84899
84772
  }
@@ -88286,6 +88159,106 @@ const PreviewStandardToolkitHandlersLive = PreviewStandardToolkit.toLayer(standa
88286
88159
  const PreviewSnapshotToolkitHandlersLive = PreviewSnapshotToolkit.toLayer({ preview_snapshot });
88287
88160
  PreviewToolkit.toLayer(handlers$3);
88288
88161
  //#endregion
88162
+ //#region src/mcp/TicketResolver.ts
88163
+ /**
88164
+ * The registered server name a Linear ticket is resolved through.
88165
+ *
88166
+ * Matched by name rather than by URL: the name is what the user typed in
88167
+ * Settings and what every other surface calls it, and a workspace may reach
88168
+ * Linear through a proxy URL that no pattern here would recognize.
88169
+ */
88170
+ const LINEAR_SERVER_NAME = "linear";
88171
+ /** Linear's own tool for reading one issue. */
88172
+ const LINEAR_GET_ISSUE_TOOL = "get_issue";
88173
+ var TicketResolver = class extends Context.Service()("@p4code/cli/mcp/TicketResolver") {};
88174
+ const stringField = (record, key) => {
88175
+ const value = record[key];
88176
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
88177
+ };
88178
+ const asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
88179
+ /**
88180
+ * Find the issue inside whatever the tool returned.
88181
+ *
88182
+ * MCP leaves the shape of a tool result to the tool, so this accepts the three
88183
+ * arrangements in the wild - the structured payload itself, that payload with
88184
+ * the issue nested one level down, or a text block that happens to be JSON -
88185
+ * rather than assuming the one Linear happens to send today.
88186
+ */
88187
+ const readIssue = (result) => {
88188
+ const structured = asRecord(result.structuredContent);
88189
+ if (structured !== void 0) {
88190
+ const nested = asRecord(structured["issue"]);
88191
+ if (nested !== void 0) return nested;
88192
+ if (stringField(structured, "url") !== void 0) return structured;
88193
+ }
88194
+ try {
88195
+ const parsed = JSON.parse(result.text);
88196
+ const record = asRecord(parsed);
88197
+ if (record === void 0) return structured;
88198
+ return asRecord(record["issue"]) ?? record;
88199
+ } catch {
88200
+ return structured;
88201
+ }
88202
+ };
88203
+ const make$4 = Effect.gen(function* () {
88204
+ const registry = yield* McpRegistry;
88205
+ const oauth = yield* McpOAuth;
88206
+ const http = yield* HttpClient$1.HttpClient;
88207
+ return { resolve: Effect.fn("TicketResolver.resolve")(function* (reference) {
88208
+ const identifier = parseTicketReference(reference);
88209
+ if (identifier === null) return yield* new TicketResolveError({
88210
+ reason: "not_found",
88211
+ detail: `"${reference}" does not look like a ticket reference.`
88212
+ });
88213
+ const server = (yield* registry.list).find((candidate) => candidate.registration.name.toLowerCase() === LINEAR_SERVER_NAME && candidate.registration.enabled);
88214
+ if (server === void 0 || server.registration.transport === "stdio") return yield* new TicketResolveError({
88215
+ reason: "not_configured",
88216
+ detail: "No Linear MCP server is registered on this machine. Add it in Settings to link tickets."
88217
+ });
88218
+ const registration = server.registration;
88219
+ const token = yield* oauth.accessTokenFor(registration);
88220
+ const headers = {
88221
+ ...registration.headers,
88222
+ ...Option.isSome(token) ? { authorization: `Bearer ${token.value}` } : {}
88223
+ };
88224
+ if (Option.isNone(token) && Object.keys(registration.headers ?? {}).length === 0) return yield* new TicketResolveError({
88225
+ reason: "not_authorized",
88226
+ detail: "Linear is registered but not signed in on this machine. Sign in from Settings."
88227
+ });
88228
+ const result = yield* callMcpTool({
88229
+ url: registration.url,
88230
+ headers,
88231
+ toolName: LINEAR_GET_ISSUE_TOOL,
88232
+ arguments: { id: identifier }
88233
+ }).pipe(Effect.provideService(HttpClient$1.HttpClient, http), Effect.mapError((error) => error.status === 401 || error.status === 403 ? new TicketResolveError({
88234
+ reason: "not_authorized",
88235
+ detail: "Linear rejected p4code's sign-in. Sign in again from Settings."
88236
+ }) : new TicketResolveError({
88237
+ reason: "unavailable",
88238
+ detail: error.detail
88239
+ })));
88240
+ const issue = readIssue(result);
88241
+ const url = issue === void 0 ? void 0 : stringField(issue, "url");
88242
+ const title = issue === void 0 ? void 0 : stringField(issue, "title");
88243
+ if (issue === void 0 || url === void 0 || title === void 0) return yield* new TicketResolveError({
88244
+ reason: "not_found",
88245
+ detail: `Linear returned nothing usable for ${identifier}.`
88246
+ });
88247
+ const externalRef = {
88248
+ source: "linear",
88249
+ identifier: stringField(issue, "identifier") ?? identifier,
88250
+ url
88251
+ };
88252
+ const description = stringField(issue, "description");
88253
+ return {
88254
+ externalRef,
88255
+ title,
88256
+ ...description === void 0 ? {} : { description }
88257
+ };
88258
+ }) };
88259
+ });
88260
+ const layer$1 = Layer.effect(TicketResolver, make$4);
88261
+ //#endregion
88289
88262
  //#region src/mcp/toolkits/tasks/tools.ts
88290
88263
  const dependencies = [McpInvocationContext, TaskRepository];
88291
88264
  /**
@@ -88374,12 +88347,13 @@ const TaskProposeTool = Tool.make("task_propose", {
88374
88347
  * to paste the description back in - which is the question they already
88375
88348
  * answered by quoting the id.
88376
88349
  *
88377
- * On the task toolkit rather than a toolkit of its own because it is board
88378
- * work: a resolved ticket's next step is `task_create` with the `externalRef`
88379
- * this returns, and the two share the one capability a session is granted.
88350
+ * On the task toolkit rather than a toolkit of its own because it is the same
88351
+ * question a board answers - what is this work - and the two share the one
88352
+ * capability a session is granted. It reads and writes nothing: a ticket stays
88353
+ * in its tracker, and p4code files no copy of it.
88380
88354
  */
88381
88355
  const TicketResolveTool = Tool.make("ticket_resolve", {
88382
- description: "Read a tracker ticket by id or URL (e.g. MOBILE-12241, or a linear.app link), returning its identifier, canonical URL, title and description. Use this whenever the user names a ticket rather than asking them to paste it. Pass the returned externalRef straight to task_create to mirror the ticket onto the board. Fails when no tracker is registered on this machine, which is a thing only the user can fix.",
88356
+ description: "Read a tracker ticket by id or URL (e.g. MOBILE-12241, or a linear.app link), returning its identifier, canonical URL, title and description. Use this whenever the user names a ticket rather than asking them to paste it. Reading is all it does - the ticket stays in its tracker and no task is filed for it. Fails when no tracker is registered on this machine, which is a thing only the user can fix.",
88383
88357
  parameters: TicketResolveInput,
88384
88358
  success: TicketResolveResult,
88385
88359
  failure: Schema$1.Union([TaskToolUnavailableError, TicketResolveError]),
@@ -92579,28 +92553,28 @@ const PlatformServicesLive = Layer.unwrap(Effect.gen(function* () {
92579
92553
  }
92580
92554
  }));
92581
92555
  const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReactorLive), Layer.provideMerge(ProviderRuntimeIngestionLive), Layer.provideMerge(ProviderCommandReactorLive), Layer.provideMerge(CheckpointReactorLive), Layer.provideMerge(ThreadDeletionReactorLive), Layer.provideMerge(RuntimeReceiptBusLive));
92582
- const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$3));
92556
+ const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$4));
92583
92557
  const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
92584
92558
  const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));
92585
92559
  const VcsDriverRegistryLayerLive = layer$37.pipe(Layer.provide(layer$38));
92586
- const SourceControlProviderRegistryLayerLive = layer$14.pipe(Layer.provide(Layer.mergeAll(layer$22, layer$20, layer$18, layer$16)), Layer.provideMerge(layer$39), Layer.provideMerge(VcsDriverRegistryLayerLive));
92587
- const GitManagerLayerLive = layer$13.pipe(Layer.provideMerge(layer$23), Layer.provideMerge(layer$39), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$33));
92560
+ const SourceControlProviderRegistryLayerLive = layer$15.pipe(Layer.provide(Layer.mergeAll(layer$23, layer$21, layer$19, layer$17)), Layer.provideMerge(layer$39), Layer.provideMerge(VcsDriverRegistryLayerLive));
92561
+ const GitManagerLayerLive = layer$14.pipe(Layer.provideMerge(layer$24), Layer.provideMerge(layer$39), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$33));
92588
92562
  const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$39));
92589
- const GitWorkflowLayerLive = layer$12.pipe(Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive));
92590
- const SourceControlRepositoryServiceLayerLive = layer$4.pipe(Layer.provideMerge(layer$39), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
92591
- const ReviewLayerLive = layer$9.pipe(Layer.provideMerge(layer$39), Layer.provideMerge(VcsDriverRegistryLayerLive));
92592
- const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$38), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(layer$10.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge(layer$11.pipe(Layer.provide(GitWorkflowLayerLive))));
92563
+ const GitWorkflowLayerLive = layer$13.pipe(Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive));
92564
+ const SourceControlRepositoryServiceLayerLive = layer$5.pipe(Layer.provideMerge(layer$39), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
92565
+ const ReviewLayerLive = layer$10.pipe(Layer.provideMerge(layer$39), Layer.provideMerge(VcsDriverRegistryLayerLive));
92566
+ const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$38), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(layer$11.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge(layer$12.pipe(Layer.provide(GitWorkflowLayerLive))));
92593
92567
  const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$35), Layer.provideMerge(layer$36.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
92594
- const PortScannerLayerLive = layer$30.pipe(Layer.provide(layer$54));
92595
- const TerminalLayerLive = layer$29.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
92596
- const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$27), Layer.provideMerge(PortScannerLayerLive));
92597
- const WorkspaceEntriesLayerLive = layer$25.pipe(Layer.provide(layer$44));
92598
- const WorkspaceFileSystemLayerLive = layer$24.pipe(Layer.provide(layer$44), Layer.provide(WorkspaceEntriesLayerLive));
92568
+ const PortScannerLayerLive = layer$31.pipe(Layer.provide(layer$54));
92569
+ const TerminalLayerLive = layer$30.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
92570
+ const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$28), Layer.provideMerge(PortScannerLayerLive));
92571
+ const WorkspaceEntriesLayerLive = layer$26.pipe(Layer.provide(layer$44));
92572
+ const WorkspaceFileSystemLayerLive = layer$25.pipe(Layer.provide(layer$44), Layer.provide(WorkspaceEntriesLayerLive));
92599
92573
  const WorkspaceLayerLive = Layer.mergeAll(layer$44, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
92600
92574
  const ProjectFaviconResolverLayerLive = layer$42.pipe(Layer.provide(layer$44), Layer.provide(layer$43));
92601
92575
  const AuthLayerLive = layer$64.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$68));
92602
92576
  const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe(Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive));
92603
- const RuntimeDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(CheckpointingLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive)), Layer.provideMerge(PersistenceLayerLive), Layer.provideMerge(layer$52), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$61.pipe(Layer.provide(layer$68))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$53), Layer.provideMerge(layer$46), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(Layer.mergeAll(layer$31, LinearMcpClientLive).pipe(Layer.provideMerge(Layer.mergeAll(layer$58, layer$32).pipe(Layer.provideMerge(layer$59), Layer.provideMerge(layer$60))))), Layer.provideMerge(layer$68)).pipe(Layer.provideMerge(layer$8), Layer.provideMerge(layer$7), Layer.provideMerge(layer$6), Layer.provideMerge(layer$49), Layer.provideMerge(layer$51), Layer.provideMerge(layer$50), Layer.provide(layer$72));
92577
+ const RuntimeDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(CheckpointingLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive)), Layer.provideMerge(PersistenceLayerLive), Layer.provideMerge(layer$52), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$61.pipe(Layer.provide(layer$68))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$53), Layer.provideMerge(layer$46), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(Layer.mergeAll(layer$1, LinearMcpClientLive).pipe(Layer.provideMerge(Layer.mergeAll(layer$58, layer$32).pipe(Layer.provideMerge(layer$59), Layer.provideMerge(layer$60))))), Layer.provideMerge(layer$68)).pipe(Layer.provideMerge(layer$9), Layer.provideMerge(layer$8), Layer.provideMerge(layer$7), Layer.provideMerge(layer$49), Layer.provideMerge(layer$51), Layer.provideMerge(layer$50), Layer.provide(layer$72));
92604
92578
  /**
92605
92579
  * Hub asset sync.
92606
92580
  *
@@ -92610,7 +92584,7 @@ const RuntimeDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(Checkpo
92610
92584
  */
92611
92585
  const AssetSyncLive = layer$55.pipe(Layer.provideMerge(layer$56), Layer.provideMerge(layer$57));
92612
92586
  const RuntimeServicesLive = layer$45.pipe(Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
92613
- const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, mcpOAuthCallbackRouteLayer, staticAndDevRouteLayer, websocketRpcRouteLayer), layer.pipe(Layer.provide(layer$2))).pipe(Layer.provide(RoutedTaskRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(ProjectionProjectRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(layer$43), Layer.provide(layer$28), Layer.provide(layer$47), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
92587
+ const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, mcpOAuthCallbackRouteLayer, staticAndDevRouteLayer, websocketRpcRouteLayer), layer.pipe(Layer.provide(layer$3))).pipe(Layer.provide(RoutedTaskRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(ProjectionProjectRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(layer$43), Layer.provide(layer$29), Layer.provide(layer$47), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
92614
92588
  const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
92615
92589
  const config = yield* ServerConfig$1;
92616
92590
  yield* fixPath();