@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.
- package/CHANGELOG.md +44 -0
- package/README.md +69 -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/plan-prompt.d.ts +7 -0
- package/dist/agent/plan-prompt.js +2 -1
- package/dist/agent/reducer.d.ts +33 -1
- package/dist/agent/reducer.js +45 -9
- 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 +10 -4
- package/dist/commands/governance-command.d.ts +35 -0
- package/dist/commands/governance-command.js +292 -0
- package/dist/commands/governance-runs-table.d.ts +40 -0
- package/dist/commands/governance-runs-table.js +130 -0
- package/dist/commands/registry.d.ts +12 -0
- 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/validate-session.js +32 -1
- 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 +145 -25
- 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 +3 -0
- package/dist/ui/entries/GovernanceCard.d.ts +30 -0
- package/dist/ui/entries/GovernanceCard.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/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 +11 -0
- 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 +9 -0
- 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.
|
|
@@ -88,7 +95,7 @@ import { PlanReviewOverlay } from './overlays/PlanReviewOverlay.js';
|
|
|
88
95
|
import { CommandRegistry, runSlashInput } from '../commands/registry.js';
|
|
89
96
|
import { registerBuiltinCommands } from '../commands/builtins.js';
|
|
90
97
|
import { makeSkillsCommand, registerSkillCommands } from '../commands/skills.js';
|
|
91
|
-
import {
|
|
98
|
+
import { MODE_TOGGLE_KEYS } from '../agent/agent-mode.js';
|
|
92
99
|
import { createClipboardCoordinator } from './clipboard-task.js';
|
|
93
100
|
import { QueuePanel } from './QueuePanel.js';
|
|
94
101
|
import { QueueOverlay } from './overlays/QueueOverlay.js';
|
|
@@ -140,6 +147,16 @@ export function resolveSettingsMaxTokens(raw, previous) {
|
|
|
140
147
|
toast: ['warn', 'Max tokens must be a number or "auto".'],
|
|
141
148
|
};
|
|
142
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* The `/gov board` overlay's data: the full run when the controller can supply it (all four
|
|
152
|
+
* tabs), else the snapshot alone (the Work packages and Claims tabs then say they are empty).
|
|
153
|
+
*/
|
|
154
|
+
function governanceBoardData(controller, snapshot) {
|
|
155
|
+
if (snapshot === null)
|
|
156
|
+
return null;
|
|
157
|
+
const input = controller.getGovernanceBoardInput?.();
|
|
158
|
+
return input ? boardDataFromRun({ snapshot, ...input }) : boardDataFromSnapshot(snapshot);
|
|
159
|
+
}
|
|
143
160
|
/** Services in a non-terminal state, from the live snapshot map. */
|
|
144
161
|
function liveServiceCount(services) {
|
|
145
162
|
let n = 0;
|
|
@@ -354,6 +371,9 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
354
371
|
const reducedMotion = cfg.reducedMotion ?? false;
|
|
355
372
|
const stateRef = useRef(state);
|
|
356
373
|
stateRef.current = state;
|
|
374
|
+
// The first-seen-eliminated map for the legion panel (a replaced member shows for one
|
|
375
|
+
// phase). A hook, so it is called unconditionally here and read further down.
|
|
376
|
+
const eliminatedSince = useEliminatedSince(state.governance);
|
|
357
377
|
/**
|
|
358
378
|
* The task label's two guards (tui-shortcut-drawer-and-task-summary D-10).
|
|
359
379
|
*
|
|
@@ -826,14 +846,22 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
826
846
|
submitRef.current(gate.message, { userInitiated: false, todoPolicy: 'continue' });
|
|
827
847
|
}, FORCED_NUDGE_GRACE_MS);
|
|
828
848
|
}
|
|
829
|
-
// A deferred `plan -> build`
|
|
830
|
-
|
|
849
|
+
// A deferred `plan -> build` (or any posture change that waited for a governed
|
|
850
|
+
// stage, governance-mode D-23) becomes real here and nowhere else (§3.2).
|
|
851
|
+
const applied = controller.applyPendingPosture();
|
|
831
852
|
if (applied) {
|
|
832
|
-
|
|
853
|
+
const split = splitPosture(applied.effective);
|
|
854
|
+
dispatch({
|
|
855
|
+
type: 'setAgentMode',
|
|
856
|
+
mode: split.mode,
|
|
857
|
+
pending: null,
|
|
858
|
+
posture: applied.effective,
|
|
859
|
+
pendingPosture: applied.pending,
|
|
860
|
+
});
|
|
833
861
|
dispatch({
|
|
834
862
|
type: 'pushToast',
|
|
835
863
|
level: 'info',
|
|
836
|
-
text:
|
|
864
|
+
text: postureAppliedToast(applied.effective),
|
|
837
865
|
});
|
|
838
866
|
}
|
|
839
867
|
});
|
|
@@ -965,6 +993,25 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
965
993
|
controller.dispose();
|
|
966
994
|
};
|
|
967
995
|
}, [controller]);
|
|
996
|
+
// --- Governance event stream (governance-mode 8.6 / 14.4). --------------
|
|
997
|
+
//
|
|
998
|
+
// ANOTHER CLI-LOCAL SUBSCRIPTION, for the reason the team one records: `GovernanceEvent`
|
|
999
|
+
// is deliberately not a member of core's `AgentEvent` union. The wiring throttles the
|
|
1000
|
+
// chatty updates; this effect only folds snapshots into the view, appends the four kinds
|
|
1001
|
+
// of settlement card (charter, phase, escalation, final) and clears the live snapshot when
|
|
1002
|
+
// the run ends. A no-op unsubscribe when governance was not registered.
|
|
1003
|
+
useEffect(() => {
|
|
1004
|
+
return controller.subscribeGovernance((event) => {
|
|
1005
|
+
dispatch({ type: 'govSnapshot', snapshot: event.snapshot });
|
|
1006
|
+
const card = event.type === 'run_started' || event.type === 'stage_ended' ? event.card
|
|
1007
|
+
: event.type === 'escalation' || event.type === 'run_closed' ? event.card
|
|
1008
|
+
: null;
|
|
1009
|
+
if (card)
|
|
1010
|
+
dispatch({ type: 'governanceCard', card });
|
|
1011
|
+
if (event.type === 'run_closed')
|
|
1012
|
+
dispatch({ type: 'govEnd' });
|
|
1013
|
+
});
|
|
1014
|
+
}, [controller]);
|
|
968
1015
|
// --- Todo event stream (todo-plan-execution §3.8 / §5.2). --------------
|
|
969
1016
|
//
|
|
970
1017
|
// A THIRD SUBSCRIPTION, for the reason the team one records: `TodoEvent` is
|
|
@@ -1386,7 +1433,14 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
1386
1433
|
// reducer's `'build'` seed would render one wrong frame without this.
|
|
1387
1434
|
useEffect(() => {
|
|
1388
1435
|
const current = controller.getAgentMode();
|
|
1389
|
-
|
|
1436
|
+
const posture = controller.getPostureState();
|
|
1437
|
+
dispatch({
|
|
1438
|
+
type: 'setAgentMode',
|
|
1439
|
+
mode: current,
|
|
1440
|
+
pending: null,
|
|
1441
|
+
posture: posture.effective,
|
|
1442
|
+
pendingPosture: posture.pending,
|
|
1443
|
+
});
|
|
1390
1444
|
}, [controller]);
|
|
1391
1445
|
// --- Let the controller drive command-list rebuilds. -------------------
|
|
1392
1446
|
useEffect(() => {
|
|
@@ -1776,19 +1830,50 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
1776
1830
|
* what was requested: dispatching the request is the one way to make the badge
|
|
1777
1831
|
* claim a permission the gate will not honour.
|
|
1778
1832
|
*/
|
|
1779
|
-
const
|
|
1780
|
-
const applied = controller.
|
|
1781
|
-
|
|
1833
|
+
const applyPosture = (next, opts = {}) => {
|
|
1834
|
+
const applied = controller.setPosture(next, opts.force ? { force: true } : {});
|
|
1835
|
+
const split = splitPosture(applied.effective);
|
|
1836
|
+
// THE ADOPTED VALUES, all four in one dispatch (governance-mode 4.3).
|
|
1837
|
+
dispatch({
|
|
1838
|
+
type: 'setAgentMode',
|
|
1839
|
+
mode: split.mode,
|
|
1840
|
+
pending: applied.pending ? splitPosture(applied.pending).mode : null,
|
|
1841
|
+
posture: applied.effective,
|
|
1842
|
+
pendingPosture: applied.pending,
|
|
1843
|
+
});
|
|
1782
1844
|
if (opts.silent)
|
|
1783
1845
|
return applied;
|
|
1784
1846
|
if (applied.pending) {
|
|
1785
|
-
toast('info',
|
|
1847
|
+
toast('info', controller.isGovernanceStageRunning()
|
|
1848
|
+
? stageRunningToast(applied.pending)
|
|
1849
|
+
: posturePendingToast(applied.pending));
|
|
1786
1850
|
}
|
|
1787
1851
|
else {
|
|
1788
|
-
toast('info',
|
|
1852
|
+
toast('info', postureAppliedToast(applied.effective));
|
|
1853
|
+
// One-time, across launches: what GOVERN means (governance-mode 4.3).
|
|
1854
|
+
if (isGovernancePosture(applied.effective) && !getGovernanceIntroSeen()) {
|
|
1855
|
+
setGovernanceIntroSeen(true);
|
|
1856
|
+
dispatch({
|
|
1857
|
+
type: 'notice',
|
|
1858
|
+
level: 'info',
|
|
1859
|
+
text: applied.effective === 'plan_govern' ? PLAN_GOVERN_INTRO_NOTICE : GOVERN_INTRO_NOTICE,
|
|
1860
|
+
});
|
|
1861
|
+
}
|
|
1789
1862
|
}
|
|
1790
1863
|
return applied;
|
|
1791
1864
|
};
|
|
1865
|
+
/**
|
|
1866
|
+
* The gate-mode view of the same write path, for `/plan`: a plain `plan` / `build`
|
|
1867
|
+
* request names a classic posture, so it CLEARS governance (an explicit command beats
|
|
1868
|
+
* an implicit carry-over, governance-mode 4.2).
|
|
1869
|
+
*/
|
|
1870
|
+
const applyMode = (next, opts = {}) => {
|
|
1871
|
+
const applied = applyPosture(next, opts);
|
|
1872
|
+
return {
|
|
1873
|
+
effective: splitPosture(applied.effective).mode,
|
|
1874
|
+
pending: applied.pending ? splitPosture(applied.pending).mode : null,
|
|
1875
|
+
};
|
|
1876
|
+
};
|
|
1792
1877
|
/**
|
|
1793
1878
|
* Cancel any in-flight label call and make its result unadoptable.
|
|
1794
1879
|
*
|
|
@@ -1971,6 +2056,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
1971
2056
|
},
|
|
1972
2057
|
refreshSkills: () => setSkillsNonce((n) => n + 1),
|
|
1973
2058
|
applyAgentMode: applyMode,
|
|
2059
|
+
applyPosture: (next, opts) => applyPosture(next, opts ?? {}),
|
|
1974
2060
|
// Read at command time, so `/todo status` reports the live count rather than
|
|
1975
2061
|
// whatever it was when this context was built.
|
|
1976
2062
|
followBudget: budgetRef.current,
|
|
@@ -2275,8 +2361,11 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2275
2361
|
// here would read `'plan'` and the badge would lag by a frame. Writing it
|
|
2276
2362
|
// first through the same single path makes the tool's call an idempotent
|
|
2277
2363
|
// no-op and keeps the mirror exact (§3.1 / R-P7).
|
|
2278
|
-
|
|
2279
|
-
|
|
2364
|
+
// PLAN+GOVERN hands over to the team instead of implementing: the same single write
|
|
2365
|
+
// path, with governance kept on (governance-mode 9.2).
|
|
2366
|
+
const governed = controller.getPosture() === 'plan_govern';
|
|
2367
|
+
applyPosture(governed ? 'govern' : 'build', { force: true, silent: true });
|
|
2368
|
+
toast('success', governed ? PLAN_APPROVED_TOAST : 'Plan approved. Implementing.');
|
|
2280
2369
|
}
|
|
2281
2370
|
else {
|
|
2282
2371
|
toast('info', 'Revision requested.');
|
|
@@ -2593,6 +2682,9 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2593
2682
|
// The Agents board pages through `overlayScroll` too, but keeps Up/Down for its
|
|
2594
2683
|
// CHILD CURSOR - the same trade `settings` makes with its field cursor.
|
|
2595
2684
|
|| overlay === 'agents'
|
|
2685
|
+
// The governance board (governance-mode 10.5): without this line a PgDn in the
|
|
2686
|
+
// board falls through to the transcript behind it.
|
|
2687
|
+
|| overlay === 'governance'
|
|
2596
2688
|
// The prompt surfaces page themselves through `overlayScroll` too
|
|
2597
2689
|
// (quick-prompt-library appendix B-1). Without them a `PgDn` in the list does
|
|
2598
2690
|
// nothing and the wheel falls through to the transcript behind it.
|
|
@@ -2630,7 +2722,10 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2630
2722
|
if ((key.tab && key.shift) || (key.ctrl && (input === 'n' || input === 'N'))) {
|
|
2631
2723
|
if (stateRef.current.overlay)
|
|
2632
2724
|
return;
|
|
2633
|
-
|
|
2725
|
+
// The cycle's basis is `pending ?? effective`: with a change already waiting, a second
|
|
2726
|
+
// press must advance from it, or it would hold on the same target (governance-mode 4.1).
|
|
2727
|
+
const postureNow = controller.getPostureState();
|
|
2728
|
+
applyPosture(nextPosture(postureNow.pending ?? postureNow.effective, controller.getPostureCycle()));
|
|
2634
2729
|
return;
|
|
2635
2730
|
}
|
|
2636
2731
|
// Moved off Ctrl+L by D-1, because Ctrl+L is the branch key now.
|
|
@@ -2945,10 +3040,32 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2945
3040
|
? Math.max(0, viewportBudget - 1)
|
|
2946
3041
|
: Math.max(0, viewportBudget - composerBaseRows - queueLayout.rows - 1),
|
|
2947
3042
|
});
|
|
3043
|
+
// THE LEGION PANEL REPLACES THE TEAM ROSTER while a governed stage runs (D-17, AC-25):
|
|
3044
|
+
// one live roster, never two. Between stages it is a two-line run strip, and it yields to
|
|
3045
|
+
// a non-governed dispatch if one is somehow live. Its height feeds the same two budgets
|
|
3046
|
+
// the roster's does, so the band and the rail never learn a second number.
|
|
3047
|
+
// PLAN+GOVERN's interview chip on the question overlay (governance-mode 9.3).
|
|
3048
|
+
const interviewState = state.posture === 'plan_govern' ? controller.getGovernanceInterview?.() : null;
|
|
3049
|
+
const interviewProps = interviewState
|
|
3050
|
+
? { interview: { round: interviewState.answered, required: interviewState.required } }
|
|
3051
|
+
: {};
|
|
3052
|
+
const governanceMode = governancePanelMode(state.governance);
|
|
3053
|
+
const governanceLayout = state.governance !== null
|
|
3054
|
+
&& liveRosterSurface(state.governance, state.team !== null) === 'governance'
|
|
3055
|
+
? buildGovernancePanelLayout({
|
|
3056
|
+
cols: native ? Math.max(1, cols - 1) : baseRail.contentCols, rows,
|
|
3057
|
+
snapshot: state.governance, glyphs, reducedMotion, now: Date.now(),
|
|
3058
|
+
mode: governanceMode === 'panel' ? 'panel' : 'run-strip', eliminatedSince,
|
|
3059
|
+
availableRows: native
|
|
3060
|
+
? Math.max(0, viewportBudget - 1)
|
|
3061
|
+
: Math.max(0, viewportBudget - composerBaseRows - queueLayout.rows - 1),
|
|
3062
|
+
})
|
|
3063
|
+
: null;
|
|
3064
|
+
const teamPanelRows = governanceLayout ? governanceLayout.height : teamLayout.rowCount;
|
|
2948
3065
|
const railLayout = buildTodoRailLayout({
|
|
2949
3066
|
cols: cols - 1, panelEnabled: cfg.todo.panel, overlayOpen: false,
|
|
2950
3067
|
itemCount: state.todos?.items.length ?? 0, viewportBudget,
|
|
2951
|
-
teamRows:
|
|
3068
|
+
teamRows: teamPanelRows, queueRows: queueLayout.rows, popupRows: 0, composerBaseRows,
|
|
2952
3069
|
});
|
|
2953
3070
|
const { visible: railVisible, width: railWidth, rows: railRows, contentCols } = railLayout;
|
|
2954
3071
|
// The FULL-SCREEN rail only: native mode draws its rail inside the live region's
|
|
@@ -2983,7 +3100,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
2983
3100
|
// second time (`buildTeamPanelLayout` stays the single authority).
|
|
2984
3101
|
itemCount: state.todos?.items.length ?? 0,
|
|
2985
3102
|
panelEnabled: cfg.todo.panel,
|
|
2986
|
-
teamRowsNatural:
|
|
3103
|
+
teamRowsNatural: teamPanelRows,
|
|
2987
3104
|
// The top give-way measures a window entry's height, and an expanded tool card is a
|
|
2988
3105
|
// different height from a collapsed one - a forgotten value would print rows the region
|
|
2989
3106
|
// is not drawing.
|
|
@@ -3079,14 +3196,16 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3079
3196
|
// mounted with `{...props}` and an undeclared prop arrives as
|
|
3080
3197
|
// `undefined`. A construction-time snapshot, so reading it per frame is
|
|
3081
3198
|
// honest (I-7).
|
|
3082
|
-
teamRegistered: controller.isTeamRegistered(), probe: probe, onProfileSave: handleProfileSave, onReload: () => controller.createModelSettingsDraft(), onClose: () => dispatch({ type: 'setOverlay', overlay: null }),
|
|
3199
|
+
teamRegistered: controller.isTeamRegistered(), governanceRegistered: controller.isGovernanceRegistered(), probe: probe, onProfileSave: handleProfileSave, onReload: () => controller.createModelSettingsDraft(), onClose: () => dispatch({ type: 'setOverlay', overlay: null }),
|
|
3083
3200
|
// Read from `cfg` (render scope, re-read every frame), so `/retry off`
|
|
3084
3201
|
// while the screen is open shows the new value on the next paint.
|
|
3085
3202
|
retrySummary: cfg.retry.enabled && cfg.retry.maxRetries > 0 ? String(cfg.retry.maxRetries) : 'off' })) : overlay === 'agents' ? (
|
|
3086
3203
|
// THE BRANCH AND THE `Overlay` MEMBER SHIP TOGETHER (R-11): a missing branch is not
|
|
3087
3204
|
// a type error, it is a SILENT BLANK FRAME, because `active={overlay === null}` has
|
|
3088
3205
|
// 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 === '
|
|
3206
|
+
_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' ? (
|
|
3207
|
+
// THE BRANCH AND THE `Overlay` MEMBER SHIP TOGETHER (R-11), like `agents` above.
|
|
3208
|
+
_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
3209
|
const density = cfg.density;
|
|
3091
3210
|
const transcriptWindow = cfg.transcriptWindow ?? DEFAULT_TRANSCRIPT_WINDOW;
|
|
3092
3211
|
// The fixed status bar remains visible underneath every overlay and toast.
|
|
@@ -3207,7 +3326,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3207
3326
|
stopping: interruptGesture.current.phase === 'stopping',
|
|
3208
3327
|
interruptPhase: interruptGesture.current.phase,
|
|
3209
3328
|
compacting: compactionLive || !!state.compaction?.inFlight,
|
|
3210
|
-
mode: state.
|
|
3329
|
+
mode: state.posture, pendingMode: state.pendingPosture,
|
|
3211
3330
|
servicesActive: { live: liveServices }, ecoRung: governor.rung,
|
|
3212
3331
|
// THE STATUS-DETAIL ROW COUNTS LIKE THE ROSTER AND THE CHIP (A-1): this was the
|
|
3213
3332
|
// last inline phase filter, left behind when the StatusBar chip converged, and it
|
|
@@ -3227,11 +3346,12 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3227
3346
|
selectionPending: selectionController?.hasPendingSelection() ?? false,
|
|
3228
3347
|
copyInFlight: copyState.busy, copyCleanupPending: copyState.cleanupPending,
|
|
3229
3348
|
hasDraft: hasDraftRef.current, services: liveServices,
|
|
3230
|
-
hintsEnabled: cfg.hints, modeToggleKey,
|
|
3349
|
+
hintsEnabled: cfg.hints, modeToggleKey, governed: isGovernancePosture(state.posture),
|
|
3350
|
+
...(state.governance?.pauseRequested === true ? { govPausePending: true } : {}),
|
|
3231
3351
|
interruptPhase: interruptGesture.current.phase,
|
|
3232
3352
|
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;
|
|
3353
|
+
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' }) }));
|
|
3354
|
+
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
3355
|
// --- Native panel band (release-gate-and-native-panels §6.3/§6.4) -------------
|
|
3236
3356
|
//
|
|
3237
3357
|
// SEPARATE NODES, NOT THE TWO ABOVE (RV-P1-7). Those carry `cols={contentCols}` for
|
|
@@ -3252,7 +3372,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3252
3372
|
// out against `previewCols` would stop its clock one rail short of the screen's edge.
|
|
3253
3373
|
// `teamRowGeometry` is continuous in `cols`, so the number that decides whether the
|
|
3254
3374
|
// 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;
|
|
3375
|
+
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
3376
|
const rail = fullscreenRailVisible && state.todos ? (_jsx(TodoPanel, { snapshot: state.todos, width: railWidth, rows: railRows, running: running, reducedMotion: viewReducedMotion, theme: theme, caps: caps })) : null;
|
|
3257
3377
|
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
3378
|
const detailsNode = _jsx(BottomStatusRow, { plan: details, columns: viewCols, theme: theme });
|
|
@@ -3264,7 +3384,7 @@ export function App({ controller, version, initialOverlay, initialPrompt, confir
|
|
|
3264
3384
|
// partially stale. The window and its `known` flag now travel INSIDE
|
|
3265
3385
|
// it, resolved by the meter - which is what makes the user's
|
|
3266
3386
|
// `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.
|
|
3387
|
+
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
3388
|
? {
|
|
3269
3389
|
// `rosterCounts`, NOT a fourth inline phase filter (A-1): the chip and
|
|
3270
3390
|
// 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;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from 'ink';
|
|
3
|
+
import { toneColor } from './governance-status.js';
|
|
4
|
+
/** The segments as nested `Text`; the CALLER owns wrapping and truncation. */
|
|
5
|
+
export function GovernanceRun({ segments, theme }) {
|
|
6
|
+
return (_jsx(_Fragment, { children: segments.map((part, index) => (_jsx(Text, { color: toneColor(part.tone, theme), ...(part.bold ? { bold: true } : {}), children: part.text }, index))) }));
|
|
7
|
+
}
|
|
8
|
+
/** One display row: the run inside a `wrap="truncate"` `Text`, so it can never wrap. */
|
|
9
|
+
export function GovernanceLine({ segments, theme }) {
|
|
10
|
+
return (_jsx(Text, { wrap: "truncate", children: _jsx(GovernanceRun, { segments: segments, theme: theme }) }));
|
|
11
|
+
}
|
package/dist/ui/StatusBar.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import type { TermCapabilities } from './capabilities.js';
|
|
|
5
5
|
import type { UsageTotal } from '../agent/reducer.js';
|
|
6
6
|
import type { ContextUsageSnapshot } from '../compaction/types.js';
|
|
7
7
|
import type { AgentMode } from '../agent/agent-mode.js';
|
|
8
|
+
import type { GovernanceSnapshot } from '../governance/types.js';
|
|
9
|
+
import type { Posture } from '../governance/posture.js';
|
|
8
10
|
import type { PendingSteering } from '../agent/queued-messages.js';
|
|
9
11
|
import { type RunPhase } from './layout/status-layout.js';
|
|
10
12
|
import type { EscapeAction, StatusFeedback } from './status-feedback.js';
|
|
@@ -63,8 +65,19 @@ export interface StatusBarProps {
|
|
|
63
65
|
modified: boolean;
|
|
64
66
|
otherNames: readonly string[];
|
|
65
67
|
} | null;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
/**
|
|
69
|
+
* The mode word's source. A `Posture` is also accepted (governance-mode 10.2): its
|
|
70
|
+
* governed members render as `GOVERN` / `PLAN+GOVERN` in the governance hue, and
|
|
71
|
+
* `build` / `plan` render exactly as the `AgentMode` of the same name always did.
|
|
72
|
+
*/
|
|
73
|
+
agentMode?: AgentMode | Posture;
|
|
74
|
+
pendingAgentMode?: AgentMode | Posture | null;
|
|
75
|
+
/**
|
|
76
|
+
* The live governed-run snapshot, or absent. Drives the governance chip
|
|
77
|
+
* (`GOV p2/3 REVIEW`); absent plans a hidden chip, which keeps this row byte-identical
|
|
78
|
+
* to the pre-governance build.
|
|
79
|
+
*/
|
|
80
|
+
governance?: GovernanceSnapshot | null;
|
|
68
81
|
/**
|
|
69
82
|
* Forced team mode is armed, with the count it was armed with
|
|
70
83
|
* (team-command-forced-dispatch §3.8 / D-9). ABSENT = not armed, and every
|