@yemi33/minions 0.1.2150 → 0.1.2152

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/bin/minions.js CHANGED
@@ -64,6 +64,10 @@ const PKG_ROOT = path.resolve(__dirname, '..');
64
64
  const shared = require(path.join(PKG_ROOT, 'engine', 'shared'));
65
65
  const { openUrlInBrowser } = shared;
66
66
  const { waitForRestartHealth, formatRestartHealthError } = require(path.join(PKG_ROOT, 'engine', 'restart-health'));
67
+ // Dev-mode dashboard port. `--dev` mode (see argv parser below) retargets
68
+ // MINIONS_HOME at PKG_ROOT and routes the dashboard onto this port so a dev
69
+ // checkout coexists with a global npm install on the normal port (7331).
70
+ const DEFAULT_DEV_DASH_PORT = 7332;
67
71
 
68
72
  /**
69
73
  * Resolve the dashboard port for any CLI command. Precedence (W-mq5nwl9l):
@@ -71,7 +75,7 @@ const { waitForRestartHealth, formatRestartHealthError } = require(path.join(PKG
71
75
  * ACTUALLY bound to. Wins over the chain so status/dash/restart-health
72
76
  * probes the right port even after an EADDRINUSE auto-fallback.
73
77
  * 2. Explicit `--port N` CLI flag if present in `argv`.
74
- * 3. env MINIONS_DASHBOARD_PORT.
78
+ * 3. env MINIONS_DASHBOARD_PORT (dev mode pre-seeds this with devPort).
75
79
  * 4. config.json#engine.dashboardPort.
76
80
  * 5. shared.DEFAULT_DASHBOARD_PORT (7331).
77
81
  *
@@ -578,7 +582,50 @@ function resolveMinionsHome(forInit = false) {
578
582
  return shared.resolveMinionsHome(forInit);
579
583
  }
580
584
 
581
- const [cmd, ...rest] = process.argv.slice(2);
585
+ // `--dev` runs the in-place checkout AS the runtime root, on a separate
586
+ // dashboard port (default 7332) so it can coexist with a global npm install on
587
+ // 7331. Only valid when bin/minions.js sits inside a git checkout — the
588
+ // `.git` probe stops the global shim (whose PKG_ROOT lives under
589
+ // node_modules/) from accidentally activating dev mode.
590
+ //
591
+ // We strip --dev / --dev-port <n> from argv BEFORE the cmd/rest split so the
592
+ // flag can appear in any position (`minions --dev help`, `minions help --dev`,
593
+ // `minions --dev start --foo` all work). Otherwise `--dev` as the first arg
594
+ // would be misread as the subcommand.
595
+ const { cmd, rest, devMode, devPort } = (() => {
596
+ const raw = process.argv.slice(2);
597
+ const out = [];
598
+ let dev = process.env.MINIONS_DEV === '1';
599
+ let port = null;
600
+ for (let i = 0; i < raw.length; i++) {
601
+ const arg = raw[i];
602
+ if (arg === '--dev') { dev = true; continue; }
603
+ if (arg === '--dev-port') {
604
+ const next = raw[i + 1];
605
+ const n = Number(next);
606
+ if (!Number.isInteger(n) || n <= 0 || n > 65535) {
607
+ console.error(`\n --dev-port requires an integer 1-65535, got: ${next || '(missing)'}\n`);
608
+ process.exit(2);
609
+ }
610
+ port = n; dev = true; i++; continue;
611
+ }
612
+ if (arg && arg.startsWith('--dev-port=')) {
613
+ const n = Number(arg.slice('--dev-port='.length));
614
+ if (!Number.isInteger(n) || n <= 0 || n > 65535) {
615
+ console.error(`\n --dev-port=<n> requires an integer 1-65535, got: ${arg}\n`);
616
+ process.exit(2);
617
+ }
618
+ port = n; dev = true; continue;
619
+ }
620
+ out.push(arg);
621
+ }
622
+ if (dev && port == null) {
623
+ const envPort = Number(process.env.MINIONS_DEV_PORT);
624
+ if (Number.isInteger(envPort) && envPort > 0 && envPort <= 65535) port = envPort;
625
+ }
626
+ const [firstCmd, ...restArgs] = out;
627
+ return { cmd: firstCmd, rest: restArgs, devMode: dev, devPort: port || DEFAULT_DEV_DASH_PORT };
628
+ })();
582
629
  let force = rest.includes('--force');
583
630
  const skipScan = rest.includes('--skip-scan');
584
631
  const skipStart = rest.includes('--skip-start') || rest.includes('--no-start');
@@ -587,8 +634,46 @@ const skipStart = rest.includes('--skip-start') || rest.includes('--no-start');
587
634
  // when the heuristic mis-fires (e.g. you closed your dashboard tab seconds before
588
635
  // running restart and its final heartbeat was still inside the 45s window).
589
636
  const forceOpen = rest.includes('--open') || process.env.MINIONS_FORCE_OPEN === '1';
590
- const MINIONS_HOME = resolveMinionsHome(cmd === 'init');
637
+ // When --dev is set, PKG_ROOT MUST be a git checkout. Without the .git probe a
638
+ // user who typed `minions --dev` from any directory would silently retarget the
639
+ // globally-installed package as its own dev workspace.
640
+ if (devMode && !fs.existsSync(path.join(PKG_ROOT, '.git'))) {
641
+ console.error(`
642
+ --dev requires running from a git checkout of minions.
643
+ This bin/minions.js lives under: ${PKG_ROOT}
644
+ No .git directory was found there — refusing to retarget runtime files.
645
+
646
+ To use dev mode, clone the repo and run from inside it:
647
+ git clone https://github.com/opg-microsoft/minions.git
648
+ cd minions && node bin/minions.js --dev restart
649
+ `);
650
+ process.exit(2);
651
+ }
652
+
653
+ const MINIONS_HOME = devMode ? PKG_ROOT : resolveMinionsHome(cmd === 'init');
591
654
  process.env.MINIONS_HOME = MINIONS_HOME;
655
+ // When --dev is set, force the dashboard chain onto the dev port (7332 by
656
+ // default or --dev-port N) so a dev checkout coexists with a global install
657
+ // on 7331. We seed MINIONS_DASHBOARD_PORT so resolveDashboardPort()'s env
658
+ // step treats devPort as the fallback while still respecting an existing dev
659
+ // runtime-file at PKG_ROOT/engine/dashboard-port.json (runtime-file wins).
660
+ if (devMode) process.env.MINIONS_DASHBOARD_PORT = String(devPort);
661
+ // Effective dashboard port for this CLI invocation. Honors the W-mq5nwl9l
662
+ // chain (runtime-file → --port → env → config → DEFAULT_DASHBOARD_PORT/7331);
663
+ // --dev overrides via the env seed above. Consumed by the watchdog tick
664
+ // callsite below and propagated to children via MINIONS_PORT.
665
+ // Named DASHBOARD_PORT (not the deprecated DASH-underscore-PORT identifier) so
666
+ // the W-mq5nwl9l source-inspection guard in
667
+ // test/unit/dashboard-port-resolution.test.js keeps holding: that test pins
668
+ // that no static `\bDASH_PORT\b` survives, because anything other than the
669
+ // dynamic chain re-introduces the 7331 bug W-mq5nwl9l was opened to fix.
670
+ const DASHBOARD_PORT = resolveDashboardPort(rest).port;
671
+ // Propagate the port to every child (engine, dashboard, delegated subcommands).
672
+ // engine/cli.js status reads MINIONS_PORT; dashboard.js reads PORT. We export
673
+ // MINIONS_PORT for the engine + watch-actions / pipeline / managed-spawn
674
+ // loopback callers that already honor it, and pass PORT explicitly when
675
+ // spawning dashboard.js.
676
+ process.env.MINIONS_PORT = String(DASHBOARD_PORT);
592
677
  const POST_UPDATE_INIT_TIMEOUT_MS = 120000;
593
678
  const POST_UPDATE_RESTART_TIMEOUT_MS = 60000;
594
679
 
@@ -1051,8 +1136,16 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
1051
1136
  minions watchdog uninstall Remove the scheduled task (idempotent)
1052
1137
  minions watchdog status Show registration + last-run details from the OS scheduler
1053
1138
  minions watchdog tick One-shot probe + recovery (used by the scheduler; safe to run by hand)
1054
-
1055
- Runtime root: ${MINIONS_HOME}
1139
+ ${fs.existsSync(path.join(PKG_ROOT, '.git')) ? `
1140
+ Dev mode (this checkout, contributors only):
1141
+ minions --dev <cmd> Run against this checkout instead of ~/.minions/
1142
+ MINIONS_HOME=<checkout>, dashboard on :7332.
1143
+ Coexists with the global install on :7331.
1144
+ minions --dev --dev-port <n> <cmd> Override the dev dashboard port.
1145
+ npm run dev Shortcut for: node bin/minions.js --dev restart
1146
+ ` : ''}
1147
+ Runtime root: ${MINIONS_HOME}${devMode ? ' [DEV]' : ''}${devMode ? `
1148
+ Dashboard port: ${DASHBOARD_PORT} [DEV]` : ''}
1056
1149
  `);
1057
1150
  } else if (cmd === 'init') {
1058
1151
  init();
@@ -1365,7 +1458,7 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
1365
1458
  watchdog.tick({
1366
1459
  minionsHome: MINIONS_HOME,
1367
1460
  minionsBin,
1368
- dashPort: resolveDashboardPort([]).port,
1461
+ dashPort: DASHBOARD_PORT,
1369
1462
  readEnginePid,
1370
1463
  isPortListening,
1371
1464
  isStopIntentSet: shared.isStopIntentSet || (() => false),
@@ -0,0 +1,128 @@
1
+ # Dashboard typography audit (W-mq1c8og40003a7cf)
2
+
3
+ This document is the pre-migration audit that justified the token set
4
+ now declared in `dashboard/styles.css` + `dashboard/slim/styles.css`.
5
+ See `dashboard/docs/typography.md` for the contract.
6
+
7
+ ## Findings
8
+
9
+ ### Baseline before this WI
10
+
11
+ | Surface | font-size declarations | Already on tokens? |
12
+ | ----------------------------- | ---------------------: | ----------------------------- |
13
+ | `dashboard/styles.css` (main) | 179 | ✅ all `var(--text-*)` except `.prd-item-id { font-size: 0.9em }` (slipped past PR #66 tripwire because the pattern was px-only) |
14
+ | `dashboard/layout.html` | 20 | ✅ all `var(--text-*)` |
15
+ | `dashboard/pages/*.html` | 32 | ✅ all `var(--text-*)` |
16
+ | `dashboard/js/*.js` | ~530 | ✅ all `var(--text-*)` except `utils.js:263` `font-size:0.9em` (same em-pattern blind spot as above) |
17
+ | `dashboard/slim/styles.css` | 82 | ❌ all literals (slim was explicitly out of scope for PR #66) |
18
+ | `dashboard/slim/body.html` | 2 | ❌ inline literals |
19
+ | **Total** | **~845** | **~84 raw / non-tokenized** |
20
+
21
+ The main dashboard was already ~99% tokenized by PR #66
22
+ (`refactor(dashboard): anchor typography scale at 12px, migrate raw px
23
+ to tokens`). Two `0.9em` declarations slipped past its `\d+\s*px`
24
+ tripwire because the regex didn't catch the em form.
25
+
26
+ The slim UX prototype (`dashboard/slim/*`) was deliberately out of scope
27
+ for PR #66 — slim is a feature-flagged playground anchored at 16px
28
+ body, and its CSS is served from disk on every request so the human can
29
+ hand-edit it (`dashboard/slim/styles.css` header comment).
30
+
31
+ ### Distinct font-size values seen across the audit
32
+
33
+ (Unique px values, sorted.)
34
+
35
+ | px | Count | Maps to | Where |
36
+ | -: | -----:| ------------------ | ---------------------------------------------------------- |
37
+ | 10 | many | `--text-xs` | main dashboard chips/badges |
38
+ | 11 | many | `--text-sm` | main dashboard status badges |
39
+ | 12 | ~30 | `--text-base` | main dashboard captions + most slim chips/labels |
40
+ | 13 | ~26 | `--text-md` | main dashboard default + slim default |
41
+ | 14 | ~10 | `--text-lg` | main dashboard body + slim body |
42
+ | 15 | 1 | `--text-lg` (round −1) | slim `.topbar-title` |
43
+ | 16 | ~7 | `--text-xl` | main dashboard body, slim chat input + msg |
44
+ | 17 | 1 | `--text-2xl` (round +1) | slim `.agent-detail-name` |
45
+ | 18 | many | `--text-2xl` | main dashboard h2 / modal headers |
46
+ | 20 | 1 | `--text-2xl` (round −2) | slim `.icon-btn` |
47
+ | 22 | many | `--text-stat` | main + slim stat readouts |
48
+ | 24 | 1 | `--text-stat` (round −2) | slim `.member-emoji` (decorative emoji glyph) |
49
+ | 28 | many | `--text-stat-lg` | main + slim large readouts |
50
+ | 32 | many | `--text-display` | main dashboard hero / H1 |
51
+ | 34 | 1 | `--text-display` (round −2) | slim `.agent-detail-emoji` (decorative emoji) |
52
+ | em | | | |
53
+ | 0.9em | 3 | `--text-code` | inline `<code>` in main + slim |
54
+
55
+ ### Rounding decisions (5 sites)
56
+
57
+ The task contract says: *"prefer rounding to the nearest token over
58
+ inventing a new token. If rounding would visibly change the UI in a way
59
+ you can't justify, flag it in the PR description."*
60
+
61
+ All five rounded sites are within ±2px of their assigned token:
62
+
63
+ | Selector | Was | Now (token) | Δ | Justification |
64
+ | ------------------------------------- | --: | ------------------ | ---: | -------------------------------------------------------------- |
65
+ | `slim .topbar-title` | 15 | 14 `--text-lg` | −1px | Topbar title — 1px reduction not perceptible at glance |
66
+ | `slim .agent-detail-name` | 17 | 18 `--text-2xl` | +1px | Detail-modal heading — 1px increase matches modal-h3 elsewhere |
67
+ | `slim .icon-btn` | 20 | 18 `--text-2xl` | −2px | Hamburger / close icon — emoji-like glyph |
68
+ | `slim .member-emoji` | 24 | 22 `--text-stat` | −2px | Decorative emoji avatar |
69
+ | `slim .agent-detail-emoji` | 34 | 32 `--text-display`| −2px | Decorative emoji in detail modal |
70
+
71
+ Each rounded site has a `/* Rounded from Npx → Mpx … */` inline comment.
72
+ All five sit inside the feature-flagged slim UX, so the blast radius is
73
+ minimal even if the human decides to revert. If any rounding visibly
74
+ breaks the slim layout, define a one-off custom property scoped to that
75
+ selector and reference it instead of expanding the global token set.
76
+
77
+ ### Tokens chosen — and rejected
78
+
79
+ **Chosen** (7 role tokens + 1 code token, all alias size primitives):
80
+
81
+ `--text-role-display`, `--text-heading`, `--text-subheading`,
82
+ `--text-body`, `--text-meta`, `--text-caption`, `--text-micro`,
83
+ `--text-code`.
84
+
85
+ **Rejected**:
86
+
87
+ - `--text-h1` / `--text-h2` / `--text-h3` — semantic HTML headings don't
88
+ map 1:1 to visual roles in this dashboard (`<h1>` in `header` is 18px;
89
+ PRD section h1s render at 32px). Role names beat heading names.
90
+ - `--text-label` — would overlap with `--text-caption`. Same role.
91
+ - `--text-large` / `--text-medium` / `--text-small` — pure-size names
92
+ duplicate the primitives without adding semantics.
93
+ - Slim-specific tokens (e.g. `--text-slim-body: 15px`) — would let slim
94
+ drift further from main. Better to round once and converge.
95
+ - A separate `--icon-*` family for the decorative emoji glyphs — only
96
+ 3 sites, all single-use, and they all happen to round cleanly to an
97
+ existing primitive. Not worth a parallel token family yet.
98
+
99
+ ### Out of scope (deliberately)
100
+
101
+ - font-weight, line-height, letter-spacing, color — explicitly out of
102
+ scope per the task contract; this WI is size-only.
103
+ - font-family — no change.
104
+ - SVG `font-size='90'` inside the favicon `data:image/svg+xml` URL —
105
+ data URLs can't resolve CSS variables. Allowlisted.
106
+ - The 4 `:root[data-font-size="…"] { --minions-font-scale: … }` rules
107
+ declare the dashboard zoom scale; they're attribute selectors, not
108
+ text-size declarations. Allowlisted.
109
+
110
+ ## Regression guard
111
+
112
+ Extended `test/unit/dashboard-font-size-tokens.test.js`:
113
+
114
+ - Already covered: main `dashboard/styles.css`, `dashboard/layout.html`,
115
+ `dashboard/pages/*.html`, `dashboard/js/*.js` for raw `Npx` font-sizes.
116
+ - New in this WI:
117
+ - Extended file set to include `dashboard/slim/styles.css` and
118
+ `dashboard/slim/body.html`.
119
+ - Added pattern for `font-size: Nem|Nrem|N%` (catches the `0.9em`
120
+ blind spot that hid the two pre-existing inline-code declarations).
121
+ - Allowlisted the `--text-code: 0.9em` token declaration itself.
122
+ - Asserted that slim's typography tokens match the main ones
123
+ (drift-detection between the two stylesheets).
124
+
125
+ The test runs in `npm test` and `npm run test:sequential`. ESLint
126
+ remains scoped to XSS-prevention (`eslint.config.js`); we don't add a
127
+ second lint plugin for CSS literals because the pure-Node tripwire
128
+ already covers every file type.
@@ -0,0 +1,114 @@
1
+ # Dashboard typography tokens
2
+
3
+ > Single source of truth for text sizing across the Minions dashboard.
4
+ > Centralized in W-mq1c8og40003a7cf (follow-up to PR #66 size primitives
5
+ > and PR #80 `.btn-add` consolidation).
6
+
7
+ ## Why this exists
8
+
9
+ The dashboard SPA renders text from ~30 modules (`dashboard/js/render-*.js`,
10
+ `dashboard/pages/*.html`, `dashboard/styles.css`, plus the slim UX prototype
11
+ in `dashboard/slim/`). Without a shared token system, every callsite picks
12
+ its own pixel size. Cards drift, captions disagree, headers don't line up
13
+ across pages, and changing the design language costs ~700 edits.
14
+
15
+ Two pieces solve this together:
16
+
17
+ 1. **Size primitives** (`--text-xs` ... `--text-display`) — raw px values.
18
+ The 10 declared sizes cover every visual role the dashboard currently
19
+ uses. Anchored at `--text-base = 12px`. PR #66 migrated ~664 callsites
20
+ from raw `Npx` to these tokens.
21
+ 2. **Role aliases** (`--text-heading`, `--text-body`, etc.) — semantic
22
+ names that point at size primitives. Added in W-mq1c8og40003a7cf so
23
+ new code talks in roles, not px. The size primitive stays the single
24
+ source of truth; role names are aliases.
25
+
26
+ ## Files this lives in
27
+
28
+ | File | What it owns |
29
+ | ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
30
+ | `dashboard/styles.css` | Canonical token declarations (`:root`), utility classes, and main-dashboard CSS rules. |
31
+ | `dashboard/slim/styles.css` | Duplicate token declarations + utility classes for the feature-flagged slim UX (self-contained stylesheet). |
32
+ | `dashboard/docs/typography.md` | This file — the contract. |
33
+ | `dashboard/docs/typography-audit.md` | The pre-migration audit + rounding decisions. |
34
+ | `test/unit/dashboard-font-size-tokens.test.js` | Tripwire that fails CI if raw `Npx` / `Nem` font-sizes leak back in. |
35
+
36
+ A tripwire asserts the slim token VALUES match the main values so the
37
+ two stay in lockstep.
38
+
39
+ ## Size primitives
40
+
41
+ | Token | Value | Common use |
42
+ | ------------------ | ----- | --------------------------------------------------------- |
43
+ | `--text-xs` | 10px | Smallest legitimate text; sidebar badges, count pills |
44
+ | `--text-sm` | 11px | Status badges, chip / tag labels |
45
+ | `--text-base` | 12px | Captions, secondary metadata, dense table cells |
46
+ | `--text-md` | 13px | Default for slim chat / detail tables / button labels |
47
+ | `--text-lg` | 14px | Body text, modal textarea, card titles |
48
+ | `--text-xl` | 16px | Main `<body>` font, secondary headers, chat input |
49
+ | `--text-2xl` | 18px | Section headers, page headers, modal h3 |
50
+ | `--text-stat` | 22px | Stat counter readouts, member emoji glyphs |
51
+ | `--text-stat-lg` | 28px | Larger stat readouts, completions-card type emoji |
52
+ | `--text-display` | 32px | Page hero / markdown H1, agent-detail emoji |
53
+ | `--text-code` | 0.9em | Inline `<code>` — relative so it scales with parent text |
54
+
55
+ > `--text-code` is intentionally relative (`em`, not `px`). Inline code
56
+ > should read 10% smaller than whatever surrounds it. This is the one
57
+ > token that breaks the "all px" rule and is explicitly allowlisted in
58
+ > the tripwire.
59
+
60
+ ## Role aliases (preferred for new code)
61
+
62
+ Use the role token when adding new UI. It survives a future size-scale
63
+ redesign without callsite edits.
64
+
65
+ | Role token | Aliases | Intended use |
66
+ | ---------------------- | ------------------- | ----------------------------------------- |
67
+ | `--text-role-display` | `--text-display` | Page hero, dashboard title |
68
+ | `--text-heading` | `--text-2xl` (18px) | Section + modal headers |
69
+ | `--text-subheading` | `--text-xl` (16px) | Secondary headers, card titles |
70
+ | `--text-body` | `--text-lg` (14px) | Default body text, paragraphs |
71
+ | `--text-meta` | `--text-md` (13px) | Captions, timestamps, secondary metadata |
72
+ | `--text-caption` | `--text-base` (12px)| Small labels, table cells |
73
+ | `--text-micro` | `--text-sm` (11px) | Chip / tag pill labels |
74
+ | `--text-code` | (`0.9em`) | Inline code |
75
+
76
+ ## Utility classes
77
+
78
+ Each role token has a matching utility class for callsites that can't
79
+ write a CSS rule (inline `class="text-meta"`, template strings, etc.).
80
+ Only `font-size` is set — weight, color, line-height stay with the caller.
81
+
82
+ ```html
83
+ <span class="text-meta">3 min ago</span>
84
+ <h3 class="text-heading">Active dispatches</h3>
85
+ <code class="text-code">npm run lint</code>
86
+ ```
87
+
88
+ Available classes: `.text-display`, `.text-heading`, `.text-subheading`,
89
+ `.text-body`, `.text-meta`, `.text-caption`, `.text-micro`, `.text-code`.
90
+
91
+ ## How to add a new text style
92
+
93
+ 1. Pick an existing role token. The 7 roles + 1 code token cover every
94
+ case the audit found.
95
+ 2. If your value doesn't fit any role, round to the nearest primitive
96
+ and document it inline. Inventing a new token requires changing
97
+ `dashboard/styles.css`, `dashboard/slim/styles.css`, this doc, AND
98
+ the tripwire.
99
+ 3. NEVER hand-roll `font-size: 14px` in CSS / inline style / JS template
100
+ string. The tripwire test `test/unit/dashboard-font-size-tokens.test.js`
101
+ fails CI.
102
+
103
+ ## Exceptions / allowlist
104
+
105
+ These declarations are intentional and exempt from the tripwire:
106
+
107
+ - `:root[data-font-size="…"]` rules in `dashboard/styles.css` — these
108
+ declare the user-level zoom scale, not text size.
109
+ - SVG `font-size='90'` inside the `data:image/svg+xml` favicon link in
110
+ `dashboard/layout.html` and `dashboard/slim/layout.html` — runtime
111
+ data URL, CSS variables don't resolve inside it.
112
+ - The `--text-*` token declarations themselves in `:root` blocks.
113
+
114
+ Everything else MUST go through a token.
@@ -82,7 +82,7 @@ async function openAgentDetail(id) {
82
82
  // guarantees no HTML interpretation even if the escape function were ever bypassed.
83
83
  const nameEl = document.getElementById('detail-agent-name');
84
84
  const emojiSpan = document.createElement('span');
85
- emojiSpan.style.fontSize = '22px';
85
+ emojiSpan.style.fontSize = 'var(--text-stat)';
86
86
  emojiSpan.textContent = agent.emoji || '';
87
87
  // Runtime tag \u2014 uses the inline-SVG logo from the same RUNTIME_TAGS map the
88
88
  // card uses, so the visual is consistent. The container's user-controlled
@@ -280,7 +280,7 @@ function _renderMdCore(s) {
280
280
  }).join('\n');
281
281
 
282
282
  html = html.replace(/`([^`\n]+)`/g, function(_, code) {
283
- codeSlots.push('<code style="background:var(--bg);padding:1px 4px;border-radius:3px;font-size:0.9em">' + code + '</code>');
283
+ codeSlots.push('<code style="background:var(--bg);padding:1px 4px;border-radius:3px;font-size:var(--text-code)">' + code + '</code>');
284
284
  return '\x00CB' + (codeSlots.length - 1) + '\x00';
285
285
  });
286
286
 
@@ -300,10 +300,10 @@
300
300
  <div class="modal-body">
301
301
  <p>Point to a local git repository. Minions will read its remote, name, and main branch automatically.</p>
302
302
  <div style="display:flex; gap:8px; align-items:stretch">
303
- <input id="slim-add-project-path" type="text" placeholder="C:\path\to\repo" style="flex:1; padding:8px 10px; background:var(--bg); border:1px solid var(--border); border-radius:var(--radius); color:var(--text); font-size:13px; font-family:inherit">
303
+ <input id="slim-add-project-path" type="text" placeholder="C:\path\to\repo" style="flex:1; padding:8px 10px; background:var(--bg); border:1px solid var(--border); border-radius:var(--radius); color:var(--text); font-size:var(--text-md); font-family:inherit">
304
304
  <button id="slim-add-project-browse" class="btn-secondary" type="button">Browse&hellip;</button>
305
305
  </div>
306
- <div id="slim-add-project-msg" style="margin-top:10px; font-size:12px; min-height:16px"></div>
306
+ <div id="slim-add-project-msg" style="margin-top:10px; font-size:var(--text-base); min-height:16px"></div>
307
307
  </div>
308
308
  <div class="modal-footer">
309
309
  <button id="slim-add-project-cancel" class="btn-secondary" type="button">Cancel</button>