feat!: rebuild Facility around persistent story workspaces - #289
feat!: rebuild Facility around persistent story workspaces#289adrian-lorenzo wants to merge 3 commits into
Conversation
Make stories the durable unit of work, configure all agents through .agents, expose the workflow through MCP and the UI, and run Claude Code or Codex with full workspace and GitHub installation access. BREAKING CHANGE: Facility 0.12 replaces the 0.11 run, receipt, approval, budget, delivery, and separate-preview model with persistent story workspaces and a new database schema.
7eb262a to
181f1f3
Compare
|
Durable workspaces look directionally strong. Before this closes #284, could the PR include a criterion-by-criterion evidence table distinguishing automated CI, completed manual validation, and still-pending gates—especially the 14-day soak and live-engine pilots? I’d also like to understand the threat model for giving GitHub-triggered reviewers and scheduled agents the same maintainer capability as builders when their inputs are explicitly untrusted. |
|
One thing I noticed while reading the 0.12 branch, in case it helps before this lands. The workspace GitHub token is minted for the whole installation, not for the project's repositories.
Consequence: when two projects share an App installation, an agent in project A holds a maintainer-capable token for project B's repositories (and for any other repository the installation covers). That seems at odds with the boundary the epic keeps: #279 says "a request for another tenant, project, installation, or repository is denied", and the new Suggested fix: pass the project's repositories for that installation in the token request ( Happy to open a PR for it if you'd take one. |
Purpose
Facility 0.12 changes the unit of work from a short-lived run to a durable workspace attached to a story. The story, conversation, Git worktree, native Claude Code and Codex sessions, development services, previews, commits, and pull request share one lifecycle.
Compute may sleep or be replaced. The workspace remains until a maintainer explicitly deletes it. Merging or archiving a story does not delete its worktree, local data, conversation, or engine sessions.
Product behavior
.facility.yml. Docker and Docker Compose run inside the workspace without mounting the host Docker socket.Agents as code
.agents/is the source of agent configuration. Kickstart, the API, MCP, the scheduler, and the UI use the same strict parser, normalized representation, and content hash.Kickstart installs six agents:
architectbuilderpr-revieweraddress-reviewci-doctorsecurity-auditEach manifest declares its prompt, engine, model, enabled state, and manual, GitHub, or schedule triggers. Permission, sandbox, tool allowlist, and
max_turnsfields are rejected. Every agent receives the same full workspace access and a short-lived GitHub App installation token with the configured maintainer capability. GitHub and scheduled triggers use the same dispatcher as MCP and the UI.Agent changes made in the UI are proposed on a branch and pull request. Repeated requests are idempotent, later edits advance the open pull request without force-pushing, and stale branches are rejected explicitly.
Interfaces
The control service hosts the MCP endpoint and OAuth flow. The deliberately small initial MCP contract contains 13 tools for discovering projects and agents, starting and continuing stories, inspecting their conversation and workspace state, managing previews and compute, and removing a workspace explicitly.
The Facility UI remains supported. It uses the same application services for project setup, agent configuration, stories, conversations, service status, preview access, archive, restore, attention items, and deletion.
Manual, MCP, UI, GitHub, and scheduled work all enter the same turn dispatcher. A second message is queued behind the active turn and is promoted after success, failure, cancellation, or stale-worker recovery.
Security boundary
This release removes receipts, approval workflows, budget enforcement, delivery brokers, and per-agent permission profiles. Agents are trusted repository maintainers inside an isolated workspace.
Authentication, project membership, tenant isolation, webhook signatures, secret handling, preview authorization, branch protection, and control-plane isolation remain enforced. Credentials are short-lived and injected per turn. Project repositories can request only explicitly configured, project-namespaced environment values; they cannot read arbitrary Facility process environment variables. Preview handoffs are single-use, expire, and are revoked when the workspace is suspended or deleted.
0.12 cutover
The package set and generated SDK are versioned at
0.12.0. The legacy run, receipt, HITL, proposal, budget gateway, watchtower, database-backed agent catalog, sandbox, and separate preview paths no longer ship.0.12 uses a clean database schema. The migration command detects a 0.11
runstable and exits before creating a migration ledger or changing schema objects. The upgrade guide documents backup, export, clean installation, and rollback to an untouched 0.11 database.Persistent storage is an operator concern. Local conformance tests use a deterministic export-and-restore fixture; hosted installations should use the workspace provider's durable volumes, snapshots, and backup facilities.
Local acceptance evidence
pnpm verifypassed after the final changes. It covered linting of 200 files, all 14 typecheck tasks, all eight clean build tasks, isolated database recreation, unit and deterministic integration suites, unused-code detection, pinned-action and Markdown-link guards, and the repository audit policy.facility-runner:dev.DATABASE_URL=postgres://facility:facility@localhost:5461/facility_ws FACILITY_E2E_DOCKER=1 FACILITY_WORKSPACE_TEST_IMAGE=facility-runner:dev pnpm --filter @facility/api test:e2e-workspacepassed: 2 files and 3 tests in 51.13 seconds.facility-ws-*containers or volumes.46ba961: commit and pull-request-title guards, Node 22.13 compatibility (1m40s), release-shaped verification (2m54s), self-hosted image build (10m22s), and Docker-backed workspace E2E (12m23s). All release allocation and publication jobs were skipped.No live repository was mutated during local acceptance testing. The private deployment was not changed. This pull request remains a draft, has not been merged, and no package or container image has been published.
Release gates still open
These checks must be completed before this PR is ready for review or merge:
b8e82829-0940-48fb-9f66-4503906fd3f4.main, so it correctly refuses this draft PR SHA.Reviewer checklist
Related to #272
Related to #273
Related to #274
Related to #275
Related to #276
Related to #277
Related to #278
Related to #279
Related to #280
Related to #281
Related to #282
Related to #283
Related to #284