@overdeck/contracts 0.62.0 → 0.63.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
@@ -61,6 +61,27 @@ const BackendPane = effect.Schema.Struct({
61
61
  /** Working directory of the pane (the issue workspace path). */
62
62
  workspace: effect.Schema.optional(effect.Schema.String)
63
63
  });
64
+ /**
65
+ * The agent id a pane answers for (PAN-4320). On Herdr `id` (`w1:p1`) and
66
+ * `terminalId` (`term_…`) are backend handles, never agent ids, so the
67
+ * `agentId` token decides; tmux panes carry `agentId` = session name.
68
+ */
69
+ function paneAgentKey(pane) {
70
+ return pane.agentId ?? pane.terminalId ?? pane.id;
71
+ }
72
+ /**
73
+ * Panes by agent key. When two panes answer for one agent (a restarted Herdr
74
+ * agent beside its exited pane), a non-exited pane wins, never the reverse.
75
+ */
76
+ function indexPanesByAgentKey(panes) {
77
+ const byKey = /* @__PURE__ */ new Map();
78
+ for (const pane of panes) {
79
+ const key = paneAgentKey(pane);
80
+ const prior = byKey.get(key);
81
+ if (!prior || prior.state === "exited" && pane.state !== "exited") byKey.set(key, pane);
82
+ }
83
+ return byKey;
84
+ }
64
85
  //#endregion
65
86
  //#region src/derived-issue-state.ts
66
87
  /**
@@ -109,7 +130,9 @@ const DerivedPrState = effect.Schema.Struct({
109
130
  reviewState: PrReviewState,
110
131
  checks: PrChecksState,
111
132
  /** Forge mergeability. `null` when the forge has not computed it yet. */
112
- mergeable: effect.Schema.NullOr(effect.Schema.Boolean)
133
+ mergeable: effect.Schema.NullOr(effect.Schema.Boolean),
134
+ /** Present only when true; survives state: closed (PAN-4290). */
135
+ merged: effect.Schema.optional(effect.Schema.Boolean)
113
136
  });
114
137
  /** The issue's feature branch as git reports it. */
115
138
  const DerivedBranchState = effect.Schema.Struct({
@@ -166,6 +189,119 @@ function isIssueAttention(value) {
166
189
  return typeof value === "string" && ISSUE_ATTENTIONS.includes(value);
167
190
  }
168
191
  //#endregion
192
+ //#region src/github-quota.ts
193
+ /**
194
+ * The closed list of logical GitHub callers. A call made outside any
195
+ * `withGitHubCaller` context is recorded as `other` (or `app-rest` when it
196
+ * goes through the GitHub App REST door).
197
+ */
198
+ const GITHUB_QUOTA_CALLERS = [
199
+ "pipeline-membership",
200
+ "pr-cache",
201
+ "pr-sync",
202
+ "ci-repair",
203
+ "issue-poller",
204
+ "close-out",
205
+ "tracker-client",
206
+ "app-rest",
207
+ "quota-sampler",
208
+ "agent",
209
+ "other"
210
+ ];
211
+ const GitHubQuotaCaller = effect.Schema.Literals(GITHUB_QUOTA_CALLERS);
212
+ /**
213
+ * Read-model pollers whose data can be stale for minutes without harm. Only
214
+ * these callers are skipped while a pause is active; every other caller
215
+ * (merge, verdict recording, tracker writes, agents) is essential and never
216
+ * paused.
217
+ */
218
+ const NON_ESSENTIAL_GITHUB_CALLERS = new Set([
219
+ "pipeline-membership",
220
+ "pr-cache",
221
+ "pr-sync",
222
+ "ci-repair",
223
+ "issue-poller",
224
+ "close-out"
225
+ ]);
226
+ /**
227
+ * The GitHub identity whose limit a call spends: `user` is the `gh` CLI token,
228
+ * `pat` is the `GITHUB_TOKEN` personal access token, `app` is a GitHub App
229
+ * installation token.
230
+ */
231
+ const GITHUB_QUOTA_POOLS = [
232
+ "user",
233
+ "pat",
234
+ "app"
235
+ ];
236
+ const GitHubQuotaPool = effect.Schema.Literals(GITHUB_QUOTA_POOLS);
237
+ /** The limit counter inside a pool. `rest` is what GitHub calls `core`. */
238
+ const GITHUB_QUOTA_BUCKETS = ["graphql", "rest"];
239
+ const GitHubQuotaBucket = effect.Schema.Literals(GITHUB_QUOTA_BUCKETS);
240
+ /** Primary = the hourly budget; secondary = GitHub's burst/abuse limit. */
241
+ const GitHubRateLimitKind = effect.Schema.Literals(["primary", "secondary"]);
242
+ /** Points spent and calls made in one bucket. */
243
+ const GitHubQuotaUsage = effect.Schema.Struct({
244
+ points: effect.Schema.Number,
245
+ calls: effect.Schema.Number
246
+ });
247
+ /** One caller's metered usage over the last hour. */
248
+ const GitHubQuotaCallerUsage = effect.Schema.Struct({
249
+ caller: GitHubQuotaCaller,
250
+ graphql: GitHubQuotaUsage,
251
+ rest: GitHubQuotaUsage,
252
+ /** True when any counted call had an estimated (not GitHub-reported) cost. */
253
+ estimated: effect.Schema.Boolean
254
+ });
255
+ /** The latest `/rate_limit` (or header) reading for one pool and bucket. */
256
+ const GitHubQuotaSample = effect.Schema.Struct({
257
+ pool: GitHubQuotaPool,
258
+ bucket: GitHubQuotaBucket,
259
+ /** ISO time the sample was taken. */
260
+ ts: effect.Schema.String,
261
+ remaining: effect.Schema.Number,
262
+ limit: effect.Schema.Number,
263
+ /** ISO time the bucket's hourly window resets. */
264
+ resetAt: effect.Schema.optional(effect.Schema.String)
265
+ });
266
+ /** An active pause on one pool and bucket (`~/.overdeck/github-quota/pause.json`). */
267
+ const GitHubQuotaPause = effect.Schema.Struct({
268
+ pool: GitHubQuotaPool,
269
+ bucket: GitHubQuotaBucket,
270
+ kind: GitHubRateLimitKind,
271
+ /** The caller whose refused call started the pause. */
272
+ caller: GitHubQuotaCaller,
273
+ /** ISO time the pause started. */
274
+ since: effect.Schema.String,
275
+ /** ISO time the pause ends. */
276
+ until: effect.Schema.String
277
+ });
278
+ /**
279
+ * The operator-facing quota view — identical to the body of
280
+ * `GET /api/github-quota`, so the pill, the banner and the CLI read one shape.
281
+ * Derived runtime state: published with `emitOnly`, never persisted.
282
+ */
283
+ const GitHubQuotaSnapshot = effect.Schema.Struct({
284
+ /** ISO time the snapshot was built. */
285
+ generatedAt: effect.Schema.String,
286
+ /** The `gh` account login. Local display only; never sent to telemetry. */
287
+ login: effect.Schema.NullOr(effect.Schema.String),
288
+ /** Per-caller usage in the last hour, highest total points first. */
289
+ callers: effect.Schema.Array(GitHubQuotaCallerUsage),
290
+ /** The latest sample per pool and bucket. */
291
+ samples: effect.Schema.Array(GitHubQuotaSample),
292
+ /** Active pauses; empty when GitHub calls are not paused. */
293
+ pauses: effect.Schema.Array(GitHubQuotaPause),
294
+ /** True when this machine's own metered usage cannot explain a primary limit. */
295
+ ownUsageLow: effect.Schema.Boolean,
296
+ /** User-pool GraphQL points the latest sample shows spent but no metered caller claims. */
297
+ unattributed: effect.Schema.Number,
298
+ /** Refusals observed in the last hour. */
299
+ refusals: effect.Schema.Struct({
300
+ primary: effect.Schema.Number,
301
+ secondary: effect.Schema.Number
302
+ })
303
+ });
304
+ //#endregion
169
305
  //#region src/types.ts
170
306
  const IssueId = effect.Schema.String;
171
307
  const MEMBERSHIP_UNAVAILABLE_REASONS = [
@@ -222,7 +358,8 @@ const KNOWN_HARNESSES = new Set([
222
358
  "acp",
223
359
  "kimi-code",
224
360
  "opencode",
225
- "muse"
361
+ "muse",
362
+ "prime-agent"
226
363
  ]);
227
364
  /**
228
365
  * Normalize a snapshot's runtime field to a known Harness value.
@@ -321,6 +458,7 @@ const AgentRuntimeSnapshot = effect.Schema.Struct({
321
458
  activity: Activity,
322
459
  lastActivity: effect.Schema.String,
323
460
  currentTool: effect.Schema.optional(effect.Schema.String),
461
+ currentToolDescription: effect.Schema.optional(effect.Schema.String),
324
462
  thinking: effect.Schema.optional(ThinkingState),
325
463
  waiting: effect.Schema.optional(WaitingState),
326
464
  claudeSessionId: effect.Schema.optional(effect.Schema.String),
@@ -584,6 +722,8 @@ const DashboardSnapshot = effect.Schema.Struct({
584
722
  embedProgressBySessionId: effect.Schema.optional(effect.Schema.Record(effect.Schema.String, EmbedProgressSnapshot)),
585
723
  ciByProjectKey: effect.Schema.optional(effect.Schema.Record(effect.Schema.String, ProjectCiSnapshot)),
586
724
  restartGate: effect.Schema.optional(RestartGateSnapshot),
725
+ /** PAN-4264 — GitHub API quota use, samples and pauses; derived, never stored. */
726
+ githubQuota: effect.Schema.optional(GitHubQuotaSnapshot),
587
727
  /** PAN-3751 — in-flight deploys keyed by project key. */
588
728
  deployByProjectKey: effect.Schema.optional(effect.Schema.Record(effect.Schema.String, ProjectDeploySnapshot)),
589
729
  timestamp: effect.Schema.String
@@ -1457,6 +1597,20 @@ const RestartGateChangedEvent = effect.Schema.Struct({
1457
1597
  payload: RestartGateSnapshot
1458
1598
  });
1459
1599
  /**
1600
+ * The GitHub API quota view changed (PAN-4264).
1601
+ *
1602
+ * The payload is the complete snapshot, so the reducer is a plain replace.
1603
+ * The server derives it from the quota ledger and pause file under
1604
+ * `~/.overdeck/github-quota/` and emits it in-memory only, like
1605
+ * `restart_gate.changed`: it is never persisted and never replayed at boot.
1606
+ */
1607
+ const GitHubQuotaChangedEvent = effect.Schema.Struct({
1608
+ type: effect.Schema.Literal("github_quota.changed"),
1609
+ sequence: SequenceNumber,
1610
+ timestamp: effect.Schema.String,
1611
+ payload: GitHubQuotaSnapshot
1612
+ });
1613
+ /**
1460
1614
  * The set of in-flight project deploys changed (PAN-3751).
1461
1615
  *
1462
1616
  * The payload is the COMPLETE projection keyed by project key, so the reducer
@@ -1671,6 +1825,7 @@ const AgentActivityChangedEvent = effect.Schema.Struct({
1671
1825
  agentId: AgentId,
1672
1826
  activity: Activity,
1673
1827
  currentTool: effect.Schema.optional(effect.Schema.String),
1828
+ toolDescription: effect.Schema.optional(effect.Schema.String),
1674
1829
  hookName: effect.Schema.optional(effect.Schema.String)
1675
1830
  })
1676
1831
  });
@@ -2773,6 +2928,7 @@ const DomainEvent = effect.Schema.Union([
2773
2928
  ProjectCiSuiteObservedEvent,
2774
2929
  ProjectCiHeadObservedEvent,
2775
2930
  RestartGateChangedEvent,
2931
+ GitHubQuotaChangedEvent,
2776
2932
  ProjectDeployChangedEvent,
2777
2933
  AgentCreatedEvent,
2778
2934
  AgentEnrichmentChangedEvent,
@@ -3163,13 +3319,23 @@ const WorkLogEntry = effect.Schema.Struct({
3163
3319
  toolInput: effect.Schema.optional(effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown)),
3164
3320
  sequence: effect.Schema.optional(effect.Schema.Number)
3165
3321
  });
3322
+ /** A human-origin message read from a subagent's own sidechain transcript (PAN-4247). */
3323
+ const SubagentHumanInput = effect.Schema.Struct({
3324
+ id: effect.Schema.String,
3325
+ text: effect.Schema.String,
3326
+ createdAt: effect.Schema.String
3327
+ });
3166
3328
  const SubagentSummary = effect.Schema.Struct({
3167
3329
  agentId: effect.Schema.String,
3168
3330
  agentType: effect.Schema.String,
3169
3331
  description: effect.Schema.String,
3170
3332
  toolUseId: effect.Schema.String,
3171
3333
  spawnDepth: effect.Schema.Number,
3172
- status: effect.Schema.Literals(["running", "done"])
3334
+ status: effect.Schema.Literals(["running", "done"]),
3335
+ /** True for a background subagent, launched with `requestShape: "background"` (PAN-4247). */
3336
+ background: effect.Schema.optional(effect.Schema.Boolean),
3337
+ /** Recent human-origin sidechain inputs, most useful when a message routed into this subagent instead of the main conversation (PAN-4247). */
3338
+ humanInputs: effect.Schema.optional(effect.Schema.Array(SubagentHumanInput))
3173
3339
  });
3174
3340
  /**
3175
3341
  * Response shape for GET /api/agents/:id/conversation.
@@ -3678,6 +3844,7 @@ const INITIAL_READ_MODEL_STATE = {
3678
3844
  embedProgressBySessionId: {},
3679
3845
  ciByProjectKey: {},
3680
3846
  restartGate: null,
3847
+ githubQuota: null,
3681
3848
  deployByProjectKey: {},
3682
3849
  agentIdBySessionId: {},
3683
3850
  dashboardLifecycle: {
@@ -3809,6 +3976,7 @@ function syncSnapshot(state, snapshot) {
3809
3976
  embedProgressBySessionId: snapshot.embedProgressBySessionId ?? {},
3810
3977
  ciByProjectKey: snapshot.ciByProjectKey ?? state.ciByProjectKey,
3811
3978
  restartGate: snapshot.restartGate ?? state.restartGate,
3979
+ githubQuota: snapshot.githubQuota ?? state.githubQuota,
3812
3980
  deployByProjectKey: snapshot.deployByProjectKey ?? state.deployByProjectKey,
3813
3981
  agentIdBySessionId
3814
3982
  };
@@ -3913,6 +4081,7 @@ function applyEvent(state, event) {
3913
4081
  ...prevRuntime,
3914
4082
  activity: "stopped",
3915
4083
  currentTool: void 0,
4084
+ currentToolDescription: void 0,
3916
4085
  thinking: void 0,
3917
4086
  waiting: void 0,
3918
4087
  channelReply: void 0,
@@ -4056,6 +4225,7 @@ function applyEvent(state, event) {
4056
4225
  ...prevRuntime,
4057
4226
  activity: "stopped",
4058
4227
  currentTool: void 0,
4228
+ currentToolDescription: void 0,
4059
4229
  thinking: void 0,
4060
4230
  waiting: void 0,
4061
4231
  channelReply: void 0,
@@ -4224,6 +4394,11 @@ function applyEvent(state, event) {
4224
4394
  ...event.payload.lastOutcome === void 0 ? {} : { lastOutcome: event.payload.lastOutcome }
4225
4395
  }
4226
4396
  };
4397
+ case "github_quota.changed": return {
4398
+ ...state,
4399
+ sequence: Math.max(state.sequence, event.sequence),
4400
+ githubQuota: event.payload
4401
+ };
4227
4402
  case "project.deploy_changed": return {
4228
4403
  ...state,
4229
4404
  sequence: Math.max(state.sequence, event.sequence),
@@ -4477,12 +4652,13 @@ function applyEvent(state, event) {
4477
4652
  sequence: Math.max(state.sequence, event.sequence)
4478
4653
  };
4479
4654
  case "agent.activity_changed": {
4480
- const { agentId, activity, currentTool } = event.payload;
4655
+ const { agentId, activity, currentTool, toolDescription } = event.payload;
4481
4656
  const prev = state.agentRuntimeById[agentId] ?? defaultRuntimeSnapshot(agentId, event.timestamp, event.sequence);
4482
4657
  const next = {
4483
4658
  ...prev,
4484
4659
  activity,
4485
4660
  currentTool: activity === "working" ? currentTool : void 0,
4661
+ currentToolDescription: activity === "working" ? toolDescription : void 0,
4486
4662
  thinking: activity === "thinking" ? prev.thinking : void 0,
4487
4663
  waiting: activity === "waiting" ? prev.waiting : void 0,
4488
4664
  channelReply: activity === "working" ? void 0 : prev.channelReply,
@@ -4505,6 +4681,7 @@ function applyEvent(state, event) {
4505
4681
  ...state.agentRuntimeById[agentId] ?? defaultRuntimeSnapshot(agentId, event.timestamp, event.sequence),
4506
4682
  activity: "thinking",
4507
4683
  currentTool: void 0,
4684
+ currentToolDescription: void 0,
4508
4685
  thinking: {
4509
4686
  since: event.timestamp,
4510
4687
  lastToolAt
@@ -4553,6 +4730,7 @@ function applyEvent(state, event) {
4553
4730
  ...state.agentRuntimeById[agentId] ?? defaultRuntimeSnapshot(agentId, event.timestamp, event.sequence),
4554
4731
  activity: "waiting",
4555
4732
  currentTool: void 0,
4733
+ currentToolDescription: void 0,
4556
4734
  thinking: void 0,
4557
4735
  waiting: {
4558
4736
  reason,
@@ -5109,6 +5287,30 @@ function deriveProjectCi(record) {
5109
5287
  };
5110
5288
  }
5111
5289
  //#endregion
5290
+ //#region src/effort.ts
5291
+ /**
5292
+ * Canonical reasoning-effort levels, end to end. `xhigh` was added in Opus 4.7
5293
+ * (between `high` and `max`); `max` predates it (Opus 4.6+/Sonnet 4.6). This is
5294
+ * the single source of truth for the enum — every other copy in the codebase
5295
+ * derives from it.
5296
+ */
5297
+ const EFFORT_LEVELS = [
5298
+ "low",
5299
+ "medium",
5300
+ "high",
5301
+ "xhigh",
5302
+ "max"
5303
+ ];
5304
+ const DEFAULT_EFFORT = "high";
5305
+ const EffortLevelSchema = effect.Schema.Literals(EFFORT_LEVELS);
5306
+ function isEffortLevel(value) {
5307
+ return typeof value === "string" && EFFORT_LEVELS.includes(value);
5308
+ }
5309
+ /** Compares two effort levels by rank; negative when `a` is lower than `b`. */
5310
+ function compareEffort(a, b) {
5311
+ return EFFORT_LEVELS.indexOf(a) - EFFORT_LEVELS.indexOf(b);
5312
+ }
5313
+ //#endregion
5112
5314
  //#region src/flywheel.ts
5113
5315
  const FlywheelRunId = effect.Schema.String.check(effect.Schema.isPattern(/^RUN-\d+$/));
5114
5316
  const FlywheelHttpUrl = effect.Schema.String.check(effect.Schema.isPattern(/^https?:\/\/\S+$/i));
@@ -5120,15 +5322,10 @@ const FlywheelHarness = effect.Schema.Literals([
5120
5322
  "acp",
5121
5323
  "kimi-code",
5122
5324
  "opencode",
5123
- "muse"
5124
- ]);
5125
- const FlywheelEffort = effect.Schema.Literals([
5126
- "low",
5127
- "medium",
5128
- "high",
5129
- "xhigh",
5130
- "max"
5325
+ "muse",
5326
+ "prime-agent"
5131
5327
  ]);
5328
+ const FlywheelEffort = EffortLevelSchema;
5132
5329
  const FlywheelOrchestrator = effect.Schema.Struct({
5133
5330
  harness: FlywheelHarness,
5134
5331
  model: effect.Schema.String,
@@ -5389,6 +5586,8 @@ const FlywheelConversationSummary = effect.Schema.Struct({
5389
5586
  model: effect.Schema.NullOr(effect.Schema.String),
5390
5587
  harness: effect.Schema.NullOr(effect.Schema.String),
5391
5588
  cwd: effect.Schema.String,
5589
+ /** When the conversation row was created — the page's elapsed run time. */
5590
+ createdAt: effect.Schema.String,
5392
5591
  sessionAlive: effect.Schema.Boolean
5393
5592
  });
5394
5593
  const FlywheelLastTick = effect.Schema.Struct({
@@ -5410,11 +5609,28 @@ const FlywheelJournalSummary = effect.Schema.Struct({
5410
5609
  type: effect.Schema.String,
5411
5610
  source: effect.Schema.optional(effect.Schema.String)
5412
5611
  });
5612
+ /** One live agent pane in the flywheel's project, as the backend inventory reports it. */
5613
+ const FlywheelAgentSummary = effect.Schema.Struct({
5614
+ issueId: effect.Schema.String,
5615
+ role: effect.Schema.String,
5616
+ harness: effect.Schema.String,
5617
+ model: effect.Schema.String,
5618
+ state: effect.Schema.String,
5619
+ agentId: effect.Schema.optional(effect.Schema.String)
5620
+ });
5413
5621
  const FlywheelInFlightRow = effect.Schema.Struct({
5414
5622
  issueId: effect.Schema.String,
5623
+ /** The tracker's title, or `null` when no tracker answered for this issue. */
5624
+ title: effect.Schema.NullOr(effect.Schema.String),
5415
5625
  state: IssueState,
5416
5626
  attention: effect.Schema.optional(IssueAttention),
5417
5627
  pr: effect.Schema.optional(DerivedPrState),
5628
+ /** Set when no configured tracker answered: the state is a guess, not a fact. */
5629
+ trackerUnknown: effect.Schema.optional(effect.Schema.Literal(true)),
5630
+ /** Live agent panes on this issue. `working` with 0 means nobody is driving it. */
5631
+ liveAgents: effect.Schema.Number,
5632
+ /** The loop named this id in its newest tick marker's in-flight list. */
5633
+ inTick: effect.Schema.Boolean,
5418
5634
  lastJournal: effect.Schema.NullOr(FlywheelJournalSummary)
5419
5635
  });
5420
5636
  const FlywheelOrderBookSummary = effect.Schema.Struct({
@@ -5431,6 +5647,13 @@ const FlywheelDerivedStatus = effect.Schema.Struct({
5431
5647
  freshness: effect.Schema.NullOr(FlywheelFreshness),
5432
5648
  policies: FlywheelPolicies,
5433
5649
  inFlight: effect.Schema.Array(FlywheelInFlightRow),
5650
+ /** Every live agent on an in-flight issue, by issue then role. */
5651
+ agents: effect.Schema.Array(FlywheelAgentSummary),
5652
+ /**
5653
+ * Which list the header counts: `tick` when a running loop named its own
5654
+ * in-flight ids, `census` when the rows are just the feature workspaces.
5655
+ */
5656
+ inFlightSource: effect.Schema.Literals(["tick", "census"]),
5434
5657
  orderBook: effect.Schema.NullOr(FlywheelOrderBookSummary),
5435
5658
  projectRoot: effect.Schema.String,
5436
5659
  generatedAt: effect.Schema.String
@@ -5496,7 +5719,8 @@ const CONTEXT_PREVIEW_HARNESSES = [
5496
5719
  "acp",
5497
5720
  "kimi-code",
5498
5721
  "opencode",
5499
- "muse"
5722
+ "muse",
5723
+ "prime-agent"
5500
5724
  ];
5501
5725
  const ContextLayerKind = effect.Schema.Literals(CONTEXT_LAYER_KINDS);
5502
5726
  const ContextPreviewHarness = effect.Schema.Literals(CONTEXT_PREVIEW_HARNESSES);
@@ -5606,6 +5830,7 @@ const ContextHarnessPreviews = effect.Schema.Struct({
5606
5830
  "kimi-code": effect.Schema.String,
5607
5831
  opencode: effect.Schema.optional(effect.Schema.String),
5608
5832
  muse: effect.Schema.String,
5833
+ "prime-agent": effect.Schema.String,
5609
5834
  fullPrompt: effect.Schema.String
5610
5835
  });
5611
5836
  const ContextPreviewDiagnostic = effect.Schema.Struct({
@@ -5664,6 +5889,7 @@ const ArtifactAgentHarness = effect.Schema.Literals([
5664
5889
  "kimi-code",
5665
5890
  "opencode",
5666
5891
  "muse",
5892
+ "prime-agent",
5667
5893
  "user"
5668
5894
  ]);
5669
5895
  const ArtifactLifecycleState = effect.Schema.Literals([
@@ -5841,7 +6067,8 @@ const CLAUDE_CODE_BEHAVIOR = {
5841
6067
  usesCodexHome: false,
5842
6068
  injectsPromptTimeMemory: false,
5843
6069
  workAgentMode: "claude-code",
5844
- readyTimeoutSeconds: 30
6070
+ readyTimeoutSeconds: 30,
6071
+ steerKind: "send-now-keys"
5845
6072
  };
5846
6073
  const OHMYPI_BEHAVIOR = {
5847
6074
  displayName: "Pi",
@@ -5863,7 +6090,14 @@ const OHMYPI_BEHAVIOR = {
5863
6090
  usesCodexHome: false,
5864
6091
  injectsPromptTimeMemory: true,
5865
6092
  workAgentMode: "ohmypi-rpc",
5866
- readyTimeoutSeconds: 120
6093
+ readyTimeoutSeconds: 120,
6094
+ steerKind: "control-channel",
6095
+ effortLevels: [
6096
+ "low",
6097
+ "medium",
6098
+ "high",
6099
+ "xhigh"
6100
+ ]
5867
6101
  };
5868
6102
  const CODEX_BEHAVIOR = {
5869
6103
  displayName: "Codex",
@@ -5885,7 +6119,8 @@ const CODEX_BEHAVIOR = {
5885
6119
  usesCodexHome: true,
5886
6120
  injectsPromptTimeMemory: false,
5887
6121
  workAgentMode: "codex-work-tui",
5888
- readyTimeoutSeconds: 30
6122
+ readyTimeoutSeconds: 30,
6123
+ steerKind: null
5889
6124
  };
5890
6125
  const ACP_BEHAVIOR = {
5891
6126
  displayName: "ACP",
@@ -5907,7 +6142,8 @@ const ACP_BEHAVIOR = {
5907
6142
  usesCodexHome: false,
5908
6143
  injectsPromptTimeMemory: false,
5909
6144
  workAgentMode: "acp-host",
5910
- readyTimeoutSeconds: 30
6145
+ readyTimeoutSeconds: 30,
6146
+ steerKind: null
5911
6147
  };
5912
6148
  const KIMI_CODE_BEHAVIOR = {
5913
6149
  displayName: "Kimi Code",
@@ -5929,7 +6165,8 @@ const KIMI_CODE_BEHAVIOR = {
5929
6165
  usesCodexHome: false,
5930
6166
  injectsPromptTimeMemory: false,
5931
6167
  workAgentMode: "kimi-code-tui",
5932
- readyTimeoutSeconds: 60
6168
+ readyTimeoutSeconds: 60,
6169
+ steerKind: null
5933
6170
  };
5934
6171
  const OPENCODE_BEHAVIOR = {
5935
6172
  ...ACP_BEHAVIOR,
@@ -5958,7 +6195,37 @@ const MUSE_BEHAVIOR = {
5958
6195
  usesCodexHome: false,
5959
6196
  injectsPromptTimeMemory: false,
5960
6197
  workAgentMode: "muse-tui",
5961
- readyTimeoutSeconds: 60
6198
+ readyTimeoutSeconds: 60,
6199
+ steerKind: null,
6200
+ effortLevels: [
6201
+ "low",
6202
+ "medium",
6203
+ "high",
6204
+ "xhigh"
6205
+ ]
6206
+ };
6207
+ const PRIME_AGENT_BEHAVIOR = {
6208
+ displayName: "Prime Agent",
6209
+ nativeCommands: [],
6210
+ executableName: "prime-agent",
6211
+ processNames: ["prime-agent"],
6212
+ launchCommandKind: "prime-agent-host",
6213
+ deliveryKind: "prime-agent-host-rpc",
6214
+ readinessKind: "prime-agent-host-ready",
6215
+ transcriptKind: "prime-agent-jsonl",
6216
+ sessionIdSource: "prime-agent-session-id",
6217
+ contextLayerKind: "prime-agent",
6218
+ feedKind: "prime_agent",
6219
+ supportsPtySupervisor: false,
6220
+ supportsChannelsBridge: false,
6221
+ supportsConversationStreaming: true,
6222
+ supportsPatchProjection: false,
6223
+ usesRpcFifo: false,
6224
+ usesCodexHome: false,
6225
+ injectsPromptTimeMemory: false,
6226
+ workAgentMode: "prime-agent-host",
6227
+ readyTimeoutSeconds: 60,
6228
+ steerKind: null
5962
6229
  };
5963
6230
  const BEHAVIORS = {
5964
6231
  "opencode": OPENCODE_BEHAVIOR,
@@ -5967,7 +6234,8 @@ const BEHAVIORS = {
5967
6234
  codex: CODEX_BEHAVIOR,
5968
6235
  acp: ACP_BEHAVIOR,
5969
6236
  "kimi-code": KIMI_CODE_BEHAVIOR,
5970
- muse: MUSE_BEHAVIOR
6237
+ muse: MUSE_BEHAVIOR,
6238
+ "prime-agent": PRIME_AGENT_BEHAVIOR
5971
6239
  };
5972
6240
  function getHarnessBehavior(harness) {
5973
6241
  if (harness === "ohmypi" || harness === "pi") return OHMYPI_BEHAVIOR;
@@ -5976,6 +6244,7 @@ function getHarnessBehavior(harness) {
5976
6244
  if (harness === "acp") return ACP_BEHAVIOR;
5977
6245
  if (harness === "kimi-code") return KIMI_CODE_BEHAVIOR;
5978
6246
  if (harness === "muse") return MUSE_BEHAVIOR;
6247
+ if (harness === "prime-agent") return PRIME_AGENT_BEHAVIOR;
5979
6248
  return CLAUDE_CODE_BEHAVIOR;
5980
6249
  }
5981
6250
  function getRuntimeBehavior(runtime) {
@@ -6090,7 +6359,10 @@ const TELEMETRY_EVENT_NAMES = [
6090
6359
  "agent_question_answered",
6091
6360
  "server_boot",
6092
6361
  "cli_command_run",
6093
- "pipeline_stage_changed"
6362
+ "pipeline_stage_changed",
6363
+ "github_quota_sample",
6364
+ "github_rate_limited",
6365
+ "instance_heartbeat"
6094
6366
  ];
6095
6367
  const TELEMETRY_CLI_VERBS = [
6096
6368
  "abort",
@@ -6207,6 +6479,19 @@ const TELEMETRY_PROPERTY_DOMAINS = {
6207
6479
  "handoff",
6208
6480
  "plain"
6209
6481
  ],
6482
+ github_caller: [
6483
+ "pipeline_membership",
6484
+ "pr_cache",
6485
+ "pr_sync",
6486
+ "ci_repair",
6487
+ "issue_poller",
6488
+ "close_out",
6489
+ "tracker_client",
6490
+ "app_rest",
6491
+ "quota_sampler",
6492
+ "agent",
6493
+ "other"
6494
+ ],
6210
6495
  harness: [
6211
6496
  "claude-code",
6212
6497
  "ohmypi",
@@ -6214,7 +6499,8 @@ const TELEMETRY_PROPERTY_DOMAINS = {
6214
6499
  "acp",
6215
6500
  "kimi-code",
6216
6501
  "opencode",
6217
- "muse"
6502
+ "muse",
6503
+ "prime-agent"
6218
6504
  ],
6219
6505
  merge_kind: ["pipeline"],
6220
6506
  model_family: [
@@ -6238,7 +6524,26 @@ const TELEMETRY_PROPERTY_DOMAINS = {
6238
6524
  "clone",
6239
6525
  "existing",
6240
6526
  "new"
6241
- ]
6527
+ ],
6528
+ quota_points_bucket: [
6529
+ "0",
6530
+ "1-49",
6531
+ "50-199",
6532
+ "200-499",
6533
+ "500-999",
6534
+ "1000-2499",
6535
+ "2500+"
6536
+ ],
6537
+ quota_remaining_bucket: [
6538
+ "0",
6539
+ "1-99",
6540
+ "100-499",
6541
+ "500-999",
6542
+ "1000-2499",
6543
+ "2500+",
6544
+ "unknown"
6545
+ ],
6546
+ rate_limit_kind: ["primary", "secondary"]
6242
6547
  };
6243
6548
  const TELEMETRY_EVENT_CATALOG = {
6244
6549
  dashboard_tab_viewed: { tab: "dashboard_tab" },
@@ -6281,8 +6586,65 @@ const TELEMETRY_EVENT_CATALOG = {
6281
6586
  stage: "pipeline_stage",
6282
6587
  harness: "harness",
6283
6588
  model: "model_family"
6589
+ },
6590
+ github_quota_sample: {
6591
+ graphql_pipeline_membership: "quota_points_bucket",
6592
+ rest_pipeline_membership: "quota_points_bucket",
6593
+ graphql_pr_cache: "quota_points_bucket",
6594
+ rest_pr_cache: "quota_points_bucket",
6595
+ graphql_pr_sync: "quota_points_bucket",
6596
+ rest_pr_sync: "quota_points_bucket",
6597
+ graphql_ci_repair: "quota_points_bucket",
6598
+ rest_ci_repair: "quota_points_bucket",
6599
+ graphql_issue_poller: "quota_points_bucket",
6600
+ rest_issue_poller: "quota_points_bucket",
6601
+ graphql_close_out: "quota_points_bucket",
6602
+ rest_close_out: "quota_points_bucket",
6603
+ graphql_tracker_client: "quota_points_bucket",
6604
+ rest_tracker_client: "quota_points_bucket",
6605
+ graphql_app_rest: "quota_points_bucket",
6606
+ rest_app_rest: "quota_points_bucket",
6607
+ graphql_agent: "quota_points_bucket",
6608
+ rest_agent: "quota_points_bucket",
6609
+ graphql_other: "quota_points_bucket",
6610
+ rest_other: "quota_points_bucket",
6611
+ graphql_unattributed: "quota_points_bucket",
6612
+ min_remaining_graphql: "quota_remaining_bucket",
6613
+ min_remaining_rest: "quota_remaining_bucket",
6614
+ primary_limit_errors: "count_bucket",
6615
+ secondary_limit_errors: "count_bucket"
6616
+ },
6617
+ github_rate_limited: {
6618
+ caller: "github_caller",
6619
+ kind: "rate_limit_kind",
6620
+ own_usage_low: "boolean"
6621
+ },
6622
+ instance_heartbeat: {
6623
+ project_count: "count_bucket",
6624
+ active_agent_count: "count_bucket",
6625
+ dashboard_running: "boolean"
6284
6626
  }
6285
6627
  };
6628
+ /** PAN-4264: GitHub quota points as a coarse bucket (raw counts are never sent). */
6629
+ function bucketQuotaPoints(points) {
6630
+ if (!(points > 0)) return "0";
6631
+ if (points < 50) return "1-49";
6632
+ if (points < 200) return "50-199";
6633
+ if (points < 500) return "200-499";
6634
+ if (points < 1e3) return "500-999";
6635
+ if (points < 2500) return "1000-2499";
6636
+ return "2500+";
6637
+ }
6638
+ /** PAN-4264: GitHub quota remaining as a coarse bucket; `unknown` without a sample. */
6639
+ function bucketQuotaRemaining(remaining) {
6640
+ if (remaining === void 0 || !Number.isFinite(remaining)) return "unknown";
6641
+ if (remaining <= 0) return "0";
6642
+ if (remaining < 100) return "1-99";
6643
+ if (remaining < 500) return "100-499";
6644
+ if (remaining < 1e3) return "500-999";
6645
+ if (remaining < 2500) return "1000-2499";
6646
+ return "2500+";
6647
+ }
6286
6648
  //#endregion
6287
6649
  //#region src/composer-commands.generated.ts
6288
6650
  const COMPOSER_COMMAND_MANIFEST = [
@@ -6510,13 +6872,65 @@ const COMPOSER_COMMAND_MANIFEST = [
6510
6872
  "id": "pan-skills",
6511
6873
  "path": ["skills"],
6512
6874
  "display": "/pan skills",
6513
- "description": "List and manage skills",
6875
+ "description": "List skills and set per-level on/off overrides",
6514
6876
  "args": [],
6877
+ "options": [],
6878
+ "aliases": [],
6879
+ "category": "Core"
6880
+ },
6881
+ {
6882
+ "id": "pan-skills-list",
6883
+ "path": ["skills", "list"],
6884
+ "display": "/pan skills list",
6885
+ "description": "List skills with effective on/off state and its source",
6886
+ "args": [],
6887
+ "options": [
6888
+ {
6889
+ "flags": "--project <key>",
6890
+ "description": "Resolve for a project",
6891
+ "required": true,
6892
+ "valueHint": "key"
6893
+ },
6894
+ {
6895
+ "flags": "--issue <id>",
6896
+ "description": "Resolve for an issue",
6897
+ "required": true,
6898
+ "valueHint": "id"
6899
+ },
6900
+ {
6901
+ "flags": "--json",
6902
+ "description": "Output as JSON",
6903
+ "required": false,
6904
+ "valueHint": null
6905
+ }
6906
+ ],
6907
+ "aliases": [],
6908
+ "category": "Core"
6909
+ },
6910
+ {
6911
+ "id": "pan-skills-set",
6912
+ "path": ["skills", "set"],
6913
+ "display": "/pan skills set",
6914
+ "description": "Set a skill on, off, or inherit (global unless --project/--issue)",
6915
+ "args": [{
6916
+ "name": "skill",
6917
+ "required": true,
6918
+ "variadic": false
6919
+ }, {
6920
+ "name": "state",
6921
+ "required": true,
6922
+ "variadic": false
6923
+ }],
6515
6924
  "options": [{
6516
- "flags": "--json",
6517
- "description": "Output as JSON",
6518
- "required": false,
6519
- "valueHint": null
6925
+ "flags": "--project <key>",
6926
+ "description": "Project override",
6927
+ "required": true,
6928
+ "valueHint": "key"
6929
+ }, {
6930
+ "flags": "--issue <id>",
6931
+ "description": "Issue override",
6932
+ "required": true,
6933
+ "valueHint": "id"
6520
6934
  }],
6521
6935
  "aliases": [],
6522
6936
  "category": "Core"
@@ -6773,7 +7187,7 @@ const COMPOSER_COMMAND_MANIFEST = [
6773
7187
  },
6774
7188
  {
6775
7189
  "flags": "--harness <harness>",
6776
- "description": "Coding-agent harness: claude-code | pi | codex | acp | kimi-code | opencode | muse (defaults to role/provider settings)",
7190
+ "description": "Coding-agent harness: claude-code | pi | codex | acp | kimi-code | opencode | muse | prime-agent (defaults to role/provider settings)",
6777
7191
  "required": true,
6778
7192
  "valueHint": "harness"
6779
7193
  },
@@ -6873,7 +7287,17 @@ const COMPOSER_COMMAND_MANIFEST = [
6873
7287
  "required": true,
6874
7288
  "variadic": false
6875
7289
  }],
6876
- "options": [],
7290
+ "options": [{
7291
+ "flags": "--force",
7292
+ "description": "Deliver even to a critic or verifier lane that already filed its verdict",
7293
+ "required": false,
7294
+ "valueHint": null
7295
+ }, {
7296
+ "flags": "--steer",
7297
+ "description": "Interrupt the running turn and send now (Claude Code send-now; Ctrl+X Ctrl+S)",
7298
+ "required": false,
7299
+ "valueHint": null
7300
+ }],
6877
7301
  "aliases": [],
6878
7302
  "category": "Lifecycle"
6879
7303
  },
@@ -7452,7 +7876,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7452
7876
  },
7453
7877
  {
7454
7878
  "flags": "--harness <harness>",
7455
- "description": "Coding-agent harness: claude-code | pi | codex | acp | kimi-code | opencode | muse (defaults to role/provider settings)",
7879
+ "description": "Coding-agent harness: claude-code | pi | codex | acp | kimi-code | opencode | muse | prime-agent (defaults to role/provider settings)",
7456
7880
  "required": true,
7457
7881
  "valueHint": "harness"
7458
7882
  },
@@ -7530,7 +7954,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7530
7954
  },
7531
7955
  {
7532
7956
  "flags": "--skip-freshness",
7533
- "description": "Bypass the plan-freshness preflight and spawn even if the plan names files that no longer exist",
7957
+ "description": "Bypass the plan-freshness preflight and spawn even if the plan names files deleted since it was written",
7534
7958
  "required": false,
7535
7959
  "valueHint": null
7536
7960
  }
@@ -7557,7 +7981,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7557
7981
  },
7558
7982
  {
7559
7983
  "flags": "--harness <harness>",
7560
- "description": "Coding-agent harness: claude-code | pi | codex | acp | kimi-code | opencode | muse (defaults to role/provider settings)",
7984
+ "description": "Coding-agent harness: claude-code | pi | codex | acp | kimi-code | opencode | muse | prime-agent (defaults to role/provider settings)",
7561
7985
  "required": true,
7562
7986
  "valueHint": "harness"
7563
7987
  },
@@ -10654,6 +11078,20 @@ const COMPOSER_COMMAND_MANIFEST = [
10654
11078
  "aliases": [],
10655
11079
  "category": "Admin"
10656
11080
  },
11081
+ {
11082
+ "id": "pan-admin-config-tiers",
11083
+ "path": [
11084
+ "admin",
11085
+ "config",
11086
+ "tiers"
11087
+ ],
11088
+ "display": "/pan admin config tiers",
11089
+ "description": "Show the effective model per tiered_execution tier and whether it overrides roles.work",
11090
+ "args": [],
11091
+ "options": [],
11092
+ "aliases": [],
11093
+ "category": "Admin"
11094
+ },
10657
11095
  {
10658
11096
  "id": "pan-admin-hooks",
10659
11097
  "path": ["admin", "hooks"],
@@ -11527,6 +11965,12 @@ const COMPOSER_COMMAND_MANIFEST = [
11527
11965
  "description": "Skip Herdr terminal backend install/verify (tmux-only hosts)",
11528
11966
  "required": false,
11529
11967
  "valueHint": null
11968
+ },
11969
+ {
11970
+ "flags": "--skip-ollama",
11971
+ "description": "Skip Ollama local-model detection and optional gemma4:12b pull",
11972
+ "required": false,
11973
+ "valueHint": null
11530
11974
  }
11531
11975
  ],
11532
11976
  "aliases": [],
@@ -11982,6 +12426,333 @@ const COMPOSER_COMMAND_MANIFEST = [
11982
12426
  "aliases": [],
11983
12427
  "category": "CLI"
11984
12428
  },
12429
+ {
12430
+ "id": "pan-lane",
12431
+ "path": ["lane"],
12432
+ "display": "/pan lane",
12433
+ "description": "Gauntlet lanes: launch, list, show, wait on, report from, stop and reap lane conversations",
12434
+ "args": [],
12435
+ "options": [],
12436
+ "aliases": [],
12437
+ "category": "CLI"
12438
+ },
12439
+ {
12440
+ "id": "pan-lane-start",
12441
+ "path": ["lane", "start"],
12442
+ "display": "/pan lane start",
12443
+ "description": "Launch a lane conversation under the calling conversation (any harness)",
12444
+ "args": [],
12445
+ "options": [
12446
+ {
12447
+ "flags": "--key <key>",
12448
+ "description": "Lane key inside the run (required unless --for)",
12449
+ "required": true,
12450
+ "valueHint": "key"
12451
+ },
12452
+ {
12453
+ "flags": "--for <builder-key>",
12454
+ "description": "Critic (required) or verifier: the builder lane judged; --key defaults to it",
12455
+ "required": true,
12456
+ "valueHint": "builder-key"
12457
+ },
12458
+ {
12459
+ "flags": "--role <role>",
12460
+ "description": "builder | critic | verifier | play | orchestrator (required)",
12461
+ "required": true,
12462
+ "valueHint": "role"
12463
+ },
12464
+ {
12465
+ "flags": "--brief <file>",
12466
+ "description": "The brief, from a file",
12467
+ "required": true,
12468
+ "valueHint": "file"
12469
+ },
12470
+ {
12471
+ "flags": "--prompt <text>",
12472
+ "description": "The brief, inline",
12473
+ "required": true,
12474
+ "valueHint": "text"
12475
+ },
12476
+ {
12477
+ "flags": "--run <key>",
12478
+ "description": "Run key (required from a root; inherited inside an orchestrator lane)",
12479
+ "required": true,
12480
+ "valueHint": "key"
12481
+ },
12482
+ {
12483
+ "flags": "--parent <conv>",
12484
+ "description": "Launching conversation (default: $OVERDECK_CONVERSATION)",
12485
+ "required": true,
12486
+ "valueHint": "conv"
12487
+ },
12488
+ {
12489
+ "flags": "--project <key>",
12490
+ "description": "Project (default: the parent's project)",
12491
+ "required": true,
12492
+ "valueHint": "key"
12493
+ },
12494
+ {
12495
+ "flags": "--model <model>",
12496
+ "description": "Model (default: projects.<key>.gauntlet.roles.<role>.model)",
12497
+ "required": true,
12498
+ "valueHint": "model"
12499
+ },
12500
+ {
12501
+ "flags": "--harness <harness>",
12502
+ "description": "Harness (default: role config, else routed from the model)",
12503
+ "required": true,
12504
+ "valueHint": "harness"
12505
+ },
12506
+ {
12507
+ "flags": "--effort <effort>",
12508
+ "description": "low | medium | high",
12509
+ "required": true,
12510
+ "valueHint": "effort"
12511
+ },
12512
+ {
12513
+ "flags": "--title <title>",
12514
+ "description": "Conversation title (default: <run> <key> · <role>)",
12515
+ "required": true,
12516
+ "valueHint": "title"
12517
+ },
12518
+ {
12519
+ "flags": "--branch <branch>",
12520
+ "description": "Builder branch (default: <run>/<key>, <run>/<key>-i<n> after)",
12521
+ "required": true,
12522
+ "valueHint": "branch"
12523
+ },
12524
+ {
12525
+ "flags": "--from <ref>",
12526
+ "description": "Base ref for a new builder branch",
12527
+ "required": true,
12528
+ "valueHint": "ref"
12529
+ },
12530
+ {
12531
+ "flags": "--at <ref>",
12532
+ "description": "Commit a critic or verifier judges (default with --for: the builder's newest done head)",
12533
+ "required": true,
12534
+ "valueHint": "ref"
12535
+ },
12536
+ {
12537
+ "flags": "--reuse",
12538
+ "description": "Continue in the directory of the latest earlier lane with the same run, key and role",
12539
+ "required": false,
12540
+ "valueHint": null
12541
+ },
12542
+ {
12543
+ "flags": "--replace",
12544
+ "description": "Stop the live lane with the same run, key and role first",
12545
+ "required": false,
12546
+ "valueHint": null
12547
+ },
12548
+ {
12549
+ "flags": "--no-wait",
12550
+ "description": "Return without waiting for the lane to start",
12551
+ "required": false,
12552
+ "valueHint": null
12553
+ },
12554
+ {
12555
+ "flags": "--json",
12556
+ "description": "Print the launch result as JSON",
12557
+ "required": false,
12558
+ "valueHint": null
12559
+ }
12560
+ ],
12561
+ "aliases": [],
12562
+ "category": "CLI"
12563
+ },
12564
+ {
12565
+ "id": "pan-lane-list",
12566
+ "path": ["lane", "list"],
12567
+ "display": "/pan lane list",
12568
+ "description": "List lanes with their activity, newest report, git facts and cost",
12569
+ "args": [],
12570
+ "options": [
12571
+ {
12572
+ "flags": "--run <key>",
12573
+ "description": "Only this run's lanes",
12574
+ "required": true,
12575
+ "valueHint": "key"
12576
+ },
12577
+ {
12578
+ "flags": "--parent <conv>",
12579
+ "description": "Only lanes launched by this conversation",
12580
+ "required": true,
12581
+ "valueHint": "conv"
12582
+ },
12583
+ {
12584
+ "flags": "--json",
12585
+ "description": "Print JSON",
12586
+ "required": false,
12587
+ "valueHint": null
12588
+ }
12589
+ ],
12590
+ "aliases": [],
12591
+ "category": "CLI"
12592
+ },
12593
+ {
12594
+ "id": "pan-lane-show",
12595
+ "path": ["lane", "show"],
12596
+ "display": "/pan lane show",
12597
+ "description": "Print the builder → critic chain of a run and key, then one line per lane",
12598
+ "args": [{
12599
+ "name": "lane",
12600
+ "required": false,
12601
+ "variadic": false
12602
+ }],
12603
+ "options": [
12604
+ {
12605
+ "flags": "--run <key>",
12606
+ "description": "Run key (with --key)",
12607
+ "required": true,
12608
+ "valueHint": "key"
12609
+ },
12610
+ {
12611
+ "flags": "--key <key>",
12612
+ "description": "Lane key (with --run)",
12613
+ "required": true,
12614
+ "valueHint": "key"
12615
+ },
12616
+ {
12617
+ "flags": "--json",
12618
+ "description": "Print { run, key, steps }",
12619
+ "required": false,
12620
+ "valueHint": null
12621
+ }
12622
+ ],
12623
+ "aliases": [],
12624
+ "category": "CLI"
12625
+ },
12626
+ {
12627
+ "id": "pan-lane-wait",
12628
+ "path": ["lane", "wait"],
12629
+ "display": "/pan lane wait",
12630
+ "description": "Wait for a lane report (exit 0 done, 4 blocked/failed, 2 no report, 3 timeout, 1 error)",
12631
+ "args": [{
12632
+ "name": "lane",
12633
+ "required": false,
12634
+ "variadic": false
12635
+ }],
12636
+ "options": [
12637
+ {
12638
+ "flags": "--run <key>",
12639
+ "description": "Wait for the next report of any lane in this run",
12640
+ "required": true,
12641
+ "valueHint": "key"
12642
+ },
12643
+ {
12644
+ "flags": "--parent <conv>",
12645
+ "description": "Wait for the next report of any lane launched by this conversation",
12646
+ "required": true,
12647
+ "valueHint": "conv"
12648
+ },
12649
+ {
12650
+ "flags": "--after <seq-or-cursor>",
12651
+ "description": "Report seq for one lane; cursor <atMs>.<name>.<seq> for a run or parent",
12652
+ "required": true,
12653
+ "valueHint": "seq-or-cursor"
12654
+ },
12655
+ {
12656
+ "flags": "--timeout <seconds>",
12657
+ "description": "Stop waiting after this many seconds (exit 3)",
12658
+ "required": true,
12659
+ "valueHint": "seconds"
12660
+ }
12661
+ ],
12662
+ "aliases": [],
12663
+ "category": "CLI"
12664
+ },
12665
+ {
12666
+ "id": "pan-lane-report",
12667
+ "path": ["lane", "report"],
12668
+ "display": "/pan lane report",
12669
+ "description": "Record this lane's report (run inside the lane)",
12670
+ "args": [],
12671
+ "options": [
12672
+ {
12673
+ "flags": "--file <path>",
12674
+ "description": "Read the Markdown report from a file",
12675
+ "required": true,
12676
+ "valueHint": "path"
12677
+ },
12678
+ {
12679
+ "flags": "--stdin",
12680
+ "description": "Read the Markdown report from stdin",
12681
+ "required": false,
12682
+ "valueHint": null
12683
+ },
12684
+ {
12685
+ "flags": "--status <status>",
12686
+ "description": "done | blocked | failed (default: done)",
12687
+ "required": true,
12688
+ "valueHint": "status"
12689
+ },
12690
+ {
12691
+ "flags": "--allow-unpushed",
12692
+ "description": "Let a builder report done with commits not on its upstream",
12693
+ "required": false,
12694
+ "valueHint": null
12695
+ },
12696
+ {
12697
+ "flags": "--verdict <value>",
12698
+ "description": "Critic or verifier done report: WOWED | IMPRESSED | NOT_YET | PASS | DEFECTS",
12699
+ "required": true,
12700
+ "valueHint": "value"
12701
+ },
12702
+ {
12703
+ "flags": "--defects <n>",
12704
+ "description": "Defect count (default: the verdict file's defects array length)",
12705
+ "required": true,
12706
+ "valueHint": "n"
12707
+ },
12708
+ {
12709
+ "flags": "--verdict-file <path>",
12710
+ "description": "The verdict JSON the lane wrote",
12711
+ "required": true,
12712
+ "valueHint": "path"
12713
+ }
12714
+ ],
12715
+ "aliases": [],
12716
+ "category": "CLI"
12717
+ },
12718
+ {
12719
+ "id": "pan-lane-stop",
12720
+ "path": ["lane", "stop"],
12721
+ "display": "/pan lane stop",
12722
+ "description": "Stop a lane through the conversation stop door",
12723
+ "args": [{
12724
+ "name": "lane",
12725
+ "required": true,
12726
+ "variadic": false
12727
+ }],
12728
+ "options": [],
12729
+ "aliases": [],
12730
+ "category": "CLI"
12731
+ },
12732
+ {
12733
+ "id": "pan-lane-reap",
12734
+ "path": ["lane", "reap"],
12735
+ "display": "/pan lane reap",
12736
+ "description": "Remove a lane's directory and archive its conversation (never kills, never discards work)",
12737
+ "args": [{
12738
+ "name": "lane",
12739
+ "required": true,
12740
+ "variadic": false
12741
+ }],
12742
+ "options": [{
12743
+ "flags": "--park",
12744
+ "description": "Save uncommitted work to a verified patch before removing a dirty worktree",
12745
+ "required": false,
12746
+ "valueHint": null
12747
+ }, {
12748
+ "flags": "--keep",
12749
+ "description": "Keep the conversation listed instead of archiving it",
12750
+ "required": false,
12751
+ "valueHint": null
12752
+ }],
12753
+ "aliases": [],
12754
+ "category": "CLI"
12755
+ },
11985
12756
  {
11986
12757
  "id": "pan-flywheel",
11987
12758
  "path": ["flywheel"],
@@ -12188,7 +12959,7 @@ const COMPOSER_COMMAND_MANIFEST = [
12188
12959
  },
12189
12960
  {
12190
12961
  "flags": "--agent-harness <harness>",
12191
- "description": "Agent harness: claude-code, pi, ohmypi, codex, acp, kimi-code, opencode, muse, or user",
12962
+ "description": "Agent harness: claude-code, pi, ohmypi, codex, acp, kimi-code, opencode, muse, prime-agent, or user",
12192
12963
  "required": true,
12193
12964
  "valueHint": "harness"
12194
12965
  },
@@ -13118,6 +13889,21 @@ const COMPOSER_COMMAND_MANIFEST = [
13118
13889
  "aliases": [],
13119
13890
  "category": "Core"
13120
13891
  },
13892
+ {
13893
+ "id": "pan-doctor-github-quota",
13894
+ "path": ["doctor", "github-quota"],
13895
+ "display": "/pan doctor github-quota",
13896
+ "description": "Show GitHub API quota use per caller, active pauses, and skipped projects",
13897
+ "args": [],
13898
+ "options": [{
13899
+ "flags": "--json",
13900
+ "description": "Print JSON",
13901
+ "required": false,
13902
+ "valueHint": null
13903
+ }],
13904
+ "aliases": [],
13905
+ "category": "Core"
13906
+ },
13121
13907
  {
13122
13908
  "id": "pan-resources",
13123
13909
  "path": ["resources"],
@@ -13667,6 +14453,11 @@ const DirectoryPause = effect.Schema.Struct({
13667
14453
  reason: effect.Schema.NullOr(effect.Schema.String),
13668
14454
  since: effect.Schema.NullOr(effect.Schema.String)
13669
14455
  });
14456
+ /** A provider error (billing, usage limit, ...) detected at the end of a transcript (PAN-4222). */
14457
+ const DirectoryProviderError = effect.Schema.Struct({
14458
+ message: effect.Schema.String,
14459
+ at: effect.Schema.String
14460
+ });
13670
14461
  const DirectoryEntry = effect.Schema.Struct({
13671
14462
  id: effect.Schema.String,
13672
14463
  kind: DirectoryEntryKind,
@@ -13691,7 +14482,29 @@ const DirectoryEntry = effect.Schema.Struct({
13691
14482
  source: DirectoryEntrySource,
13692
14483
  transcript: effect.Schema.NullOr(DirectoryTranscriptRef),
13693
14484
  /** The pause gate from state.json, native agents only (PAN-4197). */
13694
- pause: effect.Schema.optional(DirectoryPause)
14485
+ pause: effect.Schema.optional(DirectoryPause),
14486
+ /** PAN-4223: gauntlet lane facts; conversation entries that are lanes only. */
14487
+ lane: effect.Schema.optional(effect.Schema.Struct({
14488
+ run: effect.Schema.String,
14489
+ key: effect.Schema.String,
14490
+ role: effect.Schema.String,
14491
+ iteration: effect.Schema.Number,
14492
+ reportStatus: effect.Schema.NullOr(effect.Schema.Literals([
14493
+ "done",
14494
+ "blocked",
14495
+ "failed"
14496
+ ])),
14497
+ /** Critic/verifier: its verdict (or `pending`); builder: the newest critic verdict. */
14498
+ verdict: effect.Schema.optional(effect.Schema.NullOr(effect.Schema.String)),
14499
+ /** Critic/verifier: the judged builder's legacy conversation id. */
14500
+ criticOf: effect.Schema.optional(effect.Schema.Number)
14501
+ })),
14502
+ /** PAN-4223: the predecessor's legacy conversation id; successors only (links to /conv/<id>). */
14503
+ continuesFrom: effect.Schema.optional(effect.Schema.Number),
14504
+ /** The id runtime events (agentRuntimeById) are keyed under, when it differs from `id` (PAN-4222). */
14505
+ runtimeId: effect.Schema.optional(effect.Schema.String),
14506
+ /** A provider error detected at the transcript's end, conversations only (PAN-4222). */
14507
+ providerError: effect.Schema.optional(DirectoryProviderError)
13695
14508
  });
13696
14509
  /**
13697
14510
  * `window`: live entries plus finished ones active inside `windowHours`.
@@ -13788,6 +14601,32 @@ function isConfiguredPullRequestRepo(ref, repos) {
13788
14601
  return repos.some((repo) => repo.host === ref.host && repo.repository === ref.repository);
13789
14602
  }
13790
14603
  //#endregion
14604
+ //#region src/conversation-rows.ts
14605
+ /**
14606
+ * Conversation-row classifiers shared by the dashboard server (`src/lib`) and
14607
+ * the frontend (PAN-4301). One rule per question: which rows are singleton
14608
+ * runners, and what a lane conversation is doing right now (D10).
14609
+ */
14610
+ /** Singleton runners spawn under their bare id (see src/lib/agents/identity.ts normalizeAgentId). */
14611
+ const SINGLETON_AGENT_IDS = new Set(["flywheel-orchestrator", "sequencer-runner"]);
14612
+ function isSingletonConversation(row) {
14613
+ return SINGLETON_AGENT_IDS.has(row.name.toLowerCase()) || row.issueId != null && SINGLETON_AGENT_IDS.has(row.issueId.toLowerCase());
14614
+ }
14615
+ /** D10 `starting`: not alive, not ended, created less than this long ago. */
14616
+ const LANE_STARTING_GRACE_MS = 3 * 6e4;
14617
+ /** D10, first match wins. */
14618
+ function laneActivityOf(row, now) {
14619
+ if (row.archivedAt != null) return "stopped";
14620
+ if (row.spawnError) return "failed-to-start";
14621
+ if (row.sessionAlive) {
14622
+ if ((row.pendingInputCount ?? 0) > 0) return "needs-you";
14623
+ if (row.isWorking) return "working";
14624
+ return "idle";
14625
+ }
14626
+ if (row.status === "active" && now - Date.parse(row.createdAt) < 18e4) return "starting";
14627
+ return "stopped";
14628
+ }
14629
+ //#endregion
13791
14630
  exports.ACP_BEHAVIOR = ACP_BEHAVIOR;
13792
14631
  exports.AGENT_ROLES = AGENT_ROLES;
13793
14632
  exports.Activity = Activity;
@@ -13899,6 +14738,7 @@ exports.ConversationPullRequestsChangedEvent = ConversationPullRequestsChangedEv
13899
14738
  exports.ConversationResponse = ConversationResponse;
13900
14739
  exports.ConversationTitleChangedEvent = ConversationTitleChangedEvent;
13901
14740
  exports.CostEventRecordedEvent = CostEventRecordedEvent;
14741
+ exports.DEFAULT_EFFORT = DEFAULT_EFFORT;
13902
14742
  exports.DEFAULT_MAX_MEMORY_OBSERVATIONS_PER_ISSUE = DEFAULT_MAX_MEMORY_OBSERVATIONS_PER_ISSUE;
13903
14743
  exports.DEFAULT_MAX_TURN_DIFF_SUMMARIES_PER_AGENT = DEFAULT_MAX_TURN_DIFF_SUMMARIES_PER_AGENT;
13904
14744
  exports.DashboardLifecycleCompletedEvent = DashboardLifecycleCompletedEvent;
@@ -13917,12 +14757,15 @@ exports.DirectoryEntrySource = DirectoryEntrySource;
13917
14757
  exports.DirectoryEntryState = DirectoryEntryState;
13918
14758
  exports.DirectoryPause = DirectoryPause;
13919
14759
  exports.DirectoryPauseBy = DirectoryPauseBy;
14760
+ exports.DirectoryProviderError = DirectoryProviderError;
13920
14761
  exports.DirectoryScope = DirectoryScope;
13921
14762
  exports.DirectoryTranscriptRef = DirectoryTranscriptRef;
13922
14763
  exports.DiscoveredSessionSnapshot = DiscoveredSessionSnapshot;
13923
14764
  exports.DomainEvent = DomainEvent;
13924
14765
  exports.EDITORS = EDITORS;
14766
+ exports.EFFORT_LEVELS = EFFORT_LEVELS;
13925
14767
  exports.EditorIdSchema = EditorIdSchema;
14768
+ exports.EffortLevelSchema = EffortLevelSchema;
13926
14769
  exports.EmbedProgressEvent = EmbedProgressEvent;
13927
14770
  exports.EmbedProgressSnapshot = EmbedProgressSnapshot;
13928
14771
  exports.EmbedSessionsRpc = EmbedSessionsRpc;
@@ -13938,6 +14781,7 @@ exports.FeatureRegistryEntry = FeatureRegistryEntry;
13938
14781
  exports.FeatureRegistryStatus = FeatureRegistryStatus;
13939
14782
  exports.FlywheelAgent = FlywheelAgent;
13940
14783
  exports.FlywheelAgentStatus = FlywheelAgentStatus;
14784
+ exports.FlywheelAgentSummary = FlywheelAgentSummary;
13941
14785
  exports.FlywheelBugRateCriterion = FlywheelBugRateCriterion;
13942
14786
  exports.FlywheelConversationSummary = FlywheelConversationSummary;
13943
14787
  exports.FlywheelDerivedStatus = FlywheelDerivedStatus;
@@ -13974,6 +14818,9 @@ exports.FlywheelSuggestion = FlywheelSuggestion;
13974
14818
  exports.FlywheelSuggestionAction = FlywheelSuggestionAction;
13975
14819
  exports.FlywheelSuggestionPriority = FlywheelSuggestionPriority;
13976
14820
  exports.FlywheelSystemStatus = FlywheelSystemStatus;
14821
+ exports.GITHUB_QUOTA_BUCKETS = GITHUB_QUOTA_BUCKETS;
14822
+ exports.GITHUB_QUOTA_CALLERS = GITHUB_QUOTA_CALLERS;
14823
+ exports.GITHUB_QUOTA_POOLS = GITHUB_QUOTA_POOLS;
13977
14824
  exports.GetAvailableEditorsRpc = GetAvailableEditorsRpc;
13978
14825
  exports.GetConversationCostByWorkspaceRpc = GetConversationCostByWorkspaceRpc;
13979
14826
  exports.GetConversationCostRpc = GetConversationCostRpc;
@@ -13981,6 +14828,16 @@ exports.GetConversationStatsRpc = GetConversationStatsRpc;
13981
14828
  exports.GetDiscoveredSessionRpc = GetDiscoveredSessionRpc;
13982
14829
  exports.GetSessionsFeedFacetsRpc = GetSessionsFeedFacetsRpc;
13983
14830
  exports.GetSnapshotRpc = GetSnapshotRpc;
14831
+ exports.GitHubQuotaBucket = GitHubQuotaBucket;
14832
+ exports.GitHubQuotaCaller = GitHubQuotaCaller;
14833
+ exports.GitHubQuotaCallerUsage = GitHubQuotaCallerUsage;
14834
+ exports.GitHubQuotaChangedEvent = GitHubQuotaChangedEvent;
14835
+ exports.GitHubQuotaPause = GitHubQuotaPause;
14836
+ exports.GitHubQuotaPool = GitHubQuotaPool;
14837
+ exports.GitHubQuotaSample = GitHubQuotaSample;
14838
+ exports.GitHubQuotaSnapshot = GitHubQuotaSnapshot;
14839
+ exports.GitHubQuotaUsage = GitHubQuotaUsage;
14840
+ exports.GitHubRateLimitKind = GitHubRateLimitKind;
13984
14841
  exports.GlobalContextLayerRecord = GlobalContextLayerRecord;
13985
14842
  exports.GlobalContextLayerTarget = GlobalContextLayerTarget;
13986
14843
  exports.HOOK_INVENTORY = HOOK_INVENTORY;
@@ -14006,6 +14863,7 @@ exports.IssuesSnapshotEvent = IssuesSnapshotEvent;
14006
14863
  exports.IssuesUpdatedEvent = IssuesUpdatedEvent;
14007
14864
  exports.KIMI_CODE_BEHAVIOR = KIMI_CODE_BEHAVIOR;
14008
14865
  exports.KNOWN_HARNESSES = KNOWN_HARNESSES;
14866
+ exports.LANE_STARTING_GRACE_MS = LANE_STARTING_GRACE_MS;
14009
14867
  exports.LegacySystemHealthSummary = LegacySystemHealthSummary;
14010
14868
  exports.LegacyWebhookRelaySummary = LegacyWebhookRelaySummary;
14011
14869
  exports.LinearMcpAuthCallbackRelayedEvent = LinearMcpAuthCallbackRelayedEvent;
@@ -14034,6 +14892,7 @@ exports.MemoryTokenUsage = MemoryTokenUsage;
14034
14892
  exports.MergeReadyEvent = MergeReadyEvent;
14035
14893
  exports.ModelOrigin = ModelOrigin;
14036
14894
  exports.ModelOriginEntry = ModelOriginEntry;
14895
+ exports.NON_ESSENTIAL_GITHUB_CALLERS = NON_ESSENTIAL_GITHUB_CALLERS;
14037
14896
  exports.OHMYPI_BEHAVIOR = OHMYPI_BEHAVIOR;
14038
14897
  exports.OPENCODE_BEHAVIOR = OPENCODE_BEHAVIOR;
14039
14898
  exports.OVERDECK_AGENT_PROTOCOL_VERSION = OVERDECK_AGENT_PROTOCOL_VERSION;
@@ -14048,6 +14907,7 @@ exports.OrderBookPosture = OrderBookPosture;
14048
14907
  exports.OrderBookSettings = OrderBookSettings;
14049
14908
  exports.OrderBookStatus = OrderBookStatus;
14050
14909
  exports.PIPELINE_MEMBERSHIP_LOADING_CODE = PIPELINE_MEMBERSHIP_LOADING_CODE;
14910
+ exports.PRIME_AGENT_BEHAVIOR = PRIME_AGENT_BEHAVIOR;
14051
14911
  exports.PanRpcError = PanRpcError;
14052
14912
  exports.PanRpcGroup = PanRpcGroup;
14053
14913
  exports.PendingTurn = PendingTurn;
@@ -14117,6 +14977,7 @@ exports.ReviewVerdictRestoreBlockedEvent = ReviewVerdictRestoreBlockedEvent;
14117
14977
  exports.ReviewerRoundMetadata = ReviewerRoundMetadata;
14118
14978
  exports.ReviewerRoundSummary = ReviewerRoundSummary;
14119
14979
  exports.Role = Role;
14980
+ exports.SINGLETON_AGENT_IDS = SINGLETON_AGENT_IDS;
14120
14981
  exports.ScanCompleteEvent = ScanCompleteEvent;
14121
14982
  exports.ScanConversationsRpc = ScanConversationsRpc;
14122
14983
  exports.ScanProgressEvent = ScanProgressEvent;
@@ -14143,6 +15004,7 @@ exports.SpecialistLifecycle = SpecialistLifecycle;
14143
15004
  exports.SpecialistStartedEvent = SpecialistStartedEvent;
14144
15005
  exports.StartAgentRpc = StartAgentRpc;
14145
15006
  exports.StartPlanningRpc = StartPlanningRpc;
15007
+ exports.SubagentHumanInput = SubagentHumanInput;
14146
15008
  exports.SubagentSummary = SubagentSummary;
14147
15009
  exports.SubscribeAgentOutputRpc = SubscribeAgentOutputRpc;
14148
15010
  exports.SubscribeConversationMessagesRpc = SubscribeConversationMessagesRpc;
@@ -14195,8 +15057,11 @@ exports.WriteFileAtPathRpc = WriteFileAtPathRpc;
14195
15057
  exports.applyEvent = applyEvent;
14196
15058
  exports.applyEvents = applyEvents;
14197
15059
  exports.applyIssueDelta = applyIssueDelta;
15060
+ exports.bucketQuotaPoints = bucketQuotaPoints;
15061
+ exports.bucketQuotaRemaining = bucketQuotaRemaining;
14198
15062
  exports.canonicalPullRequestUrl = canonicalPullRequestUrl;
14199
15063
  exports.companionTerminalKindFor = companionTerminalKindFor;
15064
+ exports.compareEffort = compareEffort;
14200
15065
  exports.compareIssueIds = compareIssueIds;
14201
15066
  exports.createIssueDelta = createIssueDelta;
14202
15067
  exports.decodeFlywheelDerivedStatus = decodeFlywheelDerivedStatus;
@@ -14208,16 +15073,21 @@ exports.getHarnessBehavior = getHarnessBehavior;
14208
15073
  exports.getMaxMemoryObservationsPerIssue = getMaxMemoryObservationsPerIssue;
14209
15074
  exports.getMaxTurnDiffSummariesPerAgent = getMaxTurnDiffSummariesPerAgent;
14210
15075
  exports.getRuntimeBehavior = getRuntimeBehavior;
15076
+ exports.indexPanesByAgentKey = indexPanesByAgentKey;
14211
15077
  exports.isAgentRole = isAgentRole;
14212
15078
  exports.isAgentSessionName = isAgentSessionName;
14213
15079
  exports.isChannelReplyKind = isChannelReplyKind;
14214
15080
  exports.isConfiguredPullRequestRepo = isConfiguredPullRequestRepo;
15081
+ exports.isEffortLevel = isEffortLevel;
14215
15082
  exports.isIssueAttention = isIssueAttention;
14216
15083
  exports.isIssueState = isIssueState;
15084
+ exports.isSingletonConversation = isSingletonConversation;
14217
15085
  exports.isTerminalBackendName = isTerminalBackendName;
14218
15086
  exports.isTerminalTurnDiffSummaryStatus = isTerminalTurnDiffSummaryStatus;
15087
+ exports.laneActivityOf = laneActivityOf;
14219
15088
  exports.normalizeChannelReplyPayload = normalizeChannelReplyPayload;
14220
15089
  exports.omitTurnDiffSummariesForAgent = omitTurnDiffSummariesForAgent;
15090
+ exports.paneAgentKey = paneAgentKey;
14221
15091
  exports.parsePullRequestRef = parsePullRequestRef;
14222
15092
  exports.projectLegacySystemHealthSummary = projectLegacySystemHealthSummary;
14223
15093
  exports.repoFromRemoteUrl = repoFromRemoteUrl;