Files
IUMBTEMS/docs/DOGFOOD.md
T
BillyOutlastandClaude Opus 5.5 020ba87f08 Release 1.6.0: 1.0 cutover, phases 0–5 and the review remediation (#151)
- 1.0 cutover: the rewrite monorepo lands on main. 1.1.5 through 1.5.0
  never published on their own and ship here as 1.6.0, in lockstep for
  es-core, es-cli and epistemic-swarm (ADR 0001).
- Phase 0 (#140): fail-closed seat models, one CLI grammar for the
  human-only rule, sealed source-cache readers, pinned MCP identity, a
  registry-generated permission probe suite, one package list.
- Phase 1 (#141): research backends with failover, the Scraper-Swarm
  gateway, callable brainstorm/harvest, research-only runs, the
  deep-research coordinator, Markdown/HTML dossiers, domain-pack tiers.
- Phase 2 (#142): ADR 0002 and the shared approveStage service, masked
  TUI approvals, the headless runner (JSONL events, metrics, cancel).
- Phase 3 (#144): the human-only es-fleet daemon, DAG scheduler, worktree
  coordinator with a gated integration branch, telemetry bus and watch.
- Phase 4 (#146): the loopback web control plane (SolidJS, ADR 0003):
  dashboard, browser approvals, config preview, evidence explorer.
- Phase 5 (#149): telemetry harvest, distillation into proposals, the
  self-dogfood preset.
- Cutover review remediation (#152): CLI approvals bound to the preview
  with attempt limiting (#143), human-only `factory run` and fleet token,
  DNS-resolving SSRF guard, value-level secret scrubbing, fleet gc and
  allocation races, CodeQL #84, boundary-gate gaps, one REPORT.md writer
  per run mode.

Closes #96.
Closes #97.
Closes #98.
Closes #99.
Closes #100.
Closes #101.
Closes #103.
Closes #106.
Closes #107.
Closes #108.
Closes #109.
Closes #110.
Closes #111.
Closes #112.
Closes #113.
Closes #114.
Closes #117.
Closes #118.
Closes #119.
Closes #120.
Closes #122.
Closes #123.
Closes #124.
Closes #125.
Closes #126.
Closes #127.
Closes #129.
Closes #130.
Closes #131.
Closes #132.
Closes #133.
Closes #135.
Closes #136.
Closes #147.
Closes #148.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 21:33:44 -04:00

7.5 KiB

Dogfood run: the factory builds the tree-sitter complexity budget

M6's capstone is a real factory run on itself: grill → research → spec → build → QA → release, ending in a draft PR a human merges. The feature is the deferred M5 item — structural per-function complexity in the budgets gate, replacing the text heuristic when the tree-sitter index is available.

This run needs a human (the frontier and spec approvals, the spend ceiling and the merge) and a real model provider. Nothing here is automated.

1. Load the plugin

In the repository's opencode.json (or your global config), add the local package with your provider/model ids per tier:

{
  "$schema": "https://opencode.ai/config.json",
  "plugins": [
    {
      "package": "./packages/opencode",
      "options": {
        "models": {
          "deep": "<provider>/<model>",
          "balanced": "<provider>/<model>",
          "fast": "<provider>/<model>"
        }
      }
    }
  ]
}

Optionally commit a project config (.factory/config.json) with the same models — es config show and /config print the effective layers. It is a pinned control file: commit it before es approve frontier (approvals record the baseline), or accept a later edit with es rebaseline. embeddings and estimate belong in the global config or plugin options; a project file may not set them.

2. Grill (you + /grill)

Start OpenCode in this repository and run:

/grill Build the tree-sitter complexity budget: the budgets gate should count
decision points per function from the structural index (falling back to the
text heuristic when grammars are unavailable), replacing the "heuristic until
the tree-sitter index lands" comment in packages/core/src/gates/budgets.ts.
Acceptance: complexity findings name real functions with line numbers, the
existing budget tests still pass, and new tests cover the tree-sitter path and
the fallback.

Answer the interview (one question at a time). Set the spend ceiling explicitly — the run cannot start without it. When the design tree is settled, approve it:

  • TUI: /es-approve previews what you are approving, asks for your passphrase (masked), and records it; or
  • browser: es-fleet web prints a one-time URL (from a checkout: bun packages/fleet/bin/es-fleet.js web — es-fleet is private, never published to npm); the approvals page previews the subject and hashes, then asks for your passphrase (masked) and records with channel web; or
  • terminal: es approve frontier (asks for your passphrase)

3. Research and spec

Run /factory in the TUI, or es factory run --headless in a terminal for an unattended run. Either way the factory drives RESEARCH and then SPEC:

  • RESEARCH produces a cited REPORT.md, which the auditor enforces. Research alpha writes alpha.md and then beta attacks it in beta.md; only the factory merges them into REPORT.md.
  • SPEC produces the roadmap plus a GOAL.md per phase.

Seats run in the foreground, so a research turn can take minutes. That is work, not a stall: see "Watching a run" below. When the spec is ready, approve it the same way (/es-approve records it in the TUI, the approvals page records it in the browser, es approve spec records it in a terminal).

4. Autonomous build

/factory again; after the spec approval the run is autonomous: worktree per phase, gates (including the new complexity check once built), dual QA (functional + adversarial), manager tiebreak, retries bounded. Watch it as below. If something goes wrong: .factory/STOP halts everything; es factory resume clears a halt (/es-resume previews it).

Watching a run

Every view leads with one plain sentence: is the run working, waiting on you, possibly stuck, halted or done? It names the seat, its last tool and how long ago it acted.

  • es status (in the project): the headline; then which run, in which project, and how fresh it is; then each seat's state and last activity, research progress (cached sources, alpha.md, beta.md, REPORT.md, coverage), recent events, and anything waiting on you. --json gives the same to scripts. If another project's run is more recently active, it says so: es status --run <id> targets it.
  • es watch: es status, redrawn every 2 s (--interval S); q quits.
  • es runs: recent runs across your projects; * marks the one here.
  • TUI:
    • /es-factory opens the factory dashboard beside the session. Esc or q closes it, f toggles fullscreen and r refreshes; /es-close also closes it.
    • The prompt footer shows ES · <stage> · <seat> running · <age>, or what waits on you.
    • A toast announces stage changes, and also a paused factory after three turns without progress (run /factory to continue).
  • Web (es-fleet web prints a one-time loopback URL — from a checkout: bun packages/fleet/bin/es-fleet.js web): the fleet overview and per-task pages across the whole fleet — DAG, spend against the ceiling, pending approvals, live updates with a stale banner (#130).
  • Headless: es factory run --headless prints JSON lines.
    • It emits a progress event every 30 s while a turn runs.
    • stalled carries its evidence (the headline, last activity, running seats); turn-cap means the turn limit was reached.
    • --log-level quiet|info|debug (default info) sets the detail:
      • quiet: lifecycle and progress only;
      • info: one line per tool call;
      • debug: raw harness events with long strings clipped.
    • --events jsonl replaces the human lines with a versioned envelope per line (turn-metrics after every turn: spend delta + tool activity); --events-file <path> writes the envelopes to a file instead. SIGINT/SIGTERM cancel the run (exit 130, resumable); --turn-timeout S aborts a hung turn. See docs/HEADLESS.md.

es status from an agent's shell cannot verify the run (the private state dir is masked there); agents call the es_status tool, which shows the same liveness.

5. Release

es_release opens a draft PR from the run's integration branch. Review it, then merge yourself — the factory never merges or pushes the base branch.

6. Record the result

Add to the M6 close-out: the run id, the PR URL, gate/QA outcomes and anything the run exposed (those are M6 bugs to fix, not waivers). The run's artifacts live under .factory/ (specs and roadmap tracked; runtime, runs and worktrees ignored).

7. Deep research (no build)

For a question with no code to build, skip the factory: es research deep "<question>" --output <dir> --max-usd N (or /research deep <question> --max-usd N in the TUI) starts a research-only run and drives the deep-researcher headlessly. Watch it with es status in the output dir: thesis (alpha.md), antithesis (beta.md), then the synthesizer's REPORT.md, completing at DONE. Same ceiling/STOP/halt discipline, same sealed evidence.

Notes

  • Provider keys come from the environment or the harness store; they are never written into .factory/.
  • Upgrading from 0.7: the plugin options search_engine, max_iterations and mode were removed in 1.0 — a config that still carries them warns once (Ignored unknown plugin options: …) and otherwise loads. Delete those keys; only models per tier is needed (see §1).
  • Budgets use host-reported usage where exposed; estimates are labelled "estimated".
  • A failed run is evidence: fix the harness, re-grill if the design changed, and re-run. The tree-sitter complexity budget is a small feature on purpose — the point is the loop.