Re-skin the keyless DevTools replay SPA onto the apps/run design system's
"Reactor monitor" machine surface (DESIGN.md §1/§4 name it as a sanctioned dark
machine surface): a flat charcoal ground, single-voice self-hosted JetBrains
Mono, gold as the one brand accent, 1px hairlines + small radii + one soft
shadow framing, three-dot window chrome, and always-labeled status.
- Machine palette (variable NAMES preserved so app.js + every selector keep
working; only values changed): --bg #1a1c22 flat (radial gradient removed,
per "no gradients"), machine-bar chrome bars, machine-fg/dim text, white-alpha
hairlines.
- Disposition + wake-cause hues mapped to the machine signal palette, kept
distinct AND labeled (never colour-only): render = machine-ok green,
active/lit path + per-facet edge-light + cost-fresh + external-wake =
machine-gold, memo-skip = machine-dim grey, fail = machine red (deepened for
AA on charcoal), self-tick = labeled violet.
- Self-host JetBrains Mono (400/500/700 woff2, latin subset, ~65KB) under
src/public/fonts so the machine surface is the real face, offline + keyless.
- Fix copy:public to recurse (fs.cpSync) so the new fonts/ subdir builds and
ships (the old non-recursive copy threw ENOTSUP on a subdir).
Scope: CSS + index.html + fonts only. No app.js logic changes; all class names
and animation hooks preserved, so replay/scrub/animation behaviour is identical.
Verified: pnpm build + typecheck pass and the built server serves /app.css and
/fonts/*.woff2 (200).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reactor was hard-wired to OpenRouter on the CLI (only OPENROUTER_API_KEY was
ever read), stranding users holding OpenAI / Anthropic / Google keys. The SDK
already supported a scoped provider; this makes it real and elegant at the CLI.
reactor-cli (0.2.0 -> 0.2.1):
- reactor.yml model.provider now switches the live provider; built-ins
openrouter|openai|anthropic|google resolve their endpoint + key env, and any
OpenAI-compatible vendor works via model.base_url + model.api_key_env.
- A keyless ProviderPlan resolver + a model-bearing OpenAIProvider factory
(reached only past the dynamic-import offline boundary), threaded into compile
sessions and the run/serve render (incl. the configured render_model, which
the run phase previously ignored).
- doctor reports the configured provider's key (not only OPENROUTER_API_KEY) and
doctor --live smokes the configured endpoint; a missing key fails non-zero with
the exact env var (never misdirects to OpenRouter, never exits 0).
- Tests: ProviderPlan resolver + a hermetic missing-key compile.
reactor (0.3.0 -> 0.3.1):
- Receipt Cost now reports the real provider + model instead of a hardcoded
openrouter / gemini-3.5-flash (cost-only labels, never fingerprinted). New
optional RunProjectRender.providerLabel + CostLabels.
- Tests: cost-labels + a key-gated bring-your-own-provider live smoke.
Build: each reactor package cleans its output dir before tsc, so local
incremental builds cannot accumulate orphaned dist test artifacts.
Known limitation: Anthropic's direct OpenAI-compat endpoint rejects our
structured-output response_format unless strict:true; route Anthropic models
through OpenRouter today (documented).
npm --provenance validates package.json repository.url against the GitHub repo
from the OIDC attestation; these two lacked the field (reactor had it), so
publish failed E422 after reactor@0.3.0 already published. Additive metadata only.
Ships @openprose/reactor 0.3.0, @openprose/reactor-cli 0.2.0, @openprose/reactor-devtools 0.2.0: the Reactor harness (compile-once-intelligent then dumb reconciler, content-addressed receipts, cost scales with surprise) with the distilled ideal public API — curated front door, full @openai/agents passthrough, one typed handle, one Substrate, unified observe, branded ids, and additive forward seams for the fixpoint.