@overdeck/contracts 0.60.0 → 0.62.0

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/index.cjs CHANGED
@@ -30,6 +30,8 @@ effect_unstable_rpc_RpcGroup = __toESM(effect_unstable_rpc_RpcGroup, 1);
30
30
  const BackendPane = effect.Schema.Struct({
31
31
  /** Stable pane identity: the backend-native pane handle. */
32
32
  id: effect.Schema.String,
33
+ /** Overdeck agent id: Herdr `agentId` token or live agent name; tmux session name (PAN-3920). */
34
+ agentId: effect.Schema.optional(effect.Schema.String),
33
35
  /** Issue the pane belongs to; absent for operator conversations. */
34
36
  issue: effect.Schema.optional(effect.Schema.String),
35
37
  role: effect.Schema.Literals([
@@ -39,7 +41,8 @@ const BackendPane = effect.Schema.Struct({
39
41
  "test",
40
42
  "uat",
41
43
  "strike",
42
- "plan"
44
+ "plan",
45
+ "conversation"
43
46
  ]),
44
47
  harness: effect.Schema.String,
45
48
  model: effect.Schema.String,
@@ -170,9 +173,17 @@ const MEMBERSHIP_UNAVAILABLE_REASONS = [
170
173
  "repo_unavailable",
171
174
  "default_branch_unresolved",
172
175
  "forge_unavailable",
176
+ "forge_transient",
173
177
  "tracker_unconfigured",
174
178
  "gather_failed"
175
179
  ];
180
+ /**
181
+ * PAN-3527 — the membership snapshot has not been gathered yet (a freshly
182
+ * restarted server warming its cache). Sent with HTTP 503 and a `Retry-After`
183
+ * header. Unlike `PipelineMembershipUnavailableBody` (a settled answer about
184
+ * the project), this is a temporary state: callers retry it.
185
+ */
186
+ const PIPELINE_MEMBERSHIP_LOADING_CODE = "snapshot_loading";
176
187
  const AgentId = effect.Schema.String;
177
188
  const SequenceNumber = effect.Schema.Number;
178
189
  const AgentStatus = effect.Schema.Literals([
@@ -191,7 +202,8 @@ const Role = effect.Schema.Literals([
191
202
  "flywheel",
192
203
  "strike",
193
204
  "sequencer",
194
- "knowledge"
205
+ "knowledge",
206
+ "worker"
195
207
  ]);
196
208
  const AgentResolution = effect.Schema.Literals([
197
209
  "working",
@@ -350,6 +362,12 @@ const AgentSnapshot = effect.Schema.Struct({
350
362
  phase: effect.Schema.optional(effect.Schema.String),
351
363
  workType: effect.Schema.optional(effect.Schema.String),
352
364
  roleRunHead: effect.Schema.optional(effect.Schema.String),
365
+ /** The agent has a live pane on its terminal backend (Herdr or tmux). */
366
+ hasLivePane: effect.Schema.optional(effect.Schema.Boolean),
367
+ /**
368
+ * @deprecated Misnamed alias of `hasLivePane`: true for a live pane on either
369
+ * backend, not only a tmux session. Still populated for compatibility (#4105).
370
+ */
353
371
  hasLiveTmuxSession: effect.Schema.optional(effect.Schema.Boolean),
354
372
  stoppedByUser: effect.Schema.optional(effect.Schema.Boolean),
355
373
  paused: effect.Schema.optional(effect.Schema.Boolean),
@@ -464,6 +482,39 @@ const ProjectCiSnapshot = effect.Schema.Struct({
464
482
  /** Newest `observedAt` folded into this record. */
465
483
  updatedAt: effect.Schema.String
466
484
  });
485
+ /**
486
+ * Where an in-flight dashboard self-deploy (`pan reload`) stands.
487
+ *
488
+ * `building` the reload holds the restart lock and is building from origin/main;
489
+ * `awaiting-approval` the build is ready and the reload waits on the restart gate;
490
+ * `restarting` the operator approved and the old dashboard is being replaced;
491
+ * `failed` the last reload recorded a failure (visible for a short window).
492
+ */
493
+ const ProjectDeployPhase = effect.Schema.Literals([
494
+ "building",
495
+ "awaiting-approval",
496
+ "restarting",
497
+ "failed"
498
+ ]);
499
+ /**
500
+ * One project's deploy, derived on the server from live runtime files: the
501
+ * restart lock, the restart gate, the restart-status journal and the reload
502
+ * process's own stdout. Nothing here is stored; a server restart re-derives it.
503
+ */
504
+ const ProjectDeploySnapshot = effect.Schema.Struct({
505
+ projectKey: effect.Schema.String,
506
+ trigger: effect.Schema.String,
507
+ phase: ProjectDeployPhase,
508
+ /** The deploying process, while it is alive. */
509
+ pid: effect.Schema.optional(effect.Schema.Number),
510
+ /** When the server first observed this deploy (for `failed`, when it failed). */
511
+ startedAt: effect.Schema.String,
512
+ error: effect.Schema.optional(effect.Schema.String),
513
+ /** The reload's output file, when its stdout is a regular file. */
514
+ logPath: effect.Schema.optional(effect.Schema.String),
515
+ /** Last lines of `logPath`. */
516
+ logTail: effect.Schema.optional(effect.Schema.Array(effect.Schema.String))
517
+ });
467
518
  /** What kind of process asked for the voluntary dashboard restart. */
468
519
  const RestartGateKind = effect.Schema.Literals([
469
520
  "deploy",
@@ -533,6 +584,8 @@ const DashboardSnapshot = effect.Schema.Struct({
533
584
  embedProgressBySessionId: effect.Schema.optional(effect.Schema.Record(effect.Schema.String, EmbedProgressSnapshot)),
534
585
  ciByProjectKey: effect.Schema.optional(effect.Schema.Record(effect.Schema.String, ProjectCiSnapshot)),
535
586
  restartGate: effect.Schema.optional(RestartGateSnapshot),
587
+ /** PAN-3751 — in-flight deploys keyed by project key. */
588
+ deployByProjectKey: effect.Schema.optional(effect.Schema.Record(effect.Schema.String, ProjectDeploySnapshot)),
536
589
  timestamp: effect.Schema.String
537
590
  });
538
591
  const ResourceStats = effect.Schema.Struct({ containers: effect.Schema.Array(effect.Schema.Struct({
@@ -787,6 +840,95 @@ const ScanResult = effect.Schema.Struct({
787
840
  durationMs: effect.Schema.Number
788
841
  });
789
842
  //#endregion
843
+ //#region src/pull-request-links.ts
844
+ const PullRequestLinkSource = effect.Schema.Literals([
845
+ "manual",
846
+ "agent",
847
+ "created",
848
+ "branch"
849
+ ]);
850
+ const PullRequestKey = effect.Schema.Struct({
851
+ host: effect.Schema.String,
852
+ repository: effect.Schema.String,
853
+ number: effect.Schema.Number
854
+ });
855
+ const PullRequestState = effect.Schema.Literals([
856
+ "open",
857
+ "merged",
858
+ "closed"
859
+ ]);
860
+ const PullRequestSnapshot = effect.Schema.Struct({
861
+ state: PullRequestState,
862
+ isDraft: effect.Schema.Boolean,
863
+ title: effect.Schema.String,
864
+ headBranch: effect.Schema.NullOr(effect.Schema.String),
865
+ baseBranch: effect.Schema.NullOr(effect.Schema.String),
866
+ reviewState: PrReviewState,
867
+ checks: PrChecksState,
868
+ mergeable: effect.Schema.NullOr(effect.Schema.Boolean),
869
+ additions: effect.Schema.NullOr(effect.Schema.Number),
870
+ deletions: effect.Schema.NullOr(effect.Schema.Number),
871
+ changedFiles: effect.Schema.NullOr(effect.Schema.Number),
872
+ author: effect.Schema.NullOr(effect.Schema.String),
873
+ /** Forge timestamp, ISO. */
874
+ updatedAt: effect.Schema.NullOr(effect.Schema.String),
875
+ mergedAt: effect.Schema.NullOr(effect.Schema.String),
876
+ closedAt: effect.Schema.NullOr(effect.Schema.String),
877
+ /** When Overdeck last read the PR, ISO. */
878
+ syncedAt: effect.Schema.String
879
+ });
880
+ const PullRequestLink = effect.Schema.Struct({
881
+ ...PullRequestKey.fields,
882
+ url: effect.Schema.String,
883
+ source: PullRequestLinkSource,
884
+ linkedAt: effect.Schema.String,
885
+ dismissedAt: effect.Schema.NullOr(effect.Schema.String),
886
+ snapshot: effect.Schema.NullOr(PullRequestSnapshot)
887
+ });
888
+ const ConversationPullRequests = effect.Schema.Struct({
889
+ links: effect.Schema.Array(PullRequestLink),
890
+ effective: effect.Schema.NullOr(PullRequestLink)
891
+ });
892
+ /** One conversation linked to a PR — the reverse index (PR → conversations). */
893
+ const PullRequestLinkedConversation = effect.Schema.Struct({
894
+ /** The /conv/<id> number. */
895
+ id: effect.Schema.Number,
896
+ name: effect.Schema.String,
897
+ title: effect.Schema.NullOr(effect.Schema.String),
898
+ source: PullRequestLinkSource,
899
+ linkedAt: effect.Schema.String
900
+ });
901
+ /** One live link across all conversations, for the Pull requests list. */
902
+ const PullRequestLinkListing = effect.Schema.Struct({
903
+ ...PullRequestLink.fields,
904
+ conversationId: effect.Schema.Number,
905
+ conversationName: effect.Schema.String,
906
+ conversationTitle: effect.Schema.NullOr(effect.Schema.String),
907
+ /** The conversation's effective project, or null when none resolves. */
908
+ projectKey: effect.Schema.NullOr(effect.Schema.String)
909
+ });
910
+ function stateRank(link) {
911
+ if (link.snapshot === null) return 1;
912
+ if (link.snapshot.state === "open") return 0;
913
+ if (link.snapshot.state === "merged") return 2;
914
+ return 3;
915
+ }
916
+ function recency(link) {
917
+ return Date.parse(link.snapshot?.updatedAt ?? link.linkedAt) || 0;
918
+ }
919
+ /**
920
+ * The one PR shown on a conversation: explicit links before branch links,
921
+ * open before merged before closed, most recently updated among equals.
922
+ * Dismissed links never count.
923
+ */
924
+ function resolveEffectivePullRequest(links) {
925
+ const live = links.filter((link) => link.dismissedAt === null);
926
+ const explicit = live.filter((link) => link.source !== "branch");
927
+ const pool = explicit.length > 0 ? explicit : live;
928
+ if (pool.length === 0) return null;
929
+ return [...pool].sort((a, b) => stateRank(a) - stateRank(b) || recency(b) - recency(a))[0] ?? null;
930
+ }
931
+ //#endregion
790
932
  //#region src/memory.ts
791
933
  const MemoryAgentRole = effect.Schema.Union([Role, effect.Schema.Literal("conversation")]);
792
934
  const MemoryIdentity = effect.Schema.Struct({
@@ -1044,6 +1186,9 @@ const AgentHealthSnapshot = effect.Schema.Struct({
1044
1186
  kind: effect.Schema.optional(AgentHealthKind),
1045
1187
  status: AgentHealthStatus,
1046
1188
  lifecycle: effect.Schema.optional(SpecialistLifecycle),
1189
+ /** The agent has a live pane on the selected terminal backend (Herdr or tmux). */
1190
+ hasLivePane: effect.Schema.optional(effect.Schema.Boolean),
1191
+ /** @deprecated Alias of `hasLivePane` kept for existing readers; true on either backend, not only tmux. */
1047
1192
  tmuxActive: effect.Schema.optional(effect.Schema.Boolean),
1048
1193
  memoryBytes: effect.Schema.optional(effect.Schema.Number),
1049
1194
  memoryGb: effect.Schema.optional(effect.Schema.Number),
@@ -1311,6 +1456,20 @@ const RestartGateChangedEvent = effect.Schema.Struct({
1311
1456
  timestamp: effect.Schema.String,
1312
1457
  payload: RestartGateSnapshot
1313
1458
  });
1459
+ /**
1460
+ * The set of in-flight project deploys changed (PAN-3751).
1461
+ *
1462
+ * The payload is the COMPLETE projection keyed by project key, so the reducer
1463
+ * is a plain replace. The server derives it from runtime files (restart lock,
1464
+ * restart gate, restart-status journal) and emits it in-memory only, like
1465
+ * `restart_gate.changed`: it is never persisted and never replayed at boot.
1466
+ */
1467
+ const ProjectDeployChangedEvent = effect.Schema.Struct({
1468
+ type: effect.Schema.Literal("project.deploy_changed"),
1469
+ sequence: SequenceNumber,
1470
+ timestamp: effect.Schema.String,
1471
+ payload: effect.Schema.Struct({ deploys: effect.Schema.Record(effect.Schema.String, ProjectDeploySnapshot) })
1472
+ });
1314
1473
  /** Replaces socket.io `agents:changed` (event: 'started') */
1315
1474
  const AgentStartedEvent = effect.Schema.Struct({
1316
1475
  type: effect.Schema.Literal("agent.started"),
@@ -1400,6 +1559,9 @@ const AgentStatusChangedEvent = effect.Schema.Struct({
1400
1559
  workspaceId: effect.Schema.optional(effect.Schema.String),
1401
1560
  status: AgentStatus,
1402
1561
  previousStatus: effect.Schema.optional(AgentStatus),
1562
+ /** The agent has a live pane on its terminal backend (Herdr or tmux). */
1563
+ hasLivePane: effect.Schema.optional(effect.Schema.Boolean),
1564
+ /** @deprecated Alias of `hasLivePane`, kept for events written before it existed (#4105). */
1403
1565
  hasLiveTmuxSession: effect.Schema.optional(effect.Schema.Boolean),
1404
1566
  stoppedByUser: effect.Schema.optional(effect.Schema.Boolean),
1405
1567
  stoppedByPause: effect.Schema.optional(effect.Schema.Boolean),
@@ -2466,6 +2628,17 @@ const ConversationTitleChangedEvent = effect.Schema.Struct({
2466
2628
  titleSource: effect.Schema.String
2467
2629
  })
2468
2630
  });
2631
+ /** Emitted (in-memory only) when a conversation's pull-request links or their
2632
+ * snapshots change (PAN-3822), so the list and open panel refresh the badge. */
2633
+ const ConversationPullRequestsChangedEvent = effect.Schema.Struct({
2634
+ type: effect.Schema.Literal("conversation.pull_requests_changed"),
2635
+ sequence: SequenceNumber,
2636
+ timestamp: effect.Schema.String,
2637
+ payload: effect.Schema.Struct({
2638
+ conversationName: effect.Schema.String,
2639
+ effective: effect.Schema.NullOr(PullRequestLink)
2640
+ })
2641
+ });
2469
2642
  /** Emitted (in-memory only) when a PermissionRequest hook fires or resolves for a conversation. */
2470
2643
  const ConversationPermissionChangedEvent = effect.Schema.Struct({
2471
2644
  type: effect.Schema.Literal("conversation.permission_changed"),
@@ -2600,6 +2773,7 @@ const DomainEvent = effect.Schema.Union([
2600
2773
  ProjectCiSuiteObservedEvent,
2601
2774
  ProjectCiHeadObservedEvent,
2602
2775
  RestartGateChangedEvent,
2776
+ ProjectDeployChangedEvent,
2603
2777
  AgentCreatedEvent,
2604
2778
  AgentEnrichmentChangedEvent,
2605
2779
  AgentStartedEvent,
@@ -2690,6 +2864,7 @@ const DomainEvent = effect.Schema.Union([
2690
2864
  ConversationCreatedEvent,
2691
2865
  ConversationMovedEvent,
2692
2866
  ConversationTitleChangedEvent,
2867
+ ConversationPullRequestsChangedEvent,
2693
2868
  ConversationPermissionChangedEvent,
2694
2869
  ScanStartedEvent,
2695
2870
  ScanProgressEvent,
@@ -3503,6 +3678,7 @@ const INITIAL_READ_MODEL_STATE = {
3503
3678
  embedProgressBySessionId: {},
3504
3679
  ciByProjectKey: {},
3505
3680
  restartGate: null,
3681
+ deployByProjectKey: {},
3506
3682
  agentIdBySessionId: {},
3507
3683
  dashboardLifecycle: {
3508
3684
  active: false,
@@ -3633,14 +3809,29 @@ function syncSnapshot(state, snapshot) {
3633
3809
  embedProgressBySessionId: snapshot.embedProgressBySessionId ?? {},
3634
3810
  ciByProjectKey: snapshot.ciByProjectKey ?? state.ciByProjectKey,
3635
3811
  restartGate: snapshot.restartGate ?? state.restartGate,
3812
+ deployByProjectKey: snapshot.deployByProjectKey ?? state.deployByProjectKey,
3636
3813
  agentIdBySessionId
3637
3814
  };
3638
3815
  }
3816
+ /**
3817
+ * #4105 — `hasLivePane` and its deprecated alias `hasLiveTmuxSession` carry one
3818
+ * fact. An agent snapshot from a stored event may carry only the old name; fill
3819
+ * whichever one is missing so readers of either name agree.
3820
+ */
3821
+ function withPaneLivenessAlias(agent) {
3822
+ const pane = agent.hasLivePane ?? agent.hasLiveTmuxSession;
3823
+ if (pane === void 0 || agent.hasLivePane === pane && agent.hasLiveTmuxSession === pane) return agent;
3824
+ return {
3825
+ ...agent,
3826
+ hasLivePane: pane,
3827
+ hasLiveTmuxSession: pane
3828
+ };
3829
+ }
3639
3830
  function applyEvent(state, event) {
3640
3831
  switch (event.type) {
3641
3832
  case "agent.created": {
3642
3833
  const existing = state.agentsById[event.payload.agentId];
3643
- const agent = event.payload.agent;
3834
+ const agent = withPaneLivenessAlias(event.payload.agent);
3644
3835
  const nextAgentIdBySessionId = agent.sessionId ? {
3645
3836
  ...state.agentIdBySessionId,
3646
3837
  [agent.sessionId]: agent.id
@@ -3659,7 +3850,7 @@ function applyEvent(state, event) {
3659
3850
  };
3660
3851
  }
3661
3852
  case "agent.started": {
3662
- const agent = event.payload.agent;
3853
+ const agent = withPaneLivenessAlias(event.payload.agent);
3663
3854
  const nextAgentIdBySessionId = agent.sessionId ? {
3664
3855
  ...state.agentIdBySessionId,
3665
3856
  [agent.sessionId]: agent.id
@@ -3709,6 +3900,7 @@ function applyEvent(state, event) {
3709
3900
  [event.payload.agentId]: {
3710
3901
  ...stoppedAgent,
3711
3902
  status: "stopped",
3903
+ hasLivePane: false,
3712
3904
  hasLiveTmuxSession: false,
3713
3905
  lastActivity: event.timestamp
3714
3906
  }
@@ -3770,6 +3962,7 @@ function applyEvent(state, event) {
3770
3962
  status: event.payload.status
3771
3963
  };
3772
3964
  for (const field of [
3965
+ "hasLivePane",
3773
3966
  "hasLiveTmuxSession",
3774
3967
  "stoppedByUser",
3775
3968
  "stoppedByPause",
@@ -3814,7 +4007,15 @@ function applyEvent(state, event) {
3814
4007
  if (value === null || value === void 0) delete base[field];
3815
4008
  else base[field] = value;
3816
4009
  }
3817
- const sessionAlive = event.payload.hasLiveTmuxSession === true;
4010
+ const payloadPane = event.payload.hasLivePane ?? event.payload.hasLiveTmuxSession;
4011
+ if ("hasLivePane" in event.payload || "hasLiveTmuxSession" in event.payload) if (payloadPane === null || payloadPane === void 0) {
4012
+ delete base["hasLivePane"];
4013
+ delete base["hasLiveTmuxSession"];
4014
+ } else {
4015
+ base["hasLivePane"] = payloadPane;
4016
+ base["hasLiveTmuxSession"] = payloadPane;
4017
+ }
4018
+ const sessionAlive = payloadPane === true;
3818
4019
  if (event.payload.status !== "running" && event.payload.status !== "starting" && !sessionAlive) {
3819
4020
  delete base["hasPendingQuestion"];
3820
4021
  delete base["pendingQuestionCount"];
@@ -4023,6 +4224,11 @@ function applyEvent(state, event) {
4023
4224
  ...event.payload.lastOutcome === void 0 ? {} : { lastOutcome: event.payload.lastOutcome }
4024
4225
  }
4025
4226
  };
4227
+ case "project.deploy_changed": return {
4228
+ ...state,
4229
+ sequence: Math.max(state.sequence, event.sequence),
4230
+ deployByProjectKey: event.payload.deploys
4231
+ };
4026
4232
  case "resources.updated": return {
4027
4233
  ...state,
4028
4234
  sequence: Math.max(state.sequence, event.sequence),
@@ -4735,6 +4941,10 @@ function applyEvent(state, event) {
4735
4941
  ...state,
4736
4942
  conversationsListRevision: state.conversationsListRevision + 1
4737
4943
  };
4944
+ case "conversation.pull_requests_changed": return {
4945
+ ...state,
4946
+ conversationsListRevision: state.conversationsListRevision + 1
4947
+ };
4738
4948
  case "conversation.permission_changed": {
4739
4949
  const { conversationName, waiting } = event.payload;
4740
4950
  if (!waiting) {
@@ -5091,34 +5301,142 @@ const FlywheelStatsTrend = effect.Schema.Literals([
5091
5301
  "down",
5092
5302
  "flat"
5093
5303
  ]);
5094
- const FlywheelStatsCriterionValueObject = effect.Schema.Record(effect.Schema.String, effect.Schema.Json);
5095
- const FlywheelStatsCriterionValue = effect.Schema.Union([effect.Schema.Number, FlywheelStatsCriterionValueObject]);
5096
- const FlywheelStatsCriterion = effect.Schema.Struct({
5097
- label: effect.Schema.String,
5098
- value: FlywheelStatsCriterionValue,
5099
- target: FlywheelStatsCriterionValue,
5304
+ const FlywheelSubstrateSeverity = effect.Schema.Literals([
5305
+ "P0",
5306
+ "P1",
5307
+ "P2",
5308
+ "unknown"
5309
+ ]);
5310
+ const FlywheelStatsWindow = effect.Schema.Struct({
5311
+ days: effect.Schema.Number,
5312
+ since: effect.Schema.String,
5313
+ until: effect.Schema.String
5314
+ });
5315
+ /** c1: substrate bugs filed per merged PR in the window. */
5316
+ const FlywheelBugRateCriterion = effect.Schema.Struct({
5317
+ /** `null` when no PR merged in the window (the rate is undefined). */
5318
+ value: effect.Schema.NullOr(effect.Schema.Number),
5319
+ count: effect.Schema.Number,
5320
+ denominator: effect.Schema.Number,
5321
+ status: FlywheelStatsCriterionStatus,
5322
+ trend: FlywheelStatsTrend,
5323
+ dataSufficient: effect.Schema.Boolean
5324
+ });
5325
+ /** c2: P0 substrate bugs filed in the window. */
5326
+ const FlywheelP0Criterion = effect.Schema.Struct({
5327
+ value: effect.Schema.Number,
5100
5328
  status: FlywheelStatsCriterionStatus,
5101
- trend: effect.Schema.optional(FlywheelStatsTrend),
5102
- sampleSize: effect.Schema.Number,
5329
+ trend: FlywheelStatsTrend,
5103
5330
  dataSufficient: effect.Schema.Boolean
5104
5331
  });
5105
- const FlywheelStatsCriteria = effect.Schema.Struct({
5106
- c1_bugRate: FlywheelStatsCriterion,
5107
- c2_p0Bugs: FlywheelStatsCriterion,
5108
- c3_passRate: FlywheelStatsCriterion,
5109
- c4_mttr: FlywheelStatsCriterion,
5110
- c5_intervention: FlywheelStatsCriterion,
5111
- c6_timeConsistency: FlywheelStatsCriterion,
5112
- c7_flake: FlywheelStatsCriterion
5332
+ const FlywheelSubstrateBugRow = effect.Schema.Struct({
5333
+ number: effect.Schema.Number,
5334
+ title: effect.Schema.String,
5335
+ createdAt: effect.Schema.String,
5336
+ closedAt: effect.Schema.NullOr(effect.Schema.String),
5337
+ severity: FlywheelSubstrateSeverity
5113
5338
  });
5114
5339
  const FlywheelStats = effect.Schema.Struct({
5115
- window: effect.Schema.String,
5340
+ window: FlywheelStatsWindow,
5116
5341
  generatedAt: effect.Schema.String,
5117
- criteria: FlywheelStatsCriteria
5342
+ criteria: effect.Schema.Struct({
5343
+ c1_bugRate: FlywheelBugRateCriterion,
5344
+ c2_p0Bugs: FlywheelP0Criterion
5345
+ }),
5346
+ bugs: effect.Schema.Array(FlywheelSubstrateBugRow)
5118
5347
  });
5119
5348
  const decodeFlywheelStats = effect.Schema.decodeUnknownSync(FlywheelStats);
5120
5349
  const encodeFlywheelStats = effect.Schema.encodeSync(FlywheelStats);
5121
5350
  //#endregion
5351
+ //#region src/flywheel-derived.ts
5352
+ /** The loop's phases, as the skill reports them in its tick marker. */
5353
+ const TickMarkerPhase = effect.Schema.Literals([
5354
+ "orient",
5355
+ "pick",
5356
+ "launch",
5357
+ "watch",
5358
+ "park",
5359
+ "idle",
5360
+ "stopping"
5361
+ ]);
5362
+ /**
5363
+ * One parsed tick marker line:
5364
+ * `flywheel-tick: tick=<n> pick=<ID|none> phase=<phase> in-flight=<ID,…|none> needs-you=<text|none>`.
5365
+ */
5366
+ const TickMarker = effect.Schema.Struct({
5367
+ tick: effect.Schema.Number,
5368
+ pick: effect.Schema.NullOr(effect.Schema.String),
5369
+ phase: TickMarkerPhase,
5370
+ inFlight: effect.Schema.Array(effect.Schema.String),
5371
+ needsYou: effect.Schema.NullOr(effect.Schema.String)
5372
+ });
5373
+ /** `running` = row + live session; `paused` = row, no live session; `idle` = no row. */
5374
+ const FlywheelRunState = effect.Schema.Literals([
5375
+ "running",
5376
+ "paused",
5377
+ "idle"
5378
+ ]);
5379
+ /** Age of the last tick: ≤ 60 s live, ≤ 20 min breathing, older stalled. */
5380
+ const FlywheelFreshness = effect.Schema.Literals([
5381
+ "live",
5382
+ "breathing",
5383
+ "stalled"
5384
+ ]);
5385
+ const FlywheelConversationSummary = effect.Schema.Struct({
5386
+ name: effect.Schema.String,
5387
+ id: effect.Schema.Number,
5388
+ title: effect.Schema.NullOr(effect.Schema.String),
5389
+ model: effect.Schema.NullOr(effect.Schema.String),
5390
+ harness: effect.Schema.NullOr(effect.Schema.String),
5391
+ cwd: effect.Schema.String,
5392
+ sessionAlive: effect.Schema.Boolean
5393
+ });
5394
+ const FlywheelLastTick = effect.Schema.Struct({
5395
+ tick: effect.Schema.Number,
5396
+ pick: effect.Schema.NullOr(effect.Schema.String),
5397
+ phase: TickMarkerPhase,
5398
+ inFlight: effect.Schema.Array(effect.Schema.String),
5399
+ needsYou: effect.Schema.NullOr(effect.Schema.String),
5400
+ /** The assistant message's `createdAt`. */
5401
+ at: effect.Schema.String
5402
+ });
5403
+ const FlywheelPolicies = effect.Schema.Struct({
5404
+ auto_pickup_backlog: effect.Schema.Boolean,
5405
+ require_uat_before_merge: effect.Schema.Boolean,
5406
+ merge_train_enabled: effect.Schema.Boolean
5407
+ });
5408
+ const FlywheelJournalSummary = effect.Schema.Struct({
5409
+ at: effect.Schema.String,
5410
+ type: effect.Schema.String,
5411
+ source: effect.Schema.optional(effect.Schema.String)
5412
+ });
5413
+ const FlywheelInFlightRow = effect.Schema.Struct({
5414
+ issueId: effect.Schema.String,
5415
+ state: IssueState,
5416
+ attention: effect.Schema.optional(IssueAttention),
5417
+ pr: effect.Schema.optional(DerivedPrState),
5418
+ lastJournal: effect.Schema.NullOr(FlywheelJournalSummary)
5419
+ });
5420
+ const FlywheelOrderBookSummary = effect.Schema.Struct({
5421
+ id: effect.Schema.String,
5422
+ name: effect.Schema.String,
5423
+ status: effect.Schema.String,
5424
+ landed: effect.Schema.Number,
5425
+ total: effect.Schema.Number
5426
+ });
5427
+ const FlywheelDerivedStatus = effect.Schema.Struct({
5428
+ run: FlywheelRunState,
5429
+ conversation: effect.Schema.NullOr(FlywheelConversationSummary),
5430
+ lastTick: effect.Schema.NullOr(FlywheelLastTick),
5431
+ freshness: effect.Schema.NullOr(FlywheelFreshness),
5432
+ policies: FlywheelPolicies,
5433
+ inFlight: effect.Schema.Array(FlywheelInFlightRow),
5434
+ orderBook: effect.Schema.NullOr(FlywheelOrderBookSummary),
5435
+ projectRoot: effect.Schema.String,
5436
+ generatedAt: effect.Schema.String
5437
+ });
5438
+ const decodeFlywheelDerivedStatus = effect.Schema.decodeUnknownSync(FlywheelDerivedStatus);
5439
+ //#endregion
5122
5440
  //#region src/orders.ts
5123
5441
  const OrderBookLane = effect.Schema.Literals(["A", "B"]);
5124
5442
  const OrderBookStatus = effect.Schema.Literals([
@@ -6676,6 +6994,20 @@ const COMPOSER_COMMAND_MANIFEST = [
6676
6994
  "aliases": [],
6677
6995
  "category": "Lifecycle"
6678
6996
  },
6997
+ {
6998
+ "id": "pan-untroubled",
6999
+ "path": ["untroubled"],
7000
+ "display": "/pan untroubled",
7001
+ "description": "Clear an agent troubled gate without spawning it",
7002
+ "args": [{
7003
+ "name": "id",
7004
+ "required": true,
7005
+ "variadic": false
7006
+ }],
7007
+ "options": [],
7008
+ "aliases": [],
7009
+ "category": "Lifecycle"
7010
+ },
6679
7011
  {
6680
7012
  "id": "pan-fork",
6681
7013
  "path": ["fork"],
@@ -6756,10 +7088,16 @@ const COMPOSER_COMMAND_MANIFEST = [
6756
7088
  },
6757
7089
  {
6758
7090
  "flags": "--issue <id>",
6759
- "description": "Issue ID to associate with the new conversation",
7091
+ "description": "Issue ID to associate with the new conversation; without --cwd the new conversation starts in the issue workspace when it exists",
6760
7092
  "required": true,
6761
7093
  "valueHint": "id"
6762
7094
  },
7095
+ {
7096
+ "flags": "--role <role>",
7097
+ "description": "Pane role for the new conversation: conversation (default), work, review, test, plan. With --issue, review makes the handoff the issue's Review row",
7098
+ "required": true,
7099
+ "valueHint": "role"
7100
+ },
6763
7101
  {
6764
7102
  "flags": "--title <title>",
6765
7103
  "description": "Title for the new conversation; defaults to \"Handoff: <focus>\" (first ~70 chars) or \"Handoff: <source title>\" without focus",
@@ -7168,7 +7506,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7168
7506
  },
7169
7507
  {
7170
7508
  "flags": "--force",
7171
- "description": "Clear paused and pending-operator-decision gates and start anyway",
7509
+ "description": "Clear paused, troubled, and pending-operator-decision gates and start anyway",
7172
7510
  "required": false,
7173
7511
  "valueHint": null
7174
7512
  },
@@ -8123,7 +8461,7 @@ const COMPOSER_COMMAND_MANIFEST = [
8123
8461
  "id": "pan-workspace-reap",
8124
8462
  "path": ["workspace", "reap"],
8125
8463
  "display": "/pan workspace reap",
8126
- "description": "List or remove orphaned unhealthy workspace Docker stacks",
8464
+ "description": "List or remove orphaned unhealthy workspace Docker stacks and orphaned workspace networks",
8127
8465
  "args": [],
8128
8466
  "options": [
8129
8467
  {
@@ -8134,7 +8472,7 @@ const COMPOSER_COMMAND_MANIFEST = [
8134
8472
  },
8135
8473
  {
8136
8474
  "flags": "--apply",
8137
- "description": "Run docker compose down -v --remove-orphans for candidates",
8475
+ "description": "Run docker compose down -v --remove-orphans for stack candidates and remove orphaned workspace networks",
8138
8476
  "required": false,
8139
8477
  "valueHint": null
8140
8478
  },
@@ -9680,6 +10018,12 @@ const COMPOSER_COMMAND_MANIFEST = [
9680
10018
  "required": false,
9681
10019
  "valueHint": null
9682
10020
  },
10021
+ {
10022
+ "flags": "--repair-ignore",
10023
+ "description": "Only remove Overdeck's legacy .pan/ line from .gitignore and commit that file (no copy)",
10024
+ "required": false,
10025
+ "valueHint": null
10026
+ },
9683
10027
  {
9684
10028
  "flags": "--state-root <dir>",
9685
10029
  "description": "Override the state worktree root (tests / odd setups)",
@@ -9930,96 +10274,21 @@ const COMPOSER_COMMAND_MANIFEST = [
9930
10274
  "valueHint": "notes"
9931
10275
  },
9932
10276
  {
9933
- "flags": "--run-id <runId>",
9934
- "description": "Review cycle ID used to deduplicate review feedback",
10277
+ "flags": "--tested-sha <sha>",
10278
+ "description": "Test/UAT only: the commit the run exercised (git rev-parse HEAD before the gates)",
9935
10279
  "required": true,
9936
- "valueHint": "runId"
9937
- }
9938
- ],
9939
- "aliases": [],
9940
- "category": "Admin"
9941
- },
9942
- {
9943
- "id": "pan-admin-specialists-logs",
9944
- "path": [
9945
- "admin",
9946
- "specialists",
9947
- "logs"
9948
- ],
9949
- "display": "/pan admin specialists logs",
9950
- "description": "View specialist run logs",
9951
- "args": [
9952
- {
9953
- "name": "project",
9954
- "required": false,
9955
- "variadic": false
9956
- },
9957
- {
9958
- "name": "type",
9959
- "required": false,
9960
- "variadic": false
9961
- },
9962
- {
9963
- "name": "runId",
9964
- "required": false,
9965
- "variadic": false
9966
- }
9967
- ],
9968
- "options": [
9969
- {
9970
- "flags": "--json",
9971
- "description": "Output in JSON format",
9972
- "required": false,
9973
- "valueHint": null
10280
+ "valueHint": "sha"
9974
10281
  },
9975
10282
  {
9976
- "flags": "--limit <count>",
9977
- "description": "Number of runs to show (default: 10)",
10283
+ "flags": "--run-id <runId>",
10284
+ "description": "Review cycle ID used to deduplicate review feedback",
9978
10285
  "required": true,
9979
- "valueHint": "count"
9980
- },
9981
- {
9982
- "flags": "--tail",
9983
- "description": "Follow active run log in real-time",
9984
- "required": false,
9985
- "valueHint": null
10286
+ "valueHint": "runId"
9986
10287
  }
9987
10288
  ],
9988
10289
  "aliases": [],
9989
10290
  "category": "Admin"
9990
10291
  },
9991
- {
9992
- "id": "pan-admin-specialists-cleanup-logs",
9993
- "path": [
9994
- "admin",
9995
- "specialists",
9996
- "cleanup-logs"
9997
- ],
9998
- "display": "/pan admin specialists cleanup-logs",
9999
- "description": "Clean up old specialist logs",
10000
- "args": [{
10001
- "name": "project",
10002
- "required": false,
10003
- "variadic": false
10004
- }, {
10005
- "name": "type",
10006
- "required": false,
10007
- "variadic": false
10008
- }],
10009
- "options": [{
10010
- "flags": "--force",
10011
- "description": "Skip confirmation prompt",
10012
- "required": false,
10013
- "valueHint": null
10014
- }, {
10015
- "flags": "--all",
10016
- "description": "Clean up logs for all projects",
10017
- "required": false,
10018
- "valueHint": null
10019
- }],
10020
- "aliases": [],
10021
- "category": "Admin"
10022
- },
10023
10292
  {
10024
10293
  "id": "pan-admin-remote",
10025
10294
  "path": ["admin", "remote"],
@@ -10910,6 +11179,80 @@ const COMPOSER_COMMAND_MANIFEST = [
10910
11179
  "aliases": [],
10911
11180
  "category": "Conversation"
10912
11181
  },
11182
+ {
11183
+ "id": "pan-conversations-link-pr",
11184
+ "path": ["conversations", "link-pr"],
11185
+ "display": "/pan conversations link-pr",
11186
+ "description": "Link a pull request (URL, #42, or owner/repo#42) to a conversation",
11187
+ "args": [{
11188
+ "name": "query",
11189
+ "required": true,
11190
+ "variadic": false
11191
+ }, {
11192
+ "name": "ref",
11193
+ "required": true,
11194
+ "variadic": false
11195
+ }],
11196
+ "options": [{
11197
+ "flags": "--source <source>",
11198
+ "description": "agent or manual (default: agent inside an agent, else manual)",
11199
+ "required": true,
11200
+ "valueHint": "source"
11201
+ }],
11202
+ "aliases": [],
11203
+ "category": "Conversation"
11204
+ },
11205
+ {
11206
+ "id": "pan-conversations-unlink-pr",
11207
+ "path": ["conversations", "unlink-pr"],
11208
+ "display": "/pan conversations unlink-pr",
11209
+ "description": "Unlink a pull request from a conversation (the sweep will not re-add it)",
11210
+ "args": [{
11211
+ "name": "query",
11212
+ "required": true,
11213
+ "variadic": false
11214
+ }, {
11215
+ "name": "ref",
11216
+ "required": true,
11217
+ "variadic": false
11218
+ }],
11219
+ "options": [],
11220
+ "aliases": [],
11221
+ "category": "Conversation"
11222
+ },
11223
+ {
11224
+ "id": "pan-conversations-prs",
11225
+ "path": ["conversations", "prs"],
11226
+ "display": "/pan conversations prs",
11227
+ "description": "List the pull requests linked to a conversation (* = the one shown)",
11228
+ "args": [{
11229
+ "name": "query",
11230
+ "required": true,
11231
+ "variadic": false
11232
+ }],
11233
+ "options": [{
11234
+ "flags": "--json",
11235
+ "description": "Output { links, effective } as JSON",
11236
+ "required": false,
11237
+ "valueHint": null
11238
+ }],
11239
+ "aliases": [],
11240
+ "category": "Conversation"
11241
+ },
11242
+ {
11243
+ "id": "pan-conversations-auto-archive-on-merge",
11244
+ "path": ["conversations", "auto-archive-on-merge"],
11245
+ "display": "/pan conversations auto-archive-on-merge",
11246
+ "description": "Show or set (on|off) archiving operator conversations once all their linked PRs are merged or closed (default off)",
11247
+ "args": [{
11248
+ "name": "value",
11249
+ "required": false,
11250
+ "variadic": false
11251
+ }],
11252
+ "options": [],
11253
+ "aliases": [],
11254
+ "category": "Conversation"
11255
+ },
10913
11256
  {
10914
11257
  "id": "pan-conversations-heal",
10915
11258
  "path": ["conversations", "heal"],
@@ -11378,40 +11721,314 @@ const COMPOSER_COMMAND_MANIFEST = [
11378
11721
  "category": "CLI"
11379
11722
  },
11380
11723
  {
11381
- "id": "pan-flywheel",
11382
- "path": ["flywheel"],
11383
- "display": "/pan flywheel",
11384
- "description": "Start, stop, or check the flywheel conversation",
11724
+ "id": "pan-worker",
11725
+ "path": ["worker"],
11726
+ "display": "/pan worker",
11727
+ "description": "Registered workers: spawn an issue-linked agent and get its report back; register external agents",
11385
11728
  "args": [],
11386
11729
  "options": [],
11387
11730
  "aliases": [],
11388
- "category": "Flywheel"
11731
+ "category": "CLI"
11389
11732
  },
11390
11733
  {
11391
- "id": "pan-flywheel-start",
11392
- "path": ["flywheel", "start"],
11393
- "display": "/pan flywheel start",
11394
- "description": "Launch a conversation running /pan-flywheel",
11734
+ "id": "pan-worker-run",
11735
+ "path": ["worker", "run"],
11736
+ "display": "/pan worker run",
11737
+ "description": "Start a worker for an issue and wait for its report (exit 0 done, 4 blocked/failed, 2 no report, 3 timeout, 1 error)",
11395
11738
  "args": [],
11396
11739
  "options": [
11397
11740
  {
11398
- "flags": "--model <model>",
11399
- "description": "Model for the flywheel conversation",
11741
+ "flags": "--issue <id>",
11742
+ "description": "Issue the worker belongs to (required)",
11400
11743
  "required": true,
11401
- "valueHint": "model"
11744
+ "valueHint": "id"
11402
11745
  },
11403
11746
  {
11404
- "flags": "--harness <harness>",
11405
- "description": "Harness for the flywheel conversation",
11747
+ "flags": "--prompt <text>",
11748
+ "description": "The brief, inline",
11406
11749
  "required": true,
11407
- "valueHint": "harness"
11750
+ "valueHint": "text"
11408
11751
  },
11409
11752
  {
11410
- "flags": "--cwd <path>",
11411
- "description": "Working directory (default: cwd)",
11753
+ "flags": "--brief <file>",
11754
+ "description": "The brief, from a file",
11412
11755
  "required": true,
11413
- "valueHint": "path"
11414
- }
11756
+ "valueHint": "file"
11757
+ },
11758
+ {
11759
+ "flags": "--model <model>",
11760
+ "description": "Model override (default: roles.worker.model)",
11761
+ "required": true,
11762
+ "valueHint": "model"
11763
+ },
11764
+ {
11765
+ "flags": "--harness <harness>",
11766
+ "description": "Harness override (default: routed from the model)",
11767
+ "required": true,
11768
+ "valueHint": "harness"
11769
+ },
11770
+ {
11771
+ "flags": "--read-only",
11772
+ "description": "Run in the issue workspace with git writes blocked",
11773
+ "required": false,
11774
+ "valueHint": null
11775
+ },
11776
+ {
11777
+ "flags": "--cwd <path>",
11778
+ "description": "Working directory inside the issue workspace",
11779
+ "required": true,
11780
+ "valueHint": "path"
11781
+ },
11782
+ {
11783
+ "flags": "--parent <id>",
11784
+ "description": "Spawning agent or conversation (default: $OVERDECK_AGENT_ID, then $OVERDECK_CONVERSATION)",
11785
+ "required": true,
11786
+ "valueHint": "id"
11787
+ },
11788
+ {
11789
+ "flags": "--name <label>",
11790
+ "description": "Label shown in the Agents Directory",
11791
+ "required": true,
11792
+ "valueHint": "label"
11793
+ },
11794
+ {
11795
+ "flags": "--detach",
11796
+ "description": "Print the worker id and return without waiting",
11797
+ "required": false,
11798
+ "valueHint": null
11799
+ },
11800
+ {
11801
+ "flags": "--timeout <seconds>",
11802
+ "description": "Stop waiting after this many seconds (exit 3; the worker keeps running)",
11803
+ "required": true,
11804
+ "valueHint": "seconds"
11805
+ },
11806
+ {
11807
+ "flags": "--stop-after-report",
11808
+ "description": "Stop the worker after its first report",
11809
+ "required": false,
11810
+ "valueHint": null
11811
+ }
11812
+ ],
11813
+ "aliases": [],
11814
+ "category": "CLI"
11815
+ },
11816
+ {
11817
+ "id": "pan-worker-wait",
11818
+ "path": ["worker", "wait"],
11819
+ "display": "/pan worker wait",
11820
+ "description": "Wait for a worker's report (same exit codes as run); the status line names its seq",
11821
+ "args": [{
11822
+ "name": "worker-id",
11823
+ "required": true,
11824
+ "variadic": false
11825
+ }],
11826
+ "options": [{
11827
+ "flags": "--after <seq>",
11828
+ "description": "Return the next report after this seq (default: the newest report, whenever written)",
11829
+ "required": true,
11830
+ "valueHint": "seq"
11831
+ }, {
11832
+ "flags": "--timeout <seconds>",
11833
+ "description": "Stop waiting after this many seconds (exit 3)",
11834
+ "required": true,
11835
+ "valueHint": "seconds"
11836
+ }],
11837
+ "aliases": [],
11838
+ "category": "CLI"
11839
+ },
11840
+ {
11841
+ "id": "pan-worker-report",
11842
+ "path": ["worker", "report"],
11843
+ "display": "/pan worker report",
11844
+ "description": "Record a worker's report (run by the worker itself)",
11845
+ "args": [{
11846
+ "name": "worker-id",
11847
+ "required": true,
11848
+ "variadic": false
11849
+ }],
11850
+ "options": [
11851
+ {
11852
+ "flags": "--file <path>",
11853
+ "description": "Read the Markdown report from a file",
11854
+ "required": true,
11855
+ "valueHint": "path"
11856
+ },
11857
+ {
11858
+ "flags": "--stdin",
11859
+ "description": "Read the Markdown report from stdin",
11860
+ "required": false,
11861
+ "valueHint": null
11862
+ },
11863
+ {
11864
+ "flags": "--status <status>",
11865
+ "description": "done | blocked | failed (default: done)",
11866
+ "required": true,
11867
+ "valueHint": "status"
11868
+ }
11869
+ ],
11870
+ "aliases": [],
11871
+ "category": "CLI"
11872
+ },
11873
+ {
11874
+ "id": "pan-worker-list",
11875
+ "path": ["worker", "list"],
11876
+ "display": "/pan worker list",
11877
+ "description": "List workers with their parent, live state and newest report",
11878
+ "args": [],
11879
+ "options": [
11880
+ {
11881
+ "flags": "--issue <id>",
11882
+ "description": "Only this issue's workers",
11883
+ "required": true,
11884
+ "valueHint": "id"
11885
+ },
11886
+ {
11887
+ "flags": "--parent <id>",
11888
+ "description": "Only workers of this parent",
11889
+ "required": true,
11890
+ "valueHint": "id"
11891
+ },
11892
+ {
11893
+ "flags": "--json",
11894
+ "description": "Print JSON",
11895
+ "required": false,
11896
+ "valueHint": null
11897
+ }
11898
+ ],
11899
+ "aliases": [],
11900
+ "category": "CLI"
11901
+ },
11902
+ {
11903
+ "id": "pan-worker-register",
11904
+ "path": ["worker", "register"],
11905
+ "display": "/pan worker register",
11906
+ "description": "Record an agent another tool launched so the Agents Directory shows it (read-only; prints its id)",
11907
+ "args": [],
11908
+ "options": [
11909
+ {
11910
+ "flags": "--source <name>",
11911
+ "description": "Who launched it ([a-z0-9-], not codex-plugin) (required)",
11912
+ "required": true,
11913
+ "valueHint": "name"
11914
+ },
11915
+ {
11916
+ "flags": "--external-id <id>",
11917
+ "description": "The launcher's id for it (required)",
11918
+ "required": true,
11919
+ "valueHint": "id"
11920
+ },
11921
+ {
11922
+ "flags": "--harness <harness>",
11923
+ "description": "codex, claude-code, … (required)",
11924
+ "required": true,
11925
+ "valueHint": "harness"
11926
+ },
11927
+ {
11928
+ "flags": "--model <model>",
11929
+ "description": "Model it runs",
11930
+ "required": true,
11931
+ "valueHint": "model"
11932
+ },
11933
+ {
11934
+ "flags": "--cwd <path>",
11935
+ "description": "Its working directory",
11936
+ "required": true,
11937
+ "valueHint": "path"
11938
+ },
11939
+ {
11940
+ "flags": "--issue <id>",
11941
+ "description": "Issue it works on",
11942
+ "required": true,
11943
+ "valueHint": "id"
11944
+ },
11945
+ {
11946
+ "flags": "--parent <id>",
11947
+ "description": "Spawning agent id, conversation tmux session, or claude-session:<uuid>",
11948
+ "required": true,
11949
+ "valueHint": "id"
11950
+ },
11951
+ {
11952
+ "flags": "--label <text>",
11953
+ "description": "Label shown in the Agents Directory",
11954
+ "required": true,
11955
+ "valueHint": "text"
11956
+ },
11957
+ {
11958
+ "flags": "--pid <n>",
11959
+ "description": "Its process id (liveness is read from it)",
11960
+ "required": true,
11961
+ "valueHint": "n"
11962
+ },
11963
+ {
11964
+ "flags": "--transcript <path>",
11965
+ "description": "Its transcript file",
11966
+ "required": true,
11967
+ "valueHint": "path"
11968
+ },
11969
+ {
11970
+ "flags": "--session-id <id>",
11971
+ "description": "Its session or thread id",
11972
+ "required": true,
11973
+ "valueHint": "id"
11974
+ },
11975
+ {
11976
+ "flags": "--json",
11977
+ "description": "Print { id, created }",
11978
+ "required": false,
11979
+ "valueHint": null
11980
+ }
11981
+ ],
11982
+ "aliases": [],
11983
+ "category": "CLI"
11984
+ },
11985
+ {
11986
+ "id": "pan-flywheel",
11987
+ "path": ["flywheel"],
11988
+ "display": "/pan flywheel",
11989
+ "description": "Start, stop, pause, resume, or inspect the flywheel conversation",
11990
+ "args": [],
11991
+ "options": [],
11992
+ "aliases": [],
11993
+ "category": "Flywheel"
11994
+ },
11995
+ {
11996
+ "id": "pan-flywheel-start",
11997
+ "path": ["flywheel", "start"],
11998
+ "display": "/pan flywheel start",
11999
+ "description": "Launch a conversation running /pan-flywheel",
12000
+ "args": [],
12001
+ "options": [
12002
+ {
12003
+ "flags": "--model <model>",
12004
+ "description": "Model for the flywheel conversation",
12005
+ "required": true,
12006
+ "valueHint": "model"
12007
+ },
12008
+ {
12009
+ "flags": "--harness <harness>",
12010
+ "description": "Harness for the flywheel conversation",
12011
+ "required": true,
12012
+ "valueHint": "harness"
12013
+ },
12014
+ {
12015
+ "flags": "--cwd <path>",
12016
+ "description": "Working directory (default: cwd)",
12017
+ "required": true,
12018
+ "valueHint": "path"
12019
+ },
12020
+ {
12021
+ "flags": "--orders <book-id>",
12022
+ "description": "Order book the flywheel works from",
12023
+ "required": true,
12024
+ "valueHint": "book-id"
12025
+ },
12026
+ {
12027
+ "flags": "--fresh",
12028
+ "description": "Replace a paused flywheel conversation instead of refusing",
12029
+ "required": false,
12030
+ "valueHint": null
12031
+ }
11415
12032
  ],
11416
12033
  "aliases": [],
11417
12034
  "category": "Flywheel"
@@ -11420,7 +12037,52 @@ const COMPOSER_COMMAND_MANIFEST = [
11420
12037
  "id": "pan-flywheel-stop",
11421
12038
  "path": ["flywheel", "stop"],
11422
12039
  "display": "/pan flywheel stop",
11423
- "description": "Stop the flywheel conversation",
12040
+ "description": "Ask the loop to write its report, wait for it, then pause",
12041
+ "args": [],
12042
+ "options": [{
12043
+ "flags": "--timeout <ms>",
12044
+ "description": "How long to wait for the report (default 120000)",
12045
+ "required": true,
12046
+ "valueHint": "ms"
12047
+ }],
12048
+ "aliases": [],
12049
+ "category": "Flywheel"
12050
+ },
12051
+ {
12052
+ "id": "pan-flywheel-abort",
12053
+ "path": ["flywheel", "abort"],
12054
+ "display": "/pan flywheel abort",
12055
+ "description": "Stop the flywheel conversation without a report",
12056
+ "args": [],
12057
+ "options": [],
12058
+ "aliases": [],
12059
+ "category": "Flywheel"
12060
+ },
12061
+ {
12062
+ "id": "pan-flywheel-pause",
12063
+ "path": ["flywheel", "pause"],
12064
+ "display": "/pan flywheel pause",
12065
+ "description": "Stop the flywheel session, keeping its conversation and transcript",
12066
+ "args": [],
12067
+ "options": [],
12068
+ "aliases": [],
12069
+ "category": "Flywheel"
12070
+ },
12071
+ {
12072
+ "id": "pan-flywheel-resume",
12073
+ "path": ["flywheel", "resume"],
12074
+ "display": "/pan flywheel resume",
12075
+ "description": "Respawn a paused flywheel and re-send /pan-flywheel",
12076
+ "args": [],
12077
+ "options": [],
12078
+ "aliases": [],
12079
+ "category": "Flywheel"
12080
+ },
12081
+ {
12082
+ "id": "pan-flywheel-report",
12083
+ "path": ["flywheel", "report"],
12084
+ "display": "/pan flywheel report",
12085
+ "description": "Ask a running loop for its report, or print .pan/flywheel/report.md",
11424
12086
  "args": [],
11425
12087
  "options": [],
11426
12088
  "aliases": [],
@@ -11430,7 +12092,7 @@ const COMPOSER_COMMAND_MANIFEST = [
11430
12092
  "id": "pan-flywheel-status",
11431
12093
  "path": ["flywheel", "status"],
11432
12094
  "display": "/pan flywheel status",
11433
- "description": "Say whether the flywheel conversation is running",
12095
+ "description": "Show the derived flywheel status: run, last tick, policies, in-flight issues, order book",
11434
12096
  "args": [],
11435
12097
  "options": [{
11436
12098
  "flags": "--json",
@@ -11441,6 +12103,26 @@ const COMPOSER_COMMAND_MANIFEST = [
11441
12103
  "aliases": [],
11442
12104
  "category": "Flywheel"
11443
12105
  },
12106
+ {
12107
+ "id": "pan-flywheel-stats",
12108
+ "path": ["flywheel", "stats"],
12109
+ "display": "/pan flywheel stats",
12110
+ "description": "Substrate-bug discovery rate and P0 count, computed from the tracker and forge",
12111
+ "args": [],
12112
+ "options": [{
12113
+ "flags": "--json",
12114
+ "description": "Output as JSON",
12115
+ "required": false,
12116
+ "valueHint": null
12117
+ }, {
12118
+ "flags": "--window <days>",
12119
+ "description": "Window in days (default 30)",
12120
+ "required": true,
12121
+ "valueHint": "days"
12122
+ }],
12123
+ "aliases": [],
12124
+ "category": "Flywheel"
12125
+ },
11444
12126
  {
11445
12127
  "id": "pan-merge",
11446
12128
  "path": ["merge"],
@@ -11880,9 +12562,27 @@ const COMPOSER_COMMAND_MANIFEST = [
11880
12562
  "required": true,
11881
12563
  "valueHint": "duration"
11882
12564
  },
12565
+ {
12566
+ "flags": "--deacon",
12567
+ "description": "Start Cloister/Deacon on the reloaded dashboard (always on after a reload)",
12568
+ "required": false,
12569
+ "valueHint": null
12570
+ },
11883
12571
  {
11884
12572
  "flags": "--no-deacon",
11885
- "description": "Skip Cloister/Deacon auto-start after reload",
12573
+ "description": "Refused: a Deacon-off dashboard is a peer and cannot hold the host dashboard port",
12574
+ "required": false,
12575
+ "valueHint": null
12576
+ },
12577
+ {
12578
+ "flags": "--resume",
12579
+ "description": "Enable agent auto-resume on the reloaded dashboard (default: keep the running dashboard's resume gate)",
12580
+ "required": false,
12581
+ "valueHint": null
12582
+ },
12583
+ {
12584
+ "flags": "--no-resume",
12585
+ "description": "Disable agent auto-resume on the reloaded dashboard (default: keep the running dashboard's resume gate)",
11886
12586
  "required": false,
11887
12587
  "valueHint": null
11888
12588
  }
@@ -12724,9 +13424,7 @@ const COMPOSER_COMMAND_MANIFEST = [
12724
13424
  ];
12725
13425
  const COMPOSER_COMMAND_INSERT_OVERRIDES = {
12726
13426
  "plan finalize": "/pan plan finalize ",
12727
- "admin specialists done": "/pan admin specialists done",
12728
- "admin specialists logs": "/pan admin specialists logs",
12729
- "admin specialists cleanup-logs": "/pan admin specialists cleanup-logs"
13427
+ "admin specialists done": "/pan admin specialists done"
12730
13428
  };
12731
13429
  const COMPOSER_COMMAND_VARIANTS = [
12732
13430
  {
@@ -12904,7 +13602,8 @@ const AGENT_ROLES = [
12904
13602
  "test",
12905
13603
  "uat",
12906
13604
  "strike",
12907
- "plan"
13605
+ "plan",
13606
+ "conversation"
12908
13607
  ];
12909
13608
  function isTerminalBackendName(value) {
12910
13609
  return typeof value === "string" && TERMINAL_BACKEND_NAMES.includes(value);
@@ -12913,6 +13612,182 @@ function isAgentRole(value) {
12913
13612
  return typeof value === "string" && AGENT_ROLES.includes(value);
12914
13613
  }
12915
13614
  //#endregion
13615
+ //#region src/agent-directory.ts
13616
+ const DirectoryEntryKind = effect.Schema.Literals([
13617
+ "agent",
13618
+ "conversation",
13619
+ "subagent",
13620
+ "external"
13621
+ ]);
13622
+ const DirectoryEntryState = effect.Schema.Literals([
13623
+ "working",
13624
+ "idle",
13625
+ "blocked",
13626
+ "done",
13627
+ "stopped",
13628
+ "unknown"
13629
+ ]);
13630
+ const DirectoryEntrySource = effect.Schema.Literals([
13631
+ "overdeck",
13632
+ "pane",
13633
+ "conversation",
13634
+ "claude-subagent",
13635
+ "codex-subagent",
13636
+ "registered",
13637
+ "codex-plugin"
13638
+ ]);
13639
+ const DirectoryTranscriptRef = effect.Schema.Union([
13640
+ effect.Schema.Struct({
13641
+ route: effect.Schema.Literal("agent"),
13642
+ agentId: effect.Schema.String
13643
+ }),
13644
+ effect.Schema.Struct({
13645
+ route: effect.Schema.Literal("agent-subagent"),
13646
+ agentId: effect.Schema.String,
13647
+ subagentId: effect.Schema.String
13648
+ }),
13649
+ effect.Schema.Struct({
13650
+ route: effect.Schema.Literal("conversation"),
13651
+ conversationName: effect.Schema.String
13652
+ }),
13653
+ effect.Schema.Struct({
13654
+ route: effect.Schema.Literal("conversation-subagent"),
13655
+ conversationName: effect.Schema.String,
13656
+ subagentId: effect.Schema.String
13657
+ })
13658
+ ]);
13659
+ const DirectoryEntryLocation = effect.Schema.Literals(["local", "remote"]);
13660
+ const DirectoryPauseBy = effect.Schema.Literals([
13661
+ "operator",
13662
+ "scheduler",
13663
+ "machine"
13664
+ ]);
13665
+ const DirectoryPause = effect.Schema.Struct({
13666
+ by: DirectoryPauseBy,
13667
+ reason: effect.Schema.NullOr(effect.Schema.String),
13668
+ since: effect.Schema.NullOr(effect.Schema.String)
13669
+ });
13670
+ const DirectoryEntry = effect.Schema.Struct({
13671
+ id: effect.Schema.String,
13672
+ kind: DirectoryEntryKind,
13673
+ label: effect.Schema.String,
13674
+ location: DirectoryEntryLocation,
13675
+ /** projects.yaml key; `unassigned` when none (D5). */
13676
+ projectKey: effect.Schema.String,
13677
+ /** Uppercase issue id, e.g. `PAN-3920`. */
13678
+ issueId: effect.Schema.NullOr(effect.Schema.String),
13679
+ /** The issue's title from the dashboard's tracker cache; null when unknown. */
13680
+ issueTitle: effect.Schema.NullOr(effect.Schema.String),
13681
+ parentId: effect.Schema.NullOr(effect.Schema.String),
13682
+ role: effect.Schema.NullOr(effect.Schema.String),
13683
+ /** `unknown` when not known. */
13684
+ harness: effect.Schema.String,
13685
+ /** `unknown` when not known. */
13686
+ model: effect.Schema.String,
13687
+ state: DirectoryEntryState,
13688
+ startedAt: effect.Schema.NullOr(effect.Schema.String),
13689
+ lastActivityAt: effect.Schema.NullOr(effect.Schema.String),
13690
+ costUsd: effect.Schema.NullOr(effect.Schema.Number),
13691
+ source: DirectoryEntrySource,
13692
+ transcript: effect.Schema.NullOr(DirectoryTranscriptRef),
13693
+ /** The pause gate from state.json, native agents only (PAN-4197). */
13694
+ pause: effect.Schema.optional(DirectoryPause)
13695
+ });
13696
+ /**
13697
+ * `window`: live entries plus finished ones active inside `windowHours`.
13698
+ * `live` (PAN-4197): what is running or waiting now; `windowHours` is 0.
13699
+ */
13700
+ const DirectoryScope = effect.Schema.Literals(["window", "live"]);
13701
+ const AgentDirectoryResponse = effect.Schema.Struct({
13702
+ generatedAt: effect.Schema.String,
13703
+ windowHours: effect.Schema.Number,
13704
+ scope: effect.Schema.optional(DirectoryScope),
13705
+ entries: effect.Schema.Array(DirectoryEntry)
13706
+ });
13707
+ //#endregion
13708
+ //#region src/companion-terminal.ts
13709
+ /**
13710
+ * Which companion terminal a conversation gets, or `null` for "keep the
13711
+ * owner pane as TERMINAL". A Codex conversation still on the legacy
13712
+ * `codex.transport: tui` runs the native TUI in its owner pane; the server
13713
+ * adapter reports that as `unsupported` and points at the runtime pane.
13714
+ */
13715
+ function companionTerminalKindFor(conversation) {
13716
+ if (conversation.harness === "opencode") return "opencode-attach";
13717
+ if (conversation.harness === "codex") return "codex-resume-remote";
13718
+ return null;
13719
+ }
13720
+ /** Body keys each mutation accepts. Anything else is rejected as target injection. */
13721
+ const COMPANION_TERMINAL_OPEN_BODY_KEYS = [];
13722
+ const COMPANION_TERMINAL_CLOSE_BODY_KEYS = ["generation"];
13723
+ //#endregion
13724
+ //#region src/pull-request-ref.ts
13725
+ const SCHEME = String.raw`(?:https?:\/\/)?`;
13726
+ const HOST = String.raw`([a-z0-9.-]+(?::\d+)?)`;
13727
+ const TAIL = String.raw`(?:\/[^?#]*)?(?:[?#].*)?$`;
13728
+ const GITLAB_MR = new RegExp(String.raw`^${SCHEME}${HOST}\/((?:[\w.-]+\/)+[\w.-]+)\/-\/merge_requests\/(\d+)${TAIL}`, "i");
13729
+ const GITHUB_PR = new RegExp(String.raw`^${SCHEME}${HOST}\/([\w.-]+\/[\w.-]+)\/pull\/(\d+)${TAIL}`, "i");
13730
+ const GITLAB_MR_LEGACY = new RegExp(String.raw`^${SCHEME}${HOST}\/((?:[\w.-]+\/)+[\w.-]+)\/merge_requests\/(\d+)${TAIL}`, "i");
13731
+ const SHORT_REF = /^(?:((?:[\w.-]+\/)+[\w.-]+))?[#!](\d+)$/;
13732
+ function canonicalPullRequestUrl(key, forge) {
13733
+ return forge === "gitlab" ? `https://${key.host}/${key.repository}/-/merge_requests/${key.number}` : `https://${key.host}/${key.repository}/pull/${key.number}`;
13734
+ }
13735
+ function build(host, repository, number, forge) {
13736
+ if (!Number.isSafeInteger(number) || number <= 0) return null;
13737
+ const key = {
13738
+ host: host.toLowerCase(),
13739
+ repository: repository.toLowerCase().replace(/\.git$/, ""),
13740
+ number
13741
+ };
13742
+ return {
13743
+ ...key,
13744
+ forge,
13745
+ url: canonicalPullRequestUrl(key, forge)
13746
+ };
13747
+ }
13748
+ /**
13749
+ * Accepts a full PR/MR URL, `#42`, or `owner/repo#42` (`!42` for GitLab MRs).
13750
+ * The short forms need `defaultRepo` for host and forge (`#42` for the
13751
+ * repository too) and return null without it. Anything else returns null.
13752
+ */
13753
+ function parsePullRequestRef(input, defaultRepo) {
13754
+ const text = input.trim();
13755
+ if (!text) return null;
13756
+ for (const [pattern, forge] of [
13757
+ [GITLAB_MR, "gitlab"],
13758
+ [GITHUB_PR, "github"],
13759
+ [GITLAB_MR_LEGACY, "gitlab"]
13760
+ ]) {
13761
+ const match = pattern.exec(text);
13762
+ if (match) return build(match[1], match[2], Number(match[3]), forge);
13763
+ }
13764
+ const short = SHORT_REF.exec(text);
13765
+ if (!short || !defaultRepo) return null;
13766
+ return build(defaultRepo.host, short[1] ?? defaultRepo.repository, Number(short[2]), defaultRepo.forge);
13767
+ }
13768
+ /**
13769
+ * The repository behind a git remote URL (https, ssh://, or scp-style), or null
13770
+ * when the host names neither GitHub nor GitLab.
13771
+ */
13772
+ function repoFromRemoteUrl(remote) {
13773
+ if (!remote) return null;
13774
+ const text = remote.trim();
13775
+ const match = /^[a-z][a-z0-9+.-]*:\/\/(?:[^@/]*@)?([^/:]+)(?::\d+)?\/(.+?)(?:\.git)?\/?$/i.exec(text) ?? /^(?:[^@/]+@)?([^/:]+):(.+?)(?:\.git)?\/?$/i.exec(text);
13776
+ if (!match) return null;
13777
+ const host = match[1].toLowerCase();
13778
+ const forge = host.includes("gitlab") ? "gitlab" : host.includes("github") ? "github" : null;
13779
+ if (!forge) return null;
13780
+ return {
13781
+ host,
13782
+ repository: match[2].toLowerCase(),
13783
+ forge
13784
+ };
13785
+ }
13786
+ /** True when the ref's host and repository match one of the configured repos. */
13787
+ function isConfiguredPullRequestRepo(ref, repos) {
13788
+ return repos.some((repo) => repo.host === ref.host && repo.repository === ref.repository);
13789
+ }
13790
+ //#endregion
12916
13791
  exports.ACP_BEHAVIOR = ACP_BEHAVIOR;
12917
13792
  exports.AGENT_ROLES = AGENT_ROLES;
12918
13793
  exports.Activity = Activity;
@@ -12928,6 +13803,7 @@ exports.AgentCompletedEvent = AgentCompletedEvent;
12928
13803
  exports.AgentContextSaturationChangedEvent = AgentContextSaturationChangedEvent;
12929
13804
  exports.AgentCreatedEvent = AgentCreatedEvent;
12930
13805
  exports.AgentCurrentIssueSetEvent = AgentCurrentIssueSetEvent;
13806
+ exports.AgentDirectoryResponse = AgentDirectoryResponse;
12931
13807
  exports.AgentEnrichmentChangedEvent = AgentEnrichmentChangedEvent;
12932
13808
  exports.AgentHealthKind = AgentHealthKind;
12933
13809
  exports.AgentHealthSnapshot = AgentHealthSnapshot;
@@ -12980,6 +13856,8 @@ exports.BeadsFreshnessChangedEvent = BeadsFreshnessChangedEvent;
12980
13856
  exports.CHANNEL_REPLY_KIND_VALUES = CHANNEL_REPLY_KIND_VALUES;
12981
13857
  exports.CLAUDE_CODE_BEHAVIOR = CLAUDE_CODE_BEHAVIOR;
12982
13858
  exports.CODEX_BEHAVIOR = CODEX_BEHAVIOR;
13859
+ exports.COMPANION_TERMINAL_CLOSE_BODY_KEYS = COMPANION_TERMINAL_CLOSE_BODY_KEYS;
13860
+ exports.COMPANION_TERMINAL_OPEN_BODY_KEYS = COMPANION_TERMINAL_OPEN_BODY_KEYS;
12983
13861
  exports.COMPOSER_COMMAND_INSERT_OVERRIDES = COMPOSER_COMMAND_INSERT_OVERRIDES;
12984
13862
  exports.COMPOSER_COMMAND_MANIFEST = COMPOSER_COMMAND_MANIFEST;
12985
13863
  exports.COMPOSER_COMMAND_VARIANTS = COMPOSER_COMMAND_VARIANTS;
@@ -13016,6 +13894,8 @@ exports.ConversationEvent = ConversationEvent;
13016
13894
  exports.ConversationFilter = ConversationFilter;
13017
13895
  exports.ConversationMovedEvent = ConversationMovedEvent;
13018
13896
  exports.ConversationPermissionChangedEvent = ConversationPermissionChangedEvent;
13897
+ exports.ConversationPullRequests = ConversationPullRequests;
13898
+ exports.ConversationPullRequestsChangedEvent = ConversationPullRequestsChangedEvent;
13019
13899
  exports.ConversationResponse = ConversationResponse;
13020
13900
  exports.ConversationTitleChangedEvent = ConversationTitleChangedEvent;
13021
13901
  exports.CostEventRecordedEvent = CostEventRecordedEvent;
@@ -13030,6 +13910,15 @@ exports.DeployStalenessSnapshot = DeployStalenessSnapshot;
13030
13910
  exports.DerivedBranchState = DerivedBranchState;
13031
13911
  exports.DerivedIssueState = DerivedIssueState;
13032
13912
  exports.DerivedPrState = DerivedPrState;
13913
+ exports.DirectoryEntry = DirectoryEntry;
13914
+ exports.DirectoryEntryKind = DirectoryEntryKind;
13915
+ exports.DirectoryEntryLocation = DirectoryEntryLocation;
13916
+ exports.DirectoryEntrySource = DirectoryEntrySource;
13917
+ exports.DirectoryEntryState = DirectoryEntryState;
13918
+ exports.DirectoryPause = DirectoryPause;
13919
+ exports.DirectoryPauseBy = DirectoryPauseBy;
13920
+ exports.DirectoryScope = DirectoryScope;
13921
+ exports.DirectoryTranscriptRef = DirectoryTranscriptRef;
13033
13922
  exports.DiscoveredSessionSnapshot = DiscoveredSessionSnapshot;
13034
13923
  exports.DomainEvent = DomainEvent;
13035
13924
  exports.EDITORS = EDITORS;
@@ -13049,28 +13938,38 @@ exports.FeatureRegistryEntry = FeatureRegistryEntry;
13049
13938
  exports.FeatureRegistryStatus = FeatureRegistryStatus;
13050
13939
  exports.FlywheelAgent = FlywheelAgent;
13051
13940
  exports.FlywheelAgentStatus = FlywheelAgentStatus;
13941
+ exports.FlywheelBugRateCriterion = FlywheelBugRateCriterion;
13942
+ exports.FlywheelConversationSummary = FlywheelConversationSummary;
13943
+ exports.FlywheelDerivedStatus = FlywheelDerivedStatus;
13052
13944
  exports.FlywheelEffort = FlywheelEffort;
13945
+ exports.FlywheelFreshness = FlywheelFreshness;
13053
13946
  exports.FlywheelHarness = FlywheelHarness;
13054
13947
  exports.FlywheelHeadline = FlywheelHeadline;
13055
13948
  exports.FlywheelHttpUrl = FlywheelHttpUrl;
13949
+ exports.FlywheelInFlightRow = FlywheelInFlightRow;
13950
+ exports.FlywheelJournalSummary = FlywheelJournalSummary;
13951
+ exports.FlywheelLastTick = FlywheelLastTick;
13056
13952
  exports.FlywheelOrchestrator = FlywheelOrchestrator;
13953
+ exports.FlywheelOrderBookSummary = FlywheelOrderBookSummary;
13057
13954
  exports.FlywheelOrders = FlywheelOrders;
13955
+ exports.FlywheelP0Criterion = FlywheelP0Criterion;
13058
13956
  exports.FlywheelParkedItem = FlywheelParkedItem;
13059
13957
  exports.FlywheelPipelineItem = FlywheelPipelineItem;
13060
13958
  exports.FlywheelPipelineStatus = FlywheelPipelineStatus;
13061
13959
  exports.FlywheelPipelineVerb = FlywheelPipelineVerb;
13960
+ exports.FlywheelPolicies = FlywheelPolicies;
13062
13961
  exports.FlywheelRunId = FlywheelRunId;
13962
+ exports.FlywheelRunState = FlywheelRunState;
13063
13963
  exports.FlywheelScope = FlywheelScope;
13064
13964
  exports.FlywheelStats = FlywheelStats;
13065
- exports.FlywheelStatsCriteria = FlywheelStatsCriteria;
13066
- exports.FlywheelStatsCriterion = FlywheelStatsCriterion;
13067
13965
  exports.FlywheelStatsCriterionStatus = FlywheelStatsCriterionStatus;
13068
- exports.FlywheelStatsCriterionValue = FlywheelStatsCriterionValue;
13069
- exports.FlywheelStatsCriterionValueObject = FlywheelStatsCriterionValueObject;
13070
13966
  exports.FlywheelStatsTrend = FlywheelStatsTrend;
13967
+ exports.FlywheelStatsWindow = FlywheelStatsWindow;
13071
13968
  exports.FlywheelStatus = FlywheelStatus;
13072
13969
  exports.FlywheelSubstrateBug = FlywheelSubstrateBug;
13970
+ exports.FlywheelSubstrateBugRow = FlywheelSubstrateBugRow;
13073
13971
  exports.FlywheelSubstrateBugStatus = FlywheelSubstrateBugStatus;
13972
+ exports.FlywheelSubstrateSeverity = FlywheelSubstrateSeverity;
13074
13973
  exports.FlywheelSuggestion = FlywheelSuggestion;
13075
13974
  exports.FlywheelSuggestionAction = FlywheelSuggestionAction;
13076
13975
  exports.FlywheelSuggestionPriority = FlywheelSuggestionPriority;
@@ -13148,6 +14047,7 @@ exports.OrderBookLane = OrderBookLane;
13148
14047
  exports.OrderBookPosture = OrderBookPosture;
13149
14048
  exports.OrderBookSettings = OrderBookSettings;
13150
14049
  exports.OrderBookStatus = OrderBookStatus;
14050
+ exports.PIPELINE_MEMBERSHIP_LOADING_CODE = PIPELINE_MEMBERSHIP_LOADING_CODE;
13151
14051
  exports.PanRpcError = PanRpcError;
13152
14052
  exports.PanRpcGroup = PanRpcGroup;
13153
14053
  exports.PendingTurn = PendingTurn;
@@ -13171,8 +14071,18 @@ exports.ProjectCiSuite = ProjectCiSuite;
13171
14071
  exports.ProjectCiSuiteObservedEvent = ProjectCiSuiteObservedEvent;
13172
14072
  exports.ProjectContextLayerRecord = ProjectContextLayerRecord;
13173
14073
  exports.ProjectContextLayerTarget = ProjectContextLayerTarget;
14074
+ exports.ProjectDeployChangedEvent = ProjectDeployChangedEvent;
14075
+ exports.ProjectDeployPhase = ProjectDeployPhase;
14076
+ exports.ProjectDeploySnapshot = ProjectDeploySnapshot;
13174
14077
  exports.ProjectSessionTree = ProjectSessionTree;
13175
14078
  exports.ProposedPlan = ProposedPlan;
14079
+ exports.PullRequestKey = PullRequestKey;
14080
+ exports.PullRequestLink = PullRequestLink;
14081
+ exports.PullRequestLinkListing = PullRequestLinkListing;
14082
+ exports.PullRequestLinkSource = PullRequestLinkSource;
14083
+ exports.PullRequestLinkedConversation = PullRequestLinkedConversation;
14084
+ exports.PullRequestSnapshot = PullRequestSnapshot;
14085
+ exports.PullRequestState = PullRequestState;
13176
14086
  exports.RagDecision = RagDecision;
13177
14087
  exports.RagDecisionSource = RagDecisionSource;
13178
14088
  exports.ReadFileAtPathInput = ReadFileAtPathInput;
@@ -13260,6 +14170,8 @@ exports.TerminalResizeRpc = TerminalResizeRpc;
13260
14170
  exports.TerminalWriteRpc = TerminalWriteRpc;
13261
14171
  exports.TestPassedEvent = TestPassedEvent;
13262
14172
  exports.ThinkingState = ThinkingState;
14173
+ exports.TickMarker = TickMarker;
14174
+ exports.TickMarkerPhase = TickMarkerPhase;
13263
14175
  exports.TurnDiffFileChange = TurnDiffFileChange;
13264
14176
  exports.TurnDiffSummary = TurnDiffSummary;
13265
14177
  exports.WIRED_HOOK_INVENTORY = WIRED_HOOK_INVENTORY;
@@ -13283,8 +14195,11 @@ exports.WriteFileAtPathRpc = WriteFileAtPathRpc;
13283
14195
  exports.applyEvent = applyEvent;
13284
14196
  exports.applyEvents = applyEvents;
13285
14197
  exports.applyIssueDelta = applyIssueDelta;
14198
+ exports.canonicalPullRequestUrl = canonicalPullRequestUrl;
14199
+ exports.companionTerminalKindFor = companionTerminalKindFor;
13286
14200
  exports.compareIssueIds = compareIssueIds;
13287
14201
  exports.createIssueDelta = createIssueDelta;
14202
+ exports.decodeFlywheelDerivedStatus = decodeFlywheelDerivedStatus;
13288
14203
  exports.decodeFlywheelStats = decodeFlywheelStats;
13289
14204
  exports.deriveProjectCi = deriveProjectCi;
13290
14205
  exports.encodeFlywheelStats = encodeFlywheelStats;
@@ -13296,13 +14211,18 @@ exports.getRuntimeBehavior = getRuntimeBehavior;
13296
14211
  exports.isAgentRole = isAgentRole;
13297
14212
  exports.isAgentSessionName = isAgentSessionName;
13298
14213
  exports.isChannelReplyKind = isChannelReplyKind;
14214
+ exports.isConfiguredPullRequestRepo = isConfiguredPullRequestRepo;
13299
14215
  exports.isIssueAttention = isIssueAttention;
13300
14216
  exports.isIssueState = isIssueState;
13301
14217
  exports.isTerminalBackendName = isTerminalBackendName;
13302
14218
  exports.isTerminalTurnDiffSummaryStatus = isTerminalTurnDiffSummaryStatus;
13303
14219
  exports.normalizeChannelReplyPayload = normalizeChannelReplyPayload;
13304
14220
  exports.omitTurnDiffSummariesForAgent = omitTurnDiffSummariesForAgent;
14221
+ exports.parsePullRequestRef = parsePullRequestRef;
13305
14222
  exports.projectLegacySystemHealthSummary = projectLegacySystemHealthSummary;
14223
+ exports.repoFromRemoteUrl = repoFromRemoteUrl;
14224
+ exports.resolveEffectivePullRequest = resolveEffectivePullRequest;
13306
14225
  exports.syncSnapshot = syncSnapshot;
13307
14226
  exports.trimMemoryObservations = trimMemoryObservations;
13308
14227
  exports.trimTurnDiffSummaries = trimTurnDiffSummaries;
14228
+ exports.withPaneLivenessAlias = withPaneLivenessAlias;