@overdeck/contracts 0.50.4 → 0.60.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
@@ -26,6 +26,143 @@ let effect_unstable_rpc_Rpc = require("effect/unstable/rpc/Rpc");
26
26
  effect_unstable_rpc_Rpc = __toESM(effect_unstable_rpc_Rpc, 1);
27
27
  let effect_unstable_rpc_RpcGroup = require("effect/unstable/rpc/RpcGroup");
28
28
  effect_unstable_rpc_RpcGroup = __toESM(effect_unstable_rpc_RpcGroup, 1);
29
+ //#region src/backend-pane.ts
30
+ const BackendPane = effect.Schema.Struct({
31
+ /** Stable pane identity: the backend-native pane handle. */
32
+ id: effect.Schema.String,
33
+ /** Issue the pane belongs to; absent for operator conversations. */
34
+ issue: effect.Schema.optional(effect.Schema.String),
35
+ role: effect.Schema.Literals([
36
+ "work",
37
+ "worker",
38
+ "review",
39
+ "test",
40
+ "uat",
41
+ "strike",
42
+ "plan"
43
+ ]),
44
+ harness: effect.Schema.String,
45
+ model: effect.Schema.String,
46
+ state: effect.Schema.Literals([
47
+ "idle",
48
+ "working",
49
+ "blocked",
50
+ "done",
51
+ "exited",
52
+ "unknown"
53
+ ]),
54
+ /** Epoch millis the pane entered `state`; drives the `stuck` attention. */
55
+ stateSince: effect.Schema.optional(effect.Schema.Number),
56
+ /** Handle the terminal WebSocket attaches to. */
57
+ terminalId: effect.Schema.optional(effect.Schema.String),
58
+ /** Working directory of the pane (the issue workspace path). */
59
+ workspace: effect.Schema.optional(effect.Schema.String)
60
+ });
61
+ //#endregion
62
+ //#region src/derived-issue-state.ts
63
+ /**
64
+ * The nine pipeline states of the FR-6 table. They are mutually exclusive and
65
+ * resolved in this precedence (highest first), because the underlying facts
66
+ * overlap:
67
+ *
68
+ * closed > merged > ready > changes-requested > in-review > working >
69
+ * parked > planned > backlog
70
+ */
71
+ const IssueState = effect.Schema.Literals([
72
+ "backlog",
73
+ "parked",
74
+ "planned",
75
+ "working",
76
+ "in-review",
77
+ "changes-requested",
78
+ "ready",
79
+ "merged",
80
+ "closed"
81
+ ]);
82
+ /** Something the operator has to look at. Orthogonal to `IssueState`. */
83
+ const IssueAttention = effect.Schema.Literals([
84
+ "needs-you",
85
+ "stuck",
86
+ "api-error"
87
+ ]);
88
+ /** Latest review decision on the PR, as the forge reports it. */
89
+ const PrReviewState = effect.Schema.Literals([
90
+ "approved",
91
+ "changes-requested",
92
+ "review-requested",
93
+ "commented",
94
+ "none"
95
+ ]);
96
+ /** Aggregate check-run conclusion for the PR head. */
97
+ const PrChecksState = effect.Schema.Literals([
98
+ "green",
99
+ "red",
100
+ "pending"
101
+ ]);
102
+ /** The pull request (or merge request) backing an issue. */
103
+ const DerivedPrState = effect.Schema.Struct({
104
+ url: effect.Schema.String,
105
+ number: effect.Schema.Number,
106
+ reviewState: PrReviewState,
107
+ checks: PrChecksState,
108
+ /** Forge mergeability. `null` when the forge has not computed it yet. */
109
+ mergeable: effect.Schema.NullOr(effect.Schema.Boolean)
110
+ });
111
+ /** The issue's feature branch as git reports it. */
112
+ const DerivedBranchState = effect.Schema.Struct({
113
+ name: effect.Schema.String,
114
+ aheadOfMain: effect.Schema.Number,
115
+ pushed: effect.Schema.Boolean
116
+ });
117
+ /** Everything the dashboard needs to render an issue's pipeline position. */
118
+ const DerivedIssueState = effect.Schema.Struct({
119
+ issueId: effect.Schema.String,
120
+ state: IssueState,
121
+ attention: effect.Schema.optional(IssueAttention),
122
+ pr: effect.Schema.optional(DerivedPrState),
123
+ branch: effect.Schema.optional(DerivedBranchState),
124
+ /**
125
+ * No tracker answered for this issue, so `closed` — the top of the
126
+ * precedence — could not be ruled in or out. Present only in that case; an
127
+ * unresolved tracker read is never reported as an open issue.
128
+ */
129
+ trackerUnknown: effect.Schema.optional(effect.Schema.Literal(true))
130
+ });
131
+ const ISSUE_STATES = [
132
+ "backlog",
133
+ "parked",
134
+ "planned",
135
+ "working",
136
+ "in-review",
137
+ "changes-requested",
138
+ "ready",
139
+ "merged",
140
+ "closed"
141
+ ];
142
+ /** Highest precedence first — the order `deriveIssueState` resolves in. */
143
+ const ISSUE_STATE_PRECEDENCE = [
144
+ "closed",
145
+ "merged",
146
+ "ready",
147
+ "changes-requested",
148
+ "in-review",
149
+ "working",
150
+ "parked",
151
+ "planned",
152
+ "backlog"
153
+ ];
154
+ const ISSUE_ATTENTIONS = [
155
+ "needs-you",
156
+ "stuck",
157
+ "api-error"
158
+ ];
159
+ function isIssueState(value) {
160
+ return typeof value === "string" && ISSUE_STATES.includes(value);
161
+ }
162
+ function isIssueAttention(value) {
163
+ return typeof value === "string" && ISSUE_ATTENTIONS.includes(value);
164
+ }
165
+ //#endregion
29
166
  //#region src/types.ts
30
167
  const IssueId = effect.Schema.String;
31
168
  const MEMBERSHIP_UNAVAILABLE_REASONS = [
@@ -66,52 +203,6 @@ const AgentResolution = effect.Schema.Literals([
66
203
  "abandoned",
67
204
  "api_error"
68
205
  ]);
69
- const ReviewStatusValue = effect.Schema.Literals([
70
- "pending",
71
- "reviewing",
72
- "passed",
73
- "failed",
74
- "blocked",
75
- "skipped"
76
- ]);
77
- const TestStatusValue = effect.Schema.Literals([
78
- "pending",
79
- "testing",
80
- "passed",
81
- "failed",
82
- "skipped",
83
- "dispatch_failed"
84
- ]);
85
- const UatStatusValue = effect.Schema.Literals([
86
- "pending",
87
- "testing",
88
- "passed",
89
- "failed"
90
- ]);
91
- const MergeStatusValue = effect.Schema.Literals([
92
- "pending",
93
- "queued",
94
- "merging",
95
- "verifying",
96
- "merged",
97
- "failed"
98
- ]);
99
- const ReleaseStatusValue = effect.Schema.Literals([
100
- "pending",
101
- "releasing",
102
- "passed",
103
- "failed",
104
- "partial",
105
- "rolled_back",
106
- "skipped"
107
- ]);
108
- const VerificationStatusValue = effect.Schema.Literals([
109
- "pending",
110
- "running",
111
- "passed",
112
- "failed",
113
- "skipped"
114
- ]);
115
206
  const KNOWN_HARNESSES = new Set([
116
207
  "claude-code",
117
208
  "ohmypi",
@@ -301,87 +392,6 @@ const AgentSnapshot = effect.Schema.Struct({
301
392
  runtimeSnapshotSequence: effect.Schema.optional(SequenceNumber)
302
393
  });
303
394
  /** PAN-3151: A recorded cycle in the review convergence tracking series */
304
- const ReviewCycleEntry = effect.Schema.Struct({
305
- cycle: effect.Schema.Number,
306
- runId: effect.Schema.String,
307
- atCommit: effect.Schema.optional(effect.Schema.String),
308
- blockingCount: effect.Schema.Number,
309
- recordedAt: effect.Schema.String
310
- });
311
- const ReviewStatusSnapshot = effect.Schema.Struct({
312
- issueId: IssueId,
313
- reviewStatus: effect.Schema.optional(ReviewStatusValue),
314
- testStatus: effect.Schema.optional(TestStatusValue),
315
- uatStatus: effect.Schema.optional(UatStatusValue),
316
- uatNotes: effect.Schema.optional(effect.Schema.String),
317
- mergeStatus: effect.Schema.optional(MergeStatusValue),
318
- releaseStatus: effect.Schema.optional(ReleaseStatusValue),
319
- releaseNotes: effect.Schema.optional(effect.Schema.String),
320
- verificationStatus: effect.Schema.optional(VerificationStatusValue),
321
- verificationNotes: effect.Schema.optional(effect.Schema.String),
322
- verificationCycleCount: effect.Schema.optional(effect.Schema.Number),
323
- readyForMerge: effect.Schema.optional(effect.Schema.Boolean),
324
- updatedAt: effect.Schema.optional(effect.Schema.String),
325
- prUrl: effect.Schema.optional(effect.Schema.String),
326
- /** Persistent stuck flag — set by divergence guard, cleared by /unstick */
327
- stuck: effect.Schema.optional(effect.Schema.Boolean),
328
- stuckReason: effect.Schema.optional(effect.Schema.String),
329
- stuckAt: effect.Schema.optional(effect.Schema.String),
330
- stuckDetails: effect.Schema.optional(effect.Schema.String),
331
- /** PAN-3151: review cycle history for convergence detection */
332
- reviewCycleHistory: effect.Schema.optional(effect.Schema.Array(ReviewCycleEntry)),
333
- /** Commit SHA at which review passed; deacon uses this to detect new pushes after review */
334
- reviewedAtCommit: effect.Schema.optional(effect.Schema.String),
335
- /** Commit SHA at which the pre-review verification gate last passed */
336
- lastVerifiedCommit: effect.Schema.optional(effect.Schema.String),
337
- /** Current merge pipeline step (granular visibility for the merge step tracker) */
338
- mergeStep: effect.Schema.optional(effect.Schema.String),
339
- /** PAN-699: timestamp when review agents were dispatched */
340
- reviewSpawnedAt: effect.Schema.optional(effect.Schema.String),
341
- /** PAN-699: number of test-agent dispatch retries */
342
- testRetryCount: effect.Schema.optional(effect.Schema.Number),
343
- /** PAN-794: parallel-review re-dispatch retry counter (current recovery cycle) */
344
- reviewRetryCount: effect.Schema.optional(effect.Schema.Number),
345
- /** PAN-796: review auto-requeue count (circuit breaker threshold) */
346
- autoRequeueCount: effect.Schema.optional(effect.Schema.Number),
347
- /** PAN-794: ISO timestamp marking the start of the current recovery cycle */
348
- recoveryStartedAt: effect.Schema.optional(effect.Schema.String),
349
- /** Human-requested patrol opt-out — when true, Deacon ignores this issue. */
350
- deaconIgnored: effect.Schema.optional(effect.Schema.Boolean),
351
- deaconIgnoredAt: effect.Schema.optional(effect.Schema.String),
352
- deaconIgnoredReason: effect.Schema.optional(effect.Schema.String),
353
- /** PAN-1691: per-issue auto-merge routing key. undefined = project default, true = auto-merge (fast lane), false = hold for UAT. */
354
- autoMerge: effect.Schema.optional(effect.Schema.Boolean),
355
- /** Active review orchestrator tmux session name (e.g. agent-pan-540-review). */
356
- reviewCoordinatorSessionName: effect.Schema.optional(effect.Schema.String),
357
- /** Active review sub-role tmux session names (e.g. agent-pan-540-review-correctness). Discovered at emission time. */
358
- reviewSessionNames: effect.Schema.optional(effect.Schema.Array(effect.Schema.String)),
359
- /** Per-role review completion status (keyed by role: 'correctness' | 'security' | ...) */
360
- reviewSubStatuses: effect.Schema.optional(effect.Schema.Record(effect.Schema.String, effect.Schema.Literals(["running", "done"]))),
361
- /** PAN-905: queue position in the merge queue */
362
- queuePosition: effect.Schema.optional(effect.Schema.Number),
363
- /** PAN-905: currently active specialist (e.g. 'merge-agent') */
364
- activeSpecialist: effect.Schema.optional(effect.Schema.String),
365
- /** PAN-905: number of merge retries attempted */
366
- mergeRetryCount: effect.Schema.optional(effect.Schema.Number),
367
- /** PAN-905: free-form notes about the merge attempt */
368
- mergeNotes: effect.Schema.optional(effect.Schema.String),
369
- /** Merge blocker reasons surfaced to operators. */
370
- blockerReasons: effect.Schema.optional(effect.Schema.Array(effect.Schema.Struct({
371
- type: effect.Schema.Literals([
372
- "failing_checks",
373
- "merge_conflict",
374
- "unresolved_conversations",
375
- "changes_requested",
376
- "draft_pr",
377
- "not_mergeable",
378
- "unmerged_sibling_repo"
379
- ]),
380
- summary: effect.Schema.String,
381
- details: effect.Schema.optional(effect.Schema.String),
382
- detectedAt: effect.Schema.String
383
- })))
384
- });
385
395
  const TurnDiffFileChange = effect.Schema.Struct({
386
396
  path: effect.Schema.String,
387
397
  kind: effect.Schema.optional(effect.Schema.String),
@@ -507,7 +517,10 @@ const DashboardSnapshot = effect.Schema.Struct({
507
517
  sequence: SequenceNumber,
508
518
  agents: effect.Schema.Array(AgentSnapshot),
509
519
  specialists: effect.Schema.Array(effect.Schema.Unknown),
510
- reviewStatuses: effect.Schema.Array(ReviewStatusSnapshot),
520
+ /** PAN-3917 FR-6: the derived pipeline state of every known issue. */
521
+ derivedIssueStates: effect.Schema.Array(DerivedIssueState),
522
+ /** PAN-3917 FR-12: every live agent pane the terminal backend reports. */
523
+ backendPanes: effect.Schema.Array(BackendPane),
511
524
  issues: effect.Schema.Array(effect.Schema.Unknown),
512
525
  recentActivity: effect.Schema.optional(effect.Schema.Array(effect.Schema.Unknown)),
513
526
  resources: effect.Schema.optional(effect.Schema.Unknown),
@@ -522,13 +535,6 @@ const DashboardSnapshot = effect.Schema.Struct({
522
535
  restartGate: effect.Schema.optional(RestartGateSnapshot),
523
536
  timestamp: effect.Schema.String
524
537
  });
525
- const WorkspaceDetail = effect.Schema.Struct({
526
- workspace: effect.Schema.Unknown,
527
- reviewStatus: effect.Schema.Unknown,
528
- planning: effect.Schema.Unknown,
529
- costs: effect.Schema.Unknown,
530
- agentOutput: effect.Schema.Array(effect.Schema.String)
531
- });
532
538
  const ResourceStats = effect.Schema.Struct({ containers: effect.Schema.Array(effect.Schema.Struct({
533
539
  name: effect.Schema.String,
534
540
  cpu: effect.Schema.optional(effect.Schema.String),
@@ -613,14 +619,6 @@ const SessionNode = effect.Schema.Struct({
613
619
  "tmux",
614
620
  "supervisor"
615
621
  ])),
616
- paused: effect.Schema.optional(effect.Schema.Boolean),
617
- pausedReason: effect.Schema.optional(effect.Schema.String),
618
- pausedAt: effect.Schema.optional(effect.Schema.String),
619
- troubled: effect.Schema.optional(effect.Schema.Boolean),
620
- troubledAt: effect.Schema.optional(effect.Schema.String),
621
- troubledReason: effect.Schema.optional(effect.Schema.String),
622
- consecutiveFailures: effect.Schema.optional(effect.Schema.Number),
623
- queuedMailCount: effect.Schema.optional(effect.Schema.Number),
624
622
  modelOrigin: effect.Schema.optional(ModelOrigin)
625
623
  });
626
624
  const FeatureNode = effect.Schema.Struct({
@@ -1760,16 +1758,32 @@ const PlanItemsUnblockedEvent = effect.Schema.Struct({
1760
1758
  items: effect.Schema.Array(effect.Schema.String)
1761
1759
  })
1762
1760
  });
1763
- /** Replaces socket.io `pipeline:status` */
1764
- const PipelineStatusChangedEvent = effect.Schema.Struct({
1765
- type: effect.Schema.Literal("pipeline.status_changed"),
1761
+ /**
1762
+ * PAN-3917 FR-6 — an issue's derived pipeline state changed.
1763
+ *
1764
+ * Emitted with `emitOnly`: derived state is recomputed from the tracker, the
1765
+ * forge and the terminal backend on every boot, so persisting it would be
1766
+ * storing a status Overdeck can derive.
1767
+ */
1768
+ const IssueStateChangedEvent = effect.Schema.Struct({
1769
+ type: effect.Schema.Literal("issue_state.changed"),
1766
1770
  sequence: SequenceNumber,
1767
1771
  timestamp: effect.Schema.String,
1768
- payload: effect.Schema.Struct({
1769
- issueId: IssueId,
1770
- workspaceId: effect.Schema.optional(effect.Schema.String),
1771
- status: ReviewStatusSnapshot
1772
- })
1772
+ payload: effect.Schema.Struct({ issueState: DerivedIssueState })
1773
+ });
1774
+ /** PAN-3917 FR-12 — a live agent pane appeared or changed. `emitOnly`. */
1775
+ const BackendPaneChangedEvent = effect.Schema.Struct({
1776
+ type: effect.Schema.Literal("backend_pane.changed"),
1777
+ sequence: SequenceNumber,
1778
+ timestamp: effect.Schema.String,
1779
+ payload: effect.Schema.Struct({ pane: BackendPane })
1780
+ });
1781
+ /** PAN-3917 FR-12 — a pane left the backend inventory. `emitOnly`. */
1782
+ const BackendPaneRemovedEvent = effect.Schema.Struct({
1783
+ type: effect.Schema.Literal("backend_pane.removed"),
1784
+ sequence: SequenceNumber,
1785
+ timestamp: effect.Schema.String,
1786
+ payload: effect.Schema.Struct({ paneId: effect.Schema.String })
1773
1787
  });
1774
1788
  /** Replaces socket.io `merge:ready` */
1775
1789
  const MergeReadyEvent = effect.Schema.Struct({
@@ -1781,17 +1795,6 @@ const MergeReadyEvent = effect.Schema.Struct({
1781
1795
  workspaceId: effect.Schema.optional(effect.Schema.String)
1782
1796
  })
1783
1797
  });
1784
- /** New — review status changed */
1785
- const ReviewStatusChangedEvent = effect.Schema.Struct({
1786
- type: effect.Schema.Literal("review.status_changed"),
1787
- sequence: SequenceNumber,
1788
- timestamp: effect.Schema.String,
1789
- payload: effect.Schema.Struct({
1790
- issueId: IssueId,
1791
- workspaceId: effect.Schema.optional(effect.Schema.String),
1792
- status: ReviewStatusSnapshot
1793
- })
1794
- });
1795
1798
  /** New — review specialist dispatched */
1796
1799
  const PipelineReviewStartedEvent = effect.Schema.Struct({
1797
1800
  type: effect.Schema.Literal("pipeline.review-started"),
@@ -2630,9 +2633,10 @@ const DomainEvent = effect.Schema.Union([
2630
2633
  PlanItemStatusChangedEvent,
2631
2634
  PlanSubitemStatusChangedEvent,
2632
2635
  PlanItemsUnblockedEvent,
2633
- PipelineStatusChangedEvent,
2636
+ IssueStateChangedEvent,
2637
+ BackendPaneChangedEvent,
2638
+ BackendPaneRemovedEvent,
2634
2639
  MergeReadyEvent,
2635
- ReviewStatusChangedEvent,
2636
2640
  PipelineReviewStartedEvent,
2637
2641
  PipelineReviewCompletedEvent,
2638
2642
  PipelineTestStartedEvent,
@@ -2862,248 +2866,66 @@ const OpenInEditorInput = effect.Schema.Struct({
2862
2866
  editor: EditorIdSchema
2863
2867
  });
2864
2868
  //#endregion
2865
- //#region src/flywheel.ts
2866
- const FlywheelRunId = effect.Schema.String.check(effect.Schema.isPattern(/^RUN-\d+$/));
2867
- const FlywheelHttpUrl = effect.Schema.String.check(effect.Schema.isPattern(/^https?:\/\/\S+$/i));
2868
- const FlywheelHarness = effect.Schema.Literals([
2869
- "claude-code",
2870
- "pi",
2871
- "ohmypi",
2872
- "codex",
2873
- "acp",
2874
- "kimi-code",
2875
- "opencode",
2876
- "muse"
2877
- ]);
2878
- const FlywheelEffort = effect.Schema.Literals([
2879
- "low",
2880
- "medium",
2881
- "high",
2882
- "xhigh",
2883
- "max"
2884
- ]);
2885
- const FlywheelOrchestrator = effect.Schema.Struct({
2886
- harness: FlywheelHarness,
2887
- model: effect.Schema.String,
2888
- effort: FlywheelEffort,
2889
- ctxPercent: effect.Schema.Number
2869
+ //#region src/rpc.ts
2870
+ const WS_METHODS = {
2871
+ scanConversations: "pan.scanConversations",
2872
+ searchConversations: "pan.searchConversations",
2873
+ listDiscoveredSessions: "pan.listDiscoveredSessions",
2874
+ listSessionsFeed: "pan.listSessionsFeed",
2875
+ getSessionsFeedFacets: "pan.getSessionsFeedFacets",
2876
+ getDiscoveredSession: "pan.getDiscoveredSession",
2877
+ enrichSessions: "pan.enrichSessions",
2878
+ embedSessions: "pan.embedSessions",
2879
+ getConversationCost: "pan.getConversationCost",
2880
+ getConversationCostByWorkspace: "pan.getConversationCostByWorkspace",
2881
+ getConversationStats: "pan.getConversationStats",
2882
+ subscribeDomainEvents: "pan.subscribeDomainEvents",
2883
+ subscribeIssueEvents: "pan.subscribeIssueEvents",
2884
+ subscribeTerminal: "pan.subscribeTerminal",
2885
+ subscribeAgentOutput: "pan.subscribeAgentOutput",
2886
+ subscribeConversationMessages: "pan.subscribeConversationMessages",
2887
+ subscribeProjectSessionTree: "pan.subscribeProjectSessionTree",
2888
+ getSnapshot: "pan.getSnapshot",
2889
+ replayEvents: "pan.replayEvents",
2890
+ readWorkspaceFile: "pan.readWorkspaceFile",
2891
+ readFileAtPath: "pan.readFileAtPath",
2892
+ writeFileAtPath: "pan.writeFileAtPath",
2893
+ resolveFilePathExists: "pan.resolveFilePathExists",
2894
+ terminalOpen: "pan.terminalOpen",
2895
+ terminalWrite: "pan.terminalWrite",
2896
+ terminalResize: "pan.terminalResize",
2897
+ terminalClose: "pan.terminalClose",
2898
+ startPlanning: "pan.startPlanning",
2899
+ startAgent: "pan.startAgent",
2900
+ deepWipe: "pan.deepWipe",
2901
+ sendTerminalInput: "pan.sendTerminalInput",
2902
+ resizeTerminal: "pan.resizeTerminal",
2903
+ shellOpenInEditor: "pan.shellOpenInEditor",
2904
+ getAvailableEditors: "pan.getAvailableEditors"
2905
+ };
2906
+ var PanRpcError = class extends effect.Schema.TaggedErrorClass()("PanRpcError", {
2907
+ message: effect.Schema.String,
2908
+ code: effect.Schema.optional(effect.Schema.String)
2909
+ }) {};
2910
+ const TerminalOutput = effect.Schema.Struct({
2911
+ sessionName: effect.Schema.String,
2912
+ data: effect.Schema.String
2890
2913
  });
2891
- const FlywheelScope = effect.Schema.Literals(["pan-only", "all-tracked-projects"]);
2892
- const FlywheelHeadline = effect.Schema.Struct({
2893
- bugsFixed: effect.Schema.Number,
2894
- swarmItemsMerged: effect.Schema.Number,
2895
- swarmItemsTotal: effect.Schema.Number,
2896
- prsMerged: effect.Schema.Number,
2897
- awaitingUat: effect.Schema.Number
2914
+ const AgentOutput = effect.Schema.Struct({
2915
+ agentId: effect.Schema.String,
2916
+ line: effect.Schema.String
2898
2917
  });
2899
- /**
2900
- * Pipeline verbs — display state only. They no longer gate the merge queue.
2901
- *
2902
- * History worth keeping (PAN-1736 / PAN-1759): the merge queue used to be
2903
- * derived by filtering these verbs, treating only "shipping" or "merging" as
2904
- * "at the merge gate". Any other verb on an issue that was ready_for_merge in
2905
- * the review DB silently dropped it from the queue and from UAT batch
2906
- * assembly — RUN-18 shipped an empty queue with five ready issues exactly that
2907
- * way — and the queue existed only while a run was emitting a pipeline at all.
2908
- *
2909
- * PAN-1696 removed that coupling. The ready set is now sourced from the
2910
- * review-status records per project (`listEligibleCandidatesByProject` +
2911
- * `computeMergeQueueFromCandidates` in src/lib/flywheel-merge-order.ts), which
2912
- * needs no flywheel run and cannot be affected by which verb an orchestrator
2913
- * chose to report. Adding a verb here therefore has no merge-queue consequence;
2914
- * it only changes what the dashboard displays.
2915
- */
2916
- const FlywheelPipelineVerb = effect.Schema.Literals([
2917
- "planning",
2918
- "working",
2919
- "reviewing",
2920
- "testing",
2921
- "shipping",
2922
- "merging",
2923
- "blocked",
2924
- "parked"
2925
- ]);
2926
- const FlywheelPipelineStatus = effect.Schema.Literals([
2927
- "queued",
2928
- "running",
2929
- "blocked",
2930
- "passed",
2931
- "failed",
2932
- "merged",
2933
- "parked"
2934
- ]);
2935
- const FlywheelPipelineItem = effect.Schema.Struct({
2936
- issueId: effect.Schema.String,
2937
- title: effect.Schema.String,
2938
- verb: FlywheelPipelineVerb,
2939
- status: FlywheelPipelineStatus,
2940
- progressPercent: effect.Schema.optional(effect.Schema.Number),
2941
- agentId: effect.Schema.optional(effect.Schema.String),
2942
- pr: effect.Schema.optional(effect.Schema.Number),
2943
- mergeOrder: effect.Schema.optional(effect.Schema.Number),
2944
- conflictsWith: effect.Schema.optional(effect.Schema.Array(effect.Schema.String))
2945
- });
2946
- const FlywheelSubstrateBugStatus = effect.Schema.Literals([
2947
- "filed",
2948
- "fixed",
2949
- "workaround"
2950
- ]);
2951
- const FlywheelSubstrateBug = effect.Schema.Struct({
2952
- issueId: effect.Schema.String,
2953
- title: effect.Schema.String,
2954
- status: FlywheelSubstrateBugStatus,
2955
- commitSha: effect.Schema.optional(effect.Schema.String),
2956
- url: effect.Schema.optional(FlywheelHttpUrl)
2957
- });
2958
- const FlywheelAgentStatus = effect.Schema.Literals([
2959
- "starting",
2960
- "running",
2961
- "waiting",
2962
- "idle",
2963
- "stopped",
2964
- "error"
2965
- ]);
2966
- const FlywheelAgent = effect.Schema.Struct({
2967
- id: effect.Schema.String,
2968
- label: effect.Schema.String,
2969
- status: FlywheelAgentStatus,
2970
- issueId: effect.Schema.optional(effect.Schema.String),
2971
- role: effect.Schema.optional(effect.Schema.String),
2972
- model: effect.Schema.optional(effect.Schema.String),
2973
- ctxPercent: effect.Schema.optional(effect.Schema.Number),
2974
- currentAction: effect.Schema.optional(effect.Schema.String)
2975
- });
2976
- const FlywheelParkedItem = effect.Schema.Struct({
2977
- issueId: effect.Schema.String,
2978
- title: effect.Schema.String,
2979
- reason: effect.Schema.String,
2980
- parkedAt: effect.Schema.optional(effect.Schema.String)
2981
- });
2982
- const FlywheelSuggestionAction = effect.Schema.Literals([
2983
- "start",
2984
- "resume",
2985
- "plan",
2986
- "review",
2987
- "merge",
2988
- "unblock",
2989
- "park",
2990
- "investigate",
2991
- "wait"
2992
- ]);
2993
- const FlywheelSuggestionPriority = effect.Schema.Literals([
2994
- "urgent",
2995
- "high",
2996
- "medium",
2997
- "low"
2998
- ]);
2999
- const FlywheelSuggestion = effect.Schema.Struct({
3000
- action: FlywheelSuggestionAction,
3001
- issueId: effect.Schema.optional(effect.Schema.String),
3002
- rationale: effect.Schema.String,
3003
- priority: FlywheelSuggestionPriority,
3004
- filedBy: effect.Schema.optional(effect.Schema.Literals(["agent", "operator"])),
3005
- weight: effect.Schema.optional(effect.Schema.Number),
3006
- weightReason: effect.Schema.optional(effect.Schema.String)
3007
- });
3008
- const FlywheelSystemStatus = effect.Schema.Struct({
3009
- mainHead: effect.Schema.String,
3010
- ramUsedMb: effect.Schema.Number,
3011
- ramTotalMb: effect.Schema.Number,
3012
- swapUsedMb: effect.Schema.Number,
3013
- swapTotalMb: effect.Schema.Number,
3014
- agentsActive: effect.Schema.Number,
3015
- agentsCap: effect.Schema.Number
3016
- });
3017
- const FlywheelOrders = effect.Schema.Struct({
3018
- bookId: effect.Schema.String,
3019
- bookName: effect.Schema.String,
3020
- landed: effect.Schema.Number,
3021
- total: effect.Schema.Number,
3022
- laneAInFlight: effect.Schema.Array(effect.Schema.String),
3023
- laneBInFlight: effect.Schema.optional(effect.Schema.String),
3024
- drained: effect.Schema.Boolean
3025
- });
3026
- const FlywheelStatus = effect.Schema.Struct({
3027
- runId: FlywheelRunId,
3028
- startedAt: effect.Schema.String,
3029
- elapsedMs: effect.Schema.Number,
3030
- orchestrator: FlywheelOrchestrator,
3031
- headline: FlywheelHeadline,
3032
- activePipeline: effect.Schema.Array(FlywheelPipelineItem),
3033
- substrateBugs: effect.Schema.Array(FlywheelSubstrateBug),
3034
- agents: effect.Schema.Array(FlywheelAgent),
3035
- parked: effect.Schema.Array(FlywheelParkedItem),
3036
- suggestions: effect.Schema.Array(FlywheelSuggestion).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed([]))),
3037
- system: FlywheelSystemStatus,
3038
- openQuestions: effect.Schema.Array(effect.Schema.String),
3039
- orders: effect.Schema.optional(FlywheelOrders),
3040
- scope: effect.Schema.optional(FlywheelScope),
3041
- ticks: effect.Schema.Number,
3042
- lastTickAt: effect.Schema.String
3043
- });
3044
- //#endregion
3045
- //#region src/rpc.ts
3046
- const WS_METHODS = {
3047
- scanConversations: "pan.scanConversations",
3048
- searchConversations: "pan.searchConversations",
3049
- listDiscoveredSessions: "pan.listDiscoveredSessions",
3050
- listSessionsFeed: "pan.listSessionsFeed",
3051
- getSessionsFeedFacets: "pan.getSessionsFeedFacets",
3052
- getDiscoveredSession: "pan.getDiscoveredSession",
3053
- enrichSessions: "pan.enrichSessions",
3054
- embedSessions: "pan.embedSessions",
3055
- getConversationCost: "pan.getConversationCost",
3056
- getConversationCostByWorkspace: "pan.getConversationCostByWorkspace",
3057
- getConversationStats: "pan.getConversationStats",
3058
- subscribeDomainEvents: "pan.subscribeDomainEvents",
3059
- subscribeIssueEvents: "pan.subscribeIssueEvents",
3060
- subscribeTerminal: "pan.subscribeTerminal",
3061
- subscribeAgentOutput: "pan.subscribeAgentOutput",
3062
- subscribeConversationMessages: "pan.subscribeConversationMessages",
3063
- subscribeProjectSessionTree: "pan.subscribeProjectSessionTree",
3064
- subscribeFlywheelStatus: "pan.subscribeFlywheelStatus",
3065
- getSnapshot: "pan.getSnapshot",
3066
- replayEvents: "pan.replayEvents",
3067
- getWorkspaceDetail: "pan.getWorkspaceDetail",
3068
- readWorkspaceFile: "pan.readWorkspaceFile",
3069
- readFileAtPath: "pan.readFileAtPath",
3070
- writeFileAtPath: "pan.writeFileAtPath",
3071
- resolveFilePathExists: "pan.resolveFilePathExists",
3072
- terminalOpen: "pan.terminalOpen",
3073
- terminalWrite: "pan.terminalWrite",
3074
- terminalResize: "pan.terminalResize",
3075
- terminalClose: "pan.terminalClose",
3076
- startPlanning: "pan.startPlanning",
3077
- startAgent: "pan.startAgent",
3078
- deepWipe: "pan.deepWipe",
3079
- sendTerminalInput: "pan.sendTerminalInput",
3080
- resizeTerminal: "pan.resizeTerminal",
3081
- shellOpenInEditor: "pan.shellOpenInEditor",
3082
- getAvailableEditors: "pan.getAvailableEditors"
3083
- };
3084
- var PanRpcError = class extends effect.Schema.TaggedErrorClass()("PanRpcError", {
3085
- message: effect.Schema.String,
3086
- code: effect.Schema.optional(effect.Schema.String)
3087
- }) {};
3088
- const TerminalOutput = effect.Schema.Struct({
3089
- sessionName: effect.Schema.String,
3090
- data: effect.Schema.String
3091
- });
3092
- const AgentOutput = effect.Schema.Struct({
3093
- agentId: effect.Schema.String,
3094
- line: effect.Schema.String
3095
- });
3096
- const ProposedPlan = effect.Schema.Struct({
3097
- id: effect.Schema.String,
3098
- plan: effect.Schema.String,
3099
- planFilePath: effect.Schema.optional(effect.Schema.String),
3100
- status: effect.Schema.Literals([
3101
- "pending",
3102
- "approved",
3103
- "rejected"
3104
- ]),
3105
- createdAt: effect.Schema.String,
3106
- resolvedAt: effect.Schema.optional(effect.Schema.String)
2918
+ const ProposedPlan = effect.Schema.Struct({
2919
+ id: effect.Schema.String,
2920
+ plan: effect.Schema.String,
2921
+ planFilePath: effect.Schema.optional(effect.Schema.String),
2922
+ status: effect.Schema.Literals([
2923
+ "pending",
2924
+ "approved",
2925
+ "rejected"
2926
+ ]),
2927
+ createdAt: effect.Schema.String,
2928
+ resolvedAt: effect.Schema.optional(effect.Schema.String)
3107
2929
  });
3108
2930
  const CompactBoundary = effect.Schema.Struct({
3109
2931
  id: effect.Schema.String,
@@ -3305,12 +3127,6 @@ const TerminalCloseRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.terminalClose,
3305
3127
  payload: effect.Schema.Struct({ sessionName: effect.Schema.String }),
3306
3128
  error: PanRpcError
3307
3129
  });
3308
- /** 10. Get batched workspace detail (unary) — replaces 5 separate HTTP calls */
3309
- const GetWorkspaceDetailRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.getWorkspaceDetail, {
3310
- payload: effect.Schema.Struct({ issueId: IssueId }),
3311
- success: WorkspaceDetail,
3312
- error: PanRpcError
3313
- });
3314
3130
  const ReadWorkspaceFileInput = effect.Schema.Struct({
3315
3131
  issueId: IssueId,
3316
3132
  relativePath: effect.Schema.String,
@@ -3457,13 +3273,6 @@ const SubscribeProjectSessionTreeRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.s
3457
3273
  error: PanRpcError,
3458
3274
  stream: true
3459
3275
  });
3460
- /** 18. Subscribe to latest Flywheel status snapshots (stream) */
3461
- const SubscribeFlywheelStatusRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.subscribeFlywheelStatus, {
3462
- payload: effect.Schema.Struct({}),
3463
- success: effect.Schema.NullOr(FlywheelStatus),
3464
- error: PanRpcError,
3465
- stream: true
3466
- });
3467
3276
  /** 19. Open a workspace in an editor (PAN-966) */
3468
3277
  const ShellOpenInEditorRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.shellOpenInEditor, {
3469
3278
  payload: OpenInEditorInput,
@@ -3641,7 +3450,7 @@ const GetConversationStatsRpc = effect_unstable_rpc_Rpc.make(WS_METHODS.getConve
3641
3450
  error: PanRpcError
3642
3451
  });
3643
3452
  /** All Overdeck WebSocket RPC methods */
3644
- const PanRpcGroup = effect_unstable_rpc_RpcGroup.make(SubscribeDomainEventsRpc, SubscribeIssueEventsRpc, SubscribeTerminalRpc, SubscribeAgentOutputRpc, GetSnapshotRpc, ReplayEventsRpc, GetWorkspaceDetailRpc, ReadWorkspaceFileRpc, ReadFileAtPathRpc, WriteFileAtPathRpc, ResolveFilePathExistsRpc, TerminalOpenRpc, TerminalWriteRpc, TerminalResizeRpc, TerminalCloseRpc, StartPlanningRpc, StartAgentRpc, DeepWipeRpc, SendTerminalInputRpc, ResizeTerminalRpc, SubscribeConversationMessagesRpc, SubscribeProjectSessionTreeRpc, SubscribeFlywheelStatusRpc, ShellOpenInEditorRpc, GetAvailableEditorsRpc, ScanConversationsRpc, SearchConversationsRpc, ListDiscoveredSessionsRpc, ListSessionsFeedRpc, GetSessionsFeedFacetsRpc, GetDiscoveredSessionRpc, EnrichSessionsRpc, EmbedSessionsRpc, GetConversationCostRpc, GetConversationCostByWorkspaceRpc, GetConversationStatsRpc);
3453
+ const PanRpcGroup = effect_unstable_rpc_RpcGroup.make(SubscribeDomainEventsRpc, SubscribeIssueEventsRpc, SubscribeTerminalRpc, SubscribeAgentOutputRpc, GetSnapshotRpc, ReplayEventsRpc, ReadWorkspaceFileRpc, ReadFileAtPathRpc, WriteFileAtPathRpc, ResolveFilePathExistsRpc, TerminalOpenRpc, TerminalWriteRpc, TerminalResizeRpc, TerminalCloseRpc, StartPlanningRpc, StartAgentRpc, DeepWipeRpc, SendTerminalInputRpc, ResizeTerminalRpc, SubscribeConversationMessagesRpc, SubscribeProjectSessionTreeRpc, ShellOpenInEditorRpc, GetAvailableEditorsRpc, ScanConversationsRpc, SearchConversationsRpc, ListDiscoveredSessionsRpc, ListSessionsFeedRpc, GetSessionsFeedFacetsRpc, GetDiscoveredSessionRpc, EnrichSessionsRpc, EmbedSessionsRpc, GetConversationCostRpc, GetConversationCostByWorkspaceRpc, GetConversationStatsRpc);
3645
3454
  //#endregion
3646
3455
  //#region src/issue-delta.ts
3647
3456
  function createIssueDelta(previous, next) {
@@ -3666,7 +3475,8 @@ const INITIAL_READ_MODEL_STATE = {
3666
3475
  sequence: 0,
3667
3476
  agentsById: {},
3668
3477
  agentRuntimeById: {},
3669
- reviewStatusByIssueId: {},
3478
+ derivedIssueStateByIssueId: {},
3479
+ backendPanesById: {},
3670
3480
  resources: null,
3671
3481
  agentOutputById: {},
3672
3482
  issuesRaw: [],
@@ -3783,8 +3593,10 @@ function bumpRuntimeSnapshotSequence(agentsById, agentId, sequence) {
3783
3593
  function syncSnapshot(state, snapshot) {
3784
3594
  const agentsById = {};
3785
3595
  for (const agent of snapshot.agents) agentsById[agent.id] = agent;
3786
- const reviewStatusByIssueId = {};
3787
- for (const rs of snapshot.reviewStatuses) reviewStatusByIssueId[rs.issueId] = rs;
3596
+ const derivedIssueStateByIssueId = {};
3597
+ for (const derived of snapshot.derivedIssueStates ?? []) derivedIssueStateByIssueId[derived.issueId] = derived;
3598
+ const backendPanesById = {};
3599
+ for (const pane of snapshot.backendPanes ?? []) backendPanesById[pane.id] = pane;
3788
3600
  const channelPermissionRequestsById = {};
3789
3601
  const channelPermissionRequestIdsByAgentId = {};
3790
3602
  for (const request of snapshot.channelPermissionRequests ?? []) {
@@ -3800,7 +3612,8 @@ function syncSnapshot(state, snapshot) {
3800
3612
  ...state,
3801
3613
  sequence: snapshot.sequence,
3802
3614
  agentsById,
3803
- reviewStatusByIssueId,
3615
+ derivedIssueStateByIssueId,
3616
+ backendPanesById,
3804
3617
  agentRuntimeById: snapshot.agentRuntimeById ?? state.agentRuntimeById,
3805
3618
  channelPermissionRequestsById,
3806
3619
  channelPermissionRequestIdsByAgentId,
@@ -3890,7 +3703,16 @@ function applyEvent(state, event) {
3890
3703
  };
3891
3704
  }
3892
3705
  case "agent.stopped": {
3893
- const { [event.payload.agentId]: _removed, ...rest } = state.agentsById;
3706
+ const stoppedAgent = state.agentsById[event.payload.agentId];
3707
+ const nextAgentsById = stoppedAgent ? {
3708
+ ...state.agentsById,
3709
+ [event.payload.agentId]: {
3710
+ ...stoppedAgent,
3711
+ status: "stopped",
3712
+ hasLiveTmuxSession: false,
3713
+ lastActivity: event.timestamp
3714
+ }
3715
+ } : state.agentsById;
3894
3716
  const runtimeById = state.agentRuntimeById ?? {};
3895
3717
  const prevRuntime = runtimeById[event.payload.agentId];
3896
3718
  const nextRuntimeById = prevRuntime ? {
@@ -3919,7 +3741,7 @@ function applyEvent(state, event) {
3919
3741
  return {
3920
3742
  ...state,
3921
3743
  sequence: Math.max(state.sequence, event.sequence),
3922
- agentsById: rest,
3744
+ agentsById: nextAgentsById,
3923
3745
  agentRuntimeById: nextRuntimeById,
3924
3746
  channelPermissionRequestsById: nextPermissionRequestsById,
3925
3747
  channelPermissionRequestIdsByAgentId: restPendingIds,
@@ -4064,85 +3886,35 @@ function applyEvent(state, event) {
4064
3886
  }
4065
3887
  };
4066
3888
  }
4067
- case "pipeline.status_changed":
4068
- case "review.status_changed": return {
3889
+ case "issue_state.changed": return {
4069
3890
  ...state,
4070
3891
  sequence: Math.max(state.sequence, event.sequence),
4071
- reviewStatusByIssueId: {
4072
- ...state.reviewStatusByIssueId,
4073
- [event.payload.issueId]: event.payload.status
3892
+ derivedIssueStateByIssueId: {
3893
+ ...state.derivedIssueStateByIssueId,
3894
+ [event.payload.issueState.issueId]: event.payload.issueState
4074
3895
  }
4075
3896
  };
4076
- case "review.reviewer_started": {
4077
- const { issueId, role, sessionName } = event.payload;
4078
- const existing = state.reviewStatusByIssueId[issueId];
4079
- const prevSubs = existing?.reviewSubStatuses ?? {};
4080
- const prevNames = existing?.reviewSessionNames ?? [];
4081
- const nextNames = prevNames.includes(sessionName) ? prevNames : [...prevNames, sessionName];
4082
- const nextStatus = {
4083
- ...existing ?? { issueId },
4084
- reviewSubStatuses: {
4085
- ...prevSubs,
4086
- [role]: "running"
4087
- },
4088
- reviewSessionNames: nextNames
4089
- };
4090
- return {
4091
- ...state,
4092
- sequence: Math.max(state.sequence, event.sequence),
4093
- reviewStatusByIssueId: {
4094
- ...state.reviewStatusByIssueId,
4095
- [issueId]: nextStatus
4096
- }
4097
- };
4098
- }
4099
- case "review.reviewer_completed": {
4100
- const { issueId, role } = event.payload;
4101
- const existing = state.reviewStatusByIssueId[issueId];
4102
- if (!existing) return {
4103
- ...state,
4104
- sequence: Math.max(state.sequence, event.sequence)
4105
- };
4106
- const prevSubs = existing.reviewSubStatuses ?? {};
4107
- const nextStatus = {
4108
- ...existing,
4109
- reviewSubStatuses: {
4110
- ...prevSubs,
4111
- [role]: "done"
4112
- }
4113
- };
4114
- return {
4115
- ...state,
4116
- sequence: Math.max(state.sequence, event.sequence),
4117
- reviewStatusByIssueId: {
4118
- ...state.reviewStatusByIssueId,
4119
- [issueId]: nextStatus
4120
- }
4121
- };
4122
- }
4123
- case "review.specialist.timed_out": return {
3897
+ case "backend_pane.changed": return {
4124
3898
  ...state,
4125
- sequence: Math.max(state.sequence, event.sequence)
3899
+ sequence: Math.max(state.sequence, event.sequence),
3900
+ backendPanesById: {
3901
+ ...state.backendPanesById,
3902
+ [event.payload.pane.id]: event.payload.pane
3903
+ }
4126
3904
  };
4127
- case "review.coordinator_started": {
4128
- const { issueId, sessionName } = event.payload;
4129
- const nextStatus = {
4130
- ...state.reviewStatusByIssueId[issueId] ?? { issueId },
4131
- reviewCoordinatorSessionName: sessionName
4132
- };
3905
+ case "backend_pane.removed": {
3906
+ const { [event.payload.paneId]: _removed, ...rest } = state.backendPanesById;
4133
3907
  return {
4134
3908
  ...state,
4135
3909
  sequence: Math.max(state.sequence, event.sequence),
4136
- reviewStatusByIssueId: {
4137
- ...state.reviewStatusByIssueId,
4138
- [issueId]: nextStatus
4139
- }
3910
+ backendPanesById: rest
4140
3911
  };
4141
3912
  }
4142
- case "review.coordinator.died": return {
4143
- ...state,
4144
- sequence: Math.max(state.sequence, event.sequence)
4145
- };
3913
+ case "review.reviewer_started":
3914
+ case "review.reviewer_completed":
3915
+ case "review.specialist.timed_out":
3916
+ case "review.coordinator_started":
3917
+ case "review.coordinator.died":
4146
3918
  case "pipeline.review-started":
4147
3919
  case "pipeline.review-completed":
4148
3920
  case "pipeline.test-started":
@@ -5127,49 +4899,229 @@ function deriveProjectCi(record) {
5127
4899
  };
5128
4900
  }
5129
4901
  //#endregion
5130
- //#region src/flywheel-stats.ts
5131
- const FlywheelStatsCriterionStatus = effect.Schema.Literals([
5132
- "green",
5133
- "yellow",
5134
- "red",
5135
- "insufficient_data"
4902
+ //#region src/flywheel.ts
4903
+ const FlywheelRunId = effect.Schema.String.check(effect.Schema.isPattern(/^RUN-\d+$/));
4904
+ const FlywheelHttpUrl = effect.Schema.String.check(effect.Schema.isPattern(/^https?:\/\/\S+$/i));
4905
+ const FlywheelHarness = effect.Schema.Literals([
4906
+ "claude-code",
4907
+ "pi",
4908
+ "ohmypi",
4909
+ "codex",
4910
+ "acp",
4911
+ "kimi-code",
4912
+ "opencode",
4913
+ "muse"
5136
4914
  ]);
5137
- const FlywheelStatsTrend = effect.Schema.Literals([
5138
- "up",
5139
- "down",
5140
- "flat"
4915
+ const FlywheelEffort = effect.Schema.Literals([
4916
+ "low",
4917
+ "medium",
4918
+ "high",
4919
+ "xhigh",
4920
+ "max"
5141
4921
  ]);
5142
- const FlywheelStatsCriterionValueObject = effect.Schema.Record(effect.Schema.String, effect.Schema.Json);
5143
- const FlywheelStatsCriterionValue = effect.Schema.Union([effect.Schema.Number, FlywheelStatsCriterionValueObject]);
5144
- const FlywheelStatsCriterion = effect.Schema.Struct({
5145
- label: effect.Schema.String,
5146
- value: FlywheelStatsCriterionValue,
5147
- target: FlywheelStatsCriterionValue,
5148
- status: FlywheelStatsCriterionStatus,
5149
- trend: effect.Schema.optional(FlywheelStatsTrend),
5150
- sampleSize: effect.Schema.Number,
5151
- dataSufficient: effect.Schema.Boolean
5152
- });
5153
- const FlywheelStatsCriteria = effect.Schema.Struct({
5154
- c1_bugRate: FlywheelStatsCriterion,
5155
- c2_p0Bugs: FlywheelStatsCriterion,
5156
- c3_passRate: FlywheelStatsCriterion,
5157
- c4_mttr: FlywheelStatsCriterion,
5158
- c5_intervention: FlywheelStatsCriterion,
5159
- c6_timeConsistency: FlywheelStatsCriterion,
5160
- c7_flake: FlywheelStatsCriterion
4922
+ const FlywheelOrchestrator = effect.Schema.Struct({
4923
+ harness: FlywheelHarness,
4924
+ model: effect.Schema.String,
4925
+ effort: FlywheelEffort,
4926
+ ctxPercent: effect.Schema.Number
5161
4927
  });
5162
- const FlywheelStats = effect.Schema.Struct({
5163
- window: effect.Schema.String,
5164
- generatedAt: effect.Schema.String,
5165
- criteria: FlywheelStatsCriteria
4928
+ const FlywheelScope = effect.Schema.Literals(["pan-only", "all-tracked-projects"]);
4929
+ const FlywheelHeadline = effect.Schema.Struct({
4930
+ bugsFixed: effect.Schema.Number,
4931
+ swarmItemsMerged: effect.Schema.Number,
4932
+ swarmItemsTotal: effect.Schema.Number,
4933
+ prsMerged: effect.Schema.Number,
4934
+ awaitingUat: effect.Schema.Number
5166
4935
  });
5167
- const decodeFlywheelStats = effect.Schema.decodeUnknownSync(FlywheelStats);
5168
- const encodeFlywheelStats = effect.Schema.encodeSync(FlywheelStats);
5169
- //#endregion
5170
- //#region src/orders.ts
5171
- const OrderBookLane = effect.Schema.Literals(["A", "B"]);
5172
- const OrderBookStatus = effect.Schema.Literals([
4936
+ /**
4937
+ * Pipeline verbs — display state only. They no longer gate the merge queue.
4938
+ *
4939
+ * History worth keeping (PAN-1736 / PAN-1759): the merge queue used to be
4940
+ * derived by filtering these verbs, treating only "shipping" or "merging" as
4941
+ * "at the merge gate". Any other verb on an issue that was ready_for_merge in
4942
+ * the review DB silently dropped it from the queue and from UAT batch
4943
+ * assembly — RUN-18 shipped an empty queue with five ready issues exactly that
4944
+ * way — and the queue existed only while a run was emitting a pipeline at all.
4945
+ *
4946
+ * PAN-1696 removed that coupling. The ready set is now sourced from the
4947
+ * review-status records per project (`listEligibleCandidatesByProject` +
4948
+ * `computeMergeQueueFromCandidates` in src/lib/flywheel-merge-order.ts), which
4949
+ * needs no flywheel run and cannot be affected by which verb an orchestrator
4950
+ * chose to report. Adding a verb here therefore has no merge-queue consequence;
4951
+ * it only changes what the dashboard displays.
4952
+ */
4953
+ const FlywheelPipelineVerb = effect.Schema.Literals([
4954
+ "planning",
4955
+ "working",
4956
+ "reviewing",
4957
+ "testing",
4958
+ "shipping",
4959
+ "merging",
4960
+ "blocked",
4961
+ "parked"
4962
+ ]);
4963
+ const FlywheelPipelineStatus = effect.Schema.Literals([
4964
+ "queued",
4965
+ "running",
4966
+ "blocked",
4967
+ "passed",
4968
+ "failed",
4969
+ "merged",
4970
+ "parked"
4971
+ ]);
4972
+ const FlywheelPipelineItem = effect.Schema.Struct({
4973
+ issueId: effect.Schema.String,
4974
+ title: effect.Schema.String,
4975
+ verb: FlywheelPipelineVerb,
4976
+ status: FlywheelPipelineStatus,
4977
+ progressPercent: effect.Schema.optional(effect.Schema.Number),
4978
+ agentId: effect.Schema.optional(effect.Schema.String),
4979
+ pr: effect.Schema.optional(effect.Schema.Number),
4980
+ mergeOrder: effect.Schema.optional(effect.Schema.Number),
4981
+ conflictsWith: effect.Schema.optional(effect.Schema.Array(effect.Schema.String))
4982
+ });
4983
+ const FlywheelSubstrateBugStatus = effect.Schema.Literals([
4984
+ "filed",
4985
+ "fixed",
4986
+ "workaround"
4987
+ ]);
4988
+ const FlywheelSubstrateBug = effect.Schema.Struct({
4989
+ issueId: effect.Schema.String,
4990
+ title: effect.Schema.String,
4991
+ status: FlywheelSubstrateBugStatus,
4992
+ commitSha: effect.Schema.optional(effect.Schema.String),
4993
+ url: effect.Schema.optional(FlywheelHttpUrl)
4994
+ });
4995
+ const FlywheelAgentStatus = effect.Schema.Literals([
4996
+ "starting",
4997
+ "running",
4998
+ "waiting",
4999
+ "idle",
5000
+ "stopped",
5001
+ "error"
5002
+ ]);
5003
+ const FlywheelAgent = effect.Schema.Struct({
5004
+ id: effect.Schema.String,
5005
+ label: effect.Schema.String,
5006
+ status: FlywheelAgentStatus,
5007
+ issueId: effect.Schema.optional(effect.Schema.String),
5008
+ role: effect.Schema.optional(effect.Schema.String),
5009
+ model: effect.Schema.optional(effect.Schema.String),
5010
+ ctxPercent: effect.Schema.optional(effect.Schema.Number),
5011
+ currentAction: effect.Schema.optional(effect.Schema.String)
5012
+ });
5013
+ const FlywheelParkedItem = effect.Schema.Struct({
5014
+ issueId: effect.Schema.String,
5015
+ title: effect.Schema.String,
5016
+ reason: effect.Schema.String,
5017
+ parkedAt: effect.Schema.optional(effect.Schema.String)
5018
+ });
5019
+ const FlywheelSuggestionAction = effect.Schema.Literals([
5020
+ "start",
5021
+ "resume",
5022
+ "plan",
5023
+ "review",
5024
+ "merge",
5025
+ "unblock",
5026
+ "park",
5027
+ "investigate",
5028
+ "wait"
5029
+ ]);
5030
+ const FlywheelSuggestionPriority = effect.Schema.Literals([
5031
+ "urgent",
5032
+ "high",
5033
+ "medium",
5034
+ "low"
5035
+ ]);
5036
+ const FlywheelSuggestion = effect.Schema.Struct({
5037
+ action: FlywheelSuggestionAction,
5038
+ issueId: effect.Schema.optional(effect.Schema.String),
5039
+ rationale: effect.Schema.String,
5040
+ priority: FlywheelSuggestionPriority,
5041
+ filedBy: effect.Schema.optional(effect.Schema.Literals(["agent", "operator"])),
5042
+ weight: effect.Schema.optional(effect.Schema.Number),
5043
+ weightReason: effect.Schema.optional(effect.Schema.String)
5044
+ });
5045
+ const FlywheelSystemStatus = effect.Schema.Struct({
5046
+ mainHead: effect.Schema.String,
5047
+ ramUsedMb: effect.Schema.Number,
5048
+ ramTotalMb: effect.Schema.Number,
5049
+ swapUsedMb: effect.Schema.Number,
5050
+ swapTotalMb: effect.Schema.Number,
5051
+ agentsActive: effect.Schema.Number,
5052
+ agentsCap: effect.Schema.Number
5053
+ });
5054
+ const FlywheelOrders = effect.Schema.Struct({
5055
+ bookId: effect.Schema.String,
5056
+ bookName: effect.Schema.String,
5057
+ landed: effect.Schema.Number,
5058
+ total: effect.Schema.Number,
5059
+ laneAInFlight: effect.Schema.Array(effect.Schema.String),
5060
+ laneBInFlight: effect.Schema.optional(effect.Schema.String),
5061
+ drained: effect.Schema.Boolean
5062
+ });
5063
+ const FlywheelStatus = effect.Schema.Struct({
5064
+ runId: FlywheelRunId,
5065
+ startedAt: effect.Schema.String,
5066
+ elapsedMs: effect.Schema.Number,
5067
+ orchestrator: FlywheelOrchestrator,
5068
+ headline: FlywheelHeadline,
5069
+ activePipeline: effect.Schema.Array(FlywheelPipelineItem),
5070
+ substrateBugs: effect.Schema.Array(FlywheelSubstrateBug),
5071
+ agents: effect.Schema.Array(FlywheelAgent),
5072
+ parked: effect.Schema.Array(FlywheelParkedItem),
5073
+ suggestions: effect.Schema.Array(FlywheelSuggestion).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed([]))),
5074
+ system: FlywheelSystemStatus,
5075
+ openQuestions: effect.Schema.Array(effect.Schema.String),
5076
+ orders: effect.Schema.optional(FlywheelOrders),
5077
+ scope: effect.Schema.optional(FlywheelScope),
5078
+ ticks: effect.Schema.Number,
5079
+ lastTickAt: effect.Schema.String
5080
+ });
5081
+ //#endregion
5082
+ //#region src/flywheel-stats.ts
5083
+ const FlywheelStatsCriterionStatus = effect.Schema.Literals([
5084
+ "green",
5085
+ "yellow",
5086
+ "red",
5087
+ "insufficient_data"
5088
+ ]);
5089
+ const FlywheelStatsTrend = effect.Schema.Literals([
5090
+ "up",
5091
+ "down",
5092
+ "flat"
5093
+ ]);
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,
5100
+ status: FlywheelStatsCriterionStatus,
5101
+ trend: effect.Schema.optional(FlywheelStatsTrend),
5102
+ sampleSize: effect.Schema.Number,
5103
+ dataSufficient: effect.Schema.Boolean
5104
+ });
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
5113
+ });
5114
+ const FlywheelStats = effect.Schema.Struct({
5115
+ window: effect.Schema.String,
5116
+ generatedAt: effect.Schema.String,
5117
+ criteria: FlywheelStatsCriteria
5118
+ });
5119
+ const decodeFlywheelStats = effect.Schema.decodeUnknownSync(FlywheelStats);
5120
+ const encodeFlywheelStats = effect.Schema.encodeSync(FlywheelStats);
5121
+ //#endregion
5122
+ //#region src/orders.ts
5123
+ const OrderBookLane = effect.Schema.Literals(["A", "B"]);
5124
+ const OrderBookStatus = effect.Schema.Literals([
5173
5125
  "draft",
5174
5126
  "ready",
5175
5127
  "running",
@@ -5518,6 +5470,18 @@ const FeatureRegistryEntry = effect.Schema.Struct({
5518
5470
  });
5519
5471
  //#endregion
5520
5472
  //#region src/harness-behavior.ts
5473
+ const AGENT_SESSION_PREFIXES = [
5474
+ "agent-",
5475
+ "planning-",
5476
+ "specialist-",
5477
+ "strike-",
5478
+ "inspect-"
5479
+ ];
5480
+ const AGENT_SESSION_SINGLETONS = new Set(["flywheel-orchestrator", "conv-flywheel-orchestrator"]);
5481
+ /** Canonical synthetic agent-session identity shared by dashboard client/server. */
5482
+ function isAgentSessionName(name) {
5483
+ return AGENT_SESSION_SINGLETONS.has(name) || AGENT_SESSION_PREFIXES.some((prefix) => name.startsWith(prefix));
5484
+ }
5521
5485
  const CLAUDE_CODE_BEHAVIOR = {
5522
5486
  displayName: "Claude Code",
5523
5487
  nativeCommands: [
@@ -5909,6 +5873,7 @@ const TELEMETRY_PROPERTY_DOMAINS = {
5909
5873
  "sessions",
5910
5874
  "awaiting-merge",
5911
5875
  "workspace-new",
5876
+ "project-new",
5912
5877
  "workspace"
5913
5878
  ],
5914
5879
  decision_subject: ["agent", "conversation"],
@@ -5951,7 +5916,11 @@ const TELEMETRY_PROPERTY_DOMAINS = {
5951
5916
  "merged",
5952
5917
  "closed_out"
5953
5918
  ],
5954
- project_mode: ["existing", "new"]
5919
+ project_mode: [
5920
+ "clone",
5921
+ "existing",
5922
+ "new"
5923
+ ]
5955
5924
  };
5956
5925
  const TELEMETRY_EVENT_CATALOG = {
5957
5926
  dashboard_tab_viewed: { tab: "dashboard_tab" },
@@ -6271,12 +6240,6 @@ const COMPOSER_COMMAND_MANIFEST = [
6271
6240
  "required": false,
6272
6241
  "valueHint": null
6273
6242
  },
6274
- {
6275
- "flags": "--shadow-only",
6276
- "description": "Show only shadowed issues",
6277
- "required": false,
6278
- "valueHint": null
6279
- },
6280
6243
  {
6281
6244
  "flags": "--triage",
6282
6245
  "description": "Show triage queue",
@@ -6291,19 +6254,13 @@ const COMPOSER_COMMAND_MANIFEST = [
6291
6254
  "id": "pan-show",
6292
6255
  "path": ["show"],
6293
6256
  "display": "/pan show",
6294
- "description": "Unified lens: shadow state, CV, context, health for one issue",
6257
+ "description": "Unified lens: derived issue state, CV, context, health for one issue",
6295
6258
  "args": [{
6296
6259
  "name": "id",
6297
6260
  "required": true,
6298
6261
  "variadic": false
6299
6262
  }],
6300
6263
  "options": [
6301
- {
6302
- "flags": "--shadow",
6303
- "description": "Shadow state details only",
6304
- "required": false,
6305
- "valueHint": null
6306
- },
6307
6264
  {
6308
6265
  "flags": "--cv",
6309
6266
  "description": "Agent work history only",
@@ -6355,32 +6312,12 @@ const COMPOSER_COMMAND_MANIFEST = [
6355
6312
  "id": "pan-review",
6356
6313
  "path": ["review"],
6357
6314
  "display": "/pan review",
6358
- "description": "Review-loop management: pending items, request re-review, reset cycles",
6315
+ "description": "Review-loop management: request re-review, abort reviewers, restart a round",
6359
6316
  "args": [],
6360
6317
  "options": [],
6361
6318
  "aliases": [],
6362
6319
  "category": "Review"
6363
6320
  },
6364
- {
6365
- "id": "pan-review-pending",
6366
- "path": ["review", "pending"],
6367
- "display": "/pan review pending",
6368
- "description": "List completed work awaiting review",
6369
- "args": [],
6370
- "options": [{
6371
- "flags": "--ready",
6372
- "description": "List issues ready for merge (review+test green, not merged) regardless of origin",
6373
- "required": false,
6374
- "valueHint": null
6375
- }, {
6376
- "flags": "--blocked",
6377
- "description": "List issues blocked in review/test/merge from the SQLite review-status store",
6378
- "required": false,
6379
- "valueHint": null
6380
- }],
6381
- "aliases": [],
6382
- "category": "Review"
6383
- },
6384
6321
  {
6385
6322
  "id": "pan-review-request",
6386
6323
  "path": ["review", "request"],
@@ -6400,39 +6337,6 @@ const COMPOSER_COMMAND_MANIFEST = [
6400
6337
  "aliases": [],
6401
6338
  "category": "Review"
6402
6339
  },
6403
- {
6404
- "id": "pan-review-reset",
6405
- "path": ["review", "reset"],
6406
- "display": "/pan review reset",
6407
- "description": "Reset review/test/merge cycles (human override)",
6408
- "args": [{
6409
- "name": "id",
6410
- "required": true,
6411
- "variadic": false
6412
- }],
6413
- "options": [{
6414
- "flags": "--session",
6415
- "description": "Also clear all saved Claude review-session pointers",
6416
- "required": false,
6417
- "valueHint": null
6418
- }],
6419
- "aliases": [],
6420
- "category": "Review"
6421
- },
6422
- {
6423
- "id": "pan-review-resync",
6424
- "path": ["review", "resync"],
6425
- "display": "/pan review resync",
6426
- "description": "Re-emit canonical review status (heal a lost pipeline event)",
6427
- "args": [{
6428
- "name": "id",
6429
- "required": true,
6430
- "variadic": false
6431
- }],
6432
- "options": [],
6433
- "aliases": [],
6434
- "category": "Review"
6435
- },
6436
6340
  {
6437
6341
  "id": "pan-review-abort",
6438
6342
  "path": ["review", "abort"],
@@ -6447,24 +6351,6 @@ const COMPOSER_COMMAND_MANIFEST = [
6447
6351
  "aliases": [],
6448
6352
  "category": "Review"
6449
6353
  },
6450
- {
6451
- "id": "pan-review-mode",
6452
- "path": ["review", "mode"],
6453
- "display": "/pan review mode",
6454
- "description": "Set per-issue review mode (quick, full, or none)",
6455
- "args": [{
6456
- "name": "id",
6457
- "required": true,
6458
- "variadic": false
6459
- }, {
6460
- "name": "mode",
6461
- "required": true,
6462
- "variadic": false
6463
- }],
6464
- "options": [],
6465
- "aliases": [],
6466
- "category": "Review"
6467
- },
6468
6354
  {
6469
6355
  "id": "pan-review-restart",
6470
6356
  "path": ["review", "restart"],
@@ -6493,23 +6379,13 @@ const COMPOSER_COMMAND_MANIFEST = [
6493
6379
  "id": "pan-staffing",
6494
6380
  "path": ["staffing"],
6495
6381
  "display": "/pan staffing",
6496
- "description": "Show or set per-issue work-model and swarm overrides",
6382
+ "description": "Show the work model and swarm policy in effect for an issue",
6497
6383
  "args": [{
6498
6384
  "name": "id",
6499
6385
  "required": true,
6500
6386
  "variadic": false
6501
6387
  }],
6502
- "options": [{
6503
- "flags": "--model <model>",
6504
- "description": "Set the work model, or default to clear the override",
6505
- "required": true,
6506
- "valueHint": "model"
6507
- }, {
6508
- "flags": "--swarm <mode>",
6509
- "description": "Set swarm mode (off, auto, always), or default to clear the override",
6510
- "required": true,
6511
- "valueHint": "mode"
6512
- }],
6388
+ "options": [],
6513
6389
  "aliases": [],
6514
6390
  "category": "Lifecycle"
6515
6391
  },
@@ -6527,7 +6403,7 @@ const COMPOSER_COMMAND_MANIFEST = [
6527
6403
  "id": "pan-backlog-write-sequence",
6528
6404
  "path": ["backlog", "write-sequence"],
6529
6405
  "display": "/pan backlog write-sequence",
6530
- "description": "Validate a SequenceDoc JSON file and write it to .pan/backlog/sequence.md (triggers auto-commit)",
6406
+ "description": "Validate a SequenceDoc JSON file, write it to .pan/backlog/sequence.md, and commit it",
6531
6407
  "args": [{
6532
6408
  "name": "file",
6533
6409
  "required": true,
@@ -6542,21 +6418,6 @@ const COMPOSER_COMMAND_MANIFEST = [
6542
6418
  "aliases": [],
6543
6419
  "category": "Lifecycle"
6544
6420
  },
6545
- {
6546
- "id": "pan-backlog-forecast",
6547
- "path": ["backlog", "forecast"],
6548
- "display": "/pan backlog forecast",
6549
- "description": "Pickup forecast (waves / needs-planning / cohort / stats) from sequence.md + SQLite — no HTTP (sandbox-safe)",
6550
- "args": [],
6551
- "options": [{
6552
- "flags": "-n, --n <n>",
6553
- "description": "Wave size (default 5)",
6554
- "required": true,
6555
- "valueHint": "n"
6556
- }],
6557
- "aliases": [],
6558
- "category": "Lifecycle"
6559
- },
6560
6421
  {
6561
6422
  "id": "pan-plan",
6562
6423
  "path": ["plan"],
@@ -6768,25 +6629,6 @@ const COMPOSER_COMMAND_MANIFEST = [
6768
6629
  "aliases": ["stop"],
6769
6630
  "category": "Lifecycle"
6770
6631
  },
6771
- {
6772
- "id": "pan-reset-to-planned",
6773
- "path": ["reset-to-planned"],
6774
- "display": "/pan reset-to-planned",
6775
- "description": "Return a finalized issue to post-planning without deleting its workspace, plan, commits, or branch",
6776
- "args": [{
6777
- "name": "id",
6778
- "required": true,
6779
- "variadic": false
6780
- }],
6781
- "options": [{
6782
- "flags": "--dry-run",
6783
- "description": "Show the exact reset without changing state",
6784
- "required": false,
6785
- "valueHint": null
6786
- }],
6787
- "aliases": [],
6788
- "category": "Lifecycle"
6789
- },
6790
6632
  {
6791
6633
  "id": "pan-reset-session",
6792
6634
  "path": ["reset-session"],
@@ -6834,34 +6676,6 @@ const COMPOSER_COMMAND_MANIFEST = [
6834
6676
  "aliases": [],
6835
6677
  "category": "Lifecycle"
6836
6678
  },
6837
- {
6838
- "id": "pan-untroubled",
6839
- "path": ["untroubled"],
6840
- "display": "/pan untroubled",
6841
- "description": "Clear an agent troubled gate without spawning it",
6842
- "args": [{
6843
- "name": "id",
6844
- "required": true,
6845
- "variadic": false
6846
- }],
6847
- "options": [],
6848
- "aliases": [],
6849
- "category": "Lifecycle"
6850
- },
6851
- {
6852
- "id": "pan-unstick",
6853
- "path": ["unstick"],
6854
- "display": "/pan unstick",
6855
- "description": "Clear an issue stuck gate without resetting a merged lifecycle",
6856
- "args": [{
6857
- "name": "id",
6858
- "required": true,
6859
- "variadic": false
6860
- }],
6861
- "options": [],
6862
- "aliases": [],
6863
- "category": "CLI"
6864
- },
6865
6679
  {
6866
6680
  "id": "pan-fork",
6867
6681
  "path": ["fork"],
@@ -7105,13 +6919,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7105
6919
  },
7106
6920
  {
7107
6921
  "flags": "--strike",
7108
- "description": "Strike-agent shape: skip review-pipeline dispatch (used by `pan strike` agents that merged directly to main)",
7109
- "required": false,
7110
- "valueHint": null
7111
- },
7112
- {
7113
- "flags": "--json",
7114
- "description": "Output as JSON",
6922
+ "description": "Strike shape: verify the strike branch is contained in origin/main; no PR is opened",
7115
6923
  "required": false,
7116
6924
  "valueHint": null
7117
6925
  }
@@ -7119,20 +6927,6 @@ const COMPOSER_COMMAND_MANIFEST = [
7119
6927
  "aliases": [],
7120
6928
  "category": "Lifecycle"
7121
6929
  },
7122
- {
7123
- "id": "pan-approve",
7124
- "path": ["approve"],
7125
- "display": "/pan approve",
7126
- "description": "[REMOVED] Use dashboard MERGE button instead",
7127
- "args": [{
7128
- "name": "id",
7129
- "required": true,
7130
- "variadic": false
7131
- }],
7132
- "options": [],
7133
- "aliases": [],
7134
- "category": "Lifecycle"
7135
- },
7136
6930
  {
7137
6931
  "id": "pan-reopen",
7138
6932
  "path": ["reopen"],
@@ -7181,27 +6975,36 @@ const COMPOSER_COMMAND_MANIFEST = [
7181
6975
  "aliases": [],
7182
6976
  "category": "Lifecycle"
7183
6977
  },
7184
- {
7185
- "id": "pan-destroy",
7186
- "path": ["destroy"],
7187
- "display": "/pan destroy",
7188
- "description": "Alias for workspace destroy: remove the issue workspace worktree and branch",
7189
- "args": [{
7190
- "name": "id",
7191
- "required": true,
7192
- "variadic": false
7193
- }],
7194
- "options": [{
7195
- "flags": "--force",
7196
- "description": "Force removal even with uncommitted changes",
7197
- "required": false,
7198
- "valueHint": null
7199
- }, {
7200
- "flags": "--project <path>",
7201
- "description": "Explicit project path (overrides registry)",
6978
+ {
6979
+ "id": "pan-destroy",
6980
+ "path": ["destroy"],
6981
+ "display": "/pan destroy",
6982
+ "description": "Alias for workspace destroy: remove the issue workspace worktree and branch",
6983
+ "args": [{
6984
+ "name": "id",
7202
6985
  "required": true,
7203
- "valueHint": "path"
6986
+ "variadic": false
7204
6987
  }],
6988
+ "options": [
6989
+ {
6990
+ "flags": "--force",
6991
+ "description": "Force removal even with uncommitted changes",
6992
+ "required": false,
6993
+ "valueHint": null
6994
+ },
6995
+ {
6996
+ "flags": "--project <path>",
6997
+ "description": "Explicit project path (overrides registry)",
6998
+ "required": true,
6999
+ "valueHint": "path"
7000
+ },
7001
+ {
7002
+ "flags": "--shape <shape>",
7003
+ "description": "Limit to one shape: base|strike|slot|all (default: all)",
7004
+ "required": true,
7005
+ "valueHint": "shape"
7006
+ }
7007
+ ],
7205
7008
  "aliases": [],
7206
7009
  "category": "Workspace"
7207
7010
  },
@@ -7305,25 +7108,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7305
7108
  "options": [
7306
7109
  {
7307
7110
  "flags": "--model <model>",
7308
- "description": "Work model to use and persist for later respawns (defaults to Cloister config)",
7309
- "required": true,
7310
- "valueHint": "model"
7311
- },
7312
- {
7313
- "flags": "--swarm <mode>",
7314
- "description": "Per-issue swarm policy: off | auto | always",
7315
- "required": true,
7316
- "valueHint": "mode"
7317
- },
7318
- {
7319
- "flags": "--review-mode <mode>",
7320
- "description": "Per-issue review mode: quick | full | none",
7321
- "required": true,
7322
- "valueHint": "mode"
7323
- },
7324
- {
7325
- "flags": "--review-model <model>",
7326
- "description": "Per-issue review model override",
7111
+ "description": "Work model for this session (defaults to Cloister config)",
7327
7112
  "required": true,
7328
7113
  "valueHint": "model"
7329
7114
  },
@@ -7351,18 +7136,6 @@ const COMPOSER_COMMAND_MANIFEST = [
7351
7136
  "required": false,
7352
7137
  "valueHint": null
7353
7138
  },
7354
- {
7355
- "flags": "--shadow",
7356
- "description": "Enable shadow mode",
7357
- "required": false,
7358
- "valueHint": null
7359
- },
7360
- {
7361
- "flags": "--no-shadow",
7362
- "description": "Disable shadow mode",
7363
- "required": false,
7364
- "valueHint": null
7365
- },
7366
7139
  {
7367
7140
  "flags": "--remote",
7368
7141
  "description": "Use remote workspace (Fly.io)",
@@ -7418,8 +7191,8 @@ const COMPOSER_COMMAND_MANIFEST = [
7418
7191
  "valueHint": null
7419
7192
  },
7420
7193
  {
7421
- "flags": "--off-book",
7422
- "description": "Allow one work-agent dispatch outside the active order book and log the override",
7194
+ "flags": "--skip-freshness",
7195
+ "description": "Bypass the plan-freshness preflight and spawn even if the plan names files that no longer exist",
7423
7196
  "required": false,
7424
7197
  "valueHint": null
7425
7198
  }
@@ -7431,7 +7204,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7431
7204
  "id": "pan-strike",
7432
7205
  "path": ["strike"],
7433
7206
  "display": "/pan strike",
7434
- "description": "Spawn strike agent(s) — implement and push a strike branch for Deacon to land through the verified merge door. Bypasses plan/review/test/ship.",
7207
+ "description": "Spawn strike agent(s) — implement a fix on a strike branch and open a PR against main for the operator to merge. Bypasses plan/review/test/ship.",
7435
7208
  "args": [{
7436
7209
  "name": "ids",
7437
7210
  "required": true,
@@ -7466,20 +7239,6 @@ const COMPOSER_COMMAND_MANIFEST = [
7466
7239
  "aliases": [],
7467
7240
  "category": "Lifecycle"
7468
7241
  },
7469
- {
7470
- "id": "pan-strike-ready",
7471
- "path": ["strike-ready"],
7472
- "display": "/pan strike-ready",
7473
- "description": "Persist readiness for a pushed strike branch so Deacon can land it",
7474
- "args": [{
7475
- "name": "id",
7476
- "required": true,
7477
- "variadic": false
7478
- }],
7479
- "options": [],
7480
- "aliases": [],
7481
- "category": "Lifecycle"
7482
- },
7483
7242
  {
7484
7243
  "id": "pan-knowledge",
7485
7244
  "path": ["knowledge"],
@@ -7746,7 +7505,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7746
7505
  "id": "pan-task",
7747
7506
  "path": ["task"],
7748
7507
  "display": "/pan task",
7749
- "description": "Read and update xBRIEF task state for one issue",
7508
+ "description": "Read and update xBRIEF item state for one issue",
7750
7509
  "args": [],
7751
7510
  "options": [],
7752
7511
  "aliases": [],
@@ -7808,32 +7567,12 @@ const COMPOSER_COMMAND_MANIFEST = [
7808
7567
  "required": true,
7809
7568
  "variadic": false
7810
7569
  }],
7811
- "options": [
7812
- {
7813
- "flags": "--reason <text>",
7814
- "description": "Reason for the status change",
7815
- "required": true,
7816
- "valueHint": "text"
7817
- },
7818
- {
7819
- "flags": "--expected-sequence <n>",
7820
- "description": "Require the current task sequence",
7821
- "required": true,
7822
- "valueHint": "n"
7823
- },
7824
- {
7825
- "flags": "--force",
7826
- "description": "Override a non-terminal transition or claim owner; requires --reason",
7827
- "required": false,
7828
- "valueHint": null
7829
- },
7830
- {
7831
- "flags": "--json",
7832
- "description": "Print JSON",
7833
- "required": false,
7834
- "valueHint": null
7835
- }
7836
- ],
7570
+ "options": [{
7571
+ "flags": "--json",
7572
+ "description": "Print JSON",
7573
+ "required": false,
7574
+ "valueHint": null
7575
+ }],
7837
7576
  "aliases": [],
7838
7577
  "category": "Lifecycle"
7839
7578
  },
@@ -7841,7 +7580,7 @@ const COMPOSER_COMMAND_MANIFEST = [
7841
7580
  "id": "pan-task-done",
7842
7581
  "path": ["task", "done"],
7843
7582
  "display": "/pan task done",
7844
- "description": "",
7583
+ "description": "Record an item as done. Requires a commit carrying \"Item: <item>\" on a pushed branch.",
7845
7584
  "args": [{
7846
7585
  "name": "issue",
7847
7586
  "required": true,
@@ -7851,32 +7590,12 @@ const COMPOSER_COMMAND_MANIFEST = [
7851
7590
  "required": true,
7852
7591
  "variadic": false
7853
7592
  }],
7854
- "options": [
7855
- {
7856
- "flags": "--reason <text>",
7857
- "description": "Reason for the status change",
7858
- "required": true,
7859
- "valueHint": "text"
7860
- },
7861
- {
7862
- "flags": "--expected-sequence <n>",
7863
- "description": "Require the current task sequence",
7864
- "required": true,
7865
- "valueHint": "n"
7866
- },
7867
- {
7868
- "flags": "--force",
7869
- "description": "Override a non-terminal transition or claim owner; requires --reason",
7870
- "required": false,
7871
- "valueHint": null
7872
- },
7873
- {
7874
- "flags": "--json",
7875
- "description": "Print JSON",
7876
- "required": false,
7877
- "valueHint": null
7878
- }
7879
- ],
7593
+ "options": [{
7594
+ "flags": "--json",
7595
+ "description": "Print JSON",
7596
+ "required": false,
7597
+ "valueHint": null
7598
+ }],
7880
7599
  "aliases": [],
7881
7600
  "category": "Lifecycle"
7882
7601
  },
@@ -7894,32 +7613,12 @@ const COMPOSER_COMMAND_MANIFEST = [
7894
7613
  "required": true,
7895
7614
  "variadic": false
7896
7615
  }],
7897
- "options": [
7898
- {
7899
- "flags": "--reason <text>",
7900
- "description": "Reason for the status change",
7901
- "required": true,
7902
- "valueHint": "text"
7903
- },
7904
- {
7905
- "flags": "--expected-sequence <n>",
7906
- "description": "Require the current task sequence",
7907
- "required": true,
7908
- "valueHint": "n"
7909
- },
7910
- {
7911
- "flags": "--force",
7912
- "description": "Override a non-terminal transition or claim owner; requires --reason",
7913
- "required": false,
7914
- "valueHint": null
7915
- },
7916
- {
7917
- "flags": "--json",
7918
- "description": "Print JSON",
7919
- "required": false,
7920
- "valueHint": null
7921
- }
7922
- ],
7616
+ "options": [{
7617
+ "flags": "--json",
7618
+ "description": "Print JSON",
7619
+ "required": false,
7620
+ "valueHint": null
7621
+ }],
7923
7622
  "aliases": [],
7924
7623
  "category": "Lifecycle"
7925
7624
  },
@@ -7937,32 +7636,12 @@ const COMPOSER_COMMAND_MANIFEST = [
7937
7636
  "required": true,
7938
7637
  "variadic": false
7939
7638
  }],
7940
- "options": [
7941
- {
7942
- "flags": "--reason <text>",
7943
- "description": "Reason for the status change",
7944
- "required": true,
7945
- "valueHint": "text"
7946
- },
7947
- {
7948
- "flags": "--expected-sequence <n>",
7949
- "description": "Require the current task sequence",
7950
- "required": true,
7951
- "valueHint": "n"
7952
- },
7953
- {
7954
- "flags": "--force",
7955
- "description": "Override a non-terminal transition or claim owner; requires --reason",
7956
- "required": false,
7957
- "valueHint": null
7958
- },
7959
- {
7960
- "flags": "--json",
7961
- "description": "Print JSON",
7962
- "required": false,
7963
- "valueHint": null
7964
- }
7965
- ],
7639
+ "options": [{
7640
+ "flags": "--json",
7641
+ "description": "Print JSON",
7642
+ "required": false,
7643
+ "valueHint": null
7644
+ }],
7966
7645
  "aliases": [],
7967
7646
  "category": "Lifecycle"
7968
7647
  },
@@ -7980,32 +7659,12 @@ const COMPOSER_COMMAND_MANIFEST = [
7980
7659
  "required": true,
7981
7660
  "variadic": false
7982
7661
  }],
7983
- "options": [
7984
- {
7985
- "flags": "--reason <text>",
7986
- "description": "Reason for the status change",
7987
- "required": true,
7988
- "valueHint": "text"
7989
- },
7990
- {
7991
- "flags": "--expected-sequence <n>",
7992
- "description": "Require the current task sequence",
7993
- "required": true,
7994
- "valueHint": "n"
7995
- },
7996
- {
7997
- "flags": "--force",
7998
- "description": "Override a non-terminal transition or claim owner; requires --reason",
7999
- "required": false,
8000
- "valueHint": null
8001
- },
8002
- {
8003
- "flags": "--json",
8004
- "description": "Print JSON",
8005
- "required": false,
8006
- "valueHint": null
8007
- }
8008
- ],
7662
+ "options": [{
7663
+ "flags": "--json",
7664
+ "description": "Print JSON",
7665
+ "required": false,
7666
+ "valueHint": null
7667
+ }],
8009
7668
  "aliases": [],
8010
7669
  "category": "Lifecycle"
8011
7670
  },
@@ -8023,32 +7682,12 @@ const COMPOSER_COMMAND_MANIFEST = [
8023
7682
  "required": true,
8024
7683
  "variadic": false
8025
7684
  }],
8026
- "options": [
8027
- {
8028
- "flags": "--reason <text>",
8029
- "description": "Reason for the status change",
8030
- "required": true,
8031
- "valueHint": "text"
8032
- },
8033
- {
8034
- "flags": "--expected-sequence <n>",
8035
- "description": "Require the current task sequence",
8036
- "required": true,
8037
- "valueHint": "n"
8038
- },
8039
- {
8040
- "flags": "--force",
8041
- "description": "Override a non-terminal transition or claim owner; requires --reason",
8042
- "required": false,
8043
- "valueHint": null
8044
- },
8045
- {
8046
- "flags": "--json",
8047
- "description": "Print JSON",
8048
- "required": false,
8049
- "valueHint": null
8050
- }
8051
- ],
7685
+ "options": [{
7686
+ "flags": "--json",
7687
+ "description": "Print JSON",
7688
+ "required": false,
7689
+ "valueHint": null
7690
+ }],
8052
7691
  "aliases": [],
8053
7692
  "category": "Lifecycle"
8054
7693
  },
@@ -8238,6 +7877,12 @@ const COMPOSER_COMMAND_MANIFEST = [
8238
7877
  "description": "Include archived workspaces (only applies with --kind)",
8239
7878
  "required": false,
8240
7879
  "valueHint": null
7880
+ },
7881
+ {
7882
+ "flags": "--stale",
7883
+ "description": "Show reclaim candidates: merged branches still on disk, with sizes",
7884
+ "required": false,
7885
+ "valueHint": null
8241
7886
  }
8242
7887
  ],
8243
7888
  "aliases": [],
@@ -8247,7 +7892,7 @@ const COMPOSER_COMMAND_MANIFEST = [
8247
7892
  "id": "pan-workspace-destroy",
8248
7893
  "path": ["workspace", "destroy"],
8249
7894
  "display": "/pan workspace destroy",
8250
- "description": "Destroy workspace",
7895
+ "description": "Destroy workspace (all shapes by default: base, strike, and slot worktrees)",
8251
7896
  "args": [{
8252
7897
  "name": "issueId",
8253
7898
  "required": true,
@@ -8266,6 +7911,12 @@ const COMPOSER_COMMAND_MANIFEST = [
8266
7911
  "required": true,
8267
7912
  "valueHint": "path"
8268
7913
  },
7914
+ {
7915
+ "flags": "--shape <shape>",
7916
+ "description": "Limit to one shape: base|strike|slot|all (default: all)",
7917
+ "required": true,
7918
+ "valueHint": "shape"
7919
+ },
8269
7920
  {
8270
7921
  "flags": "--purge-memory",
8271
7922
  "description": "Also permanently delete the workspace's memory home (irreversible)",
@@ -8983,7 +8634,7 @@ const COMPOSER_COMMAND_MANIFEST = [
8983
8634
  "id": "pan-rollout-status",
8984
8635
  "path": ["rollout", "status"],
8985
8636
  "display": "/pan rollout status",
8986
- "description": "Print the release set for an issue (releaseStatus + per-component status)",
8637
+ "description": "Print the release set for an issue (overall + per-component status)",
8987
8638
  "args": [{
8988
8639
  "name": "issueId",
8989
8640
  "required": true,
@@ -9853,47 +9504,18 @@ const COMPOSER_COMMAND_MANIFEST = [
9853
9504
  "aliases": [],
9854
9505
  "category": "Flywheel"
9855
9506
  },
9856
- {
9857
- "id": "pan-parked",
9858
- "path": ["parked"],
9859
- "display": "/pan parked",
9860
- "description": "List every issue parked in a stall orbit (stuck flags, gates, failed merges, zombies), oldest first, with why + release condition",
9861
- "args": [],
9862
- "options": [{
9863
- "flags": "--json",
9864
- "description": "Print the raw parked rows as JSON",
9865
- "required": false,
9866
- "valueHint": null
9867
- }],
9868
- "aliases": [],
9869
- "category": "CLI"
9870
- },
9871
- {
9872
- "id": "pan-parked-ack",
9873
- "path": ["parked", "ack"],
9874
- "display": "/pan parked ack",
9875
- "description": "Batch-acknowledge parked rows (default orbit: needs-you), then print the flywheel hand-off",
9876
- "args": [],
9877
- "options": [
9878
- {
9879
- "flags": "--orbit <orbit>",
9880
- "description": "Parked orbit to acknowledge",
9881
- "required": true,
9882
- "valueHint": "orbit"
9883
- },
9884
- {
9885
- "flags": "--older-than <days>",
9886
- "description": "Only rows parked at least this many days",
9887
- "required": true,
9888
- "valueHint": "days"
9889
- },
9890
- {
9891
- "flags": "--dry-run",
9892
- "description": "List what would be acknowledged without writing",
9893
- "required": false,
9894
- "valueHint": null
9895
- }
9896
- ],
9507
+ {
9508
+ "id": "pan-parked",
9509
+ "path": ["parked"],
9510
+ "display": "/pan parked",
9511
+ "description": "List every issue parked in a stall orbit (operator gates, zombie sessions, idle-running agents), oldest first, with why + release condition",
9512
+ "args": [],
9513
+ "options": [{
9514
+ "flags": "--json",
9515
+ "description": "Print the raw parked rows as JSON",
9516
+ "required": false,
9517
+ "valueHint": null
9518
+ }],
9897
9519
  "aliases": [],
9898
9520
  "category": "CLI"
9899
9521
  },
@@ -10017,32 +9639,18 @@ const COMPOSER_COMMAND_MANIFEST = [
10017
9639
  "category": "Admin"
10018
9640
  },
10019
9641
  {
10020
- "id": "pan-admin-state",
10021
- "path": ["admin", "state"],
10022
- "display": "/pan admin state",
10023
- "description": "Permanent state administration",
10024
- "args": [],
10025
- "options": [],
10026
- "aliases": [],
10027
- "category": "Admin"
10028
- },
10029
- {
10030
- "id": "pan-admin-state-migrate",
10031
- "path": [
10032
- "admin",
10033
- "state",
10034
- "migrate"
10035
- ],
10036
- "display": "/pan admin state migrate",
10037
- "description": "Move permanent state to the orphan overdeck-state branch",
9642
+ "id": "pan-admin-seed-uat-fixtures",
9643
+ "path": ["admin", "seed-uat-fixtures"],
9644
+ "display": "/pan admin seed-uat-fixtures",
9645
+ "description": "Seed the obviously-fake FIX-1 issue fixture into a workspace container for UI UAT. Host mode: `pan admin seed-uat-fixtures <issue-id>` seeds and restarts that issue's workspace container from the host. `--local` runs the seed itself against the current OVERDECK_HOME — used by the host wrapper, or manually inside a container.",
10038
9646
  "args": [{
10039
- "name": "project",
10040
- "required": true,
9647
+ "name": "issue-id",
9648
+ "required": false,
10041
9649
  "variadic": false
10042
9650
  }],
10043
9651
  "options": [{
10044
- "flags": "--dry-run",
10045
- "description": "Print the exact migration plan without mutating anything",
9652
+ "flags": "--local",
9653
+ "description": "Seed the current (container-local) OVERDECK_HOME directly, without a host wrapper step",
10046
9654
  "required": false,
10047
9655
  "valueHint": null
10048
9656
  }],
@@ -10050,91 +9658,79 @@ const COMPOSER_COMMAND_MANIFEST = [
10050
9658
  "category": "Admin"
10051
9659
  },
10052
9660
  {
10053
- "id": "pan-admin-state-migrate-xbrief",
10054
- "path": [
10055
- "admin",
10056
- "state",
10057
- "migrate-xbrief"
10058
- ],
10059
- "display": "/pan admin state migrate-xbrief",
10060
- "description": "Rename state documents to .xbrief.json and migrate legacy envelopes",
9661
+ "id": "pan-admin-migrate-plan-home",
9662
+ "path": ["admin", "migrate-plan-home"],
9663
+ "display": "/pan admin migrate-plan-home",
9664
+ "description": "One-time bridge: copy open-issue planning artifacts and item progress from ~/.overdeck/state/<project>/ into <planHome>/.pan/ (PAN-3917 D8)",
10061
9665
  "args": [{
10062
- "name": "project",
9666
+ "name": "project-key",
10063
9667
  "required": true,
10064
9668
  "variadic": false
10065
9669
  }],
10066
- "options": [{
10067
- "flags": "--dry-run",
10068
- "description": "Print the exact xBRIEF migration plan without mutating anything",
10069
- "required": false,
10070
- "valueHint": null
10071
- }],
10072
- "aliases": [],
10073
- "category": "Admin"
10074
- },
10075
- {
10076
- "id": "pan-admin-state-backfill-agents",
10077
- "path": [
10078
- "admin",
10079
- "state",
10080
- "backfill-agents"
9670
+ "options": [
9671
+ {
9672
+ "flags": "--commit",
9673
+ "description": "Commit the copied artifacts in the plan home",
9674
+ "required": false,
9675
+ "valueHint": null
9676
+ },
9677
+ {
9678
+ "flags": "--dry-run",
9679
+ "description": "Preview what would be copied without writing anything",
9680
+ "required": false,
9681
+ "valueHint": null
9682
+ },
9683
+ {
9684
+ "flags": "--state-root <dir>",
9685
+ "description": "Override the state worktree root (tests / odd setups)",
9686
+ "required": true,
9687
+ "valueHint": "dir"
9688
+ },
9689
+ {
9690
+ "flags": "--plan-home <dir>",
9691
+ "description": "Override the plan home (tests / odd setups)",
9692
+ "required": true,
9693
+ "valueHint": "dir"
9694
+ },
9695
+ {
9696
+ "flags": "--open-issues <file>",
9697
+ "description": "Read open issue ids from a file instead of calling the tracker",
9698
+ "required": true,
9699
+ "valueHint": "file"
9700
+ }
10081
9701
  ],
10082
- "display": "/pan admin state backfill-agents",
10083
- "description": "Reconstruct durable agent runtime records from local and retained state",
10084
- "args": [{
10085
- "name": "project",
10086
- "required": false,
10087
- "variadic": false
10088
- }],
10089
- "options": [{
10090
- "flags": "--dry-run",
10091
- "description": "Report the records and sessions that would be written",
10092
- "required": false,
10093
- "valueHint": null
10094
- }],
10095
- "aliases": [],
10096
- "category": "Admin"
10097
- },
10098
- {
10099
- "id": "pan-admin-reconcile-labels",
10100
- "path": ["admin", "reconcile-labels"],
10101
- "display": "/pan admin reconcile-labels",
10102
- "description": "Reconcile pipeline labels from permanent issue truth",
10103
- "args": [],
10104
- "options": [{
10105
- "flags": "--dry-run",
10106
- "description": "Print changes without mutating labels",
10107
- "required": false,
10108
- "valueHint": null
10109
- }],
10110
9702
  "aliases": [],
10111
9703
  "category": "Admin"
10112
9704
  },
10113
9705
  {
10114
- "id": "pan-admin-migrate-legacy-agent-dirs",
10115
- "path": ["admin", "migrate-legacy-agent-dirs"],
10116
- "display": "/pan admin migrate-legacy-agent-dirs",
10117
- "description": "Copy pre-rebrand conv-* agent dirs into the configured Overdeck home without overwriting",
9706
+ "id": "pan-admin-agents",
9707
+ "path": ["admin", "agents"],
9708
+ "display": "/pan admin agents",
9709
+ "description": "Agent state plumbing",
10118
9710
  "args": [],
10119
9711
  "options": [],
10120
9712
  "aliases": [],
10121
9713
  "category": "Admin"
10122
9714
  },
10123
9715
  {
10124
- "id": "pan-admin-seed-uat-fixtures",
10125
- "path": ["admin", "seed-uat-fixtures"],
10126
- "display": "/pan admin seed-uat-fixtures",
10127
- "description": "Seed the obviously-fake FIX-1 issue fixture into a workspace container for UI UAT. Host mode: `pan admin seed-uat-fixtures <issue-id>` seeds and restarts that issue's workspace container from the host. `--local` runs the seed itself against the current OVERDECK_HOME — used by the host wrapper, or manually inside a container.",
9716
+ "id": "pan-admin-agents-exited",
9717
+ "path": [
9718
+ "admin",
9719
+ "agents",
9720
+ "exited"
9721
+ ],
9722
+ "display": "/pan admin agents exited",
9723
+ "description": "Record that an agent process exited (reported by its launcher; PAN-3848)",
10128
9724
  "args": [{
10129
- "name": "issue-id",
10130
- "required": false,
9725
+ "name": "agentId",
9726
+ "required": true,
10131
9727
  "variadic": false
10132
9728
  }],
10133
9729
  "options": [{
10134
- "flags": "--local",
10135
- "description": "Seed the current (container-local) OVERDECK_HOME directly, without a host wrapper step",
10136
- "required": false,
10137
- "valueHint": null
9730
+ "flags": "--code <n>",
9731
+ "description": "Process exit code",
9732
+ "required": true,
9733
+ "valueHint": "n"
10138
9734
  }],
10139
9735
  "aliases": [],
10140
9736
  "category": "Admin"
@@ -10210,53 +9806,6 @@ const COMPOSER_COMMAND_MANIFEST = [
10210
9806
  "aliases": [],
10211
9807
  "category": "Admin"
10212
9808
  },
10213
- {
10214
- "id": "pan-admin-cloister-brake",
10215
- "path": [
10216
- "admin",
10217
- "cloister",
10218
- "brake"
10219
- ],
10220
- "display": "/pan admin cloister brake",
10221
- "description": "Emergency brake - trim running work agents down to the concurrency cap (idle-first, resumable)",
10222
- "args": [],
10223
- "options": [{
10224
- "flags": "--json",
10225
- "description": "Output in JSON format",
10226
- "required": false,
10227
- "valueHint": null
10228
- }],
10229
- "aliases": [],
10230
- "category": "Admin"
10231
- },
10232
- {
10233
- "id": "pan-admin-cloister-freeze",
10234
- "path": [
10235
- "admin",
10236
- "cloister",
10237
- "freeze"
10238
- ],
10239
- "display": "/pan admin cloister freeze",
10240
- "description": "Globally pause the Deacon (patrols run but skip all actions); running agents unaffected",
10241
- "args": [],
10242
- "options": [],
10243
- "aliases": [],
10244
- "category": "Admin"
10245
- },
10246
- {
10247
- "id": "pan-admin-cloister-unfreeze",
10248
- "path": [
10249
- "admin",
10250
- "cloister",
10251
- "unfreeze"
10252
- ],
10253
- "display": "/pan admin cloister unfreeze",
10254
- "description": "Resume the Deacon from a global pause",
10255
- "args": [],
10256
- "options": [],
10257
- "aliases": [],
10258
- "category": "Admin"
10259
- },
10260
9809
  {
10261
9810
  "id": "pan-admin-specialists",
10262
9811
  "path": ["admin", "specialists"],
@@ -10345,7 +9894,7 @@ const COMPOSER_COMMAND_MANIFEST = [
10345
9894
  "done"
10346
9895
  ],
10347
9896
  "display": "/pan admin specialists done",
10348
- "description": "Signal specialist completion (deterministic status update)",
9897
+ "description": "Post a specialist verdict to the issue's pull/merge request (review, test, uat)",
10349
9898
  "args": [{
10350
9899
  "name": "type",
10351
9900
  "required": true,
@@ -10362,12 +9911,6 @@ const COMPOSER_COMMAND_MANIFEST = [
10362
9911
  "required": true,
10363
9912
  "valueHint": "status"
10364
9913
  },
10365
- {
10366
- "flags": "--item <itemId>",
10367
- "description": "xBRIEF item ID (required for inspect verdicts)",
10368
- "required": true,
10369
- "valueHint": "itemId"
10370
- },
10371
9914
  {
10372
9915
  "flags": "--notes <notes>",
10373
9916
  "description": "Optional notes about the result",
@@ -10731,30 +10274,6 @@ const COMPOSER_COMMAND_MANIFEST = [
10731
10274
  "aliases": [],
10732
10275
  "category": "Admin"
10733
10276
  },
10734
- {
10735
- "id": "pan-admin-db-rebuild-agents",
10736
- "path": [
10737
- "admin",
10738
- "db",
10739
- "rebuild-agents"
10740
- ],
10741
- "display": "/pan admin db rebuild-agents",
10742
- "description": "Rebuild the SQLite agents table from state.json rollback sources (PAN-1908)",
10743
- "args": [],
10744
- "options": [{
10745
- "flags": "--dry-run",
10746
- "description": "Show what would be backfilled without writing",
10747
- "required": false,
10748
- "valueHint": null
10749
- }, {
10750
- "flags": "--verbose",
10751
- "description": "Log each processed agent",
10752
- "required": false,
10753
- "valueHint": null
10754
- }],
10755
- "aliases": [],
10756
- "category": "Admin"
10757
- },
10758
10277
  {
10759
10278
  "id": "pan-admin-db-rebuild-workspaces",
10760
10279
  "path": [
@@ -10817,105 +10336,6 @@ const COMPOSER_COMMAND_MANIFEST = [
10817
10336
  "aliases": [],
10818
10337
  "category": "Admin"
10819
10338
  },
10820
- {
10821
- "id": "pan-admin-db-backfill-records",
10822
- "path": [
10823
- "admin",
10824
- "db",
10825
- "backfill-records"
10826
- ],
10827
- "display": "/pan admin db backfill-records",
10828
- "description": "Backfill per-issue permanent records into the infra repo (PAN-1908)",
10829
- "args": [],
10830
- "options": [
10831
- {
10832
- "flags": "--issue-id <id>",
10833
- "description": "Backfill only this issue",
10834
- "required": true,
10835
- "valueHint": "id"
10836
- },
10837
- {
10838
- "flags": "--force",
10839
- "description": "Overwrite records even if unchanged",
10840
- "required": false,
10841
- "valueHint": null
10842
- },
10843
- {
10844
- "flags": "--verbose",
10845
- "description": "Log each processed issue",
10846
- "required": false,
10847
- "valueHint": null
10848
- }
10849
- ],
10850
- "aliases": [],
10851
- "category": "Admin"
10852
- },
10853
- {
10854
- "id": "pan-admin-db-restore-verdicts",
10855
- "path": [
10856
- "admin",
10857
- "db",
10858
- "restore-verdicts"
10859
- ],
10860
- "display": "/pan admin db restore-verdicts",
10861
- "description": "Rebuild review_status verdicts from per-issue records + live GitHub PR state (PAN-1922)",
10862
- "args": [],
10863
- "options": [
10864
- {
10865
- "flags": "--issue-id <id>",
10866
- "description": "Restore only this issue",
10867
- "required": true,
10868
- "valueHint": "id"
10869
- },
10870
- {
10871
- "flags": "--dry-run",
10872
- "description": "Show what would be restored without writing",
10873
- "required": false,
10874
- "valueHint": null
10875
- },
10876
- {
10877
- "flags": "--verbose",
10878
- "description": "Log each processed issue",
10879
- "required": false,
10880
- "valueHint": null
10881
- }
10882
- ],
10883
- "aliases": [],
10884
- "category": "Admin"
10885
- },
10886
- {
10887
- "id": "pan-admin-db-reconcile-merges",
10888
- "path": [
10889
- "admin",
10890
- "db",
10891
- "reconcile-merges"
10892
- ],
10893
- "display": "/pan admin db reconcile-merges",
10894
- "description": "Backfill fulfilled merge state from tracked PR and branch ancestry evidence (PAN-2311)",
10895
- "args": [],
10896
- "options": [
10897
- {
10898
- "flags": "--issue-id <id>",
10899
- "description": "Reconcile only this issue",
10900
- "required": true,
10901
- "valueHint": "id"
10902
- },
10903
- {
10904
- "flags": "--dry-run",
10905
- "description": "Show what would be reconciled without writing",
10906
- "required": false,
10907
- "valueHint": null
10908
- },
10909
- {
10910
- "flags": "--verbose",
10911
- "description": "Log each processed issue",
10912
- "required": false,
10913
- "valueHint": null
10914
- }
10915
- ],
10916
- "aliases": [],
10917
- "category": "Admin"
10918
- },
10919
10339
  {
10920
10340
  "id": "pan-admin-config",
10921
10341
  "path": ["admin", "config"],
@@ -11754,47 +11174,20 @@ const COMPOSER_COMMAND_MANIFEST = [
11754
11174
  "valueHint": null
11755
11175
  },
11756
11176
  {
11757
- "flags": "--skip-tts-daemon",
11758
- "description": "Skip Qwen TTS daemon venv install (CUDA torch download is large)",
11759
- "required": false,
11760
- "valueHint": null
11761
- }
11762
- ],
11763
- "aliases": [],
11764
- "category": "Core"
11765
- },
11766
- {
11767
- "id": "pan-inspect",
11768
- "path": ["inspect"],
11769
- "display": "/pan inspect",
11770
- "description": "Request inspection of a completed xBRIEF item before proceeding to the next",
11771
- "args": [{
11772
- "name": "issueId",
11773
- "required": true,
11774
- "variadic": false
11775
- }],
11776
- "options": [
11777
- {
11778
- "flags": "--item <itemId>",
11779
- "description": "xBRIEF item ID to inspect",
11780
- "required": true,
11781
- "valueHint": "itemId"
11782
- },
11783
- {
11784
- "flags": "--workspace <path>",
11785
- "description": "Workspace path (auto-detected if not provided)",
11786
- "required": true,
11787
- "valueHint": "path"
11788
- },
11789
- {
11790
- "flags": "--deep",
11791
- "description": "Use the deep inspection sub-role",
11177
+ "flags": "--skip-tts-daemon",
11178
+ "description": "Skip Qwen TTS daemon venv install (CUDA torch download is large)",
11179
+ "required": false,
11180
+ "valueHint": null
11181
+ },
11182
+ {
11183
+ "flags": "--skip-herdr",
11184
+ "description": "Skip Herdr terminal backend install/verify (tmux-only hosts)",
11792
11185
  "required": false,
11793
11186
  "valueHint": null
11794
11187
  }
11795
11188
  ],
11796
11189
  "aliases": [],
11797
- "category": "Lifecycle"
11190
+ "category": "Core"
11798
11191
  },
11799
11192
  {
11800
11193
  "id": "pan-caveman-compress",
@@ -11950,111 +11343,86 @@ const COMPOSER_COMMAND_MANIFEST = [
11950
11343
  "category": "Lifecycle"
11951
11344
  },
11952
11345
  {
11953
- "id": "pan-flywheel",
11954
- "path": ["flywheel"],
11955
- "display": "/pan flywheel",
11956
- "description": "Flywheel orchestrator lifecycle and status helpers",
11957
- "args": [],
11958
- "options": [],
11959
- "aliases": [],
11960
- "category": "Flywheel"
11961
- },
11962
- {
11963
- "id": "pan-flywheel-merge-blockers",
11964
- "path": ["flywheel", "merge-blockers"],
11965
- "display": "/pan flywheel merge-blockers",
11966
- "description": "PRs that passed review but cannot merge (GitHub-native reasons) — reads SQLite directly, no HTTP (sandbox-safe)",
11967
- "args": [],
11968
- "options": [{
11969
- "flags": "--json",
11970
- "description": "Output JSON",
11971
- "required": false,
11972
- "valueHint": null
11973
- }],
11974
- "aliases": [],
11975
- "category": "Flywheel"
11976
- },
11977
- {
11978
- "id": "pan-flywheel-weights",
11979
- "path": ["flywheel", "weights"],
11980
- "display": "/pan flywheel weights",
11981
- "description": "Weighted substrate bugs by affected v1.0 criterion — reads SQLite directly, no HTTP (sandbox-safe)",
11346
+ "id": "pan-spawn",
11347
+ "path": ["spawn"],
11348
+ "display": "/pan spawn",
11349
+ "description": "Create a worker pane for one xBRIEF item in the issue workspace",
11982
11350
  "args": [],
11983
11351
  "options": [
11984
11352
  {
11985
11353
  "flags": "--issue <id>",
11986
- "description": "Filter to a single issue",
11354
+ "description": "Issue the worker belongs to",
11987
11355
  "required": true,
11988
11356
  "valueHint": "id"
11989
11357
  },
11990
11358
  {
11991
- "flags": "--window <dur>",
11992
- "description": "Stats window like 30d, 7d (default 30d)",
11359
+ "flags": "--item <item>",
11360
+ "description": "xBRIEF item the worker takes",
11993
11361
  "required": true,
11994
- "valueHint": "dur"
11362
+ "valueHint": "item"
11995
11363
  },
11996
11364
  {
11997
- "flags": "--json",
11998
- "description": "Output JSON",
11999
- "required": false,
12000
- "valueHint": null
11365
+ "flags": "--model <model>",
11366
+ "description": "Model the worker runs on",
11367
+ "required": true,
11368
+ "valueHint": "model"
11369
+ },
11370
+ {
11371
+ "flags": "--harness <harness>",
11372
+ "description": "Coding-agent harness (default: claude-code)",
11373
+ "required": true,
11374
+ "valueHint": "harness"
12001
11375
  }
12002
11376
  ],
12003
11377
  "aliases": [],
12004
- "category": "Flywheel"
11378
+ "category": "CLI"
12005
11379
  },
12006
11380
  {
12007
- "id": "pan-flywheel-start",
12008
- "path": ["flywheel", "start"],
12009
- "display": "/pan flywheel start",
12010
- "description": "Start the Flywheel orchestrator",
11381
+ "id": "pan-flywheel",
11382
+ "path": ["flywheel"],
11383
+ "display": "/pan flywheel",
11384
+ "description": "Start, stop, or check the flywheel conversation",
12011
11385
  "args": [],
12012
- "options": [{
12013
- "flags": "--brief <path>",
12014
- "description": "Path to the Flywheel brief",
12015
- "required": true,
12016
- "valueHint": "path"
12017
- }, {
12018
- "flags": "--orders <book-id>",
12019
- "description": "Bind the run to a validated order book",
12020
- "required": true,
12021
- "valueHint": "book-id"
12022
- }],
11386
+ "options": [],
12023
11387
  "aliases": [],
12024
11388
  "category": "Flywheel"
12025
11389
  },
12026
11390
  {
12027
- "id": "pan-flywheel-emit-status",
12028
- "path": ["flywheel", "emit-status"],
12029
- "display": "/pan flywheel emit-status",
12030
- "description": "Validate and publish a FlywheelStatus JSON snapshot to the local dashboard",
11391
+ "id": "pan-flywheel-start",
11392
+ "path": ["flywheel", "start"],
11393
+ "display": "/pan flywheel start",
11394
+ "description": "Launch a conversation running /pan-flywheel",
12031
11395
  "args": [],
12032
- "options": [{
12033
- "flags": "--file <path>",
12034
- "description": "Path to FlywheelStatus JSON, or - to read from stdin",
12035
- "required": true,
12036
- "valueHint": "path"
12037
- }],
11396
+ "options": [
11397
+ {
11398
+ "flags": "--model <model>",
11399
+ "description": "Model for the flywheel conversation",
11400
+ "required": true,
11401
+ "valueHint": "model"
11402
+ },
11403
+ {
11404
+ "flags": "--harness <harness>",
11405
+ "description": "Harness for the flywheel conversation",
11406
+ "required": true,
11407
+ "valueHint": "harness"
11408
+ },
11409
+ {
11410
+ "flags": "--cwd <path>",
11411
+ "description": "Working directory (default: cwd)",
11412
+ "required": true,
11413
+ "valueHint": "path"
11414
+ }
11415
+ ],
12038
11416
  "aliases": [],
12039
11417
  "category": "Flywheel"
12040
11418
  },
12041
11419
  {
12042
- "id": "pan-flywheel-config",
12043
- "path": ["flywheel", "config"],
12044
- "display": "/pan flywheel config",
12045
- "description": "Get or set Flywheel autonomy configuration",
11420
+ "id": "pan-flywheel-stop",
11421
+ "path": ["flywheel", "stop"],
11422
+ "display": "/pan flywheel stop",
11423
+ "description": "Stop the flywheel conversation",
12046
11424
  "args": [],
12047
- "options": [{
12048
- "flags": "--get [key]",
12049
- "description": "Print Flywheel config values",
12050
- "required": false,
12051
- "valueHint": "key"
12052
- }, {
12053
- "flags": "--set <key=value>",
12054
- "description": "Set a Flywheel config boolean",
12055
- "required": true,
12056
- "valueHint": "key=value"
12057
- }],
11425
+ "options": [],
12058
11426
  "aliases": [],
12059
11427
  "category": "Flywheel"
12060
11428
  },
@@ -12062,107 +11430,17 @@ const COMPOSER_COMMAND_MANIFEST = [
12062
11430
  "id": "pan-flywheel-status",
12063
11431
  "path": ["flywheel", "status"],
12064
11432
  "display": "/pan flywheel status",
12065
- "description": "Show the active Flywheel run status",
12066
- "args": [],
12067
- "options": [{
12068
- "flags": "--json",
12069
- "description": "Emit the raw FlywheelStatus JSON",
12070
- "required": false,
12071
- "valueHint": null
12072
- }],
12073
- "aliases": [],
12074
- "category": "Flywheel"
12075
- },
12076
- {
12077
- "id": "pan-flywheel-stats",
12078
- "path": ["flywheel", "stats"],
12079
- "display": "/pan flywheel stats",
12080
- "description": "Show Flywheel v1.0 readiness stats",
11433
+ "description": "Say whether the flywheel conversation is running",
12081
11434
  "args": [],
12082
11435
  "options": [{
12083
- "flags": "--window <duration>",
12084
- "description": "Stats window duration",
12085
- "required": true,
12086
- "valueHint": "duration"
12087
- }, {
12088
11436
  "flags": "--json",
12089
- "description": "Emit the raw FlywheelStats JSON",
12090
- "required": false,
12091
- "valueHint": null
12092
- }],
12093
- "aliases": [],
12094
- "category": "Flywheel"
12095
- },
12096
- {
12097
- "id": "pan-flywheel-pause",
12098
- "path": ["flywheel", "pause"],
12099
- "display": "/pan flywheel pause",
12100
- "description": "Pause the active Flywheel orchestrator run",
12101
- "args": [],
12102
- "options": [],
12103
- "aliases": [],
12104
- "category": "Flywheel"
12105
- },
12106
- {
12107
- "id": "pan-flywheel-resume",
12108
- "path": ["flywheel", "resume"],
12109
- "display": "/pan flywheel resume",
12110
- "description": "Resume the paused Flywheel orchestrator run",
12111
- "args": [],
12112
- "options": [],
12113
- "aliases": [],
12114
- "category": "Flywheel"
12115
- },
12116
- {
12117
- "id": "pan-flywheel-report",
12118
- "path": ["flywheel", "report"],
12119
- "display": "/pan flywheel report",
12120
- "description": "Finalize the active Flywheel run: write report.md, compact over-threshold FLYWHEEL-STATE.md history, commit State changes, and clear the active-run gate. Refuses to run while the orchestrator session is alive (pause or abort first).",
12121
- "args": [],
12122
- "options": [{
12123
- "flags": "--force",
12124
- "description": "Bypass the orchestrator-alive guard. Intended for the orchestrator role's own end-of-run call.",
12125
- "required": false,
12126
- "valueHint": null
12127
- }],
12128
- "aliases": [],
12129
- "category": "Flywheel"
12130
- },
12131
- {
12132
- "id": "pan-flywheel-complete",
12133
- "path": ["flywheel", "complete"],
12134
- "display": "/pan flywheel complete",
12135
- "description": "Complete a drained order-book run, write its report and retrospective, then continue mechanically",
12136
- "args": [],
12137
- "options": [{
12138
- "flags": "--force",
12139
- "description": "Complete even when the order book still has non-terminal items",
11437
+ "description": "Output as JSON",
12140
11438
  "required": false,
12141
11439
  "valueHint": null
12142
11440
  }],
12143
11441
  "aliases": [],
12144
11442
  "category": "Flywheel"
12145
11443
  },
12146
- {
12147
- "id": "pan-flywheel-stop",
12148
- "path": ["flywheel", "stop"],
12149
- "display": "/pan flywheel stop",
12150
- "description": "Stop the Flywheel orchestrator gracefully: kill any live session, write report.md, commit FLYWHEEL-STATE.md changes, and clear the active-run gate",
12151
- "args": [],
12152
- "options": [],
12153
- "aliases": [],
12154
- "category": "Flywheel"
12155
- },
12156
- {
12157
- "id": "pan-flywheel-abort",
12158
- "path": ["flywheel", "abort"],
12159
- "display": "/pan flywheel abort",
12160
- "description": "Discard the active Flywheel run without writing a report",
12161
- "args": [],
12162
- "options": [],
12163
- "aliases": [],
12164
- "category": "Flywheel"
12165
- },
12166
11444
  {
12167
11445
  "id": "pan-merge",
12168
11446
  "path": ["merge"],
@@ -12743,11 +12021,75 @@ const COMPOSER_COMMAND_MANIFEST = [
12743
12021
  "description": "Rally project OID (e.g., /project/822404704163)",
12744
12022
  "required": true,
12745
12023
  "valueHint": "oid"
12024
+ },
12025
+ {
12026
+ "flags": "--dry-run",
12027
+ "description": "Validate without creating (resolve-before-create pattern)",
12028
+ "required": false,
12029
+ "valueHint": null
12030
+ }
12031
+ ],
12032
+ "aliases": [],
12033
+ "category": "Project"
12034
+ },
12035
+ {
12036
+ "id": "pan-project-clone",
12037
+ "path": ["project", "clone"],
12038
+ "display": "/pan project clone",
12039
+ "description": "Clone a GitHub or GitLab repository and register it as a project",
12040
+ "args": [{
12041
+ "name": "url",
12042
+ "required": true,
12043
+ "variadic": false
12044
+ }],
12045
+ "options": [
12046
+ {
12047
+ "flags": "--parent <dir>",
12048
+ "description": "Parent directory (default: ~/Projects)",
12049
+ "required": true,
12050
+ "valueHint": "dir"
12051
+ },
12052
+ {
12053
+ "flags": "--name <name>",
12054
+ "description": "Project name (default: repository name)",
12055
+ "required": true,
12056
+ "valueHint": "name"
12057
+ },
12058
+ {
12059
+ "flags": "--issue-prefix <prefix>",
12060
+ "description": "Issue prefix (default: derived from the name)",
12061
+ "required": true,
12062
+ "valueHint": "prefix"
12063
+ },
12064
+ {
12065
+ "flags": "--dry-run",
12066
+ "description": "Print the resolved intent as JSON and create nothing",
12067
+ "required": false,
12068
+ "valueHint": null
12746
12069
  }
12747
12070
  ],
12748
12071
  "aliases": [],
12749
12072
  "category": "Project"
12750
12073
  },
12074
+ {
12075
+ "id": "pan-project-finish-setup",
12076
+ "path": ["project", "finish-setup"],
12077
+ "display": "/pan project finish-setup",
12078
+ "description": "Finish setup for a registered project whose creation did not complete",
12079
+ "args": [{
12080
+ "name": "key",
12081
+ "required": true,
12082
+ "variadic": false
12083
+ }],
12084
+ "options": [{
12085
+ "flags": "--path <path>",
12086
+ "description": "Expected project path; refuses if it does not match the registration",
12087
+ "required": true,
12088
+ "valueHint": "path"
12089
+ }],
12090
+ "aliases": [],
12091
+ "category": "Project"
12092
+ },
12751
12093
  {
12752
12094
  "id": "pan-project-list",
12753
12095
  "path": ["project", "list"],
@@ -12887,11 +12229,75 @@ const COMPOSER_COMMAND_MANIFEST = [
12887
12229
  "description": "Rally project OID (e.g., /project/822404704163)",
12888
12230
  "required": true,
12889
12231
  "valueHint": "oid"
12232
+ },
12233
+ {
12234
+ "flags": "--dry-run",
12235
+ "description": "Validate without creating (resolve-before-create pattern)",
12236
+ "required": false,
12237
+ "valueHint": null
12238
+ }
12239
+ ],
12240
+ "aliases": [],
12241
+ "category": "Project"
12242
+ },
12243
+ {
12244
+ "id": "pan-projects-clone",
12245
+ "path": ["projects", "clone"],
12246
+ "display": "/pan projects clone",
12247
+ "description": "Clone a GitHub or GitLab repository and register it as a project",
12248
+ "args": [{
12249
+ "name": "url",
12250
+ "required": true,
12251
+ "variadic": false
12252
+ }],
12253
+ "options": [
12254
+ {
12255
+ "flags": "--parent <dir>",
12256
+ "description": "Parent directory (default: ~/Projects)",
12257
+ "required": true,
12258
+ "valueHint": "dir"
12259
+ },
12260
+ {
12261
+ "flags": "--name <name>",
12262
+ "description": "Project name (default: repository name)",
12263
+ "required": true,
12264
+ "valueHint": "name"
12265
+ },
12266
+ {
12267
+ "flags": "--issue-prefix <prefix>",
12268
+ "description": "Issue prefix (default: derived from the name)",
12269
+ "required": true,
12270
+ "valueHint": "prefix"
12271
+ },
12272
+ {
12273
+ "flags": "--dry-run",
12274
+ "description": "Print the resolved intent as JSON and create nothing",
12275
+ "required": false,
12276
+ "valueHint": null
12890
12277
  }
12891
12278
  ],
12892
12279
  "aliases": [],
12893
12280
  "category": "Project"
12894
12281
  },
12282
+ {
12283
+ "id": "pan-projects-finish-setup",
12284
+ "path": ["projects", "finish-setup"],
12285
+ "display": "/pan projects finish-setup",
12286
+ "description": "Finish setup for a registered project whose creation did not complete",
12287
+ "args": [{
12288
+ "name": "key",
12289
+ "required": true,
12290
+ "variadic": false
12291
+ }],
12292
+ "options": [{
12293
+ "flags": "--path <path>",
12294
+ "description": "Expected project path; refuses if it does not match the registration",
12295
+ "required": true,
12296
+ "valueHint": "path"
12297
+ }],
12298
+ "aliases": [],
12299
+ "category": "Project"
12300
+ },
12895
12301
  {
12896
12302
  "id": "pan-projects-list",
12897
12303
  "path": ["projects", "list"],
@@ -13355,14 +12761,6 @@ const COMPOSER_COMMAND_VARIANTS = [
13355
12761
  "insert": "/pan plan --auto --auto-start ",
13356
12762
  "category": "Lifecycle"
13357
12763
  },
13358
- {
13359
- "id": "pan-review-reset-session",
13360
- "path": ["review", "reset"],
13361
- "display": "/pan review reset --session",
13362
- "description": "Reset review and clear saved Claude session",
13363
- "insert": "/pan review reset --session",
13364
- "category": "Review"
13365
- },
13366
12764
  {
13367
12765
  "id": "pan-fork-plain",
13368
12766
  "path": ["fork"],
@@ -13497,7 +12895,26 @@ const HOOK_INVENTORY = [
13497
12895
  const WIRED_HOOK_INVENTORY = HOOK_INVENTORY.filter((hook) => hook.wired);
13498
12896
  const WIRED_HOOK_NAMES = WIRED_HOOK_INVENTORY.map((hook) => hook.name);
13499
12897
  //#endregion
12898
+ //#region src/terminal-backend.ts
12899
+ const TERMINAL_BACKEND_NAMES = ["herdr", "tmux"];
12900
+ const AGENT_ROLES = [
12901
+ "work",
12902
+ "worker",
12903
+ "review",
12904
+ "test",
12905
+ "uat",
12906
+ "strike",
12907
+ "plan"
12908
+ ];
12909
+ function isTerminalBackendName(value) {
12910
+ return typeof value === "string" && TERMINAL_BACKEND_NAMES.includes(value);
12911
+ }
12912
+ function isAgentRole(value) {
12913
+ return typeof value === "string" && AGENT_ROLES.includes(value);
12914
+ }
12915
+ //#endregion
13500
12916
  exports.ACP_BEHAVIOR = ACP_BEHAVIOR;
12917
+ exports.AGENT_ROLES = AGENT_ROLES;
13501
12918
  exports.Activity = Activity;
13502
12919
  exports.ActivityDetailedEvent = ActivityDetailedEvent;
13503
12920
  exports.ActivityEntryEvent = ActivityEntryEvent;
@@ -13556,6 +12973,9 @@ exports.ArtifactUrls = ArtifactUrls;
13556
12973
  exports.ArtifactValidationCode = ArtifactValidationCode;
13557
12974
  exports.ArtifactValidationFinding = ArtifactValidationFinding;
13558
12975
  exports.ArtifactValidationResult = ArtifactValidationResult;
12976
+ exports.BackendPane = BackendPane;
12977
+ exports.BackendPaneChangedEvent = BackendPaneChangedEvent;
12978
+ exports.BackendPaneRemovedEvent = BackendPaneRemovedEvent;
13559
12979
  exports.BeadsFreshnessChangedEvent = BeadsFreshnessChangedEvent;
13560
12980
  exports.CHANNEL_REPLY_KIND_VALUES = CHANNEL_REPLY_KIND_VALUES;
13561
12981
  exports.CLAUDE_CODE_BEHAVIOR = CLAUDE_CODE_BEHAVIOR;
@@ -13607,6 +13027,9 @@ exports.DashboardLifecycleStartedEvent = DashboardLifecycleStartedEvent;
13607
13027
  exports.DashboardSnapshot = DashboardSnapshot;
13608
13028
  exports.DeepWipeRpc = DeepWipeRpc;
13609
13029
  exports.DeployStalenessSnapshot = DeployStalenessSnapshot;
13030
+ exports.DerivedBranchState = DerivedBranchState;
13031
+ exports.DerivedIssueState = DerivedIssueState;
13032
+ exports.DerivedPrState = DerivedPrState;
13610
13033
  exports.DiscoveredSessionSnapshot = DiscoveredSessionSnapshot;
13611
13034
  exports.DomainEvent = DomainEvent;
13612
13035
  exports.EDITORS = EDITORS;
@@ -13659,7 +13082,6 @@ exports.GetConversationStatsRpc = GetConversationStatsRpc;
13659
13082
  exports.GetDiscoveredSessionRpc = GetDiscoveredSessionRpc;
13660
13083
  exports.GetSessionsFeedFacetsRpc = GetSessionsFeedFacetsRpc;
13661
13084
  exports.GetSnapshotRpc = GetSnapshotRpc;
13662
- exports.GetWorkspaceDetailRpc = GetWorkspaceDetailRpc;
13663
13085
  exports.GlobalContextLayerRecord = GlobalContextLayerRecord;
13664
13086
  exports.GlobalContextLayerTarget = GlobalContextLayerTarget;
13665
13087
  exports.HOOK_INVENTORY = HOOK_INVENTORY;
@@ -13671,7 +13093,13 @@ exports.HygieneFinding = HygieneFinding;
13671
13093
  exports.HygienePullRequest = HygienePullRequest;
13672
13094
  exports.HygieneReport = HygieneReport;
13673
13095
  exports.INITIAL_READ_MODEL_STATE = INITIAL_READ_MODEL_STATE;
13096
+ exports.ISSUE_ATTENTIONS = ISSUE_ATTENTIONS;
13097
+ exports.ISSUE_STATES = ISSUE_STATES;
13098
+ exports.ISSUE_STATE_PRECEDENCE = ISSUE_STATE_PRECEDENCE;
13099
+ exports.IssueAttention = IssueAttention;
13674
13100
  exports.IssueId = IssueId;
13101
+ exports.IssueState = IssueState;
13102
+ exports.IssueStateChangedEvent = IssueStateChangedEvent;
13675
13103
  exports.IssueStatusChangedEvent = IssueStatusChangedEvent;
13676
13104
  exports.IssueTransitionedEvent = IssueTransitionedEvent;
13677
13105
  exports.IssuesDeltaEvent = IssuesDeltaEvent;
@@ -13705,7 +13133,6 @@ exports.MemoryStatusPhase = MemoryStatusPhase;
13705
13133
  exports.MemoryStatusUpdatedEvent = MemoryStatusUpdatedEvent;
13706
13134
  exports.MemoryTokenUsage = MemoryTokenUsage;
13707
13135
  exports.MergeReadyEvent = MergeReadyEvent;
13708
- exports.MergeStatusValue = MergeStatusValue;
13709
13136
  exports.ModelOrigin = ModelOrigin;
13710
13137
  exports.ModelOriginEntry = ModelOriginEntry;
13711
13138
  exports.OHMYPI_BEHAVIOR = OHMYPI_BEHAVIOR;
@@ -13726,7 +13153,6 @@ exports.PanRpcGroup = PanRpcGroup;
13726
13153
  exports.PendingTurn = PendingTurn;
13727
13154
  exports.PipelineReviewCompletedEvent = PipelineReviewCompletedEvent;
13728
13155
  exports.PipelineReviewStartedEvent = PipelineReviewStartedEvent;
13729
- exports.PipelineStatusChangedEvent = PipelineStatusChangedEvent;
13730
13156
  exports.PipelineTestCompletedEvent = PipelineTestCompletedEvent;
13731
13157
  exports.PipelineTestStartedEvent = PipelineTestStartedEvent;
13732
13158
  exports.PipelineVerificationFailedEvent = PipelineVerificationFailedEvent;
@@ -13737,6 +13163,8 @@ exports.PlanSubitemStatusChangedEvent = PlanSubitemStatusChangedEvent;
13737
13163
  exports.PlanningFailedEvent = PlanningFailedEvent;
13738
13164
  exports.PlanningStartedEvent = PlanningStartedEvent;
13739
13165
  exports.PlanningSyncEvent = PlanningSyncEvent;
13166
+ exports.PrChecksState = PrChecksState;
13167
+ exports.PrReviewState = PrReviewState;
13740
13168
  exports.ProjectCiHeadObservedEvent = ProjectCiHeadObservedEvent;
13741
13169
  exports.ProjectCiSnapshot = ProjectCiSnapshot;
13742
13170
  exports.ProjectCiSuite = ProjectCiSuite;
@@ -13753,7 +13181,6 @@ exports.ReadFileAtPathRpc = ReadFileAtPathRpc;
13753
13181
  exports.ReadWorkspaceFileInput = ReadWorkspaceFileInput;
13754
13182
  exports.ReadWorkspaceFileResult = ReadWorkspaceFileResult;
13755
13183
  exports.ReadWorkspaceFileRpc = ReadWorkspaceFileRpc;
13756
- exports.ReleaseStatusValue = ReleaseStatusValue;
13757
13184
  exports.ReplayEventsRpc = ReplayEventsRpc;
13758
13185
  exports.ResetMarker = ResetMarker;
13759
13186
  exports.ResetMarkerScope = ResetMarkerScope;
@@ -13771,13 +13198,9 @@ exports.RestartGateSnapshot = RestartGateSnapshot;
13771
13198
  exports.ReviewApprovedEvent = ReviewApprovedEvent;
13772
13199
  exports.ReviewCoordinatorDiedEvent = ReviewCoordinatorDiedEvent;
13773
13200
  exports.ReviewCoordinatorStartedEvent = ReviewCoordinatorStartedEvent;
13774
- exports.ReviewCycleEntry = ReviewCycleEntry;
13775
13201
  exports.ReviewReviewerCompletedEvent = ReviewReviewerCompletedEvent;
13776
13202
  exports.ReviewReviewerStartedEvent = ReviewReviewerStartedEvent;
13777
13203
  exports.ReviewSpecialistTimedOutEvent = ReviewSpecialistTimedOutEvent;
13778
- exports.ReviewStatusChangedEvent = ReviewStatusChangedEvent;
13779
- exports.ReviewStatusSnapshot = ReviewStatusSnapshot;
13780
- exports.ReviewStatusValue = ReviewStatusValue;
13781
13204
  exports.ReviewVerdictDispatchedEvent = ReviewVerdictDispatchedEvent;
13782
13205
  exports.ReviewVerdictRejectedEvent = ReviewVerdictRejectedEvent;
13783
13206
  exports.ReviewVerdictRestoreBlockedEvent = ReviewVerdictRestoreBlockedEvent;
@@ -13814,7 +13237,6 @@ exports.SubagentSummary = SubagentSummary;
13814
13237
  exports.SubscribeAgentOutputRpc = SubscribeAgentOutputRpc;
13815
13238
  exports.SubscribeConversationMessagesRpc = SubscribeConversationMessagesRpc;
13816
13239
  exports.SubscribeDomainEventsRpc = SubscribeDomainEventsRpc;
13817
- exports.SubscribeFlywheelStatusRpc = SubscribeFlywheelStatusRpc;
13818
13240
  exports.SubscribeIssueEventsRpc = SubscribeIssueEventsRpc;
13819
13241
  exports.SubscribeProjectSessionTreeRpc = SubscribeProjectSessionTreeRpc;
13820
13242
  exports.SubscribeTerminalRpc = SubscribeTerminalRpc;
@@ -13830,18 +13252,16 @@ exports.TELEMETRY_CLI_VERBS = TELEMETRY_CLI_VERBS;
13830
13252
  exports.TELEMETRY_EVENT_CATALOG = TELEMETRY_EVENT_CATALOG;
13831
13253
  exports.TELEMETRY_EVENT_NAMES = TELEMETRY_EVENT_NAMES;
13832
13254
  exports.TELEMETRY_PROPERTY_DOMAINS = TELEMETRY_PROPERTY_DOMAINS;
13255
+ exports.TERMINAL_BACKEND_NAMES = TERMINAL_BACKEND_NAMES;
13833
13256
  exports.TerminalCloseRpc = TerminalCloseRpc;
13834
13257
  exports.TerminalOpenRpc = TerminalOpenRpc;
13835
13258
  exports.TerminalOutput = TerminalOutput;
13836
13259
  exports.TerminalResizeRpc = TerminalResizeRpc;
13837
13260
  exports.TerminalWriteRpc = TerminalWriteRpc;
13838
13261
  exports.TestPassedEvent = TestPassedEvent;
13839
- exports.TestStatusValue = TestStatusValue;
13840
13262
  exports.ThinkingState = ThinkingState;
13841
13263
  exports.TurnDiffFileChange = TurnDiffFileChange;
13842
13264
  exports.TurnDiffSummary = TurnDiffSummary;
13843
- exports.UatStatusValue = UatStatusValue;
13844
- exports.VerificationStatusValue = VerificationStatusValue;
13845
13265
  exports.WIRED_HOOK_INVENTORY = WIRED_HOOK_INVENTORY;
13846
13266
  exports.WIRED_HOOK_NAMES = WIRED_HOOK_NAMES;
13847
13267
  exports.WS_METHODS = WS_METHODS;
@@ -13856,7 +13276,6 @@ exports.WorkspaceContextLayerTarget = WorkspaceContextLayerTarget;
13856
13276
  exports.WorkspaceCreatedEvent = WorkspaceCreatedEvent;
13857
13277
  exports.WorkspaceDeletedEvent = WorkspaceDeletedEvent;
13858
13278
  exports.WorkspaceDestroyedEvent = WorkspaceDestroyedEvent;
13859
- exports.WorkspaceDetail = WorkspaceDetail;
13860
13279
  exports.WorkspaceWipeStartedEvent = WorkspaceWipeStartedEvent;
13861
13280
  exports.WriteFileAtPathInput = WriteFileAtPathInput;
13862
13281
  exports.WriteFileAtPathResult = WriteFileAtPathResult;
@@ -13874,7 +13293,12 @@ exports.getHarnessBehavior = getHarnessBehavior;
13874
13293
  exports.getMaxMemoryObservationsPerIssue = getMaxMemoryObservationsPerIssue;
13875
13294
  exports.getMaxTurnDiffSummariesPerAgent = getMaxTurnDiffSummariesPerAgent;
13876
13295
  exports.getRuntimeBehavior = getRuntimeBehavior;
13296
+ exports.isAgentRole = isAgentRole;
13297
+ exports.isAgentSessionName = isAgentSessionName;
13877
13298
  exports.isChannelReplyKind = isChannelReplyKind;
13299
+ exports.isIssueAttention = isIssueAttention;
13300
+ exports.isIssueState = isIssueState;
13301
+ exports.isTerminalBackendName = isTerminalBackendName;
13878
13302
  exports.isTerminalTurnDiffSummaryStatus = isTerminalTurnDiffSummaryStatus;
13879
13303
  exports.normalizeChannelReplyPayload = normalizeChannelReplyPayload;
13880
13304
  exports.omitTurnDiffSummariesForAgent = omitTurnDiffSummariesForAgent;