@aragon-agent/cli 0.6.44 → 0.6.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/README.md +120 -2
- package/dist/agent/controller.d.ts +69 -0
- package/dist/agent/controller.js +224 -11
- package/dist/agent/governance-view.d.ts +40 -0
- package/dist/agent/governance-view.js +40 -0
- package/dist/agent/governance-wiring.d.ts +162 -0
- package/dist/agent/governance-wiring.js +470 -0
- package/dist/agent/invocation-card.d.ts +77 -0
- package/dist/agent/invocation-card.js +169 -0
- package/dist/agent/plan-prompt.d.ts +7 -0
- package/dist/agent/plan-prompt.js +2 -1
- package/dist/agent/prompt-options.d.ts +6 -0
- package/dist/agent/queued-messages.d.ts +3 -0
- package/dist/agent/queued-messages.js +4 -1
- package/dist/agent/reducer.d.ts +38 -1
- package/dist/agent/reducer.js +57 -12
- package/dist/agent/system-prompt.d.ts +19 -0
- package/dist/agent/system-prompt.js +9 -1
- package/dist/cli.js +45 -1
- package/dist/commands/builtins.js +22 -4
- package/dist/commands/governance-command.d.ts +35 -0
- package/dist/commands/governance-command.js +304 -0
- package/dist/commands/governance-runs-table.d.ts +40 -0
- package/dist/commands/governance-runs-table.js +130 -0
- package/dist/commands/index-build.d.ts +8 -0
- package/dist/commands/index-build.js +11 -0
- package/dist/commands/registry.d.ts +35 -0
- package/dist/commands/registry.js +20 -7
- package/dist/commands/skills.js +36 -2
- package/dist/commands/subagent-command.js +3 -1
- package/dist/commands/team-command.d.ts +6 -0
- package/dist/commands/team-command.js +40 -3
- package/dist/config/app-paths.d.ts +10 -0
- package/dist/config/app-paths.js +12 -0
- package/dist/config/cli-commands.d.ts +18 -0
- package/dist/config/cli-commands.js +47 -1
- package/dist/config/env.d.ts +2 -1
- package/dist/config/env.js +10 -1
- package/dist/config/governance-config.d.ts +125 -0
- package/dist/config/governance-config.js +164 -0
- package/dist/config/governance-launch.d.ts +71 -0
- package/dist/config/governance-launch.js +58 -0
- package/dist/config/load.d.ts +15 -0
- package/dist/config/load.js +26 -1
- package/dist/config/model-profile-store.d.ts +4 -2
- package/dist/config/schema.d.ts +22 -0
- package/dist/config/schema.js +6 -0
- package/dist/config/store.js +14 -1
- package/dist/config/ui-state.d.ts +11 -0
- package/dist/config/ui-state.js +11 -0
- package/dist/diagnostics/doctor.js +20 -0
- package/dist/governance/card-normalize.d.ts +24 -0
- package/dist/governance/card-normalize.js +76 -0
- package/dist/governance/copy.d.ts +109 -0
- package/dist/governance/copy.js +223 -0
- package/dist/governance/engine/aftermath.d.ts +49 -0
- package/dist/governance/engine/aftermath.js +134 -0
- package/dist/governance/engine/artifact-persist.d.ts +35 -0
- package/dist/governance/engine/artifact-persist.js +86 -0
- package/dist/governance/engine/budget.d.ts +52 -0
- package/dist/governance/engine/budget.js +112 -0
- package/dist/governance/engine/cards.d.ts +18 -0
- package/dist/governance/engine/cards.js +186 -0
- package/dist/governance/engine/digest.d.ts +32 -0
- package/dist/governance/engine/digest.js +63 -0
- package/dist/governance/engine/engine-core.d.ts +219 -0
- package/dist/governance/engine/engine-core.js +562 -0
- package/dist/governance/engine/engine.d.ts +68 -0
- package/dist/governance/engine/engine.js +314 -0
- package/dist/governance/engine/estimate.d.ts +38 -0
- package/dist/governance/engine/estimate.js +46 -0
- package/dist/governance/engine/inspector.d.ts +16 -0
- package/dist/governance/engine/inspector.js +396 -0
- package/dist/governance/engine/integration.d.ts +35 -0
- package/dist/governance/engine/integration.js +220 -0
- package/dist/governance/engine/lifecycle.d.ts +29 -0
- package/dist/governance/engine/lifecycle.js +656 -0
- package/dist/governance/engine/pause.d.ts +56 -0
- package/dist/governance/engine/pause.js +107 -0
- package/dist/governance/engine/phase-members.d.ts +15 -0
- package/dist/governance/engine/phase-members.js +34 -0
- package/dist/governance/engine/phase-planner.d.ts +53 -0
- package/dist/governance/engine/phase-planner.js +282 -0
- package/dist/governance/engine/rebuild.d.ts +27 -0
- package/dist/governance/engine/rebuild.js +57 -0
- package/dist/governance/engine/report.d.ts +66 -0
- package/dist/governance/engine/report.js +220 -0
- package/dist/governance/engine/run-digest.d.ts +20 -0
- package/dist/governance/engine/run-digest.js +42 -0
- package/dist/governance/engine/spec-builder.d.ts +117 -0
- package/dist/governance/engine/spec-builder.js +321 -0
- package/dist/governance/engine/stage-runner.d.ts +22 -0
- package/dist/governance/engine/stage-runner.js +664 -0
- package/dist/governance/engine/start-input.d.ts +19 -0
- package/dist/governance/engine/start-input.js +111 -0
- package/dist/governance/engine/state-machine.d.ts +101 -0
- package/dist/governance/engine/state-machine.js +586 -0
- package/dist/governance/engine/submission-queries.d.ts +42 -0
- package/dist/governance/engine/submission-queries.js +97 -0
- package/dist/governance/engine/submission-render.d.ts +12 -0
- package/dist/governance/engine/submission-render.js +92 -0
- package/dist/governance/engine/submissions.d.ts +27 -0
- package/dist/governance/engine/submissions.js +455 -0
- package/dist/governance/engine/visibility.d.ts +104 -0
- package/dist/governance/engine/visibility.js +223 -0
- package/dist/governance/governed-dispatch.d.ts +19 -0
- package/dist/governance/governed-dispatch.js +17 -0
- package/dist/governance/limits.d.ts +107 -0
- package/dist/governance/limits.js +131 -0
- package/dist/governance/posture-transition.d.ts +38 -0
- package/dist/governance/posture-transition.js +44 -0
- package/dist/governance/posture.d.ts +35 -0
- package/dist/governance/posture.js +59 -0
- package/dist/governance/profiles.d.ts +48 -0
- package/dist/governance/profiles.js +140 -0
- package/dist/governance/prompts/orchestrator-block.d.ts +40 -0
- package/dist/governance/prompts/orchestrator-block.js +128 -0
- package/dist/governance/prompts/plan-addendum.d.ts +22 -0
- package/dist/governance/prompts/plan-addendum.js +60 -0
- package/dist/governance/prompts/refusals.d.ts +48 -0
- package/dist/governance/prompts/refusals.js +82 -0
- package/dist/governance/prompts/role-blocks.d.ts +40 -0
- package/dist/governance/prompts/role-blocks.js +255 -0
- package/dist/governance/report-reader.d.ts +31 -0
- package/dist/governance/report-reader.js +57 -0
- package/dist/governance/roles.d.ts +83 -0
- package/dist/governance/roles.js +142 -0
- package/dist/governance/rules/claims.d.ts +83 -0
- package/dist/governance/rules/claims.js +250 -0
- package/dist/governance/rules/elimination.d.ts +66 -0
- package/dist/governance/rules/elimination.js +105 -0
- package/dist/governance/rules/events-table.d.ts +46 -0
- package/dist/governance/rules/events-table.js +94 -0
- package/dist/governance/rules/failure-analysis.d.ts +28 -0
- package/dist/governance/rules/failure-analysis.js +93 -0
- package/dist/governance/rules/ledger-replay.d.ts +53 -0
- package/dist/governance/rules/ledger-replay.js +53 -0
- package/dist/governance/rules/ledger-state.d.ts +85 -0
- package/dist/governance/rules/ledger-state.js +175 -0
- package/dist/governance/rules/ledger.d.ts +228 -0
- package/dist/governance/rules/ledger.js +560 -0
- package/dist/governance/rules/rca.d.ts +68 -0
- package/dist/governance/rules/rca.js +220 -0
- package/dist/governance/rules/settlement.d.ts +129 -0
- package/dist/governance/rules/settlement.js +363 -0
- package/dist/governance/rules/suspicion.d.ts +66 -0
- package/dist/governance/rules/suspicion.js +169 -0
- package/dist/governance/store/artifacts.d.ts +81 -0
- package/dist/governance/store/artifacts.js +173 -0
- package/dist/governance/store/atomic.d.ts +79 -0
- package/dist/governance/store/atomic.js +119 -0
- package/dist/governance/store/events-log.d.ts +35 -0
- package/dist/governance/store/events-log.js +86 -0
- package/dist/governance/store/run-lock.d.ts +51 -0
- package/dist/governance/store/run-lock.js +122 -0
- package/dist/governance/store/run-store.d.ts +229 -0
- package/dist/governance/store/run-store.js +644 -0
- package/dist/governance/store/scoreboard-export.d.ts +53 -0
- package/dist/governance/store/scoreboard-export.js +65 -0
- package/dist/governance/tools/child-tools.d.ts +31 -0
- package/dist/governance/tools/child-tools.js +65 -0
- package/dist/governance/tools/guard.d.ts +71 -0
- package/dist/governance/tools/guard.js +194 -0
- package/dist/governance/tools/inspector-tools.d.ts +63 -0
- package/dist/governance/tools/inspector-tools.js +424 -0
- package/dist/governance/tools/lead-tools.d.ts +42 -0
- package/dist/governance/tools/lead-tools.js +226 -0
- package/dist/governance/tools/normalize-util.d.ts +101 -0
- package/dist/governance/tools/normalize-util.js +230 -0
- package/dist/governance/tools/scan-incomplete.d.ts +79 -0
- package/dist/governance/tools/scan-incomplete.js +486 -0
- package/dist/governance/tools/shared-tools.d.ts +44 -0
- package/dist/governance/tools/shared-tools.js +125 -0
- package/dist/governance/tools/submit-normalizers.d.ts +28 -0
- package/dist/governance/tools/submit-normalizers.js +474 -0
- package/dist/governance/tools/submit-tools.d.ts +26 -0
- package/dist/governance/tools/submit-tools.js +171 -0
- package/dist/governance/types.d.ts +661 -0
- package/dist/governance/types.js +27 -0
- package/dist/session/persist.js +10 -0
- package/dist/session/validate-session.js +36 -3
- package/dist/team/forced-mode.d.ts +19 -0
- package/dist/team/forced-mode.js +42 -20
- package/dist/team/runtime.d.ts +8 -0
- package/dist/team/runtime.js +9 -0
- package/dist/team/subagent.d.ts +23 -0
- package/dist/team/subagent.js +14 -3
- package/dist/team/types.d.ts +6 -0
- package/dist/tools/index.d.ts +30 -7
- package/dist/tools/index.js +14 -0
- package/dist/tools/plan-tools.d.ts +14 -2
- package/dist/tools/plan-tools.js +5 -2
- package/dist/ui/App.js +170 -31
- package/dist/ui/BottomStatusRow.js +1 -1
- package/dist/ui/Composer.d.ts +7 -1
- package/dist/ui/Composer.js +9 -6
- package/dist/ui/GovernancePanel.d.ts +50 -0
- package/dist/ui/GovernancePanel.js +77 -0
- package/dist/ui/GovernanceRun.d.ts +18 -0
- package/dist/ui/GovernanceRun.js +11 -0
- package/dist/ui/StatusBar.d.ts +15 -2
- package/dist/ui/StatusBar.js +10 -4
- package/dist/ui/Transcript.js +7 -1
- package/dist/ui/entries/GovernanceCard.d.ts +30 -0
- package/dist/ui/entries/GovernanceCard.js +32 -0
- package/dist/ui/entries/InvocationCard.d.ts +20 -0
- package/dist/ui/entries/InvocationCard.js +32 -0
- package/dist/ui/governance-copy.d.ts +69 -0
- package/dist/ui/governance-copy.js +104 -0
- package/dist/ui/governance-status.d.ts +145 -0
- package/dist/ui/governance-status.js +326 -0
- package/dist/ui/interaction-copy.d.ts +4 -0
- package/dist/ui/interaction-copy.js +5 -0
- package/dist/ui/interaction-hints.d.ts +17 -0
- package/dist/ui/interaction-hints.js +14 -2
- package/dist/ui/layout/governance-board.d.ts +121 -0
- package/dist/ui/layout/governance-board.js +382 -0
- package/dist/ui/layout/governance-card.d.ts +53 -0
- package/dist/ui/layout/governance-card.js +134 -0
- package/dist/ui/layout/governance-chip.d.ts +38 -0
- package/dist/ui/layout/governance-chip.js +64 -0
- package/dist/ui/layout/governance-panel.d.ts +85 -0
- package/dist/ui/layout/governance-panel.js +358 -0
- package/dist/ui/layout/governance-roster.d.ts +65 -0
- package/dist/ui/layout/governance-roster.js +275 -0
- package/dist/ui/layout/invocation-card.d.ts +41 -0
- package/dist/ui/layout/invocation-card.js +91 -0
- package/dist/ui/layout/status-detail-layout.js +3 -3
- package/dist/ui/layout/status-layout.d.ts +5 -2
- package/dist/ui/layout/status-layout.js +10 -6
- package/dist/ui/layout/virtual-window.js +22 -1
- package/dist/ui/overlays/GovernanceBoardOverlay.d.ts +41 -0
- package/dist/ui/overlays/GovernanceBoardOverlay.js +76 -0
- package/dist/ui/overlays/GovernanceSettingsPage.d.ts +48 -0
- package/dist/ui/overlays/GovernanceSettingsPage.js +93 -0
- package/dist/ui/overlays/HelpOverlay.js +4 -3
- package/dist/ui/overlays/QuestionOverlay.d.ts +9 -1
- package/dist/ui/overlays/QuestionOverlay.js +4 -2
- package/dist/ui/overlays/SettingsScreen.d.ts +7 -0
- package/dist/ui/overlays/SettingsScreen.js +21 -1
- package/dist/ui/overlays/governance-settings.d.ts +79 -0
- package/dist/ui/overlays/governance-settings.js +140 -0
- package/dist/ui/overlays/model-profile-state.d.ts +6 -1
- package/dist/ui/overlays/model-profile-state.js +10 -0
- package/dist/ui/palettes.d.ts +17 -0
- package/dist/ui/palettes.js +9 -0
- package/dist/ui/scrollback/live-preview.js +2 -0
- package/dist/ui/scrollback/settled-boundary.js +3 -0
- package/dist/ui/shortcuts.js +2 -2
- package/dist/ui/theme.d.ts +7 -0
- package/dist/ui/theme.js +1 -0
- package/dist/ui/transcript-text.js +13 -1
- package/dist/ui/use-wheel-routing.js +3 -1
- package/package.json +2 -2
package/dist/ui/App.js
CHANGED
|
@@ -16,7 +16,7 @@ import { computeCost } from '../agent/usage.js';
|
|
|
16
16
|
import { parseMaxTokensInput, DEFAULT_TRANSCRIPT_RETAIN, DEFAULT_TRANSCRIPT_WINDOW, } from '../config/schema.js';
|
|
17
17
|
import { updatePersistedConfig } from '../config/store.js';
|
|
18
18
|
import { appendPrompt, loadPromptHistory } from '../config/prompt-history.js';
|
|
19
|
-
import { bumpSubmitCount, setMouseNoticeVersion, setPromptKeyNoticeVersion, setScrollModeNoticeVersion, setVtInputNoticeVersion, } from '../config/ui-state.js';
|
|
19
|
+
import { bumpSubmitCount, getGovernanceIntroSeen, setGovernanceIntroSeen, setMouseNoticeVersion, setPromptKeyNoticeVersion, setScrollModeNoticeVersion, setVtInputNoticeVersion, } from '../config/ui-state.js';
|
|
20
20
|
import { getLogger } from '../logging/logger.js';
|
|
21
21
|
import { isTerminalStatus } from '../proc/types.js';
|
|
22
22
|
import { getSecrets } from '../logging/secret-registry.js';
|
|
@@ -33,6 +33,13 @@ import { Composer } from './Composer.js';
|
|
|
33
33
|
import { StatusBar } from './StatusBar.js';
|
|
34
34
|
import { secondsLeft } from '../agent/retry-view.js';
|
|
35
35
|
import { TeamPanel } from './TeamPanel.js';
|
|
36
|
+
import { GovernancePanel, useEliminatedSince } from './GovernancePanel.js';
|
|
37
|
+
import { GovernanceBoardOverlay } from './overlays/GovernanceBoardOverlay.js';
|
|
38
|
+
import { governancePanelMode, liveRosterSurface } from './governance-status.js';
|
|
39
|
+
import { buildGovernancePanelLayout } from './layout/governance-panel.js';
|
|
40
|
+
import { boardDataFromRun, boardDataFromSnapshot, } from './layout/governance-board.js';
|
|
41
|
+
import { isGovernancePosture, nextPosture, splitPosture, } from '../governance/posture.js';
|
|
42
|
+
import { GOVERN_INTRO_NOTICE, PLAN_APPROVED_TOAST, PLAN_GOVERN_INTRO_NOTICE, posturePendingToast, postureAppliedToast, stageRunningToast, } from '../governance/copy.js';
|
|
36
43
|
import { TodoPanel } from './TodoPanel.js';
|
|
37
44
|
import { BottomStatusRow } from './BottomStatusRow.js';
|
|
38
45
|
// Only the updater's pure visibility predicate enters the status detail plan.
|
|
@@ -85,10 +92,11 @@ import { SettingsScreen, compactionSettingsFrom, fastSettingsFrom, } from './ove
|
|
|
85
92
|
import { ConfirmDialog } from './overlays/ConfirmDialog.js';
|
|
86
93
|
import { QuestionOverlay } from './overlays/QuestionOverlay.js';
|
|
87
94
|
import { PlanReviewOverlay } from './overlays/PlanReviewOverlay.js';
|
|
88
|
-
import { CommandRegistry, runSlashInput } from '../commands/registry.js';
|
|
95
|
+
import { CommandRegistry, parseSlashInput, runSlashInput, } from '../commands/registry.js';
|
|
96
|
+
import { buildInvocationCard, invocationCardsEnabled } from '../agent/invocation-card.js';
|
|
89
97
|
import { registerBuiltinCommands } from '../commands/builtins.js';
|
|
90
98
|
import { makeSkillsCommand, registerSkillCommands } from '../commands/skills.js';
|
|
91
|
-
import {
|
|
99
|
+
import { MODE_TOGGLE_KEYS } from '../agent/agent-mode.js';
|
|
92
100
|
import { createClipboardCoordinator } from './clipboard-task.js';
|
|
93
101
|
import { QueuePanel } from './QueuePanel.js';
|
|
94
102
|
import { QueueOverlay } from './overlays/QueueOverlay.js';
|
|
@@ -140,6 +148,16 @@ export function resolveSettingsMaxTokens(raw, previous) {
|
|
|
140
148
|
toast: ['warn', 'Max tokens must be a number or "auto".'],
|
|
141
149
|
};
|
|
142
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* The `/gov board` overlay's data: the full run when the controller can supply it (all four
|
|
153
|
+
* tabs), else the snapshot alone (the Work packages and Claims tabs then say they are empty).
|
|
154
|
+
*/
|
|
155
|
+
function governanceBoardData(controller, snapshot) {
|
|
156
|
+
if (snapshot === null)
|
|
157
|
+
return null;
|
|
158
|
+
const input = controller.getGovernanceBoardInput?.();
|
|
159
|
+
return input ? boardDataFromRun({ snapshot, ...input }) : boardDataFromSnapshot(snapshot);
|
|
160
|
+
}
|
|
143
161
|
/** Services in a non-terminal state, from the live snapshot map. */
|
|
144
162
|
function liveServiceCount(services) {
|
|
145
163
|
let n = 0;
|
|
@@ -354,6 +372,9 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
354
372
|
const reducedMotion = cfg.reducedMotion ?? false;
|
|
355
373
|
const stateRef = useRef(state);
|
|
356
374
|
stateRef.current = state;
|
|
375
|
+
// The first-seen-eliminated map for the legion panel (a replaced member shows for one
|
|
376
|
+
// phase). A hook, so it is called unconditionally here and read further down.
|
|
377
|
+
const eliminatedSince = useEliminatedSince(state.governance);
|
|
357
378
|
/**
|
|
358
379
|
* The task label's two guards (tui-shortcut-drawer-and-task-summary D-10).
|
|
359
380
|
*
|
|
@@ -826,14 +847,22 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
826
847
|
submitRef.current(gate.message, { userInitiated: false, todoPolicy: 'continue' });
|
|
827
848
|
}, FORCED_NUDGE_GRACE_MS);
|
|
828
849
|
}
|
|
829
|
-
// A deferred `plan -> build`
|
|
830
|
-
|
|
850
|
+
// A deferred `plan -> build` (or any posture change that waited for a governed
|
|
851
|
+
// stage, governance-mode D-23) becomes real here and nowhere else (§3.2).
|
|
852
|
+
const applied = controller.applyPendingPosture();
|
|
831
853
|
if (applied) {
|
|
832
|
-
|
|
854
|
+
const split = splitPosture(applied.effective);
|
|
855
|
+
dispatch({
|
|
856
|
+
type: 'setAgentMode',
|
|
857
|
+
mode: split.mode,
|
|
858
|
+
pending: null,
|
|
859
|
+
posture: applied.effective,
|
|
860
|
+
pendingPosture: applied.pending,
|
|
861
|
+
});
|
|
833
862
|
dispatch({
|
|
834
863
|
type: 'pushToast',
|
|
835
864
|
level: 'info',
|
|
836
|
-
text:
|
|
865
|
+
text: postureAppliedToast(applied.effective),
|
|
837
866
|
});
|
|
838
867
|
}
|
|
839
868
|
});
|
|
@@ -965,6 +994,25 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
965
994
|
controller.dispose();
|
|
966
995
|
};
|
|
967
996
|
}, [controller]);
|
|
997
|
+
// --- Governance event stream (governance-mode 8.6 / 14.4). --------------
|
|
998
|
+
//
|
|
999
|
+
// ANOTHER CLI-LOCAL SUBSCRIPTION, for the reason the team one records: `GovernanceEvent`
|
|
1000
|
+
// is deliberately not a member of core's `AgentEvent` union. The wiring throttles the
|
|
1001
|
+
// chatty updates; this effect only folds snapshots into the view, appends the four kinds
|
|
1002
|
+
// of settlement card (charter, phase, escalation, final) and clears the live snapshot when
|
|
1003
|
+
// the run ends. A no-op unsubscribe when governance was not registered.
|
|
1004
|
+
useEffect(() => {
|
|
1005
|
+
return controller.subscribeGovernance((event) => {
|
|
1006
|
+
dispatch({ type: 'govSnapshot', snapshot: event.snapshot });
|
|
1007
|
+
const card = event.type === 'run_started' || event.type === 'stage_ended' ? event.card
|
|
1008
|
+
: event.type === 'escalation' || event.type === 'run_closed' ? event.card
|
|
1009
|
+
: null;
|
|
1010
|
+
if (card)
|
|
1011
|
+
dispatch({ type: 'governanceCard', card });
|
|
1012
|
+
if (event.type === 'run_closed')
|
|
1013
|
+
dispatch({ type: 'govEnd' });
|
|
1014
|
+
});
|
|
1015
|
+
}, [controller]);
|
|
968
1016
|
// --- Todo event stream (todo-plan-execution §3.8 / §5.2). --------------
|
|
969
1017
|
//
|
|
970
1018
|
// A THIRD SUBSCRIPTION, for the reason the team one records: `TodoEvent` is
|
|
@@ -1386,7 +1434,14 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
1386
1434
|
// reducer's `'build'` seed would render one wrong frame without this.
|
|
1387
1435
|
useEffect(() => {
|
|
1388
1436
|
const current = controller.getAgentMode();
|
|
1389
|
-
|
|
1437
|
+
const posture = controller.getPostureState();
|
|
1438
|
+
dispatch({
|
|
1439
|
+
type: 'setAgentMode',
|
|
1440
|
+
mode: current,
|
|
1441
|
+
pending: null,
|
|
1442
|
+
posture: posture.effective,
|
|
1443
|
+
pendingPosture: posture.pending,
|
|
1444
|
+
});
|
|
1390
1445
|
}, [controller]);
|
|
1391
1446
|
// --- Let the controller drive command-list rebuilds. -------------------
|
|
1392
1447
|
useEffect(() => {
|
|
@@ -1776,19 +1831,50 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
1776
1831
|
* what was requested: dispatching the request is the one way to make the badge
|
|
1777
1832
|
* claim a permission the gate will not honour.
|
|
1778
1833
|
*/
|
|
1779
|
-
const
|
|
1780
|
-
const applied = controller.
|
|
1781
|
-
|
|
1834
|
+
const applyPosture = (next, opts = {}) => {
|
|
1835
|
+
const applied = controller.setPosture(next, opts.force ? { force: true } : {});
|
|
1836
|
+
const split = splitPosture(applied.effective);
|
|
1837
|
+
// THE ADOPTED VALUES, all four in one dispatch (governance-mode 4.3).
|
|
1838
|
+
dispatch({
|
|
1839
|
+
type: 'setAgentMode',
|
|
1840
|
+
mode: split.mode,
|
|
1841
|
+
pending: applied.pending ? splitPosture(applied.pending).mode : null,
|
|
1842
|
+
posture: applied.effective,
|
|
1843
|
+
pendingPosture: applied.pending,
|
|
1844
|
+
});
|
|
1782
1845
|
if (opts.silent)
|
|
1783
1846
|
return applied;
|
|
1784
1847
|
if (applied.pending) {
|
|
1785
|
-
toast('info',
|
|
1848
|
+
toast('info', controller.isGovernanceStageRunning()
|
|
1849
|
+
? stageRunningToast(applied.pending)
|
|
1850
|
+
: posturePendingToast(applied.pending));
|
|
1786
1851
|
}
|
|
1787
1852
|
else {
|
|
1788
|
-
toast('info',
|
|
1853
|
+
toast('info', postureAppliedToast(applied.effective));
|
|
1854
|
+
// One-time, across launches: what GOVERN means (governance-mode 4.3).
|
|
1855
|
+
if (isGovernancePosture(applied.effective) && !getGovernanceIntroSeen()) {
|
|
1856
|
+
setGovernanceIntroSeen(true);
|
|
1857
|
+
dispatch({
|
|
1858
|
+
type: 'notice',
|
|
1859
|
+
level: 'info',
|
|
1860
|
+
text: applied.effective === 'plan_govern' ? PLAN_GOVERN_INTRO_NOTICE : GOVERN_INTRO_NOTICE,
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1789
1863
|
}
|
|
1790
1864
|
return applied;
|
|
1791
1865
|
};
|
|
1866
|
+
/**
|
|
1867
|
+
* The gate-mode view of the same write path, for `/plan`: a plain `plan` / `build`
|
|
1868
|
+
* request names a classic posture, so it CLEARS governance (an explicit command beats
|
|
1869
|
+
* an implicit carry-over, governance-mode 4.2).
|
|
1870
|
+
*/
|
|
1871
|
+
const applyMode = (next, opts = {}) => {
|
|
1872
|
+
const applied = applyPosture(next, opts);
|
|
1873
|
+
return {
|
|
1874
|
+
effective: splitPosture(applied.effective).mode,
|
|
1875
|
+
pending: applied.pending ? splitPosture(applied.pending).mode : null,
|
|
1876
|
+
};
|
|
1877
|
+
};
|
|
1792
1878
|
/**
|
|
1793
1879
|
* Cancel any in-flight label call and make its result unadoptable.
|
|
1794
1880
|
*
|
|
@@ -1857,8 +1943,10 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
1857
1943
|
dispatch({ type: 'taskSummaryReady', view: outcome.view });
|
|
1858
1944
|
});
|
|
1859
1945
|
};
|
|
1946
|
+
const invocationCardsOn = invocationCardsEnabled();
|
|
1860
1947
|
const makeCtx = (args) => ({
|
|
1861
1948
|
args,
|
|
1949
|
+
invocationCards: invocationCardsOn,
|
|
1862
1950
|
requestCopy: copyCoordinator.requestCopy,
|
|
1863
1951
|
controller,
|
|
1864
1952
|
state: stateRef.current,
|
|
@@ -1971,6 +2059,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
1971
2059
|
},
|
|
1972
2060
|
refreshSkills: () => setSkillsNonce((n) => n + 1),
|
|
1973
2061
|
applyAgentMode: applyMode,
|
|
2062
|
+
applyPosture: (next, opts) => applyPosture(next, opts ?? {}),
|
|
1974
2063
|
// Read at command time, so `/todo status` reports the live count rather than
|
|
1975
2064
|
// whatever it was when this context was built.
|
|
1976
2065
|
followBudget: budgetRef.current,
|
|
@@ -2035,10 +2124,17 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2035
2124
|
// must be the one that runs, whichever branch it takes.
|
|
2036
2125
|
cancelFollowThrough();
|
|
2037
2126
|
cancelConfirmation();
|
|
2127
|
+
// THE ONE PLACE A CARD IS BUILT (tui-invocation-cards I-3 / I-6): redact -> normalise ->
|
|
2128
|
+
// limit, with the same redactor the `Command:` echo uses. `message` below is the model's
|
|
2129
|
+
// input and is never touched; the card only replaces what the TRANSCRIPT shows.
|
|
2130
|
+
const card = invocationCardsOn && opts.invocation
|
|
2131
|
+
? buildInvocationCard(opts.invocation, (text) => redactText(text, getSecrets()))
|
|
2132
|
+
: undefined;
|
|
2133
|
+
const shown = card?.commandLine ?? message;
|
|
2038
2134
|
if (interactionPhase.current === 'running' || controller.isCompactionBusy?.()) {
|
|
2039
2135
|
try {
|
|
2040
2136
|
const queueId = controller.queueUserMessage(message);
|
|
2041
|
-
dispatch({ type: 'steerQueued', queueId, text:
|
|
2137
|
+
dispatch({ type: 'steerQueued', queueId, text: shown, ...(card ? { invocation: card } : {}) });
|
|
2042
2138
|
return { accepted: true };
|
|
2043
2139
|
}
|
|
2044
2140
|
catch (error) {
|
|
@@ -2057,7 +2153,10 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2057
2153
|
// the user has learned, so suppressing the fade is correct rather than
|
|
2058
2154
|
// incidental — which is why the parameter is named for the CAUSE (P2-8).
|
|
2059
2155
|
if (opts.userInitiated !== false) {
|
|
2060
|
-
|
|
2156
|
+
// A card's command line was already recorded by `executeSlashInput`; the payload
|
|
2157
|
+
// behind it must never reach the up-arrow history (I-9: the gate is unchanged).
|
|
2158
|
+
if (!card)
|
|
2159
|
+
recordPrompt(message);
|
|
2061
2160
|
// THE ONE PLACE THE NUDGE BUDGET IS REFILLED (P0-2 / I-10). Same predicate
|
|
2062
2161
|
// as `recordPrompt`, and for the same reason: the question is "did a human
|
|
2063
2162
|
// ask for this?", and only a human may hand the gate another attempt. A
|
|
@@ -2068,7 +2167,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2068
2167
|
// Mirrors where the reducer clears its own copies, in the same action
|
|
2069
2168
|
// (C-11): a new turn's end reason must not inherit the previous one's.
|
|
2070
2169
|
endReasonRef.current = { aborted: false, errored: false };
|
|
2071
|
-
dispatch({ type: 'submit', text:
|
|
2170
|
+
dispatch({ type: 'submit', text: shown, ...(card ? { invocation: card } : {}) });
|
|
2072
2171
|
const pre = controller.preflight();
|
|
2073
2172
|
if (!pre.ok) {
|
|
2074
2173
|
dispatch({ type: 'runError' });
|
|
@@ -2088,7 +2187,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2088
2187
|
// model call that describes a turn nobody ran; and below, in the queueing
|
|
2089
2188
|
// branch, the message is steering rather than a new task.
|
|
2090
2189
|
if (opts.userInitiated !== false)
|
|
2091
|
-
ensureTaskSummary(
|
|
2190
|
+
ensureTaskSummary(shown);
|
|
2092
2191
|
void controller.prompt(message, { todoPolicy: opts.todoPolicy ?? 'new-task' }).then((outcome) => {
|
|
2093
2192
|
if (!mounted.current || sequence !== submissionSequence.current)
|
|
2094
2193
|
return;
|
|
@@ -2127,7 +2226,13 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2127
2226
|
// Retain a recoverable command before any asynchronous handler can fail.
|
|
2128
2227
|
const safe = redactText(raw, getSecrets());
|
|
2129
2228
|
recordPrompt(safe);
|
|
2130
|
-
|
|
2229
|
+
// The echo is suppressed BEFORE the command runs and never deleted afterwards: printed
|
|
2230
|
+
// scrollback rows cannot be rewritten (I-5). The predicate is the command's own (I-8).
|
|
2231
|
+
const parsed = parseSlashInput(raw);
|
|
2232
|
+
const rendersCard = invocationCardsOn && parsed !== null
|
|
2233
|
+
&& registry.get(parsed.name)?.rendersInvocationCard?.(parsed.args) === true;
|
|
2234
|
+
if (!rendersCard)
|
|
2235
|
+
notify('info', `Command: ${safe}`);
|
|
2131
2236
|
try {
|
|
2132
2237
|
await runSlashInput(registry, raw, makeCtx);
|
|
2133
2238
|
}
|
|
@@ -2275,8 +2380,11 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2275
2380
|
// here would read `'plan'` and the badge would lag by a frame. Writing it
|
|
2276
2381
|
// first through the same single path makes the tool's call an idempotent
|
|
2277
2382
|
// no-op and keeps the mirror exact (§3.1 / R-P7).
|
|
2278
|
-
|
|
2279
|
-
|
|
2383
|
+
// PLAN+GOVERN hands over to the team instead of implementing: the same single write
|
|
2384
|
+
// path, with governance kept on (governance-mode 9.2).
|
|
2385
|
+
const governed = controller.getPosture() === 'plan_govern';
|
|
2386
|
+
applyPosture(governed ? 'govern' : 'build', { force: true, silent: true });
|
|
2387
|
+
toast('success', governed ? PLAN_APPROVED_TOAST : 'Plan approved. Implementing.');
|
|
2280
2388
|
}
|
|
2281
2389
|
else {
|
|
2282
2390
|
toast('info', 'Revision requested.');
|
|
@@ -2593,6 +2701,9 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2593
2701
|
// The Agents board pages through `overlayScroll` too, but keeps Up/Down for its
|
|
2594
2702
|
// CHILD CURSOR - the same trade `settings` makes with its field cursor.
|
|
2595
2703
|
|| overlay === 'agents'
|
|
2704
|
+
// The governance board (governance-mode 10.5): without this line a PgDn in the
|
|
2705
|
+
// board falls through to the transcript behind it.
|
|
2706
|
+
|| overlay === 'governance'
|
|
2596
2707
|
// The prompt surfaces page themselves through `overlayScroll` too
|
|
2597
2708
|
// (quick-prompt-library appendix B-1). Without them a `PgDn` in the list does
|
|
2598
2709
|
// nothing and the wheel falls through to the transcript behind it.
|
|
@@ -2630,7 +2741,10 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2630
2741
|
if ((key.tab && key.shift) || (key.ctrl && (input === 'n' || input === 'N'))) {
|
|
2631
2742
|
if (stateRef.current.overlay)
|
|
2632
2743
|
return;
|
|
2633
|
-
|
|
2744
|
+
// The cycle's basis is `pending ?? effective`: with a change already waiting, a second
|
|
2745
|
+
// press must advance from it, or it would hold on the same target (governance-mode 4.1).
|
|
2746
|
+
const postureNow = controller.getPostureState();
|
|
2747
|
+
applyPosture(nextPosture(postureNow.pending ?? postureNow.effective, controller.getPostureCycle()));
|
|
2634
2748
|
return;
|
|
2635
2749
|
}
|
|
2636
2750
|
// Moved off Ctrl+L by D-1, because Ctrl+L is the branch key now.
|
|
@@ -2945,10 +3059,32 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2945
3059
|
? Math.max(0, viewportBudget - 1)
|
|
2946
3060
|
: Math.max(0, viewportBudget - composerBaseRows - queueLayout.rows - 1),
|
|
2947
3061
|
});
|
|
3062
|
+
// THE LEGION PANEL REPLACES THE TEAM ROSTER while a governed stage runs (D-17, AC-25):
|
|
3063
|
+
// one live roster, never two. Between stages it is a two-line run strip, and it yields to
|
|
3064
|
+
// a non-governed dispatch if one is somehow live. Its height feeds the same two budgets
|
|
3065
|
+
// the roster's does, so the band and the rail never learn a second number.
|
|
3066
|
+
// PLAN+GOVERN's interview chip on the question overlay (governance-mode 9.3).
|
|
3067
|
+
const interviewState = state.posture === 'plan_govern' ? controller.getGovernanceInterview?.() : null;
|
|
3068
|
+
const interviewProps = interviewState
|
|
3069
|
+
? { interview: { round: interviewState.answered, required: interviewState.required } }
|
|
3070
|
+
: {};
|
|
3071
|
+
const governanceMode = governancePanelMode(state.governance);
|
|
3072
|
+
const governanceLayout = state.governance !== null
|
|
3073
|
+
&& liveRosterSurface(state.governance, state.team !== null) === 'governance'
|
|
3074
|
+
? buildGovernancePanelLayout({
|
|
3075
|
+
cols: native ? Math.max(1, cols - 1) : baseRail.contentCols, rows,
|
|
3076
|
+
snapshot: state.governance, glyphs, reducedMotion, now: Date.now(),
|
|
3077
|
+
mode: governanceMode === 'panel' ? 'panel' : 'run-strip', eliminatedSince,
|
|
3078
|
+
availableRows: native
|
|
3079
|
+
? Math.max(0, viewportBudget - 1)
|
|
3080
|
+
: Math.max(0, viewportBudget - composerBaseRows - queueLayout.rows - 1),
|
|
3081
|
+
})
|
|
3082
|
+
: null;
|
|
3083
|
+
const teamPanelRows = governanceLayout ? governanceLayout.height : teamLayout.rowCount;
|
|
2948
3084
|
const railLayout = buildTodoRailLayout({
|
|
2949
3085
|
cols: cols - 1, panelEnabled: cfg.todo.panel, overlayOpen: false,
|
|
2950
3086
|
itemCount: state.todos?.items.length ?? 0, viewportBudget,
|
|
2951
|
-
teamRows:
|
|
3087
|
+
teamRows: teamPanelRows, queueRows: queueLayout.rows, popupRows: 0, composerBaseRows,
|
|
2952
3088
|
});
|
|
2953
3089
|
const { visible: railVisible, width: railWidth, rows: railRows, contentCols } = railLayout;
|
|
2954
3090
|
// The FULL-SCREEN rail only: native mode draws its rail inside the live region's
|
|
@@ -2983,7 +3119,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2983
3119
|
// second time (`buildTeamPanelLayout` stays the single authority).
|
|
2984
3120
|
itemCount: state.todos?.items.length ?? 0,
|
|
2985
3121
|
panelEnabled: cfg.todo.panel,
|
|
2986
|
-
teamRowsNatural:
|
|
3122
|
+
teamRowsNatural: teamPanelRows,
|
|
2987
3123
|
// The top give-way measures a window entry's height, and an expanded tool card is a
|
|
2988
3124
|
// different height from a collapsed one - a forgotten value would print rows the region
|
|
2989
3125
|
// is not drawing.
|
|
@@ -3079,14 +3215,16 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3079
3215
|
// mounted with `{...props}` and an undeclared prop arrives as
|
|
3080
3216
|
// `undefined`. A construction-time snapshot, so reading it per frame is
|
|
3081
3217
|
// honest (I-7).
|
|
3082
|
-
teamRegistered: controller.isTeamRegistered(), probe: probe, onProfileSave: handleProfileSave, onReload: () => controller.createModelSettingsDraft(), onClose: () => dispatch({ type: 'setOverlay', overlay: null }),
|
|
3218
|
+
teamRegistered: controller.isTeamRegistered(), governanceRegistered: controller.isGovernanceRegistered(), probe: probe, onProfileSave: handleProfileSave, onReload: () => controller.createModelSettingsDraft(), onClose: () => dispatch({ type: 'setOverlay', overlay: null }),
|
|
3083
3219
|
// Read from `cfg` (render scope, re-read every frame), so `/retry off`
|
|
3084
3220
|
// while the screen is open shows the new value on the next paint.
|
|
3085
3221
|
retrySummary: cfg.retry.enabled && cfg.retry.maxRetries > 0 ? String(cfg.retry.maxRetries) : 'off' })) : overlay === 'agents' ? (
|
|
3086
3222
|
// THE BRANCH AND THE `Overlay` MEMBER SHIP TOGETHER (R-11): a missing branch is not
|
|
3087
3223
|
// a type error, it is a SILENT BLANK FRAME, because `active={overlay === null}` has
|
|
3088
3224
|
// already disabled the transcript underneath.
|
|
3089
|
-
_jsx(AgentsBoardOverlay, { team: state.team, entries: state.entries, cols: viewCols, maxRows: overlayMaxRows, scrollOffset: overlayScroll, onScrollClamp: setOverlayScroll, isActive: !tooSmall, native: native, theme: theme, caps: caps })) : overlay === '
|
|
3225
|
+
_jsx(AgentsBoardOverlay, { team: state.team, entries: state.entries, cols: viewCols, maxRows: overlayMaxRows, scrollOffset: overlayScroll, onScrollClamp: setOverlayScroll, isActive: !tooSmall, native: native, theme: theme, caps: caps })) : overlay === 'governance' ? (
|
|
3226
|
+
// THE BRANCH AND THE `Overlay` MEMBER SHIP TOGETHER (R-11), like `agents` above.
|
|
3227
|
+
_jsx(GovernanceBoardOverlay, { data: governanceBoardData(controller, state.governance), cols: viewCols, maxRows: overlayMaxRows, scrollOffset: overlayScroll, onScrollClamp: setOverlayScroll, isActive: !tooSmall, theme: theme, caps: caps, onCopyPath: (path) => { void copyCoordinator.requestCopy({ text: path, lines: 1 }); }, onNotice: toast })) : overlay === 'confirm' && confirmState ? (_jsx(ConfirmDialog, { isActive: !tooSmall, state: confirmState, maxRows: overlayMaxRows, cols: viewCols, theme: theme, caps: caps, onClose: closeConfirm })) : overlay === 'question' && humanRequest?.kind === 'questions' ? (_jsx(QuestionOverlay, { isActive: !tooSmall, questions: humanRequest.questions, maxRows: overlayMaxRows, cols: viewCols, theme: theme, caps: caps, onSubmit: (answers) => resolveHuman({ kind: 'answers', answers, cancelled: false }), ...interviewProps })) : overlay === 'plan' && humanRequest?.kind === 'plan' ? (_jsx(PlanReviewOverlay, { isActive: !tooSmall, plan: humanRequest.plan, maxRows: overlayMaxRows, cols: viewCols, scrollOffset: overlayScroll, onScrollClamp: setOverlayScroll, theme: theme, caps: caps, onVerdict: handlePlanVerdict })) : null;
|
|
3090
3228
|
const density = cfg.density;
|
|
3091
3229
|
const transcriptWindow = cfg.transcriptWindow ?? DEFAULT_TRANSCRIPT_WINDOW;
|
|
3092
3230
|
// The fixed status bar remains visible underneath every overlay and toast.
|
|
@@ -3207,7 +3345,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3207
3345
|
stopping: interruptGesture.current.phase === 'stopping',
|
|
3208
3346
|
interruptPhase: interruptGesture.current.phase,
|
|
3209
3347
|
compacting: compactionLive || !!state.compaction?.inFlight,
|
|
3210
|
-
mode: state.
|
|
3348
|
+
mode: state.posture, pendingMode: state.pendingPosture,
|
|
3211
3349
|
servicesActive: { live: liveServices }, ecoRung: governor.rung,
|
|
3212
3350
|
// THE STATUS-DETAIL ROW COUNTS LIKE THE ROSTER AND THE CHIP (A-1): this was the
|
|
3213
3351
|
// last inline phase filter, left behind when the StatusBar chip converged, and it
|
|
@@ -3227,11 +3365,12 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3227
3365
|
selectionPending: selectionController?.hasPendingSelection() ?? false,
|
|
3228
3366
|
copyInFlight: copyState.busy, copyCleanupPending: copyState.cleanupPending,
|
|
3229
3367
|
hasDraft: hasDraftRef.current, services: liveServices,
|
|
3230
|
-
hintsEnabled: cfg.hints, modeToggleKey,
|
|
3368
|
+
hintsEnabled: cfg.hints, modeToggleKey, governed: isGovernancePosture(state.posture),
|
|
3369
|
+
...(state.governance?.pauseRequested === true ? { govPausePending: true } : {}),
|
|
3231
3370
|
interruptPhase: interruptGesture.current.phase,
|
|
3232
3371
|
updateAvailable: !!updateSnapshot && shouldRenderUpdateLine(updateSnapshot) } });
|
|
3233
|
-
const composer = (_jsx(Composer, { deleteDisambiguated: terminal?.deleteDisambiguated ?? false, onCompletionContextChange: setCompletion, cols: frameBudget.composerCols, terminalRows: rows, statusExpanded: statusExpanded, onInteraction: returnToComposer, reducedMotion: cfg.reducedMotion ?? false, onEscape: handleComposerEscape, onEscapeDismiss: cancelConfirmation, isActive: overlay === null && !tooSmall, running: state.status === 'running', history: promptHistory, commands: commandOptions, cwd: controller.getCwd(), showHint: false, submitCount: cfg.submitCount, hintsEnabled: cfg.hints, agentMode: state.agentMode, services: liveServices, modeToggleKey: modeToggleKey, popupMaxRows: popupMaxRows, popupMaxHeight: frameBudget.popupMaxHeight, onPopupRowsChange: onPopupRowsChange, onDraftRows: onDraftRows, onDraftPresence: onDraftPresence, draftClearNonce: draftClearNonce, ...(draftFill ? { draftFill } : {}), insertMode: cfg.prompts?.insertMode ?? 'insert', onNotice: notify, theme: theme, caps: caps, onSubmit: handleSubmit, onHelp: () => dispatch({ type: 'setOverlay', overlay: 'help' }) }));
|
|
3234
|
-
const team = state.team ? (_jsx(TeamPanel, { snapshot: state.team, layout: teamLayout, rows: rows, cols: contentCols, reducedMotion: viewReducedMotion, theme: theme, caps: caps })) : null;
|
|
3372
|
+
const composer = (_jsx(Composer, { deleteDisambiguated: terminal?.deleteDisambiguated ?? false, onCompletionContextChange: setCompletion, cols: frameBudget.composerCols, terminalRows: rows, statusExpanded: statusExpanded, onInteraction: returnToComposer, reducedMotion: cfg.reducedMotion ?? false, onEscape: handleComposerEscape, onEscapeDismiss: cancelConfirmation, isActive: overlay === null && !tooSmall, running: state.status === 'running', history: promptHistory, commands: commandOptions, cwd: controller.getCwd(), showHint: false, submitCount: cfg.submitCount, hintsEnabled: cfg.hints, agentMode: state.agentMode, posture: state.posture, services: liveServices, modeToggleKey: modeToggleKey, popupMaxRows: popupMaxRows, popupMaxHeight: frameBudget.popupMaxHeight, onPopupRowsChange: onPopupRowsChange, onDraftRows: onDraftRows, onDraftPresence: onDraftPresence, draftClearNonce: draftClearNonce, ...(draftFill ? { draftFill } : {}), insertMode: cfg.prompts?.insertMode ?? 'insert', onNotice: notify, theme: theme, caps: caps, onSubmit: handleSubmit, onHelp: () => dispatch({ type: 'setOverlay', overlay: 'help' }) }));
|
|
3373
|
+
const team = governanceLayout ? (_jsx(GovernancePanel, { layout: governanceLayout, theme: theme, caps: caps })) : state.team ? (_jsx(TeamPanel, { snapshot: state.team, layout: teamLayout, rows: rows, cols: contentCols, reducedMotion: viewReducedMotion, theme: theme, caps: caps })) : null;
|
|
3235
3374
|
// --- Native panel band (release-gate-and-native-panels §6.3/§6.4) -------------
|
|
3236
3375
|
//
|
|
3237
3376
|
// SEPARATE NODES, NOT THE TWO ABOVE (RV-P1-7). Those carry `cols={contentCols}` for
|
|
@@ -3252,7 +3391,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3252
3391
|
// out against `previewCols` would stop its clock one rail short of the screen's edge.
|
|
3253
3392
|
// `teamRowGeometry` is continuous in `cols`, so the number that decides whether the
|
|
3254
3393
|
// panel mounts IS the number it lays out against.
|
|
3255
|
-
const nativeTeam = state.team && nativeBand ? (_jsx(TeamPanel, { snapshot: state.team, layout: teamLayout, rows: rows, cols: nativeBandCols, reducedMotion: viewReducedMotion, theme: theme, caps: caps })) : null;
|
|
3394
|
+
const nativeTeam = governanceLayout && nativeBand ? (_jsx(GovernancePanel, { layout: governanceLayout, theme: theme, caps: caps })) : state.team && nativeBand ? (_jsx(TeamPanel, { snapshot: state.team, layout: teamLayout, rows: rows, cols: nativeBandCols, reducedMotion: viewReducedMotion, theme: theme, caps: caps })) : null;
|
|
3256
3395
|
const rail = fullscreenRailVisible && state.todos ? (_jsx(TodoPanel, { snapshot: state.todos, width: railWidth, rows: railRows, running: running, reducedMotion: viewReducedMotion, theme: theme, caps: caps })) : null;
|
|
3257
3396
|
const viewport = (_jsxs(ScrollViewport, { active: overlay === null && !tooSmall, overlay: overlayNode, footer: _jsxs(_Fragment, { children: [team, _jsx(QueuePanel, { layout: queueLayout, theme: theme })] }), rail: rail, scrollbar: terminal?.scrollbar, resetKey: scrollResetKey, intent: scrollIntent, pinToBottomNonce: pinToBottomNonce, onScrolledLinesChange: setScrolledLines, onViewportShiftChange: onViewportShiftChange, onGeometryChange: onGeometryChange, geometryKey: `${rows}:${cols}:${viewportBudget}:${frameBudget.composerSlotRows}:${frameBudget.statusRows}:${contentCols}:${overlay}:${tooSmall}`, tailRowsRef: tailSink, hold: selectionHold, resumeMs: cfg.scrollResumeMs, showScrollIndicator: true, cols: contentCols, theme: theme, caps: caps, children: [opener, _jsx(TranscriptList, { entries: transcriptEntries, expandedToolIds: state.expandedToolIds, thinkingVisible: state.thinkingVisible, reducedMotion: viewReducedMotion, density: density, nowSec: nowSec, theme: theme, caps: caps, windowSize: transcriptWindow, cols: contentCols, heights: heights, mountedSink: mountedCount, tailSink: tailSink })] }));
|
|
3258
3397
|
const detailsNode = _jsx(BottomStatusRow, { plan: details, columns: viewCols, theme: theme });
|
|
@@ -3264,7 +3403,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3264
3403
|
// partially stale. The window and its `known` flag now travel INSIDE
|
|
3265
3404
|
// it, resolved by the meter - which is what makes the user's
|
|
3266
3405
|
// `contextWindow` override reach the bar.
|
|
3267
|
-
context: state.context, status: state.status, elapsedMs: elapsedMs, thinkingLevel: cfg.thinkingLevel, tokPerSec: tokPerSec, theme: theme, caps: caps, scrolledLines: scrolledLines, redrawNonce: redrawNonce, agentMode: state.
|
|
3406
|
+
context: state.context, status: state.status, elapsedMs: elapsedMs, thinkingLevel: cfg.thinkingLevel, tokPerSec: tokPerSec, theme: theme, caps: caps, scrolledLines: scrolledLines, redrawNonce: redrawNonce, agentMode: state.posture, pendingAgentMode: state.pendingPosture, governance: state.governance, ...(forcedTeam ? { forcedTeam } : {}), ecoRung: governor.rung, ...(state.team
|
|
3268
3407
|
? {
|
|
3269
3408
|
// `rosterCounts`, NOT a fourth inline phase filter (A-1): the chip and
|
|
3270
3409
|
// the roster header above it must never disagree.
|
|
@@ -4,6 +4,6 @@ import React from 'react';
|
|
|
4
4
|
import { Box, Text } from 'ink';
|
|
5
5
|
export function BottomStatusRow({ plan, columns, theme }) {
|
|
6
6
|
const tones = { normal: theme.primary, muted: theme.muted, warning: theme.noticeWarn, error: theme.noticeError,
|
|
7
|
-
accent: theme.accent };
|
|
7
|
+
accent: theme.accent, govern: theme.governAccent };
|
|
8
8
|
return _jsxs(Box, { height: 1, width: columns, flexShrink: 0, overflow: "hidden", children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { children: " " }) }), plan.fields.map((field, index) => _jsxs(React.Fragment, { children: [index > 0 && _jsx(Box, { width: plan.separatorCells, flexShrink: 0, children: _jsx(Text, { color: theme.muted, children: plan.separator }) }), _jsx(Box, { width: field.cells, flexShrink: 0, children: _jsx(Text, { wrap: "truncate", color: tones[field.tone], children: field.text }) })] }, field.id))] });
|
|
9
9
|
}
|
package/dist/ui/Composer.d.ts
CHANGED
|
@@ -44,6 +44,12 @@ export interface ComposerProps {
|
|
|
44
44
|
hintsEnabled: boolean;
|
|
45
45
|
/** Mirror of the controller's effective mode; drives the border. */
|
|
46
46
|
agentMode: AgentMode;
|
|
47
|
+
/**
|
|
48
|
+
* The adopted posture (governance-mode 10.2). A governed one paints the idle/draft
|
|
49
|
+
* border in `governAccent`, the same slot PLAN uses `accent` for. Absent = the
|
|
50
|
+
* pre-governance border logic, unchanged.
|
|
51
|
+
*/
|
|
52
|
+
posture?: string;
|
|
47
53
|
/** Compatibility prop; the global action row names the effective mode key. */
|
|
48
54
|
modeToggleKey?: string;
|
|
49
55
|
popupMaxRows?: number;
|
|
@@ -105,5 +111,5 @@ declare function hintText(opts: {
|
|
|
105
111
|
}): string;
|
|
106
112
|
/** Compatibility export for existing hint contract tests. */
|
|
107
113
|
export declare const hintTextForTest: typeof hintText;
|
|
108
|
-
export declare function Composer({ deleteDisambiguated, onCompletionContextChange, cols, terminalRows, statusExpanded, cursorVisible, onInteraction, measureRef, isActive, reducedMotion, onEscape, onEscapeDismiss, running, history, commands, cwd, agentMode, popupMaxRows, popupMaxHeight, onPopupRowsChange, onDraftRows, onDraftPresence, draftClearNonce, draftFill, insertMode, onNotice, theme, caps, onSubmit, onHelp, }: ComposerProps): React.ReactElement;
|
|
114
|
+
export declare function Composer({ deleteDisambiguated, onCompletionContextChange, cols, terminalRows, statusExpanded, cursorVisible, onInteraction, measureRef, isActive, reducedMotion, onEscape, onEscapeDismiss, running, history, commands, cwd, agentMode, posture, popupMaxRows, popupMaxHeight, onPopupRowsChange, onDraftRows, onDraftPresence, draftClearNonce, draftFill, insertMode, onNotice, theme, caps, onSubmit, onHelp, }: ComposerProps): React.ReactElement;
|
|
109
115
|
export {};
|
package/dist/ui/Composer.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Box } from 'ink';
|
|
|
5
5
|
import { HINT_FADE_AFTER } from '../config/schema.js';
|
|
6
6
|
import { PromptInput } from './PromptInput.js';
|
|
7
7
|
import { MODE_LABEL, nextMode } from '../agent/agent-mode.js';
|
|
8
|
+
import { isGovernedModeValue } from './governance-status.js';
|
|
8
9
|
/** Legacy helper retained for consumers and contract tests; not rendered by Composer. */
|
|
9
10
|
export function runningHintClauses(opts) {
|
|
10
11
|
const { glyphs, services } = opts;
|
|
@@ -36,7 +37,7 @@ function hintText(opts) {
|
|
|
36
37
|
}
|
|
37
38
|
/** Compatibility export for existing hint contract tests. */
|
|
38
39
|
export const hintTextForTest = hintText;
|
|
39
|
-
export function Composer({ deleteDisambiguated, onCompletionContextChange, cols, terminalRows, statusExpanded, cursorVisible, onInteraction, measureRef, isActive, reducedMotion, onEscape, onEscapeDismiss, running, history, commands, cwd, agentMode, popupMaxRows, popupMaxHeight, onPopupRowsChange, onDraftRows, onDraftPresence, draftClearNonce, draftFill, insertMode, onNotice, theme, caps, onSubmit, onHelp, }) {
|
|
40
|
+
export function Composer({ deleteDisambiguated, onCompletionContextChange, cols, terminalRows, statusExpanded, cursorVisible, onInteraction, measureRef, isActive, reducedMotion, onEscape, onEscapeDismiss, running, history, commands, cwd, agentMode, posture, popupMaxRows, popupMaxHeight, onPopupRowsChange, onDraftRows, onDraftPresence, draftClearNonce, draftFill, insertMode, onNotice, theme, caps, onSubmit, onHelp, }) {
|
|
40
41
|
const [hasDraft, setHasDraft] = useState(false);
|
|
41
42
|
const onDraftChange = useCallback((next) => {
|
|
42
43
|
setHasDraft(next.hasDraft);
|
|
@@ -52,10 +53,12 @@ export function Composer({ deleteDisambiguated, onCompletionContextChange, cols,
|
|
|
52
53
|
? theme.toolPending
|
|
53
54
|
: running
|
|
54
55
|
? theme.toolRunning
|
|
55
|
-
:
|
|
56
|
-
? theme.
|
|
57
|
-
:
|
|
58
|
-
? theme.
|
|
59
|
-
:
|
|
56
|
+
: isGovernedModeValue(posture)
|
|
57
|
+
? theme.governAccent
|
|
58
|
+
: agentMode === 'plan'
|
|
59
|
+
? theme.accent
|
|
60
|
+
: hasDraft
|
|
61
|
+
? theme.focusBorder ?? theme.primary
|
|
62
|
+
: theme.idleBorder ?? theme.border;
|
|
60
63
|
return (_jsx(Box, { ref: measureRef, width: cols, flexDirection: "column", flexShrink: 0, children: _jsx(PromptInput, { deleteDisambiguated: deleteDisambiguated, onCompletionContextChange: onCompletionContextChange, cols: cols, terminalRows: terminalRows, statusExpanded: statusExpanded, cursorVisible: cursorVisible, onInteraction: onInteraction, isActive: isActive, reducedMotion: reducedMotion, onEscape: onEscape, onEscapeDismiss: onEscapeDismiss, running: running, history: history, commands: commands, cwd: cwd, theme: theme, caps: caps, popupMaxRows: popupMaxRows, popupMaxHeight: popupMaxHeight, onPopupRowsChange: onPopupRowsChange, onSubmit: onSubmit, onHelp: onHelp, agentMode: agentMode, borderColor: borderColor, onDraftChange: onDraftChange, draftClearNonce: draftClearNonce, draftFill: draftFill, insertMode: insertMode, onNotice: onNotice }) }));
|
|
61
64
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GovernancePanel - the legion panel (governance-mode section 10.3).
|
|
3
|
+
*
|
|
4
|
+
* ASCII ONLY: every glyph comes from `pickGlyphs`, through the layout.
|
|
5
|
+
*
|
|
6
|
+
* THIS COMPONENT ONLY COLOURS AND PLACES. Every decision - which tier, which columns, how
|
|
7
|
+
* wide, what each cell says, which row is hidden - was made by
|
|
8
|
+
* `layout/governance-panel.ts`, and the `layout` prop is REQUIRED: `App` builds it once to
|
|
9
|
+
* learn the panel's height (the native band and the TODO rail both budget against it) and
|
|
10
|
+
* hands the very same object here, so the number that decides whether the panel mounts is
|
|
11
|
+
* the number it is drawn from. A panel that re-planned itself could draw a taller tier than
|
|
12
|
+
* the one the band reserved, and the band clips the overflow in silence.
|
|
13
|
+
*
|
|
14
|
+
* IT REPLACES `TeamPanel` WHILE A GOVERNED STAGE RUNS (D-17), it does not stack with it:
|
|
15
|
+
* the repo has been bitten by a "double roster" once (tui-subagent-double-roster), and a
|
|
16
|
+
* governed dispatch is the one case where two live rosters would be the same children
|
|
17
|
+
* listed twice.
|
|
18
|
+
*
|
|
19
|
+
* NO `ink-spinner` HERE, on purpose. While a governed stage runs the lead's turn is
|
|
20
|
+
* running, the activity row owns the one spinner (single-spinner-while-running), and every
|
|
21
|
+
* panel is handed the widened reduced-motion signal anyway - an animation here would never
|
|
22
|
+
* play. The working marker is `statusGlyph(...)`, and `reducedMotion` is the USER's
|
|
23
|
+
* preference: it only decides whether a score change flashes for four seconds or stays put.
|
|
24
|
+
*
|
|
25
|
+
* COLUMNS ARE FIXED-WIDTH BOXES with exactly one elastic cell (`governance-roster.ts`), the
|
|
26
|
+
* lesson `TeamPanel` records at length: a flex-grown column under a fixed-height parent
|
|
27
|
+
* stretches to its widest child and the cells to its right lose their offsets.
|
|
28
|
+
*/
|
|
29
|
+
import React from 'react';
|
|
30
|
+
import type { GovernanceSnapshot } from '../governance/types.js';
|
|
31
|
+
import type { Theme } from './theme.js';
|
|
32
|
+
import type { TermCapabilities } from './capabilities.js';
|
|
33
|
+
import { type EliminatedSince } from './governance-status.js';
|
|
34
|
+
import type { GovernancePanelLayout } from './layout/governance-panel.js';
|
|
35
|
+
/**
|
|
36
|
+
* The first-seen-eliminated map, kept across snapshots so a replaced member shows its
|
|
37
|
+
* `replaced by ...` note for exactly one phase. Reset when the run changes or ends.
|
|
38
|
+
*
|
|
39
|
+
* A ref written during render is acceptable here because the write is idempotent
|
|
40
|
+
* (`trackEliminated` returns the same object when nothing is new) and no other component
|
|
41
|
+
* reads the ref - `App` reads only the returned value.
|
|
42
|
+
*/
|
|
43
|
+
export declare function useEliminatedSince(snapshot: GovernanceSnapshot | null): EliminatedSince;
|
|
44
|
+
export interface GovernancePanelProps {
|
|
45
|
+
/** Built by `buildGovernancePanelLayout`; the SAME object `App` read the height from. */
|
|
46
|
+
layout: GovernancePanelLayout;
|
|
47
|
+
theme: Theme;
|
|
48
|
+
caps: TermCapabilities;
|
|
49
|
+
}
|
|
50
|
+
export declare function GovernancePanel({ layout, theme, caps }: GovernancePanelProps): React.ReactElement | null;
|
|
@@ -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;
|