smol-symphony 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +41 -22
- package/DESIGN.md +494 -273
- package/README.md +109 -57
- package/SPEC.md +33 -24
- package/WORKFLOW.minimal.yaml +34 -0
- package/{WORKFLOW.template.md → WORKFLOW.template.yaml} +409 -256
- package/WORKFLOW.yaml +487 -0
- package/assets/skills/symphony-issues/SKILL.md +136 -0
- package/assets/symphony-mise.system.toml +68 -0
- package/dist/src/bin/symphony.js +30 -0
- package/dist/src/bin/symphony.js.map +1 -0
- package/dist/src/core/actions/context.js +109 -0
- package/dist/src/core/actions/context.js.map +1 -0
- package/dist/{actions/parsing.js → src/core/actions/parse.js} +33 -114
- package/dist/src/core/actions/parse.js.map +1 -0
- package/dist/src/core/actions/plan.js +197 -0
- package/dist/src/core/actions/plan.js.map +1 -0
- package/dist/src/core/actions/predicates.js +111 -0
- package/dist/src/core/actions/predicates.js.map +1 -0
- package/dist/src/core/actions/run-fold.js +248 -0
- package/dist/src/core/actions/run-fold.js.map +1 -0
- package/dist/src/core/actions/template.js +118 -0
- package/dist/src/core/actions/template.js.map +1 -0
- package/dist/src/core/cli/args.js +116 -0
- package/dist/src/core/cli/args.js.map +1 -0
- package/dist/src/core/coerce.js +75 -0
- package/dist/src/core/coerce.js.map +1 -0
- package/dist/src/core/credential/account-id.js +20 -0
- package/dist/src/core/credential/account-id.js.map +1 -0
- package/dist/src/core/credential/adapter-config.js +136 -0
- package/dist/src/core/credential/adapter-config.js.map +1 -0
- package/dist/src/core/credential/availability.js +98 -0
- package/dist/src/core/credential/availability.js.map +1 -0
- package/dist/src/core/credential/extract.js +228 -0
- package/dist/src/core/credential/extract.js.map +1 -0
- package/dist/src/core/credential/fake-creds.js +171 -0
- package/dist/src/core/credential/fake-creds.js.map +1 -0
- package/dist/src/core/credential/identity.js +125 -0
- package/dist/src/core/credential/identity.js.map +1 -0
- package/dist/src/core/credential/shape.js +230 -0
- package/dist/src/core/credential/shape.js.map +1 -0
- package/dist/src/core/credential/strings.js +15 -0
- package/dist/src/core/credential/strings.js.map +1 -0
- package/dist/src/core/doctor/checks.js +303 -0
- package/dist/src/core/doctor/checks.js.map +1 -0
- package/dist/src/core/git/result.js +107 -0
- package/dist/src/core/git/result.js.map +1 -0
- package/dist/src/core/http/decisions.js +225 -0
- package/dist/src/core/http/decisions.js.map +1 -0
- package/dist/{http.js → src/core/http/render.js} +472 -738
- package/dist/src/core/http/render.js.map +1 -0
- package/dist/{http-handlers.js → src/core/http/routes.js} +52 -87
- package/dist/src/core/http/routes.js.map +1 -0
- package/dist/src/core/http/views.js +181 -0
- package/dist/src/core/http/views.js.map +1 -0
- package/dist/src/core/image/managed-image.js +95 -0
- package/dist/src/core/image/managed-image.js.map +1 -0
- package/dist/src/core/issue/file.js +149 -0
- package/dist/src/core/issue/file.js.map +1 -0
- package/dist/src/core/issue/parse.js +210 -0
- package/dist/src/core/issue/parse.js.map +1 -0
- package/dist/src/core/mcp/dispatch.js +239 -0
- package/dist/src/core/mcp/dispatch.js.map +1 -0
- package/dist/src/core/mcp/post-move.js +92 -0
- package/dist/src/core/mcp/post-move.js.map +1 -0
- package/dist/src/core/mcp/protocol.js +293 -0
- package/dist/src/core/mcp/protocol.js.map +1 -0
- package/dist/src/core/mcp/url.js +162 -0
- package/dist/src/core/mcp/url.js.map +1 -0
- package/dist/src/core/path.js +63 -0
- package/dist/src/core/path.js.map +1 -0
- package/dist/src/core/reconcile/image-decide.js +48 -0
- package/dist/src/core/reconcile/image-decide.js.map +1 -0
- package/dist/src/core/reconcile/ledger.js +142 -0
- package/dist/src/core/reconcile/ledger.js.map +1 -0
- package/dist/src/core/reconcile/pr-classify.js +62 -0
- package/dist/src/core/reconcile/pr-classify.js.map +1 -0
- package/dist/{reconciler → src/core/reconcile}/pr-decide.js +25 -12
- package/dist/src/core/reconcile/pr-decide.js.map +1 -0
- package/dist/src/core/reconcile/pr-loop.js +161 -0
- package/dist/src/core/reconcile/pr-loop.js.map +1 -0
- package/dist/src/core/reconcile/pr-notes.js +35 -0
- package/dist/src/core/reconcile/pr-notes.js.map +1 -0
- package/dist/src/core/reconcile/vm-decide.js +70 -0
- package/dist/src/core/reconcile/vm-decide.js.map +1 -0
- package/dist/src/core/reconcile/vm-reap.js +207 -0
- package/dist/src/core/reconcile/vm-reap.js.map +1 -0
- package/dist/src/core/reconcile/workspace-decide.js +162 -0
- package/dist/src/core/reconcile/workspace-decide.js.map +1 -0
- package/dist/src/core/runlog/summary.js +231 -0
- package/dist/src/core/runlog/summary.js.map +1 -0
- package/dist/src/core/runner/dispatch-config.js +95 -0
- package/dist/src/core/runner/dispatch-config.js.map +1 -0
- package/dist/src/core/runner/injection.js +61 -0
- package/dist/src/core/runner/injection.js.map +1 -0
- package/dist/src/core/runner/mise.js +210 -0
- package/dist/src/core/runner/mise.js.map +1 -0
- package/dist/src/core/runner/prompt.js +720 -0
- package/dist/src/core/runner/prompt.js.map +1 -0
- package/dist/src/core/runner/turn.js +242 -0
- package/dist/src/core/runner/turn.js.map +1 -0
- package/dist/src/core/runner/vm-plan.js +390 -0
- package/dist/src/core/runner/vm-plan.js.map +1 -0
- package/dist/src/core/schedule/admission.js +123 -0
- package/dist/src/core/schedule/admission.js.map +1 -0
- package/dist/src/core/schedule/circuit-breaker.js +111 -0
- package/dist/src/core/schedule/circuit-breaker.js.map +1 -0
- package/dist/src/core/schedule/eligibility.js +83 -0
- package/dist/src/core/schedule/eligibility.js.map +1 -0
- package/dist/src/core/schedule/reconcile-issue.js +82 -0
- package/dist/src/core/schedule/reconcile-issue.js.map +1 -0
- package/dist/src/core/schedule/retry.js +96 -0
- package/dist/src/core/schedule/retry.js.map +1 -0
- package/dist/src/core/schedule/sleep-cycle.js +133 -0
- package/dist/src/core/schedule/sleep-cycle.js.map +1 -0
- package/dist/src/core/schedule/slots.js +124 -0
- package/dist/src/core/schedule/slots.js.map +1 -0
- package/dist/src/core/schedule/tick.js +553 -0
- package/dist/src/core/schedule/tick.js.map +1 -0
- package/dist/src/core/schedule/token-fold.js +181 -0
- package/dist/src/core/schedule/token-fold.js.map +1 -0
- package/dist/src/core/state-resolve.js +86 -0
- package/dist/src/core/state-resolve.js.map +1 -0
- package/dist/src/core/vm-guards.js +278 -0
- package/dist/src/core/vm-guards.js.map +1 -0
- package/dist/src/core/workflow/derive.js +107 -0
- package/dist/src/core/workflow/derive.js.map +1 -0
- package/dist/src/core/workflow/parse.js +687 -0
- package/dist/src/core/workflow/parse.js.map +1 -0
- package/dist/src/core/workflow/prompt-probe.js +78 -0
- package/dist/src/core/workflow/prompt-probe.js.map +1 -0
- package/dist/src/core/workflow/validate.js +189 -0
- package/dist/src/core/workflow/validate.js.map +1 -0
- package/dist/src/core/workspace-key.js +19 -0
- package/dist/src/core/workspace-key.js.map +1 -0
- package/dist/src/shell/actions-runner.js +356 -0
- package/dist/src/shell/actions-runner.js.map +1 -0
- package/dist/src/shell/adapter/adapter-registry.js +45 -0
- package/dist/src/shell/adapter/adapter-registry.js.map +1 -0
- package/dist/src/shell/adapter/clock-random.js +96 -0
- package/dist/src/shell/adapter/clock-random.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-dispatch-helpers.js +158 -0
- package/dist/src/shell/adapter/gondolin-dispatch-helpers.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-dispatch.js +385 -0
- package/dist/src/shell/adapter/gondolin-dispatch.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-image-converter.js +233 -0
- package/dist/src/shell/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-image-fetch.js +180 -0
- package/dist/src/shell/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/src/shell/adapter/launcher-asset.js +57 -0
- package/dist/src/shell/adapter/launcher-asset.js.map +1 -0
- package/dist/src/shell/adapter/mise-config-asset.js +65 -0
- package/dist/src/shell/adapter/mise-config-asset.js.map +1 -0
- package/dist/src/shell/adapter/workflow-loader.js +304 -0
- package/dist/src/shell/adapter/workflow-loader.js.map +1 -0
- package/dist/src/shell/cli/doctor.js +268 -0
- package/dist/src/shell/cli/doctor.js.map +1 -0
- package/dist/src/shell/effect-interpreter-families.js +314 -0
- package/dist/src/shell/effect-interpreter-families.js.map +1 -0
- package/dist/src/shell/effect-interpreter.js +29 -0
- package/dist/src/shell/effect-interpreter.js.map +1 -0
- package/dist/src/shell/interp/acp-frame.js +137 -0
- package/dist/src/shell/interp/acp-frame.js.map +1 -0
- package/dist/src/shell/interp/acp-ws-conn.js +320 -0
- package/dist/src/shell/interp/acp-ws-conn.js.map +1 -0
- package/dist/src/shell/interp/acp-ws-frames.js +159 -0
- package/dist/src/shell/interp/acp-ws-frames.js.map +1 -0
- package/dist/src/shell/interp/acp-ws.js +197 -0
- package/dist/src/shell/interp/acp-ws.js.map +1 -0
- package/dist/src/shell/interp/acp.js +319 -0
- package/dist/src/shell/interp/acp.js.map +1 -0
- package/dist/src/shell/interp/credential-defaults.js +128 -0
- package/dist/src/shell/interp/credential-defaults.js.map +1 -0
- package/dist/src/shell/interp/credential-hooks.js +149 -0
- package/dist/src/shell/interp/credential-hooks.js.map +1 -0
- package/dist/src/shell/interp/credential-registry.js +226 -0
- package/dist/src/shell/interp/credential-registry.js.map +1 -0
- package/dist/src/shell/interp/credential.js +103 -0
- package/dist/src/shell/interp/credential.js.map +1 -0
- package/dist/src/shell/interp/gh.js +163 -0
- package/dist/src/shell/interp/gh.js.map +1 -0
- package/dist/src/shell/interp/git.js +28 -0
- package/dist/src/shell/interp/git.js.map +1 -0
- package/dist/src/shell/interp/log.js +213 -0
- package/dist/src/shell/interp/log.js.map +1 -0
- package/dist/src/shell/interp/process.js +178 -0
- package/dist/src/shell/interp/process.js.map +1 -0
- package/dist/src/shell/interp/runlog.js +193 -0
- package/dist/src/shell/interp/runlog.js.map +1 -0
- package/dist/src/shell/interp/timer.js +64 -0
- package/dist/src/shell/interp/timer.js.map +1 -0
- package/dist/src/shell/interp/tracker-disk.js +99 -0
- package/dist/src/shell/interp/tracker-disk.js.map +1 -0
- package/dist/src/shell/interp/tracker-parse.js +71 -0
- package/dist/src/shell/interp/tracker-parse.js.map +1 -0
- package/dist/src/shell/interp/tracker-scan.js +238 -0
- package/dist/src/shell/interp/tracker-scan.js.map +1 -0
- package/dist/src/shell/interp/tracker-write.js +91 -0
- package/dist/src/shell/interp/tracker-write.js.map +1 -0
- package/dist/src/shell/interp/tracker.js +41 -0
- package/dist/src/shell/interp/tracker.js.map +1 -0
- package/dist/src/shell/interp/tty.js +48 -0
- package/dist/src/shell/interp/tty.js.map +1 -0
- package/dist/src/shell/interp/vm.js +199 -0
- package/dist/src/shell/interp/vm.js.map +1 -0
- package/dist/src/shell/interp/workspace.js +310 -0
- package/dist/src/shell/interp/workspace.js.map +1 -0
- package/dist/src/shell/main-acp.js +78 -0
- package/dist/src/shell/main-acp.js.map +1 -0
- package/dist/src/shell/main-adapters.js +222 -0
- package/dist/src/shell/main-adapters.js.map +1 -0
- package/dist/src/shell/main-credential.js +122 -0
- package/dist/src/shell/main-credential.js.map +1 -0
- package/dist/src/shell/main-doctor.js +22 -0
- package/dist/src/shell/main-doctor.js.map +1 -0
- package/dist/src/shell/main-entry.js +46 -0
- package/dist/src/shell/main-entry.js.map +1 -0
- package/dist/src/shell/main-http-csrf.js +45 -0
- package/dist/src/shell/main-http-csrf.js.map +1 -0
- package/dist/src/shell/main-http-handler.js +389 -0
- package/dist/src/shell/main-http-handler.js.map +1 -0
- package/dist/src/shell/main-http-mcp.js +122 -0
- package/dist/src/shell/main-http-mcp.js.map +1 -0
- package/dist/src/shell/main-http-views.js +253 -0
- package/dist/src/shell/main-http-views.js.map +1 -0
- package/dist/src/shell/main-http.js +76 -0
- package/dist/src/shell/main-http.js.map +1 -0
- package/dist/src/shell/main-loops.js +130 -0
- package/dist/src/shell/main-loops.js.map +1 -0
- package/dist/src/shell/main-mcp.js +129 -0
- package/dist/src/shell/main-mcp.js.map +1 -0
- package/dist/src/shell/main-orchestrator.js +120 -0
- package/dist/src/shell/main-orchestrator.js.map +1 -0
- package/dist/src/shell/main-preflight.js +43 -0
- package/dist/src/shell/main-preflight.js.map +1 -0
- package/dist/src/shell/main-reconcilers-helpers.js +244 -0
- package/dist/src/shell/main-reconcilers-helpers.js.map +1 -0
- package/dist/src/shell/main-reconcilers-pr.js +148 -0
- package/dist/src/shell/main-reconcilers-pr.js.map +1 -0
- package/dist/src/shell/main-reconcilers.js +225 -0
- package/dist/src/shell/main-reconcilers.js.map +1 -0
- package/dist/src/shell/main-runner.js +355 -0
- package/dist/src/shell/main-runner.js.map +1 -0
- package/dist/src/shell/main-scaffold.js +116 -0
- package/dist/src/shell/main-scaffold.js.map +1 -0
- package/dist/src/shell/main-shutdown.js +115 -0
- package/dist/src/shell/main-shutdown.js.map +1 -0
- package/dist/src/shell/main-startup.js +48 -0
- package/dist/src/shell/main-startup.js.map +1 -0
- package/dist/src/shell/main-substrates.js +43 -0
- package/dist/src/shell/main-substrates.js.map +1 -0
- package/dist/src/shell/main.js +385 -0
- package/dist/src/shell/main.js.map +1 -0
- package/dist/src/shell/orchestrator-feedback.js +69 -0
- package/dist/src/shell/orchestrator-feedback.js.map +1 -0
- package/dist/src/shell/orchestrator-image.js +167 -0
- package/dist/src/shell/orchestrator-image.js.map +1 -0
- package/dist/src/shell/orchestrator-loop.js +468 -0
- package/dist/src/shell/orchestrator-loop.js.map +1 -0
- package/dist/src/shell/orchestrator-reconcile.js +36 -0
- package/dist/src/shell/orchestrator-reconcile.js.map +1 -0
- package/dist/src/shell/reconciler-loop.js +228 -0
- package/dist/src/shell/reconciler-loop.js.map +1 -0
- package/dist/src/shell/runner-loop-turn.js +301 -0
- package/dist/src/shell/runner-loop-turn.js.map +1 -0
- package/dist/src/shell/runner-loop.js +338 -0
- package/dist/src/shell/runner-loop.js.map +1 -0
- package/dist/src/shell/server/http.js +208 -0
- package/dist/src/shell/server/http.js.map +1 -0
- package/dist/src/shell/server/mcp-runtime-effects.js +237 -0
- package/dist/src/shell/server/mcp-runtime-effects.js.map +1 -0
- package/dist/src/shell/server/mcp-runtime.js +99 -0
- package/dist/src/shell/server/mcp-runtime.js.map +1 -0
- package/dist/src/shell/workspace-key.js +14 -0
- package/dist/src/shell/workspace-key.js.map +1 -0
- package/dist/src/types/acp.js +8 -0
- package/dist/src/types/acp.js.map +1 -0
- package/dist/src/types/actions/plan.js +6 -0
- package/dist/src/types/actions/plan.js.map +1 -0
- package/dist/src/types/actions/predicates.js +6 -0
- package/dist/src/types/actions/predicates.js.map +1 -0
- package/dist/src/types/actions/run-fold.js +8 -0
- package/dist/src/types/actions/run-fold.js.map +1 -0
- package/dist/src/types/actions.js +7 -0
- package/dist/src/types/actions.js.map +1 -0
- package/dist/src/types/adapter/clock-random.js +4 -0
- package/dist/src/types/adapter/clock-random.js.map +1 -0
- package/dist/src/types/adapter/gondolin-image-converter.js +5 -0
- package/dist/src/types/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/src/types/adapter/gondolin-image-fetch.js +5 -0
- package/dist/src/types/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/src/types/adapter/workflow-loader.js +4 -0
- package/dist/src/types/adapter/workflow-loader.js.map +1 -0
- package/dist/src/types/cli/args.js +8 -0
- package/dist/src/types/cli/args.js.map +1 -0
- package/dist/src/types/config.js +8 -0
- package/dist/src/types/config.js.map +1 -0
- package/dist/src/types/credential-interp.js +6 -0
- package/dist/src/types/credential-interp.js.map +1 -0
- package/dist/src/types/credentials.js +10 -0
- package/dist/src/types/credentials.js.map +1 -0
- package/dist/src/types/doctor.js +7 -0
- package/dist/src/types/doctor.js.map +1 -0
- package/dist/src/types/domain.js +7 -0
- package/dist/src/types/domain.js.map +1 -0
- package/dist/src/types/effect.js +15 -0
- package/dist/src/types/effect.js.map +1 -0
- package/dist/src/types/errors.js +39 -0
- package/dist/src/types/errors.js.map +1 -0
- package/dist/src/types/http/decisions.js +6 -0
- package/dist/src/types/http/decisions.js.map +1 -0
- package/dist/src/types/http/render.js +10 -0
- package/dist/src/types/http/render.js.map +1 -0
- package/dist/src/types/http/views.js +6 -0
- package/dist/src/types/http/views.js.map +1 -0
- package/dist/src/types/http.js +9 -0
- package/dist/src/types/http.js.map +1 -0
- package/dist/src/types/image/managed-image.js +7 -0
- package/dist/src/types/image/managed-image.js.map +1 -0
- package/dist/src/types/interp/effect-interpreter.js +8 -0
- package/dist/src/types/interp/effect-interpreter.js.map +1 -0
- package/dist/src/types/interp/tracker.js +7 -0
- package/dist/src/types/interp/tracker.js.map +1 -0
- package/dist/src/types/issue/file.js +6 -0
- package/dist/src/types/issue/file.js.map +1 -0
- package/dist/src/types/issue/parse.js +8 -0
- package/dist/src/types/issue/parse.js.map +1 -0
- package/dist/src/types/main-acp.js +13 -0
- package/dist/src/types/main-acp.js.map +1 -0
- package/dist/src/types/main-adapters.js +5 -0
- package/dist/src/types/main-adapters.js.map +1 -0
- package/dist/src/types/main-credential.js +21 -0
- package/dist/src/types/main-credential.js.map +1 -0
- package/dist/src/types/main-doctor.js +6 -0
- package/dist/src/types/main-doctor.js.map +1 -0
- package/dist/src/types/main-http-handler.js +12 -0
- package/dist/src/types/main-http-handler.js.map +1 -0
- package/dist/src/types/main-http.js +5 -0
- package/dist/src/types/main-http.js.map +1 -0
- package/dist/src/types/main-loops.js +5 -0
- package/dist/src/types/main-loops.js.map +1 -0
- package/dist/src/types/main-mcp.js +12 -0
- package/dist/src/types/main-mcp.js.map +1 -0
- package/dist/src/types/main-orchestrator.js +5 -0
- package/dist/src/types/main-orchestrator.js.map +1 -0
- package/dist/src/types/main-reconcilers.js +11 -0
- package/dist/src/types/main-reconcilers.js.map +1 -0
- package/dist/src/types/main-runner.js +13 -0
- package/dist/src/types/main-runner.js.map +1 -0
- package/dist/src/types/main-startup.js +5 -0
- package/dist/src/types/main-startup.js.map +1 -0
- package/dist/src/types/main-substrates.js +5 -0
- package/dist/src/types/main-substrates.js.map +1 -0
- package/dist/src/types/mcp/dispatch.js +4 -0
- package/dist/src/types/mcp/dispatch.js.map +1 -0
- package/dist/src/types/mcp/post-move.js +7 -0
- package/dist/src/types/mcp/post-move.js.map +1 -0
- package/dist/src/types/mcp.js +9 -0
- package/dist/src/types/mcp.js.map +1 -0
- package/dist/src/types/ports.js +12 -0
- package/dist/src/types/ports.js.map +1 -0
- package/dist/src/types/reconcile/image-decide.js +5 -0
- package/dist/src/types/reconcile/image-decide.js.map +1 -0
- package/dist/src/types/reconcile/ledger.js +7 -0
- package/dist/src/types/reconcile/ledger.js.map +1 -0
- package/dist/src/types/reconcile/pr-loop.js +8 -0
- package/dist/src/types/reconcile/pr-loop.js.map +1 -0
- package/dist/src/types/reconcile/vm-reap.js +8 -0
- package/dist/src/types/reconcile/vm-reap.js.map +1 -0
- package/dist/src/types/reconcile/workspace-decide.js +7 -0
- package/dist/src/types/reconcile/workspace-decide.js.map +1 -0
- package/dist/src/types/reconcile.js +9 -0
- package/dist/src/types/reconcile.js.map +1 -0
- package/dist/src/types/runlog.js +7 -0
- package/dist/src/types/runlog.js.map +1 -0
- package/dist/src/types/runner/actions-runner.js +12 -0
- package/dist/src/types/runner/actions-runner.js.map +1 -0
- package/dist/src/types/runner/gondolin-dispatch.js +5 -0
- package/dist/src/types/runner/gondolin-dispatch.js.map +1 -0
- package/dist/src/types/runner/injection.js +6 -0
- package/dist/src/types/runner/injection.js.map +1 -0
- package/dist/src/types/runner/runner-loop.js +5 -0
- package/dist/src/types/runner/runner-loop.js.map +1 -0
- package/dist/src/types/runner/turn.js +4 -0
- package/dist/src/types/runner/turn.js.map +1 -0
- package/dist/src/types/runner/vm-plan.js +4 -0
- package/dist/src/types/runner/vm-plan.js.map +1 -0
- package/dist/src/types/runtime.js +9 -0
- package/dist/src/types/runtime.js.map +1 -0
- package/dist/src/types/schedule/admission.js +7 -0
- package/dist/src/types/schedule/admission.js.map +1 -0
- package/dist/src/types/schedule/circuit-breaker.js +2 -0
- package/dist/src/types/schedule/circuit-breaker.js.map +1 -0
- package/dist/src/types/schedule/eligibility.js +9 -0
- package/dist/src/types/schedule/eligibility.js.map +1 -0
- package/dist/src/types/schedule/orchestrator-loop.js +10 -0
- package/dist/src/types/schedule/orchestrator-loop.js.map +1 -0
- package/dist/src/types/schedule/sleep-cycle.js +4 -0
- package/dist/src/types/schedule/sleep-cycle.js.map +1 -0
- package/dist/src/types/schedule/slots.js +8 -0
- package/dist/src/types/schedule/slots.js.map +1 -0
- package/dist/src/types/schedule/tick.js +9 -0
- package/dist/src/types/schedule/tick.js.map +1 -0
- package/dist/src/types/server/mcp-runtime.js +8 -0
- package/dist/src/types/server/mcp-runtime.js.map +1 -0
- package/dist/src/types/workflow/parse.js +4 -0
- package/dist/src/types/workflow/parse.js.map +1 -0
- package/dist/tests/core/account-id.test.js +35 -0
- package/dist/tests/core/account-id.test.js.map +1 -0
- package/dist/tests/core/actions-parse.test.js +176 -0
- package/dist/tests/core/actions-parse.test.js.map +1 -0
- package/dist/tests/core/adapter-config.test.js +133 -0
- package/dist/tests/core/adapter-config.test.js.map +1 -0
- package/dist/tests/core/admission.test.js +215 -0
- package/dist/tests/core/admission.test.js.map +1 -0
- package/dist/tests/core/args.test.js +132 -0
- package/dist/tests/core/args.test.js.map +1 -0
- package/dist/tests/core/availability.test.js +62 -0
- package/dist/tests/core/availability.test.js.map +1 -0
- package/dist/tests/core/checks.test.js +395 -0
- package/dist/tests/core/checks.test.js.map +1 -0
- package/dist/tests/core/circuit-breaker.test.js +172 -0
- package/dist/tests/core/circuit-breaker.test.js.map +1 -0
- package/dist/tests/core/coerce.test.js +87 -0
- package/dist/tests/core/coerce.test.js.map +1 -0
- package/dist/tests/core/context.test.js +228 -0
- package/dist/tests/core/context.test.js.map +1 -0
- package/dist/tests/core/decisions.test.js +310 -0
- package/dist/tests/core/decisions.test.js.map +1 -0
- package/dist/tests/core/derive.test.js +205 -0
- package/dist/tests/core/derive.test.js.map +1 -0
- package/dist/tests/core/dispatch-config.test.js +164 -0
- package/dist/tests/core/dispatch-config.test.js.map +1 -0
- package/dist/tests/core/dispatch.test.js +302 -0
- package/dist/tests/core/dispatch.test.js.map +1 -0
- package/dist/tests/core/eligibility.test.js +163 -0
- package/dist/tests/core/eligibility.test.js.map +1 -0
- package/dist/tests/core/extract.test.js +139 -0
- package/dist/tests/core/extract.test.js.map +1 -0
- package/dist/tests/core/fake-creds.test.js +134 -0
- package/dist/tests/core/fake-creds.test.js.map +1 -0
- package/dist/tests/core/file.test.js +197 -0
- package/dist/tests/core/file.test.js.map +1 -0
- package/dist/tests/core/git-result.test.js +113 -0
- package/dist/tests/core/git-result.test.js.map +1 -0
- package/dist/tests/core/identity.test.js +180 -0
- package/dist/tests/core/identity.test.js.map +1 -0
- package/dist/tests/core/image-decide.test.js +59 -0
- package/dist/tests/core/image-decide.test.js.map +1 -0
- package/dist/tests/core/injection.test.js +163 -0
- package/dist/tests/core/injection.test.js.map +1 -0
- package/dist/tests/core/ledger.test.js +218 -0
- package/dist/tests/core/ledger.test.js.map +1 -0
- package/dist/tests/core/managed-image.test.js +68 -0
- package/dist/tests/core/managed-image.test.js.map +1 -0
- package/dist/tests/core/mise.test.js +138 -0
- package/dist/tests/core/mise.test.js.map +1 -0
- package/dist/tests/core/parse.test.js +174 -0
- package/dist/tests/core/parse.test.js.map +1 -0
- package/dist/tests/core/path.test.js +50 -0
- package/dist/tests/core/path.test.js.map +1 -0
- package/dist/tests/core/plan.test.js +218 -0
- package/dist/tests/core/plan.test.js.map +1 -0
- package/dist/tests/core/post-move.test.js +162 -0
- package/dist/tests/core/post-move.test.js.map +1 -0
- package/dist/tests/core/pr-classify.test.js +117 -0
- package/dist/tests/core/pr-classify.test.js.map +1 -0
- package/dist/tests/core/pr-decide.test.js +298 -0
- package/dist/tests/core/pr-decide.test.js.map +1 -0
- package/dist/tests/core/pr-loop.test.js +301 -0
- package/dist/tests/core/pr-loop.test.js.map +1 -0
- package/dist/tests/core/pr-notes.test.js +165 -0
- package/dist/tests/core/pr-notes.test.js.map +1 -0
- package/dist/tests/core/predicates.test.js +154 -0
- package/dist/tests/core/predicates.test.js.map +1 -0
- package/dist/tests/core/prompt.test.js +189 -0
- package/dist/tests/core/prompt.test.js.map +1 -0
- package/dist/tests/core/protocol.test.js +195 -0
- package/dist/tests/core/protocol.test.js.map +1 -0
- package/dist/tests/core/reconcile-issue.test.js +116 -0
- package/dist/tests/core/reconcile-issue.test.js.map +1 -0
- package/dist/tests/core/render.test.js +549 -0
- package/dist/tests/core/render.test.js.map +1 -0
- package/dist/tests/core/retry.test.js +186 -0
- package/dist/tests/core/retry.test.js.map +1 -0
- package/dist/tests/core/routes.test.js +247 -0
- package/dist/tests/core/routes.test.js.map +1 -0
- package/dist/tests/core/run-fold.test.js +299 -0
- package/dist/tests/core/run-fold.test.js.map +1 -0
- package/dist/tests/core/shape.test.js +185 -0
- package/dist/tests/core/shape.test.js.map +1 -0
- package/dist/tests/core/sleep-cycle.test.js +150 -0
- package/dist/tests/core/sleep-cycle.test.js.map +1 -0
- package/dist/tests/core/slots.test.js +201 -0
- package/dist/tests/core/slots.test.js.map +1 -0
- package/dist/tests/core/state-resolve.test.js +80 -0
- package/dist/tests/core/state-resolve.test.js.map +1 -0
- package/dist/tests/core/summary.test.js +200 -0
- package/dist/tests/core/summary.test.js.map +1 -0
- package/dist/tests/core/template.test.js +116 -0
- package/dist/tests/core/template.test.js.map +1 -0
- package/dist/tests/core/tick.test.js +558 -0
- package/dist/tests/core/tick.test.js.map +1 -0
- package/dist/tests/core/token-fold.test.js +176 -0
- package/dist/tests/core/token-fold.test.js.map +1 -0
- package/dist/tests/core/turn.test.js +388 -0
- package/dist/tests/core/turn.test.js.map +1 -0
- package/dist/tests/core/url.test.js +118 -0
- package/dist/tests/core/url.test.js.map +1 -0
- package/dist/tests/core/validate.test.js +247 -0
- package/dist/tests/core/validate.test.js.map +1 -0
- package/dist/tests/core/views.test.js +252 -0
- package/dist/tests/core/views.test.js.map +1 -0
- package/dist/tests/core/vm-decide.test.js +110 -0
- package/dist/tests/core/vm-decide.test.js.map +1 -0
- package/dist/tests/core/vm-guards.test.js +153 -0
- package/dist/tests/core/vm-guards.test.js.map +1 -0
- package/dist/tests/core/vm-plan.test.js +332 -0
- package/dist/tests/core/vm-plan.test.js.map +1 -0
- package/dist/tests/core/vm-reap.test.js +196 -0
- package/dist/tests/core/vm-reap.test.js.map +1 -0
- package/dist/tests/core/workflow-parse.test.js +493 -0
- package/dist/tests/core/workflow-parse.test.js.map +1 -0
- package/dist/tests/core/workspace-decide.test.js +236 -0
- package/dist/tests/core/workspace-decide.test.js.map +1 -0
- package/dist/tests/helpers/fixtures.js +167 -0
- package/dist/tests/helpers/fixtures.js.map +1 -0
- package/dist/tests/shell/acp-substrate.test.js +101 -0
- package/dist/tests/shell/acp-substrate.test.js.map +1 -0
- package/dist/tests/shell/actions-runner-push.test.js +203 -0
- package/dist/tests/shell/actions-runner-push.test.js.map +1 -0
- package/dist/tests/shell/credential-hooks.test.js +36 -0
- package/dist/tests/shell/credential-hooks.test.js.map +1 -0
- package/dist/tests/shell/credential-registry.test.js +165 -0
- package/dist/tests/shell/credential-registry.test.js.map +1 -0
- package/dist/tests/shell/credential-substrate.test.js +179 -0
- package/dist/tests/shell/credential-substrate.test.js.map +1 -0
- package/dist/tests/shell/dockerfile-mise-pin.test.js +51 -0
- package/dist/tests/shell/dockerfile-mise-pin.test.js.map +1 -0
- package/dist/tests/shell/doctor.test.js +101 -0
- package/dist/tests/shell/doctor.test.js.map +1 -0
- package/dist/tests/shell/effect-vm-create.test.js +52 -0
- package/dist/tests/shell/effect-vm-create.test.js.map +1 -0
- package/dist/tests/shell/gh-port.test.js +63 -0
- package/dist/tests/shell/gh-port.test.js.map +1 -0
- package/dist/tests/shell/gondolin-dispatch-guard.test.js +144 -0
- package/dist/tests/shell/gondolin-dispatch-guard.test.js.map +1 -0
- package/dist/tests/shell/gondolin-dispatch-shquote.test.js +168 -0
- package/dist/tests/shell/gondolin-dispatch-shquote.test.js.map +1 -0
- package/dist/tests/shell/gondolin-image-converter.test.js +208 -0
- package/dist/tests/shell/gondolin-image-converter.test.js.map +1 -0
- package/dist/tests/shell/gondolin-image-fetch.test.js +93 -0
- package/dist/tests/shell/gondolin-image-fetch.test.js.map +1 -0
- package/dist/tests/shell/http-handler.test.js +608 -0
- package/dist/tests/shell/http-handler.test.js.map +1 -0
- package/dist/tests/shell/http-server.test.js +53 -0
- package/dist/tests/shell/http-server.test.js.map +1 -0
- package/dist/tests/shell/mcp-runtime.test.js +366 -0
- package/dist/tests/shell/mcp-runtime.test.js.map +1 -0
- package/dist/tests/shell/mise-config-asset.test.js +87 -0
- package/dist/tests/shell/mise-config-asset.test.js.map +1 -0
- package/dist/tests/shell/orchestrator-loop.test.js +583 -0
- package/dist/tests/shell/orchestrator-loop.test.js.map +1 -0
- package/dist/tests/shell/reconciler-passes.test.js +314 -0
- package/dist/tests/shell/reconciler-passes.test.js.map +1 -0
- package/dist/tests/shell/runner-loop-turn.test.js +97 -0
- package/dist/tests/shell/runner-loop-turn.test.js.map +1 -0
- package/dist/tests/shell/runner-slice.test.js +536 -0
- package/dist/tests/shell/runner-slice.test.js.map +1 -0
- package/dist/tests/shell/scaffold.test.js +65 -0
- package/dist/tests/shell/scaffold.test.js.map +1 -0
- package/dist/tests/shell/tick-config.test.js +83 -0
- package/dist/tests/shell/tick-config.test.js.map +1 -0
- package/dist/tests/shell/tracker-parse-dates.test.js +44 -0
- package/dist/tests/shell/tracker-parse-dates.test.js.map +1 -0
- package/dist/tests/shell/tracker-write-issue.test.js +154 -0
- package/dist/tests/shell/tracker-write-issue.test.js.map +1 -0
- package/dist/tests/shell/workflow-prompt-split.test.js +208 -0
- package/dist/tests/shell/workflow-prompt-split.test.js.map +1 -0
- package/dist/tests/shell/workspace-live-config.test.js +140 -0
- package/dist/tests/shell/workspace-live-config.test.js.map +1 -0
- package/package.json +21 -9
- package/patches/@earendil-works+gondolin+0.12.0.patch +173 -0
- package/prompts/Reflect.md +91 -0
- package/prompts/Review.md +97 -0
- package/prompts/Todo.md +96 -0
- package/prompts/_footer.md +41 -0
- package/prompts/_preamble.md +42 -0
- package/prompts-minimal/Todo.md +26 -0
- package/scripts/postinstall.mjs +63 -0
- package/scripts/vm-agent.mjs +312 -90
- package/WORKFLOW.md +0 -744
- package/dist/acp-bridge.js +0 -324
- package/dist/acp-bridge.js.map +0 -1
- package/dist/actions/cache.js +0 -191
- package/dist/actions/cache.js.map +0 -1
- package/dist/actions/effects.js +0 -41
- package/dist/actions/effects.js.map +0 -1
- package/dist/actions/executor.js +0 -570
- package/dist/actions/executor.js.map +0 -1
- package/dist/actions/index.js +0 -13
- package/dist/actions/index.js.map +0 -1
- package/dist/actions/parsing.js.map +0 -1
- package/dist/actions/predicate-env.js +0 -27
- package/dist/actions/predicate-env.js.map +0 -1
- package/dist/actions/predicates.js +0 -49
- package/dist/actions/predicates.js.map +0 -1
- package/dist/actions/templating.js +0 -66
- package/dist/actions/templating.js.map +0 -1
- package/dist/actions/types.js +0 -15
- package/dist/actions/types.js.map +0 -1
- package/dist/agent/acp.js +0 -473
- package/dist/agent/acp.js.map +0 -1
- package/dist/agent/adapter-names.js +0 -159
- package/dist/agent/adapter-names.js.map +0 -1
- package/dist/agent/adapters.js +0 -511
- package/dist/agent/adapters.js.map +0 -1
- package/dist/agent/credential-extractors.js +0 -342
- package/dist/agent/credential-extractors.js.map +0 -1
- package/dist/agent/credential-secrets.js +0 -628
- package/dist/agent/credential-secrets.js.map +0 -1
- package/dist/agent/credential-ticker.js +0 -57
- package/dist/agent/credential-ticker.js.map +0 -1
- package/dist/agent/gondolin-creds-staging.js +0 -356
- package/dist/agent/gondolin-creds-staging.js.map +0 -1
- package/dist/agent/gondolin-dispatch.js +0 -375
- package/dist/agent/gondolin-dispatch.js.map +0 -1
- package/dist/agent/gondolin.js +0 -124
- package/dist/agent/gondolin.js.map +0 -1
- package/dist/agent/runner-decisions.js +0 -134
- package/dist/agent/runner-decisions.js.map +0 -1
- package/dist/agent/runner.js +0 -1456
- package/dist/agent/runner.js.map +0 -1
- package/dist/agent/tool-call-summary.js +0 -102
- package/dist/agent/tool-call-summary.js.map +0 -1
- package/dist/agent/vm-acp-mapping.js +0 -73
- package/dist/agent/vm-acp-mapping.js.map +0 -1
- package/dist/agent/vm-guards.js +0 -262
- package/dist/agent/vm-guards.js.map +0 -1
- package/dist/agent/vm-port.js +0 -22
- package/dist/agent/vm-port.js.map +0 -1
- package/dist/agent/vm-process-registry.js +0 -79
- package/dist/agent/vm-process-registry.js.map +0 -1
- package/dist/bin/cli-args.js +0 -105
- package/dist/bin/cli-args.js.map +0 -1
- package/dist/bin/symphony.js +0 -794
- package/dist/bin/symphony.js.map +0 -1
- package/dist/errors.js +0 -15
- package/dist/errors.js.map +0 -1
- package/dist/http-disk.js +0 -135
- package/dist/http-disk.js.map +0 -1
- package/dist/http-handlers.js.map +0 -1
- package/dist/http.js.map +0 -1
- package/dist/issues.js +0 -178
- package/dist/issues.js.map +0 -1
- package/dist/logging.js +0 -203
- package/dist/logging.js.map +0 -1
- package/dist/mcp.js +0 -706
- package/dist/mcp.js.map +0 -1
- package/dist/memory.js +0 -85
- package/dist/memory.js.map +0 -1
- package/dist/orchestrator-decisions.js +0 -331
- package/dist/orchestrator-decisions.js.map +0 -1
- package/dist/orchestrator.js +0 -1569
- package/dist/orchestrator.js.map +0 -1
- package/dist/prompt.js +0 -65
- package/dist/prompt.js.map +0 -1
- package/dist/reconciler/cache.js +0 -65
- package/dist/reconciler/cache.js.map +0 -1
- package/dist/reconciler/index.js +0 -448
- package/dist/reconciler/index.js.map +0 -1
- package/dist/reconciler/ledger.js +0 -131
- package/dist/reconciler/ledger.js.map +0 -1
- package/dist/reconciler/pr-adapters.js +0 -174
- package/dist/reconciler/pr-adapters.js.map +0 -1
- package/dist/reconciler/pr-decide.js.map +0 -1
- package/dist/reconciler/pr.js +0 -422
- package/dist/reconciler/pr.js.map +0 -1
- package/dist/reconciler/types.js +0 -12
- package/dist/reconciler/types.js.map +0 -1
- package/dist/reconciler/vm.js +0 -243
- package/dist/reconciler/vm.js.map +0 -1
- package/dist/reconciler/workspace-defaults.js +0 -83
- package/dist/reconciler/workspace-defaults.js.map +0 -1
- package/dist/reconciler/workspace.js +0 -272
- package/dist/reconciler/workspace.js.map +0 -1
- package/dist/runlog.js +0 -403
- package/dist/runlog.js.map +0 -1
- package/dist/scaffold.js +0 -165
- package/dist/scaffold.js.map +0 -1
- package/dist/trackers/local.js +0 -445
- package/dist/trackers/local.js.map +0 -1
- package/dist/trackers/types.js +0 -10
- package/dist/trackers/types.js.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/util/clock.js +0 -12
- package/dist/util/clock.js.map +0 -1
- package/dist/util/crypto.js +0 -25
- package/dist/util/crypto.js.map +0 -1
- package/dist/util/frontmatter.js +0 -70
- package/dist/util/frontmatter.js.map +0 -1
- package/dist/util/fs-issues.js +0 -22
- package/dist/util/fs-issues.js.map +0 -1
- package/dist/util/process.js +0 -152
- package/dist/util/process.js.map +0 -1
- package/dist/util/workspace-key.js +0 -10
- package/dist/util/workspace-key.js.map +0 -1
- package/dist/workflow-loader.js +0 -147
- package/dist/workflow-loader.js.map +0 -1
- package/dist/workflow.js +0 -822
- package/dist/workflow.js.map +0 -1
- package/dist/workspace-types.js +0 -8
- package/dist/workspace-types.js.map +0 -1
- package/dist/workspace.js +0 -443
- package/dist/workspace.js.map +0 -1
package/DESIGN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: smol-symphony
|
|
3
|
-
description: The orchestrator's console. A small dark workshop for dispatching and watching coding agents.
|
|
3
|
+
description: The orchestrator's console. A small dark workshop for dispatching and watching coding agents, laid out as a kanban bench.
|
|
4
4
|
colors:
|
|
5
5
|
surface-inset: "#0c0f15"
|
|
6
6
|
surface-base: "#0f1115"
|
|
@@ -12,26 +12,31 @@ colors:
|
|
|
12
12
|
text-muted: "#9aa4b2"
|
|
13
13
|
text-base: "#dfe2e7"
|
|
14
14
|
text-strong: "#e6ebf2"
|
|
15
|
-
text-on-accent: "#
|
|
15
|
+
text-on-accent: "#f4f6fb"
|
|
16
16
|
dispatch-blue: "#2a6df4"
|
|
17
|
+
link-hover: "#9cc0ff"
|
|
17
18
|
running-bg: "#1f3a26"
|
|
18
19
|
running-fg: "#58d68d"
|
|
19
20
|
retrying-bg: "#3a2f1f"
|
|
20
21
|
retrying-fg: "#f0c060"
|
|
21
22
|
idle-bg: "#20242c"
|
|
22
23
|
idle-fg: "#9aa4b2"
|
|
24
|
+
await-bg: "#1f2a36"
|
|
25
|
+
await-fg: "#7fb5d4"
|
|
26
|
+
done-bg: "#1c2a1f"
|
|
27
|
+
done-fg: "#82c896"
|
|
23
28
|
error-fg: "#ff7676"
|
|
24
29
|
success-fg: "#58d68d"
|
|
25
30
|
typography:
|
|
26
31
|
headline:
|
|
27
32
|
fontFamily: "ui-sans-serif, system-ui, sans-serif"
|
|
28
33
|
fontSize: "1.3rem"
|
|
29
|
-
fontWeight:
|
|
30
|
-
lineHeight: 1.
|
|
34
|
+
fontWeight: 500
|
|
35
|
+
lineHeight: 1.3
|
|
31
36
|
title:
|
|
32
37
|
fontFamily: "ui-sans-serif, system-ui, sans-serif"
|
|
33
38
|
fontSize: "1rem"
|
|
34
|
-
fontWeight:
|
|
39
|
+
fontWeight: 500
|
|
35
40
|
lineHeight: 1.3
|
|
36
41
|
body:
|
|
37
42
|
fontFamily: "ui-sans-serif, system-ui, sans-serif"
|
|
@@ -43,9 +48,14 @@ typography:
|
|
|
43
48
|
fontSize: "14px"
|
|
44
49
|
fontWeight: 400
|
|
45
50
|
lineHeight: 1.4
|
|
51
|
+
colhead:
|
|
52
|
+
fontFamily: "ui-sans-serif, system-ui, sans-serif"
|
|
53
|
+
fontSize: "14px"
|
|
54
|
+
fontWeight: 500
|
|
55
|
+
lineHeight: 1.4
|
|
46
56
|
pill:
|
|
47
57
|
fontFamily: "ui-sans-serif, system-ui, sans-serif"
|
|
48
|
-
fontSize: "0.
|
|
58
|
+
fontSize: "0.78em"
|
|
49
59
|
fontWeight: 400
|
|
50
60
|
lineHeight: 1.4
|
|
51
61
|
data:
|
|
@@ -54,14 +64,15 @@ typography:
|
|
|
54
64
|
fontWeight: 400
|
|
55
65
|
fontFeature: "tabular-nums"
|
|
56
66
|
lineHeight: 1.45
|
|
57
|
-
|
|
58
|
-
fontFamily: "ui-
|
|
59
|
-
fontSize: "
|
|
60
|
-
fontWeight:
|
|
67
|
+
mono:
|
|
68
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
|
|
69
|
+
fontSize: "13px"
|
|
70
|
+
fontWeight: 400
|
|
71
|
+
fontFeature: "tabular-nums"
|
|
61
72
|
lineHeight: 1.4
|
|
62
73
|
rounded:
|
|
74
|
+
xs: "3px"
|
|
63
75
|
sm: "4px"
|
|
64
|
-
md: "8px"
|
|
65
76
|
pill: "999px"
|
|
66
77
|
spacing:
|
|
67
78
|
"2xs": "0.1rem"
|
|
@@ -75,53 +86,96 @@ components:
|
|
|
75
86
|
backgroundColor: "{colors.dispatch-blue}"
|
|
76
87
|
textColor: "{colors.text-on-accent}"
|
|
77
88
|
rounded: "{rounded.sm}"
|
|
78
|
-
padding: "0.
|
|
89
|
+
padding: "0.55rem 1.1rem"
|
|
79
90
|
typography: "{typography.body}"
|
|
80
91
|
button-ghost:
|
|
81
92
|
backgroundColor: "{colors.surface-chip}"
|
|
82
93
|
textColor: "{colors.text-base}"
|
|
94
|
+
border: "1px solid {colors.border-firm}"
|
|
83
95
|
rounded: "{rounded.sm}"
|
|
84
|
-
padding: "0.
|
|
96
|
+
padding: "0.35rem 0.85rem"
|
|
85
97
|
typography: "{typography.body}"
|
|
98
|
+
button-ghost-sm:
|
|
99
|
+
backgroundColor: "transparent"
|
|
100
|
+
textColor: "{colors.text-muted}"
|
|
101
|
+
border: "1px solid {colors.border-firm}"
|
|
102
|
+
rounded: "{rounded.xs}"
|
|
103
|
+
padding: "0.18rem 0.6rem"
|
|
104
|
+
typography: "{typography.pill}"
|
|
105
|
+
icon-button:
|
|
106
|
+
backgroundColor: "{colors.surface-chip}"
|
|
107
|
+
textColor: "{colors.text-muted}"
|
|
108
|
+
border: "1px solid {colors.border-firm}"
|
|
109
|
+
rounded: "{rounded.sm}"
|
|
110
|
+
size: "22–28px square"
|
|
86
111
|
input:
|
|
87
112
|
backgroundColor: "{colors.surface-inset}"
|
|
88
113
|
textColor: "{colors.text-strong}"
|
|
114
|
+
border: "1px solid {colors.border-firm}"
|
|
89
115
|
rounded: "{rounded.sm}"
|
|
90
|
-
padding: "0.
|
|
116
|
+
padding: "0.45rem 0.6rem"
|
|
117
|
+
focusOutline: "1px solid {colors.dispatch-blue}"
|
|
91
118
|
typography: "{typography.body}"
|
|
92
|
-
|
|
119
|
+
new-issue-panel:
|
|
93
120
|
backgroundColor: "{colors.surface-raised}"
|
|
94
121
|
textColor: "{colors.text-base}"
|
|
95
|
-
|
|
96
|
-
|
|
122
|
+
borderLeft: "1px solid {colors.border-firm}"
|
|
123
|
+
rounded: "0"
|
|
124
|
+
placement: "fixed, right edge, full height, slides in"
|
|
125
|
+
header-badge:
|
|
126
|
+
rounded: "{rounded.pill}"
|
|
127
|
+
padding: "0.1rem 0.55rem"
|
|
128
|
+
typography: "{typography.pill}"
|
|
129
|
+
transform: "uppercase"
|
|
130
|
+
variants:
|
|
131
|
+
idle: { backgroundColor: "{colors.idle-bg}", textColor: "{colors.idle-fg}" }
|
|
132
|
+
working: { backgroundColor: "{colors.running-bg}", textColor: "{colors.running-fg}" }
|
|
133
|
+
attention: { backgroundColor: "{colors.await-bg}", textColor: "{colors.await-fg}" }
|
|
97
134
|
pill-running:
|
|
98
135
|
backgroundColor: "{colors.running-bg}"
|
|
99
136
|
textColor: "{colors.running-fg}"
|
|
100
137
|
rounded: "{rounded.pill}"
|
|
101
|
-
padding: "0.1rem 0.
|
|
138
|
+
padding: "0.1rem 0.55rem"
|
|
102
139
|
typography: "{typography.pill}"
|
|
103
140
|
pill-retrying:
|
|
104
141
|
backgroundColor: "{colors.retrying-bg}"
|
|
105
142
|
textColor: "{colors.retrying-fg}"
|
|
106
143
|
rounded: "{rounded.pill}"
|
|
107
|
-
padding: "0.1rem 0.
|
|
144
|
+
padding: "0.1rem 0.55rem"
|
|
108
145
|
typography: "{typography.pill}"
|
|
109
146
|
pill-idle:
|
|
110
147
|
backgroundColor: "{colors.idle-bg}"
|
|
111
148
|
textColor: "{colors.idle-fg}"
|
|
112
149
|
rounded: "{rounded.pill}"
|
|
113
|
-
padding: "0.1rem 0.
|
|
150
|
+
padding: "0.1rem 0.55rem"
|
|
151
|
+
typography: "{typography.pill}"
|
|
152
|
+
pill-awaiting:
|
|
153
|
+
backgroundColor: "{colors.await-bg}"
|
|
154
|
+
textColor: "{colors.await-fg}"
|
|
155
|
+
rounded: "{rounded.pill}"
|
|
156
|
+
padding: "0.1rem 0.55rem"
|
|
157
|
+
typography: "{typography.pill}"
|
|
158
|
+
pill-done:
|
|
159
|
+
backgroundColor: "{colors.done-bg}"
|
|
160
|
+
textColor: "{colors.done-fg}"
|
|
161
|
+
rounded: "{rounded.pill}"
|
|
162
|
+
padding: "0.1rem 0.55rem"
|
|
114
163
|
typography: "{typography.pill}"
|
|
115
|
-
|
|
116
|
-
|
|
164
|
+
kanban-column:
|
|
165
|
+
headerBorderBottom: "1px solid {colors.border-firm}"
|
|
166
|
+
nameColor: "{colors.text-muted}"
|
|
167
|
+
countColor: "{colors.text-dim}"
|
|
168
|
+
typography: "{typography.colhead}"
|
|
169
|
+
issue-row:
|
|
170
|
+
backgroundColor: "transparent"
|
|
171
|
+
borderBottom: "1px solid {colors.border-soft}"
|
|
172
|
+
rounded: "{rounded.xs}"
|
|
173
|
+
awaitTint: "rgba(127, 181, 212, 0.07)"
|
|
174
|
+
retryStuckTint: "rgba(240, 192, 96, 0.05)"
|
|
175
|
+
health-field:
|
|
117
176
|
textColor: "{colors.text-muted}"
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
td:
|
|
121
|
-
backgroundColor: "{colors.surface-base}"
|
|
122
|
-
textColor: "{colors.text-base}"
|
|
123
|
-
typography: "{typography.data}"
|
|
124
|
-
padding: "0.4rem 0.6rem"
|
|
177
|
+
badColor: "{colors.error-fg}"
|
|
178
|
+
typography: "{typography.mono}"
|
|
125
179
|
---
|
|
126
180
|
|
|
127
181
|
# Design System: smol-symphony
|
|
@@ -131,323 +185,490 @@ components:
|
|
|
131
185
|
**Creative North Star: "The Quiet Workshop"**
|
|
132
186
|
|
|
133
187
|
A tidy workbench, not a control room. The orchestrator does the real work; this
|
|
134
|
-
surface only shows what is on the bench right now,
|
|
135
|
-
new work on. Everything you can see is
|
|
136
|
-
knows it, and nothing is there for
|
|
188
|
+
surface only shows what is on the bench right now, lays it out as a kanban board
|
|
189
|
+
of states, and gives one place to put new work on. Everything you can see is
|
|
190
|
+
there because the orchestrator actually knows it, and nothing is there for
|
|
191
|
+
atmosphere.
|
|
137
192
|
|
|
138
193
|
The system is dark because the user opens it next to a terminal, against an
|
|
139
194
|
already-dark editor, in the middle of doing other things. It is flat because
|
|
140
195
|
the workshop has no spotlights: depth is conveyed by stacking slightly lighter
|
|
141
196
|
panels on a slightly darker bench, never by glow or lift. Numbers are tabular,
|
|
142
|
-
labels are real field names, and
|
|
143
|
-
|
|
197
|
+
identifiers are monospace, labels are real field names, and every status colour
|
|
198
|
+
encodes one distinct thing the orchestrator tracks.
|
|
144
199
|
|
|
145
200
|
What this system rejects, drawn from PRODUCT.md: generic SaaS dashboard chrome
|
|
146
|
-
(sidebar nav, gradient metric tiles, identical card grids
|
|
147
|
-
heaviness (modal-on-modal flows, status pills whose
|
|
148
|
-
distinct state), and AI-product chrome (violet gradients,
|
|
149
|
-
sparkle iconography). smol-symphony runs AI agents but is not an
|
|
150
|
-
the agents are infrastructure, not the narrative.
|
|
201
|
+
(sidebar nav, gradient metric tiles, identical card grids, "Welcome back"
|
|
202
|
+
heroes), Jira-style ITSM heaviness (modal-on-modal flows, status pills whose
|
|
203
|
+
colours don't encode distinct state), and AI-product chrome (violet gradients,
|
|
204
|
+
glassmorphism, sparkle iconography). smol-symphony runs AI agents but is not an
|
|
205
|
+
AI product; the agents are infrastructure, not the narrative.
|
|
151
206
|
|
|
152
207
|
**Key Characteristics:**
|
|
153
208
|
- Dark, cool-blue-leaning neutrals stacked into four tonal layers.
|
|
154
|
-
- One saturated accent (Dispatch Blue)
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
|
|
158
|
-
|
|
209
|
+
- One saturated brand accent (Dispatch Blue), used for the primary verb and the
|
|
210
|
+
keyboard-focus ring. No second saturated hue competes with it.
|
|
211
|
+
- Five semantic status pairs (running, retrying, idle, await, done), each a
|
|
212
|
+
paired bg + fg colour mapped to a real orchestrator state. New states earn a
|
|
213
|
+
new named pair; colours never get reused for a second meaning.
|
|
214
|
+
- The board is a **kanban**: one column per declared workflow state, each issue
|
|
215
|
+
a flat row. Transient runtime status (running / retrying / awaiting steering)
|
|
216
|
+
is overlaid on the row via a pill, a metadata trail, and tint.
|
|
217
|
+
- A sticky **header strip** carries a single tracker-state badge (idle /
|
|
218
|
+
working / attention), and a dense **system-health line** answers "is this
|
|
219
|
+
connected?" without a hero.
|
|
220
|
+
- New work is composed in a **slide-in panel** that enters from the right edge.
|
|
221
|
+
It is the one card-shaped surface; the board stays visible and interactive
|
|
222
|
+
behind it (non-modal).
|
|
223
|
+
- No shadows. Depth is tonal stacking, plus the one panel that slides in over
|
|
224
|
+
the bench.
|
|
225
|
+
- Two native font stacks: a system sans for prose, and a system monospace for
|
|
226
|
+
identifiers, code, paths, and the health line. No web fonts. Tabular numerics
|
|
227
|
+
on anything that holds a number.
|
|
228
|
+
- Density over whitespace luxury: columns are tight, rows are flat, the health
|
|
229
|
+
line is a single `key=value` strip.
|
|
230
|
+
- Motion exists only to encode or reveal state (the panel sliding in, a region
|
|
231
|
+
expanding when it has something to say, a hover affordance) — never as
|
|
232
|
+
decoration.
|
|
159
233
|
|
|
160
234
|
## 2. Colors: The Workshop Bench Palette
|
|
161
235
|
|
|
162
|
-
A cool-blue-leaning dark stack with one saturated accent and
|
|
163
|
-
status pairs. Each neutral is tinted toward the accent hue at near-zero
|
|
164
|
-
|
|
236
|
+
A cool-blue-leaning dark stack with one saturated brand accent and five semantic
|
|
237
|
+
status pairs. Each neutral is tinted toward the accent hue at near-zero chroma
|
|
238
|
+
so no surface reads as pure grey. All values below are the live CSS custom
|
|
239
|
+
properties from the shipping dashboard (`:root` in `src/http.ts`).
|
|
165
240
|
|
|
166
241
|
### Primary
|
|
167
|
-
- **Dispatch Blue** (`#2a6df4`, ≈`oklch(55% 0.22 261)`): the
|
|
168
|
-
the
|
|
169
|
-
|
|
170
|
-
|
|
242
|
+
- **Dispatch Blue** (`#2a6df4`, ≈`oklch(55% 0.22 261)`): the brand accent. It
|
|
243
|
+
fills the one primary verb — the **create** button in the new-issue panel —
|
|
244
|
+
and draws the keyboard **focus ring** on every interactive control
|
|
245
|
+
(`outline … solid var(--accent)`; inputs also take it as a focus
|
|
246
|
+
border-colour). It is the interaction accent, never a decorative one. Its
|
|
247
|
+
on-accent text is **`#f4f6fb`**, a near-white tinted toward the brand hue (the
|
|
248
|
+
old pure-`#fff` button label has been retired — see Don'ts).
|
|
249
|
+
- **Link Hover** (`#9cc0ff`): a lightened Dispatch Blue used for the hover /
|
|
250
|
+
focus state of identifiers and links (row identifiers, ticker IDs, the
|
|
251
|
+
steering panel's links, issue-detail body links). The resting state of those
|
|
252
|
+
links is a neutral text tone; the blue appears only on interaction.
|
|
171
253
|
|
|
172
254
|
### Neutral (the bench, four tonal layers)
|
|
173
|
-
- **Inset** (`#0c0f15`, ≈`oklch(16% 0.008 260)`): input field interiors
|
|
174
|
-
Deeper than the body so fields read as sunken
|
|
175
|
-
- **Bench** (`#0f1115`, ≈`oklch(18% 0.005 260)`): the page body
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
255
|
+
- **Inset** (`#0c0f15`, ≈`oklch(16% 0.008 260)`): input field interiors and code
|
|
256
|
+
blocks. Deeper than the body so fields read as sunken slots, not floating.
|
|
257
|
+
- **Bench** (`#0f1115`, ≈`oklch(18% 0.005 260)`): the page body, the header
|
|
258
|
+
strip, the health line, and the ticker. The default surface; everything else
|
|
259
|
+
stacks on or beneath this.
|
|
260
|
+
- **Raised Panel** (`#161a22`, ≈`oklch(21% 0.012 260)`): the slide-in new-issue
|
|
261
|
+
panel. One step lighter than the bench, signalling "this is where you put new
|
|
179
262
|
things."
|
|
180
|
-
- **Chip** (`#20242c`, ≈`oklch(27% 0.012 260)`):
|
|
181
|
-
idle pill. The most-lifted neutral; reserved
|
|
182
|
-
and quiet status.
|
|
263
|
+
- **Chip** (`#20242c`, ≈`oklch(27% 0.012 260)`): ghost buttons, the icon buttons
|
|
264
|
+
(refresh, panel close), and the idle pill. The most-lifted neutral; reserved
|
|
265
|
+
for small interactive surfaces and quiet status.
|
|
183
266
|
|
|
184
267
|
### Border / Rule
|
|
185
|
-
- **Soft Rule** (`#1c2029`, ≈`oklch(25% 0.010 260)`):
|
|
186
|
-
|
|
187
|
-
- **Firm Rule** (`#2a2e36`, ≈`oklch(31% 0.008 260)`):
|
|
188
|
-
|
|
268
|
+
- **Soft Rule** (`#1c2029`, ≈`oklch(25% 0.010 260)`): row dividers, and the
|
|
269
|
+
thin separators under the health line and ticker. Just barely visible.
|
|
270
|
+
- **Firm Rule** (`#2a2e36`, ≈`oklch(31% 0.008 260)`): control borders, the
|
|
271
|
+
header's bottom edge, the panel's left edge, and column-header underlines.
|
|
272
|
+
The structural lines.
|
|
189
273
|
|
|
190
274
|
### Text (the four-step ramp)
|
|
191
|
-
- **Dim** (`#6b7280`): timestamps,
|
|
192
|
-
|
|
193
|
-
- **Muted** (`#9aa4b2`):
|
|
194
|
-
- **Base** (`#dfe2e7`): primary body text
|
|
195
|
-
- **Strong** (`#e6ebf2`):
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
275
|
+
- **Dim** (`#6b7280`): timestamps, the row "peek" line, column counts, the
|
|
276
|
+
totals footer, `.dim` annotations. The lowest reading layer.
|
|
277
|
+
- **Muted** (`#9aa4b2`): labels, column names, the health line, secondary copy.
|
|
278
|
+
- **Base** (`#dfe2e7`): primary body text, row titles, table-less cell content.
|
|
279
|
+
- **Strong** (`#e6ebf2`): text the user is typing (inputs), row identifiers,
|
|
280
|
+
section and panel titles. One step brighter than base.
|
|
281
|
+
|
|
282
|
+
### Status (five paired roles)
|
|
283
|
+
Each carries both a background and a foreground; the pair is fixed per state and
|
|
284
|
+
never reused across states. The light-on-dark foreground is what reads at a
|
|
285
|
+
glance. The dashboard uses these as **pills** on rows, as the header **badge**,
|
|
286
|
+
and as faint full-row **tints**; the issue-detail page reuses the same pairs.
|
|
287
|
+
|
|
288
|
+
- **Running** (`bg #1f3a26`, `fg #58d68d`): a live session. The orchestrator is
|
|
289
|
+
currently spending tokens on this issue. A *continuation* (the slot-holding
|
|
290
|
+
resume of a clean handoff, e.g. Review → Todo) deliberately reads as running,
|
|
291
|
+
not retrying, so a clean handoff never flashes an error colour (issue 146).
|
|
292
|
+
- **Retrying** (`bg #3a2f1f`, `fg #f0c060`): the failure-backoff queue. The
|
|
293
|
+
orchestrator hit a recoverable failure and will dispatch again on backoff.
|
|
294
|
+
Only `failure` retries are amber; continuations are not. Amber also tints the
|
|
295
|
+
name of a holding column and the "N retrying" ticker label.
|
|
207
296
|
- **Idle** (`bg #20242c`, `fg #9aa4b2`): on disk, not running, not retrying.
|
|
208
297
|
Deliberately the same hex as Chip + Muted, because idle is *the absence of
|
|
209
|
-
status
|
|
298
|
+
status colour*.
|
|
299
|
+
- **Await** (`bg #1f2a36`, `fg #7fb5d4`): an agent has called
|
|
300
|
+
`request_human_steering` and is blocked on the operator's reply. A calm blue,
|
|
301
|
+
not an alarm. Drives the `awaiting` pill, the "attention" header badge, the
|
|
302
|
+
"N awaiting" ticker label, and a faint blue wash on the awaiting row. The
|
|
303
|
+
same pair backs the (currently unused) `resuming` pill alias, kept calm-blue
|
|
304
|
+
for the same reason continuations stay green.
|
|
305
|
+
- **Done** (`bg #1c2a1f`, `fg #82c896`): a terminal state (Done, Cancelled). A
|
|
306
|
+
muted, settled green — quieter than running. Terminal columns are omitted from
|
|
307
|
+
the board, so this pair appears mainly on the issue-detail page and on any
|
|
308
|
+
trailing "undeclared" column.
|
|
210
309
|
|
|
211
310
|
### Inline message
|
|
212
|
-
- **Error** (`#ff7676`): the
|
|
213
|
-
a
|
|
214
|
-
|
|
215
|
-
|
|
311
|
+
- **Error** (`#ff7676`, ≈`oklch(70% 0.18 22)`): the panel's error line, a stuck
|
|
312
|
+
retry's error text, a bad health field (`hf-bad`), the "undeclared" column
|
|
313
|
+
badge, and the ticker error chip. Inline, never a toast, never a modal.
|
|
314
|
+
- **Success** (`#58d68d`): the panel's OK line. Shares the running-fg green by
|
|
315
|
+
design; success means "the orchestrator now knows about this."
|
|
216
316
|
|
|
217
317
|
### Named Rules
|
|
218
318
|
|
|
219
|
-
**The One
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
319
|
+
**The One-Accent Rule** (was "The One Verb Rule"). There is exactly one
|
|
320
|
+
saturated brand hue: Dispatch Blue. It marks the single primary verb (the create
|
|
321
|
+
button) and the keyboard-focus ring — both are *interaction*, not decoration. If
|
|
322
|
+
a second saturated accent is wanted, the design is wrong; reach for a status
|
|
323
|
+
pair or text weight first. (This rule was once "Dispatch Blue on exactly one
|
|
324
|
+
element per page"; the focus ring legitimately spreads the same hue across every
|
|
325
|
+
control, so the rule is now scoped to "one hue, interaction-only," not "one
|
|
326
|
+
element.")
|
|
327
|
+
|
|
328
|
+
**The Status-Pair Rule** (replaces "The Three-Pill Rule"). Status colour is a
|
|
329
|
+
closed vocabulary of *named bg + fg pairs*, each mapped to one real orchestrator
|
|
330
|
+
state: running, retrying, idle, await, done. Never invent a colour for taste; if
|
|
331
|
+
a new state emerges, name it semantically and add a new pair here before using
|
|
332
|
+
it. (The original "three pills — running/retrying/idle, no fourth ever" was
|
|
333
|
+
written before the board surfaced awaiting-steering and terminal state; the
|
|
334
|
+
*discipline* — one colour, one true state, no reuse — is unchanged, only the
|
|
335
|
+
count.)
|
|
227
336
|
|
|
228
337
|
**The Tinted Neutral Rule.** No pure greys. Every neutral leans on the cool
|
|
229
338
|
blue brand axis (hue ≈260) at near-zero chroma (0.005–0.012). Pure `#000` and
|
|
230
|
-
pure `#fff` are prohibited.
|
|
339
|
+
pure `#fff` are prohibited (the create button's label is `#f4f6fb`, not `#fff`).
|
|
231
340
|
|
|
232
341
|
## 3. Typography
|
|
233
342
|
|
|
234
343
|
**Body Font:** `ui-sans-serif, system-ui, sans-serif` (browser native).
|
|
235
|
-
**Display Font:** none. The
|
|
236
|
-
**Mono / Data Font:**
|
|
237
|
-
|
|
344
|
+
**Display Font:** none. The sans family carries every prose role.
|
|
345
|
+
**Mono / Data Font:** `ui-monospace, SFMono-Regular, Menlo, Consolas, monospace`
|
|
346
|
+
— a real, distinct (still native) monospace stack used for identifiers, code,
|
|
347
|
+
on-disk paths, the tracker root, the health line, and ticker IDs. Any cell that
|
|
348
|
+
holds a number — sans or mono — carries `font-variant-numeric: tabular-nums`.
|
|
238
349
|
|
|
239
|
-
**Character:** the system
|
|
240
|
-
|
|
241
|
-
|
|
350
|
+
**Character:** the system fonts of whatever OS the user is on. No web fonts, no
|
|
351
|
+
FOUT, no loading flash. The console reads like the operating system, not like a
|
|
352
|
+
product. Identifiers and paths are monospace so they line up and read as
|
|
353
|
+
literal strings; prose stays sans.
|
|
242
354
|
|
|
243
355
|
### Hierarchy
|
|
244
356
|
|
|
245
|
-
The scale is intentionally tight
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
- **
|
|
257
|
-
- **
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
357
|
+
The scale is intentionally tight. The dashboard has **no `h1`** — its identity
|
|
358
|
+
is the header strip (`symphony · <workflow> · <tracker.root>`), not a page
|
|
359
|
+
title. The Headline role now lives on the **issue-detail page** (the issue
|
|
360
|
+
title) and the not-found page. Section titles match body size and lean on a
|
|
361
|
+
divider rule plus top margin for hierarchy, keeping the page console-like.
|
|
362
|
+
|
|
363
|
+
- **Headline** (h1, 500, `1.3rem` ≈ 20.8px, lh 1.3): the issue-detail page title
|
|
364
|
+
(and the not-found page). Once per page; absent on the dashboard.
|
|
365
|
+
- **Title** (h2, 500, `1rem` = 16px, with a `1px` Firm Rule underline): the
|
|
366
|
+
detail page's section labels and the slide-in panel's "new issue" heading.
|
|
367
|
+
Same size as a paragraph; the rule beneath does the hierarchy work.
|
|
368
|
+
- **Body** (400, `14px`, lh 1.45): default text, row titles.
|
|
369
|
+
- **Label** (400, `14px`, colour Muted): form labels in the new-issue panel.
|
|
370
|
+
- **Column header** (500, `14px`, colour Muted): kanban column names. One weight
|
|
371
|
+
step above body (400 → 500) so columns name themselves; a holding column's
|
|
372
|
+
name takes the amber (retrying) tone, a terminal/undeclared column's the Dim
|
|
373
|
+
tone.
|
|
374
|
+
- **Data** (400, `14px`, `tabular-nums`): every number — token counts, attempt
|
|
375
|
+
numbers, runtime, time-of-day, counts.
|
|
376
|
+
- **Pill** (400, `0.78em` ≈ 10.9px against 14px body): status pills and the
|
|
377
|
+
header badge. Smaller than body so they read as inline metadata, not content.
|
|
378
|
+
(The issue-detail page renders its pill slightly larger, `0.82em`.)
|
|
379
|
+
- **Mono** (400, `13px`, `tabular-nums`): identifiers, the tracker root, the
|
|
380
|
+
health line (`12px`), and `<code>`. The CLI-in-HTML texture.
|
|
263
381
|
|
|
264
382
|
### Named Rules
|
|
265
383
|
|
|
266
|
-
**The System-Font Rule.** No web fonts are loaded, ever.
|
|
267
|
-
|
|
268
|
-
the
|
|
384
|
+
**The System-Font Rule.** No web fonts are loaded, ever. Both stacks — the sans
|
|
385
|
+
and the monospace — are the user's native OS fonts. The console must look like
|
|
386
|
+
the user's OS. If a custom face is added later, it has to justify the latency
|
|
387
|
+
cost in writing.
|
|
269
388
|
|
|
270
|
-
**The Tabular-Numbers Rule.** Any
|
|
271
|
-
`font-variant-numeric: tabular-nums`. Token counts, attempt counts,
|
|
272
|
-
|
|
389
|
+
**The Tabular-Numbers Rule.** Any element that contains a number applies
|
|
390
|
+
`font-variant-numeric: tabular-nums`. Token counts, attempt counts, timestamps,
|
|
391
|
+
identifiers with digits, column counts: all of them. Columns of numbers must
|
|
392
|
+
line up.
|
|
273
393
|
|
|
274
|
-
**The Same-Size Section-Header Rule.** Section titles (h2) are the same size
|
|
275
|
-
|
|
276
|
-
|
|
394
|
+
**The Same-Size Section-Header Rule.** Section titles (h2) are the same size as
|
|
395
|
+
body. Hierarchy comes from the divider rule beneath and the margin above, not
|
|
396
|
+
from type scale. This keeps page density high.
|
|
277
397
|
|
|
278
398
|
## 4. Elevation
|
|
279
399
|
|
|
280
|
-
**The system is flat.** No `box-shadow` rule appears anywhere in the
|
|
281
|
-
|
|
282
|
-
`surface-
|
|
283
|
-
|
|
400
|
+
**The system is flat.** No `box-shadow` rule appears anywhere in the stylesheet.
|
|
401
|
+
Depth is conveyed by tonal stacking of the neutrals: `surface-inset` (deepest) →
|
|
402
|
+
`surface-base` (default) → `surface-raised` (the panel) → `surface-chip` (chips,
|
|
403
|
+
icon buttons, idle pill).
|
|
284
404
|
|
|
285
|
-
|
|
286
|
-
panel
|
|
287
|
-
|
|
405
|
+
The one surface that genuinely sits *above* the bench is the **slide-in
|
|
406
|
+
new-issue panel**: it is a Raised-Panel-coloured `aside` fixed to the right
|
|
407
|
+
edge, separated from the bench by a `1px` Firm Rule on its left and by **motion**
|
|
408
|
+
(it slides in on a 320ms ease), not by a shadow or a glow. There is no hover
|
|
409
|
+
lift and no focus glow anywhere; focus is an outline ring in Dispatch Blue.
|
|
288
410
|
|
|
289
411
|
### Named Rules
|
|
290
412
|
|
|
291
|
-
**The Flat-By-Default Rule.** Surfaces are flat. Shadows are forbidden.
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
fifth neutral step
|
|
413
|
+
**The Flat-By-Default Rule.** Surfaces are flat. Shadows are forbidden. Depth
|
|
414
|
+
cues come from the four-step neutral stack, from the divider rules, and from the
|
|
415
|
+
one panel that translates in from the edge. If a future surface needs visible
|
|
416
|
+
elevation, introduce a fifth neutral step (or lean on the existing slide
|
|
417
|
+
motion) before reaching for `box-shadow`.
|
|
418
|
+
|
|
419
|
+
**The No-Glow Rule.** Focus, hover, and active states change colour, border, or
|
|
420
|
+
position — never glow. Focus is a crisp Dispatch Blue outline ring.
|
|
421
|
+
Glassmorphism, blur backdrops, and shimmer animations are prohibited (carries
|
|
422
|
+
PRODUCT.md's AI-product-chrome anti-reference).
|
|
295
423
|
|
|
296
|
-
**The
|
|
297
|
-
|
|
298
|
-
|
|
424
|
+
**The State-Only-Motion Rule.** Motion encodes or reveals state: the panel
|
|
425
|
+
sliding in (it is open or closed), the ticker expanding when it has something to
|
|
426
|
+
say and collapsing to zero height when it doesn't, a hover border easing in as
|
|
427
|
+
an affordance cue, the 2-second poll refreshing. There is no motion that doesn't
|
|
428
|
+
mean something. No animated layout for flourish, no decorative loops, no
|
|
429
|
+
thinking-dots.
|
|
299
430
|
|
|
300
431
|
## 5. Components
|
|
301
432
|
|
|
302
|
-
The doctrine is **crisp and exact**: minimal radius vocabulary (
|
|
303
|
-
|
|
304
|
-
structurally necessary, hairline-tight alignment,
|
|
433
|
+
The doctrine is **crisp and exact**: a minimal radius vocabulary (`3px` for
|
|
434
|
+
rows, `4px` for controls, `999px` for pills and badges), `1px` borders only
|
|
435
|
+
where structurally necessary, hairline-tight alignment, and motion only where it
|
|
436
|
+
encodes state.
|
|
437
|
+
|
|
438
|
+
### Header strip
|
|
439
|
+
|
|
440
|
+
A sticky strip across the top of the dashboard, Bench-coloured with a `1px` Firm
|
|
441
|
+
Rule bottom edge. Left to right: the **brand** (`symphony`, weight 600, Strong),
|
|
442
|
+
a Dim `·`, the **workflow** name (Base), the **tracker root** (Mono, Dim,
|
|
443
|
+
ellipsised, takes the free space), the live **tracker-state badge**, and the
|
|
444
|
+
**refresh** icon button.
|
|
445
|
+
|
|
446
|
+
The **tracker-state badge** is the dashboard's single glance signal, polled
|
|
447
|
+
every 2s. It is a pill that takes one of three states from `trackerStatus()`:
|
|
448
|
+
- **idle** — idle pair (`bg #20242c` / `fg #9aa4b2`): nothing running.
|
|
449
|
+
- **working** — running pair (`bg #1f3a26` / `fg #58d68d`): at least one session
|
|
450
|
+
is live and nothing needs the operator.
|
|
451
|
+
- **attention** — await pair (`bg #1f2a36` / `fg #7fb5d4`): something is awaiting
|
|
452
|
+
steering, or a failure-backoff retry is queued. The badge uses the calm await
|
|
453
|
+
blue (it means "needs your eyes," not "broken"). Continuations never trip it.
|
|
454
|
+
|
|
455
|
+
The badge text is uppercased and letter-spaced; this is the one place type goes
|
|
456
|
+
uppercase, marking it as a status indicator rather than content.
|
|
457
|
+
|
|
458
|
+
### System-health line
|
|
459
|
+
|
|
460
|
+
A dense, single-row `key=value` strip under the header (Bench background, Soft
|
|
461
|
+
Rule below, Mono `12px`, Muted, tabular-nums, wraps on narrow widths). It answers
|
|
462
|
+
the first-run question "is this thing actually connected?" without a hero or a
|
|
463
|
+
metric tile. Each field is a fact the orchestrator already knows from its health
|
|
464
|
+
probe:
|
|
465
|
+
- one `<State>=<adapter>/<model>` field per active state (per-state overrides
|
|
466
|
+
applied; an inherited model shows `/default`),
|
|
467
|
+
- `image=<short-digest>` (the gondolin image; full ref in the `title`),
|
|
468
|
+
- `cred=ok` / `cred=missing:<adapter>`,
|
|
469
|
+
- `tracker=writable` / `tracker=readonly`,
|
|
470
|
+
- `poll=<HH:MM:SS>` (the last poll time).
|
|
471
|
+
|
|
472
|
+
Only genuine problems — a missing credential, a read-only tracker — flag in the
|
|
473
|
+
Error colour (`hf-bad`). No new accent, no tiles, no hero. The region rides the
|
|
474
|
+
same 2s poll as everything else.
|
|
475
|
+
|
|
476
|
+
### Attention ticker
|
|
477
|
+
|
|
478
|
+
A thin strip below the health line listing what currently needs eyes: pending
|
|
479
|
+
steering replies ("N awaiting", await-blue label) and stuck retries ("N retrying
|
|
480
|
+
· M with error", amber label). Each identifier is a monospace anchor that jumps
|
|
481
|
+
to the issue's row in the board. When nothing needs attention the strip
|
|
482
|
+
collapses to **zero height** (padding and border animate away) so an all-clear
|
|
483
|
+
board shows no empty chrome.
|
|
484
|
+
|
|
485
|
+
### Board (kanban)
|
|
486
|
+
|
|
487
|
+
The dominant surface. A horizontally-scrolling grid of columns
|
|
488
|
+
(`grid-auto-flow: column`, min column width `260px`, `1.5rem` gap), **one column
|
|
489
|
+
per declared workflow state in declaration order**. Replaces the old flat
|
|
490
|
+
tables entirely.
|
|
491
|
+
|
|
492
|
+
- **Active** and **holding** states get a column. **Terminal** states (Done,
|
|
493
|
+
Cancelled) are deliberately omitted — the glance test is "what's running,
|
|
494
|
+
what's stuck," which finished work doesn't answer; terminal issues stay
|
|
495
|
+
reachable via their detail page.
|
|
496
|
+
- **Orphan columns**: an on-disk state directory whose name isn't in the
|
|
497
|
+
declared `states:` set (e.g. after a workflow rename) gets a trailing column
|
|
498
|
+
flagged with an Error-coloured `undeclared` badge, so stranded files stay
|
|
499
|
+
visible rather than silently dropping out.
|
|
500
|
+
|
|
501
|
+
Each **column** has a header — name (Column-header type; amber if holding, Dim
|
|
502
|
+
if terminal/orphan), a Dim tabular count, and, for active/holding columns, a
|
|
503
|
+
small `+` **add** icon button that opens the new-issue panel pre-set to that
|
|
504
|
+
column — over a body of rows. An empty active column shows a Dim hint, `drop
|
|
505
|
+
into <State>/`.
|
|
506
|
+
|
|
507
|
+
### Issue row (the flat card)
|
|
508
|
+
|
|
509
|
+
Each on-disk issue is a flat row in its state's column — **not** a card. It has
|
|
510
|
+
a `1px` Soft Rule bottom divider, a small `3px` radius, and no fill at rest.
|
|
511
|
+
Runtime status is overlaid:
|
|
512
|
+
- **Row head**: the monospace identifier (Strong, links to the detail page), a
|
|
513
|
+
status **pill** (`awaiting` / `running` / `retrying`, in that priority), and a
|
|
514
|
+
Muted metadata trail (`turn N · X tok` while running, `attempt N · due
|
|
515
|
+
HH:MM:SS` while in failure backoff).
|
|
516
|
+
- **Title** (Base), then an optional Dim **peek** of the agent's last message
|
|
517
|
+
(clamped to two lines while running).
|
|
518
|
+
- A **stuck retry** shows its error text in the Error colour.
|
|
519
|
+
- A **triage** row (holding state, not otherwise busy) shows inline `approve` /
|
|
520
|
+
`discard` ghost-sm buttons.
|
|
521
|
+
- **Tints, not stripes**: an awaiting row gets a faint blue wash
|
|
522
|
+
(`rgba(127,181,212,0.07)`), a stuck retry a faint amber wash
|
|
523
|
+
(`rgba(240,192,96,0.05)`), an orphan row drops to 70% opacity. The whole row
|
|
524
|
+
tints; there is no colored left-border stripe.
|
|
525
|
+
|
|
526
|
+
Within a column, rows sort so anything needing attention floats up: awaiting →
|
|
527
|
+
running → retrying → idle.
|
|
528
|
+
|
|
529
|
+
### Inline steering (on awaiting rows)
|
|
530
|
+
|
|
531
|
+
When an agent is awaiting steering, its row expands in place (a dashed Firm Rule
|
|
532
|
+
top separator) to show the agent's question (rendered Markdown), an optional
|
|
533
|
+
collapsible recap of the original task and the agent's context, and a reply
|
|
534
|
+
`<textarea>` + send button. Enter sends, Shift+Enter inserts a newline; the
|
|
535
|
+
draft is preserved across the 2s repoll. Steering happens **inline on the row**,
|
|
536
|
+
never in a modal.
|
|
537
|
+
|
|
538
|
+
### Slide-in new-issue panel (the One Card)
|
|
539
|
+
|
|
540
|
+
The dashboard's only card-shaped surface. A Raised-Panel `aside` fixed to the
|
|
541
|
+
right edge (`400px`, max `90vw`, full height), separated from the bench by a
|
|
542
|
+
`1px` Firm Rule left edge. It is **non-modal**: it slides in on a 320ms ease when
|
|
543
|
+
the operator presses a column's `+` button (the originating column pre-selects
|
|
544
|
+
the state field), and the board stays fully visible and interactive on the left.
|
|
545
|
+
Esc closes it; a backdrop click does **not** (so an in-progress draft isn't lost
|
|
546
|
+
to a stray click).
|
|
547
|
+
|
|
548
|
+
It holds the create form: a **column** `<select>`, a **title** input, a
|
|
549
|
+
**description** `<textarea>` (all sunken inputs — Inset background, Strong text,
|
|
550
|
+
Firm Rule border, Dispatch Blue focus ring), an inline status line (`np-msg`:
|
|
551
|
+
Muted, Error, or success-green), and the one **primary** create button
|
|
552
|
+
(Dispatch Blue, `#f4f6fb` label).
|
|
553
|
+
|
|
554
|
+
### Whole-board empty state (first run)
|
|
555
|
+
|
|
556
|
+
When the entire tracker holds zero issues, three terse lines sit on the bench
|
|
557
|
+
above the (empty) columns — no hero, no modal, no illustration:
|
|
558
|
+
- a Base lead, `no issues yet — dispatch your first`,
|
|
559
|
+
- a Muted how-to, `press + on a column, or add issues/<FirstActive>/<id>.md`,
|
|
560
|
+
with the `+` shown as a small keycap (a `1px` Firm-Rule box),
|
|
561
|
+
- a Dim note, `agents pick up <FirstActive> on the next poll`.
|
|
562
|
+
|
|
563
|
+
It teaches the two first-run affordances once and disappears the instant any
|
|
564
|
+
issue exists.
|
|
305
565
|
|
|
306
566
|
### Buttons
|
|
307
567
|
|
|
308
|
-
|
|
568
|
+
Radius `4px` (`3px` for ghost-sm), body type, no shadow. Hover changes
|
|
569
|
+
border-colour; focus draws a Dispatch Blue outline ring.
|
|
309
570
|
|
|
310
|
-
- **Primary** (
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
`
|
|
317
|
-
console-style "refresh now" actions only.
|
|
318
|
-
|
|
319
|
-
Hover and focus states are presently unstyled. The "crisp and exact"
|
|
320
|
-
philosophy permits adding a `1px` Dispatch Blue focus-visible ring on both
|
|
321
|
-
variants in a future pass; do not add hover lift or color shifts that imply
|
|
322
|
-
elevation.
|
|
571
|
+
- **Primary** (create, in the panel): Dispatch Blue background, `#f4f6fb` label,
|
|
572
|
+
no border. The one primary verb.
|
|
573
|
+
- **Ghost** (send reply): Chip background, Base text, `1px` Firm Rule border.
|
|
574
|
+
- **Ghost-sm** (triage approve / discard): transparent, Muted text, `1px` Firm
|
|
575
|
+
Rule border, smaller; the `discard` variant hovers to the Error colour.
|
|
576
|
+
- **Icon buttons** (refresh, column `+`, panel close): square (22–28px),
|
|
577
|
+
Chip-or-transparent, `1px` Firm Rule border, a single glyph.
|
|
323
578
|
|
|
324
579
|
### Inputs
|
|
325
580
|
|
|
326
|
-
`<input>`, `<select>`, `<textarea>` share one style
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
- **Border** `1px solid` Firm Rule (`#2a2e36`).
|
|
331
|
-
- **Text** Strong (`#e6ebf2`) so what is being typed sits one step above
|
|
332
|
-
surrounding body text.
|
|
333
|
-
- **Radius** `4px`.
|
|
334
|
-
- **Padding** `0.4rem 0.6rem`.
|
|
335
|
-
- **Width** `100%` of the form grid's value column.
|
|
336
|
-
- **Textareas** add `min-height: 80px; resize: vertical`.
|
|
337
|
-
|
|
338
|
-
Focus state is currently the browser default. Adding a `1px` Dispatch Blue
|
|
339
|
-
focus-visible outline is the obvious next refinement, consistent with the
|
|
340
|
-
philosophy.
|
|
341
|
-
|
|
342
|
-
### Card (the create-issue form)
|
|
343
|
-
|
|
344
|
-
The only card-shaped surface in the system. There is exactly one.
|
|
581
|
+
`<input>`, `<select>`, `<textarea>` share one style: **Inset** background (one
|
|
582
|
+
step deeper than the panel, so they read as sunken slots), `1px` Firm Rule
|
|
583
|
+
border, **Strong** text, `4px` radius. Focus replaces the border with Dispatch
|
|
584
|
+
Blue and draws a `1px` Dispatch Blue outline. Textareas resize vertically only.
|
|
345
585
|
|
|
346
|
-
|
|
347
|
-
- **Radius** `8px` (the only place 8px appears).
|
|
348
|
-
- **Padding** `1rem`.
|
|
349
|
-
- **No border, no shadow.**
|
|
350
|
-
- **Layout** `display: grid; grid-template-columns: max-content 1fr; gap:
|
|
351
|
-
0.5rem 1rem; align-items: center;` so labels (max-content) align with
|
|
352
|
-
their inputs (1fr) on the same row.
|
|
586
|
+
### Totals footer
|
|
353
587
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
it to 4px or to a `1px` Firm Rule border with no radius. Either move would
|
|
357
|
-
push the system further toward CLI-in-HTML.
|
|
358
|
-
|
|
359
|
-
### Pills (status chips)
|
|
360
|
-
|
|
361
|
-
`display: inline-block`, `padding: 0.1rem 0.5rem`, `border-radius: 999px`,
|
|
362
|
-
`font-size: 0.85em`. Three semantic instances, each a paired bg + fg:
|
|
363
|
-
|
|
364
|
-
- **Running** — bg `#1f3a26`, fg `#58d68d`. Live session.
|
|
365
|
-
- **Retrying** — bg `#3a2f1f`, fg `#f0c060`. Backoff queue.
|
|
366
|
-
- **Idle** — bg `#20242c`, fg `#9aa4b2`. On disk, not active.
|
|
367
|
-
|
|
368
|
-
No fourth pill exists. If a new orchestrator state appears, the new pill
|
|
369
|
-
gets a named bg + fg pair entered into the colors block and a row added in
|
|
370
|
-
this section. Do not reuse an existing pair for a new meaning.
|
|
371
|
-
|
|
372
|
-
### Tables
|
|
373
|
-
|
|
374
|
-
The dominant content shape. Three tables on the page: Active sessions, Retry
|
|
375
|
-
queue, All known issues.
|
|
376
|
-
|
|
377
|
-
- `width: 100%`, `border-collapse: collapse`.
|
|
378
|
-
- `th, td` padding `0.4rem 0.6rem`, `border-bottom: 1px solid` Soft Rule
|
|
379
|
-
(`#1c2029`).
|
|
380
|
-
- `th` text-align left, color Muted, weight 500.
|
|
381
|
-
- Every cell inherits `font-variant-numeric: tabular-nums`.
|
|
382
|
-
- No striping. The Soft Rule divider is enough.
|
|
383
|
-
|
|
384
|
-
### Inline status messages
|
|
385
|
-
|
|
386
|
-
The form's `.msg` line is `grid-column: 1 / span 2; min-height: 1.2em`. It
|
|
387
|
-
holds three states: neutral (color Muted), error (`#ff7676`), ok (`#58d68d`).
|
|
388
|
-
Always inline, never a toast, never a modal.
|
|
588
|
+
A Dim, tabular `X in · Y out · Z total · runtime` strip pinned to the bottom,
|
|
589
|
+
hidden entirely when there's nothing to total. Numbers only, no chrome.
|
|
389
590
|
|
|
390
591
|
### Named Rules
|
|
391
592
|
|
|
392
|
-
**The One-Card Rule.** The
|
|
393
|
-
surface.
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
593
|
+
**The One-Card Rule.** The slide-in new-issue panel is the only card-shaped
|
|
594
|
+
surface in the system. Everything else stands on the bench directly: columns are
|
|
595
|
+
unbordered, rows are flat dividers, the health line and ticker are bare strips.
|
|
596
|
+
Resist wrapping rows, columns, or stats in cards. (Originally the create-issue
|
|
597
|
+
*form card* was the one card; it became this slide-in panel, but the "exactly
|
|
598
|
+
one card" discipline holds.)
|
|
599
|
+
|
|
600
|
+
**The Non-Modal Composer Rule** (replaces the blanket "no modals / inline-first"
|
|
601
|
+
absolute). New-issue composition is a slide-in `aside`, not a modal: no backdrop
|
|
602
|
+
blocks the board, no scroll lock, Esc closes, and the board keeps polling and
|
|
603
|
+
responding behind it. The brand's anti-modal intent — never a modal-on-modal
|
|
604
|
+
ITSM flow, never a blocking confirmation dialog — is preserved; a non-blocking
|
|
605
|
+
edge panel is the sanctioned exception, and it is the *only* one. Operator
|
|
606
|
+
feedback (steering replies, triage, errors) still lands **inline** on the row or
|
|
607
|
+
in the panel's own status line, never in a toast.
|
|
608
|
+
|
|
609
|
+
**The Sunken-Input Rule.** Inputs are visually deeper than the surface they sit
|
|
610
|
+
on (Inset against the Raised Panel). They must not appear to float; any new
|
|
611
|
+
input style follows this depth rule.
|
|
403
612
|
|
|
404
613
|
## 6. Do's and Don'ts
|
|
405
614
|
|
|
406
615
|
### Do:
|
|
407
|
-
- **Do** stack neutrals in four steps (Inset → Bench → Raised Panel → Chip)
|
|
408
|
-
|
|
409
|
-
- **Do** keep Dispatch Blue (`#2a6df4`)
|
|
410
|
-
primary verb. Everywhere else, status
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
- **Do**
|
|
416
|
-
|
|
417
|
-
- **Do**
|
|
418
|
-
|
|
419
|
-
- **Do**
|
|
420
|
-
|
|
616
|
+
- **Do** stack neutrals in four steps (Inset → Bench → Raised Panel → Chip) to
|
|
617
|
+
convey depth. No shadows.
|
|
618
|
+
- **Do** keep Dispatch Blue (`#2a6df4`) as the single saturated brand hue: the
|
|
619
|
+
primary verb and the focus ring. Everywhere else, status pairs and text weight
|
|
620
|
+
do the work.
|
|
621
|
+
- **Do** give every status colour a named bg + fg pair tied to a real
|
|
622
|
+
orchestrator state (running, retrying, idle, await, done). A new state earns a
|
|
623
|
+
new pair; colours are never reused for a second meaning.
|
|
624
|
+
- **Do** apply `font-variant-numeric: tabular-nums` to every element holding a
|
|
625
|
+
number — token counts, attempts, timestamps, counts. They must align.
|
|
626
|
+
- **Do** use the monospace stack for literal strings (identifiers, paths, the
|
|
627
|
+
health line, code) and the sans stack for prose.
|
|
628
|
+
- **Do** put feedback inline — on the awaiting row, or in the panel's `np-msg`
|
|
629
|
+
slot. Errors and successes never become toasts.
|
|
630
|
+
- **Do** keep the type scale tight: detail h1 1.3rem, h2 1rem (same as body),
|
|
631
|
+
body 14px, pill 0.78em. Hierarchy through rules and weight, not scale.
|
|
632
|
+
- **Do** let the board omit terminal columns and tint awaiting/stuck rows — show
|
|
633
|
+
real state, surface what needs eyes, and let finished work fall away.
|
|
421
634
|
|
|
422
635
|
### Don't:
|
|
423
|
-
- **Don't** add a
|
|
424
|
-
|
|
425
|
-
|
|
636
|
+
- **Don't** add a second saturated accent. There is one brand hue (Dispatch
|
|
637
|
+
Blue); status pairs carry the only other saturation, and each encodes a named
|
|
638
|
+
state.
|
|
639
|
+
- **Don't** invent a status colour for taste, or reuse an existing pair for a
|
|
640
|
+
new meaning. Name the state, add a bg + fg pair, then use it.
|
|
426
641
|
- **Don't** ship a sidebar nav, breadcrumb trail, or a "Welcome back" hero.
|
|
427
|
-
PRODUCT.md flags this as generic-SaaS-dashboard chrome; the workshop has
|
|
428
|
-
|
|
642
|
+
PRODUCT.md flags this as generic-SaaS-dashboard chrome; the workshop has one
|
|
643
|
+
room. (The detail page's `symphony · workflow · id` crumb is navigation back
|
|
644
|
+
to the board, not a nav chrome shelf.)
|
|
429
645
|
- **Don't** use big-number-with-tiny-label metric tiles. The hero-metric
|
|
430
|
-
template is explicitly prohibited
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
AI
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
- **Don't** introduce `box-shadow`. Depth is tonal
|
|
438
|
-
shadow, add a fifth neutral step instead.
|
|
439
|
-
- **Don't** use `border-left`
|
|
440
|
-
rows, cards, or alerts (
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
- **Don't**
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
646
|
+
template is explicitly prohibited; the totals footer is a plain text strip,
|
|
647
|
+
not a tile.
|
|
648
|
+
- **Don't** add violet gradients, glassmorphic blur, sparkle / star icons, or
|
|
649
|
+
any "AI inside" iconography. smol-symphony runs AI agents but is not an AI
|
|
650
|
+
product. (PRODUCT.md anti-reference, verbatim.)
|
|
651
|
+
- **Don't** add status pills whose colours don't map to distinct orchestrator
|
|
652
|
+
state. Five pairs, five real states. Status theater is banned.
|
|
653
|
+
- **Don't** introduce `box-shadow`. Depth is tonal, plus the one panel that
|
|
654
|
+
slides in. If you reach for a shadow, add a fifth neutral step instead.
|
|
655
|
+
- **Don't** use a `border-left` wider than `1px` as a *saturated status stripe*
|
|
656
|
+
on rows, cards, or alerts (the Linear/ITSM stripe pattern — impeccable's
|
|
657
|
+
absolute ban). Row status is a faint full-row tint, not a stripe. (Rendered
|
|
658
|
+
Markdown blockquotes use a 2px **neutral** Firm-Rule bar; that's typographic
|
|
659
|
+
quoting, not a status stripe.)
|
|
660
|
+
- **Don't** use `#000` or `#fff` as text or background. The create button's
|
|
661
|
+
label is `#f4f6fb`, tinted toward the brand hue.
|
|
662
|
+
- **Don't** introduce a web font. Both native stacks
|
|
663
|
+
(`ui-sans-serif, system-ui, sans-serif` and
|
|
664
|
+
`ui-monospace, …, monospace`) are non-negotiable unless an intentional
|
|
665
|
+
editorial change is being made.
|
|
666
|
+
- **Don't** add a modal. The non-modal slide-in composer is the one sanctioned
|
|
667
|
+
edge panel; everything else is inline. No blocking dialogs, no modal-on-modal
|
|
668
|
+
ITSM flows, no scroll-locking backdrops.
|
|
669
|
+
- **Don't** add motion that doesn't encode state. The panel slide, the ticker
|
|
670
|
+
collapse, hover affordances, and the 2s poll all mean something; decorative
|
|
671
|
+
animation does not belong.
|
|
672
|
+
- **Don't** wrap content in a generic container. The slide-in panel is the one
|
|
673
|
+
card. Columns, rows, the health line, and the totals strip stand on the bench
|
|
674
|
+
directly.
|