@aragon-agent/cli 0.6.44 → 0.6.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/README.md +69 -2
- package/dist/agent/controller.d.ts +69 -0
- package/dist/agent/controller.js +224 -11
- package/dist/agent/governance-view.d.ts +40 -0
- package/dist/agent/governance-view.js +40 -0
- package/dist/agent/governance-wiring.d.ts +162 -0
- package/dist/agent/governance-wiring.js +470 -0
- package/dist/agent/plan-prompt.d.ts +7 -0
- package/dist/agent/plan-prompt.js +2 -1
- package/dist/agent/reducer.d.ts +33 -1
- package/dist/agent/reducer.js +45 -9
- package/dist/agent/system-prompt.d.ts +19 -0
- package/dist/agent/system-prompt.js +9 -1
- package/dist/cli.js +45 -1
- package/dist/commands/builtins.js +10 -4
- package/dist/commands/governance-command.d.ts +35 -0
- package/dist/commands/governance-command.js +292 -0
- package/dist/commands/governance-runs-table.d.ts +40 -0
- package/dist/commands/governance-runs-table.js +130 -0
- package/dist/commands/registry.d.ts +12 -0
- package/dist/config/app-paths.d.ts +10 -0
- package/dist/config/app-paths.js +12 -0
- package/dist/config/cli-commands.d.ts +18 -0
- package/dist/config/cli-commands.js +47 -1
- package/dist/config/env.d.ts +2 -1
- package/dist/config/env.js +10 -1
- package/dist/config/governance-config.d.ts +125 -0
- package/dist/config/governance-config.js +164 -0
- package/dist/config/governance-launch.d.ts +71 -0
- package/dist/config/governance-launch.js +58 -0
- package/dist/config/load.d.ts +15 -0
- package/dist/config/load.js +26 -1
- package/dist/config/model-profile-store.d.ts +4 -2
- package/dist/config/schema.d.ts +22 -0
- package/dist/config/schema.js +6 -0
- package/dist/config/store.js +14 -1
- package/dist/config/ui-state.d.ts +11 -0
- package/dist/config/ui-state.js +11 -0
- package/dist/diagnostics/doctor.js +20 -0
- package/dist/governance/card-normalize.d.ts +24 -0
- package/dist/governance/card-normalize.js +76 -0
- package/dist/governance/copy.d.ts +109 -0
- package/dist/governance/copy.js +223 -0
- package/dist/governance/engine/aftermath.d.ts +49 -0
- package/dist/governance/engine/aftermath.js +134 -0
- package/dist/governance/engine/artifact-persist.d.ts +35 -0
- package/dist/governance/engine/artifact-persist.js +86 -0
- package/dist/governance/engine/budget.d.ts +52 -0
- package/dist/governance/engine/budget.js +112 -0
- package/dist/governance/engine/cards.d.ts +18 -0
- package/dist/governance/engine/cards.js +186 -0
- package/dist/governance/engine/digest.d.ts +32 -0
- package/dist/governance/engine/digest.js +63 -0
- package/dist/governance/engine/engine-core.d.ts +219 -0
- package/dist/governance/engine/engine-core.js +562 -0
- package/dist/governance/engine/engine.d.ts +68 -0
- package/dist/governance/engine/engine.js +314 -0
- package/dist/governance/engine/estimate.d.ts +38 -0
- package/dist/governance/engine/estimate.js +46 -0
- package/dist/governance/engine/inspector.d.ts +16 -0
- package/dist/governance/engine/inspector.js +396 -0
- package/dist/governance/engine/integration.d.ts +35 -0
- package/dist/governance/engine/integration.js +220 -0
- package/dist/governance/engine/lifecycle.d.ts +29 -0
- package/dist/governance/engine/lifecycle.js +656 -0
- package/dist/governance/engine/pause.d.ts +56 -0
- package/dist/governance/engine/pause.js +107 -0
- package/dist/governance/engine/phase-members.d.ts +15 -0
- package/dist/governance/engine/phase-members.js +34 -0
- package/dist/governance/engine/phase-planner.d.ts +53 -0
- package/dist/governance/engine/phase-planner.js +282 -0
- package/dist/governance/engine/rebuild.d.ts +27 -0
- package/dist/governance/engine/rebuild.js +57 -0
- package/dist/governance/engine/report.d.ts +66 -0
- package/dist/governance/engine/report.js +220 -0
- package/dist/governance/engine/run-digest.d.ts +20 -0
- package/dist/governance/engine/run-digest.js +42 -0
- package/dist/governance/engine/spec-builder.d.ts +117 -0
- package/dist/governance/engine/spec-builder.js +321 -0
- package/dist/governance/engine/stage-runner.d.ts +22 -0
- package/dist/governance/engine/stage-runner.js +664 -0
- package/dist/governance/engine/start-input.d.ts +19 -0
- package/dist/governance/engine/start-input.js +111 -0
- package/dist/governance/engine/state-machine.d.ts +101 -0
- package/dist/governance/engine/state-machine.js +586 -0
- package/dist/governance/engine/submission-queries.d.ts +42 -0
- package/dist/governance/engine/submission-queries.js +97 -0
- package/dist/governance/engine/submission-render.d.ts +12 -0
- package/dist/governance/engine/submission-render.js +92 -0
- package/dist/governance/engine/submissions.d.ts +27 -0
- package/dist/governance/engine/submissions.js +455 -0
- package/dist/governance/engine/visibility.d.ts +104 -0
- package/dist/governance/engine/visibility.js +223 -0
- package/dist/governance/governed-dispatch.d.ts +19 -0
- package/dist/governance/governed-dispatch.js +17 -0
- package/dist/governance/limits.d.ts +107 -0
- package/dist/governance/limits.js +131 -0
- package/dist/governance/posture-transition.d.ts +38 -0
- package/dist/governance/posture-transition.js +44 -0
- package/dist/governance/posture.d.ts +35 -0
- package/dist/governance/posture.js +59 -0
- package/dist/governance/profiles.d.ts +48 -0
- package/dist/governance/profiles.js +140 -0
- package/dist/governance/prompts/orchestrator-block.d.ts +40 -0
- package/dist/governance/prompts/orchestrator-block.js +128 -0
- package/dist/governance/prompts/plan-addendum.d.ts +22 -0
- package/dist/governance/prompts/plan-addendum.js +60 -0
- package/dist/governance/prompts/refusals.d.ts +48 -0
- package/dist/governance/prompts/refusals.js +82 -0
- package/dist/governance/prompts/role-blocks.d.ts +40 -0
- package/dist/governance/prompts/role-blocks.js +255 -0
- package/dist/governance/report-reader.d.ts +31 -0
- package/dist/governance/report-reader.js +57 -0
- package/dist/governance/roles.d.ts +83 -0
- package/dist/governance/roles.js +142 -0
- package/dist/governance/rules/claims.d.ts +83 -0
- package/dist/governance/rules/claims.js +250 -0
- package/dist/governance/rules/elimination.d.ts +66 -0
- package/dist/governance/rules/elimination.js +105 -0
- package/dist/governance/rules/events-table.d.ts +46 -0
- package/dist/governance/rules/events-table.js +94 -0
- package/dist/governance/rules/failure-analysis.d.ts +28 -0
- package/dist/governance/rules/failure-analysis.js +93 -0
- package/dist/governance/rules/ledger-replay.d.ts +53 -0
- package/dist/governance/rules/ledger-replay.js +53 -0
- package/dist/governance/rules/ledger-state.d.ts +85 -0
- package/dist/governance/rules/ledger-state.js +175 -0
- package/dist/governance/rules/ledger.d.ts +228 -0
- package/dist/governance/rules/ledger.js +560 -0
- package/dist/governance/rules/rca.d.ts +68 -0
- package/dist/governance/rules/rca.js +220 -0
- package/dist/governance/rules/settlement.d.ts +129 -0
- package/dist/governance/rules/settlement.js +363 -0
- package/dist/governance/rules/suspicion.d.ts +66 -0
- package/dist/governance/rules/suspicion.js +169 -0
- package/dist/governance/store/artifacts.d.ts +81 -0
- package/dist/governance/store/artifacts.js +173 -0
- package/dist/governance/store/atomic.d.ts +79 -0
- package/dist/governance/store/atomic.js +119 -0
- package/dist/governance/store/events-log.d.ts +35 -0
- package/dist/governance/store/events-log.js +86 -0
- package/dist/governance/store/run-lock.d.ts +51 -0
- package/dist/governance/store/run-lock.js +122 -0
- package/dist/governance/store/run-store.d.ts +229 -0
- package/dist/governance/store/run-store.js +644 -0
- package/dist/governance/store/scoreboard-export.d.ts +53 -0
- package/dist/governance/store/scoreboard-export.js +65 -0
- package/dist/governance/tools/child-tools.d.ts +31 -0
- package/dist/governance/tools/child-tools.js +65 -0
- package/dist/governance/tools/guard.d.ts +71 -0
- package/dist/governance/tools/guard.js +194 -0
- package/dist/governance/tools/inspector-tools.d.ts +63 -0
- package/dist/governance/tools/inspector-tools.js +424 -0
- package/dist/governance/tools/lead-tools.d.ts +42 -0
- package/dist/governance/tools/lead-tools.js +226 -0
- package/dist/governance/tools/normalize-util.d.ts +101 -0
- package/dist/governance/tools/normalize-util.js +230 -0
- package/dist/governance/tools/scan-incomplete.d.ts +79 -0
- package/dist/governance/tools/scan-incomplete.js +486 -0
- package/dist/governance/tools/shared-tools.d.ts +44 -0
- package/dist/governance/tools/shared-tools.js +125 -0
- package/dist/governance/tools/submit-normalizers.d.ts +28 -0
- package/dist/governance/tools/submit-normalizers.js +474 -0
- package/dist/governance/tools/submit-tools.d.ts +26 -0
- package/dist/governance/tools/submit-tools.js +171 -0
- package/dist/governance/types.d.ts +661 -0
- package/dist/governance/types.js +27 -0
- package/dist/session/validate-session.js +32 -1
- package/dist/team/runtime.d.ts +8 -0
- package/dist/team/runtime.js +9 -0
- package/dist/team/subagent.d.ts +23 -0
- package/dist/team/subagent.js +14 -3
- package/dist/team/types.d.ts +6 -0
- package/dist/tools/index.d.ts +30 -7
- package/dist/tools/index.js +14 -0
- package/dist/tools/plan-tools.d.ts +14 -2
- package/dist/tools/plan-tools.js +5 -2
- package/dist/ui/App.js +145 -25
- package/dist/ui/BottomStatusRow.js +1 -1
- package/dist/ui/Composer.d.ts +7 -1
- package/dist/ui/Composer.js +9 -6
- package/dist/ui/GovernancePanel.d.ts +50 -0
- package/dist/ui/GovernancePanel.js +77 -0
- package/dist/ui/GovernanceRun.d.ts +18 -0
- package/dist/ui/GovernanceRun.js +11 -0
- package/dist/ui/StatusBar.d.ts +15 -2
- package/dist/ui/StatusBar.js +10 -4
- package/dist/ui/Transcript.js +3 -0
- package/dist/ui/entries/GovernanceCard.d.ts +30 -0
- package/dist/ui/entries/GovernanceCard.js +32 -0
- package/dist/ui/governance-copy.d.ts +69 -0
- package/dist/ui/governance-copy.js +104 -0
- package/dist/ui/governance-status.d.ts +145 -0
- package/dist/ui/governance-status.js +326 -0
- package/dist/ui/interaction-copy.d.ts +4 -0
- package/dist/ui/interaction-copy.js +5 -0
- package/dist/ui/interaction-hints.d.ts +17 -0
- package/dist/ui/interaction-hints.js +14 -2
- package/dist/ui/layout/governance-board.d.ts +121 -0
- package/dist/ui/layout/governance-board.js +382 -0
- package/dist/ui/layout/governance-card.d.ts +53 -0
- package/dist/ui/layout/governance-card.js +134 -0
- package/dist/ui/layout/governance-chip.d.ts +38 -0
- package/dist/ui/layout/governance-chip.js +64 -0
- package/dist/ui/layout/governance-panel.d.ts +85 -0
- package/dist/ui/layout/governance-panel.js +358 -0
- package/dist/ui/layout/governance-roster.d.ts +65 -0
- package/dist/ui/layout/governance-roster.js +275 -0
- package/dist/ui/layout/status-detail-layout.js +3 -3
- package/dist/ui/layout/status-layout.d.ts +5 -2
- package/dist/ui/layout/status-layout.js +10 -6
- package/dist/ui/layout/virtual-window.js +11 -0
- package/dist/ui/overlays/GovernanceBoardOverlay.d.ts +41 -0
- package/dist/ui/overlays/GovernanceBoardOverlay.js +76 -0
- package/dist/ui/overlays/GovernanceSettingsPage.d.ts +48 -0
- package/dist/ui/overlays/GovernanceSettingsPage.js +93 -0
- package/dist/ui/overlays/HelpOverlay.js +4 -3
- package/dist/ui/overlays/QuestionOverlay.d.ts +9 -1
- package/dist/ui/overlays/QuestionOverlay.js +4 -2
- package/dist/ui/overlays/SettingsScreen.d.ts +7 -0
- package/dist/ui/overlays/SettingsScreen.js +21 -1
- package/dist/ui/overlays/governance-settings.d.ts +79 -0
- package/dist/ui/overlays/governance-settings.js +140 -0
- package/dist/ui/overlays/model-profile-state.d.ts +6 -1
- package/dist/ui/overlays/model-profile-state.js +10 -0
- package/dist/ui/palettes.d.ts +17 -0
- package/dist/ui/palettes.js +9 -0
- package/dist/ui/scrollback/live-preview.js +2 -0
- package/dist/ui/scrollback/settled-boundary.js +3 -0
- package/dist/ui/shortcuts.js +2 -2
- package/dist/ui/theme.d.ts +7 -0
- package/dist/ui/theme.js +1 -0
- package/dist/ui/transcript-text.js +9 -0
- package/dist/ui/use-wheel-routing.js +3 -1
- package/package.json +2 -2
package/dist/config/env.js
CHANGED
|
@@ -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 {};
|
|
@@ -0,0 +1,164 @@
|
|
|
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 process from 'node:process';
|
|
16
|
+
import { GOV_LIMITS } from '../governance/limits.js';
|
|
17
|
+
import { PROFILE_IDS } from '../governance/types.js';
|
|
18
|
+
export const DEFAULT_GOVERNANCE_CONFIG = {
|
|
19
|
+
enabled: true,
|
|
20
|
+
shiftTab: true,
|
|
21
|
+
panel: true,
|
|
22
|
+
profile: 'general',
|
|
23
|
+
maxWorkPackages: 4,
|
|
24
|
+
maxPhases: 3,
|
|
25
|
+
maxRework: 3,
|
|
26
|
+
maxFixCycles: 3,
|
|
27
|
+
minAskRounds: 2,
|
|
28
|
+
budgetTokens: 0,
|
|
29
|
+
confirmCharter: false,
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Inclusive range per numeric key. The upper bounds of the four structural keys are
|
|
33
|
+
* `GOV_LIMITS.hardMax*` (NOT repeated here), so the clamp and the engine can never
|
|
34
|
+
* disagree: a hand-edited `config.json` cannot exceed what the engine enforces.
|
|
35
|
+
*/
|
|
36
|
+
const NUMERIC_RANGES = {
|
|
37
|
+
maxWorkPackages: { min: 1, max: GOV_LIMITS.hardMaxWorkPackages },
|
|
38
|
+
maxPhases: { min: 1, max: GOV_LIMITS.hardMaxPhases },
|
|
39
|
+
maxRework: { min: 1, max: GOV_LIMITS.hardMaxRework },
|
|
40
|
+
maxFixCycles: { min: 1, max: GOV_LIMITS.hardMaxFixCycles },
|
|
41
|
+
minAskRounds: { min: 0, max: 5 },
|
|
42
|
+
budgetTokens: { min: 0, max: 1_000_000_000 },
|
|
43
|
+
};
|
|
44
|
+
/** The numeric keys, in display order; shared with the settings and `config` surfaces. */
|
|
45
|
+
export const GOVERNANCE_NUMERIC_KEYS = Object.keys(NUMERIC_RANGES);
|
|
46
|
+
/** The inclusive range a numeric key is clamped to. */
|
|
47
|
+
export function governanceRangeOf(key) {
|
|
48
|
+
return NUMERIC_RANGES[key];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Only a real, finite INTEGER survives. A float, NaN, a string ("2") or null is
|
|
52
|
+
* REPAIRED TO THE DEFAULT, not rounded or coerced: a hand-edited `maxRework: 2.5` has no
|
|
53
|
+
* defensible reading, and "typo changes nothing" is the discipline every sibling clamp
|
|
54
|
+
* follows. Out-of-range integers are clamped, not rejected.
|
|
55
|
+
*/
|
|
56
|
+
function clampRangedInt(value, key) {
|
|
57
|
+
const range = NUMERIC_RANGES[key];
|
|
58
|
+
const fallback = DEFAULT_GOVERNANCE_CONFIG[key];
|
|
59
|
+
if (typeof value !== 'number' || !Number.isInteger(value))
|
|
60
|
+
return fallback;
|
|
61
|
+
return Math.min(range.max, Math.max(range.min, value));
|
|
62
|
+
}
|
|
63
|
+
function pickBool(value, fallback) {
|
|
64
|
+
return typeof value === 'boolean' ? value : fallback;
|
|
65
|
+
}
|
|
66
|
+
function pickProfile(value) {
|
|
67
|
+
return typeof value === 'string' && PROFILE_IDS.includes(value)
|
|
68
|
+
? value
|
|
69
|
+
: DEFAULT_GOVERNANCE_CONFIG.profile;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* THE single gate for every governance-config read AND write, mirroring
|
|
73
|
+
* `clampTeamConfig` for the reason that one records: hardening only the read path
|
|
74
|
+
* leaves a bad value on disk that the read path then rewrites on every launch, which
|
|
75
|
+
* presents to the user as "my setting won't stick". Unknown keys are dropped.
|
|
76
|
+
*/
|
|
77
|
+
export function clampGovernanceConfig(raw) {
|
|
78
|
+
const src = (raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {});
|
|
79
|
+
const defaults = DEFAULT_GOVERNANCE_CONFIG;
|
|
80
|
+
return {
|
|
81
|
+
enabled: pickBool(src.enabled, defaults.enabled),
|
|
82
|
+
shiftTab: pickBool(src.shiftTab, defaults.shiftTab),
|
|
83
|
+
panel: pickBool(src.panel, defaults.panel),
|
|
84
|
+
profile: pickProfile(src.profile),
|
|
85
|
+
maxWorkPackages: clampRangedInt(src.maxWorkPackages, 'maxWorkPackages'),
|
|
86
|
+
maxPhases: clampRangedInt(src.maxPhases, 'maxPhases'),
|
|
87
|
+
maxRework: clampRangedInt(src.maxRework, 'maxRework'),
|
|
88
|
+
maxFixCycles: clampRangedInt(src.maxFixCycles, 'maxFixCycles'),
|
|
89
|
+
minAskRounds: clampRangedInt(src.minAskRounds, 'minAskRounds'),
|
|
90
|
+
budgetTokens: clampRangedInt(src.budgetTokens, 'budgetTokens'),
|
|
91
|
+
confirmCharter: pickBool(src.confirmCharter, defaults.confirmCharter),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// Environment kill switch + availability (config-level part)
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
/** The spellings of "off" the kill switch accepts, matching the other ARAGON_* switches. */
|
|
98
|
+
const ENV_OFF_VALUES = new Set(['0', 'false', 'off', 'no']);
|
|
99
|
+
/**
|
|
100
|
+
* `ARAGON_GOVERNANCE=0` is a KILL switch, not a toggle: it can only disable. Any other
|
|
101
|
+
* value (including `1`) is ignored, so an environment can never switch a feature ON that
|
|
102
|
+
* the user's config or a `--no-governance` flag turned off.
|
|
103
|
+
*
|
|
104
|
+
* Takes the env as a parameter so tests and `doctor` do not touch `process.env`.
|
|
105
|
+
*/
|
|
106
|
+
export function isGovernanceEnvDisabled(env = process.env) {
|
|
107
|
+
const value = env.ARAGON_GOVERNANCE?.trim().toLowerCase();
|
|
108
|
+
return value !== undefined && ENV_OFF_VALUES.has(value);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Config-only availability, in precedence order: the environment kill switch first (it is
|
|
112
|
+
* the strongest), then the config key, then the team dependency. Pure: no I/O.
|
|
113
|
+
*/
|
|
114
|
+
export function describeGovernanceConfigAvailability(config, env = process.env) {
|
|
115
|
+
if (isGovernanceEnvDisabled(env))
|
|
116
|
+
return { ok: false, reason: 'disabled_env' };
|
|
117
|
+
if (config.governance?.enabled === false)
|
|
118
|
+
return { ok: false, reason: 'disabled_config' };
|
|
119
|
+
if (!config.team.enabled)
|
|
120
|
+
return { ok: false, reason: 'team_off' };
|
|
121
|
+
return { ok: true };
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Launch resolution (load.ts calls these; kept here so load.ts barely grows)
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
/**
|
|
127
|
+
* Merge the `governance` section across the layers (defaults > file > env > flag).
|
|
128
|
+
*
|
|
129
|
+
* The environment and `--no-governance` layers can ONLY switch `enabled` off (they are kill
|
|
130
|
+
* switches), and they are applied last so nothing in the file can outvote them. The flag is a
|
|
131
|
+
* launch-only override: it is resolved here into the in-memory config and never reaches the
|
|
132
|
+
* store, which is what "not persisted" means.
|
|
133
|
+
*/
|
|
134
|
+
export function resolveGovernanceConfig(layers) {
|
|
135
|
+
return clampGovernanceConfig({
|
|
136
|
+
...DEFAULT_GOVERNANCE_CONFIG,
|
|
137
|
+
...(isPlainObject(layers.file) ? layers.file : {}),
|
|
138
|
+
...(isPlainObject(layers.env) ? layers.env : {}),
|
|
139
|
+
...(layers.disableForLaunch === true ? { enabled: false } : {}),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function isPlainObject(value) {
|
|
143
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The posture the session starts in. Governance flags win over `--plan` / `planModeDefault`
|
|
147
|
+
* (a user who asked for a governed run did not ask for a plain one); when governance is
|
|
148
|
+
* unavailable at the CONFIG level the request degrades to the classic posture the same launch
|
|
149
|
+
* would have had, and the reason is returned so the caller can say so instead of silently
|
|
150
|
+
* dropping the flag. Without a governance flag this is exactly `startInPlanMode ? 'plan' :
|
|
151
|
+
* 'build'`, so `--plan` behaviour is untouched.
|
|
152
|
+
*/
|
|
153
|
+
export function resolveInitialPosture(input, env = process.env) {
|
|
154
|
+
const classic = input.startInPlanMode ? 'plan' : 'build';
|
|
155
|
+
const requested = input.planGovern === true
|
|
156
|
+
? 'plan_govern'
|
|
157
|
+
: input.govern === true ? 'govern' : null;
|
|
158
|
+
if (requested === null)
|
|
159
|
+
return { posture: classic };
|
|
160
|
+
const availability = describeGovernanceConfigAvailability({ governance: input.governance, team: { enabled: input.teamEnabled } }, env);
|
|
161
|
+
return availability.ok
|
|
162
|
+
? { posture: requested }
|
|
163
|
+
: { posture: classic, degradedReason: availability.reason };
|
|
164
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command-line validation for the governance flags (governance-mode 11.2).
|
|
3
|
+
*
|
|
4
|
+
* PURE, AND OUT OF `cli.tsx` ON PURPOSE: that file is far past the size limit, and these four
|
|
5
|
+
* rules are exactly the kind that regress silently (a missing one lets `-p --govern` start a
|
|
6
|
+
* run that can never reach a human). `cli.tsx` only gathers the facts and prints the message.
|
|
7
|
+
*
|
|
8
|
+
* ASCII ONLY: `src/config/**` is inside the glyph scanner's scope.
|
|
9
|
+
*/
|
|
10
|
+
export interface GovernanceLaunchInput {
|
|
11
|
+
/** `--govern`. */
|
|
12
|
+
govern?: boolean;
|
|
13
|
+
/** `--plan-govern`. */
|
|
14
|
+
planGovern?: boolean;
|
|
15
|
+
/** `--plan` (`true` only when passed; `--no-plan` and silence are both falsy here). */
|
|
16
|
+
plan?: boolean;
|
|
17
|
+
/** `--no-team`. */
|
|
18
|
+
noTeam?: boolean;
|
|
19
|
+
/** `--no-governance`. */
|
|
20
|
+
noGovernance?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The run cannot reach a human: `-p/--print`, the `exec` subcommand, piped stdin or a
|
|
23
|
+
* non-TTY stdout. Governance needs `ask_user` and the review overlays, which headless
|
|
24
|
+
* runs deny wholesale.
|
|
25
|
+
*/
|
|
26
|
+
headless: boolean;
|
|
27
|
+
}
|
|
28
|
+
export type GovernanceLaunchCheck = {
|
|
29
|
+
ok: true;
|
|
30
|
+
} | {
|
|
31
|
+
ok: false;
|
|
32
|
+
message: string;
|
|
33
|
+
};
|
|
34
|
+
export declare const GOVERNANCE_EXCLUSIVE_MESSAGE = "--govern, --plan-govern and --plan are mutually exclusive. Pass only one of them.";
|
|
35
|
+
export declare const GOVERNANCE_HEADLESS_MESSAGE: string;
|
|
36
|
+
export declare const GOVERNANCE_NO_TEAM_MESSAGE: string;
|
|
37
|
+
export declare const GOVERNANCE_NO_GOVERNANCE_MESSAGE: string;
|
|
38
|
+
/**
|
|
39
|
+
* The first violated rule, or `{ ok: true }`. ORDER IS THE CONTRACT: the exclusivity error
|
|
40
|
+
* is the one a user typing three flags needs to see first, and the headless rule outranks
|
|
41
|
+
* `--no-team` because it is the one that cannot be fixed by dropping a second flag.
|
|
42
|
+
* Nothing is checked unless a governance posture was actually requested.
|
|
43
|
+
*/
|
|
44
|
+
export declare function validateGovernanceLaunch(input: GovernanceLaunchInput): GovernanceLaunchCheck;
|
|
45
|
+
/** The root-level options the rules read, as commander materialises them. */
|
|
46
|
+
export interface GovernanceRootOptions {
|
|
47
|
+
govern?: boolean;
|
|
48
|
+
planGovern?: boolean;
|
|
49
|
+
plan?: boolean;
|
|
50
|
+
/** `--team` / `--no-team`: only an explicit `false` is a refusal. */
|
|
51
|
+
team?: boolean;
|
|
52
|
+
/** `--no-governance` is declared alone, so this is `true` when absent and `false` when given. */
|
|
53
|
+
governance?: boolean;
|
|
54
|
+
print?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface GovernanceCommandContext {
|
|
57
|
+
/** The command about to run: `exec`, `config`, or the root command's own name. */
|
|
58
|
+
commandName: string;
|
|
59
|
+
/** `true` for the root command's own action (the TUI / `-p` entry), not a subcommand. */
|
|
60
|
+
isRootAction: boolean;
|
|
61
|
+
stdinIsTty: boolean;
|
|
62
|
+
stdoutIsTty: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The `preAction` hook's decision. `exec` is always headless; the root action is headless
|
|
66
|
+
* when `-p` was given or either stream is not a terminal (the TUI would refuse to start
|
|
67
|
+
* anyway, but it would do so AFTER a governance run had been promised). Other subcommands
|
|
68
|
+
* (`config`, `logs`, ...) never start a governed run, so only the flag-combination rules
|
|
69
|
+
* apply to them.
|
|
70
|
+
*/
|
|
71
|
+
export declare function checkGovernanceCommandLine(options: GovernanceRootOptions, context: GovernanceCommandContext): GovernanceLaunchCheck;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command-line validation for the governance flags (governance-mode 11.2).
|
|
3
|
+
*
|
|
4
|
+
* PURE, AND OUT OF `cli.tsx` ON PURPOSE: that file is far past the size limit, and these four
|
|
5
|
+
* rules are exactly the kind that regress silently (a missing one lets `-p --govern` start a
|
|
6
|
+
* run that can never reach a human). `cli.tsx` only gathers the facts and prints the message.
|
|
7
|
+
*
|
|
8
|
+
* ASCII ONLY: `src/config/**` is inside the glyph scanner's scope.
|
|
9
|
+
*/
|
|
10
|
+
export const GOVERNANCE_EXCLUSIVE_MESSAGE = '--govern, --plan-govern and --plan are mutually exclusive. Pass only one of them.';
|
|
11
|
+
export const GOVERNANCE_HEADLESS_MESSAGE = 'Governance mode needs an interactive terminal. It cannot be combined with -p/--print, '
|
|
12
|
+
+ 'the exec subcommand or piped input.';
|
|
13
|
+
export const GOVERNANCE_NO_TEAM_MESSAGE = '--govern and --plan-govern run their roles as team subagents, so they cannot be '
|
|
14
|
+
+ 'combined with --no-team. Remove --no-team to use governance mode.';
|
|
15
|
+
export const GOVERNANCE_NO_GOVERNANCE_MESSAGE = '--no-governance disables governance mode for this launch, so it cannot be combined with '
|
|
16
|
+
+ '--govern or --plan-govern.';
|
|
17
|
+
/**
|
|
18
|
+
* The first violated rule, or `{ ok: true }`. ORDER IS THE CONTRACT: the exclusivity error
|
|
19
|
+
* is the one a user typing three flags needs to see first, and the headless rule outranks
|
|
20
|
+
* `--no-team` because it is the one that cannot be fixed by dropping a second flag.
|
|
21
|
+
* Nothing is checked unless a governance posture was actually requested.
|
|
22
|
+
*/
|
|
23
|
+
export function validateGovernanceLaunch(input) {
|
|
24
|
+
const requested = input.govern === true || input.planGovern === true;
|
|
25
|
+
const exclusive = [input.govern === true, input.planGovern === true, input.plan === true];
|
|
26
|
+
if (exclusive.filter(Boolean).length > 1) {
|
|
27
|
+
return { ok: false, message: GOVERNANCE_EXCLUSIVE_MESSAGE };
|
|
28
|
+
}
|
|
29
|
+
if (!requested)
|
|
30
|
+
return { ok: true };
|
|
31
|
+
if (input.noGovernance === true)
|
|
32
|
+
return { ok: false, message: GOVERNANCE_NO_GOVERNANCE_MESSAGE };
|
|
33
|
+
if (input.headless)
|
|
34
|
+
return { ok: false, message: GOVERNANCE_HEADLESS_MESSAGE };
|
|
35
|
+
if (input.noTeam === true)
|
|
36
|
+
return { ok: false, message: GOVERNANCE_NO_TEAM_MESSAGE };
|
|
37
|
+
return { ok: true };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The `preAction` hook's decision. `exec` is always headless; the root action is headless
|
|
41
|
+
* when `-p` was given or either stream is not a terminal (the TUI would refuse to start
|
|
42
|
+
* anyway, but it would do so AFTER a governance run had been promised). Other subcommands
|
|
43
|
+
* (`config`, `logs`, ...) never start a governed run, so only the flag-combination rules
|
|
44
|
+
* apply to them.
|
|
45
|
+
*/
|
|
46
|
+
export function checkGovernanceCommandLine(options, context) {
|
|
47
|
+
const headless = context.commandName === 'exec'
|
|
48
|
+
|| (context.isRootAction
|
|
49
|
+
&& (options.print === true || !context.stdinIsTty || !context.stdoutIsTty));
|
|
50
|
+
return validateGovernanceLaunch({
|
|
51
|
+
govern: options.govern,
|
|
52
|
+
planGovern: options.planGovern,
|
|
53
|
+
plan: options.plan,
|
|
54
|
+
noTeam: options.team === false,
|
|
55
|
+
noGovernance: options.governance === false,
|
|
56
|
+
headless,
|
|
57
|
+
});
|
|
58
|
+
}
|
package/dist/config/load.d.ts
CHANGED
|
@@ -240,6 +240,21 @@ export interface CliFlags {
|
|
|
240
240
|
compaction?: boolean;
|
|
241
241
|
/** `--compaction-threshold <0..1|N%>` — session override for `threshold`. */
|
|
242
242
|
compactionThreshold?: string;
|
|
243
|
+
/**
|
|
244
|
+
* `--govern` / `--plan-govern` (governance-mode 11.2). Plain booleans: they only ever ask
|
|
245
|
+
* for a starting posture and are persisted nowhere, so unlike the pairs above there is no
|
|
246
|
+
* stored value for a commander default to overwrite. `cli.tsx` rejects the combinations
|
|
247
|
+
* (mutually exclusive, headless, `--no-team`) before this layer sees them.
|
|
248
|
+
*/
|
|
249
|
+
govern?: boolean;
|
|
250
|
+
planGovern?: boolean;
|
|
251
|
+
/**
|
|
252
|
+
* `--no-governance`, carried as `false` ONLY. A lone negative flag makes commander default
|
|
253
|
+
* its option to `true`, so `cli.tsx` forwards `undefined` for that case and nothing here can
|
|
254
|
+
* mistake silence for an override. Launch-only: it lands in the resolved `CliConfig` and is
|
|
255
|
+
* never written to the store.
|
|
256
|
+
*/
|
|
257
|
+
governance?: boolean;
|
|
243
258
|
/**
|
|
244
259
|
* `--resume <id|path>` - continue a saved session under a NEW id
|
|
245
260
|
* (tui-session-id-resume 4).
|
package/dist/config/load.js
CHANGED
|
@@ -15,6 +15,7 @@ import { getConfigPath } from './app-paths.js';
|
|
|
15
15
|
import { setHistoryEnabled } from './prompt-history.js';
|
|
16
16
|
import { setEntryRetain } from '../agent/entry-limits.js';
|
|
17
17
|
import { readSubmitCount } from './ui-state.js';
|
|
18
|
+
import { resolveGovernanceConfig, resolveInitialPosture } from './governance-config.js';
|
|
18
19
|
import { getLogger } from '../logging/logger.js';
|
|
19
20
|
import { registerSecret, registerSecretsFrom } from '../logging/secret-registry.js';
|
|
20
21
|
import { detectCapabilities, resolveTuiCapabilities } from '../ui/capabilities.js';
|
|
@@ -710,6 +711,28 @@ export function loadConfig(flags = {}, options = {}) {
|
|
|
710
711
|
// `viewReducer` is pure and takes no config, so the resolved ring cap reaches
|
|
711
712
|
// it through the same module-singleton channel `setHistoryEnabled` uses.
|
|
712
713
|
setEntryRetain(transcriptRetain);
|
|
714
|
+
// Governance: file < env (kill switch) < `--no-governance`, clamped like every section. The
|
|
715
|
+
// initial posture is resolved against the SAME team value the config carries, and a request
|
|
716
|
+
// that cannot be honoured degrades to the classic posture with a log record, never silently.
|
|
717
|
+
const governance = resolveGovernanceConfig({
|
|
718
|
+
file: file.governance,
|
|
719
|
+
env: env.partial.governance,
|
|
720
|
+
disableForLaunch: flags.governance === false,
|
|
721
|
+
});
|
|
722
|
+
const team = resolveTeamConfig(flags, env.partial, file);
|
|
723
|
+
const posture = resolveInitialPosture({
|
|
724
|
+
govern: flags.govern,
|
|
725
|
+
planGovern: flags.planGovern,
|
|
726
|
+
startInPlanMode,
|
|
727
|
+
governance,
|
|
728
|
+
teamEnabled: team.enabled,
|
|
729
|
+
});
|
|
730
|
+
const initialPosture = posture.posture;
|
|
731
|
+
if (posture.degradedReason !== undefined) {
|
|
732
|
+
getLogger().warn('config', 'governance_initial_posture_degraded', {
|
|
733
|
+
reason: posture.degradedReason,
|
|
734
|
+
});
|
|
735
|
+
}
|
|
713
736
|
const config = {
|
|
714
737
|
modelProfiles: projection.issues.length ? undefined : file.modelProfiles,
|
|
715
738
|
provider,
|
|
@@ -768,7 +791,7 @@ export function loadConfig(flags = {}, options = {}) {
|
|
|
768
791
|
: {}),
|
|
769
792
|
},
|
|
770
793
|
log: resolveLogConfig(flags, env.partial, file),
|
|
771
|
-
team
|
|
794
|
+
team,
|
|
772
795
|
todo: resolveTodoConfig(flags, env.partial, file),
|
|
773
796
|
retry: resolveRetryConfig(flags, env.partial, file),
|
|
774
797
|
fast: resolveFastConfig(flags, env.partial, file),
|
|
@@ -790,6 +813,8 @@ export function loadConfig(flags = {}, options = {}) {
|
|
|
790
813
|
// `taskSummary.enabled: false` cannot arrive as two different shapes.
|
|
791
814
|
taskSummary: clampTaskSummaryConfig({ ...DEFAULT_CONFIG.taskSummary,
|
|
792
815
|
...(env.partial.taskSummary ?? {}), ...(file.taskSummary ?? {}) }),
|
|
816
|
+
governance,
|
|
817
|
+
initialPosture,
|
|
793
818
|
cwd,
|
|
794
819
|
color,
|
|
795
820
|
colorLevel,
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { type ModelProfilesConfig, type ModelRole, type ProfileValidationIssue } from './model-profiles.js';
|
|
2
2
|
import type { SessionKitState } from './model-kits.js';
|
|
3
|
-
import type { CliConfig, CompactionConfig, FastConfig, LogConfig, PersistedConfig, TeamConfig } from './schema.js';
|
|
4
|
-
export interface ModelSettingsPatch extends Partial<Omit<PersistedConfig, 'modelProfiles' | 'fast' | 'compaction' | 'log' | 'team'>> {
|
|
3
|
+
import type { CliConfig, CompactionConfig, FastConfig, GovernanceConfig, LogConfig, PersistedConfig, TeamConfig } from './schema.js';
|
|
4
|
+
export interface ModelSettingsPatch extends Partial<Omit<PersistedConfig, 'modelProfiles' | 'fast' | 'compaction' | 'log' | 'team' | 'governance'>> {
|
|
5
5
|
fast?: Partial<FastConfig>;
|
|
6
6
|
compaction?: Partial<CompactionConfig>;
|
|
7
7
|
log?: Partial<LogConfig>;
|
|
8
8
|
/** The subagent-model picker writes here (subagent-model D-5/I-5): draft-only until Save. */
|
|
9
9
|
team?: Partial<TeamConfig>;
|
|
10
|
+
/** Governance writers (`config set`, `/gov budget`) send single keys; the store clamps. */
|
|
11
|
+
governance?: Partial<GovernanceConfig>;
|
|
10
12
|
}
|
|
11
13
|
export interface ModelSettingsDraft {
|
|
12
14
|
profiles?: ModelProfilesConfig;
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { type RetryPolicy, type ThinkingLevel } from '@aragon-agent/core';
|
|
9
9
|
import { type LogLevelName } from '../logging/levels.js';
|
|
10
|
+
import { type GovernanceConfig } from './governance-config.js';
|
|
11
|
+
import type { Posture } from '../governance/posture.js';
|
|
10
12
|
import type { FollowThroughMode } from '../todo/types.js';
|
|
13
|
+
export { clampGovernanceConfig, DEFAULT_GOVERNANCE_CONFIG, type GovernanceConfig, } from './governance-config.js';
|
|
11
14
|
/**
|
|
12
15
|
* `ModelRegistry` seeds builtin lists for five providers, but `initProviders()`
|
|
13
16
|
* registers only three adapters. Running a model whose provider has no adapter
|
|
@@ -1146,6 +1149,8 @@ export interface PersistedConfig {
|
|
|
1146
1149
|
prompts: PromptsConfig;
|
|
1147
1150
|
/** The header task label. The THIRTEENTH; two scalars (see TaskSummaryConfig). */
|
|
1148
1151
|
taskSummary: TaskSummaryConfig;
|
|
1152
|
+
/** Governance mode. The FOURTEENTH; scalars only (see GovernanceConfig). */
|
|
1153
|
+
governance: GovernanceConfig;
|
|
1149
1154
|
}
|
|
1150
1155
|
export declare const DEFAULT_CONFIG: PersistedConfig;
|
|
1151
1156
|
/**
|
|
@@ -1534,6 +1539,23 @@ export interface CliConfig {
|
|
|
1534
1539
|
* switched-off feature.
|
|
1535
1540
|
*/
|
|
1536
1541
|
taskSummary?: TaskSummaryConfig;
|
|
1542
|
+
/**
|
|
1543
|
+
* Governance mode (governance-mode 11.1). The FOURTEENTH nested object; scalars only.
|
|
1544
|
+
*
|
|
1545
|
+
* OPTIONAL HERE FOR THE SAME REASON AS `prompts` / `taskSummary` ABOVE: `CliConfig` is built
|
|
1546
|
+
* by hand in many fixtures, `loadConfig` always fills it, and readers treat a missing
|
|
1547
|
+
* section as the documented defaults. `enabled` here (after env kill switch and
|
|
1548
|
+
* `--no-governance`) decides whether governance tools are REGISTERED, once at construction.
|
|
1549
|
+
*/
|
|
1550
|
+
governance?: GovernanceConfig;
|
|
1551
|
+
/**
|
|
1552
|
+
* The posture the session starts in (governance-mode 11.2): `--plan` / `planModeDefault`
|
|
1553
|
+
* still decide `startInPlanMode` exactly as before, and `--govern` / `--plan-govern` win over
|
|
1554
|
+
* them when governance is available. Optional on this shape for the fixture reason above;
|
|
1555
|
+
* `loadConfig` always fills it. Without a governance flag it is `'plan'` when
|
|
1556
|
+
* `startInPlanMode`, else `'build'`.
|
|
1557
|
+
*/
|
|
1558
|
+
initialPosture?: Posture;
|
|
1537
1559
|
/**
|
|
1538
1560
|
* Lifetime submit count driving the composer hint fade (`HINT_FADE_AFTER`).
|
|
1539
1561
|
*
|
package/dist/config/schema.js
CHANGED
|
@@ -9,6 +9,9 @@ import { isAbsolute } from 'node:path';
|
|
|
9
9
|
import { ABSOLUTE_MAX_OUTPUT_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_RETRY_POLICY, MIN_MAX_OUTPUT_TOKENS, RETRY_LIMITS, } from '@aragon-agent/core';
|
|
10
10
|
import { clampLogLevel } from '../logging/levels.js';
|
|
11
11
|
import { TEAM_LIMITS } from '../team/limits.js';
|
|
12
|
+
import { DEFAULT_GOVERNANCE_CONFIG } from './governance-config.js';
|
|
13
|
+
// Governance mode (governance-mode 11.1): defined in its own file so this one does not grow.
|
|
14
|
+
export { clampGovernanceConfig, DEFAULT_GOVERNANCE_CONFIG, } from './governance-config.js';
|
|
12
15
|
// ---------------------------------------------------------------------------
|
|
13
16
|
// Provider set — only the adapter-backed providers are usable at run time (R5).
|
|
14
17
|
// ---------------------------------------------------------------------------
|
|
@@ -1194,6 +1197,9 @@ export const DEFAULT_CONFIG = {
|
|
|
1194
1197
|
// `config list`, so the file would report a section it never wrote. One line
|
|
1195
1198
|
// here, like the seven above it.
|
|
1196
1199
|
taskSummary: DEFAULT_TASK_SUMMARY_CONFIG,
|
|
1200
|
+
// And one section later again. Without this line a `config.json` predating governance
|
|
1201
|
+
// resolves `governance` to `undefined`; every reader would then disagree with `config list`.
|
|
1202
|
+
governance: DEFAULT_GOVERNANCE_CONFIG,
|
|
1197
1203
|
};
|
|
1198
1204
|
/**
|
|
1199
1205
|
* Runtime state that used to be stored in `config.json` by mistake
|
package/dist/config/store.js
CHANGED
|
@@ -17,7 +17,7 @@ import { getConfigPath, getSessionsDir } from './app-paths.js';
|
|
|
17
17
|
import { registerProfileSecrets, registerSecretsFrom } from '../logging/secret-registry.js';
|
|
18
18
|
import { adaptLegacyConnectionPatch, ModelProfileConfigError, readModelSettingsDisk } from './model-profile-store.js';
|
|
19
19
|
import { normalizeModelProfiles } from './model-profiles.js';
|
|
20
|
-
import { clampBashConfig, clampJobsConfig, clampPromptsConfig, clampTaskSummaryConfig, CONFIG_VERSION, DEFAULT_CONFIG, clampCompactionConfig, clampFastConfig, clampLogConfig, clampMaxTokens, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampContextWindow, clampUpdateConfig, isAutoToken, stripLegacyStateKeys, stripRetiredConfigKeys, } from './schema.js';
|
|
20
|
+
import { clampBashConfig, clampJobsConfig, clampPromptsConfig, clampTaskSummaryConfig, CONFIG_VERSION, DEFAULT_CONFIG, clampCompactionConfig, clampFastConfig, clampGovernanceConfig, clampLogConfig, clampMaxTokens, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampContextWindow, clampUpdateConfig, isAutoToken, stripLegacyStateKeys, stripRetiredConfigKeys, } from './schema.js';
|
|
21
21
|
/**
|
|
22
22
|
* Normalize `maxTokens` for both directions of the config file.
|
|
23
23
|
*
|
|
@@ -213,6 +213,13 @@ export function normalizePersistedConfig(input) {
|
|
|
213
213
|
...DEFAULT_CONFIG.taskSummary,
|
|
214
214
|
...(partial.taskSummary ?? {}),
|
|
215
215
|
}),
|
|
216
|
+
// And the fourteenth. The READ half supplies a whole section to every user whose
|
|
217
|
+
// `config.json` predates governance, and clamps a hand-edited one: the file cannot
|
|
218
|
+
// carry a `maxRework` the engine would refuse.
|
|
219
|
+
governance: clampGovernanceConfig({
|
|
220
|
+
...DEFAULT_CONFIG.governance,
|
|
221
|
+
...(partial.governance ?? {}),
|
|
222
|
+
}),
|
|
216
223
|
};
|
|
217
224
|
}
|
|
218
225
|
/**
|
|
@@ -334,6 +341,12 @@ export function mergePersistedConfig(current, patch) {
|
|
|
334
341
|
// that must never happen is a FAILED summary call landing on "show nothing"
|
|
335
342
|
// because a switch the user never touched defaulted away.
|
|
336
343
|
taskSummary: clampTaskSummaryConfig({ ...current.taskSummary, ...(patch.taskSummary ?? {}) }),
|
|
344
|
+
// The fourteenth section, and the ninth time this file records the same trap.
|
|
345
|
+
// `aragon config set governance.maxRework 9` sends `{ governance: { maxRework: 9 } }`;
|
|
346
|
+
// without this merge the shallow spread REPLACES the section and `enabled` is written
|
|
347
|
+
// absent, and without the clamp 9 reaches the disk and the engine's ceiling is the
|
|
348
|
+
// only thing that stops it. The WRITE half of the two-direction gate.
|
|
349
|
+
governance: clampGovernanceConfig({ ...current.governance, ...(patch.governance ?? {}) }),
|
|
337
350
|
};
|
|
338
351
|
return merged;
|
|
339
352
|
}
|