@yemi33/minions 0.1.2448 → 0.1.2449
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/cli-api-client.js +1 -1
- package/bin/install-internal-minions.js +1382 -44
- package/bin/install-layout.js +150 -0
- package/bin/minions.js +460 -167
- package/dashboard/docs/typography.md +65 -12
- package/dashboard/js/command-center.js +58 -4
- package/dashboard/js/detail-panel.js +36 -0
- package/dashboard/js/memory-panel.js +59 -12
- package/dashboard/js/qa.js +179 -20
- package/dashboard/js/refresh.js +148 -12
- package/dashboard/js/render-dispatch.js +3 -4
- package/dashboard/js/render-inbox.js +2 -2
- package/dashboard/js/render-other.js +3 -3
- package/dashboard/js/render-pipelines.js +14 -0
- package/dashboard/js/render-plans.js +57 -9
- package/dashboard/js/render-prd.js +132 -23
- package/dashboard/js/render-prs.js +195 -166
- package/dashboard/js/render-schedules.js +63 -3
- package/dashboard/js/render-utils.js +3 -3
- package/dashboard/js/render-watches.js +19 -3
- package/dashboard/js/render-work-items.js +238 -30
- package/dashboard/js/settings.js +205 -54
- package/dashboard/js/utils.js +51 -1
- package/dashboard/pages/home.html +1 -1
- package/dashboard/pages/qa.html +1 -16
- package/dashboard/pages/work.html +40 -0
- package/dashboard/shared/cc-limits.js +79 -0
- package/dashboard/shared/pr-filters.js +21 -38
- package/dashboard/shared/project-git-summary.js +1 -1
- package/dashboard/shared/record-filters.js +169 -0
- package/dashboard/shared/watches-source.js +1 -1
- package/dashboard/shared/welcome-popup.js +1 -1
- package/dashboard/shared/wi-filters.js +302 -0
- package/dashboard/slim/body.html +1 -0
- package/dashboard/slim/js/command-send.js +26 -0
- package/dashboard/slim/js/modals-tiles.js +380 -39
- package/dashboard/slim/js/status.js +13 -21
- package/dashboard/slim/layout.html +1 -0
- package/dashboard/slim/panel-bootstrap.js +6 -2
- package/dashboard/slim/styles.css +38 -0
- package/dashboard/styles.css +159 -55
- package/dashboard-build.js +13 -2
- package/dashboard.js +956 -423
- package/docs/README.md +11 -6
- package/docs/api-errors.md +2 -2
- package/docs/architecture-review-2026-07-09.md +1 -1
- package/docs/architecture.excalidraw +2 -2
- package/docs/auto-discovery.md +18 -9
- package/docs/branch-derivation.md +4 -4
- package/docs/capture-demos.js +39 -2
- package/docs/ci-runner-canary.md +123 -0
- package/docs/claude-md-propagation.md +2 -2
- package/docs/cloud-agent-dispatch.md +204 -0
- package/docs/command-center.md +7 -7
- package/docs/completion-reports.md +43 -20
- package/docs/constants.md +10 -3
- package/docs/constellation-bridge.md +134 -6
- package/docs/constellation-style-telemetry.md +4 -4
- package/docs/contracts/capability-protocol.v1.json +165 -0
- package/docs/cooldown-merge-semantics.md +12 -12
- package/docs/copilot-cli-schema.md +7 -7
- package/docs/cross-repo-plans.md +10 -10
- package/docs/dead-code-audit-retractions.md +5 -5
- package/docs/default-branch-ci.md +173 -0
- package/docs/deprecated.json +31 -31
- package/docs/design-inbox-entries-schema.md +3 -3
- package/docs/design-language.md +1051 -0
- package/docs/design-state-storage.md +11 -11
- package/docs/diagnostics-crash-reports.md +9 -9
- package/docs/diagnostics-memory.md +5 -5
- package/docs/documentation-audit-2026-07-09.md +7 -7
- package/docs/engine-restart.md +90 -5
- package/docs/harness-mode.md +1 -1
- package/docs/internal-install.md +338 -39
- package/docs/kb-dedup-duplicate-pair-investigation.md +5 -5
- package/docs/kb-pr3223-cascade-archiving.md +1 -1
- package/docs/kb-pr696-merge-conflict-docs.md +6 -6
- package/docs/kb-sweep.md +35 -35
- package/docs/keep-processes.md +1 -1
- package/docs/live-checkout-mode.md +30 -30
- package/docs/managed-spawn.md +18 -14
- package/docs/named-agents.md +7 -7
- package/docs/plan-lifecycle.md +69 -2
- package/docs/pr-author-identity.md +114 -0
- package/docs/pr-auto-fix-dispatch.md +19 -4
- package/docs/pr-comment-followup.md +6 -6
- package/docs/pr-review-fix-loop.md +59 -10
- package/docs/process-termination.md +40 -0
- package/docs/proposals/repo-pool-for-live-checkout.md +13 -13
- package/docs/qa-runbook-lifecycle.md +367 -17
- package/docs/qa-runbooks.md +3 -3
- package/docs/rfc-completion-json.md +18 -18
- package/docs/runtime-adapters.md +26 -21
- package/docs/security.md +6 -6
- package/docs/self-improvement.md +4 -4
- package/docs/shared-lifecycle-module-map.md +473 -472
- package/docs/skills.md +52 -3
- package/docs/slim-ux/concepts.md +121 -116
- package/docs/specs/agent-configurability.md +18 -18
- package/docs/specs/agent-rename.md +18 -18
- package/docs/team-memory.md +38 -21
- package/docs/timeouts-and-liveness.md +118 -10
- package/docs/tutorials/01-install-and-connect.md +1 -1
- package/docs/watches.md +40 -39
- package/docs/workspace-manifests.md +4 -4
- package/docs/worktree-lifecycle.md +293 -14
- package/engine/README.md +46 -0
- package/engine/{ado-comment.js → ado/comment.js} +8 -8
- package/engine/{ado-git-auth.js → ado/git-auth.js} +4 -4
- package/engine/{ado.js → ado/index.js} +417 -63
- package/engine/{ado-status.js → ado/status.js} +6 -8
- package/engine/{ado-token.js → ado/token.js} +1 -1
- package/engine/{acp-transport.js → agents/acp-transport.js} +62 -22
- package/engine/{agent-worker-pool.js → agents/agent-worker-pool.js} +17 -8
- package/engine/{cc-worker-pool.js → agents/cc-worker-pool.js} +16 -6
- package/engine/{claude-md-context.js → agents/claude-md-context.js} +5 -5
- package/engine/{harness-context.js → agents/harness-context.js} +5 -5
- package/engine/{harness.js → agents/harness.js} +3 -3
- package/engine/{llm.js → agents/llm.js} +18 -14
- package/engine/{model-discovery.js → agents/model-discovery.js} +2 -2
- package/engine/{playbook.js → agents/playbook.js} +155 -22
- package/engine/{pooled-agent-process.js → agents/pooled-agent-process.js} +14 -12
- package/engine/{preflight.js → agents/preflight.js} +29 -10
- package/engine/{spawn-agent.js → agents/spawn-agent.js} +25 -14
- package/engine/{spawn-phase-watchdog.js → agents/spawn-phase-watchdog.js} +16 -7
- package/engine/{steering.js → agents/steering.js} +5 -5
- package/engine/{tools-inventory.js → agents/tools-inventory.js} +2 -2
- package/engine/{agent-api-validation.js → api/agent-api-validation.js} +2 -2
- package/engine/{api-validation.js → api/api-validation.js} +1 -1
- package/engine/api/bridge.js +787 -0
- package/engine/{cc-api-validation.js → api/cc-api-validation.js} +1 -1
- package/engine/api/companion.js +560 -0
- package/engine/{content-api-validation.js → api/content-api-validation.js} +2 -2
- package/engine/{pr-issue-validation.js → api/pr-issue-validation.js} +33 -6
- package/engine/{settings-validation.js → api/settings-validation.js} +32 -4
- package/engine/api-contracts/agent-content.js +4 -4
- package/engine/api-contracts/capability-manifest.js +236 -0
- package/engine/api-contracts/capability-protocol.js +333 -0
- package/engine/api-contracts/cc-ops.js +1 -1
- package/engine/api-contracts/config-runtime.js +5 -0
- package/engine/api-contracts/core.js +28 -1
- package/engine/api-contracts/index.js +100 -0
- package/engine/api-contracts/orchestration.js +18 -5
- package/engine/api-contracts/pull-requests.js +37 -6
- package/engine/api-contracts/qa-process.js +29 -6
- package/engine/api-contracts/work-plan-prd.js +21 -1
- package/engine/cloud/contract.js +212 -0
- package/engine/cloud/index.js +159 -0
- package/engine/{execution-model.js → core/execution-model.js} +1 -1
- package/engine/{features.js → core/features.js} +4 -4
- package/engine/{operator-identity.js → core/operator-identity.js} +1 -1
- package/engine/{queries.js → core/queries.js} +201 -36
- package/engine/{safe-expr.js → core/safe-expr.js} +1 -1
- package/engine/{shared.js → core/shared.js} +1637 -175
- package/engine/{stdio-timestamps.js → core/stdio-timestamps.js} +1 -1
- package/engine/{untrusted-fence.js → core/untrusted-fence.js} +3 -3
- package/engine/db/index.js +11 -2
- package/engine/db/migrations/002-dispatches.js +3 -3
- package/engine/db/migrations/003-work-items.js +1 -1
- package/engine/db/migrations/004-pull-requests.js +1 -1
- package/engine/db/migrations/006-metrics.js +1 -1
- package/engine/db/migrations/007-watches.js +2 -2
- package/engine/db/migrations/008-small-state.js +1 -1
- package/engine/db/migrations/009-qa.js +1 -1
- package/engine/db/migrations/010-pr-links.js +1 -1
- package/engine/db/migrations/011-remaining-state.js +1 -1
- package/engine/db/migrations/012-steering-deliveries.js +2 -2
- package/engine/db/migrations/013-backfill-broken-note-links.js +1 -1
- package/engine/db/migrations/014-pr-fix-target-prefs.js +2 -2
- package/engine/db/migrations/015-plans-prds.js +0 -0
- package/engine/db/migrations/018-sql-only-cutover.js +2 -2
- package/engine/db/migrations/021-archived-work-items.js +1 -1
- package/engine/db/migrations/022-global-cc-session.js +1 -1
- package/engine/db/migrations/023-engine-state.js +1 -1
- package/engine/db/migrations/025-malformed-work-item-phantoms.js +1 -1
- package/engine/db/migrations/027-review-learning-lifecycle.js +1 -1
- package/engine/db/migrations/029-repair-reused-versions.js +20 -0
- package/engine/db/migrations/031-pr-author-identity.js +137 -0
- package/engine/{consolidation.js → memory/consolidation.js} +6 -6
- package/engine/{kb-sweep-runner.js → memory/kb-sweep-runner.js} +2 -2
- package/engine/{kb-sweep.js → memory/kb-sweep.js} +9 -7
- package/engine/{memory-retrieval.js → memory/memory-retrieval.js} +46 -4
- package/engine/{memory-store.js → memory/memory-store.js} +3 -3
- package/engine/{promotion.js → memory/promotion.js} +3 -3
- package/engine/{review-learning-backfill.js → memory/review-learning-backfill.js} +6 -6
- package/engine/{review-learning.js → memory/review-learning.js} +10 -5
- package/engine/{diagnostics-memory.js → observability/diagnostics-memory.js} +1 -1
- package/engine/{logs-store.js → observability/logs-store.js} +5 -5
- package/engine/{metrics-store.js → observability/metrics-store.js} +4 -4
- package/engine/{check-status.js → operations/check-status.js} +3 -3
- package/engine/{cli.js → operations/cli.js} +271 -113
- package/engine/{distribution.js → operations/distribution.js} +5 -6
- package/engine/{cleanup.js → orchestration/cleanup.js} +72 -45
- package/engine/{cooldown.js → orchestration/cooldown.js} +5 -5
- package/engine/{dispatch-events.js → orchestration/dispatch-events.js} +2 -2
- package/engine/{dispatch.js → orchestration/dispatch.js} +129 -36
- package/engine/orchestration/failed-scheduled-cleanup.js +274 -0
- package/engine/{lifecycle.js → orchestration/lifecycle.js} +198 -90
- package/engine/{meeting.js → orchestration/meeting.js} +6 -16
- package/engine/{pipeline.js → orchestration/pipeline.js} +12 -12
- package/engine/{pre-dispatch-eval.js → orchestration/pre-dispatch-eval.js} +10 -9
- package/engine/{routing.js → orchestration/routing.js} +3 -3
- package/engine/{schedule-bootstrap.js → orchestration/schedule-bootstrap.js} +4 -4
- package/engine/{scheduler.js → orchestration/scheduler.js} +38 -8
- package/engine/{timeout.js → orchestration/timeout.js} +158 -109
- package/engine/{db-events.js → persistence/db-events.js} +2 -2
- package/engine/{dispatch-store.js → persistence/dispatch-store.js} +7 -7
- package/engine/{inbox-store.js → persistence/inbox-store.js} +2 -2
- package/engine/{note-link-backfill.js → persistence/note-link-backfill.js} +4 -4
- package/engine/{pr-fix-target-store.js → persistence/pr-fix-target-store.js} +8 -8
- package/engine/{pull-requests-store.js → persistence/pull-requests-store.js} +21 -7
- package/engine/{small-state-store.js → persistence/small-state-store.js} +31 -31
- package/engine/persistence/state-operations.js +350 -0
- package/engine/{steering-store.js → persistence/steering-store.js} +6 -6
- package/engine/{issues.js → planning/issues.js} +2 -2
- package/engine/{plan-prd-validation.js → planning/plan-prd-validation.js} +8 -2
- package/engine/planning/prd-result-sidecar.js +190 -0
- package/engine/{prd-store.js → planning/prd-store.js} +17 -17
- package/engine/{project-discovery.js → planning/project-discovery.js} +5 -5
- package/engine/{projects.js → planning/projects.js} +10 -10
- package/engine/{resolve-area.js → planning/resolve-area.js} +1 -1
- package/engine/{work-item-validation.js → planning/work-item-validation.js} +39 -3
- package/engine/{work-items-store.js → planning/work-items-store.js} +29 -21
- package/engine/{keep-process-sweep.js → processes/keep-process-sweep.js} +57 -17
- package/engine/{managed-spawn-launcher.js → processes/managed-spawn-launcher.js} +3 -3
- package/engine/{managed-spawn.js → processes/managed-spawn.js} +97 -46
- package/engine/{process-utils.js → processes/process-utils.js} +599 -55
- package/engine/{abandoned-pr-reconciliation.js → providers/abandoned-pr-reconciliation.js} +17 -7
- package/engine/{comment-classifier.js → providers/comment-classifier.js} +85 -17
- package/engine/{comment-format.js → providers/comment-format.js} +5 -5
- package/engine/{gh-comment.js → providers/gh-comment.js} +15 -15
- package/engine/{gh-token.js → providers/gh-token.js} +4 -4
- package/engine/{github.js → providers/github.js} +131 -54
- package/engine/{pr-action.js → providers/pr-action.js} +13 -12
- package/engine/{pr-clone-keep.js → providers/pr-clone-keep.js} +7 -7
- package/engine/{pr-devbox.js → providers/pr-devbox.js} +6 -6
- package/engine/{pr-fix-target.js → providers/pr-fix-target.js} +13 -13
- package/engine/{pr-remote-patch.js → providers/pr-remote-patch.js} +4 -4
- package/engine/{pr-resolve.js → providers/pr-resolve.js} +7 -7
- package/engine/{pr-temp-clone.js → providers/pr-temp-clone.js} +5 -5
- package/engine/{pr-track.js → providers/pr-track.js} +11 -13
- package/engine/{shared-branch-pr-reconcile.js → providers/shared-branch-pr-reconcile.js} +4 -4
- package/engine/qa/auto-prd-qa.js +313 -0
- package/engine/{qa-from-prd.js → qa/from-prd.js} +42 -12
- package/engine/qa/prd-session.js +240 -0
- package/engine/{qa-process-validation.js → qa/process-validation.js} +14 -9
- package/engine/{qa-runbooks.js → qa/runbooks.js} +1 -1
- package/engine/{qa-runs.js → qa/runs.js} +286 -15
- package/engine/{qa-sessions.js → qa/sessions.js} +595 -49
- package/engine/qa/visual-journey.js +654 -0
- package/engine/{qa-runners.js → qa-runners/index.js} +7 -7
- package/engine/qa-runners/maestro.js +3 -3
- package/engine/qa-runners/playwright.js +2 -2
- package/engine/{restart-health.js → recovery/restart-health.js} +48 -4
- package/engine/recovery/stop-stack.js +607 -0
- package/engine/{supervisor.js → recovery/supervisor.js} +105 -175
- package/engine/{watchdog.js → recovery/watchdog.js} +136 -13
- package/engine/runtimes/claude.js +14 -12
- package/engine/runtimes/codex.js +8 -6
- package/engine/runtimes/copilot.js +17 -16
- package/engine/{watch-actions.js → watches/actions.js} +13 -13
- package/engine/{watches.js → watches/index.js} +43 -32
- package/engine/{watches-store.js → watches/store.js} +4 -4
- package/engine/{create-pr-worktree.js → worktrees/create-pr.js} +1 -1
- package/engine/{worktree-gc.js → worktrees/gc.js} +70 -22
- package/engine/worktrees/inventory.js +671 -0
- package/engine/{live-checkout.js → worktrees/live-checkout.js} +4 -4
- package/engine/{worktree-pool.js → worktrees/pool.js} +2 -2
- package/engine/{worktree-preflight.js → worktrees/preflight.js} +1 -0
- package/engine/worktrees/quarantine-refs.js +173 -0
- package/engine.js +1137 -208
- package/minions.js +147 -77
- package/package.json +10 -6
- package/playbooks/_pr-description-audit.md +110 -78
- package/playbooks/build-fix-complex.md +2 -0
- package/playbooks/fix.md +16 -12
- package/playbooks/implement-shared.md +2 -0
- package/playbooks/implement.md +19 -20
- package/playbooks/plan-to-prd.md +18 -3
- package/playbooks/qa-session-draft.md +136 -1
- package/playbooks/qa-session-execute.md +80 -2
- package/playbooks/qa-session-setup.md +17 -1
- package/playbooks/qa-validate.md +1 -1
- package/playbooks/setup.md +2 -0
- package/playbooks/shared-rules.md +25 -32
- package/playbooks/templates/followup-dispatch.md +4 -3
- package/playbooks/verify.md +1 -1
- package/prompts/cc-system.md +19 -27
- package/watch-plugins/README.md +92 -0
- package/watch-plugins/ado-author-prs.js +336 -0
- package/watch-plugins/gh-author-prs.js +375 -0
- package/watch-plugins/http.js +474 -0
- package/watch-plugins/teams-channel.js +869 -0
- package/docs/dev-composite-workflow.md +0 -101
- package/docs/pr-screenshots/pr-886/after-single-header.png +0 -0
- package/docs/pr-screenshots/pr-886/before-duplicate-header.png +0 -0
- package/docs/pr-screenshots/pr-895/01-cancellation-reason-detail.png +0 -0
- package/docs/pr-screenshots/pr-899/worker-pool-worktrees-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-899/worker-pool-worktrees-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-901/projects-tab-default.png +0 -0
- package/docs/pr-screenshots/pr-901/projects-tab-fmf-selected.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-AFTER-crop.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-BEFORE-crop.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-dropdown-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-979/auto-fix-pane-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-979/auto-fix-pane-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-985/pr-column-em-dash-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-985/pr-column-em-dash-BEFORE.png +0 -0
- package/docs/visual-evidence-ci.md +0 -103
- package/engine/bridge.js +0 -379
- package/engine/quarantine-refs.js +0 -103
- package/engine/state-operations.js +0 -178
- /package/engine/{steering-constraints.js → agents/steering-constraints.js} +0 -0
|
@@ -0,0 +1,1051 @@
|
|
|
1
|
+
# Minions Design Language
|
|
2
|
+
|
|
3
|
+
> A code-derived specification of the Minions dashboard visual and interaction
|
|
4
|
+
> system. Every rule below is traceable to a concrete token, selector, HTML
|
|
5
|
+
> fragment, or JavaScript renderer in `dashboard/`. Treat this as both an
|
|
6
|
+
> **implementation guide** (convert another app to the Minions language) and an
|
|
7
|
+
> **audit standard** (grade new and existing Minions UI objectively).
|
|
8
|
+
|
|
9
|
+
**Scope.** This covers the two live front-ends served by `dashboard.js`:
|
|
10
|
+
|
|
11
|
+
- **Classic UX** — the default multi-page SPA. Canonical stylesheet
|
|
12
|
+
`dashboard/styles.css`; shell `dashboard/layout.html`; page fragments
|
|
13
|
+
`dashboard/pages/*.html`; renderers `dashboard/js/*.js`.
|
|
14
|
+
- **Slim UX** — a feature-flagged (`slim-ux`) single-screen cockpit. Self-contained
|
|
15
|
+
stylesheet `dashboard/slim/styles.css`; shell `dashboard/slim/layout.html` +
|
|
16
|
+
`dashboard/slim/body.html`; renderers `dashboard/slim/js/*.js`.
|
|
17
|
+
|
|
18
|
+
Both are assembled into one HTML string at startup by `dashboard-build.js` and
|
|
19
|
+
served from disk on each request (no build step). The two stylesheets are
|
|
20
|
+
**served independently** and intentionally duplicate their token blocks; a
|
|
21
|
+
tripwire test keeps the shared values in lockstep (see
|
|
22
|
+
[§13 Known inconsistencies](#13-known-inconsistencies--legacy-exceptions)).
|
|
23
|
+
|
|
24
|
+
> **Golden rule.** The design language lives in CSS custom properties declared
|
|
25
|
+
> in the `:root` blocks of the two stylesheets. New UI MUST consume tokens, never
|
|
26
|
+
> raw hex or raw `Npx`. Ad-hoc values are the single most common audit failure.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Table of contents
|
|
31
|
+
|
|
32
|
+
1. [Design principles & personality](#1-design-principles--personality)
|
|
33
|
+
2. [Color system](#2-color-system)
|
|
34
|
+
3. [Typography](#3-typography)
|
|
35
|
+
4. [Spacing, radii, shadows, motion](#4-spacing-radii-shadows-motion)
|
|
36
|
+
5. [Layout & page shells](#5-layout--page-shells)
|
|
37
|
+
6. [Components](#6-components)
|
|
38
|
+
7. [Status & content language](#7-status--content-language)
|
|
39
|
+
8. [Interaction states & accessibility](#8-interaction-states--accessibility)
|
|
40
|
+
9. [Classic vs Slim: shared foundations vs intentional differences](#9-classic-vs-slim-shared-foundations-vs-intentional-differences)
|
|
41
|
+
10. [Reusable implementation patterns](#10-reusable-implementation-patterns)
|
|
42
|
+
11. [Migration playbook (adopt Minions in another app)](#11-migration-playbook)
|
|
43
|
+
12. [Audit rubric & checklist](#12-audit-rubric--checklist)
|
|
44
|
+
13. [Known inconsistencies & legacy exceptions](#13-known-inconsistencies--legacy-exceptions)
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 1. Design principles & personality
|
|
49
|
+
|
|
50
|
+
Minions is **mission control for an autonomous agent fleet** — a dense,
|
|
51
|
+
always-on operator dashboard, not a marketing surface. The visual language is
|
|
52
|
+
derived directly from its implementation and reflects five principles:
|
|
53
|
+
|
|
54
|
+
1. **Dark, terminal-adjacent, GitHub-native.** The palette is GitHub's Primer
|
|
55
|
+
dark scale (`#0d1117` canvas, `#161b22` surface, `#30363d` border, `#58a6ff`
|
|
56
|
+
blue). Operators live in GitHub, ADO, and terminals all day; the dashboard
|
|
57
|
+
sits beside them without a jarring context switch. There is **no light theme**
|
|
58
|
+
— dark is the only mode (see [§2](#2-color-system)).
|
|
59
|
+
|
|
60
|
+
2. **Information density over whitespace.** Tight spacing (`2/4/6/8px` base
|
|
61
|
+
rhythm), a `12px` type floor for readable metadata, uppercase micro-labels,
|
|
62
|
+
and `tabular-nums` for aligned counters. The sidebar is a fixed `150px`; cards
|
|
63
|
+
and tables pack many rows per viewport. Compare a consumer app's airy
|
|
64
|
+
`24px` gutters — Minions deliberately uses `--space-4: 8px` as its workhorse.
|
|
65
|
+
|
|
66
|
+
3. **Color is semantic, never decorative.** Each accent hue maps to a fixed
|
|
67
|
+
meaning: **green = success/create/go**, **red = failure/destroy/stop**,
|
|
68
|
+
**yellow/amber = in-progress/attention**, **blue = active/primary/info**,
|
|
69
|
+
**purple = merged/agent/review**, **muted grey = idle/neutral/disabled**. A
|
|
70
|
+
badge's color IS its status. Never pick a hue for looks (see
|
|
71
|
+
[§7](#7-status--content-language)).
|
|
72
|
+
|
|
73
|
+
4. **State is always legible at a glance.** Every agent, work item, PR, plan,
|
|
74
|
+
dispatch, and engine has a color-coded badge plus, where it matters, motion
|
|
75
|
+
(a pulsing dot = live/working, a dashed border = stale/needs-attention). An
|
|
76
|
+
operator should read fleet health from across the room.
|
|
77
|
+
|
|
78
|
+
5. **Progressive disclosure through panels & modals.** The surface stays calm;
|
|
79
|
+
detail lives one click deep. Cards open modals (`.modal-bg` / `.modal`), the
|
|
80
|
+
modal stack supports depth up to 5 (`.modal-stack-chip`), and the Command
|
|
81
|
+
Center is a right-hand drawer, not a page.
|
|
82
|
+
|
|
83
|
+
**Interaction philosophy.** Optimistic UI (flip a toggle, then await the API),
|
|
84
|
+
non-blocking async refresh (`/api/status` polled every 4s), hover-to-preview /
|
|
85
|
+
click-to-open, and keyboard-reachable focus rings on every interactive element.
|
|
86
|
+
Destructive actions route through a promise-based confirm dialog
|
|
87
|
+
(`dashboard/js/confirm-dialog.js`), never `window.confirm`.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 2. Color system
|
|
92
|
+
|
|
93
|
+
### 2.1 Source of truth
|
|
94
|
+
|
|
95
|
+
All colors are CSS custom properties in the `:root` block of each stylesheet.
|
|
96
|
+
**Classic:** `dashboard/styles.css:10-12`. **Slim:** `dashboard/slim/styles.css:13-25`.
|
|
97
|
+
Never write a raw hex outside these blocks; the only sanctioned literals are the
|
|
98
|
+
`rgba(...)` tint fills derived from these hues (see [§2.4](#24-tint-fills)) and
|
|
99
|
+
the one audited scoped token block slim declares for the reused detail panel
|
|
100
|
+
(`dashboard/slim/styles.css:1859-1865` — see [§2.3](#23-palette-tokens-that-diverge-classic-vs-slim)
|
|
101
|
+
and §13 item 10).
|
|
102
|
+
|
|
103
|
+
### 2.2 Core palette (shared foundation)
|
|
104
|
+
|
|
105
|
+
These seven tokens are **byte-identical** across Classic and Slim and form the
|
|
106
|
+
neutral + primary spine:
|
|
107
|
+
|
|
108
|
+
| Token | Hex | Semantic role |
|
|
109
|
+
| ------------ | --------- | --------------------------------------------------------- |
|
|
110
|
+
| `--bg` | `#0d1117` | App canvas / page background, input backgrounds |
|
|
111
|
+
| `--surface` | `#161b22` | Header, sidebar, modals, table sticky headers, raised bars|
|
|
112
|
+
| `--border` | `#30363d` | Hairline borders, dividers, default (idle) button borders |
|
|
113
|
+
| `--muted` | `#8b949e` | Secondary text, metadata, timestamps, disabled/idle state |
|
|
114
|
+
| `--blue` | `#58a6ff` | Primary action, active state, links, info, focus rings |
|
|
115
|
+
| `--green` | `#3fb950` | Success, create/add, approve, build-pass, "go" |
|
|
116
|
+
| `--red` | `#f85149` | Failure, destroy/delete, changes-requested, build-fail |
|
|
117
|
+
|
|
118
|
+
### 2.3 Palette tokens that diverge Classic vs Slim
|
|
119
|
+
|
|
120
|
+
These carry the **same semantic role** but different hex. The table describes
|
|
121
|
+
slim's **global** `:root` (`dashboard/slim/styles.css:13-56`) — see the scoped
|
|
122
|
+
token island below before auditing a rule. Do **not** assume parity — the
|
|
123
|
+
divergence is real and load-bearing (see
|
|
124
|
+
[§13](#13-known-inconsistencies--legacy-exceptions)):
|
|
125
|
+
|
|
126
|
+
| Token | Classic (`styles.css`) | Slim `:root` (`slim/styles.css`) | Role |
|
|
127
|
+
| ------------ | ---------------------- | -------------------------------- | -------------------------------------- |
|
|
128
|
+
| `--surface2` | `#21262d` | `#1c2128` | Cards, chips, nested panels, row hover |
|
|
129
|
+
| `--text` | `#e6edf3` | `#c9d1d9` | Primary body text |
|
|
130
|
+
| in-progress | `--yellow: #d29922` | `--amber: #d29922` | Working / building (same hex, diff name)|
|
|
131
|
+
| `--orange` | `#e3b341` | `#ea580c` | Attention / stale / fan-out |
|
|
132
|
+
| `--purple` | `#bc8cff` | *(not in slim `:root`)* | Merged / agent / review / archive |
|
|
133
|
+
|
|
134
|
+
> **Audit note.** Slim names its in-progress token `--amber` and Classic names it
|
|
135
|
+
> `--yellow`, but both resolve to `#d29922`. Slim's `--orange` (`#ea580c`, a hotter
|
|
136
|
+
> red-orange) and Classic's `--orange` (`#e3b341`, a golden amber) genuinely
|
|
137
|
+
> differ. Reference the token by name; never hard-code the hex.
|
|
138
|
+
|
|
139
|
+
> 🔑 **Scoped token island — slim is not token-poor everywhere.** Beyond its
|
|
140
|
+
> global `:root`, slim re-declares the **full Classic token set** scoped to the
|
|
141
|
+
> reused agent detail panel: `--yellow`, `--purple`, `--orange` (at the *Classic*
|
|
142
|
+
> `#e3b341`, not slim's `#ea580c`), `--radius-sm..--radius-full`,
|
|
143
|
+
> `--transition-fast/base/slow`, and `--space-1..--space-9` at the *Classic* 2px
|
|
144
|
+
> values — all under `#detail-panel, #detail-overlay`
|
|
145
|
+
> (`dashboard/slim/styles.css:1859-1865`). It exists so the panel rules mirrored
|
|
146
|
+
> verbatim from Classic (`dashboard/slim/styles.css:1867-1974`) resolve to
|
|
147
|
+
> Classic values **without** disturbing slim's global palette. Consequence for
|
|
148
|
+
> auditors: `var(--purple)` is *valid* in a panel descendant — e.g.
|
|
149
|
+
> `.dispatch-type.review` (`:1914`) and `.dispatch-type.decompose` (`:1923`) —
|
|
150
|
+
> and *invalid* anywhere else in slim. Always resolve the selector's scope before
|
|
151
|
+
> flagging a slim token reference (§13 item 10).
|
|
152
|
+
|
|
153
|
+
### 2.4 Tint fills
|
|
154
|
+
|
|
155
|
+
Accent backgrounds are the accent hue at **~15% opacity** with a **solid 1px
|
|
156
|
+
border** at full opacity. This "ghost chip" pattern is the entire badge/pill
|
|
157
|
+
system. Canonical values (`dashboard/styles.css:769-774`):
|
|
158
|
+
|
|
159
|
+
```css
|
|
160
|
+
.badge-blue { background: rgba(88,166,255,0.15); color: var(--blue); border: 1px solid var(--blue); }
|
|
161
|
+
.badge-green { background: rgba(63,185,80,0.15); color: var(--green); border: 1px solid var(--green); }
|
|
162
|
+
.badge-red { background: rgba(248,81,73,0.15); color: var(--red); border: 1px solid var(--red); }
|
|
163
|
+
.badge-yellow { background: rgba(210,153,34,0.15); color: var(--yellow); border: 1px solid var(--yellow); }
|
|
164
|
+
.badge-purple { background: rgba(188,140,255,0.15);color: var(--purple); border: 1px solid var(--purple); }
|
|
165
|
+
.badge-muted { background: var(--surface); color: var(--muted); border: 1px solid var(--border); }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Hover tints on action buttons use **~10%** opacity of the same hue
|
|
169
|
+
(`.btn-add:hover { background: rgba(63,185,80,0.1); }`,
|
|
170
|
+
`dashboard/styles.css:568`). Emphasis variants step up to `0.22`–`0.25` and swap
|
|
171
|
+
to a **dashed** or **2px** border (`.pr-badge.build-escalated`,
|
|
172
|
+
`dashboard/styles.css:441`).
|
|
173
|
+
|
|
174
|
+
> The `rgba()` literals restate the hex of the corresponding token. This is the
|
|
175
|
+
> one sanctioned exception to "no raw color" — CSS cannot yet apply alpha to a
|
|
176
|
+
> custom property without `color-mix`, which the codebase does not use. When you
|
|
177
|
+
> add a tinted surface, reuse the exact `rgba` triplet already used for that hue
|
|
178
|
+
> elsewhere; do not introduce a new opacity step without cause.
|
|
179
|
+
|
|
180
|
+
### 2.5 Off-palette accent literals (observed, constrained)
|
|
181
|
+
|
|
182
|
+
A handful of dispatch/type chips use raw hex for hues with no token, in
|
|
183
|
+
`dashboard/styles.css:1089-1098`:
|
|
184
|
+
|
|
185
|
+
- `#a855f7` — `plan` / `plan-to-prd` dispatch type (violet, distinct from `--purple`)
|
|
186
|
+
- `#38bdf8` — `docs` dispatch type (sky)
|
|
187
|
+
- `#14b8a6` — `setup` dispatch type (teal)
|
|
188
|
+
|
|
189
|
+
**Observed vs canonical:** these are intentional type-taxonomy colors with no
|
|
190
|
+
`:root` token. Recommended canonical guidance: if you add a new dispatch/work
|
|
191
|
+
type chip, follow the same tint pattern (`rgba(...,0.15)` fill + solid text
|
|
192
|
+
color) and, if the hue recurs, promote it to a `:root` token. Do not scatter new
|
|
193
|
+
raw hex for one-off UI.
|
|
194
|
+
|
|
195
|
+
### 2.6 Light/dark & contrast
|
|
196
|
+
|
|
197
|
+
There is **no light mode**. All contrast targets assume the dark canvas.
|
|
198
|
+
Expectations:
|
|
199
|
+
|
|
200
|
+
- Body text `--text` on `--bg`/`--surface`: comfortably exceeds WCAG AA (7:1+).
|
|
201
|
+
- `--muted` (`#8b949e`) on `--bg` is the **contrast floor** (~AA for normal text
|
|
202
|
+
≥ the `12px` type floor). Do **not** put `--muted` below `12px` for
|
|
203
|
+
reading text — that combination fails; the type system enforces a `12px` floor
|
|
204
|
+
precisely for this reason (see [§3.4](#34-the-12px-readability-floor)).
|
|
205
|
+
- Accent text (`--blue`, `--green`, `--red`, etc.) is only used at badge/label
|
|
206
|
+
weight (`font-weight: 600`, uppercase) on its matching `0.15` tint, which
|
|
207
|
+
preserves legibility. Never use a `0.15` tint as text color.
|
|
208
|
+
|
|
209
|
+
**Prohibited:**
|
|
210
|
+
- Raw hex or named CSS colors (`#fff`, `white`, `black`) outside the `:root`
|
|
211
|
+
blocks — with the audited exceptions `#fff` for text-on-solid-accent buttons
|
|
212
|
+
(`.btn-primary`, `dashboard/styles.css:539`) and the `rgba(0,0,0,…)` shadow /
|
|
213
|
+
modal-backdrop scrims.
|
|
214
|
+
- Introducing a second neutral scale, a light theme, or a gradient background
|
|
215
|
+
(the only gradients are the intentional "Try Slim UX" shimmer animation,
|
|
216
|
+
`dashboard/styles.css:966`).
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 3. Typography
|
|
221
|
+
|
|
222
|
+
### 3.1 Font families
|
|
223
|
+
|
|
224
|
+
- **UI:** `'Segoe UI', system-ui, sans-serif` (Classic body,
|
|
225
|
+
`dashboard/styles.css:72`; Slim adds `-apple-system, BlinkMacSystemFont`,
|
|
226
|
+
`dashboard/slim/styles.css:86`).
|
|
227
|
+
- **Monospace:** `Consolas, monospace` for IDs, branch names, feature IDs, code
|
|
228
|
+
(`.mono`, `dashboard/styles.css:795`; `.feat-id`, `:510`).
|
|
229
|
+
- **Inline code:** `--text-code: 0.9em` — the one relative token, so code reads
|
|
230
|
+
10% smaller than its surrounding text (`dashboard/styles.css:49`).
|
|
231
|
+
|
|
232
|
+
### 3.2 Size primitives (single source of truth)
|
|
233
|
+
|
|
234
|
+
Declared once per stylesheet (`dashboard/styles.css:31-33`), documented in
|
|
235
|
+
`dashboard/docs/typography.md`. **Never hand-roll a `font-size: Npx`** — a
|
|
236
|
+
tripwire test (`test/unit/dashboard-font-size-tokens.test.js`) fails CI if a raw
|
|
237
|
+
px/em font-size leaks in.
|
|
238
|
+
|
|
239
|
+
| Token | Base | Common use |
|
|
240
|
+
| ---------------- | ----- | ------------------------------------------------------- |
|
|
241
|
+
| `--text-xs` | 10px | Reserved dense chrome only (below the readability floor) |
|
|
242
|
+
| `--text-sm` | 12px | Status badges, chip / tag labels |
|
|
243
|
+
| `--text-base` | 12px | Captions, secondary metadata, dense table cells |
|
|
244
|
+
| `--text-md` | 13px | Detail tables, button labels, slim chat body |
|
|
245
|
+
| `--text-lg` | 14px | Body text, modal textarea, card titles |
|
|
246
|
+
| `--text-xl` | 16px | Main `<body>` font, secondary headers, chat input |
|
|
247
|
+
| `--text-2xl` | 18px | Section headers, page headers, modal h3 |
|
|
248
|
+
| `--text-stat` | 22px | Stat counter readouts, member emoji glyphs |
|
|
249
|
+
| `--text-stat-lg` | 28px | Larger stat readouts, completion type emoji |
|
|
250
|
+
| `--text-display` | 32px | Page hero, markdown H1, agent-detail emoji |
|
|
251
|
+
| `--text-code` | 0.9em | Inline `<code>` (relative) |
|
|
252
|
+
|
|
253
|
+
Each primitive is `calc(<base>px * var(--minions-text-scale))`. Classic pins
|
|
254
|
+
`--minions-text-scale: 1.05` (a global +5% bump); Slim pins it to `1`. The base
|
|
255
|
+
px values **must** match between the two stylesheets.
|
|
256
|
+
|
|
257
|
+
### 3.3 Role aliases (preferred for new code)
|
|
258
|
+
|
|
259
|
+
Semantic names that point at primitives (`dashboard/styles.css:42-49`). Prefer
|
|
260
|
+
these — they survive a size redesign without callsite edits:
|
|
261
|
+
|
|
262
|
+
| Role token | Alias → size | Intended use |
|
|
263
|
+
| --------------------- | ------------------- | ---------------------------------------- |
|
|
264
|
+
| `--text-role-display` | `--text-display` | Page hero, dashboard title |
|
|
265
|
+
| `--text-heading` | `--text-2xl` (18px) | Section + modal headers |
|
|
266
|
+
| `--text-subheading` | `--text-xl` (16px) | Secondary headers, card titles |
|
|
267
|
+
| `--text-body` | `--text-lg` (14px) | Default body text |
|
|
268
|
+
| `--text-meta` | `--text-md` (13px) | Captions, timestamps, secondary metadata |
|
|
269
|
+
| `--text-caption` | `--text-base` (12px)| Small labels, table cells |
|
|
270
|
+
| `--text-micro` | `--text-sm` (12px) | Chip / tag pill labels |
|
|
271
|
+
| `--text-code` | `0.9em` | Inline code |
|
|
272
|
+
|
|
273
|
+
Utility classes mirror each role: `.text-display .text-heading .text-subheading
|
|
274
|
+
.text-body .text-meta .text-caption .text-micro .text-code`
|
|
275
|
+
(`dashboard/styles.css:80-87`). They set **only** `font-size`; weight, color, and
|
|
276
|
+
line-height stay with the caller.
|
|
277
|
+
|
|
278
|
+
### 3.4 The 12px readability floor
|
|
279
|
+
|
|
280
|
+
`--text-sm` was raised to a **12px** base so it clears the readability floor in
|
|
281
|
+
both stylesheets (Classic renders `12 × 1.05 = 12.6px`, Slim `12px`). `--text-xs`
|
|
282
|
+
(10px) stays below the floor and is retained only at two genuinely dense chrome
|
|
283
|
+
callsites (`.token-chart-labels span`, `.qa-phase-arrow`). See
|
|
284
|
+
`dashboard/docs/typography.md` §"12px readability floor". **Do not** introduce
|
|
285
|
+
new `--text-xs` reading text.
|
|
286
|
+
|
|
287
|
+
### 3.5 Weight, case, and treatment conventions
|
|
288
|
+
|
|
289
|
+
- **Section headers:** `text-transform: uppercase; letter-spacing: 1px; color:
|
|
290
|
+
var(--muted); font-weight: 600` at `--text-base` (`section h2`,
|
|
291
|
+
`dashboard/styles.css:114`). Uppercase micro-labels are a signature of the
|
|
292
|
+
language.
|
|
293
|
+
- **Table headers:** uppercase, `letter-spacing: 0.5px`, `--muted`,
|
|
294
|
+
`font-weight: 500`, `--text-sm` (`.table th`, `:778`; `.pr-table th`, `:381`).
|
|
295
|
+
- **Badges/pills:** uppercase, `font-weight: 600`, `--text-sm` (`.badge`, `:764`;
|
|
296
|
+
`.pr-badge`, `:428`).
|
|
297
|
+
- **Body:** default weight, `--text` color; **bold** = `font-weight: 600` via
|
|
298
|
+
`.font-bold` (`:796`) — the design uses 600 as its "bold", not 700, except for
|
|
299
|
+
emphasis badges (`.dispatch-stat-num` 700, `:1073`).
|
|
300
|
+
- **Numeric readouts:** `font-variant-numeric: tabular-nums` for timestamps and
|
|
301
|
+
counters (`.timestamp`, `:98`; `.modal-stack-chip`, `:1210`).
|
|
302
|
+
|
|
303
|
+
### 3.6 Truncation & wrapping
|
|
304
|
+
|
|
305
|
+
- Single-line ellipsis via `.truncate` (`white-space:nowrap; overflow:hidden;
|
|
306
|
+
text-overflow:ellipsis`, `:797`) — used for agent actions, dispatch tasks, PR
|
|
307
|
+
titles/branches, project branches. Always pair a truncated element with a
|
|
308
|
+
`title` attribute carrying the full text (see `_renderProjectBranch` note,
|
|
309
|
+
`dashboard/styles.css:1523`).
|
|
310
|
+
- Multi-line content that must wrap uses `white-space: pre-wrap; word-break:
|
|
311
|
+
break-word` (`.modal-qa-a`, `:137`).
|
|
312
|
+
|
|
313
|
+
### 3.7 Responsive type scaling
|
|
314
|
+
|
|
315
|
+
Two independent mechanisms:
|
|
316
|
+
|
|
317
|
+
1. **User zoom** — `[data-font-size]` on `<html>` drives `--minions-font-scale`
|
|
318
|
+
applied as body-level `zoom` (`small 1.0 / medium 1.08 / large 1.18 / xlarge
|
|
319
|
+
1.30`, `dashboard/styles.css:66-69,72`). Set in `<head>` before first paint
|
|
320
|
+
from `localStorage['minions:font-size']` (`dashboard/layout.html:13-19`).
|
|
321
|
+
2. **Global bump** — `--minions-text-scale` (Classic `1.05`) is an actual
|
|
322
|
+
font-size change applied uniformly to every primitive.
|
|
323
|
+
|
|
324
|
+
At `≤640px`, headers, stats, and tables shrink to smaller tokens (`.pr-table`
|
|
325
|
+
→ `--text-base`, headers → `--text-xl`, `dashboard/styles.css:1470-1483`).
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## 4. Spacing, radii, shadows, motion
|
|
330
|
+
|
|
331
|
+
### 4.1 Spacing scale
|
|
332
|
+
|
|
333
|
+
**Classic** — 9-step, `2px`-anchored (`dashboard/styles.css:15-16`):
|
|
334
|
+
|
|
335
|
+
`--space-1:2 --space-2:4 --space-3:6 --space-4:8 --space-5:10 --space-6:12
|
|
336
|
+
--space-7:16 --space-8:20 --space-9:24`
|
|
337
|
+
|
|
338
|
+
**Slim (global `:root`)** — 5-step, `4px`-anchored `4/8/12/16/20` rhythm
|
|
339
|
+
(`dashboard/slim/styles.css:30`):
|
|
340
|
+
|
|
341
|
+
`--space-1:4 --space-2:8 --space-3:12 --space-4:16 --space-5:20`
|
|
342
|
+
|
|
343
|
+
> **Critical divergence.** The `--space-N` tokens mean **different pixel values**
|
|
344
|
+
> in the two stylesheets. `--space-4` = `8px` in Classic but `16px` in Slim. Never
|
|
345
|
+
> copy a spacing rule between the two without re-mapping. Slim declares its own
|
|
346
|
+
> scale precisely because it ships CSS independently. `--space-4: 8px` is the
|
|
347
|
+
> Classic workhorse gutter (cards, flex gaps, table cells).
|
|
348
|
+
|
|
349
|
+
> **Exception — the scoped token island.** Inside `#detail-panel,
|
|
350
|
+
> #detail-overlay` slim re-declares the **Classic** 9-step 2px scale
|
|
351
|
+
> (`--space-1..--space-9`, `dashboard/slim/styles.css:1863-1864`), so panel
|
|
352
|
+
> descendants resolve `--space-4` to `8px`, not `16px`. Panel rules mirrored from
|
|
353
|
+
> Classic into that subtree are therefore correct **unmapped** — the re-mapping
|
|
354
|
+
> rule above governs slim's *global* surfaces only (§2.3, §13 item 10).
|
|
355
|
+
|
|
356
|
+
### 4.2 Border radius (Classic, `dashboard/styles.css:52`)
|
|
357
|
+
|
|
358
|
+
`--radius-sm:4px --radius-md:6px --radius-lg:8px --radius-xl:10px
|
|
359
|
+
--radius-full:50%`
|
|
360
|
+
|
|
361
|
+
- Buttons, inputs, small chips → `--radius-sm`.
|
|
362
|
+
- Cards, dispatch items → `--radius-md` / `--radius-lg`.
|
|
363
|
+
- Badges/pills → `--radius-xl` (`10px`, near-pill).
|
|
364
|
+
- Dots/avatars → `--radius-full`.
|
|
365
|
+
|
|
366
|
+
Slim's **global** `:root` collapses this to a single `--radius: 6px`
|
|
367
|
+
(`dashboard/slim/styles.css:25`), but slim re-declares the whole
|
|
368
|
+
`--radius-sm..--radius-full` ladder at the Classic values scoped to
|
|
369
|
+
`#detail-panel, #detail-overlay` (`dashboard/slim/styles.css:1861`). So
|
|
370
|
+
`var(--radius-xl)` resolves inside the slim detail panel and nowhere else in
|
|
371
|
+
slim — check the selector's scope before flagging it (§2.3, §13 item 10).
|
|
372
|
+
|
|
373
|
+
### 4.3 Shadows (Classic, `dashboard/styles.css:55-57`)
|
|
374
|
+
|
|
375
|
+
`--shadow-sm: 0 1px 3px rgba(0,0,0,0.2)` · `--shadow-md: 0 2px 8px rgba(0,0,0,0.3)`
|
|
376
|
+
· `--shadow-lg: 0 4px 16px rgba(0,0,0,0.4)`
|
|
377
|
+
|
|
378
|
+
Shadows are **restrained** — used for hover lift on cards (`.agent-card:hover`,
|
|
379
|
+
`:122`), floating buttons (`.ask-selection-btn`, `:157`), and elevated menus.
|
|
380
|
+
The primary elevation signal is **border-color change**, not shadow. Focus glow
|
|
381
|
+
uses a blue ring: `box-shadow: 0 0 0 3px rgba(88,166,255,0.12)`
|
|
382
|
+
(`.cmd-input-wrap:focus-within`, `:811`).
|
|
383
|
+
|
|
384
|
+
### 4.4 Motion (Classic, `dashboard/styles.css:60`)
|
|
385
|
+
|
|
386
|
+
`--transition-fast:0.15s --transition-base:0.2s --transition-slow:0.3s`
|
|
387
|
+
|
|
388
|
+
- Hover/color transitions → `--transition-fast` / `--transition-base`.
|
|
389
|
+
- Card transforms → `--transition-slow`.
|
|
390
|
+
- **Live-state animations** are the semantic motion vocabulary:
|
|
391
|
+
- `pulse` (2s opacity, `:97`) — the live "engine running" dot (`.pulse`),
|
|
392
|
+
working badges, stuck warnings.
|
|
393
|
+
- `dotPulse` (1.2s, `:145`) — loading "typing" dots (QA, notif-processing).
|
|
394
|
+
- `notifPulse` (2s, `:1251`) — red unread notification dot.
|
|
395
|
+
- `planPulse` / `wipPulse` / `prdWipPulse` / `plSegPulse` — WIP emphasis on
|
|
396
|
+
plan/PRD/pipeline nodes.
|
|
397
|
+
- **Reduced motion:** honor `@media (prefers-reduced-motion: reduce)`
|
|
398
|
+
(`.try-slim-ux-btn` animation disabled, `:982`). One deliberate exception is
|
|
399
|
+
documented inline at `:1000` (the Command Center sweep). New decorative
|
|
400
|
+
animation MUST respect the reduced-motion query.
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## 5. Layout & page shells
|
|
405
|
+
|
|
406
|
+
### 5.1 Classic shell (`dashboard/layout.html`)
|
|
407
|
+
|
|
408
|
+
```
|
|
409
|
+
<body> (flex column, height 100%, overflow hidden, zoom = font-scale)
|
|
410
|
+
├─ <header> sticky, --surface, bottom border, title + engine badge + tools
|
|
411
|
+
├─ .engine-alert cross-page alert strip
|
|
412
|
+
├─ .paused-banner sticky kill-switch banner (pollingPaused / autoFixPaused)
|
|
413
|
+
├─ #cc-drawer Command Center right drawer (420px, fixed)
|
|
414
|
+
└─ .page-layout flex row, flex:1, overflow hidden
|
|
415
|
+
├─ .sidebar 150px fixed, --surface, right border, sticky
|
|
416
|
+
└─ .page-content flex:1, scrollable; holds .page fragments (one .active)
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Key rules:
|
|
420
|
+
- **Header** — `dashboard/styles.css:89-98`. Sticky, `z-index:100`. `h1` is
|
|
421
|
+
`--text-2xl`, `font-weight:600`, `--blue`, `letter-spacing:0.5px`, with a muted
|
|
422
|
+
`<span>` suffix.
|
|
423
|
+
- **Sidebar** — `:105-111`. Fixed `150px`; links are `--muted` → `--text` on
|
|
424
|
+
hover, active link gets a `3px` `--blue` left border + `--surface2` bg + 600
|
|
425
|
+
weight. Each link carries a `.sidebar-count` pill and optional `.notif-badge`.
|
|
426
|
+
- **Pages** — `.page { display:none }`, `.page.active { display:block }` (`:112`).
|
|
427
|
+
Single-page-at-a-time; sidebar nav swaps `.active`.
|
|
428
|
+
- **Section** — `section { padding: 20px 24px; border-bottom: 1px solid
|
|
429
|
+
var(--border) }` (`:101`); `section h2` is the uppercase muted micro-header
|
|
430
|
+
with an optional `.count` chip (`:114-115`).
|
|
431
|
+
- **Embed mode** — `?embed=1` adds `.embed` to `<html>` to strip chrome (header,
|
|
432
|
+
sidebar, banners) so a page can be iframed as just its panel
|
|
433
|
+
(`dashboard/layout.html:20-32`).
|
|
434
|
+
|
|
435
|
+
### 5.2 Slim shell (`dashboard/slim/layout.html` + `body.html`)
|
|
436
|
+
|
|
437
|
+
A three-region cockpit — **ACTIONS / STATUS / HISTORY** — built from `.panel`
|
|
438
|
+
grid areas (`dashboard/slim/styles.css:204-276`), a `.topbar` (46px, `:123-132`),
|
|
439
|
+
a chat surface (`.chat-*`), and member/tile grids. It is a **single screen**, not
|
|
440
|
+
a paged SPA. See `docs/slim-ux/concepts.md`.
|
|
441
|
+
|
|
442
|
+
### 5.3 Cards, panels, grids
|
|
443
|
+
|
|
444
|
+
- **Card base** `.card` — `--surface2` bg, `1px --border`, `--radius-lg`, padding
|
|
445
|
+
`12px 16px`, hover → `--blue` border (`dashboard/styles.css:522-528`). The
|
|
446
|
+
universal container primitive; specific cards (`.agent-card`, `.plan-card`,
|
|
447
|
+
`.archive-card`) extend it.
|
|
448
|
+
- **Agent grid** — 2-column (`.agents { grid-template-columns: 1fr 1fr }`,
|
|
449
|
+
`:117`), collapses to 1 column at `≤640px` (`:1475`).
|
|
450
|
+
- **Hover lift** — cards raise via `transform: translateY(-1px)` + `--shadow-md` +
|
|
451
|
+
accent border (`.agent-card:hover`, `:122`).
|
|
452
|
+
|
|
453
|
+
### 5.4 Tables
|
|
454
|
+
|
|
455
|
+
Two table systems:
|
|
456
|
+
- **Generic** `.table` (`:777-780`) — full-width, `border-collapse`, `--text-md`
|
|
457
|
+
body, uppercase muted `th`, `--surface2` row hover.
|
|
458
|
+
- **PR/work-item** `.pr-table` (`:354-384`) — adds sticky headers
|
|
459
|
+
(`thead th { position: sticky; top: 0; background: var(--surface) }`, `:380`),
|
|
460
|
+
horizontal scroll wrapper (`.pr-table-wrap { overflow-x: auto }`, `:353`), a
|
|
461
|
+
fixed-layout `--prs` variant with `min-width: 1600px` and per-column ellipsis
|
|
462
|
+
(`:361-372`), and a mobile card-reflow for `.quarantine-ref-table` at `≤640px`
|
|
463
|
+
(`:1484-1508`).
|
|
464
|
+
|
|
465
|
+
Tables are dense: `td` padding `8px 10px`, `1px --border` row dividers, no zebra
|
|
466
|
+
striping — hover is the row-affordance.
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## 6. Components
|
|
471
|
+
|
|
472
|
+
### 6.1 Buttons
|
|
473
|
+
|
|
474
|
+
Minions has a **deliberately consolidated** button taxonomy. Each family is a
|
|
475
|
+
single source of truth with size variants; **do not** re-create the inline style
|
|
476
|
+
blob for a new button — extend the primitive. All families share: `--surface2`
|
|
477
|
+
or transparent bg, `--radius-sm`, `--transition` on hover, a `~10%` hue-tint
|
|
478
|
+
hover, a `2px` accent `:focus-visible` outline, and a `0.4` opacity disabled
|
|
479
|
+
state.
|
|
480
|
+
|
|
481
|
+
| Class | Identity | Use | Source |
|
|
482
|
+
| -------------------- | --------------------------------- | ------------------------------------------ | ------ |
|
|
483
|
+
| `.btn` | neutral bordered, `--surface` | generic default button | `:531` |
|
|
484
|
+
| `.btn-primary` | solid `--blue`, `#fff` text | inline primary | `:539` |
|
|
485
|
+
| `.btn-success/-danger/-warning` | colored border/text | semantic outline variants | `:542` |
|
|
486
|
+
| `.btn-add` (+`-lg`) | green border/text, no glyph rules | "+ Add / + New" creators | `:558` |
|
|
487
|
+
| `.btn-action` (+`-md/-lg`) | green border/text | verb actions (Approve/Verify/Save/Run) | `:592` |
|
|
488
|
+
| `.btn-destructive` (+`-md/-lg`) | red border/text | Delete / Abort / Remove / Unpin | `:625` |
|
|
489
|
+
| `.pr-info-pill` | blue border/text (↗) | open-PR-detail affordance in PR rows | `:652` |
|
|
490
|
+
| `.btn-primary-solid` | solid blue, `font-weight:600` | gating CTA (Start QA, Save runbook) | `:673` |
|
|
491
|
+
| `.btn-primary-lg` | solid blue, normal weight | modal Save / Create / Re-execute | `:697` |
|
|
492
|
+
| `.btn-ghost` | transparent, muted, bordered | secondary next to a primary CTA | `:717` |
|
|
493
|
+
| `.empty-state-add` | dashed border, green, CTA chip | empty-state "+ Add Project" | `:736` |
|
|
494
|
+
|
|
495
|
+
**Rule:** color encodes intent — green = create/affirm, red = destroy, blue =
|
|
496
|
+
primary/navigate, muted ghost = secondary. Size variant suffixes (`-md`, `-lg`)
|
|
497
|
+
change only padding/size, never color. Positional spacing (`margin-left`) lives
|
|
498
|
+
at the callsite, not on the button (`dashboard/styles.css:555`).
|
|
499
|
+
|
|
500
|
+
### 6.2 Badges & status pills
|
|
501
|
+
|
|
502
|
+
- **`.badge`** (`:764-774`) — generic uppercase pill, `--radius-xl`, `--text-sm`,
|
|
503
|
+
600 weight, 6 color variants (`-blue -green -red -yellow -purple -muted`) using
|
|
504
|
+
the `0.15` tint pattern.
|
|
505
|
+
- **`.pr-badge`** (`:428-443`) — the PR/work-item status pill with a **status
|
|
506
|
+
vocabulary of classes** rather than color names:
|
|
507
|
+
`draft active approved rejected needs-review review-escalated merged building
|
|
508
|
+
build-pass build-fail no-build build-stale build-escalated needs-attention`.
|
|
509
|
+
See [§7](#7-status--content-language) for the state→class→color mapping.
|
|
510
|
+
- **`.status-badge`** (`:128-131`) — agent status (`idle` muted / `working`
|
|
511
|
+
amber-pulsing / `done` green).
|
|
512
|
+
- **`.dispatch-type.*`** (`:1081-1098`) — per-work-type chips (implement, review,
|
|
513
|
+
fix, test, plan, docs, setup, …), each a fixed tint.
|
|
514
|
+
|
|
515
|
+
Emphasis: escalated / needs-attention states step the tint to `0.22–0.25` and
|
|
516
|
+
switch to a **dashed** or **2px** border + `font-weight:700` (`:434, :441`).
|
|
517
|
+
Motion (`animation: pulse`) marks live/critical states (`building`,
|
|
518
|
+
`dispatch-stuck`).
|
|
519
|
+
|
|
520
|
+
### 6.3 Forms & inputs
|
|
521
|
+
|
|
522
|
+
- Inputs/textareas: `--bg` background, `1px --border`, `--radius-sm`, `--text`
|
|
523
|
+
color, `font-family: inherit`; focus swaps border to `--blue` and drops the
|
|
524
|
+
native outline (`.modal-qa-input`, `:152-153`).
|
|
525
|
+
- The **Command Center composer** (`.cmd-input-wrap`, `:806-838`) is the richest
|
|
526
|
+
input: a `2px` border that lights `--blue` with a `3px` glow on
|
|
527
|
+
`:focus-within`, a transparent syntax-highlight layer under the textarea
|
|
528
|
+
(`.cmd-highlight-layer` colorizes `@mentions`, `/commands`, `!priority`,
|
|
529
|
+
`#project`, `--flags`), and intent chips (`.cmd-chip`) beneath.
|
|
530
|
+
- Toggles: `.settings-switch` and `.pr-automation-switch` are custom checkbox
|
|
531
|
+
switches with `:focus-visible` rings on the track (`:1455, :493`).
|
|
532
|
+
|
|
533
|
+
### 6.4 Dialogs & modals
|
|
534
|
+
|
|
535
|
+
- **Backdrop** `.modal-bg` — `position:fixed; inset:0; background:
|
|
536
|
+
rgba(0,0,0,0.75); z-index:400`; `.open` sets `display:flex` centered
|
|
537
|
+
(`:1185-1186`).
|
|
538
|
+
- **Card** `.modal` — `--surface`, `1px --border`, `--radius-xl`, `width:95%;
|
|
539
|
+
max-width:1100px; max-height:80vh`, flex column (`:1187`). `.modal-wide` widens
|
|
540
|
+
to `1500px`.
|
|
541
|
+
- **Header** — flex row, bottom border, `h3` is `--text-xl` `--blue`
|
|
542
|
+
(`:1189-1190`); a `.modal-close` muted × and optional `.modal-copy` chrome.
|
|
543
|
+
- **Modal stack** — supports depth (back button `.modal-back-btn` +
|
|
544
|
+
`.modal-stack-chip` showing `n/5`, `:1200-1211`).
|
|
545
|
+
- **Confirm dialog** — promise-based, reuses `.modal-bg`/`.modal` sized down to
|
|
546
|
+
`.confirm-card` (max 480px), right-aligned action row (`:1234-1244`). Replaces
|
|
547
|
+
`window.confirm`; behavior in `dashboard/js/confirm-dialog.js`.
|
|
548
|
+
|
|
549
|
+
### 6.5 Command Center (drawer)
|
|
550
|
+
|
|
551
|
+
A right-hand `420px` fixed drawer (`#cc-drawer`, `dashboard/layout.html:60`) with
|
|
552
|
+
its own overlay scrim, the rich composer (§6.3), streaming tool chips
|
|
553
|
+
(`renderToolChip`, `dashboard/js/render-utils.js:13`), and action/message chips.
|
|
554
|
+
It is a **surface, not a page** — the primary conversational control plane.
|
|
555
|
+
|
|
556
|
+
### 6.6 Empty / loading / error states
|
|
557
|
+
|
|
558
|
+
- **Empty** — `.empty { color: var(--muted); font-style: italic; font-size:
|
|
559
|
+
var(--text-md); padding: 8px 0 }` (`:802`); `.tile-empty` in slim
|
|
560
|
+
(`slim/styles.css:889`). Empty-state CTAs use the dashed `.empty-state-add`
|
|
561
|
+
chip.
|
|
562
|
+
- **Loading** — animated dot triads (`.modal-qa-loading .dot-pulse span`,
|
|
563
|
+
`:141-144`; `.notif-badge.processing`, `:1247`) using `dotPulse`. Live
|
|
564
|
+
activity uses the `pulse` dot.
|
|
565
|
+
- **Error** — red accent: `.modal-copy.is-danger` (`:1196`), agent-detail error
|
|
566
|
+
state with a `.btn-primary-lg` Retry (`:694`), `.dispatch-stuck` dashed-red
|
|
567
|
+
pulsing warning (`:1102`). Error text uses `--red`; never a raw red.
|
|
568
|
+
|
|
569
|
+
### 6.7 Notification badges
|
|
570
|
+
|
|
571
|
+
`.notif-badge` (`:1245-1250`) — absolutely positioned dot on sidebar links / CC
|
|
572
|
+
tabs. `.done` = `8px` red `notifPulse` dot (unread completion); `.processing` =
|
|
573
|
+
three blue `dotPulse` dots (in-flight).
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
## 7. Status & content language
|
|
578
|
+
|
|
579
|
+
Status is the heart of the design. The mapping from **domain state → CSS class →
|
|
580
|
+
color → meaning** is defined in the renderers and MUST be reused, not re-derived.
|
|
581
|
+
|
|
582
|
+
### 7.1 Work-item status (`dashboard/js/render-work-items.js:200-201, 810`)
|
|
583
|
+
|
|
584
|
+
| Status | `.pr-badge` class | Color | Meaning |
|
|
585
|
+
| --------------------- | ----------------- | ---------------- | -------------------- |
|
|
586
|
+
| `pending` / `queued` | `active` | blue | waiting to dispatch |
|
|
587
|
+
| `dispatched` | `building` | yellow (pulsing) | agent running |
|
|
588
|
+
| `done` / `decomposed` | `approved` | green | complete |
|
|
589
|
+
| `failed` | `rejected` | red | failed |
|
|
590
|
+
| `cancelled` | `draft` | muted | cancelled/removed |
|
|
591
|
+
|
|
592
|
+
### 7.2 PR review status (`dashboard/js/render-prs.js:130, 480`)
|
|
593
|
+
|
|
594
|
+
| `reviewStatus` | class | Color |
|
|
595
|
+
| --------------------- | ---------- | ---------------- |
|
|
596
|
+
| `approved` | `approved` | green |
|
|
597
|
+
| `changes-requested` / `rejected` | `rejected` | red |
|
|
598
|
+
| `waiting` | `building` | yellow (pulsing) |
|
|
599
|
+
| everything else / `pending` | `draft` | muted |
|
|
600
|
+
|
|
601
|
+
Minions-sourced review labels append `(minions)` and the "reviewing (minions)"
|
|
602
|
+
wording (`render-prs.js:131`).
|
|
603
|
+
|
|
604
|
+
### 7.3 PR build status (`dashboard/js/render-prs.js:133-134, 484-487`)
|
|
605
|
+
|
|
606
|
+
| `buildStatus` | class | Color |
|
|
607
|
+
| --------------------- | ------------ | --------------------- |
|
|
608
|
+
| `passing` | `build-pass` | green |
|
|
609
|
+
| `failing` | `build-fail` | red |
|
|
610
|
+
| `running` | `building` | yellow (pulsing) |
|
|
611
|
+
| `none` | `no-build` | muted |
|
|
612
|
+
| `_buildStatusStale` | `build-stale`| orange, **dashed** border |
|
|
613
|
+
|
|
614
|
+
Stale/escalated states are visually distinct (dashed / 2px border) so an operator
|
|
615
|
+
never confuses a **confirmed** failure with a **cached/stale** one — a
|
|
616
|
+
load-bearing product rule (build fixes are not dispatched from stale failures).
|
|
617
|
+
|
|
618
|
+
### 7.4 Agent status (`.status-badge`, `dashboard/styles.css:129-131`)
|
|
619
|
+
|
|
620
|
+
`idle` (muted) · `working` (amber, pulsing) · `done` (green). Agent cards also
|
|
621
|
+
recolor their border: `.agent-card.working` yellow, `.agent-card.done` green
|
|
622
|
+
(`:123-124`).
|
|
623
|
+
|
|
624
|
+
### 7.5 Dispatch type taxonomy (`.dispatch-type.*`, `:1082-1098`)
|
|
625
|
+
|
|
626
|
+
Each work type has a fixed chip color: `implement`/`meeting` blue,
|
|
627
|
+
`review`/`decompose` purple, `fix` yellow, `analyze`/`ask`/`verify` green, `test`
|
|
628
|
+
orange, `explore`/`manual` muted, `plan` violet `#a855f7`, `docs` sky `#38bdf8`,
|
|
629
|
+
`setup` teal `#14b8a6`, `evaluate` red.
|
|
630
|
+
|
|
631
|
+
### 7.6 Content & label conventions
|
|
632
|
+
|
|
633
|
+
- **IDs & branches** — monospace (`.mono`), often muted; truncate with a `title`.
|
|
634
|
+
- **Timestamps** — `--muted`, `tabular-nums`, relative ("3 min ago").
|
|
635
|
+
- **Section headers** — UPPERCASE, muted, letter-spaced.
|
|
636
|
+
- **Counts** — pill chips (`.sidebar-count`, `.count`) with tabular numerals.
|
|
637
|
+
- **Status verbs** — imperative and terminal: `approved`, `failing`, `merged`,
|
|
638
|
+
`needs-attention`, `dispatched`. Match the engine constants (`WI_STATUS`,
|
|
639
|
+
`PR_STATUS`, `DISPATCH_RESULT` in `engine/core/shared.js`) — do not invent UI-only
|
|
640
|
+
status words. Never surface a raw enum the user can't read; humanize but keep
|
|
641
|
+
the canonical term recognizable.
|
|
642
|
+
|
|
643
|
+
---
|
|
644
|
+
|
|
645
|
+
## 8. Interaction states & accessibility
|
|
646
|
+
|
|
647
|
+
### 8.1 The four interactive states
|
|
648
|
+
|
|
649
|
+
Every interactive element defines all four:
|
|
650
|
+
|
|
651
|
+
1. **Default** — `--border` hairline, `--muted` or `--text` label.
|
|
652
|
+
2. **Hover** — border → accent or `--text`; background → `~10%` hue tint or
|
|
653
|
+
`--surface2`; cards add `translateY(-1px)` + shadow.
|
|
654
|
+
3. **Focus** — `:focus-visible { outline: 2px solid <accent>; outline-offset:
|
|
655
|
+
1–2px }` on **every** button family (`:569, :603, :636, :664, :685, :708,
|
|
656
|
+
:728, :749`), plus the `3px` blue glow on rich inputs. **Never** remove focus
|
|
657
|
+
without a visible replacement.
|
|
658
|
+
4. **Disabled** — `opacity: 0.4; cursor: not-allowed; pointer-events: none`
|
|
659
|
+
(uniform across every button family).
|
|
660
|
+
|
|
661
|
+
### 8.2 Accessibility requirements
|
|
662
|
+
|
|
663
|
+
- **Hit targets ≥ 24×24px** — enforced via `min-height/min-width` on small
|
|
664
|
+
affordances (command-chip close, `dashboard/styles.css:854`; `.empty-state-add`
|
|
665
|
+
`min 24×24`, `:738`).
|
|
666
|
+
- **12px readability floor** — enforced by the type system (§3.4); do not put
|
|
667
|
+
reading text below it.
|
|
668
|
+
- **Truncated text carries `title`** — full value always reachable (§3.6).
|
|
669
|
+
- **Reduced motion** — honor `prefers-reduced-motion` for decorative animation
|
|
670
|
+
(§4.4).
|
|
671
|
+
- **Focus-visible on all controls**, including custom switches (track gets the
|
|
672
|
+
ring, `:493, :1455`).
|
|
673
|
+
- **Contrast** — accent-on-tint at badge weight; muted text kept ≥ 12px (§2.6).
|
|
674
|
+
- **Semantic markers** — `cursor: help` on informational badges that expose a
|
|
675
|
+
`title` explanation (`.needs-attention`, `:443`; `.dispatch-stuck`, `:1102`).
|
|
676
|
+
- **XSS discipline (implementation a11y/security)** — dashboard JS prefers
|
|
677
|
+
`insertAdjacentHTML('beforeend', …)` / DOM construction over `innerHTML +=`
|
|
678
|
+
(preserves event handlers); an ESLint gate
|
|
679
|
+
(`eslint-plugin-no-unsanitized`, `npm run lint`) blocks unsanitized sinks. All
|
|
680
|
+
user/agent text is escaped via `escapeHtml` before interpolation
|
|
681
|
+
(`dashboard/js/render-work-items.js:202`).
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## 9. Classic vs Slim: shared foundations vs intentional differences
|
|
686
|
+
|
|
687
|
+
**Do not assume parity.** The two front-ends share a language but ship
|
|
688
|
+
independent CSS. This is the authoritative reconciliation.
|
|
689
|
+
|
|
690
|
+
### 9.1 Genuinely shared (kept in lockstep by a tripwire)
|
|
691
|
+
|
|
692
|
+
- The **7 core palette tokens** `--bg --surface --border --muted --blue --green
|
|
693
|
+
--red` (identical hex).
|
|
694
|
+
- The **typography size primitives** (base px identical; tripwire
|
|
695
|
+
`test/unit/dashboard-font-size-tokens.test.js`) and **role aliases**.
|
|
696
|
+
- The **`.text-*` utility classes** (duplicated verbatim,
|
|
697
|
+
`dashboard/slim/styles.css:61-68`).
|
|
698
|
+
- The **dark, GitHub-Primer aesthetic**, semantic-color philosophy, uppercase
|
|
699
|
+
micro-labels, and pulse-for-live motion vocabulary.
|
|
700
|
+
- **`.status-line`** and **`.status-badge`** definitions appear in both — but
|
|
701
|
+
slim's copies (`slim/styles.css:1900-1906`) live inside the mirrored
|
|
702
|
+
detail-panel block and depend on the scoped token island (`.status-badge.working`
|
|
703
|
+
resolves `var(--yellow)` only under `#detail-panel` / `#detail-overlay`). They
|
|
704
|
+
are duplicated *presentation*, not a globally shared slim primitive (§9.2 †).
|
|
705
|
+
|
|
706
|
+
### 9.2 Intentional differences (do NOT "fix" toward parity)
|
|
707
|
+
|
|
708
|
+
| Aspect | Classic | Slim (global `:root`) |
|
|
709
|
+
| --------------------- | ------------------------------------ | -------------------------------------- |
|
|
710
|
+
| `--minions-text-scale`| `1.05` (global +5% bump) | `1` (pinned — excluded from bump) |
|
|
711
|
+
| Spacing scale | 9-step, 2px base (`--space-1..9`) | 5-step, 4px base (`--space-1..5`) † |
|
|
712
|
+
| `--surface2` | `#21262d` | `#1c2128` |
|
|
713
|
+
| `--text` | `#e6edf3` | `#c9d1d9` |
|
|
714
|
+
| In-progress token | `--yellow` | `--amber` (same hex `#d29922`) † |
|
|
715
|
+
| `--orange` | `#e3b341` (golden) | `#ea580c` (hot) † |
|
|
716
|
+
| `--purple` | declared | not in `:root` † |
|
|
717
|
+
| Radius | 5 tokens (`--radius-sm..full`) | single `--radius: 6px` † |
|
|
718
|
+
| Shell | paged SPA (sidebar + `.page`) | single-screen cockpit (`.panel` grid) |
|
|
719
|
+
| Line-height baseline | none on body | `line-height: 1.5` on body |
|
|
720
|
+
| Scrollbars | `6px` thin (`:799`) | `10px` themed + thin nested (`:98-120`)|
|
|
721
|
+
|
|
722
|
+
> † **Global `:root` only — mind the scoped token island.** The Slim column
|
|
723
|
+
> describes `dashboard/slim/styles.css:13-56`. Slim *also* re-declares the
|
|
724
|
+
> Classic `--yellow` / `--purple` / `--orange` (Classic `#e3b341`) /
|
|
725
|
+
> `--radius-sm..full` / `--transition-*` / `--space-1..9` (Classic 2px) set
|
|
726
|
+
> scoped to `#detail-panel, #detail-overlay`
|
|
727
|
+
> (`dashboard/slim/styles.css:1859-1865`), so the detail-panel rules mirrored
|
|
728
|
+
> verbatim from Classic (`:1867-1974`) resolve correctly without disturbing
|
|
729
|
+
> slim's global palette. **Inside that subtree the Classic values apply.** Do not
|
|
730
|
+
> flag a mirrored panel rule that uses `var(--purple)`, `var(--radius-xl)`, or
|
|
731
|
+
> Classic `--space-*` arithmetic as a token violation — resolve the selector's
|
|
732
|
+
> scope first (§13 item 10).
|
|
733
|
+
|
|
734
|
+
### 9.3 Reuse-before-fork rule
|
|
735
|
+
|
|
736
|
+
When adding behavior to Slim, first check whether Classic already implements it
|
|
737
|
+
and extract a **shared helper** rather than forking a divergent copy (CLAUDE.md
|
|
738
|
+
"Slim UX vs Classic UX — reuse, don't fork"). A divergent parallel copy of an
|
|
739
|
+
existing renderer is grounds for review rejection. The token *duplication* is
|
|
740
|
+
sanctioned (independent stylesheets); *logic* duplication is not.
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
## 10. Reusable implementation patterns
|
|
745
|
+
|
|
746
|
+
Concrete, traceable references for converting or auditing UI.
|
|
747
|
+
|
|
748
|
+
### 10.1 Token consumption
|
|
749
|
+
|
|
750
|
+
```css
|
|
751
|
+
/* GOOD — every value is a token */
|
|
752
|
+
.my-chip {
|
|
753
|
+
background: var(--surface2);
|
|
754
|
+
border: 1px solid var(--border);
|
|
755
|
+
border-radius: var(--radius-sm);
|
|
756
|
+
padding: var(--space-2) var(--space-5);
|
|
757
|
+
font-size: var(--text-micro);
|
|
758
|
+
color: var(--muted);
|
|
759
|
+
}
|
|
760
|
+
/* BAD — raw hex + raw px (fails audit + font-size tripwire) */
|
|
761
|
+
.my-chip { background:#1c2128; padding:4px 10px; font-size:12px; color:#8b949e; }
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
### 10.2 Status badge
|
|
765
|
+
|
|
766
|
+
```js
|
|
767
|
+
// Reuse the class vocabulary, never re-pick colors:
|
|
768
|
+
const cls = s === 'failed' ? 'rejected'
|
|
769
|
+
: s === 'dispatched' ? 'building'
|
|
770
|
+
: s === 'done' ? 'approved'
|
|
771
|
+
: s === 'cancelled' ? 'draft' : 'active';
|
|
772
|
+
return `<span class="pr-badge ${cls}">${escapeHtml(s)}</span>`;
|
|
773
|
+
// (dashboard/js/render-work-items.js:200-202, 810)
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### 10.3 Button — extend, don't inline
|
|
777
|
+
|
|
778
|
+
```html
|
|
779
|
+
<!-- GOOD -->
|
|
780
|
+
<button class="btn-action btn-action-lg" onclick="save()">Save</button>
|
|
781
|
+
<!-- BAD — re-creating the green blob -->
|
|
782
|
+
<button style="color:var(--green);border:1px solid var(--green);padding:2px 10px">Save</button>
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
### 10.4 DOM-safe rendering
|
|
786
|
+
|
|
787
|
+
```js
|
|
788
|
+
el.insertAdjacentHTML('beforeend', html); // preserves handlers; passes lint
|
|
789
|
+
// el.innerHTML += html; // BANNED — drops handlers, XSS risk
|
|
790
|
+
text = escapeHtml(userValue); // ALWAYS escape untrusted text
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
### 10.5 Truncate + title
|
|
794
|
+
|
|
795
|
+
```js
|
|
796
|
+
`<span class="truncate" title="${escapeHtml(full)}">${escapeHtml(full)}</span>`
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
### 10.6 Reference index (files & symbols)
|
|
800
|
+
|
|
801
|
+
| Concern | File | Anchor |
|
|
802
|
+
| ----------------------- | ----------------------------------------------- | ----------------------------------- |
|
|
803
|
+
| Tokens (Classic) | `dashboard/styles.css` | `:root` `:1-61` |
|
|
804
|
+
| Tokens (Slim) | `dashboard/slim/styles.css` | `:root` `:13-56` |
|
|
805
|
+
| Tokens (Slim, scoped) | `dashboard/slim/styles.css` | `#detail-panel, #detail-overlay` `:1859-1865` |
|
|
806
|
+
| Typography contract | `dashboard/docs/typography.md` | whole file |
|
|
807
|
+
| Type tripwire | `test/unit/dashboard-font-size-tokens.test.js` | raw-px gate |
|
|
808
|
+
| Buttons | `dashboard/styles.css` | `:519-761` |
|
|
809
|
+
| Badges / pr-badge | `dashboard/styles.css` | `:428-443, 763-774` |
|
|
810
|
+
| Tables | `dashboard/styles.css` | `:354-384, 776-780` |
|
|
811
|
+
| Modals / confirm | `dashboard/styles.css` | `:1185-1244` |
|
|
812
|
+
| Command Center composer | `dashboard/styles.css` | `:804-853` |
|
|
813
|
+
| Status renderers | `dashboard/js/render-prs.js`, `render-work-items.js` | status→class maps |
|
|
814
|
+
| Shared render helpers | `dashboard/js/render-utils.js` | `renderToolChip`, `escapeHtml` uses |
|
|
815
|
+
| Shell / embed mode | `dashboard/layout.html` | `:38-60, :20-32` |
|
|
816
|
+
| Slim shell | `dashboard/slim/layout.html`, `body.html` | `.panel` grid |
|
|
817
|
+
| Lint gate | `npm run lint` | `eslint-plugin-no-unsanitized` |
|
|
818
|
+
|
|
819
|
+
---
|
|
820
|
+
|
|
821
|
+
## 11. Migration playbook
|
|
822
|
+
|
|
823
|
+
Adopting the Minions language in another application, in dependency order.
|
|
824
|
+
|
|
825
|
+
**Phase 0 — Establish tokens.**
|
|
826
|
+
1. Copy the `:root` token block (`dashboard/styles.css:1-61`) into your global
|
|
827
|
+
stylesheet: the 7 core palette tokens, accent tokens, the full type primitive
|
|
828
|
+
+ role-alias system, the 9-step spacing scale, radii, shadows, transitions.
|
|
829
|
+
2. Set the body baseline: `background: var(--bg); color: var(--text);
|
|
830
|
+
font-family: 'Segoe UI', system-ui, sans-serif; font-size: var(--text-xl)`.
|
|
831
|
+
3. Add the `.text-*` utility classes and (optionally) the `[data-font-size]`
|
|
832
|
+
zoom mechanism from `dashboard/layout.html:13-19`.
|
|
833
|
+
|
|
834
|
+
**Phase 1 — Token mapping.** Map your existing values to tokens:
|
|
835
|
+
|
|
836
|
+
| Your value | Minions token |
|
|
837
|
+
| ------------------------- | ------------------- |
|
|
838
|
+
| page background | `--bg` |
|
|
839
|
+
| card / panel background | `--surface2` |
|
|
840
|
+
| raised bar / header | `--surface` |
|
|
841
|
+
| primary text | `--text` |
|
|
842
|
+
| secondary/meta text | `--muted` |
|
|
843
|
+
| hairline border | `--border` |
|
|
844
|
+
| primary action / link | `--blue` |
|
|
845
|
+
| success / create | `--green` |
|
|
846
|
+
| error / destroy | `--red` |
|
|
847
|
+
| in-progress / warning | `--yellow` |
|
|
848
|
+
| gutter (default) | `--space-4` (8px) |
|
|
849
|
+
| card padding | `--space-6 --space-7` |
|
|
850
|
+
| body font | `--text-body` |
|
|
851
|
+
| labels | `--text-micro` |
|
|
852
|
+
|
|
853
|
+
Replace every raw hex and raw `font-size` as you go; run a grep for `#[0-9a-f]{3,6}`
|
|
854
|
+
and `font-size:\s*\d` to find stragglers.
|
|
855
|
+
|
|
856
|
+
**Phase 2 — Component conversion.** Port the primitives in this order (each
|
|
857
|
+
depends on tokens only): `.card` → `.btn*` families → `.badge`/`.pr-badge` →
|
|
858
|
+
`.table`/`.pr-table` → `.modal`/confirm → inputs/switches → empty/loading/error
|
|
859
|
+
states → Command-Center-style composer (if you need a conversational surface).
|
|
860
|
+
Reuse the exact class vocabulary and status→class maps from §7 and §10.
|
|
861
|
+
|
|
862
|
+
**Phase 3 — Interaction & states.** Add the four interactive states (§8.1) to
|
|
863
|
+
every control: hover tint, `:focus-visible` accent outline, `0.4` disabled,
|
|
864
|
+
`--transition-fast` timing. Wire the `pulse`/`dotPulse` live-state animations and
|
|
865
|
+
respect `prefers-reduced-motion`.
|
|
866
|
+
|
|
867
|
+
**Phase 4 — Responsive validation.** Add the `≤1100px` and `≤640px` breakpoints
|
|
868
|
+
(`dashboard/styles.css:1460-1514`): grids collapse to 1 column, stats wrap,
|
|
869
|
+
tables shrink type and gain horizontal scroll, modals go to `95vw`. Verify at
|
|
870
|
+
`320 / 640 / 1100 / 1440px`.
|
|
871
|
+
|
|
872
|
+
**Phase 5 — Accessibility.** Confirm §8.2: ≥24px hit targets, 12px reading floor,
|
|
873
|
+
`title` on all truncation, focus-visible everywhere, contrast on the dark canvas,
|
|
874
|
+
escaped user text, sanitized HTML sinks.
|
|
875
|
+
|
|
876
|
+
**Phase 6 — Visual-regression.** Capture Playwright screenshots of each converted
|
|
877
|
+
surface at a normal viewport (BEFORE/AFTER for conversions). Minions gates this
|
|
878
|
+
in CI (`docs/visual-evidence-ci.md`); mirror that discipline. Run the type
|
|
879
|
+
tripwire equivalent to prevent raw-px regressions.
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
|
|
883
|
+
## 12. Audit rubric & checklist
|
|
884
|
+
|
|
885
|
+
Grade a Minions UI change objectively. **Severity:** 🔴 blocker (must fix before
|
|
886
|
+
merge) · 🟡 major (fix or file follow-up) · 🔵 minor (nit).
|
|
887
|
+
|
|
888
|
+
### 12.1 Tokens & color
|
|
889
|
+
|
|
890
|
+
- 🔴 Any raw hex / named CSS color outside a `:root` block (except audited
|
|
891
|
+
`#fff`-on-accent and `rgba(0,0,0,…)` scrims/shadows, and the sanctioned slim
|
|
892
|
+
scoped token island at `dashboard/slim/styles.css:1859-1865` — §13 item 10).
|
|
893
|
+
- 🔴 A color chosen for looks rather than its semantic role (§2.2, §7).
|
|
894
|
+
- 🟡 A new tint fill with a novel opacity step instead of the established
|
|
895
|
+
`0.10 / 0.15 / 0.22–0.25` ladder.
|
|
896
|
+
- 🟡 A hue that recurs ≥3× still hard-coded instead of promoted to a token.
|
|
897
|
+
|
|
898
|
+
### 12.2 Typography
|
|
899
|
+
|
|
900
|
+
- 🔴 Raw `font-size: Npx` / `Nem` in CSS, inline style, or JS template (fails
|
|
901
|
+
`test/unit/dashboard-font-size-tokens.test.js`).
|
|
902
|
+
- 🟡 Reading text below the 12px floor (`--text-xs` used for anything but the two
|
|
903
|
+
allowlisted dense-chrome callsites).
|
|
904
|
+
- 🔵 New code using a size primitive where a role alias exists.
|
|
905
|
+
|
|
906
|
+
### 12.3 Spacing / layout
|
|
907
|
+
|
|
908
|
+
- 🟡 Raw `Npx` padding/margin/gap where a `--space-*` token fits.
|
|
909
|
+
- 🔴 Copying a `--space-*` rule between Classic and Slim without re-mapping (the
|
|
910
|
+
scales differ — §4.1). **Not** a violation inside `#detail-panel,
|
|
911
|
+
#detail-overlay` in slim, where the Classic 9-step scale is re-declared on
|
|
912
|
+
purpose (§9.2 †, §13 item 10) — verify the selector's scope before flagging.
|
|
913
|
+
- 🟡 A new card/panel not built on `.card` (or a slim `.panel`).
|
|
914
|
+
|
|
915
|
+
### 12.4 Components & states
|
|
916
|
+
|
|
917
|
+
- 🔴 A new button that inlines the color/border blob instead of extending a
|
|
918
|
+
`.btn-*` family (§6.1).
|
|
919
|
+
- 🔴 Missing `:focus-visible` outline on an interactive element.
|
|
920
|
+
- 🟡 Missing hover and/or disabled state.
|
|
921
|
+
- 🟡 A status rendered with an ad-hoc class instead of the `.pr-badge` / status
|
|
922
|
+
vocabulary and the §7 maps.
|
|
923
|
+
- 🔵 Hit target < 24px without a `min-width/min-height` bump.
|
|
924
|
+
|
|
925
|
+
### 12.5 Accessibility & safety
|
|
926
|
+
|
|
927
|
+
- 🔴 `innerHTML +=` / unsanitized HTML sink (fails `npm run lint`).
|
|
928
|
+
- 🔴 Unescaped user/agent text interpolated into markup.
|
|
929
|
+
- 🟡 Truncated text without a `title`.
|
|
930
|
+
- 🟡 Decorative animation ignoring `prefers-reduced-motion`.
|
|
931
|
+
|
|
932
|
+
### 12.6 Classic/Slim discipline
|
|
933
|
+
|
|
934
|
+
- 🔴 Forking an existing Classic renderer into a divergent Slim copy instead of
|
|
935
|
+
extracting a shared helper (§9.3).
|
|
936
|
+
- 🟡 "Normalizing" an intentional Classic/Slim token difference toward false
|
|
937
|
+
parity (§9.2).
|
|
938
|
+
|
|
939
|
+
### 12.7 Common anti-patterns (fast reference)
|
|
940
|
+
|
|
941
|
+
| Anti-pattern | Correct pattern |
|
|
942
|
+
| ----------------------------------------------- | -------------------------------------- |
|
|
943
|
+
| `style="color:#3fb950"` | `class="text-green"` / token |
|
|
944
|
+
| `font-size:14px` | `var(--text-body)` / `.text-body` |
|
|
945
|
+
| `padding:8px` | `var(--space-4)` |
|
|
946
|
+
| new `<button style="border:1px solid green…">` | `class="btn-action"` |
|
|
947
|
+
| `innerHTML += row` | `insertAdjacentHTML('beforeend', row)` |
|
|
948
|
+
| `window.confirm('Sure?')` | `confirm-dialog.js` promise |
|
|
949
|
+
| raw enum text `"changes_requested"` in UI | humanized label + `.pr-badge rejected` |
|
|
950
|
+
|
|
951
|
+
### 12.8 Worked review examples
|
|
952
|
+
|
|
953
|
+
- **REJECT:** a PR adds `<span style="background:#21262d;padding:4px;font-size:12px">`.
|
|
954
|
+
→ 🔴 raw hex, raw px, raw padding. Fix: `class="card text-caption"` with
|
|
955
|
+
`--space-*` padding.
|
|
956
|
+
- **APPROVE:** a PR adds a new work-type chip as
|
|
957
|
+
`.dispatch-type.migrate { background: rgba(88,166,255,0.15); color: var(--blue); }`
|
|
958
|
+
extending the existing pattern with a token color. 🟢 (Would be 🟡 if it
|
|
959
|
+
introduced a novel raw hue used only once.)
|
|
960
|
+
- **REQUEST CHANGES:** a Slim panel re-implements the PR status→class logic
|
|
961
|
+
inline instead of importing the shared helper. → 🔴 fork; extract shared.
|
|
962
|
+
|
|
963
|
+
---
|
|
964
|
+
|
|
965
|
+
## 13. Known inconsistencies & legacy exceptions
|
|
966
|
+
|
|
967
|
+
Labelled **observed** (what the code does today) vs **canonical** (recommended
|
|
968
|
+
guidance). Do not silently normalize these away.
|
|
969
|
+
|
|
970
|
+
1. **Duplicated token blocks, by design.** Classic and Slim declare separate
|
|
971
|
+
`:root` blocks. *Observed:* intentional (independent stylesheets served from
|
|
972
|
+
disk). *Canonical:* keep them duplicated but rely on
|
|
973
|
+
`test/unit/dashboard-font-size-tokens.test.js` to keep the type values in
|
|
974
|
+
lockstep; there is **no** tripwire for the palette/spacing tokens, so
|
|
975
|
+
palette/spacing drift is possible — verify manually when touching either
|
|
976
|
+
`:root`. Slim additionally carries a **third**, scoped declaration block for
|
|
977
|
+
the reused detail panel — see item 10.
|
|
978
|
+
|
|
979
|
+
2. **`--yellow` (Classic) vs `--amber` (Slim), same hex.** *Observed:* two names,
|
|
980
|
+
one value `#d29922`. *Canonical:* reference the token that exists in the
|
|
981
|
+
stylesheet you're editing; do not cross-import the name.
|
|
982
|
+
|
|
983
|
+
3. **`--orange` differs in hue between the two.** Classic `#e3b341` (golden),
|
|
984
|
+
Slim `#ea580c` (hot). *Observed:* genuine difference. *Canonical:* accept it;
|
|
985
|
+
both signal "attention/fan-out/stale" in their own surface.
|
|
986
|
+
|
|
987
|
+
4. **`--space-*` tokens mean different pixels.** Classic 2px-base 9-step vs Slim
|
|
988
|
+
4px-base 5-step. *Observed & canonical:* never copy spacing rules across
|
|
989
|
+
without re-mapping.
|
|
990
|
+
|
|
991
|
+
5. **Off-palette dispatch-type hues** (`#a855f7`, `#38bdf8`, `#14b8a6`,
|
|
992
|
+
`dashboard/styles.css:1089-1098`). *Observed:* raw hex with no token.
|
|
993
|
+
*Canonical:* acceptable as a fixed type taxonomy; promote to tokens if reused
|
|
994
|
+
outside the dispatch chips.
|
|
995
|
+
|
|
996
|
+
6. **Two table systems** (`.table` and `.pr-table`). *Observed:* `.pr-table`
|
|
997
|
+
duplicates much of `.table` plus sticky-header/scroll behavior. *Canonical:*
|
|
998
|
+
use `.pr-table` for data grids (PRs, work items) and `.table` for simple
|
|
999
|
+
tables; do not add a third system.
|
|
1000
|
+
|
|
1001
|
+
7. **`--text-xs` below the 12px floor.** *Observed:* retained at two dense-chrome
|
|
1002
|
+
callsites only. *Canonical:* never use it for reading text.
|
|
1003
|
+
|
|
1004
|
+
8. **Legacy `.layout` grid** is superseded by `.page-layout`
|
|
1005
|
+
(`dashboard/styles.css:100` comments "Replaced by page-layout"). *Observed:*
|
|
1006
|
+
the old `.layout` rule and its `≤1100px` media rule (`:1461`) still exist.
|
|
1007
|
+
*Canonical:* build on `.page-layout`; treat `.layout` as dead.
|
|
1008
|
+
|
|
1009
|
+
9. **Inline styles in `layout.html`.** *Observed:* the header toolbar buttons
|
|
1010
|
+
carry inline `style="…"` blobs (`dashboard/layout.html:41-47`) with token
|
|
1011
|
+
values. *Canonical:* new controls should use the button primitives (§6.1)
|
|
1012
|
+
rather than inline blobs; these header buttons predate the consolidation.
|
|
1013
|
+
|
|
1014
|
+
10. **Slim's scoped Classic-token island (`#detail-panel, #detail-overlay`).**
|
|
1015
|
+
*Observed:* `dashboard/slim/styles.css:1859-1865` re-declares the full
|
|
1016
|
+
Classic token set — `--yellow: #d29922`, `--purple: #bc8cff`,
|
|
1017
|
+
`--orange: #e3b341` (the *Classic* golden value, shadowing slim's global hot
|
|
1018
|
+
`#ea580c`), `--radius-sm..--radius-full`, `--transition-fast/base/slow`, and
|
|
1019
|
+
`--space-1..--space-9` at the Classic 2px values — scoped to the two panel
|
|
1020
|
+
roots. It exists because the agent detail-panel markup and JS are reused
|
|
1021
|
+
**verbatim** from Classic (`dashboard/layout.html` +
|
|
1022
|
+
`dashboard/js/{render-agents,detail-panel,live-stream,charter-editor,…}.js`),
|
|
1023
|
+
while slim and Classic ship separate top-level stylesheets with no shared CSS
|
|
1024
|
+
partial (W-mrz11djx00050594, rationale comment at
|
|
1025
|
+
`dashboard/slim/styles.css:1845-1858`). Mirroring the classic rule bodies
|
|
1026
|
+
unchanged (`:1867-1974`) is only sound because the tokens they reference
|
|
1027
|
+
resolve to Classic values inside that subtree.
|
|
1028
|
+
|
|
1029
|
+
*Canonical:* keep it. It is the cheapest way to reuse Classic panel CSS
|
|
1030
|
+
without forking it (§9.3) or globally re-pointing slim's palette. Two
|
|
1031
|
+
consequences bind every auditor and contributor:
|
|
1032
|
+
- **Scope before flagging.** `var(--purple)`, `var(--radius-xl)`, and Classic
|
|
1033
|
+
`--space-*` arithmetic are *valid* inside a panel descendant and *invalid*
|
|
1034
|
+
elsewhere in slim. A blanket "slim has no `--purple`" rejection is a
|
|
1035
|
+
false positive (§2.3, §9.2 †, §12.1, §12.3).
|
|
1036
|
+
- **Don't widen it.** Add tokens to the island only when a newly mirrored
|
|
1037
|
+
Classic panel rule needs them; never promote them to slim's global `:root`
|
|
1038
|
+
(that would silently re-skin slim), and never author *new* slim-native UI
|
|
1039
|
+
against island tokens.
|
|
1040
|
+
|
|
1041
|
+
---
|
|
1042
|
+
|
|
1043
|
+
## Validation
|
|
1044
|
+
|
|
1045
|
+
Every claim above was verified against source at the paths/line ranges cited.
|
|
1046
|
+
This is a **documentation-only** artifact — no UI behavior changed. When the
|
|
1047
|
+
implementation evolves, update the cited anchors here and re-run
|
|
1048
|
+
`test/unit/dashboard-font-size-tokens.test.js` (the one automated guard this doc
|
|
1049
|
+
depends on).
|
|
1050
|
+
|
|
1051
|
+
Authored with [Minions](https://icy-water-0224cc51e.2.azurestaticapps.net/minions).
|