@kal-elsam/kairo-runtime 0.7.0 → 0.9.0

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 (42) hide show
  1. package/README.md +43 -11
  2. package/global-template/components/catalog.json +4 -1
  3. package/global-template/components/orchestrator/extensions/pi/kairo-minion.js +604 -0
  4. package/package.json +1 -1
  5. package/scripts/cockpit-smoke.mjs +4 -4
  6. package/src/cli.js +34 -2
  7. package/src/global/adapters/pi.js +1 -1
  8. package/src/global/global-doctor.js +2 -0
  9. package/src/global/ink/cockpit/primitives.js +96 -31
  10. package/src/global/ink/cockpit-alerts.js +36 -0
  11. package/src/global/ink/cockpit-changes.js +59 -35
  12. package/src/global/ink/cockpit-control-center.js +129 -51
  13. package/src/global/ink/cockpit-controller.js +58 -11
  14. package/src/global/ink/cockpit-focus.js +4 -2
  15. package/src/global/ink/cockpit-models.js +89 -47
  16. package/src/global/ink/cockpit-palette.js +98 -0
  17. package/src/global/ink/cockpit-path-label.js +19 -0
  18. package/src/global/ink/cockpit-recovery.js +78 -15
  19. package/src/global/ink/cockpit-reviews.js +14 -10
  20. package/src/global/ink/cockpit-runs.js +13 -4
  21. package/src/global/ink/cockpit-settings.js +194 -0
  22. package/src/global/ink/cockpit-views.js +88 -57
  23. package/src/global/ink/orchestrator-app.js +137 -46
  24. package/src/global/ink/orchestrator-state.js +24 -14
  25. package/src/global/ink/use-orchestrator-data.js +58 -0
  26. package/src/global/paths.js +3 -0
  27. package/src/global/runtime/alerts/alert-store.js +216 -0
  28. package/src/global/runtime/alerts/alert-types.js +59 -0
  29. package/src/global/runtime/alerts/alert-validate.js +117 -0
  30. package/src/global/runtime/execution-adapters/pi.js +12 -2
  31. package/src/global/runtime/monitor/monitor-cli.js +62 -0
  32. package/src/global/runtime/monitor/monitor-platform.js +95 -0
  33. package/src/global/runtime/monitor/monitor.js +249 -0
  34. package/src/global/runtime/orchestration/index.js +23 -0
  35. package/src/global/runtime/orchestration/orch-receipts.js +234 -0
  36. package/src/global/runtime/orchestration/orch-types.js +173 -0
  37. package/src/global/runtime/orchestration/orch-validate.js +63 -0
  38. package/src/global/runtime/run-cli.js +1 -0
  39. package/src/global/runtime/run-manager.js +59 -4
  40. package/src/global/runtime/run-strategy.js +71 -0
  41. package/src/global/runtime/run-supervisor.js +22 -2
  42. package/src/global/runtime/run-types.js +5 -1
@@ -1,20 +1,27 @@
1
1
  import { CONTROL_PLANE_HEALTH } from "../control-plane-snapshot.js";
2
- import { formatProposalLines, proposalLimitForLayout } from "./cockpit-proposals.js";
2
+ import { formatAlertsHeadline } from "./cockpit-alerts.js";
3
3
 
4
4
  export function buildControlCenterModel({
5
5
  projectName = "project",
6
6
  snapshot = null,
7
- layoutMode = "compact"
7
+ dashboard = null,
8
+ layoutMode = "compact",
9
+ alerts = null
8
10
  } = {}) {
9
11
  if (!snapshot) {
10
12
  return {
11
- title: `CONTROL CENTER — ${projectName}`,
12
- purpose: "Kairo aligns installed IDEs and agents with this project's architecture, rules, tools, and workflows.",
13
+ title: `OVERVIEW — ${projectName}`,
14
+ purpose: "",
13
15
  health: {
14
16
  kind: CONTROL_PLANE_HEALTH.CHECK_FAILED,
15
17
  label: "CHECK FAILED",
16
18
  summaryLine: "Control-plane scan not available yet."
17
19
  },
20
+ status: {
21
+ kind: CONTROL_PLANE_HEALTH.CHECK_FAILED,
22
+ label: "CHECK FAILED",
23
+ summaryLine: "Control-plane scan not available yet."
24
+ },
18
25
  coverageLines: [],
19
26
  cta: {
20
27
  title: "NEXT",
@@ -24,54 +31,66 @@ export function buildControlCenterModel({
24
31
  kind: "verify",
25
32
  destination: null
26
33
  },
34
+ nextAction: {
35
+ title: "NEXT",
36
+ actionTitle: "Retry scan",
37
+ actionDetail: "Press R to reload the read-only governance scan.",
38
+ enterHint: "R Retry",
39
+ kind: "verify",
40
+ destination: null
41
+ },
27
42
  notes: [],
28
- proposalLines: ["No evidence-backed proposals."],
29
- includeEmbeddedStatus: layoutMode !== "wide"
43
+ proposalLines: [],
44
+ activity: { headline: "No activity yet" },
45
+ alerts: formatAlertsHeadline(alerts),
46
+ tokens: { headline: "Data unavailable" },
47
+ includeEmbeddedStatus: layoutMode !== "wide",
48
+ runsSecondaryHint: "Detail via Enter · / actions"
30
49
  };
31
50
  }
32
51
 
33
52
  const healthLabel = formatHealthLabel(snapshot.health);
34
53
  const coverage = snapshot.coverage ?? {};
35
- const policy = snapshot.policy;
36
- const warnings = snapshot.status?.counts?.warning ?? 0;
54
+ const active = dashboard?.activeRuns?.length ?? snapshot.runtime?.activeRuns ?? 0;
55
+ const recent = dashboard?.recentRuns?.[0] ?? null;
56
+ const health = {
57
+ kind: snapshot.health,
58
+ label: healthLabel,
59
+ summaryLine: [
60
+ `${coverage.governedAgents ?? 0}/${coverage.detectedAgents ?? 0} agents governed`,
61
+ snapshot.diff?.hasChanges ? "drift pending" : "drift clean"
62
+ ].join(" · ")
63
+ };
64
+ const cta = {
65
+ title: "NEXT",
66
+ actionTitle: snapshot.cta?.title ?? "Review control plane",
67
+ actionDetail: snapshot.cta?.detail ?? "",
68
+ enterHint: "Enter again →",
69
+ kind: snapshot.cta?.kind ?? null,
70
+ destination: snapshot.cta?.destination ?? null
71
+ };
37
72
 
38
73
  return {
39
- title: `CONTROL CENTER — ${projectName}`,
40
- purpose: "Kairo aligns installed IDEs and agents with this project's architecture, rules, tools, and workflows.",
41
- health: {
42
- kind: snapshot.health,
43
- label: healthLabel,
44
- summaryLine: [
45
- `${coverage.governedAgents ?? 0}/${coverage.detectedAgents ?? 0} agents governed`,
46
- `${coverage.components ?? 0} modules`,
47
- `${snapshot.backups?.count ?? 0} backups`
48
- ].join(" · ")
49
- },
50
- coverageLines: [
51
- `Active modules: ${(coverage.activeModules ?? []).join(", ") || "none"}`,
52
- `Policy: ${policy?.profile ?? "none"} · applyMode ${policy?.applyMode ?? "n/a"}`,
53
- warnings > 0
54
- ? `Notes: ${warnings} non-blocking check warning(s)`
55
- : "Notes: none",
56
- snapshot.diff?.hasChanges
57
- ? `Drift: ${snapshot.diff.changeCount ?? snapshot.diff.changes?.length ?? 0} change(s) pending review`
58
- : "Drift: clean"
59
- ],
60
- cta: {
61
- title: "NEXT",
62
- actionTitle: snapshot.cta?.title ?? "Review control plane",
63
- actionDetail: snapshot.cta?.detail ?? "",
64
- enterHint: "Enter again →",
65
- kind: snapshot.cta?.kind ?? null,
66
- destination: snapshot.cta?.destination ?? null
74
+ title: `OVERVIEW — ${projectName}`,
75
+ purpose: "",
76
+ health,
77
+ status: health,
78
+ coverageLines: [],
79
+ cta,
80
+ nextAction: cta,
81
+ notes: [],
82
+ proposalLines: [],
83
+ activity: {
84
+ headline: active > 0
85
+ ? `${active} active run${active === 1 ? "" : "s"}`
86
+ : recent?.agentId
87
+ ? `Last · ${recent.agentId} · ${recent.state ?? "done"}`
88
+ : "Idle"
67
89
  },
68
- notes: buildNotes(snapshot),
69
- proposalLines: formatProposalLines(snapshot.proposals ?? [], {
70
- limit: proposalLimitForLayout(layoutMode),
71
- budgets: snapshot.budgets ?? null
72
- }),
90
+ alerts: formatAlertsHeadline(alerts),
91
+ tokens: { headline: formatTokenHeadline(snapshot.budgets) },
73
92
  includeEmbeddedStatus: layoutMode !== "wide",
74
- runsSecondaryHint: "Runs remain available as a secondary capability after setup and repairs."
93
+ runsSecondaryHint: "Detail via Enter · / actions"
75
94
  };
76
95
  }
77
96
 
@@ -92,15 +111,74 @@ function formatHealthLabel(kind) {
92
111
  }
93
112
  }
94
113
 
95
- function buildNotes(snapshot) {
96
- const notes = [];
97
- for (const check of snapshot.status?.checks ?? []) {
98
- if (check.status === "warning") {
99
- notes.push(`${check.name}: ${check.detail ?? check.status}`);
100
- }
114
+ function formatTokenHeadline(budgets) {
115
+ if (!budgets || typeof budgets !== "object") return "Data unavailable";
116
+ const parts = [];
117
+ if (Number.isFinite(budgets.stableUsedTokens) && Number.isFinite(budgets.stableBudgetTokens)) {
118
+ parts.push(`stable ${budgets.stableUsedTokens}/${budgets.stableBudgetTokens}`);
101
119
  }
102
- if (notes.length === 0 && snapshot.health === CONTROL_PLANE_HEALTH.HEALTHY_WITH_NOTES) {
103
- notes.push("Non-blocking notes are present. Open IDEs & models or Harness modules for detail.");
120
+ if (Number.isFinite(budgets.requestUsedTokens) && Number.isFinite(budgets.requestBudgetTokens)) {
121
+ parts.push(`request ${budgets.requestUsedTokens}/${budgets.requestBudgetTokens}`);
104
122
  }
105
- return notes.slice(0, 6);
123
+ return parts.length > 0 ? parts.join(" · ") : "Data unavailable";
124
+ }
125
+
126
+ /**
127
+ * Usage surface: measured budgets when present, configured profile limits,
128
+ * and auditable run tokenUsage — never invent totals.
129
+ */
130
+ function resolveProfileLimits(dashboard) {
131
+ const resolved = dashboard?.profile?.profile ?? {};
132
+ const configured = [];
133
+ if (Number.isFinite(resolved.tokenBudget)) configured.push(`token ${resolved.tokenBudget}`);
134
+ if (Number.isFinite(resolved.stableContextBudget)) configured.push(`stable ${resolved.stableContextBudget}`);
135
+ if (Number.isFinite(resolved.requestContextBudget)) configured.push(`request ${resolved.requestContextBudget}`);
136
+ return configured;
137
+ }
138
+
139
+ function hasFiniteUsage(usage) {
140
+ if (!usage || typeof usage !== "object") return false;
141
+ return Number.isFinite(usage.total)
142
+ || Number.isFinite(usage.input)
143
+ || Number.isFinite(usage.output);
144
+ }
145
+
146
+ function formatRunUsageLine(run) {
147
+ const usage = run.tokenUsage;
148
+ const parts = [];
149
+ if (Number.isFinite(usage.input)) parts.push(`in ${usage.input}`);
150
+ if (Number.isFinite(usage.output)) parts.push(`out ${usage.output}`);
151
+ if (Number.isFinite(usage.total)) parts.push(`total ${usage.total}`);
152
+ return `${run.agentId ?? "agent"} · ${parts.join(" · ")}`;
153
+ }
154
+
155
+ export function formatUsageLines({ snapshot = null, dashboard = null } = {}) {
156
+ const lines = ["MEASURED"];
157
+ const measured = formatTokenHeadline(snapshot?.budgets);
158
+ lines.push(measured === "Data unavailable" ? "Data unavailable" : measured);
159
+
160
+ const configured = resolveProfileLimits(dashboard);
161
+ lines.push("", "CONFIGURED LIMITS");
162
+ lines.push(configured.length > 0 ? configured.join(" · ") : "No profile token budgets configured.");
163
+
164
+ const runs = [...(dashboard?.activeRuns ?? []), ...(dashboard?.recentRuns ?? [])]
165
+ .filter((run) => hasFiniteUsage(run?.tokenUsage));
166
+ lines.push("", "RUN USAGE");
167
+ if (runs.length === 0) {
168
+ lines.push("No auditable run tokenUsage yet.");
169
+ } else {
170
+ for (const run of runs.slice(0, 3)) {
171
+ lines.push(formatRunUsageLine(run));
172
+ }
173
+ }
174
+
175
+ lines.push("", "Auditable budgets only — no invented token savings.");
176
+ return lines;
177
+ }
178
+
179
+ export function hasAuditableUsage({ snapshot = null, dashboard = null } = {}) {
180
+ if (formatTokenHeadline(snapshot?.budgets) !== "Data unavailable") return true;
181
+ if (resolveProfileLimits(dashboard).length > 0) return true;
182
+ return [...(dashboard?.activeRuns ?? []), ...(dashboard?.recentRuns ?? [])]
183
+ .some((run) => hasFiniteUsage(run?.tokenUsage));
106
184
  }
@@ -33,7 +33,9 @@ export function createCockpitUiState({
33
33
  navIndex = 0,
34
34
  listIndex = 0,
35
35
  helpOpen = false,
36
- returnView = null
36
+ returnView = null,
37
+ paletteOpen = false,
38
+ paletteIndex = 0
37
39
  } = {}) {
38
40
  const regions = regionsForLayout(layoutMode);
39
41
  const preferred = region ?? defaultRegionForView(view, layoutMode);
@@ -48,12 +50,54 @@ export function createCockpitUiState({
48
50
  listIndex: Math.max(0, listIndex),
49
51
  helpOpen,
50
52
  returnView,
53
+ paletteOpen,
54
+ paletteIndex: Math.max(0, paletteIndex),
51
55
  shouldExit: false
52
56
  };
53
57
  }
54
58
 
59
+ function closePalette(state) {
60
+ return { ...state, paletteOpen: false, paletteIndex: 0 };
61
+ }
62
+
55
63
  export function reduceCockpitUi(state, action) {
56
64
  switch (action.type) {
65
+ case "toggle-palette":
66
+ if (state.paletteOpen) return closePalette(state);
67
+ return { ...state, paletteOpen: true, paletteIndex: 0, helpOpen: false };
68
+ case "close-palette":
69
+ return closePalette(state);
70
+ case "palette-arrow": {
71
+ const max = Math.max(0, (action.listLength ?? 1) - 1);
72
+ const delta = action.direction === "up" ? -1 : 1;
73
+ return {
74
+ ...state,
75
+ paletteIndex: clamp(state.paletteIndex + delta, 0, max)
76
+ };
77
+ }
78
+ case "run-palette": {
79
+ const next = closePalette(state);
80
+ if (action.kind === "help") {
81
+ return {
82
+ ...next,
83
+ helpOpen: true,
84
+ view: ORCHESTRATOR_VIEWS.HELP,
85
+ region: defaultRegionForView(ORCHESTRATOR_VIEWS.HELP, state.layoutMode)
86
+ };
87
+ }
88
+ if (action.kind === "navigate" && action.view) {
89
+ return {
90
+ ...next,
91
+ view: action.view,
92
+ navIndex: navIndexForView(action.view),
93
+ listIndex: 0,
94
+ region: defaultRegionForView(action.view, state.layoutMode),
95
+ helpOpen: false,
96
+ returnView: null
97
+ };
98
+ }
99
+ return next;
100
+ }
57
101
  case "resize": {
58
102
  const regions = regionsForLayout(action.layoutMode);
59
103
  const preferred = regions.includes(state.region)
@@ -95,18 +139,18 @@ export function reduceCockpitUi(state, action) {
95
139
  case "enter-nav": {
96
140
  const item = COCKPIT_NAV[state.navIndex];
97
141
  if (!item) return state;
98
- return {
142
+ return closePalette({
99
143
  ...state,
100
144
  view: item.view,
101
145
  listIndex: 0,
102
146
  region: defaultRegionForView(item.view, state.layoutMode),
103
147
  helpOpen: false,
104
148
  returnView: null
105
- };
149
+ });
106
150
  }
107
151
  case "set-view": {
108
152
  const nextView = action.view;
109
- return {
153
+ return closePalette({
110
154
  ...state,
111
155
  view: nextView,
112
156
  listIndex: 0,
@@ -116,19 +160,22 @@ export function reduceCockpitUi(state, action) {
116
160
  region: action.region ?? defaultRegionForView(nextView, state.layoutMode),
117
161
  returnView: action.returnView ?? state.returnView,
118
162
  helpOpen: nextView === ORCHESTRATOR_VIEWS.HELP
119
- };
163
+ });
120
164
  }
121
165
  case "toggle-help":
122
166
  if (state.helpOpen || state.view === ORCHESTRATOR_VIEWS.HELP) {
123
167
  return goOverview(state);
124
168
  }
125
- return {
169
+ return closePalette({
126
170
  ...state,
127
171
  helpOpen: true,
128
172
  view: ORCHESTRATOR_VIEWS.HELP,
129
173
  region: defaultRegionForView(ORCHESTRATOR_VIEWS.HELP, state.layoutMode)
130
- };
174
+ });
131
175
  case "escape": {
176
+ if (state.paletteOpen) {
177
+ return closePalette(state);
178
+ }
132
179
  if (state.helpOpen || state.view === ORCHESTRATOR_VIEWS.HELP) {
133
180
  return goOverview(state);
134
181
  }
@@ -174,7 +221,7 @@ export function resolveNavAction(navIndex) {
174
221
  }
175
222
 
176
223
  function goOverview(state) {
177
- return {
224
+ return closePalette({
178
225
  ...state,
179
226
  helpOpen: false,
180
227
  view: ORCHESTRATOR_VIEWS.HOME,
@@ -182,11 +229,11 @@ function goOverview(state) {
182
229
  listIndex: 0,
183
230
  region: defaultRegionForView(ORCHESTRATOR_VIEWS.HOME, state.layoutMode),
184
231
  returnView: null
185
- };
232
+ });
186
233
  }
187
234
 
188
235
  function goRunsHub(state) {
189
- return {
236
+ return closePalette({
190
237
  ...state,
191
238
  helpOpen: false,
192
239
  view: ORCHESTRATOR_VIEWS.RUNS,
@@ -194,5 +241,5 @@ function goRunsHub(state) {
194
241
  listIndex: 0,
195
242
  region: defaultRegionForView(ORCHESTRATOR_VIEWS.RUNS, state.layoutMode),
196
243
  returnView: null
197
- };
244
+ });
198
245
  }
@@ -7,9 +7,9 @@ const NAV_FOCUSED_VIEWS = new Set([
7
7
  ORCHESTRATOR_VIEWS.IDES,
8
8
  ORCHESTRATOR_VIEWS.MODULES,
9
9
  ORCHESTRATOR_VIEWS.CHANGES,
10
- ORCHESTRATOR_VIEWS.PROFILE,
11
10
  ORCHESTRATOR_VIEWS.PROVIDERS,
12
11
  ORCHESTRATOR_VIEWS.DIAGNOSTICS,
12
+ ORCHESTRATOR_VIEWS.USAGE,
13
13
  ORCHESTRATOR_VIEWS.HELP
14
14
  ]);
15
15
 
@@ -20,8 +20,10 @@ const CONTENT_INTERACTIVE_VIEWS = new Set([
20
20
  ORCHESTRATOR_VIEWS.RUN_DETAIL,
21
21
  ORCHESTRATOR_VIEWS.REVIEWS,
22
22
  ORCHESTRATOR_VIEWS.REVIEW_DETAIL,
23
+ ORCHESTRATOR_VIEWS.ALERTS,
23
24
  ORCHESTRATOR_VIEWS.LAUNCH,
24
- ORCHESTRATOR_VIEWS.ACTIVITY
25
+ ORCHESTRATOR_VIEWS.ACTIVITY,
26
+ ORCHESTRATOR_VIEWS.PROFILE
25
27
  ]);
26
28
 
27
29
  export function isNavFocusedView(view) {
@@ -7,6 +7,7 @@ import { buildHomeMissionModel, formatHomeRecentRun } from "./cockpit-home.js";
7
7
  import { isRunsBranchView } from "./cockpit-runs.js";
8
8
  import { buildChangesFooterParts } from "./cockpit-changes.js";
9
9
  import { buildRecoveryFooterParts } from "./cockpit-recovery.js";
10
+ import { buildSettingsFooterParts, SETTINGS_PHASE } from "./cockpit-settings.js";
10
11
 
11
12
  export const COCKPIT_REGIONS = {
12
13
  NAV: "nav",
@@ -17,53 +18,45 @@ export const COCKPIT_REGIONS = {
17
18
  export const COCKPIT_NAV = [
18
19
  {
19
20
  id: "overview",
20
- label: "Control center",
21
+ label: "Overview",
21
22
  view: ORCHESTRATOR_VIEWS.HOME,
22
- description: "Coverage, integrity, and the next governance action."
23
+ description: "Status, next action, activity, alerts, and tokens."
23
24
  },
24
25
  {
25
- id: "ides",
26
- label: "IDEs & models",
27
- view: ORCHESTRATOR_VIEWS.IDES,
28
- description: "Detected agents, auth signals, capabilities, and recommended policy."
29
- },
30
- {
31
- id: "modules",
32
- label: "Harness modules",
33
- view: ORCHESTRATOR_VIEWS.MODULES,
34
- description: "Orchestrator, SDD/TDD, and external Engram/Graphify integrations."
35
- },
36
- {
37
- id: "changes",
38
- label: "Changes",
26
+ id: "governance",
27
+ label: "Governance",
39
28
  view: ORCHESTRATOR_VIEWS.CHANGES,
40
- description: "Findings, drift, and exact preview before any write."
29
+ description: "Repair drift and apply governed changes."
41
30
  },
42
31
  {
43
32
  id: "activity",
44
- label: "Activity & recovery",
33
+ label: "Activity",
45
34
  view: ORCHESTRATOR_VIEWS.ACTIVITY,
46
- description: "Kairo operations, backups, and rollback readiness."
35
+ description: "Operations, backups, and recovery."
47
36
  },
48
37
  {
49
- id: "profile",
50
- label: "Profile & policy",
51
- view: ORCHESTRATOR_VIEWS.PROFILE,
52
- description: "Defaults, scopes, consent, and precedence."
38
+ id: "orchestration",
39
+ label: "Orchestration",
40
+ view: ORCHESTRATOR_VIEWS.RUNS,
41
+ description: "Runs, reviews, and supervised execution."
53
42
  },
54
43
  {
55
- id: "runs",
56
- label: "Runs",
57
- view: ORCHESTRATOR_VIEWS.RUNS,
58
- description: "Optional supervised execution Active, History, and New run."
44
+ id: "usage",
45
+ label: "Usage",
46
+ view: ORCHESTRATOR_VIEWS.USAGE,
47
+ description: "Token and context pressure when auditable."
48
+ },
49
+ {
50
+ id: "settings",
51
+ label: "Settings",
52
+ view: ORCHESTRATOR_VIEWS.PROFILE,
53
+ description: "Profile, policy, and guided configuration."
59
54
  }
60
55
  ];
61
56
 
62
57
  export function regionsForLayout(layoutMode) {
63
- if (layoutMode === LAYOUT_MODES.WIDE) {
64
- return [COCKPIT_REGIONS.NAV, COCKPIT_REGIONS.CONTENT, COCKPIT_REGIONS.SYSTEM];
65
- }
66
- if (layoutMode === LAYOUT_MODES.COMPACT) {
58
+ // Single main panel: nav strip + content. SYSTEM column retired from the shell.
59
+ if (layoutMode === LAYOUT_MODES.WIDE || layoutMode === LAYOUT_MODES.COMPACT) {
67
60
  return [COCKPIT_REGIONS.NAV, COCKPIT_REGIONS.CONTENT];
68
61
  }
69
62
  return [COCKPIT_REGIONS.CONTENT];
@@ -71,8 +64,8 @@ export function regionsForLayout(layoutMode) {
71
64
 
72
65
  export function navIndexForView(view, items = COCKPIT_NAV) {
73
66
  if (isRunsBranchView(view)) {
74
- const runsIndex = items.findIndex((item) => item.id === "runs");
75
- return runsIndex >= 0 ? runsIndex : 0;
67
+ const orchIndex = items.findIndex((item) => item.id === "orchestration");
68
+ return orchIndex >= 0 ? orchIndex : 0;
76
69
  }
77
70
  const index = items.findIndex((item) => item.view === view);
78
71
  return index >= 0 ? index : 0;
@@ -119,18 +112,40 @@ export function resolveNavStatusSummary(item, {
119
112
  diagnostics,
120
113
  dashboard
121
114
  }).label;
115
+ case "governance":
116
+ return changes > 0 ? `${changes} pending` : "Clean";
117
+ case "activity":
118
+ return backups > 0 ? `${backups} backups` : "No backups";
119
+ case "orchestration":
120
+ return active === 0 ? "Idle" : `${active} active`;
121
+ case "usage": {
122
+ if (Number.isFinite(snapshot?.budgets?.stableUsedTokens)) return "Auditable";
123
+ const resolved = dashboard?.profile?.profile ?? {};
124
+ if (Number.isFinite(resolved.tokenBudget)
125
+ || Number.isFinite(resolved.stableContextBudget)
126
+ || Number.isFinite(resolved.requestContextBudget)) {
127
+ return "Auditable";
128
+ }
129
+ const runs = [...(dashboard?.activeRuns ?? []), ...(dashboard?.recentRuns ?? [])];
130
+ return runs.some((run) => {
131
+ const u = run?.tokenUsage;
132
+ return u && typeof u === "object"
133
+ && (Number.isFinite(u.total) || Number.isFinite(u.input) || Number.isFinite(u.output));
134
+ })
135
+ ? "Auditable"
136
+ : "n/a";
137
+ }
138
+ case "settings":
139
+ return snapshot?.policy?.profile ?? "defaults";
122
140
  case "ides":
123
141
  return `${governed}/${detected} governed`;
124
142
  case "modules":
125
143
  return `${snapshot?.coverage?.components ?? 0} modules`;
126
144
  case "changes":
127
145
  return changes > 0 ? `${changes} pending` : "Clean";
128
- case "activity":
129
- return backups > 0 ? `${backups} backups` : "No backups";
130
146
  case "profile":
131
147
  return snapshot?.policy?.profile ?? "defaults";
132
148
  case "runs":
133
- return active === 0 ? "Idle" : `${active} active`;
134
149
  case "active":
135
150
  return active === 0 ? "Idle" : `${active} active`;
136
151
  case "providers":
@@ -159,7 +174,7 @@ export function buildNavModel({
159
174
  const mapped = items.map((item, index) => {
160
175
  const isSelected = index === navIndex;
161
176
  const isCurrent = item.view === currentView
162
- || (item.id === "runs" && isRunsBranchView(currentView));
177
+ || (item.id === "orchestration" && isRunsBranchView(currentView));
163
178
  return {
164
179
  ...item,
165
180
  marker: isSelected ? glyphs.focus : (isCurrent ? glyphs.bullet : " "),
@@ -222,45 +237,70 @@ export function buildFooterModel({
222
237
  region = COCKPIT_REGIONS.NAV,
223
238
  navIndex = 0,
224
239
  helpOpen = false,
240
+ paletteOpen = false,
225
241
  canCancel = false,
226
242
  unicode = true,
227
243
  hasError = false,
228
244
  changesPhase = null,
229
- recoveryPhase = null
245
+ recoveryPhase = null,
246
+ settingsPhase = null,
247
+ columns = 80
230
248
  } = {}) {
231
249
  const glyphs = resolveGlyphs(unicode);
232
250
  const parts = [];
251
+ const footerColumns = Math.max(24, Math.min(Number(columns) || 80, 120));
233
252
 
234
253
  if (hasError) {
235
254
  parts.push("R Retry");
236
255
  parts.push("Esc Exit");
237
- return { text: parts.join(` ${glyphs.bullet} `) };
256
+ return { text: parts.join(` ${glyphs.bullet} `), columns: footerColumns };
257
+ }
258
+
259
+ if (paletteOpen) {
260
+ return {
261
+ text: ["↑↓ Select", "Enter Run", "Esc Close"].join(` ${glyphs.bullet} `),
262
+ columns: footerColumns
263
+ };
238
264
  }
239
265
 
240
266
  if (helpOpen || view === ORCHESTRATOR_VIEWS.HELP) {
241
267
  parts.push("Esc close help");
242
268
  parts.push("? Help");
243
- return { text: parts.join(` ${glyphs.bullet} `) };
269
+ return { text: parts.join(` ${glyphs.bullet} `), columns: footerColumns };
244
270
  }
245
271
 
246
272
  if (view === ORCHESTRATOR_VIEWS.RUN_DETAIL) {
247
273
  parts.push("R refresh");
248
274
  if (canCancel) parts.push("C cancel");
249
275
  parts.push("Esc Back");
250
- return { text: parts.join(` ${glyphs.bullet} `) };
276
+ return { text: parts.join(` ${glyphs.bullet} `), columns: footerColumns };
251
277
  }
252
278
 
253
279
  if (view === ORCHESTRATOR_VIEWS.REVIEW_DETAIL) {
254
280
  parts.push("Esc Back");
255
- return { text: parts.join(` ${glyphs.bullet} `) };
281
+ return { text: parts.join(` ${glyphs.bullet} `), columns: footerColumns };
256
282
  }
257
283
 
258
284
  if (view === ORCHESTRATOR_VIEWS.CHANGES) {
259
- return { text: buildChangesFooterParts(changesPhase).join(` ${glyphs.bullet} `) };
285
+ return {
286
+ text: buildChangesFooterParts(changesPhase).join(` ${glyphs.bullet} `),
287
+ columns: footerColumns
288
+ };
260
289
  }
261
290
 
262
291
  if (view === ORCHESTRATOR_VIEWS.ACTIVITY) {
263
- return { text: buildRecoveryFooterParts(recoveryPhase).join(` ${glyphs.bullet} `) };
292
+ return {
293
+ text: buildRecoveryFooterParts(recoveryPhase).join(` ${glyphs.bullet} `),
294
+ columns: footerColumns
295
+ };
296
+ }
297
+
298
+ if (view === ORCHESTRATOR_VIEWS.PROFILE) {
299
+ return {
300
+ text: buildSettingsFooterParts(settingsPhase ?? SETTINGS_PHASE.BROWSE)
301
+ .join(` ${glyphs.bullet} `),
302
+ columns: footerColumns
303
+ };
264
304
  }
265
305
 
266
306
  parts.push("↑↓ Navigate");
@@ -275,14 +315,15 @@ export function buildFooterModel({
275
315
  parts.push("Tab Region");
276
316
  }
277
317
 
278
- const activatesControlCenterCta = view === ORCHESTRATOR_VIEWS.HOME && navIndex === 0;
279
- if (activatesControlCenterCta) {
318
+ const activatesOverviewCta = view === ORCHESTRATOR_VIEWS.HOME && navIndex === 0;
319
+ if (activatesOverviewCta) {
280
320
  parts.push("Enter Activate");
281
321
  } else if (view === ORCHESTRATOR_VIEWS.IDES
282
322
  || view === ORCHESTRATOR_VIEWS.MODULES
283
323
  || view === ORCHESTRATOR_VIEWS.PROFILE
284
324
  || view === ORCHESTRATOR_VIEWS.PROVIDERS
285
325
  || view === ORCHESTRATOR_VIEWS.DIAGNOSTICS
326
+ || view === ORCHESTRATOR_VIEWS.USAGE
286
327
  || region === COCKPIT_REGIONS.NAV
287
328
  || view === ORCHESTRATOR_VIEWS.RUNS
288
329
  || view === ORCHESTRATOR_VIEWS.ACTIVE_RUNS
@@ -295,9 +336,10 @@ export function buildFooterModel({
295
336
  }
296
337
 
297
338
  parts.push("? Help");
339
+ parts.push("/ Actions");
298
340
  parts.push(view === ORCHESTRATOR_VIEWS.HOME ? "Esc Exit" : "Esc Back");
299
341
 
300
- return { text: parts.join(` ${glyphs.bullet} `) };
342
+ return { text: parts.join(` ${glyphs.bullet} `), columns: footerColumns };
301
343
  }
302
344
 
303
345
  export function windowLinesForLayout(lines = [], layoutMode = LAYOUT_MODES.COMPACT, contentRows = 12) {