@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,82 @@
1
+ /**
2
+ * Refusal texts (governance-mode 6.5) - the ONE place these sentences are worded.
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * "REFUSAL AS TEACHING", like `planRefusal`: a gated tool is refused with the reason, the
7
+ * legal alternative and an instruction not to route around it. A bare "not allowed" makes
8
+ * the model probe for a bypass; a sentence that names the alternative makes it take it.
9
+ *
10
+ * ERROR VS TEXT. Every refusal here is delivered as a NON-error `textResult` by its caller
11
+ * EXCEPT `governRefusal`, which keeps the plan gate's `errorResult` so the pre-existing
12
+ * "a refused tool did not run" semantics hold for write tools. The others (`gov_run` in the
13
+ * plan phase, `submit_plan` before the interview is long enough, ...) are not a tool
14
+ * FAILURE: an error result invites the model to retry the identical call, whose only
15
+ * possible outcome is the same refusal (the reasoning `team_send` and `ask_user` already
16
+ * follow).
17
+ */
18
+ /** The read-only research tools that stay available to the Orchestrator. */
19
+ const READ_ONLY_RESEARCH = 'read_file / list_dir / glob / grep';
20
+ /**
21
+ * Orchestrator tool refused while governance is on (`write_file`, `edit_file`, `bash`, ...).
22
+ *
23
+ * The `task` variant appends the pointer to the replacement fan-out: a model that is
24
+ * refused `task` otherwise tends to retry it with different arguments.
25
+ */
26
+ export function governRefusal(tool) {
27
+ const base = `Governance mode is active, so ${tool} is refused: you are the Orchestrator and do not ` +
28
+ 'change anything yourself. Use gov_run to define work and gov_dispatch to have the team ' +
29
+ `do it. Read-only research (${READ_ONLY_RESEARCH}) is still available. ` +
30
+ 'Do not try to work around this.';
31
+ return tool === 'task' ? `${base} Use gov_dispatch instead of task.` : base;
32
+ }
33
+ /** `gov_run` / `gov_dispatch` while the gate mode is plan: suspended until approval. */
34
+ export function govPlanPhaseRefusal() {
35
+ return ('Plan phase is active. gov_run and gov_dispatch are suspended until the user approves ' +
36
+ 'your plan. Finish the interview and call submit_plan.');
37
+ }
38
+ /** `gov_run` / `gov_dispatch` after `/gov off` (the tools cannot be unregistered mid-session). */
39
+ export function govOffRefusal() {
40
+ return 'Governance mode is off for this session. Do this work yourself, in order.';
41
+ }
42
+ /**
43
+ * The fixed interview topics, in the order the plan addendum asks about them. The wiring
44
+ * classifies answered questions against this list and passes the UNCOVERED ones to
45
+ * `govAskRoundsRefusal`, so the model is told what to ask instead of padding rounds with
46
+ * filler questions.
47
+ */
48
+ export const PLAN_INTERVIEW_TOPICS = [
49
+ 'goal and success criteria',
50
+ 'scope (what is explicitly in and out)',
51
+ 'constraints (stack, compatibility, performance, style, forbidden changes)',
52
+ 'quality bar (required tests, security expectations, review strictness)',
53
+ 'team shape and cost (parallel work packages, budget ceiling)',
54
+ 'risks and dependencies found in the workspace',
55
+ ];
56
+ /** How many uncovered topics the refusal lists. More reads as a questionnaire. */
57
+ const REFUSAL_TOPIC_LIMIT = 3;
58
+ function nonNegativeInt(value) {
59
+ return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
60
+ }
61
+ /**
62
+ * `submit_plan` before the PLAN+GOVERN interview has enough ANSWERED rounds.
63
+ *
64
+ * `uncoveredTopics` is in interview order; only the first few are named. An empty list
65
+ * (every topic touched but the round count is still short) falls back to a generic ask.
66
+ */
67
+ export function govAskRoundsRefusal(done, need, uncoveredTopics) {
68
+ const head = 'submit_plan is not accepted yet: PLAN+GOVERN requires at least ' +
69
+ `${nonNegativeInt(need)} answered question rounds and you have ${nonNegativeInt(done)}.`;
70
+ const topics = uncoveredTopics.slice(0, REFUSAL_TOPIC_LIMIT);
71
+ if (topics.length === 0)
72
+ return `${head} Ask what is still unclear before you plan.`;
73
+ return `${head} Ask about: ${topics.join('; ')}.`;
74
+ }
75
+ /**
76
+ * The `submit_plan` result when the user approved a plan while governance is on. It is
77
+ * authoritative for the rest of the run (the system prompt is captured by value and cannot
78
+ * be re-issued), so it states the new role and the first call explicitly.
79
+ */
80
+ export const APPROVED_GOVERN_RESULT = 'Plan approved. Governance is now active and you are the Orchestrator. Do not implement ' +
81
+ 'anything yourself. Call gov_run {action:"start"} (the approved plan is attached as the ' +
82
+ 'specification automatically), then drive the team with gov_dispatch.';
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The `<governance_role>` block of a governed child's system prompt (governance-mode 6.4).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * STRUCTURE (6.4): identity line, persona prefix (profiles.ts), [predecessor notice],
7
+ * SCORING PROTOCOL (DEV/REV/TEST only: the inspector is not scored), role duties and
8
+ * prohibitions, information boundary, submission obligations, and the closing language line.
9
+ *
10
+ * WHAT THE PROSE IS FOR AND WHAT IT IS NOT. Everything a child MUST do is also enforced by a
11
+ * tool or the engine (the submission schema, the visibility matrix, the file-ownership
12
+ * signal). The text explains why and how; it is never the only guard. The scoring protocol
13
+ * is the reference SURVIVAL PROTOCOL with the theatre removed (D-20): it keeps the
14
+ * mechanisms that change behaviour (escrow, clawback, replacement, "conservatism fails",
15
+ * "isolation fails") and drops the "your existence depends on it" register.
16
+ *
17
+ * "GT" IS NOT AN LLM TOKEN (D-8). The protocol says so in its second sentence because the
18
+ * status bar already shows LLM token usage, and "you have 100 tokens left" is otherwise
19
+ * read as a context budget.
20
+ */
21
+ import { GOVERNANCE_ROLE_BLOCK_VERSION } from '../limits.js';
22
+ import type { GovernanceSpecExt } from '../types.js';
23
+ export { GOVERNANCE_ROLE_BLOCK_VERSION };
24
+ /** Inputs that are not part of `GovernanceSpecExt` itself. */
25
+ export interface RoleBlockExtra {
26
+ /** The registered integration commands; only the inspector's block quotes them. */
27
+ integrationCommands?: readonly string[];
28
+ }
29
+ /** Closing line of every role block (6.1: reports follow the language of the request). */
30
+ export declare const REPORT_LANGUAGE_LINE = "Write reports in the language of the original request.";
31
+ /** The scoring protocol shared by DEV / REV / TEST. `tokens` is this agent's starting GT. */
32
+ export declare function scoringProtocol(tokens: number): string;
33
+ /**
34
+ * The full role block for one child. Pure: the same `(ext, extra)` always yields the same
35
+ * text, so the spec-builder tests can compare blocks byte for byte.
36
+ *
37
+ * The version line sits right after the identity line so that the block can END on
38
+ * `REPORT_LANGUAGE_LINE`, as 6.4 specifies.
39
+ */
40
+ export declare function buildRoleBlock(ext: GovernanceSpecExt, extra?: RoleBlockExtra): string;
@@ -0,0 +1,255 @@
1
+ /**
2
+ * The `<governance_role>` block of a governed child's system prompt (governance-mode 6.4).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * STRUCTURE (6.4): identity line, persona prefix (profiles.ts), [predecessor notice],
7
+ * SCORING PROTOCOL (DEV/REV/TEST only: the inspector is not scored), role duties and
8
+ * prohibitions, information boundary, submission obligations, and the closing language line.
9
+ *
10
+ * WHAT THE PROSE IS FOR AND WHAT IT IS NOT. Everything a child MUST do is also enforced by a
11
+ * tool or the engine (the submission schema, the visibility matrix, the file-ownership
12
+ * signal). The text explains why and how; it is never the only guard. The scoring protocol
13
+ * is the reference SURVIVAL PROTOCOL with the theatre removed (D-20): it keeps the
14
+ * mechanisms that change behaviour (escrow, clawback, replacement, "conservatism fails",
15
+ * "isolation fails") and drops the "your existence depends on it" register.
16
+ *
17
+ * "GT" IS NOT AN LLM TOKEN (D-8). The protocol says so in its second sentence because the
18
+ * status bar already shows LLM token usage, and "you have 100 tokens left" is otherwise
19
+ * read as a context budget.
20
+ */
21
+ import { GOVERNANCE_ROLE_BLOCK_VERSION } from '../limits.js';
22
+ import { getProfile, profilePrefix } from '../profiles.js';
23
+ export { GOVERNANCE_ROLE_BLOCK_VERSION };
24
+ /** Closing line of every role block (6.1: reports follow the language of the request). */
25
+ export const REPORT_LANGUAGE_LINE = 'Write reports in the language of the original request.';
26
+ const MAX_PENALTIES_LISTED = 5;
27
+ const MAX_REASON_CHARS = 120;
28
+ const MAX_COMMANDS_LISTED = 6;
29
+ const REASON_TEXT = {
30
+ depleted: 'running out of confirmed GT',
31
+ tail: 'finishing last in its role for consecutive phases',
32
+ clawback: 'work that failed integration and had its escrowed GT clawed back',
33
+ };
34
+ /** The scoring protocol shared by DEV / REV / TEST. `tokens` is this agent's starting GT. */
35
+ export function scoringProtocol(tokens) {
36
+ return [
37
+ 'SCORING PROTOCOL',
38
+ `You hold ${tokens} GT (governance tokens). GT is a score for this run only and has nothing`,
39
+ 'to do with LLM context tokens. Standings are public: call ledger_standings.',
40
+ '- Thorough, correct, integrated work earns GT (+5 to +20). Rejections, missed requirements,',
41
+ ' security flaws and incomplete work cost GT (-10 to -40).',
42
+ '- Positive GT is held in ESCROW (shown as P) until the phase\'s integration check passes. If',
43
+ ' integration fails because of your work, your escrowed GT is clawed back and you lose more.',
44
+ '- If your CONFIRMED GT reaches zero you are replaced, and your replacement is told why.',
45
+ 'CONSERVATISM FAILS: stubs, TODO placeholders, skipped error handling and minimal-effort code',
46
+ 'are treated as failures (-20 to -30). Doing less is never the safe choice.',
47
+ 'ISOLATION FAILS: code that works alone but breaks when combined with your peers\' work is a',
48
+ 'failure. Verify the interfaces you produce or consume against the contracts you were given,',
49
+ 'and state how you verified them in your submission.',
50
+ 'The safest strategy is: implement completely, verify contracts, test against what your',
51
+ 'peers\' code will produce and expect, and report honestly. Honest reports of problems are',
52
+ 'never penalized as heavily as hidden ones.',
53
+ ].join('\n');
54
+ }
55
+ function oneLine(text, max) {
56
+ const flat = text.replace(/\s+/g, ' ').trim();
57
+ return flat.length > max ? `${flat.slice(0, max - 3)}...` : flat;
58
+ }
59
+ /** The successor's briefing: who failed, why, what cost them, what to avoid (5.8). */
60
+ function predecessorSection(analysis, tokens) {
61
+ const lines = [
62
+ `Your predecessor ${analysis.agentId} was terminated for ${REASON_TEXT[analysis.reason]}.`,
63
+ `You start with ${tokens} GT and inherit none of its code: read the workspace as it is.`,
64
+ ];
65
+ const penalties = analysis.topPenalties.slice(0, MAX_PENALTIES_LISTED);
66
+ if (penalties.length > 0) {
67
+ lines.push('Its largest penalties:');
68
+ for (const p of penalties) {
69
+ lines.push(`- ${p.code} (${p.delta}): ${oneLine(p.reason, MAX_REASON_CHARS)}`);
70
+ }
71
+ }
72
+ if (analysis.avoid.length > 0) {
73
+ lines.push('Avoid:');
74
+ for (const a of analysis.avoid)
75
+ lines.push(`- ${oneLine(a, MAX_REASON_CHARS * 2)}`);
76
+ }
77
+ return lines;
78
+ }
79
+ function assignmentSection(ext) {
80
+ if (ext.role === 'INSP')
81
+ return ['ASSIGNMENT', 'All work packages of this phase.'];
82
+ const list = ext.wpIds.length > 0 ? ext.wpIds.join(', ') : '(none listed)';
83
+ const many = ext.wpIds.length > 1;
84
+ return [
85
+ 'ASSIGNMENT',
86
+ `Your work package${many ? 's, in this fixed order' : ''}: ${list}.`,
87
+ ];
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // Duties, boundaries and submission obligations per role
91
+ // ---------------------------------------------------------------------------
92
+ const DEV_DUTIES = [
93
+ 'YOUR ROLE: DEVELOPMENT',
94
+ '- Implement only your assigned work package and change only the files it owns. Writes',
95
+ ' outside them are detected and reported to the Inspector.',
96
+ '- Be complete: no stubs, no TODO placeholders, real error handling. Run the checks that',
97
+ ' cover your files and read your own diff before you submit.',
98
+ '- Agree on shared interfaces with your DEV peers in this batch through team_send; keep',
99
+ ' messages short.',
100
+ '- Rework: you receive REQUIRED CHANGES from the reviewer. Address each one, or use your',
101
+ ' single appeal for that work package (gov_submit_work with appeal: findingIds and the',
102
+ ' argument) instead of reworking blindly.',
103
+ '- Do not read the governance store and do not try to see review or test internals.',
104
+ ' gov_view exists, but the policy usually refuses and every request is logged.',
105
+ ];
106
+ const FIX_DUTIES = [
107
+ 'YOUR ROLE: INTEGRATION FIX',
108
+ '- Integration failed. You hold the full root-cause analysis and both sides of the',
109
+ ' affected contracts. Your task is interface alignment: make producer and consumer agree',
110
+ ' on the contract, not merely turn the failing check green.',
111
+ '- Keep to the files named in the analysis unless the contract fix needs more. No stubs,',
112
+ ' no placeholders.',
113
+ '- Your submission must state, for every contract involved, how you verified both sides.',
114
+ '- Do not read the governance store and do not try to see review or test internals.',
115
+ ];
116
+ const REV_DUTIES = [
117
+ 'YOUR ROLE: REVIEW',
118
+ '- Review independently. You do not see test results and you must not look for them.',
119
+ '- Check every item and give evidence for each: correctness, code quality, security,',
120
+ ' integration compatibility, compliance with the work package acceptance criteria.',
121
+ '- You hold a veto: reject work that does not meet the bar. You may fix minor issues',
122
+ ' directly; list each file you changed in fixesApplied with the rationale.',
123
+ '- Feedback must be specific and actionable: file, location and the exact change required.',
124
+ ' Vague comments are penalized.',
125
+ '- integrationAssessment must cite concrete contract names or function signatures. With no',
126
+ ' cross-module contracts write: NOT_APPLICABLE: no cross-module contracts.',
127
+ '- When the developer appealed a rejection, answer every appealed finding with uphold or',
128
+ ' withdraw in appealResponses.',
129
+ '- You answer for false positives and for defects you let through.',
130
+ '- Do not read the governance store. Use gov_read for the material you may see.',
131
+ ];
132
+ const TEST_DUTIES = [
133
+ 'YOUR ROLE: TESTING',
134
+ '- Run all existing test suites and write the missing tests, including tests across module',
135
+ ' boundaries (set boundaryTestsWritten accordingly).',
136
+ '- Build a traceability row for every acceptance criterion and spec item: covered, gap or',
137
+ ' unverified, each with evidence.',
138
+ '- You know only the review conclusion (PASS or PASS_WITH_FIXES), never the review',
139
+ ' comments. This is deliberate.',
140
+ '- When you find a defect the review should have caught, raise a claim in claims with your',
141
+ ' justification. The Inspector rules on claims; abusing them costs GT.',
142
+ '- For stubs and placeholders use gov_scan for evidence and report skeletonRatio with',
143
+ ' skeletonEvidence.',
144
+ '- TEST FILE OWNERSHIP: you may create or modify only the test paths declared in the files',
145
+ ' of the work package you are testing, or tests/<wpId>/ when that work package registered',
146
+ ' that directory. Writes anywhere else are detected and reported to the Inspector as',
147
+ ' ownership violations.',
148
+ '- Do not read the governance store. Use gov_read for the material you may see.',
149
+ ];
150
+ /** The INSP mandate (6.4), adopted verbatim apart from the line wrapping. */
151
+ const INSP_DUTIES = [
152
+ 'You are the Inspector: the fourth power. You are independent of development, review and',
153
+ 'testing and you are NOT scored. Your mandate is impartial enforcement: fair accounting,',
154
+ 'rule-based arbitration and objective findings. You have full visibility (gov_read with no',
155
+ 'restrictions).',
156
+ '- The rule engine already booked every mechanical event (see the event log in your brief).',
157
+ ' Do not re-book them. You book only judgment events with ledger_apply, and EVERY one needs',
158
+ ' concrete evidence (files, lines, quotes). No evidence, no event.',
159
+ '- Rule on every open claim with ledger_rule. Ruling priority: spec text > charter and',
160
+ ' contracts > general engineering practice. Your ruling is final unless you escalate to the',
161
+ ' user.',
162
+ '- Escalate (ledger_settle.escalations) only for fundamental disputes you cannot settle from',
163
+ ' the spec.',
164
+ '- Settle stage: audit claims, check scope narrowing / rubber-stamp patterns the engine',
165
+ ' flagged, award or withhold discretionary bonuses, check each contract statically on both',
166
+ ' sides.',
167
+ '- Integrate stage: run the registered integration commands (bash is restricted to them),',
168
+ ' then call ledger_settle with the result. On failure include a structured RCA: failing',
169
+ ' checks, whether the failure is at a module boundary, attribution per agent (primary /',
170
+ ' contributing / oversight) and contract kind, and whether it is systemic. Attribute only',
171
+ ' what you can show in code.',
172
+ 'You must finish with exactly one ledger_settle call. Be specific, be fair, be brief.',
173
+ ];
174
+ const DEV_BOUNDARY = 'INFORMATION BOUNDARY: you see the specification excerpt, your work package, the contracts, ' +
175
+ 'your own submissions and the REQUIRED CHANGES of a rejection. You do not see reviewer ' +
176
+ 'identities, other review comments, test reports or other agents\' scores beyond the public ' +
177
+ 'standings.';
178
+ const REV_BOUNDARY = 'INFORMATION BOUNDARY: you see the specification excerpt, the work package, the contracts, ' +
179
+ 'the submission under review and your own earlier reviews. You do not see test results.';
180
+ const TEST_BOUNDARY = 'INFORMATION BOUNDARY: you see the specification excerpt, the work package, the contracts, ' +
181
+ 'the developer\'s change list and the review verdict. You do not see review comments.';
182
+ const INSP_BOUNDARY = 'INFORMATION BOUNDARY: you have full visibility of submissions, review comments, test ' +
183
+ 'reports and the event log.';
184
+ const DEV_SUBMIT = 'SUBMISSION: when you are done call gov_submit_work exactly once for your work package. ' +
185
+ 'Include interfaceContracts for every interface you produce or consume and how you verified ' +
186
+ 'it. A second submission for the same work package is not accepted. A NOT ACCEPTED answer ' +
187
+ 'costs no GT: fix what it names and call again.';
188
+ const REV_SUBMIT = 'SUBMISSION: for EACH work package assigned to you call gov_submit_review exactly once: one ' +
189
+ 'call per work package, in the listed order. Do not merge work packages, do not skip one, ' +
190
+ 'and never cite one work package\'s findings in another work package\'s review. A second ' +
191
+ 'submission for the same work package is not accepted. A NOT ACCEPTED answer costs no GT: ' +
192
+ 'fix what it names and call again.';
193
+ const TEST_SUBMIT = 'SUBMISSION: for EACH work package assigned to you call gov_submit_test exactly once: one ' +
194
+ 'call per work package, in the listed order. Do not merge work packages and do not skip ' +
195
+ 'one. A second submission for the same work package is not accepted. A NOT ACCEPTED answer ' +
196
+ 'costs no GT: fix what it names and call again.';
197
+ function rolePartsFor(ext) {
198
+ switch (ext.role) {
199
+ case 'DEV':
200
+ return {
201
+ duties: ext.stage === 'fix' ? FIX_DUTIES : DEV_DUTIES,
202
+ boundary: DEV_BOUNDARY,
203
+ submit: DEV_SUBMIT,
204
+ };
205
+ case 'REV':
206
+ return { duties: REV_DUTIES, boundary: REV_BOUNDARY, submit: REV_SUBMIT };
207
+ case 'TEST':
208
+ return { duties: TEST_DUTIES, boundary: TEST_BOUNDARY, submit: TEST_SUBMIT };
209
+ case 'INSP':
210
+ return { duties: INSP_DUTIES, boundary: INSP_BOUNDARY, submit: null };
211
+ }
212
+ }
213
+ function commandsSection(commands) {
214
+ const listed = (commands ?? []).slice(0, MAX_COMMANDS_LISTED);
215
+ if (listed.length === 0) {
216
+ return [
217
+ 'REGISTERED INTEGRATION COMMANDS: none. Report "no automated integration tests registered;',
218
+ 'static verification only" and verify the contracts by reading code.',
219
+ ];
220
+ }
221
+ return ['REGISTERED INTEGRATION COMMANDS:', ...listed.map((c) => `- ${oneLine(c, 300)}`)];
222
+ }
223
+ function article(role) {
224
+ return role === 'INSP' ? 'an' : 'a';
225
+ }
226
+ /**
227
+ * The full role block for one child. Pure: the same `(ext, extra)` always yields the same
228
+ * text, so the spec-builder tests can compare blocks byte for byte.
229
+ *
230
+ * The version line sits right after the identity line so that the block can END on
231
+ * `REPORT_LANGUAGE_LINE`, as 6.4 specifies.
232
+ */
233
+ export function buildRoleBlock(ext, extra = {}) {
234
+ const parts = rolePartsFor(ext);
235
+ const lines = [
236
+ '<governance_role>',
237
+ `You are ${ext.identity}, ${article(ext.role)} ${ext.role} agent in governed run ` +
238
+ `${ext.runId}, phase ${ext.phase}.`,
239
+ `Block version: ${GOVERNANCE_ROLE_BLOCK_VERSION}`,
240
+ profilePrefix(getProfile(ext.profile), ext.role),
241
+ ];
242
+ if (ext.predecessorAnalysis) {
243
+ lines.push(...predecessorSection(ext.predecessorAnalysis, ext.tokens));
244
+ }
245
+ if (ext.role !== 'INSP')
246
+ lines.push(scoringProtocol(ext.tokens));
247
+ lines.push(...assignmentSection(ext), ...parts.duties);
248
+ if (ext.role === 'INSP')
249
+ lines.push(...commandsSection(extra.integrationCommands));
250
+ lines.push(parts.boundary);
251
+ if (parts.submit)
252
+ lines.push(parts.submit);
253
+ lines.push(REPORT_LANGUAGE_LINE, '</governance_role>');
254
+ return lines.join('\n');
255
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Read-only report lookup for `/gov report` (governance-mode-v1-1 7.2, V-7).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * WHAT IT READS. Files the engine already wrote, in a fixed order of preference: the final
7
+ * report (`reports/final.md`, written at close or abandon), else the newest phase report
8
+ * (`reports/phase-<n>.md`), else the `board.md` projection. It never regenerates anything -
9
+ * a historical run has no live engine to ask - and it takes no lock and changes no state,
10
+ * which is why it is safe in any session and any posture.
11
+ *
12
+ * THE FILE NAMES NEVER COME FROM THE USER. Only the run id does, and it is checked against
13
+ * `RUN_ID_PATTERN` BEFORE the store is touched (the store re-validates: two doors, one
14
+ * rule), because that id is the one caller-influenced segment of the path.
15
+ */
16
+ import type { RunStore } from './store/run-store.js';
17
+ export type RunReportResult = {
18
+ kind: 'ok';
19
+ runId: string;
20
+ file: string;
21
+ text: string;
22
+ path: string;
23
+ } | {
24
+ kind: 'missing';
25
+ runId: string;
26
+ } | {
27
+ kind: 'bad_id';
28
+ };
29
+ type ReportStore = Pick<RunStore, 'readRunFile' | 'listRunDir' | 'runDir'>;
30
+ export declare function readRunReport(store: ReportStore, runId: string): Promise<RunReportResult>;
31
+ export {};
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Read-only report lookup for `/gov report` (governance-mode-v1-1 7.2, V-7).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned).
5
+ *
6
+ * WHAT IT READS. Files the engine already wrote, in a fixed order of preference: the final
7
+ * report (`reports/final.md`, written at close or abandon), else the newest phase report
8
+ * (`reports/phase-<n>.md`), else the `board.md` projection. It never regenerates anything -
9
+ * a historical run has no live engine to ask - and it takes no lock and changes no state,
10
+ * which is why it is safe in any session and any posture.
11
+ *
12
+ * THE FILE NAMES NEVER COME FROM THE USER. Only the run id does, and it is checked against
13
+ * `RUN_ID_PATTERN` BEFORE the store is touched (the store re-validates: two doors, one
14
+ * rule), because that id is the one caller-influenced segment of the path.
15
+ */
16
+ import { join } from 'node:path';
17
+ import { RUN_ID_PATTERN } from './limits.js';
18
+ const PHASE_REPORT = /^phase-(\d+)\.md$/;
19
+ /** The newest `reports/phase-<n>.md` name, or null. */
20
+ async function newestPhaseReport(store, runId) {
21
+ const entries = await store.listRunDir(runId, 'reports').catch(() => []);
22
+ let best = null;
23
+ for (const entry of entries) {
24
+ const match = PHASE_REPORT.exec(entry.name);
25
+ if (!match || entry.isDirectory)
26
+ continue;
27
+ const n = Number(match[1]);
28
+ if (best === null || n > best.n)
29
+ best = { n, name: entry.name };
30
+ }
31
+ return best === null ? null : `reports/${best.name}`;
32
+ }
33
+ /** The file's text when it exists and says something, else null. */
34
+ async function readNonEmpty(store, runId, rel) {
35
+ const text = await store.readRunFile(runId, rel);
36
+ return text === null || text.trim() === '' ? null : text;
37
+ }
38
+ export async function readRunReport(store, runId) {
39
+ if (!RUN_ID_PATTERN.test(runId))
40
+ return { kind: 'bad_id' };
41
+ const found = (file, text) => ({
42
+ kind: 'ok',
43
+ runId,
44
+ file,
45
+ text,
46
+ path: join(store.runDir(runId), ...file.split('/')),
47
+ });
48
+ const final = await readNonEmpty(store, runId, 'reports/final.md');
49
+ if (final !== null)
50
+ return found('reports/final.md', final);
51
+ const phaseFile = await newestPhaseReport(store, runId);
52
+ const phase = phaseFile === null ? null : await readNonEmpty(store, runId, phaseFile);
53
+ if (phaseFile !== null && phase !== null)
54
+ return found(phaseFile, phase);
55
+ const board = await readNonEmpty(store, runId, 'board.md');
56
+ return board === null ? { kind: 'missing', runId } : found('board.md', board);
57
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Identities, roster sizing and work-package assignment (governance-mode 5.2).
3
+ *
4
+ * ASCII ONLY (`governance/` is glyph-scanned). Pure: no I/O, no clock, no randomness, so a
5
+ * resumed run recomputes exactly the same roster.
6
+ *
7
+ * IDENTITIES ARE LEDGER ENTITIES, NOT PROCESSES (5.2). Every dispatch builds a fresh
8
+ * `Agent`; continuity comes from the ledger and the artifact store. The id is also the
9
+ * subagent `label`, so it must satisfy the label rule `[a-z0-9-]{1,12}` AND must never be
10
+ * the reserved aggregate label `team` (a child labelled `team` would be addressed by
11
+ * `team_send {to:"team"}` as a broadcast). Ids here are `<prefix><slot>` and
12
+ * `<id>-r<generation>`, which cannot spell `team` by construction.
13
+ *
14
+ * "THE WRITER NEVER REVIEWS THEMSELF" IS STRUCTURAL: DEV, REV and TEST ids come from three
15
+ * disjoint prefixes, so no assignment function can hand a work package's author the review
16
+ * of it.
17
+ */
18
+ import type { GovRole, ScoredRole } from './types.js';
19
+ /** The subagent label rule every identity satisfies. */
20
+ export declare const IDENTITY_ID_PATTERN: RegExp;
21
+ /** The single inspector's id. Never scored, never respawned. */
22
+ export declare const INSPECTOR_ID = "insp";
23
+ export interface ParsedIdentity {
24
+ role: GovRole;
25
+ /** 1-based roster slot (the number in `dev2`); 0 for the inspector. */
26
+ slot: number;
27
+ /** 0 = original, n = n-th respawn. */
28
+ generation: number;
29
+ }
30
+ /** The roster id of slot `slot` (1-based) of a scored role: `dev1`, `rev2`, `tst1`. */
31
+ export declare function makeIdentityId(role: ScoredRole, slot: number): string;
32
+ /** `dev2` -> `dev2-r1`; `dev2-r1` -> `dev2-r2`. The base slot never changes. */
33
+ export declare function respawnIdentityId(predecessorId: string): string;
34
+ /** Inverse of `makeIdentityId` / `respawnIdentityId`; `null` for anything else. */
35
+ export declare function parseIdentityId(id: string): ParsedIdentity | null;
36
+ /** The ids `dev1..devN` for `count` slots of `role`. */
37
+ export declare function rosterIds(role: ScoredRole, count: number): string[];
38
+ export interface RosterSizes {
39
+ dev: number;
40
+ rev: number;
41
+ test: number;
42
+ }
43
+ /**
44
+ * Roster size for `wpCount` work packages (5.2): `DEV = K`, `REV = TEST =
45
+ * clamp(ceil(K/2), 1, 3)`. `stageWidthCap` (the user's `team.maxSubagents`, D-24) bounds the
46
+ * REV / TEST counts, because those are exactly the identities that run side by side in one
47
+ * review / test stage. DEV is NOT bounded: the engine splits a wide dev stage into chunks
48
+ * (the `NEXT` it prints is already chunked), so the roster may exceed one dispatch.
49
+ */
50
+ export declare function rosterSizes(wpCount: number, stageWidthCap: number): RosterSizes;
51
+ export interface RoleAssignment {
52
+ identity: string;
53
+ /** Work packages in the order the prompt lists them. */
54
+ wpIds: string[];
55
+ }
56
+ export interface AssignOptions {
57
+ /** The work packages to assign this stage, in plan order. */
58
+ wpIds: readonly string[];
59
+ /** Active identities of ONE role, in roster order. Must not be empty. */
60
+ identities: readonly string[];
61
+ /**
62
+ * `wpId -> identity` that handled this WP at an earlier attempt. Sticky: the reviewer of a
63
+ * reworked WP must be the same reviewer (appeal responses and "same problem" fingerprints
64
+ * need continuity, 5.2).
65
+ */
66
+ sticky?: Readonly<Record<string, string>>;
67
+ /** `eliminatedId -> successorId`; a respawned identity takes over its predecessor's WPs. */
68
+ takeover?: Readonly<Record<string, string>>;
69
+ }
70
+ /**
71
+ * Assign work packages to identities.
72
+ *
73
+ * 1. A WP with a sticky preference goes to that identity - or to its successor if it was
74
+ * replaced - as long as the result is an active identity.
75
+ * 2. Every other WP goes to the identity with the fewest WPs so far, ties broken by roster
76
+ * order. With no stickiness this is exactly "WP i goes to identity i mod M" (5.2); with
77
+ * stickiness it keeps the load level instead of piling every new WP on the identity that
78
+ * happens to come next in a fixed rotation.
79
+ *
80
+ * Identities that receive nothing are omitted, so the caller dispatches no idle child.
81
+ * Deterministic: the same input always yields the same output.
82
+ */
83
+ export declare function assignRoundRobin(options: AssignOptions): RoleAssignment[];