feat: migrate dashboard to React + Zustand + Tailwind - #3
Merged
Conversation
- Replace vanilla TS DOM manipulation with React components - Add Zustand store for theme, session, and status state - Add Tailwind CSS via @tailwindcss/vite plugin - Extract terminal logic into useTerminal hook - Component structure: App, Header, TerminalView - VSCode-style scrollbar (visible on hover, proportional thumb) - All existing functionality preserved (themes, keybindings, resize) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nox-0x
approved these changes
Mar 7, 2026
nox-0x
left a comment
Collaborator
There was a problem hiding this comment.
Clean React migration. Store structure is solid, theme cycling works correctly, Vite proxy config is unchanged. LGTM.
- Remove StrictMode to prevent xterm.js/WebGL double-mount issues in dev - Add spawn guard on New Session button to prevent racing sessions - Remove unused API_URL constant and observerRef - Simplify fetch error handling with .catch(() => null) pattern - Condense verbose callbacks to concise arrow expressions - Move container.replaceChildren() into effect cleanup - Extract isThemeName type guard for proper type narrowing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nox-0x
approved these changes
Mar 7, 2026
nox-0x
left a comment
Collaborator
There was a problem hiding this comment.
React migration looks solid. Clean component decomposition, proper cleanup in useTerminal (ResizeObserver + WebSocket + terminal.dispose), Zustand store handles localStorage persistence correctly. LGTM 🚀
aterrylu
added a commit
that referenced
this pull request
May 13, 2026
…ss semantics CI failure: biome's organizeImports rule flagged the parseCliArgs call sandwiched between import groups. Reviewer @nox-0x flagged the same issue separately. Moved all imports to the top, then the parseCliArgs + --help short-circuit, then the rest of the imperative startup work. Also added a comment clarifying that --help only avoids imperative work, not import-time side effects (since ESM hoists all imports regardless). Review observation #3 (readiness semantics): AUTONOMOS_READY signal means "HTTP listener accepting connections" — NOT "agents fully hydrated." Gateway init, resumeActiveAgents, and scheduler startup run in the same tick but may finish slightly later. Documented this in: - embedded-mode.ts (next to the signal emitter) - phase-1b-sketch.md (in the integration contract section) So Phase 1B's Electron shell can load the webview as soon as the signal fires, with the understanding that "fully populated UI" may lag by ~ms. Verified: - npx biome check packages/ → clean (only pre-existing warnings unrelated to 1A.1) - ./scripts/test-1a1-isolated.sh → all checks still pass Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aterrylu
added a commit
that referenced
this pull request
May 13, 2026
* feat(server): Phase 1A.1 — bundleable server foundation for desktop app Adds the runtime contract + build pipeline that Phase 1B's Electron desktop app will use to spawn the autonomos-server as a child process. Purely additive — the existing make dev / make prod / pm2 paths continue to work unchanged. What lands: - packages/server/src/cli-args.ts: --port and --embedded argv parser, --help - packages/server/src/embedded-mode.ts: localhost-only bind + AUTONOMOS_READY stdout signal for parent-process discovery - packages/server/src/index.ts: wires both, also fixes a latent fragility where existsSync(dashboardDist) returned true on a tsc-only artifact dir (now checks for index.html explicitly, prefers _embedded_dashboard over fallback path) - packages/server/build/embed-dashboard.ts: copies dashboard/dist into the server tree so the bundler sees it - packages/server/build/build-binary.ts: orchestrates bun build --target=node, copies embedded dashboard next to bundled JS for runtime resolution - scripts/test-1a1-isolated.sh: full isolated smoke test (separate config dir, dedicated port, never touches ~/.autonomos/) - docs/research/: consolidated design notes + Phase 1A.1 proposal + Phase 1B/1C sketches capturing the full plan Build deviation from original proposal: bun build --compile is blocked by a hard ABI mismatch between Bun 1.3.10 (ABI 137) and node-pty's prebuilt (ABI 141). Both the static-binary path AND --target=bun fail because the Bun runtime can't load node-pty at all. Pivoted to --target=node so the bundle runs under Node, which loads node-pty cleanly. Phase 1B's Electron bundles Node + this bundle. Static-binary aspiration deferred until either Bun's ABI matches or PTY is refactored to Bun's native API. Smoke test results (./scripts/test-1a1-isolated.sh on darwin-arm64): ✓ AUTONOMOS_READY signal received in 2s ✓ /api/host returns 200 ✓ Dashboard / serves embedded HTML ✓ SIGTERM triggers clean shutdown in 2s ✓ ~/.autonomos/ untouched (test ran in isolation) ✓ make dev path still boots cleanly (regression check) Contract Phase 1B will rely on: Spawn: node dist/<platform>/index.js --port=0 --embedded Discovery: parse "AUTONOMOS_READY port=<N>" from child stdout Shutdown: send SIGTERM, child exits within ~2s Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(server): address PR #169 review — group imports, document readiness semantics CI failure: biome's organizeImports rule flagged the parseCliArgs call sandwiched between import groups. Reviewer @nox-0x flagged the same issue separately. Moved all imports to the top, then the parseCliArgs + --help short-circuit, then the rest of the imperative startup work. Also added a comment clarifying that --help only avoids imperative work, not import-time side effects (since ESM hoists all imports regardless). Review observation #3 (readiness semantics): AUTONOMOS_READY signal means "HTTP listener accepting connections" — NOT "agents fully hydrated." Gateway init, resumeActiveAgents, and scheduler startup run in the same tick but may finish slightly later. Documented this in: - embedded-mode.ts (next to the signal emitter) - phase-1b-sketch.md (in the integration contract section) So Phase 1B's Electron shell can load the webview as soon as the signal fires, with the understanding that "fully populated UI" may lag by ~ms. Verified: - npx biome check packages/ → clean (only pre-existing warnings unrelated to 1A.1) - ./scripts/test-1a1-isolated.sh → all checks still pass Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merged
4 tasks
aterrylu
added a commit
that referenced
this pull request
Jun 6, 2026
…LOG (pipeline PR 1/6) (#181) build(release): adopt changesets — automated versioning + single root CHANGELOG PR #1 of the professional release pipeline (approved design, macOS-only desktop). Replaces the manual `sed`-across-5-package.json version bump that caused the 0.0.2-code / v0.0.1-tag drift. ## What this adds - **changesets** (`@changesets/cli` + `@changesets/changelog-github`) with a `fixed` group covering all 5 packages → they always version in lockstep to a single version. Devs declare bumps via `bun run changeset` (a 3-line file per user-facing PR); see `.changeset/README.md`. - **Single root `CHANGELOG.md`** (Keep-a-Changelog), seeded with the hand-written 0.0.1 + 0.0.2 history. From the next release on it's generated automatically. Per-package changelogs are gitignored — `scripts/sync-changelog.ts` promotes each new version's section into the root one after `changeset version`. - **`scripts/release-notes.ts`** extracts a version's CHANGELOG section for the GitHub Release body (wired into release.yml in PR #3). - **`.github/workflows/version.yml`** — maintains the "Version Packages" PR and, when it merges, auto-tags `vX.Y.Z` to trigger the release build. Releasing becomes "merge the Version Packages PR" — no manual version edits, ever. - **`.github/workflows/changeset-check.yml`** — informational PR nudge to include a changeset (never blocks; trivial PRs use `--empty`). - Marked `cli`/`core`/`dashboard`/`server` **private** — they're internal workspace packages, not npm publishes (prevents accidental publish + clarifies intent to changesets). ## Validated locally (not just claimed) - `bun run version` with a throwaway minor changeset → all 5 packages bumped 0.0.2 → 0.1.0 in lockstep, root CHANGELOG got a dated section, then reverted. - `bun scripts/release-notes.ts 0.0.2` extracts the right section. - `make check`: 353/353 tests pass; `biome check packages/` clean. ## Dormant until PR #3 No changeset is included in this PR on purpose — the version machinery stays dormant (no Version PR / tag) until the new `release.yml` lands in PR #3. The changeset-check will warn on this infra PR; that's expected. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
aterrylu
added a commit
that referenced
this pull request
Jun 6, 2026
Encodes the "run CI locally before push" discipline as enforcement instead of memory — the exact failure mode that caused repeated red-CI pushes. ## Hooks (lefthook) - **pre-commit** — `biome check` (no --write) on staged package files. Fails on lint/format issues rather than silently fixing, mirroring CI. - **commit-msg** — commitlint (Conventional Commits, loose rules). - **pre-push** — the FULL CI gate: `biome check packages/ && make check`. If this passes, the PR's `check` job will. Emergency bypass: `git push --no-verify`. ## commitlint (loose, hygiene not gatekeeping) Since changesets owns versioning, commit messages aren't release-critical — the config is permissive: project commit types incl. repo-specific `init`/`research`, any subject case, no body-line-length policing (our commits carry URLs + code). `prepare` script runs `lefthook install` on `bun install` so hooks activate for everyone automatically. ## Validated locally (real, dogfooded) - commitlint: accepts `feat(app): ...`, rejects `added some stuff`, allows our long-body style. - `lefthook run pre-push`: ran biome + make check → 353/353 tests, 19s. - This very commit + push runs through the new commit-msg + pre-push hooks. Stacked on #181 (changesets). No changeset — infra PR, machinery stays dormant until release.yml lands in PR #3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
aterrylu
added a commit
that referenced
this pull request
Jun 6, 2026
build(release): add lefthook + commitlint git hooks (pipeline PR 2/6) Encodes the "run CI locally before push" discipline as enforcement instead of memory — the exact failure mode that caused repeated red-CI pushes. ## Hooks (lefthook) - **pre-commit** — `biome check` (no --write) on staged package files. Fails on lint/format issues rather than silently fixing, mirroring CI. - **commit-msg** — commitlint (Conventional Commits, loose rules). - **pre-push** — the FULL CI gate: `biome check packages/ && make check`. If this passes, the PR's `check` job will. Emergency bypass: `git push --no-verify`. ## commitlint (loose, hygiene not gatekeeping) Since changesets owns versioning, commit messages aren't release-critical — the config is permissive: project commit types incl. repo-specific `init`/`research`, any subject case, no body-line-length policing (our commits carry URLs + code). `prepare` script runs `lefthook install` on `bun install` so hooks activate for everyone automatically. ## Validated locally (real, dogfooded) - commitlint: accepts `feat(app): ...`, rejects `added some stuff`, allows our long-body style. - `lefthook run pre-push`: ran biome + make check → 353/353 tests, 19s. - This very commit + push runs through the new commit-msg + pre-push hooks. Stacked on #181 (changesets). No changeset — infra PR, machinery stays dormant until release.yml lands in PR #3. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
aterrylu
added a commit
that referenced
this pull request
Jun 6, 2026
The written runbook the pipeline was missing — releasing is no longer tribal knowledge. - docs/RELEASE.md: the full runbook. Mental model (changesets → Version PR → auto-tag → release.yml), day-to-day changeset ritual, how to cut a release, beta/pre-release, rollback, local DMG builds, the secrets table, and troubleshooting. - docs/DECISIONS.md ADR-031: the release-pipeline decision record — context (version drift + hand-built DMG), the 6-PR design, scope decisions (macOS-only desktop, universal2 from day one, changesets over release-please), rationale, alternatives, and implications. ADR-031 is team-lead-owned — drafted here, flagged for review. Numbering note: ADR-030 informally forward-referenced "ADR-031" for unbuilt named-profiles; this ADR claims it for the release pipeline (the real decision), noted in the entry. SLSA provenance (the other half of PR #6) edits release.yml, which lives in the unmerged PR #3 — deferred to a follow-up once #3 lands to avoid a conflict. Docs-only, no version impact (empty changeset). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
aterrylu
added a commit
that referenced
this pull request
Jun 6, 2026
docs(release): add RELEASE.md runbook + ADR-031 (pipeline PR 6/6, docs) The written runbook the pipeline was missing — releasing is no longer tribal knowledge. - docs/RELEASE.md: the full runbook. Mental model (changesets → Version PR → auto-tag → release.yml), day-to-day changeset ritual, how to cut a release, beta/pre-release, rollback, local DMG builds, the secrets table, and troubleshooting. - docs/DECISIONS.md ADR-031: the release-pipeline decision record — context (version drift + hand-built DMG), the 6-PR design, scope decisions (macOS-only desktop, universal2 from day one, changesets over release-please), rationale, alternatives, and implications. ADR-031 is team-lead-owned — drafted here, flagged for review. Numbering note: ADR-030 informally forward-referenced "ADR-031" for unbuilt named-profiles; this ADR claims it for the release pipeline (the real decision), noted in the entry. SLSA provenance (the other half of PR #6) edits release.yml, which lives in the unmerged PR #3 — deferred to a follow-up once #3 lands to avoid a conflict. Docs-only, no version impact (empty changeset). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates the dashboard from vanilla TypeScript DOM manipulation to React + Zustand + Tailwind (ADR-010).
Every comparable product in our research uses React (Zo Computer, Mission Control, LM Studio, YepAnywhere). This migration sets us up for multi-session UI, panels, and richer dashboard features.
Architecture
What changed
useTerminalcustom hookWhat didn't change
Test plan
make checkpasses (lint + typecheck + 18 tests)🤖 Generated with Claude Code