@aragon-agent/cli 0.6.44 → 0.6.46

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 (255) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +120 -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/invocation-card.d.ts +77 -0
  10. package/dist/agent/invocation-card.js +169 -0
  11. package/dist/agent/plan-prompt.d.ts +7 -0
  12. package/dist/agent/plan-prompt.js +2 -1
  13. package/dist/agent/prompt-options.d.ts +6 -0
  14. package/dist/agent/queued-messages.d.ts +3 -0
  15. package/dist/agent/queued-messages.js +4 -1
  16. package/dist/agent/reducer.d.ts +38 -1
  17. package/dist/agent/reducer.js +57 -12
  18. package/dist/agent/system-prompt.d.ts +19 -0
  19. package/dist/agent/system-prompt.js +9 -1
  20. package/dist/cli.js +45 -1
  21. package/dist/commands/builtins.js +22 -4
  22. package/dist/commands/governance-command.d.ts +35 -0
  23. package/dist/commands/governance-command.js +304 -0
  24. package/dist/commands/governance-runs-table.d.ts +40 -0
  25. package/dist/commands/governance-runs-table.js +130 -0
  26. package/dist/commands/index-build.d.ts +8 -0
  27. package/dist/commands/index-build.js +11 -0
  28. package/dist/commands/registry.d.ts +35 -0
  29. package/dist/commands/registry.js +20 -7
  30. package/dist/commands/skills.js +36 -2
  31. package/dist/commands/subagent-command.js +3 -1
  32. package/dist/commands/team-command.d.ts +6 -0
  33. package/dist/commands/team-command.js +40 -3
  34. package/dist/config/app-paths.d.ts +10 -0
  35. package/dist/config/app-paths.js +12 -0
  36. package/dist/config/cli-commands.d.ts +18 -0
  37. package/dist/config/cli-commands.js +47 -1
  38. package/dist/config/env.d.ts +2 -1
  39. package/dist/config/env.js +10 -1
  40. package/dist/config/governance-config.d.ts +125 -0
  41. package/dist/config/governance-config.js +164 -0
  42. package/dist/config/governance-launch.d.ts +71 -0
  43. package/dist/config/governance-launch.js +58 -0
  44. package/dist/config/load.d.ts +15 -0
  45. package/dist/config/load.js +26 -1
  46. package/dist/config/model-profile-store.d.ts +4 -2
  47. package/dist/config/schema.d.ts +22 -0
  48. package/dist/config/schema.js +6 -0
  49. package/dist/config/store.js +14 -1
  50. package/dist/config/ui-state.d.ts +11 -0
  51. package/dist/config/ui-state.js +11 -0
  52. package/dist/diagnostics/doctor.js +20 -0
  53. package/dist/governance/card-normalize.d.ts +24 -0
  54. package/dist/governance/card-normalize.js +76 -0
  55. package/dist/governance/copy.d.ts +109 -0
  56. package/dist/governance/copy.js +223 -0
  57. package/dist/governance/engine/aftermath.d.ts +49 -0
  58. package/dist/governance/engine/aftermath.js +134 -0
  59. package/dist/governance/engine/artifact-persist.d.ts +35 -0
  60. package/dist/governance/engine/artifact-persist.js +86 -0
  61. package/dist/governance/engine/budget.d.ts +52 -0
  62. package/dist/governance/engine/budget.js +112 -0
  63. package/dist/governance/engine/cards.d.ts +18 -0
  64. package/dist/governance/engine/cards.js +186 -0
  65. package/dist/governance/engine/digest.d.ts +32 -0
  66. package/dist/governance/engine/digest.js +63 -0
  67. package/dist/governance/engine/engine-core.d.ts +219 -0
  68. package/dist/governance/engine/engine-core.js +562 -0
  69. package/dist/governance/engine/engine.d.ts +68 -0
  70. package/dist/governance/engine/engine.js +314 -0
  71. package/dist/governance/engine/estimate.d.ts +38 -0
  72. package/dist/governance/engine/estimate.js +46 -0
  73. package/dist/governance/engine/inspector.d.ts +16 -0
  74. package/dist/governance/engine/inspector.js +396 -0
  75. package/dist/governance/engine/integration.d.ts +35 -0
  76. package/dist/governance/engine/integration.js +220 -0
  77. package/dist/governance/engine/lifecycle.d.ts +29 -0
  78. package/dist/governance/engine/lifecycle.js +656 -0
  79. package/dist/governance/engine/pause.d.ts +56 -0
  80. package/dist/governance/engine/pause.js +107 -0
  81. package/dist/governance/engine/phase-members.d.ts +15 -0
  82. package/dist/governance/engine/phase-members.js +34 -0
  83. package/dist/governance/engine/phase-planner.d.ts +53 -0
  84. package/dist/governance/engine/phase-planner.js +282 -0
  85. package/dist/governance/engine/rebuild.d.ts +27 -0
  86. package/dist/governance/engine/rebuild.js +57 -0
  87. package/dist/governance/engine/report.d.ts +66 -0
  88. package/dist/governance/engine/report.js +220 -0
  89. package/dist/governance/engine/run-digest.d.ts +20 -0
  90. package/dist/governance/engine/run-digest.js +42 -0
  91. package/dist/governance/engine/spec-builder.d.ts +117 -0
  92. package/dist/governance/engine/spec-builder.js +321 -0
  93. package/dist/governance/engine/stage-runner.d.ts +22 -0
  94. package/dist/governance/engine/stage-runner.js +664 -0
  95. package/dist/governance/engine/start-input.d.ts +19 -0
  96. package/dist/governance/engine/start-input.js +111 -0
  97. package/dist/governance/engine/state-machine.d.ts +101 -0
  98. package/dist/governance/engine/state-machine.js +586 -0
  99. package/dist/governance/engine/submission-queries.d.ts +42 -0
  100. package/dist/governance/engine/submission-queries.js +97 -0
  101. package/dist/governance/engine/submission-render.d.ts +12 -0
  102. package/dist/governance/engine/submission-render.js +92 -0
  103. package/dist/governance/engine/submissions.d.ts +27 -0
  104. package/dist/governance/engine/submissions.js +455 -0
  105. package/dist/governance/engine/visibility.d.ts +104 -0
  106. package/dist/governance/engine/visibility.js +223 -0
  107. package/dist/governance/governed-dispatch.d.ts +19 -0
  108. package/dist/governance/governed-dispatch.js +17 -0
  109. package/dist/governance/limits.d.ts +107 -0
  110. package/dist/governance/limits.js +131 -0
  111. package/dist/governance/posture-transition.d.ts +38 -0
  112. package/dist/governance/posture-transition.js +44 -0
  113. package/dist/governance/posture.d.ts +35 -0
  114. package/dist/governance/posture.js +59 -0
  115. package/dist/governance/profiles.d.ts +48 -0
  116. package/dist/governance/profiles.js +140 -0
  117. package/dist/governance/prompts/orchestrator-block.d.ts +40 -0
  118. package/dist/governance/prompts/orchestrator-block.js +128 -0
  119. package/dist/governance/prompts/plan-addendum.d.ts +22 -0
  120. package/dist/governance/prompts/plan-addendum.js +60 -0
  121. package/dist/governance/prompts/refusals.d.ts +48 -0
  122. package/dist/governance/prompts/refusals.js +82 -0
  123. package/dist/governance/prompts/role-blocks.d.ts +40 -0
  124. package/dist/governance/prompts/role-blocks.js +255 -0
  125. package/dist/governance/report-reader.d.ts +31 -0
  126. package/dist/governance/report-reader.js +57 -0
  127. package/dist/governance/roles.d.ts +83 -0
  128. package/dist/governance/roles.js +142 -0
  129. package/dist/governance/rules/claims.d.ts +83 -0
  130. package/dist/governance/rules/claims.js +250 -0
  131. package/dist/governance/rules/elimination.d.ts +66 -0
  132. package/dist/governance/rules/elimination.js +105 -0
  133. package/dist/governance/rules/events-table.d.ts +46 -0
  134. package/dist/governance/rules/events-table.js +94 -0
  135. package/dist/governance/rules/failure-analysis.d.ts +28 -0
  136. package/dist/governance/rules/failure-analysis.js +93 -0
  137. package/dist/governance/rules/ledger-replay.d.ts +53 -0
  138. package/dist/governance/rules/ledger-replay.js +53 -0
  139. package/dist/governance/rules/ledger-state.d.ts +85 -0
  140. package/dist/governance/rules/ledger-state.js +175 -0
  141. package/dist/governance/rules/ledger.d.ts +228 -0
  142. package/dist/governance/rules/ledger.js +560 -0
  143. package/dist/governance/rules/rca.d.ts +68 -0
  144. package/dist/governance/rules/rca.js +220 -0
  145. package/dist/governance/rules/settlement.d.ts +129 -0
  146. package/dist/governance/rules/settlement.js +363 -0
  147. package/dist/governance/rules/suspicion.d.ts +66 -0
  148. package/dist/governance/rules/suspicion.js +169 -0
  149. package/dist/governance/store/artifacts.d.ts +81 -0
  150. package/dist/governance/store/artifacts.js +173 -0
  151. package/dist/governance/store/atomic.d.ts +79 -0
  152. package/dist/governance/store/atomic.js +119 -0
  153. package/dist/governance/store/events-log.d.ts +35 -0
  154. package/dist/governance/store/events-log.js +86 -0
  155. package/dist/governance/store/run-lock.d.ts +51 -0
  156. package/dist/governance/store/run-lock.js +122 -0
  157. package/dist/governance/store/run-store.d.ts +229 -0
  158. package/dist/governance/store/run-store.js +644 -0
  159. package/dist/governance/store/scoreboard-export.d.ts +53 -0
  160. package/dist/governance/store/scoreboard-export.js +65 -0
  161. package/dist/governance/tools/child-tools.d.ts +31 -0
  162. package/dist/governance/tools/child-tools.js +65 -0
  163. package/dist/governance/tools/guard.d.ts +71 -0
  164. package/dist/governance/tools/guard.js +194 -0
  165. package/dist/governance/tools/inspector-tools.d.ts +63 -0
  166. package/dist/governance/tools/inspector-tools.js +424 -0
  167. package/dist/governance/tools/lead-tools.d.ts +42 -0
  168. package/dist/governance/tools/lead-tools.js +226 -0
  169. package/dist/governance/tools/normalize-util.d.ts +101 -0
  170. package/dist/governance/tools/normalize-util.js +230 -0
  171. package/dist/governance/tools/scan-incomplete.d.ts +79 -0
  172. package/dist/governance/tools/scan-incomplete.js +486 -0
  173. package/dist/governance/tools/shared-tools.d.ts +44 -0
  174. package/dist/governance/tools/shared-tools.js +125 -0
  175. package/dist/governance/tools/submit-normalizers.d.ts +28 -0
  176. package/dist/governance/tools/submit-normalizers.js +474 -0
  177. package/dist/governance/tools/submit-tools.d.ts +26 -0
  178. package/dist/governance/tools/submit-tools.js +171 -0
  179. package/dist/governance/types.d.ts +661 -0
  180. package/dist/governance/types.js +27 -0
  181. package/dist/session/persist.js +10 -0
  182. package/dist/session/validate-session.js +36 -3
  183. package/dist/team/forced-mode.d.ts +19 -0
  184. package/dist/team/forced-mode.js +42 -20
  185. package/dist/team/runtime.d.ts +8 -0
  186. package/dist/team/runtime.js +9 -0
  187. package/dist/team/subagent.d.ts +23 -0
  188. package/dist/team/subagent.js +14 -3
  189. package/dist/team/types.d.ts +6 -0
  190. package/dist/tools/index.d.ts +30 -7
  191. package/dist/tools/index.js +14 -0
  192. package/dist/tools/plan-tools.d.ts +14 -2
  193. package/dist/tools/plan-tools.js +5 -2
  194. package/dist/ui/App.js +170 -31
  195. package/dist/ui/BottomStatusRow.js +1 -1
  196. package/dist/ui/Composer.d.ts +7 -1
  197. package/dist/ui/Composer.js +9 -6
  198. package/dist/ui/GovernancePanel.d.ts +50 -0
  199. package/dist/ui/GovernancePanel.js +77 -0
  200. package/dist/ui/GovernanceRun.d.ts +18 -0
  201. package/dist/ui/GovernanceRun.js +11 -0
  202. package/dist/ui/StatusBar.d.ts +15 -2
  203. package/dist/ui/StatusBar.js +10 -4
  204. package/dist/ui/Transcript.js +7 -1
  205. package/dist/ui/entries/GovernanceCard.d.ts +30 -0
  206. package/dist/ui/entries/GovernanceCard.js +32 -0
  207. package/dist/ui/entries/InvocationCard.d.ts +20 -0
  208. package/dist/ui/entries/InvocationCard.js +32 -0
  209. package/dist/ui/governance-copy.d.ts +69 -0
  210. package/dist/ui/governance-copy.js +104 -0
  211. package/dist/ui/governance-status.d.ts +145 -0
  212. package/dist/ui/governance-status.js +326 -0
  213. package/dist/ui/interaction-copy.d.ts +4 -0
  214. package/dist/ui/interaction-copy.js +5 -0
  215. package/dist/ui/interaction-hints.d.ts +17 -0
  216. package/dist/ui/interaction-hints.js +14 -2
  217. package/dist/ui/layout/governance-board.d.ts +121 -0
  218. package/dist/ui/layout/governance-board.js +382 -0
  219. package/dist/ui/layout/governance-card.d.ts +53 -0
  220. package/dist/ui/layout/governance-card.js +134 -0
  221. package/dist/ui/layout/governance-chip.d.ts +38 -0
  222. package/dist/ui/layout/governance-chip.js +64 -0
  223. package/dist/ui/layout/governance-panel.d.ts +85 -0
  224. package/dist/ui/layout/governance-panel.js +358 -0
  225. package/dist/ui/layout/governance-roster.d.ts +65 -0
  226. package/dist/ui/layout/governance-roster.js +275 -0
  227. package/dist/ui/layout/invocation-card.d.ts +41 -0
  228. package/dist/ui/layout/invocation-card.js +91 -0
  229. package/dist/ui/layout/status-detail-layout.js +3 -3
  230. package/dist/ui/layout/status-layout.d.ts +5 -2
  231. package/dist/ui/layout/status-layout.js +10 -6
  232. package/dist/ui/layout/virtual-window.js +22 -1
  233. package/dist/ui/overlays/GovernanceBoardOverlay.d.ts +41 -0
  234. package/dist/ui/overlays/GovernanceBoardOverlay.js +76 -0
  235. package/dist/ui/overlays/GovernanceSettingsPage.d.ts +48 -0
  236. package/dist/ui/overlays/GovernanceSettingsPage.js +93 -0
  237. package/dist/ui/overlays/HelpOverlay.js +4 -3
  238. package/dist/ui/overlays/QuestionOverlay.d.ts +9 -1
  239. package/dist/ui/overlays/QuestionOverlay.js +4 -2
  240. package/dist/ui/overlays/SettingsScreen.d.ts +7 -0
  241. package/dist/ui/overlays/SettingsScreen.js +21 -1
  242. package/dist/ui/overlays/governance-settings.d.ts +79 -0
  243. package/dist/ui/overlays/governance-settings.js +140 -0
  244. package/dist/ui/overlays/model-profile-state.d.ts +6 -1
  245. package/dist/ui/overlays/model-profile-state.js +10 -0
  246. package/dist/ui/palettes.d.ts +17 -0
  247. package/dist/ui/palettes.js +9 -0
  248. package/dist/ui/scrollback/live-preview.js +2 -0
  249. package/dist/ui/scrollback/settled-boundary.js +3 -0
  250. package/dist/ui/shortcuts.js +2 -2
  251. package/dist/ui/theme.d.ts +7 -0
  252. package/dist/ui/theme.js +1 -0
  253. package/dist/ui/transcript-text.js +13 -1
  254. package/dist/ui/use-wheel-routing.js +3 -1
  255. package/package.json +2 -2
@@ -6,6 +6,7 @@ import type { SubmitMessageOptions } from '../agent/prompt-options.js';
6
6
  import type { CopyRequest, CopyRequestResult } from '../ui/clipboard-task.js';
7
7
  import type { AgentController } from '../agent/controller.js';
8
8
  import type { AgentMode } from '../agent/agent-mode.js';
9
+ import type { Posture } from '../governance/posture.js';
9
10
  import type { Entry, NoticeLevel, Overlay, ToastLevel, ViewAction, ViewState } from '../agent/reducer.js';
10
11
  import type { PersistedConfig } from '../config/schema.js';
11
12
  import type { FollowThroughBudget } from '../todo/follow-through.js';
@@ -92,6 +93,17 @@ export interface CommandContext {
92
93
  effective: AgentMode;
93
94
  pending: AgentMode | null;
94
95
  };
96
+ /**
97
+ * The same single write path, widened to the four postures (governance-mode 4.2).
98
+ * OPTIONAL so the many fixtures that build this context by literal need no change; the
99
+ * App always supplies it, and `/gov` reports "unavailable" when it is absent.
100
+ */
101
+ applyPosture?: (next: Posture, opts?: {
102
+ force?: boolean;
103
+ }) => {
104
+ effective: Posture;
105
+ pending: Posture | null;
106
+ };
95
107
  /**
96
108
  * Mouse capture, for `/mouse` (tui-selection-and-scroll-follow §6.2 / G3).
97
109
  *
@@ -189,6 +201,13 @@ export interface CommandContext {
189
201
  * TYPE-ONLY import, for the reason the `branch` note above records.
190
202
  */
191
203
  taskSummary?: TaskSummaryCommandPort;
204
+ /**
205
+ * Whether transcript invocation cards are on (tui-invocation-cards section 3.6).
206
+ * `false` only under `ARAGON_NO_INVOCATION_CARDS=1`; commands then fall back to the
207
+ * pre-card notices and submit without `invocation`. Absent (every fixture built by
208
+ * literal) means ON.
209
+ */
210
+ invocationCards?: boolean;
192
211
  }
193
212
  /**
194
213
  * What `/keys` and `/task` may do.
@@ -228,6 +247,12 @@ export interface SlashCommand {
228
247
  aliases?: string[];
229
248
  description: string;
230
249
  run: (ctx: CommandContext) => void | Promise<void>;
250
+ /**
251
+ * True when running with these args will submit a message that renders as an invocation
252
+ * card, so the `Command:` echo would only repeat it. MUST be the same predicate the
253
+ * command itself branches on (I-8); absent means false.
254
+ */
255
+ rendersInvocationCard?: (args: string) => boolean;
231
256
  }
232
257
  export declare class CommandRegistry {
233
258
  private readonly byName;
@@ -235,6 +260,16 @@ export declare class CommandRegistry {
235
260
  get(name: string): SlashCommand | undefined;
236
261
  all(): SlashCommand[];
237
262
  }
263
+ /**
264
+ * Split raw composer input into a command word and its trimmed args; `null` when the
265
+ * input is not a slash command (no leading `/`, or the `//` literal-slash escape).
266
+ * `runSlashInput` and the App's echo suppression both go through here so they cannot
267
+ * disagree about what counts as a command.
268
+ */
269
+ export declare function parseSlashInput(input: string): {
270
+ name: string;
271
+ args: string;
272
+ } | null;
238
273
  /**
239
274
  * Try to run a slash command from raw input. Returns `true` if the input was a
240
275
  * (known or unknown) slash command and was consumed; `false` if it is a normal
@@ -19,21 +19,34 @@ export class CommandRegistry {
19
19
  }
20
20
  }
21
21
  /**
22
- * Try to run a slash command from raw input. Returns `true` if the input was a
23
- * (known or unknown) slash command and was consumed; `false` if it is a normal
24
- * message that should go to the agent.
22
+ * Split raw composer input into a command word and its trimmed args; `null` when the
23
+ * input is not a slash command (no leading `/`, or the `//` literal-slash escape).
24
+ * `runSlashInput` and the App's echo suppression both go through here so they cannot
25
+ * disagree about what counts as a command.
25
26
  */
26
- export async function runSlashInput(registry, input, makeCtx) {
27
+ export function parseSlashInput(input) {
27
28
  const trimmed = input.trimStart();
28
29
  if (!trimmed.startsWith('/'))
29
- return false;
30
- // `//...` escapes a literal leading slash — not a command.
30
+ return null;
31
+ // `//...` escapes a literal leading slash - not a command.
31
32
  if (trimmed.startsWith('//'))
32
- return false;
33
+ return null;
33
34
  const withoutSlash = trimmed.slice(1);
34
35
  const spaceIdx = withoutSlash.search(/\s/);
35
36
  const name = spaceIdx === -1 ? withoutSlash : withoutSlash.slice(0, spaceIdx);
36
37
  const args = spaceIdx === -1 ? '' : withoutSlash.slice(spaceIdx + 1).trim();
38
+ return { name, args };
39
+ }
40
+ /**
41
+ * Try to run a slash command from raw input. Returns `true` if the input was a
42
+ * (known or unknown) slash command and was consumed; `false` if it is a normal
43
+ * message that should go to the agent.
44
+ */
45
+ export async function runSlashInput(registry, input, makeCtx) {
46
+ const parsed = parseSlashInput(input);
47
+ if (parsed === null)
48
+ return false;
49
+ const { name, args } = parsed;
37
50
  const command = registry.get(name);
38
51
  const ctx = makeCtx(args);
39
52
  if (!command) {
@@ -16,6 +16,7 @@ import { SKILL_TRIAGE_LIMITS } from '../skills/triage.js';
16
16
  import { HOST_TOOL_NAMES, SKILL_TOOL_FLOOR } from '../tools/index.js';
17
17
  import { SKILLS_TOOL_POLICY_MODES, isSkillsToolPolicyMode } from '../config/schema.js';
18
18
  import { pickGlyphs } from '../ui/glyphs.js';
19
+ import { INDEX_SKILL_NAME, isIndexBuildArgs } from './index-build.js';
19
20
  function marksFor(ctx) {
20
21
  const cfg = ctx.controller.getConfig();
21
22
  const glyphs = pickGlyphs({ colorLevel: cfg.colorLevel ?? 0, unicode: cfg.unicode ?? false });
@@ -673,10 +674,37 @@ export function registerSkillCommands(registry, service) {
673
674
  }
674
675
  }
675
676
  }
677
+ /**
678
+ * The card's raw material for one skill run (tui-invocation-cards section 3.3). The
679
+ * command line always uses the namespaced `/skill:<name>` form - the stable handle -
680
+ * even when the user typed the bare name. Ctrl+I's machine-written sentence is NOT the
681
+ * user's input (RV-3): the card says `ctrl+i` and shows no input row.
682
+ */
683
+ function skillCardInput(record, args, sent) {
684
+ const machine = record.name === INDEX_SKILL_NAME && isIndexBuildArgs(args);
685
+ const version = record.frontmatter.version;
686
+ const facts = [
687
+ ...(machine ? ['ctrl+i'] : []),
688
+ ...(version ? [`v${version}`] : []),
689
+ record.scope,
690
+ `${sent.kb} KB`,
691
+ ...(sent.files > 0 ? [`${sent.files} files`] : []),
692
+ ...(sent.policy ? ['tool ceiling'] : []),
693
+ ];
694
+ const typed = machine ? '' : args;
695
+ return {
696
+ variant: 'skill',
697
+ name: record.name,
698
+ commandLine: typed === '' ? `/skill:${record.name}` : `/skill:${record.name} ${typed}`,
699
+ input: typed,
700
+ facts,
701
+ };
702
+ }
676
703
  function makeSkillCommand(record, service) {
677
704
  return {
678
705
  name: record.name,
679
706
  description: shortDescription(record),
707
+ rendersInvocationCard: () => true,
680
708
  run: (ctx) => {
681
709
  let loaded;
682
710
  try {
@@ -703,8 +731,14 @@ function makeSkillCommand(record, service) {
703
731
  // The SUBMITTED size, not the file's. Reporting 480 KB while sending 30 KB
704
732
  // is how a user concludes the truncation marker is a rendering glitch.
705
733
  const kb = Math.max(1, Math.round(Buffer.byteLength(message, 'utf-8') / 1024));
706
- ctx.notify('info', `Skill "${record.name}" loaded (${kb} KB submitted, ${loaded.files.length} bundled files).`);
707
- ctx.submit(message);
734
+ if (ctx.invocationCards === false) {
735
+ ctx.notify('info', `Skill "${record.name}" loaded (${kb} KB submitted, ${loaded.files.length} bundled files).`);
736
+ ctx.submit(message);
737
+ return;
738
+ }
739
+ ctx.submit(message, {
740
+ invocation: skillCardInput(record, ctx.args, { kb, files: loaded.files.length, policy: !!policy }),
741
+ });
708
742
  },
709
743
  };
710
744
  }
@@ -17,7 +17,7 @@
17
17
  * file therefore holds ONE delegation and one line of deprecation text, and
18
18
  * `subagent-command.test.ts` asserts both (I-8).
19
19
  */
20
- import { runTeamCommand } from './team-command.js';
20
+ import { runTeamCommand, teamRendersInvocationCard } from './team-command.js';
21
21
  /**
22
22
  * Run `/team`, having first said out loud that this is the same thing.
23
23
  *
@@ -33,6 +33,8 @@ export function runSubagentCommand(ctx) {
33
33
  export function registerSubagentCommand(registry) {
34
34
  registry.register({
35
35
  name: 'subagent',
36
+ // A fresh object inherits nothing from `/team`: reference the SAME predicate (RV-5).
37
+ rendersInvocationCard: teamRendersInvocationCard,
36
38
  description: 'Deprecated alias of /team - same arguments',
37
39
  run: (ctx) => { runSubagentCommand(ctx); },
38
40
  });
@@ -43,6 +43,12 @@
43
43
  * `Team 4` chip would wait for an unrelated state change before appearing.
44
44
  */
45
45
  import type { CommandContext, CommandRegistry } from './registry.js';
46
+ /**
47
+ * Whether `/team <args>` ends in a card. The SAME function the command branches on
48
+ * (`readTeamIntent`), and shared by `/team` and the `/subagent` alias by reference: the
49
+ * alias builds a fresh object and inherits nothing (RV-5, I-8).
50
+ */
51
+ export declare function teamRendersInvocationCard(args: string): boolean;
46
52
  /** The command body; `registerTeamCommand` is the only registration site. */
47
53
  export declare function runTeamCommand(ctx: CommandContext): void;
48
54
  /** Registered from `builtins.ts` with one line, next to every other subsystem. */
@@ -43,7 +43,7 @@
43
43
  * `Team 4` chip would wait for an unrelated state change before appearing.
44
44
  */
45
45
  import { buildForcedDirective } from '../team/forced-dispatch.js';
46
- import { DEFAULT_FORCED_COUNT, planForced, planNotice, readTeamIntent, } from '../team/forced-mode.js';
46
+ import { DEFAULT_FORCED_COUNT, forcedCardNote, planForced, planNotice, readTeamIntent, } from '../team/forced-mode.js';
47
47
  import { subagentModelSummary } from '../ui/overlays/model-profile-state.js';
48
48
  /**
49
49
  * The subagent model line, phrased by the same authority the settings root row
@@ -199,6 +199,34 @@ function enterForcedMode(ctx) {
199
199
  ctx.notify('info', `Forced team mode on: ${adopted} subagents per turn. `
200
200
  + 'Your next message dispatches.');
201
201
  }
202
+ /**
203
+ * The card's raw material for `/team <brief>` (tui-invocation-cards section 3.3). The
204
+ * command line is always spelled `/team`, even when the user came in through the
205
+ * deprecated `/subagent` alias: the card names the canonical command.
206
+ */
207
+ function forcedCardInput(args, planned, note, ctx) {
208
+ const noun = planned.count === 1 ? 'subagent' : 'subagents';
209
+ const facts = [
210
+ planned.parts.length > 0 ? `parts ${planned.parts.join(', ')}` : `${planned.count} ${noun}`,
211
+ ...(planned.readOnly ? ['read-only'] : []),
212
+ ...(ctx.controller.getAgentMode() === 'plan' ? ['plan mode'] : []),
213
+ ];
214
+ return {
215
+ variant: 'team',
216
+ commandLine: args === '' ? '/team' : `/team ${args}`,
217
+ input: planned.brief,
218
+ facts,
219
+ ...(note !== undefined ? { note } : {}),
220
+ };
221
+ }
222
+ /**
223
+ * Whether `/team <args>` ends in a card. The SAME function the command branches on
224
+ * (`readTeamIntent`), and shared by `/team` and the `/subagent` alias by reference: the
225
+ * alias builds a fresh object and inherits nothing (RV-5, I-8).
226
+ */
227
+ export function teamRendersInvocationCard(args) {
228
+ return readTeamIntent(args).kind === 'brief';
229
+ }
202
230
  /** `/team [-n n|--parts a,b] [--read-only] <brief>`: arm and submit in one act. */
203
231
  function armAndSubmit(ctx, intent) {
204
232
  const team = ctx.controller.getTeamConfig();
@@ -209,7 +237,11 @@ function armAndSubmit(ctx, intent) {
209
237
  // directive names: the later turns reuse this count, so the first turn and the
210
238
  // rest of the session cannot disagree about how wide the fan-out is (D-7).
211
239
  ctx.controller.armForcedTeam(planned.count);
212
- ctx.notify('info', planNotice(planned, team));
240
+ // With cards on, the disclosure rides on the card (`forcedCardNote`, same source as
241
+ // `planNotice`); with them off this is the pre-card notice, byte for byte.
242
+ const cards = ctx.invocationCards !== false;
243
+ if (!cards)
244
+ ctx.notify('info', planNotice(planned, team));
213
245
  const directive = buildForcedDirective({
214
246
  brief: planned.brief,
215
247
  count: planned.count,
@@ -222,7 +254,11 @@ function armAndSubmit(ctx, intent) {
222
254
  });
223
255
  // `userInitiated: false`: a directive the user did not type belongs in neither
224
256
  // the prompt history nor the hint-fade counter (todo-plan-followthrough C-12).
225
- ctx.submit(directive, { userInitiated: false });
257
+ const note = forcedCardNote(planned, team);
258
+ ctx.submit(directive, {
259
+ userInitiated: false,
260
+ ...(cards ? { invocation: forcedCardInput(ctx.args, planned, note, ctx) } : {}),
261
+ });
226
262
  }
227
263
  /** The command body; `registerTeamCommand` is the only registration site. */
228
264
  export function runTeamCommand(ctx) {
@@ -253,6 +289,7 @@ export function runTeamCommand(ctx) {
253
289
  export function registerTeamCommand(registry) {
254
290
  registry.register({
255
291
  name: 'team',
292
+ rendersInvocationCard: teamRendersInvocationCard,
256
293
  description: 'Force team mode and start now: /team <brief>; /team [on|off|status]',
257
294
  run: (ctx) => { runTeamCommand(ctx); },
258
295
  });
@@ -151,6 +151,16 @@ export declare function getSessionsDir(): string;
151
151
  * a per-process run id and why retention is two-tier (§3.5.2 / RV-6).
152
152
  */
153
153
  export declare function getCompactionArchiveDir(): string;
154
+ /**
155
+ * `<home>/governance` - governance-mode run records (governance-mode 11.1 / 12.1).
156
+ *
157
+ * ITS OWN ROOT, for the reason `getCompactionArchiveDir` above records: `logs/`, `sessions/`
158
+ * and `skills/` are scan roots, and every extra directory inside one is another thing each
159
+ * walk has to recognise and skip. Derived from the same `resolution.root`, so the
160
+ * `ARAGON_HOME` / VITEST isolation contract at the top of this file covers it too.
161
+ * The caller creates it (0700 on POSIX); this function only names it.
162
+ */
163
+ export declare function getGovernanceDir(): string;
154
164
  /** `<home>` — parent of `skills/`, and where sidecar state such as usage lives. */
155
165
  export declare function getUserDataDir(): string;
156
166
  export declare function getUserSkillsDir(): string;
@@ -242,6 +242,18 @@ export function getSessionsDir() {
242
242
  export function getCompactionArchiveDir() {
243
243
  return join(resolution.root, 'compaction');
244
244
  }
245
+ /**
246
+ * `<home>/governance` - governance-mode run records (governance-mode 11.1 / 12.1).
247
+ *
248
+ * ITS OWN ROOT, for the reason `getCompactionArchiveDir` above records: `logs/`, `sessions/`
249
+ * and `skills/` are scan roots, and every extra directory inside one is another thing each
250
+ * walk has to recognise and skip. Derived from the same `resolution.root`, so the
251
+ * `ARAGON_HOME` / VITEST isolation contract at the top of this file covers it too.
252
+ * The caller creates it (0700 on POSIX); this function only names it.
253
+ */
254
+ export function getGovernanceDir() {
255
+ return join(resolution.root, 'governance');
256
+ }
245
257
  /** `<home>` — parent of `skills/`, and where sidecar state such as usage lives. */
246
258
  export function getUserDataDir() {
247
259
  return resolution.root;
@@ -96,6 +96,11 @@ export declare const UPDATE_CONFIG_SET_KEYS: readonly ["update.mode", "update.ch
96
96
  * persisted-off-survives-a-flagless-run check — runs exactly that command.
97
97
  */
98
98
  export declare const COMPACTION_CONFIG_SET_KEYS: readonly ["compaction.enabled", "compaction.threshold", "compaction.warnThreshold", "compaction.keepRecentTurns", "compaction.useFastTier", "compaction.onFailure", "compaction.subagents", "compaction.archive"];
99
+ /**
100
+ * Config keys under `governance.` that `aragon config set` accepts (governance-mode 11.1).
101
+ * Every key is writable and ONE level deep, so `runConfigGet`'s single-dot split resolves it.
102
+ */
103
+ export declare const GOVERNANCE_CONFIG_SET_KEYS: readonly ["governance.enabled", "governance.shiftTab", "governance.panel", "governance.profile", "governance.maxWorkPackages", "governance.maxPhases", "governance.maxRework", "governance.maxFixCycles", "governance.minAskRounds", "governance.budgetTokens", "governance.confirmCharter"];
99
104
  /**
100
105
  * Translate a `log.*` dotted key into a patch, or `null` for anything else.
101
106
  *
@@ -131,6 +136,19 @@ export declare function applyJobsConfigSet(key: string, value: string): Partial<
131
136
  * rather than silently mean `false`.
132
137
  */
133
138
  export declare function applyTaskSummaryConfigSet(key: string, value: string): Partial<PersistedConfig> | null;
139
+ /**
140
+ * Translate a `governance.*` dotted key into a patch, or `null` for anything else.
141
+ *
142
+ * EVERY KEY ROUTES THROUGH `clampGovernanceConfig`, so `config set governance.maxRework 9`
143
+ * stores 5 (the engine's `hardMaxRework`) and the caller echoes the STORED value. The string
144
+ * is turned into a number HERE, because the clamp deliberately repairs a string to the
145
+ * default (a hand-edited `"2"` has no defensible reading); an unparseable argument becomes
146
+ * `NaN`, which the clamp repairs to the default - the "typo changes nothing" rule.
147
+ *
148
+ * The patch is a PARTIAL section, safe only because `updatePersistedConfig` deep-merges
149
+ * `governance` (the ninth time that trap is recorded in `store.ts`).
150
+ */
151
+ export declare function applyGovernanceConfigSet(key: string, value: string): Partial<PersistedConfig> | null;
134
152
  /**
135
153
  * Translate a `team.*` dotted key into a patch, or `null` for anything else.
136
154
  *
@@ -14,7 +14,7 @@ import { getConfigBackupPath, getConfigPath, getHomeRoot, getLogsDir, getPromptH
14
14
  import { getHomeMigrationBreadcrumbPath } from './migrate-home.js';
15
15
  import { loadPersistedConfig, updatePersistedConfig } from './store.js';
16
16
  import { normalizeModelProfiles, validateModelProfiles } from './model-profiles.js';
17
- import { clampFastConfig, clampRetryConfig, clampCompactionConfig, clampTeamConfig, parseThresholdInput, clampUpdateConfig, coercePositiveInt, maskSecret, DEFAULT_FAST_CONFIG, DEFAULT_RETRY_CONFIG, DEFAULT_TEAM_CONFIG, DEFAULT_COMPACTION_CONFIG, DEFAULT_UPDATE_CONFIG, DEFAULT_JOBS_CONFIG, clampJobsConfig, } from './schema.js';
17
+ import { clampFastConfig, clampRetryConfig, clampCompactionConfig, clampTeamConfig, parseThresholdInput, clampUpdateConfig, coercePositiveInt, maskSecret, DEFAULT_FAST_CONFIG, DEFAULT_RETRY_CONFIG, DEFAULT_TEAM_CONFIG, DEFAULT_COMPACTION_CONFIG, DEFAULT_UPDATE_CONFIG, DEFAULT_JOBS_CONFIG, clampJobsConfig, clampGovernanceConfig, DEFAULT_GOVERNANCE_CONFIG, } from './schema.js';
18
18
  import { clampLogLevel } from '../logging/levels.js';
19
19
  /** Config keys under `log.` that `aragon config set` accepts. */
20
20
  export const LOG_CONFIG_SET_KEYS = [
@@ -167,6 +167,23 @@ export const COMPACTION_CONFIG_SET_KEYS = [
167
167
  'compaction.subagents',
168
168
  'compaction.archive',
169
169
  ];
170
+ /**
171
+ * Config keys under `governance.` that `aragon config set` accepts (governance-mode 11.1).
172
+ * Every key is writable and ONE level deep, so `runConfigGet`'s single-dot split resolves it.
173
+ */
174
+ export const GOVERNANCE_CONFIG_SET_KEYS = [
175
+ 'governance.enabled',
176
+ 'governance.shiftTab',
177
+ 'governance.panel',
178
+ 'governance.profile',
179
+ 'governance.maxWorkPackages',
180
+ 'governance.maxPhases',
181
+ 'governance.maxRework',
182
+ 'governance.maxFixCycles',
183
+ 'governance.minAskRounds',
184
+ 'governance.budgetTokens',
185
+ 'governance.confirmCharter',
186
+ ];
170
187
  function isTrue(value) {
171
188
  return value === 'true' || value === '1';
172
189
  }
@@ -255,6 +272,35 @@ export function applyTaskSummaryConfigSet(key, value) {
255
272
  return null;
256
273
  }
257
274
  }
275
+ /**
276
+ * Translate a `governance.*` dotted key into a patch, or `null` for anything else.
277
+ *
278
+ * EVERY KEY ROUTES THROUGH `clampGovernanceConfig`, so `config set governance.maxRework 9`
279
+ * stores 5 (the engine's `hardMaxRework`) and the caller echoes the STORED value. The string
280
+ * is turned into a number HERE, because the clamp deliberately repairs a string to the
281
+ * default (a hand-edited `"2"` has no defensible reading); an unparseable argument becomes
282
+ * `NaN`, which the clamp repairs to the default - the "typo changes nothing" rule.
283
+ *
284
+ * The patch is a PARTIAL section, safe only because `updatePersistedConfig` deep-merges
285
+ * `governance` (the ninth time that trap is recorded in `store.ts`).
286
+ */
287
+ export function applyGovernanceConfigSet(key, value) {
288
+ if (!GOVERNANCE_CONFIG_SET_KEYS.includes(key))
289
+ return null;
290
+ const field = key.slice('governance.'.length);
291
+ const typed = parseGovernanceArgument(field, value);
292
+ const clamped = clampGovernanceConfig({ ...DEFAULT_GOVERNANCE_CONFIG, [field]: typed });
293
+ return { governance: { [field]: clamped[field] } };
294
+ }
295
+ function parseGovernanceArgument(field, value) {
296
+ const kind = typeof DEFAULT_GOVERNANCE_CONFIG[field];
297
+ const trimmed = value.trim();
298
+ if (kind === 'boolean')
299
+ return isTrue(trimmed);
300
+ if (kind === 'number')
301
+ return trimmed === '' ? Number.NaN : Number(trimmed);
302
+ return trimmed;
303
+ }
258
304
  /**
259
305
  * Translate a `team.*` dotted key into a patch, or `null` for anything else.
260
306
  *
@@ -21,7 +21,8 @@
21
21
  * ARAGON_COMPACTION_ARCHIVE,
22
22
  * ARAGON_JOBS_ENABLED, ARAGON_JOBS_WAIT_SECONDS, ARAGON_JOBS_STALL_SECONDS,
23
23
  * ARAGON_JOBS_PERSIST_LOG, ARAGON_JOBS_NOTICE_STEER,
24
- * ARAGON_PROMPTS (the quick-prompt library's `enabled` switch, and only that).
24
+ * ARAGON_PROMPTS (the quick-prompt library's `enabled` switch, and only that),
25
+ * ARAGON_GOVERNANCE (a KILL switch: `0` disables governance mode, nothing enables it).
25
26
  *
26
27
  * READ ELSEWHERE, ON PURPOSE: `ARAGON_UPDATE_REGISTRY` and `npm_config_registry`
27
28
  * are resolved by `update/registry.ts::resolveRegistryUrl`, NOT here, because
@@ -21,7 +21,8 @@
21
21
  * ARAGON_COMPACTION_ARCHIVE,
22
22
  * ARAGON_JOBS_ENABLED, ARAGON_JOBS_WAIT_SECONDS, ARAGON_JOBS_STALL_SECONDS,
23
23
  * ARAGON_JOBS_PERSIST_LOG, ARAGON_JOBS_NOTICE_STEER,
24
- * ARAGON_PROMPTS (the quick-prompt library's `enabled` switch, and only that).
24
+ * ARAGON_PROMPTS (the quick-prompt library's `enabled` switch, and only that),
25
+ * ARAGON_GOVERNANCE (a KILL switch: `0` disables governance mode, nothing enables it).
25
26
  *
26
27
  * READ ELSEWHERE, ON PURPOSE: `ARAGON_UPDATE_REGISTRY` and `npm_config_registry`
27
28
  * are resolved by `update/registry.ts::resolveRegistryUrl`, NOT here, because
@@ -41,6 +42,7 @@ import process from 'node:process';
41
42
  import dotenv from 'dotenv';
42
43
  import { registerSecretsFrom } from '../logging/secret-registry.js';
43
44
  import { clampLogLevel } from '../logging/levels.js';
45
+ import { isGovernanceEnvDisabled } from './governance-config.js';
44
46
  import { clampContextWindow, clampMaxTokens, clampTheme, clampThinkingLevel, isAutoToken, parseThresholdInput, } from './schema.js';
45
47
  /**
46
48
  * Load a project `.env` from the given directory into `process.env` (existing
@@ -318,6 +320,13 @@ export function readEnvConfig() {
318
320
  enabled: prompts === '1' || prompts === 'true' || prompts === 'on' || prompts === 'yes',
319
321
  };
320
322
  }
323
+ // ARAGON_GOVERNANCE=0 is the governance-mode KILL switch (governance-mode 11.1): it can only
324
+ // switch `enabled` OFF, and it outranks the config file (the layers merge file < env). It is
325
+ // deliberately not a toggle - `ARAGON_GOVERNANCE=1` writes nothing, so an environment can
326
+ // never re-enable what the user's config or `--no-governance` turned off.
327
+ if (isGovernanceEnvDisabled(process.env)) {
328
+ partial.governance = { enabled: false };
329
+ }
321
330
  // ARAGON_TASK_SUMMARY is the header label's kill switch
322
331
  // (tui-shortcut-drawer-and-task-summary §4.8 / P2-7), and it maps `enabled` and
323
332
  // NOTHING ELSE - the same wording and the same reason as the block above. A
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Governance-mode configuration (governance-mode sections 11.1 / 13.2).
3
+ *
4
+ * LIVES IN ITS OWN FILE, NOT IN `schema.ts`: that file is far past the repo's
5
+ * 1000-line limit, and a section whose clamp depends on nothing else in it has no
6
+ * reason to grow it. `schema.ts` imports and re-exports everything below, so every
7
+ * importer still reaches the section through `config/schema.js`.
8
+ *
9
+ * SELF-CONTAINED ON PURPOSE. The integer/boolean helpers in `schema.ts` are private,
10
+ * and importing back from it would make a cycle (`schema.ts` re-exports this file).
11
+ * The two helpers here are four lines each.
12
+ *
13
+ * ASCII ONLY: `src/config/**` is inside the glyph scanner's scope.
14
+ */
15
+ import type { Posture } from '../governance/posture.js';
16
+ import { type ProfileId } from '../governance/types.js';
17
+ export interface GovernanceConfig {
18
+ /** `false` => the feature is absent: no tools, no prompt blocks, no posture. */
19
+ enabled: boolean;
20
+ /** `false` => Shift+Tab stays BUILD<->PLAN; `/gov` still works. */
21
+ shiftTab: boolean;
22
+ /** `false` => the status chip only, no legion panel. */
23
+ panel: boolean;
24
+ /** Domain profile that names the roles' focus areas. */
25
+ profile: ProfileId;
26
+ /** 1..8. Work packages per run. */
27
+ maxWorkPackages: number;
28
+ /** 1..6. Phases per run. */
29
+ maxPhases: number;
30
+ /** 1..5. Rework rounds per work package. */
31
+ maxRework: number;
32
+ /** 1..5. Fix cycles per phase. */
33
+ maxFixCycles: number;
34
+ /** 0..5. Question rounds before PLAN+GOVERN may submit a plan. */
35
+ minAskRounds: number;
36
+ /** 0..1_000_000_000. Token budget per run; `0` = unlimited. */
37
+ budgetTokens: number;
38
+ /** `true` => the user approves the run charter before any dispatch. */
39
+ confirmCharter: boolean;
40
+ }
41
+ export declare const DEFAULT_GOVERNANCE_CONFIG: GovernanceConfig;
42
+ type NumericKey = 'maxWorkPackages' | 'maxPhases' | 'maxRework' | 'maxFixCycles' | 'minAskRounds' | 'budgetTokens';
43
+ /** The numeric keys, in display order; shared with the settings and `config` surfaces. */
44
+ export declare const GOVERNANCE_NUMERIC_KEYS: readonly NumericKey[];
45
+ /** The inclusive range a numeric key is clamped to. */
46
+ export declare function governanceRangeOf(key: NumericKey): {
47
+ min: number;
48
+ max: number;
49
+ };
50
+ /**
51
+ * THE single gate for every governance-config read AND write, mirroring
52
+ * `clampTeamConfig` for the reason that one records: hardening only the read path
53
+ * leaves a bad value on disk that the read path then rewrites on every launch, which
54
+ * presents to the user as "my setting won't stick". Unknown keys are dropped.
55
+ */
56
+ export declare function clampGovernanceConfig(raw: unknown): GovernanceConfig;
57
+ /**
58
+ * `ARAGON_GOVERNANCE=0` is a KILL switch, not a toggle: it can only disable. Any other
59
+ * value (including `1`) is ignored, so an environment can never switch a feature ON that
60
+ * the user's config or a `--no-governance` flag turned off.
61
+ *
62
+ * Takes the env as a parameter so tests and `doctor` do not touch `process.env`.
63
+ */
64
+ export declare function isGovernanceEnvDisabled(env?: Readonly<Record<string, string | undefined>>): boolean;
65
+ /**
66
+ * The config-level reasons governance can be unavailable. A SUBSET of the
67
+ * `GovernanceUnavailableReason` vocabulary in `governance/copy.ts` (the controller adds
68
+ * `no_api_key`, `headless`, `restart_required` at runtime); the codes are spelled
69
+ * identically so the integration can unify the two without renaming anything.
70
+ */
71
+ export type GovernanceConfigUnavailableReason = 'disabled_config' | 'disabled_env' | 'team_off';
72
+ export type GovernanceConfigAvailability = {
73
+ ok: true;
74
+ } | {
75
+ ok: false;
76
+ reason: GovernanceConfigUnavailableReason;
77
+ };
78
+ /**
79
+ * Config-only availability, in precedence order: the environment kill switch first (it is
80
+ * the strongest), then the config key, then the team dependency. Pure: no I/O.
81
+ */
82
+ export declare function describeGovernanceConfigAvailability(config: {
83
+ governance?: Pick<GovernanceConfig, 'enabled'>;
84
+ team: {
85
+ enabled: boolean;
86
+ };
87
+ }, env?: Readonly<Record<string, string | undefined>>): GovernanceConfigAvailability;
88
+ /**
89
+ * Merge the `governance` section across the layers (defaults > file > env > flag).
90
+ *
91
+ * The environment and `--no-governance` layers can ONLY switch `enabled` off (they are kill
92
+ * switches), and they are applied last so nothing in the file can outvote them. The flag is a
93
+ * launch-only override: it is resolved here into the in-memory config and never reaches the
94
+ * store, which is what "not persisted" means.
95
+ */
96
+ export declare function resolveGovernanceConfig(layers: {
97
+ file?: unknown;
98
+ env?: unknown;
99
+ disableForLaunch?: boolean;
100
+ }): GovernanceConfig;
101
+ export interface InitialPostureInput {
102
+ /** `--govern`. */
103
+ govern?: boolean;
104
+ /** `--plan-govern`. Wins over `govern` if a programmatic caller passes both. */
105
+ planGovern?: boolean;
106
+ /** The already-resolved `--plan` / `planModeDefault` result (unchanged by governance). */
107
+ startInPlanMode: boolean;
108
+ governance: Pick<GovernanceConfig, 'enabled'>;
109
+ teamEnabled: boolean;
110
+ }
111
+ export interface InitialPostureResolution {
112
+ posture: Posture;
113
+ /** Set when a governance posture was requested but could not be honoured. */
114
+ degradedReason?: GovernanceConfigUnavailableReason;
115
+ }
116
+ /**
117
+ * The posture the session starts in. Governance flags win over `--plan` / `planModeDefault`
118
+ * (a user who asked for a governed run did not ask for a plain one); when governance is
119
+ * unavailable at the CONFIG level the request degrades to the classic posture the same launch
120
+ * would have had, and the reason is returned so the caller can say so instead of silently
121
+ * dropping the flag. Without a governance flag this is exactly `startInPlanMode ? 'plan' :
122
+ * 'build'`, so `--plan` behaviour is untouched.
123
+ */
124
+ export declare function resolveInitialPosture(input: InitialPostureInput, env?: Readonly<Record<string, string | undefined>>): InitialPostureResolution;
125
+ export {};