Development
This repository uses Bun 1.4.2 everywhere. .bun-version is the canonical pin consumed by local version managers and every GitHub Actions workflow; bun run version:check rejects drift in the runtime, package metadata, Docker base image, type definitions, CI, or publish job.
New here? Start with the Quickstart for a guided first run, then use the deployment overview to choose how the dashboard connects to bunqueue. Control-agent environment variables are documented under Control agent configuration. This page is the day-to-day workflow: run, gate, and how to add a page additively.
Run
bun install
bun start # agent + dashboard together (Ctrl-C stops both)bun start (scripts/dev.ts) is the one-command path. Prefer separate processes? The granular commands still work:
bun run agent # control agent (start/stop/restart) → 127.0.0.1:6800
bun dev # dashboard → http://localhost:5273Point it at a server via Settings (or VITE_BUNQUEUE_URL). In dev, /api/* is proxied to http://localhost:6790.
Quality gate
bun run qualityThis is the exact blocking gate run by the CI workflow on every push and pull request. Release, Pages, and Docker run the same command before publishing. It executes, in order:
bun run version:check: enforce the Bun version pin.bun run architecture: enforce the TypeScript source file size budget.bun run check: Oxlint plus an Oxfmt formatting check (bun run check:fixapplies safe lint fixes, then formats files).bun run build: strict typechecks forsrc/,agent/,scripts/, examples and browser fixtures, then the production Vite build.bun run size: initial-load and total JavaScript bundle budgets.bun run docs:build: the VitePress production build, including dead-link checks.bun run test:coverage: the complete Bun test suite plus aggregate coverage floors.bun run test:e2e: disposable Bunqueue 2.9.4 TLS, SQLite migration, Flow/Workflow/Queue contracts plus three authenticated brokers and agents sharing PostgreSQL 18.6 (Docker required).bun run test:package: packs, installs, starts, and probes the published binary from a clean temporary consumer.bun run audit:high: a blocking dependency audit for HIGH and CRITICAL advisories.
CI also runs bun run test:e2e:browser as a separate blocking matrix on Chromium, Firefox, and WebKit. The suite uses the production bundle, a non-root BASE_PATH, an authenticated disposable Bunqueue 2.9.4 process, and a temporary database. It verifies the token gate, full sidebar navigation, SSE reconnection after an actual upstream restart, confirmed Cron mutations, and automated WCAG A/AA rules. Operational browser tests also submit and inspect jobs, import bulk jobs, reconcile a 40-job benchmark, execute SQLite queries, operate webhook entries, inspect DLQ failures, receive live logs and evaluate alert rules. For a local first run:
bun run test:e2e:browser:install
bun run test:e2e:browserFor multi-node UI verification, also run bun run test:e2e:browser:postgres-fleet (Docker and Chromium required). This command is separate from quality and the regular browser matrix. The Chromium CI job also runs bun run test:e2e:browser:managed for managed lifecycle, Workflow, Flow, MCP, local S3 and scripted Copilot transport/tool checks. See Testing & verification for the coverage of each section and external service prerequisites. bun run test:e2e:docs separately checks clean documentation URLs on desktop/mobile and search/navigation after the VitePress build.
The audit has no ID-specific exceptions: any HIGH or CRITICAL advisory fails the gate. Transitive fixes are pinned through overrides in package.json.
Notes:
.oxlintrc.jsonand.oxfmtrc.jsonare the committed root configurations for Oxlint and Oxfmt. Oxlint runs the JavaScript, TypeScript, Oxc, Unicorn, React, and JSX accessibility plugins with the project's curated severities;oxlint-tsgolintprovides the type-aware rules. The lint script also retains Biome's implicit-anydeclaration check, which Oxlint does not yet implement. Oxfmt keeps the established two-space, 100-column, single-quote style and deterministic imports.src/index.css(Tailwind v4 at-rules),agent/, andscripts/are excluded from formatting and linting. They are not skipped by typechecking:tsconfig.jsoncoverssrc/, whiletsconfig.agent.jsoncovers both Bun runtime directories (except the generatedscripts/embedded.gen.ts).bunfig.tomlpreloadstest/setup.ts(alocalStorageshim) so store imports work underbun test.
Adding a page (additive)
- Create
src/pages/control/MyPage.tsx(a new file). Usebqfor data, theui/*kit for layout (see components.md),usePolledDatafor polling. - Wire it in
src/App.tsx(a new<Route>). - Add a nav item in
src/components/layout/Sidebar.tsx'sNAVarray (reuse an existing icon or add one toui/icons). - If the page shows a job/queue state, drive its state-dependent buttons off
lib/jobActions.ts::actionGatesrather than re-deriving which actions are dashboard-authorized, see api-mapping.md. Upstream endpoint acceptance alone is not authorization: the shared gates intentionally keep DLQ retry and completed-job requeue false.
Both steps 2 and 3 are required: a route with no nav entry (or vice versa) is a dead end. The route-completeness tests compare the registered routes, sidebar destinations, and page-title map; do not leave a new page outside that contract.
Do not rewrite existing pages or the api.ts client. Corrected behaviour goes in a new page using bq. If you find a live bug while working nearby, check known-issues.md first, it may already be tracked, and add it there if not, rather than silently patching something out of scope.
Conventions
- Data:
usePolledData(() => bq.x())returns{ data, error, loading, refetching, refetch }. RenderLoadingStateon first load,ErrorStateon failure with data absent, otherwise the content (keep last data while refreshing). - Actions: call
bq.*thenrefetch(); guard destructive ops withwindow.confirm; surface failures inline. - Formatting: use
lib/format(formatNumberuses.thousands; times are relative; durations fromstartedAt/completedAt). - Styling: Tailwind tokens (
bg-surface,text-muted,border-line,text-accent),.tnumfor numbers, mono for IDs. - Keep files focused; prefer new small components over growing a page past ~300 lines.
Tests
Use bun test for a fast local iteration and bun run test:coverage for the same suite with the CI coverage floor. Tests live under test/ and cover pure logic, stores and clients, component regressions, SSE parsing, and control-agent behaviour. Add focused regression coverage there for every bug fix or new testable behaviour.
Dependency patch
ai is pinned to 7.0.14 because patches/ai@7.0.14.patch handles a rejected browser telemetry completion promise on cancellation. Keep patches/ alongside package.json and bun.lock before running a frozen install, including in Docker. When upgrading the SDK, verify the managed Copilot Stop regression against the production browser bundle before removing or refreshing the patch.