@p4code/cli 0.2.7 → 0.2.8

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
@@ -125,7 +125,7 @@ const closeServer = (server) => {
125
125
  * NetService - Service tag for startup networking helpers.
126
126
  */
127
127
  var NetService = class extends Context.Service()("@p4code/shared/Net/NetService") {};
128
- const make$87 = () => {
128
+ const make$88 = () => {
129
129
  /**
130
130
  * Returns true when a TCP server can bind to {host, port}.
131
131
  * `EADDRNOTAVAIL` is treated as available so IPv6-absent hosts don't fail
@@ -234,10 +234,10 @@ const make$87 = () => {
234
234
  })
235
235
  };
236
236
  };
237
- const layer$79 = Layer.sync(NetService, make$87);
237
+ const layer$79 = Layer.sync(NetService, make$88);
238
238
  //#endregion
239
239
  //#region package.json
240
- var version = "0.2.7";
240
+ var version = "0.2.8";
241
241
  //#endregion
242
242
  //#region src/config.ts
243
243
  /**
@@ -258,8 +258,8 @@ var ServerConfig$1 = class extends Context.Service()("@p4code/cli/config/ServerC
258
258
  /** @deprecated Import and use `layerTest` from this module. */
259
259
  static layerTest = (cwd, baseDirOrPrefix) => layerTest$3(cwd, baseDirOrPrefix);
260
260
  };
261
- const make$86 = (config) => ServerConfig$1.of(config);
262
- const layer$78 = (config) => Layer.succeed(ServerConfig$1, make$86(config));
261
+ const make$87 = (config) => ServerConfig$1.of(config);
262
+ const layer$78 = (config) => Layer.succeed(ServerConfig$1, make$87(config));
263
263
  const deriveServerPaths = Effect.fn(function* (baseDir, devUrl, options = {}) {
264
264
  const { join } = yield* Path.Path;
265
265
  const stateDir = join(baseDir, devUrl !== void 0 && !options.baseDirIsExplicit ? "dev" : "userdata");
@@ -1005,6 +1005,7 @@ const makeEntityId = (brand) => {
1005
1005
  return TrimmedNonEmptyString.pipe(Schema$1.brand(brand));
1006
1006
  };
1007
1007
  const ThreadId = makeEntityId("ThreadId");
1008
+ const ThreadPairId = makeEntityId("ThreadPairId");
1008
1009
  const ProjectId = makeEntityId("ProjectId");
1009
1010
  /**
1010
1011
  * Identifies a task on the agent task board. Unrelated to {@link RuntimeTaskId},
@@ -1830,6 +1831,8 @@ const OrchestrationMessage = Schema$1.Struct({
1830
1831
  createdAt: IsoDateTime,
1831
1832
  updatedAt: IsoDateTime
1832
1833
  });
1834
+ const FUSION_REVIEW_PROMPT_PREFIX = "[fusion-review]";
1835
+ const FUSION_NO_OBJECTION_TEXT = "[fusion-no-objection]";
1833
1836
  const OrchestrationProposedPlanId = TrimmedNonEmptyString;
1834
1837
  const OrchestrationProposedPlan = Schema$1.Struct({
1835
1838
  id: OrchestrationProposedPlanId,
@@ -1947,10 +1950,20 @@ const OrchestrationThread = Schema$1.Struct({
1947
1950
  checkpoints: Schema$1.Array(OrchestrationCheckpointSummary),
1948
1951
  session: Schema$1.NullOr(OrchestrationSession)
1949
1952
  });
1953
+ /** Persisted relationship between two otherwise ordinary threads. */
1954
+ const OrchestrationThreadPair = Schema$1.Struct({
1955
+ id: ThreadPairId,
1956
+ implementerThreadId: ThreadId,
1957
+ watcherThreadId: ThreadId,
1958
+ lastReviewedImplementerSequence: NonNegativeInt,
1959
+ createdAt: IsoDateTime,
1960
+ detachedAt: Schema$1.NullOr(IsoDateTime)
1961
+ });
1950
1962
  const OrchestrationReadModel = Schema$1.Struct({
1951
1963
  snapshotSequence: NonNegativeInt,
1952
1964
  projects: Schema$1.Array(OrchestrationProject),
1953
1965
  threads: Schema$1.Array(OrchestrationThread),
1966
+ threadPairs: Schema$1.optional(Schema$1.Array(OrchestrationThreadPair)),
1954
1967
  updatedAt: IsoDateTime
1955
1968
  });
1956
1969
  const OrchestrationProjectShell = Schema$1.Struct({
@@ -1994,6 +2007,7 @@ const OrchestrationShellSnapshot = Schema$1.Struct({
1994
2007
  snapshotSequence: NonNegativeInt,
1995
2008
  projects: Schema$1.Array(OrchestrationProjectShell),
1996
2009
  threads: Schema$1.Array(OrchestrationThreadShell),
2010
+ threadPairs: Schema$1.optional(Schema$1.Array(OrchestrationThreadPair)),
1997
2011
  updatedAt: IsoDateTime
1998
2012
  });
1999
2013
  const OrchestrationShellStreamEvent = Schema$1.Union([
@@ -2016,6 +2030,16 @@ const OrchestrationShellStreamEvent = Schema$1.Union([
2016
2030
  kind: Schema$1.Literal("thread-removed"),
2017
2031
  sequence: NonNegativeInt,
2018
2032
  threadId: ThreadId
2033
+ }),
2034
+ Schema$1.Struct({
2035
+ kind: Schema$1.Literal("thread-pair-upserted"),
2036
+ sequence: NonNegativeInt,
2037
+ pair: OrchestrationThreadPair
2038
+ }),
2039
+ Schema$1.Struct({
2040
+ kind: Schema$1.Literal("thread-pair-removed"),
2041
+ sequence: NonNegativeInt,
2042
+ pairId: ThreadPairId
2019
2043
  })
2020
2044
  ]);
2021
2045
  const OrchestrationShellStreamItem = Schema$1.Union([
@@ -2282,6 +2306,20 @@ const ThreadSessionStopCommand = Schema$1.Struct({
2282
2306
  threadId: ThreadId,
2283
2307
  createdAt: IsoDateTime
2284
2308
  });
2309
+ const ThreadPairCreateCommand = Schema$1.Struct({
2310
+ type: Schema$1.Literal("thread-pair.create"),
2311
+ commandId: CommandId,
2312
+ pairId: ThreadPairId,
2313
+ implementerThreadId: ThreadId,
2314
+ watcherThreadId: ThreadId,
2315
+ createdAt: IsoDateTime
2316
+ });
2317
+ const ThreadPairDetachCommand = Schema$1.Struct({
2318
+ type: Schema$1.Literal("thread-pair.detach"),
2319
+ commandId: CommandId,
2320
+ pairId: ThreadPairId,
2321
+ createdAt: IsoDateTime
2322
+ });
2285
2323
  const DispatchableClientOrchestrationCommand = Schema$1.Union([
2286
2324
  ProjectCreateCommand,
2287
2325
  ProjectMetaUpdateCommand,
@@ -2304,7 +2342,9 @@ const DispatchableClientOrchestrationCommand = Schema$1.Union([
2304
2342
  ThreadApprovalRespondCommand,
2305
2343
  ThreadUserInputRespondCommand,
2306
2344
  ThreadCheckpointRevertCommand,
2307
- ThreadSessionStopCommand
2345
+ ThreadSessionStopCommand,
2346
+ ThreadPairCreateCommand,
2347
+ ThreadPairDetachCommand
2308
2348
  ]);
2309
2349
  const ClientOrchestrationCommand = Schema$1.Union([
2310
2350
  ProjectCreateCommand,
@@ -2328,7 +2368,9 @@ const ClientOrchestrationCommand = Schema$1.Union([
2328
2368
  ThreadApprovalRespondCommand,
2329
2369
  ThreadUserInputRespondCommand,
2330
2370
  ThreadCheckpointRevertCommand,
2331
- ThreadSessionStopCommand
2371
+ ThreadSessionStopCommand,
2372
+ ThreadPairCreateCommand,
2373
+ ThreadPairDetachCommand
2332
2374
  ]);
2333
2375
  const ThreadSessionSetCommand = Schema$1.Struct({
2334
2376
  type: Schema$1.Literal("thread.session.set"),
@@ -2337,6 +2379,26 @@ const ThreadSessionSetCommand = Schema$1.Struct({
2337
2379
  session: OrchestrationSession,
2338
2380
  createdAt: IsoDateTime
2339
2381
  });
2382
+ const ThreadTurnCompleteCommand = Schema$1.Struct({
2383
+ type: Schema$1.Literal("thread.turn.complete"),
2384
+ commandId: CommandId,
2385
+ threadId: ThreadId,
2386
+ turnId: Schema$1.optional(TurnId),
2387
+ state: Schema$1.Literals([
2388
+ "completed",
2389
+ "failed",
2390
+ "interrupted",
2391
+ "cancelled"
2392
+ ]),
2393
+ completedAt: IsoDateTime
2394
+ });
2395
+ const ThreadPairCursorAdvanceCommand = Schema$1.Struct({
2396
+ type: Schema$1.Literal("thread-pair.cursor.advance"),
2397
+ commandId: CommandId,
2398
+ pairId: ThreadPairId,
2399
+ implementerSequence: NonNegativeInt,
2400
+ advancedAt: IsoDateTime
2401
+ });
2340
2402
  const ThreadMessageAssistantDeltaCommand = Schema$1.Struct({
2341
2403
  type: Schema$1.Literal("thread.message.assistant.delta"),
2342
2404
  commandId: CommandId,
@@ -2390,6 +2452,8 @@ const ThreadRevertCompleteCommand = Schema$1.Struct({
2390
2452
  });
2391
2453
  const InternalOrchestrationCommand = Schema$1.Union([
2392
2454
  ThreadSessionSetCommand,
2455
+ ThreadTurnCompleteCommand,
2456
+ ThreadPairCursorAdvanceCommand,
2393
2457
  ThreadMessageAssistantDeltaCommand,
2394
2458
  ThreadMessageAssistantCompleteCommand,
2395
2459
  ThreadProposedPlanUpsertCommand,
@@ -2426,9 +2490,17 @@ const OrchestrationEventType = Schema$1.Literals([
2426
2490
  "thread.session-set",
2427
2491
  "thread.proposed-plan-upserted",
2428
2492
  "thread.turn-diff-completed",
2429
- "thread.activity-appended"
2493
+ "thread.activity-appended",
2494
+ "thread.turn-completed",
2495
+ "thread-pair.created",
2496
+ "thread-pair.detached",
2497
+ "thread-pair.cursor-advanced"
2498
+ ]);
2499
+ const OrchestrationAggregateKind = Schema$1.Literals([
2500
+ "project",
2501
+ "thread",
2502
+ "thread-pair"
2430
2503
  ]);
2431
- const OrchestrationAggregateKind = Schema$1.Literals(["project", "thread"]);
2432
2504
  const OrchestrationActorKind = Schema$1.Literals([
2433
2505
  "client",
2434
2506
  "server",
@@ -2595,6 +2667,33 @@ const ThreadSessionSetPayload$1 = Schema$1.Struct({
2595
2667
  threadId: ThreadId,
2596
2668
  session: OrchestrationSession
2597
2669
  });
2670
+ const ThreadTurnCompletedPayload = Schema$1.Struct({
2671
+ threadId: ThreadId,
2672
+ turnId: Schema$1.NullOr(TurnId),
2673
+ state: Schema$1.Literals([
2674
+ "completed",
2675
+ "failed",
2676
+ "interrupted",
2677
+ "cancelled"
2678
+ ]),
2679
+ completedAt: IsoDateTime
2680
+ });
2681
+ const ThreadPairCreatedPayload$1 = Schema$1.Struct({
2682
+ pairId: ThreadPairId,
2683
+ implementerThreadId: ThreadId,
2684
+ watcherThreadId: ThreadId,
2685
+ lastReviewedImplementerSequence: NonNegativeInt,
2686
+ createdAt: IsoDateTime
2687
+ });
2688
+ const ThreadPairDetachedPayload$1 = Schema$1.Struct({
2689
+ pairId: ThreadPairId,
2690
+ detachedAt: IsoDateTime
2691
+ });
2692
+ const ThreadPairCursorAdvancedPayload$1 = Schema$1.Struct({
2693
+ pairId: ThreadPairId,
2694
+ implementerSequence: NonNegativeInt,
2695
+ advancedAt: IsoDateTime
2696
+ });
2598
2697
  const ThreadProposedPlanUpsertedPayload$1 = Schema$1.Struct({
2599
2698
  threadId: ThreadId,
2600
2699
  proposedPlan: OrchestrationProposedPlan
@@ -2624,7 +2723,11 @@ const EventBaseFields = {
2624
2723
  sequence: NonNegativeInt,
2625
2724
  eventId: EventId,
2626
2725
  aggregateKind: OrchestrationAggregateKind,
2627
- aggregateId: Schema$1.Union([ProjectId, ThreadId]),
2726
+ aggregateId: Schema$1.Union([
2727
+ ProjectId,
2728
+ ThreadId,
2729
+ ThreadPairId
2730
+ ]),
2628
2731
  occurredAt: IsoDateTime,
2629
2732
  commandId: Schema$1.NullOr(CommandId),
2630
2733
  causationEventId: Schema$1.NullOr(EventId),
@@ -2771,6 +2874,26 @@ const OrchestrationEvent = Schema$1.Union([
2771
2874
  ...EventBaseFields,
2772
2875
  type: Schema$1.Literal("thread.activity-appended"),
2773
2876
  payload: ThreadActivityAppendedPayload$1
2877
+ }),
2878
+ Schema$1.Struct({
2879
+ ...EventBaseFields,
2880
+ type: Schema$1.Literal("thread.turn-completed"),
2881
+ payload: ThreadTurnCompletedPayload
2882
+ }),
2883
+ Schema$1.Struct({
2884
+ ...EventBaseFields,
2885
+ type: Schema$1.Literal("thread-pair.created"),
2886
+ payload: ThreadPairCreatedPayload$1
2887
+ }),
2888
+ Schema$1.Struct({
2889
+ ...EventBaseFields,
2890
+ type: Schema$1.Literal("thread-pair.detached"),
2891
+ payload: ThreadPairDetachedPayload$1
2892
+ }),
2893
+ Schema$1.Struct({
2894
+ ...EventBaseFields,
2895
+ type: Schema$1.Literal("thread-pair.cursor-advanced"),
2896
+ payload: ThreadPairCursorAdvancedPayload$1
2774
2897
  })
2775
2898
  ]);
2776
2899
  const OrchestrationThreadStreamItem = Schema$1.Union([
@@ -11565,7 +11688,7 @@ function deriveAuthClientMetadata(input) {
11565
11688
  //#endregion
11566
11689
  //#region src/auth/EnvironmentAuthPolicy.ts
11567
11690
  var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
11568
- const make$85 = Effect.gen(function* () {
11691
+ const make$86 = Effect.gen(function* () {
11569
11692
  const config = yield* ServerConfig$1;
11570
11693
  const isRemoteReachable = isRemoteReachableHost(config.host);
11571
11694
  const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
@@ -11583,7 +11706,7 @@ const make$85 = Effect.gen(function* () {
11583
11706
  };
11584
11707
  return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
11585
11708
  });
11586
- const layer$77 = Layer.effect(EnvironmentAuthPolicy, make$85);
11709
+ const layer$77 = Layer.effect(EnvironmentAuthPolicy, make$86);
11587
11710
  //#endregion
11588
11711
  //#region src/persistence/Errors.ts
11589
11712
  function summarizeSchemaIssue(issue) {
@@ -11764,7 +11887,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
11764
11887
  cause
11765
11888
  });
11766
11889
  }
11767
- const make$84 = Effect.gen(function* () {
11890
+ const make$85 = Effect.gen(function* () {
11768
11891
  const sql = yield* SqlClient.SqlClient;
11769
11892
  const createSessionRow = SqlSchema.void({
11770
11893
  Request: CreateAuthSessionInput,
@@ -11898,7 +12021,7 @@ const make$84 = Effect.gen(function* () {
11898
12021
  setLastConnectedAt
11899
12022
  };
11900
12023
  });
11901
- const layer$76 = Layer.effect(AuthSessionRepository, make$84);
12024
+ const layer$76 = Layer.effect(AuthSessionRepository, make$85);
11902
12025
  //#endregion
11903
12026
  //#region src/auth/ServerSecretStore.ts
11904
12027
  const secretStoreErrorContext = {
@@ -11965,7 +12088,7 @@ const isSecretStoreError = Schema$1.is(SecretStoreError);
11965
12088
  const isPlatformError = (value) => Predicate.isTagged(value, "PlatformError");
11966
12089
  const isSecretAlreadyExistsError = (error) => "cause" in error && isPlatformError(error.cause) && error.cause.reason._tag === "AlreadyExists";
11967
12090
  var ServerSecretStore = class extends Context.Service()("@p4code/cli/auth/ServerSecretStore") {};
11968
- const make$83 = Effect.gen(function* () {
12091
+ const make$84 = Effect.gen(function* () {
11969
12092
  const crypto = yield* Crypto.Crypto;
11970
12093
  const fileSystem = yield* FileSystem.FileSystem;
11971
12094
  const path = yield* Path.Path;
@@ -12035,7 +12158,7 @@ const make$83 = Effect.gen(function* () {
12035
12158
  remove
12036
12159
  });
12037
12160
  });
12038
- const layer$75 = Layer.effect(ServerSecretStore, make$83);
12161
+ const layer$75 = Layer.effect(ServerSecretStore, make$84);
12039
12162
  //#endregion
12040
12163
  //#region src/auth/SessionStore.ts
12041
12164
  var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
@@ -12273,7 +12396,7 @@ function toAuthClientSession(input) {
12273
12396
  current: false
12274
12397
  };
12275
12398
  }
12276
- const make$82 = Effect.gen(function* () {
12399
+ const make$83 = Effect.gen(function* () {
12277
12400
  const crypto = yield* Crypto.Crypto;
12278
12401
  const serverConfig = yield* ServerConfig$1;
12279
12402
  const secretStore = yield* ServerSecretStore;
@@ -12587,7 +12710,7 @@ const make$82 = Effect.gen(function* () {
12587
12710
  markDisconnected
12588
12711
  });
12589
12712
  });
12590
- const layer$74 = Layer.effect(SessionStore, make$82).pipe(Layer.provideMerge(layer$76));
12713
+ const layer$74 = Layer.effect(SessionStore, make$83).pipe(Layer.provideMerge(layer$76));
12591
12714
  //#endregion
12592
12715
  //#region src/persistence/AuthPairingLinks.ts
12593
12716
  const AuthPairingLinkRecord = Schema$1.Struct({
@@ -12648,7 +12771,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
12648
12771
  cause
12649
12772
  });
12650
12773
  }
12651
- const make$81 = Effect.gen(function* () {
12774
+ const make$82 = Effect.gen(function* () {
12652
12775
  const sql = yield* SqlClient.SqlClient;
12653
12776
  const createPairingLinkRow = SqlSchema.void({
12654
12777
  Request: CreateAuthPairingLinkInput,
@@ -12783,7 +12906,7 @@ const make$81 = Effect.gen(function* () {
12783
12906
  getByCredential
12784
12907
  };
12785
12908
  });
12786
- const layer$73 = Layer.effect(AuthPairingLinkRepository, make$81);
12909
+ const layer$73 = Layer.effect(AuthPairingLinkRepository, make$82);
12787
12910
  //#endregion
12788
12911
  //#region src/auth/PairingGrantStore.ts
12789
12912
  var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
@@ -12878,7 +13001,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
12878
13001
  const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
12879
13002
  const PAIRING_TOKEN_LENGTH = 12;
12880
13003
  const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
12881
- const make$80 = Effect.gen(function* () {
13004
+ const make$81 = Effect.gen(function* () {
12882
13005
  const crypto = yield* Crypto.Crypto;
12883
13006
  const config = yield* ServerConfig$1;
12884
13007
  const pairingLinks = yield* AuthPairingLinkRepository;
@@ -13076,7 +13199,7 @@ const make$80 = Effect.gen(function* () {
13076
13199
  consume
13077
13200
  });
13078
13201
  });
13079
- const layer$72 = Layer.effect(PairingGrantStore, make$80).pipe(Layer.provideMerge(layer$73));
13202
+ const layer$72 = Layer.effect(PairingGrantStore, make$81).pipe(Layer.provideMerge(layer$73));
13080
13203
  //#endregion
13081
13204
  //#region src/persistence/DatabaseSnapshot.ts
13082
13205
  /**
@@ -14831,6 +14954,69 @@ var _045_ProjectionThreadsBackgroundWork_default = Effect.gen(function* () {
14831
14954
  `;
14832
14955
  });
14833
14956
  //#endregion
14957
+ //#region src/persistence/Migrations/046_ThreadPairs.ts
14958
+ /** Persisted Fusion relationship and durable watcher cursor. */
14959
+ var _046_ThreadPairs_default = Effect.gen(function* () {
14960
+ const sql = yield* SqlClient.SqlClient;
14961
+ yield* sql`
14962
+ CREATE TABLE thread_pairs (
14963
+ pair_id TEXT PRIMARY KEY,
14964
+ implementer_thread_id TEXT NOT NULL,
14965
+ watcher_thread_id TEXT NOT NULL,
14966
+ last_reviewed_implementer_sequence INTEGER NOT NULL DEFAULT 0,
14967
+ created_at TEXT NOT NULL,
14968
+ detached_at TEXT,
14969
+ CHECK (implementer_thread_id <> watcher_thread_id),
14970
+ CHECK (last_reviewed_implementer_sequence >= 0),
14971
+ FOREIGN KEY (implementer_thread_id) REFERENCES projection_threads(thread_id),
14972
+ FOREIGN KEY (watcher_thread_id) REFERENCES projection_threads(thread_id)
14973
+ )
14974
+ `;
14975
+ yield* sql`
14976
+ CREATE UNIQUE INDEX thread_pairs_active_implementer_idx
14977
+ ON thread_pairs(implementer_thread_id)
14978
+ WHERE detached_at IS NULL
14979
+ `;
14980
+ yield* sql`
14981
+ CREATE UNIQUE INDEX thread_pairs_active_watcher_idx
14982
+ ON thread_pairs(watcher_thread_id)
14983
+ WHERE detached_at IS NULL
14984
+ `;
14985
+ yield* sql`
14986
+ CREATE TRIGGER thread_pairs_active_cross_role_insert
14987
+ BEFORE INSERT ON thread_pairs
14988
+ WHEN NEW.detached_at IS NULL AND EXISTS (
14989
+ SELECT 1
14990
+ FROM thread_pairs
14991
+ WHERE detached_at IS NULL
14992
+ AND (
14993
+ implementer_thread_id IN (NEW.implementer_thread_id, NEW.watcher_thread_id)
14994
+ OR watcher_thread_id IN (NEW.implementer_thread_id, NEW.watcher_thread_id)
14995
+ )
14996
+ )
14997
+ BEGIN
14998
+ SELECT RAISE(ABORT, 'thread already belongs to an active pair');
14999
+ END
15000
+ `;
15001
+ yield* sql`
15002
+ CREATE TRIGGER thread_pairs_active_cross_role_update
15003
+ BEFORE UPDATE OF implementer_thread_id, watcher_thread_id, detached_at ON thread_pairs
15004
+ WHEN NEW.detached_at IS NULL AND EXISTS (
15005
+ SELECT 1
15006
+ FROM thread_pairs
15007
+ WHERE pair_id <> NEW.pair_id
15008
+ AND detached_at IS NULL
15009
+ AND (
15010
+ implementer_thread_id IN (NEW.implementer_thread_id, NEW.watcher_thread_id)
15011
+ OR watcher_thread_id IN (NEW.implementer_thread_id, NEW.watcher_thread_id)
15012
+ )
15013
+ )
15014
+ BEGIN
15015
+ SELECT RAISE(ABORT, 'thread already belongs to an active pair');
15016
+ END
15017
+ `;
15018
+ });
15019
+ //#endregion
14834
15020
  //#region src/persistence/Migrations.ts
14835
15021
  /**
14836
15022
  * MigrationsLive - Migration runner with inline loader
@@ -15076,6 +15262,11 @@ const migrationEntries = [
15076
15262
  45,
15077
15263
  "ProjectionThreadsBackgroundWork",
15078
15264
  _045_ProjectionThreadsBackgroundWork_default
15265
+ ],
15266
+ [
15267
+ 46,
15268
+ "ThreadPairs",
15269
+ _046_ThreadPairs_default
15079
15270
  ]
15080
15271
  ];
15081
15272
  const makeMigrationLoader = (throughId) => Migrator.fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
@@ -15326,7 +15517,7 @@ function parseBearerToken(request) {
15326
15517
  const token = header.slice(7).trim();
15327
15518
  return token.length > 0 ? token : null;
15328
15519
  }
15329
- const make$79 = Effect.gen(function* () {
15520
+ const make$80 = Effect.gen(function* () {
15330
15521
  const policy = yield* EnvironmentAuthPolicy;
15331
15522
  const bootstrapCredentials = yield* PairingGrantStore;
15332
15523
  const sessions = yield* SessionStore;
@@ -15521,7 +15712,7 @@ const make$79 = Effect.gen(function* () {
15521
15712
  issueStartupPairingUrl
15522
15713
  });
15523
15714
  });
15524
- const layer$71 = Layer.effect(EnvironmentAuth, make$79).pipe(Layer.provideMerge(layer$72), Layer.provideMerge(layer$74), Layer.provideMerge(layer$77));
15715
+ const layer$71 = Layer.effect(EnvironmentAuth, make$80).pipe(Layer.provideMerge(layer$72), Layer.provideMerge(layer$74), Layer.provideMerge(layer$77));
15525
15716
  const storageLayer = Layer.mergeAll(layer$75, layerConfig);
15526
15717
  const runtimeLayer = layer$71.pipe(Layer.provideMerge(storageLayer));
15527
15718
  //#endregion
@@ -16418,7 +16609,7 @@ const DEFAULT_LIMITS = {
16418
16609
  windowMillis: FAILURE_WINDOW_MS,
16419
16610
  blockMillis: BLOCK_DURATION_MS
16420
16611
  };
16421
- const make$78 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
16612
+ const make$79 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
16422
16613
  const state = yield* Ref.make(initialThrottleState);
16423
16614
  return HubAuthThrottle.of({
16424
16615
  shouldRefuse: Effect.gen(function* () {
@@ -16432,7 +16623,7 @@ const make$78 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LI
16432
16623
  })
16433
16624
  });
16434
16625
  });
16435
- const layer$70 = Layer.effect(HubAuthThrottle, make$78());
16626
+ const layer$70 = Layer.effect(HubAuthThrottle, make$79());
16436
16627
  //#endregion
16437
16628
  //#region src/hub/HubAuth.ts
16438
16629
  /**
@@ -17755,7 +17946,7 @@ function stripDefaultServerSettings(current, defaults) {
17755
17946
  }
17756
17947
  return Object.is(current, defaults) ? void 0 : current;
17757
17948
  }
17758
- const make$77 = Effect.gen(function* () {
17949
+ const make$78 = Effect.gen(function* () {
17759
17950
  const { settingsPath } = yield* ServerConfig$1;
17760
17951
  const fs = yield* FileSystem.FileSystem;
17761
17952
  const pathService = yield* Path.Path;
@@ -17976,7 +18167,7 @@ const make$77 = Effect.gen(function* () {
17976
18167
  }
17977
18168
  };
17978
18169
  });
17979
- const layer$68 = Layer.effect(ServerSettingsService, make$77);
18170
+ const layer$68 = Layer.effect(ServerSettingsService, make$78);
17980
18171
  //#endregion
17981
18172
  //#region src/pathExpansion.ts
17982
18173
  /**
@@ -18350,7 +18541,7 @@ function claudeEntryFromRegistration(registration) {
18350
18541
  };
18351
18542
  }
18352
18543
  var ClaudeMcpFiles = class extends Context.Service()("@p4code/cli/mcp/ClaudeMcpFiles") {};
18353
- const make$76 = Effect.gen(function* () {
18544
+ const make$77 = Effect.gen(function* () {
18354
18545
  const fileSystem = yield* FileSystem.FileSystem;
18355
18546
  const path = yield* Path.Path;
18356
18547
  const services = yield* Effect.context();
@@ -18415,7 +18606,7 @@ const make$76 = Effect.gen(function* () {
18415
18606
  removeProject: (projectDir, name) => removeAt(Effect.succeed(projectFile(projectDir)))(name)
18416
18607
  };
18417
18608
  });
18418
- const layer$67 = Layer.effect(ClaudeMcpFiles, make$76);
18609
+ const layer$67 = Layer.effect(ClaudeMcpFiles, make$77);
18419
18610
  Layer.succeed(ClaudeMcpFiles, {
18420
18611
  readUser: Effect.succeed([]),
18421
18612
  upsertUser: () => Effect.fail(new McpRegistryError({ detail: "No Claude config in tests." })),
@@ -18551,7 +18742,7 @@ const decodeClientRegistration = Schema$1.decodeUnknownExit(ClientRegistrationRe
18551
18742
  const decodeTokenResponse = Schema$1.decodeUnknownExit(TokenResponse);
18552
18743
  var McpOAuth = class extends Context.Service()("@p4code/cli/mcp/McpOAuth") {};
18553
18744
  const registryError = (detail) => new McpRegistryError({ detail });
18554
- const make$75 = Effect.gen(function* () {
18745
+ const make$76 = Effect.gen(function* () {
18555
18746
  const config = yield* ServerConfig$1;
18556
18747
  const secrets = yield* ServerSecretStore;
18557
18748
  const http = yield* HttpClient.HttpClient;
@@ -18871,7 +19062,7 @@ const make$75 = Effect.gen(function* () {
18871
19062
  accessTokenFor
18872
19063
  };
18873
19064
  });
18874
- const layer$66 = Layer.effect(McpOAuth, make$75);
19065
+ const layer$66 = Layer.effect(McpOAuth, make$76);
18875
19066
  Layer.succeed(McpOAuth, {
18876
19067
  statusFor: () => Effect.succeed(Option.none()),
18877
19068
  begin: () => Effect.fail(new McpRegistryError({ detail: "OAuth sign-in is not available." })),
@@ -18889,7 +19080,7 @@ const decodeRegistration$1 = Schema$1.decodeUnknownExit(RegistrationFromJson$1);
18889
19080
  const encodeRegistration = Schema$1.encodeSync(RegistrationFromJson$1);
18890
19081
  var McpRegistry = class extends Context.Service()("@p4code/cli/mcp/McpRegistry") {};
18891
19082
  const slotsOf = (registration) => registration.secrets ?? [];
18892
- const make$74 = Effect.gen(function* () {
19083
+ const make$75 = Effect.gen(function* () {
18893
19084
  const config = yield* ServerConfig$1;
18894
19085
  const secrets = yield* ServerSecretStore;
18895
19086
  const oauth = yield* McpOAuth;
@@ -19040,7 +19231,7 @@ const make$74 = Effect.gen(function* () {
19040
19231
  }).pipe(Effect.provide(services), Effect.catchCause((cause) => Effect.logWarning("mcp registry resolve failed", { cause }).pipe(Effect.as({}))))
19041
19232
  };
19042
19233
  });
19043
- const layer$65 = Layer.effect(McpRegistry, make$74);
19234
+ const layer$65 = Layer.effect(McpRegistry, make$75);
19044
19235
  //#endregion
19045
19236
  //#region src/sync/skillDirectory.ts
19046
19237
  /**
@@ -19419,7 +19610,7 @@ const formatHubLink = (input) => encodeStoredHubLink({
19419
19610
  shareMode: input.shareMode
19420
19611
  });
19421
19612
  const fromEnvironment = (environment) => validateHubLink(environment.P4CODE_HUB_URL ?? "", environment.P4CODE_HUB_TOKEN ?? "");
19422
- const make$73 = Effect.fn("HubLink.make")(function* (environment) {
19613
+ const make$74 = Effect.fn("HubLink.make")(function* (environment) {
19423
19614
  const secrets = yield* ServerSecretStore;
19424
19615
  const env = environment ?? process.env;
19425
19616
  const fromEnv = fromEnvironment(env);
@@ -19485,7 +19676,7 @@ const make$73 = Effect.fn("HubLink.make")(function* (environment) {
19485
19676
  })
19486
19677
  };
19487
19678
  });
19488
- const layer$64 = Layer.effect(HubLink, make$73());
19679
+ const layer$64 = Layer.effect(HubLink, make$74());
19489
19680
  //#endregion
19490
19681
  //#region src/sync/HubAssetClient.ts
19491
19682
  /**
@@ -19518,7 +19709,7 @@ const decodeAssetListPage = Schema$1.decodeUnknownEffect(AssetListPage);
19518
19709
  const decodeConflictBody$1 = Schema$1.decodeUnknownEffect(ConflictBody$1);
19519
19710
  const decodeAsset = Schema$1.decodeUnknownEffect(AgentAsset);
19520
19711
  var HubAssetClient = class extends Context.Service()("@p4code/cli/sync/HubAssetClient") {};
19521
- const make$72 = Effect.gen(function* () {
19712
+ const make$73 = Effect.gen(function* () {
19522
19713
  const http = yield* HttpClient.HttpClient;
19523
19714
  const link = yield* HubLink;
19524
19715
  const requireSettings = Effect.gen(function* () {
@@ -19600,7 +19791,7 @@ const make$72 = Effect.gen(function* () {
19600
19791
  remove
19601
19792
  };
19602
19793
  });
19603
- const layer$63 = Layer.effect(HubAssetClient, make$72);
19794
+ const layer$63 = Layer.effect(HubAssetClient, make$73);
19604
19795
  //#endregion
19605
19796
  //#region src/sync/mcpRegistrationFiles.ts
19606
19797
  /**
@@ -20175,7 +20366,7 @@ const EMPTY_REPORT = {
20175
20366
  unavailable: null
20176
20367
  };
20177
20368
  var AssetSync = class extends Context.Service()("@p4code/cli/sync/AssetSync") {};
20178
- const make$71 = Effect.gen(function* () {
20369
+ const make$72 = Effect.gen(function* () {
20179
20370
  const client = yield* HubAssetClient;
20180
20371
  const link = yield* HubLink;
20181
20372
  const settingsStore = yield* ServerSettingsService;
@@ -20888,7 +21079,7 @@ const make$71 = Effect.gen(function* () {
20888
21079
  removeLocal
20889
21080
  };
20890
21081
  });
20891
- const layer$62 = Layer.effect(AssetSync, make$71);
21082
+ const layer$62 = Layer.effect(AssetSync, make$72);
20892
21083
  //#endregion
20893
21084
  //#region src/provider/CompressPrompts.ts
20894
21085
  /**
@@ -21808,7 +21999,11 @@ var ProjectionSnapshotQuery = class extends Context.Service()("@p4code/cli/orche
21808
21999
  const OrchestrationCommandReceipt = Schema$1.Struct({
21809
22000
  commandId: CommandId,
21810
22001
  aggregateKind: OrchestrationAggregateKind,
21811
- aggregateId: Schema$1.Union([ProjectId, ThreadId]),
22002
+ aggregateId: Schema$1.Union([
22003
+ ProjectId,
22004
+ ThreadId,
22005
+ ThreadPairId
22006
+ ]),
21812
22007
  acceptedAt: IsoDateTime,
21813
22008
  resultSequence: NonNegativeInt,
21814
22009
  status: OrchestrationCommandReceiptStatus,
@@ -21900,7 +22095,11 @@ const EventMetadataFromJsonString = Schema$1.fromJsonString(OrchestrationEventMe
21900
22095
  const AppendEventRequestSchema = Schema$1.Struct({
21901
22096
  eventId: EventId,
21902
22097
  aggregateKind: OrchestrationAggregateKind,
21903
- streamId: Schema$1.Union([ProjectId, ThreadId]),
22098
+ streamId: Schema$1.Union([
22099
+ ProjectId,
22100
+ ThreadId,
22101
+ ThreadPairId
22102
+ ]),
21904
22103
  type: OrchestrationEventType,
21905
22104
  causationEventId: Schema$1.NullOr(EventId),
21906
22105
  correlationId: Schema$1.NullOr(CommandId),
@@ -21915,7 +22114,11 @@ const OrchestrationEventPersistedRowSchema = Schema$1.Struct({
21915
22114
  eventId: EventId,
21916
22115
  type: OrchestrationEventType,
21917
22116
  aggregateKind: OrchestrationAggregateKind,
21918
- aggregateId: Schema$1.Union([ProjectId, ThreadId]),
22117
+ aggregateId: Schema$1.Union([
22118
+ ProjectId,
22119
+ ThreadId,
22120
+ ThreadPairId
22121
+ ]),
21919
22122
  occurredAt: IsoDateTime,
21920
22123
  commandId: Schema$1.NullOr(CommandId),
21921
22124
  causationEventId: Schema$1.NullOr(EventId),
@@ -22274,6 +22477,9 @@ const ThreadSessionSetPayload = ThreadSessionSetPayload$1;
22274
22477
  const ThreadTurnDiffCompletedPayload = ThreadTurnDiffCompletedPayload$1;
22275
22478
  const ThreadRevertedPayload = ThreadRevertedPayload$1;
22276
22479
  const ThreadActivityAppendedPayload = ThreadActivityAppendedPayload$1;
22480
+ const ThreadPairCreatedPayload = ThreadPairCreatedPayload$1;
22481
+ const ThreadPairDetachedPayload = ThreadPairDetachedPayload$1;
22482
+ const ThreadPairCursorAdvancedPayload = ThreadPairCursorAdvancedPayload$1;
22277
22483
  //#endregion
22278
22484
  //#region src/orchestration/projector.ts
22279
22485
  function checkpointStatusToLatestTurnState(status) {
@@ -22347,6 +22553,7 @@ function createEmptyReadModel(nowIso) {
22347
22553
  snapshotSequence: 0,
22348
22554
  projects: [],
22349
22555
  threads: [],
22556
+ threadPairs: [],
22350
22557
  updatedAt: nowIso
22351
22558
  };
22352
22559
  }
@@ -22357,6 +22564,31 @@ function projectEvent(model, event) {
22357
22564
  updatedAt: event.occurredAt
22358
22565
  };
22359
22566
  switch (event.type) {
22567
+ case "thread-pair.created": return decodeForEvent(ThreadPairCreatedPayload, event.payload, event.type, "payload").pipe(Effect.map((payload) => ({
22568
+ ...nextBase,
22569
+ threadPairs: [...(nextBase.threadPairs ?? []).filter((pair) => pair.id !== payload.pairId), {
22570
+ id: payload.pairId,
22571
+ implementerThreadId: payload.implementerThreadId,
22572
+ watcherThreadId: payload.watcherThreadId,
22573
+ lastReviewedImplementerSequence: payload.lastReviewedImplementerSequence,
22574
+ createdAt: payload.createdAt,
22575
+ detachedAt: null
22576
+ }]
22577
+ })));
22578
+ case "thread-pair.detached": return decodeForEvent(ThreadPairDetachedPayload, event.payload, event.type, "payload").pipe(Effect.map((payload) => ({
22579
+ ...nextBase,
22580
+ threadPairs: (nextBase.threadPairs ?? []).map((pair) => pair.id === payload.pairId ? {
22581
+ ...pair,
22582
+ detachedAt: payload.detachedAt
22583
+ } : pair)
22584
+ })));
22585
+ case "thread-pair.cursor-advanced": return decodeForEvent(ThreadPairCursorAdvancedPayload, event.payload, event.type, "payload").pipe(Effect.map((payload) => ({
22586
+ ...nextBase,
22587
+ threadPairs: (nextBase.threadPairs ?? []).map((pair) => pair.id === payload.pairId ? {
22588
+ ...pair,
22589
+ lastReviewedImplementerSequence: payload.implementerSequence
22590
+ } : pair)
22591
+ })));
22360
22592
  case "project.created": return decodeForEvent(ProjectCreatedPayload, event.payload, event.type, "payload").pipe(Effect.map((payload) => {
22361
22593
  const existing = nextBase.projects.find((entry) => entry.id === payload.projectId);
22362
22594
  const nextProject = {
@@ -22896,6 +23128,16 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
22896
23128
  command,
22897
23129
  threadId: command.threadId
22898
23130
  });
23131
+ const activePair = (readModel.threadPairs ?? []).find((pair) => pair.detachedAt === null && (pair.implementerThreadId === command.threadId || pair.watcherThreadId === command.threadId));
23132
+ if (activePair !== void 0) return yield* decideCommandSequence({
23133
+ readModel,
23134
+ commands: [{
23135
+ type: "thread-pair.detach",
23136
+ commandId: command.commandId,
23137
+ pairId: activePair.id,
23138
+ createdAt: yield* nowIso$8
23139
+ }, command]
23140
+ });
22899
23141
  const occurredAt = yield* nowIso$8;
22900
23142
  return {
22901
23143
  ...yield* withEventBase({
@@ -22911,6 +23153,118 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
22911
23153
  }
22912
23154
  };
22913
23155
  }
23156
+ case "thread-pair.create": {
23157
+ if (command.implementerThreadId === command.watcherThreadId) return yield* new OrchestrationCommandInvariantError({
23158
+ commandType: command.type,
23159
+ detail: "Fusion implementer and watcher must be distinct threads."
23160
+ });
23161
+ const implementer = yield* requireThread({
23162
+ readModel,
23163
+ command,
23164
+ threadId: command.implementerThreadId
23165
+ });
23166
+ const watcher = yield* requireThread({
23167
+ readModel,
23168
+ command,
23169
+ threadId: command.watcherThreadId
23170
+ });
23171
+ if (implementer.projectId !== watcher.projectId) return yield* new OrchestrationCommandInvariantError({
23172
+ commandType: command.type,
23173
+ detail: "Fusion implementer and watcher must belong to the same project."
23174
+ });
23175
+ const activePairs = readModel.threadPairs ?? [];
23176
+ if (activePairs.some((pair) => pair.id === command.pairId)) return yield* new OrchestrationCommandInvariantError({
23177
+ commandType: command.type,
23178
+ detail: `Thread pair '${command.pairId}' already exists.`
23179
+ });
23180
+ const occupiedThreadIds = new Set(activePairs.filter((pair) => pair.detachedAt === null).flatMap((pair) => [pair.implementerThreadId, pair.watcherThreadId]));
23181
+ if (occupiedThreadIds.has(command.implementerThreadId) || occupiedThreadIds.has(command.watcherThreadId)) return yield* new OrchestrationCommandInvariantError({
23182
+ commandType: command.type,
23183
+ detail: "Each thread may belong to only one active Fusion pair."
23184
+ });
23185
+ return {
23186
+ ...yield* withEventBase({
23187
+ aggregateKind: "thread-pair",
23188
+ aggregateId: command.pairId,
23189
+ occurredAt: command.createdAt,
23190
+ commandId: command.commandId
23191
+ }),
23192
+ type: "thread-pair.created",
23193
+ payload: {
23194
+ pairId: command.pairId,
23195
+ implementerThreadId: command.implementerThreadId,
23196
+ watcherThreadId: command.watcherThreadId,
23197
+ lastReviewedImplementerSequence: readModel.snapshotSequence,
23198
+ createdAt: command.createdAt
23199
+ }
23200
+ };
23201
+ }
23202
+ case "thread.turn.complete":
23203
+ yield* requireThread({
23204
+ readModel,
23205
+ command,
23206
+ threadId: command.threadId
23207
+ });
23208
+ return {
23209
+ ...yield* withEventBase({
23210
+ aggregateKind: "thread",
23211
+ aggregateId: command.threadId,
23212
+ occurredAt: command.completedAt,
23213
+ commandId: command.commandId
23214
+ }),
23215
+ type: "thread.turn-completed",
23216
+ payload: {
23217
+ threadId: command.threadId,
23218
+ turnId: command.turnId ?? null,
23219
+ state: command.state,
23220
+ completedAt: command.completedAt
23221
+ }
23222
+ };
23223
+ case "thread-pair.detach": {
23224
+ const pair = (readModel.threadPairs ?? []).find((candidate) => candidate.id === command.pairId);
23225
+ if (pair === void 0 || pair.detachedAt !== null) return yield* new OrchestrationCommandInvariantError({
23226
+ commandType: command.type,
23227
+ detail: `Active thread pair '${command.pairId}' does not exist.`
23228
+ });
23229
+ return {
23230
+ ...yield* withEventBase({
23231
+ aggregateKind: "thread-pair",
23232
+ aggregateId: command.pairId,
23233
+ occurredAt: command.createdAt,
23234
+ commandId: command.commandId
23235
+ }),
23236
+ type: "thread-pair.detached",
23237
+ payload: {
23238
+ pairId: command.pairId,
23239
+ detachedAt: command.createdAt
23240
+ }
23241
+ };
23242
+ }
23243
+ case "thread-pair.cursor.advance": {
23244
+ const pair = (readModel.threadPairs ?? []).find((candidate) => candidate.id === command.pairId);
23245
+ if (pair === void 0 || pair.detachedAt !== null) return yield* new OrchestrationCommandInvariantError({
23246
+ commandType: command.type,
23247
+ detail: `Active thread pair '${command.pairId}' does not exist.`
23248
+ });
23249
+ if (command.implementerSequence < pair.lastReviewedImplementerSequence) return yield* new OrchestrationCommandInvariantError({
23250
+ commandType: command.type,
23251
+ detail: `Thread pair '${command.pairId}' cursor cannot move backwards.`
23252
+ });
23253
+ return {
23254
+ ...yield* withEventBase({
23255
+ aggregateKind: "thread-pair",
23256
+ aggregateId: command.pairId,
23257
+ occurredAt: command.advancedAt,
23258
+ commandId: command.commandId
23259
+ }),
23260
+ type: "thread-pair.cursor-advanced",
23261
+ payload: {
23262
+ pairId: command.pairId,
23263
+ implementerSequence: command.implementerSequence,
23264
+ advancedAt: command.advancedAt
23265
+ }
23266
+ };
23267
+ }
22914
23268
  case "thread.archive": {
22915
23269
  yield* requireThreadNotArchived({
22916
23270
  readModel,
@@ -23601,6 +23955,12 @@ function commandToAggregateRef(command) {
23601
23955
  aggregateKind: "project",
23602
23956
  aggregateId: command.projectId
23603
23957
  };
23958
+ case "thread-pair.create":
23959
+ case "thread-pair.detach":
23960
+ case "thread-pair.cursor.advance": return {
23961
+ aggregateKind: "thread-pair",
23962
+ aggregateId: command.pairId
23963
+ };
23604
23964
  default: return {
23605
23965
  aggregateKind: "thread",
23606
23966
  aggregateId: command.threadId
@@ -25247,7 +25607,8 @@ const ORCHESTRATION_PROJECTOR_NAMES = {
25247
25607
  threadSessions: "projection.thread-sessions",
25248
25608
  threadTurns: "projection.thread-turns",
25249
25609
  checkpoints: "projection.checkpoints",
25250
- pendingApprovals: "projection.pending-approvals"
25610
+ pendingApprovals: "projection.pending-approvals",
25611
+ threadPairs: "projection.thread-pairs"
25251
25612
  };
25252
25613
  /**
25253
25614
  * Turn state to settle still-running turns with when their session leaves the
@@ -25506,6 +25867,50 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
25506
25867
  default: return;
25507
25868
  }
25508
25869
  });
25870
+ const applyThreadPairsProjection = Effect.fn("applyThreadPairsProjection")(function* (event, _attachmentSideEffects) {
25871
+ switch (event.type) {
25872
+ case "thread-pair.created":
25873
+ yield* sql`
25874
+ INSERT INTO thread_pairs (
25875
+ pair_id,
25876
+ implementer_thread_id,
25877
+ watcher_thread_id,
25878
+ last_reviewed_implementer_sequence,
25879
+ created_at,
25880
+ detached_at
25881
+ ) VALUES (
25882
+ ${event.payload.pairId},
25883
+ ${event.payload.implementerThreadId},
25884
+ ${event.payload.watcherThreadId},
25885
+ ${event.payload.lastReviewedImplementerSequence},
25886
+ ${event.payload.createdAt},
25887
+ NULL
25888
+ )
25889
+ ON CONFLICT(pair_id) DO UPDATE SET
25890
+ implementer_thread_id = excluded.implementer_thread_id,
25891
+ watcher_thread_id = excluded.watcher_thread_id,
25892
+ last_reviewed_implementer_sequence = excluded.last_reviewed_implementer_sequence,
25893
+ created_at = excluded.created_at,
25894
+ detached_at = NULL
25895
+ `.pipe(Effect.mapError(toPersistenceSqlError("ProjectionPipeline.threadPairs:create")));
25896
+ return;
25897
+ case "thread-pair.detached":
25898
+ yield* sql`
25899
+ UPDATE thread_pairs
25900
+ SET detached_at = ${event.payload.detachedAt}
25901
+ WHERE pair_id = ${event.payload.pairId}
25902
+ `.pipe(Effect.mapError(toPersistenceSqlError("ProjectionPipeline.threadPairs:detach")));
25903
+ return;
25904
+ case "thread-pair.cursor-advanced":
25905
+ yield* sql`
25906
+ UPDATE thread_pairs
25907
+ SET last_reviewed_implementer_sequence = ${event.payload.implementerSequence}
25908
+ WHERE pair_id = ${event.payload.pairId}
25909
+ `.pipe(Effect.mapError(toPersistenceSqlError("ProjectionPipeline.threadPairs:cursor")));
25910
+ return;
25911
+ default: return;
25912
+ }
25913
+ });
25509
25914
  const refreshThreadShellSummary = Effect.fn("refreshThreadShellSummary")(function* (threadId) {
25510
25915
  const existingRow = yield* projectionThreadRepository.getById({ threadId });
25511
25916
  if (Option.isNone(existingRow)) return;
@@ -26144,6 +26549,10 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
26144
26549
  name: ORCHESTRATION_PROJECTOR_NAMES.projects,
26145
26550
  apply: applyProjectsProjection
26146
26551
  },
26552
+ {
26553
+ name: ORCHESTRATION_PROJECTOR_NAMES.threadPairs,
26554
+ apply: applyThreadPairsProjection
26555
+ },
26147
26556
  {
26148
26557
  name: ORCHESTRATION_PROJECTOR_NAMES.threadMessages,
26149
26558
  apply: applyThreadMessagesProjection
@@ -26739,12 +27148,12 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* (spaw
26739
27148
  stderrInvalidUtf8: stderr.invalidUtf8
26740
27149
  };
26741
27150
  });
26742
- const make$70 = Effect.fn("ProcessRunner.make")(function* () {
27151
+ const make$71 = Effect.fn("ProcessRunner.make")(function* () {
26743
27152
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
26744
27153
  const run = (input) => finalizeRunProcess(runProcessCore(spawner, input), input);
26745
27154
  return ProcessRunner.of({ run });
26746
27155
  });
26747
- const layer$61 = Layer.effect(ProcessRunner, make$70());
27156
+ const layer$61 = Layer.effect(ProcessRunner, make$71());
26748
27157
  //#endregion
26749
27158
  //#region src/project/RepositoryIdentityResolver.ts
26750
27159
  const DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY = 512;
@@ -26835,7 +27244,7 @@ const resolveRepositoryIdentityFromCacheKey = Effect.fn("RepositoryIdentityResol
26835
27244
  rootPath: cacheKey
26836
27245
  }) : null;
26837
27246
  });
26838
- const make$69 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
27247
+ const make$70 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
26839
27248
  const processRunner = yield* ProcessRunner;
26840
27249
  const repositoryIdentityCache = yield* Cache.makeWith((cacheKey) => resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(Effect.provideService(ProcessRunner, processRunner)), {
26841
27250
  capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
@@ -26850,7 +27259,7 @@ const make$69 = Effect.fn("RepositoryIdentityResolver.make")(function* (options
26850
27259
  });
26851
27260
  return RepositoryIdentityResolver.of({ resolve });
26852
27261
  });
26853
- const layer$60 = Layer.effect(RepositoryIdentityResolver, make$69()).pipe(Layer.provide(layer$61));
27262
+ const layer$60 = Layer.effect(RepositoryIdentityResolver, make$70()).pipe(Layer.provide(layer$61));
26854
27263
  //#endregion
26855
27264
  //#region src/orchestration/Layers/ProjectionSnapshotQuery.ts
26856
27265
  const decodeReadModel = Schema$1.decodeUnknownEffect(OrchestrationReadModel);
@@ -26891,6 +27300,14 @@ const ProjectionTurnSummaryDbRowSchema = Schema$1.Struct({
26891
27300
  completedAt: Schema$1.NullOr(IsoDateTime)
26892
27301
  });
26893
27302
  const ProjectionStateDbRowSchema = ProjectionState;
27303
+ const ProjectionThreadPairDbRowSchema = Schema$1.Struct({
27304
+ id: ThreadPairId,
27305
+ implementerThreadId: ThreadId,
27306
+ watcherThreadId: ThreadId,
27307
+ lastReviewedImplementerSequence: NonNegativeInt,
27308
+ createdAt: IsoDateTime,
27309
+ detachedAt: Schema$1.NullOr(IsoDateTime)
27310
+ });
26894
27311
  const ProjectionCountsRowSchema = Schema$1.Struct({
26895
27312
  projectCount: Schema$1.Number,
26896
27313
  threadCount: Schema$1.Number
@@ -26938,7 +27355,8 @@ const REQUIRED_SNAPSHOT_PROJECTORS = [
26938
27355
  ORCHESTRATION_PROJECTOR_NAMES.threadProposedPlans,
26939
27356
  ORCHESTRATION_PROJECTOR_NAMES.threadActivities,
26940
27357
  ORCHESTRATION_PROJECTOR_NAMES.threadSessions,
26941
- ORCHESTRATION_PROJECTOR_NAMES.checkpoints
27358
+ ORCHESTRATION_PROJECTOR_NAMES.checkpoints,
27359
+ ORCHESTRATION_PROJECTOR_NAMES.threadPairs
26942
27360
  ];
26943
27361
  function maxIso(left, right) {
26944
27362
  if (left === null) return right;
@@ -27060,6 +27478,21 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27060
27478
  deleted_at AS "deletedAt"
27061
27479
  FROM projection_projects
27062
27480
  ORDER BY created_at ASC, project_id ASC
27481
+ `
27482
+ });
27483
+ const listThreadPairRows = SqlSchema.findAll({
27484
+ Request: Schema$1.Void,
27485
+ Result: ProjectionThreadPairDbRowSchema,
27486
+ execute: () => sql`
27487
+ SELECT
27488
+ pair_id AS "id",
27489
+ implementer_thread_id AS "implementerThreadId",
27490
+ watcher_thread_id AS "watcherThreadId",
27491
+ last_reviewed_implementer_sequence AS "lastReviewedImplementerSequence",
27492
+ created_at AS "createdAt",
27493
+ detached_at AS "detachedAt"
27494
+ FROM thread_pairs
27495
+ ORDER BY created_at ASC, pair_id ASC
27063
27496
  `
27064
27497
  });
27065
27498
  const listThreadRows = SqlSchema.findAll({
@@ -27765,8 +28198,9 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27765
28198
  listCheckpointRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listCheckpoints:query", "ProjectionSnapshotQuery.getSnapshot:listCheckpoints:decodeRows"))),
27766
28199
  listTurnSummaryRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listTurnSummaries:query", "ProjectionSnapshotQuery.getSnapshot:listTurnSummaries:decodeRows"))),
27767
28200
  listLatestTurnRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listLatestTurns:query", "ProjectionSnapshotQuery.getSnapshot:listLatestTurns:decodeRows"))),
27768
- listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listProjectionState:query", "ProjectionSnapshotQuery.getSnapshot:listProjectionState:decodeRows")))
27769
- ])).pipe(Effect.flatMap(([projectRows, threadRows, messageRows, proposedPlanRows, activityRows, sessionRows, checkpointRows, turnRows, latestTurnRows, stateRows]) => Effect.gen(function* () {
28201
+ listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listProjectionState:query", "ProjectionSnapshotQuery.getSnapshot:listProjectionState:decodeRows"))),
28202
+ listThreadPairRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listThreadPairs:query", "ProjectionSnapshotQuery.getSnapshot:listThreadPairs:decodeRows")))
28203
+ ])).pipe(Effect.flatMap(([projectRows, threadRows, messageRows, proposedPlanRows, activityRows, sessionRows, checkpointRows, turnRows, latestTurnRows, stateRows, threadPairRows]) => Effect.gen(function* () {
27770
28204
  const messagesByThread = /* @__PURE__ */ new Map();
27771
28205
  const proposedPlansByThread = /* @__PURE__ */ new Map();
27772
28206
  const activitiesByThread = /* @__PURE__ */ new Map();
@@ -27774,6 +28208,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27774
28208
  const turnsByThread = /* @__PURE__ */ new Map();
27775
28209
  const sessionsByThread = /* @__PURE__ */ new Map();
27776
28210
  const latestTurnByThread = /* @__PURE__ */ new Map();
28211
+ const threadPairs = [...threadPairRows];
27777
28212
  let updatedAt = null;
27778
28213
  for (const row of projectRows) updatedAt = maxIso(updatedAt, row.updatedAt);
27779
28214
  for (const row of threadRows) updatedAt = maxIso(updatedAt, row.updatedAt);
@@ -27904,6 +28339,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27904
28339
  snapshotSequence: computeSnapshotSequence(stateRows),
27905
28340
  projects,
27906
28341
  threads,
28342
+ threadPairs,
27907
28343
  updatedAt: updatedAt ?? "1970-01-01T00:00:00.000Z"
27908
28344
  };
27909
28345
  return yield* decodeReadModel(snapshot).pipe(Effect.mapError(toPersistenceDecodeError("ProjectionSnapshotQuery.getSnapshot:decodeReadModel")));
@@ -27917,11 +28353,13 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27917
28353
  listThreadProposedPlanRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getCommandReadModel:listThreadProposedPlans:query", "ProjectionSnapshotQuery.getCommandReadModel:listThreadProposedPlans:decodeRows"))),
27918
28354
  listThreadSessionRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getCommandReadModel:listThreadSessions:query", "ProjectionSnapshotQuery.getCommandReadModel:listThreadSessions:decodeRows"))),
27919
28355
  listLatestTurnRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getCommandReadModel:listLatestTurns:query", "ProjectionSnapshotQuery.getCommandReadModel:listLatestTurns:decodeRows"))),
27920
- listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getCommandReadModel:listProjectionState:query", "ProjectionSnapshotQuery.getCommandReadModel:listProjectionState:decodeRows")))
27921
- ])).pipe(Effect.flatMap(([projectRows, threadRows, proposedPlanRows, sessionRows, latestTurnRows, stateRows]) => Effect.sync(() => {
28356
+ listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getCommandReadModel:listProjectionState:query", "ProjectionSnapshotQuery.getCommandReadModel:listProjectionState:decodeRows"))),
28357
+ listThreadPairRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getCommandReadModel:listThreadPairs:query", "ProjectionSnapshotQuery.getCommandReadModel:listThreadPairs:decodeRows")))
28358
+ ])).pipe(Effect.flatMap(([projectRows, threadRows, proposedPlanRows, sessionRows, latestTurnRows, stateRows, threadPairRows]) => Effect.sync(() => {
27922
28359
  let updatedAt = null;
27923
28360
  const projects = [];
27924
28361
  const threads = [];
28362
+ const threadPairs = [...threadPairRows];
27925
28363
  for (let index = 0; index < projectRows.length; index += 1) {
27926
28364
  const row = projectRows[index];
27927
28365
  if (!row) continue;
@@ -28018,6 +28456,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
28018
28456
  snapshotSequence: computeSnapshotSequence(stateRows),
28019
28457
  projects,
28020
28458
  threads,
28459
+ threadPairs,
28021
28460
  updatedAt: updatedAt ?? "1970-01-01T00:00:00.000Z"
28022
28461
  };
28023
28462
  })), Effect.mapError((error) => {
@@ -28029,8 +28468,9 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
28029
28468
  listActiveThreadRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getShellSnapshot:listThreads:query", "ProjectionSnapshotQuery.getShellSnapshot:listThreads:decodeRows"))),
28030
28469
  listActiveThreadSessionRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getShellSnapshot:listThreadSessions:query", "ProjectionSnapshotQuery.getShellSnapshot:listThreadSessions:decodeRows"))),
28031
28470
  listActiveLatestTurnRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getShellSnapshot:listLatestTurns:query", "ProjectionSnapshotQuery.getShellSnapshot:listLatestTurns:decodeRows"))),
28032
- listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getShellSnapshot:listProjectionState:query", "ProjectionSnapshotQuery.getShellSnapshot:listProjectionState:decodeRows")))
28033
- ])).pipe(Effect.flatMap(([projectRows, threadRows, sessionRows, latestTurnRows, stateRows]) => Effect.gen(function* () {
28471
+ listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getShellSnapshot:listProjectionState:query", "ProjectionSnapshotQuery.getShellSnapshot:listProjectionState:decodeRows"))),
28472
+ listThreadPairRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getShellSnapshot:listThreadPairs:query", "ProjectionSnapshotQuery.getShellSnapshot:listThreadPairs:decodeRows")))
28473
+ ])).pipe(Effect.flatMap(([projectRows, threadRows, sessionRows, latestTurnRows, stateRows, threadPairRows]) => Effect.gen(function* () {
28034
28474
  let updatedAt = null;
28035
28475
  for (const row of projectRows) updatedAt = maxIso(updatedAt, row.updatedAt);
28036
28476
  for (const row of threadRows) updatedAt = maxIso(updatedAt, row.updatedAt);
@@ -28074,6 +28514,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
28074
28514
  hasBackgroundTasks: row.backgroundTaskCount > 0,
28075
28515
  scheduledWakeAt: row.scheduledWakeAt
28076
28516
  }) : Result.failVoid),
28517
+ threadPairs: threadPairRows.filter((pair) => pair.detachedAt === null),
28077
28518
  updatedAt: updatedAt ?? "1970-01-01T00:00:00.000Z"
28078
28519
  };
28079
28520
  return yield* decodeShellSnapshot(snapshot).pipe(Effect.mapError(toPersistenceDecodeError("ProjectionSnapshotQuery.getShellSnapshot:decodeShellSnapshot")));
@@ -28860,7 +29301,7 @@ function mergeWithDefaultKeybindings(custom) {
28860
29301
  * Keybindings - Service tag for keybinding configuration operations.
28861
29302
  */
28862
29303
  var Keybindings = class extends Context.Service()("@p4code/cli/keybindings") {};
28863
- const make$68 = Effect.gen(function* () {
29304
+ const make$69 = Effect.gen(function* () {
28864
29305
  const { keybindingsConfigPath } = yield* ServerConfig$1;
28865
29306
  const fs = yield* FileSystem.FileSystem;
28866
29307
  const path = yield* Path.Path;
@@ -29121,7 +29562,7 @@ const make$68 = Effect.gen(function* () {
29121
29562
  }))
29122
29563
  };
29123
29564
  });
29124
- const layer$59 = Layer.effect(Keybindings, make$68);
29565
+ const layer$59 = Layer.effect(Keybindings, make$69);
29125
29566
  //#endregion
29126
29567
  //#region src/process/externalLauncher.ts
29127
29568
  /**
@@ -29348,7 +29789,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu
29348
29789
  cause
29349
29790
  }));
29350
29791
  });
29351
- const make$67 = Effect.gen(function* () {
29792
+ const make$68 = Effect.gen(function* () {
29352
29793
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
29353
29794
  const fileSystem = yield* FileSystem.FileSystem;
29354
29795
  const path = yield* Path.Path;
@@ -29359,7 +29800,7 @@ const make$67 = Effect.gen(function* () {
29359
29800
  launchEditor: (input) => provideCommandResolutionServices(Effect.flatMap(resolveEditorLaunch(input), (launch) => launchEditorProcess(launch).pipe(Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner))))
29360
29801
  });
29361
29802
  });
29362
- const layer$58 = Layer.effect(ExternalLauncher, make$67);
29803
+ const layer$58 = Layer.effect(ExternalLauncher, make$68);
29363
29804
  //#endregion
29364
29805
  //#region src/orchestration/Services/OrchestrationReactor.ts
29365
29806
  /**
@@ -29377,7 +29818,7 @@ var OrchestrationReactor = class extends Context.Service()("@p4code/cli/orchestr
29377
29818
  //#endregion
29378
29819
  //#region src/serverLifecycleEvents.ts
29379
29820
  var ServerLifecycleEvents = class extends Context.Service()("@p4code/cli/serverLifecycleEvents") {};
29380
- const make$66 = Effect.gen(function* () {
29821
+ const make$67 = Effect.gen(function* () {
29381
29822
  const pubsub = yield* PubSub.unbounded();
29382
29823
  const state = yield* Ref.make({
29383
29824
  sequence: 0,
@@ -29401,7 +29842,7 @@ const make$66 = Effect.gen(function* () {
29401
29842
  }
29402
29843
  };
29403
29844
  });
29404
- const layer$57 = Layer.effect(ServerLifecycleEvents, make$66);
29845
+ const layer$57 = Layer.effect(ServerLifecycleEvents, make$67);
29405
29846
  //#endregion
29406
29847
  //#region src/telemetry/Identify.ts
29407
29848
  const CodexAuthJsonSchema = Schema$1.Struct({ tokens: Schema$1.Struct({ account_id: Schema$1.String }) });
@@ -29574,7 +30015,7 @@ var AnalyticsService = class AnalyticsService extends Context.Service()("@p4code
29574
30015
  /** No-op layer for callers that intentionally disable telemetry. */
29575
30016
  static layerTest = Layer.succeed(AnalyticsService, inert);
29576
30017
  };
29577
- const make$65 = Effect.gen(function* () {
30018
+ const make$66 = Effect.gen(function* () {
29578
30019
  const telemetryConfig = yield* TelemetryEnvConfig;
29579
30020
  const posthogKey = telemetryConfig.posthogKey.trim();
29580
30021
  if (!telemetryConfig.enabled || posthogKey === "") return inert;
@@ -29644,7 +30085,7 @@ const make$65 = Effect.gen(function* () {
29644
30085
  flush
29645
30086
  });
29646
30087
  });
29647
- const layer$56 = Layer.effect(AnalyticsService, make$65);
30088
+ const layer$56 = Layer.effect(AnalyticsService, make$66);
29648
30089
  AnalyticsService.layerTest;
29649
30090
  //#endregion
29650
30091
  //#region src/service/pinnedRuntime.ts
@@ -29991,7 +30432,7 @@ var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootSer
29991
30432
  }
29992
30433
  };
29993
30434
  var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
29994
- const make$64 = Effect.fn("cloud.boot_service.make")(function* (input) {
30435
+ const make$65 = Effect.fn("cloud.boot_service.make")(function* (input) {
29995
30436
  const hostExecPath = yield* HostProcessExecutablePath;
29996
30437
  const hostArguments = yield* HostProcessArguments;
29997
30438
  const host = input.host ?? {
@@ -30213,7 +30654,7 @@ const make$64 = Effect.fn("cloud.boot_service.make")(function* (input) {
30213
30654
  logPath
30214
30655
  });
30215
30656
  });
30216
- const layer$55 = (input) => Layer.effect(BootService, make$64(input));
30657
+ const layer$55 = (input) => Layer.effect(BootService, make$65(input));
30217
30658
  //#endregion
30218
30659
  //#region src/service/selfUpdate.ts
30219
30660
  /**
@@ -30288,7 +30729,7 @@ const resolveServerSelfUpdateCapability = Effect.fn("cloud.server_self_update.re
30288
30729
  return null;
30289
30730
  });
30290
30731
  var ServerSelfUpdate = class extends Context.Service()("@p4code/cli/service/selfUpdate/ServerSelfUpdate") {};
30291
- const make$63 = Effect.fn("cloud.server_self_update.make")(function* (options) {
30732
+ const make$64 = Effect.fn("cloud.server_self_update.make")(function* (options) {
30292
30733
  const serverConfig = yield* ServerConfig$1;
30293
30734
  const fs = yield* FileSystem.FileSystem;
30294
30735
  const path = yield* Path.Path;
@@ -30438,7 +30879,7 @@ const make$63 = Effect.fn("cloud.server_self_update.make")(function* (options) {
30438
30879
  });
30439
30880
  return ServerSelfUpdate.of({ update });
30440
30881
  });
30441
- const layer$54 = Layer.effect(ServerSelfUpdate, make$63()).pipe(Layer.provide(layer$61));
30882
+ const layer$54 = Layer.effect(ServerSelfUpdate, make$64()).pipe(Layer.provide(layer$61));
30442
30883
  //#endregion
30443
30884
  //#region src/environment/ServerEnvironmentLabel.ts
30444
30885
  const ServerEnvironmentLabelCommandProbe = Schema$1.Literals(["macos-computer-name", "linux-pretty-hostname"]);
@@ -30570,7 +31011,7 @@ function platformArch(architecture) {
30570
31011
  default: return "other";
30571
31012
  }
30572
31013
  }
30573
- const make$62 = Effect.gen(function* () {
31014
+ const make$63 = Effect.gen(function* () {
30574
31015
  const fileSystem = yield* FileSystem.FileSystem;
30575
31016
  const path = yield* Path.Path;
30576
31017
  const serverConfig = yield* ServerConfig$1;
@@ -30634,7 +31075,7 @@ const make$62 = Effect.gen(function* () {
30634
31075
  * state. It intentionally has no fallback Layer.succeed value: callers must
30635
31076
  * provide the external platform services and a ServerConfig.
30636
31077
  */
30637
- const layer$53 = Layer.effect(ServerEnvironment, make$62).pipe(Layer.provide(layer$61));
31078
+ const layer$53 = Layer.effect(ServerEnvironment, make$63).pipe(Layer.provide(layer$61));
30638
31079
  //#endregion
30639
31080
  //#region src/provider/Services/ProviderSessionReaper.ts
30640
31081
  var ProviderSessionReaper = class extends Context.Service()("@p4code/cli/provider/Services/ProviderSessionReaper") {};
@@ -31712,7 +32153,7 @@ const maybeOpenBrowser = (target) => Effect.gen(function* () {
31712
32153
  yield* (yield* ExternalLauncher).launchBrowser(target).pipe(Effect.catch(() => Effect.logInfo("browser auto-open unavailable", { hint: `Open ${target} in your browser.` })));
31713
32154
  });
31714
32155
  const runStartupPhase = (phase, effect) => effect.pipe(Effect.annotateSpans({ "startup.phase": phase }), Effect.withSpan(`server.startup.${phase}`));
31715
- const make$61 = Effect.gen(function* () {
32156
+ const make$62 = Effect.gen(function* () {
31716
32157
  const serverConfig = yield* ServerConfig$1;
31717
32158
  const keybindings = yield* Keybindings;
31718
32159
  const orchestrationReactor = yield* OrchestrationReactor;
@@ -31853,7 +32294,7 @@ const make$61 = Effect.gen(function* () {
31853
32294
  enqueueCommand: commandGate.enqueueCommand
31854
32295
  };
31855
32296
  });
31856
- const layer$52 = Layer.effect(ServerRuntimeStartup, make$61);
32297
+ const layer$52 = Layer.effect(ServerRuntimeStartup, make$62);
31857
32298
  //#endregion
31858
32299
  //#region src/serverRuntimeState.ts
31859
32300
  const PersistedServerRuntimeState = Schema$1.Struct({
@@ -32010,7 +32451,7 @@ function expandHomePath$2(input, path) {
32010
32451
  if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
32011
32452
  return input;
32012
32453
  }
32013
- const make$60 = Effect.gen(function* () {
32454
+ const make$61 = Effect.gen(function* () {
32014
32455
  const fileSystem = yield* FileSystem.FileSystem;
32015
32456
  const path = yield* Path.Path;
32016
32457
  const statWorkspaceRoot = Effect.fn("WorkspacePaths.statWorkspaceRoot")(function* (workspaceRoot, normalizedWorkspaceRoot, phase) {
@@ -32067,7 +32508,7 @@ const make$60 = Effect.gen(function* () {
32067
32508
  resolveRelativePathWithinRoot
32068
32509
  });
32069
32510
  });
32070
- const layer$51 = Layer.effect(WorkspacePaths, make$60);
32511
+ const layer$51 = Layer.effect(WorkspacePaths, make$61);
32071
32512
  //#endregion
32072
32513
  //#region src/cli/project.ts
32073
32514
  const isEnvironmentHttpCommonError = Schema$1.is(EnvironmentHttpCommonError);
@@ -33250,7 +33691,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
33250
33691
  filePath: error.filePath,
33251
33692
  errorTag: error._tag
33252
33693
  }));
33253
- const make$59 = Effect.gen(function* () {
33694
+ const make$60 = Effect.gen(function* () {
33254
33695
  const fileSystem = yield* FileSystem.FileSystem;
33255
33696
  const path = yield* Path.Path;
33256
33697
  const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
@@ -33271,7 +33712,7 @@ const make$59 = Effect.gen(function* () {
33271
33712
  });
33272
33713
  return P4ProjectFileLoader.of({ load });
33273
33714
  });
33274
- const layer$50 = Layer.effect(P4ProjectFileLoader, make$59);
33715
+ const layer$50 = Layer.effect(P4ProjectFileLoader, make$60);
33275
33716
  //#endregion
33276
33717
  //#region src/project/ProjectFaviconResolver.ts
33277
33718
  /**
@@ -33346,7 +33787,7 @@ function extractIconHref(source) {
33346
33787
  return null;
33347
33788
  }
33348
33789
  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) }));
33349
- const make$58 = Effect.gen(function* () {
33790
+ const make$59 = Effect.gen(function* () {
33350
33791
  const fileSystem = yield* FileSystem.FileSystem;
33351
33792
  const path = yield* Path.Path;
33352
33793
  const workspacePaths = yield* WorkspacePaths;
@@ -33415,7 +33856,7 @@ const make$58 = Effect.gen(function* () {
33415
33856
  });
33416
33857
  return ProjectFaviconResolver.of({ resolvePath });
33417
33858
  });
33418
- const layer$49 = Layer.effect(ProjectFaviconResolver, make$58);
33859
+ const layer$49 = Layer.effect(ProjectFaviconResolver, make$59);
33419
33860
  //#endregion
33420
33861
  //#region src/assets/AssetAccess.ts
33421
33862
  const ASSET_ROUTE_PREFIX = "/api/assets";
@@ -33826,10 +34267,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
33826
34267
  //#endregion
33827
34268
  //#region src/observability/BrowserTraceCollector.ts
33828
34269
  var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
33829
- const make$57 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
34270
+ const make$58 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
33830
34271
  for (const record of records) sink.push(record);
33831
34272
  }) });
33832
- const layer$48 = (sink) => Layer.succeed(BrowserTraceCollector, make$57(sink));
34273
+ const layer$48 = (sink) => Layer.succeed(BrowserTraceCollector, make$58(sink));
33833
34274
  //#endregion
33834
34275
  //#region src/auth/http.ts
33835
34276
  const CREDENTIAL_RESPONSE_HEADERS = {
@@ -36882,7 +37323,7 @@ const classifyNonZeroExit = (command, stderr) => {
36882
37323
  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";
36883
37324
  return "command-failed";
36884
37325
  };
36885
- const make$56 = Effect.gen(function* () {
37326
+ const make$57 = Effect.gen(function* () {
36886
37327
  const processRunner = yield* ProcessRunner;
36887
37328
  const run = Effect.fn("VcsProcess.run")(function* (input) {
36888
37329
  const baseError = {
@@ -36941,7 +37382,7 @@ const make$56 = Effect.gen(function* () {
36941
37382
  });
36942
37383
  return VcsProcess.of({ run });
36943
37384
  });
36944
- const layer$47 = Layer.effect(VcsProcess, make$56).pipe(Layer.provide(layer$61));
37385
+ const layer$47 = Layer.effect(VcsProcess, make$57).pipe(Layer.provide(layer$61));
36945
37386
  //#endregion
36946
37387
  //#region src/vcs/VcsDriver.ts
36947
37388
  var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
@@ -37392,12 +37833,12 @@ const makeVcsDriver = Effect.gen(function* () {
37392
37833
  const driver = yield* makeVcsDriverShape();
37393
37834
  return VcsDriver.of(driver);
37394
37835
  });
37395
- const make$55 = Effect.gen(function* () {
37836
+ const make$56 = Effect.gen(function* () {
37396
37837
  const git = yield* makeGitVcsDriverCore();
37397
37838
  return GitVcsDriver.of(git);
37398
37839
  });
37399
37840
  Layer.effect(VcsDriver, makeVcsDriver);
37400
- const layer$46 = Layer.effect(GitVcsDriver, make$55);
37841
+ const layer$46 = Layer.effect(GitVcsDriver, make$56);
37401
37842
  //#endregion
37402
37843
  //#region src/vcs/VcsProjectConfig.ts
37403
37844
  const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
@@ -37429,7 +37870,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
37429
37870
  configPath: error.configPath,
37430
37871
  errorTag: error._tag
37431
37872
  }));
37432
- const make$54 = Effect.gen(function* () {
37873
+ const make$55 = Effect.gen(function* () {
37433
37874
  const fileSystem = yield* FileSystem.FileSystem;
37434
37875
  const path = yield* Path.Path;
37435
37876
  const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
@@ -37470,7 +37911,7 @@ const make$54 = Effect.gen(function* () {
37470
37911
  });
37471
37912
  return VcsProjectConfig.of({ resolveKind });
37472
37913
  });
37473
- const layer$45 = Layer.effect(VcsProjectConfig, make$54);
37914
+ const layer$45 = Layer.effect(VcsProjectConfig, make$55);
37474
37915
  //#endregion
37475
37916
  //#region src/vcs/VcsDriverRegistry.ts
37476
37917
  const DETECTION_CACHE_CAPACITY = 2048;
@@ -37490,7 +37931,7 @@ function parseDetectionCacheKey(key) {
37490
37931
  cwd: key.slice(separatorIndex + 1)
37491
37932
  };
37492
37933
  }
37493
- const make$53 = Effect.gen(function* () {
37934
+ const make$54 = Effect.gen(function* () {
37494
37935
  const projectConfig = yield* VcsProjectConfig;
37495
37936
  const git = yield* makeVcsDriver;
37496
37937
  const drivers = { git };
@@ -37547,7 +37988,7 @@ const make$53 = Effect.gen(function* () {
37547
37988
  resolve
37548
37989
  });
37549
37990
  });
37550
- const layer$44 = Layer.effect(VcsDriverRegistry, make$53).pipe(Layer.provide(layer$45));
37991
+ const layer$44 = Layer.effect(VcsDriverRegistry, make$54).pipe(Layer.provide(layer$45));
37551
37992
  //#endregion
37552
37993
  //#region src/checkpointing/CheckpointStore.ts
37553
37994
  /**
@@ -37567,7 +38008,7 @@ const layer$44 = Layer.effect(VcsDriverRegistry, make$53).pipe(Layer.provide(lay
37567
38008
  */
37568
38009
  /** Service tag for checkpoint persistence and restore operations. */
37569
38010
  var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
37570
- const make$52 = Effect.gen(function* () {
38011
+ const make$53 = Effect.gen(function* () {
37571
38012
  const vcsRegistry = yield* VcsDriverRegistry;
37572
38013
  const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
37573
38014
  const handle = yield* vcsRegistry.resolve({ cwd });
@@ -37606,7 +38047,7 @@ const make$52 = Effect.gen(function* () {
37606
38047
  deleteCheckpointRefs
37607
38048
  });
37608
38049
  });
37609
- const layer$43 = Layer.effect(CheckpointStore, make$52);
38050
+ const layer$43 = Layer.effect(CheckpointStore, make$53);
37610
38051
  //#endregion
37611
38052
  //#region src/checkpointing/CheckpointDiffQuery.ts
37612
38053
  /**
@@ -37628,7 +38069,7 @@ function buildTurnDiffResult(input, diff) {
37628
38069
  diff
37629
38070
  };
37630
38071
  }
37631
- const make$51 = Effect.gen(function* () {
38072
+ const make$52 = Effect.gen(function* () {
37632
38073
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
37633
38074
  const checkpointStore = yield* CheckpointStore;
37634
38075
  const threadActivities = yield* ProjectionThreadActivityRepository;
@@ -37799,7 +38240,7 @@ const make$51 = Effect.gen(function* () {
37799
38240
  getFullThreadDiff
37800
38241
  });
37801
38242
  });
37802
- const layer$42 = Layer.effect(CheckpointDiffQuery, make$51);
38243
+ const layer$42 = Layer.effect(CheckpointDiffQuery, make$52);
37803
38244
  //#endregion
37804
38245
  //#region ../../packages/shared/src/toolCategory.ts
37805
38246
  const TOOL_CATEGORY_TITLES = {
@@ -40813,7 +41254,7 @@ function makeUpdateState(input) {
40813
41254
  output: input.output ?? null
40814
41255
  };
40815
41256
  }
40816
- const make$50 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
41257
+ const make$51 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
40817
41258
  const providerRegistry = yield* ProviderRegistry;
40818
41259
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
40819
41260
  const httpClient = yield* HttpClient.HttpClient;
@@ -40928,7 +41369,7 @@ const make$50 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
40928
41369
  });
40929
41370
  return ProviderMaintenanceRunner.of({ updateProvider });
40930
41371
  });
40931
- const layer$41 = Layer.effect(ProviderMaintenanceRunner, make$50());
41372
+ const layer$41 = Layer.effect(ProviderMaintenanceRunner, make$51());
40932
41373
  //#endregion
40933
41374
  //#region src/provider/Services/ProviderInstanceRegistry.ts
40934
41375
  var ProviderInstanceRegistry = class extends Context.Service()("@p4code/cli/provider/Services/ProviderInstanceRegistry") {};
@@ -40952,11 +41393,11 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
40952
41393
  detail: "This provider does not report account usage."
40953
41394
  }))))
40954
41395
  });
40955
- const make$49 = Effect.gen(function* () {
41396
+ const make$50 = Effect.gen(function* () {
40956
41397
  const registry = yield* ProviderInstanceRegistry;
40957
41398
  return makeTextGenerationFromRegistry(registry);
40958
41399
  });
40959
- const layer$40 = Layer.effect(TextGeneration, make$49);
41400
+ const layer$40 = Layer.effect(TextGeneration, make$50);
40960
41401
  //#endregion
40961
41402
  //#region src/provider/Drivers/ClaudeHome.ts
40962
41403
  const resolveClaudeHomePath = Effect.fn("resolveClaudeHomePath")(function* (config) {
@@ -41948,7 +42389,7 @@ Layer.succeed(UsageService, UsageService.of({ readSummary: (input) => Effect.suc
41948
42389
  },
41949
42390
  scanDurationMs: 0
41950
42391
  }) }));
41951
- const make$48 = Effect.gen(function* () {
42392
+ const make$49 = Effect.gen(function* () {
41952
42393
  const fileSystem = yield* FileSystem.FileSystem;
41953
42394
  const path = yield* Path.Path;
41954
42395
  const config = yield* ServerConfig$1;
@@ -42180,7 +42621,7 @@ const make$48 = Effect.gen(function* () {
42180
42621
  };
42181
42622
  }) };
42182
42623
  });
42183
- const layer$39 = Layer.effect(UsageService, make$48);
42624
+ const layer$39 = Layer.effect(UsageService, make$49);
42184
42625
  const SKILL_MANIFEST_FILENAME = "SKILL.md";
42185
42626
  /**
42186
42627
  * Split a catalogue id (`owner/repo/skill-name`) into its parts.
@@ -42326,7 +42767,7 @@ const emptyFetch = (id, unavailable) => ({
42326
42767
  skipped: [],
42327
42768
  unavailable
42328
42769
  });
42329
- const make$47 = Effect.gen(function* () {
42770
+ const make$48 = Effect.gen(function* () {
42330
42771
  const http = yield* HttpClient.HttpClient;
42331
42772
  const request = Effect.fn("SkillRegistry.request")(function* (url) {
42332
42773
  return yield* http.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("accept", "application/json"), HttpClientRequest.setHeader("user-agent", "p4code"))).pipe(Effect.timeout(REQUEST_TIMEOUT_MS));
@@ -42397,7 +42838,7 @@ const make$47 = Effect.gen(function* () {
42397
42838
  fetch
42398
42839
  };
42399
42840
  });
42400
- const layer$38 = Layer.effect(SkillRegistry, make$47);
42841
+ const layer$38 = Layer.effect(SkillRegistry, make$48);
42401
42842
  //#endregion
42402
42843
  //#region ../../packages/shared/src/KeyedCoalescingWorker.ts
42403
42844
  const makeKeyedCoalescingWorker = (options) => Effect.gen(function* () {
@@ -42696,7 +43137,7 @@ const serversEqual = (left, right) => {
42696
43137
  }
42697
43138
  return true;
42698
43139
  };
42699
- const make$46 = Effect.gen(function* PortDiscoveryMake() {
43140
+ const make$47 = Effect.gen(function* PortDiscoveryMake() {
42700
43141
  const net = yield* NetService;
42701
43142
  const processRunner = yield* ProcessRunner;
42702
43143
  const hostPlatform = yield* HostProcessPlatform;
@@ -42847,7 +43288,7 @@ const make$46 = Effect.gen(function* PortDiscoveryMake() {
42847
43288
  unregisterTerminal
42848
43289
  });
42849
43290
  }).pipe(Effect.withSpan("PortDiscovery.make"));
42850
- const layer$37 = Layer.effect(PortDiscovery, make$46);
43291
+ const layer$37 = Layer.effect(PortDiscovery, make$47);
42851
43292
  //#endregion
42852
43293
  //#region src/terminal/Manager.ts
42853
43294
  /**
@@ -43525,7 +43966,7 @@ function normalizedRuntimeEnv(env) {
43525
43966
  if (entries.length === 0) return null;
43526
43967
  return Object.fromEntries(entries.toSorted(([left], [right]) => left.localeCompare(right)));
43527
43968
  }
43528
- const make$45 = Effect.fn("TerminalManager.make")(function* () {
43969
+ const make$46 = Effect.fn("TerminalManager.make")(function* () {
43529
43970
  const { terminalLogsDir } = yield* ServerConfig$1;
43530
43971
  const ptyAdapter = yield* PtyAdapter;
43531
43972
  const portDiscovery = yield* PortDiscovery;
@@ -44487,7 +44928,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
44487
44928
  subscribeMetadata
44488
44929
  });
44489
44930
  });
44490
- const layer$36 = Layer.effect(TerminalManager, make$45()).pipe(Layer.provide(layer$61));
44931
+ const layer$36 = Layer.effect(TerminalManager, make$46()).pipe(Layer.provide(layer$61));
44491
44932
  //#endregion
44492
44933
  //#region src/mcp/McpInvocationContext.ts
44493
44934
  var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
@@ -44697,7 +45138,7 @@ const classifyResponseError = (context, error) => {
44697
45138
  });
44698
45139
  }
44699
45140
  };
44700
- const make$44 = Effect.gen(function* PreviewAutomationBrokerMake() {
45141
+ const make$45 = Effect.gen(function* PreviewAutomationBrokerMake() {
44701
45142
  const crypto = yield* Crypto.Crypto;
44702
45143
  const state = yield* SynchronizedRef.make({
44703
45144
  clients: /* @__PURE__ */ new Map(),
@@ -44931,7 +45372,7 @@ const make$44 = Effect.gen(function* PreviewAutomationBrokerMake() {
44931
45372
  invoke
44932
45373
  });
44933
45374
  }).pipe(Effect.withSpan("PreviewAutomationBroker.make"));
44934
- const layer$35 = Layer.effect(PreviewAutomationBroker, make$44);
45375
+ const layer$35 = Layer.effect(PreviewAutomationBroker, make$45);
44935
45376
  //#endregion
44936
45377
  //#region src/preview/Manager.ts
44937
45378
  /**
@@ -44995,7 +45436,7 @@ const buildIdleSnapshot = (input) => ({
44995
45436
  viewport: FILL_PREVIEW_VIEWPORT,
44996
45437
  updatedAt: input.updatedAt
44997
45438
  });
44998
- const make$43 = Effect.gen(function* PreviewManagerMake() {
45439
+ const make$44 = Effect.gen(function* PreviewManagerMake() {
44999
45440
  const serverEpoch = NodeCrypto.randomUUID();
45000
45441
  const stateRef = yield* SynchronizedRef.make(initialState);
45001
45442
  const eventsPubSub = yield* PubSub.unbounded();
@@ -45226,7 +45667,7 @@ const make$43 = Effect.gen(function* PreviewManagerMake() {
45226
45667
  subscribeEvents: PubSub.subscribe(eventsPubSub)
45227
45668
  });
45228
45669
  }).pipe(Effect.withSpan("PreviewManager.make"));
45229
- const layer$34 = Layer.effect(PreviewManager, make$43);
45670
+ const layer$34 = Layer.effect(PreviewManager, make$44);
45230
45671
  //#endregion
45231
45672
  //#region src/workspace/WorkspaceSearchIndex.ts
45232
45673
  const WORKSPACE_INDEX_MAX_ENTRIES = 25e3;
@@ -45360,7 +45801,7 @@ const waitForScan = (cwd, finder, onFailure) => Effect.try({
45360
45801
  timeout: WORKSPACE_INDEX_SCAN_TIMEOUT
45361
45802
  })
45362
45803
  }), Effect.withSpan("WorkspaceSearchIndex.waitForScan"));
45363
- const make$42 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
45804
+ const make$43 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
45364
45805
  const finder = yield* Effect.acquireRelease(createFinder(cwd), (finder) => Effect.try({
45365
45806
  try: () => finder.destroy(),
45366
45807
  catch: (cause) => new WorkspaceSearchIndexDestroyFailed({
@@ -45434,7 +45875,7 @@ const make$42 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
45434
45875
  * workspace root. WorkspaceSearchIndexMap owns memoization and idle cleanup;
45435
45876
  * using a default cwd here would mix resources from different workspaces.
45436
45877
  */
45437
- const layer$33 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$42(cwd));
45878
+ const layer$33 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$43(cwd));
45438
45879
  var WorkspaceSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceSearchIndexMap", {
45439
45880
  lookup: layer$33,
45440
45881
  idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
@@ -45498,7 +45939,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu
45498
45939
  if (!input.cwd) return yield* new WorkspaceEntriesCurrentProjectRequiredError({ partialPath: input.partialPath });
45499
45940
  return path.resolve(expandHomePath$1(input.cwd, path), input.partialPath);
45500
45941
  });
45501
- const make$41 = Effect.gen(function* () {
45942
+ const make$42 = Effect.gen(function* () {
45502
45943
  const path = yield* Path.Path;
45503
45944
  const workspacePaths = yield* WorkspacePaths;
45504
45945
  const workspaceSearchIndexes = yield* WorkspaceSearchIndexMap;
@@ -45572,7 +46013,7 @@ const make$41 = Effect.gen(function* () {
45572
46013
  search
45573
46014
  });
45574
46015
  });
45575
- const layer$32 = Layer.effect(WorkspaceEntries, make$41).pipe(Layer.provide(WorkspaceSearchIndexMap.layer));
46016
+ const layer$32 = Layer.effect(WorkspaceEntries, make$42).pipe(Layer.provide(WorkspaceSearchIndexMap.layer));
45576
46017
  //#endregion
45577
46018
  //#region src/workspace/WorkspaceFileSystem.ts
45578
46019
  /**
@@ -45631,7 +46072,7 @@ Schema$1.Union([
45631
46072
  ]);
45632
46073
  /** Service tag for workspace file operations. */
45633
46074
  var WorkspaceFileSystem = class extends Context.Service()("@p4code/cli/workspace/WorkspaceFileSystem") {};
45634
- const make$40 = Effect.gen(function* () {
46075
+ const make$41 = Effect.gen(function* () {
45635
46076
  const fileSystem = yield* FileSystem.FileSystem;
45636
46077
  const path = yield* Path.Path;
45637
46078
  const workspacePaths = yield* WorkspacePaths;
@@ -45775,7 +46216,7 @@ const make$40 = Effect.gen(function* () {
45775
46216
  writeFile
45776
46217
  });
45777
46218
  });
45778
- const layer$31 = Layer.effect(WorkspaceFileSystem, make$40);
46219
+ const layer$31 = Layer.effect(WorkspaceFileSystem, make$41);
45779
46220
  //#endregion
45780
46221
  //#region src/textGeneration/TextGenerationPresets.ts
45781
46222
  const conventionalCommitsTextGenerationPolicy = {
@@ -45839,7 +46280,7 @@ var ProjectSetupScriptProjectNotFoundError = class extends Schema$1.TaggedErrorC
45839
46280
  };
45840
46281
  Schema$1.Union([ProjectSetupScriptOperationError, ProjectSetupScriptProjectNotFoundError]);
45841
46282
  var ProjectSetupScriptRunner = class extends Context.Service()("@p4code/cli/project/ProjectSetupScriptRunner") {};
45842
- const make$39 = Effect.gen(function* () {
46283
+ const make$40 = Effect.gen(function* () {
45843
46284
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
45844
46285
  const terminalManager = yield* TerminalManager;
45845
46286
  const runForThread = Effect.fn("ProjectSetupScriptRunner.runForThread")(function* (input) {
@@ -45897,7 +46338,7 @@ const make$39 = Effect.gen(function* () {
45897
46338
  });
45898
46339
  return ProjectSetupScriptRunner.of({ runForThread });
45899
46340
  });
45900
- const layer$30 = Layer.effect(ProjectSetupScriptRunner, make$39);
46341
+ const layer$30 = Layer.effect(ProjectSetupScriptRunner, make$40);
45901
46342
  //#endregion
45902
46343
  //#region src/sourceControl/azureDevOpsPullRequests.ts
45903
46344
  const AzureDevOpsPullRequestSchema = Schema$1.Struct({
@@ -46221,7 +46662,7 @@ function decodeAzureDevOpsJson(raw, schema, operation, cwd) {
46221
46662
  cause
46222
46663
  })));
46223
46664
  }
46224
- const make$38 = Effect.gen(function* () {
46665
+ const make$39 = Effect.gen(function* () {
46225
46666
  const process = yield* VcsProcess;
46226
46667
  const execute = (input) => process.run({
46227
46668
  operation: "AzureDevOpsCli.execute",
@@ -46363,7 +46804,7 @@ const make$38 = Effect.gen(function* () {
46363
46804
  }).pipe(Effect.asVoid)
46364
46805
  });
46365
46806
  });
46366
- const layer$29 = Layer.effect(AzureDevOpsCli, make$38);
46807
+ const layer$29 = Layer.effect(AzureDevOpsCli, make$39);
46367
46808
  //#endregion
46368
46809
  //#region src/sourceControl/SourceControlProviderDiscovery.ts
46369
46810
  function firstNonEmptyLine(text) {
@@ -46566,7 +47007,7 @@ function toChangeRequest$5(summary) {
46566
47007
  isCrossRepository: false
46567
47008
  };
46568
47009
  }
46569
- const make$37 = Effect.gen(function* () {
47010
+ const make$38 = Effect.gen(function* () {
46570
47011
  const azure = yield* AzureDevOpsCli;
46571
47012
  return SourceControlProvider.of({
46572
47013
  kind: "azure-devops",
@@ -46658,7 +47099,7 @@ const make$37 = Effect.gen(function* () {
46658
47099
  })))
46659
47100
  });
46660
47101
  });
46661
- Layer.effect(SourceControlProvider, make$37);
47102
+ Layer.effect(SourceControlProvider, make$38);
46662
47103
  //#endregion
46663
47104
  //#region src/sourceControl/bitbucketPullRequests.ts
46664
47105
  const BitbucketRepositoryRefSchema = Schema$1.Struct({
@@ -47035,7 +47476,7 @@ function responseError(operation, response) {
47035
47476
  responseBodyLength: collected.text.length
47036
47477
  }))));
47037
47478
  }
47038
- const make$36 = Effect.gen(function* () {
47479
+ const make$37 = Effect.gen(function* () {
47039
47480
  const config = yield* BitbucketApiEnvConfig;
47040
47481
  const httpClient = yield* HttpClient.HttpClient;
47041
47482
  const fileSystem = yield* FileSystem.FileSystem;
@@ -47251,7 +47692,7 @@ const make$36 = Effect.gen(function* () {
47251
47692
  })))
47252
47693
  });
47253
47694
  });
47254
- const layer$27 = Layer.effect(BitbucketApi, make$36);
47695
+ const layer$27 = Layer.effect(BitbucketApi, make$37);
47255
47696
  //#endregion
47256
47697
  //#region src/sourceControl/BitbucketSourceControlProvider.ts
47257
47698
  function toChangeRequest$4(summary) {
@@ -47269,7 +47710,7 @@ function toChangeRequest$4(summary) {
47269
47710
  ...summary.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin } : {}
47270
47711
  };
47271
47712
  }
47272
- const make$35 = Effect.gen(function* () {
47713
+ const make$36 = Effect.gen(function* () {
47273
47714
  const bitbucket = yield* BitbucketApi;
47274
47715
  return SourceControlProvider.of({
47275
47716
  kind: "bitbucket",
@@ -47360,7 +47801,7 @@ const make$35 = Effect.gen(function* () {
47360
47801
  })))
47361
47802
  });
47362
47803
  });
47363
- Layer.effect(SourceControlProvider, make$35);
47804
+ Layer.effect(SourceControlProvider, make$36);
47364
47805
  const makeDiscovery = Effect.gen(function* () {
47365
47806
  return {
47366
47807
  type: "api",
@@ -47602,7 +48043,7 @@ function deriveRepositoryCloneUrlsFromCreateOutput(stdout, repository) {
47602
48043
  sshUrl: `git@${fallbackHost}:${repository}.git`
47603
48044
  };
47604
48045
  }
47605
- const make$34 = Effect.gen(function* () {
48046
+ const make$35 = Effect.gen(function* () {
47606
48047
  const process = yield* VcsProcess;
47607
48048
  const execute = (input) => process.run({
47608
48049
  operation: "GitHubCli.execute",
@@ -47720,7 +48161,7 @@ const make$34 = Effect.gen(function* () {
47720
48161
  }).pipe(Effect.asVoid)
47721
48162
  });
47722
48163
  });
47723
- const layer$25 = Layer.effect(GitHubCli, make$34);
48164
+ const layer$25 = Layer.effect(GitHubCli, make$35);
47724
48165
  //#endregion
47725
48166
  //#region src/sourceControl/gitHubAuthStatus.ts
47726
48167
  const GitHubAuthStatusAccountSchema = Schema$1.Struct({
@@ -47821,7 +48262,7 @@ const discovery$1 = {
47821
48262
  parseAuth: parseGitHubAuth,
47822
48263
  installHint: "Install the GitHub command-line tool (`gh`) via https://cli.github.com/ or your package manager (for example `brew install gh`)."
47823
48264
  };
47824
- const make$33 = Effect.gen(function* () {
48265
+ const make$34 = Effect.gen(function* () {
47825
48266
  const github = yield* GitHubCli;
47826
48267
  const listChangeRequests = (input) => {
47827
48268
  if (input.state === "open") return github.listOpenPullRequests({
@@ -47937,7 +48378,7 @@ const make$33 = Effect.gen(function* () {
47937
48378
  })))
47938
48379
  });
47939
48380
  });
47940
- Layer.effect(SourceControlProvider, make$33);
48381
+ Layer.effect(SourceControlProvider, make$34);
47941
48382
  //#endregion
47942
48383
  //#region src/sourceControl/gitLabMergeRequests.ts
47943
48384
  const GitLabProjectReferenceSchema = Schema$1.Struct({
@@ -48249,7 +48690,7 @@ function parseRepositoryPath(repository) {
48249
48690
  projectPath
48250
48691
  };
48251
48692
  }
48252
- const make$32 = Effect.gen(function* () {
48693
+ const make$33 = Effect.gen(function* () {
48253
48694
  const process = yield* VcsProcess;
48254
48695
  const run = (input, mapError) => process.run({
48255
48696
  operation: "GitLabCli.execute",
@@ -48400,7 +48841,7 @@ const make$32 = Effect.gen(function* () {
48400
48841
  }).pipe(Effect.asVoid)
48401
48842
  });
48402
48843
  });
48403
- const layer$23 = Layer.effect(GitLabCli, make$32);
48844
+ const layer$23 = Layer.effect(GitLabCli, make$33);
48404
48845
  //#endregion
48405
48846
  //#region src/sourceControl/gitLabAuthStatus.ts
48406
48847
  const HOST_LINE_PATTERN = /^(?:[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?|\[[a-f0-9:.]+\])(?::\d+)?$/iu;
@@ -48497,7 +48938,7 @@ const discovery = {
48497
48938
  refineUnknownRemote: refineUnknownGitLabRemote,
48498
48939
  installHint: "Install the GitLab command-line tool (`glab`) from https://gitlab.com/gitlab-org/cli or your package manager (for example `brew install glab`)."
48499
48940
  };
48500
- const make$31 = Effect.gen(function* () {
48941
+ const make$32 = Effect.gen(function* () {
48501
48942
  const gitlab = yield* GitLabCli;
48502
48943
  return SourceControlProvider.of({
48503
48944
  kind: "gitlab",
@@ -48585,7 +49026,7 @@ const make$31 = Effect.gen(function* () {
48585
49026
  })))
48586
49027
  });
48587
49028
  });
48588
- Layer.effect(SourceControlProvider, make$31);
49029
+ Layer.effect(SourceControlProvider, make$32);
48589
49030
  //#endregion
48590
49031
  //#region src/sourceControl/SourceControlProviderRegistry.ts
48591
49032
  const PROVIDER_DETECTION_CACHE_CAPACITY = 2048;
@@ -48741,12 +49182,12 @@ const makeWithProviders = Effect.fn("makeSourceControlProviderRegistryWithProvid
48741
49182
  })), { concurrency: "unbounded" })
48742
49183
  });
48743
49184
  });
48744
- const make$30 = Effect.gen(function* () {
48745
- const github = yield* make$33;
48746
- const gitlab = yield* make$31;
48747
- const bitbucket = yield* make$35;
49185
+ const make$31 = Effect.gen(function* () {
49186
+ const github = yield* make$34;
49187
+ const gitlab = yield* make$32;
49188
+ const bitbucket = yield* make$36;
48748
49189
  const bitbucketDiscovery = yield* makeDiscovery;
48749
- const azureDevOps = yield* make$37;
49190
+ const azureDevOps = yield* make$38;
48750
49191
  return yield* makeWithProviders([
48751
49192
  {
48752
49193
  kind: "github",
@@ -48770,7 +49211,7 @@ const make$30 = Effect.gen(function* () {
48770
49211
  }
48771
49212
  ]);
48772
49213
  });
48773
- const layer$21 = Layer.effect(SourceControlProviderRegistry, make$30);
49214
+ const layer$21 = Layer.effect(SourceControlProviderRegistry, make$31);
48774
49215
  //#endregion
48775
49216
  //#region src/sourceControl/PrTemplateDetection.ts
48776
49217
  const TEMPLATE_MAX_BYTES = 8e3;
@@ -49140,7 +49581,7 @@ function toPullRequestHeadRemoteInfo(pr) {
49140
49581
  ...pr.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: pr.headRepositoryOwnerLogin } : {}
49141
49582
  };
49142
49583
  }
49143
- const make$29 = Effect.gen(function* () {
49584
+ const make$30 = Effect.gen(function* () {
49144
49585
  const gitCore = yield* GitVcsDriver;
49145
49586
  const sourceControlProviders = yield* SourceControlProviderRegistry;
49146
49587
  const textGeneration = yield* TextGeneration;
@@ -50062,7 +50503,7 @@ const make$29 = Effect.gen(function* () {
50062
50503
  runStackedAction
50063
50504
  });
50064
50505
  });
50065
- const layer$20 = Layer.effect(GitManager, make$29);
50506
+ const layer$20 = Layer.effect(GitManager, make$30);
50066
50507
  //#endregion
50067
50508
  //#region src/git/GitWorkflowService.ts
50068
50509
  var GitWorkflowService = class extends Context.Service()("@p4code/cli/git/GitWorkflowService") {};
@@ -50099,7 +50540,7 @@ function nonRepositoryListRefs() {
50099
50540
  totalCount: 0
50100
50541
  };
50101
50542
  }
50102
- const make$28 = Effect.gen(function* () {
50543
+ const make$29 = Effect.gen(function* () {
50103
50544
  const registry = yield* VcsDriverRegistry;
50104
50545
  const git = yield* GitVcsDriver;
50105
50546
  const gitManager = yield* GitManager;
@@ -50185,7 +50626,7 @@ const make$28 = Effect.gen(function* () {
50185
50626
  renameBranch: (input) => ensureGit("GitWorkflowService.renameBranch", input.cwd).pipe(Effect.andThen(git.renameBranch(input)))
50186
50627
  });
50187
50628
  });
50188
- const layer$19 = Layer.effect(GitWorkflowService, make$28);
50629
+ const layer$19 = Layer.effect(GitWorkflowService, make$29);
50189
50630
  //#endregion
50190
50631
  //#region src/vcs/VcsStatusBroadcaster.ts
50191
50632
  const DEFAULT_VCS_STATUS_REFRESH_INTERVAL = Duration.seconds(30);
@@ -50257,7 +50698,7 @@ function fingerprintStatusPart(status) {
50257
50698
  return JSON.stringify(status);
50258
50699
  }
50259
50700
  const normalizeCwd = (cwd) => Effect.service(FileSystem.FileSystem).pipe(Effect.flatMap((fs) => fs.realPath(cwd)), Effect.orElseSucceed(() => cwd));
50260
- const make$27 = Effect.gen(function* () {
50701
+ const make$28 = Effect.gen(function* () {
50261
50702
  const workflow = yield* GitWorkflowService;
50262
50703
  const fs = yield* FileSystem.FileSystem;
50263
50704
  const changesPubSub = yield* Effect.acquireRelease(PubSub.unbounded(), (pubsub) => PubSub.shutdown(pubsub));
@@ -50481,7 +50922,7 @@ const make$27 = Effect.gen(function* () {
50481
50922
  streamStatus
50482
50923
  });
50483
50924
  });
50484
- const layer$18 = Layer.effect(VcsStatusBroadcaster, make$27);
50925
+ const layer$18 = Layer.effect(VcsStatusBroadcaster, make$28);
50485
50926
  //#endregion
50486
50927
  //#region src/vcs/VcsProvisioningService.ts
50487
50928
  var VcsProvisioningService = class extends Context.Service()("@p4code/cli/vcs/VcsProvisioningService") {};
@@ -50494,7 +50935,7 @@ function resolveRequestedKind(kind) {
50494
50935
  }));
50495
50936
  return Effect.succeed(kind);
50496
50937
  }
50497
- const make$26 = Effect.gen(function* () {
50938
+ const make$27 = Effect.gen(function* () {
50498
50939
  const registry = yield* VcsDriverRegistry;
50499
50940
  const initRepository = Effect.fn("VcsProvisioningService.initRepository")(function* (input) {
50500
50941
  const kind = yield* resolveRequestedKind(input.kind);
@@ -50502,11 +50943,11 @@ const make$26 = Effect.gen(function* () {
50502
50943
  });
50503
50944
  return VcsProvisioningService.of({ initRepository });
50504
50945
  });
50505
- const layer$17 = Layer.effect(VcsProvisioningService, make$26);
50946
+ const layer$17 = Layer.effect(VcsProvisioningService, make$27);
50506
50947
  //#endregion
50507
50948
  //#region src/review/ReviewService.ts
50508
50949
  var ReviewService = class extends Context.Service()("@p4code/cli/review/ReviewService") {};
50509
- const make$25 = Effect.gen(function* () {
50950
+ const make$26 = Effect.gen(function* () {
50510
50951
  const config = yield* ServerConfig$1;
50511
50952
  const fileSystem = yield* FileSystem.FileSystem;
50512
50953
  const path = yield* Path.Path;
@@ -50562,7 +51003,7 @@ const make$25 = Effect.gen(function* () {
50562
51003
  });
50563
51004
  return ReviewService.of({ getDiffPreview });
50564
51005
  });
50565
- const layer$16 = Layer.effect(ReviewService, make$25);
51006
+ const layer$16 = Layer.effect(ReviewService, make$26);
50566
51007
  //#endregion
50567
51008
  //#region src/diagnostics/ProcessDiagnostics.ts
50568
51009
  const PROCESS_QUERY_TIMEOUT_MS = 1e3;
@@ -50857,7 +51298,7 @@ function assertDescendantPid(pid) {
50857
51298
  }));
50858
51299
  }));
50859
51300
  }
50860
- const make$24 = Effect.gen(function* () {
51301
+ const make$25 = Effect.gen(function* () {
50861
51302
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
50862
51303
  const read = Effect.gen(function* () {
50863
51304
  const readAt = yield* DateTime.now;
@@ -50901,7 +51342,7 @@ const make$24 = Effect.gen(function* () {
50901
51342
  signal
50902
51343
  });
50903
51344
  });
50904
- const layer$15 = Layer.effect(ProcessDiagnostics, make$24);
51345
+ const layer$15 = Layer.effect(ProcessDiagnostics, make$25);
50905
51346
  //#endregion
50906
51347
  //#region src/diagnostics/ProcessResourceMonitor.ts
50907
51348
  const SAMPLE_INTERVAL_MS = 5e3;
@@ -51052,7 +51493,7 @@ function aggregateProcessResourceHistory(input) {
51052
51493
  }) : Option.none()
51053
51494
  };
51054
51495
  }
51055
- const make$23 = Effect.gen(function* () {
51496
+ const make$24 = Effect.gen(function* () {
51056
51497
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
51057
51498
  const state = yield* Ref.make({
51058
51499
  samples: [],
@@ -51101,7 +51542,7 @@ const make$23 = Effect.gen(function* () {
51101
51542
  });
51102
51543
  return ProcessResourceMonitor.of({ readHistory });
51103
51544
  });
51104
- const layer$14 = Layer.effect(ProcessResourceMonitor, make$23);
51545
+ const layer$14 = Layer.effect(ProcessResourceMonitor, make$24);
51105
51546
  //#endregion
51106
51547
  //#region src/diagnostics/TraceDiagnostics.ts
51107
51548
  var TraceFileReadError = class extends Schema$1.TaggedErrorClass()("TraceFileReadError", {
@@ -51349,7 +51790,7 @@ function readTraceFile(fileSystem, path) {
51349
51790
  cause
51350
51791
  })) }));
51351
51792
  }
51352
- const make$22 = Effect.gen(function* () {
51793
+ const make$23 = Effect.gen(function* () {
51353
51794
  const fileSystem = yield* FileSystem.FileSystem;
51354
51795
  const read = Effect.fn("TraceDiagnostics.read")(function* (options) {
51355
51796
  const readAt = options.readAt ?? (yield* DateTime.now);
@@ -51393,7 +51834,7 @@ const make$22 = Effect.gen(function* () {
51393
51834
  });
51394
51835
  return TraceDiagnostics.of({ read });
51395
51836
  });
51396
- const layer$13 = Layer.effect(TraceDiagnostics, make$22);
51837
+ const layer$13 = Layer.effect(TraceDiagnostics, make$23);
51397
51838
  function readTraceDiagnostics(options) {
51398
51839
  return Effect.gen(function* () {
51399
51840
  return yield* (yield* TraceDiagnostics).read(options);
@@ -51755,7 +52196,7 @@ function isReviewerName(value) {
51755
52196
  const name = value.trim();
51756
52197
  return name.length > 0 && !name.startsWith("-");
51757
52198
  }
51758
- const make$21 = Effect.gen(function* () {
52199
+ const make$22 = Effect.gen(function* () {
51759
52200
  const azure = yield* AzureDevOpsCli;
51760
52201
  const detectArgs = ["--detect", "true"];
51761
52202
  const executeJson = (input) => azure.execute({
@@ -51955,7 +52396,7 @@ const make$21 = Effect.gen(function* () {
51955
52396
  }).pipe(Effect.asVoid)
51956
52397
  });
51957
52398
  });
51958
- const layer$12 = Layer.effect(AzureDevOpsPullRequestCli, make$21);
52399
+ const layer$12 = Layer.effect(AzureDevOpsPullRequestCli, make$22);
51959
52400
  //#endregion
51960
52401
  //#region src/pullRequest/AzureDevOpsPullRequestProvider.ts
51961
52402
  const CAPABILITIES$3 = {
@@ -52030,7 +52471,7 @@ function toChangeRequest$1(pullRequest) {
52030
52471
  labels: []
52031
52472
  };
52032
52473
  }
52033
- const make$20 = Effect.gen(function* () {
52474
+ const make$21 = Effect.gen(function* () {
52034
52475
  const cli = yield* AzureDevOpsPullRequestCli;
52035
52476
  const fail = (operation) => (error) => new PullRequestProviderError({
52036
52477
  provider: "azure-devops",
@@ -52762,7 +53203,7 @@ function mergeStrategy(method) {
52762
53203
  default: return "merge_commit";
52763
53204
  }
52764
53205
  }
52765
- const make$19 = Effect.gen(function* () {
53206
+ const make$20 = Effect.gen(function* () {
52766
53207
  const bitbucket = yield* BitbucketApi;
52767
53208
  /**
52768
53209
  * The repository's own path, and the workspace above it — which the people who may review are
@@ -53042,7 +53483,7 @@ const make$19 = Effect.gen(function* () {
53042
53483
  }).pipe(Effect.asVoid))
53043
53484
  });
53044
53485
  });
53045
- const layer$11 = Layer.effect(BitbucketPullRequestApi, make$19);
53486
+ const layer$11 = Layer.effect(BitbucketPullRequestApi, make$20);
53046
53487
  //#endregion
53047
53488
  //#region src/pullRequest/BitbucketPullRequestProvider.ts
53048
53489
  const CAPABILITIES$2 = {
@@ -53122,7 +53563,7 @@ function toChangeRequest(pullRequest) {
53122
53563
  labels: []
53123
53564
  };
53124
53565
  }
53125
- const make$18 = Effect.gen(function* () {
53566
+ const make$19 = Effect.gen(function* () {
53126
53567
  const api = yield* BitbucketPullRequestApi;
53127
53568
  const fail = (operation) => (error) => new PullRequestProviderError({
53128
53569
  provider: "bitbucket",
@@ -55003,7 +55444,7 @@ function actionArgs$1(action, mergeMethod, updateMethod) {
55003
55444
  case "reopen": return ["reopen"];
55004
55445
  }
55005
55446
  }
55006
- const make$17 = Effect.gen(function* () {
55447
+ const make$18 = Effect.gen(function* () {
55007
55448
  const github = yield* GitHubCli;
55008
55449
  /**
55009
55450
  * The pull request's own node id, which is what a mutation against the pull request itself is
@@ -55723,7 +56164,7 @@ const make$17 = Effect.gen(function* () {
55723
56164
  })))
55724
56165
  });
55725
56166
  });
55726
- const layer$10 = Layer.effect(GitHubPullRequestCli, make$17);
56167
+ const layer$10 = Layer.effect(GitHubPullRequestCli, make$18);
55727
56168
  //#endregion
55728
56169
  //#region src/pullRequest/GitHubPullRequestProvider.ts
55729
56170
  const CAPABILITIES$1 = {
@@ -55838,7 +56279,7 @@ function loginAvatarUrl(login, host) {
55838
56279
  }
55839
56280
  /** True where markdown would render nothing: whitespace, or only HTML comments. */
55840
56281
  const rendersEmpty = (body) => body.replace(/<!--[\s\S]*?-->/g, "").trim().length === 0;
55841
- const make$16 = Effect.gen(function* () {
56282
+ const make$17 = Effect.gen(function* () {
55842
56283
  const cli = yield* GitHubPullRequestCli;
55843
56284
  const fail = (operation) => (error) => new PullRequestProviderError({
55844
56285
  provider: "github",
@@ -56852,7 +57293,7 @@ function actionArgs(action, mergeMethod) {
56852
57293
  case "reopen": return ["reopen"];
56853
57294
  }
56854
57295
  }
56855
- const make$15 = Effect.gen(function* () {
57296
+ const make$16 = Effect.gen(function* () {
56856
57297
  const gitlab = yield* GitLabCli;
56857
57298
  const api = (input) => gitlab.execute({
56858
57299
  cwd: input.cwd,
@@ -57423,7 +57864,7 @@ const make$15 = Effect.gen(function* () {
57423
57864
  }).pipe(Effect.asVoid)
57424
57865
  });
57425
57866
  });
57426
- const layer$9 = Layer.effect(GitLabPullRequestCli, make$15);
57867
+ const layer$9 = Layer.effect(GitLabPullRequestCli, make$16);
57427
57868
  //#endregion
57428
57869
  //#region src/pullRequest/GitLabPullRequestProvider.ts
57429
57870
  const CAPABILITIES = {
@@ -57503,7 +57944,7 @@ function reasonFor(error) {
57503
57944
  if (error._tag === "GitLabCliAuthenticationError") return "unauthenticated";
57504
57945
  return "failed";
57505
57946
  }
57506
- const make$14 = Effect.gen(function* () {
57947
+ const make$15 = Effect.gen(function* () {
57507
57948
  const cli = yield* GitLabPullRequestCli;
57508
57949
  const fail = (operation) => (error) => new PullRequestProviderError({
57509
57950
  provider: "gitlab",
@@ -57646,13 +58087,13 @@ function fromProviders(providers) {
57646
58087
  * The hosts this build can read change requests from. A host with no entry here still shows up
57647
58088
  * in the provider list as unimplemented, so its projects are explained rather than missing.
57648
58089
  */
57649
- const make$13 = Effect.map(Effect.all([
57650
- make$16,
57651
- make$14,
57652
- make$18,
57653
- make$20
58090
+ const make$14 = Effect.map(Effect.all([
58091
+ make$17,
58092
+ make$15,
58093
+ make$19,
58094
+ make$21
57654
58095
  ]), fromProviders);
57655
- const layer$8 = Layer.effect(PullRequestProviderRegistry, make$13).pipe(Layer.provide(layer$10.pipe(Layer.provide(layer$25))), Layer.provide(layer$9.pipe(Layer.provide(layer$23))), Layer.provide(layer$11.pipe(Layer.provide(layer$27))), Layer.provide(layer$12.pipe(Layer.provide(layer$29))));
58096
+ const layer$8 = Layer.effect(PullRequestProviderRegistry, make$14).pipe(Layer.provide(layer$10.pipe(Layer.provide(layer$25))), Layer.provide(layer$9.pipe(Layer.provide(layer$23))), Layer.provide(layer$11.pipe(Layer.provide(layer$27))), Layer.provide(layer$12.pipe(Layer.provide(layer$29))));
57656
58097
  //#endregion
57657
58098
  //#region src/pullRequest/PullRequestService.ts
57658
58099
  /**
@@ -57840,7 +58281,7 @@ function repositoryIdentityOf(project) {
57840
58281
  if (identity.displayName) return identity.displayName;
57841
58282
  return identity.owner && identity.name ? `${identity.owner}/${identity.name}` : null;
57842
58283
  }
57843
- const make$12 = Effect.gen(function* () {
58284
+ const make$13 = Effect.gen(function* () {
57844
58285
  const registry = yield* PullRequestProviderRegistry;
57845
58286
  const projections = yield* ProjectionSnapshotQuery;
57846
58287
  const sourceControlProviders = yield* SourceControlProviderRegistry;
@@ -58808,7 +59249,7 @@ const make$12 = Effect.gen(function* () {
58808
59249
  invalidate
58809
59250
  });
58810
59251
  });
58811
- const layer$7 = Layer.effect(PullRequestService, make$12);
59252
+ const layer$7 = Layer.effect(PullRequestService, make$13);
58812
59253
  //#endregion
58813
59254
  //#region src/sourceControl/SourceControlDiscovery.ts
58814
59255
  const VCS_PROBES = [{
@@ -58827,7 +59268,7 @@ const VCS_PROBES = [{
58827
59268
  installHint: "Install Jujutsu with `brew install jj` or from https://github.com/jj-vcs/jj."
58828
59269
  }];
58829
59270
  var SourceControlDiscovery = class extends Context.Service()("@p4code/cli/sourceControl/SourceControlDiscovery") {};
58830
- const make$11 = Effect.gen(function* () {
59271
+ const make$12 = Effect.gen(function* () {
58831
59272
  const config = yield* ServerConfig$1;
58832
59273
  const process = yield* VcsProcess;
58833
59274
  const sourceControlProviders = yield* SourceControlProviderRegistry;
@@ -58876,7 +59317,7 @@ const make$11 = Effect.gen(function* () {
58876
59317
  sourceControlProviders: sourceControlProviders.discover
58877
59318
  }) });
58878
59319
  });
58879
- const layer$6 = Layer.effect(SourceControlDiscovery, make$11);
59320
+ const layer$6 = Layer.effect(SourceControlDiscovery, make$12);
58880
59321
  //#endregion
58881
59322
  //#region src/sourceControl/SourceControlRepositoryService.ts
58882
59323
  const isSourceControlRepositoryError = Schema$1.is(SourceControlRepositoryError);
@@ -58909,7 +59350,7 @@ function expandHomePath(input, path) {
58909
59350
  if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
58910
59351
  return input;
58911
59352
  }
58912
- const make$10 = Effect.gen(function* () {
59353
+ const make$11 = Effect.gen(function* () {
58913
59354
  const config = yield* ServerConfig$1;
58914
59355
  const fileSystem = yield* FileSystem.FileSystem;
58915
59356
  const git = yield* GitVcsDriver;
@@ -59048,7 +59489,7 @@ const make$10 = Effect.gen(function* () {
59048
59489
  publishRepository: (input) => publishRepository(input).pipe(mapRepositoryError("publishRepository", input.provider))
59049
59490
  });
59050
59491
  });
59051
- const layer$5 = Layer.effect(SourceControlRepositoryService, make$10);
59492
+ const layer$5 = Layer.effect(SourceControlRepositoryService, make$11);
59052
59493
  //#endregion
59053
59494
  //#region src/ws.ts
59054
59495
  /** Matches `p4c hub token add`, so a token minted here and one minted there are the same thing. */
@@ -59451,6 +59892,23 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
59451
59892
  threadId: event.payload.threadId
59452
59893
  }));
59453
59894
  case "thread.unarchived": return threadUpsertOrRemove(event.payload.threadId, event.sequence);
59895
+ case "thread-pair.created": return Effect.succeed(Option.some({
59896
+ kind: "thread-pair-upserted",
59897
+ sequence: event.sequence,
59898
+ pair: {
59899
+ id: event.payload.pairId,
59900
+ implementerThreadId: event.payload.implementerThreadId,
59901
+ watcherThreadId: event.payload.watcherThreadId,
59902
+ lastReviewedImplementerSequence: event.payload.lastReviewedImplementerSequence,
59903
+ createdAt: event.payload.createdAt,
59904
+ detachedAt: null
59905
+ }
59906
+ }));
59907
+ case "thread-pair.detached": return Effect.succeed(Option.some({
59908
+ kind: "thread-pair-removed",
59909
+ sequence: event.sequence,
59910
+ pairId: event.payload.pairId
59911
+ }));
59454
59912
  default:
59455
59913
  if (event.aggregateKind !== "thread") return Effect.succeed(Option.none());
59456
59914
  return threadUpsertOrRemove(ThreadId.make(event.aggregateId), event.sequence);
@@ -60272,7 +60730,7 @@ function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation, correlatio
60272
60730
  cause
60273
60731
  });
60274
60732
  }
60275
- const make$9 = Effect.gen(function* () {
60733
+ const make$10 = Effect.gen(function* () {
60276
60734
  const sql = yield* SqlClient.SqlClient;
60277
60735
  const upsertRuntimeRow = SqlSchema.void({
60278
60736
  Request: ProviderSessionRuntimeDbRowSchema,
@@ -60375,7 +60833,7 @@ const make$9 = Effect.gen(function* () {
60375
60833
  deleteByThreadId
60376
60834
  };
60377
60835
  });
60378
- const layer$4 = Layer.effect(ProviderSessionRuntimeRepository, make$9);
60836
+ const layer$4 = Layer.effect(ProviderSessionRuntimeRepository, make$10);
60379
60837
  //#endregion
60380
60838
  //#region src/provider/Errors.ts
60381
60839
  /**
@@ -61029,6 +61487,54 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
61029
61487
  };
61030
61488
  });
61031
61489
  });
61490
+ const grantWatchThread = Effect.fn("McpSessionRegistry.grantWatchThread")(function* ({ watcherThreadId, watchedThreadId }) {
61491
+ yield* SynchronizedRef.update(state, ({ records, spawnedThreadIds }) => {
61492
+ const next = new Map(records);
61493
+ for (const [tokenHash, record] of records) {
61494
+ if (record.scope.threadId !== watcherThreadId) continue;
61495
+ next.set(tokenHash, {
61496
+ ...record,
61497
+ scope: {
61498
+ ...record.scope,
61499
+ capabilities: /* @__PURE__ */ new Set([...record.scope.capabilities, "watch"]),
61500
+ watchThreadIds: /* @__PURE__ */ new Set([...record.scope.watchThreadIds ?? [], watchedThreadId])
61501
+ }
61502
+ });
61503
+ }
61504
+ return {
61505
+ records: next,
61506
+ spawnedThreadIds
61507
+ };
61508
+ });
61509
+ });
61510
+ const revokeWatchThread = Effect.fn("McpSessionRegistry.revokeWatchThread")(function* ({ watcherThreadId, watchedThreadId }) {
61511
+ yield* SynchronizedRef.update(state, ({ records, spawnedThreadIds }) => {
61512
+ const next = new Map(records);
61513
+ for (const [tokenHash, record] of records) {
61514
+ if (record.scope.threadId !== watcherThreadId) continue;
61515
+ const watchThreadIds = new Set(record.scope.watchThreadIds ?? []);
61516
+ watchThreadIds.delete(watchedThreadId);
61517
+ const capabilities = new Set(record.scope.capabilities);
61518
+ if (watchThreadIds.size === 0) capabilities.delete("watch");
61519
+ const { watchThreadIds: _previousWatchThreadIds, ...scopeWithoutWatch } = record.scope;
61520
+ next.set(tokenHash, {
61521
+ ...record,
61522
+ scope: watchThreadIds.size > 0 ? {
61523
+ ...scopeWithoutWatch,
61524
+ capabilities,
61525
+ watchThreadIds
61526
+ } : {
61527
+ ...scopeWithoutWatch,
61528
+ capabilities
61529
+ }
61530
+ });
61531
+ }
61532
+ return {
61533
+ records: next,
61534
+ spawnedThreadIds
61535
+ };
61536
+ });
61537
+ });
61032
61538
  const recordSpawnedThread = Effect.fn("McpSessionRegistry.recordSpawnedThread")(function* (input) {
61033
61539
  yield* SynchronizedRef.update(state, ({ records, spawnedThreadIds }) => {
61034
61540
  const next = new Map(records);
@@ -61050,6 +61556,8 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
61050
61556
  issue,
61051
61557
  resolve,
61052
61558
  touch,
61559
+ grantWatchThread,
61560
+ revokeWatchThread,
61053
61561
  recordSpawnedThread,
61054
61562
  revokeProviderSession: Effect.fn("McpSessionRegistry.revokeProviderSession")(function* (providerSessionId) {
61055
61563
  yield* revokeWhere((record) => record.scope.providerSessionId === providerSessionId);
@@ -61064,18 +61572,20 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
61064
61572
  });
61065
61573
  });
61066
61574
  let activeMcpSessionRegistry;
61067
- const make$8 = Effect.acquireRelease(makeWithOptions().pipe(Effect.tap((registry) => Effect.sync(() => {
61575
+ const make$9 = Effect.acquireRelease(makeWithOptions().pipe(Effect.tap((registry) => Effect.sync(() => {
61068
61576
  activeMcpSessionRegistry = registry;
61069
61577
  }))), (registry) => Effect.sync(() => {
61070
61578
  if (activeMcpSessionRegistry === registry) activeMcpSessionRegistry = void 0;
61071
61579
  }));
61072
- const layer$3 = Layer.effect(McpSessionRegistry, make$8);
61580
+ const layer$3 = Layer.effect(McpSessionRegistry, make$9);
61073
61581
  const issueActiveMcpCredential = (request) => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeThread(request.threadId).pipe(Effect.andThen(activeMcpSessionRegistry.issue(request))) : Effect.sync(() => void 0);
61074
61582
  /**
61075
61583
  * Refreshes the liveness of a thread's MCP credential. Called on every provider
61076
61584
  * turn so an active session is never mistaken for an abandoned one.
61077
61585
  */
61078
61586
  const touchActiveMcpThread = (threadId) => activeMcpSessionRegistry ? activeMcpSessionRegistry.touch(threadId) : Effect.void;
61587
+ const grantActiveMcpWatchThread = (input) => activeMcpSessionRegistry ? activeMcpSessionRegistry.grantWatchThread(input) : Effect.void;
61588
+ const revokeActiveMcpWatchThread = (input) => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeWatchThread(input) : Effect.void;
61079
61589
  const revokeActiveMcpThread = (threadId) => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeThread(threadId) : Effect.void;
61080
61590
  const revokeAllActiveMcpCredentials = () => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeAll : Effect.void;
61081
61591
  //#endregion
@@ -61161,9 +61671,10 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
61161
61671
  const directory = yield* ProviderSessionDirectory;
61162
61672
  const runtimeEventPubSub = yield* PubSub.unbounded();
61163
61673
  const nowIso = Effect.map(DateTime.now, DateTime.formatIso);
61164
- const prepareMcpSession = (threadId, providerInstanceId) => issueActiveMcpCredential({
61674
+ const prepareMcpSession = (threadId, providerInstanceId, watchThreadIds) => issueActiveMcpCredential({
61165
61675
  threadId,
61166
- providerInstanceId
61676
+ providerInstanceId,
61677
+ ...watchThreadIds !== void 0 ? { watchThreadIds } : {}
61167
61678
  }).pipe(Effect.tap((credential) => credential ? Effect.sync(() => setMcpProviderSession(credential.config)) : Effect.void));
61168
61679
  const clearMcpSession = (threadId) => revokeActiveMcpThread(threadId).pipe(Effect.tap(() => Effect.sync(() => clearMcpProviderSession(threadId))));
61169
61680
  const publishRuntimeEvent = (event) => Effect.succeed(event).pipe(Effect.tap((canonicalEvent) => canonicalEventLogger ? canonicalEventLogger.write(canonicalEvent, canonicalEvent.threadId) : Effect.void), Effect.flatMap((canonicalEvent) => PubSub.publish(runtimeEventPubSub, canonicalEvent)), Effect.asVoid);
@@ -61308,7 +61819,7 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
61308
61819
  })));
61309
61820
  }), { discard: true });
61310
61821
  });
61311
- const startSession = Effect.fn("startSession")(function* (threadId, rawInput) {
61822
+ const startSession = Effect.fn("startSession")(function* (threadId, rawInput, options) {
61312
61823
  const parsed = yield* decodeInputOrValidationError({
61313
61824
  operation: "ProviderService.startSession",
61314
61825
  schema: ProviderSessionStartInput,
@@ -61344,7 +61855,7 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
61344
61855
  "provider.cwd.effective": effectiveCwd ?? ""
61345
61856
  });
61346
61857
  const adapter = yield* registry.getByInstance(resolvedInstanceId);
61347
- yield* prepareMcpSession(threadId, resolvedInstanceId);
61858
+ yield* prepareMcpSession(threadId, resolvedInstanceId, options?.watchThreadIds);
61348
61859
  const session = yield* adapter.startSession({
61349
61860
  ...input,
61350
61861
  providerInstanceId: resolvedInstanceId,
@@ -85119,7 +85630,7 @@ const makeTerminationError$1 = (handle) => Effect.match(handle.exitCode, {
85119
85630
  //#endregion
85120
85631
  //#region ../../packages/effect-codex-app-server/src/client.ts
85121
85632
  var CodexAppServerClient = class extends Context.Service()("effect-codex-app-server/client/CodexAppServerClient") {};
85122
- const make$7 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
85633
+ const make$8 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
85123
85634
  const requestHandlers = /* @__PURE__ */ new Map();
85124
85635
  const notificationHandlers = /* @__PURE__ */ new Map();
85125
85636
  let unknownRequestHandler;
@@ -85186,7 +85697,7 @@ const make$7 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(fu
85186
85697
  const layerChildProcess$1 = (handle, options = {}) => Layer.effect(CodexAppServerClient, makeChildProcessClient(handle, options));
85187
85698
  const makeChildProcessClient = Effect.fn("effect-codex-app-server/CodexAppServerClient.makeChildProcessClient")(function* (handle, options) {
85188
85699
  yield* Stream.runDrain(handle.stderr).pipe(Effect.ignore, Effect.forkScoped);
85189
- return yield* make$7(makeChildStdio$1(handle), options, makeTerminationError$1(handle));
85700
+ return yield* make$8(makeChildStdio$1(handle), options, makeTerminationError$1(handle));
85190
85701
  });
85191
85702
  //#endregion
85192
85703
  //#region src/provider/Layers/CodexProvider.ts
@@ -91244,7 +91755,7 @@ const makeTerminationError = (handle) => Effect.match(handle.exitCode, {
91244
91755
  //#endregion
91245
91756
  //#region ../../packages/effect-acp/src/client.ts
91246
91757
  var AcpClient = class extends Context.Service()("effect-acp/client/AcpClient") {};
91247
- const make$6 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options = {}, terminationError) {
91758
+ const make$7 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options = {}, terminationError) {
91248
91759
  const coreHandlers = {};
91249
91760
  const notificationHandlers = {
91250
91761
  sessionUpdate: {
@@ -91402,7 +91913,7 @@ const make$6 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options
91402
91913
  const layerChildProcess = (handle, options = {}) => {
91403
91914
  const stdio = makeChildStdio(handle);
91404
91915
  const terminationError = makeTerminationError(handle);
91405
- return Layer.effect(AcpClient, make$6(stdio, options, terminationError));
91916
+ return Layer.effect(AcpClient, make$7(stdio, options, terminationError));
91406
91917
  };
91407
91918
  //#endregion
91408
91919
  //#region ../../packages/shared/src/toolActivity.ts
@@ -91862,7 +92373,7 @@ function formatConfigOptionValue(value) {
91862
92373
  const defaultSessionLoadTimeout = Duration.seconds(90);
91863
92374
  const defaultSessionLoadReplayIdleGap = Duration.seconds(2);
91864
92375
  var AcpSessionRuntime = class extends Context.Service()("@p4code/cli/provider/acp/AcpSessionRuntime") {};
91865
- const make$5 = (options) => Effect.gen(function* () {
92376
+ const make$6 = (options) => Effect.gen(function* () {
91866
92377
  const crypto = yield* Crypto.Crypto;
91867
92378
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
91868
92379
  const runtimeScope = yield* Scope.Scope;
@@ -92171,7 +92682,7 @@ const make$5 = (options) => Effect.gen(function* () {
92171
92682
  notify: acp.raw.notify
92172
92683
  };
92173
92684
  });
92174
- const layer$2 = (options) => Layer.effect(AcpSessionRuntime, make$5(options));
92685
+ const layer$2 = (options) => Layer.effect(AcpSessionRuntime, make$6(options));
92175
92686
  function sessionConfigOptionsFromSetup(response) {
92176
92687
  return response?.configOptions ?? [];
92177
92688
  }
@@ -99558,7 +100069,7 @@ const stringField = (record, key) => {
99558
100069
  const value = record[key];
99559
100070
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
99560
100071
  };
99561
- const make$4 = Effect.gen(function* () {
100072
+ const make$5 = Effect.gen(function* () {
99562
100073
  const linear = yield* LinearClient;
99563
100074
  return { resolve: Effect.fn("TicketResolver.resolve")(function* (reference) {
99564
100075
  const identifier = parseTicketReference(reference);
@@ -99589,7 +100100,7 @@ const make$4 = Effect.gen(function* () {
99589
100100
  };
99590
100101
  }) };
99591
100102
  });
99592
- const layer$1 = Layer.effect(TicketResolver, make$4);
100103
+ const layer$1 = Layer.effect(TicketResolver, make$5);
99593
100104
  //#endregion
99594
100105
  //#region src/mcp/toolkits/tasks/tools.ts
99595
100106
  const dependencies = [McpInvocationContext, TaskRepository];
@@ -100695,17 +101206,22 @@ var ProviderRuntimeIngestionService = class extends Context.Service()("@p4code/c
100695
101206
  */
100696
101207
  var ThreadDeletionReactor = class extends Context.Service()("@p4code/cli/orchestration/Services/ThreadDeletionReactor") {};
100697
101208
  //#endregion
101209
+ //#region src/orchestration/Services/FusionWatcherReactor.ts
101210
+ var FusionWatcherReactor = class extends Context.Service()("@p4code/cli/orchestration/Services/FusionWatcherReactor") {};
101211
+ //#endregion
100698
101212
  //#region src/orchestration/Layers/OrchestrationReactor.ts
100699
101213
  const makeOrchestrationReactor = Effect.gen(function* () {
100700
101214
  const providerRuntimeIngestion = yield* ProviderRuntimeIngestionService;
100701
101215
  const providerCommandReactor = yield* ProviderCommandReactor;
100702
101216
  const checkpointReactor = yield* CheckpointReactor;
100703
101217
  const threadDeletionReactor = yield* ThreadDeletionReactor;
101218
+ const fusionWatcherReactor = yield* FusionWatcherReactor;
100704
101219
  return { start: Effect.fn("start")(function* () {
100705
101220
  yield* providerRuntimeIngestion.start();
100706
101221
  yield* providerCommandReactor.start();
100707
101222
  yield* checkpointReactor.start();
100708
101223
  yield* threadDeletionReactor.start();
101224
+ yield* fusionWatcherReactor.start();
100709
101225
  }) };
100710
101226
  });
100711
101227
  const OrchestrationReactorLive = Layer.effect(OrchestrationReactor, makeOrchestrationReactor);
@@ -101287,7 +101803,7 @@ function runtimeEventToActivities(event, taskTitle, compressMode) {
101287
101803
  }
101288
101804
  return [];
101289
101805
  }
101290
- const make$3 = Effect.gen(function* () {
101806
+ const make$4 = Effect.gen(function* () {
101291
101807
  const crypto = yield* Crypto.Crypto;
101292
101808
  const orchestrationEngine = yield* OrchestrationEngineService;
101293
101809
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
@@ -101790,6 +102306,14 @@ const make$3 = Effect.gen(function* () {
101790
102306
  updatedAt: now
101791
102307
  });
101792
102308
  }
102309
+ if (shouldApplyThreadLifecycle) yield* orchestrationEngine.dispatch({
102310
+ type: "thread.turn.complete",
102311
+ commandId: yield* providerCommandId(event, "thread-turn-complete"),
102312
+ threadId: thread.id,
102313
+ ...turnId ? { turnId } : {},
102314
+ state: normalizeRuntimeTurnState(event.payload.state),
102315
+ completedAt: now
102316
+ });
101793
102317
  }
101794
102318
  if (event.type === "session.exited") yield* clearTurnStateForSession(thread.id);
101795
102319
  if (event.type === "runtime.error") {
@@ -101888,7 +102412,7 @@ const make$3 = Effect.gen(function* () {
101888
102412
  drain: worker.drain
101889
102413
  };
101890
102414
  });
101891
- const ProviderRuntimeIngestionLive = Layer.effect(ProviderRuntimeIngestionService, make$3).pipe(Layer.provide(ProjectionTurnRepositoryLive));
102415
+ const ProviderRuntimeIngestionLive = Layer.effect(ProviderRuntimeIngestionService, make$4).pipe(Layer.provide(ProjectionTurnRepositoryLive));
101892
102416
  //#endregion
101893
102417
  //#region src/provider/userInvokedSkills.ts
101894
102418
  /**
@@ -102074,7 +102598,7 @@ function buildGeneratedWorktreeBranchName(raw) {
102074
102598
  const branchFragment = (normalized.startsWith(`p4code/`) ? normalized.slice(`${WORKTREE_BRANCH_PREFIX}/`.length) : normalized).replace(/[^a-z0-9/_-]+/g, "-").replace(/\/+/g, "/").replace(/-+/g, "-").replace(/^[./_-]+|[./_-]+$/g, "").slice(0, 64).replace(/[./_-]+$/g, "");
102075
102599
  return `${WORKTREE_BRANCH_PREFIX}/${branchFragment.length > 0 ? branchFragment : "update"}`;
102076
102600
  }
102077
- const make$2 = Effect.gen(function* () {
102601
+ const make$3 = Effect.gen(function* () {
102078
102602
  const crypto = yield* Crypto.Crypto;
102079
102603
  const orchestrationEngine = yield* OrchestrationEngineService;
102080
102604
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
@@ -102282,6 +102806,11 @@ const make$2 = Effect.gen(function* () {
102282
102806
  if (!thread) return yield* Effect.die(/* @__PURE__ */ new Error(`Thread '${threadId}' was not found in read model.`));
102283
102807
  const desiredRuntimeMode = thread.runtimeMode;
102284
102808
  const requestedModelSelection = options?.modelSelection;
102809
+ const watchThreadIds = ((yield* projectionSnapshotQuery.getCommandReadModel()).threadPairs ?? []).filter((pair) => pair.detachedAt === null && pair.watcherThreadId === threadId).map((pair) => pair.implementerThreadId);
102810
+ yield* Effect.forEach(watchThreadIds, (watchedThreadId) => grantActiveMcpWatchThread({
102811
+ watcherThreadId: threadId,
102812
+ watchedThreadId
102813
+ }), { discard: true });
102285
102814
  const resolveActiveSession = (threadId) => providerService.listSessions().pipe(Effect.map((sessions) => sessions.find((session) => session.threadId === threadId)));
102286
102815
  const activeSession = yield* resolveActiveSession(threadId);
102287
102816
  const activeThreadSession = thread.session !== null && thread.session.status !== "stopped" && activeSession ? thread.session : null;
@@ -102371,7 +102900,7 @@ const make$2 = Effect.gen(function* () {
102371
102900
  runtimeMode: desiredRuntimeMode,
102372
102901
  compressMode: thread.compressMode,
102373
102902
  unpromptedSubagents: thread.unpromptedSubagents
102374
- });
102903
+ }, watchThreadIds.length > 0 ? { watchThreadIds } : void 0);
102375
102904
  };
102376
102905
  const bindSessionToThread = (session) => Effect.gen(function* () {
102377
102906
  if (session.providerInstanceId === void 0) return yield* new ProviderAdapterRequestError({
@@ -102789,7 +103318,7 @@ const make$2 = Effect.gen(function* () {
102789
103318
  drain: worker.drain
102790
103319
  };
102791
103320
  });
102792
- const ProviderCommandReactorLive = Layer.effect(ProviderCommandReactor, make$2);
103321
+ const ProviderCommandReactorLive = Layer.effect(ProviderCommandReactor, make$3);
102793
103322
  //#endregion
102794
103323
  //#region src/checkpointing/Diffs.ts
102795
103324
  function parseTurnDiffFilesFromUnifiedDiff(diff) {
@@ -102819,7 +103348,7 @@ function checkpointStatusFromRuntime(status) {
102819
103348
  default: return "ready";
102820
103349
  }
102821
103350
  }
102822
- const make$1 = Effect.gen(function* () {
103351
+ const make$2 = Effect.gen(function* () {
102823
103352
  const randomUUID = (yield* Crypto.Crypto).randomUUIDv4;
102824
103353
  const serverEventId = randomUUID.pipe(Effect.map(EventId.make));
102825
103354
  const serverCommandId = (tag) => randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`)));
@@ -103301,7 +103830,106 @@ const make$1 = Effect.gen(function* () {
103301
103830
  drain: worker.drain
103302
103831
  };
103303
103832
  });
103304
- const CheckpointReactorLive = Layer.effect(CheckpointReactor, make$1);
103833
+ const CheckpointReactorLive = Layer.effect(CheckpointReactor, make$2);
103834
+ //#endregion
103835
+ //#region src/orchestration/Layers/FusionWatcherReactor.ts
103836
+ const reviewCommandId = (pairId, sequence) => CommandId.make(`server:fusion:${pairId}:review:${sequence}`);
103837
+ const cursorCommandId = (pairId, sequence) => CommandId.make(`server:fusion:${pairId}:cursor:${sequence}`);
103838
+ const reviewMessageId = (pairId, sequence) => MessageId.make(`fusion-review:${pairId}:${sequence}`);
103839
+ const watcherPrompt = (input) => `${FUSION_REVIEW_PROMPT_PREFIX}
103840
+ Review implementer thread ${input.implementerThreadId} after its accepted turn completion.
103841
+
103842
+ Call thread_watch_events with threadId ${input.implementerThreadId} and afterSequence ${input.afterSequence}. Continue paging through sequence ${input.throughSequence}. Inspect repository state when useful.
103843
+
103844
+ Report only a concrete objection: correctness risk, missed requirement, regression, unsafe change, or unnecessary scope. Cite evidence. If no objection exists, return exactly ${FUSION_NO_OBJECTION_TEXT} and nothing else. This marker is hidden from the transcript.`;
103845
+ const make$1 = Effect.gen(function* () {
103846
+ const orchestrationEngine = yield* OrchestrationEngineService;
103847
+ const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
103848
+ const processReview = Effect.fn("FusionWatcherReactor.processReview")(function* (pair, completion) {
103849
+ const readModel = yield* projectionSnapshotQuery.getCommandReadModel();
103850
+ const currentPair = (readModel.threadPairs ?? []).find((candidate) => candidate.id === pair.id);
103851
+ if (currentPair === void 0 || currentPair.detachedAt !== null || completion.sequence <= currentPair.lastReviewedImplementerSequence) return;
103852
+ const watcher = readModel.threads.find((thread) => thread.id === currentPair.watcherThreadId && thread.deletedAt === null);
103853
+ if (watcher === void 0) return;
103854
+ yield* orchestrationEngine.dispatch({
103855
+ type: "thread.turn.start",
103856
+ commandId: reviewCommandId(currentPair.id, completion.sequence),
103857
+ threadId: watcher.id,
103858
+ message: {
103859
+ messageId: reviewMessageId(currentPair.id, completion.sequence),
103860
+ role: "user",
103861
+ text: watcherPrompt({
103862
+ implementerThreadId: currentPair.implementerThreadId,
103863
+ afterSequence: currentPair.lastReviewedImplementerSequence,
103864
+ throughSequence: completion.sequence
103865
+ }),
103866
+ attachments: []
103867
+ },
103868
+ runtimeMode: watcher.runtimeMode,
103869
+ interactionMode: watcher.interactionMode,
103870
+ compressMode: watcher.compressMode,
103871
+ unpromptedSubagents: watcher.unpromptedSubagents,
103872
+ createdAt: completion.occurredAt
103873
+ });
103874
+ yield* orchestrationEngine.dispatch({
103875
+ type: "thread-pair.cursor.advance",
103876
+ commandId: cursorCommandId(currentPair.id, completion.sequence),
103877
+ pairId: currentPair.id,
103878
+ implementerSequence: completion.sequence,
103879
+ advancedAt: completion.occurredAt
103880
+ });
103881
+ });
103882
+ const catchUpPair = Effect.fn("FusionWatcherReactor.catchUpPair")(function* (pair, throughSequence) {
103883
+ if (throughSequence <= pair.lastReviewedImplementerSequence) return;
103884
+ const completions = (yield* orchestrationEngine.readEvents(pair.lastReviewedImplementerSequence, throughSequence - pair.lastReviewedImplementerSequence).pipe(Stream.takeWhile((event) => event.sequence <= throughSequence), Stream.runCollect)).filter((event) => event.type === "thread.turn-completed" && event.payload.threadId === pair.implementerThreadId);
103885
+ for (const completion of completions) yield* processReview(pair, completion);
103886
+ });
103887
+ const processCompletion = Effect.fn("FusionWatcherReactor.processCompletion")(function* (event) {
103888
+ const pairs = ((yield* projectionSnapshotQuery.getCommandReadModel()).threadPairs ?? []).filter((pair) => pair.detachedAt === null && pair.implementerThreadId === event.payload.threadId && event.sequence > pair.lastReviewedImplementerSequence);
103889
+ yield* Effect.forEach(pairs, (pair) => catchUpPair(pair, event.sequence), {
103890
+ concurrency: 1,
103891
+ discard: true
103892
+ });
103893
+ });
103894
+ const processEvent = Effect.fn("FusionWatcherReactor.processEvent")(function* (event) {
103895
+ if (event.type === "thread.turn-completed") {
103896
+ yield* processCompletion(event);
103897
+ return;
103898
+ }
103899
+ if (event.type === "thread-pair.created") {
103900
+ yield* grantActiveMcpWatchThread({
103901
+ watcherThreadId: event.payload.watcherThreadId,
103902
+ watchedThreadId: event.payload.implementerThreadId
103903
+ });
103904
+ return;
103905
+ }
103906
+ const pair = ((yield* projectionSnapshotQuery.getCommandReadModel()).threadPairs ?? []).find((candidate) => candidate.id === event.payload.pairId);
103907
+ if (pair === void 0) return;
103908
+ yield* revokeActiveMcpWatchThread({
103909
+ watcherThreadId: pair.watcherThreadId,
103910
+ watchedThreadId: pair.implementerThreadId
103911
+ });
103912
+ });
103913
+ const processSafely = (event) => processEvent(event).pipe(Effect.catchCause((cause) => {
103914
+ if (Cause.hasInterruptsOnly(cause)) return Effect.failCause(cause);
103915
+ return Effect.logWarning("fusion watcher reactor failed to process completion", {
103916
+ eventType: event.type,
103917
+ sequence: event.sequence,
103918
+ cause: Cause.pretty(cause)
103919
+ });
103920
+ }));
103921
+ const worker = yield* makeDrainableWorker(processSafely);
103922
+ const enqueueEvent = (event) => event.type === "thread.turn-completed" || event.type === "thread-pair.created" || event.type === "thread-pair.detached" ? worker.enqueue(event) : Effect.void;
103923
+ return {
103924
+ start: Effect.fn("FusionWatcherReactor.start")(function* () {
103925
+ yield* Effect.forkScoped(Stream.runForEach(orchestrationEngine.streamDomainEvents, enqueueEvent));
103926
+ const headSequence = yield* orchestrationEngine.latestSequence;
103927
+ yield* Stream.runForEach(orchestrationEngine.readEvents(0, Math.max(1, headSequence)), enqueueEvent).pipe(Effect.catchCause((cause) => Effect.logWarning("fusion watcher reactor failed historical replay", { cause: Cause.pretty(cause) })));
103928
+ }),
103929
+ drain: worker.drain
103930
+ };
103931
+ });
103932
+ const FusionWatcherReactorLive = Layer.effect(FusionWatcherReactor, make$1);
103305
103933
  //#endregion
103306
103934
  //#region src/orchestration/Layers/ThreadDeletionReactor.ts
103307
103935
  const logCleanupCauseUnlessInterrupted = ({ effect, message, threadId }) => effect.pipe(Effect.catchCause((cause) => {
@@ -104063,7 +104691,7 @@ const PlatformServicesLive = Layer.unwrap(Effect.gen(function* () {
104063
104691
  return layer;
104064
104692
  }
104065
104693
  }));
104066
- const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReactorLive), Layer.provideMerge(ProviderRuntimeIngestionLive), Layer.provideMerge(ProviderCommandReactorLive), Layer.provideMerge(CheckpointReactorLive), Layer.provideMerge(ThreadDeletionReactorLive), Layer.provideMerge(RuntimeReceiptBusLive));
104694
+ const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReactorLive), Layer.provideMerge(ProviderRuntimeIngestionLive), Layer.provideMerge(ProviderCommandReactorLive), Layer.provideMerge(CheckpointReactorLive), Layer.provideMerge(ThreadDeletionReactorLive), Layer.provideMerge(FusionWatcherReactorLive), Layer.provideMerge(RuntimeReceiptBusLive));
104067
104695
  const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$4));
104068
104696
  const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
104069
104697
  const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));