@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.
Files changed (236) 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/session/validate-session.js +32 -1
  170. package/dist/team/runtime.d.ts +8 -0
  171. package/dist/team/runtime.js +9 -0
  172. package/dist/team/subagent.d.ts +23 -0
  173. package/dist/team/subagent.js +14 -3
  174. package/dist/team/types.d.ts +6 -0
  175. package/dist/tools/index.d.ts +30 -7
  176. package/dist/tools/index.js +14 -0
  177. package/dist/tools/plan-tools.d.ts +14 -2
  178. package/dist/tools/plan-tools.js +5 -2
  179. package/dist/ui/App.js +145 -25
  180. package/dist/ui/BottomStatusRow.js +1 -1
  181. package/dist/ui/Composer.d.ts +7 -1
  182. package/dist/ui/Composer.js +9 -6
  183. package/dist/ui/GovernancePanel.d.ts +50 -0
  184. package/dist/ui/GovernancePanel.js +77 -0
  185. package/dist/ui/GovernanceRun.d.ts +18 -0
  186. package/dist/ui/GovernanceRun.js +11 -0
  187. package/dist/ui/StatusBar.d.ts +15 -2
  188. package/dist/ui/StatusBar.js +10 -4
  189. package/dist/ui/Transcript.js +3 -0
  190. package/dist/ui/entries/GovernanceCard.d.ts +30 -0
  191. package/dist/ui/entries/GovernanceCard.js +32 -0
  192. package/dist/ui/governance-copy.d.ts +69 -0
  193. package/dist/ui/governance-copy.js +104 -0
  194. package/dist/ui/governance-status.d.ts +145 -0
  195. package/dist/ui/governance-status.js +326 -0
  196. package/dist/ui/interaction-copy.d.ts +4 -0
  197. package/dist/ui/interaction-copy.js +5 -0
  198. package/dist/ui/interaction-hints.d.ts +17 -0
  199. package/dist/ui/interaction-hints.js +14 -2
  200. package/dist/ui/layout/governance-board.d.ts +121 -0
  201. package/dist/ui/layout/governance-board.js +382 -0
  202. package/dist/ui/layout/governance-card.d.ts +53 -0
  203. package/dist/ui/layout/governance-card.js +134 -0
  204. package/dist/ui/layout/governance-chip.d.ts +38 -0
  205. package/dist/ui/layout/governance-chip.js +64 -0
  206. package/dist/ui/layout/governance-panel.d.ts +85 -0
  207. package/dist/ui/layout/governance-panel.js +358 -0
  208. package/dist/ui/layout/governance-roster.d.ts +65 -0
  209. package/dist/ui/layout/governance-roster.js +275 -0
  210. package/dist/ui/layout/status-detail-layout.js +3 -3
  211. package/dist/ui/layout/status-layout.d.ts +5 -2
  212. package/dist/ui/layout/status-layout.js +10 -6
  213. package/dist/ui/layout/virtual-window.js +11 -0
  214. package/dist/ui/overlays/GovernanceBoardOverlay.d.ts +41 -0
  215. package/dist/ui/overlays/GovernanceBoardOverlay.js +76 -0
  216. package/dist/ui/overlays/GovernanceSettingsPage.d.ts +48 -0
  217. package/dist/ui/overlays/GovernanceSettingsPage.js +93 -0
  218. package/dist/ui/overlays/HelpOverlay.js +4 -3
  219. package/dist/ui/overlays/QuestionOverlay.d.ts +9 -1
  220. package/dist/ui/overlays/QuestionOverlay.js +4 -2
  221. package/dist/ui/overlays/SettingsScreen.d.ts +7 -0
  222. package/dist/ui/overlays/SettingsScreen.js +21 -1
  223. package/dist/ui/overlays/governance-settings.d.ts +79 -0
  224. package/dist/ui/overlays/governance-settings.js +140 -0
  225. package/dist/ui/overlays/model-profile-state.d.ts +6 -1
  226. package/dist/ui/overlays/model-profile-state.js +10 -0
  227. package/dist/ui/palettes.d.ts +17 -0
  228. package/dist/ui/palettes.js +9 -0
  229. package/dist/ui/scrollback/live-preview.js +2 -0
  230. package/dist/ui/scrollback/settled-boundary.js +3 -0
  231. package/dist/ui/shortcuts.js +2 -2
  232. package/dist/ui/theme.d.ts +7 -0
  233. package/dist/ui/theme.js +1 -0
  234. package/dist/ui/transcript-text.js +9 -0
  235. package/dist/ui/use-wheel-routing.js +3 -1
  236. package/package.json +2 -2
@@ -0,0 +1,314 @@
1
+ /**
2
+ * GovernanceEngine - the facade the tools, the wiring and the UI call
3
+ * (governance-mode 14.1).
4
+ *
5
+ * ASCII ONLY (`governance/` is glyph-scanned).
6
+ *
7
+ * Thin on purpose: the work lives in `lifecycle.ts` (run state), `stage-runner.ts`
8
+ * (dispatch), `submissions.ts` / `inspector.ts` (what children submit) and `engine-core.ts`
9
+ * (state, persistence, events). This class composes them and adds the read-side child
10
+ * entry points (`gov_read`, `gov_view`, `ledger_standings`, scan) that need nothing but the
11
+ * visibility matrix and the submission cache.
12
+ *
13
+ * NOTHING HERE THROWS TO THE MODEL. Every entry point converts an unexpected failure into a
14
+ * `NOT ACCEPTED: internal error` result: a thrown exception inside a tool call becomes an
15
+ * error result that invites an identical retry, and a governed run has no way to explain
16
+ * "the engine crashed" to a child in any other voice.
17
+ */
18
+ import { getLogger } from '../../logging/logger.js';
19
+ import { scanPaths, formatScanReport } from '../tools/scan-incomplete.js';
20
+ import { GOV_LIMITS } from '../limits.js';
21
+ import { findingsForFile } from './visibility.js';
22
+ import { accessFor, decideView, formatPage, formatReadableList, listReadable, pageText, } from './visibility.js';
23
+ import { parseArtifactId } from '../store/artifacts.js';
24
+ import { EngineCore } from './engine-core.js';
25
+ import { currentDisplayPhase } from './engine-core.js';
26
+ import { handleInspectorApply, handleInspectorRule, handleInspectorSettle } from './inspector.js';
27
+ import { abandonRun, closeRun, resolveEscalation, resumeRun, startRun, statusText, } from './lifecycle.js';
28
+ import { cancelPause, requestPause } from './pause.js';
29
+ import { renderStandings } from './report.js';
30
+ import { runStage } from './stage-runner.js';
31
+ import { handleSubmitReview, handleSubmitTest, handleSubmitWork } from './submissions.js';
32
+ import { isRecord } from '../tools/normalize-util.js';
33
+ const FILE_LIKE = /[\w./\\-]+\.[A-Za-z0-9]{1,8}/g;
34
+ function internalError(where, error) {
35
+ const message = error instanceof Error ? error.message : String(error);
36
+ getLogger().warn('agent', 'governance.engine.internal_error', {
37
+ where,
38
+ error: message.slice(0, 300),
39
+ });
40
+ return (`NOT ACCEPTED: internal error in ${where} (${message.slice(0, 160)}). ` +
41
+ 'Nothing was recorded and no GT was deducted; retry once, then tell the orchestrator.');
42
+ }
43
+ function viewerOf(identity) {
44
+ return identity.role;
45
+ }
46
+ /** Text a viewer gets for one artifact at access level `access`. */
47
+ function renderForAccess(item, access, markdown) {
48
+ switch (access) {
49
+ case 'full':
50
+ return markdown;
51
+ case 'summary': {
52
+ const summary = 'summary' in item && typeof item.summary === 'string' ? item.summary : '';
53
+ return summary !== '' ? `Summary only: ${summary}` : 'Summary only: (none recorded)';
54
+ }
55
+ case 'verdict': {
56
+ const verdict = 'verdict' in item ? String(item.verdict) : 'n/a';
57
+ return `Conclusion only: ${verdict}`;
58
+ }
59
+ case 'changes': {
60
+ const files = 'filesChanged' in item ? item.filesChanged : [];
61
+ return `Files changed: ${files.join(', ') || '(none)'}`;
62
+ }
63
+ case 'none':
64
+ return '';
65
+ }
66
+ }
67
+ export class GovernanceEngine {
68
+ core;
69
+ constructor(deps) {
70
+ this.core = new EngineCore(deps);
71
+ }
72
+ /** Exposed for tests and the wiring's persistence helpers; not part of the tool surface. */
73
+ get internals() {
74
+ return this.core;
75
+ }
76
+ // ---------------------------------------------------------------------------
77
+ // Orchestrator surface (async, flushed)
78
+ // ---------------------------------------------------------------------------
79
+ async start(input, signal) {
80
+ return this.guard('start', () => startRun(this.core, input, signal));
81
+ }
82
+ status() {
83
+ try {
84
+ return statusText(this.core);
85
+ }
86
+ catch (error) {
87
+ return internalError('status', error);
88
+ }
89
+ }
90
+ async resume(runId) {
91
+ return this.guard('resume', () => resumeRun(this.core, runId));
92
+ }
93
+ async dispatchStage(input, signal) {
94
+ return this.guard('dispatch', () => runStage(this.core, input, signal));
95
+ }
96
+ async close(summary) {
97
+ return this.guard('close', () => closeRun(this.core, summary));
98
+ }
99
+ async abandon(reason) {
100
+ return this.guard('abandon', () => abandonRun(this.core, reason));
101
+ }
102
+ async resolve(input) {
103
+ return this.guard('resolve', () => resolveEscalation(this.core, input));
104
+ }
105
+ async guard(where, fn) {
106
+ try {
107
+ return await fn();
108
+ }
109
+ catch (error) {
110
+ return internalError(where, error);
111
+ }
112
+ }
113
+ // ---------------------------------------------------------------------------
114
+ // UI / wiring surface
115
+ // ---------------------------------------------------------------------------
116
+ snapshot() {
117
+ return this.core.snapshot();
118
+ }
119
+ isStageRunning() {
120
+ return this.core.isStageRunning();
121
+ }
122
+ abortStage() {
123
+ this.core.abortStage();
124
+ }
125
+ /**
126
+ * `/gov pause`: stop at the next clean boundary (governance-mode-v1-1 6). A human
127
+ * decision, so it is NOT on `GovernanceEngineApi` and no tool can reach it.
128
+ */
129
+ requestPause() {
130
+ return requestPause(this.core);
131
+ }
132
+ /** `/gov pause cancel`: true when a pending request was withdrawn. */
133
+ cancelPause() {
134
+ return cancelPause(this.core);
135
+ }
136
+ subscribe(listener) {
137
+ return this.core.subscribe(listener);
138
+ }
139
+ /**
140
+ * Stop timers and release the run lock WITHOUT closing the run: quitting the CLI leaves
141
+ * the run resumable (D-12), exactly as an Esc does.
142
+ */
143
+ dispose() {
144
+ const runId = this.core.run?.runId;
145
+ if (this.core.isStageRunning())
146
+ this.core.abortStage();
147
+ if (runId !== undefined) {
148
+ this.core.deps.store.stopHeartbeat(runId);
149
+ void this.core.deps.store.releaseLock(runId).catch(() => undefined);
150
+ }
151
+ this.core.dispose();
152
+ }
153
+ // ---------------------------------------------------------------------------
154
+ // Child entry points (synchronous: a tool call cannot wait on the disk)
155
+ // ---------------------------------------------------------------------------
156
+ submitWork(identity, input) {
157
+ return this.child('gov_submit_work', () => handleSubmitWork(this.core, identity, input));
158
+ }
159
+ submitReview(identity, input) {
160
+ return this.child('gov_submit_review', () => handleSubmitReview(this.core, identity, input));
161
+ }
162
+ submitTest(identity, input) {
163
+ return this.child('gov_submit_test', () => handleSubmitTest(this.core, identity, input));
164
+ }
165
+ inspectorApply(input) {
166
+ return this.child('ledger_apply', () => handleInspectorApply(this.core, input));
167
+ }
168
+ inspectorRule(input) {
169
+ return this.child('ledger_rule', () => handleInspectorRule(this.core, input));
170
+ }
171
+ inspectorSettle(input) {
172
+ return this.child('ledger_settle', () => handleInspectorSettle(this.core, input));
173
+ }
174
+ child(where, fn) {
175
+ try {
176
+ return fn();
177
+ }
178
+ catch (error) {
179
+ return internalError(where, error);
180
+ }
181
+ }
182
+ standings() {
183
+ if (this.core.run === null)
184
+ return 'OK: no governance run is active.';
185
+ return `OK: standings\n${renderStandings(this.core.standingRows(), this.core.health())}`;
186
+ }
187
+ // ---------------------------------------------------------------------------
188
+ // gov_read / gov_view / gov_scan
189
+ // ---------------------------------------------------------------------------
190
+ refs() {
191
+ const out = [];
192
+ for (const id of this.core.submissionCache.keys()) {
193
+ const ref = parseArtifactId(id);
194
+ if (ref)
195
+ out.push(ref);
196
+ }
197
+ return out.sort((a, b) => a.id.localeCompare(b.id, 'en', { numeric: true }));
198
+ }
199
+ deny(identity, id, why) {
200
+ this.core.log('view_denied', identity.id, { id, why });
201
+ const phase = currentDisplayPhase(this.core.run);
202
+ const log = this.core.viewLog.get(phase) ?? [];
203
+ this.core.viewLog.set(phase, [...log, `denied ${identity.id}: ${id} (${why})`].slice(-20));
204
+ return `NOT ACCEPTED: ${id} is not visible to your role (${identity.role}). The information ` +
205
+ 'boundary is deliberate; use gov_read {"list":true} to see what you may read.';
206
+ }
207
+ readArtifact(identity, input) {
208
+ return this.child('gov_read', () => this.doRead(identity, input));
209
+ }
210
+ doRead(identity, input) {
211
+ if (this.core.run === null)
212
+ return 'NOT ACCEPTED: no governance run is active.';
213
+ const request = isRecord(input) ? input : {};
214
+ const viewer = viewerOf(identity);
215
+ if (request.list === true || typeof request.id !== 'string') {
216
+ return formatReadableList(listReadable({ viewer, identity: identity.id, refs: this.refs() }));
217
+ }
218
+ const id = request.id;
219
+ const ref = parseArtifactId(id);
220
+ const item = ref ? this.core.submissionCache.get(ref.id) : undefined;
221
+ if (ref === null || item === undefined) {
222
+ return `NOT ACCEPTED: no artifact with id "${id.slice(0, 80)}". Use gov_read {"list":true}.`;
223
+ }
224
+ const access = accessFor(viewer, ref.kind, ref.identity === identity.id ? 'own' : 'other');
225
+ if (access === 'none')
226
+ return this.deny(identity, id, 'role');
227
+ const markdown = JSON.stringify(item, null, 2);
228
+ const offset = typeof request.offset === 'number' ? request.offset : 0;
229
+ return formatPage(id, pageText(renderForAccess(item, access, markdown), offset));
230
+ }
231
+ requestView(identity, input) {
232
+ return this.child('gov_view', () => this.doView(identity, input));
233
+ }
234
+ doView(identity, input) {
235
+ const run = this.core.run;
236
+ if (run === null)
237
+ return 'NOT ACCEPTED: no governance run is active.';
238
+ const request = isRecord(input) ? input : {};
239
+ const target = typeof request.target === 'string' ? request.target : '';
240
+ const reason = typeof request.reason === 'string' ? request.reason : '';
241
+ const lower = target.toLowerCase();
242
+ const kind = lower.includes('test')
243
+ ? 'test'
244
+ : lower.includes('work') || lower.includes('dev')
245
+ ? 'work'
246
+ : lower.includes('inspector')
247
+ ? 'inspector'
248
+ : 'review';
249
+ const file = target.match(FILE_LIKE)?.[0];
250
+ const used = this.core.viewRequests.get(identity.id) ?? 0;
251
+ const decision = decideView({
252
+ viewer: identity.role,
253
+ target: { kind, relation: 'other', ...(file ? { file } : {}) },
254
+ reason,
255
+ requestsUsed: used,
256
+ failingFiles: this.failingFiles(identity),
257
+ });
258
+ if (decision.consumesRequest)
259
+ this.core.viewRequests.set(identity.id, used + 1);
260
+ const type = decision.granted ? 'view_granted' : 'view_denied';
261
+ this.core.log(type, identity.id, { target: target.slice(0, 200), code: decision.code });
262
+ const phase = currentDisplayPhase(run);
263
+ this.core.viewLog.set(phase, [
264
+ ...(this.core.viewLog.get(phase) ?? []),
265
+ `${type} ${identity.id}: ${decision.code}`,
266
+ ].slice(-20));
267
+ if (!decision.granted)
268
+ return decision.message;
269
+ return `${decision.message}\n${this.scopedFindings(decision.scopeFile ?? '')}`;
270
+ }
271
+ failingFiles(identity) {
272
+ const files = new Set();
273
+ for (const item of this.core.submissionCache.values()) {
274
+ if (item.kind !== 'test' || item.identity !== identity.id)
275
+ continue;
276
+ const test = item;
277
+ const texts = [
278
+ ...test.issues.map((i) => i.description),
279
+ ...test.commands.map((c) => c.summary),
280
+ ];
281
+ for (const text of texts)
282
+ for (const f of text.match(FILE_LIKE) ?? [])
283
+ files.add(f);
284
+ }
285
+ return [...files];
286
+ }
287
+ scopedFindings(file) {
288
+ const lines = [];
289
+ for (const item of this.core.submissionCache.values()) {
290
+ if (item.kind !== 'review')
291
+ continue;
292
+ const review = item;
293
+ for (const f of findingsForFile(review.findings, file)) {
294
+ const where = f.line ? `${f.file}:${f.line}` : f.file;
295
+ lines.push(`[${f.severity}] ${where} ${f.issue} -> ${f.requiredChange}`);
296
+ }
297
+ }
298
+ return lines.length > 0 ? lines.slice(0, 20).join('\n') : '(no findings in that file)';
299
+ }
300
+ scan(_identity, input) {
301
+ const paths = isRecord(input) && Array.isArray(input.paths)
302
+ ? input.paths.filter((p) => typeof p === 'string')
303
+ : [];
304
+ if (paths.length === 0)
305
+ return 'NOT ACCEPTED: scan needs at least one path.';
306
+ const capped = paths.slice(0, GOV_LIMITS.scanPathsMax);
307
+ return scanPaths({ cwd: this.core.deps.getCwd(), paths: capped })
308
+ .then(formatScanReport)
309
+ .catch((error) => internalError('gov_scan', error));
310
+ }
311
+ }
312
+ export function createGovernanceEngine(deps) {
313
+ return new GovernanceEngine(deps);
314
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `estimateDispatches` - how many `gov_dispatch` calls a plan needs, and nothing more
3
+ * (governance-mode-v1-1 7.3, V-5).
4
+ *
5
+ * ASCII ONLY (`governance/` is glyph-scanned). Pure.
6
+ *
7
+ * ONLY THE QUANTITIES THAT CAN BE PROVEN TRUE. A total "upper bound" is NOT one of them:
8
+ * the rework cap is per work package and different work packages can be sent back in
9
+ * different rounds, authorised grants raise the caps, and chunking multiplies the calls a
10
+ * stage needs. So this module reports the clean-run count (chunking included), what ONE
11
+ * more rework round or fix cycle can add, and the hard per-run cap - and the formatter that
12
+ * prints it must never call any of them a ceiling on the total.
13
+ *
14
+ * The chunk sizes come from `stageChunkSize` (the same function `checkStage` enforces), so
15
+ * the estimate cannot drift from what the legality gate will actually demand.
16
+ */
17
+ import type { RunState } from '../types.js';
18
+ export interface DispatchEstimateInput {
19
+ /** Work packages per planned phase, in phase order. */
20
+ phaseWpCounts: readonly number[];
21
+ /** The ceiling `checkStage` enforces: `min(team.maxSubagents, hard cap)`. */
22
+ teamCeiling: number;
23
+ }
24
+ export interface DispatchEstimate {
25
+ /** Calls for a run with no rework, no fix cycle and a first-try integration. */
26
+ cleanRun: number;
27
+ /** The most one rework round can add in a single phase (dev + review + test). */
28
+ perReworkRound: number;
29
+ /** The most one fix cycle can add in a single phase (fix + the integrate after it). */
30
+ perFixCycle: number;
31
+ /** `GOV_LIMITS.hardMaxDispatches`: per run. */
32
+ hardCap: number;
33
+ /** Some phase is wider than the ceiling, so its stages are split into several calls. */
34
+ chunked: boolean;
35
+ }
36
+ export declare function estimateDispatches(input: DispatchEstimateInput): DispatchEstimate;
37
+ /** The estimate for a run (or a plan) that already has its phases. */
38
+ export declare function estimateForRun(run: Pick<RunState, 'phases'>, teamCeiling: number): DispatchEstimate;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * `estimateDispatches` - how many `gov_dispatch` calls a plan needs, and nothing more
3
+ * (governance-mode-v1-1 7.3, V-5).
4
+ *
5
+ * ASCII ONLY (`governance/` is glyph-scanned). Pure.
6
+ *
7
+ * ONLY THE QUANTITIES THAT CAN BE PROVEN TRUE. A total "upper bound" is NOT one of them:
8
+ * the rework cap is per work package and different work packages can be sent back in
9
+ * different rounds, authorised grants raise the caps, and chunking multiplies the calls a
10
+ * stage needs. So this module reports the clean-run count (chunking included), what ONE
11
+ * more rework round or fix cycle can add, and the hard per-run cap - and the formatter that
12
+ * prints it must never call any of them a ceiling on the total.
13
+ *
14
+ * The chunk sizes come from `stageChunkSize` (the same function `checkStage` enforces), so
15
+ * the estimate cannot drift from what the legality gate will actually demand.
16
+ */
17
+ import { GOV_LIMITS } from '../limits.js';
18
+ import { stageChunkSize } from './state-machine.js';
19
+ /** Calls one stage needs over `wpCount` work packages at `ceiling`. */
20
+ function callsFor(stage, wpCount, ceiling) {
21
+ if (wpCount <= 0)
22
+ return 0;
23
+ const size = stageChunkSize(stage, ceiling);
24
+ return Number.isFinite(size) ? Math.ceil(wpCount / size) : 1;
25
+ }
26
+ /** Calls that always happen once per phase: the settle and the first integrate. */
27
+ const FIXED_CALLS_PER_PHASE = 2;
28
+ export function estimateDispatches(input) {
29
+ const counts = input.phaseWpCounts.filter((w) => w > 0);
30
+ const at = (stage, w) => callsFor(stage, w, input.teamCeiling);
31
+ const roundOf = (w) => at('dev', w) + at('review', w) + at('test', w);
32
+ return {
33
+ cleanRun: counts.reduce((sum, w) => sum + roundOf(w) + FIXED_CALLS_PER_PHASE, 0),
34
+ perReworkRound: Math.max(0, ...counts.map(roundOf)),
35
+ perFixCycle: counts.length === 0 ? 0 : Math.max(...counts.map((w) => at('fix', w))) + 1,
36
+ hardCap: GOV_LIMITS.hardMaxDispatches,
37
+ chunked: counts.some((w) => w > Math.max(1, Math.floor(input.teamCeiling))),
38
+ };
39
+ }
40
+ /** The estimate for a run (or a plan) that already has its phases. */
41
+ export function estimateForRun(run, teamCeiling) {
42
+ return estimateDispatches({
43
+ phaseWpCounts: run.phases.map((phase) => phase.wpIds.length),
44
+ teamCeiling,
45
+ });
46
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `ledger_apply` / `ledger_rule` / `ledger_settle` - the engine side (governance-mode 5.4,
3
+ * 5.6, 5.7, 7.3).
4
+ *
5
+ * ASCII ONLY (`governance/` is glyph-scanned).
6
+ *
7
+ * THE INSPECTOR HAS NO SECOND ACCOUNTING PATH (I-G7). Everything it books goes through the
8
+ * same `core.ledgerOp` as the engine's own events, with the same catalogue deltas and the
9
+ * same caps; the only difference is `by: "inspector:insp"` and the evidence it must attach.
10
+ * It cannot name its own amount, cannot target itself (I-G5) and cannot book a mechanical
11
+ * code - those are refused here even if the tool layer let them through.
12
+ */
13
+ import type { EngineCore } from './engine-core.js';
14
+ export declare function handleInspectorApply(core: EngineCore, input: unknown): string;
15
+ export declare function handleInspectorRule(core: EngineCore, input: unknown): string;
16
+ export declare function handleInspectorSettle(core: EngineCore, input: unknown): string;