Skip to content

Latest commit

 

History

History
235 lines (200 loc) · 11.2 KB

File metadata and controls

235 lines (200 loc) · 11.2 KB

Bobsled

Bobsled is a local-first, agent-agnostic control harness for an AI-native software delivery lifecycle. Claude Code, OpenAI Codex, and GitHub Copilot are replaceable executors. Bobsled owns the workflow state, artifact chain, approval records, evidence, and runner/model routing.

One constitution, three executors.

The product contract is NORTHSTAR.md. The live delivery record and remaining work are in PLAN.md.

Run it

Requirements:

  • Node.js 22.13 or newer
  • Git
  • GitHub CLI (gh) for pull-request creation and merge reconciliation
  • Any or all of claude, codex, and copilot on PATH
  • Existing runner authentication when performing an opt-in live invocation
npm install
npm run dev

Open http://localhost:3000. The web app proxies typed /api operations to a control process bound only to 127.0.0.1:4242.

npm run dev starts both processes. For separate logs, use npm run dev:web and npm run dev:control. Those commands are development-only: dev:control uses hot reload, so its captured boot commit proves only the commit from which that control process most recently started, not dependency or in-memory module identity across reloads. A governed local deployment must start the authoritative process with npm run control (and restart it after upgrading), not npm run dev:control.

Run the complete verification suite with:

npm run check
npm audit --omit=dev

What is implemented

  • Responsive Mission Control with live changes, runner health, approval inbox, task routing, and a truthful control inventory.
  • Addressable, read-only change detail with the complete recorded artifact chain, transition timeline, review disposition, approval bindings, evidence, provenance, full digests, and source commits. Change cards and attention rows link to the inspection surface; it contains no decision or execution action.
  • Governed artifact and evidence-log viewing by recorded UUID only. The server accepts no path, verifies containment and regular-file identity, checks raw artifact bytes against the recorded digest, refuses binary or invalid UTF-8, applies complete-value secret and host-path redaction, and then enforces inline, download, and line bounds.
  • Inert Markdown, diff, and evidence rendering. Recorded links, images, HTML, scripts, styles, handlers, frames, and remote resources remain text rather than browser authority; eligible downloads are fixed text/plain attachments with restrictive response headers.
  • Provider-neutral types and validation for projects, changes, artifacts, approvals, routes, transitions, and invocations.
  • Append-only hash-chained JSONL ledger, fail-closed semantic replay, a single-writer lock, atomic snapshots, SSE updates, and interrupted-run reconciliation.
  • Artifact digests that are reread from disk before guarded transitions; mutation invalidates the usable approval.
  • Server-owned lifecycle guards. Agent output has no transition authority.
  • Claude, Codex, and Copilot capability probes and fixed read-only command adapters with timeouts, bounded retained output, normalized/raw events, provider-scoped environments, authentication-aware Claude readiness, and resolved-model capture when reported.
  • Ledger-backed role routing by runner, model, and capability profile.
  • Web-driven artifact production for intent, specification, plan, and review: the chosen runner stays read-only, Bobsled writes the returned Markdown, commits that artifact, records its digest/evidence/model identity, and stops at the human gate.
  • Codex build execution in a retained change-specific Git worktree. Bobsled rejects protected paths, validates and commits the diff itself, records the base/head commits and branch, and leaves the primary checkout untouched.
  • Repository-owned verification command vectors executed without a shell in a macOS Seatbelt sandbox. The current diff commit must have passing evidence before independent review can start.
  • Independent review admission: the reviewer must use a different runner from the diff author, and higher-risk changes must also resolve to a different model family.
  • Machine-validated review dispositions. A blocking review returns the change to a bounded verification/rework loop; review prose alone cannot expose the pull-request approval gate.
  • Target-aware merge-candidate verification. Before the PR gate opens, Bobsled assembles the current target head plus the governed branch in a detached worktree and binds a fresh configured-check receipt to all three commits.
  • Explicit pull-request creation after digest-bound human approval. Bobsled pushes only the retained governed branch to an existing GitHub origin; it never creates or guesses a repository.
  • Read-only pull-request reconciliation through one fixed gh pr view broker action. Every definitive, negative, or indeterminate observation is retained as append-only evidence; only a fresh, identity-matched merge opens the human release-approval gate.
  • Deterministic local deployment verification. Monitoring opens only when the clean registered default-branch checkout contains GitHub's reported merge commit and its HEAD matches the commit captured when the control process started.
  • Web registration for additional local Git repositories.
  • A real dogfood review recorded under .bobsled/changes/bootstrap-control-plane/review.md.

Deliberately not implemented yet

Bobsled does not expose a browser shell or a general-purpose command endpoint. Claude and Copilot mutating adapters, authenticated human roles, live process cancellation, streamed run detail, non-macOS verification sandboxes, merge automation, and general deployment orchestration remain sequenced in PLAN.md.

The local API's fixed CLI flags are a useful permission profile, not an independent OS security boundary. The UI labels this control advisory.

Change detail is not a repository browser. Only artifact records already in a change and retained logs already named by its evidence receipts are addressable. Missing, unreadable, oversized, binary, invalid-UTF-8, and digest-mismatched records remain visible as explicit refusal states. Binary and digest-mismatched bytes cannot be downloaded through Bobsled. Evidence outputDigest covers receipt output and is not represented as a digest of the retained log; a successful log read reports a separate observed digest. Displayed or downloaded redacted text will not re-hash to an artifact's raw recorded digest because integrity is evaluated before transformation.

State and recovery

Authoritative local runtime data lives in .bobsled/runtime/ and is ignored by Git:

.bobsled/runtime/
  events.jsonl      append-only hash chain
  snapshot.json     rebuildable materialized state
  writer.lock       live control-plane ownership
  runs/             bounded raw and normalized invocation records
  worktrees/         retained isolated build checkouts

Startup verifies envelope integrity and every event payload's shape, governed values, historical references, and ownership before publishing reconstructed state or performing interrupted-run recovery. Any failure prevents the API from binding, leaves the ledger and prior snapshot untouched, and releases the writer lock.

Run the same checks without acquiring the writer lock or writing runtime data:

npm run ledger:verify

The command reports the last validated sequence and bounded event identity. It does not repair, truncate, skip, or accept a valid prefix. For explicit local diagnosis, BOBSLED_REPLAY_EXPLAIN=1 npm run ledger:verify may additionally print the offending field value; treat that output as potentially sensitive. Before upgrading, stop Bobsled, retain an operator-managed byte-for-byte backup, and run the diagnostic against the configured ledger. Do not hand-edit the ledger.

Configuration

Routes begin in .bobsled/config.yaml. A route consists of a role, runner, requested model, and capability profile. Environment placeholders such as ${CODEX_BUILD_MODEL} are resolved by the control process. Missing values are shown as unconfigured rather than silently replaced. Changes made in the web UI are durable ledger overrides for the running Bobsled workspace.

Verification commands are also repository-owned configuration. They are arrays of executable arguments, not browser-supplied shell strings. A newly registered project may complete read-only artifact stages immediately, but builds fail closed until its project ID has at least one verification command in .bobsled/config.yaml and the local control process is restarted.

The merge-read broker may use GitHub CLI's existing stored authentication. To provide a dedicated environment credential, set BOBSLED_GITHUB_TOKEN only on the control process. Bobsled maps it to GH_TOKEN only for the fixed broker child, excludes inherited GitHub token variables, and redacts the resolved credential plus recognized GitHub token formats before retaining or digesting output. Never put this value in repository files.

Build to pull request

At Building, the UI can run the configured isolated-worktree route. A successful admitted diff and configured verification advance the change to Reviewing. A separate read-only runner writes a review with an explicit APPROVE or REWORK disposition. Blocking findings return to author rework; only a no-blocker disposition exposes human approval of the exact diff digest. Before that gate opens, Bobsled verifies a detached merge candidate containing the current target head and governed branch head. If the target moves, approval and PR creation fail closed until the candidate is refreshed. After approval, Open approved pull request pushes the retained branch and calls GitHub CLI. If origin is missing or is not GitHub, Bobsled retains the local branch and reports the blocker without performing an external write.

After GitHub reports that exact pull request merged, Confirm merge records a fresh read-only observation and opens a separate release-approval gate. Merge confirmation is not release approval. Once the named release manager approves the current diff, upgrade the clean default-branch checkout, restart the control process with npm run control, and use Verify local deployment.

The deployment receipt proves Git commit identity, branch, ancestry, and a clean tree. It does not prove that dependencies were reinstalled or otherwise match the commit. The broker's environment excludes its dedicated token from runners, but normal GitHub CLI credential files remain readable to a runner until filesystem-level isolation exists. A squash or rebase merge is bound to the approved pull-request head and GitHub's reported merge commit; Bobsled does not independently re-derive content equivalence for those merge strategies.

Architecture

Browser (localhost:3000)
       |
typed API + SSE
       |
Local control plane (127.0.0.1:4242)
  |-- workflow guards and approval service
  |-- artifact digests and evidence ledger
  |-- task / runner / model router
  |-- read-only and isolated-worktree process supervisor
  |-- diff admission and sandboxed verification
  |
  +-- Claude adapter
  +-- Codex adapter
  +-- Copilot adapter

The supported application is local-only. The browser UI runs on localhost:3000, and the authoritative control process binds only to 127.0.0.1:4242.