@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/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,44 @@ were written.
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
|
+
- **Governance mode - a multi-agent "legion" collaboration posture.** `Shift+Tab` (and `Ctrl+N`)
|
|
12
|
+
now cycle `BUILD -> PLAN -> GOVERN -> PLAN+GOVERN -> BUILD`; `/gov` goes to any of them
|
|
13
|
+
directly. In `GOVERN` the main agent becomes an **Orchestrator** that cannot write files or run
|
|
14
|
+
shell commands (enforced at the tool layer) and drives a team under a separation of powers
|
|
15
|
+
(development, review, testing, plus an unscored inspector) and a GT token economy: automatic
|
|
16
|
+
scoring from structured verdicts, escrow released only when integration passes, clawback on
|
|
17
|
+
failure, elimination and respawn. `PLAN+GOVERN` interviews you for at least
|
|
18
|
+
`governance.minAskRounds` answered rounds before the plan is accepted, then runs the approved
|
|
19
|
+
plan as the specification. New: the `gov_run` / `gov_dispatch` tools (never part of
|
|
20
|
+
`aragon exec`), the `/gov` command (`status|on|plan|off|board|runs|resume|abort|budget|help`), a
|
|
21
|
+
Legion panel, settlement cards in the transcript, a `/gov board` overview, the `governAccent`
|
|
22
|
+
theme token, `--govern` / `--plan-govern` / `--no-governance`, the `governance.*` config keys
|
|
23
|
+
and `ARAGON_GOVERNANCE=0`. Runs are persisted under `<home>/governance/` and survive `Esc`,
|
|
24
|
+
crashes and restarts. With governance disabled the system prompt, the tool list and the tool
|
|
25
|
+
timeout table are byte-identical to before. Cost note: the two orchestrator tool definitions
|
|
26
|
+
add a small per-request overhead to every session in which governance is available.
|
|
27
|
+
- **Governance mode, round two: a gentle stop, a settings page, visible cost, a report you can
|
|
28
|
+
re-read.** `/gov pause` pauses a governed run at the end of the stage that is running - nothing is
|
|
29
|
+
killed, no submission is lost, no GT moves (Esc is still the immediate stop) - and pauses at once
|
|
30
|
+
when no stage is running; `/gov pause cancel` withdraws a request that has not fired. While it
|
|
31
|
+
waits, the panel header reads `pausing after REVIEW`, the status chip `GOV pausing`, and the hint
|
|
32
|
+
row `pause pending: /gov pause cancel`. A run that is `escalated` (waiting on your ruling) is never
|
|
33
|
+
overwritten by a pause. The Orchestrator is told to stop and wait, and not to resume a run you
|
|
34
|
+
paused. **Settings > Governance** is now a page (a row under Team): the eleven `governance.*`
|
|
35
|
+
keys adjust with the arrow keys and save with the rest of Settings; turning `Governance` on or
|
|
36
|
+
off says that it applies next launch. `/gov runs` is a table with phase, health, team tokens,
|
|
37
|
+
cost (`n/a` when the model is unpriced, never `$0.00`) and the last update, and marks unfinished
|
|
38
|
+
runs with `*`; the columns drop with the terminal width. `/gov report [runId]` re-reads the final
|
|
39
|
+
report of a run (or its newest phase report, or the board) in the transcript, capped at 120
|
|
40
|
+
lines with the full path. The charter card, `/gov status` and the Orchestrator's `gov_run start`
|
|
41
|
+
result now carry a **dispatch plan** (`Dispatch plan: 10 for a clean run; a rework round adds up to
|
|
42
|
+
3, a fix cycle up to 2; the run is capped at 120. Counts only`). It states counts of
|
|
43
|
+
`gov_dispatch` calls only - never tokens or money - and it is deliberately not an upper bound.
|
|
44
|
+
A model-free screen gallery (`GOV_GALLERY=1 npx vitest run governance-gallery`) renders every
|
|
45
|
+
governance surface at 60/80/100/160 columns in colour, no-colour and ASCII variants. No config
|
|
46
|
+
key changed. On disk, `index.jsonl` rows gain an optional `digest` and a run now appends at most
|
|
47
|
+
one extra index row per change of that digest (about 250 rows for a run of 120 dispatches);
|
|
48
|
+
older rows read back as `-`.
|
|
11
49
|
- **Automatic skill triage, and no round limit on questions.** Two changes that
|
|
12
50
|
share one idea: replace a hard limit with guidance the agent can act on.
|
|
13
51
|
`ask_user` is no longer capped at four rounds per turn — the cap, its prompt
|
|
@@ -168,6 +206,12 @@ were written.
|
|
|
168
206
|
the same bytes it wrote before.
|
|
169
207
|
|
|
170
208
|
### Fixed
|
|
209
|
+
- `/gov runs` listed the **oldest** ten governed runs instead of the newest ten once there
|
|
210
|
+
were more than ten (the store already returned newest first and the listing then took the last
|
|
211
|
+
ten and reversed them). It now shows the newest ten, newest first.
|
|
212
|
+
- A settings save now composes the Orchestrator prompt from the config being saved, not from the
|
|
213
|
+
one it replaces, so the limits the prompt quotes (`maxRework`, `maxWorkPackages`, ...) are the
|
|
214
|
+
new ones the moment Settings closes.
|
|
171
215
|
- Changing only the fan-out width no longer drops the subagent model a session kit
|
|
172
216
|
installed. The settings save read "the `team` section was written" as "the user
|
|
173
217
|
re-decided the subagent slot", so adjusting `Max subagents` silently released a slot the
|
package/README.md
CHANGED
|
@@ -950,7 +950,8 @@ ignores them rather than rejecting the library):
|
|
|
950
950
|
| `/save [file]` | Export the session to JSON - a file you keep, unchanged by this feature |
|
|
951
951
|
| `/resume [file]` | Load a saved session. This session moves to a NEW id, and the spend counter restarts |
|
|
952
952
|
| `/session [copy\|pin]` | Report this session's id, file and branch parent; `copy` puts `aragon --resume <id>` on the clipboard; `pin` makes `sessions prune` skip the file forever |
|
|
953
|
-
| `/plan [on\|off\|status]` | Toggle plan mode - the keyboard-free equivalent of `Shift+Tab` |
|
|
953
|
+
| `/plan [on\|off\|status]` | Toggle plan mode (and leave governance) - the keyboard-free equivalent of `Shift+Tab` |
|
|
954
|
+
| `/gov [status\|on\|plan\|off\|board\|runs\|report [id]\|resume [id]\|pause [cancel]\|abort\|budget <n\|off>\|help]` | **Governance mode**: a governed engineering team (dev / review / test / inspector) with a GT scoring economy. `on` = GOVERN, `plan` = PLAN+GOVERN (interview first), `board` opens the full-screen overview, `runs` lists past runs with phase / health / tokens / cost, `report` re-reads a run's report, `pause` stops at the end of the running stage (nothing is killed), `abort` stops the running stage at once (the run is resumable). See [Governance mode](#governance-mode) |
|
|
954
955
|
| `/team [on\|off\|status]` / `/team [-n <n>] [--parts a,b,c] [--read-only] <brief>` | **Force team mode and start now.** `/team <brief>` arms forced team mode and submits that work as a normal turn: the lead analyses and plans it, then calls `task` — the directive, the `<forced_team_mode>` prompt block and a mechanical end-of-turn gate all say so. `/team on` arms without submitting, `/team off` leaves, `/team` reports. The configuration it used to carry (team switch, width, concurrency, supervisor, subagent model) lives in `Settings > Team` |
|
|
955
956
|
| `/todo [on\|off\|panel on\|off\|follow <mode>\|acceptance on\|off\|reset\|clear\|continue]` | Todo planning: status, the on/off switch, the rail, follow-through, acceptance criteria, and picking an unfinished plan back up |
|
|
956
957
|
| `/retry [show\|on\|off\|max <n>]` | API retry: the effective ladder, the on/off switch, the retry count. Takes effect **in the running session**, children included |
|
|
@@ -984,7 +985,7 @@ completes, `Up` / `Down` moves the selection, `Esc` closes it.
|
|
|
984
985
|
| `Ctrl+G` | **快捷键抽屉**:自上而下列出全部快捷键、各自的作用关键词,选中行下方再给一句话说明。`Up`/`Down`(或 `k`/`j`)移动、`PgUp`/`PgDn` 翻页、`d` 切换状态详情行、`r` 重新生成任务摘要、`Esc` 关闭。再按一次 `Ctrl+G` 关闭;其它参考类浮层打开时按它会直接接管,等待决策的 `confirm` / `question` / `plan` 除外 |
|
|
985
986
|
| `Enter` | 空闲时发送,运行时加入队列;收到 Core 已纳入会话的接收凭据后才移除 Queue 提示 |
|
|
986
987
|
| `Ctrl+J` / `Alt+Enter` / `Shift+Enter` | 插入换行。应用默认请求终端区分修饰键(Windows 用 win32-input-mode,macOS/Linux 用 kitty/modifyOtherKeys),Shift+Enter 在支持的终端开箱即用;不支持的终端用 Ctrl+J。参见 [终端设置](#terminal-setup-for-shiftenter) |
|
|
987
|
-
| `Shift+Tab` |
|
|
988
|
+
| `Shift+Tab` | Cycle the posture `BUILD` -> `PLAN` -> `GOVERN` -> `PLAN+GOVERN` -> `BUILD` (two states when governance is unavailable or `governance.shiftTab` is off). Equivalent: `/plan`, `/gov`. On Windows this needs a console flag Node < 22.17 does not set; aragon sets it at startup — see [Requirements](#requirements) |
|
|
988
989
|
| `Ctrl+N` | The same toggle, over a channel no Windows console can swallow. Use it if `Shift+Tab` does nothing. Written `Ctrl+N` everywhere, never `^N` - `^N` is the header's line-offset chip |
|
|
989
990
|
| `Ctrl+P` | **Quick prompt library**: the manager - create, edit, delete, favourite and reorder your own prompts. See [Quick prompt library](#quick-prompt-library) |
|
|
990
991
|
| `Ctrl+B` | **Agents board**: the details of a running dispatch. Left column lists every child (not just the five the roster fits), the right-hand sections show the selected child's state, turns, tools, tokens, files, mail, supervisor actions, retries, compaction, its current activity, its final answer or error, and the last 24 events. `Up` / `Down` change the child, `PgUp` / `PgDn` and the wheel page, `Esc` closes. The board survives the end of the dispatch - it freezes the last live snapshot and marks it `dispatch ended` - and opens after the fact from the session's own team card, where everything except the live-only sections (current activity, mail count, timeline) is still readable. Pressing `Ctrl+B` again, or `/agents`, opens and closes it |
|
|
@@ -1539,6 +1540,72 @@ rung. `--no-render-governor` (or `renderGovernor: false`, or
|
|
|
1539
1540
|
`ARAGON_RENDER_GOVERNOR=0`) turns the adaptation off entirely; the output is
|
|
1540
1541
|
identical, just heavier under load.
|
|
1541
1542
|
|
|
1543
|
+
## Governance mode
|
|
1544
|
+
|
|
1545
|
+
`GOVERN` and `PLAN+GOVERN` are two more postures on the same `Shift+Tab` cycle. In either,
|
|
1546
|
+
your session is led by an **Orchestrator** that cannot touch your files: it reads, asks you what
|
|
1547
|
+
it must, splits the work into work packages (WPs) and drives a governed team through the
|
|
1548
|
+
`gov_run` / `gov_dispatch` tools. Every implementation step is done by a dispatched agent, and
|
|
1549
|
+
the writer of a change is never the one who judges it.
|
|
1550
|
+
|
|
1551
|
+
| Power | Role | What it does |
|
|
1552
|
+
| --- | --- | --- |
|
|
1553
|
+
| Development | `DEV` | Implements one WP completely and reports which interface contracts it verified |
|
|
1554
|
+
| Review | `REV` | Reviews independently, may reject or fix small issues directly |
|
|
1555
|
+
| Testing | `TEST` | Verifies behaviour and traces every acceptance criterion to evidence |
|
|
1556
|
+
| Inspector | `INSP` | The fourth power: rules on claims, checks contracts, runs the registered integration commands, arbitrates. Not scored |
|
|
1557
|
+
|
|
1558
|
+
**GT (governance tokens)** is a score for the run, unrelated to LLM context tokens. Every
|
|
1559
|
+
DEV / REV / TEST agent starts with 100 GT. Rule-engine events are booked automatically from
|
|
1560
|
+
structured verdicts (a passed review is +15, a rejection -20, ...); positive scores are held in
|
|
1561
|
+
**escrow** until the phase's integration check passes, and are clawed back from whoever caused a
|
|
1562
|
+
failure. An agent whose confirmed score reaches zero is replaced by a successor that is told why.
|
|
1563
|
+
The inspector books only judgement events, and each one needs written evidence.
|
|
1564
|
+
|
|
1565
|
+
Each phase runs `dev -> review -> test -> settle -> integrate` (plus `fix` and a second
|
|
1566
|
+
`integrate` if integration fails). The engine refuses illegal orders and every tool result ends
|
|
1567
|
+
with `NEXT:` - the legal next actions - so a compacted or `/clear`ed session can resume.
|
|
1568
|
+
Disputes go to the inspector first and, if fundamental, to you (`ask_user`), and your ruling
|
|
1569
|
+
closes the loop with `gov_run resolve`.
|
|
1570
|
+
|
|
1571
|
+
`PLAN+GOVERN` first runs the normal plan mode with at least `governance.minAskRounds` (default 2)
|
|
1572
|
+
**answered** question rounds before `submit_plan` is accepted; approving the plan switches to
|
|
1573
|
+
`GOVERN` and the plan becomes the specification.
|
|
1574
|
+
|
|
1575
|
+
While a stage runs, a compact panel shows the pipeline, the roster, the GT bars and the latest
|
|
1576
|
+
ledger movements; the transcript gets a card only at charter, phase settlement, escalation and
|
|
1577
|
+
close. `/gov board` opens the full overview. `Esc` stops the running stage; the run is saved
|
|
1578
|
+
(`<home>/governance/<runId>/`) and `/gov resume` picks it up, re-dispatching only the missing
|
|
1579
|
+
work. A stage in flight defers any posture change until it ends.
|
|
1580
|
+
|
|
1581
|
+
**Stopping gently.** `/gov pause` lets the stage that is running finish - every submission lands,
|
|
1582
|
+
nothing is killed or rolled back, no GT moves - and then pauses the run; with no stage running it
|
|
1583
|
+
pauses at once. `/gov pause cancel` withdraws a request that has not fired, and `/gov resume`
|
|
1584
|
+
continues a paused run. Unlike `Esc`, it never throws away work in progress. A run that is waiting
|
|
1585
|
+
on your ruling is left as it is.
|
|
1586
|
+
|
|
1587
|
+
**Cost before you start.** The charter, `/gov status` and the `gov_run start` result carry a
|
|
1588
|
+
dispatch plan: how many `gov_dispatch` calls a clean run needs (stages wider than
|
|
1589
|
+
`team.maxSubagents` are split, which adds calls), how many one more rework round or fix cycle adds,
|
|
1590
|
+
and the hard cap of 120 per run. These are counts of calls, not a forecast of tokens or money, and
|
|
1591
|
+
not an upper bound on the total.
|
|
1592
|
+
|
|
1593
|
+
**Looking back.** `/gov runs` shows each run's phase, health, team tokens, cost (`n/a` for an
|
|
1594
|
+
unpriced model) and last update, newest first, with `*` on runs you can still resume. `/gov report
|
|
1595
|
+
[runId]` prints the run's final report (else its newest phase report, else the board) in the
|
|
1596
|
+
transcript, up to 120 lines and the path of the full file. Nothing is regenerated; it only reads.
|
|
1597
|
+
|
|
1598
|
+
Limits and switches (`aragon config set governance.<key> <value>`, or **Settings > Governance**): `enabled`, `shiftTab`,
|
|
1599
|
+
`panel`, `profile` (`general` / `ml` / `product` / `api-security`), `maxWorkPackages` (<= 8),
|
|
1600
|
+
`maxPhases` (<= 6), `maxRework` (<= 5), `maxFixCycles` (<= 5), `minAskRounds` (0-5),
|
|
1601
|
+
`budgetTokens` (team tokens only; 0 = unlimited), `confirmCharter`. `ARAGON_GOVERNANCE=0` and
|
|
1602
|
+
`--no-governance` disable it; `--govern` / `--plan-govern` start in a governed posture. It is not
|
|
1603
|
+
available in `aragon exec` / `-p`. Governed agents are team agents: each one spends tokens, so a
|
|
1604
|
+
run costs several times a single-agent turn - watch the status-bar chip and set `budgetTokens`.
|
|
1605
|
+
|
|
1606
|
+
The information boundary is a tripwire, not a sandbox: roles are shown only what they may see and
|
|
1607
|
+
cannot read the governance store through the tools, but a determined `bash` command could.
|
|
1608
|
+
|
|
1542
1609
|
## Plan mode
|
|
1543
1610
|
|
|
1544
1611
|
`aragon` has two postures, and `Shift+Tab` switches between them. `/plan` does
|
|
@@ -35,6 +35,12 @@ import type { TaskSummaryOutcome } from '../fast/task-summary-types.js';
|
|
|
35
35
|
import { ContextMeter, type ContextUsageListener } from '../compaction/meter.js';
|
|
36
36
|
import type { CompactionEventListener, CompactionSnapshot, ContextUsageSnapshot } from '../compaction/types.js';
|
|
37
37
|
import type { AcceptanceItem, TodoEventListener, TodoSnapshot } from '../todo/types.js';
|
|
38
|
+
import { GovernanceWiring } from './governance-wiring.js';
|
|
39
|
+
import { type GovernanceConfig } from '../config/governance-config.js';
|
|
40
|
+
import { type Posture } from '../governance/posture.js';
|
|
41
|
+
import type { GovernanceAvailability } from '../governance/copy.js';
|
|
42
|
+
import type { PauseOutcome } from '../governance/engine/pause.js';
|
|
43
|
+
import type { GovernanceEventListener, GovernanceSnapshot } from '../governance/types.js';
|
|
38
44
|
import { type HumanInputGate } from '../tools/human-input.js';
|
|
39
45
|
import { SkillService, type ApprovalGate } from '../skills/service.js';
|
|
40
46
|
import type { SkillRoutingReport } from '../skills/triage.js';
|
|
@@ -198,6 +204,12 @@ export interface AgentModeState {
|
|
|
198
204
|
/** Non-null only while a `plan -> build` switch is waiting for `agent_end`. */
|
|
199
205
|
pending: AgentMode | null;
|
|
200
206
|
}
|
|
207
|
+
/** What `setPosture` adopted (governance-mode 4.2): the same contract as `AgentModeState`. */
|
|
208
|
+
export interface PostureState {
|
|
209
|
+
effective: Posture;
|
|
210
|
+
/** A change waiting for `agent_end` (plan-to-build, or any change while a stage runs). */
|
|
211
|
+
pending: Posture | null;
|
|
212
|
+
}
|
|
201
213
|
export interface PreflightResult {
|
|
202
214
|
ok: boolean;
|
|
203
215
|
message?: string;
|
|
@@ -297,6 +309,11 @@ export declare class AgentController {
|
|
|
297
309
|
private readonly planInteractive;
|
|
298
310
|
private readonly teamRegistered;
|
|
299
311
|
private readonly teamRuntime;
|
|
312
|
+
/**
|
|
313
|
+
* Governance mode (governance-mode 14.2). Every decision lives in the wiring class; this
|
|
314
|
+
* file only forwards. `registered` inside it is fixed at construction (D-22).
|
|
315
|
+
*/
|
|
316
|
+
private readonly governance;
|
|
300
317
|
private forcedTeam;
|
|
301
318
|
private readonly todoRegistered;
|
|
302
319
|
private todoEnabled;
|
|
@@ -635,6 +652,58 @@ export declare class AgentController {
|
|
|
635
652
|
applyPendingMode(): AgentModeState | null;
|
|
636
653
|
/** Named read surface for `/plan status`, so no command reaches into internals. */
|
|
637
654
|
getPlanStatus(): AgentModeState;
|
|
655
|
+
getPosture(): Posture;
|
|
656
|
+
getPostureState(): PostureState;
|
|
657
|
+
/** The Shift+Tab cycle: four states when governance is usable, else the classic two. */
|
|
658
|
+
getPostureCycle(): readonly Posture[];
|
|
659
|
+
isGovernanceAvailable(): GovernanceAvailability;
|
|
660
|
+
/** The precise sentence for why governance cannot be used now, or null. */
|
|
661
|
+
getGovernanceUnavailableText(): string | null;
|
|
662
|
+
/**
|
|
663
|
+
* Request a posture and return what was ADOPTED (the `setAgentMode` contract: the caller
|
|
664
|
+
* dispatches the returned value, never the requested one). Tighten at once, loosen when
|
|
665
|
+
* idle, and while a governed stage runs defer EVERYTHING to `agent_end` (D-23).
|
|
666
|
+
*/
|
|
667
|
+
setPosture(next: Posture, opts?: {
|
|
668
|
+
force?: boolean;
|
|
669
|
+
}): PostureState;
|
|
670
|
+
/** Adopt a deferred posture. Call from `agent_end`. Null when nothing was pending. */
|
|
671
|
+
applyPendingPosture(): PostureState | null;
|
|
672
|
+
/** Esc / `/gov abort`: stop the in-flight governed stage (the run becomes `paused`). */
|
|
673
|
+
abortGovernanceStage(): void;
|
|
674
|
+
isGovernanceStageRunning(): boolean;
|
|
675
|
+
getGovernanceSnapshot(): GovernanceSnapshot | null;
|
|
676
|
+
/** Run + ledger behind the `/gov board` tabs that the snapshot alone cannot fill. */
|
|
677
|
+
getGovernanceBoardInput(): ReturnType<GovernanceWiring['boardInput']>;
|
|
678
|
+
subscribeGovernance(listener: GovernanceEventListener): () => void;
|
|
679
|
+
/** Recent governed runs (`/gov runs`). */
|
|
680
|
+
listGovernanceRuns(): ReturnType<GovernanceWiring['listRuns']>;
|
|
681
|
+
/** `/gov pause` and `/gov pause cancel`: stop at the next clean stage boundary. */
|
|
682
|
+
requestGovernancePause(): Promise<PauseOutcome>;
|
|
683
|
+
cancelGovernancePause(): boolean;
|
|
684
|
+
/** Whether the governance tools were registered at launch (Settings > Governance). */
|
|
685
|
+
isGovernanceRegistered(): boolean;
|
|
686
|
+
/** `/gov report [runId]`: a stored report, read-only. */
|
|
687
|
+
readGovernanceReport(runId?: string): ReturnType<GovernanceWiring['readReport']>;
|
|
688
|
+
/** The dispatch-plan line for the live run, for `/gov status`. */
|
|
689
|
+
getGovernanceDispatchPlan(): string | null;
|
|
690
|
+
/**
|
|
691
|
+
* The PLAN+GOVERN interview progress for the question overlay's chip, or null outside that
|
|
692
|
+
* posture or when no minimum is enforced (governance-mode 9.3).
|
|
693
|
+
*/
|
|
694
|
+
getGovernanceInterview(): {
|
|
695
|
+
answered: number;
|
|
696
|
+
required: number;
|
|
697
|
+
} | null;
|
|
698
|
+
/** `/gov resume`: the run id to hand to the orchestrator, or null when none exists. */
|
|
699
|
+
findResumableGovernanceRun(runId?: string): Promise<string | null>;
|
|
700
|
+
getGovernanceConfig(): GovernanceConfig;
|
|
701
|
+
/** Adopt a governance config patch for this session and re-render (the block quotes limits). */
|
|
702
|
+
setGovernanceConfig(patch: Partial<GovernanceConfig>): GovernanceConfig;
|
|
703
|
+
/** `submit_plan` approval: PLAN+GOVERN hands over to the team, plain PLAN goes to BUILD. */
|
|
704
|
+
private onPlanApproved;
|
|
705
|
+
/** What a team child costs per token, or undefined for an unpriced model (never $0.00). */
|
|
706
|
+
private teamModelCost;
|
|
638
707
|
/**
|
|
639
708
|
* READ-ONLY guard probe, called by `ask_user` BEFORE it opens the overlay.
|
|
640
709
|
*
|
package/dist/agent/controller.js
CHANGED
|
@@ -48,6 +48,12 @@ import { TodoStore } from '../todo/store.js';
|
|
|
48
48
|
import { createTodoTool } from '../todo/todo-tool.js';
|
|
49
49
|
import { buildTodoBlock } from '../todo/prompt.js';
|
|
50
50
|
import { createPlanTools } from '../tools/plan-tools.js';
|
|
51
|
+
import { GovernanceWiring } from './governance-wiring.js';
|
|
52
|
+
import { clampGovernanceConfig } from '../config/governance-config.js';
|
|
53
|
+
import { decidePostureTransition } from '../governance/posture-transition.js';
|
|
54
|
+
import { composePosture, splitPosture } from '../governance/posture.js';
|
|
55
|
+
import { APPROVED_GOVERN_RESULT } from '../governance/prompts/refusals.js';
|
|
56
|
+
import { GOV_LEAD_TOOL_NAMES } from '../governance/limits.js';
|
|
51
57
|
import { ASK_GUARD_LIMITS, DENY_ALL_HUMAN_INPUT, questionFingerprint, } from '../tools/human-input.js';
|
|
52
58
|
import { getLogger } from '../logging/logger.js';
|
|
53
59
|
import { createNodeSkillHost } from '../skills/node-host.js';
|
|
@@ -190,6 +196,11 @@ export class AgentController {
|
|
|
190
196
|
// -----------------------------------------------------------------------
|
|
191
197
|
teamRegistered;
|
|
192
198
|
teamRuntime;
|
|
199
|
+
/**
|
|
200
|
+
* Governance mode (governance-mode 14.2). Every decision lives in the wiring class; this
|
|
201
|
+
* file only forwards. `registered` inside it is fixed at construction (D-22).
|
|
202
|
+
*/
|
|
203
|
+
governance;
|
|
193
204
|
// -----------------------------------------------------------------------
|
|
194
205
|
// Forced team mode (team-command-forced-dispatch §3.5 / D-4).
|
|
195
206
|
//
|
|
@@ -447,6 +458,29 @@ export class AgentController {
|
|
|
447
458
|
// snapshot of "is `task` in this.tools at all". The live switch is
|
|
448
459
|
// `config.team.enabled`, read through `isTeamEnabled()` — no second copy.
|
|
449
460
|
this.teamRegistered = config.team.enabled;
|
|
461
|
+
// BEFORE the runtime: its child hooks are read off this object. `getRuntime` is a
|
|
462
|
+
// closure because the engine (created lazily on first use) needs the runtime, and the
|
|
463
|
+
// runtime needs these hooks.
|
|
464
|
+
this.governance = new GovernanceWiring({
|
|
465
|
+
teamRegistered: this.teamRegistered,
|
|
466
|
+
config: () => this.config,
|
|
467
|
+
gate: humanInput,
|
|
468
|
+
getCwd: () => this.cwd,
|
|
469
|
+
getGateMode: () => this.effectiveMode,
|
|
470
|
+
withPausedWatchdog: (fn) => this.withPausedWatchdog(fn),
|
|
471
|
+
withHumanWait: (fn) => this.withHumanWait(fn),
|
|
472
|
+
hasApiKey: () => this.hasApiKey(),
|
|
473
|
+
modelCost: () => this.teamModelCost(),
|
|
474
|
+
getRuntime: () => this.teamRuntime,
|
|
475
|
+
});
|
|
476
|
+
// THE LAUNCH POSTURE (`--govern` / `--plan-govern`, governance-mode 11.2). Only when the
|
|
477
|
+
// tools were actually registered: `loadConfig` already degraded an unusable request to the
|
|
478
|
+
// classic posture, and this guards the remaining construction-time case.
|
|
479
|
+
const initialPosture = config.initialPosture;
|
|
480
|
+
if (this.governance.isRegistered() && (initialPosture === 'govern' || initialPosture === 'plan_govern')) {
|
|
481
|
+
this.governance.setGovernOn(true);
|
|
482
|
+
this.effectiveMode = initialPosture === 'plan_govern' ? 'plan' : 'build';
|
|
483
|
+
}
|
|
450
484
|
this.teamRuntime = this.teamRegistered
|
|
451
485
|
? new TeamRuntime({
|
|
452
486
|
getConfig: () => this.config,
|
|
@@ -530,6 +564,16 @@ export class AgentController {
|
|
|
530
564
|
// and nothing anywhere reports it. Spread conditionally so a session
|
|
531
565
|
// with no policy builds `SubagentDeps` exactly as it does today.
|
|
532
566
|
...(deps.permission ? { permission: deps.permission } : {}),
|
|
567
|
+
// GOVERNANCE CHILD HOOKS (governance-mode 13.2): present only when governance was
|
|
568
|
+
// registered, so every other session builds children exactly as before.
|
|
569
|
+
...(this.governance.isRegistered()
|
|
570
|
+
? {
|
|
571
|
+
extraToolsFor: (spec) => this.governance.childToolsFor(spec),
|
|
572
|
+
narrowToolsFor: (spec, tools) => this.governance.narrowToolsFor(spec, tools),
|
|
573
|
+
governanceRoleBlockFor: (spec) => this.governance.roleBlockFor(spec),
|
|
574
|
+
extraPolicyExempt: this.governance.childPolicyExempt(),
|
|
575
|
+
}
|
|
576
|
+
: {}),
|
|
533
577
|
})
|
|
534
578
|
: null;
|
|
535
579
|
// ABOVE `createBuiltinTools`, and the ordering is load-bearing for the
|
|
@@ -654,7 +698,8 @@ export class AgentController {
|
|
|
654
698
|
hasAnsweredQuestions: (questions) => this.hasAnswered(questions),
|
|
655
699
|
noteAnsweredQuestions: (questions) => this.noteAnswered(questions),
|
|
656
700
|
withHumanWait: (fn) => this.withHumanWait(fn),
|
|
657
|
-
onPlanApproved: () => this.
|
|
701
|
+
onPlanApproved: (plan) => this.onPlanApproved(plan),
|
|
702
|
+
beforeSubmit: () => this.governance.beforeSubmitPlan(),
|
|
658
703
|
}),
|
|
659
704
|
// THROUGH THE FACTORY for the reason `teamTools` records below (C-2), and
|
|
660
705
|
// empty when todo planning was off at construction — which leaves the
|
|
@@ -742,14 +787,7 @@ export class AgentController {
|
|
|
742
787
|
// table (I-2 byte parity); a fast or profile model the static
|
|
743
788
|
// tables do not price yields undefined, so the report says
|
|
744
789
|
// `pricing unknown` rather than fabricating $0.00 (C-11 / RV-4).
|
|
745
|
-
modelCost: () =>
|
|
746
|
-
const resolution = this.subagentModelResolution();
|
|
747
|
-
if (resolution.effective === 'main')
|
|
748
|
-
return this.getModelInfo().cost;
|
|
749
|
-
return this.isPricedModel(resolution.ref)
|
|
750
|
-
? this.getModelInfoFor(resolution.ref).cost
|
|
751
|
-
: undefined;
|
|
752
|
-
},
|
|
790
|
+
modelCost: () => this.teamModelCost(),
|
|
753
791
|
// The same resolution, re-read per dispatch, feeds the report's
|
|
754
792
|
// disclosure line - one read per consumer, one authority both.
|
|
755
793
|
subagentModel: () => this.subagentModelResolution(),
|
|
@@ -770,6 +808,20 @@ export class AgentController {
|
|
|
770
808
|
}),
|
|
771
809
|
]
|
|
772
810
|
: [],
|
|
811
|
+
// GOVERNANCE (governance-mode 14.3): the Orchestrator's two tools, the ceiling
|
|
812
|
+
// exemption for exactly those two names (D-22b: NOT HOST_TOOL_NAMES), and the live gate
|
|
813
|
+
// that refuses the lead's own writes. All three are spread ONLY when registered, so a
|
|
814
|
+
// session without governance builds the identical options bag.
|
|
815
|
+
...(this.governance.isRegistered()
|
|
816
|
+
? {
|
|
817
|
+
governTools: this.governance.leadTools(),
|
|
818
|
+
policyExempt: GOV_LEAD_TOOL_NAMES,
|
|
819
|
+
governGate: () => ({
|
|
820
|
+
governOn: this.governance.isGovernOn(),
|
|
821
|
+
mode: this.effectiveMode,
|
|
822
|
+
}),
|
|
823
|
+
}
|
|
824
|
+
: {}),
|
|
773
825
|
// Read at CALL time, never cached: the mode flips mid-run when the user
|
|
774
826
|
// approves a plan, and a cached 'plan' would refuse the work they just
|
|
775
827
|
// authorized.
|
|
@@ -909,6 +961,14 @@ export class AgentController {
|
|
|
909
961
|
// outlived a mid-session `Settings > Team` switch to the supervisor
|
|
910
962
|
// and killed the dispatch the supervisor was meant to look after.
|
|
911
963
|
...(this.teamRegistered ? { task: 0 } : {}),
|
|
964
|
+
// P0 (governance-mode D-21 / RV-0): `gov_dispatch` runs a whole governed stage,
|
|
965
|
+
// routinely longer than `toolTimeoutMs`, and it listens to `ctx.signal` (it hands
|
|
966
|
+
// it to `TeamRuntime.dispatch`), which is what makes `0` safe. Registered in the SAME
|
|
967
|
+
// change as the tool itself: a registered tool with no entry here is killed by the
|
|
968
|
+
// executor at the default timeout on the first long stage, and no unit test with an
|
|
969
|
+
// instant stub dispatch would notice. Absent when unregistered, so the table is
|
|
970
|
+
// unchanged for every session without governance.
|
|
971
|
+
...(this.governance.isRegistered() ? { gov_dispatch: 0 } : {}),
|
|
912
972
|
},
|
|
913
973
|
},
|
|
914
974
|
});
|
|
@@ -1066,6 +1126,13 @@ export class AgentController {
|
|
|
1066
1126
|
const triageBlock = triageOn && skillsCatalog.length > 0
|
|
1067
1127
|
? buildSkillTriageBlock({ candidates: this.turnRouting?.candidates ?? [] })
|
|
1068
1128
|
: '';
|
|
1129
|
+
// GOVERNANCE (governance-mode 6.1). '' for every non-governed posture, which splices
|
|
1130
|
+
// nothing. In GOVERN with gate mode `build` the team blocks are dropped below: `task` is
|
|
1131
|
+
// refused there, and advertising it would describe a refused capability.
|
|
1132
|
+
const posture = this.getPosture();
|
|
1133
|
+
const governBlock = this.governance.orchestratorBlock(posture, config);
|
|
1134
|
+
const governAddendum = this.governance.planAddendum(posture, config);
|
|
1135
|
+
const dropTeamBlocks = governBlock !== '' && this.effectiveMode === 'build';
|
|
1069
1136
|
return buildSystemPrompt({
|
|
1070
1137
|
cwd: this.cwd,
|
|
1071
1138
|
tools: this.tools,
|
|
@@ -1075,13 +1142,15 @@ export class AgentController {
|
|
|
1075
1142
|
skillTriageBlock: triageBlock,
|
|
1076
1143
|
agentMode: this.effectiveMode,
|
|
1077
1144
|
planInteractive: this.planInteractive,
|
|
1145
|
+
...(governBlock ? { governBlock } : {}),
|
|
1146
|
+
...(governAddendum ? { governAddendum } : {}),
|
|
1078
1147
|
// BOTH halves, and both are required (§4.5). `teamRegistered` false means
|
|
1079
1148
|
// there is no `task` tool to advertise; `config.team.enabled` false means
|
|
1080
1149
|
// the user turned the capability off (in settings — the only writer).
|
|
1081
1150
|
// Advertising in either case would describe a capability the model does not
|
|
1082
1151
|
// have. Read through the field rather than `this.isTeamEnabled()` so the
|
|
1083
1152
|
// sentence and the code agree, as the two flags always have here (P1-4).
|
|
1084
|
-
teamBlock: this.teamRegistered && this.config.team.enabled
|
|
1153
|
+
teamBlock: this.teamRegistered && this.config.team.enabled && !dropTeamBlocks
|
|
1085
1154
|
? buildTeamBlock({
|
|
1086
1155
|
maxSubagents: config.team.maxSubagents,
|
|
1087
1156
|
maxConcurrent: config.team.maxConcurrent,
|
|
@@ -1094,7 +1163,7 @@ export class AgentController {
|
|
|
1094
1163
|
// session can never be told to use a tool the prompt above it does not
|
|
1095
1164
|
// mention. Empty everywhere else, which is what keeps I-2 (byte-identical
|
|
1096
1165
|
// prompt) true for every session that never types `/team`.
|
|
1097
|
-
forcedTeamBlock: this.forcedTeam && this.teamRegistered && this.config.team.enabled
|
|
1166
|
+
forcedTeamBlock: this.forcedTeam && this.teamRegistered && this.config.team.enabled && !dropTeamBlocks
|
|
1098
1167
|
? buildForcedTeamBlock({
|
|
1099
1168
|
count: this.forcedTeam.count,
|
|
1100
1169
|
planMode: this.effectiveMode === 'plan',
|
|
@@ -1635,6 +1704,148 @@ export class AgentController {
|
|
|
1635
1704
|
pending: this.pendingMode,
|
|
1636
1705
|
};
|
|
1637
1706
|
}
|
|
1707
|
+
// -----------------------------------------------------------------------
|
|
1708
|
+
// Posture (governance-mode 4.2). The gate mode above stays the only thing the tools
|
|
1709
|
+
// read; governance is a second, orthogonal flag (D-1), so none of the 25 `=== 'plan'`
|
|
1710
|
+
// sites changed. These methods compose the two and are the only writers of both.
|
|
1711
|
+
// -----------------------------------------------------------------------
|
|
1712
|
+
getPosture() {
|
|
1713
|
+
return composePosture(this.effectiveMode, this.governance.isGovernOn());
|
|
1714
|
+
}
|
|
1715
|
+
getPostureState() {
|
|
1716
|
+
return { effective: this.getPosture(), pending: this.governance.getPendingPosture() };
|
|
1717
|
+
}
|
|
1718
|
+
/** The Shift+Tab cycle: four states when governance is usable, else the classic two. */
|
|
1719
|
+
getPostureCycle() {
|
|
1720
|
+
return this.governance.postureCycle();
|
|
1721
|
+
}
|
|
1722
|
+
isGovernanceAvailable() {
|
|
1723
|
+
return this.governance.isAvailable();
|
|
1724
|
+
}
|
|
1725
|
+
/** The precise sentence for why governance cannot be used now, or null. */
|
|
1726
|
+
getGovernanceUnavailableText() {
|
|
1727
|
+
return this.governance.unavailableText();
|
|
1728
|
+
}
|
|
1729
|
+
/**
|
|
1730
|
+
* Request a posture and return what was ADOPTED (the `setAgentMode` contract: the caller
|
|
1731
|
+
* dispatches the returned value, never the requested one). Tighten at once, loosen when
|
|
1732
|
+
* idle, and while a governed stage runs defer EVERYTHING to `agent_end` (D-23).
|
|
1733
|
+
*/
|
|
1734
|
+
setPosture(next, opts = {}) {
|
|
1735
|
+
const before = this.getPosture();
|
|
1736
|
+
// An unregistered session has no governance to be "on": a stray governed request
|
|
1737
|
+
// degrades to its classic half, so the badge can never claim a gate that is not there.
|
|
1738
|
+
const target = this.governance.isRegistered() ? next : splitPosture(next).mode;
|
|
1739
|
+
const result = decidePostureTransition({
|
|
1740
|
+
current: { mode: this.effectiveMode, governOn: this.governance.isGovernOn() },
|
|
1741
|
+
target,
|
|
1742
|
+
force: opts.force === true,
|
|
1743
|
+
running: this.isRunning(),
|
|
1744
|
+
stageRunning: this.governance.isStageRunning(),
|
|
1745
|
+
});
|
|
1746
|
+
this.effectiveMode = result.mode;
|
|
1747
|
+
this.governance.setGovernOn(result.governOn);
|
|
1748
|
+
this.governance.setPendingPosture(result.pending);
|
|
1749
|
+
// A posture request supersedes a stale plan-to-build deferral from `setAgentMode`.
|
|
1750
|
+
this.pendingMode = null;
|
|
1751
|
+
this.governance.onPostureAdopted(this.getPosture(), before);
|
|
1752
|
+
this.rebuildSystemPrompt();
|
|
1753
|
+
return this.getPostureState();
|
|
1754
|
+
}
|
|
1755
|
+
/** Adopt a deferred posture. Call from `agent_end`. Null when nothing was pending. */
|
|
1756
|
+
applyPendingPosture() {
|
|
1757
|
+
const pending = this.governance.getPendingPosture();
|
|
1758
|
+
if (pending === null)
|
|
1759
|
+
return this.applyPendingMode() === null ? null : this.getPostureState();
|
|
1760
|
+
if (this.governance.isStageRunning())
|
|
1761
|
+
return null;
|
|
1762
|
+
this.governance.setPendingPosture(null);
|
|
1763
|
+
return this.setPosture(pending, { force: true });
|
|
1764
|
+
}
|
|
1765
|
+
/** Esc / `/gov abort`: stop the in-flight governed stage (the run becomes `paused`). */
|
|
1766
|
+
abortGovernanceStage() {
|
|
1767
|
+
this.governance.abortStage();
|
|
1768
|
+
}
|
|
1769
|
+
isGovernanceStageRunning() {
|
|
1770
|
+
return this.governance.isStageRunning();
|
|
1771
|
+
}
|
|
1772
|
+
getGovernanceSnapshot() {
|
|
1773
|
+
return this.governance.snapshot();
|
|
1774
|
+
}
|
|
1775
|
+
/** Run + ledger behind the `/gov board` tabs that the snapshot alone cannot fill. */
|
|
1776
|
+
getGovernanceBoardInput() {
|
|
1777
|
+
return this.governance.boardInput();
|
|
1778
|
+
}
|
|
1779
|
+
subscribeGovernance(listener) {
|
|
1780
|
+
return this.governance.subscribe(listener);
|
|
1781
|
+
}
|
|
1782
|
+
/** Recent governed runs (`/gov runs`). */
|
|
1783
|
+
listGovernanceRuns() {
|
|
1784
|
+
return this.governance.listRuns();
|
|
1785
|
+
}
|
|
1786
|
+
/** `/gov pause` and `/gov pause cancel`: stop at the next clean stage boundary. */
|
|
1787
|
+
requestGovernancePause() {
|
|
1788
|
+
return this.governance.requestPause();
|
|
1789
|
+
}
|
|
1790
|
+
cancelGovernancePause() {
|
|
1791
|
+
return this.governance.cancelPause();
|
|
1792
|
+
}
|
|
1793
|
+
/** Whether the governance tools were registered at launch (Settings > Governance). */
|
|
1794
|
+
isGovernanceRegistered() {
|
|
1795
|
+
return this.governance.isRegistered();
|
|
1796
|
+
}
|
|
1797
|
+
/** `/gov report [runId]`: a stored report, read-only. */
|
|
1798
|
+
readGovernanceReport(runId) {
|
|
1799
|
+
return this.governance.readReport(runId);
|
|
1800
|
+
}
|
|
1801
|
+
/** The dispatch-plan line for the live run, for `/gov status`. */
|
|
1802
|
+
getGovernanceDispatchPlan() {
|
|
1803
|
+
return this.governance.dispatchPlanText();
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* The PLAN+GOVERN interview progress for the question overlay's chip, or null outside that
|
|
1807
|
+
* posture or when no minimum is enforced (governance-mode 9.3).
|
|
1808
|
+
*/
|
|
1809
|
+
getGovernanceInterview() {
|
|
1810
|
+
if (this.getPosture() !== 'plan_govern')
|
|
1811
|
+
return null;
|
|
1812
|
+
const required = this.getGovernanceConfig().minAskRounds;
|
|
1813
|
+
if (required <= 0)
|
|
1814
|
+
return null;
|
|
1815
|
+
return { answered: this.governance.answeredRoundCount(), required };
|
|
1816
|
+
}
|
|
1817
|
+
/** `/gov resume`: the run id to hand to the orchestrator, or null when none exists. */
|
|
1818
|
+
findResumableGovernanceRun(runId) {
|
|
1819
|
+
return this.governance.findResumableRun(runId);
|
|
1820
|
+
}
|
|
1821
|
+
getGovernanceConfig() {
|
|
1822
|
+
return clampGovernanceConfig(this.config.governance);
|
|
1823
|
+
}
|
|
1824
|
+
/** Adopt a governance config patch for this session and re-render (the block quotes limits). */
|
|
1825
|
+
setGovernanceConfig(patch) {
|
|
1826
|
+
const governance = clampGovernanceConfig({ ...this.getGovernanceConfig(), ...patch });
|
|
1827
|
+
this.advanceSettingsRevision();
|
|
1828
|
+
this.config = { ...this.config, governance };
|
|
1829
|
+
this.rebuildSystemPrompt();
|
|
1830
|
+
return governance;
|
|
1831
|
+
}
|
|
1832
|
+
/** `submit_plan` approval: PLAN+GOVERN hands over to the team, plain PLAN goes to BUILD. */
|
|
1833
|
+
onPlanApproved(plan) {
|
|
1834
|
+
if (this.governance.handlePlanApproved(plan) === 'govern') {
|
|
1835
|
+
this.setPosture('govern', { force: true });
|
|
1836
|
+
return APPROVED_GOVERN_RESULT;
|
|
1837
|
+
}
|
|
1838
|
+
this.setAgentMode('build', { force: true });
|
|
1839
|
+
}
|
|
1840
|
+
/** What a team child costs per token, or undefined for an unpriced model (never $0.00). */
|
|
1841
|
+
teamModelCost() {
|
|
1842
|
+
const resolution = this.subagentModelResolution();
|
|
1843
|
+
if (resolution.effective === 'main')
|
|
1844
|
+
return this.getModelInfo().cost;
|
|
1845
|
+
return this.isPricedModel(resolution.ref)
|
|
1846
|
+
? this.getModelInfoFor(resolution.ref).cost
|
|
1847
|
+
: undefined;
|
|
1848
|
+
}
|
|
1638
1849
|
/**
|
|
1639
1850
|
* READ-ONLY guard probe, called by `ask_user` BEFORE it opens the overlay.
|
|
1640
1851
|
*
|
|
@@ -1653,6 +1864,7 @@ export class AgentController {
|
|
|
1653
1864
|
* deleted round cap wearing a bigger number.
|
|
1654
1865
|
*/
|
|
1655
1866
|
noteAnswered(questions) {
|
|
1867
|
+
this.governance.noteAnsweredRound(questions);
|
|
1656
1868
|
this.askedFingerprints.add(questionFingerprint(questions));
|
|
1657
1869
|
while (this.askedFingerprints.size > ASK_GUARD_LIMITS.maxRemembered) {
|
|
1658
1870
|
const oldest = this.askedFingerprints.values().next();
|
|
@@ -1872,6 +2084,7 @@ export class AgentController {
|
|
|
1872
2084
|
this.modelMetadataGeneration += 1;
|
|
1873
2085
|
this.modelMetadataAbort.abort();
|
|
1874
2086
|
this.teamRuntime?.dispose();
|
|
2087
|
+
this.governance.dispose();
|
|
1875
2088
|
this.fast?.dispose();
|
|
1876
2089
|
this.compaction?.dispose();
|
|
1877
2090
|
this.contextMeter.dispose();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The governance slice of the view model: the small pure folds `reducer.ts` delegates to
|
|
3
|
+
* (governance-mode section 14.4).
|
|
4
|
+
*
|
|
5
|
+
* Pure: no React, no I/O. ASCII ONLY (`agent/` is glyph-scanned).
|
|
6
|
+
*
|
|
7
|
+
* WHY A FILE OF ITS OWN. `reducer.ts` is already past the file-size ceiling and the repo
|
|
8
|
+
* rule is "wiring-style growth only": each governance `case` in the reducer is a line or
|
|
9
|
+
* two that calls a function here, so the logic is unit-testable without a `ViewState`.
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentMode } from './agent-mode.js';
|
|
12
|
+
import type { GovernanceSnapshot } from '../governance/types.js';
|
|
13
|
+
import { type Posture } from '../governance/posture.js';
|
|
14
|
+
/** The posture half of a `setAgentMode` action. */
|
|
15
|
+
export interface AdoptedPostureInput {
|
|
16
|
+
mode: AgentMode;
|
|
17
|
+
pending: AgentMode | null;
|
|
18
|
+
/** Written from the controller's adopted state; absent for callers that predate postures. */
|
|
19
|
+
posture?: Posture;
|
|
20
|
+
pendingPosture?: Posture | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The pair of posture fields one `setAgentMode` dispatch writes.
|
|
24
|
+
*
|
|
25
|
+
* "NEVER DISPATCH THE REQUESTED VALUE, ONLY THE ADOPTED ONE" (spec 4.3): the controller
|
|
26
|
+
* reports all four values together and the reducer mirrors them, so the badge and the gate
|
|
27
|
+
* cannot disagree. A dispatch that carries only the gate mode (every pre-governance call
|
|
28
|
+
* site) keeps the governance dimension the view already has and swaps the mode half, which
|
|
29
|
+
* is exactly what such a caller meant.
|
|
30
|
+
*/
|
|
31
|
+
export declare function adoptPosture(current: Posture, action: AdoptedPostureInput): {
|
|
32
|
+
posture: Posture;
|
|
33
|
+
pendingPosture: Posture | null;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Fold a pushed snapshot into the view: a snapshot OLDER than the one held, for the same
|
|
37
|
+
* run, is dropped (the wiring throttles, and a late flush must not roll the panel back).
|
|
38
|
+
* Returns the held object unchanged when nothing should change.
|
|
39
|
+
*/
|
|
40
|
+
export declare function foldGovernanceSnapshot(held: GovernanceSnapshot | null, incoming: GovernanceSnapshot): GovernanceSnapshot;
|