@aragon-agent/cli 0.6.43 → 0.6.45

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 (251) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +69 -2
  3. package/dist/agent/controller.d.ts +69 -0
  4. package/dist/agent/controller.js +224 -11
  5. package/dist/agent/governance-view.d.ts +40 -0
  6. package/dist/agent/governance-view.js +40 -0
  7. package/dist/agent/governance-wiring.d.ts +162 -0
  8. package/dist/agent/governance-wiring.js +470 -0
  9. package/dist/agent/plan-prompt.d.ts +7 -0
  10. package/dist/agent/plan-prompt.js +2 -1
  11. package/dist/agent/reducer.d.ts +33 -1
  12. package/dist/agent/reducer.js +45 -9
  13. package/dist/agent/system-prompt.d.ts +19 -0
  14. package/dist/agent/system-prompt.js +9 -1
  15. package/dist/cli.js +45 -1
  16. package/dist/commands/builtins.js +10 -4
  17. package/dist/commands/governance-command.d.ts +35 -0
  18. package/dist/commands/governance-command.js +292 -0
  19. package/dist/commands/governance-runs-table.d.ts +40 -0
  20. package/dist/commands/governance-runs-table.js +130 -0
  21. package/dist/commands/registry.d.ts +12 -0
  22. package/dist/config/app-paths.d.ts +10 -0
  23. package/dist/config/app-paths.js +12 -0
  24. package/dist/config/cli-commands.d.ts +18 -0
  25. package/dist/config/cli-commands.js +47 -1
  26. package/dist/config/env.d.ts +2 -1
  27. package/dist/config/env.js +10 -1
  28. package/dist/config/governance-config.d.ts +125 -0
  29. package/dist/config/governance-config.js +164 -0
  30. package/dist/config/governance-launch.d.ts +71 -0
  31. package/dist/config/governance-launch.js +58 -0
  32. package/dist/config/load.d.ts +15 -0
  33. package/dist/config/load.js +26 -1
  34. package/dist/config/model-profile-store.d.ts +4 -2
  35. package/dist/config/schema.d.ts +22 -0
  36. package/dist/config/schema.js +6 -0
  37. package/dist/config/store.js +14 -1
  38. package/dist/config/ui-state.d.ts +11 -0
  39. package/dist/config/ui-state.js +11 -0
  40. package/dist/diagnostics/doctor.js +20 -0
  41. package/dist/governance/card-normalize.d.ts +24 -0
  42. package/dist/governance/card-normalize.js +76 -0
  43. package/dist/governance/copy.d.ts +109 -0
  44. package/dist/governance/copy.js +223 -0
  45. package/dist/governance/engine/aftermath.d.ts +49 -0
  46. package/dist/governance/engine/aftermath.js +134 -0
  47. package/dist/governance/engine/artifact-persist.d.ts +35 -0
  48. package/dist/governance/engine/artifact-persist.js +86 -0
  49. package/dist/governance/engine/budget.d.ts +52 -0
  50. package/dist/governance/engine/budget.js +112 -0
  51. package/dist/governance/engine/cards.d.ts +18 -0
  52. package/dist/governance/engine/cards.js +186 -0
  53. package/dist/governance/engine/digest.d.ts +32 -0
  54. package/dist/governance/engine/digest.js +63 -0
  55. package/dist/governance/engine/engine-core.d.ts +219 -0
  56. package/dist/governance/engine/engine-core.js +562 -0
  57. package/dist/governance/engine/engine.d.ts +68 -0
  58. package/dist/governance/engine/engine.js +314 -0
  59. package/dist/governance/engine/estimate.d.ts +38 -0
  60. package/dist/governance/engine/estimate.js +46 -0
  61. package/dist/governance/engine/inspector.d.ts +16 -0
  62. package/dist/governance/engine/inspector.js +396 -0
  63. package/dist/governance/engine/integration.d.ts +35 -0
  64. package/dist/governance/engine/integration.js +220 -0
  65. package/dist/governance/engine/lifecycle.d.ts +29 -0
  66. package/dist/governance/engine/lifecycle.js +656 -0
  67. package/dist/governance/engine/pause.d.ts +56 -0
  68. package/dist/governance/engine/pause.js +107 -0
  69. package/dist/governance/engine/phase-members.d.ts +15 -0
  70. package/dist/governance/engine/phase-members.js +34 -0
  71. package/dist/governance/engine/phase-planner.d.ts +53 -0
  72. package/dist/governance/engine/phase-planner.js +282 -0
  73. package/dist/governance/engine/rebuild.d.ts +27 -0
  74. package/dist/governance/engine/rebuild.js +57 -0
  75. package/dist/governance/engine/report.d.ts +66 -0
  76. package/dist/governance/engine/report.js +220 -0
  77. package/dist/governance/engine/run-digest.d.ts +20 -0
  78. package/dist/governance/engine/run-digest.js +42 -0
  79. package/dist/governance/engine/spec-builder.d.ts +117 -0
  80. package/dist/governance/engine/spec-builder.js +321 -0
  81. package/dist/governance/engine/stage-runner.d.ts +22 -0
  82. package/dist/governance/engine/stage-runner.js +664 -0
  83. package/dist/governance/engine/start-input.d.ts +19 -0
  84. package/dist/governance/engine/start-input.js +111 -0
  85. package/dist/governance/engine/state-machine.d.ts +101 -0
  86. package/dist/governance/engine/state-machine.js +586 -0
  87. package/dist/governance/engine/submission-queries.d.ts +42 -0
  88. package/dist/governance/engine/submission-queries.js +97 -0
  89. package/dist/governance/engine/submission-render.d.ts +12 -0
  90. package/dist/governance/engine/submission-render.js +92 -0
  91. package/dist/governance/engine/submissions.d.ts +27 -0
  92. package/dist/governance/engine/submissions.js +455 -0
  93. package/dist/governance/engine/visibility.d.ts +104 -0
  94. package/dist/governance/engine/visibility.js +223 -0
  95. package/dist/governance/governed-dispatch.d.ts +19 -0
  96. package/dist/governance/governed-dispatch.js +17 -0
  97. package/dist/governance/limits.d.ts +107 -0
  98. package/dist/governance/limits.js +131 -0
  99. package/dist/governance/posture-transition.d.ts +38 -0
  100. package/dist/governance/posture-transition.js +44 -0
  101. package/dist/governance/posture.d.ts +35 -0
  102. package/dist/governance/posture.js +59 -0
  103. package/dist/governance/profiles.d.ts +48 -0
  104. package/dist/governance/profiles.js +140 -0
  105. package/dist/governance/prompts/orchestrator-block.d.ts +40 -0
  106. package/dist/governance/prompts/orchestrator-block.js +128 -0
  107. package/dist/governance/prompts/plan-addendum.d.ts +22 -0
  108. package/dist/governance/prompts/plan-addendum.js +60 -0
  109. package/dist/governance/prompts/refusals.d.ts +48 -0
  110. package/dist/governance/prompts/refusals.js +82 -0
  111. package/dist/governance/prompts/role-blocks.d.ts +40 -0
  112. package/dist/governance/prompts/role-blocks.js +255 -0
  113. package/dist/governance/report-reader.d.ts +31 -0
  114. package/dist/governance/report-reader.js +57 -0
  115. package/dist/governance/roles.d.ts +83 -0
  116. package/dist/governance/roles.js +142 -0
  117. package/dist/governance/rules/claims.d.ts +83 -0
  118. package/dist/governance/rules/claims.js +250 -0
  119. package/dist/governance/rules/elimination.d.ts +66 -0
  120. package/dist/governance/rules/elimination.js +105 -0
  121. package/dist/governance/rules/events-table.d.ts +46 -0
  122. package/dist/governance/rules/events-table.js +94 -0
  123. package/dist/governance/rules/failure-analysis.d.ts +28 -0
  124. package/dist/governance/rules/failure-analysis.js +93 -0
  125. package/dist/governance/rules/ledger-replay.d.ts +53 -0
  126. package/dist/governance/rules/ledger-replay.js +53 -0
  127. package/dist/governance/rules/ledger-state.d.ts +85 -0
  128. package/dist/governance/rules/ledger-state.js +175 -0
  129. package/dist/governance/rules/ledger.d.ts +228 -0
  130. package/dist/governance/rules/ledger.js +560 -0
  131. package/dist/governance/rules/rca.d.ts +68 -0
  132. package/dist/governance/rules/rca.js +220 -0
  133. package/dist/governance/rules/settlement.d.ts +129 -0
  134. package/dist/governance/rules/settlement.js +363 -0
  135. package/dist/governance/rules/suspicion.d.ts +66 -0
  136. package/dist/governance/rules/suspicion.js +169 -0
  137. package/dist/governance/store/artifacts.d.ts +81 -0
  138. package/dist/governance/store/artifacts.js +173 -0
  139. package/dist/governance/store/atomic.d.ts +79 -0
  140. package/dist/governance/store/atomic.js +119 -0
  141. package/dist/governance/store/events-log.d.ts +35 -0
  142. package/dist/governance/store/events-log.js +86 -0
  143. package/dist/governance/store/run-lock.d.ts +51 -0
  144. package/dist/governance/store/run-lock.js +122 -0
  145. package/dist/governance/store/run-store.d.ts +229 -0
  146. package/dist/governance/store/run-store.js +644 -0
  147. package/dist/governance/store/scoreboard-export.d.ts +53 -0
  148. package/dist/governance/store/scoreboard-export.js +65 -0
  149. package/dist/governance/tools/child-tools.d.ts +31 -0
  150. package/dist/governance/tools/child-tools.js +65 -0
  151. package/dist/governance/tools/guard.d.ts +71 -0
  152. package/dist/governance/tools/guard.js +194 -0
  153. package/dist/governance/tools/inspector-tools.d.ts +63 -0
  154. package/dist/governance/tools/inspector-tools.js +424 -0
  155. package/dist/governance/tools/lead-tools.d.ts +42 -0
  156. package/dist/governance/tools/lead-tools.js +226 -0
  157. package/dist/governance/tools/normalize-util.d.ts +101 -0
  158. package/dist/governance/tools/normalize-util.js +230 -0
  159. package/dist/governance/tools/scan-incomplete.d.ts +79 -0
  160. package/dist/governance/tools/scan-incomplete.js +486 -0
  161. package/dist/governance/tools/shared-tools.d.ts +44 -0
  162. package/dist/governance/tools/shared-tools.js +125 -0
  163. package/dist/governance/tools/submit-normalizers.d.ts +28 -0
  164. package/dist/governance/tools/submit-normalizers.js +474 -0
  165. package/dist/governance/tools/submit-tools.d.ts +26 -0
  166. package/dist/governance/tools/submit-tools.js +171 -0
  167. package/dist/governance/types.d.ts +661 -0
  168. package/dist/governance/types.js +27 -0
  169. package/dist/proc/kill-tree.d.ts +19 -1
  170. package/dist/proc/kill-tree.js +32 -5
  171. package/dist/proc/limits.d.ts +19 -0
  172. package/dist/proc/limits.js +19 -0
  173. package/dist/proc/supervisor.js +8 -1
  174. package/dist/session/validate-session.js +32 -1
  175. package/dist/team/runtime.d.ts +8 -0
  176. package/dist/team/runtime.js +9 -0
  177. package/dist/team/subagent.d.ts +23 -0
  178. package/dist/team/subagent.js +14 -3
  179. package/dist/team/types.d.ts +6 -0
  180. package/dist/tools/bounded-spawn.d.ts +56 -0
  181. package/dist/tools/bounded-spawn.js +76 -0
  182. package/dist/tools/index.d.ts +30 -7
  183. package/dist/tools/index.js +14 -0
  184. package/dist/tools/plan-tools.d.ts +14 -2
  185. package/dist/tools/plan-tools.js +5 -2
  186. package/dist/tools/search-tools.js +52 -44
  187. package/dist/ui/App.js +145 -25
  188. package/dist/ui/BottomStatusRow.js +1 -1
  189. package/dist/ui/Composer.d.ts +7 -1
  190. package/dist/ui/Composer.js +9 -6
  191. package/dist/ui/GovernancePanel.d.ts +50 -0
  192. package/dist/ui/GovernancePanel.js +77 -0
  193. package/dist/ui/GovernanceRun.d.ts +18 -0
  194. package/dist/ui/GovernanceRun.js +11 -0
  195. package/dist/ui/ScrollbackShell.d.ts +35 -7
  196. package/dist/ui/ScrollbackShell.js +1 -1
  197. package/dist/ui/StatusBar.d.ts +15 -2
  198. package/dist/ui/StatusBar.js +10 -4
  199. package/dist/ui/Transcript.js +3 -0
  200. package/dist/ui/entries/GovernanceCard.d.ts +30 -0
  201. package/dist/ui/entries/GovernanceCard.js +32 -0
  202. package/dist/ui/governance-copy.d.ts +69 -0
  203. package/dist/ui/governance-copy.js +104 -0
  204. package/dist/ui/governance-status.d.ts +145 -0
  205. package/dist/ui/governance-status.js +326 -0
  206. package/dist/ui/interaction-copy.d.ts +4 -0
  207. package/dist/ui/interaction-copy.js +5 -0
  208. package/dist/ui/interaction-hints.d.ts +17 -0
  209. package/dist/ui/interaction-hints.js +14 -2
  210. package/dist/ui/layout/governance-board.d.ts +121 -0
  211. package/dist/ui/layout/governance-board.js +382 -0
  212. package/dist/ui/layout/governance-card.d.ts +53 -0
  213. package/dist/ui/layout/governance-card.js +134 -0
  214. package/dist/ui/layout/governance-chip.d.ts +38 -0
  215. package/dist/ui/layout/governance-chip.js +64 -0
  216. package/dist/ui/layout/governance-panel.d.ts +85 -0
  217. package/dist/ui/layout/governance-panel.js +358 -0
  218. package/dist/ui/layout/governance-roster.d.ts +65 -0
  219. package/dist/ui/layout/governance-roster.js +275 -0
  220. package/dist/ui/layout/status-detail-layout.js +3 -3
  221. package/dist/ui/layout/status-layout.d.ts +5 -2
  222. package/dist/ui/layout/status-layout.js +10 -6
  223. package/dist/ui/layout/virtual-window.js +11 -0
  224. package/dist/ui/overlays/GovernanceBoardOverlay.d.ts +41 -0
  225. package/dist/ui/overlays/GovernanceBoardOverlay.js +76 -0
  226. package/dist/ui/overlays/GovernanceSettingsPage.d.ts +48 -0
  227. package/dist/ui/overlays/GovernanceSettingsPage.js +93 -0
  228. package/dist/ui/overlays/HelpOverlay.js +4 -3
  229. package/dist/ui/overlays/QuestionOverlay.d.ts +9 -1
  230. package/dist/ui/overlays/QuestionOverlay.js +4 -2
  231. package/dist/ui/overlays/SettingsScreen.d.ts +7 -0
  232. package/dist/ui/overlays/SettingsScreen.js +21 -1
  233. package/dist/ui/overlays/governance-settings.d.ts +79 -0
  234. package/dist/ui/overlays/governance-settings.js +140 -0
  235. package/dist/ui/overlays/model-profile-state.d.ts +6 -1
  236. package/dist/ui/overlays/model-profile-state.js +10 -0
  237. package/dist/ui/palettes.d.ts +17 -0
  238. package/dist/ui/palettes.js +9 -0
  239. package/dist/ui/scrollback/LiveTail.d.ts +3 -1
  240. package/dist/ui/scrollback/budget.d.ts +12 -6
  241. package/dist/ui/scrollback/budget.js +11 -4
  242. package/dist/ui/scrollback/live-preview.js +2 -0
  243. package/dist/ui/scrollback/settled-boundary.js +3 -0
  244. package/dist/ui/scrollback/tail-anchor.d.ts +5 -2
  245. package/dist/ui/scrollback/tail-anchor.js +3 -1
  246. package/dist/ui/shortcuts.js +2 -2
  247. package/dist/ui/theme.d.ts +7 -0
  248. package/dist/ui/theme.js +1 -0
  249. package/dist/ui/transcript-text.js +9 -0
  250. package/dist/ui/use-wheel-routing.js +3 -1
  251. package/package.json +2 -2
@@ -0,0 +1,77 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * GovernancePanel - the legion panel (governance-mode section 10.3).
4
+ *
5
+ * ASCII ONLY: every glyph comes from `pickGlyphs`, through the layout.
6
+ *
7
+ * THIS COMPONENT ONLY COLOURS AND PLACES. Every decision - which tier, which columns, how
8
+ * wide, what each cell says, which row is hidden - was made by
9
+ * `layout/governance-panel.ts`, and the `layout` prop is REQUIRED: `App` builds it once to
10
+ * learn the panel's height (the native band and the TODO rail both budget against it) and
11
+ * hands the very same object here, so the number that decides whether the panel mounts is
12
+ * the number it is drawn from. A panel that re-planned itself could draw a taller tier than
13
+ * the one the band reserved, and the band clips the overflow in silence.
14
+ *
15
+ * IT REPLACES `TeamPanel` WHILE A GOVERNED STAGE RUNS (D-17), it does not stack with it:
16
+ * the repo has been bitten by a "double roster" once (tui-subagent-double-roster), and a
17
+ * governed dispatch is the one case where two live rosters would be the same children
18
+ * listed twice.
19
+ *
20
+ * NO `ink-spinner` HERE, on purpose. While a governed stage runs the lead's turn is
21
+ * running, the activity row owns the one spinner (single-spinner-while-running), and every
22
+ * panel is handed the widened reduced-motion signal anyway - an animation here would never
23
+ * play. The working marker is `statusGlyph(...)`, and `reducedMotion` is the USER's
24
+ * preference: it only decides whether a score change flashes for four seconds or stays put.
25
+ *
26
+ * COLUMNS ARE FIXED-WIDTH BOXES with exactly one elastic cell (`governance-roster.ts`), the
27
+ * lesson `TeamPanel` records at length: a flex-grown column under a fixed-height parent
28
+ * stretches to its widest child and the cells to its right lose their offsets.
29
+ */
30
+ import { useRef } from 'react';
31
+ import { Box, Text } from 'ink';
32
+ import { pickGlyphs } from './glyphs.js';
33
+ import { trackEliminated } from './governance-status.js';
34
+ import { GovernanceLine } from './GovernanceRun.js';
35
+ import { PANEL_MARGIN_CELLS, } from './layout/governance-roster.js';
36
+ /**
37
+ * The first-seen-eliminated map, kept across snapshots so a replaced member shows its
38
+ * `replaced by ...` note for exactly one phase. Reset when the run changes or ends.
39
+ *
40
+ * A ref written during render is acceptable here because the write is idempotent
41
+ * (`trackEliminated` returns the same object when nothing is new) and no other component
42
+ * reads the ref - `App` reads only the returned value.
43
+ */
44
+ export function useEliminatedSince(snapshot) {
45
+ const ref = useRef({ runId: null, since: {} });
46
+ if (snapshot === null) {
47
+ if (ref.current.runId !== null)
48
+ ref.current = { runId: null, since: {} };
49
+ return ref.current.since;
50
+ }
51
+ const base = ref.current.runId === snapshot.runId ? ref.current.since : {};
52
+ ref.current = { runId: snapshot.runId, since: trackEliminated(base, snapshot) };
53
+ return ref.current.since;
54
+ }
55
+ function Margin() {
56
+ return (_jsx(Box, { width: PANEL_MARGIN_CELLS, flexShrink: 0, children: _jsx(Text, { children: " " }) }));
57
+ }
58
+ function LineView({ line, theme }) {
59
+ return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, overflow: "hidden", children: [_jsx(Margin, {}), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsx(GovernanceLine, { segments: line.left, theme: theme }) }), line.rightCells > 0 && (_jsx(Box, { width: line.rightCells, flexShrink: 0, justifyContent: "flex-end", children: _jsx(GovernanceLine, { segments: line.right, theme: theme }) }))] }));
60
+ }
61
+ function CellView({ cell, theme }) {
62
+ const content = _jsx(GovernanceLine, { segments: cell.segments, theme: theme });
63
+ if (cell.elastic) {
64
+ return _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: content });
65
+ }
66
+ return (_jsx(Box, { width: cell.width, flexShrink: 0, overflow: "hidden", justifyContent: cell.align === 'right' ? 'flex-end' : 'flex-start', children: content }));
67
+ }
68
+ function RosterView({ line, theme }) {
69
+ return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, overflow: "hidden", children: [_jsx(Margin, {}), line.cells.map((cell) => (_jsx(CellView, { cell: cell, theme: theme }, cell.key)))] }));
70
+ }
71
+ export function GovernancePanel({ layout, theme, caps }) {
72
+ if (layout.height === 0 || layout.header === null)
73
+ return null;
74
+ const glyphs = pickGlyphs(caps);
75
+ const rule = layout.ruleCells > 0 ? (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, overflow: "hidden", children: [_jsx(Margin, {}), _jsx(Text, { wrap: "truncate", color: theme.border, children: glyphs.hrule.repeat(layout.ruleCells) })] })) : null;
76
+ return (_jsxs(Box, { flexDirection: "column", width: "100%", flexShrink: 0, children: [_jsx(LineView, { line: layout.header, theme: theme }), layout.pipeline !== null && _jsx(LineView, { line: layout.pipeline, theme: theme }), rule, layout.rosterRows.map((line) => (_jsx(RosterView, { line: line, theme: theme }, line.key))), layout.overflow !== null && (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, overflow: "hidden", children: [_jsx(Margin, {}), _jsx(Text, { wrap: "truncate", color: theme.muted, children: layout.overflow })] })), rule, layout.ticker.map((line, index) => (_jsx(LineView, { line: line, theme: theme }, `ticker-${index}`)))] }));
77
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * GovernanceRun - paints one `Segment[]` run: the single place a governance layout's
3
+ * semantic tones become Ink colours.
4
+ *
5
+ * ASCII ONLY. The panel, the card and the board all draw the same `Segment` vocabulary,
6
+ * and three private copies of this loop is how their bold / tone handling drifts apart.
7
+ */
8
+ import React from 'react';
9
+ import type { Theme } from './theme.js';
10
+ import { type Segment } from './governance-status.js';
11
+ export interface GovernanceRunProps {
12
+ segments: readonly Segment[];
13
+ theme: Theme;
14
+ }
15
+ /** The segments as nested `Text`; the CALLER owns wrapping and truncation. */
16
+ export declare function GovernanceRun({ segments, theme }: GovernanceRunProps): React.ReactElement;
17
+ /** One display row: the run inside a `wrap="truncate"` `Text`, so it can never wrap. */
18
+ export declare function GovernanceLine({ segments, theme }: GovernanceRunProps): React.ReactElement;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Text } from 'ink';
3
+ import { toneColor } from './governance-status.js';
4
+ /** The segments as nested `Text`; the CALLER owns wrapping and truncation. */
5
+ export function GovernanceRun({ segments, theme }) {
6
+ return (_jsx(_Fragment, { children: segments.map((part, index) => (_jsx(Text, { color: toneColor(part.tone, theme), ...(part.bold ? { bold: true } : {}), children: part.text }, index))) }));
7
+ }
8
+ /** One display row: the run inside a `wrap="truncate"` `Text`, so it can never wrap. */
9
+ export function GovernanceLine({ segments, theme }) {
10
+ return (_jsx(Text, { wrap: "truncate", children: _jsx(GovernanceRun, { segments: segments, theme: theme }) }));
11
+ }
@@ -11,7 +11,7 @@
11
11
  * off its `clearTerminal` branch (that branch fires at `outputHeight >= rows` and
12
12
  * contains `ESC[3J`, which erases the user's scrollback).
13
13
  *
14
- * Top to bottom: [header][overlay | panel band][composer][status][details].
14
+ * Top to bottom: [overlay | panel band][composer][identity][status][details].
15
15
  *
16
16
  * THE PANEL BAND IS THE PART NATIVE MODE WAS MISSING
17
17
  * (release-gate-and-native-panels §6.1). A fixed frame can put a rail beside the
@@ -40,11 +40,39 @@
40
40
  * content would make the region taller than `budget.liveRows`, and a frame as tall as
41
41
  * the terminal makes Ink erase the user's scrollback.
42
42
  *
43
+ * THE IDENTITY ROW IS A BOTTOM SLOT, NOT THE FIRST ONE
44
+ * (tui-header-leaks-into-scrollback, plan A-prime). It is still `budget.headerRows` tall
45
+ * and still spent out of the region's pool - only its ORDER changed:
46
+ * - position is not cosmetic here, it is the whole defect. The writer lays the canvas out
47
+ * as `[gap][content][region]` and only CONTENT rows ever scroll out (`canvas.ts`), so
48
+ * region row 0 is by construction the successor of the newest row in the terminal's
49
+ * scrollback. A tall reply gives way at the top (`overflow-print.ts`: head printed,
50
+ * tail on screen), so chrome parked on row 0 is read BETWEEN two rows of the SAME
51
+ * answer: the user's report is the word mark, `provider:model`, `cwd`, the key and
52
+ * `^G more` appearing in the middle of a finished reply.
53
+ * - the bottom slots have no such property: nothing below the band is ever printed or
54
+ * scrolled, so `[composer][identity][status][details]` stays outside the conversation
55
+ * for a reply of any length. That band is also the one the writer protects on purpose
56
+ * (I-B17: give way at the TOP, because the composer and the status line are the two
57
+ * rows the human is interacting with).
58
+ * - the two surrounding slots are NOT interchangeable. Above the composer would also
59
+ * dodge the seam, but it would break the promise that the newest line hugs the input
60
+ * box (`canvas.ts`, `tail-anchor.ts`); below the status group would split the
61
+ * `[status][details]` pair, and "the status is the screen's last row" is its own
62
+ * invariant (`tui-duplicate-status-row`); inside the band's row pool would change
63
+ * `previewRows`, and no budget number may move for this fix.
64
+ * - `app` mode (`layout/AppShell.tsx`) deliberately keeps its header on TOP, so the two
65
+ * modes do NOT agree and must not be "unified": there the header sits above a viewport
66
+ * that scrolls itself, so there is no print channel and no seam to leak into.
67
+ * - `headerRows` is still produced by `buildScrollbackBudget` alone (still 1, still
68
+ * subtracted from `remaining`), so `liveRows`, `bandRows`, `previewRows` and `railCols`
69
+ * are unchanged: a row ORDER change, not a row BUDGET change.
70
+ * - the row is still NOT printed into the scrollback: at `H = rows - 1` any printed row
71
+ * is pushed off the screen by the next frame, so "print the header" would mean "the
72
+ * header is never visible".
73
+ *
43
74
  * THE BAND'S PREVIEW BOX IS TOP-ALIGNED; THE OTHER SLOTS ARE FIXED
44
75
  * (D3 / D4 / I-F7; tui-first-reply-bottom-aligned, plan A-prime):
45
- * - `header` is the fixed 1-row slot at the very top. It is NOT printed into the
46
- * scrollback any more: at `H = rows - 1` any printed row is pushed off the screen by
47
- * the next frame, so "print the header" would mean "the header is never visible".
48
76
  * - the band's preview box is TOP-aligned unconditionally, which is why the alignment is
49
77
  * no longer a function of `opener`. `opener` is a 12-row card in a 24-row column, so
50
78
  * bottom-aligning it left 12 blank rows in the upper half of the screen - the original
@@ -71,9 +99,9 @@ import type { ScrollbackBudget } from './scrollback/budget.js';
71
99
  export interface ScrollbackShellProps {
72
100
  budget: ScrollbackBudget;
73
101
  /**
74
- * REQUIRED: the one-row slot at the top of the region, `budget.headerRows` tall.
75
- * Required rather than optional for the reason `budget` and `band` are - a frame
76
- * that forgot it would render a header-less screen with nothing to catch it.
102
+ * REQUIRED: the identity row, `budget.headerRows` tall, drawn BETWEEN the composer and
103
+ * the status group. Required rather than optional for the reason `budget` and `band` are
104
+ * - a frame that forgot it would render a header-less screen with nothing to catch it.
77
105
  */
78
106
  header: React.ReactNode;
79
107
  /** Shown instead of the band when an overlay is open. */
@@ -22,5 +22,5 @@ export function ScrollbackShell({ budget, header, overlay, liveTailLines, opener
22
22
  const top = band.reason === 'overlay' ? (_jsx(Box, { flexDirection: "column", height: budget.overlayRows, flexShrink: 0, overflow: "hidden", children: overlay })) : band.bandRows > 0 ? (
23
23
  // ROW REGION ABOVE, FULL-WIDTH ROSTER BELOW (tui-subagent-panel §4.1.2 / D-2).
24
24
  _jsxs(Box, { flexDirection: "column", height: band.bandRows, flexShrink: 0, overflow: "hidden", children: [_jsxs(Box, { flexDirection: "row", height: rowRegion, flexShrink: 0, overflow: "hidden", children: [_jsx(Box, { flexDirection: "column", width: budget.previewCols, height: rowRegion, flexShrink: 0, overflow: "hidden", children: band.previewRows > 0 && (_jsx(Box, { flexDirection: "column", height: band.previewRows, flexShrink: 0, justifyContent: "flex-start", overflow: "hidden", children: leftColumn ?? tailLines.map((line, index) => (_jsx(Text, { wrap: "truncate", color: theme.muted, children: line }, index))) })) }), band.railRows > 0 && (_jsx(Box, { height: band.railRows, width: band.railCols, flexShrink: 0, overflow: "hidden", children: rail }))] }), band.teamRows > 0 && (_jsx(Box, { width: width, height: band.teamRows, flexShrink: 0, overflow: "hidden", children: team }))] })) : null;
25
- return (_jsxs(Box, { flexDirection: "column", height: budget.liveRows, width: width, overflow: "hidden", flexShrink: 0, children: [budget.headerRows > 0 && (_jsx(Box, { height: budget.headerRows, flexShrink: 0, overflow: "hidden", children: header })), top, _jsx(Box, { flexDirection: "column", height: budget.composerSlotRows, justifyContent: "flex-end", flexShrink: 0, overflow: "hidden", children: composer }), _jsx(Box, { height: budget.statusRows > 0 ? 1 : 0, flexShrink: 0, overflow: "hidden", children: status }), budget.statusRows === 2 && (_jsx(Box, { height: 1, flexShrink: 0, overflow: "hidden", children: details }))] }));
25
+ return (_jsxs(Box, { flexDirection: "column", height: budget.liveRows, width: width, overflow: "hidden", flexShrink: 0, children: [top, _jsx(Box, { flexDirection: "column", height: budget.composerSlotRows, justifyContent: "flex-end", flexShrink: 0, overflow: "hidden", children: composer }), budget.headerRows > 0 && (_jsx(Box, { height: budget.headerRows, flexShrink: 0, overflow: "hidden", children: header })), _jsx(Box, { height: budget.statusRows > 0 ? 1 : 0, flexShrink: 0, overflow: "hidden", children: status }), budget.statusRows === 2 && (_jsx(Box, { height: 1, flexShrink: 0, overflow: "hidden", children: details }))] }));
26
26
  }
@@ -5,6 +5,8 @@ import type { TermCapabilities } from './capabilities.js';
5
5
  import type { UsageTotal } from '../agent/reducer.js';
6
6
  import type { ContextUsageSnapshot } from '../compaction/types.js';
7
7
  import type { AgentMode } from '../agent/agent-mode.js';
8
+ import type { GovernanceSnapshot } from '../governance/types.js';
9
+ import type { Posture } from '../governance/posture.js';
8
10
  import type { PendingSteering } from '../agent/queued-messages.js';
9
11
  import { type RunPhase } from './layout/status-layout.js';
10
12
  import type { EscapeAction, StatusFeedback } from './status-feedback.js';
@@ -63,8 +65,19 @@ export interface StatusBarProps {
63
65
  modified: boolean;
64
66
  otherNames: readonly string[];
65
67
  } | null;
66
- agentMode?: AgentMode;
67
- pendingAgentMode?: AgentMode | null;
68
+ /**
69
+ * The mode word's source. A `Posture` is also accepted (governance-mode 10.2): its
70
+ * governed members render as `GOVERN` / `PLAN+GOVERN` in the governance hue, and
71
+ * `build` / `plan` render exactly as the `AgentMode` of the same name always did.
72
+ */
73
+ agentMode?: AgentMode | Posture;
74
+ pendingAgentMode?: AgentMode | Posture | null;
75
+ /**
76
+ * The live governed-run snapshot, or absent. Drives the governance chip
77
+ * (`GOV p2/3 REVIEW`); absent plans a hidden chip, which keeps this row byte-identical
78
+ * to the pre-governance build.
79
+ */
80
+ governance?: GovernanceSnapshot | null;
68
81
  /**
69
82
  * Forced team mode is armed, with the count it was armed with
70
83
  * (team-command-forced-dispatch §3.8 / D-9). ABSENT = not armed, and every
@@ -3,10 +3,12 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
3
3
  import React from 'react';
4
4
  import { Box, Text } from 'ink';
5
5
  import { pickGlyphs } from './glyphs.js';
6
+ import { planGovernanceChip } from './layout/governance-chip.js';
6
7
  import { liveSpinner } from './ActivityLine.js';
7
8
  import { planPrimaryStatusFields } from './layout/status-layout.js';
8
9
  import { planSessionChip } from './layout/session-chip.js';
9
10
  import { planKitChip } from './layout/kit-chip.js';
11
+ import { toneColor } from './governance-status.js';
10
12
  /** An invisible leading byte change forces Ink to repaint on Ctrl+L. */
11
13
  const redrawChar = (nonce) => nonce % 2 ? String.fromCharCode(0x00a0) : ' ';
12
14
  export function StatusBar(props) {
@@ -28,8 +30,12 @@ export function StatusBar(props) {
28
30
  // byte-identical to the build before the feature (I-9).
29
31
  const kit = planKitChip({ columns: cols - chipCells, kit: props.kit });
30
32
  const kitCells = kit.visible ? kit.cells + kit.gap : 0;
33
+ // THE GOVERNANCE CHIP IS PLANNED THIRD, out of what the other two left, by the same
34
+ // comparison (the left half keeps its 34-cell floor). Hidden without a live run.
35
+ const govern = planGovernanceChip({ columns: cols - chipCells - kitCells, snapshot: props.governance });
36
+ const governCells = govern.visible ? govern.cells + govern.gap : 0;
31
37
  const plan = planPrimaryStatusFields({
32
- reserveRight: chipCells + kitCells,
38
+ reserveRight: chipCells + kitCells + governCells,
33
39
  columns: cols, phase, pendingCount: props.pendingSteering?.length ?? 0,
34
40
  context: props.context, usageTotal: props.usageTotal,
35
41
  thinkingLevel: props.thinkingLevel, elapsedMs: props.elapsedMs, tokPerSec: props.tokPerSec,
@@ -48,8 +54,8 @@ export function StatusBar(props) {
48
54
  });
49
55
  const tones = { normal: props.theme.primary, muted: props.theme.muted,
50
56
  warning: props.theme.noticeWarn, error: props.theme.noticeError,
51
- accent: props.theme.accent };
52
- return _jsxs(Box, { width: cols, height: 1, flexShrink: 0, flexDirection: "row", overflow: "hidden", children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { children: redrawChar(props.redrawNonce ?? 0) }) }), _jsx(Box, { width: Math.max(0, cols - 1 - chipCells - kitCells), flexShrink: 0, flexDirection: "row", overflow: "hidden", children: plan.fields.map((item, index) => _jsxs(React.Fragment, { children: [index > 0 && _jsx(Box, { width: plan.separatorCells, flexShrink: 0, children: _jsx(Text, { color: props.theme.muted, children: plan.separator }) }), _jsx(Box, { width: item.cells, flexShrink: 0, children: _jsx(Text, { color: tones[item.tone], wrap: "truncate", children: item.id === 'phase' && active
57
+ accent: props.theme.accent, govern: props.theme.governAccent };
58
+ return _jsxs(Box, { width: cols, height: 1, flexShrink: 0, flexDirection: "row", overflow: "hidden", children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { children: redrawChar(props.redrawNonce ?? 0) }) }), _jsx(Box, { width: Math.max(0, cols - 1 - chipCells - kitCells - governCells), flexShrink: 0, flexDirection: "row", overflow: "hidden", children: plan.fields.map((item, index) => _jsxs(React.Fragment, { children: [index > 0 && _jsx(Box, { width: plan.separatorCells, flexShrink: 0, children: _jsx(Text, { color: props.theme.muted, children: plan.separator }) }), _jsx(Box, { width: item.cells, flexShrink: 0, children: _jsx(Text, { color: tones[item.tone], wrap: "truncate", children: item.id === 'phase' && active
53
59
  ? _jsxs(_Fragment, { children: [spinner ?? glyph, item.text.slice(glyph.length)] })
54
- : item.text }) })] }, item.id)) }), kit.visible && _jsx(Box, { width: kitCells, flexShrink: 0, justifyContent: "flex-end", overflow: "hidden", children: _jsx(Text, { color: props.theme.muted, wrap: "truncate", children: kit.text }) }), chip.visible && _jsx(Box, { width: chipCells, flexShrink: 0, justifyContent: "flex-end", overflow: "hidden", children: _jsx(Text, { color: props.theme.muted, wrap: "truncate", children: chip.text }) })] });
60
+ : item.text }) })] }, item.id)) }), govern.visible && _jsx(Box, { width: governCells, flexShrink: 0, justifyContent: "flex-end", overflow: "hidden", children: _jsx(Text, { color: toneColor(govern.tone, props.theme), wrap: "truncate", bold: true, children: govern.text }) }), kit.visible && _jsx(Box, { width: kitCells, flexShrink: 0, justifyContent: "flex-end", overflow: "hidden", children: _jsx(Text, { color: props.theme.muted, wrap: "truncate", children: kit.text }) }), chip.visible && _jsx(Box, { width: chipCells, flexShrink: 0, justifyContent: "flex-end", overflow: "hidden", children: _jsx(Text, { color: props.theme.muted, wrap: "truncate", children: chip.text }) })] });
55
61
  }
@@ -12,6 +12,7 @@ import { QueuedEntry } from './entries/QueuedEntry.js';
12
12
  import { AssistantEntry } from './entries/AssistantEntry.js';
13
13
  import { ToolCard, statusColor, toolEntryGlyph } from './entries/ToolCard.js';
14
14
  import { TeamCard, teamCardColor } from './entries/TeamCard.js';
15
+ import { GovernanceCard, governanceCardColor } from './entries/GovernanceCard.js';
15
16
  import { isLiveTeamCard, rosterCounts } from './team-status.js';
16
17
  import { TodoCard, todoCardColor } from './entries/TodoCard.js';
17
18
  import { RetryCard, retryCardColor } from './entries/RetryCard.js';
@@ -118,6 +119,8 @@ function EntryViewImpl({ entry, prev, expanded, thinkingVisible, reducedMotion,
118
119
  return null;
119
120
  return frame(glyphs.teamAgent, teamCardColor(rosterCounts(entry.runs), entry.active, entry.aborted, theme), _jsx(TeamCard, { requested: entry.requested, runs: entry.runs, aborted: entry.aborted, durationMs: entry.durationMs, active: entry.active, expanded: expanded, reducedMotion: reducedMotion, theme: theme, caps: caps, nowSec: nowSecFor(entry, nowSec) }));
120
121
  }
122
+ case 'governance':
123
+ return frame(glyphs.teamAgent, governanceCardColor(entry.card, theme), _jsx(GovernanceCard, { card: entry.card, theme: theme, caps: caps }));
121
124
  case 'todo':
122
125
  return frame(toolGlyph(glyphs, 'todo_write'), todoCardColor(entry.doneCount, entry.total, entry.live, theme), _jsx(TodoCard, { items: entry.items, doneCount: entry.doneCount, total: entry.total, acceptance: entry.acceptance ?? null, live: entry.live, interrupted: entry.interrupted, theme: theme, caps: caps }));
123
126
  case 'retry':
@@ -0,0 +1,30 @@
1
+ /**
2
+ * GovernanceCard - the settlement card for a `kind: 'governance'` entry
3
+ * (governance-mode section 10.4).
4
+ *
5
+ * ASCII ONLY: every glyph comes from `pickGlyphs`, through the layout.
6
+ *
7
+ * It renders inside the `EntryFrame` that `Transcript.tsx` supplies, so the left rail is
8
+ * the card's frame - no second box drawn inside the rail. (The spec sketches a
9
+ * rounded box; nested inside the gutter rail it would be two frames for one thing, and the
10
+ * rail already carries the tone colour. Recorded as a deliberate deviation.)
11
+ *
12
+ * EVERY LINE TRUNCATES, none wraps, so the card's height is a function of its data alone
13
+ * (`governanceCardRows`) and `virtual-window.ts::estimateEntryRows` is exact rather than an
14
+ * upper bound. A narrow terminal therefore degrades by truncation to one plain line per
15
+ * agent without any width-dependent branch here.
16
+ */
17
+ import React from 'react';
18
+ import type { GovernanceCardData } from '../../governance/types.js';
19
+ import type { Theme } from '../theme.js';
20
+ import type { TermCapabilities } from '../capabilities.js';
21
+ export interface GovernanceCardProps {
22
+ card: GovernanceCardData;
23
+ theme: Theme;
24
+ caps: TermCapabilities;
25
+ }
26
+ /** The rail colour: the card's verdict, resolved like every other governance tone. */
27
+ export declare function governanceCardColor(card: GovernanceCardData, theme: Theme): string | undefined;
28
+ declare function GovernanceCardImpl({ card, theme, caps }: GovernanceCardProps): React.ReactElement;
29
+ export declare const GovernanceCard: React.MemoExoticComponent<typeof GovernanceCardImpl>;
30
+ export {};
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * GovernanceCard - the settlement card for a `kind: 'governance'` entry
4
+ * (governance-mode section 10.4).
5
+ *
6
+ * ASCII ONLY: every glyph comes from `pickGlyphs`, through the layout.
7
+ *
8
+ * It renders inside the `EntryFrame` that `Transcript.tsx` supplies, so the left rail is
9
+ * the card's frame - no second box drawn inside the rail. (The spec sketches a
10
+ * rounded box; nested inside the gutter rail it would be two frames for one thing, and the
11
+ * rail already carries the tone colour. Recorded as a deliberate deviation.)
12
+ *
13
+ * EVERY LINE TRUNCATES, none wraps, so the card's height is a function of its data alone
14
+ * (`governanceCardRows`) and `virtual-window.ts::estimateEntryRows` is exact rather than an
15
+ * upper bound. A narrow terminal therefore degrades by truncation to one plain line per
16
+ * agent without any width-dependent branch here.
17
+ */
18
+ import React from 'react';
19
+ import { Box, Text } from 'ink';
20
+ import { pickGlyphs } from '../glyphs.js';
21
+ import { toneColor } from '../governance-status.js';
22
+ import { GovernanceLine, GovernanceRun } from '../GovernanceRun.js';
23
+ import { buildGovernanceCardLayout, cardTone } from '../layout/governance-card.js';
24
+ /** The rail colour: the card's verdict, resolved like every other governance tone. */
25
+ export function governanceCardColor(card, theme) {
26
+ return toneColor(cardTone(card), theme);
27
+ }
28
+ function GovernanceCardImpl({ card, theme, caps }) {
29
+ const layout = buildGovernanceCardLayout(card, pickGlyphs(caps));
30
+ return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsx(GovernanceLine, { segments: layout.title, theme: theme }), layout.headline && (_jsx(GovernanceLine, { segments: layout.headline, theme: theme })), layout.tableHeader && (_jsx(Text, { wrap: "truncate", children: layout.tableHeader.map((cell, index) => (_jsx(GovernanceRun, { segments: cell, theme: theme }, index))) })), layout.rows.map((row) => (_jsx(Text, { wrap: "truncate", children: row.cells.map((cell, index) => (_jsx(GovernanceRun, { segments: cell, theme: theme }, index))) }, row.key))), layout.notes && _jsx(GovernanceLine, { segments: layout.notes, theme: theme })] }));
31
+ }
32
+ export const GovernanceCard = React.memo(GovernanceCardImpl);
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Governance TUI copy: every user-visible English phrase of the legion panel, the chip,
3
+ * the settlement card and the `/gov board` overlay (governance-mode section 10.6).
4
+ *
5
+ * ASCII ONLY (`src/ui/**` is glyph-scanned). Phrases that need a symbol take it as a
6
+ * template parameter from `pickGlyphs(caps)` instead of spelling it.
7
+ *
8
+ * WHY THIS LIVES IN `ui/` AND NOT IN `governance/copy.ts`: the engine author owns that
9
+ * file and it carries the model-facing and notice wording. This module holds the strings
10
+ * only the TUI draws, so the two cannot collide while both are being written. When
11
+ * `governance/copy.ts` lands, a phrase that appears in both belongs THERE and this file
12
+ * re-exports it - the unit tests pin these strings, so the move is a compile error and
13
+ * not a silent fork.
14
+ */
15
+ import type { GovAgentState, GovRole, PipelineStepKey } from '../governance/types.js';
16
+ export declare const GOV_TITLE = "GOVERN";
17
+ /** One word for each pipeline step, as printed in the step strip. */
18
+ export declare const PIPELINE_LABEL: Readonly<Record<PipelineStepKey, string>>;
19
+ /** The role word in the roster's role column. */
20
+ export declare const ROLE_LABEL: Readonly<Record<GovRole, string>>;
21
+ /** What a `working` agent is doing, by role: the row says WHAT, the marker says THAT. */
22
+ export declare const WORKING_VERB: Readonly<Record<GovRole, string>>;
23
+ /** The state column's word for every non-working state. */
24
+ export declare const STATE_WORD: Readonly<Record<Exclude<GovAgentState, 'working'>, string>>;
25
+ export declare const NOT_SCORED = "not scored";
26
+ export declare const MORE_HINT = "(/gov board)";
27
+ export declare const PANEL_LEDGER_LABEL = "ledger";
28
+ export declare const PANEL_HEALTH_LABEL = "health";
29
+ export declare const PANEL_TOKEN_UNIT = "tok";
30
+ export declare const PANEL_BOARD_HINT = "/gov board";
31
+ export declare const STATUS_WORD: {
32
+ readonly pausing: "pausing";
33
+ readonly paused: "paused";
34
+ readonly escalated: "escalated";
35
+ readonly abandoned: "abandoned";
36
+ readonly closed: "closed";
37
+ };
38
+ /** `pausing after REVIEW`: a `/gov pause` is waiting for the running stage to finish. */
39
+ export declare function pausingText(stage: string): string;
40
+ /** `replaced by dev2-r1` (the glyph in front comes from the roster marker). */
41
+ export declare function replacedByText(successor: string | null): string;
42
+ export declare function moreText(hidden: number): string;
43
+ export declare function workingCountText(count: number): string;
44
+ export declare function phaseText(phase: number, phaseCount: number): string;
45
+ export declare function phaseLongText(phase: number, phaseCount: number): string;
46
+ /** Board tab names, in tab order. */
47
+ export declare const BOARD_TAB_LABEL: {
48
+ readonly roster: "Roster";
49
+ readonly work: "Work packages";
50
+ readonly ledger: "Ledger";
51
+ readonly claims: "Claims";
52
+ };
53
+ export declare const BOARD_TITLE = "Governance board";
54
+ export declare const BOARD_EMPTY: {
55
+ readonly noRun: "No governed run yet. Use /gov or Shift+Tab to enter GOVERN.";
56
+ readonly roster: "No agents yet.";
57
+ readonly work: "No work packages recorded for this view.";
58
+ readonly ledger: "No ledger entries yet.";
59
+ readonly claims: "No claims or escalations.";
60
+ };
61
+ export declare const BOARD_COPIED = "Copied the board file path";
62
+ export declare const BOARD_NO_PATH = "No board file path is available yet";
63
+ export declare const CARD_TITLE = "Governance";
64
+ export declare const CARD_COLUMNS: {
65
+ readonly id: "id";
66
+ readonly role: "role";
67
+ readonly confirmed: "confirmed";
68
+ readonly delta: "delta";
69
+ };
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Governance TUI copy: every user-visible English phrase of the legion panel, the chip,
3
+ * the settlement card and the `/gov board` overlay (governance-mode section 10.6).
4
+ *
5
+ * ASCII ONLY (`src/ui/**` is glyph-scanned). Phrases that need a symbol take it as a
6
+ * template parameter from `pickGlyphs(caps)` instead of spelling it.
7
+ *
8
+ * WHY THIS LIVES IN `ui/` AND NOT IN `governance/copy.ts`: the engine author owns that
9
+ * file and it carries the model-facing and notice wording. This module holds the strings
10
+ * only the TUI draws, so the two cannot collide while both are being written. When
11
+ * `governance/copy.ts` lands, a phrase that appears in both belongs THERE and this file
12
+ * re-exports it - the unit tests pin these strings, so the move is a compile error and
13
+ * not a silent fork.
14
+ */
15
+ export const GOV_TITLE = 'GOVERN';
16
+ /** One word for each pipeline step, as printed in the step strip. */
17
+ export const PIPELINE_LABEL = {
18
+ intake: 'INTAKE',
19
+ dev: 'DEV',
20
+ review: 'REVIEW',
21
+ test: 'TEST',
22
+ settle: 'SETTLE',
23
+ integrate: 'INTEGRATE',
24
+ fix: 'FIX',
25
+ };
26
+ /** The role word in the roster's role column. */
27
+ export const ROLE_LABEL = {
28
+ DEV: 'DEV',
29
+ REV: 'REV',
30
+ TEST: 'TEST',
31
+ INSP: 'INSP',
32
+ };
33
+ /** What a `working` agent is doing, by role: the row says WHAT, the marker says THAT. */
34
+ export const WORKING_VERB = {
35
+ DEV: 'coding',
36
+ REV: 'reviewing',
37
+ TEST: 'testing',
38
+ INSP: 'checking',
39
+ };
40
+ /** The state column's word for every non-working state. */
41
+ export const STATE_WORD = {
42
+ queued: 'queued',
43
+ submitted: 'submitted',
44
+ idle: 'idle',
45
+ failed: 'failed',
46
+ eliminated: 'replaced',
47
+ };
48
+ export const NOT_SCORED = 'not scored';
49
+ export const MORE_HINT = '(/gov board)';
50
+ export const PANEL_LEDGER_LABEL = 'ledger';
51
+ export const PANEL_HEALTH_LABEL = 'health';
52
+ export const PANEL_TOKEN_UNIT = 'tok';
53
+ export const PANEL_BOARD_HINT = '/gov board';
54
+ export const STATUS_WORD = {
55
+ pausing: 'pausing',
56
+ paused: 'paused',
57
+ escalated: 'escalated',
58
+ abandoned: 'abandoned',
59
+ closed: 'closed',
60
+ };
61
+ /** `pausing after REVIEW`: a `/gov pause` is waiting for the running stage to finish. */
62
+ export function pausingText(stage) {
63
+ return stage === '' ? STATUS_WORD.pausing : `${STATUS_WORD.pausing} after ${stage}`;
64
+ }
65
+ /** `replaced by dev2-r1` (the glyph in front comes from the roster marker). */
66
+ export function replacedByText(successor) {
67
+ return successor === null ? 'replaced' : `replaced by ${successor}`;
68
+ }
69
+ export function moreText(hidden) {
70
+ return `+${hidden} more ${MORE_HINT}`;
71
+ }
72
+ export function workingCountText(count) {
73
+ return `${count} working`;
74
+ }
75
+ export function phaseText(phase, phaseCount) {
76
+ return `p${phase}/${phaseCount}`;
77
+ }
78
+ export function phaseLongText(phase, phaseCount) {
79
+ return `phase ${phase}/${phaseCount}`;
80
+ }
81
+ /** Board tab names, in tab order. */
82
+ export const BOARD_TAB_LABEL = {
83
+ roster: 'Roster',
84
+ work: 'Work packages',
85
+ ledger: 'Ledger',
86
+ claims: 'Claims',
87
+ };
88
+ export const BOARD_TITLE = 'Governance board';
89
+ export const BOARD_EMPTY = {
90
+ noRun: 'No governed run yet. Use /gov or Shift+Tab to enter GOVERN.',
91
+ roster: 'No agents yet.',
92
+ work: 'No work packages recorded for this view.',
93
+ ledger: 'No ledger entries yet.',
94
+ claims: 'No claims or escalations.',
95
+ };
96
+ export const BOARD_COPIED = 'Copied the board file path';
97
+ export const BOARD_NO_PATH = 'No board file path is available yet';
98
+ export const CARD_TITLE = 'Governance';
99
+ export const CARD_COLUMNS = {
100
+ id: 'id',
101
+ role: 'role',
102
+ confirmed: 'confirmed',
103
+ delta: 'delta',
104
+ };