@aragon-agent/cli 0.6.44 → 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 (236) 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/session/validate-session.js +32 -1
  170. package/dist/team/runtime.d.ts +8 -0
  171. package/dist/team/runtime.js +9 -0
  172. package/dist/team/subagent.d.ts +23 -0
  173. package/dist/team/subagent.js +14 -3
  174. package/dist/team/types.d.ts +6 -0
  175. package/dist/tools/index.d.ts +30 -7
  176. package/dist/tools/index.js +14 -0
  177. package/dist/tools/plan-tools.d.ts +14 -2
  178. package/dist/tools/plan-tools.js +5 -2
  179. package/dist/ui/App.js +145 -25
  180. package/dist/ui/BottomStatusRow.js +1 -1
  181. package/dist/ui/Composer.d.ts +7 -1
  182. package/dist/ui/Composer.js +9 -6
  183. package/dist/ui/GovernancePanel.d.ts +50 -0
  184. package/dist/ui/GovernancePanel.js +77 -0
  185. package/dist/ui/GovernanceRun.d.ts +18 -0
  186. package/dist/ui/GovernanceRun.js +11 -0
  187. package/dist/ui/StatusBar.d.ts +15 -2
  188. package/dist/ui/StatusBar.js +10 -4
  189. package/dist/ui/Transcript.js +3 -0
  190. package/dist/ui/entries/GovernanceCard.d.ts +30 -0
  191. package/dist/ui/entries/GovernanceCard.js +32 -0
  192. package/dist/ui/governance-copy.d.ts +69 -0
  193. package/dist/ui/governance-copy.js +104 -0
  194. package/dist/ui/governance-status.d.ts +145 -0
  195. package/dist/ui/governance-status.js +326 -0
  196. package/dist/ui/interaction-copy.d.ts +4 -0
  197. package/dist/ui/interaction-copy.js +5 -0
  198. package/dist/ui/interaction-hints.d.ts +17 -0
  199. package/dist/ui/interaction-hints.js +14 -2
  200. package/dist/ui/layout/governance-board.d.ts +121 -0
  201. package/dist/ui/layout/governance-board.js +382 -0
  202. package/dist/ui/layout/governance-card.d.ts +53 -0
  203. package/dist/ui/layout/governance-card.js +134 -0
  204. package/dist/ui/layout/governance-chip.d.ts +38 -0
  205. package/dist/ui/layout/governance-chip.js +64 -0
  206. package/dist/ui/layout/governance-panel.d.ts +85 -0
  207. package/dist/ui/layout/governance-panel.js +358 -0
  208. package/dist/ui/layout/governance-roster.d.ts +65 -0
  209. package/dist/ui/layout/governance-roster.js +275 -0
  210. package/dist/ui/layout/status-detail-layout.js +3 -3
  211. package/dist/ui/layout/status-layout.d.ts +5 -2
  212. package/dist/ui/layout/status-layout.js +10 -6
  213. package/dist/ui/layout/virtual-window.js +11 -0
  214. package/dist/ui/overlays/GovernanceBoardOverlay.d.ts +41 -0
  215. package/dist/ui/overlays/GovernanceBoardOverlay.js +76 -0
  216. package/dist/ui/overlays/GovernanceSettingsPage.d.ts +48 -0
  217. package/dist/ui/overlays/GovernanceSettingsPage.js +93 -0
  218. package/dist/ui/overlays/HelpOverlay.js +4 -3
  219. package/dist/ui/overlays/QuestionOverlay.d.ts +9 -1
  220. package/dist/ui/overlays/QuestionOverlay.js +4 -2
  221. package/dist/ui/overlays/SettingsScreen.d.ts +7 -0
  222. package/dist/ui/overlays/SettingsScreen.js +21 -1
  223. package/dist/ui/overlays/governance-settings.d.ts +79 -0
  224. package/dist/ui/overlays/governance-settings.js +140 -0
  225. package/dist/ui/overlays/model-profile-state.d.ts +6 -1
  226. package/dist/ui/overlays/model-profile-state.js +10 -0
  227. package/dist/ui/palettes.d.ts +17 -0
  228. package/dist/ui/palettes.js +9 -0
  229. package/dist/ui/scrollback/live-preview.js +2 -0
  230. package/dist/ui/scrollback/settled-boundary.js +3 -0
  231. package/dist/ui/shortcuts.js +2 -2
  232. package/dist/ui/theme.d.ts +7 -0
  233. package/dist/ui/theme.js +1 -0
  234. package/dist/ui/transcript-text.js +9 -0
  235. package/dist/ui/use-wheel-routing.js +3 -1
  236. package/package.json +2 -2
@@ -47,7 +47,7 @@ export function allKeyRows(times) {
47
47
  // product's word for transcript line offset (the header chip and the row below),
48
48
  // so abbreviating the mode fallback would put two meanings of `^` on one screen
49
49
  // (quick-prompt-library D-1 / P1-7).
50
- ['Shift+Tab / Ctrl+N', 'Toggle plan mode (same as /plan)'],
50
+ ['Shift+Tab / Ctrl+N', 'Cycle BUILD / PLAN / GOVERN / PLAN+GOVERN (/plan and /gov pick one)'],
51
51
  ['Ctrl+P', 'Quick prompt library: manage, create, reorder, pick'],
52
52
  // The ladder clears a draft first (ctrl-c-clear-draft-exit):
53
53
  // with a draft x2 clears the input and x3 exits; an empty input
@@ -117,7 +117,8 @@ const COMMANDS = [
117
117
  ['/task refresh', 'Regenerate the header task summary from the last prompt'],
118
118
  ['/model', 'Open the model picker'],
119
119
  ['/settings', 'Open the settings screen'],
120
- ['/plan [on|off|status]', 'Toggle plan mode (same as Shift+Tab)'],
120
+ ['/plan [on|off|status]', 'Toggle plan mode (leaves GOVERN)'],
121
+ ['/gov [on|plan|off|board|status]', 'Governed team: enter, leave, the board, the run status'],
121
122
  ['/theme <name>', 'auto | warm | cool | light'],
122
123
  ['/thinking <level>', 'Set thinking level'],
123
124
  ['/max-tokens [n|auto]', 'Output token cap; no argument reports the effective one'],
@@ -165,7 +166,7 @@ const SKILL_ROWS = [
165
166
  ['skill / skill_install', 'Tools the model uses to load and install skills'],
166
167
  ];
167
168
  const PLAN_ROWS = [
168
- ['Shift+Tab / /plan', 'Switch between BUILD (do it now) and PLAN (research first)'],
169
+ ['Shift+Tab / /plan', 'Switch BUILD (do it now) and PLAN (research first); Shift+Tab also cycles GOVERN'],
169
170
  // A ROW OF ITS OWN, not a third name on the line above: the reader who needs
170
171
  // this one is the reader whose `Shift+Tab` does nothing, and what they need is
171
172
  // the reason, not another synonym. Listing the key in both places instead just
@@ -26,6 +26,14 @@ interface QuestionOverlayProps {
26
26
  theme: Theme;
27
27
  caps: TermCapabilities;
28
28
  onSubmit: (answers: Answer[]) => void;
29
+ /**
30
+ * PLAN+GOVERN interview progress (governance-mode 9 / 10.6). Present only in that
31
+ * posture; absent leaves the title byte-identical to the pre-governance overlay.
32
+ */
33
+ interview?: {
34
+ round: number;
35
+ required: number;
36
+ };
29
37
  }
30
- export declare function QuestionOverlay({ isActive, questions, maxRows, cols, theme, caps, onSubmit, }: QuestionOverlayProps): React.ReactElement;
38
+ export declare function QuestionOverlay({ isActive, questions, maxRows, cols, theme, caps, onSubmit, interview, }: QuestionOverlayProps): React.ReactElement;
31
39
  export {};
@@ -22,6 +22,7 @@ import { wrapToRows } from '../layout/wrap-rows.js';
22
22
  import { OverlayFrame, overlayBodyRows } from '../layout/OverlayFrame.js';
23
23
  import { stripPasteFrames } from '../paste-frames.js';
24
24
  import { stripEnterFrames } from '../enter-frames.js';
25
+ import { interviewChipText } from '../governance-status.js';
25
26
  /** Which option index each question starts on: the recommended one. */
26
27
  function initialCursors(questions) {
27
28
  return questions.map((q) => Math.max(0, q.options.findIndex((o) => o.recommended)));
@@ -32,7 +33,7 @@ function initialSelections(questions) {
32
33
  return new Set(recommended >= 0 ? [recommended] : [0]);
33
34
  });
34
35
  }
35
- export function QuestionOverlay({ isActive = true, questions, maxRows, cols, theme, caps, onSubmit, }) {
36
+ export function QuestionOverlay({ isActive = true, questions, maxRows, cols, theme, caps, onSubmit, interview, }) {
36
37
  const glyphs = pickGlyphs(caps);
37
38
  const [step, setStep] = useState(0);
38
39
  const [phase, setPhase] = useState('choosing');
@@ -215,6 +216,7 @@ export function QuestionOverlay({ isActive = true, questions, maxRows, cols, the
215
216
  });
216
217
  const title = phase === 'review' ? 'Review your answers' : 'Clarify the request';
217
218
  const position = phase === 'review' ? '' : ` ${step + 1}/${questions.length}`;
219
+ const interviewChip = interview ? ` ${interviewChipText(interview.round, interview.required)}` : '';
218
220
  const hint = phase === 'typingOther'
219
221
  ? `type your answer ${glyphs.midDot} ${glyphs.enterKey} commit ${glyphs.midDot} ${glyphs.arrowLeft} back ${glyphs.midDot} esc cancel`
220
222
  : phase === 'review'
@@ -252,5 +254,5 @@ export function QuestionOverlay({ isActive = true, questions, maxRows, cols, the
252
254
  const shortHint = phase === 'typingOther' ? 'Enter commit | Left back | Esc cancel'
253
255
  : phase === 'review' ? 'Enter submit | Left back | Esc cancel'
254
256
  : '^v choose Space select Enter next Esc';
255
- return _jsx(OverlayFrame, { title: `${title}${position}`, hint: cols <= 48 ? shortHint : hint, maxRows: maxRows, cols: cols, theme: theme, caps: caps, rows: rowTexts.map((line, index) => _jsx(Text, { wrap: "truncate", children: line || ' ' }, index)), scrollOffset: offset, onScrollClamp: setOffset });
257
+ return _jsx(OverlayFrame, { title: `${title}${position}${interviewChip}`, hint: cols <= 48 ? shortHint : hint, maxRows: maxRows, cols: cols, theme: theme, caps: caps, rows: rowTexts.map((line, index) => _jsx(Text, { wrap: "truncate", children: line || ' ' }, index)), scrollOffset: offset, onScrollClamp: setOffset });
256
258
  }
@@ -146,6 +146,13 @@ interface SettingsScreenProps {
146
146
  * literal, and absent honestly means "unknown, so do not disclose".
147
147
  */
148
148
  teamRegistered?: boolean;
149
+ /**
150
+ * Whether the governance tools were registered when this session started
151
+ * (governance-mode-v1-1 5.2). Same contract as `teamRegistered`: a CONSTRUCTION-TIME
152
+ * snapshot, OPTIONAL, and `undefined` means "not disclosed" so no note is shown. It is
153
+ * what lets the page say `applies next launch` when the draft's `enabled` disagrees.
154
+ */
155
+ governanceRegistered?: boolean;
149
156
  }
150
157
  /**
151
158
  * The derived, non-editable line under the five fast rows — the sibling of
@@ -29,6 +29,8 @@ import { KitEditor } from './KitEditor.js';
29
29
  import { KitManager } from './KitManager.js';
30
30
  import { TeamFanoutPage } from './TeamFanoutPage.js';
31
31
  import { fanoutRows, teamFanoutValues, teamSummary } from './team-fanout-state.js';
32
+ import { GovernanceSettingsPage } from './GovernanceSettingsPage.js';
33
+ import { draftGovernance, governanceRestartNote, governanceSettingRows, governanceSummary, } from './governance-settings.js';
32
34
  import { heldSlots, kitManagerRows, kitPackRow, kitReducer } from './kit-settings-state.js';
33
35
  /**
34
36
  * THE ROOT PAGE'S ROW INDEXES, AS NAMES (subagent-model V-5).
@@ -42,7 +44,7 @@ import { heldSlots, kitManagerRows, kitPackRow, kitReducer } from './kit-setting
42
44
  * fifth of these and the "five offsets agreed by accident" defect does not need
43
45
  * a sequel. Order here IS the render order.
44
46
  */
45
- const ROOT_ROWS = ['main', 'fast', 'subagent', 'team', 'kit', 'manage'];
47
+ const ROOT_ROWS = ['main', 'fast', 'subagent', 'team', 'governance', 'kit', 'manage'];
46
48
  const ROOT_MAIN = ROOT_ROWS.indexOf('main');
47
49
  const ROOT_FAST = ROOT_ROWS.indexOf('fast');
48
50
  const ROOT_SUBAGENT = ROOT_ROWS.indexOf('subagent');
@@ -51,6 +53,9 @@ const ROOT_SUBAGENT = ROOT_ROWS.indexOf('subagent');
51
53
  // one decision, and splitting them across the page would make the pair harder to
52
54
  // keep consistent than the pair of numbers inside it.
53
55
  const ROOT_TEAM = ROOT_ROWS.indexOf('team');
56
+ // Governance (governance-mode-v1-1 5.2) sits right under Team: both decide the SHAPE of the
57
+ // team, and the row is an index into this list like every other, never a typed number.
58
+ const ROOT_GOVERNANCE = ROOT_ROWS.indexOf('governance');
54
59
  const ROOT_KIT = ROOT_ROWS.indexOf('kit');
55
60
  const ROOT_MANAGE = ROOT_ROWS.indexOf('manage');
56
61
  const ROOT_FIRST_FIELD = ROOT_ROWS.length;
@@ -693,6 +698,12 @@ function activateRootSetting(props, view) {
693
698
  // `team-fanout-page.test.tsx` asserts that Enter on this row saves nothing.
694
699
  dispatch({ type: 'page', page: 'team' });
695
700
  }
701
+ else if (index === ROOT_GOVERNANCE) {
702
+ // SAME RULE AS THE TEAM BRANCH ABOVE, and the same cost of getting it wrong: this MUST
703
+ // stay above the fallback `else`, which is `saveProfileSettings`. A misplaced branch
704
+ // compiles and silently commits the whole draft when Enter opens the page.
705
+ dispatch({ type: 'page', page: 'governance' });
706
+ }
696
707
  else if (index === ROOT_KIT) {
697
708
  // The fifth root row opens the manager, not a picker: kits are data the user
698
709
  // owns here, and `ctrl+K` is where they are CONSUMED (agent-model-kits §4.5).
@@ -858,6 +869,14 @@ function renderProfileSubpage(props, view) {
858
869
  rows: fanoutRows(teamFanoutValues(state.draft), props.teamRegistered),
859
870
  error: state.error,
860
871
  }, dispatch: dispatch, onBack: () => dispatch({ type: 'page', page: 'root' }) });
872
+ if (state.page === 'governance') {
873
+ const config = draftGovernance(state.draft);
874
+ return _jsx(GovernanceSettingsPage, { ...props, view: {
875
+ rows: governanceSettingRows(config),
876
+ error: state.error,
877
+ restartNote: governanceRestartNote(config.enabled, props.governanceRegistered),
878
+ }, dispatch: dispatch, onBack: () => dispatch({ type: 'page', page: 'root' }) });
879
+ }
861
880
  // THE KIT PAGES (agent-model-kits §4.5). They are dispatched BEFORE the profile
862
881
  // pages because `'kit-slot'` RENDERS a profile picker while belonging to the
863
882
  // kit editor - the page name, not the component, decides where the user is.
@@ -982,6 +1001,7 @@ function buildRootSettingsRows(props, view) {
982
1001
  // four values, only two of which are about fan-out width. `padEnd(18)` is
983
1002
  // unchanged, so the value column still lines up with `Subagent model`.
984
1003
  `Team ${summary}`,
1004
+ `Governance ${governanceSummary(draftGovernance(state.draft))}`,
985
1005
  `Kit pack ${kitPackRow(state)}`,
986
1006
  `Manage profiles ${library.entries.length} saved`,
987
1007
  ...fields.map((item) => `${item.label.padEnd(18)}${item.key === 'apiKey'
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Settings > Governance: the pure half of the page (governance-mode 11.1).
3
+ *
4
+ * ASCII ONLY - `src/ui/**` is inside `glyphs.test.ts::inScope`.
5
+ *
6
+ * FIELD DEFINITIONS AND THE ARROW-KEY STEP, NOTHING ELSE. `SettingsScreen.tsx` is far past
7
+ * the size limit, so the page lists its rows from here and adds wiring only, mirroring
8
+ * `team-fanout-state.ts`. Every value a step produces goes back through
9
+ * `clampGovernanceConfig`, so the page, `config set` and a hand-edited `config.json` can
10
+ * never disagree about a range.
11
+ *
12
+ * THE PAGE MAY WRITE THE ELEVEN POLICY KEYS AND NOTHING ELSE. The structural bounds
13
+ * (`GOV_LIMITS`) are not settings: a number a user can tune past what the store and the
14
+ * panel can carry is not a preference, it is a crash.
15
+ */
16
+ import { type GovernanceConfig } from '../../config/governance-config.js';
17
+ import type { ModelSettingsDraft } from '../../config/model-profile-store.js';
18
+ export type GovernanceSettingKey = keyof GovernanceConfig;
19
+ export type GovernanceSettingKind = 'toggle' | 'number' | 'choice';
20
+ export interface GovernanceSettingDef {
21
+ key: GovernanceSettingKey;
22
+ /** At most 17 columns: the page pads labels to 18, like the Team page. */
23
+ label: string;
24
+ /** One line, at most 60 columns: WHY this setting, not a restatement of the label. */
25
+ description: string;
26
+ kind: GovernanceSettingKind;
27
+ /** Inclusive; numbers only. Read from the clamp, never repeated here. */
28
+ range?: {
29
+ min: number;
30
+ max: number;
31
+ };
32
+ /** Arrow-key increment; numbers only. */
33
+ step?: number;
34
+ /** Cycle order; choices only. */
35
+ choices?: readonly string[];
36
+ }
37
+ /** The rows in cursor order. The switch is first: the rest describe what it turns on. */
38
+ export declare const GOVERNANCE_SETTING_DEFS: readonly GovernanceSettingDef[];
39
+ export interface GovernanceSettingRow {
40
+ key: GovernanceSettingKey;
41
+ label: string;
42
+ /** The value as the page prints it (`'on'` / `'3'` / `'unlimited'`). */
43
+ value: string;
44
+ /** Description plus the range, one line. */
45
+ hint: string;
46
+ }
47
+ /** The page's rows for the CLAMPED section, so the screen shows what would be saved. */
48
+ export declare function governanceSettingRows(values: unknown): GovernanceSettingRow[];
49
+ /**
50
+ * The PATCH FRAGMENT for one arrow press, for a section the screen already shows
51
+ * (`current`). Exactly one key, so a step can never carry a second one into the draft.
52
+ * Toggles flip on either arrow, as on the Team page: a direction means nothing for two
53
+ * states. An unknown key yields an empty patch rather than throwing.
54
+ */
55
+ export declare function stepGovernanceSetting(current: unknown, key: GovernanceSettingKey, delta: -1 | 1): Partial<GovernanceConfig>;
56
+ /**
57
+ * The governance section this draft would save: the patch over the disk baseline, then the
58
+ * clamp (governance-mode-v1-1 5.2). Same order as `teamFanoutValues`, and the clamp is not
59
+ * cosmetic: it is what makes the number on screen the number `Ctrl+S` writes, whatever a
60
+ * hand-edited `config.json` or an old patch carried.
61
+ */
62
+ export declare function draftGovernance(draft: ModelSettingsDraft): GovernanceConfig;
63
+ /**
64
+ * The one-line summary the settings root row prints. A DERIVED row, never a control: the
65
+ * values change on the page Enter opens, so the root row cannot be moved by a stray arrow.
66
+ * `off` alone when the switch is off, because the numbers then describe a capability that
67
+ * is not there (the `teamSummary` rule).
68
+ */
69
+ export declare function governanceSummary(config: GovernanceConfig): string;
70
+ export type GovernanceRestartNote = string | null;
71
+ /**
72
+ * Whether saving the `enabled` switch would not take effect in THIS session. The tool array
73
+ * is immutable after construction (v1 D-22), so a draft that disagrees with what was
74
+ * registered at launch only applies next launch, and the page says so rather than letting a
75
+ * user believe a toggle summoned `gov_run` into the running session. `undefined` means the
76
+ * host did not say, and the page then discloses nothing (every fixture builds props by
77
+ * literal).
78
+ */
79
+ export declare function governanceRestartNote(enabledInDraft: boolean, registeredAtLaunch: boolean | undefined): GovernanceRestartNote;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Settings > Governance: the pure half of the page (governance-mode 11.1).
3
+ *
4
+ * ASCII ONLY - `src/ui/**` is inside `glyphs.test.ts::inScope`.
5
+ *
6
+ * FIELD DEFINITIONS AND THE ARROW-KEY STEP, NOTHING ELSE. `SettingsScreen.tsx` is far past
7
+ * the size limit, so the page lists its rows from here and adds wiring only, mirroring
8
+ * `team-fanout-state.ts`. Every value a step produces goes back through
9
+ * `clampGovernanceConfig`, so the page, `config set` and a hand-edited `config.json` can
10
+ * never disagree about a range.
11
+ *
12
+ * THE PAGE MAY WRITE THE ELEVEN POLICY KEYS AND NOTHING ELSE. The structural bounds
13
+ * (`GOV_LIMITS`) are not settings: a number a user can tune past what the store and the
14
+ * panel can carry is not a preference, it is a crash.
15
+ */
16
+ import { clampGovernanceConfig, governanceRangeOf, } from '../../config/governance-config.js';
17
+ import { PROFILE_IDS } from '../../governance/types.js';
18
+ function numeric(key, label, description, step = 1) {
19
+ return { key, label, description, kind: 'number', range: governanceRangeOf(key), step };
20
+ }
21
+ /** The rows in cursor order. The switch is first: the rest describe what it turns on. */
22
+ export const GOVERNANCE_SETTING_DEFS = [
23
+ { key: 'enabled', label: 'Governance', kind: 'toggle',
24
+ description: 'Off removes it entirely. Turning it on needs a restart.' },
25
+ { key: 'shiftTab', label: 'Shift+Tab cycle', kind: 'toggle',
26
+ description: 'Off keeps Shift+Tab on BUILD/PLAN; /gov still works.' },
27
+ { key: 'panel', label: 'Legion panel', kind: 'toggle',
28
+ description: 'Off shows the status chip only, no panel.' },
29
+ { key: 'profile', label: 'Profile', kind: 'choice', choices: PROFILE_IDS,
30
+ description: 'Domain wording for the roles and their checklists.' },
31
+ numeric('maxWorkPackages', 'Work packages', 'Most work packages one run may define.'),
32
+ numeric('maxPhases', 'Phases', 'Most dev/review/test rounds one run may take.'),
33
+ numeric('maxRework', 'Rework rounds', 'Rework rounds per work package before escalation.'),
34
+ numeric('maxFixCycles', 'Fix cycles', 'Fix cycles per phase after integration fails.'),
35
+ numeric('minAskRounds', 'Ask rounds', 'Questions PLAN+GOVERN asks before a plan is allowed.'),
36
+ numeric('budgetTokens', 'Token budget', 'Per-run token ceiling; 0 means unlimited.', 100_000),
37
+ { key: 'confirmCharter', label: 'Confirm charter', kind: 'toggle',
38
+ description: 'On asks you to approve the run plan before any dispatch.' },
39
+ ];
40
+ function formatValue(def, config) {
41
+ const value = config[def.key];
42
+ if (def.kind === 'toggle')
43
+ return value ? 'on' : 'off';
44
+ if (def.key === 'budgetTokens')
45
+ return value === 0 ? 'unlimited' : String(value);
46
+ return String(value);
47
+ }
48
+ function formatHint(def) {
49
+ if (def.range === undefined)
50
+ return def.description;
51
+ return `${def.description} (${def.range.min}-${def.range.max})`;
52
+ }
53
+ /** The page's rows for the CLAMPED section, so the screen shows what would be saved. */
54
+ export function governanceSettingRows(values) {
55
+ const config = clampGovernanceConfig(values);
56
+ return GOVERNANCE_SETTING_DEFS.map((def) => ({
57
+ key: def.key,
58
+ label: def.label,
59
+ value: formatValue(def, config),
60
+ hint: formatHint(def),
61
+ }));
62
+ }
63
+ function stepNumber(config, def, delta) {
64
+ const key = def.key;
65
+ // NO WRAPAROUND: a form control is not a ring, and Left at the floor jumping to the
66
+ // ceiling would be a way to raise a limit while trying to lower it. The clamp does it.
67
+ const next = clampGovernanceConfig({ ...config, [key]: config[key] + delta * (def.step ?? 1) });
68
+ return { [key]: next[key] };
69
+ }
70
+ function stepChoice(config, def, delta) {
71
+ const choices = def.choices ?? [];
72
+ const at = choices.indexOf(String(config[def.key]));
73
+ const next = choices[(at + delta + choices.length) % choices.length];
74
+ // Through the clamp, so a choice list that ever drifts from the clamp's vocabulary cannot
75
+ // write a value the read path would silently repair.
76
+ const stored = clampGovernanceConfig({ ...config, [def.key]: next })[def.key];
77
+ return { [def.key]: stored };
78
+ }
79
+ /**
80
+ * The PATCH FRAGMENT for one arrow press, for a section the screen already shows
81
+ * (`current`). Exactly one key, so a step can never carry a second one into the draft.
82
+ * Toggles flip on either arrow, as on the Team page: a direction means nothing for two
83
+ * states. An unknown key yields an empty patch rather than throwing.
84
+ */
85
+ export function stepGovernanceSetting(current, key, delta) {
86
+ const config = clampGovernanceConfig(current);
87
+ const def = GOVERNANCE_SETTING_DEFS.find((candidate) => candidate.key === key);
88
+ if (def === undefined)
89
+ return {};
90
+ if (def.kind === 'toggle')
91
+ return { [key]: !config[key] };
92
+ return def.kind === 'number' ? stepNumber(config, def, delta) : stepChoice(config, def, delta);
93
+ }
94
+ /**
95
+ * The governance section this draft would save: the patch over the disk baseline, then the
96
+ * clamp (governance-mode-v1-1 5.2). Same order as `teamFanoutValues`, and the clamp is not
97
+ * cosmetic: it is what makes the number on screen the number `Ctrl+S` writes, whatever a
98
+ * hand-edited `config.json` or an old patch carried.
99
+ */
100
+ export function draftGovernance(draft) {
101
+ return clampGovernanceConfig({ ...draft.baseline.governance, ...draft.patch.governance });
102
+ }
103
+ /** `0` is unlimited; otherwise a compact figure (`500k`, `1.2M`). */
104
+ function budgetText(tokens) {
105
+ if (tokens <= 0)
106
+ return 'unlimited';
107
+ if (tokens >= 1_000_000)
108
+ return `${Number((tokens / 1_000_000).toFixed(1))}M`;
109
+ return `${Math.round(tokens / 1_000)}k`;
110
+ }
111
+ /**
112
+ * The one-line summary the settings root row prints. A DERIVED row, never a control: the
113
+ * values change on the page Enter opens, so the root row cannot be moved by a stray arrow.
114
+ * `off` alone when the switch is off, because the numbers then describe a capability that
115
+ * is not there (the `teamSummary` rule).
116
+ */
117
+ export function governanceSummary(config) {
118
+ if (!config.enabled)
119
+ return 'off';
120
+ return [
121
+ 'on',
122
+ `${config.maxWorkPackages} WP`,
123
+ `${config.maxPhases} phases`,
124
+ `rework ${config.maxRework}`,
125
+ `budget ${budgetText(config.budgetTokens)}`,
126
+ ].join(' | ');
127
+ }
128
+ /**
129
+ * Whether saving the `enabled` switch would not take effect in THIS session. The tool array
130
+ * is immutable after construction (v1 D-22), so a draft that disagrees with what was
131
+ * registered at launch only applies next launch, and the page says so rather than letting a
132
+ * user believe a toggle summoned `gov_run` into the running session. `undefined` means the
133
+ * host did not say, and the page then discloses nothing (every fixture builds props by
134
+ * literal).
135
+ */
136
+ export function governanceRestartNote(enabledInDraft, registeredAtLaunch) {
137
+ if (registeredAtLaunch === undefined || enabledInDraft === registeredAtLaunch)
138
+ return null;
139
+ return 'Governance is registered at launch; this change applies next launch.';
140
+ }
@@ -4,7 +4,8 @@ import type { ModelSettingsDraft } from '../../config/model-profile-store.js';
4
4
  import type { SubagentModelMode } from '../../team/model.js';
5
5
  import type { KitDraft } from './kit-settings-state.js';
6
6
  import { type TeamFanoutField } from './team-fanout-state.js';
7
- export type ProfilePage = 'root' | 'picker' | 'manager' | 'editor' | 'models' | 'delete-confirm' | 'discard-confirm' | 'kits' | 'kit-edit' | 'kit-slot' | 'kit-delete' | 'team';
7
+ import { type GovernanceSettingKey } from './governance-settings.js';
8
+ export type ProfilePage = 'root' | 'picker' | 'manager' | 'editor' | 'models' | 'delete-confirm' | 'discard-confirm' | 'kits' | 'kit-edit' | 'kit-slot' | 'kit-delete' | 'team' | 'governance';
8
9
  /**
9
10
  * `'team'` is the fan-out page (subagent-fanout D-5), and it is a PAGE rather
10
11
  * than three more fields on the root page for a measurable reason: the root page
@@ -118,6 +119,10 @@ export type ModelProfileAction = {
118
119
  type: 'team-fanout';
119
120
  field: TeamFanoutField;
120
121
  delta: -1 | 1;
122
+ } | {
123
+ type: 'governance-step';
124
+ key: GovernanceSettingKey;
125
+ delta: -1 | 1;
121
126
  };
122
127
  /** Keep the original secret separate from the empty replacement field. */
123
128
  export declare function createProfileEditor(profile: ModelProfile): ProfileEditorDraft;
@@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto';
2
2
  import { emptyModelProfiles, duplicateModelProfile, normalizeModelProfiles, validateModelProfiles } from '../../config/model-profiles.js';
3
3
  import { parseContextWindowInput } from '../../config/schema.js';
4
4
  import { stepFanoutValue, teamFanoutValues } from './team-fanout-state.js';
5
+ import { draftGovernance, stepGovernanceSetting } from './governance-settings.js';
5
6
  /** The picker's built-in `Fast tier model` row; never a profile id on disk. */
6
7
  export const SUBAGENT_FAST_ROW_ID = '__fast__';
7
8
  /** Keep the original secret separate from the empty replacement field. */
@@ -233,6 +234,15 @@ export function modelProfileReducer(state, action) {
233
234
  draft: { ...state.draft,
234
235
  patch: { ...state.draft.patch, team: { ...state.draft.patch.team, ...step } } } };
235
236
  }
237
+ case 'governance-step': {
238
+ // THE FRAGMENT IS THE ONLY THING WRITTEN, as for `team-fanout`: `stepGovernanceSetting`
239
+ // returns exactly one key, clamped, from the value the screen is showing
240
+ // (`draftGovernance`), so a step can never drag a second key into the patch.
241
+ const step = stepGovernanceSetting(draftGovernance(state.draft), action.key, action.delta);
242
+ return { ...state, dirty: true, error: undefined,
243
+ draft: { ...state.draft, patch: { ...state.draft.patch,
244
+ governance: { ...state.draft.patch.governance, ...step } } } };
245
+ }
236
246
  case 'duplicate': {
237
247
  if (library.entries.length >= 200)
238
248
  return { ...state,
@@ -71,6 +71,17 @@ export interface Palette {
71
71
  fg: string;
72
72
  bg: string;
73
73
  };
74
+ /**
75
+ * The GOVERN / PLAN+GOVERN posture badge, the legion panel title and the status chip
76
+ * (governance-mode section 10.7).
77
+ *
78
+ * A hue of its own, pinned by `palettes.test.ts`: >= 4.5:1 against THIS palette's own
79
+ * surface and >= 30 degrees away from the six semantic hues it must never be confused
80
+ * with (`primary`, `accent`, `user`, `toolDone`, `noticeWarn`, `noticeError`) - the
81
+ * last four because governance score gains and losses are drawn in `toolDone` /
82
+ * `noticeError` right beside it. The numbers below are the measured starting points.
83
+ */
84
+ governAccent: string;
74
85
  }
75
86
  /**
76
87
  * The reference dark background these palettes are contrast-checked against.
@@ -79,6 +90,12 @@ export interface Palette {
79
90
  * text unreadable.
80
91
  */
81
92
  export declare const DARK_SURFACE = "#1c1917";
93
+ /**
94
+ * The reference background of the `LIGHT` palette. `LIGHT` text is dark-on-light, so
95
+ * contrast-checking it against `DARK_SURFACE` would pass a pair that is unreadable in
96
+ * the only place it is ever used (the same trap `selectionBg` documents).
97
+ */
98
+ export declare const LIGHT_SURFACE = "#ffffff";
82
99
  /** Terracotta + amber over warm neutrals — the v0.4.0 default. */
83
100
  export declare const WARM: Palette;
84
101
  /** The v0.3.0 palette, renamed. Reachable via `--theme cool` / `theme: "dark"`. */
@@ -18,6 +18,12 @@
18
18
  * text unreadable.
19
19
  */
20
20
  export const DARK_SURFACE = '#1c1917';
21
+ /**
22
+ * The reference background of the `LIGHT` palette. `LIGHT` text is dark-on-light, so
23
+ * contrast-checking it against `DARK_SURFACE` would pass a pair that is unreadable in
24
+ * the only place it is ever used (the same trap `selectionBg` documents).
25
+ */
26
+ export const LIGHT_SURFACE = '#ffffff';
21
27
  /** Terracotta + amber over warm neutrals — the v0.4.0 default. */
22
28
  export const WARM = {
23
29
  primary: '#d08c60',
@@ -46,6 +52,7 @@ export const WARM = {
46
52
  diff: { add: '#7fb08a', remove: '#cf6b5c', meta: '#d08c60', context: '#a2968a' },
47
53
  toast: { info: '#d08c60', warn: '#c9a227', error: '#cf6b5c', success: '#7fb08a' },
48
54
  chip: { fg: '#1c1917', bg: '#d08c60' },
55
+ governAccent: '#B79CED',
49
56
  };
50
57
  /** The v0.3.0 palette, renamed. Reachable via `--theme cool` / `theme: "dark"`. */
51
58
  export const COOL = {
@@ -75,6 +82,7 @@ export const COOL = {
75
82
  diff: { add: '#9ece6a', remove: '#f7768e', meta: '#7aa2f7', context: '#7a86b8' },
76
83
  toast: { info: '#7aa2f7', warn: '#e0af68', error: '#f7768e', success: '#9ece6a' },
77
84
  chip: { fg: '#1a1b26', bg: '#7aa2f7' },
85
+ governAccent: '#73DACA',
78
86
  };
79
87
  export const LIGHT = {
80
88
  primary: '#2959aa',
@@ -103,6 +111,7 @@ export const LIGHT = {
103
111
  diff: { add: '#2e7d32', remove: '#c62828', meta: '#2959aa', context: '#6b7280' },
104
112
  toast: { info: '#2959aa', warn: '#b5730f', error: '#c62828', success: '#2e7d32' },
105
113
  chip: { fg: '#ffffff', bg: '#2959aa' },
114
+ governAccent: '#A8327A',
106
115
  };
107
116
  /**
108
117
  * Resolve a theme name to its palette.
@@ -95,6 +95,8 @@ function entryRows(entry, input) {
95
95
  return [fit(firstLine(entry.text), cols)];
96
96
  case 'service':
97
97
  return [];
98
+ case 'governance':
99
+ return [fit(`Governance: ${entry.card.title}`, cols)];
98
100
  default: {
99
101
  const exhaustive = entry;
100
102
  return exhaustive;
@@ -61,6 +61,9 @@ export function isEntryStable(entry, runActive, isTail) {
61
61
  case 'service':
62
62
  // Only the terminal record is ever a candidate; `isExcluded` filters the rest.
63
63
  return entry.terminal === true;
64
+ case 'governance':
65
+ // A settlement card is appended once, already complete.
66
+ return true;
64
67
  default: {
65
68
  const exhaustive = entry;
66
69
  return exhaustive;
@@ -84,11 +84,11 @@ export const SHORTCUTS = [
84
84
  },
85
85
  {
86
86
  id: 'shift-tab', keys: 'Shift+Tab', keyword: 'plan mode', group: 'run', availability: 'always',
87
- detail: 'Toggles BUILD and PLAN; writes are refused and the agent only investigates.',
87
+ detail: 'Cycles BUILD / PLAN / GOVERN / PLAN+GOVERN. PLAN refuses writes; GOVERN runs a governed team.',
88
88
  },
89
89
  {
90
90
  id: 'ctrl-n', keys: 'Ctrl+N', keyword: 'plan mode', group: 'run', availability: 'always',
91
- detail: 'The same toggle, for Windows consoles that cannot deliver Shift+Tab.',
91
+ detail: 'The same cycle (BUILD / PLAN / GOVERN / PLAN+GOVERN), for consoles that cannot deliver Shift+Tab.',
92
92
  },
93
93
  {
94
94
  id: 'ctrl-t', keys: 'Ctrl+T', keyword: 'thinking', group: 'run', availability: 'always',
@@ -84,6 +84,13 @@ export interface Theme {
84
84
  fg: Color;
85
85
  bg: Color;
86
86
  };
87
+ /**
88
+ * The GOVERN posture colour (governance-mode section 10.7). Hex above ansi-256 and
89
+ * `undefined` at level 0 like every other token, but PINNED to `magenta` at 16 colours
90
+ * instead of the nearest-ANSI search: that search lands COOL's teal on cyan, which is
91
+ * `user`'s colour, and the badge exists to be unmistakable.
92
+ */
93
+ governAccent: Color;
87
94
  }
88
95
  export declare function getTheme(name: ThemeName, caps: TermCapabilities): Theme;
89
96
  export {};
package/dist/ui/theme.js CHANGED
@@ -123,6 +123,7 @@ export function getTheme(name, caps) {
123
123
  success: d(palette.toast.success),
124
124
  },
125
125
  chip: { fg: d(palette.chip.fg), bg: d(palette.chip.bg) },
126
+ governAccent: level === 1 ? 'magenta' : d(palette.governAccent),
126
127
  };
127
128
  cache.set(key, theme);
128
129
  return theme;
@@ -2,6 +2,7 @@ import { formatCost, formatDuration, formatTokens, promptTokensOf } from '../age
2
2
  import { formatRetryLine } from '../agent/retry-view.js';
3
3
  import { childStatus, outcomePhrase, rosterCounts, statusMarkerCell } from './team-status.js';
4
4
  import { expandTabs } from './display-tab.js';
5
+ import { governanceCardLines } from './layout/governance-card.js';
5
6
  const DEFAULT_MAX_ENTRIES = 200;
6
7
  const CONTINUATION_INDENT = ' ';
7
8
  const TOOL_INDENT = ' ';
@@ -195,6 +196,14 @@ function renderEntry(entry, glyphs) {
195
196
  `${entry.status}${where}${code}`.trimEnd(),
196
197
  ];
197
198
  }
199
+ case 'governance': {
200
+ // A settlement card is the record of what a governed run decided and scored; an
201
+ // exported transcript that omitted it would be unaccountable for the run (the
202
+ // argument the `team`, `retry` and `fast` cases make in their own words). Same
203
+ // lines as the card, without colour.
204
+ const lines = governanceCardLines(entry.card, glyphs);
205
+ return lines.map((line, index) => `${TOOL_INDENT}${index === 0 ? glyphs.teamAgent : ' '} ${line}`.trimEnd());
206
+ }
198
207
  case 'notice': {
199
208
  const glyph = entry.level === 'error'
200
209
  ? glyphs.error
@@ -118,7 +118,9 @@ export function useWheelRouting(options) {
118
118
  // The Agents board (tui-subagent-panel §6.5). Missing this line makes the
119
119
  // wheel fall through to the transcript BEHIND the open board, which reads
120
120
  // as a frozen list and a jumping transcript at the same time.
121
- || overlay === 'agents';
121
+ || overlay === 'agents'
122
+ // The governance board pages through `overlayScroll` too (governance-mode 10.5).
123
+ || overlay === 'governance';
122
124
  if (!controlled)
123
125
  return;
124
126
  // D-3: the row is not consulted here either. Behind an overlay the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aragon-agent/cli",
3
- "version": "0.6.44",
3
+ "version": "0.6.45",
4
4
  "description": "AragonAgent CLI — a Claude-Code / Codex-style interactive terminal UI (TUI) on top of the @aragon-agent/core engine. Installable and runnable via npm / npx.",
5
5
  "license": "MIT",
6
6
  "author": "AragonAgent contributors",
@@ -56,7 +56,7 @@
56
56
  "prepublishOnly": "npm run build"
57
57
  },
58
58
  "dependencies": {
59
- "@aragon-agent/core": "^0.2.56",
59
+ "@aragon-agent/core": "^0.2.57",
60
60
  "chalk": "^5.6.2",
61
61
  "cli-highlight": "^2.0.0",
62
62
  "commander": "^12.1.0",