@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.
Files changed (251) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +69 -2
  3. package/dist/agent/controller.d.ts +69 -0
  4. package/dist/agent/controller.js +224 -11
  5. package/dist/agent/governance-view.d.ts +40 -0
  6. package/dist/agent/governance-view.js +40 -0
  7. package/dist/agent/governance-wiring.d.ts +162 -0
  8. package/dist/agent/governance-wiring.js +470 -0
  9. package/dist/agent/plan-prompt.d.ts +7 -0
  10. package/dist/agent/plan-prompt.js +2 -1
  11. package/dist/agent/reducer.d.ts +33 -1
  12. package/dist/agent/reducer.js +45 -9
  13. package/dist/agent/system-prompt.d.ts +19 -0
  14. package/dist/agent/system-prompt.js +9 -1
  15. package/dist/cli.js +45 -1
  16. package/dist/commands/builtins.js +10 -4
  17. package/dist/commands/governance-command.d.ts +35 -0
  18. package/dist/commands/governance-command.js +292 -0
  19. package/dist/commands/governance-runs-table.d.ts +40 -0
  20. package/dist/commands/governance-runs-table.js +130 -0
  21. package/dist/commands/registry.d.ts +12 -0
  22. package/dist/config/app-paths.d.ts +10 -0
  23. package/dist/config/app-paths.js +12 -0
  24. package/dist/config/cli-commands.d.ts +18 -0
  25. package/dist/config/cli-commands.js +47 -1
  26. package/dist/config/env.d.ts +2 -1
  27. package/dist/config/env.js +10 -1
  28. package/dist/config/governance-config.d.ts +125 -0
  29. package/dist/config/governance-config.js +164 -0
  30. package/dist/config/governance-launch.d.ts +71 -0
  31. package/dist/config/governance-launch.js +58 -0
  32. package/dist/config/load.d.ts +15 -0
  33. package/dist/config/load.js +26 -1
  34. package/dist/config/model-profile-store.d.ts +4 -2
  35. package/dist/config/schema.d.ts +22 -0
  36. package/dist/config/schema.js +6 -0
  37. package/dist/config/store.js +14 -1
  38. package/dist/config/ui-state.d.ts +11 -0
  39. package/dist/config/ui-state.js +11 -0
  40. package/dist/diagnostics/doctor.js +20 -0
  41. package/dist/governance/card-normalize.d.ts +24 -0
  42. package/dist/governance/card-normalize.js +76 -0
  43. package/dist/governance/copy.d.ts +109 -0
  44. package/dist/governance/copy.js +223 -0
  45. package/dist/governance/engine/aftermath.d.ts +49 -0
  46. package/dist/governance/engine/aftermath.js +134 -0
  47. package/dist/governance/engine/artifact-persist.d.ts +35 -0
  48. package/dist/governance/engine/artifact-persist.js +86 -0
  49. package/dist/governance/engine/budget.d.ts +52 -0
  50. package/dist/governance/engine/budget.js +112 -0
  51. package/dist/governance/engine/cards.d.ts +18 -0
  52. package/dist/governance/engine/cards.js +186 -0
  53. package/dist/governance/engine/digest.d.ts +32 -0
  54. package/dist/governance/engine/digest.js +63 -0
  55. package/dist/governance/engine/engine-core.d.ts +219 -0
  56. package/dist/governance/engine/engine-core.js +562 -0
  57. package/dist/governance/engine/engine.d.ts +68 -0
  58. package/dist/governance/engine/engine.js +314 -0
  59. package/dist/governance/engine/estimate.d.ts +38 -0
  60. package/dist/governance/engine/estimate.js +46 -0
  61. package/dist/governance/engine/inspector.d.ts +16 -0
  62. package/dist/governance/engine/inspector.js +396 -0
  63. package/dist/governance/engine/integration.d.ts +35 -0
  64. package/dist/governance/engine/integration.js +220 -0
  65. package/dist/governance/engine/lifecycle.d.ts +29 -0
  66. package/dist/governance/engine/lifecycle.js +656 -0
  67. package/dist/governance/engine/pause.d.ts +56 -0
  68. package/dist/governance/engine/pause.js +107 -0
  69. package/dist/governance/engine/phase-members.d.ts +15 -0
  70. package/dist/governance/engine/phase-members.js +34 -0
  71. package/dist/governance/engine/phase-planner.d.ts +53 -0
  72. package/dist/governance/engine/phase-planner.js +282 -0
  73. package/dist/governance/engine/rebuild.d.ts +27 -0
  74. package/dist/governance/engine/rebuild.js +57 -0
  75. package/dist/governance/engine/report.d.ts +66 -0
  76. package/dist/governance/engine/report.js +220 -0
  77. package/dist/governance/engine/run-digest.d.ts +20 -0
  78. package/dist/governance/engine/run-digest.js +42 -0
  79. package/dist/governance/engine/spec-builder.d.ts +117 -0
  80. package/dist/governance/engine/spec-builder.js +321 -0
  81. package/dist/governance/engine/stage-runner.d.ts +22 -0
  82. package/dist/governance/engine/stage-runner.js +664 -0
  83. package/dist/governance/engine/start-input.d.ts +19 -0
  84. package/dist/governance/engine/start-input.js +111 -0
  85. package/dist/governance/engine/state-machine.d.ts +101 -0
  86. package/dist/governance/engine/state-machine.js +586 -0
  87. package/dist/governance/engine/submission-queries.d.ts +42 -0
  88. package/dist/governance/engine/submission-queries.js +97 -0
  89. package/dist/governance/engine/submission-render.d.ts +12 -0
  90. package/dist/governance/engine/submission-render.js +92 -0
  91. package/dist/governance/engine/submissions.d.ts +27 -0
  92. package/dist/governance/engine/submissions.js +455 -0
  93. package/dist/governance/engine/visibility.d.ts +104 -0
  94. package/dist/governance/engine/visibility.js +223 -0
  95. package/dist/governance/governed-dispatch.d.ts +19 -0
  96. package/dist/governance/governed-dispatch.js +17 -0
  97. package/dist/governance/limits.d.ts +107 -0
  98. package/dist/governance/limits.js +131 -0
  99. package/dist/governance/posture-transition.d.ts +38 -0
  100. package/dist/governance/posture-transition.js +44 -0
  101. package/dist/governance/posture.d.ts +35 -0
  102. package/dist/governance/posture.js +59 -0
  103. package/dist/governance/profiles.d.ts +48 -0
  104. package/dist/governance/profiles.js +140 -0
  105. package/dist/governance/prompts/orchestrator-block.d.ts +40 -0
  106. package/dist/governance/prompts/orchestrator-block.js +128 -0
  107. package/dist/governance/prompts/plan-addendum.d.ts +22 -0
  108. package/dist/governance/prompts/plan-addendum.js +60 -0
  109. package/dist/governance/prompts/refusals.d.ts +48 -0
  110. package/dist/governance/prompts/refusals.js +82 -0
  111. package/dist/governance/prompts/role-blocks.d.ts +40 -0
  112. package/dist/governance/prompts/role-blocks.js +255 -0
  113. package/dist/governance/report-reader.d.ts +31 -0
  114. package/dist/governance/report-reader.js +57 -0
  115. package/dist/governance/roles.d.ts +83 -0
  116. package/dist/governance/roles.js +142 -0
  117. package/dist/governance/rules/claims.d.ts +83 -0
  118. package/dist/governance/rules/claims.js +250 -0
  119. package/dist/governance/rules/elimination.d.ts +66 -0
  120. package/dist/governance/rules/elimination.js +105 -0
  121. package/dist/governance/rules/events-table.d.ts +46 -0
  122. package/dist/governance/rules/events-table.js +94 -0
  123. package/dist/governance/rules/failure-analysis.d.ts +28 -0
  124. package/dist/governance/rules/failure-analysis.js +93 -0
  125. package/dist/governance/rules/ledger-replay.d.ts +53 -0
  126. package/dist/governance/rules/ledger-replay.js +53 -0
  127. package/dist/governance/rules/ledger-state.d.ts +85 -0
  128. package/dist/governance/rules/ledger-state.js +175 -0
  129. package/dist/governance/rules/ledger.d.ts +228 -0
  130. package/dist/governance/rules/ledger.js +560 -0
  131. package/dist/governance/rules/rca.d.ts +68 -0
  132. package/dist/governance/rules/rca.js +220 -0
  133. package/dist/governance/rules/settlement.d.ts +129 -0
  134. package/dist/governance/rules/settlement.js +363 -0
  135. package/dist/governance/rules/suspicion.d.ts +66 -0
  136. package/dist/governance/rules/suspicion.js +169 -0
  137. package/dist/governance/store/artifacts.d.ts +81 -0
  138. package/dist/governance/store/artifacts.js +173 -0
  139. package/dist/governance/store/atomic.d.ts +79 -0
  140. package/dist/governance/store/atomic.js +119 -0
  141. package/dist/governance/store/events-log.d.ts +35 -0
  142. package/dist/governance/store/events-log.js +86 -0
  143. package/dist/governance/store/run-lock.d.ts +51 -0
  144. package/dist/governance/store/run-lock.js +122 -0
  145. package/dist/governance/store/run-store.d.ts +229 -0
  146. package/dist/governance/store/run-store.js +644 -0
  147. package/dist/governance/store/scoreboard-export.d.ts +53 -0
  148. package/dist/governance/store/scoreboard-export.js +65 -0
  149. package/dist/governance/tools/child-tools.d.ts +31 -0
  150. package/dist/governance/tools/child-tools.js +65 -0
  151. package/dist/governance/tools/guard.d.ts +71 -0
  152. package/dist/governance/tools/guard.js +194 -0
  153. package/dist/governance/tools/inspector-tools.d.ts +63 -0
  154. package/dist/governance/tools/inspector-tools.js +424 -0
  155. package/dist/governance/tools/lead-tools.d.ts +42 -0
  156. package/dist/governance/tools/lead-tools.js +226 -0
  157. package/dist/governance/tools/normalize-util.d.ts +101 -0
  158. package/dist/governance/tools/normalize-util.js +230 -0
  159. package/dist/governance/tools/scan-incomplete.d.ts +79 -0
  160. package/dist/governance/tools/scan-incomplete.js +486 -0
  161. package/dist/governance/tools/shared-tools.d.ts +44 -0
  162. package/dist/governance/tools/shared-tools.js +125 -0
  163. package/dist/governance/tools/submit-normalizers.d.ts +28 -0
  164. package/dist/governance/tools/submit-normalizers.js +474 -0
  165. package/dist/governance/tools/submit-tools.d.ts +26 -0
  166. package/dist/governance/tools/submit-tools.js +171 -0
  167. package/dist/governance/types.d.ts +661 -0
  168. package/dist/governance/types.js +27 -0
  169. package/dist/proc/kill-tree.d.ts +19 -1
  170. package/dist/proc/kill-tree.js +32 -5
  171. package/dist/proc/limits.d.ts +19 -0
  172. package/dist/proc/limits.js +19 -0
  173. package/dist/proc/supervisor.js +8 -1
  174. package/dist/session/validate-session.js +32 -1
  175. package/dist/team/runtime.d.ts +8 -0
  176. package/dist/team/runtime.js +9 -0
  177. package/dist/team/subagent.d.ts +23 -0
  178. package/dist/team/subagent.js +14 -3
  179. package/dist/team/types.d.ts +6 -0
  180. package/dist/tools/bounded-spawn.d.ts +56 -0
  181. package/dist/tools/bounded-spawn.js +76 -0
  182. package/dist/tools/index.d.ts +30 -7
  183. package/dist/tools/index.js +14 -0
  184. package/dist/tools/plan-tools.d.ts +14 -2
  185. package/dist/tools/plan-tools.js +5 -2
  186. package/dist/tools/search-tools.js +52 -44
  187. package/dist/ui/App.js +145 -25
  188. package/dist/ui/BottomStatusRow.js +1 -1
  189. package/dist/ui/Composer.d.ts +7 -1
  190. package/dist/ui/Composer.js +9 -6
  191. package/dist/ui/GovernancePanel.d.ts +50 -0
  192. package/dist/ui/GovernancePanel.js +77 -0
  193. package/dist/ui/GovernanceRun.d.ts +18 -0
  194. package/dist/ui/GovernanceRun.js +11 -0
  195. package/dist/ui/ScrollbackShell.d.ts +35 -7
  196. package/dist/ui/ScrollbackShell.js +1 -1
  197. package/dist/ui/StatusBar.d.ts +15 -2
  198. package/dist/ui/StatusBar.js +10 -4
  199. package/dist/ui/Transcript.js +3 -0
  200. package/dist/ui/entries/GovernanceCard.d.ts +30 -0
  201. package/dist/ui/entries/GovernanceCard.js +32 -0
  202. package/dist/ui/governance-copy.d.ts +69 -0
  203. package/dist/ui/governance-copy.js +104 -0
  204. package/dist/ui/governance-status.d.ts +145 -0
  205. package/dist/ui/governance-status.js +326 -0
  206. package/dist/ui/interaction-copy.d.ts +4 -0
  207. package/dist/ui/interaction-copy.js +5 -0
  208. package/dist/ui/interaction-hints.d.ts +17 -0
  209. package/dist/ui/interaction-hints.js +14 -2
  210. package/dist/ui/layout/governance-board.d.ts +121 -0
  211. package/dist/ui/layout/governance-board.js +382 -0
  212. package/dist/ui/layout/governance-card.d.ts +53 -0
  213. package/dist/ui/layout/governance-card.js +134 -0
  214. package/dist/ui/layout/governance-chip.d.ts +38 -0
  215. package/dist/ui/layout/governance-chip.js +64 -0
  216. package/dist/ui/layout/governance-panel.d.ts +85 -0
  217. package/dist/ui/layout/governance-panel.js +358 -0
  218. package/dist/ui/layout/governance-roster.d.ts +65 -0
  219. package/dist/ui/layout/governance-roster.js +275 -0
  220. package/dist/ui/layout/status-detail-layout.js +3 -3
  221. package/dist/ui/layout/status-layout.d.ts +5 -2
  222. package/dist/ui/layout/status-layout.js +10 -6
  223. package/dist/ui/layout/virtual-window.js +11 -0
  224. package/dist/ui/overlays/GovernanceBoardOverlay.d.ts +41 -0
  225. package/dist/ui/overlays/GovernanceBoardOverlay.js +76 -0
  226. package/dist/ui/overlays/GovernanceSettingsPage.d.ts +48 -0
  227. package/dist/ui/overlays/GovernanceSettingsPage.js +93 -0
  228. package/dist/ui/overlays/HelpOverlay.js +4 -3
  229. package/dist/ui/overlays/QuestionOverlay.d.ts +9 -1
  230. package/dist/ui/overlays/QuestionOverlay.js +4 -2
  231. package/dist/ui/overlays/SettingsScreen.d.ts +7 -0
  232. package/dist/ui/overlays/SettingsScreen.js +21 -1
  233. package/dist/ui/overlays/governance-settings.d.ts +79 -0
  234. package/dist/ui/overlays/governance-settings.js +140 -0
  235. package/dist/ui/overlays/model-profile-state.d.ts +6 -1
  236. package/dist/ui/overlays/model-profile-state.js +10 -0
  237. package/dist/ui/palettes.d.ts +17 -0
  238. package/dist/ui/palettes.js +9 -0
  239. package/dist/ui/scrollback/LiveTail.d.ts +3 -1
  240. package/dist/ui/scrollback/budget.d.ts +12 -6
  241. package/dist/ui/scrollback/budget.js +11 -4
  242. package/dist/ui/scrollback/live-preview.js +2 -0
  243. package/dist/ui/scrollback/settled-boundary.js +3 -0
  244. package/dist/ui/scrollback/tail-anchor.d.ts +5 -2
  245. package/dist/ui/scrollback/tail-anchor.js +3 -1
  246. package/dist/ui/shortcuts.js +2 -2
  247. package/dist/ui/theme.d.ts +7 -0
  248. package/dist/ui/theme.js +1 -0
  249. package/dist/ui/transcript-text.js +9 -0
  250. package/dist/ui/use-wheel-routing.js +3 -1
  251. package/package.json +2 -2
@@ -0,0 +1,65 @@
1
+ /**
2
+ * One-way export of the ledger in the `token_ledger.py` v2.0 field layout
3
+ * (governance-mode section 12.3).
4
+ *
5
+ * ASCII ONLY (`governance/` is glyph-scanned).
6
+ *
7
+ * The point is that a user can point the reference skill's scripts at
8
+ * `scoreboard.json` for ad-hoc analysis. It is NEVER read back: the ledger of record is
9
+ * `events.jsonl` (+ `ledger.json`), and a second readable copy would be a second source
10
+ * of truth that could drift. Python's vocabulary only knows `provisional` and
11
+ * `confirmed` as history statuses, so `immediate` positives (which land in `confirmed`,
12
+ * RV-9) are exported as `confirmed`.
13
+ */
14
+ export const SCOREBOARD_VERSION = '2.0';
15
+ function iso(ms) {
16
+ return new Date(ms).toISOString();
17
+ }
18
+ function historyRow(entry) {
19
+ return {
20
+ event: entry.code,
21
+ delta: entry.delta,
22
+ status: entry.settlement === 'provisional' ? 'provisional' : 'confirmed',
23
+ balance_after: entry.confirmedAfter + entry.provisionalAfter,
24
+ confirmed_after: entry.confirmedAfter,
25
+ provisional_after: entry.provisionalAfter,
26
+ reason: entry.reason,
27
+ timestamp: iso(entry.at),
28
+ };
29
+ }
30
+ function escrowRow(entry) {
31
+ const actionMap = { held: 'hold', released: 'confirm', clawed_back: 'clawback' };
32
+ return {
33
+ action: actionMap[entry.action],
34
+ phase: entry.phase,
35
+ delta: entry.action === 'clawed_back' ? -entry.amount : entry.amount,
36
+ reason: entry.reason,
37
+ timestamp: iso(entry.at),
38
+ };
39
+ }
40
+ function agentRow(record) {
41
+ return {
42
+ role: record.role,
43
+ generation: record.generation,
44
+ tokens: record.confirmed + record.provisional,
45
+ tokens_confirmed: record.confirmed,
46
+ tokens_provisional: record.provisional,
47
+ status: record.status,
48
+ replaced_by: record.replacedBy,
49
+ history: record.history.map(historyRow),
50
+ escrow_history: record.escrowHistory.map(escrowRow),
51
+ };
52
+ }
53
+ /** Build the export document. Pure: `now` is injected so the output is reproducible. */
54
+ export function buildScoreboard(ledger, now) {
55
+ const agents = {};
56
+ for (const [id, record] of Object.entries(ledger.agents))
57
+ agents[id] = agentRow(record);
58
+ return {
59
+ version: SCOREBOARD_VERSION,
60
+ generated_by: 'aragon-governance',
61
+ generated_at: iso(now),
62
+ agents,
63
+ phase_reports: [],
64
+ };
65
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The governance tool array of one governed child, by role (governance-mode 5.1, 7.3).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * THE ROLE DECIDES THE TOOLS, AND THE TOOLS DECIDE THE POWERS:
7
+ *
8
+ * - DEV / FIX: submit work, read, standings, view. No scan (the developer is the one being
9
+ * scanned) and no review or ledger tool.
10
+ * - REV: submit review, scan, read, standings, view.
11
+ * - TEST: submit test, scan, read, standings, view.
12
+ * - INSP: the three ledger tools, read, scan, standings. No submit tools and no `gov_view`
13
+ * (its read access has no restriction to ask around).
14
+ *
15
+ * Nothing here can write the ledger except the inspector tools (I-G1): the submit tools hand
16
+ * structured data to the engine, which books it. This function returns ONLY governance
17
+ * tools; the caller appends them to the child's built-in tools and, for the inspector,
18
+ * passes the built-ins through `applyInspectorToolPolicy`.
19
+ */
20
+ import type { AgentTool } from '@aragon-agent/core';
21
+ import type { GovRole, GovernanceEngineApi, Identity } from '../types.js';
22
+ import { type ScanToolContext } from './scan-incomplete.js';
23
+ /** What a child's tools need from the host. Read live, never cached. */
24
+ export type ChildToolContext = ScanToolContext;
25
+ /**
26
+ * Build the governance tools for `identity` in `role`.
27
+ *
28
+ * `identity.role` is not consulted: the caller states the role explicitly so a mismatched
29
+ * pair fails a test instead of silently handing out the wrong powers.
30
+ */
31
+ export declare function buildChildTools(role: GovRole, engine: GovernanceEngineApi, identity: Identity, ctx: ChildToolContext): AgentTool[];
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The governance tool array of one governed child, by role (governance-mode 5.1, 7.3).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * THE ROLE DECIDES THE TOOLS, AND THE TOOLS DECIDE THE POWERS:
7
+ *
8
+ * - DEV / FIX: submit work, read, standings, view. No scan (the developer is the one being
9
+ * scanned) and no review or ledger tool.
10
+ * - REV: submit review, scan, read, standings, view.
11
+ * - TEST: submit test, scan, read, standings, view.
12
+ * - INSP: the three ledger tools, read, scan, standings. No submit tools and no `gov_view`
13
+ * (its read access has no restriction to ask around).
14
+ *
15
+ * Nothing here can write the ledger except the inspector tools (I-G1): the submit tools hand
16
+ * structured data to the engine, which books it. This function returns ONLY governance
17
+ * tools; the caller appends them to the child's built-in tools and, for the inspector,
18
+ * passes the built-ins through `applyInspectorToolPolicy`.
19
+ */
20
+ import { makeLedgerApplyTool, makeLedgerRuleTool, makeLedgerSettleTool, } from './inspector-tools.js';
21
+ import { makeScanTool } from './scan-incomplete.js';
22
+ import { makeReadTool, makeStandingsTool, makeViewTool } from './shared-tools.js';
23
+ import { makeSubmitReviewTool, makeSubmitTestTool, makeSubmitWorkTool, } from './submit-tools.js';
24
+ /**
25
+ * Build the governance tools for `identity` in `role`.
26
+ *
27
+ * `identity.role` is not consulted: the caller states the role explicitly so a mismatched
28
+ * pair fails a test instead of silently handing out the wrong powers.
29
+ */
30
+ export function buildChildTools(role, engine, identity, ctx) {
31
+ switch (role) {
32
+ case 'DEV':
33
+ return [
34
+ makeSubmitWorkTool(engine, identity),
35
+ makeReadTool(engine, identity),
36
+ makeStandingsTool(engine),
37
+ makeViewTool(engine, identity),
38
+ ];
39
+ case 'REV':
40
+ return [
41
+ makeSubmitReviewTool(engine, identity),
42
+ makeScanTool(ctx),
43
+ makeReadTool(engine, identity),
44
+ makeStandingsTool(engine),
45
+ makeViewTool(engine, identity),
46
+ ];
47
+ case 'TEST':
48
+ return [
49
+ makeSubmitTestTool(engine, identity),
50
+ makeScanTool(ctx),
51
+ makeReadTool(engine, identity),
52
+ makeStandingsTool(engine),
53
+ makeViewTool(engine, identity),
54
+ ];
55
+ case 'INSP':
56
+ return [
57
+ makeLedgerApplyTool(engine),
58
+ makeLedgerRuleTool(engine),
59
+ makeLedgerSettleTool(engine),
60
+ makeReadTool(engine, identity),
61
+ makeScanTool(ctx),
62
+ makeStandingsTool(engine),
63
+ ];
64
+ }
65
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Tool wrappers that enforce the governance boundaries (governance-mode 7.4, D-2, D-6).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * THREE WRAPPERS, THREE DIFFERENT STRENGTHS - and the difference is the point:
7
+ *
8
+ * - `withGovernanceGate` is a HARD gate on the Orchestrator's tool calls (D-2): the lead
9
+ * cannot change the workspace, whatever the prompt says. It is a property of the tool
10
+ * layer, not a request.
11
+ * - `applyInspectorToolPolicy` removes the inspector's write tools and narrows its shell to
12
+ * the registered integration commands.
13
+ * - `withGovernanceReadGuard` is a TRIPWIRE, not a security boundary (D-6). The shell cannot
14
+ * be fully confined, so a child that has been told nothing about the governance store's
15
+ * location and that is refused when a call mentions it is a speed bump for a model that
16
+ * stumbles into it, nothing more. Do not cite it as a security control anywhere.
17
+ */
18
+ import { type AgentTool } from '@aragon-agent/core';
19
+ import type { AgentMode } from '../../agent/agent-mode.js';
20
+ /** What the gate reads on EVERY call. Never captured: `/gov off` and Shift+Tab flip both. */
21
+ export interface GovernanceGateState {
22
+ governOn: boolean;
23
+ mode: AgentMode;
24
+ }
25
+ /**
26
+ * Wrap one lead tool with the governance gate.
27
+ *
28
+ * Tools the gate has no opinion on are returned UNCHANGED (same object), so the wrapped
29
+ * array differs from the input only where the gate can act, and a hot read-only tool pays
30
+ * no extra frame.
31
+ *
32
+ * Decision table (state is read live, per call):
33
+ * - `write_file / edit_file / bash / bash_kill / skill_install / skill_create`: refused
34
+ * whenever governance is on, in either gate mode (plan mode refuses them too; the plan
35
+ * gate is the outer wrapper and speaks first).
36
+ * - `task`: refused only when governance is on AND the mode is `build`. In the PLAN+GOVERN
37
+ * planning phase it stays available for read-only research (6.1).
38
+ * - `gov_run / gov_dispatch`: refused with the off text when governance is off, and with
39
+ * the plan-phase text when the mode is `plan`.
40
+ *
41
+ * Refusals of the refused-tool set are `errorResult` (the plan gate's convention: a refused
42
+ * tool did not run); the gov-tool refusals are plain text (a retry cannot help).
43
+ */
44
+ export declare function withGovernanceGate(tool: AgentTool, getState: () => GovernanceGateState): AgentTool;
45
+ export interface InspectorPolicyOptions {
46
+ /** The commands the orchestrator registered at `start`. Empty = the inspector has no bash. */
47
+ integrationCommands: readonly string[];
48
+ }
49
+ /** True when `command` is exactly a registered command or extends one at a word boundary. */
50
+ export declare function isAllowedIntegrationCommand(command: string, registered: readonly string[]): boolean;
51
+ /**
52
+ * The inspector's tool array: write tools removed; `bash` replaced by the restricted shell
53
+ * (or dropped when no integration command is registered - the inspector then verifies
54
+ * statically and says so in its report).
55
+ *
56
+ * It is NOT done with `spec.readOnly`: that would route the child through the plan gate,
57
+ * which refuses `bash` in full ("a shell string cannot be classified"), and the inspector
58
+ * could not run the integration suite at all (5.1).
59
+ */
60
+ export declare function applyInspectorToolPolicy(tools: readonly AgentTool[], options: InspectorPolicyOptions): AgentTool[];
61
+ /**
62
+ * Refuse a read-class tool call whose arguments mention the governance root.
63
+ *
64
+ * A TRIPWIRE (D-6). Defeating it needs a path the model was never given, spelled in a form
65
+ * the substring test misses (a symlink, an environment variable, a relative hop). It exists
66
+ * to stop the accidental read and to make the deliberate one a conscious act that the
67
+ * refusal text names.
68
+ *
69
+ * An empty `governanceRoot` returns the tool unchanged: `''.includes` would match every call.
70
+ */
71
+ export declare function withGovernanceReadGuard(tool: AgentTool, governanceRoot: string): AgentTool;
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Tool wrappers that enforce the governance boundaries (governance-mode 7.4, D-2, D-6).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * THREE WRAPPERS, THREE DIFFERENT STRENGTHS - and the difference is the point:
7
+ *
8
+ * - `withGovernanceGate` is a HARD gate on the Orchestrator's tool calls (D-2): the lead
9
+ * cannot change the workspace, whatever the prompt says. It is a property of the tool
10
+ * layer, not a request.
11
+ * - `applyInspectorToolPolicy` removes the inspector's write tools and narrows its shell to
12
+ * the registered integration commands.
13
+ * - `withGovernanceReadGuard` is a TRIPWIRE, not a security boundary (D-6). The shell cannot
14
+ * be fully confined, so a child that has been told nothing about the governance store's
15
+ * location and that is refused when a call mentions it is a speed bump for a model that
16
+ * stumbles into it, nothing more. Do not cite it as a security control anywhere.
17
+ */
18
+ import { errorResult, textResult } from '@aragon-agent/core';
19
+ import { GOV_LEAD_TOOL_NAMES, GOVERN_ORCHESTRATOR_REFUSED_TOOLS } from '../limits.js';
20
+ import { govOffRefusal, govPlanPhaseRefusal, governRefusal } from '../prompts/refusals.js';
21
+ const REFUSED_TOOLS = new Set(GOVERN_ORCHESTRATOR_REFUSED_TOOLS);
22
+ /**
23
+ * Wrap one lead tool with the governance gate.
24
+ *
25
+ * Tools the gate has no opinion on are returned UNCHANGED (same object), so the wrapped
26
+ * array differs from the input only where the gate can act, and a hot read-only tool pays
27
+ * no extra frame.
28
+ *
29
+ * Decision table (state is read live, per call):
30
+ * - `write_file / edit_file / bash / bash_kill / skill_install / skill_create`: refused
31
+ * whenever governance is on, in either gate mode (plan mode refuses them too; the plan
32
+ * gate is the outer wrapper and speaks first).
33
+ * - `task`: refused only when governance is on AND the mode is `build`. In the PLAN+GOVERN
34
+ * planning phase it stays available for read-only research (6.1).
35
+ * - `gov_run / gov_dispatch`: refused with the off text when governance is off, and with
36
+ * the plan-phase text when the mode is `plan`.
37
+ *
38
+ * Refusals of the refused-tool set are `errorResult` (the plan gate's convention: a refused
39
+ * tool did not run); the gov-tool refusals are plain text (a retry cannot help).
40
+ */
41
+ export function withGovernanceGate(tool, getState) {
42
+ const refusable = REFUSED_TOOLS.has(tool.name);
43
+ const isGovTool = GOV_LEAD_TOOL_NAMES.has(tool.name);
44
+ if (!refusable && !isGovTool)
45
+ return tool;
46
+ const original = tool.execute;
47
+ return {
48
+ ...tool,
49
+ async execute(id, params, ctx) {
50
+ const { governOn, mode } = getState();
51
+ if (isGovTool) {
52
+ if (!governOn)
53
+ return textResult(govOffRefusal());
54
+ if (mode === 'plan')
55
+ return textResult(govPlanPhaseRefusal());
56
+ }
57
+ else if (governOn && (tool.name !== 'task' || mode === 'build')) {
58
+ return errorResult(governRefusal(tool.name));
59
+ }
60
+ return original(id, params, ctx);
61
+ },
62
+ };
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // Inspector tool policy
66
+ // ---------------------------------------------------------------------------
67
+ /** Tools the inspector never receives: it audits, it does not change the workspace. */
68
+ const INSPECTOR_REMOVED_TOOLS = new Set([
69
+ 'write_file',
70
+ 'edit_file',
71
+ 'skill_install',
72
+ 'skill_create',
73
+ 'bash_kill',
74
+ ]);
75
+ /**
76
+ * Shell metacharacters that would let an allowed prefix carry a second command
77
+ * (`npm test; curl ...`, `npm test && rm -rf`, `npm test $(...)`). The registered command
78
+ * may itself contain any of them (an exact match is always allowed); only the SUFFIX the
79
+ * inspector appends is screened. Stricter than the spec's "word-boundary prefix", on
80
+ * purpose: a prefix rule alone is a shell with extra steps.
81
+ */
82
+ const SHELL_CONTROL_CHARS = /[;&|<>`\r\n]|\$\(/;
83
+ /** True when `command` is exactly a registered command or extends one at a word boundary. */
84
+ export function isAllowedIntegrationCommand(command, registered) {
85
+ const candidate = command.trim();
86
+ if (candidate === '')
87
+ return false;
88
+ return registered.some((raw) => {
89
+ const base = raw.trim();
90
+ if (base === '')
91
+ return false;
92
+ if (candidate === base)
93
+ return true;
94
+ if (!candidate.startsWith(base))
95
+ return false;
96
+ const rest = candidate.slice(base.length);
97
+ return /^\s/.test(rest) && !SHELL_CONTROL_CHARS.test(rest);
98
+ });
99
+ }
100
+ function restrictBash(bash, registered) {
101
+ const original = bash.execute;
102
+ const listing = registered.join('; ');
103
+ return {
104
+ ...bash,
105
+ description: `${bash.description} RESTRICTED: only the registered integration commands may run ` +
106
+ `(${listing}); anything else is refused.`,
107
+ async execute(id, params, ctx) {
108
+ const command = params.command;
109
+ if (typeof command !== 'string' || !isAllowedIntegrationCommand(command, registered)) {
110
+ return textResult('NOT ACCEPTED: the inspector may only run the registered integration commands: ' +
111
+ `${listing}`);
112
+ }
113
+ return original(id, params, ctx);
114
+ },
115
+ };
116
+ }
117
+ /**
118
+ * The inspector's tool array: write tools removed; `bash` replaced by the restricted shell
119
+ * (or dropped when no integration command is registered - the inspector then verifies
120
+ * statically and says so in its report).
121
+ *
122
+ * It is NOT done with `spec.readOnly`: that would route the child through the plan gate,
123
+ * which refuses `bash` in full ("a shell string cannot be classified"), and the inspector
124
+ * could not run the integration suite at all (5.1).
125
+ */
126
+ export function applyInspectorToolPolicy(tools, options) {
127
+ const registered = options.integrationCommands.map((c) => c.trim()).filter((c) => c !== '');
128
+ const out = [];
129
+ for (const tool of tools) {
130
+ if (INSPECTOR_REMOVED_TOOLS.has(tool.name))
131
+ continue;
132
+ if (tool.name === 'bash') {
133
+ if (registered.length > 0)
134
+ out.push(restrictBash(tool, registered));
135
+ continue;
136
+ }
137
+ out.push(tool);
138
+ }
139
+ return out;
140
+ }
141
+ // ---------------------------------------------------------------------------
142
+ // Governance-store read tripwire
143
+ // ---------------------------------------------------------------------------
144
+ const READ_GUARDED_TOOLS = new Set([
145
+ 'read_file',
146
+ 'list_dir',
147
+ 'glob',
148
+ 'grep',
149
+ 'bash',
150
+ ]);
151
+ const STORE_REFUSAL = 'NOT ACCEPTED: the governance store is not readable from here; use gov_read';
152
+ /** Forward-slash, lower-case form used ONLY for the substring comparison. */
153
+ function comparable(text) {
154
+ return text.replace(/\\/g, '/').toLowerCase();
155
+ }
156
+ /** Every string anywhere in `value`, depth-bounded so a hostile argument cannot blow up. */
157
+ function collectStrings(value, out, depth = 0) {
158
+ if (typeof value === 'string')
159
+ out.push(value);
160
+ else if (depth < 4 && Array.isArray(value)) {
161
+ for (const item of value)
162
+ collectStrings(item, out, depth + 1);
163
+ }
164
+ else if (depth < 4 && value !== null && typeof value === 'object') {
165
+ for (const item of Object.values(value))
166
+ collectStrings(item, out, depth + 1);
167
+ }
168
+ }
169
+ /**
170
+ * Refuse a read-class tool call whose arguments mention the governance root.
171
+ *
172
+ * A TRIPWIRE (D-6). Defeating it needs a path the model was never given, spelled in a form
173
+ * the substring test misses (a symlink, an environment variable, a relative hop). It exists
174
+ * to stop the accidental read and to make the deliberate one a conscious act that the
175
+ * refusal text names.
176
+ *
177
+ * An empty `governanceRoot` returns the tool unchanged: `''.includes` would match every call.
178
+ */
179
+ export function withGovernanceReadGuard(tool, governanceRoot) {
180
+ const root = comparable(governanceRoot).replace(/\/+$/, '');
181
+ if (root === '' || !READ_GUARDED_TOOLS.has(tool.name))
182
+ return tool;
183
+ const original = tool.execute;
184
+ return {
185
+ ...tool,
186
+ async execute(id, params, ctx) {
187
+ const strings = [];
188
+ collectStrings(params, strings);
189
+ if (strings.some((s) => comparable(s).includes(root)))
190
+ return textResult(STORE_REFUSAL);
191
+ return original(id, params, ctx);
192
+ },
193
+ };
194
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The Inspector's ledger tools: `ledger_apply`, `ledger_rule`, `ledger_settle`
3
+ * (governance-mode 5.4, 5.6, 5.7, 7.3).
4
+ *
5
+ * ASCII ONLY (`governance/` is glyph-scanned).
6
+ *
7
+ * THE INSPECTOR BOOKS JUDGEMENT, NOT MECHANICS (D-4). The rule engine books every
8
+ * mechanical event by itself; `ledger_apply` accepts ONLY the codes whose bookers include
9
+ * `S` (`isInspectorBookable`), and answers any other code with "this event is handled by
10
+ * the engine". That is what removes a whole class of failure: an LLM inspector that forgets
11
+ * to book, books twice, or invents an amount. Amounts never come from the model - the
12
+ * catalogue row supplies the delta.
13
+ *
14
+ * EVIDENCE OR NO EVENT. A judgement event needs concrete evidence (files, lines, quotes) of
15
+ * at least `GOV_LIMITS.evidenceMinChars`; the check also rejects filler such as one repeated
16
+ * character, which would satisfy a bare length test.
17
+ *
18
+ * THE INSPECTOR IS NOT SCORED (I-G5). A target of `insp` is refused here, before the
19
+ * engine, and the engine refuses it again (defence in depth for a rule the whole fairness
20
+ * argument rests on).
21
+ *
22
+ * THE TARGET'S ROLE MUST MATCH THE EVENT'S. `D6` is a developer event; booking it against
23
+ * `rev1` is a typo or a hallucination, and a ledger that accepts it is wrong silently.
24
+ */
25
+ import { type AgentTool } from '@aragon-agent/core';
26
+ import { type EventCode } from '../rules/events-table.js';
27
+ import type { GovernanceEngineApi, InspectorReport, RcaInput } from '../types.js';
28
+ import { type Normalized } from './normalize-util.js';
29
+ export interface LedgerApplyInput {
30
+ code: EventCode;
31
+ agentId: string;
32
+ wpId?: string;
33
+ reason: string;
34
+ evidence: string;
35
+ incidentId?: string;
36
+ }
37
+ export interface LedgerRuleInput {
38
+ claimId: string;
39
+ decision: 'upheld' | 'rejected';
40
+ ruling: string;
41
+ }
42
+ /** `ledger_settle` arguments. `kind` is the tool's name for the report's `stage`. */
43
+ export interface LedgerSettleInput {
44
+ kind: InspectorReport['stage'];
45
+ phase: number;
46
+ summary: string;
47
+ contractChecks: InspectorReport['contractChecks'];
48
+ integration?: NonNullable<InspectorReport['integration']>;
49
+ rca?: RcaInput;
50
+ escalations: InspectorReport['escalations'];
51
+ }
52
+ /** Validate a `ledger_apply` argument object. Pure; the engine may reuse it. */
53
+ export declare function normalizeLedgerApply(raw: unknown): Normalized<LedgerApplyInput>;
54
+ /** Validate a `ledger_rule` argument object. Pure. */
55
+ export declare function normalizeLedgerRule(raw: unknown): Normalized<LedgerRuleInput>;
56
+ /** Validate a `ledger_settle` argument object. Pure. */
57
+ export declare function normalizeLedgerSettle(raw: unknown): Normalized<LedgerSettleInput>;
58
+ /** `ledger_apply`: INSP only. */
59
+ export declare function makeLedgerApplyTool(engine: GovernanceEngineApi): AgentTool;
60
+ /** `ledger_rule`: INSP only. */
61
+ export declare function makeLedgerRuleTool(engine: GovernanceEngineApi): AgentTool;
62
+ /** `ledger_settle`: INSP only. The stage ends with this call. */
63
+ export declare function makeLedgerSettleTool(engine: GovernanceEngineApi): AgentTool;