@p4code/cli 0.5.17 → 0.5.19

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
@@ -153,7 +153,7 @@ const closeServer = (server) => {
153
153
  * NetService - Service tag for startup networking helpers.
154
154
  */
155
155
  var NetService = class extends Context.Service()("@p4code/shared/Net/NetService") {};
156
- const make$120 = () => {
156
+ const make$122 = () => {
157
157
  /**
158
158
  * Returns true when a TCP server can bind to {host, port}.
159
159
  * `EADDRNOTAVAIL` is treated as available so IPv6-absent hosts don't fail
@@ -262,10 +262,10 @@ const make$120 = () => {
262
262
  })
263
263
  };
264
264
  };
265
- const layer$122 = Layer.sync(NetService, make$120);
265
+ const layer$122 = Layer.sync(NetService, make$122);
266
266
  //#endregion
267
267
  //#region package.json
268
- var version$1 = "0.5.17";
268
+ var version$1 = "0.5.19";
269
269
  //#endregion
270
270
  //#region src/config.ts
271
271
  /**
@@ -286,8 +286,8 @@ var ServerConfig$1 = class extends Context.Service()("@p4code/cli/config/ServerC
286
286
  /** @deprecated Import and use `layerTest` from this module. */
287
287
  static layerTest = (cwd, baseDirOrPrefix) => layerTest$4(cwd, baseDirOrPrefix);
288
288
  };
289
- const make$119 = (config) => ServerConfig$1.of(config);
290
- const layer$121 = (config) => Layer.succeed(ServerConfig$1, make$119(config));
289
+ const make$121 = (config) => ServerConfig$1.of(config);
290
+ const layer$121 = (config) => Layer.succeed(ServerConfig$1, make$121(config));
291
291
  const deriveServerPaths = Effect.fn(function* (baseDir, devUrl, options = {}) {
292
292
  const { join } = yield* Path$1.Path;
293
293
  const stateDir = join(baseDir, devUrl !== void 0 && !options.baseDirIsExplicit ? "dev" : "userdata");
@@ -3521,6 +3521,21 @@ const OrchestrationThreadActivity = Schema$1.Struct({
3521
3521
  sequence: Schema$1.optional(NonNegativeInt),
3522
3522
  createdAt: IsoDateTime
3523
3523
  });
3524
+ /**
3525
+ * The activity a turn gets when Jev (TypeSafe System One) answered for it.
3526
+ *
3527
+ * One per consultation, never merged: a turn that took a skill hint and a
3528
+ * workspace choice from Jev carries two, and each names what it decided.
3529
+ * Silence, a timeout or a declined answer append nothing, so the row's
3530
+ * presence is the whole claim.
3531
+ */
3532
+ const JEV_CONSULTED_ACTIVITY_KIND = "jev.consulted";
3533
+ const JevConsultedFeature = Schema$1.Literals(["capability-hints", "auto-workspace"]);
3534
+ Schema$1.Struct({
3535
+ feature: JevConsultedFeature,
3536
+ /** What Jev decided, in one short clause: "Suggested: design, publish". */
3537
+ summary: TrimmedNonEmptyString
3538
+ });
3524
3539
  const OrchestrationLatestTurnState = Schema$1.Literals([
3525
3540
  "running",
3526
3541
  "interrupted",
@@ -10400,6 +10415,11 @@ const ClientSettingsSchema = Schema$1.Struct({
10400
10415
  })).pipe(Schema$1.withDecodingDefault(Effect.succeed(13)))
10401
10416
  });
10402
10417
  const DEFAULT_CLIENT_SETTINGS = Schema$1.decodeSync(ClientSettingsSchema)({});
10418
+ const DEFAULT_JEV_PREFETCH_TIMEOUT_MS = 2e3;
10419
+ const JevPrefetchTimeoutMs = Schema$1.Int.check(Schema$1.isBetween({
10420
+ minimum: 100,
10421
+ maximum: 3e4
10422
+ }));
10403
10423
  const ThreadEnvMode = Schema$1.Literals([
10404
10424
  "auto",
10405
10425
  "local",
@@ -10766,6 +10786,32 @@ const ServerSettings = Schema$1.Struct({
10766
10786
  /** Supervisor wake pre-filter; disabled by default. */
10767
10787
  fusionReviewTriage: FusionReviewTriageSettings.pipe(Schema$1.withDecodingDefault(Effect.succeed(Schema$1.decodeUnknownSync(FusionReviewTriageSettings)({})))),
10768
10788
  /**
10789
+ * Whether a turn asks Jev which of this environment's capabilities to name
10790
+ * to the model before its first request.
10791
+ *
10792
+ * One environment-wide switch rather than a per-thread control: which skills
10793
+ * and commands exist is a fact about the machine, not about a conversation,
10794
+ * and nobody wants to answer the same question on every new thread. The
10795
+ * ranking is advisory - it adds a few names to the turn and changes nothing
10796
+ * else - so the cost of leaving it on is a short request, which is why it is
10797
+ * on by default.
10798
+ *
10799
+ * Off removes the request entirely. So does a missing Jev key, a timeout or
10800
+ * an unreadable answer: every one of those is the same turn the agent would
10801
+ * have had before this setting existed.
10802
+ */
10803
+ enableJevPrefetch: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
10804
+ /** Maximum per-turn wait for capability hints; failures continue without hints. */
10805
+ jevPrefetchTimeoutMs: JevPrefetchTimeoutMs.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_JEV_PREFETCH_TIMEOUT_MS))),
10806
+ /**
10807
+ * Whether Auto checkout mode asks Jev to choose between the current
10808
+ * checkout and a fresh worktree before falling back to the text generation
10809
+ * model. Same shape as `enableJevPrefetch`: environment-wide, on by
10810
+ * default, and every failure path is the decision the turn would have
10811
+ * made without it.
10812
+ */
10813
+ enableJevAutoWorkspace: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
10814
+ /**
10769
10815
  * Whether the board offers the scoping agent: the Scope action on a task and
10770
10816
  * the panel that drafts a new one by interview.
10771
10817
  *
@@ -10995,6 +11041,9 @@ const ServerSettingsPatch = Schema$1.Struct({
10995
11041
  fusionSummarizerModel: Schema$1.optionalKey(Schema$1.NullOr(ModelSelection)),
10996
11042
  fusionPromptOverrides: Schema$1.optionalKey(FusionPromptOverrides),
10997
11043
  fusionReviewTriage: Schema$1.optionalKey(FusionReviewTriageSettings),
11044
+ enableJevPrefetch: Schema$1.optionalKey(Schema$1.Boolean),
11045
+ jevPrefetchTimeoutMs: Schema$1.optionalKey(JevPrefetchTimeoutMs),
11046
+ enableJevAutoWorkspace: Schema$1.optionalKey(Schema$1.Boolean),
10998
11047
  enableScopingAgent: Schema$1.optionalKey(Schema$1.Boolean),
10999
11048
  enablePlanPhase: Schema$1.optionalKey(Schema$1.Boolean),
11000
11049
  writeGeneratedSkillsToRepo: Schema$1.optionalKey(Schema$1.Boolean),
@@ -12575,7 +12624,7 @@ const ThreadSpawnInput = Schema$1.Struct({
12575
12624
  interactionMode: Schema$1.optional(ProviderInteractionMode),
12576
12625
  compressMode: Schema$1.optional(CompressMode),
12577
12626
  unpromptedSubagents: Schema$1.optional(Schema$1.Boolean),
12578
- fusion: Schema$1.optional(Schema$1.Boolean.annotate({ description: "Create two new threads as a separate Fusion pair, then start the builder with prompt. Leaves the caller and its existing pair unchanged. Cannot be combined with fusionWatcher." })),
12627
+ fusion: Schema$1.optional(Schema$1.Boolean.annotate({ description: "Create two new threads as a separate Fusion pair, then start the supervisor with prompt. The builder stays empty until advised. Leaves the caller and its existing pair unchanged. Cannot be combined with fusionWatcher." })),
12579
12628
  fusionWatcher: Schema$1.optional(Schema$1.Boolean.annotate({ description: "Set true only when creating the watcher to pair with the current thread. Defaults to the saved Fusion supervisor model. No special user command syntax is required." }))
12580
12629
  });
12581
12630
  const ThreadSpawnResult = Schema$1.Struct({
@@ -12587,16 +12636,16 @@ const ThreadSpawnResult = Schema$1.Struct({
12587
12636
  watcherThreadId: Schema$1.optional(ThreadId)
12588
12637
  });
12589
12638
  const ThreadPairCreateInput = Schema$1.Struct({
12590
- watcherThreadId: ThreadId.annotate({ description: "The supervisor thread to pair with this session's own builder thread. It must have been created by this session through thread_spawn." }),
12639
+ watcherThreadId: Schema$1.optional(ThreadId.annotate({ description: "Legacy pairing: use an existing spawned supervisor and keep this chat as builder. Omit to keep this chat and its history as supervisor and create a new empty builder, idle until advised." })),
12591
12640
  gateTimeoutMs: Schema$1.optional(NonNegativeInt.annotate({ description: "How long a gate waits on the supervisor before failing open, in milliseconds. Defaults to 120000." }))
12592
12641
  });
12593
12642
  const ThreadPairCreateResult = Schema$1.Struct({
12594
12643
  pairId: ThreadPairId,
12595
12644
  implementerThreadId: ThreadId,
12596
12645
  watcherThreadId: ThreadId,
12597
- continuationMessageId: MessageId
12646
+ continuationMessageId: Schema$1.optional(MessageId)
12598
12647
  });
12599
- const ThreadPairDetachInput = Schema$1.Struct({ pairId: ThreadPairId.annotate({ description: "The active Fusion pair to detach. This session must be its implementer and must have created its watcher with thread_spawn." }) });
12648
+ const ThreadPairDetachInput = Schema$1.Struct({ pairId: ThreadPairId.annotate({ description: "The active Fusion pair to detach. This session must belong to the pair and must have created its other thread." }) });
12600
12649
  const ThreadPairDetachResult = Schema$1.Struct({
12601
12650
  pairId: ThreadPairId,
12602
12651
  implementerThreadId: ThreadId,
@@ -16072,7 +16121,7 @@ function deriveAuthClientMetadata(input) {
16072
16121
  //#endregion
16073
16122
  //#region src/auth/EnvironmentAuthPolicy.ts
16074
16123
  var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
16075
- const make$118 = Effect.gen(function* () {
16124
+ const make$120 = Effect.gen(function* () {
16076
16125
  const config = yield* ServerConfig$1;
16077
16126
  const isRemoteReachable = isRemoteReachableHost(config.host);
16078
16127
  const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
@@ -16090,7 +16139,7 @@ const make$118 = Effect.gen(function* () {
16090
16139
  };
16091
16140
  return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
16092
16141
  });
16093
- const layer$120 = Layer.effect(EnvironmentAuthPolicy, make$118);
16142
+ const layer$120 = Layer.effect(EnvironmentAuthPolicy, make$120);
16094
16143
  //#endregion
16095
16144
  //#region src/persistence/Errors.ts
16096
16145
  function summarizeSchemaIssue(issue) {
@@ -16271,7 +16320,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
16271
16320
  cause
16272
16321
  });
16273
16322
  }
16274
- const make$117 = Effect.gen(function* () {
16323
+ const make$119 = Effect.gen(function* () {
16275
16324
  const sql = yield* SqlClient.SqlClient;
16276
16325
  const createSessionRow = SqlSchema.void({
16277
16326
  Request: CreateAuthSessionInput,
@@ -16405,7 +16454,7 @@ const make$117 = Effect.gen(function* () {
16405
16454
  setLastConnectedAt
16406
16455
  };
16407
16456
  });
16408
- const layer$119 = Layer.effect(AuthSessionRepository, make$117);
16457
+ const layer$119 = Layer.effect(AuthSessionRepository, make$119);
16409
16458
  //#endregion
16410
16459
  //#region src/auth/ServerSecretStore.ts
16411
16460
  const secretStoreErrorContext = {
@@ -16547,11 +16596,11 @@ const makeForDirectory = Effect.fn("ServerSecretStore.makeForDirectory")(functio
16547
16596
  remove
16548
16597
  });
16549
16598
  });
16550
- const make$116 = Effect.gen(function* () {
16599
+ const make$118 = Effect.gen(function* () {
16551
16600
  const config = yield* ServerConfig$1;
16552
16601
  return yield* makeForDirectory(config.secretsDir);
16553
16602
  });
16554
- const layer$118 = Layer.effect(ServerSecretStore, make$116);
16603
+ const layer$118 = Layer.effect(ServerSecretStore, make$118);
16555
16604
  //#endregion
16556
16605
  //#region src/auth/SessionStore.ts
16557
16606
  var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
@@ -16789,7 +16838,7 @@ function toAuthClientSession(input) {
16789
16838
  current: false
16790
16839
  };
16791
16840
  }
16792
- const make$115 = Effect.gen(function* () {
16841
+ const make$117 = Effect.gen(function* () {
16793
16842
  const crypto = yield* Crypto.Crypto;
16794
16843
  const serverConfig = yield* ServerConfig$1;
16795
16844
  const secretStore = yield* ServerSecretStore;
@@ -17104,7 +17153,7 @@ const make$115 = Effect.gen(function* () {
17104
17153
  markDisconnected
17105
17154
  });
17106
17155
  });
17107
- const layer$117 = Layer.effect(SessionStore, make$115).pipe(Layer.provideMerge(layer$119));
17156
+ const layer$117 = Layer.effect(SessionStore, make$117).pipe(Layer.provideMerge(layer$119));
17108
17157
  //#endregion
17109
17158
  //#region src/persistence/AuthPairingLinks.ts
17110
17159
  const AuthPairingLinkRecord = Schema$1.Struct({
@@ -17165,7 +17214,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
17165
17214
  cause
17166
17215
  });
17167
17216
  }
17168
- const make$114 = Effect.gen(function* () {
17217
+ const make$116 = Effect.gen(function* () {
17169
17218
  const sql = yield* SqlClient.SqlClient;
17170
17219
  const createPairingLinkRow = SqlSchema.void({
17171
17220
  Request: CreateAuthPairingLinkInput,
@@ -17300,7 +17349,7 @@ const make$114 = Effect.gen(function* () {
17300
17349
  getByCredential
17301
17350
  };
17302
17351
  });
17303
- const layer$116 = Layer.effect(AuthPairingLinkRepository, make$114);
17352
+ const layer$116 = Layer.effect(AuthPairingLinkRepository, make$116);
17304
17353
  //#endregion
17305
17354
  //#region src/auth/PairingGrantStore.ts
17306
17355
  var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
@@ -17395,7 +17444,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
17395
17444
  const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
17396
17445
  const PAIRING_TOKEN_LENGTH = 12;
17397
17446
  const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
17398
- const make$113 = Effect.gen(function* () {
17447
+ const make$115 = Effect.gen(function* () {
17399
17448
  const crypto = yield* Crypto.Crypto;
17400
17449
  const config = yield* ServerConfig$1;
17401
17450
  const pairingLinks = yield* AuthPairingLinkRepository;
@@ -17593,7 +17642,7 @@ const make$113 = Effect.gen(function* () {
17593
17642
  consume
17594
17643
  });
17595
17644
  });
17596
- const layer$115 = Layer.effect(PairingGrantStore, make$113).pipe(Layer.provideMerge(layer$116));
17645
+ const layer$115 = Layer.effect(PairingGrantStore, make$115).pipe(Layer.provideMerge(layer$116));
17597
17646
  //#endregion
17598
17647
  //#region src/persistence/DatabaseSnapshot.ts
17599
17648
  /**
@@ -20978,7 +21027,7 @@ function parseBearerToken(request) {
20978
21027
  const token = header.slice(7).trim();
20979
21028
  return token.length > 0 ? token : null;
20980
21029
  }
20981
- const make$112 = Effect.gen(function* () {
21030
+ const make$114 = Effect.gen(function* () {
20982
21031
  const policy = yield* EnvironmentAuthPolicy;
20983
21032
  const bootstrapCredentials = yield* PairingGrantStore;
20984
21033
  const sessions = yield* SessionStore;
@@ -21173,7 +21222,7 @@ const make$112 = Effect.gen(function* () {
21173
21222
  issueStartupPairingUrl
21174
21223
  });
21175
21224
  });
21176
- const layer$114 = Layer.effect(EnvironmentAuth, make$112).pipe(Layer.provideMerge(layer$115), Layer.provideMerge(layer$117), Layer.provideMerge(layer$120));
21225
+ const layer$114 = Layer.effect(EnvironmentAuth, make$114).pipe(Layer.provideMerge(layer$115), Layer.provideMerge(layer$117), Layer.provideMerge(layer$120));
21177
21226
  const storageLayer = Layer.mergeAll(layer$118, layerConfig);
21178
21227
  const runtimeLayer = layer$114.pipe(Layer.provideMerge(storageLayer));
21179
21228
  //#endregion
@@ -23169,7 +23218,7 @@ const DEFAULT_LIMITS = {
23169
23218
  windowMillis: FAILURE_WINDOW_MS$1,
23170
23219
  blockMillis: BLOCK_DURATION_MS
23171
23220
  };
23172
- const make$111 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
23221
+ const make$113 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
23173
23222
  const state = yield* Ref.make(initialThrottleState);
23174
23223
  return HubAuthThrottle.of({
23175
23224
  shouldRefuse: Effect.gen(function* () {
@@ -23183,7 +23232,7 @@ const make$111 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_L
23183
23232
  })
23184
23233
  });
23185
23234
  });
23186
- const layer$113 = Layer.effect(HubAuthThrottle, make$111());
23235
+ const layer$113 = Layer.effect(HubAuthThrottle, make$113());
23187
23236
  //#endregion
23188
23237
  //#region src/hub/HubAuth.ts
23189
23238
  /**
@@ -25165,12 +25214,12 @@ const persistHubAgentActivity = Effect.fn("HubNotificationActivity.persist")(fun
25165
25214
  var HubSecretStoreUnavailable = class extends Data.TaggedError("HubSecretStoreUnavailable") {};
25166
25215
  const HUB_SECRETS_SUFFIX = ".secrets";
25167
25216
  /** Dedicated sibling directory per Hub database; no environment configuration is consulted. */
25168
- const make$110 = Effect.gen(function* () {
25217
+ const make$112 = Effect.gen(function* () {
25169
25218
  const config = yield* HubConfig;
25170
25219
  if (!(yield* Path$1.Path).isAbsolute(config.dbPath)) return yield* Effect.fail(new HubSecretStoreUnavailable({ message: "Hub secret storage requires an absolute database path." }));
25171
25220
  return yield* makeForDirectory(`${config.dbPath}${HUB_SECRETS_SUFFIX}`);
25172
25221
  });
25173
- const layer$107 = Layer.effect(ServerSecretStore, make$110);
25222
+ const layer$107 = Layer.effect(ServerSecretStore, make$112);
25174
25223
  //#endregion
25175
25224
  //#region src/hub/HubNotificationRoutes.ts
25176
25225
  const MAX_NOTIFICATION_BODY_BYTES = 16 * 1024;
@@ -29268,7 +29317,7 @@ function stripDefaultServerSettings(current, defaults) {
29268
29317
  }
29269
29318
  return Object.is(current, defaults) ? void 0 : current;
29270
29319
  }
29271
- const make$109 = Effect.gen(function* () {
29320
+ const make$111 = Effect.gen(function* () {
29272
29321
  const { settingsPath } = yield* ServerConfig$1;
29273
29322
  const fs = yield* FileSystem.FileSystem;
29274
29323
  const pathService = yield* Path$1.Path;
@@ -29491,7 +29540,7 @@ const make$109 = Effect.gen(function* () {
29491
29540
  }
29492
29541
  };
29493
29542
  });
29494
- const layer$93 = Layer.effect(ServerSettingsService, make$109);
29543
+ const layer$93 = Layer.effect(ServerSettingsService, make$111);
29495
29544
  //#endregion
29496
29545
  //#region src/pathExpansion.ts
29497
29546
  /**
@@ -30193,7 +30242,7 @@ function claudeEntryFromRegistration(registration) {
30193
30242
  };
30194
30243
  }
30195
30244
  var ClaudeMcpFiles = class extends Context.Service()("@p4code/cli/mcp/ClaudeMcpFiles") {};
30196
- const make$108 = Effect.gen(function* () {
30245
+ const make$110 = Effect.gen(function* () {
30197
30246
  const fileSystem = yield* FileSystem.FileSystem;
30198
30247
  const path = yield* Path$1.Path;
30199
30248
  const services = yield* Effect.context();
@@ -30260,7 +30309,7 @@ const make$108 = Effect.gen(function* () {
30260
30309
  removeProject: (projectDir, name) => removeAt(Effect.succeed(projectFile(projectDir)))(name)
30261
30310
  };
30262
30311
  });
30263
- const layer$92 = Layer.effect(ClaudeMcpFiles, make$108);
30312
+ const layer$92 = Layer.effect(ClaudeMcpFiles, make$110);
30264
30313
  Layer.succeed(ClaudeMcpFiles, {
30265
30314
  readUser: Effect.succeed([]),
30266
30315
  readUserAt: () => Effect.succeed([]),
@@ -30398,7 +30447,7 @@ const decodeClientRegistration = Schema$1.decodeUnknownExit(ClientRegistrationRe
30398
30447
  const decodeTokenResponse = Schema$1.decodeUnknownExit(TokenResponse);
30399
30448
  var McpOAuth = class extends Context.Service()("@p4code/cli/mcp/McpOAuth") {};
30400
30449
  const registryError = (detail) => new McpRegistryError({ detail });
30401
- const make$107 = Effect.gen(function* () {
30450
+ const make$109 = Effect.gen(function* () {
30402
30451
  const config = yield* ServerConfig$1;
30403
30452
  const secrets = yield* ServerSecretStore;
30404
30453
  const http = yield* HttpClient.HttpClient;
@@ -30718,7 +30767,7 @@ const make$107 = Effect.gen(function* () {
30718
30767
  accessTokenFor
30719
30768
  };
30720
30769
  });
30721
- const layer$91 = Layer.effect(McpOAuth, make$107);
30770
+ const layer$91 = Layer.effect(McpOAuth, make$109);
30722
30771
  Layer.succeed(McpOAuth, {
30723
30772
  statusFor: () => Effect.succeed(Option.none()),
30724
30773
  begin: () => Effect.fail(new McpRegistryError({ detail: "OAuth sign-in is not available." })),
@@ -30736,7 +30785,7 @@ const decodeRegistration$1 = Schema$1.decodeUnknownExit(RegistrationFromJson$1);
30736
30785
  const encodeRegistration = Schema$1.encodeSync(RegistrationFromJson$1);
30737
30786
  var McpRegistry = class extends Context.Service()("@p4code/cli/mcp/McpRegistry") {};
30738
30787
  const slotsOf = (registration) => registration.secrets ?? [];
30739
- const make$106 = Effect.gen(function* () {
30788
+ const make$108 = Effect.gen(function* () {
30740
30789
  const config = yield* ServerConfig$1;
30741
30790
  const secrets = yield* ServerSecretStore;
30742
30791
  const oauth = yield* McpOAuth;
@@ -30910,7 +30959,7 @@ const make$106 = Effect.gen(function* () {
30910
30959
  resolveForSessionAtClaudeUserConfigPath
30911
30960
  };
30912
30961
  });
30913
- const layer$90 = Layer.effect(McpRegistry, make$106);
30962
+ const layer$90 = Layer.effect(McpRegistry, make$108);
30914
30963
  //#endregion
30915
30964
  //#region src/sync/skillDirectory.ts
30916
30965
  /**
@@ -31289,7 +31338,7 @@ const formatHubLink = (input) => encodeStoredHubLink({
31289
31338
  shareMode: input.shareMode
31290
31339
  });
31291
31340
  const fromEnvironment = (environment) => validateHubLink(environment.P4CODE_HUB_URL ?? "", environment.P4CODE_HUB_TOKEN ?? "");
31292
- const make$105 = Effect.fn("HubLink.make")(function* (environment) {
31341
+ const make$107 = Effect.fn("HubLink.make")(function* (environment) {
31293
31342
  const secrets = yield* ServerSecretStore;
31294
31343
  const env = environment ?? process.env;
31295
31344
  const fromEnv = fromEnvironment(env);
@@ -31362,7 +31411,7 @@ const make$105 = Effect.fn("HubLink.make")(function* (environment) {
31362
31411
  })
31363
31412
  };
31364
31413
  });
31365
- const layer$89 = Layer.effect(HubLink, make$105());
31414
+ const layer$89 = Layer.effect(HubLink, make$107());
31366
31415
  //#endregion
31367
31416
  //#region src/sync/HubAssetClient.ts
31368
31417
  /**
@@ -31395,7 +31444,7 @@ const decodeAssetListPage = Schema$1.decodeUnknownEffect(AssetListPage);
31395
31444
  const decodeConflictBody$1 = Schema$1.decodeUnknownEffect(ConflictBody$1);
31396
31445
  const decodeAsset = Schema$1.decodeUnknownEffect(AgentAsset);
31397
31446
  var HubAssetClient = class extends Context.Service()("@p4code/cli/sync/HubAssetClient") {};
31398
- const make$104 = Effect.gen(function* () {
31447
+ const make$106 = Effect.gen(function* () {
31399
31448
  const http = yield* HttpClient.HttpClient;
31400
31449
  const link = yield* HubLink;
31401
31450
  const requireSettings = Effect.gen(function* () {
@@ -31477,7 +31526,7 @@ const make$104 = Effect.gen(function* () {
31477
31526
  remove
31478
31527
  };
31479
31528
  });
31480
- const layer$88 = Layer.effect(HubAssetClient, make$104);
31529
+ const layer$88 = Layer.effect(HubAssetClient, make$106);
31481
31530
  //#endregion
31482
31531
  //#region src/sync/mcpRegistrationFiles.ts
31483
31532
  /**
@@ -32408,7 +32457,7 @@ const EMPTY_REPORT = {
32408
32457
  unavailable: null
32409
32458
  };
32410
32459
  var AssetSync = class extends Context.Service()("@p4code/cli/sync/AssetSync") {};
32411
- const make$103 = Effect.gen(function* () {
32460
+ const make$105 = Effect.gen(function* () {
32412
32461
  const client = yield* HubAssetClient;
32413
32462
  const link = yield* HubLink;
32414
32463
  const settingsStore = yield* ServerSettingsService;
@@ -33272,7 +33321,7 @@ const make$103 = Effect.gen(function* () {
33272
33321
  removeLocal
33273
33322
  };
33274
33323
  });
33275
- const layer$87 = Layer.effect(AssetSync, make$103);
33324
+ const layer$87 = Layer.effect(AssetSync, make$105);
33276
33325
  //#endregion
33277
33326
  //#region src/provider/CompressPrompts.ts
33278
33327
  /**
@@ -34661,7 +34710,7 @@ const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
34661
34710
  "interrupted"
34662
34711
  ]);
34663
34712
  var ThreadBackgroundLivenessService = class extends Context.Service()("@p4code/cli/orchestration/ThreadBackgroundLiveness/ThreadBackgroundLivenessService") {};
34664
- function make$102() {
34713
+ function make$104() {
34665
34714
  const stateByThreadId = /* @__PURE__ */ new Map();
34666
34715
  const stateFor = (threadId) => {
34667
34716
  const existing = stateByThreadId.get(threadId);
@@ -34717,7 +34766,7 @@ function make$102() {
34717
34766
  }
34718
34767
  };
34719
34768
  }
34720
- const layer$86 = Layer.effect(ThreadBackgroundLivenessService, Effect.sync(make$102));
34769
+ const layer$86 = Layer.effect(ThreadBackgroundLivenessService, Effect.sync(make$104));
34721
34770
  //#endregion
34722
34771
  //#region ../../packages/shared/src/sourceControl.ts
34723
34772
  const GITHUB_CHANGE_REQUEST_PRESENTATION = {
@@ -41185,12 +41234,12 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* (spaw
41185
41234
  stderrInvalidUtf8: stderr.invalidUtf8
41186
41235
  };
41187
41236
  });
41188
- const make$101 = Effect.fn("ProcessRunner.make")(function* () {
41237
+ const make$103 = Effect.fn("ProcessRunner.make")(function* () {
41189
41238
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
41190
41239
  const run = (input) => finalizeRunProcess(runProcessCore(spawner, input), input);
41191
41240
  return ProcessRunner.of({ run });
41192
41241
  });
41193
- const layer$85 = Layer.effect(ProcessRunner, make$101());
41242
+ const layer$85 = Layer.effect(ProcessRunner, make$103());
41194
41243
  //#endregion
41195
41244
  //#region src/project/RepositoryIdentityResolver.ts
41196
41245
  const DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY = 512;
@@ -41281,7 +41330,7 @@ const resolveRepositoryIdentityFromCacheKey = Effect.fn("RepositoryIdentityResol
41281
41330
  rootPath: cacheKey
41282
41331
  }) : null;
41283
41332
  });
41284
- const make$100 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
41333
+ const make$102 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
41285
41334
  const processRunner = yield* ProcessRunner;
41286
41335
  const repositoryIdentityCache = yield* Cache.makeWith((cacheKey) => resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(Effect.provideService(ProcessRunner, processRunner)), {
41287
41336
  capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
@@ -41296,7 +41345,7 @@ const make$100 = Effect.fn("RepositoryIdentityResolver.make")(function* (options
41296
41345
  });
41297
41346
  return RepositoryIdentityResolver.of({ resolve });
41298
41347
  });
41299
- const layer$84 = Layer.effect(RepositoryIdentityResolver, make$100()).pipe(Layer.provide(layer$85));
41348
+ const layer$84 = Layer.effect(RepositoryIdentityResolver, make$102()).pipe(Layer.provide(layer$85));
41300
41349
  //#endregion
41301
41350
  //#region src/orchestration/Layers/ProjectionSnapshotQuery.ts
41302
41351
  const decodeReadModel = Schema$1.decodeUnknownEffect(OrchestrationReadModel);
@@ -43590,7 +43639,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
43590
43639
  threadId,
43591
43640
  turnId
43592
43641
  }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getTurnStart:query", "ProjectionSnapshotQuery.getTurnStart:decodeRow")));
43593
- const getActiveTurnId = (threadId) => getActiveTurnIdRow(threadId).pipe(Effect.map(Option.flatMap((row) => Option.fromNullable(row.activeTurnId))), Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getActiveTurnId:query", "ProjectionSnapshotQuery.getActiveTurnId:decodeRow")));
43642
+ const getActiveTurnId = (threadId) => getActiveTurnIdRow(threadId).pipe(Effect.map(Option.flatMap((row) => Option.fromNullishOr(row.activeTurnId))), Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getActiveTurnId:query", "ProjectionSnapshotQuery.getActiveTurnId:decodeRow")));
43594
43643
  const getLatestThreadMessageWithIdPrefix = (threadId, idPrefix) => getLatestThreadMessageWithIdPrefixRow({
43595
43644
  threadId,
43596
43645
  idPrefix
@@ -44618,7 +44667,7 @@ function mergeWithDefaultKeybindings(custom) {
44618
44667
  * Keybindings - Service tag for keybinding configuration operations.
44619
44668
  */
44620
44669
  var Keybindings = class extends Context.Service()("@p4code/cli/keybindings") {};
44621
- const make$99 = Effect.gen(function* () {
44670
+ const make$101 = Effect.gen(function* () {
44622
44671
  const { keybindingsConfigPath } = yield* ServerConfig$1;
44623
44672
  const fs = yield* FileSystem.FileSystem;
44624
44673
  const path = yield* Path$1.Path;
@@ -44879,7 +44928,7 @@ const make$99 = Effect.gen(function* () {
44879
44928
  }))
44880
44929
  };
44881
44930
  });
44882
- const layer$83 = Layer.effect(Keybindings, make$99);
44931
+ const layer$83 = Layer.effect(Keybindings, make$101);
44883
44932
  //#endregion
44884
44933
  //#region src/process/externalLauncher.ts
44885
44934
  /**
@@ -45106,7 +45155,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu
45106
45155
  cause
45107
45156
  }));
45108
45157
  });
45109
- const make$98 = Effect.gen(function* () {
45158
+ const make$100 = Effect.gen(function* () {
45110
45159
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
45111
45160
  const fileSystem = yield* FileSystem.FileSystem;
45112
45161
  const path = yield* Path$1.Path;
@@ -45117,7 +45166,7 @@ const make$98 = Effect.gen(function* () {
45117
45166
  launchEditor: (input) => provideCommandResolutionServices(Effect.flatMap(resolveEditorLaunch(input), (launch) => launchEditorProcess(launch).pipe(Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner))))
45118
45167
  });
45119
45168
  });
45120
- const layer$82 = Layer.effect(ExternalLauncher, make$98);
45169
+ const layer$82 = Layer.effect(ExternalLauncher, make$100);
45121
45170
  //#endregion
45122
45171
  //#region src/orchestration/Services/OrchestrationReactor.ts
45123
45172
  /**
@@ -45135,7 +45184,7 @@ var OrchestrationReactor = class extends Context.Service()("@p4code/cli/orchestr
45135
45184
  //#endregion
45136
45185
  //#region src/serverLifecycleEvents.ts
45137
45186
  var ServerLifecycleEvents = class extends Context.Service()("@p4code/cli/serverLifecycleEvents") {};
45138
- const make$97 = Effect.gen(function* () {
45187
+ const make$99 = Effect.gen(function* () {
45139
45188
  const pubsub = yield* PubSub.unbounded();
45140
45189
  const state = yield* Ref.make({
45141
45190
  sequence: 0,
@@ -45159,7 +45208,7 @@ const make$97 = Effect.gen(function* () {
45159
45208
  }
45160
45209
  };
45161
45210
  });
45162
- const layer$81 = Layer.effect(ServerLifecycleEvents, make$97);
45211
+ const layer$81 = Layer.effect(ServerLifecycleEvents, make$99);
45163
45212
  //#endregion
45164
45213
  //#region src/telemetry/Identify.ts
45165
45214
  const CodexAuthJsonSchema = Schema$1.Struct({ tokens: Schema$1.Struct({ account_id: Schema$1.String }) });
@@ -45332,7 +45381,7 @@ var AnalyticsService = class AnalyticsService extends Context.Service()("@p4code
45332
45381
  /** No-op layer for callers that intentionally disable telemetry. */
45333
45382
  static layerTest = Layer.succeed(AnalyticsService, inert);
45334
45383
  };
45335
- const make$96 = Effect.gen(function* () {
45384
+ const make$98 = Effect.gen(function* () {
45336
45385
  const telemetryConfig = yield* TelemetryEnvConfig;
45337
45386
  const posthogKey = telemetryConfig.posthogKey.trim();
45338
45387
  if (!telemetryConfig.enabled || posthogKey === "") return inert;
@@ -45402,7 +45451,7 @@ const make$96 = Effect.gen(function* () {
45402
45451
  flush
45403
45452
  });
45404
45453
  });
45405
- const layer$80 = Layer.effect(AnalyticsService, make$96);
45454
+ const layer$80 = Layer.effect(AnalyticsService, make$98);
45406
45455
  AnalyticsService.layerTest;
45407
45456
  //#endregion
45408
45457
  //#region src/provider/Services/ProviderSessionDirectory.ts
@@ -45833,7 +45882,7 @@ var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootSer
45833
45882
  }
45834
45883
  };
45835
45884
  var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
45836
- const make$95 = Effect.fn("cloud.boot_service.make")(function* (input) {
45885
+ const make$97 = Effect.fn("cloud.boot_service.make")(function* (input) {
45837
45886
  const hostExecPath = yield* HostProcessExecutablePath;
45838
45887
  const hostArguments = yield* HostProcessArguments;
45839
45888
  const host = input.host ?? {
@@ -46055,7 +46104,7 @@ const make$95 = Effect.fn("cloud.boot_service.make")(function* (input) {
46055
46104
  logPath
46056
46105
  });
46057
46106
  });
46058
- const layer$79 = (input) => Layer.effect(BootService, make$95(input));
46107
+ const layer$79 = (input) => Layer.effect(BootService, make$97(input));
46059
46108
  //#endregion
46060
46109
  //#region src/service/selfUpdate.ts
46061
46110
  /**
@@ -46130,7 +46179,7 @@ const resolveServerSelfUpdateCapability = Effect.fn("cloud.server_self_update.re
46130
46179
  return null;
46131
46180
  });
46132
46181
  var ServerSelfUpdate = class extends Context.Service()("@p4code/cli/service/selfUpdate/ServerSelfUpdate") {};
46133
- const make$94 = Effect.fn("cloud.server_self_update.make")(function* (options) {
46182
+ const make$96 = Effect.fn("cloud.server_self_update.make")(function* (options) {
46134
46183
  const serverConfig = yield* ServerConfig$1;
46135
46184
  const settings = yield* ServerSettingsService;
46136
46185
  const continuationContext = yield* Effect.context();
@@ -46293,7 +46342,7 @@ const make$94 = Effect.fn("cloud.server_self_update.make")(function* (options) {
46293
46342
  });
46294
46343
  return ServerSelfUpdate.of({ update });
46295
46344
  });
46296
- const layer$78 = Layer.effect(ServerSelfUpdate, make$94()).pipe(Layer.provide(layer$85));
46345
+ const layer$78 = Layer.effect(ServerSelfUpdate, make$96()).pipe(Layer.provide(layer$85));
46297
46346
  //#endregion
46298
46347
  //#region src/environment/ServerEnvironmentLabel.ts
46299
46348
  const ServerEnvironmentLabelCommandProbe = Schema$1.Literals(["macos-computer-name", "linux-pretty-hostname"]);
@@ -46425,7 +46474,7 @@ function platformArch(architecture) {
46425
46474
  default: return "other";
46426
46475
  }
46427
46476
  }
46428
- const make$93 = Effect.gen(function* () {
46477
+ const make$95 = Effect.gen(function* () {
46429
46478
  const fileSystem = yield* FileSystem.FileSystem;
46430
46479
  const path = yield* Path$1.Path;
46431
46480
  const serverConfig = yield* ServerConfig$1;
@@ -46503,7 +46552,7 @@ const make$93 = Effect.gen(function* () {
46503
46552
  * state. It intentionally has no fallback Layer.succeed value: callers must
46504
46553
  * provide the external platform services and a ServerConfig.
46505
46554
  */
46506
- const layer$77 = Layer.effect(ServerEnvironment, make$93).pipe(Layer.provide(layer$85));
46555
+ const layer$77 = Layer.effect(ServerEnvironment, make$95).pipe(Layer.provide(layer$85));
46507
46556
  //#endregion
46508
46557
  //#region src/sync/SettingsSync.ts
46509
46558
  /**
@@ -46533,7 +46582,9 @@ const IDLE = {
46533
46582
  sent: []
46534
46583
  };
46535
46584
  var SettingsSync = class extends Context.Service()("@p4code/cli/sync/SettingsSync") {};
46536
- const decodePayload = Schema$1.decodeUnknownOption(SettingsSyncPayload);
46585
+ const payloadJson = Schema$1.fromJsonString(SettingsSyncPayload);
46586
+ const decodePayload = Schema$1.decodeUnknownOption(payloadJson);
46587
+ const encodePayload = Schema$1.encodeEffect(payloadJson);
46537
46588
  /** The machine's own name, so history can say where a change came from. */
46538
46589
  const environmentLabel = () => {
46539
46590
  const hostname = NodeOS.hostname().trim();
@@ -46562,7 +46613,7 @@ const promptOverrideIsRunnable = (value) => {
46562
46613
  }
46563
46614
  return true;
46564
46615
  };
46565
- const make$92 = Effect.gen(function* () {
46616
+ const make$94 = Effect.gen(function* () {
46566
46617
  const settingsService = yield* ServerSettingsService;
46567
46618
  const client = yield* HubAssetClient;
46568
46619
  const label = environmentLabel();
@@ -46590,13 +46641,9 @@ const make$92 = Effect.gen(function* () {
46590
46641
  const incoming = Option.flatMap(fetched.asset, (asset) => {
46591
46642
  const file = asset.files.find((candidate) => candidate.path === SETTINGS_SYNC_FILE_PATH);
46592
46643
  if (file === void 0) return Option.none();
46593
- try {
46594
- return decodePayload(JSON.parse(file.content));
46595
- } catch {
46596
- return Option.none();
46597
- }
46644
+ return decodePayload(file.content);
46598
46645
  });
46599
- const now = new Date(yield* Clock.currentTimeMillis).toISOString();
46646
+ const now = DateTime.formatIso(yield* DateTime.now);
46600
46647
  const plan = planSettingsSync({
46601
46648
  local: filterSyncedSettings(settings),
46602
46649
  base: settings.settingsSync.base,
@@ -46650,12 +46697,13 @@ const make$92 = Effect.gen(function* () {
46650
46697
  environmentLabel: label,
46651
46698
  publishedAt: now
46652
46699
  };
46700
+ const content = yield* encodePayload(payload).pipe(Effect.orDie);
46653
46701
  const written = yield* client.write({
46654
46702
  kind: "settings",
46655
46703
  name: ASSET_NAME,
46656
46704
  files: [{
46657
46705
  path: SETTINGS_SYNC_FILE_PATH,
46658
- content: JSON.stringify(payload)
46706
+ content
46659
46707
  }],
46660
46708
  ...Option.match(fetched.asset, {
46661
46709
  onNone: () => ({}),
@@ -46707,7 +46755,7 @@ const make$92 = Effect.gen(function* () {
46707
46755
  unavailable: "settings sync failed"
46708
46756
  })))) };
46709
46757
  });
46710
- const layer$76 = Layer.effect(SettingsSync, make$92);
46758
+ const layer$76 = Layer.effect(SettingsSync, make$94);
46711
46759
  //#endregion
46712
46760
  //#region src/provider/Services/ProviderHealthRefresher.ts
46713
46761
  var ProviderHealthRefresher = class extends Context.Service()("@p4code/cli/provider/Services/ProviderHealthRefresher") {};
@@ -47065,7 +47113,7 @@ function daemonPortLine(line) {
47065
47113
  const port = Number(raw);
47066
47114
  return Number.isInteger(port) && port > 0 && port <= MAX_PORT$1 ? port : null;
47067
47115
  }
47068
- const make$91 = Effect.fn("AgentDeviceProcess.make")(function* () {
47116
+ const make$93 = Effect.fn("AgentDeviceProcess.make")(function* () {
47069
47117
  const fs = yield* FileSystem.FileSystem;
47070
47118
  const path = yield* Path$1.Path;
47071
47119
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
@@ -47177,7 +47225,7 @@ const make$91 = Effect.fn("AgentDeviceProcess.make")(function* () {
47177
47225
  });
47178
47226
  return { start };
47179
47227
  });
47180
- const layer$75 = Layer.effect(AgentDeviceProcess, make$91());
47228
+ const layer$75 = Layer.effect(AgentDeviceProcess, make$93());
47181
47229
  //#endregion
47182
47230
  //#region src/device/DeviceDiscovery.ts
47183
47231
  var DeviceDiscoveryFailure = class extends Data.TaggedError("DeviceDiscoveryFailure") {};
@@ -47210,7 +47258,7 @@ const decodeDeviceDiscovery = (hostId, body) => Schema$1.decodeUnknownEffect(Sch
47210
47258
  partial: (value.errors?.length ?? 0) > 0
47211
47259
  });
47212
47260
  }));
47213
- const make$90 = Effect.fn("DeviceDiscovery.make")(function* () {
47261
+ const make$92 = Effect.fn("DeviceDiscovery.make")(function* () {
47214
47262
  const http = yield* HttpClient.HttpClient;
47215
47263
  return Effect.fn("DeviceDiscovery.read")(function* (input) {
47216
47264
  const origin = yield* Effect.try(() => new URL(input.ready.hub.origin));
@@ -47272,7 +47320,7 @@ const Result = Schema$1.Struct({
47272
47320
  serial: Schema$1.optional(DeviceId),
47273
47321
  error: Schema$1.optional(Schema$1.String)
47274
47322
  });
47275
- const make$89 = Effect.fn("DeviceHubActions.make")(function* () {
47323
+ const make$91 = Effect.fn("DeviceHubActions.make")(function* () {
47276
47324
  const http = yield* HttpClient.HttpClient;
47277
47325
  const post = Effect.fn("DeviceHubActions.post")(function* (ready, route, payload, timeoutMs) {
47278
47326
  return yield* Effect.gen(function* () {
@@ -47341,7 +47389,7 @@ function sessionsToClose(sessions, input) {
47341
47389
  //#endregion
47342
47390
  //#region src/device/DeviceCommandLeases.ts
47343
47391
  /** Owns commands by exact session object, so close/reopen cannot revive an old lease. */
47344
- const make$88 = Effect.fn("DeviceCommandLeases.make")(function* () {
47392
+ const make$90 = Effect.fn("DeviceCommandLeases.make")(function* () {
47345
47393
  const lock = yield* Semaphore.make(1);
47346
47394
  const entries = /* @__PURE__ */ new Map();
47347
47395
  const revoked = /* @__PURE__ */ new WeakSet();
@@ -47387,7 +47435,7 @@ const make$88 = Effect.fn("DeviceCommandLeases.make")(function* () {
47387
47435
  //#endregion
47388
47436
  //#region src/device/DeviceThreadLeases.ts
47389
47437
  /** Thread retirement also cancels opens that have not created a session yet. */
47390
- const make$87 = Effect.fn("DeviceThreadLeases.make")(function* () {
47438
+ const make$89 = Effect.fn("DeviceThreadLeases.make")(function* () {
47391
47439
  const lock = yield* Semaphore.make(1);
47392
47440
  const scopes = /* @__PURE__ */ new Map();
47393
47441
  const blocked = /* @__PURE__ */ new Set();
@@ -47435,7 +47483,7 @@ const make$87 = Effect.fn("DeviceThreadLeases.make")(function* () {
47435
47483
  //#region src/device/DeviceHostRegistry.ts
47436
47484
  const sameConfig = (a, b) => a === b || a !== null && b !== null && a.id === b.id && a.label === b.label && a.target === b.target && a.port === b.port && a.identityFile === b.identityFile;
47437
47485
  /** Owns configuration generations; use() interrupts in-flight work before a host is retired. */
47438
- const make$86 = Effect.fn("DeviceHostRegistry.make")(function* (factories) {
47486
+ const make$88 = Effect.fn("DeviceHostRegistry.make")(function* (factories) {
47439
47487
  const factoryContext = yield* Effect.context();
47440
47488
  const lock = yield* Semaphore.make(1);
47441
47489
  const entries = /* @__PURE__ */ new Map();
@@ -47603,7 +47651,7 @@ function pngDimensions(png) {
47603
47651
  height
47604
47652
  };
47605
47653
  }
47606
- const make$85 = Effect.fn("DeviceScreenshot.make")(function* () {
47654
+ const make$87 = Effect.fn("DeviceScreenshot.make")(function* () {
47607
47655
  const http = yield* HttpClient.HttpClient;
47608
47656
  return Effect.fn("DeviceScreenshot.capture")(function* (ready, session) {
47609
47657
  const origin = yield* Effect.try(() => new URL(ready.hub.origin));
@@ -47630,7 +47678,7 @@ const make$85 = Effect.fn("DeviceScreenshot.make")(function* () {
47630
47678
  })));
47631
47679
  });
47632
47680
  var DeviceScreenshot = class extends Context.Service()("@p4code/cli/device/DeviceScreenshot") {};
47633
- const layer$74 = Layer.effect(DeviceScreenshot, make$85().pipe(Effect.map((capture) => ({ capture }))));
47681
+ const layer$74 = Layer.effect(DeviceScreenshot, make$87().pipe(Effect.map((capture) => ({ capture }))));
47634
47682
  //#endregion
47635
47683
  //#region src/device/XcodeMcpClient.ts
47636
47684
  const XCODE_BUILD_MCP_VERSION = "2.7.0";
@@ -48443,7 +48491,7 @@ const COMMAND_TIMEOUT_MS$1 = 2e4;
48443
48491
  const COMMAND_OUTPUT_LIMIT = 1024 * 1024;
48444
48492
  const COMMAND_FAILURE_CODE = 127;
48445
48493
  const APPLE_DEVICE_MCP_MINIMUM_XCODE = 27;
48446
- const make$84 = Effect.fn("LocalDeviceHost.make")(function* () {
48494
+ const make$86 = Effect.fn("LocalDeviceHost.make")(function* () {
48447
48495
  const config = yield* ServerConfig$1;
48448
48496
  const fs = yield* FileSystem.FileSystem;
48449
48497
  const path = yield* Path$1.Path;
@@ -48596,7 +48644,7 @@ const make$84 = Effect.fn("LocalDeviceHost.make")(function* () {
48596
48644
  stop: lock.withPermit(stop)
48597
48645
  };
48598
48646
  });
48599
- Layer.effect(DeviceHost, make$84()).pipe(Layer.provide(layer$75));
48647
+ Layer.effect(DeviceHost, make$86()).pipe(Layer.provide(layer$75));
48600
48648
  Data.TaggedError("SshHostDiscoveryError");
48601
48649
  var SshInvalidTargetError = class extends Data.TaggedError("SshInvalidTargetError") {};
48602
48650
  var SshCommandError = class extends Data.TaggedError("SshCommandError") {};
@@ -49455,7 +49503,7 @@ const probeSshDeviceHost = Effect.fn("SshDeviceDiagnostics.probe")(function* (co
49455
49503
  //#endregion
49456
49504
  //#region src/device/SshDeviceHost.ts
49457
49505
  const DIAGNOSTICS_CACHE_MS = 1e4;
49458
- const make$83 = Effect.fn("SshDeviceHost.make")(function* (input) {
49506
+ const make$85 = Effect.fn("SshDeviceHost.make")(function* (input) {
49459
49507
  const config = yield* Schema$1.decodeUnknownEffect(SshDeviceHostConfig)({ ...input }).pipe(Effect.mapError(() => new DeviceHostError({
49460
49508
  hostId: input.id,
49461
49509
  step: "configuring SSH device host",
@@ -49595,8 +49643,8 @@ var DeviceService = class extends Context.Service()("@p4code/cli/device/DeviceSe
49595
49643
  const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input) {
49596
49644
  const settings = yield* ServerSettingsService;
49597
49645
  const scope = yield* Scope.Scope;
49598
- const registry = yield* make$86(input);
49599
- const commands = yield* make$88();
49646
+ const registry = yield* make$88(input);
49647
+ const commands = yield* make$90();
49600
49648
  const adapterLeases = /* @__PURE__ */ new Map();
49601
49649
  const closeCommands = (sessions) => Effect.sync(() => {
49602
49650
  for (const session of sessions) {
@@ -49605,7 +49653,7 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
49605
49653
  adapterLeases.delete(session.leaseId);
49606
49654
  }
49607
49655
  }).pipe(Effect.andThen(commands.close(sessions)));
49608
- const threads = yield* make$87();
49656
+ const threads = yield* make$89();
49609
49657
  const changes = yield* Effect.acquireRelease(PubSub.sliding(STATE_BUFFER_SIZE), PubSub.shutdown);
49610
49658
  const stateLock = yield* Semaphore.make(1);
49611
49659
  const discoveryLock = yield* Semaphore.make(1);
@@ -50016,17 +50064,17 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
50016
50064
  }))
50017
50065
  };
50018
50066
  });
50019
- const make$82 = Effect.gen(function* () {
50020
- const discover = yield* make$90();
50021
- const actions = yield* make$89();
50067
+ const make$84 = Effect.gen(function* () {
50068
+ const discover = yield* make$92();
50069
+ const actions = yield* make$91();
50022
50070
  return yield* makeWithHosts({
50023
- local: make$84(),
50024
- ssh: make$83,
50071
+ local: make$86(),
50072
+ ssh: make$85,
50025
50073
  discover,
50026
50074
  actions
50027
50075
  });
50028
50076
  }).pipe(Effect.provide(layer$75));
50029
- const layer$72 = Layer.effect(DeviceService, make$82);
50077
+ const layer$72 = Layer.effect(DeviceService, make$84);
50030
50078
  //#endregion
50031
50079
  //#region src/serverRuntimeStartup.ts
50032
50080
  var ServerRuntimeStartupError = class extends Schema$1.TaggedErrorClass()("ServerRuntimeStartupError", {
@@ -50171,7 +50219,7 @@ const startProviderRecovery = Effect.fn("startup.startProviderRecovery")(functio
50171
50219
  yield* input.recover;
50172
50220
  yield* input.startReaper;
50173
50221
  });
50174
- const make$81 = Effect.gen(function* () {
50222
+ const make$83 = Effect.gen(function* () {
50175
50223
  const serverConfig = yield* ServerConfig$1;
50176
50224
  const keybindings = yield* Keybindings;
50177
50225
  const orchestrationReactor = yield* OrchestrationReactor;
@@ -50325,7 +50373,7 @@ const make$81 = Effect.gen(function* () {
50325
50373
  enqueueCommand: commandGate.enqueueCommand
50326
50374
  };
50327
50375
  });
50328
- const layer$71 = Layer.effect(ServerRuntimeStartup, make$81);
50376
+ const layer$71 = Layer.effect(ServerRuntimeStartup, make$83);
50329
50377
  //#endregion
50330
50378
  //#region src/serverRuntimeState.ts
50331
50379
  const PersistedServerRuntimeState = Schema$1.Struct({
@@ -50482,7 +50530,7 @@ function expandHomePath$2(input, path) {
50482
50530
  if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
50483
50531
  return input;
50484
50532
  }
50485
- const make$80 = Effect.gen(function* () {
50533
+ const make$82 = Effect.gen(function* () {
50486
50534
  const fileSystem = yield* FileSystem.FileSystem;
50487
50535
  const path = yield* Path$1.Path;
50488
50536
  const statWorkspaceRoot = Effect.fn("WorkspacePaths.statWorkspaceRoot")(function* (workspaceRoot, normalizedWorkspaceRoot, phase) {
@@ -50539,7 +50587,7 @@ const make$80 = Effect.gen(function* () {
50539
50587
  resolveRelativePathWithinRoot
50540
50588
  });
50541
50589
  });
50542
- const layer$70 = Layer.effect(WorkspacePaths, make$80);
50590
+ const layer$70 = Layer.effect(WorkspacePaths, make$82);
50543
50591
  //#endregion
50544
50592
  //#region src/cli/project.ts
50545
50593
  const isEnvironmentHttpCommonError = Schema$1.is(EnvironmentHttpCommonError);
@@ -54463,7 +54511,7 @@ const makeTerminationError$1 = (handle) => Effect.match(handle.exitCode, {
54463
54511
  //#region ../../packages/effect-acp/src/client.ts
54464
54512
  const MAX_STDERR_CALLBACK_CHARS = 32768;
54465
54513
  var AcpClient = class extends Context.Service()("effect-acp/client/AcpClient") {};
54466
- const make$79 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options = {}, terminationError) {
54514
+ const make$81 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options = {}, terminationError) {
54467
54515
  const coreHandlers = {};
54468
54516
  const notificationHandlers = {
54469
54517
  sessionUpdate: {
@@ -54630,7 +54678,7 @@ const layerChildProcess$1 = (handle, options = {}) => {
54630
54678
  })), Stream.drain)) : stdout
54631
54679
  };
54632
54680
  const terminationError = makeTerminationError$1(handle);
54633
- return Layer.effect(AcpClient, make$79(stdio, options, terminationError));
54681
+ return Layer.effect(AcpClient, make$81(stdio, options, terminationError));
54634
54682
  };
54635
54683
  //#endregion
54636
54684
  //#region src/provider/Drivers/AntigravitySkills.ts
@@ -55909,7 +55957,7 @@ const Reply = Schema$1.Struct({
55909
55957
  id: Schema$1.String,
55910
55958
  result: Schema$1.Struct({ ok: Schema$1.Boolean })
55911
55959
  });
55912
- const make$78 = Effect.fn("DeviceCommandProxy.make")(function* () {
55960
+ const make$80 = Effect.fn("DeviceCommandProxy.make")(function* () {
55913
55961
  const http = yield* HttpClient.HttpClient;
55914
55962
  const daemonSessions = /* @__PURE__ */ new WeakMap();
55915
55963
  return Effect.fn("DeviceCommandProxy.execute")(function* (endpoint, session, payload) {
@@ -55962,7 +56010,7 @@ const make$78 = Effect.fn("DeviceCommandProxy.make")(function* () {
55962
56010
  })));
55963
56011
  });
55964
56012
  var DeviceCommandProxy = class extends Context.Service()("@p4code/cli/device/DeviceCommandProxy") {};
55965
- const layer$69 = Layer.effect(DeviceCommandProxy, make$78().pipe(Effect.map((execute) => ({ execute }))));
56013
+ const layer$69 = Layer.effect(DeviceCommandProxy, make$80().pipe(Effect.map((execute) => ({ execute }))));
55966
56014
  //#endregion
55967
56015
  //#region src/device/DeviceHubRoute.ts
55968
56016
  const DEVICE_HUB_PROXY_PREFIX = "/api/device-hub";
@@ -58311,7 +58359,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
58311
58359
  filePath: error.filePath,
58312
58360
  errorTag: error._tag
58313
58361
  }));
58314
- const make$77 = Effect.gen(function* () {
58362
+ const make$79 = Effect.gen(function* () {
58315
58363
  const fileSystem = yield* FileSystem.FileSystem;
58316
58364
  const path = yield* Path$1.Path;
58317
58365
  const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
@@ -58332,7 +58380,7 @@ const make$77 = Effect.gen(function* () {
58332
58380
  });
58333
58381
  return P4ProjectFileLoader.of({ load });
58334
58382
  });
58335
- const layer$66 = Layer.effect(P4ProjectFileLoader, make$77);
58383
+ const layer$66 = Layer.effect(P4ProjectFileLoader, make$79);
58336
58384
  //#endregion
58337
58385
  //#region src/project/ProjectFaviconResolver.ts
58338
58386
  /**
@@ -58407,7 +58455,7 @@ function extractIconHref(source) {
58407
58455
  return null;
58408
58456
  }
58409
58457
  const optionOnNotFound$1 = (effect) => effect.pipe(Effect.map(Option.some), Effect.catchTags({ PlatformError: (error) => error.reason._tag === "NotFound" ? Effect.succeed(Option.none()) : Effect.fail(error) }));
58410
- const make$76 = Effect.gen(function* () {
58458
+ const make$78 = Effect.gen(function* () {
58411
58459
  const fileSystem = yield* FileSystem.FileSystem;
58412
58460
  const path = yield* Path$1.Path;
58413
58461
  const workspacePaths = yield* WorkspacePaths;
@@ -58476,7 +58524,7 @@ const make$76 = Effect.gen(function* () {
58476
58524
  });
58477
58525
  return ProjectFaviconResolver.of({ resolvePath });
58478
58526
  });
58479
- const layer$65 = Layer.effect(ProjectFaviconResolver, make$76);
58527
+ const layer$65 = Layer.effect(ProjectFaviconResolver, make$78);
58480
58528
  //#endregion
58481
58529
  //#region src/assets/AssetAccess.ts
58482
58530
  const ASSET_ROUTE_PREFIX = "/api/assets";
@@ -58887,10 +58935,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
58887
58935
  //#endregion
58888
58936
  //#region src/observability/BrowserTraceCollector.ts
58889
58937
  var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
58890
- const make$75 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
58938
+ const make$77 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
58891
58939
  for (const record of records) sink.push(record);
58892
58940
  }) });
58893
- const layer$64 = (sink) => Layer.succeed(BrowserTraceCollector, make$75(sink));
58941
+ const layer$64 = (sink) => Layer.succeed(BrowserTraceCollector, make$77(sink));
58894
58942
  //#endregion
58895
58943
  //#region src/auth/http.ts
58896
58944
  const CREDENTIAL_RESPONSE_HEADERS = {
@@ -59303,6 +59351,17 @@ function isAutoCheckoutBusy(input) {
59303
59351
  return thread.latestTurn?.state === "running" || thread.session?.status === "starting" || thread.session?.status === "running";
59304
59352
  });
59305
59353
  }
59354
+ /** The brief every advisor gets; Jev reads it as instructions, the model as a question. */
59355
+ const AUTO_WORKSPACE_QUESTION_LINES = (hasWorkingTreeChanges) => [
59356
+ "Choose the workspace for this task before its coding agent starts.",
59357
+ "Return exactly local or worktree in the answer field. Do not perform the task.",
59358
+ "No other P4 agent is currently working in this checkout.",
59359
+ `Uncommitted changes are ${hasWorkingTreeChanges ? "present" : "absent"}.`,
59360
+ "Prefer local for questions, investigation, small focused edits, and work that needs current uncommitted changes.",
59361
+ "Prefer worktree for independent implementation, broad changes, risky experiments, or possible interference with someone else's edits.",
59362
+ "A new worktree starts from the selected base branch; uncommitted files are not copied.",
59363
+ "Honor an explicit workspace preference in the task. Preserve unrelated changes. If uncertain, choose worktree."
59364
+ ];
59306
59365
  const BUSY_CHECKOUT_DECISION = {
59307
59366
  mode: "worktree",
59308
59367
  reason: "Another agent is working in the current checkout."
@@ -59311,27 +59370,23 @@ const UNAVAILABLE_DECISION = {
59311
59370
  mode: "worktree",
59312
59371
  reason: "The agent could not choose a workspace; using an isolated worktree."
59313
59372
  };
59314
- const chooseAutoWorkspace = Effect.fn("chooseAutoWorkspace")(function* (input, textGeneration) {
59373
+ const chooseAutoWorkspace = Effect.fn("chooseAutoWorkspace")(function* (input, textGeneration, advisor) {
59315
59374
  if (!input.isRepo) return {
59316
59375
  mode: "local",
59317
59376
  reason: "This project has no Git repository."
59318
59377
  };
59319
59378
  if (input.busy) return BUSY_CHECKOUT_DECISION;
59379
+ const advised = advisor ? yield* advisor.chooseWorkspace({
59380
+ message: input.message,
59381
+ hasWorkingTreeChanges: input.hasWorkingTreeChanges
59382
+ }) : void 0;
59383
+ if (advised) return advised;
59320
59384
  if (!textGeneration.generateBtwAnswer || !input.modelSelection) return UNAVAILABLE_DECISION;
59321
59385
  return yield* textGeneration.generateBtwAnswer({
59322
59386
  cwd: input.cwd,
59323
59387
  modelSelection: input.modelSelection,
59324
59388
  context: input.message,
59325
- question: [
59326
- "Choose the workspace for this task before its coding agent starts.",
59327
- "Return exactly local or worktree in the answer field. Do not perform the task.",
59328
- "No other P4 agent is currently working in this checkout.",
59329
- `Uncommitted changes are ${input.hasWorkingTreeChanges ? "present" : "absent"}.`,
59330
- "Prefer local for questions, investigation, small focused edits, and work that needs current uncommitted changes.",
59331
- "Prefer worktree for independent implementation, broad changes, risky experiments, or possible interference with someone else's edits.",
59332
- "A new worktree starts from the selected base branch; uncommitted files are not copied.",
59333
- "Honor an explicit workspace preference in the task. Preserve unrelated changes. If uncertain, choose worktree."
59334
- ].join("\n")
59389
+ question: AUTO_WORKSPACE_QUESTION_LINES(input.hasWorkingTreeChanges).join("\n")
59335
59390
  }).pipe(Effect.timeout(AUTO_WORKSPACE_DECISION_TIMEOUT), Effect.map(({ answer }) => {
59336
59391
  const mode = answer.trim().toLowerCase();
59337
59392
  if (mode === "local") return {
@@ -59504,7 +59559,20 @@ const FUSION_PAIR_COMMUNICATION_INSTRUCTIONS = `Everything you send the other ha
59504
59559
  * enforces into one it merely suggests.
59505
59560
  */
59506
59561
  const FUSION_TOOL_BOUNDARY_INSTRUCTIONS = `A tool missing from your role, or a call the server denies for want of a capability or a grant, is a limit to report rather than an obstacle to route around. Never substitute the server's own database, its HTTP API, another MCP server, or any other back channel for a capability you were not granted; say which tool or grant you lacked and what you would have done with it.`;
59507
- const FUSION_BUILDER_INSTRUCTIONS = `You are Fusion Builder in an already-created native server pair. Server owns pairing and coordination. Follow the current turn's [fusion-review-policy] block when present; it overrides the phase-boundary scheduling rules below. Do not inspect or invoke the Fusion skill, create/pair/rename threads, or announce/setup Fusion. Start the user's task directly. The phase plan is not yours: Supervisor authors it, orders it, and moves every phase status, and it renders in your task banner from there. Never create or edit a phase list yourself - not with TaskCreate, TaskUpdate, TodoWrite, update_plan, the MCP task board tools, or thread_plan_update - and never mark your own phase complete. Work the one phase Supervisor put in progress, and report what you did. Step-level notes for your own use are fine as long as they never become a phase list. Complete exactly one phase per turn, and finish the whole phase in that turn rather than stopping early. Do not run tests, typecheck, lint, or builds per phase; write the tests the change needs, then run verification once in the final phase over the whole task. Exception: a phase whose own correctness is unclear may run the single narrowest check that resolves it. End every phase turn with a report of at most six non-empty lines: the phase you finished, what changed and where, what you verified with its result, and anything unresolved. One line each, every fact once, no restatement of the plan or of advice you were given. Code, exact error text and security warnings are exempt from the cap. Do not start the next phase in the same turn. Server then wakes the paired Supervisor, which resumes you through ${FUSION_ADVICE_PROMPT_PREFIX}; a user message may also revise or resume the work. Final phase verifies the entire task against the original request and labels it ready for whole-task review. Supervisor is unreachable during your turn. Never spawn/use another Supervisor thread/subagent or attribute Supervisor decisions without ${FUSION_ADVICE_PROMPT_PREFIX}. Within the current phase, continue when straightforward or evidence is clear. For a concrete unresolved tradeoff, correctness risk, or design decision materially needing judgment, stop safely before the risky choice; final response states the exact question and why review is needed. Evaluate/follow Supervisor advice unless conflicting with user request or verified repo state. The review tools are Supervisor's half of the pair, not yours: thread_watch_review, thread_watch_events and thread_evidence_report are its tools, and a thread outside this pair is not yours to read. Your provider may still list them; that is not a grant, and every call fails. The tracker is Supervisor's too: you neither read nor write tickets, so when the work needs one filed, commented, or moved, say so in your phase report and let Supervisor carry it. ${FUSION_TOOL_BOUNDARY_INSTRUCTIONS} ${FUSION_PAIR_COMMUNICATION_INSTRUCTIONS}`;
59562
+ /**
59563
+ * What a role does when the user asks it, in person, for the other half's work.
59564
+ *
59565
+ * Distinct from the tool boundary above: there the role wants a capability and
59566
+ * is told to report the limit, while here the user wants something and the
59567
+ * quiet handover is the failure. A builder that silently parks a tracker
59568
+ * request in its phase report, or a supervisor that silently forwards an
59569
+ * implementation request through thread_advise, answers a question the user
59570
+ * never asked - they may have addressed the wrong half, or may want that half
59571
+ * to say plainly that it cannot. Confirmation costs one turn; a misrouted
59572
+ * instruction costs the work done under it.
59573
+ */
59574
+ const FUSION_OUT_OF_ROLE_REQUEST_INSTRUCTIONS = `A request the user addresses to you that your role does not own is neither yours to perform nor yours to hand to the other half on your own initiative. Name the capability you lack and the half that owns it, ask the user whether they meant it to go there, and end the turn without acting; carry it across only once they confirm. This governs an instruction aimed at you, not a need your own work turned up - something the task itself raised still travels its normal path. A user who already named the other half, or whose instruction only the other half could have been meant for, has confirmed it; do not ask again.`;
59575
+ const FUSION_BUILDER_INSTRUCTIONS = `You are Fusion Builder in an already-created native server pair. Server owns pairing and coordination. Follow the current turn's [fusion-review-policy] block when present; it overrides the phase-boundary scheduling rules below. Do not inspect or invoke the Fusion skill, create/pair/rename threads, or announce/setup Fusion. Start the user's task directly. The phase plan is not yours: Supervisor authors it, orders it, and moves every phase status, and it renders in your task banner from there. Never create or edit a phase list yourself - not with TaskCreate, TaskUpdate, TodoWrite, update_plan, the MCP task board tools, or thread_plan_update - and never mark your own phase complete. Work the one phase Supervisor put in progress, and report what you did. Step-level notes for your own use are fine as long as they never become a phase list. Complete exactly one phase per turn, and finish the whole phase in that turn rather than stopping early. Do not run tests, typecheck, lint, or builds per phase; write the tests the change needs, then run verification once in the final phase over the whole task. Exception: a phase whose own correctness is unclear may run the single narrowest check that resolves it. End every phase turn with a report of at most six non-empty lines: the phase you finished, what changed and where, what you verified with its result, and anything unresolved. One line each, every fact once, no restatement of the plan or of advice you were given. Code, exact error text and security warnings are exempt from the cap. Do not start the next phase in the same turn. Server then wakes the paired Supervisor, which resumes you through ${FUSION_ADVICE_PROMPT_PREFIX}; a user message may also revise or resume the work. Final phase verifies the entire task against the original request and labels it ready for whole-task review. Supervisor is unreachable during your turn. Never spawn/use another Supervisor thread/subagent or attribute Supervisor decisions without ${FUSION_ADVICE_PROMPT_PREFIX}. Within the current phase, continue when straightforward or evidence is clear. For a concrete unresolved tradeoff, correctness risk, or design decision materially needing judgment, stop safely before the risky choice; final response states the exact question and why review is needed. Evaluate/follow Supervisor advice unless conflicting with user request or verified repo state. The review tools are Supervisor's half of the pair, not yours: thread_watch_review, thread_watch_events and thread_evidence_report are its tools, and a thread outside this pair is not yours to read. Your provider may still list them; that is not a grant, and every call fails. The tracker is Supervisor's too: you neither read nor write tickets, so when the work needs one filed, commented, or moved, say so in your phase report and let Supervisor carry it. ${FUSION_OUT_OF_ROLE_REQUEST_INSTRUCTIONS} ${FUSION_TOOL_BOUNDARY_INSTRUCTIONS} ${FUSION_PAIR_COMMUNICATION_INSTRUCTIONS}`;
59508
59576
  const FUSION_WATCHER_TOOL_INSTRUCTIONS = `Supervisor tools belong to the p4-code MCP server: thread_watch_review, thread_watch_events, thread_evidence_report, thread_plan_update, thread_advise, thread_gate_respond, and the task board tools task_current, task_get, task_list, task_create and task_update. Read the board whenever planning needs it, and read a named ticket with ticket_resolve together with its comments, treating a later comment as newer intent than the description. Resolve which task that is by calling task_current with the builder's threadId, because a pair started from the board links the row to the builder and not to you; a bare task_current answers for your own thread and reports the task as unlinked. Write only within that task: update it or a subtask you created under it, never an unrelated row, never another project's board, and never any board but this one - task_create files a real ticket on an external tracker when given a source such as 'linear', and that is not yours to file. If absent from the visible tool list, first use the available tool search/discovery facility to load those exact tools, including provider-prefixed names; absence from the initial list does not establish unavailability. If discovery or a call fails, report the exact missing capability or error and the need to restore the p4-code MCP connection. Do not offer manual relay, draft or implement the task yourself, or abandon the supervisor role as a workaround. For an actionable user requirement, read the relevant builder evidence and relay it through thread_advise; when a gate is open, answer through thread_gate_respond instead. Structure every actionable supervisor advice message with these Markdown headings, in order:
59509
59577
  ## Recommendation
59510
59578
  State the decision or correction in one sentence. For a phase review, say whether the phase is approved or needs changes.
@@ -59520,7 +59588,7 @@ Give ordered, concrete actions for the builder, including the next phase and its
59520
59588
  * which is what it did before this existed.
59521
59589
  */
59522
59590
  const FUSION_EVIDENCE_SUMMARY_INSTRUCTIONS = `Read the builder's evidence through a summarizer subagent rather than into your own context: spawn one subagent with the evidence range and have it call thread_watch_review itself, paging with nextAfterSequence against a fixed throughSequence until hasMore is false, and return a summary. Your tool grants reach it, so it can read the paired builder thread exactly as you can. Instruct that subagent that thread_watch_review and thread_watch_events may be absent from its visible tool list and that absence does not establish unavailability: it must first use the available tool search/discovery facility to load those exact tools by name, including provider-prefixed names, and if discovery itself fails it must report that exact error rather than reporting no such tool. Require of that summary: every file path touched with the scale of the change to each, every command run and whether it succeeded or failed, check and test results with their counts, exact error text quoted rather than characterized, the builder's completion claims marked as claims, and anything the builder flagged as uncertain, blocked or unresolved. Over a multi-turn range it must also carry unresolved objections of yours and whether each was answered, phases completed versus reopened, claims never verified, and files touched repeatedly. Every statement cites the sequences behind it so you can check any one of them with a targeted thread_watch_events read. Fail open: if no subagent is available, the spawn errors, it times out, or what comes back is empty or does not cite sequences, read the range yourself and review from the raw evidence. Never skip or shorten a review because a summary was unavailable. Record which fallback you took: a subagent that could not load the watch tools is a misconfiguration worth naming in your report, and it is not the same as a spawn that errored or timed out. Then close the review by calling thread_evidence_report exactly once, after the last page: pass the watched thread id, the same fixed throughSequence the first review page returned - not lastSequence and not the final page's nextAfterSequence, because the server pairs the report to the read by that exact number - the first and last sequence you actually covered, the model you spawned on, and outcome summarized with the subagent's exact returned text, fallback when you read the raw range yourself, or failed when the summarizer could not run or could not report - with the reason in your own words for the last two. Report even when the summary never arrived; a review with no report cannot be told apart from a supervisor that never tried. Never paste builder tool output into it.`;
59523
- const FUSION_WATCHER_INSTRUCTIONS = `You are Fusion Supervisor (watcher) in an already-created native server pair. Follow the current turn's [fusion-review-policy] block when present; it overrides phase scheduling. Server owns pairing and coordination and wakes you with ${FUSION_REVIEW_PROMPT_PREFIX} or ${FUSION_GATE_PROMPT_PREFIX} prompts at builder turn boundaries. A plain message outside such a wake may arrive after your conversational memory of the pair is gone; its [fusion-pair] metadata block is authoritative: the builder thread exists and is the counterpart thread id. Never report that no builder thread exists. For a new pair, the initial user request is yours, and its first turn is research, not relay. Research it: when the request names a ticket, read that ticket AND its comments, including replies and inline comments, and treat a later comment as newer intent than the description; read the code, docs, project instructions, and current state the request touches. Analyse what you found: root cause or the concrete design constraint, scope, what the user actually wants delivered, and which delivery steps they authorized. Only then write the phase plan and direct its first phase. The plan is yours alone: call thread_plan_update with the builder's threadId, sending the complete ordered list every time, each phase named in 3-6 words by its outcome rather than by a command, file path, or flag, with exactly one in progress. Split it into the fewest substantial phases the task genuinely needs plus a final integration/whole-task phase; most tasks need one to three work phases, each a complete reviewable slice of behavior. Never split per file, per function, or per trivial step. State each phase's completion condition to the builder in the advice, not in the banner title. On every later review, rewrite the same plan: an approved phase becomes completed and the next becomes in progress in the same call, an objection leaves the current phase in progress or reopens a phase you had marked completed, and the final approval completes the last phase. The builder never touches it, so a phase you do not move stays where it is. Then direct the phase to the idle builder through thread_advise, stating the findings that make the direction actionable alongside the original requirements, constraints, and authorized delivery scope. Never echo the request back as its own direction, never hand over a plan you did not ground in evidence, and never send ${FUSION_NO_OBJECTION_TEXT} before the builder has received its first phase and produced a turn to review. The builder has not received the initial prompt and must not start before your direction. Missing builder turn evidence is expected before that first direction; do not wait for it or implement the work yourself. Ask the user only when needed to resolve a blocking requirement. ${FUSION_WATCHER_TOOL_INSTRUCTIONS} To resume supervision, read builder evidence with thread_watch_review from lastReviewedImplementerSequence, capture its throughSequence on the first page and reuse that fixed bound while paging with nextAfterSequence until hasMore is false (including empty pages). Apply message append/replace operations by identity; recover truncated evidence through targeted raw thread_watch_events source ranges. Retain reviewed requirements and evidence for final review; recover missing context with targeted history reads rather than mandatory raw replay from zero, derive phase from artifacts (git log/status, PR, builder events, including its turn.plan.updated phase list), steer with thread_advise, and answer an open gate with thread_gate_respond. When a review or gate wake prompt specifies an explicit event range, that range wins over this metadata. Never poll or wait for the builder; deliver review or advice, then end the turn. Every thread_advise starts a builder turn whose completion wakes you again, so never advise a builder that is idle on an external wait or has nothing actionable; report the state in your own thread and end without advising. ${FUSION_TOOL_BOUNDARY_INSTRUCTIONS} ${FUSION_PAIR_COMMUNICATION_INSTRUCTIONS}`;
59591
+ const FUSION_WATCHER_INSTRUCTIONS = `You are Fusion Supervisor (watcher) in an already-created native server pair. Follow the current turn's [fusion-review-policy] block when present; it overrides phase scheduling. Server owns pairing and coordination and wakes you with ${FUSION_REVIEW_PROMPT_PREFIX} or ${FUSION_GATE_PROMPT_PREFIX} prompts at builder turn boundaries. A plain message outside such a wake may arrive after your conversational memory of the pair is gone; its [fusion-pair] metadata block is authoritative: the builder thread exists and is the counterpart thread id. Never report that no builder thread exists. For a new pair, the initial user request is yours, and its first turn is research, not relay. Research it: when the request names a ticket, read that ticket AND its comments, including replies and inline comments, and treat a later comment as newer intent than the description; read the code, docs, project instructions, and current state the request touches. Analyse what you found: root cause or the concrete design constraint, scope, what the user actually wants delivered, and which delivery steps they authorized. Only then write the phase plan and direct its first phase. The plan is yours alone: call thread_plan_update with the builder's threadId, sending the complete ordered list every time, each phase named in 3-6 words by its outcome rather than by a command, file path, or flag, with exactly one in progress. Split it into the fewest substantial phases the task genuinely needs plus a final integration/whole-task phase; most tasks need one to three work phases, each a complete reviewable slice of behavior. Never split per file, per function, or per trivial step. State each phase's completion condition to the builder in the advice, not in the banner title. On every later review, rewrite the same plan: an approved phase becomes completed and the next becomes in progress in the same call, an objection leaves the current phase in progress or reopens a phase you had marked completed, and the final approval completes the last phase. The builder never touches it, so a phase you do not move stays where it is. Then direct the phase to the idle builder through thread_advise, stating the findings that make the direction actionable alongside the original requirements, constraints, and authorized delivery scope. Never echo the request back as its own direction, never hand over a plan you did not ground in evidence, and never send ${FUSION_NO_OBJECTION_TEXT} before the builder has received its first phase and produced a turn to review. The builder has not received the initial prompt and must not start before your direction. Missing builder turn evidence is expected before that first direction; do not wait for it or implement the work yourself. Ask the user only when needed to resolve a blocking requirement. ${FUSION_WATCHER_TOOL_INSTRUCTIONS} To resume supervision, read builder evidence with thread_watch_review from lastReviewedImplementerSequence, capture its throughSequence on the first page and reuse that fixed bound while paging with nextAfterSequence until hasMore is false (including empty pages). Apply message append/replace operations by identity; recover truncated evidence through targeted raw thread_watch_events source ranges. Retain reviewed requirements and evidence for final review; recover missing context with targeted history reads rather than mandatory raw replay from zero, derive phase from artifacts (git log/status, PR, builder events, including its turn.plan.updated phase list), steer with thread_advise, and answer an open gate with thread_gate_respond. When a review or gate wake prompt specifies an explicit event range, that range wins over this metadata. Never poll or wait for the builder; deliver review or advice, then end the turn. Every thread_advise starts a builder turn whose completion wakes you again, so never advise a builder that is idle on an external wait or has nothing actionable; report the state in your own thread and end without advising. ${FUSION_OUT_OF_ROLE_REQUEST_INSTRUCTIONS} ${FUSION_TOOL_BOUNDARY_INSTRUCTIONS} ${FUSION_PAIR_COMMUNICATION_INSTRUCTIONS}`;
59524
59592
  /**
59525
59593
  * The one-line stand-in for the full block on a message whose session already
59526
59594
  * carries the role instructions.
@@ -59698,6 +59766,7 @@ const FUSION_SUPERVISOR_P4_TOOLS = /* @__PURE__ */ new Set([
59698
59766
  "thread_evidence_report",
59699
59767
  "thread_advise",
59700
59768
  "thread_gate_respond",
59769
+ "thread_pair_detach",
59701
59770
  "thread_plan_update",
59702
59771
  "ask_user_question",
59703
59772
  "task_current",
@@ -59720,13 +59789,9 @@ const FUSION_SUPERVISOR_P4_TOOLS = /* @__PURE__ */ new Set([
59720
59789
  * the review of the builder's own work, which is the supervisor watching the
59721
59790
  * builder and never the other way round.
59722
59791
  *
59723
- * `thread_pair_detach` is the one piece of pair machinery the builder keeps,
59724
- * because it is the way out of the arrangement rather than a way to do the
59725
- * supervisor's job. `thread_pair_detach`'s own handler already limits it to a
59726
- * pair whose implementer is the calling thread and whose supervisor that
59727
- * thread created, so the only pair a builder can end is one it made of itself.
59728
- * Denying it here would leave no agent able to detach any pair at all, which
59729
- * is the one-way door this repository treats as a bug.
59792
+ * Both roles retain `thread_pair_detach` as their way out. Its handler limits
59793
+ * detaching to a pair containing the caller whose other thread this session
59794
+ * created. The role policy exposes the action; the handler enforces ownership.
59730
59795
  */
59731
59796
  const FUSION_BUILDER_DENIED_P4_TOOLS = /* @__PURE__ */ new Set([
59732
59797
  "thread_spawn",
@@ -60505,7 +60570,7 @@ const defaultCancelTimeout = Duration.seconds(15);
60505
60570
  const defaultSessionLoadTimeout = Duration.seconds(90);
60506
60571
  const defaultSessionLoadReplayIdleGap = Duration.seconds(2);
60507
60572
  var AcpSessionRuntime = class extends Context.Service()("@p4code/cli/provider/acp/AcpSessionRuntime") {};
60508
- const make$74 = (options) => Effect.gen(function* () {
60573
+ const make$76 = (options) => Effect.gen(function* () {
60509
60574
  const crypto = yield* Crypto.Crypto;
60510
60575
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
60511
60576
  const runtimeScope = yield* Scope.Scope;
@@ -60909,7 +60974,7 @@ const make$74 = (options) => Effect.gen(function* () {
60909
60974
  notify: acp.raw.notify
60910
60975
  };
60911
60976
  });
60912
- const layer$63 = (options) => Layer.effect(AcpSessionRuntime, make$74(options));
60977
+ const layer$63 = (options) => Layer.effect(AcpSessionRuntime, make$76(options));
60913
60978
  function sessionConfigOptionsFromSetup(response) {
60914
60979
  return response?.configOptions ?? [];
60915
60980
  }
@@ -65367,7 +65432,7 @@ const BundledOnlyModelManifest = {
65367
65432
  refreshInBackground: Effect.void
65368
65433
  };
65369
65434
  Layer.succeed(ModelManifest, BundledOnlyModelManifest);
65370
- const make$73 = Effect.gen(function* () {
65435
+ const make$75 = Effect.gen(function* () {
65371
65436
  const fileSystem = yield* FileSystem.FileSystem;
65372
65437
  const path = yield* Path$1.Path;
65373
65438
  const config = yield* ServerConfig$1;
@@ -65412,7 +65477,7 @@ const make$73 = Effect.gen(function* () {
65412
65477
  refreshInBackground: Effect.forkIn(guardedRefresh, serviceScope).pipe(Effect.asVoid)
65413
65478
  });
65414
65479
  });
65415
- const layer$62 = Layer.effect(ModelManifest, make$73);
65480
+ const layer$62 = Layer.effect(ModelManifest, make$75);
65416
65481
  //#endregion
65417
65482
  //#region src/provider/ProviderDriver.ts
65418
65483
  function defaultProviderContinuationIdentity(input) {
@@ -65678,11 +65743,11 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
65678
65743
  detail: "This provider does not report account usage."
65679
65744
  }))))
65680
65745
  });
65681
- const make$72 = Effect.gen(function* () {
65746
+ const make$74 = Effect.gen(function* () {
65682
65747
  const registry = yield* ProviderInstanceRegistry;
65683
65748
  return makeTextGenerationFromRegistry(registry);
65684
65749
  });
65685
- const layer$61 = Layer.effect(TextGeneration, make$72);
65750
+ const layer$61 = Layer.effect(TextGeneration, make$74);
65686
65751
  //#endregion
65687
65752
  //#region src/provider/Layers/claudeUsageLimits.ts
65688
65753
  const SESSION_MINS$1 = 300;
@@ -88651,7 +88716,7 @@ const makeTerminationError = (handle) => Effect.match(handle.exitCode, {
88651
88716
  //#endregion
88652
88717
  //#region ../../packages/effect-codex-app-server/src/client.ts
88653
88718
  var CodexAppServerClient = class extends Context.Service()("effect-codex-app-server/client/CodexAppServerClient") {};
88654
- const make$71 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
88719
+ const make$73 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
88655
88720
  const requestHandlers = /* @__PURE__ */ new Map();
88656
88721
  const notificationHandlers = /* @__PURE__ */ new Map();
88657
88722
  let unknownRequestHandler;
@@ -88718,7 +88783,7 @@ const make$71 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(f
88718
88783
  const layerChildProcess = (handle, options = {}) => Layer.effect(CodexAppServerClient, makeChildProcessClient(handle, options));
88719
88784
  const makeChildProcessClient = Effect.fn("effect-codex-app-server/CodexAppServerClient.makeChildProcessClient")(function* (handle, options) {
88720
88785
  yield* Stream.runDrain(handle.stderr).pipe(Effect.ignore, Effect.forkScoped);
88721
- return yield* make$71(makeChildStdio(handle), options, makeTerminationError(handle));
88786
+ return yield* make$73(makeChildStdio(handle), options, makeTerminationError(handle));
88722
88787
  });
88723
88788
  const resolveCodexLaunchArgs = (launchArgs, environment = process.env) => environment["P4CODE_CODEX_LAUNCH_ARGS"]?.trim() || launchArgs?.trim() || "";
88724
88789
  const codexLaunchArgv = (launchArgs) => tokenizeCliArgs(launchArgs);
@@ -95877,7 +95942,7 @@ function mapMuseExecRecord(input) {
95877
95942
  const toolName = state.toolNameByTaskId.get(taskId);
95878
95943
  state.settledToolTaskIds.add(taskId);
95879
95944
  const failed = stringField$1(recordField(payload, "correlation_facts"), "outcome") === "error";
95880
- const detail = truncate(stringField$1(payload, "text"), MAX_TOOL_DETAIL_CHARS);
95945
+ const detail = truncate$1(stringField$1(payload, "text"), MAX_TOOL_DETAIL_CHARS);
95881
95946
  const editFacts = recordField(payload, "edit_facts");
95882
95947
  return [(stamp) => ({
95883
95948
  type: "item.completed",
@@ -95901,7 +95966,7 @@ function mapMuseExecRecord(input) {
95901
95966
  const toolName = state.toolNameByTaskId.get(taskId);
95902
95967
  if (!toolName || state.settledToolTaskIds.has(taskId)) return [];
95903
95968
  state.settledToolTaskIds.add(taskId);
95904
- const detail = truncate(stringField$1(event, "reason"), MAX_TOOL_DETAIL_CHARS);
95969
+ const detail = truncate$1(stringField$1(event, "reason"), MAX_TOOL_DETAIL_CHARS);
95905
95970
  return [(stamp) => ({
95906
95971
  type: "item.completed",
95907
95972
  ...stamp,
@@ -96078,7 +96143,7 @@ function recordField(source, key) {
96078
96143
  function eventField(payload) {
96079
96144
  return recordField(payload, "event");
96080
96145
  }
96081
- function truncate(value, max) {
96146
+ function truncate$1(value, max) {
96082
96147
  if (value === void 0) return void 0;
96083
96148
  const trimmed = value.trim();
96084
96149
  if (trimmed.length === 0) return void 0;
@@ -100479,8 +100544,8 @@ const makeWithReader = (api) => Effect.gen(function* () {
100479
100544
  }))
100480
100545
  };
100481
100546
  });
100482
- const make$70 = makeCliproxyApi.pipe(Effect.flatMap(makeWithReader));
100483
- const layer$60 = Layer.effect(UsageLimitSources, make$70);
100547
+ const make$72 = makeCliproxyApi.pipe(Effect.flatMap(makeWithReader));
100548
+ const layer$60 = Layer.effect(UsageLimitSources, make$72);
100484
100549
  //#endregion
100485
100550
  //#region src/resourceTelemetry/HostResources.ts
100486
100551
  const CPU_SAMPLE_INTERVAL = "200 millis";
@@ -100515,7 +100580,7 @@ function darwinAvailableMemory(output) {
100515
100580
  const available = (Number(free) + Number(inactive) + Number(speculative)) * Number(pageSize);
100516
100581
  return Number.isSafeInteger(available) && Number(pageSize) > 0 ? available : null;
100517
100582
  }
100518
- const make$69 = Effect.fn("makeHostResources")(function* () {
100583
+ const make$71 = Effect.fn("makeHostResources")(function* () {
100519
100584
  const fs = yield* FileSystem.FileSystem;
100520
100585
  const platform = yield* HostProcessPlatform;
100521
100586
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
@@ -100549,7 +100614,7 @@ const make$69 = Effect.fn("makeHostResources")(function* () {
100549
100614
  });
100550
100615
  return HostResources.of({ read: Cache.get(cache, "host") });
100551
100616
  });
100552
- const layer$59 = Layer.effect(HostResources, make$69());
100617
+ const layer$59 = Layer.effect(HostResources, make$71());
100553
100618
  //#endregion
100554
100619
  //#region src/resourceTelemetry/DesktopTelemetryReceiver.ts
100555
100620
  const INITIAL_SAMPLE_DEADLINE_MS = 9e4;
@@ -100684,7 +100749,7 @@ function requireDesktopTelemetryWriteProgress(fd, remainingBytes, written) {
100684
100749
  }));
100685
100750
  }
100686
100751
  /** @public Service construction is part of the canonical Effect module API. */
100687
- const make$68 = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(function* () {
100752
+ const make$70 = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(function* () {
100688
100753
  const serverConfig = yield* ServerConfig$1;
100689
100754
  const hasDescriptors = serverConfig.mode === "desktop" && serverConfig.desktopTelemetryFd === 4 && serverConfig.desktopTelemetryControlFd === 5;
100690
100755
  const config = {
@@ -100841,7 +100906,7 @@ const make$68 = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(fun
100841
100906
  setDiagnosticsDemand
100842
100907
  });
100843
100908
  });
100844
- const layer$58 = Layer.effect(DesktopTelemetryReceiver, make$68());
100909
+ const layer$58 = Layer.effect(DesktopTelemetryReceiver, make$70());
100845
100910
  //#endregion
100846
100911
  //#region src/resourceTelemetry/Model.ts
100847
100912
  const MAX_DELTA_INTERVAL_MS = 3e4;
@@ -101266,7 +101331,7 @@ function resourceMonitorRustTarget(platform, architecture, linuxLibc) {
101266
101331
  }
101267
101332
  if (platform === "win32") return architecture === "arm64" ? "aarch64-pc-windows-msvc" : architecture === "x64" ? "x86_64-pc-windows-msvc" : void 0;
101268
101333
  }
101269
- const make$67 = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(function* () {
101334
+ const make$69 = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(function* () {
101270
101335
  const fileSystem = yield* FileSystem.FileSystem;
101271
101336
  const path = yield* Path$1.Path;
101272
101337
  const platform = yield* HostProcessPlatform;
@@ -101312,7 +101377,7 @@ const make$67 = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(functi
101312
101377
  });
101313
101378
  return ResourceMonitorBinary.of({ resolve });
101314
101379
  });
101315
- const layer$57 = Layer.effect(ResourceMonitorBinary, make$67());
101380
+ const layer$57 = Layer.effect(ResourceMonitorBinary, make$69());
101316
101381
  //#endregion
101317
101382
  //#region src/resourceTelemetry/NativeTelemetryClient.ts
101318
101383
  const SAMPLE_INTERVAL_MS$1 = 1e3;
@@ -101462,7 +101527,7 @@ function canCommandNativeTelemetrySidecar(status, hasHandle) {
101462
101527
  return hasHandle && (status === "healthy" || status === "degraded");
101463
101528
  }
101464
101529
  /** @public Service construction is part of the canonical Effect module API. */
101465
- const make$66 = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(function* () {
101530
+ const make$68 = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(function* () {
101466
101531
  const binary = yield* ResourceMonitorBinary;
101467
101532
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
101468
101533
  const crypto = yield* Crypto.Crypto;
@@ -101873,7 +101938,7 @@ const make$66 = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(functi
101873
101938
  })
101874
101939
  });
101875
101940
  });
101876
- const layer$56 = Layer.effect(NativeTelemetryClient, make$66());
101941
+ const layer$56 = Layer.effect(NativeTelemetryClient, make$68());
101877
101942
  //#endregion
101878
101943
  //#region src/resourceTelemetry/ResourceAttribution.ts
101879
101944
  var ResourceAttribution = class extends Context.Service()("@p4code/cli/resourceTelemetry/ResourceAttribution") {};
@@ -101885,7 +101950,7 @@ function nonNegativeInteger(value, fallback) {
101885
101950
  if (!Number.isFinite(value)) return 0;
101886
101951
  return Math.max(0, Math.round(value));
101887
101952
  }
101888
- const make$65 = Effect.fn("resourceTelemetry.resourceAttribution.make")(function* () {
101953
+ const make$67 = Effect.fn("resourceTelemetry.resourceAttribution.make")(function* () {
101889
101954
  const entries = yield* Ref.make(/* @__PURE__ */ new Map());
101890
101955
  const record = (input) => Ref.update(entries, (current) => {
101891
101956
  const next = new Map(current);
@@ -101911,7 +101976,7 @@ const make$65 = Effect.fn("resourceTelemetry.resourceAttribution.make")(function
101911
101976
  })
101912
101977
  });
101913
101978
  });
101914
- const layer$55 = Layer.effect(ResourceAttribution, make$65());
101979
+ const layer$55 = Layer.effect(ResourceAttribution, make$67());
101915
101980
  //#endregion
101916
101981
  //#region src/resourceTelemetry/ResourceTelemetryHistory.ts
101917
101982
  const MAX_HISTORY_WINDOW_MS = 60 * 6e4;
@@ -102134,7 +102199,7 @@ function buildHealth(input) {
102134
102199
  };
102135
102200
  }
102136
102201
  /** @public Service construction is part of the canonical Effect module API. */
102137
- const make$64 = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function* () {
102202
+ const make$66 = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function* () {
102138
102203
  const nativeClient = yield* NativeTelemetryClient;
102139
102204
  const desktopReceiver = yield* DesktopTelemetryReceiver;
102140
102205
  const attribution = yield* ResourceAttribution;
@@ -102386,7 +102451,7 @@ const make$64 = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function*
102386
102451
  })))
102387
102452
  });
102388
102453
  });
102389
- const layer$54 = Layer.effect(ResourceTelemetry, make$64());
102454
+ const layer$54 = Layer.effect(ResourceTelemetry, make$66());
102390
102455
  //#endregion
102391
102456
  //#region src/device/DeviceInspection.ts
102392
102457
  const READ_TIMEOUT_MS = 1e4;
@@ -105541,7 +105606,7 @@ const classifyNonZeroExit = (command, stderr) => {
105541
105606
  if (command === "gh" && (normalized.includes("could not resolve to a pullrequest") || normalized.includes("repository.pullrequest") || normalized.includes("no pull requests found for branch") || normalized.includes("pull request not found")) || command === "glab" && (normalized.includes("merge request not found") || normalized.includes("not found") || normalized.includes("404")) || command === "az" && normalized.includes("pull request") && (normalized.includes("not found") || normalized.includes("does not exist"))) return "not-found";
105542
105607
  return "command-failed";
105543
105608
  };
105544
- const make$63 = Effect.gen(function* () {
105609
+ const make$65 = Effect.gen(function* () {
105545
105610
  const processRunner = yield* ProcessRunner;
105546
105611
  const run = Effect.fn("VcsProcess.run")(function* (input) {
105547
105612
  const baseError = {
@@ -105600,7 +105665,7 @@ const make$63 = Effect.gen(function* () {
105600
105665
  });
105601
105666
  return VcsProcess.of({ run });
105602
105667
  });
105603
- const layer$53 = Layer.effect(VcsProcess, make$63).pipe(Layer.provide(layer$85));
105668
+ const layer$53 = Layer.effect(VcsProcess, make$65).pipe(Layer.provide(layer$85));
105604
105669
  //#endregion
105605
105670
  //#region src/vcs/VcsDriver.ts
105606
105671
  var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
@@ -106051,12 +106116,12 @@ const makeVcsDriver = Effect.gen(function* () {
106051
106116
  const driver = yield* makeVcsDriverShape();
106052
106117
  return VcsDriver.of(driver);
106053
106118
  });
106054
- const make$62 = Effect.gen(function* () {
106119
+ const make$64 = Effect.gen(function* () {
106055
106120
  const git = yield* makeGitVcsDriverCore();
106056
106121
  return GitVcsDriver.of(git);
106057
106122
  });
106058
106123
  Layer.effect(VcsDriver, makeVcsDriver);
106059
- const layer$52 = Layer.effect(GitVcsDriver, make$62);
106124
+ const layer$52 = Layer.effect(GitVcsDriver, make$64);
106060
106125
  //#endregion
106061
106126
  //#region src/vcs/VcsProjectConfig.ts
106062
106127
  const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
@@ -106088,7 +106153,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
106088
106153
  configPath: error.configPath,
106089
106154
  errorTag: error._tag
106090
106155
  }));
106091
- const make$61 = Effect.gen(function* () {
106156
+ const make$63 = Effect.gen(function* () {
106092
106157
  const fileSystem = yield* FileSystem.FileSystem;
106093
106158
  const path = yield* Path$1.Path;
106094
106159
  const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
@@ -106129,7 +106194,7 @@ const make$61 = Effect.gen(function* () {
106129
106194
  });
106130
106195
  return VcsProjectConfig.of({ resolveKind });
106131
106196
  });
106132
- const layer$51 = Layer.effect(VcsProjectConfig, make$61);
106197
+ const layer$51 = Layer.effect(VcsProjectConfig, make$63);
106133
106198
  //#endregion
106134
106199
  //#region src/vcs/VcsDriverRegistry.ts
106135
106200
  const DETECTION_CACHE_CAPACITY = 2048;
@@ -106149,7 +106214,7 @@ function parseDetectionCacheKey(key) {
106149
106214
  cwd: key.slice(separatorIndex + 1)
106150
106215
  };
106151
106216
  }
106152
- const make$60 = Effect.gen(function* () {
106217
+ const make$62 = Effect.gen(function* () {
106153
106218
  const projectConfig = yield* VcsProjectConfig;
106154
106219
  const git = yield* makeVcsDriver;
106155
106220
  const drivers = { git };
@@ -106206,7 +106271,7 @@ const make$60 = Effect.gen(function* () {
106206
106271
  resolve
106207
106272
  });
106208
106273
  });
106209
- const layer$50 = Layer.effect(VcsDriverRegistry, make$60).pipe(Layer.provide(layer$51));
106274
+ const layer$50 = Layer.effect(VcsDriverRegistry, make$62).pipe(Layer.provide(layer$51));
106210
106275
  //#endregion
106211
106276
  //#region src/checkpointing/CheckpointStore.ts
106212
106277
  /**
@@ -106226,7 +106291,7 @@ const layer$50 = Layer.effect(VcsDriverRegistry, make$60).pipe(Layer.provide(lay
106226
106291
  */
106227
106292
  /** Service tag for checkpoint persistence and restore operations. */
106228
106293
  var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
106229
- const make$59 = Effect.gen(function* () {
106294
+ const make$61 = Effect.gen(function* () {
106230
106295
  const vcsRegistry = yield* VcsDriverRegistry;
106231
106296
  const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
106232
106297
  const handle = yield* vcsRegistry.resolve({ cwd });
@@ -106265,7 +106330,7 @@ const make$59 = Effect.gen(function* () {
106265
106330
  deleteCheckpointRefs
106266
106331
  });
106267
106332
  });
106268
- const layer$49 = Layer.effect(CheckpointStore, make$59);
106333
+ const layer$49 = Layer.effect(CheckpointStore, make$61);
106269
106334
  //#endregion
106270
106335
  //#region src/checkpointing/CheckpointDiffQuery.ts
106271
106336
  /**
@@ -106287,7 +106352,7 @@ function buildTurnDiffResult(input, diff) {
106287
106352
  diff
106288
106353
  };
106289
106354
  }
106290
- const make$58 = Effect.gen(function* () {
106355
+ const make$60 = Effect.gen(function* () {
106291
106356
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
106292
106357
  const checkpointStore = yield* CheckpointStore;
106293
106358
  const threadActivities = yield* ProjectionThreadActivityRepository;
@@ -106458,7 +106523,7 @@ const make$58 = Effect.gen(function* () {
106458
106523
  getFullThreadDiff
106459
106524
  });
106460
106525
  });
106461
- const layer$48 = Layer.effect(CheckpointDiffQuery, make$58);
106526
+ const layer$48 = Layer.effect(CheckpointDiffQuery, make$60);
106462
106527
  //#endregion
106463
106528
  //#region src/orchestration/ThreadLiveEventCoalescer.ts
106464
106529
  const COALESCE_WINDOW = Duration.millis(50);
@@ -107003,7 +107068,7 @@ const serversEqual = (left, right) => {
107003
107068
  }
107004
107069
  return true;
107005
107070
  };
107006
- const make$57 = Effect.gen(function* PortDiscoveryMake() {
107071
+ const make$59 = Effect.gen(function* PortDiscoveryMake() {
107007
107072
  const net = yield* NetService;
107008
107073
  const processRunner = yield* ProcessRunner;
107009
107074
  const hostPlatform = yield* HostProcessPlatform;
@@ -107154,7 +107219,7 @@ const make$57 = Effect.gen(function* PortDiscoveryMake() {
107154
107219
  unregisterTerminal
107155
107220
  });
107156
107221
  }).pipe(Effect.withSpan("PortDiscovery.make"));
107157
- const layer$47 = Layer.effect(PortDiscovery, make$57);
107222
+ const layer$47 = Layer.effect(PortDiscovery, make$59);
107158
107223
  //#endregion
107159
107224
  //#region src/terminal/Manager.ts
107160
107225
  /**
@@ -107832,7 +107897,7 @@ function normalizedRuntimeEnv(env) {
107832
107897
  if (entries.length === 0) return null;
107833
107898
  return Object.fromEntries(entries.toSorted(([left], [right]) => left.localeCompare(right)));
107834
107899
  }
107835
- const make$56 = Effect.fn("TerminalManager.make")(function* () {
107900
+ const make$58 = Effect.fn("TerminalManager.make")(function* () {
107836
107901
  const { terminalLogsDir } = yield* ServerConfig$1;
107837
107902
  const ptyAdapter = yield* PtyAdapter;
107838
107903
  const portDiscovery = yield* PortDiscovery;
@@ -108794,7 +108859,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
108794
108859
  subscribeMetadata
108795
108860
  });
108796
108861
  });
108797
- const layer$46 = Layer.effect(TerminalManager, make$56()).pipe(Layer.provide(layer$85));
108862
+ const layer$46 = Layer.effect(TerminalManager, make$58()).pipe(Layer.provide(layer$85));
108798
108863
  //#endregion
108799
108864
  //#region src/project/ProjectSetupScriptRunner.ts
108800
108865
  var ProjectSetupScriptOperationError = class extends Schema$1.TaggedErrorClass()("ProjectSetupScriptOperationError", {
@@ -108826,7 +108891,7 @@ var ProjectSetupScriptProjectNotFoundError = class extends Schema$1.TaggedErrorC
108826
108891
  };
108827
108892
  Schema$1.Union([ProjectSetupScriptOperationError, ProjectSetupScriptProjectNotFoundError]);
108828
108893
  var ProjectSetupScriptRunner = class extends Context.Service()("@p4code/cli/project/ProjectSetupScriptRunner") {};
108829
- const make$55 = Effect.gen(function* () {
108894
+ const make$57 = Effect.gen(function* () {
108830
108895
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
108831
108896
  const terminalManager = yield* TerminalManager;
108832
108897
  const settingsService = yield* Effect.serviceOption(ServerSettingsService);
@@ -108889,7 +108954,7 @@ const make$55 = Effect.gen(function* () {
108889
108954
  });
108890
108955
  return ProjectSetupScriptRunner.of({ runForThread });
108891
108956
  });
108892
- const layer$45 = Layer.effect(ProjectSetupScriptRunner, make$55);
108957
+ const layer$45 = Layer.effect(ProjectSetupScriptRunner, make$57);
108893
108958
  //#endregion
108894
108959
  //#region src/sourceControl/azureDevOpsPullRequests.ts
108895
108960
  const AzureDevOpsPullRequestSchema = Schema$1.Struct({
@@ -109217,7 +109282,7 @@ function decodeAzureDevOpsJson(raw, schema, operation, cwd) {
109217
109282
  cause
109218
109283
  })));
109219
109284
  }
109220
- const make$54 = Effect.gen(function* () {
109285
+ const make$56 = Effect.gen(function* () {
109221
109286
  const process = yield* VcsProcess;
109222
109287
  const execute = (input) => process.run({
109223
109288
  operation: "AzureDevOpsCli.execute",
@@ -109359,7 +109424,7 @@ const make$54 = Effect.gen(function* () {
109359
109424
  }).pipe(Effect.asVoid)
109360
109425
  });
109361
109426
  });
109362
- const layer$44 = Layer.effect(AzureDevOpsCli, make$54);
109427
+ const layer$44 = Layer.effect(AzureDevOpsCli, make$56);
109363
109428
  //#endregion
109364
109429
  //#region src/sourceControl/SourceControlProviderDiscovery.ts
109365
109430
  function firstNonEmptyLine(text) {
@@ -109563,7 +109628,7 @@ function toChangeRequest$5(summary) {
109563
109628
  isCrossRepository: false
109564
109629
  };
109565
109630
  }
109566
- const make$53 = Effect.gen(function* () {
109631
+ const make$55 = Effect.gen(function* () {
109567
109632
  const azure = yield* AzureDevOpsCli;
109568
109633
  return SourceControlProvider.of({
109569
109634
  kind: "azure-devops",
@@ -109656,7 +109721,7 @@ const make$53 = Effect.gen(function* () {
109656
109721
  })))
109657
109722
  });
109658
109723
  });
109659
- Layer.effect(SourceControlProvider, make$53);
109724
+ Layer.effect(SourceControlProvider, make$55);
109660
109725
  //#endregion
109661
109726
  //#region src/sourceControl/bitbucketPullRequests.ts
109662
109727
  const BitbucketRepositoryRefSchema = Schema$1.Struct({
@@ -110033,7 +110098,7 @@ function responseError(operation, response) {
110033
110098
  responseBodyLength: collected.text.length
110034
110099
  }))));
110035
110100
  }
110036
- const make$52 = Effect.gen(function* () {
110101
+ const make$54 = Effect.gen(function* () {
110037
110102
  const config = yield* BitbucketApiEnvConfig;
110038
110103
  const httpClient = yield* HttpClient.HttpClient;
110039
110104
  const fileSystem = yield* FileSystem.FileSystem;
@@ -110249,7 +110314,7 @@ const make$52 = Effect.gen(function* () {
110249
110314
  })))
110250
110315
  });
110251
110316
  });
110252
- const layer$42 = Layer.effect(BitbucketApi, make$52);
110317
+ const layer$42 = Layer.effect(BitbucketApi, make$54);
110253
110318
  //#endregion
110254
110319
  //#region src/sourceControl/BitbucketSourceControlProvider.ts
110255
110320
  function toChangeRequest$4(summary) {
@@ -110267,7 +110332,7 @@ function toChangeRequest$4(summary) {
110267
110332
  ...summary.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin } : {}
110268
110333
  };
110269
110334
  }
110270
- const make$51 = Effect.gen(function* () {
110335
+ const make$53 = Effect.gen(function* () {
110271
110336
  const bitbucket = yield* BitbucketApi;
110272
110337
  return SourceControlProvider.of({
110273
110338
  kind: "bitbucket",
@@ -110358,7 +110423,7 @@ const make$51 = Effect.gen(function* () {
110358
110423
  })))
110359
110424
  });
110360
110425
  });
110361
- Layer.effect(SourceControlProvider, make$51);
110426
+ Layer.effect(SourceControlProvider, make$53);
110362
110427
  const makeDiscovery = Effect.gen(function* () {
110363
110428
  return {
110364
110429
  type: "api",
@@ -110606,7 +110671,7 @@ function deriveRepositoryCloneUrlsFromCreateOutput(stdout, repository) {
110606
110671
  sshUrl: `git@${fallbackHost}:${repository}.git`
110607
110672
  };
110608
110673
  }
110609
- const make$50 = Effect.gen(function* () {
110674
+ const make$52 = Effect.gen(function* () {
110610
110675
  const process = yield* VcsProcess;
110611
110676
  const execute = (input) => process.run({
110612
110677
  operation: "GitHubCli.execute",
@@ -110724,7 +110789,7 @@ const make$50 = Effect.gen(function* () {
110724
110789
  }).pipe(Effect.asVoid)
110725
110790
  });
110726
110791
  });
110727
- const layer$40 = Layer.effect(GitHubCli, make$50);
110792
+ const layer$40 = Layer.effect(GitHubCli, make$52);
110728
110793
  //#endregion
110729
110794
  //#region src/sourceControl/gitHubAuthStatus.ts
110730
110795
  const GitHubAuthStatusAccountSchema = Schema$1.Struct({
@@ -110826,7 +110891,7 @@ const discovery$1 = {
110826
110891
  parseAuth: parseGitHubAuth,
110827
110892
  installHint: "Install the GitHub command-line tool (`gh`) via https://cli.github.com/ or your package manager (for example `brew install gh`)."
110828
110893
  };
110829
- const make$49 = Effect.gen(function* () {
110894
+ const make$51 = Effect.gen(function* () {
110830
110895
  const github = yield* GitHubCli;
110831
110896
  const listChangeRequests = (input) => {
110832
110897
  if (input.state === "open") return github.listOpenPullRequests({
@@ -110942,7 +111007,7 @@ const make$49 = Effect.gen(function* () {
110942
111007
  })))
110943
111008
  });
110944
111009
  });
110945
- Layer.effect(SourceControlProvider, make$49);
111010
+ Layer.effect(SourceControlProvider, make$51);
110946
111011
  //#endregion
110947
111012
  //#region src/sourceControl/gitLabMergeRequests.ts
110948
111013
  const GitLabProjectReferenceSchema = Schema$1.Struct({
@@ -111261,7 +111326,7 @@ function parseRepositoryPath(repository) {
111261
111326
  projectPath
111262
111327
  };
111263
111328
  }
111264
- const make$48 = Effect.gen(function* () {
111329
+ const make$50 = Effect.gen(function* () {
111265
111330
  const process = yield* VcsProcess;
111266
111331
  const run = (input, mapError) => process.run({
111267
111332
  operation: "GitLabCli.execute",
@@ -111412,7 +111477,7 @@ const make$48 = Effect.gen(function* () {
111412
111477
  }).pipe(Effect.asVoid)
111413
111478
  });
111414
111479
  });
111415
- const layer$38 = Layer.effect(GitLabCli, make$48);
111480
+ const layer$38 = Layer.effect(GitLabCli, make$50);
111416
111481
  //#endregion
111417
111482
  //#region src/sourceControl/gitLabAuthStatus.ts
111418
111483
  const HOST_LINE_PATTERN = /^(?:[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?|\[[a-f0-9:.]+\])(?::\d+)?$/iu;
@@ -111510,7 +111575,7 @@ const discovery = {
111510
111575
  refineUnknownRemote: refineUnknownGitLabRemote,
111511
111576
  installHint: "Install the GitLab command-line tool (`glab`) from https://gitlab.com/gitlab-org/cli or your package manager (for example `brew install glab`)."
111512
111577
  };
111513
- const make$47 = Effect.gen(function* () {
111578
+ const make$49 = Effect.gen(function* () {
111514
111579
  const gitlab = yield* GitLabCli;
111515
111580
  return SourceControlProvider.of({
111516
111581
  kind: "gitlab",
@@ -111599,7 +111664,7 @@ const make$47 = Effect.gen(function* () {
111599
111664
  })))
111600
111665
  });
111601
111666
  });
111602
- Layer.effect(SourceControlProvider, make$47);
111667
+ Layer.effect(SourceControlProvider, make$49);
111603
111668
  //#endregion
111604
111669
  //#region src/sourceControl/SourceControlProviderRegistry.ts
111605
111670
  const PROVIDER_DETECTION_CACHE_CAPACITY = 2048;
@@ -111755,12 +111820,12 @@ const makeWithProviders = Effect.fn("makeSourceControlProviderRegistryWithProvid
111755
111820
  })), { concurrency: "unbounded" })
111756
111821
  });
111757
111822
  });
111758
- const make$46 = Effect.gen(function* () {
111759
- const github = yield* make$49;
111760
- const gitlab = yield* make$47;
111761
- const bitbucket = yield* make$51;
111823
+ const make$48 = Effect.gen(function* () {
111824
+ const github = yield* make$51;
111825
+ const gitlab = yield* make$49;
111826
+ const bitbucket = yield* make$53;
111762
111827
  const bitbucketDiscovery = yield* makeDiscovery;
111763
- const azureDevOps = yield* make$53;
111828
+ const azureDevOps = yield* make$55;
111764
111829
  return yield* makeWithProviders([
111765
111830
  {
111766
111831
  kind: "github",
@@ -111784,7 +111849,7 @@ const make$46 = Effect.gen(function* () {
111784
111849
  }
111785
111850
  ]);
111786
111851
  });
111787
- const layer$36 = Layer.effect(SourceControlProviderRegistry, make$46);
111852
+ const layer$36 = Layer.effect(SourceControlProviderRegistry, make$48);
111788
111853
  //#endregion
111789
111854
  //#region src/sourceControl/PrTemplateDetection.ts
111790
111855
  const TEMPLATE_MAX_BYTES = 8e3;
@@ -112155,7 +112220,7 @@ function toPullRequestHeadRemoteInfo(pr) {
112155
112220
  ...pr.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: pr.headRepositoryOwnerLogin } : {}
112156
112221
  };
112157
112222
  }
112158
- const make$45 = Effect.gen(function* () {
112223
+ const make$47 = Effect.gen(function* () {
112159
112224
  const gitCore = yield* GitVcsDriver;
112160
112225
  const sourceControlProviders = yield* SourceControlProviderRegistry;
112161
112226
  const textGeneration = yield* TextGeneration;
@@ -113129,7 +113194,7 @@ const make$45 = Effect.gen(function* () {
113129
113194
  runStackedAction
113130
113195
  });
113131
113196
  });
113132
- const layer$35 = Layer.effect(GitManager, make$45);
113197
+ const layer$35 = Layer.effect(GitManager, make$47);
113133
113198
  //#endregion
113134
113199
  //#region src/git/GitWorkflowService.ts
113135
113200
  var GitWorkflowService = class extends Context.Service()("@p4code/cli/git/GitWorkflowService") {};
@@ -113166,7 +113231,7 @@ function nonRepositoryListRefs() {
113166
113231
  totalCount: 0
113167
113232
  };
113168
113233
  }
113169
- const make$44 = Effect.gen(function* () {
113234
+ const make$46 = Effect.gen(function* () {
113170
113235
  const registry = yield* VcsDriverRegistry;
113171
113236
  const git = yield* GitVcsDriver;
113172
113237
  const gitManager = yield* GitManager;
@@ -113252,7 +113317,7 @@ const make$44 = Effect.gen(function* () {
113252
113317
  renameBranch: (input) => ensureGit("GitWorkflowService.renameBranch", input.cwd).pipe(Effect.andThen(git.renameBranch(input)))
113253
113318
  });
113254
113319
  });
113255
- const layer$34 = Layer.effect(GitWorkflowService, make$44);
113320
+ const layer$34 = Layer.effect(GitWorkflowService, make$46);
113256
113321
  //#endregion
113257
113322
  //#region src/pullRequest/PullRequestProvider.ts
113258
113323
  /**
@@ -113613,7 +113678,7 @@ function isReviewerName(value) {
113613
113678
  const name = value.trim();
113614
113679
  return name.length > 0 && !name.startsWith("-");
113615
113680
  }
113616
- const make$43 = Effect.gen(function* () {
113681
+ const make$45 = Effect.gen(function* () {
113617
113682
  const azure = yield* AzureDevOpsCli;
113618
113683
  const detectArgs = ["--detect", "true"];
113619
113684
  const executeJson = (input) => azure.execute({
@@ -113813,7 +113878,7 @@ const make$43 = Effect.gen(function* () {
113813
113878
  }).pipe(Effect.asVoid)
113814
113879
  });
113815
113880
  });
113816
- const layer$33 = Layer.effect(AzureDevOpsPullRequestCli, make$43);
113881
+ const layer$33 = Layer.effect(AzureDevOpsPullRequestCli, make$45);
113817
113882
  //#endregion
113818
113883
  //#region src/pullRequest/AzureDevOpsPullRequestProvider.ts
113819
113884
  const CAPABILITIES$3 = {
@@ -113888,7 +113953,7 @@ function toChangeRequest$1(pullRequest) {
113888
113953
  labels: []
113889
113954
  };
113890
113955
  }
113891
- const make$42 = Effect.gen(function* () {
113956
+ const make$44 = Effect.gen(function* () {
113892
113957
  const cli = yield* AzureDevOpsPullRequestCli;
113893
113958
  const fail = (operation) => (error) => new PullRequestProviderError({
113894
113959
  provider: "azure-devops",
@@ -114628,7 +114693,7 @@ function mergeStrategy(method) {
114628
114693
  default: return "merge_commit";
114629
114694
  }
114630
114695
  }
114631
- const make$41 = Effect.gen(function* () {
114696
+ const make$43 = Effect.gen(function* () {
114632
114697
  const bitbucket = yield* BitbucketApi;
114633
114698
  /**
114634
114699
  * The repository's own path, and the workspace above it — which the people who may review are
@@ -114908,7 +114973,7 @@ const make$41 = Effect.gen(function* () {
114908
114973
  }).pipe(Effect.asVoid))
114909
114974
  });
114910
114975
  });
114911
- const layer$32 = Layer.effect(BitbucketPullRequestApi, make$41);
114976
+ const layer$32 = Layer.effect(BitbucketPullRequestApi, make$43);
114912
114977
  //#endregion
114913
114978
  //#region src/pullRequest/BitbucketPullRequestProvider.ts
114914
114979
  const CAPABILITIES$2 = {
@@ -114988,7 +115053,7 @@ function toChangeRequest(pullRequest) {
114988
115053
  labels: []
114989
115054
  };
114990
115055
  }
114991
- const make$40 = Effect.gen(function* () {
115056
+ const make$42 = Effect.gen(function* () {
114992
115057
  const api = yield* BitbucketPullRequestApi;
114993
115058
  const fail = (operation) => (error) => new PullRequestProviderError({
114994
115059
  provider: "bitbucket",
@@ -117217,7 +117282,7 @@ function actionArgs$1(action, mergeMethod, updateMethod) {
117217
117282
  case "reopen": return ["reopen"];
117218
117283
  }
117219
117284
  }
117220
- const make$39 = Effect.gen(function* () {
117285
+ const make$41 = Effect.gen(function* () {
117221
117286
  const github = yield* GitHubCli;
117222
117287
  /**
117223
117288
  * The pull request's own node id, which is what a mutation against the pull request itself is
@@ -117980,7 +118045,7 @@ const make$39 = Effect.gen(function* () {
117980
118045
  })))
117981
118046
  });
117982
118047
  });
117983
- const layer$31 = Layer.effect(GitHubPullRequestCli, make$39);
118048
+ const layer$31 = Layer.effect(GitHubPullRequestCli, make$41);
117984
118049
  //#endregion
117985
118050
  //#region src/pullRequest/GitHubPullRequestProvider.ts
117986
118051
  const CAPABILITIES$1 = {
@@ -118097,7 +118162,7 @@ function loginAvatarUrl(login, host) {
118097
118162
  }
118098
118163
  /** True where markdown would render nothing: whitespace, or only HTML comments. */
118099
118164
  const rendersEmpty = (body) => body.replace(/<!--[\s\S]*?-->/g, "").trim().length === 0;
118100
- const make$38 = Effect.gen(function* () {
118165
+ const make$40 = Effect.gen(function* () {
118101
118166
  const cli = yield* GitHubPullRequestCli;
118102
118167
  const fail = (operation) => (error) => new PullRequestProviderError({
118103
118168
  provider: "github",
@@ -119119,7 +119184,7 @@ function actionArgs(action, mergeMethod) {
119119
119184
  case "reopen": return ["reopen"];
119120
119185
  }
119121
119186
  }
119122
- const make$37 = Effect.gen(function* () {
119187
+ const make$39 = Effect.gen(function* () {
119123
119188
  const gitlab = yield* GitLabCli;
119124
119189
  const api = (input) => gitlab.execute({
119125
119190
  cwd: input.cwd,
@@ -119690,7 +119755,7 @@ const make$37 = Effect.gen(function* () {
119690
119755
  }).pipe(Effect.asVoid)
119691
119756
  });
119692
119757
  });
119693
- const layer$30 = Layer.effect(GitLabPullRequestCli, make$37);
119758
+ const layer$30 = Layer.effect(GitLabPullRequestCli, make$39);
119694
119759
  //#endregion
119695
119760
  //#region src/pullRequest/GitLabPullRequestProvider.ts
119696
119761
  const CAPABILITIES = {
@@ -119770,7 +119835,7 @@ function reasonFor(error) {
119770
119835
  if (error._tag === "GitLabCliAuthenticationError") return "unauthenticated";
119771
119836
  return "failed";
119772
119837
  }
119773
- const make$36 = Effect.gen(function* () {
119838
+ const make$38 = Effect.gen(function* () {
119774
119839
  const cli = yield* GitLabPullRequestCli;
119775
119840
  const fail = (operation) => (error) => new PullRequestProviderError({
119776
119841
  provider: "gitlab",
@@ -119913,13 +119978,13 @@ function fromProviders(providers) {
119913
119978
  * The hosts this build can read change requests from. A host with no entry here still shows up
119914
119979
  * in the provider list as unimplemented, so its projects are explained rather than missing.
119915
119980
  */
119916
- const make$35 = Effect.map(Effect.all([
119917
- make$38,
119918
- make$36,
119981
+ const make$37 = Effect.map(Effect.all([
119919
119982
  make$40,
119920
- make$42
119983
+ make$38,
119984
+ make$42,
119985
+ make$44
119921
119986
  ]), fromProviders);
119922
- const layer$29 = Layer.effect(PullRequestProviderRegistry, make$35).pipe(Layer.provide(layer$31.pipe(Layer.provide(layer$40))), Layer.provide(layer$30.pipe(Layer.provide(layer$38))), Layer.provide(layer$32.pipe(Layer.provide(layer$42))), Layer.provide(layer$33.pipe(Layer.provide(layer$44))));
119987
+ const layer$29 = Layer.effect(PullRequestProviderRegistry, make$37).pipe(Layer.provide(layer$31.pipe(Layer.provide(layer$40))), Layer.provide(layer$30.pipe(Layer.provide(layer$38))), Layer.provide(layer$32.pipe(Layer.provide(layer$42))), Layer.provide(layer$33.pipe(Layer.provide(layer$44))));
119923
119988
  //#endregion
119924
119989
  //#region src/pullRequest/PullRequestService.ts
119925
119990
  /**
@@ -120107,7 +120172,7 @@ function repositoryIdentityOf(project) {
120107
120172
  if (identity.displayName) return identity.displayName;
120108
120173
  return identity.owner && identity.name ? `${identity.owner}/${identity.name}` : null;
120109
120174
  }
120110
- const make$34 = Effect.gen(function* () {
120175
+ const make$36 = Effect.gen(function* () {
120111
120176
  const registry = yield* PullRequestProviderRegistry;
120112
120177
  const projections = yield* ProjectionSnapshotQuery;
120113
120178
  const sourceControlProviders = yield* SourceControlProviderRegistry;
@@ -121105,7 +121170,7 @@ const make$34 = Effect.gen(function* () {
121105
121170
  invalidate
121106
121171
  });
121107
121172
  });
121108
- const layer$28 = Layer.effect(PullRequestService, make$34);
121173
+ const layer$28 = Layer.effect(PullRequestService, make$36);
121109
121174
  //#endregion
121110
121175
  //#region src/orchestration/ThreadWorkspaceLifecycle.ts
121111
121176
  var ThreadWorkspaceLifecycleError = class extends Data.TaggedError("ThreadWorkspaceLifecycleError") {};
@@ -121149,7 +121214,7 @@ const mapLifecycleError = Effect.mapError((cause) => cause instanceof ThreadWork
121149
121214
  detail: "Thread workspace lifecycle operation failed.",
121150
121215
  cause
121151
121216
  }));
121152
- const make$33 = Effect.gen(function* () {
121217
+ const make$35 = Effect.gen(function* () {
121153
121218
  const snapshots = yield* ProjectionSnapshotQuery;
121154
121219
  const engine = yield* OrchestrationEngineService;
121155
121220
  const gitWorkflow = yield* GitWorkflowService;
@@ -121403,7 +121468,7 @@ const make$33 = Effect.gen(function* () {
121403
121468
  record
121404
121469
  };
121405
121470
  });
121406
- const layer$27 = Layer.effect(ThreadWorkspaceLifecycleService, make$33);
121471
+ const layer$27 = Layer.effect(ThreadWorkspaceLifecycleService, make$35);
121407
121472
  //#endregion
121408
121473
  //#region src/textGeneration/BtwRequestCoordinator.ts
121409
121474
  const MAX_PENDING_BTW_CANCELLATIONS = 256;
@@ -123676,7 +123741,7 @@ function makeUpdateState(input) {
123676
123741
  output: input.output ?? null
123677
123742
  };
123678
123743
  }
123679
- const make$32 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
123744
+ const make$34 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
123680
123745
  const providerRegistry = yield* ProviderRegistry;
123681
123746
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
123682
123747
  const httpClient = yield* HttpClient.HttpClient;
@@ -123791,7 +123856,7 @@ const make$32 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
123791
123856
  });
123792
123857
  return ProviderMaintenanceRunner.of({ updateProvider });
123793
123858
  });
123794
- const layer$26 = Layer.effect(ProviderMaintenanceRunner, make$32());
123859
+ const layer$26 = Layer.effect(ProviderMaintenanceRunner, make$34());
123795
123860
  //#endregion
123796
123861
  //#region src/usage/usageTranscripts.ts
123797
123862
  const EMPTY_TOTALS = {
@@ -124617,7 +124682,7 @@ Layer.succeed(UsageService, UsageService.of({
124617
124682
  scanDurationMs: 0
124618
124683
  })
124619
124684
  }));
124620
- const make$31 = Effect.gen(function* () {
124685
+ const make$33 = Effect.gen(function* () {
124621
124686
  const fileSystem = yield* FileSystem.FileSystem;
124622
124687
  const path = yield* Path$1.Path;
124623
124688
  const config = yield* ServerConfig$1;
@@ -124900,7 +124965,7 @@ const make$31 = Effect.gen(function* () {
124900
124965
  readSessionRecords: (input) => scanLock.withPermits(1)(readSessionRecords(input))
124901
124966
  };
124902
124967
  });
124903
- const layer$25 = Layer.effect(UsageService, make$31);
124968
+ const layer$25 = Layer.effect(UsageService, make$33);
124904
124969
  //#endregion
124905
124970
  //#region src/feed/FeedStore.ts
124906
124971
  const storageFailure = (message) => new FeedError({
@@ -125264,7 +125329,7 @@ const jsonRequest = Effect.fn("FeedService.jsonRequest")(function* (url, token,
125264
125329
  catch: () => fail("hub_unavailable", "Hub returned invalid JSON.")
125265
125330
  });
125266
125331
  });
125267
- const make$30 = Effect.gen(function* () {
125332
+ const make$32 = Effect.gen(function* () {
125268
125333
  const hubLink = yield* HubLink;
125269
125334
  const providers = yield* ProviderInstanceRegistry;
125270
125335
  const config = yield* ServerConfig$1;
@@ -125502,7 +125567,7 @@ var FeedService = class extends Context.Reference("@p4code/cli/feed/FeedService"
125502
125567
  markRead: unavailable,
125503
125568
  cleanup: unavailable
125504
125569
  }) }) {};
125505
- const layer$24 = Layer.effect(FeedService, make$30);
125570
+ const layer$24 = Layer.effect(FeedService, make$32);
125506
125571
  //#endregion
125507
125572
  //#region src/storageCleanup.ts
125508
125573
  const DAY_MS$1 = 864e5;
@@ -125519,7 +125584,7 @@ function isExpired(modifiedAtMs, days, nowMs) {
125519
125584
  return modifiedAtMs < nowMs - days * DAY_MS$1;
125520
125585
  }
125521
125586
  var StorageCleanup = class extends Context.Service()("@p4code/cli/storageCleanup") {};
125522
- const make$29 = Effect.gen(function* () {
125587
+ const make$31 = Effect.gen(function* () {
125523
125588
  const fs = yield* FileSystem.FileSystem;
125524
125589
  const path = yield* Path$1.Path;
125525
125590
  const config = yield* ServerConfig$1;
@@ -125608,7 +125673,7 @@ const make$29 = Effect.gen(function* () {
125608
125673
  })
125609
125674
  };
125610
125675
  });
125611
- const layer$23 = Layer.effect(StorageCleanup, make$29);
125676
+ const layer$23 = Layer.effect(StorageCleanup, make$31);
125612
125677
  //#endregion
125613
125678
  //#region src/worktreeCleanupRules.ts
125614
125679
  /**
@@ -125708,7 +125773,7 @@ function planWorktreeCleanup(facts, settings, nowMs) {
125708
125773
  * @module worktreeCleanup
125709
125774
  */
125710
125775
  var WorktreeCleanup = class extends Context.Service()("@p4code/cli/worktreeCleanup") {};
125711
- const make$28 = Effect.gen(function* () {
125776
+ const make$30 = Effect.gen(function* () {
125712
125777
  const threads = yield* ProjectionThreadRepository;
125713
125778
  const projects = yield* ProjectionProjectRepository;
125714
125779
  const sessions = yield* ProviderSessionDirectory;
@@ -125803,7 +125868,7 @@ const make$28 = Effect.gen(function* () {
125803
125868
  })
125804
125869
  };
125805
125870
  });
125806
- const layer$22 = Layer.effect(WorktreeCleanup, make$28);
125871
+ const layer$22 = Layer.effect(WorktreeCleanup, make$30);
125807
125872
  const SKILL_MANIFEST_FILENAME = "SKILL.md";
125808
125873
  /**
125809
125874
  * Split a catalogue id (`owner/repo/skill-name`) into its parts.
@@ -125949,7 +126014,7 @@ const emptyFetch = (id, unavailable) => ({
125949
126014
  skipped: [],
125950
126015
  unavailable
125951
126016
  });
125952
- const make$27 = Effect.gen(function* () {
126017
+ const make$29 = Effect.gen(function* () {
125953
126018
  const http = yield* HttpClient.HttpClient;
125954
126019
  const request = Effect.fn("SkillRegistry.request")(function* (url) {
125955
126020
  return yield* http.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("accept", "application/json"), HttpClientRequest.setHeader("user-agent", "p4code"))).pipe(Effect.timeout(REQUEST_TIMEOUT_MS$1));
@@ -126020,7 +126085,7 @@ const make$27 = Effect.gen(function* () {
126020
126085
  fetch
126021
126086
  };
126022
126087
  });
126023
- const layer$21 = Layer.effect(SkillRegistry, make$27);
126088
+ const layer$21 = Layer.effect(SkillRegistry, make$29);
126024
126089
  //#endregion
126025
126090
  //#region src/orchestration/SupervisorSecrets.ts
126026
126091
  /**
@@ -126096,6 +126161,9 @@ const makeSupervisorSecrets = Effect.gen(function* () {
126096
126161
  });
126097
126162
  const SupervisorSecretsLive = Layer.effect(SupervisorSecrets, makeSupervisorSecrets);
126098
126163
  //#endregion
126164
+ //#region src/orchestration/Services/JevWorkspaceAdvisor.ts
126165
+ var JevWorkspaceAdvisor = class extends Context.Service()("@p4code/cli/orchestration/Services/JevWorkspaceAdvisor") {};
126166
+ //#endregion
126099
126167
  //#region src/mcp/PreviewAutomationBroker.ts
126100
126168
  var PreviewAutomationBroker = class extends Context.Service()("@p4code/cli/mcp/PreviewAutomationBroker") {};
126101
126169
  const removeConnectionFromState = (current, clientId, queue) => {
@@ -126212,7 +126280,7 @@ const classifyResponseError = (context, error) => {
126212
126280
  });
126213
126281
  }
126214
126282
  };
126215
- const make$26 = Effect.gen(function* PreviewAutomationBrokerMake() {
126283
+ const make$28 = Effect.gen(function* PreviewAutomationBrokerMake() {
126216
126284
  const crypto = yield* Crypto.Crypto;
126217
126285
  const state = yield* SynchronizedRef.make({
126218
126286
  clients: /* @__PURE__ */ new Map(),
@@ -126446,7 +126514,7 @@ const make$26 = Effect.gen(function* PreviewAutomationBrokerMake() {
126446
126514
  invoke
126447
126515
  });
126448
126516
  }).pipe(Effect.withSpan("PreviewAutomationBroker.make"));
126449
- const layer$20 = Layer.effect(PreviewAutomationBroker, make$26);
126517
+ const layer$20 = Layer.effect(PreviewAutomationBroker, make$28);
126450
126518
  //#endregion
126451
126519
  //#region src/preview/Manager.ts
126452
126520
  /**
@@ -126510,7 +126578,7 @@ const buildIdleSnapshot = (input) => ({
126510
126578
  viewport: FILL_PREVIEW_VIEWPORT,
126511
126579
  updatedAt: input.updatedAt
126512
126580
  });
126513
- const make$25 = Effect.gen(function* PreviewManagerMake() {
126581
+ const make$27 = Effect.gen(function* PreviewManagerMake() {
126514
126582
  const serverEpoch = NodeCrypto.randomUUID();
126515
126583
  const stateRef = yield* SynchronizedRef.make(initialState);
126516
126584
  const eventsPubSub = yield* PubSub.unbounded();
@@ -126741,7 +126809,7 @@ const make$25 = Effect.gen(function* PreviewManagerMake() {
126741
126809
  subscribeEvents: PubSub.subscribe(eventsPubSub)
126742
126810
  });
126743
126811
  }).pipe(Effect.withSpan("PreviewManager.make"));
126744
- const layer$19 = Layer.effect(PreviewManager, make$25);
126812
+ const layer$19 = Layer.effect(PreviewManager, make$27);
126745
126813
  //#endregion
126746
126814
  //#region src/workspace/WorkspaceSearchIndex.ts
126747
126815
  const WORKSPACE_INDEX_MAX_ENTRIES = 25e3;
@@ -126878,7 +126946,7 @@ const waitForScan = (cwd, finder, onFailure) => Effect.try({
126878
126946
  timeout: WORKSPACE_INDEX_SCAN_TIMEOUT
126879
126947
  })
126880
126948
  }), Effect.withSpan("WorkspaceSearchIndex.waitForScan"));
126881
- const make$24 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSearch = false) {
126949
+ const make$26 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSearch = false) {
126882
126950
  const finder = yield* Effect.acquireRelease(createFinder(cwd, contentSearch), (finder) => Effect.try({
126883
126951
  try: () => finder.destroy(),
126884
126952
  catch: (cause) => new WorkspaceSearchIndexDestroyFailed({
@@ -127018,14 +127086,14 @@ const make$24 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSe
127018
127086
  * workspace root. WorkspaceSearchIndexMap owns memoization and idle cleanup;
127019
127087
  * using a default cwd here would mix resources from different workspaces.
127020
127088
  */
127021
- const layer$18 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$24(cwd));
127089
+ const layer$18 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$26(cwd));
127022
127090
  var WorkspaceSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceSearchIndexMap", {
127023
127091
  lookup: layer$18,
127024
127092
  idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
127025
127093
  }) {};
127026
127094
  /** Content indexing is allocated only when workspace content search is used. */
127027
127095
  var WorkspaceContentSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceContentSearchIndexMap", {
127028
- lookup: (cwd) => Layer.effect(WorkspaceSearchIndex, make$24(cwd, true)),
127096
+ lookup: (cwd) => Layer.effect(WorkspaceSearchIndex, make$26(cwd, true)),
127029
127097
  idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
127030
127098
  }) {};
127031
127099
  //#endregion
@@ -127087,7 +127155,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu
127087
127155
  if (!input.cwd) return yield* new WorkspaceEntriesCurrentProjectRequiredError({ partialPath: input.partialPath });
127088
127156
  return path.resolve(expandHomePath$1(input.cwd, path), input.partialPath);
127089
127157
  });
127090
- const make$23 = Effect.gen(function* () {
127158
+ const make$25 = Effect.gen(function* () {
127091
127159
  const path = yield* Path$1.Path;
127092
127160
  const workspacePaths = yield* WorkspacePaths;
127093
127161
  const contentSearchIndexes = yield* WorkspaceContentSearchIndexMap;
@@ -127169,7 +127237,7 @@ const make$23 = Effect.gen(function* () {
127169
127237
  searchContents
127170
127238
  });
127171
127239
  });
127172
- const layer$17 = Layer.effect(WorkspaceEntries, make$23).pipe(Layer.provide(WorkspaceSearchIndexMap.layer), Layer.provide(WorkspaceContentSearchIndexMap.layer));
127240
+ const layer$17 = Layer.effect(WorkspaceEntries, make$25).pipe(Layer.provide(WorkspaceSearchIndexMap.layer), Layer.provide(WorkspaceContentSearchIndexMap.layer));
127173
127241
  //#endregion
127174
127242
  //#region src/workspace/WorkspaceFileSystem.ts
127175
127243
  /**
@@ -127228,7 +127296,7 @@ Schema$1.Union([
127228
127296
  ]);
127229
127297
  /** Service tag for workspace file operations. */
127230
127298
  var WorkspaceFileSystem = class extends Context.Service()("@p4code/cli/workspace/WorkspaceFileSystem") {};
127231
- const make$22 = Effect.gen(function* () {
127299
+ const make$24 = Effect.gen(function* () {
127232
127300
  const fileSystem = yield* FileSystem.FileSystem;
127233
127301
  const path = yield* Path$1.Path;
127234
127302
  const workspacePaths = yield* WorkspacePaths;
@@ -127372,7 +127440,7 @@ const make$22 = Effect.gen(function* () {
127372
127440
  writeFile
127373
127441
  });
127374
127442
  });
127375
- const layer$16 = Layer.effect(WorkspaceFileSystem, make$22);
127443
+ const layer$16 = Layer.effect(WorkspaceFileSystem, make$24);
127376
127444
  //#endregion
127377
127445
  //#region src/vcs/VcsStatusBroadcaster.ts
127378
127446
  const DEFAULT_VCS_STATUS_REFRESH_INTERVAL = Duration.seconds(30);
@@ -127454,7 +127522,7 @@ const autoPullPolicyLayer = Layer.effect(VcsAutoPullPolicy, Effect.gen(function*
127454
127522
  return resolveProjectAutoPull(yield* settingsService.getSettings, project.value.id);
127455
127523
  }, Effect.orElseSucceed(() => false)) };
127456
127524
  }));
127457
- const make$21 = Effect.gen(function* () {
127525
+ const make$23 = Effect.gen(function* () {
127458
127526
  const autoPullPolicy = yield* VcsAutoPullPolicy;
127459
127527
  const workflow = yield* GitWorkflowService;
127460
127528
  const fs = yield* FileSystem.FileSystem;
@@ -127713,7 +127781,7 @@ const make$21 = Effect.gen(function* () {
127713
127781
  streamStatus
127714
127782
  });
127715
127783
  });
127716
- const layer$15 = Layer.effect(VcsStatusBroadcaster, make$21);
127784
+ const layer$15 = Layer.effect(VcsStatusBroadcaster, make$23);
127717
127785
  //#endregion
127718
127786
  //#region src/vcs/VcsProvisioningService.ts
127719
127787
  var VcsProvisioningService = class extends Context.Service()("@p4code/cli/vcs/VcsProvisioningService") {};
@@ -127726,7 +127794,7 @@ function resolveRequestedKind(kind) {
127726
127794
  }));
127727
127795
  return Effect.succeed(kind);
127728
127796
  }
127729
- const make$20 = Effect.gen(function* () {
127797
+ const make$22 = Effect.gen(function* () {
127730
127798
  const registry = yield* VcsDriverRegistry;
127731
127799
  const initRepository = Effect.fn("VcsProvisioningService.initRepository")(function* (input) {
127732
127800
  const kind = yield* resolveRequestedKind(input.kind);
@@ -127734,11 +127802,11 @@ const make$20 = Effect.gen(function* () {
127734
127802
  });
127735
127803
  return VcsProvisioningService.of({ initRepository });
127736
127804
  });
127737
- const layer$14 = Layer.effect(VcsProvisioningService, make$20);
127805
+ const layer$14 = Layer.effect(VcsProvisioningService, make$22);
127738
127806
  //#endregion
127739
127807
  //#region src/review/ReviewService.ts
127740
127808
  var ReviewService = class extends Context.Service()("@p4code/cli/review/ReviewService") {};
127741
- const make$19 = Effect.gen(function* () {
127809
+ const make$21 = Effect.gen(function* () {
127742
127810
  const config = yield* ServerConfig$1;
127743
127811
  const fileSystem = yield* FileSystem.FileSystem;
127744
127812
  const path = yield* Path$1.Path;
@@ -127794,7 +127862,7 @@ const make$19 = Effect.gen(function* () {
127794
127862
  });
127795
127863
  return ReviewService.of({ getDiffPreview });
127796
127864
  });
127797
- const layer$13 = Layer.effect(ReviewService, make$19);
127865
+ const layer$13 = Layer.effect(ReviewService, make$21);
127798
127866
  //#endregion
127799
127867
  //#region src/diagnostics/ProcessDiagnostics.ts
127800
127868
  const PROCESS_QUERY_TIMEOUT_MS = 1e3;
@@ -128089,7 +128157,7 @@ function assertDescendantPid(pid) {
128089
128157
  }));
128090
128158
  }));
128091
128159
  }
128092
- const make$18 = Effect.gen(function* () {
128160
+ const make$20 = Effect.gen(function* () {
128093
128161
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
128094
128162
  const read = Effect.gen(function* () {
128095
128163
  const readAt = yield* DateTime.now;
@@ -128133,7 +128201,7 @@ const make$18 = Effect.gen(function* () {
128133
128201
  signal
128134
128202
  });
128135
128203
  });
128136
- const layer$12 = Layer.effect(ProcessDiagnostics, make$18);
128204
+ const layer$12 = Layer.effect(ProcessDiagnostics, make$20);
128137
128205
  //#endregion
128138
128206
  //#region src/diagnostics/ProcessResourceMonitor.ts
128139
128207
  const SAMPLE_INTERVAL_MS = 5e3;
@@ -128284,7 +128352,7 @@ function aggregateProcessResourceHistory(input) {
128284
128352
  }) : Option.none()
128285
128353
  };
128286
128354
  }
128287
- const make$17 = Effect.gen(function* () {
128355
+ const make$19 = Effect.gen(function* () {
128288
128356
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
128289
128357
  const state = yield* Ref.make({
128290
128358
  samples: [],
@@ -128333,7 +128401,7 @@ const make$17 = Effect.gen(function* () {
128333
128401
  });
128334
128402
  return ProcessResourceMonitor.of({ readHistory });
128335
128403
  });
128336
- const layer$11 = Layer.effect(ProcessResourceMonitor, make$17);
128404
+ const layer$11 = Layer.effect(ProcessResourceMonitor, make$19);
128337
128405
  //#endregion
128338
128406
  //#region src/diagnostics/TraceDiagnostics.ts
128339
128407
  var TraceFileReadError = class extends Schema$1.TaggedErrorClass()("TraceFileReadError", {
@@ -128581,7 +128649,7 @@ function readTraceFile(fileSystem, path) {
128581
128649
  cause
128582
128650
  })) }));
128583
128651
  }
128584
- const make$16 = Effect.gen(function* () {
128652
+ const make$18 = Effect.gen(function* () {
128585
128653
  const fileSystem = yield* FileSystem.FileSystem;
128586
128654
  const read = Effect.fn("TraceDiagnostics.read")(function* (options) {
128587
128655
  const readAt = options.readAt ?? (yield* DateTime.now);
@@ -128625,7 +128693,7 @@ const make$16 = Effect.gen(function* () {
128625
128693
  });
128626
128694
  return TraceDiagnostics.of({ read });
128627
128695
  });
128628
- const layer$10 = Layer.effect(TraceDiagnostics, make$16);
128696
+ const layer$10 = Layer.effect(TraceDiagnostics, make$18);
128629
128697
  function readTraceDiagnostics(options) {
128630
128698
  return Effect.gen(function* () {
128631
128699
  return yield* (yield* TraceDiagnostics).read(options);
@@ -128660,7 +128728,7 @@ function snapshotFromDetail(link, detail, syncedAt) {
128660
128728
  mergeability: detail.mergeability
128661
128729
  };
128662
128730
  }
128663
- const make$15 = Effect.gen(function* () {
128731
+ const make$17 = Effect.gen(function* () {
128664
128732
  const engine = yield* OrchestrationEngineService;
128665
128733
  const projections = yield* ProjectionSnapshotQuery;
128666
128734
  const pullRequests = yield* PullRequestService;
@@ -128754,7 +128822,7 @@ const make$15 = Effect.gen(function* () {
128754
128822
  };
128755
128823
  });
128756
128824
  var PullRequestSyncReactor = class extends Context.Service()("@p4code/cli/orchestration/Layers/PullRequestSyncReactor") {};
128757
- const PullRequestSyncReactorLive = Layer.effect(PullRequestSyncReactor, make$15);
128825
+ const PullRequestSyncReactorLive = Layer.effect(PullRequestSyncReactor, make$17);
128758
128826
  //#endregion
128759
128827
  //#region src/sourceControl/SourceControlDiscovery.ts
128760
128828
  const VCS_PROBES = [{
@@ -128773,7 +128841,7 @@ const VCS_PROBES = [{
128773
128841
  installHint: "Install Jujutsu with `brew install jj` or from https://github.com/jj-vcs/jj."
128774
128842
  }];
128775
128843
  var SourceControlDiscovery = class extends Context.Service()("@p4code/cli/sourceControl/SourceControlDiscovery") {};
128776
- const make$14 = Effect.gen(function* () {
128844
+ const make$16 = Effect.gen(function* () {
128777
128845
  const config = yield* ServerConfig$1;
128778
128846
  const process = yield* VcsProcess;
128779
128847
  const sourceControlProviders = yield* SourceControlProviderRegistry;
@@ -128822,7 +128890,7 @@ const make$14 = Effect.gen(function* () {
128822
128890
  sourceControlProviders: sourceControlProviders.discover
128823
128891
  }) });
128824
128892
  });
128825
- const layer$9 = Layer.effect(SourceControlDiscovery, make$14);
128893
+ const layer$9 = Layer.effect(SourceControlDiscovery, make$16);
128826
128894
  //#endregion
128827
128895
  //#region src/sourceControl/SourceControlRepositoryService.ts
128828
128896
  const isSourceControlRepositoryError = Schema$1.is(SourceControlRepositoryError);
@@ -128855,7 +128923,7 @@ function expandHomePath(input, path) {
128855
128923
  if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
128856
128924
  return input;
128857
128925
  }
128858
- const make$13 = Effect.gen(function* () {
128926
+ const make$15 = Effect.gen(function* () {
128859
128927
  const config = yield* ServerConfig$1;
128860
128928
  const fileSystem = yield* FileSystem.FileSystem;
128861
128929
  const git = yield* GitVcsDriver;
@@ -128994,7 +129062,7 @@ const make$13 = Effect.gen(function* () {
128994
129062
  publishRepository: (input) => publishRepository(input).pipe(mapRepositoryError("publishRepository", input.provider))
128995
129063
  });
128996
129064
  });
128997
- const layer$8 = Layer.effect(SourceControlRepositoryService, make$13);
129065
+ const layer$8 = Layer.effect(SourceControlRepositoryService, make$15);
128998
129066
  //#endregion
128999
129067
  //#region src/ws.ts
129000
129068
  /** Matches `p4c hub token add`, so a token minted here and one minted there are the same thing. */
@@ -129367,6 +129435,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
129367
129435
  const mcpOAuth = yield* McpOAuth;
129368
129436
  const linearClient = yield* LinearClient;
129369
129437
  const supervisorSecrets = yield* SupervisorSecrets;
129438
+ const jevWorkspaceAdvisor = yield* JevWorkspaceAdvisor;
129370
129439
  /** Status with the key masked. The unmasked value never leaves the store. */
129371
129440
  const supervisorSecretStatuses = supervisorSecrets.status.pipe(Effect.flatMap((entries) => Effect.forEach(entries, (entry) => supervisorSecrets.read(entry.service).pipe(Effect.map((credential) => ({
129372
129441
  ...entry,
@@ -129705,7 +129774,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
129705
129774
  }),
129706
129775
  hasWorkingTreeChanges: localStatus.hasWorkingTreeChanges,
129707
129776
  modelSelection: command.modelSelection ?? currentThread?.modelSelection
129708
- }, textGeneration);
129777
+ }, textGeneration, jevWorkspaceAdvisor);
129709
129778
  if (decision.mode === "local" && localStatus.isRepo && isAutoCheckoutBusy({
129710
129779
  snapshot: yield* projectionSnapshotQuery.getCommandReadModel(),
129711
129780
  threadId: command.threadId,
@@ -129729,6 +129798,24 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
129729
129798
  },
129730
129799
  createdAt: command.createdAt
129731
129800
  });
129801
+ if (decision.source === "jev") yield* orchestrationEngine.dispatch({
129802
+ type: "thread.activity.append",
129803
+ commandId: yield* serverCommandId("jev-consulted-workspace"),
129804
+ threadId: command.threadId,
129805
+ activity: {
129806
+ id: yield* serverEventId,
129807
+ tone: "info",
129808
+ kind: JEV_CONSULTED_ACTIVITY_KIND,
129809
+ turnId: null,
129810
+ summary: "Consulted with Jev",
129811
+ payload: {
129812
+ feature: "auto-workspace",
129813
+ summary: decision.mode === "worktree" ? "Chose a new worktree" : "Chose the current checkout"
129814
+ },
129815
+ createdAt: command.createdAt
129816
+ },
129817
+ createdAt: command.createdAt
129818
+ });
129732
129819
  if (decision.mode === "local") {
129733
129820
  yield* orchestrationEngine.dispatch({
129734
129821
  type: "thread.meta.update",
@@ -130573,7 +130660,7 @@ function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation, correlatio
130573
130660
  cause
130574
130661
  });
130575
130662
  }
130576
- const make$12 = Effect.gen(function* () {
130663
+ const make$14 = Effect.gen(function* () {
130577
130664
  const sql = yield* SqlClient.SqlClient;
130578
130665
  const upsertRuntimeRow = SqlSchema.void({
130579
130666
  Request: ProviderSessionRuntimeDbRowSchema,
@@ -130676,7 +130763,7 @@ const make$12 = Effect.gen(function* () {
130676
130763
  deleteByThreadId
130677
130764
  };
130678
130765
  });
130679
- const layer$7 = Layer.effect(ProviderSessionRuntimeRepository, make$12);
130766
+ const layer$7 = Layer.effect(ProviderSessionRuntimeRepository, make$14);
130680
130767
  //#endregion
130681
130768
  //#region src/provider/Layers/ProviderSessionDirectory.ts
130682
130769
  const decodeProviderDriverKindValue = Schema$1.decodeUnknownEffect(ProviderDriverKind);
@@ -131186,7 +131273,7 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
131186
131273
  });
131187
131274
  });
131188
131275
  let activeMcpSessionRegistry;
131189
- const make$11 = Effect.acquireRelease(Effect.gen(function* () {
131276
+ const make$13 = Effect.acquireRelease(Effect.gen(function* () {
131190
131277
  const broker = yield* Effect.serviceOption(ComputerUseBroker);
131191
131278
  return yield* makeWithOptions(Option.isSome(broker) ? { onRevoke: broker.value.invalidate } : {});
131192
131279
  }).pipe(Effect.tap((registry) => Effect.sync(() => {
@@ -131194,7 +131281,7 @@ const make$11 = Effect.acquireRelease(Effect.gen(function* () {
131194
131281
  }))), (registry) => registry.revokeAll.pipe(Effect.andThen(Effect.sync(() => {
131195
131282
  if (activeMcpSessionRegistry === registry) activeMcpSessionRegistry = void 0;
131196
131283
  }))));
131197
- const layer$6 = Layer.effect(McpSessionRegistry, make$11);
131284
+ const layer$6 = Layer.effect(McpSessionRegistry, make$13);
131198
131285
  const issueActiveMcpCredential = (request) => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeThread(request.threadId).pipe(Effect.andThen(activeMcpSessionRegistry.issue(request))) : Effect.sync(() => void 0);
131199
131286
  /**
131200
131287
  * Refreshes the liveness of a thread's MCP credential. Called on every provider
@@ -132706,7 +132793,7 @@ const stringField = (record, key) => {
132706
132793
  const value = record[key];
132707
132794
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
132708
132795
  };
132709
- const make$10 = Effect.gen(function* () {
132796
+ const make$12 = Effect.gen(function* () {
132710
132797
  const linear = yield* LinearClient;
132711
132798
  return { resolve: Effect.fn("TicketResolver.resolve")(function* (reference) {
132712
132799
  const identifier = parseTicketReference(reference);
@@ -132737,7 +132824,7 @@ const make$10 = Effect.gen(function* () {
132737
132824
  };
132738
132825
  }) };
132739
132826
  });
132740
- const layer$5 = Layer.effect(TicketResolver, make$10);
132827
+ const layer$5 = Layer.effect(TicketResolver, make$12);
132741
132828
  //#endregion
132742
132829
  //#region src/mcp/toolkits/tasks/tools.ts
132743
132830
  const dependencies = [McpInvocationContext, TaskRepository];
@@ -133276,7 +133363,7 @@ const AskUserQuestionTool = Tool.make("ask_user_question", {
133276
133363
  ]
133277
133364
  }).annotate(Tool.Title, "Ask user question").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
133278
133365
  const ThreadSpawnTool = Tool.make("thread_spawn", {
133279
- description: "Start a new agent thread and send it a first message, then return its id. Use it to hand a piece of work to a fresh thread - a subtask you just planned, a job that wants its own transcript. Set fusion true to create two new threads as a separate Fusion pair and send prompt to its supervisor, which plans and directs the builder later, even when this thread already belongs to a pair. Set fusionWatcher true only for a supervisor to pair with the current thread. Both use saved Fusion role models unless overridden. Act on the user's request; no special command syntax is required. The new thread inherits this one's project, model, permission mode, interaction mode, compression and subagent policy, and every one of those can be set here instead - what you set is already in force for the first turn, so a thread never has to be corrected after it starts. Set modelSelection to run it on another model: give the model id, and leave instanceId out to keep this thread's provider instance. Once started it can be watched with thread_watch_events and changed later with thread_configure. A thread that was itself started this way cannot start another.",
133366
+ description: "Start a new agent thread and send it a first message, then return its id. Use it to hand a piece of work to a fresh thread - a subtask you just planned, a job that wants its own transcript. For activation here or a new Fusion in this chat, use thread_pair_create with no watcherThreadId so this chat becomes Supervisor and its new Builder starts empty. Set fusion true only for an explicitly separate pair to create two new threads and send prompt to its supervisor, which plans and directs the builder later, even when this thread already belongs to a pair. Set fusionWatcher true only for legacy current-chat-as-builder pairing. Both use saved Fusion role models unless overridden. Act on the user's request; no special command syntax is required. The new thread inherits this one's project, model, permission mode, interaction mode, compression and subagent policy, and every one of those can be set here instead - what you set is already in force for the first turn, so a thread never has to be corrected after it starts. Set modelSelection to run it on another model: give the model id, and leave instanceId out to keep this thread's provider instance. Once started it can be watched with thread_watch_events and changed later with thread_configure. A thread that was itself started this way cannot start another.",
133280
133367
  parameters: ThreadSpawnInput,
133281
133368
  success: ThreadSpawnResult,
133282
133369
  failure: ThreadControlToolError,
@@ -133290,7 +133377,7 @@ const ThreadSpawnTool = Tool.make("thread_spawn", {
133290
133377
  ]
133291
133378
  }).annotate(Tool.Title, "Start a thread").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
133292
133379
  const ThreadPairCreateTool = Tool.make("thread_pair_create", {
133293
- description: "Create a persisted Fusion pair between this agent session's own thread as builder and a supervisor it previously created with thread_spawn. Act on the user's request; no special command syntax is required. The current thread must not already belong to an active Fusion pair. Successful creation automatically continues the builder, so never ask the user to resend the task.",
133380
+ description: "Activate Fusion here: call with no watcherThreadId to retain this chat and its history as Supervisor and create a new Builder with no messages or provider context. Builder stays idle until you send thread_advise. Use the returned implementerThreadId for the phase plan and advice. No transcript is copied. Requires explicit user authorization and a standalone current thread. Only an explicitly separate pair should use thread_spawn with fusion true. Supplying watcherThreadId retains legacy current-chat-as-builder pairing.",
133294
133381
  parameters: ThreadPairCreateInput,
133295
133382
  success: ThreadPairCreateResult,
133296
133383
  failure: ThreadControlToolError,
@@ -133298,11 +133385,14 @@ const ThreadPairCreateTool = Tool.make("thread_pair_create", {
133298
133385
  McpInvocationContext,
133299
133386
  OrchestrationEngineService,
133300
133387
  McpSessionRegistry,
133388
+ ProjectionThreadRepository,
133389
+ ProjectionSnapshotQuery,
133390
+ ServerSettingsService,
133301
133391
  Crypto.Crypto
133302
133392
  ]
133303
133393
  }).annotate(Tool.Title, "Create a Fusion pair").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
133304
133394
  const ThreadPairDetachTool = Tool.make("thread_pair_detach", {
133305
- description: "Detach this agent session's active Fusion pair, stopping future automatic supervisor reviews while preserving both threads. The session must be the pair's implementer and must have created its supervisor through thread_spawn.",
133395
+ description: "Detach this agent session's active Fusion pair, stopping future automatic supervisor reviews while preserving both threads. The session must belong to the pair and must have created its other thread.",
133306
133396
  parameters: ThreadPairDetachInput,
133307
133397
  success: ThreadPairDetachResult,
133308
133398
  failure: ThreadControlToolError,
@@ -133727,6 +133817,74 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
133727
133817
  };
133728
133818
  }),
133729
133819
  thread_pair_create: (input) => Effect.gen(function* () {
133820
+ if (input.watcherThreadId === void 0) {
133821
+ const invocation = yield* requireThreadSpawn(true);
133822
+ const reject = (detail) => new ThreadControlRejectedError({
133823
+ threadId: invocation.threadId,
133824
+ commandType: "thread-pair.create",
133825
+ detail
133826
+ });
133827
+ if ((yield* (yield* ProjectionSnapshotQuery).getCommandReadModel().pipe(Effect.mapError((cause) => reject(cause.message)))).threadPairs?.some((pair) => pair.detachedAt === null && (pair.implementerThreadId === invocation.threadId || pair.watcherThreadId === invocation.threadId))) return yield* reject("Current thread already belongs to an active Fusion pair.");
133828
+ const current = yield* (yield* ProjectionThreadRepository).getById({ threadId: invocation.threadId }).pipe(Effect.mapError((cause) => reject(cause.message)));
133829
+ if (Option.isNone(current) || current.value.deletedAt !== null) return yield* reject("Current thread does not exist.");
133830
+ const settings = yield* (yield* ServerSettingsService).getSettings.pipe(Effect.mapError((cause) => reject(cause.message)));
133831
+ const crypto = yield* Crypto.Crypto;
133832
+ const implementerThreadId = ThreadId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
133833
+ const pairId = ThreadPairId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
133834
+ const createdAt = DateTime.formatIso(yield* DateTime.now);
133835
+ const template = current.value;
133836
+ yield* dispatchControl({
133837
+ type: "thread.create",
133838
+ commandId: yield* newCommandId,
133839
+ threadId: implementerThreadId,
133840
+ projectId: template.projectId,
133841
+ title: `Implement: ${template.title}`,
133842
+ modelSelection: settings.fusionBuilderModelSelection ?? template.modelSelection,
133843
+ runtimeMode: template.runtimeMode,
133844
+ interactionMode: template.interactionMode,
133845
+ compressMode: template.compressMode,
133846
+ unpromptedSubagents: template.unpromptedSubagents === 1,
133847
+ branch: template.branch,
133848
+ worktreePath: template.worktreePath,
133849
+ createdAt
133850
+ }, invocation.threadId);
133851
+ yield* dispatchControl({
133852
+ type: "thread-pair.create",
133853
+ commandId: yield* newCommandId,
133854
+ pairId,
133855
+ implementerThreadId,
133856
+ watcherThreadId: invocation.threadId,
133857
+ ...input.gateTimeoutMs === void 0 ? {} : { gateTimeoutMs: input.gateTimeoutMs },
133858
+ createdAt
133859
+ }, invocation.threadId);
133860
+ const registry = yield* McpSessionRegistry;
133861
+ yield* registry.recordSpawnedThread({
133862
+ providerSessionId: invocation.providerSessionId,
133863
+ threadId: implementerThreadId
133864
+ });
133865
+ yield* registry.setFusionRole({
133866
+ threadId: implementerThreadId,
133867
+ role: "implementer"
133868
+ });
133869
+ yield* registry.setFusionRole({
133870
+ threadId: invocation.threadId,
133871
+ role: "watcher"
133872
+ });
133873
+ const grant = {
133874
+ watcherThreadId: invocation.threadId,
133875
+ watchedThreadId: implementerThreadId
133876
+ };
133877
+ yield* registry.grantWatchThread(grant);
133878
+ yield* registry.grantAdviseThread({
133879
+ watcherThreadId: invocation.threadId,
133880
+ advisedThreadId: implementerThreadId
133881
+ });
133882
+ return {
133883
+ pairId,
133884
+ implementerThreadId,
133885
+ watcherThreadId: invocation.threadId
133886
+ };
133887
+ }
133730
133888
  const { invocation, threadId: watcherThreadId } = yield* requireThreadControlTarget(input.watcherThreadId);
133731
133889
  const crypto = yield* Crypto.Crypto;
133732
133890
  const pairId = ThreadPairId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
@@ -133768,15 +133926,16 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
133768
133926
  commandType: "thread-pair.detach",
133769
133927
  detail: `Active Fusion pair '${input.pairId}' was not found.`
133770
133928
  });
133771
- if (pair.implementerThreadId !== invocation.threadId) return yield* new ThreadControlRejectedError({
133929
+ if (pair.implementerThreadId !== invocation.threadId && pair.watcherThreadId !== invocation.threadId) return yield* new ThreadControlRejectedError({
133772
133930
  threadId: invocation.threadId,
133773
133931
  commandType: "thread-pair.detach",
133774
- detail: "This session is not the pair's implementer."
133932
+ detail: "This session is not a member of the pair."
133775
133933
  });
133776
- if (!invocation.controlThreadIds?.has(pair.watcherThreadId)) return yield* new ThreadControlRejectedError({
133934
+ const otherThreadId = pair.implementerThreadId === invocation.threadId ? pair.watcherThreadId : pair.implementerThreadId;
133935
+ if (!invocation.controlThreadIds?.has(otherThreadId)) return yield* new ThreadControlRejectedError({
133777
133936
  threadId: invocation.threadId,
133778
133937
  commandType: "thread-pair.detach",
133779
- detail: "This session did not create the pair's supervisor with thread_spawn."
133938
+ detail: "This session did not create the other thread in the pair."
133780
133939
  });
133781
133940
  const detachedAt = DateTime.formatIso(yield* DateTime.now);
133782
133941
  yield* dispatchControl({
@@ -134393,6 +134552,20 @@ var TypeSafeRequestError = class extends Data.TaggedError("TypeSafeRequestError"
134393
134552
  var TypeSafeClient = class extends Context.Service()("@p4code/cli/orchestration/triage/TypeSafeClient") {};
134394
134553
  const asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
134395
134554
  /**
134555
+ * The finite numbers out of a probability map, or nothing.
134556
+ *
134557
+ * Non-numeric and non-finite entries are dropped rather than coerced, for the
134558
+ * same reason a missing confidence is never read as zero: a rank built on an
134559
+ * invented number is worse than one built on fewer.
134560
+ */
134561
+ function readProbabilities(value) {
134562
+ const record = asRecord(value);
134563
+ if (record === void 0) return void 0;
134564
+ const probabilities = {};
134565
+ for (const [key, entry] of Object.entries(record)) if (typeof entry === "number" && Number.isFinite(entry)) probabilities[key] = entry;
134566
+ return Object.keys(probabilities).length === 0 ? void 0 : probabilities;
134567
+ }
134568
+ /**
134396
134569
  * Reads one answer, or nothing.
134397
134570
  *
134398
134571
  * A `choice` or `score` without a numeric `confidence` is rejected rather than
@@ -134407,10 +134580,16 @@ function parseTypeSafeAnswer(value) {
134407
134580
  case "choice": {
134408
134581
  const choice = record["choice"];
134409
134582
  if (typeof choice !== "string" || typeof confidence !== "number") return void 0;
134410
- return {
134583
+ const probabilities = readProbabilities(record["probabilities"]);
134584
+ return probabilities === void 0 ? {
134411
134585
  type: "choice",
134412
134586
  choice,
134413
134587
  confidence
134588
+ } : {
134589
+ type: "choice",
134590
+ choice,
134591
+ confidence,
134592
+ probabilities
134414
134593
  };
134415
134594
  }
134416
134595
  case "score": {
@@ -134551,7 +134730,7 @@ const TypeSafeToolkit = Toolkit.make(TypeSafeAskTool);
134551
134730
  /** Headroom for the envelope and for the estimate's own error. */
134552
134731
  const RESERVE_TOKENS = 2e3;
134553
134732
  /** One question per call, so the id is fixed rather than invented. */
134554
- const QUESTION_ID = "question";
134733
+ const QUESTION_ID$1 = "question";
134555
134734
  const requestTokens = (input) => estimateTokens(input.data) + estimateTokens(input.instructions) + estimateTokens(JSON.stringify(input.criteria));
134556
134735
  const TypeSafeToolkitHandlersLive = TypeSafeToolkit.toLayer({ typesafe_ask: (input) => Effect.gen(function* () {
134557
134736
  const tokens = requestTokens(input);
@@ -134565,7 +134744,7 @@ const TypeSafeToolkitHandlersLive = TypeSafeToolkit.toLayer({ typesafe_ask: (inp
134565
134744
  model: settings?.fusionReviewTriage.triageModel ?? "jev-latest",
134566
134745
  state: input.data,
134567
134746
  question: {
134568
- id: QUESTION_ID,
134747
+ id: QUESTION_ID$1,
134569
134748
  type: input.type,
134570
134749
  instructions: input.instructions,
134571
134750
  criteria: input.criteria
@@ -136230,7 +136409,7 @@ const COMPLETION_SWEEP_BATCH_SIZE = 25;
136230
136409
  const COMPLETION_SWEEP_INTERVAL = Duration.minutes(1);
136231
136410
  const COMPLETION_PR_TIMEOUT = Duration.seconds(10);
136232
136411
  const MILLISECONDS_PER_DAY = 1440 * 60 * 1e3;
136233
- const make$9 = Effect.gen(function* () {
136412
+ const make$11 = Effect.gen(function* () {
136234
136413
  const sql = yield* SqlClient.SqlClient;
136235
136414
  const settings = yield* ServerSettingsService;
136236
136415
  const git = yield* GitManager;
@@ -136317,7 +136496,7 @@ const make$9 = Effect.gen(function* () {
136317
136496
  };
136318
136497
  });
136319
136498
  var ThreadCompletionReactor = class extends Context.Service()("@p4code/cli/orchestration/Layers/ThreadCompletionReactor") {};
136320
- const ThreadCompletionReactorLive = Layer.effect(ThreadCompletionReactor, make$9);
136499
+ const ThreadCompletionReactorLive = Layer.effect(ThreadCompletionReactor, make$11);
136321
136500
  //#endregion
136322
136501
  //#region src/orchestration/Services/ScheduledTaskReactor.ts
136323
136502
  /**
@@ -136509,7 +136688,7 @@ const decodeReportStamp = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(R
136509
136688
  const decodeTurns = Schema$1.decodeUnknownEffect(Schema$1.Array(TurnRow));
136510
136689
  const encodeReport = Schema$1.encodeEffect(Schema$1.UnknownFromJsonString);
136511
136690
  /** Reads existing projections only; observation never dispatches orchestration commands. */
136512
- const make$8 = Effect.gen(function* () {
136691
+ const make$10 = Effect.gen(function* () {
136513
136692
  const sql = yield* SqlClient.SqlClient;
136514
136693
  const fs = yield* FileSystem.FileSystem;
136515
136694
  const path = yield* Path$1.Path;
@@ -136583,7 +136762,7 @@ const make$8 = Effect.gen(function* () {
136583
136762
  };
136584
136763
  });
136585
136764
  const layer$1 = Layer.effectDiscard(Effect.gen(function* () {
136586
- yield* (yield* make$8).start;
136765
+ yield* (yield* make$10).start;
136587
136766
  }));
136588
136767
  //#endregion
136589
136768
  //#region src/orchestration/Services/RuntimeReceiptBus.ts
@@ -137171,7 +137350,7 @@ function runtimeEventToActivities(event, taskTitle, compressMode) {
137171
137350
  }
137172
137351
  return [];
137173
137352
  }
137174
- const make$7 = Effect.gen(function* () {
137353
+ const make$9 = Effect.gen(function* () {
137175
137354
  const crypto = yield* Crypto.Crypto;
137176
137355
  const orchestrationEngine = yield* OrchestrationEngineService;
137177
137356
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
@@ -137804,7 +137983,7 @@ const make$7 = Effect.gen(function* () {
137804
137983
  drain: worker.drain
137805
137984
  };
137806
137985
  });
137807
- const ProviderRuntimeIngestionLive = Layer.effect(ProviderRuntimeIngestionService, make$7).pipe(Layer.provide(ProjectionTurnRepositoryLive), Layer.provide(layer$86));
137986
+ const ProviderRuntimeIngestionLive = Layer.effect(ProviderRuntimeIngestionService, make$9).pipe(Layer.provide(ProjectionTurnRepositoryLive), Layer.provide(layer$86));
137808
137987
  //#endregion
137809
137988
  //#region src/provider/userInvokedSkills.ts
137810
137989
  /**
@@ -137926,6 +138105,9 @@ const expandUserInvokedSkill = Effect.fnUntraced(function* (input) {
137926
138105
  });
137927
138106
  });
137928
138107
  //#endregion
138108
+ //#region src/orchestration/Services/JevToolPrefetch.ts
138109
+ var JevToolPrefetch = class extends Context.Service()("@p4code/cli/orchestration/Services/JevToolPrefetch") {};
138110
+ //#endregion
137929
138111
  //#region src/orchestration/Layers/ProviderCommandReactor.ts
137930
138112
  const isProviderAdapterRequestError = Schema$1.is(ProviderAdapterRequestError);
137931
138113
  const isProviderDriverKind = Schema$1.is(ProviderDriverKind);
@@ -138080,13 +138262,14 @@ function resolvePendingWorkspaceCleanupGroups(input) {
138080
138262
  }
138081
138263
  return groups;
138082
138264
  }
138083
- const make$6 = Effect.gen(function* () {
138265
+ const make$8 = Effect.gen(function* () {
138084
138266
  const compactingThreads = /* @__PURE__ */ new Map();
138085
138267
  const crypto = yield* Crypto.Crypto;
138086
138268
  const orchestrationEngine = yield* OrchestrationEngineService;
138087
138269
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
138088
138270
  const providerService = yield* ProviderService;
138089
138271
  const providerRegistry = yield* ProviderRegistry;
138272
+ const jevToolPrefetch = yield* JevToolPrefetch;
138090
138273
  const gitWorkflow = yield* GitWorkflowService;
138091
138274
  const threadWorkspaceLifecycle = yield* ThreadWorkspaceLifecycleService;
138092
138275
  const vcsStatusBroadcaster = yield* VcsStatusBroadcaster;
@@ -138148,6 +138331,27 @@ const make$6 = Effect.gen(function* () {
138148
138331
  },
138149
138332
  createdAt: input.createdAt
138150
138333
  })));
138334
+ const appendJevConsultedActivity = (input) => Effect.all({
138335
+ commandId: serverCommandId("jev-consulted-activity"),
138336
+ eventId: serverEventId()
138337
+ }).pipe(Effect.flatMap(({ commandId, eventId }) => orchestrationEngine.dispatch({
138338
+ type: "thread.activity.append",
138339
+ commandId,
138340
+ threadId: input.threadId,
138341
+ activity: {
138342
+ id: eventId,
138343
+ tone: "info",
138344
+ kind: JEV_CONSULTED_ACTIVITY_KIND,
138345
+ summary: "Consulted with Jev",
138346
+ payload: {
138347
+ feature: input.feature,
138348
+ summary: input.summary
138349
+ },
138350
+ turnId: input.turnId,
138351
+ createdAt: input.createdAt
138352
+ },
138353
+ createdAt: input.createdAt
138354
+ })), Effect.catchCause(() => Effect.void));
138151
138355
  /**
138152
138356
  * A stop otherwise leaves nothing behind: the only row the
138153
138357
  * timeline ever got was the failure case above, and the turn fold's "You
@@ -138668,10 +138872,47 @@ const make$6 = Effect.gen(function* () {
138668
138872
  if (levelChangedMidSession) threadSessionRulesetModes.set(input.threadId, compressMode);
138669
138873
  const chatInput = isChatProject(thread.projectId) && activeSession?.provider !== "opencode" && activeSession?.provider !== "claudeAgent" && thread.messages.filter((message) => message.role === "user").length === 1 ? [P4_CHAT_SYSTEM_PROMPT, inputWithStructuredQuestionPolicy].filter(Boolean).join("\n\n") : inputWithStructuredQuestionPolicy;
138670
138874
  const inputWithCompressSuffix = chatInput !== void 0 && compressSuffix !== void 0 ? `${chatInput}\n\n${compressSuffix}` : chatInput;
138875
+ const prefetchProvider = (yield* providerRegistry.getProviders).find((snapshot) => snapshot.instanceId === modelForTurn.instanceId);
138876
+ yield* Effect.logDebug("jev prefetch evaluated", {
138877
+ threadId: input.threadId,
138878
+ instanceId: modelForTurn.instanceId,
138879
+ providerFound: prefetchProvider !== void 0,
138880
+ catalogSize: (prefetchProvider?.skills.length ?? 0) + (prefetchProvider?.slashCommands.length ?? 0),
138881
+ hasInput: inputWithCompressSuffix !== void 0
138882
+ });
138883
+ if (prefetchProvider === void 0) yield* Effect.logDebug("jev prefetch skipped", {
138884
+ reason: "provider not registered",
138885
+ instanceId: modelForTurn.instanceId
138886
+ });
138887
+ const prefetch = inputWithCompressSuffix === void 0 || prefetchProvider === void 0 ? void 0 : yield* jevToolPrefetch.hintFor({
138888
+ request: input.messageText,
138889
+ skills: prefetchProvider.skills,
138890
+ ...activeSession?.cwd ? { cwd: activeSession.cwd } : {},
138891
+ compact: compressMode !== "off",
138892
+ maxChars: Math.max(0, PROVIDER_SEND_TURN_MAX_INPUT_CHARS - inputWithCompressSuffix.length - 2),
138893
+ catalog: [...prefetchProvider.skills.map((skill) => ({
138894
+ kind: "skill",
138895
+ name: skill.name,
138896
+ description: skill.shortDescription ?? skill.description,
138897
+ enabled: skill.enabled
138898
+ })), ...prefetchProvider.slashCommands.map((command) => ({
138899
+ kind: "command",
138900
+ name: command.name,
138901
+ description: command.description
138902
+ }))]
138903
+ });
138904
+ const inputWithPrefetchHint = inputWithCompressSuffix !== void 0 && prefetch !== void 0 ? `${inputWithCompressSuffix}\n\n${prefetch.hint}` : inputWithCompressSuffix;
138905
+ if (prefetch !== void 0) yield* appendJevConsultedActivity({
138906
+ threadId: input.threadId,
138907
+ turnId: null,
138908
+ createdAt: input.createdAt,
138909
+ feature: "capability-hints",
138910
+ summary: [`Suggested: ${prefetch.selected.join(", ")}`, ...prefetch.loaded?.length ? [`Preloaded: ${prefetch.loaded.join(", ")}`] : []].join("; ")
138911
+ });
138671
138912
  return {
138672
138913
  threadId: input.threadId,
138673
138914
  ...isChatProject(thread.projectId) && activeSession?.provider === "opencode" ? { systemPrompt: P4_CHAT_SYSTEM_PROMPT } : {},
138674
- ...inputWithCompressSuffix ? { input: inputWithCompressSuffix } : {},
138915
+ ...inputWithPrefetchHint ? { input: inputWithPrefetchHint } : {},
138675
138916
  ...providerAttachments.length > 0 ? { attachments: providerAttachments } : {},
138676
138917
  ...modelForTurn !== void 0 ? { modelSelection: modelForTurn } : {},
138677
138918
  ...input.interactionMode !== void 0 ? { interactionMode: input.interactionMode } : {},
@@ -139121,7 +139362,7 @@ const make$6 = Effect.gen(function* () {
139121
139362
  drain: Effect.all([worker.drain, forceStopDrain], { discard: true }).pipe(Effect.asVoid)
139122
139363
  };
139123
139364
  });
139124
- const ProviderCommandReactorLive = Layer.effect(ProviderCommandReactor, make$6);
139365
+ const ProviderCommandReactorLive = Layer.effect(ProviderCommandReactor, make$8);
139125
139366
  //#endregion
139126
139367
  //#region src/checkpointing/Diffs.ts
139127
139368
  function parseTurnDiffFilesFromUnifiedDiff(diff) {
@@ -139151,7 +139392,7 @@ function checkpointStatusFromRuntime(status) {
139151
139392
  default: return "ready";
139152
139393
  }
139153
139394
  }
139154
- const make$5 = Effect.gen(function* () {
139395
+ const make$7 = Effect.gen(function* () {
139155
139396
  const randomUUID = (yield* Crypto.Crypto).randomUUIDv4;
139156
139397
  const serverEventId = randomUUID.pipe(Effect.map(EventId.make));
139157
139398
  const serverCommandId = (tag) => randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`)));
@@ -139633,7 +139874,7 @@ const make$5 = Effect.gen(function* () {
139633
139874
  drain: worker.drain
139634
139875
  };
139635
139876
  });
139636
- const CheckpointReactorLive = Layer.effect(CheckpointReactor, make$5);
139877
+ const CheckpointReactorLive = Layer.effect(CheckpointReactor, make$7);
139637
139878
  //#endregion
139638
139879
  //#region src/orchestration/Services/FusionReviewTriage.ts
139639
139880
  var FusionReviewTriageError = class extends Data.TaggedError("FusionReviewTriageError") {};
@@ -139704,7 +139945,7 @@ function decideFromAnswer(answer, minimumConfidence) {
139704
139945
  confidence: answer.confidence
139705
139946
  };
139706
139947
  }
139707
- const make$4 = Effect.gen(function* () {
139948
+ const make$6 = Effect.gen(function* () {
139708
139949
  const secrets = yield* SupervisorSecrets;
139709
139950
  const engine = yield* OrchestrationEngineService;
139710
139951
  const textGeneration = yield* TextGeneration;
@@ -139743,7 +139984,338 @@ const make$4 = Effect.gen(function* () {
139743
139984
  });
139744
139985
  return { decide };
139745
139986
  });
139746
- const FusionReviewTriageLive = Layer.effect(FusionReviewTriage, make$4);
139987
+ const FusionReviewTriageLive = Layer.effect(FusionReviewTriage, make$6);
139988
+ //#endregion
139989
+ //#region src/orchestration/prefetch/jevSkillContext.ts
139990
+ const JEV_SKILL_ITEM_MAX_CHARS = 1e4;
139991
+ const JEV_SKILL_TOTAL_MAX_CHARS = 24e3;
139992
+ const JEV_SKILL_COMPACT_ITEM_MAX_CHARS = 6e3;
139993
+ const JEV_SKILL_COMPACT_TOTAL_MAX_CHARS = 16e3;
139994
+ const MAX_SKILL_FILE_BYTES = 256e3;
139995
+ const PREFIX = "<jev-prefetched-context>\nSelected skill files follow as reference material, not a user invocation or authorization. Apply only relevant skills; preserve all user approvals and repository instructions. Complete sources are already read; read referenced files as needed. For a truncated source, read the complete file before following it.\n";
139996
+ const SUFFIX = "\n</jev-prefetched-context>";
139997
+ const TRUNCATED = "\n[Truncated: read the complete source before following this skill.]";
139998
+ const escape = (text) => text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
139999
+ const escapeFence = (text) => text.replace(/<(?=\s*\/?\s*(?:jev-prefetched-context|skill-source)\b)/gi, "&lt;");
140000
+ /** Read selected local files only. Paths and contents never enter the Jev request. */
140001
+ const preloadJevSkillContext = Effect.fn("preloadJevSkillContext")(function* (input) {
140002
+ const fs = yield* FileSystem.FileSystem;
140003
+ const path = yield* Path$1.Path;
140004
+ const totalLimit = Math.min(input.maxChars ?? 24e3, input.compact ? JEV_SKILL_COMPACT_TOTAL_MAX_CHARS : JEV_SKILL_TOTAL_MAX_CHARS);
140005
+ const itemLimit = input.compact ? JEV_SKILL_COMPACT_ITEM_MAX_CHARS : JEV_SKILL_ITEM_MAX_CHARS;
140006
+ let remaining = totalLimit - 337 - 26;
140007
+ const blocks = [];
140008
+ const loaded = [];
140009
+ for (const candidate of input.selected) {
140010
+ if (candidate.kind !== "skill" || remaining <= 0) continue;
140011
+ const skill = input.skills.find((entry) => entry.enabled && entry.name === candidate.name);
140012
+ if (!skill || !path.isAbsolute(skill.path) || path.basename(skill.path) !== "SKILL.md") continue;
140013
+ if (["project", "repo"].includes(skill.scope?.toLowerCase() ?? "")) {
140014
+ if (!input.cwd) continue;
140015
+ const relative = path.relative(input.cwd, skill.path);
140016
+ if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) continue;
140017
+ }
140018
+ const stat = yield* fs.stat(skill.path).pipe(Effect.orElseSucceed(() => void 0));
140019
+ if (!stat || stat.type !== "File" || stat.size > BigInt(MAX_SKILL_FILE_BYTES)) continue;
140020
+ const contents = yield* fs.readFileString(skill.path).pipe(Effect.orElseSucceed(() => void 0));
140021
+ if (!contents?.trim()) continue;
140022
+ const frontmatter = parseMarkdownFrontmatter(contents);
140023
+ if (frontmatter.kind === "malformed" || frontmatter.kind === "parsed" && frontmatter.disableModelInvocation === true) continue;
140024
+ const header = `\n<skill-source name="${escape(skill.name)}" path="${escape(skill.path)}">\n`;
140025
+ const footer = "\n</skill-source>";
140026
+ const budget = Math.min(itemLimit, remaining) - header.length - 16;
140027
+ if (budget <= 67) continue;
140028
+ const escaped = escapeFence(contents);
140029
+ const block = `${header}${escaped.length <= budget ? escaped : `${escaped.slice(0, budget - 67)}${TRUNCATED}`}${footer}`;
140030
+ blocks.push(block);
140031
+ loaded.push(skill.name);
140032
+ remaining -= block.length;
140033
+ }
140034
+ return {
140035
+ context: blocks.length ? `${PREFIX}${blocks.join("")}${SUFFIX}` : "",
140036
+ loaded
140037
+ };
140038
+ });
140039
+ //#endregion
140040
+ //#region src/orchestration/prefetch/jevPrefetch.ts
140041
+ /** Use the service's current Jev model. */
140042
+ const JEV_PREFETCH_MODEL = "jev-latest";
140043
+ /** Enough of the request to rank against, without sending a whole essay. */
140044
+ const JEV_PREFETCH_REQUEST_MAX_CHARS = 4e3;
140045
+ /** The option that means "none of these", so the ranker can decline. */
140046
+ const JEV_PREFETCH_NONE_CHOICE = "none";
140047
+ /** The one question id; the answer comes back under it. */
140048
+ const JEV_PREFETCH_QUESTION_ID = "relevant_capability";
140049
+ const collapseWhitespace = (value) => value.replace(/\s+/g, " ").trim();
140050
+ const truncate = (value, maxChars) => {
140051
+ const collapsed = collapseWhitespace(value);
140052
+ return collapsed.length <= maxChars ? collapsed : `${collapsed.slice(0, maxChars - 1).trim()}…`;
140053
+ };
140054
+ /** Words worth matching on; anything shorter matches everything. */
140055
+ const MIN_LEXICAL_TOKEN_LENGTH = 3;
140056
+ const lexicalTokens = (value) => new Set(value.toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length >= MIN_LEXICAL_TOKEN_LENGTH));
140057
+ /**
140058
+ * The catalog, deduplicated, bounded and stripped to metadata.
140059
+ *
140060
+ * Entries without a description are dropped rather than sent bare: a name
140061
+ * alone gives the ranker nothing to distinguish `review` from
140062
+ * `review-animations`, and an unrankable candidate spends budget a rankable
140063
+ * one could have used. Disabled entries are dropped because naming one to the
140064
+ * model would be advertising something the user switched off.
140065
+ *
140066
+ * Past {@link JEV_PREFETCH_CATALOG_CAP} the list is shortlisted by word
140067
+ * overlap with the request rather than cut at the cap. Cutting would hand the
140068
+ * ranker whichever capabilities happen to sort first, which on a large
140069
+ * install is the same as not ranking at all; overlap is a crude signal, but it
140070
+ * is a signal, and ties keep their original order so the result stays
140071
+ * deterministic.
140072
+ */
140073
+ function buildPrefetchCatalog(entries, request = "") {
140074
+ const seen = /* @__PURE__ */ new Set();
140075
+ const kept = [];
140076
+ for (const entry of entries) {
140077
+ if (entry.enabled === false) continue;
140078
+ const name = collapseWhitespace(entry.name);
140079
+ const description = entry.description === void 0 ? "" : collapseWhitespace(entry.description);
140080
+ if (name.length === 0 || name.length > 128 || description.length === 0) continue;
140081
+ const key = `${entry.kind}:${name.toLowerCase()}`;
140082
+ if (seen.has(key)) continue;
140083
+ seen.add(key);
140084
+ kept.push({
140085
+ kind: entry.kind,
140086
+ name,
140087
+ description: truncate(description, 200)
140088
+ });
140089
+ }
140090
+ return (kept.length <= 128 ? kept : shortlistByOverlap(kept, request)).map((entry, index) => ({
140091
+ id: `c${index}`,
140092
+ ...entry
140093
+ }));
140094
+ }
140095
+ function shortlistByOverlap(entries, request) {
140096
+ const requestTokens = lexicalTokens(request);
140097
+ const scored = entries.map((entry, order) => {
140098
+ let overlap = 0;
140099
+ for (const token of lexicalTokens(`${entry.name} ${entry.description}`)) if (requestTokens.has(token)) overlap += 1;
140100
+ return {
140101
+ entry,
140102
+ order,
140103
+ overlap
140104
+ };
140105
+ });
140106
+ scored.sort((left, right) => right.overlap - left.overlap || left.order - right.order);
140107
+ return scored.slice(0, 128).sort((left, right) => left.order - right.order).map((scoredEntry) => scoredEntry.entry);
140108
+ }
140109
+ /** The request, collapsed and clipped. Nothing else is ever the state. */
140110
+ const buildPrefetchState = (request) => truncate(request, JEV_PREFETCH_REQUEST_MAX_CHARS);
140111
+ const QUESTION_INSTRUCTIONS = [
140112
+ "The state is a request a user just sent to a coding agent.",
140113
+ "Choose the one listed capability most likely needed to carry it out.",
140114
+ `Choose "${JEV_PREFETCH_NONE_CHOICE}" when none of them is needed.`
140115
+ ].join(" ");
140116
+ const criterionFor = (candidate) => `${candidate.name} (${candidate.kind}): ${candidate.description}`;
140117
+ /**
140118
+ * One question over the whole shortlist, not one per candidate.
140119
+ *
140120
+ * A choice against a criteria map is a single request whose answer already
140121
+ * ranks every option; asking each candidate separately would multiply the
140122
+ * request by the size of the catalog for a ranking the API produces anyway.
140123
+ */
140124
+ const prefetchQuestion = (candidates) => ({
140125
+ id: JEV_PREFETCH_QUESTION_ID,
140126
+ type: "choice",
140127
+ instructions: QUESTION_INSTRUCTIONS,
140128
+ criteria: {
140129
+ ...Object.fromEntries(candidates.map((candidate) => [candidate.id, criterionFor(candidate)])),
140130
+ [JEV_PREFETCH_NONE_CHOICE]: "No listed capability is needed for this request."
140131
+ }
140132
+ });
140133
+ const criterionTokens = (candidate) => estimateTokens(`${candidate.id}${criterionFor(candidate)}`);
140134
+ /**
140135
+ * As many candidates as the shared request budget can carry, in catalog order.
140136
+ *
140137
+ * The cap bounds the count and this bounds the size; both are needed, because
140138
+ * 128 candidates with long descriptions can exceed the budget that 128 short
140139
+ * ones fit inside. Dropping the tail is deterministic and keeps the request
140140
+ * valid, which is better than sending one the API rejects.
140141
+ */
140142
+ function fitWithinBudget(state, candidates) {
140143
+ let remaining = TYPESAFE_REQUEST_BUDGET_TOKENS - TYPESAFE_BUDGET_RESERVE_TOKENS - estimateTokens(state) - estimateTokens(QUESTION_INSTRUCTIONS);
140144
+ const fitted = [];
140145
+ for (const candidate of candidates) {
140146
+ const cost = criterionTokens(candidate);
140147
+ if (cost > remaining) break;
140148
+ remaining -= cost;
140149
+ fitted.push(candidate);
140150
+ }
140151
+ return fitted;
140152
+ }
140153
+ const clampSelectionLimit = (limit) => {
140154
+ if (limit === void 0 || !Number.isFinite(limit)) return 3;
140155
+ return Math.min(5, Math.max(0, Math.floor(limit)));
140156
+ };
140157
+ /**
140158
+ * The chosen candidate first, then whatever the probability map can rank.
140159
+ *
140160
+ * `noul` is an abstention and a `score` answers a question that was not asked;
140161
+ * both give nothing. So does choosing {@link JEV_PREFETCH_NONE_CHOICE}, which
140162
+ * is the ranker saying the catalog is irrelevant and is worth honouring rather
140163
+ * than overriding with the next-best guess.
140164
+ *
140165
+ * Without a probability map only the chosen candidate comes back. Filling the
140166
+ * remaining slots from catalog order would present unranked names as ranked
140167
+ * ones, which is the one way this feature could actively mislead.
140168
+ */
140169
+ function rankPrefetchAnswer(candidates, answer, limit) {
140170
+ const selectionLimit = clampSelectionLimit(limit);
140171
+ if (answer === void 0 || answer.type !== "choice") return [];
140172
+ if (answer.choice === "none") return [];
140173
+ const chosen = candidates.find((candidate) => candidate.id === answer.choice);
140174
+ const probabilities = answer.probabilities;
140175
+ if (probabilities === void 0) return chosen === void 0 ? [] : [chosen].slice(0, selectionLimit);
140176
+ const ranked = candidates.map((candidate, order) => ({
140177
+ candidate,
140178
+ order,
140179
+ probability: probabilities[candidate.id]
140180
+ })).filter((entry) => entry.probability !== void 0 && entry.candidate.id !== chosen?.id);
140181
+ ranked.sort((left, right) => right.probability - left.probability || left.order - right.order);
140182
+ return [...chosen === void 0 ? [] : [chosen], ...ranked.map((entry) => entry.candidate)].slice(0, selectionLimit);
140183
+ }
140184
+ /**
140185
+ * The one line the model sees, or nothing at all.
140186
+ *
140187
+ * Phrased as a suggestion because that is what it is: a ranking from a model
140188
+ * that read names and descriptions, not the repository. Presenting it as an
140189
+ * instruction would let a bad ranking override the agent's own judgement,
140190
+ * which is a worse failure than a prefetch that was not useful.
140191
+ */
140192
+ function renderPrefetchHint(selected) {
140193
+ if (selected.length === 0) return void 0;
140194
+ return [
140195
+ "[jev-prefetch] These may be relevant to this request:",
140196
+ selected.map((candidate) => `- ${criterionFor(candidate)}`).join("\n"),
140197
+ "Ranked from names and descriptions alone. Use what fits and ignore the rest."
140198
+ ].join("\n");
140199
+ }
140200
+ //#endregion
140201
+ //#region src/orchestration/Layers/JevToolPrefetch.ts
140202
+ /** Why a turn got no hint, at debug level: the fail-open path is otherwise mute. */
140203
+ const skipped = (reason, catalogSize) => Effect.logDebug("jev prefetch skipped", {
140204
+ reason,
140205
+ ...catalogSize === void 0 ? {} : { catalogSize }
140206
+ }).pipe(Effect.as(void 0));
140207
+ const make$5 = Effect.gen(function* () {
140208
+ const secrets = yield* SupervisorSecrets;
140209
+ const serverSettings = yield* ServerSettingsService;
140210
+ const jev = yield* TypeSafeClient;
140211
+ const fs = yield* FileSystem.FileSystem;
140212
+ const path = yield* Path$1.Path;
140213
+ const hintFor = (input) => Effect.gen(function* () {
140214
+ const settings = yield* serverSettings.getSettings.pipe(Effect.catchCause(() => Effect.succeed(void 0)));
140215
+ if (!settings?.enableJevPrefetch) return yield* skipped("setting off");
140216
+ const request = buildPrefetchState(input.request);
140217
+ if (request.length === 0) return yield* skipped("empty request");
140218
+ const candidates = fitWithinBudget(request, buildPrefetchCatalog(input.catalog, request));
140219
+ if (candidates.length === 0) return yield* skipped("empty catalog", input.catalog.length);
140220
+ const key = yield* secrets.read("typesafe");
140221
+ if (Option.isNone(key)) return yield* skipped("no key");
140222
+ const startedAt = yield* Clock.currentTimeMillis;
140223
+ return yield* Effect.gen(function* () {
140224
+ const answer = yield* jev.ask({
140225
+ apiKey: key.value.apiKey,
140226
+ model: JEV_PREFETCH_MODEL,
140227
+ state: request,
140228
+ question: prefetchQuestion(candidates)
140229
+ });
140230
+ const selected = rankPrefetchAnswer(candidates, answer, input.limit);
140231
+ const hint = renderPrefetchHint(selected);
140232
+ if (hint === void 0) {
140233
+ yield* Effect.logDebug("jev prefetch skipped", {
140234
+ reason: "ranker declined",
140235
+ catalogSize: candidates.length,
140236
+ answer: answer?.type === "choice" ? answer.choice : answer?.type ?? "none"
140237
+ });
140238
+ return;
140239
+ }
140240
+ const maxChars = input.maxChars ?? Number.POSITIVE_INFINITY;
140241
+ if (hint.length > maxChars) return void 0;
140242
+ const { context, loaded } = yield* preloadJevSkillContext({
140243
+ selected,
140244
+ skills: input.skills ?? [],
140245
+ ...input.cwd === void 0 ? {} : { cwd: input.cwd },
140246
+ ...input.compact === void 0 ? {} : { compact: input.compact },
140247
+ maxChars: Math.max(0, maxChars - hint.length - 2)
140248
+ }).pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path$1.Path, path));
140249
+ return {
140250
+ hint: context ? `${hint}\n\n${context}` : hint,
140251
+ selected: [...new Set(selected.map((candidate) => candidate.name))],
140252
+ loaded
140253
+ };
140254
+ }).pipe(Effect.timeout(settings.jevPrefetchTimeoutMs), Effect.tapCause((cause) => Clock.currentTimeMillis.pipe(Effect.flatMap((finishedAt) => Effect.logWarning("jev prefetch did not answer", {
140255
+ elapsedMs: finishedAt - startedAt,
140256
+ cause
140257
+ })))), Effect.catchCause(() => Effect.succeed(void 0)));
140258
+ });
140259
+ return { hintFor };
140260
+ });
140261
+ const JevToolPrefetchLive = Layer.effect(JevToolPrefetch, make$5);
140262
+ //#endregion
140263
+ //#region src/orchestration/Layers/JevWorkspaceAdvisor.ts
140264
+ /**
140265
+ * This answer gates the thread's first turn. Its fixed budget is separate
140266
+ * from the configurable capability-hint timeout and shorter than the text
140267
+ * generation fallback's budget.
140268
+ */
140269
+ const JEV_WORKSPACE_TIMEOUT_MS = 2e3;
140270
+ const QUESTION_ID = "auto-workspace";
140271
+ const JEV_DECISIONS = {
140272
+ local: {
140273
+ mode: "local",
140274
+ reason: "Jev chose the current checkout for this task.",
140275
+ source: "jev"
140276
+ },
140277
+ worktree: {
140278
+ mode: "worktree",
140279
+ reason: "Jev chose an isolated worktree for this task.",
140280
+ source: "jev"
140281
+ }
140282
+ };
140283
+ /** The same brief the text generation model gets, as a two-way choice. */
140284
+ const workspaceQuestion = (hasWorkingTreeChanges) => ({
140285
+ id: QUESTION_ID,
140286
+ type: "choice",
140287
+ instructions: AUTO_WORKSPACE_QUESTION_LINES(hasWorkingTreeChanges).join("\n"),
140288
+ criteria: {
140289
+ local: "Work in the current checkout: questions, investigation, small focused edits, or work that needs the current uncommitted changes.",
140290
+ worktree: "Start an isolated worktree: independent implementation, broad changes, risky experiments, or possible interference with someone else's edits."
140291
+ }
140292
+ });
140293
+ const make$4 = Effect.gen(function* () {
140294
+ const secrets = yield* SupervisorSecrets;
140295
+ const serverSettings = yield* ServerSettingsService;
140296
+ const jev = yield* TypeSafeClient;
140297
+ const chooseWorkspace = (input) => Effect.gen(function* () {
140298
+ if (!(yield* serverSettings.getSettings.pipe(Effect.map((settings) => settings.enableJevAutoWorkspace), Effect.catchCause(() => Effect.succeed(false))))) return void 0;
140299
+ const message = input.message.trim();
140300
+ if (message.length === 0) return void 0;
140301
+ const key = yield* secrets.read("typesafe");
140302
+ if (Option.isNone(key)) return void 0;
140303
+ const startedAt = yield* Clock.currentTimeMillis;
140304
+ const answer = yield* jev.ask({
140305
+ apiKey: key.value.apiKey,
140306
+ model: JEV_PREFETCH_MODEL,
140307
+ state: message,
140308
+ question: workspaceQuestion(input.hasWorkingTreeChanges)
140309
+ }).pipe(Effect.timeout(JEV_WORKSPACE_TIMEOUT_MS), Effect.tapCause((cause) => Clock.currentTimeMillis.pipe(Effect.flatMap((finishedAt) => Effect.logWarning("jev workspace advice did not answer", {
140310
+ elapsedMs: finishedAt - startedAt,
140311
+ cause
140312
+ })))), Effect.catchCause(() => Effect.succeed(void 0)));
140313
+ if (answer?.type !== "choice") return void 0;
140314
+ return JEV_DECISIONS[answer.choice];
140315
+ });
140316
+ return { chooseWorkspace };
140317
+ });
140318
+ const JevWorkspaceAdvisorLive = Layer.effect(JevWorkspaceAdvisor, make$4);
139747
140319
  //#endregion
139748
140320
  //#region src/orchestration/Layers/FusionWatcherReactor.ts
139749
140321
  const GATE_TIMEOUT_SWEEP_INTERVAL = "10 seconds";
@@ -142033,7 +142605,7 @@ const PlatformServicesLive = Layer.unwrap(Effect.gen(function* () {
142033
142605
  return layer;
142034
142606
  }
142035
142607
  }));
142036
- const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReactorLive), Layer.provideMerge(ProviderRuntimeIngestionLive), Layer.provideMerge(ProviderCommandReactorLive), Layer.provideMerge(CheckpointReactorLive), Layer.provideMerge(ThreadDeletionReactorLive), Layer.provideMerge(FusionWatcherReactorLive.pipe(Layer.provide(FusionReviewTriageLive.pipe(Layer.provide(TypeSafeClientLive))))), Layer.provideMerge(ScheduledTaskReactorLive), Layer.provideMerge(ThreadCompletionReactorLive), Layer.provideMerge(PullRequestSyncReactorLive), Layer.provideMerge(RuntimeReceiptBusLive));
142608
+ const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReactorLive), Layer.provideMerge(ProviderRuntimeIngestionLive), Layer.provideMerge(ProviderCommandReactorLive.pipe(Layer.provide(JevToolPrefetchLive.pipe(Layer.provide(TypeSafeClientLive))))), Layer.provideMerge(CheckpointReactorLive), Layer.provideMerge(ThreadDeletionReactorLive), Layer.provideMerge(FusionWatcherReactorLive.pipe(Layer.provide(FusionReviewTriageLive.pipe(Layer.provide(TypeSafeClientLive))))), Layer.provideMerge(ScheduledTaskReactorLive), Layer.provideMerge(ThreadCompletionReactorLive), Layer.provideMerge(PullRequestSyncReactorLive), Layer.provideMerge(RuntimeReceiptBusLive));
142037
142609
  const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$7));
142038
142610
  const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
142039
142611
  const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));
@@ -142056,7 +142628,7 @@ const WorkspaceLayerLive = Layer.mergeAll(layer$70, WorkspaceEntriesLayerLive, W
142056
142628
  const ProjectFaviconResolverLayerLive = layer$65.pipe(Layer.provide(layer$70), Layer.provide(layer$66));
142057
142629
  const AuthLayerLive = layer$114.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$118));
142058
142630
  const ProviderRuntimeLayerLive = Layer.mergeAll(ProviderSessionReaperLive, ProviderHealthRefresherLive).pipe(Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive));
142059
- const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(layer$27), Layer.provideMerge(Layer.mergeAll(PullRequestServiceLive, CheckpointingLayerLive, SourceControlProviderRegistryLayerLive)), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderAuthServiceLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive, RoutedTaskRepositoryLive)), Layer.provideMerge(Layer.mergeAll(PersistenceLayerLive, layer$89)), Layer.provideMerge(layer$83), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(layer$60), Layer.provideMerge(Layer.mergeAll(layer$59, layer$72.pipe(Layer.provide(layer$85)), layer$74, layer$69)), Layer.provideMerge(layer$54), Layer.provideMerge(layer$55), Layer.provideMerge(layer$56), Layer.provideMerge(layer$57), Layer.provideMerge(layer$58)).pipe(Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(AntigravityInstallation.layer), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$62), Layer.provideMerge(layer$93.pipe(Layer.provide(layer$118))), Layer.provideMerge(SupervisorSecretsLive.pipe(Layer.provide(layer$118))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$84), Layer.provideMerge(layer$68), Layer.provideMerge(remoteComputerUseBindingsLayer.pipe(Layer.provide(layer$89))), Layer.provideMerge(layer$77), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(layer$5.pipe(Layer.provideMerge(LinearClientLive), Layer.provideMerge(Layer.mergeAll(LinearMcpClientLive, TrackerSecretsLive)), Layer.provideMerge(Layer.mergeAll(layer$90, layer$21).pipe(Layer.provideMerge(layer$91), Layer.provideMerge(layer$92))))), Layer.provideMerge(layer$118));
142631
+ const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(layer$27), Layer.provideMerge(Layer.mergeAll(PullRequestServiceLive, CheckpointingLayerLive, SourceControlProviderRegistryLayerLive)), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderAuthServiceLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive, RoutedTaskRepositoryLive)), Layer.provideMerge(Layer.mergeAll(PersistenceLayerLive, layer$89)), Layer.provideMerge(layer$83), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(layer$60), Layer.provideMerge(Layer.mergeAll(layer$59, layer$72.pipe(Layer.provide(layer$85)), layer$74, layer$69)), Layer.provideMerge(layer$54), Layer.provideMerge(layer$55), Layer.provideMerge(layer$56), Layer.provideMerge(layer$57), Layer.provideMerge(layer$58)).pipe(Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(AntigravityInstallation.layer), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$62), Layer.provideMerge(JevWorkspaceAdvisorLive.pipe(Layer.provide(TypeSafeClientLive))), Layer.provideMerge(layer$93.pipe(Layer.provide(layer$118))), Layer.provideMerge(SupervisorSecretsLive.pipe(Layer.provide(layer$118))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$84), Layer.provideMerge(layer$68), Layer.provideMerge(remoteComputerUseBindingsLayer.pipe(Layer.provide(layer$89))), Layer.provideMerge(layer$77), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(layer$5.pipe(Layer.provideMerge(LinearClientLive), Layer.provideMerge(Layer.mergeAll(LinearMcpClientLive, TrackerSecretsLive)), Layer.provideMerge(Layer.mergeAll(layer$90, layer$21).pipe(Layer.provideMerge(layer$91), Layer.provideMerge(layer$92))))), Layer.provideMerge(layer$118));
142060
142632
  const UsageLayerLive = layer$25.pipe(Layer.provide(layer$93.pipe(Layer.provide(layer$118))));
142061
142633
  const RuntimeDependenciesLive = layer$24.pipe(Layer.provideMerge(RuntimeCoreDependenciesLive)).pipe(Layer.provideMerge(UsageLayerLive), Layer.provideMerge(layer$12), Layer.provideMerge(layer$11), Layer.provideMerge(layer$10), Layer.provideMerge(layer$80), Layer.provideMerge(layer$82), Layer.provideMerge(layer$81), Layer.provide(layer$122));
142062
142634
  /**