@kal-elsam/kairo-runtime 0.10.0 → 0.11.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kal-elsam/kairo-runtime",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Kairo Runtime — local agent operating system for Codex, Cursor, Claude, Pi, Engram, and Graphify.",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/Kal-elSam/harness#readme",
@@ -26,7 +26,7 @@ const root = join(dirname(fileURLToPath(import.meta.url)), "..");
26
26
  const require = createRequire(import.meta.url);
27
27
  const pkg = require(join(root, "package.json"));
28
28
 
29
- assert.equal(pkg.version, "0.10.0");
29
+ assert.equal(pkg.version, "0.11.0");
30
30
  assert.ok(pkg.dependencies["ansi-escapes"]);
31
31
 
32
32
  assert.equal(resolveLayoutMode({ columns: 120, rows: 40 }), LAYOUT_MODES.WIDE);
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Static ASCII wordmark for Kairo Overview — no figlet dependency.
3
+ * Hero art appears only on Overview (wide / compact); minimal stays textual.
4
+ */
5
+
6
+ import { LAYOUT_MODES } from "../layout.js";
7
+
8
+ const WORDMARK_WIDE = [
9
+ "╦╔═╔═╗╦╦═╗╔═╗",
10
+ "╠╩╗╠═╣║╠╦╝║ ║",
11
+ "╩ ╩╩ ╩╩╩╚═╚═╝"
12
+ ];
13
+
14
+ const WORDMARK_COMPACT = [
15
+ "╦╔═╔═╗╦╦═╗╔═╗",
16
+ "╩ ╩╩ ╩╩╩╚═╚═╝"
17
+ ];
18
+
19
+ const WORDMARK_WIDE_ASCII = [
20
+ "K A I R O",
21
+ "========="
22
+ ];
23
+
24
+ const WORDMARK_COMPACT_ASCII = [
25
+ "KAIRO"
26
+ ];
27
+
28
+ export function shouldShowWordmark(layoutMode) {
29
+ return layoutMode === LAYOUT_MODES.WIDE || layoutMode === LAYOUT_MODES.COMPACT;
30
+ }
31
+
32
+ /**
33
+ * @param {"wide"|"compact"|"minimal"|string} layoutMode
34
+ * @param {{ unicode?: boolean }} [opts]
35
+ * @returns {string[]}
36
+ */
37
+ export function wordmarkLines(layoutMode, { unicode = true } = {}) {
38
+ if (layoutMode === LAYOUT_MODES.WIDE) {
39
+ return unicode ? WORDMARK_WIDE.slice() : WORDMARK_WIDE_ASCII.slice();
40
+ }
41
+ if (layoutMode === LAYOUT_MODES.COMPACT) {
42
+ return unicode ? WORDMARK_COMPACT.slice() : WORDMARK_COMPACT_ASCII.slice();
43
+ }
44
+ return [];
45
+ }
46
+
47
+ export function overviewBrandTitle(layoutMode) {
48
+ if (shouldShowWordmark(layoutMode)) return null;
49
+ return "KAIRO · Overview";
50
+ }
@@ -12,7 +12,7 @@ export function CockpitEmptyState({ title, message, hint, colorEnabled = true })
12
12
  return React.createElement(Box, { flexDirection: "column", marginY: 1 },
13
13
  title && React.createElement(Text, {
14
14
  bold: true,
15
- color: resolveInkColor(colorEnabled, COCKPIT_COLORS.secondary)
15
+ color: resolveInkColor(colorEnabled, COCKPIT_COLORS.brand)
16
16
  }, title),
17
17
  message && React.createElement(Text, null, message),
18
18
  hint && React.createElement(Text, {
@@ -21,23 +21,20 @@ export function CockpitEmptyState({ title, message, hint, colorEnabled = true })
21
21
  );
22
22
  }
23
23
 
24
+ /** Content region — no border; focus is conveyed by interactive children. */
24
25
  export function CockpitPanel({ title, focused = false, width, children, colorEnabled = true }) {
25
26
  return React.createElement(Box, {
26
27
  flexDirection: "column",
27
28
  width,
28
- borderStyle: "single",
29
- borderColor: resolveInkColor(
30
- colorEnabled,
31
- focused ? COCKPIT_COLORS.primary : COCKPIT_COLORS.muted
32
- ),
33
- paddingX: 1,
29
+ paddingX: 0,
30
+ marginY: 1,
34
31
  flexGrow: 1
35
32
  },
36
33
  title && React.createElement(Text, {
37
34
  bold: true,
38
35
  color: resolveInkColor(
39
36
  colorEnabled,
40
- focused ? COCKPIT_COLORS.primary : COCKPIT_COLORS.secondary
37
+ focused ? COCKPIT_COLORS.interactive : COCKPIT_COLORS.brand
41
38
  )
42
39
  }, title),
43
40
  children
@@ -48,7 +45,7 @@ export function CockpitSection({ title, children, colorEnabled = true }) {
48
45
  return React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
49
46
  title && React.createElement(Text, {
50
47
  bold: true,
51
- color: resolveInkColor(colorEnabled, COCKPIT_COLORS.secondary)
48
+ color: resolveInkColor(colorEnabled, COCKPIT_COLORS.brand)
52
49
  }, title),
53
50
  children
54
51
  );
@@ -60,15 +57,29 @@ export function CockpitKeyHint({ keys, label, colorEnabled = true }) {
60
57
  }, `${keys} ${label}`);
61
58
  }
62
59
 
60
+ /** Compact header: brand · status · project — no box-drawing. */
63
61
  export function CockpitTopBar({ model, colorEnabled = true }) {
62
+ const statusKind = String(model.status ?? "").toUpperCase() === "ONLINE"
63
+ ? "online"
64
+ : "muted";
64
65
  return React.createElement(Box, { justifyContent: "space-between", width: "100%" },
65
- React.createElement(Text, {
66
- bold: true,
67
- color: resolveInkColor(colorEnabled, COCKPIT_COLORS.primary)
68
- }, `╭─ ${model.brand} ─ ${model.status}`),
66
+ React.createElement(Box, null,
67
+ React.createElement(Text, {
68
+ bold: true,
69
+ color: resolveInkColor(colorEnabled, COCKPIT_COLORS.brand)
70
+ }, model.brand),
71
+ React.createElement(Text, {
72
+ color: resolveInkColor(colorEnabled, COCKPIT_COLORS.muted)
73
+ }, " · "),
74
+ React.createElement(CockpitBadge, {
75
+ label: model.status,
76
+ kind: statusKind,
77
+ colorEnabled
78
+ })
79
+ ),
69
80
  React.createElement(Text, {
70
81
  color: resolveInkColor(colorEnabled, COCKPIT_COLORS.muted)
71
- }, `${model.projectLabel} ─╮`)
82
+ }, model.projectLabel)
72
83
  );
73
84
  }
74
85
 
@@ -78,9 +89,9 @@ export function CockpitNav({ model, colorEnabled = true }) {
78
89
  model.items.map((item) => {
79
90
  const suffix = item.current && !item.selected ? " (open)" : "";
80
91
  const color = item.focused
81
- ? resolveInkColor(colorEnabled, COCKPIT_COLORS.primary)
92
+ ? resolveInkColor(colorEnabled, COCKPIT_COLORS.interactive)
82
93
  : item.selected
83
- ? resolveInkColor(colorEnabled, COCKPIT_COLORS.secondary)
94
+ ? resolveInkColor(colorEnabled, COCKPIT_COLORS.brand)
84
95
  : item.current
85
96
  ? resolveInkColor(colorEnabled, COCKPIT_COLORS.muted)
86
97
  : undefined;
@@ -101,7 +112,7 @@ function stripLabel(item, { compact }) {
101
112
  return item.label.split(/[&·]/)[0].trim().split(/\s+/)[0];
102
113
  }
103
114
 
104
- /** Horizontal navigation strip under the top bar. */
115
+ /** Segmented horizontal nav no border; active segment uses interactive. */
105
116
  export function CockpitNavStrip({
106
117
  model,
107
118
  colorEnabled = true,
@@ -112,16 +123,20 @@ export function CockpitNavStrip({
112
123
  const parts = model.items.map((item) => {
113
124
  const label = stripLabel(item, { compact });
114
125
  const suffix = item.current && !item.selected ? "*" : "";
115
- const color = item.focused
116
- ? resolveInkColor(colorEnabled, COCKPIT_COLORS.primary)
126
+ const active = item.focused || item.selected;
127
+ const color = item.focused || (focused && item.selected)
128
+ ? resolveInkColor(colorEnabled, COCKPIT_COLORS.interactive)
117
129
  : item.selected
118
- ? resolveInkColor(colorEnabled, COCKPIT_COLORS.secondary)
130
+ ? resolveInkColor(colorEnabled, COCKPIT_COLORS.interactive)
119
131
  : resolveInkColor(colorEnabled, COCKPIT_COLORS.muted);
132
+ const text = focused && item.selected
133
+ ? `[${label}]${suffix}`
134
+ : `${item.marker}${label}${suffix}`;
120
135
  return React.createElement(Text, {
121
136
  key: item.id,
122
- bold: item.focused || item.selected,
137
+ bold: active,
123
138
  color
124
- }, `${item.marker}${label}${suffix}`);
139
+ }, text);
125
140
  });
126
141
 
127
142
  const joined = [];
@@ -138,12 +153,8 @@ export function CockpitNavStrip({
138
153
  return React.createElement(Box, {
139
154
  flexDirection: "column",
140
155
  width: "100%",
141
- borderStyle: "single",
142
- borderColor: resolveInkColor(
143
- colorEnabled,
144
- focused ? COCKPIT_COLORS.primary : COCKPIT_COLORS.muted
145
- ),
146
- paddingX: 1
156
+ marginTop: 0,
157
+ marginBottom: 0
147
158
  },
148
159
  React.createElement(Box, { flexDirection: "row", flexWrap: "wrap" }, ...joined),
149
160
  model.explanation && React.createElement(Text, {
@@ -170,20 +181,19 @@ export function CockpitSystemStrip({ model, colorEnabled = true }) {
170
181
  );
171
182
  }
172
183
 
184
+ /** Single-line shortcut bar — no framed box. */
173
185
  export function CockpitFooter({ model, columns = 80, colorEnabled = true }) {
174
186
  const width = Math.max(24, Math.min(Number(columns) || 80, 120));
175
- const bar = Math.max(20, width - 2);
176
- const muted = resolveInkColor(colorEnabled, COCKPIT_COLORS.muted);
177
- return React.createElement(Box, { flexDirection: "column", width: "100%" },
178
- React.createElement(Text, { color: muted }, `├${"".repeat(bar)}┤`),
179
- React.createElement(Text, { color: muted }, `│ ${model.text}`),
180
- React.createElement(Text, { color: muted }, `╰${"─".repeat(bar)}╯`)
187
+ return React.createElement(Box, { width: "100%", marginTop: 1 },
188
+ React.createElement(Text, {
189
+ color: resolveInkColor(colorEnabled, COCKPIT_COLORS.muted)
190
+ }, String(model.text ?? "").slice(0, width))
181
191
  );
182
192
  }
183
193
 
184
194
  /**
185
195
  * Responsive single-panel shell: TopBar → NavStrip → Main → Footer.
186
- * SYSTEM side column removed (diagnostics via Enter/detail in later slices).
196
+ * No nested borders hierarchy via type and spacing.
187
197
  */
188
198
  export function CockpitShell({
189
199
  topBar,
@@ -111,7 +111,8 @@ export function renderCockpitView({
111
111
  model: controlCenter,
112
112
  detailsOpen: overviewDetailsOpen,
113
113
  colorEnabled,
114
- unicode
114
+ unicode,
115
+ layoutMode
115
116
  });
116
117
  case ORCHESTRATOR_VIEWS.USAGE:
117
118
  return React.createElement(SemanticUsagePanel, {
@@ -41,7 +41,7 @@ import { handleLaunchInput } from "./launch-input.js";
41
41
  import { useTerminalSize } from "./use-terminal-size.js";
42
42
  import { useOrchestratorData } from "./use-orchestrator-data.js";
43
43
  import { resolveTerminalCapabilities } from "./terminal-capabilities.js";
44
- import { COCKPIT_COLORS } from "./theme.js";
44
+ import { COCKPIT_COLORS, resolveInkColor } from "./theme.js";
45
45
  import { LAYOUT_MODES } from "./layout.js";
46
46
  import { CHANGES_PHASE } from "./cockpit-changes.js";
47
47
  import { RECOVERY_PHASE, listRecoverySnapshots } from "./cockpit-recovery.js";
@@ -466,14 +466,22 @@ export function OrchestratorApp({
466
466
 
467
467
  if (data.loading) {
468
468
  return React.createElement(Box, { flexDirection: "column" },
469
- React.createElement(Text, { bold: true, color: COCKPIT_COLORS.primary }, "KAIRO"),
470
- React.createElement(Text, { color: COCKPIT_COLORS.muted }, "Loading cockpit…")
469
+ React.createElement(Text, {
470
+ bold: true,
471
+ color: resolveInkColor(caps.color, COCKPIT_COLORS.brand)
472
+ }, "KAIRO"),
473
+ React.createElement(Text, {
474
+ color: resolveInkColor(caps.color, COCKPIT_COLORS.muted)
475
+ }, "Loading cockpit…")
471
476
  );
472
477
  }
473
478
 
474
479
  if (data.error) {
475
480
  return React.createElement(Box, { flexDirection: "column" },
476
- React.createElement(Text, { bold: true, color: COCKPIT_COLORS.danger }, "Runtime error"),
481
+ React.createElement(Text, {
482
+ bold: true,
483
+ color: resolveInkColor(caps.color, COCKPIT_COLORS.danger)
484
+ }, "Runtime error"),
477
485
  React.createElement(Text, null, data.error),
478
486
  React.createElement(Text, { dimColor: true },
479
487
  data.retrying ? "Retrying read-only scan…" : "R Retry · Esc to exit")
@@ -1,15 +1,20 @@
1
1
  /**
2
- * Deep-space cockpit theme. Status always has a text label — never color alone.
2
+ * Kairo Cockpit theme amber brand, ice interactive, semantic status.
3
+ * Status always has a text label — never color alone.
3
4
  */
4
5
 
5
6
  export const COCKPIT_COLORS = {
6
- primary: "cyan",
7
- secondary: "magenta",
8
- success: "green",
9
- warning: "yellow",
10
- danger: "red",
7
+ brand: "#E8A017",
8
+ interactive: "#7EC8E8",
9
+ success: "#3DDC97",
10
+ warning: "#F0C674",
11
+ danger: "#FF6B6B",
11
12
  muted: "gray",
12
- border: "cyan"
13
+ /** @deprecated alias — prefer interactive */
14
+ primary: "#7EC8E8",
15
+ /** @deprecated alias — prefer brand */
16
+ secondary: "#E8A017",
17
+ border: "#7EC8E8"
13
18
  };
14
19
 
15
20
  export const STATUS_LABELS = {
@@ -69,7 +74,7 @@ export function statusColor(kind, { colorEnabled = true } = {}) {
69
74
  case "muted":
70
75
  return COCKPIT_COLORS.muted;
71
76
  default:
72
- return COCKPIT_COLORS.primary;
77
+ return COCKPIT_COLORS.interactive;
73
78
  }
74
79
  }
75
80
 
@@ -1,13 +1,12 @@
1
1
  /** Live semantic Activity/Recovery. Callout=status · Confirm=action · footer=keys · snapshots=focus. */
2
2
  import React from "react";
3
3
  import { Box, Text } from "ink";
4
- import { COCKPIT_COLORS } from "../theme.js";
5
4
  import { formatConfirmPath } from "../cockpit-path-label.js";
6
5
  import {
7
6
  RECOVERY_PHASE, listRecoverySnapshots, formatWhen, formatResult, shortName
8
7
  } from "../cockpit-recovery.js";
9
8
  import { LAYOUT_MODES } from "../layout.js";
10
- import { ActionList, Callout, Confirm, Details } from "./semantic.js";
9
+ import { ActionList, Callout, Confirm, Details, SectionLabel, ViewTitle } from "./semantic.js";
11
10
  import { detailsPathLimit } from "./live-governance.js";
12
11
 
13
12
  export function activityContentLimits(layoutMode = LAYOUT_MODES.COMPACT) {
@@ -157,9 +156,7 @@ export function SemanticActivityPanel({
157
156
  snapshot, recoveryAction, dashboard, listIndex, homeDir, detailsOpen, layoutMode
158
157
  });
159
158
  return React.createElement(Box, { flexDirection: "column" },
160
- React.createElement(Text, {
161
- bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
162
- }, view.title),
159
+ React.createElement(ViewTitle, { colorEnabled }, view.title),
163
160
  React.createElement(Callout, {
164
161
  tone: view.callout.tone, title: view.callout.title,
165
162
  body: view.callout.body || undefined, colorEnabled, compact: true
@@ -174,11 +171,11 @@ export function SemanticActivityPanel({
174
171
  : null,
175
172
  view.primary?.detail && !view.confirm
176
173
  ? React.createElement(Text, null, view.primary.detail) : null,
177
- React.createElement(Text, { bold: true }, "Recent"),
174
+ React.createElement(SectionLabel, { colorEnabled }, "Recent"),
178
175
  React.createElement(ActionList, {
179
176
  items: view.recent, selectedIndex: -1, focused: false, colorEnabled, unicode
180
177
  }),
181
- React.createElement(Text, { bold: true }, "Snapshots"),
178
+ React.createElement(SectionLabel, { colorEnabled }, "Snapshots"),
182
179
  React.createElement(ActionList, {
183
180
  items: view.snapshots, selectedIndex: view.selectedIndex,
184
181
  focused: contentFocused, colorEnabled, unicode
@@ -5,11 +5,10 @@
5
5
  */
6
6
  import React from "react";
7
7
  import { Box, Text } from "ink";
8
- import { COCKPIT_COLORS } from "../theme.js";
9
8
  import { LAYOUT_MODES } from "../layout.js";
10
9
  import { ALERT_STATES } from "../../runtime/alerts/alert-types.js";
11
10
  import { formatAlertsHeadline, selectAlertFromList } from "../cockpit-alerts.js";
12
- import { ActionList, Callout } from "./semantic.js";
11
+ import { ActionList, Callout, ViewTitle } from "./semantic.js";
13
12
  import { windowSlice } from "./live-activity.js";
14
13
 
15
14
  export function alertsListLimit(layoutMode = LAYOUT_MODES.COMPACT) {
@@ -138,9 +137,7 @@ export function SemanticAlertsPanel({
138
137
  const model = adaptAlertsModel({ alerts, listIndex, layoutMode });
139
138
  const listFocused = contentFocused && !model.isEmpty && !model.isUnavailable;
140
139
  return React.createElement(Box, { flexDirection: "column" },
141
- React.createElement(Text, {
142
- bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
143
- }, model.title),
140
+ React.createElement(ViewTitle, { colorEnabled }, model.title),
144
141
  React.createElement(Callout, {
145
142
  tone: model.callout.tone,
146
143
  title: model.callout.title,
@@ -1,11 +1,10 @@
1
1
  /** Live semantic Governance. Ownership: Callout=status · Confirm/primary=action · footer=keys. */
2
2
  import React from "react";
3
3
  import { Box, Text } from "ink";
4
- import { COCKPIT_COLORS } from "../theme.js";
5
4
  import { formatConfirmPath } from "../cockpit-path-label.js";
6
5
  import { CHANGES_PHASE } from "../cockpit-changes.js";
7
6
  import { LAYOUT_MODES } from "../layout.js";
8
- import { ActionList, Callout, Confirm, Details } from "./semantic.js";
7
+ import { ActionList, Callout, Confirm, Details, ViewTitle } from "./semantic.js";
9
8
  import { mapHealthTone } from "./live-overview.js";
10
9
 
11
10
  function healthLabel(kind) {
@@ -151,10 +150,7 @@ export function SemanticGovernancePanel({
151
150
  snapshot, changesAction, homeDir, detailsOpen, layoutMode
152
151
  });
153
152
  return React.createElement(Box, { flexDirection: "column" },
154
- React.createElement(Text, {
155
- bold: true,
156
- color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
157
- }, view.title),
153
+ React.createElement(ViewTitle, { colorEnabled }, view.title),
158
154
  React.createElement(Callout, {
159
155
  tone: view.callout.tone,
160
156
  title: view.callout.title,
@@ -5,14 +5,13 @@
5
5
  */
6
6
  import React from "react";
7
7
  import { Box, Text } from "ink";
8
- import { COCKPIT_COLORS } from "../theme.js";
9
8
  import { LAYOUT_MODES } from "../layout.js";
10
9
  import { ORCHESTRATOR_VIEWS, formatRunLines } from "../orchestrator-state.js";
11
10
  import {
12
11
  RUNS_HUB_ITEMS, formatOrchestrationStatus, formatRunsHubLines
13
12
  } from "../cockpit-runs.js";
14
13
  import { formatReviewListLines } from "../cockpit-reviews.js";
15
- import { ActionList, Callout } from "./semantic.js";
14
+ import { ActionList, Callout, ViewTitle } from "./semantic.js";
16
15
  import { windowSlice } from "./live-activity.js";
17
16
 
18
17
  export function orchestrationListLimit(layoutMode = LAYOUT_MODES.COMPACT) {
@@ -167,9 +166,7 @@ export function SemanticOrchestrationPanel({
167
166
  });
168
167
  const listFocused = contentFocused && !model.isEmpty;
169
168
  return React.createElement(Box, { flexDirection: "column" },
170
- React.createElement(Text, {
171
- bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
172
- }, model.title),
169
+ React.createElement(ViewTitle, { colorEnabled }, model.title),
173
170
  React.createElement(Callout, {
174
171
  tone: model.callout.tone,
175
172
  title: model.callout.title,
@@ -1,11 +1,18 @@
1
1
  /**
2
- * Live semantic Overview for Cockpit HOME.
2
+ * Live semantic Overview for Cockpit HOME — product cover.
3
3
  * Nav owns the sole focus mark — this panel never renders `>`.
4
+ * ASCII wordmark only here (wide/compact); minimal is textual.
4
5
  */
5
6
  import React from "react";
6
7
  import { Box, Text } from "ink";
7
8
  import { CONTROL_PLANE_HEALTH } from "../../control-plane-snapshot.js";
9
+ import { LAYOUT_MODES } from "../layout.js";
8
10
  import { COCKPIT_COLORS } from "../theme.js";
11
+ import {
12
+ overviewBrandTitle,
13
+ shouldShowWordmark,
14
+ wordmarkLines
15
+ } from "../brand/wordmark.js";
9
16
  import { ActionList, Callout, Details } from "./semantic.js";
10
17
 
11
18
  const DESTINATION_LABELS = {
@@ -80,39 +87,82 @@ export function adaptControlCenterToOverview(model = {}) {
80
87
  };
81
88
  }
82
89
 
90
+ function renderWordmark({ layoutMode, colorEnabled = true, unicode = true }) {
91
+ const lines = wordmarkLines(layoutMode, { unicode });
92
+ if (lines.length === 0) return null;
93
+ return React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
94
+ ...lines.map((line, i) => React.createElement(Text, {
95
+ key: `wm-${i}`,
96
+ bold: i === 0,
97
+ color: colorEnabled ? COCKPIT_COLORS.brand : undefined
98
+ }, line))
99
+ );
100
+ }
101
+
102
+ function renderCallout(view, colorEnabled) {
103
+ return React.createElement(Callout, {
104
+ tone: view.callout.tone,
105
+ title: view.callout.title,
106
+ body: view.callout.body,
107
+ colorEnabled,
108
+ compact: true
109
+ });
110
+ }
111
+
83
112
  export function SemanticOverviewPanel({
84
113
  model,
85
114
  detailsOpen = false,
86
115
  colorEnabled = true,
87
- unicode = true
116
+ unicode = true,
117
+ layoutMode = LAYOUT_MODES.COMPACT
88
118
  }) {
89
119
  const view = adaptControlCenterToOverview(model);
120
+ const showArt = shouldShowWordmark(layoutMode);
121
+ const brandTitle = overviewBrandTitle(layoutMode);
122
+ const isWide = layoutMode === LAYOUT_MODES.WIDE;
123
+ const mark = renderWordmark({ layoutMode, colorEnabled, unicode });
124
+ const status = renderCallout(view, colorEnabled);
125
+
126
+ const hero = showArt
127
+ ? (isWide
128
+ ? React.createElement(Box, { flexDirection: "row", marginBottom: 1 },
129
+ React.createElement(Box, { marginRight: 2 }, mark),
130
+ React.createElement(Box, { flexDirection: "column", flexGrow: 1 }, status)
131
+ )
132
+ : React.createElement(Box, { flexDirection: "column" }, mark, status))
133
+ : React.createElement(Box, { flexDirection: "column" },
134
+ React.createElement(Text, {
135
+ bold: true,
136
+ color: colorEnabled ? COCKPIT_COLORS.brand : undefined
137
+ }, brandTitle),
138
+ status
139
+ );
140
+
90
141
  return React.createElement(Box, { flexDirection: "column" },
91
- React.createElement(Text, {
92
- bold: true,
93
- color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
94
- }, view.title),
95
- React.createElement(Callout, {
96
- tone: view.callout.tone,
97
- title: view.callout.title,
98
- body: view.callout.body,
99
- colorEnabled,
100
- compact: true
101
- }),
102
- React.createElement(Text, { bold: true }, ` ${view.primary.label}`),
103
- view.primary.detail
104
- ? React.createElement(Text, null, view.primary.detail)
105
- : null,
106
- view.primary.hint
107
- ? React.createElement(Text, { color: colorEnabled ? COCKPIT_COLORS.muted : undefined }, view.primary.hint)
108
- : null,
109
- React.createElement(ActionList, {
110
- items: view.metrics,
111
- selectedIndex: -1,
112
- focused: false,
113
- colorEnabled,
114
- unicode
115
- }),
142
+ hero,
143
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" },
144
+ React.createElement(Text, {
145
+ bold: true,
146
+ color: colorEnabled ? COCKPIT_COLORS.interactive : undefined
147
+ }, view.primary.label),
148
+ view.primary.detail
149
+ ? React.createElement(Text, null, view.primary.detail)
150
+ : null,
151
+ view.primary.hint
152
+ ? React.createElement(Text, {
153
+ color: colorEnabled ? COCKPIT_COLORS.muted : undefined
154
+ }, view.primary.hint)
155
+ : null
156
+ ),
157
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" },
158
+ React.createElement(ActionList, {
159
+ items: view.metrics,
160
+ selectedIndex: -1,
161
+ focused: false,
162
+ colorEnabled,
163
+ unicode
164
+ })
165
+ ),
116
166
  React.createElement(Details, {
117
167
  open: detailsOpen,
118
168
  summary: "Details",
@@ -4,12 +4,11 @@
4
4
  */
5
5
  import React from "react";
6
6
  import { Box, Text } from "ink";
7
- import { COCKPIT_COLORS } from "../theme.js";
8
7
  import { LAYOUT_MODES } from "../layout.js";
9
8
  import {
10
9
  SETTINGS_PHASE, getCuratedIntegration, listCuratedIntegrations
11
10
  } from "../cockpit-settings.js";
12
- import { ActionList, Callout, Confirm, Details, Receipt } from "./semantic.js";
11
+ import { ActionList, Callout, Confirm, Details, Receipt, SectionLabel, ViewTitle } from "./semantic.js";
13
12
  import { windowSlice } from "./live-activity.js";
14
13
 
15
14
  export function settingsListLimit(layoutMode = LAYOUT_MODES.COMPACT) {
@@ -160,9 +159,7 @@ export function SemanticSettingsPanel({
160
159
  model.receipt && React.createElement(Receipt, {
161
160
  title: model.receipt.title, lines: model.receipt.lines, colorEnabled
162
161
  }),
163
- React.createElement(Text, {
164
- bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
165
- }, model.title),
162
+ React.createElement(ViewTitle, { colorEnabled }, model.title),
166
163
  React.createElement(Callout, {
167
164
  tone: model.callout.tone, title: model.callout.title,
168
165
  body: model.callout.body || undefined, colorEnabled, compact: true
@@ -176,7 +173,7 @@ export function SemanticSettingsPanel({
176
173
  focused: listFocused, colorEnabled, unicode
177
174
  }),
178
175
  model.profilePolicy.length > 0 && React.createElement(Box, { flexDirection: "column" },
179
- React.createElement(Text, { bold: true }, "Profile & Policy"),
176
+ React.createElement(SectionLabel, { colorEnabled }, "Profile & Policy"),
180
177
  React.createElement(ActionList, {
181
178
  items: model.profilePolicy, selectedIndex: -1, focused: false, colorEnabled, unicode
182
179
  })
@@ -7,7 +7,7 @@ import { Box, Text } from "ink";
7
7
  import { COCKPIT_COLORS } from "../theme.js";
8
8
  import { LAYOUT_MODES } from "../layout.js";
9
9
  import { adaptUsageModel } from "../cockpit-usage.js";
10
- import { ActionList, Callout } from "./semantic.js";
10
+ import { ActionList, Callout, SectionLabel, ViewTitle } from "./semantic.js";
11
11
 
12
12
  export function SemanticUsagePanel({
13
13
  snapshot = null,
@@ -19,9 +19,7 @@ export function SemanticUsagePanel({
19
19
  const model = adaptUsageModel({ snapshot, dashboard, layoutMode });
20
20
  const muted = colorEnabled ? COCKPIT_COLORS.muted : undefined;
21
21
  return React.createElement(Box, { flexDirection: "column" },
22
- React.createElement(Text, {
23
- bold: true, color: colorEnabled ? COCKPIT_COLORS.secondary : undefined
24
- }, model.title),
22
+ React.createElement(ViewTitle, { colorEnabled }, model.title),
25
23
  React.createElement(Callout, {
26
24
  tone: model.callout.tone,
27
25
  title: model.callout.title,
@@ -29,11 +27,11 @@ export function SemanticUsagePanel({
29
27
  colorEnabled,
30
28
  compact: true
31
29
  }),
32
- React.createElement(Text, { bold: true }, "Measured"),
30
+ React.createElement(SectionLabel, { colorEnabled }, "Measured"),
33
31
  React.createElement(Text, null, ` ${model.measured}`),
34
- React.createElement(Text, { bold: true }, "Configured limits"),
32
+ React.createElement(SectionLabel, { colorEnabled }, "Configured limits"),
35
33
  React.createElement(Text, null, ` ${model.configured}`),
36
- React.createElement(Text, { bold: true }, "Run usage"),
34
+ React.createElement(SectionLabel, { colorEnabled }, "Run usage"),
37
35
  model.runs.length === 0
38
36
  ? React.createElement(Text, null, " No auditable run tokenUsage yet.")
39
37
  : React.createElement(ActionList, {
@@ -4,6 +4,15 @@ import { Box, Text } from "ink";
4
4
  import { COCKPIT_COLORS, statusColor, resolveGlyphs } from "../theme.js";
5
5
 
6
6
  const mute = (on) => (on ? COCKPIT_COLORS.muted : undefined);
7
+ const ice = (on) => (on ? COCKPIT_COLORS.interactive : undefined);
8
+
9
+ /** Short typographic view title — brand amber, no border. */
10
+ export function ViewTitle({ children, colorEnabled = true }) {
11
+ return React.createElement(Text, {
12
+ bold: true,
13
+ color: colorEnabled ? COCKPIT_COLORS.brand : undefined
14
+ }, children);
15
+ }
7
16
 
8
17
  export function ActionList({ items = [], selectedIndex = 0, focused = true, colorEnabled = true, unicode = true }) {
9
18
  const g = resolveGlyphs(unicode);
@@ -13,7 +22,7 @@ export function ActionList({ items = [], selectedIndex = 0, focused = true, colo
13
22
  return React.createElement(Text, {
14
23
  key: item.id ?? String(i),
15
24
  bold: sel,
16
- color: sel && focused && colorEnabled ? COCKPIT_COLORS.primary : undefined
25
+ color: sel && focused && colorEnabled ? COCKPIT_COLORS.interactive : undefined
17
26
  }, `${sel && focused ? g.focus : " "} ${item.label}${item.hint ? ` ${item.hint}` : ""}`);
18
27
  })
19
28
  );
@@ -30,7 +39,7 @@ export function Stepper({ steps = [], currentIndex = 0, colorEnabled = true, uni
30
39
  const cur = i === currentIndex;
31
40
  const color = isDone
32
41
  ? (colorEnabled ? COCKPIT_COLORS.success : undefined)
33
- : cur ? (colorEnabled ? COCKPIT_COLORS.primary : undefined) : mute(colorEnabled);
42
+ : cur ? ice(colorEnabled) : mute(colorEnabled);
34
43
  return React.createElement(Text, {
35
44
  key: step.id ?? String(i), bold: cur, color
36
45
  }, `${isDone ? done : cur ? current : idle} ${i + 1}. ${step.label}`);
@@ -50,24 +59,24 @@ export function Callout({ tone = "info", title, body, colorEnabled = true, compa
50
59
  }
51
60
 
52
61
  export function Confirm({ summary, primaryLabel = "Confirm", focused = true, colorEnabled = true, mark = " " }) {
53
- return React.createElement(Box, { flexDirection: "column" },
62
+ return React.createElement(Box, { flexDirection: "column", marginY: 1 },
54
63
  summary ? React.createElement(Text, null, summary) : null,
55
64
  React.createElement(Text, {
56
65
  bold: focused,
57
- color: focused && colorEnabled ? COCKPIT_COLORS.primary : undefined
66
+ color: focused && colorEnabled ? COCKPIT_COLORS.interactive : undefined
58
67
  }, `${mark} ${primaryLabel}`)
59
68
  );
60
69
  }
61
70
 
62
71
  export function Receipt({ title = "Receipt", lines = [], colorEnabled = true }) {
63
- return React.createElement(Box, { flexDirection: "column" },
72
+ return React.createElement(Box, { flexDirection: "column", marginY: 1 },
64
73
  React.createElement(Text, { bold: true, color: colorEnabled ? COCKPIT_COLORS.success : undefined }, title),
65
74
  ...lines.map((line, i) => React.createElement(Text, { key: `r${i}`, color: mute(colorEnabled) }, line))
66
75
  );
67
76
  }
68
77
 
69
78
  export function Details({ open = false, summary = "Details", lines = [], colorEnabled = true, focused = false, mark = " " }) {
70
- const color = focused && colorEnabled ? COCKPIT_COLORS.primary : mute(colorEnabled);
79
+ const color = focused && colorEnabled ? COCKPIT_COLORS.interactive : mute(colorEnabled);
71
80
  if (!open) return React.createElement(Text, { bold: focused, color }, `${mark} ${summary} · Space`);
72
81
  return React.createElement(Box, { flexDirection: "column" },
73
82
  React.createElement(Text, { bold: true, color }, `${mark} ${summary}`),
@@ -82,3 +91,11 @@ export function KeyBar({ hints = [], colorEnabled = true, columns = 80 }) {
82
91
  hints.map((h) => `${h.keys} ${h.label}`).join(" · "))
83
92
  );
84
93
  }
94
+
95
+ /** Section label inside a panel — muted brand hierarchy under ViewTitle. */
96
+ export function SectionLabel({ children, colorEnabled = true }) {
97
+ return React.createElement(Text, {
98
+ bold: true,
99
+ color: colorEnabled ? COCKPIT_COLORS.muted : undefined
100
+ }, children);
101
+ }