@h-rig/cli 0.0.6-alpha.83 → 0.0.6-alpha.85

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.
Files changed (163) hide show
  1. package/dist/bin/rig.js +22060 -14620
  2. package/dist/src/app/board.js +155 -28
  3. package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
  4. package/dist/src/app-opentui/adapters/doctor.js +1 -25
  5. package/dist/src/app-opentui/adapters/family.d.ts +62 -0
  6. package/dist/src/app-opentui/adapters/family.js +14305 -0
  7. package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
  8. package/dist/src/app-opentui/adapters/fleet.js +6 -40
  9. package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
  10. package/dist/src/app-opentui/adapters/inbox.js +54 -59
  11. package/dist/src/app-opentui/adapters/init.d.ts +0 -2
  12. package/dist/src/app-opentui/adapters/init.js +0 -26
  13. package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
  14. package/dist/src/app-opentui/adapters/inspect.js +1024 -0
  15. package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
  16. package/dist/src/app-opentui/adapters/pi-attach.js +348 -93
  17. package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
  18. package/dist/src/app-opentui/adapters/pi.js +363 -0
  19. package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
  20. package/dist/src/app-opentui/adapters/plugin.js +544 -0
  21. package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
  22. package/dist/src/app-opentui/adapters/repo.js +186 -0
  23. package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
  24. package/dist/src/app-opentui/adapters/run-detail.js +97 -44
  25. package/dist/src/app-opentui/adapters/server.d.ts +10 -2
  26. package/dist/src/app-opentui/adapters/server.js +96 -27
  27. package/dist/src/app-opentui/adapters/tasks.d.ts +0 -2
  28. package/dist/src/app-opentui/adapters/tasks.js +437 -105
  29. package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
  30. package/dist/src/app-opentui/adapters/workspace.js +333 -0
  31. package/dist/src/app-opentui/autocomplete.d.ts +20 -0
  32. package/dist/src/app-opentui/autocomplete.js +576 -0
  33. package/dist/src/app-opentui/bootstrap.js +24313 -16963
  34. package/dist/src/app-opentui/command-palette.d.ts +3 -0
  35. package/dist/src/app-opentui/command-palette.js +1010 -0
  36. package/dist/src/app-opentui/drone.js +8 -6
  37. package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
  38. package/dist/src/app-opentui/fleet-stats.js +114 -0
  39. package/dist/src/app-opentui/index.js +3438 -1724
  40. package/dist/src/app-opentui/intent.js +71 -48
  41. package/dist/src/app-opentui/keymap.d.ts +6 -5
  42. package/dist/src/app-opentui/keymap.js +1064 -23
  43. package/dist/src/app-opentui/layout.d.ts +7 -0
  44. package/dist/src/app-opentui/layout.js +13 -6
  45. package/dist/src/app-opentui/list-search.d.ts +24 -0
  46. package/dist/src/app-opentui/list-search.js +88 -1
  47. package/dist/src/app-opentui/pi-host-child.js +33 -1
  48. package/dist/src/app-opentui/pi-pty-host.d.ts +5 -0
  49. package/dist/src/app-opentui/pi-pty-host.js +21 -3
  50. package/dist/src/app-opentui/react/App.d.ts +9 -0
  51. package/dist/src/app-opentui/react/App.js +5099 -0
  52. package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
  53. package/dist/src/app-opentui/react/Backdrop.js +829 -0
  54. package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
  55. package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
  56. package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
  57. package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
  58. package/dist/src/app-opentui/react/context.d.ts +17 -0
  59. package/dist/src/app-opentui/react/context.js +37 -0
  60. package/dist/src/app-opentui/react/launch.d.ts +2 -0
  61. package/dist/src/app-opentui/react/launch.js +5698 -0
  62. package/dist/src/app-opentui/react/nav.d.ts +18 -0
  63. package/dist/src/app-opentui/react/nav.js +54 -0
  64. package/dist/src/app-opentui/react/scroll.d.ts +12 -0
  65. package/dist/src/app-opentui/react/scroll.js +21 -0
  66. package/dist/src/app-opentui/react/syntax.d.ts +2 -0
  67. package/dist/src/app-opentui/react/syntax.js +64 -0
  68. package/dist/src/app-opentui/registry.js +19923 -5151
  69. package/dist/src/app-opentui/render/constants.d.ts +31 -0
  70. package/dist/src/app-opentui/render/constants.js +66 -0
  71. package/dist/src/app-opentui/render/graphics.d.ts +2 -1
  72. package/dist/src/app-opentui/render/graphics.js +106 -39
  73. package/dist/src/app-opentui/render/image-visual-layer-worker.js +108 -20
  74. package/dist/src/app-opentui/render/image-visual-layer.d.ts +7 -0
  75. package/dist/src/app-opentui/render/image-visual-layer.js +109 -20
  76. package/dist/src/app-opentui/render/native-host.d.ts +37 -0
  77. package/dist/src/app-opentui/render/native-host.js +179 -0
  78. package/dist/src/app-opentui/render/panels.js +18 -11
  79. package/dist/src/app-opentui/render/preloader.js +8 -6
  80. package/dist/src/app-opentui/render/scene.d.ts +50 -1
  81. package/dist/src/app-opentui/render/scene.js +183 -6
  82. package/dist/src/app-opentui/render/text.d.ts +7 -1
  83. package/dist/src/app-opentui/render/text.js +10 -7
  84. package/dist/src/app-opentui/render/type-bar.js +69 -30
  85. package/dist/src/app-opentui/runtime.d.ts +44 -1
  86. package/dist/src/app-opentui/runtime.js +3231 -1363
  87. package/dist/src/app-opentui/scenes/command.js +20 -6
  88. package/dist/src/app-opentui/scenes/doctor.js +176 -11
  89. package/dist/src/app-opentui/scenes/error.js +20 -10
  90. package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
  91. package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
  92. package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
  93. package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
  94. package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
  95. package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
  96. package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
  97. package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
  98. package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
  99. package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
  100. package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
  101. package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
  102. package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
  103. package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
  104. package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
  105. package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
  106. package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
  107. package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
  108. package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
  109. package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
  110. package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
  111. package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
  112. package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
  113. package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
  114. package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
  115. package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
  116. package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
  117. package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
  118. package/dist/src/app-opentui/scenes/family.d.ts +3 -0
  119. package/dist/src/app-opentui/scenes/family.js +2144 -0
  120. package/dist/src/app-opentui/scenes/fleet.js +521 -31
  121. package/dist/src/app-opentui/scenes/handoff.js +204 -12
  122. package/dist/src/app-opentui/scenes/help.js +609 -40
  123. package/dist/src/app-opentui/scenes/inbox.js +278 -17
  124. package/dist/src/app-opentui/scenes/init.js +84 -39
  125. package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
  126. package/dist/src/app-opentui/scenes/inspect.js +793 -0
  127. package/dist/src/app-opentui/scenes/main.js +218 -39
  128. package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
  129. package/dist/src/app-opentui/scenes/pi.js +508 -0
  130. package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
  131. package/dist/src/app-opentui/scenes/plugin.js +486 -0
  132. package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
  133. package/dist/src/app-opentui/scenes/repo.js +424 -0
  134. package/dist/src/app-opentui/scenes/run-detail.js +333 -20
  135. package/dist/src/app-opentui/scenes/server.js +181 -15
  136. package/dist/src/app-opentui/scenes/tasks.js +486 -31
  137. package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
  138. package/dist/src/app-opentui/scenes/workspace.js +426 -0
  139. package/dist/src/app-opentui/selectable.d.ts +19 -0
  140. package/dist/src/app-opentui/selectable.js +79 -0
  141. package/dist/src/app-opentui/state.js +83 -30
  142. package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
  143. package/dist/src/app-opentui/surface-catalog.js +540 -0
  144. package/dist/src/app-opentui/theme.d.ts +28 -6
  145. package/dist/src/app-opentui/theme.js +61 -8
  146. package/dist/src/app-opentui/types.d.ts +121 -4
  147. package/dist/src/commands/_authority-runs.d.ts +1 -1
  148. package/dist/src/commands/_authority-runs.js +2 -12
  149. package/dist/src/commands/_help-catalog.js +95 -15
  150. package/dist/src/commands/_operator-view.js +34 -2
  151. package/dist/src/commands/_pi-frontend.d.ts +2 -0
  152. package/dist/src/commands/_pi-frontend.js +34 -0
  153. package/dist/src/commands/_server-events.d.ts +26 -0
  154. package/dist/src/commands/_server-events.js +310 -0
  155. package/dist/src/commands/agent.js +2 -12
  156. package/dist/src/commands/run.js +34 -2
  157. package/dist/src/commands/server.js +2 -12
  158. package/dist/src/commands/stats.js +95 -15
  159. package/dist/src/commands/task-run-driver.js +2 -12
  160. package/dist/src/commands/task.js +131 -29
  161. package/dist/src/commands.js +192 -31
  162. package/dist/src/index.js +192 -31
  163. package/package.json +11 -9
@@ -11,15 +11,17 @@ var RIG_UI = {
11
11
  bg: "#070809",
12
12
  bg2: "#0b0c0e",
13
13
  panel: "#101115",
14
- panel2: "#101115",
15
- glass: "#14161b",
16
- ink: "#f2f3f6",
17
- ink2: "#aeb0ba",
18
- ink3: "#6c6e79",
19
- ink4: "#44464f",
14
+ panel2: "#14161b",
15
+ glass: "#1e2230",
16
+ border: "#2a2e3a",
17
+ ink: "#f4f5f8",
18
+ ink2: "#c7c9d3",
19
+ ink3: "#9aa0ae",
20
+ ink4: "#787b86",
20
21
  lime: "#ccff4d",
21
22
  limeDim: "#a9d63f",
22
23
  cyan: "#56d8ff",
24
+ cyanDim: "#3f9fbd",
23
25
  red: "#ff5d5d",
24
26
  yellow: "#ffd24d",
25
27
  magenta: "#ff79b0"
@@ -37,6 +39,18 @@ var styles = {
37
39
  magenta: otuiFg(RIG_UI.magenta)
38
40
  };
39
41
 
42
+ // packages/cli/src/app-opentui/drone.ts
43
+ import { RGBA, StyledText, TextAttributes as TextAttributes2 } from "@opentui/core";
44
+ var COLOR = {
45
+ body: RGBA.fromHex(RIG_UI.lime),
46
+ mini: RGBA.fromHex(RIG_UI.limeDim),
47
+ rotor: RGBA.fromHex(RIG_UI.cyan),
48
+ path: RGBA.fromHex(RIG_UI.cyan),
49
+ eye: RGBA.fromHex(RIG_UI.ink),
50
+ dim: RGBA.fromHex(RIG_UI.ink4),
51
+ ink: RGBA.fromHex(RIG_UI.ink2)
52
+ };
53
+
40
54
  // packages/cli/src/app-opentui/render/scene.ts
41
55
  function line(text, options = {}) {
42
56
  return { text, ...options };
@@ -61,23 +75,102 @@ function makeSceneFrame(input) {
61
75
  return input;
62
76
  }
63
77
 
78
+ // packages/cli/src/app-opentui/selectable.ts
79
+ function selectableDeckRow(deck, item) {
80
+ return { ...deckRow({ ...deck, activateOnClick: true }), selectable: item };
81
+ }
82
+
83
+ // packages/cli/src/app-opentui/fleet-stats.ts
84
+ var ACTIVE_STATUSES = new Set([
85
+ "running",
86
+ "preparing",
87
+ "created",
88
+ "validating",
89
+ "reviewing",
90
+ "closing-out",
91
+ "stopping",
92
+ "loading"
93
+ ]);
94
+ var SPARK_CHARS = ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"];
95
+ function normalizeStatus(status) {
96
+ return status.replace(/_/g, "-").toLowerCase();
97
+ }
98
+ function runsFromState(state) {
99
+ const fleet = state.data.fleet;
100
+ if (!fleet || typeof fleet !== "object" || Array.isArray(fleet))
101
+ return [];
102
+ const runs = fleet.runs;
103
+ return Array.isArray(runs) ? runs : [];
104
+ }
105
+ function computeFleetStats(runs) {
106
+ const byStatus = new Map;
107
+ let active = 0;
108
+ let succeeded = 0;
109
+ let failed = 0;
110
+ for (const run of runs) {
111
+ const status = normalizeStatus(run.status ?? "");
112
+ byStatus.set(status, (byStatus.get(status) ?? 0) + 1);
113
+ if (ACTIVE_STATUSES.has(status))
114
+ active += 1;
115
+ else if (status === "success" || status === "completed" || status === "merged")
116
+ succeeded += 1;
117
+ else if (status === "failed" || status === "error")
118
+ failed += 1;
119
+ }
120
+ const total = runs.length;
121
+ const load = total === 0 ? 0 : active / total;
122
+ const sparkline = buildSparklineSeries(active, succeeded, failed);
123
+ return { total, active, succeeded, failed, byStatus, load, sparkline };
124
+ }
125
+ function buildSparklineSeries(active, succeeded, failed) {
126
+ const peak = Math.max(1, active, succeeded, failed);
127
+ const base = [succeeded, Math.round(succeeded * 0.6 + failed * 0.4), failed, Math.round((active + failed) / 2), active];
128
+ return base.map((value) => Math.max(0, Math.min(peak, value)) / peak);
129
+ }
130
+ function fleetStatsFromState(state) {
131
+ return computeFleetStats(runsFromState(state));
132
+ }
133
+ function sparklineString(values, width) {
134
+ if (values.length === 0)
135
+ return "";
136
+ const series = width && width > 0 && values.length > width ? values.slice(values.length - width) : values;
137
+ return series.map((value) => {
138
+ const clamped = Math.max(0, Math.min(1, value));
139
+ const index = Math.min(SPARK_CHARS.length - 1, Math.round(clamped * (SPARK_CHARS.length - 1)));
140
+ return SPARK_CHARS[index];
141
+ }).join("");
142
+ }
143
+
64
144
  // packages/cli/src/app-opentui/scenes/main.ts
65
145
  var CONFIGURED_MENU = [
66
- ["init", "setup, reconfigure, repair project state"],
67
- ["server", "local/remote target, auth, linkage"],
68
- ["github", "auth, selected repo, stored token"],
69
- ["tasks", "browse, filter, dispatch, attach active work"],
70
- ["runs", "attach, stop, resume, inspect live sessions"],
71
- ["inbox", "approve, reject, answer, attach"],
72
- ["doctor", "diagnose and repair broken surfaces"],
73
- ["help", "all actions, shortcuts, mouse controls"]
146
+ ["init", "setup, reconfigure, repair project state", { id: "init", label: "init", intent: { scene: "command", argv: ["init"], action: { kind: "command-run", label: "Run init" } }, message: "run setup/reconfigure flow" }],
147
+ ["server", "local/remote target, auth, linkage", { id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Checking server" } }, message: "check selected server" }],
148
+ ["github", "auth, selected repo, stored token", { id: "github", label: "github", intent: { scene: "server", argv: ["github", "auth", "status"], action: { kind: "refresh", label: "Checking GitHub auth" } }, message: "check GitHub auth" }],
149
+ ["tasks", "browse, filter, dispatch, attach active work", { id: "tasks", label: "tasks", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Opening tasks" } }, message: "selected tasks" }],
150
+ ["runs", "attach, stop, resume, inspect live sessions", { id: "runs", label: "runs", intent: { scene: "fleet", argv: ["runs"], action: { kind: "refresh", label: "Opening runs" } }, message: "selected runs" }],
151
+ ["inbox", "approve, reject, answer, attach", { id: "inbox", label: "inbox", intent: { scene: "inbox", argv: ["inbox"], action: { kind: "refresh", label: "Loading inbox" } }, message: "selected inbox" }],
152
+ ["doctor", "diagnose and repair broken surfaces", { id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Running doctor" } }, message: "diagnose project" }],
153
+ ["browser", "browser workstation, hp-next, CDP, profile smokes", { id: "browser", label: "browser", intent: { scene: "family", argv: ["browser"], action: { kind: "refresh", label: "Open browser workstation", payload: { family: "browser" } } }, message: "browser workstation control panel" }],
154
+ ["stats", "fleet metrics: completion, failures, run time", { id: "stats", label: "stats", intent: { scene: "family", argv: ["stats"], action: { kind: "refresh", label: "Open stats", payload: { family: "stats" } } }, message: "fleet metrics dashboard" }],
155
+ ["agent", "runtime agent workspace roster and controls", { id: "agent", label: "agent", intent: { scene: "family", argv: ["agent"], action: { kind: "refresh", label: "Open agents", payload: { family: "agent" } } }, message: "agent workspace controls" }],
156
+ ["remote", "remote orchestration status and controls", { id: "remote", label: "remote", intent: { scene: "family", argv: ["remote"], action: { kind: "refresh", label: "Open remote", payload: { family: "remote" } } }, message: "remote orchestration controls" }],
157
+ ["pi", "Pi extension packages, search/add/remove/list", { id: "pi", label: "pi", intent: { scene: "pi", argv: ["pi", "list"], action: { kind: "refresh", label: "Open Pi extensions" } }, message: "Pi extension package actions" }],
158
+ ["inspect", "logs, artifacts, failures, graph, audit, diff", { id: "inspect", label: "inspect", intent: { scene: "inspect", argv: ["inspect"], action: { kind: "refresh", label: "Open inspect actions" } }, message: "logs/artifacts/failures/diff" }],
159
+ ["plugin", "plugin list, validation, contributed commands", { id: "plugin", label: "plugin", intent: { scene: "plugin", argv: ["plugin", "list"], action: { kind: "refresh", label: "Open plugin actions" } }, message: "plugin contributions" }],
160
+ ["repo", "repo sync, git helper, harness helper", { id: "repo", label: "repo", intent: { scene: "repo", argv: ["repo", "status"], action: { kind: "refresh", label: "Open repo/git/harness actions" } }, message: "repo/git/harness helpers" }],
161
+ ["workspace", "workspace topology, remotes, service helpers", { id: "workspace", label: "workspace", intent: { scene: "workspace", argv: ["workspace", "summary"], action: { kind: "refresh", label: "Open workspace summary" } }, message: "workspace topology" }],
162
+ ["help", "all actions, shortcuts, mouse controls", { id: "help", label: "help", intent: { scene: "help", argv: ["help"], action: { kind: "none", label: "Opening help" } }, message: "selected help" }]
74
163
  ];
75
- var UNCONFIGURED_MENU = [
76
- ["init", "full setup wizard and reconfigure flow"],
77
- ["server", "select local/remote target"],
78
- ["github", "connect or import authentication"],
79
- ["doctor", "find missing setup pieces"],
80
- ["help", "all actions and controls"]
164
+ var ONBOARD_PRIMARY = {
165
+ id: "onboard-setup",
166
+ label: "Start guided setup",
167
+ intent: { scene: "init", argv: ["init"], action: { kind: "refresh", label: "Setup" } },
168
+ message: "open the guided setup checklist"
169
+ };
170
+ var ONBOARD_SECONDARY = [
171
+ ["server", "select a local or remote target", { id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Checking server" } }, message: "check selected server" }],
172
+ ["doctor", "diagnose what is missing", { id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Running doctor" } }, message: "diagnose missing setup" }],
173
+ ["help", "shortcuts and controls", { id: "help", label: "help", intent: { scene: "help", argv: ["help"], action: { kind: "none", label: "Opening help" } }, message: "selected help" }]
81
174
  ];
82
175
  function record(value) {
83
176
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -94,42 +187,129 @@ function serverSummary(state) {
94
187
  auth: server ? signedIn ? `signed in${login ? ` as ${login}` : ""}` : "not signed in / unknown" : "pending"
95
188
  };
96
189
  }
190
+ function inboxPending(state) {
191
+ const inbox = record(state.data.inbox);
192
+ const approvals = Array.isArray(inbox?.approvals) ? inbox.approvals.length : 0;
193
+ const inputs = Array.isArray(inbox?.inputs) ? inbox.inputs.length : 0;
194
+ return approvals + inputs;
195
+ }
196
+ function readyTaskCount(state) {
197
+ const tasks = record(state.data.tasks);
198
+ const records = Array.isArray(tasks?.records) ? tasks.records : [];
199
+ return records.filter((entry) => {
200
+ const status = record(entry)?.status;
201
+ return typeof status === "string" && /(ready|open|todo|pending)/i.test(status);
202
+ }).length;
203
+ }
204
+ function needsAttention(state) {
205
+ const stats = fleetStatsFromState(state);
206
+ let attention = stats.failed;
207
+ for (const [status, count] of stats.byStatus) {
208
+ if (/(needs-attention|stalled|blocked|error)/i.test(status))
209
+ attention += count;
210
+ }
211
+ return attention;
212
+ }
213
+ function tile(count, label, hint, color, item, active) {
214
+ const lit = count > 0;
215
+ const row = selectableDeckRow({ label: `${String(count).padStart(2)} ${label}`, detail: hint, active }, item);
216
+ return { ...row, fg: lit ? color : RIG_UI.ink3, bold: lit || active };
217
+ }
97
218
  function panelWidth(layout) {
98
219
  return layout?.centerWidth ?? 118;
99
220
  }
100
221
  function panelHeight(layout) {
101
222
  return Math.max(22, layout?.centerHeight ?? 36);
102
223
  }
103
- function actionRows(state, configured) {
104
- const options = configured ? CONFIGURED_MENU : UNCONFIGURED_MENU;
105
- const selected = Math.max(0, Math.min(options.length - 1, state.selection.index));
106
- return options.map(([label, detail], index) => deckRow({ label, detail, index, active: index === selected, activateOnClick: true }));
224
+ function configuredMenuRows(selectedIndex) {
225
+ return CONFIGURED_MENU.map(([label, detail, item], index) => ({
226
+ ...deckRow({ label, detail, index, active: index === selectedIndex, activateOnClick: true }),
227
+ selectable: item
228
+ }));
229
+ }
230
+ function onboardingRows(selectedIndex) {
231
+ const primary = selectableDeckRow({ label: "setup", detail: "Start guided setup \u2014 recommended", active: selectedIndex === 0 }, ONBOARD_PRIMARY);
232
+ const secondary = ONBOARD_SECONDARY.map(([label, detail, item], index) => ({
233
+ ...deckRow({ label, detail, index: index + 1, active: selectedIndex === index + 1, activateOnClick: true }),
234
+ selectable: item
235
+ }));
236
+ return [primary, ...secondary];
237
+ }
238
+ var TILE_RUNS = { id: "tile-runs", label: "runs", intent: { scene: "fleet", argv: ["runs"], action: { kind: "refresh", label: "Opening runs" } }, message: "active runs \u2014 attach/stop/inspect" };
239
+ var TILE_ATTENTION = { id: "tile-attention", label: "attention", intent: { scene: "fleet", argv: ["runs"], action: { kind: "refresh", label: "Opening runs" } }, message: "runs that need attention" };
240
+ var TILE_INBOX = { id: "tile-inbox", label: "inbox", intent: { scene: "inbox", argv: ["inbox"], action: { kind: "refresh", label: "Loading inbox" } }, message: "pending approvals + input requests" };
241
+ var TILE_TASKS = { id: "tile-tasks", label: "tasks", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Opening tasks" } }, message: "ready tasks \u2014 dispatch work" };
242
+ function dashboardLines(state, selected) {
243
+ const stats = fleetStatsFromState(state);
244
+ const attention = needsAttention(state);
245
+ const pending = inboxPending(state);
246
+ const ready = readyTaskCount(state);
247
+ const spark = sparklineString(stats.sparkline, 24);
248
+ const lines = [
249
+ line("FLEET", { fg: RIG_UI.ink, bold: true }),
250
+ tile(stats.active, "ACTIVE RUNS", "attach \xB7 steer \xB7 stop \xB7 inspect", RIG_UI.cyan, TILE_RUNS, selected === 0),
251
+ tile(attention, "NEEDS ATTENTION", "failed / stalled runs to triage", RIG_UI.red, TILE_ATTENTION, selected === 1),
252
+ tile(pending, "PENDING APPROVALS", "blockers waiting on you", RIG_UI.yellow, TILE_INBOX, selected === 2),
253
+ tile(ready, "READY TASKS", "dispatch a new run", RIG_UI.lime, TILE_TASKS, selected === 3)
254
+ ];
255
+ if (spark.trim())
256
+ lines.push(line(` throughput ${spark} ${stats.succeeded} done \xB7 ${stats.failed} failed \xB7 ${stats.total} total`, { fg: RIG_UI.ink3 }));
257
+ return { lines, tileCount: 4 };
258
+ }
259
+ function statusLine(state) {
260
+ const label = state.actionLabel ?? (state.runtimeReady ? "ready" : "starting up");
261
+ if (state.status === "error") {
262
+ return line(`\u2717 ${state.error?.message ?? label}`, { fg: RIG_UI.red, bold: true });
263
+ }
264
+ if (state.status === "action") {
265
+ return line(`\u25D0 ${label}`, { fg: RIG_UI.cyan, bold: true });
266
+ }
267
+ if (state.status === "success") {
268
+ return line(`\u2713 ${label}`, { fg: RIG_UI.limeDim, bold: true });
269
+ }
270
+ return line(`\u25CF ${label}`, { fg: RIG_UI.ink2, bold: true });
107
271
  }
108
272
  function renderMainScene(state, layout) {
109
273
  const configured = state.data.projectConfigured === true;
110
274
  const server = serverSummary(state);
111
- const lines = [
112
- line("PROJECT COCKPIT", { fg: RIG_UI.ink3, bold: true }),
113
- line("click a row or use arrows + enter \xB7 esc returns here \xB7 ctrl-c exits", { fg: RIG_UI.ink4 }),
275
+ const selected = Math.max(0, state.selection.index);
276
+ const dash = configured ? dashboardLines(state, selected) : { lines: [], tileCount: 0 };
277
+ const actionSelected = configured ? selected - dash.tileCount : selected;
278
+ const lines = configured ? [
279
+ line("COCKPIT", { fg: RIG_UI.ink, bold: true }),
280
+ line("arrows + enter or click a tile/row \xB7 esc goes back \xB7 ctrl-c exits", { fg: RIG_UI.ink3 }),
281
+ blank(),
282
+ ...dash.lines,
283
+ blank(),
284
+ line("MANAGE", { fg: RIG_UI.ink, bold: true }),
285
+ ...configuredMenuRows(actionSelected),
286
+ blank(),
287
+ line("CONTEXT", { fg: RIG_UI.ink3, bold: true }),
288
+ kv("config", "configured", RIG_UI.limeDim),
289
+ kv("server", `${server.label} \xB7 ${server.health}`, server.health === "reachable" ? RIG_UI.limeDim : RIG_UI.yellow),
290
+ kv("github", server.auth, server.auth.startsWith("signed in") ? RIG_UI.limeDim : RIG_UI.yellow),
291
+ blank(),
292
+ statusLine(state)
293
+ ] : [
294
+ line("WELCOME", { fg: RIG_UI.ink, bold: true }),
295
+ line("This project isn't set up yet. One guided flow gets you running.", { fg: RIG_UI.ink2 }),
114
296
  blank(),
115
- line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
116
- ...actionRows(state, configured),
297
+ line("GET STARTED", { fg: RIG_UI.ink, bold: true }),
298
+ ...onboardingRows(actionSelected),
117
299
  blank(),
118
300
  line("CONTEXT", { fg: RIG_UI.ink3, bold: true }),
119
- kv("workspace", "current repository", RIG_UI.ink2),
120
- kv("config", configured ? "configured" : "needs setup", configured ? RIG_UI.limeDim : RIG_UI.yellow),
121
- kv("server", server.label, server.health === "reachable" ? RIG_UI.limeDim : RIG_UI.yellow),
122
- kv("target", server.target, RIG_UI.ink3),
301
+ kv("config", "needs setup", RIG_UI.yellow),
302
+ kv("server", `${server.label} \xB7 ${server.health}`, server.health === "reachable" ? RIG_UI.limeDim : RIG_UI.yellow),
123
303
  kv("github", server.auth, server.auth.startsWith("signed in") ? RIG_UI.limeDim : RIG_UI.yellow),
124
304
  blank(),
125
- line(state.actionLabel ?? "ready", { fg: state.status === "action" ? RIG_UI.cyan : RIG_UI.ink4 })
305
+ statusLine(state)
126
306
  ];
127
307
  return makeSceneFrame({
128
308
  scene: "main",
129
- title: "Project cockpit",
309
+ title: "Cockpit",
130
310
  lines: [],
131
311
  panels: [{
132
- id: "project-cockpit",
312
+ id: "cockpit",
133
313
  top: 0,
134
314
  width: panelWidth(layout),
135
315
  height: panelHeight(layout),
@@ -139,12 +319,11 @@ function renderMainScene(state, layout) {
139
319
  opacity: 0.98,
140
320
  border: false,
141
321
  chrome: "ad-terminal",
142
- headerText: "project cockpit",
322
+ headerText: "cockpit",
143
323
  paddingX: layout?.compact ? 3 : 5,
144
324
  paddingY: 2
145
325
  }],
146
- live: true,
147
- hideTypeBar: true
326
+ live: true
148
327
  });
149
328
  }
150
329
  export {
@@ -0,0 +1,3 @@
1
+ import type { AppSceneFrame, AppState } from "../types";
2
+ import type { StageLayout } from "../layout";
3
+ export declare function renderPiScene(state: AppState, layout?: StageLayout): AppSceneFrame;