← All posts

A software factory you run from a phone

The software-factory plugin: a request becomes work a person approves from one card, a contract a headless worker executes in its own checkout, evidence QA checks against the contract, and a release the asker hears about. Three pages, four seats, gates at every handoff. vocion-core#655, #658, #672, #683, #695.

Vocion Team

Status: shipped. The software-factory plugin ships in vocion-core at packages/core/templates/plugins/software-factory/. Its 2.0 rebuild is vocion-core#655 and #658 (merged 2026-09-24); the gates it declares are #672 and #683 (2026-09-24); triage naming the platform piece is #695 (2026-09-25). Live on the instance that runs Vocion for Metacto since the 2026-09-25 pin bump to 3179fafa. Turn it on with:

# workspace.yaml
plugins: [software-factory]

What it is

A request — a bug, a store review, a support email, an incident, an ask typed into chat — becomes one request record in the asker's words. A product manager prepares the commitment: a draft contract, the main risk, the expected result, how it will be checked, and a mockup when the change is something people will see. Then the product owner decides from one card: Approve build, Request changes, or Defer with a reason and a revisit date. Approving freezes the acceptance criteria. Nothing executes on a draft.

The contract — an engineering_task with an objective, the base commit, the paths the worker may touch, the checks that must pass, the acceptance criteria, a risk class — goes to an engineer that runs as an external worker in its own checkout. It pushes a factory/ branch, opens a pull request, attaches the proof. QA reads the contract, the diff and the evidence — never the engineer's conversation — and writes a verdict bound to the commit it read. The engineering owner merges from a card carrying the commit, the verdict, the risk class and the rollback; the card says STALE when the branch has moved. Whatever deployed writes the release; the PM tells the asker on their channel; and after a check window the request gets a result: helped, did not help, or not enough evidence.

That is the loop: asked → decided → planned → building → QA → released, with an answered branch for the things that will not be built and the asker told why.

Three pages

The first version of this plugin had nine pages. On 2026-09-24 the brief was: "I only want to see 3 pages. Products, Work, Releases. The work object should encompass the full loop. I should be able to run a whole software company from my phone." Every page and every element was kept only if a product exec can make a decision or get value from it.

PageThe question it answers
ProductsHow are my products doing? Stage, health, price beside the incumbent, last release, open work — one derived sentence per product.
WorkWhat is running, what is proposed, what just landed — and what is waiting on me? Three tabs; a row is one outcome.
ReleasesWhat reached people, what it carried, what the post-deploy check said, who has been told?

Opening a row on Work opens the work item: the ask, the decision and who made it, the plan, the mockup, the contract, every run with its checks and cost, the pull request, QA's verdict, the release, the after-shot. Every stage that did not happen says so. The page is hidden from the nav because it is the row, not a place.

Factory, Factory log, Performance and Guide are gone. They explained the machine, and the machine can be complicated; the product cannot be. Reporting comes back when use demands it.

Four seats

SeatAgentOwnsNever
PMproduct-manager (lead)triage, in scope or not, the plan, the contract, telling the askermerges, writes code
Designdesignerthe mockup before a decision, the after-shot before a closebuilds, decides
Engtask-engineer (runsOn: external-worker)the change inside allowedPaths, the checks with artifacts, the PRmerges, deploys, touches a credential
QAchange-reviewerthe verdict against the contract and the evidencemerges, sees the engineer's conversation

Each seat has a one-page rubric — the question it is judged by — as a skill in the plugin (#665). Three standing missions: no request waits more than a week, every asker hears back, every criterion is proven or named unproven. Ten automations wake them — a request arrives, a decision lands, the weekday planning pass, a failed check on a factory branch, work finished, and QA's three red-team reads (the proposal at triage, the diff at PR open, the evidence when checks pass).

Gates at the handoffs

The seats' instructions alone would drift. Same day as the rebuild: a PM card that invented an iOS harness for a web app; a contract dispatched without reading the repo; a bug report that filed the wrong request. So the plugin declares handoff gates on its object types:

A write that fails is refused, the record reads Returned to PM with each missing thing named, and nobody is interrupted. The mechanism is core; the plugin only says which fields, on which transition, judged by whose rubric. Quality control at the handoffs, without over-engineering is the full account.

From a phone

The decision card has a minimum — outcome, who asked, recommendation, change, done when, spend range and review minutes, main risk, expected result — so a person can decide it on a phone without opening anything else. "What should I do right now" is answered from the records with links. And since #693 the phone shell acts like an app: no zoom, no sideways scroll, a wide table scrolls inside its own box, the composer sits above the home indicator.

Two people, two decisions: the product owner commits, the engineering owner merges. A routine completion reply can go out under a policy the product owner turns on; a decline or an incident update is a person's every time.

What core had to grow

The plugin is YAML and markdown. What it needed from core, each landed generic: the engineering_task storage and the worker_run control plane (claim, lease, heartbeat, checkpoint, budget); the external-worker harness target; the handoff gate grammar on object types; a plugin's own nav section (nav: {section: Software factory}) and offered routes — the factory lists Evals under its "More ›" so the reference sets sit one tap from the pages they grade (#692). Triage now also names the platform piece a request touches and, while planning, adds a candidate for core when the shape would serve another workspace (#695) — the ladder, concrete → abstract → core, run by the factory on itself.

What is not there

Performance and reporting pages, per-run activity logs, board counters, the incumbent price check, dependency currency, the nightly e2e mission, tag audits, batches of ten. Each was built; each was removed on 2026-09-24 because it explained the machine rather than helping a person decide. The first live judged gate crossing has not yet been observed on the box; the deterministic half has. The typed card contract that would let the plugin add its own card kinds — the gate verdict, the QA finding, the release — is specified and not built.

The workspace fixtures in the plugin are fictional. Metacto is the seller in every fixture; no customer, repository or product of a customer appears in it.