@aragon-agent/cli 0.6.43 → 0.6.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/proc/kill-tree.d.ts +19 -1
- package/dist/proc/kill-tree.js +32 -5
- package/dist/proc/limits.d.ts +19 -0
- package/dist/proc/limits.js +19 -0
- package/dist/proc/supervisor.js +8 -1
- 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/bounded-spawn.d.ts +56 -0
- package/dist/tools/bounded-spawn.js +76 -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/tools/search-tools.js +52 -44
- 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/ScrollbackShell.d.ts +35 -7
- package/dist/ui/ScrollbackShell.js +1 -1
- 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/LiveTail.d.ts +3 -1
- package/dist/ui/scrollback/budget.d.ts +12 -6
- package/dist/ui/scrollback/budget.js +11 -4
- package/dist/ui/scrollback/live-preview.js +2 -0
- package/dist/ui/scrollback/settled-boundary.js +3 -0
- package/dist/ui/scrollback/tail-anchor.d.ts +5 -2
- package/dist/ui/scrollback/tail-anchor.js +3 -1
- 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
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Governance status: snapshot -> display derivations (governance-mode section 10.3).
|
|
3
|
+
*
|
|
4
|
+
* Pure: no Ink, no clock (callers inject `now`), no I/O. ASCII ONLY.
|
|
5
|
+
*
|
|
6
|
+
* WHAT LIVES HERE AND WHAT DOES NOT. The panel, the chip, the card and the board each
|
|
7
|
+
* need the same few JUDGEMENTS - which colour a score label gets, whether a score change
|
|
8
|
+
* is still inside its emphasis window, which pipeline step is current, what an agent's
|
|
9
|
+
* state looks like to `team-status.ts`. Putting each judgement here once is the same
|
|
10
|
+
* discipline `team-status.ts` records: the roster, the card and the chip used to disagree
|
|
11
|
+
* about what "running" looked like because nine files each answered it.
|
|
12
|
+
*
|
|
13
|
+
* COLOUR IS A SEMANTIC KEY, NOT A THEME FIELD. The layout modules emit `Tone` values and
|
|
14
|
+
* the components resolve them through `toneColor`, so a layout test never needs a `Theme`
|
|
15
|
+
* and a theme change never touches a layout.
|
|
16
|
+
*/
|
|
17
|
+
import type { GovAgentState, GovernanceSnapshot, RosterRow, RunStatus, StageKind } from '../governance/types.js';
|
|
18
|
+
import type { ChildStatus } from './team-status.js';
|
|
19
|
+
import type { Theme } from './theme.js';
|
|
20
|
+
/** Semantic colour slots shared by every governance surface. */
|
|
21
|
+
export type Tone = 'text' | 'muted' | 'hint' | 'border' | 'primary' | 'govern' | 'ok' | 'warn' | 'error' | 'pending' | 'running';
|
|
22
|
+
/** Resolve a tone against a theme. The ONLY place a `Tone` becomes a colour. */
|
|
23
|
+
export declare function toneColor(tone: Tone, theme: Theme): string | undefined;
|
|
24
|
+
/** A run of text in one tone: the unit every layout line is made of. */
|
|
25
|
+
export interface Segment {
|
|
26
|
+
text: string;
|
|
27
|
+
tone: Tone;
|
|
28
|
+
bold?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function segment(text: string, tone: Tone, bold?: boolean): Segment;
|
|
31
|
+
export declare function govChildStatus(state: GovAgentState): ChildStatus;
|
|
32
|
+
export declare function statusTone(status: ChildStatus): Tone;
|
|
33
|
+
/** How a standing label reads on screen. */
|
|
34
|
+
export type ScoreTone = 'ok' | 'warn' | 'danger' | 'muted';
|
|
35
|
+
export declare function scoreTone(label: RosterRow['label']): ScoreTone;
|
|
36
|
+
export declare function scoreToneKey(label: RosterRow['label']): Tone;
|
|
37
|
+
/** The short word for a label in the roster's tag column; `NORMAL` says nothing. */
|
|
38
|
+
export declare function labelTag(label: RosterRow['label']): string;
|
|
39
|
+
/** Scored agents start here; the gauge is full at this value. */
|
|
40
|
+
export declare const GAUGE_FULL_SCORE: 100;
|
|
41
|
+
export declare const GAUGE_CELLS = 10;
|
|
42
|
+
/**
|
|
43
|
+
* Filled cells of the 10-cell score gauge: `round(confirmed / 100 * 10)` clamped to
|
|
44
|
+
* [0, 10] (spec 10.3). Non-finite input draws an empty bar rather than throwing - the
|
|
45
|
+
* gauge is decoration over a number that is printed beside it.
|
|
46
|
+
*/
|
|
47
|
+
export declare function gaugeFilledCells(confirmed: number): number;
|
|
48
|
+
/** `115+` when the score is over the starting value, otherwise the plain number. */
|
|
49
|
+
export declare function scoreText(confirmed: number): string;
|
|
50
|
+
/** How long a score change stays emphasised on its row. */
|
|
51
|
+
export declare const DELTA_EMPHASIS_MS = 4000;
|
|
52
|
+
export interface DeltaCell {
|
|
53
|
+
/** `+10` / `-20`, or '' when the row has nothing to say. */
|
|
54
|
+
text: string;
|
|
55
|
+
tone: Tone;
|
|
56
|
+
bold: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** Signed delta text; a provisional gain carries the `P` suffix (`+15P`). */
|
|
59
|
+
export declare function signedDeltaText(delta: number, provisional: boolean): string;
|
|
60
|
+
/**
|
|
61
|
+
* The emphasised delta of a row.
|
|
62
|
+
*
|
|
63
|
+
* Motion allowed: bold + coloured for `DELTA_EMPHASIS_MS` after the change, then gone.
|
|
64
|
+
* Reduced motion: nothing is time-windowed, so nothing flashes - the delta stays, plain,
|
|
65
|
+
* until the engine replaces or clears `lastDelta` at the next phase (spec 10.3 "the
|
|
66
|
+
* increment text is kept until the next phase"). A zero delta says nothing in either mode.
|
|
67
|
+
*/
|
|
68
|
+
export declare function deltaCell(row: RosterRow, now: number, reducedMotion: boolean): DeltaCell;
|
|
69
|
+
/** The display modes of the legion panel (spec 10.3 mount rules). */
|
|
70
|
+
export type GovernancePanelMode = 'none' | 'run-strip' | 'panel';
|
|
71
|
+
/**
|
|
72
|
+
* Mount rule (D-17): a running stage -> the full panel (which REPLACES the team roster);
|
|
73
|
+
* a live run between stages -> the two-line strip; no run, a closed run or an abandoned
|
|
74
|
+
* run -> nothing at all (zero rows, zero layout shift).
|
|
75
|
+
*/
|
|
76
|
+
export declare function governancePanelMode(snapshot: GovernanceSnapshot | null): GovernancePanelMode;
|
|
77
|
+
/** Which component owns the bottom transient region's live roster. */
|
|
78
|
+
export type LiveRosterSurface = 'governance' | 'team' | 'none';
|
|
79
|
+
/**
|
|
80
|
+
* EXACTLY ONE LIVE ROSTER (D-17 / AC-25). A running governed stage owns the region even
|
|
81
|
+
* though the same children are also in `state.team` (the reducer still writes it for
|
|
82
|
+
* `/agents`); between stages the two-line strip shows only when no dispatch is live; with
|
|
83
|
+
* no live governed run the team roster behaves exactly as it always did.
|
|
84
|
+
*/
|
|
85
|
+
export declare function liveRosterSurface(snapshot: GovernanceSnapshot | null, teamLive: boolean): LiveRosterSurface;
|
|
86
|
+
export declare function isFinishedRun(status: RunStatus): boolean;
|
|
87
|
+
/** Agents currently doing something: the minimal tier's "4 working". */
|
|
88
|
+
export declare function workingCount(snapshot: GovernanceSnapshot): number;
|
|
89
|
+
/** Display position in the pipeline: the active step's key, or the stage, or null. */
|
|
90
|
+
export declare function activeStepKey(snapshot: GovernanceSnapshot): StageKind | null;
|
|
91
|
+
/** Tokens spent by the governed team (spec 8.5: team tokens, never the session total). */
|
|
92
|
+
export declare function teamTokens(snapshot: GovernanceSnapshot): number;
|
|
93
|
+
/**
|
|
94
|
+
* Budget readout for the chip's `$` hint: 'none' without a budget, 'warn' from 80%,
|
|
95
|
+
* 'over' from 100% (spec 8.5). Only budgets > 0 are budgets.
|
|
96
|
+
*/
|
|
97
|
+
export declare function budgetState(snapshot: GovernanceSnapshot): 'none' | 'ok' | 'warn' | 'over';
|
|
98
|
+
/** Short run id for the header: the last five alphanumerics, so ids that share a prefix differ. */
|
|
99
|
+
export declare function shortRunId(runId: string): string;
|
|
100
|
+
/** Phase at which each eliminated id was FIRST seen eliminated. */
|
|
101
|
+
export type EliminatedSince = Readonly<Record<string, number>>;
|
|
102
|
+
/**
|
|
103
|
+
* Fold a snapshot into the first-seen-eliminated map.
|
|
104
|
+
*
|
|
105
|
+
* WHY THE PANEL KEEPS THIS ITSELF: `RosterRow` carries no "eliminated in phase N" field,
|
|
106
|
+
* and the board still needs the full roster from the same snapshot, so the engine cannot
|
|
107
|
+
* simply drop the row. A member that disappears from the map's keys (never happens) or
|
|
108
|
+
* that was never seen eliminated is treated as "eliminated now" by `isRetired`. Returns
|
|
109
|
+
* the SAME object when nothing changed so React memo / ref comparisons stay cheap.
|
|
110
|
+
*/
|
|
111
|
+
export declare function trackEliminated(previous: EliminatedSince, snapshot: GovernanceSnapshot): EliminatedSince;
|
|
112
|
+
/**
|
|
113
|
+
* True when an eliminated member's one visible phase is over: it was first seen in an
|
|
114
|
+
* earlier phase than the one now displayed.
|
|
115
|
+
*/
|
|
116
|
+
export declare function isRetired(row: RosterRow, phase: number, since: EliminatedSince): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Roster order: DEV -> REV -> TEST -> INSP, active members before eliminated ones, then
|
|
119
|
+
* by generation and id so `dev2` precedes its successor `dev2-r1` and the order is total
|
|
120
|
+
* (a stable roster does not reshuffle between snapshots).
|
|
121
|
+
*/
|
|
122
|
+
export declare function sortRoster(roster: readonly RosterRow[]): RosterRow[];
|
|
123
|
+
/**
|
|
124
|
+
* `PLAN+GOVERN interview round 2/2+` while rounds are still owed, and `... 2/2 OK` once
|
|
125
|
+
* the minimum is met (governance-mode 10.6). The trailing `+` reads "at least this many":
|
|
126
|
+
* the model may ask more rounds than the minimum.
|
|
127
|
+
*/
|
|
128
|
+
export declare function interviewChipText(round: number, required: number): string;
|
|
129
|
+
/**
|
|
130
|
+
* A `/gov pause` is waiting for the running stage to finish (governance-mode-v1-1 6.4).
|
|
131
|
+
* Only meaningful while the run is still `executing`: once it is `paused` the request has
|
|
132
|
+
* been redeemed, and an `escalated` run drops it.
|
|
133
|
+
*/
|
|
134
|
+
export declare function isPausePending(snapshot: GovernanceSnapshot): boolean;
|
|
135
|
+
/** True for the two governed postures, given a mode OR posture value as a string. */
|
|
136
|
+
export declare function isGovernedModeValue(value: string | null | undefined): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* The status row's word for a mode OR a posture. `MODE_LABEL` answers for `build` /
|
|
139
|
+
* `plan` (so the byte-identical pre-governance output is preserved); the two governed
|
|
140
|
+
* postures are the only values that reach the second table.
|
|
141
|
+
*
|
|
142
|
+
* Short form: the first letter, except `plan_govern` which is `PG` - `P` is already PLAN
|
|
143
|
+
* and a status row that cannot tell them apart has defeated the badge.
|
|
144
|
+
*/
|
|
145
|
+
export declare function modeWord(value: string, full: boolean): string | undefined;
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Governance status: snapshot -> display derivations (governance-mode section 10.3).
|
|
3
|
+
*
|
|
4
|
+
* Pure: no Ink, no clock (callers inject `now`), no I/O. ASCII ONLY.
|
|
5
|
+
*
|
|
6
|
+
* WHAT LIVES HERE AND WHAT DOES NOT. The panel, the chip, the card and the board each
|
|
7
|
+
* need the same few JUDGEMENTS - which colour a score label gets, whether a score change
|
|
8
|
+
* is still inside its emphasis window, which pipeline step is current, what an agent's
|
|
9
|
+
* state looks like to `team-status.ts`. Putting each judgement here once is the same
|
|
10
|
+
* discipline `team-status.ts` records: the roster, the card and the chip used to disagree
|
|
11
|
+
* about what "running" looked like because nine files each answered it.
|
|
12
|
+
*
|
|
13
|
+
* COLOUR IS A SEMANTIC KEY, NOT A THEME FIELD. The layout modules emit `Tone` values and
|
|
14
|
+
* the components resolve them through `toneColor`, so a layout test never needs a `Theme`
|
|
15
|
+
* and a theme change never touches a layout.
|
|
16
|
+
*/
|
|
17
|
+
import { POSTURE_LABEL } from '../governance/posture.js';
|
|
18
|
+
import { MODE_LABEL } from '../agent/agent-mode.js';
|
|
19
|
+
import { GOV_LIMITS } from '../governance/limits.js';
|
|
20
|
+
/**
|
|
21
|
+
* A table, not a switch: exhaustive over `Tone` at compile time (a new tone is a
|
|
22
|
+
* missing-key error) and flat in complexity however many tones there are.
|
|
23
|
+
*/
|
|
24
|
+
const TONE_COLOR = {
|
|
25
|
+
text: (theme) => theme.assistant,
|
|
26
|
+
muted: (theme) => theme.muted,
|
|
27
|
+
hint: (theme) => theme.hintFg,
|
|
28
|
+
border: (theme) => theme.border,
|
|
29
|
+
primary: (theme) => theme.primary,
|
|
30
|
+
govern: (theme) => theme.governAccent,
|
|
31
|
+
ok: (theme) => theme.toolDone,
|
|
32
|
+
warn: (theme) => theme.noticeWarn,
|
|
33
|
+
error: (theme) => theme.noticeError,
|
|
34
|
+
pending: (theme) => theme.toolPending,
|
|
35
|
+
running: (theme) => theme.toolRunning,
|
|
36
|
+
};
|
|
37
|
+
/** Resolve a tone against a theme. The ONLY place a `Tone` becomes a colour. */
|
|
38
|
+
export function toneColor(tone, theme) {
|
|
39
|
+
return TONE_COLOR[tone](theme);
|
|
40
|
+
}
|
|
41
|
+
export function segment(text, tone, bold = false) {
|
|
42
|
+
return bold ? { text, tone, bold } : { text, tone };
|
|
43
|
+
}
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Agent state -> the team roster's vocabulary
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
/**
|
|
48
|
+
* A governance agent state, read as a `team-status.ts` `ChildStatus`, so the glyph and
|
|
49
|
+
* the colour come from THAT module (`statusGlyph` / `statusMarkerCell`) and not from a
|
|
50
|
+
* second table (spec 10.3, "do not make a second copy").
|
|
51
|
+
*
|
|
52
|
+
* `idle` and `queued` are both "not doing anything yet"; `eliminated` borrows the
|
|
53
|
+
* failure reading because the marker for it is the cross and the colour is the error
|
|
54
|
+
* colour - the row's TEXT says `replaced by ...`, which is what stops it reading as a
|
|
55
|
+
* crash.
|
|
56
|
+
*/
|
|
57
|
+
const STATUS_BY_STATE = {
|
|
58
|
+
queued: 'queued',
|
|
59
|
+
idle: 'queued',
|
|
60
|
+
working: 'running',
|
|
61
|
+
submitted: 'done',
|
|
62
|
+
failed: 'failed',
|
|
63
|
+
eliminated: 'failed',
|
|
64
|
+
};
|
|
65
|
+
export function govChildStatus(state) {
|
|
66
|
+
return STATUS_BY_STATE[state];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The tone that `statusColor(status, theme)` resolves to, as a key. A test pins the pair
|
|
70
|
+
* (`toneColor(statusTone(s), theme) === statusColor(s, theme)` for every status and every
|
|
71
|
+
* theme) so the two tables cannot drift apart.
|
|
72
|
+
*/
|
|
73
|
+
const TONE_BY_STATUS = {
|
|
74
|
+
queued: 'pending',
|
|
75
|
+
running: 'running',
|
|
76
|
+
done: 'ok',
|
|
77
|
+
failed: 'error',
|
|
78
|
+
aborted: 'warn',
|
|
79
|
+
};
|
|
80
|
+
export function statusTone(status) {
|
|
81
|
+
return TONE_BY_STATUS[status];
|
|
82
|
+
}
|
|
83
|
+
export function scoreTone(label) {
|
|
84
|
+
switch (label) {
|
|
85
|
+
case 'NORMAL':
|
|
86
|
+
return 'ok';
|
|
87
|
+
case 'WARNING':
|
|
88
|
+
return 'warn';
|
|
89
|
+
case 'DANGER':
|
|
90
|
+
case 'KILLED':
|
|
91
|
+
return 'danger';
|
|
92
|
+
case 'NOT_SCORED':
|
|
93
|
+
return 'muted';
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const TONE_BY_SCORE = {
|
|
97
|
+
ok: 'ok',
|
|
98
|
+
warn: 'warn',
|
|
99
|
+
danger: 'error',
|
|
100
|
+
muted: 'muted',
|
|
101
|
+
};
|
|
102
|
+
export function scoreToneKey(label) {
|
|
103
|
+
return TONE_BY_SCORE[scoreTone(label)];
|
|
104
|
+
}
|
|
105
|
+
/** The short word for a label in the roster's tag column; `NORMAL` says nothing. */
|
|
106
|
+
export function labelTag(label) {
|
|
107
|
+
switch (label) {
|
|
108
|
+
case 'WARNING':
|
|
109
|
+
return 'WARN';
|
|
110
|
+
case 'DANGER':
|
|
111
|
+
return 'DANGER';
|
|
112
|
+
case 'KILLED':
|
|
113
|
+
return 'KILLED';
|
|
114
|
+
case 'NORMAL':
|
|
115
|
+
case 'NOT_SCORED':
|
|
116
|
+
return '';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Scored agents start here; the gauge is full at this value. */
|
|
120
|
+
export const GAUGE_FULL_SCORE = GOV_LIMITS.initialTokens;
|
|
121
|
+
export const GAUGE_CELLS = 10;
|
|
122
|
+
/**
|
|
123
|
+
* Filled cells of the 10-cell score gauge: `round(confirmed / 100 * 10)` clamped to
|
|
124
|
+
* [0, 10] (spec 10.3). Non-finite input draws an empty bar rather than throwing - the
|
|
125
|
+
* gauge is decoration over a number that is printed beside it.
|
|
126
|
+
*/
|
|
127
|
+
export function gaugeFilledCells(confirmed) {
|
|
128
|
+
if (!Number.isFinite(confirmed))
|
|
129
|
+
return 0;
|
|
130
|
+
const raw = Math.round((confirmed / GAUGE_FULL_SCORE) * GAUGE_CELLS);
|
|
131
|
+
return Math.min(GAUGE_CELLS, Math.max(0, raw));
|
|
132
|
+
}
|
|
133
|
+
/** `115+` when the score is over the starting value, otherwise the plain number. */
|
|
134
|
+
export function scoreText(confirmed) {
|
|
135
|
+
const rounded = Math.round(confirmed);
|
|
136
|
+
return rounded > GAUGE_FULL_SCORE ? `${rounded}+` : String(Math.max(0, rounded));
|
|
137
|
+
}
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
// Delta emphasis (AC-27)
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
/** How long a score change stays emphasised on its row. */
|
|
142
|
+
export const DELTA_EMPHASIS_MS = 4000;
|
|
143
|
+
const NO_DELTA = { text: '', tone: 'muted', bold: false };
|
|
144
|
+
/** Signed delta text; a provisional gain carries the `P` suffix (`+15P`). */
|
|
145
|
+
export function signedDeltaText(delta, provisional) {
|
|
146
|
+
const sign = delta > 0 ? '+' : delta < 0 ? '-' : '';
|
|
147
|
+
return `${sign}${Math.abs(Math.round(delta))}${provisional && delta > 0 ? 'P' : ''}`;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The emphasised delta of a row.
|
|
151
|
+
*
|
|
152
|
+
* Motion allowed: bold + coloured for `DELTA_EMPHASIS_MS` after the change, then gone.
|
|
153
|
+
* Reduced motion: nothing is time-windowed, so nothing flashes - the delta stays, plain,
|
|
154
|
+
* until the engine replaces or clears `lastDelta` at the next phase (spec 10.3 "the
|
|
155
|
+
* increment text is kept until the next phase"). A zero delta says nothing in either mode.
|
|
156
|
+
*/
|
|
157
|
+
export function deltaCell(row, now, reducedMotion) {
|
|
158
|
+
const last = row.lastDelta;
|
|
159
|
+
if (last === null || last.delta === 0)
|
|
160
|
+
return NO_DELTA;
|
|
161
|
+
const tone = last.delta > 0 ? 'ok' : 'error';
|
|
162
|
+
const text = signedDeltaText(last.delta, last.provisional);
|
|
163
|
+
if (reducedMotion)
|
|
164
|
+
return { text, tone, bold: false };
|
|
165
|
+
const age = now - last.at;
|
|
166
|
+
if (age < 0 || age > DELTA_EMPHASIS_MS)
|
|
167
|
+
return NO_DELTA;
|
|
168
|
+
return { text, tone, bold: true };
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Mount rule (D-17): a running stage -> the full panel (which REPLACES the team roster);
|
|
172
|
+
* a live run between stages -> the two-line strip; no run, a closed run or an abandoned
|
|
173
|
+
* run -> nothing at all (zero rows, zero layout shift).
|
|
174
|
+
*/
|
|
175
|
+
export function governancePanelMode(snapshot) {
|
|
176
|
+
if (snapshot === null)
|
|
177
|
+
return 'none';
|
|
178
|
+
if (isFinishedRun(snapshot.status))
|
|
179
|
+
return 'none';
|
|
180
|
+
return snapshot.stageRunning ? 'panel' : 'run-strip';
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* EXACTLY ONE LIVE ROSTER (D-17 / AC-25). A running governed stage owns the region even
|
|
184
|
+
* though the same children are also in `state.team` (the reducer still writes it for
|
|
185
|
+
* `/agents`); between stages the two-line strip shows only when no dispatch is live; with
|
|
186
|
+
* no live governed run the team roster behaves exactly as it always did.
|
|
187
|
+
*/
|
|
188
|
+
export function liveRosterSurface(snapshot, teamLive) {
|
|
189
|
+
const mode = governancePanelMode(snapshot);
|
|
190
|
+
if (mode === 'panel')
|
|
191
|
+
return 'governance';
|
|
192
|
+
if (mode === 'run-strip' && !teamLive)
|
|
193
|
+
return 'governance';
|
|
194
|
+
return teamLive ? 'team' : 'none';
|
|
195
|
+
}
|
|
196
|
+
export function isFinishedRun(status) {
|
|
197
|
+
return status === 'closed' || status === 'abandoned';
|
|
198
|
+
}
|
|
199
|
+
/** Agents currently doing something: the minimal tier's "4 working". */
|
|
200
|
+
export function workingCount(snapshot) {
|
|
201
|
+
return snapshot.roster.filter((row) => row.state === 'working').length;
|
|
202
|
+
}
|
|
203
|
+
/** Display position in the pipeline: the active step's key, or the stage, or null. */
|
|
204
|
+
export function activeStepKey(snapshot) {
|
|
205
|
+
const active = snapshot.pipeline.find((step) => step.state === 'active');
|
|
206
|
+
if (active !== undefined && active.key !== 'intake')
|
|
207
|
+
return active.key;
|
|
208
|
+
return snapshot.stage;
|
|
209
|
+
}
|
|
210
|
+
/** Tokens spent by the governed team (spec 8.5: team tokens, never the session total). */
|
|
211
|
+
export function teamTokens(snapshot) {
|
|
212
|
+
return snapshot.usage.inputTokens + snapshot.usage.outputTokens;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Budget readout for the chip's `$` hint: 'none' without a budget, 'warn' from 80%,
|
|
216
|
+
* 'over' from 100% (spec 8.5). Only budgets > 0 are budgets.
|
|
217
|
+
*/
|
|
218
|
+
export function budgetState(snapshot) {
|
|
219
|
+
if (snapshot.budgetTokens <= 0)
|
|
220
|
+
return 'none';
|
|
221
|
+
const fraction = teamTokens(snapshot) / snapshot.budgetTokens;
|
|
222
|
+
if (fraction >= 1)
|
|
223
|
+
return 'over';
|
|
224
|
+
return fraction >= 0.8 ? 'warn' : 'ok';
|
|
225
|
+
}
|
|
226
|
+
/** Short run id for the header: the last five alphanumerics, so ids that share a prefix differ. */
|
|
227
|
+
export function shortRunId(runId) {
|
|
228
|
+
const clean = runId.replace(/[^A-Za-z0-9]/g, '');
|
|
229
|
+
return clean.length <= 5 ? clean : clean.slice(clean.length - 5);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Fold a snapshot into the first-seen-eliminated map.
|
|
233
|
+
*
|
|
234
|
+
* WHY THE PANEL KEEPS THIS ITSELF: `RosterRow` carries no "eliminated in phase N" field,
|
|
235
|
+
* and the board still needs the full roster from the same snapshot, so the engine cannot
|
|
236
|
+
* simply drop the row. A member that disappears from the map's keys (never happens) or
|
|
237
|
+
* that was never seen eliminated is treated as "eliminated now" by `isRetired`. Returns
|
|
238
|
+
* the SAME object when nothing changed so React memo / ref comparisons stay cheap.
|
|
239
|
+
*/
|
|
240
|
+
export function trackEliminated(previous, snapshot) {
|
|
241
|
+
let next = null;
|
|
242
|
+
for (const row of snapshot.roster) {
|
|
243
|
+
if (row.state !== 'eliminated' || previous[row.id] !== undefined)
|
|
244
|
+
continue;
|
|
245
|
+
next ??= { ...previous };
|
|
246
|
+
next[row.id] = snapshot.phase;
|
|
247
|
+
}
|
|
248
|
+
return next ?? previous;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* True when an eliminated member's one visible phase is over: it was first seen in an
|
|
252
|
+
* earlier phase than the one now displayed.
|
|
253
|
+
*/
|
|
254
|
+
export function isRetired(row, phase, since) {
|
|
255
|
+
if (row.state !== 'eliminated')
|
|
256
|
+
return false;
|
|
257
|
+
const seen = since[row.id];
|
|
258
|
+
return seen !== undefined && phase > seen;
|
|
259
|
+
}
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
// Sorting
|
|
262
|
+
// ---------------------------------------------------------------------------
|
|
263
|
+
const ROLE_ORDER = { DEV: 0, REV: 1, TEST: 2, INSP: 3 };
|
|
264
|
+
/**
|
|
265
|
+
* Roster order: DEV -> REV -> TEST -> INSP, active members before eliminated ones, then
|
|
266
|
+
* by generation and id so `dev2` precedes its successor `dev2-r1` and the order is total
|
|
267
|
+
* (a stable roster does not reshuffle between snapshots).
|
|
268
|
+
*/
|
|
269
|
+
export function sortRoster(roster) {
|
|
270
|
+
return [...roster].sort((a, b) => {
|
|
271
|
+
const gone = Number(a.state === 'eliminated') - Number(b.state === 'eliminated');
|
|
272
|
+
if (gone !== 0)
|
|
273
|
+
return gone;
|
|
274
|
+
const role = ROLE_ORDER[a.role] - ROLE_ORDER[b.role];
|
|
275
|
+
if (role !== 0)
|
|
276
|
+
return role;
|
|
277
|
+
if (a.generation !== b.generation)
|
|
278
|
+
return a.generation - b.generation;
|
|
279
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
// PLAN+GOVERN interview chip
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
/**
|
|
286
|
+
* `PLAN+GOVERN interview round 2/2+` while rounds are still owed, and `... 2/2 OK` once
|
|
287
|
+
* the minimum is met (governance-mode 10.6). The trailing `+` reads "at least this many":
|
|
288
|
+
* the model may ask more rounds than the minimum.
|
|
289
|
+
*/
|
|
290
|
+
export function interviewChipText(round, required) {
|
|
291
|
+
const answered = Math.max(0, Math.floor(round));
|
|
292
|
+
const needed = Math.max(0, Math.floor(required));
|
|
293
|
+
const met = answered >= needed;
|
|
294
|
+
return `${POSTURE_LABEL.plan_govern} interview round ${answered}/${needed}${met ? ' OK' : '+'}`;
|
|
295
|
+
}
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
// Posture words
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
/**
|
|
300
|
+
* A `/gov pause` is waiting for the running stage to finish (governance-mode-v1-1 6.4).
|
|
301
|
+
* Only meaningful while the run is still `executing`: once it is `paused` the request has
|
|
302
|
+
* been redeemed, and an `escalated` run drops it.
|
|
303
|
+
*/
|
|
304
|
+
export function isPausePending(snapshot) {
|
|
305
|
+
return snapshot.pauseRequested === true && snapshot.status === 'executing';
|
|
306
|
+
}
|
|
307
|
+
/** True for the two governed postures, given a mode OR posture value as a string. */
|
|
308
|
+
export function isGovernedModeValue(value) {
|
|
309
|
+
return value === 'govern' || value === 'plan_govern';
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* The status row's word for a mode OR a posture. `MODE_LABEL` answers for `build` /
|
|
313
|
+
* `plan` (so the byte-identical pre-governance output is preserved); the two governed
|
|
314
|
+
* postures are the only values that reach the second table.
|
|
315
|
+
*
|
|
316
|
+
* Short form: the first letter, except `plan_govern` which is `PG` - `P` is already PLAN
|
|
317
|
+
* and a status row that cannot tell them apart has defeated the badge.
|
|
318
|
+
*/
|
|
319
|
+
export function modeWord(value, full) {
|
|
320
|
+
const label = MODE_LABEL[value] ?? POSTURE_LABEL[value];
|
|
321
|
+
if (label === undefined)
|
|
322
|
+
return undefined;
|
|
323
|
+
if (full)
|
|
324
|
+
return label;
|
|
325
|
+
return value === 'plan_govern' ? 'PG' : label[0];
|
|
326
|
+
}
|
|
@@ -69,6 +69,10 @@ export declare const interactionCopy: {
|
|
|
69
69
|
readonly stopServices: "Ctrl+C stop services";
|
|
70
70
|
readonly exit: "Ctrl+C x2 exit";
|
|
71
71
|
readonly exitDraft: "Ctrl+C x2 clear input, x3 exit";
|
|
72
|
+
readonly governIdle: "type a task - the Orchestrator will assemble the team";
|
|
73
|
+
readonly governInterrupt: "Esc x2 interrupt (run is resumable)";
|
|
74
|
+
readonly governInterruptAgain: "Esc interrupt (run is resumable)";
|
|
75
|
+
readonly governPausePending: "pause pending: /gov pause cancel";
|
|
72
76
|
readonly help: "/help";
|
|
73
77
|
readonly shiftNewline: "Shift+Enter newline needs terminal support";
|
|
74
78
|
readonly mode: "Shift+Tab switch mode";
|
|
@@ -27,6 +27,11 @@ export const interactionCopy = {
|
|
|
27
27
|
complete: 'Tab complete', select: 'Up/Down select', scroll: 'PgUp/PgDn scroll',
|
|
28
28
|
confirm: 'Enter confirm', stopServices: 'Ctrl+C stop services', exit: 'Ctrl+C x2 exit',
|
|
29
29
|
exitDraft: 'Ctrl+C x2 clear input, x3 exit',
|
|
30
|
+
// GOVERN posture (governance-mode 10.6). The run is resumable, so Esc is not destructive.
|
|
31
|
+
governIdle: 'type a task - the Orchestrator will assemble the team',
|
|
32
|
+
governInterrupt: 'Esc x2 interrupt (run is resumable)',
|
|
33
|
+
governInterruptAgain: 'Esc interrupt (run is resumable)',
|
|
34
|
+
governPausePending: 'pause pending: /gov pause cancel',
|
|
30
35
|
help: '/help', shiftNewline: 'Shift+Enter newline needs terminal support',
|
|
31
36
|
mode: 'Shift+Tab switch mode', update: '/update',
|
|
32
37
|
idlePlaceholder: 'Ask a question or describe a task...', runningPlaceholder: 'Add a follow-up...',
|
|
@@ -19,6 +19,23 @@ export interface ActionHintInput {
|
|
|
19
19
|
modeToggleKey?: string;
|
|
20
20
|
/** Draft present: the exit clause becomes the clear-then-exit ladder. */
|
|
21
21
|
hasDraft?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The session is in a governed posture (governance-mode 10.6): the idle row teaches
|
|
24
|
+
* what the first message does, and the running row says an interrupt is resumable.
|
|
25
|
+
* ABSENT = every clause below is byte-identical to the pre-governance build.
|
|
26
|
+
*/
|
|
27
|
+
governed?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* A `/gov pause` is waiting for the running stage to finish (governance-mode-v1-1 6.4):
|
|
30
|
+
* the row says so and how to undo it. Absent keeps every clause byte-identical.
|
|
31
|
+
*/
|
|
32
|
+
govPausePending?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* The word after the toggle key, from `postureHintWord(nextPosture(...))`. Absent keeps
|
|
35
|
+
* the classic `switch mode`; only the wiring that knows the live posture cycle can say
|
|
36
|
+
* which posture is next, so this layer never guesses.
|
|
37
|
+
*/
|
|
38
|
+
nextPostureWord?: string;
|
|
22
39
|
}
|
|
23
40
|
export declare function escapeClause(input: ActionHintInput): string;
|
|
24
41
|
export declare function clipStatusText(text: string, cells: number): string;
|
|
@@ -13,6 +13,9 @@ export function escapeClause(input) {
|
|
|
13
13
|
return input.interruptPhase === 'armed' ? copy.cancelStartAgain : copy.cancelStart;
|
|
14
14
|
if (input.interactionPhase !== 'running')
|
|
15
15
|
return '';
|
|
16
|
+
if (input.governed) {
|
|
17
|
+
return input.interruptPhase === 'armed' ? copy.governInterruptAgain : copy.governInterrupt;
|
|
18
|
+
}
|
|
16
19
|
return input.interruptPhase === 'armed' ? copy.interruptAgain : copy.interrupt;
|
|
17
20
|
}
|
|
18
21
|
export function clipStatusText(text, cells) {
|
|
@@ -40,6 +43,9 @@ export function actionCandidates(input) {
|
|
|
40
43
|
...(selects ? [input.overlay === 'settings' ? copy.saveSettings : copy.confirm] : [])];
|
|
41
44
|
}
|
|
42
45
|
const actions = [];
|
|
46
|
+
if (input.governed && input.govPausePending && input.interactionPhase === 'running') {
|
|
47
|
+
actions.push(copy.governPausePending);
|
|
48
|
+
}
|
|
43
49
|
if (input.selectionPending)
|
|
44
50
|
actions.push(copy.copy);
|
|
45
51
|
else if (input.services)
|
|
@@ -48,7 +54,13 @@ export function actionCandidates(input) {
|
|
|
48
54
|
actions.push(...(input.completion === 'slash' ? [copy.executeCommand] : []), copy.complete, copy.select);
|
|
49
55
|
return actions;
|
|
50
56
|
}
|
|
51
|
-
|
|
57
|
+
// THE GOVERNED IDLE SENTENCE REPLACES `Enter send` / `newline` rather than joining them:
|
|
58
|
+
// at 120 columns it is 53 of the row's 119 cells, and the clause that would be crowded
|
|
59
|
+
// out is `Shift+Tab <next>`, the one the posture cycle most needs taught.
|
|
60
|
+
if (input.hintsEnabled !== false && input.governed && input.interactionPhase === 'idle') {
|
|
61
|
+
actions.push(copy.governIdle);
|
|
62
|
+
}
|
|
63
|
+
else if (input.hintsEnabled !== false && input.interactionPhase !== 'starting')
|
|
52
64
|
actions.push(input.interactionPhase === 'running' ? copy.enqueue : copy.send, input.cols < 72 ? copy.newline : copy.newlineLong);
|
|
53
65
|
return actions;
|
|
54
66
|
}
|
|
@@ -78,7 +90,7 @@ export function buildActionClauses(input) {
|
|
|
78
90
|
if (input.updateAvailable)
|
|
79
91
|
add(copy.update);
|
|
80
92
|
add(input.hasDraft ? copy.exitDraft : copy.exit);
|
|
81
|
-
add((input.modeToggleKey ?? 'Shift+Tab') + ' ' + copy.modeLabel);
|
|
93
|
+
add((input.modeToggleKey ?? 'Shift+Tab') + ' ' + (input.nextPostureWord ?? copy.modeLabel));
|
|
82
94
|
add(copy.help);
|
|
83
95
|
}
|
|
84
96
|
return result;
|