The 2.0.0-2.3.0 entries described the Phase 6-9 mechanisms as working
flows ("stop needing a human passphrase", "hot-swap its own binaries").
A symbol search over packages/*/src finds no caller for the machine key,
the staging pipeline, the prompt optimizer, the canary runner or lease
acquisition, and run-dag plus the canary live in the private fleet package.
- CHANGELOG: each intro now names what is reachable; 2.3.0 lists reachable,
library-only and not-in-npm pieces, and records that 1.6.1-2.2.0 were
never published and ship in 2.3.0.
- README status line: same correction.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
57 KiB
Changelog
2.3.0 — 2026-10-11
Phase 9 recursive self-improvement & model distillation. This release adds a prompt optimizer, a trajectory exporter for local-model training data and a canary hot-swap harness — every loop fail-closed and human-gated by construction: nothing rewrites prompts, weights or shipped code without a recorded human approval, and the canary stays OFF until a human explicitly enables it. The published trio (core/CLI/plugin) releases in lockstep as 2.3.0.
2.3.0 is the first published release since 1.6.0. Versions 1.6.1, 2.0.0, 2.1.0 and 2.2.0 were merged but never tagged or published; everything in their entries below ships as part of 2.3.0.
What is reachable in this release. Several Phase 6–9 pieces are library APIs with tests that no factory, CLI or daemon path calls yet. They are inert until wired:
- Reachable:
es improve export-dataset(#175),es rebase cascade(#165),es worktree pruneand startup orphan GC (#160), the opt-in mutation gate (#169), the model-diversity check (#170) and the benchmark suite (#171). - Library only, not called: the prompt optimizer (#174), the machine key and
proof-carrying transitions (#164), the staging pipeline (#166) and lease
acquisition through
WorktreeLeaseManager(#160). Stage exits still need the human passphrase. - Not in the npm packages:
es-fleet run-dag(#161) and the canary harness (#176) live in the privatepackages/fleet.
Behaviour changes.
- #174: Evolutionary prompt & cognitive strategy optimizer.
generatePromptCandidates(packages/core/src/improve/optimizer.ts) turns telemetry failure clusters into targeted prompt variations (append-guidance, trim-bloat, multi-generation combine);evolvePromptsgrades each against the benchmark suite and keeps only strict Pareto winners (zero regressions plus a strictly better pass rate or lower spend/steps). Winners become review-only proposal dirs with before/after benchmark receipts;applyPromptPatchis the sole applier and refuses without a matching recorded human approval. Signal-free telemetry yields no candidates and vacuous baselines are refused. - #175: Synthetic trajectory harvester for distillation.
harvestTrajectoriescaptures multi-turn trajectories of passed, verified phase worktrees only (green gate summaries plus a non-vacuous audit chain, derived byes improve export-datasetfrom on-disk evidence); every string is secret-scrubbed, diffs are path- and existence-verified, and unverified/missing/escaping inputs are skipped with reasons. Exports Unsloth/Axolotl/HF-compatible chat JSONL (sft) and prompt/chosen/rejected pairs (dpo, never inventing negatives) with a provenance manifest. - #176: Canary self-compilation and hot-swap harness.
CanaryRunner(packages/fleet/src/canary.ts) builds candidates in an isolated staging sandbox, shadow-tests them beside the live worker, and atomically re-points the active symlink only when green — rolling back instantly when red. OFF by default: construction withoutenabled: trueand a recorded human approval throws. The rollback target is frozen at construction, guarded writes deny the rollback tree and the active link, and candidates built inside the rollback tree are refused.
Security.
- No autonomous path rewrites prompts, weights or shipped code: the optimizer and canary apply only under recorded human approvals, and the canary pipeline seam has no silent defaults.
- Distillation datasets are secret-scrubbed (token families, credentials, private-key blocks) with redaction counts; DPO export refuses to invent rejected responses.
- Test fixtures build fake secrets by interpolation (repo precedent) so static scanners never see credential-like literals.
2.2.0 — 2026-10-11
Phase 8 anti-Goodhart verification & mutation oracle. Tools against
tautological tests, shared-weight blind spots and string-assertion evals: a
mutation gate that requires mutants to be killed, a policy that refuses
builder and checker seats on the same model provider, and 54 oracle-graded
software engineering instances for measuring factory fitness. Both checks
are opt-in: the mutation gate runs only when a human enables mutation in
.factory/gates.json, and seats with no model set are unverified, not
refused, unless models.requireDiversity is on. Never published on its
own; ships in 2.3.0.
Behaviour changes.
- #169: AST mutation testing gate.
generateMutants(packages/core/src/gates/mutation.ts) injects subtle mutants into touched sources (negated conditions, swapped arithmetic, stripped calls, voided returns, capped per file) and the gate engine reruns the touched suite per mutant (mutationcheck inpackages/core/src/gates/engine.ts, enabled viamutationin.factory/gates.json). Kill rates below 80% reject the phase with amutation/kill-rateerror — including the zero-mutant case, which fails closed instead of passing vacuously. Results are cached by a test-aware fingerprint (source plus in-scope test contents under a constant-time compare), so unchanged files skip the suite but edited tests always rerun it, and sources are restored after every mutant. - #170: Heterogeneous multi-model policy.
packages/core/src/agents/models.tsresolves the programmer, QA and auditor seats (per-agent override > role key > tier) and refuses shared-provider programmer/QA pairs at build initiation (Factory.startBuild, wired with the effective config by the plugin and best-effort byes mcp) and at seat launch (plugin launch guard).models.programmer,models.qaandmodels.auditorjoin the config with per-seat model assignment, so enforcement and reality cannot diverge; unset seats are unverified (refused only undermodels.requireDiversity). - #171: Rigorous SWE benchmark suite.
54 isolated instances across algorithms, refactoring, API integration and
debugging (
packages/core/src/evals/benchmark-cases.ts, per-category files), graded by a deterministic oracle — real bundle compilation, property tests and performance budgets (packages/core/src/evals/benchmarks.ts). The unit self-check grades every reference green and every seed red.scripts/benchmarks.tsruns the oracle smoke (rewritingevals/benchmarks/baseline.json) and, only with--model, dispatches spend-bearing model turns that record pass@1, spend, steps and the regression delta; model runs are never CI-blocking.
Security.
- Mutation sources are always restored (try/finally, witnessed by test); cache fingerprints are content hashes compared in constant time.
- Model diversity is enforced on every build path (plugin, MCP, seat launch); config stays a human-only control file, so agents cannot relax it.
- Benchmark oracles stay hidden from the agent; catalog seeds are reviewed repo files that must terminate (proven by the completing self-check).
2.1.0 — 2026-10-11
Phase 7 key delegation & consensus governance. Building blocks for
autonomous background builds that do not need a human passphrase at every
stage exit: a machine key that signs stage transitions on topic branches
only under a cryptographic gate proof, a rebase cascade for stacked
branches, and a staging pipeline that lands integration branches on
staging/autonomous until a human-signed release cut. Only the cascade is
reachable today (es rebase cascade). The machine key and the staging
pipeline are library APIs that the factory state machine, the headless
runner and the CLI do not call yet, so stage exits still need the human
passphrase. Never published on its own; ships in 2.3.0.
Behaviour changes.
- #164: MachineKeyStore with proof-carrying transitions.
MachineKeyStore(packages/core/src/approval/machine.ts) holds an in-memory Ed25519 key (privates in a module WeakMap, never on the store object) scoped strictly tointegration/*andfactory/*. It signs a stage transition only for a greenGateProofBundle: 100% passing Tier 1-3 tests, zero un-waived secrets or dependency vulnerabilities, verified spec and schema hashes, and a proof commit/branch matching the signed branch. Release merges andmaintargets are refused at sign time and fail closed at verify time — those stay human-only. - #165: SemanticRebaseManager and
es rebase cascade.cascadeRebase(packages/core/src/worktree/rebase.ts) replays a downstream branch's commits onto an upstream tip in a scratch worktree: single-line TypeScript import union per module (defaults, named,import type, linear-scan parser with no ReDoS), package.json dependency union with higher-semver-wins, and generic JSON deep-merge. The target moves only on green post-rebase tests (including the fast-forward path); any failure restores the witnessed SHA. Cascades involvingmainare refused. CLI:es rebase cascade --from <branch> --to <branch> [--no-verify]. - #166: AutonomousStagingPipeline with human release veto.
landOnStaging(packages/core/src/factory/staging.ts) merges integration branches ontostaging/autonomouson green gate proof (structural mirror of #164's bundle),runStagingSuitesruns the regression and compatibility fires against isolated scratch checkouts, andcutReleasemints an UNSIGNED consolidated cut:openReleasePrrefuses unsigned cuts andcountersignReleaseCutrefuses machine-shaped signers, so no agent path exercises the veto — a human countersigns with the passphrase-unlocked Ed25519 key at a terminal.
Security.
- Machine signing power is unextractable (WeakMap-held privates), branch- and target-scoped, and proof-bound; tampered or cross-key records fail verification closed.
- The import merger bails to a human on multi-line imports, clashing defaults, mixed type/value imports and non-TS/JSON files instead of guessing; hostile input terminates (ReDoS regression test).
- Staging and rebase scratch work happens off-branch; targets move only
after green verification, and
mainadvances through the human release flow only.
2.0.0 — 2026-10-11
Phase 6 autonomous orchestration & fleet hardening. Groundwork for
concurrent runs that do not coordinate through shell flock and 50KB
orchestrator prompts: atomic worktree leases with heartbeat TTLs, and a
fleet daemon that drives multi-phase task DAGs natively. Stale-lease and
orphan-checkout GC runs at factory startup and through es worktree prune;
nothing acquires leases through WorktreeLeaseManager yet. run-dag lives
in the private fleet daemon (es-fleet), which is not in the npm packages.
Never published on its own; ships in 2.3.0.
Behaviour changes.
- #160: atomic worktree lease manager.
WorktreeLeaseManager(packages/core/src/worktree/lease.ts) holds one heartbeat lease per.worktrees/checkout (default TTL 120s), acquired withopen(O_CREAT | O_EXCL)so racing acquirers elect exactly one winner; expired and dead-holder leases are reclaimable, and only the token holder may heartbeat or release.es worktree prune(agent-safe) and factory startup garbage-collect stale leases and orphaned checkouts; prune deletes checkouts, never branches. - #161: fleet process orchestrator.
run-dag <roadmap.json>loads a ticket-scoped roadmap into a validated task DAG and ticks theFleetDaemonto full settlement with no human in the loop and no prompt-level orchestration — tasks carry only their own objective. The daemon records heartbeats in.factory/runtime/fleet.json, restarts stuck turns through each task's own failure policy (retry re-queues, otherwise terminal; library default off, verb default 30 minutes), and guards late worker settlement so a restarted turn can never disturb its relaunch. Covered by a fake-model integration test proving a three-phase DAG runs to done in dependency order. es-fleet run-dagis human-only, like every spend-bearing verb.
Security.
- Lease dirs refuse slugs outside
[a-z0-9-]and checkouts outside the managed root; prune never follows stray paths or deletes history. - No new human-only surface is agent-reachable:
es worktree pruneis intentionally agent-safe (orphan GC must run at factory startup).
1.6.1 — 2026-10-11
Never published on its own; ships in 2.3.0.
Trust hash covers the full gate command (#217). commandSetHash now hashes
the complete normalized CommandCheck — kind, parser, related,
touchedArgs/extensions and timeoutMs alongside id/command — so any
change to what a gate runs revokes trust. Humans: re-run es trust after
upgrading; previously approved command sets hash differently and the gates
refuse to run until the new set is approved. The e2e regression gate now fails
closed when no history is sampled (#210). The self-dogfood preset releases
onto main post-cutover: the rewrite pin, workflow triggers and runbook
now target main (#281); the rewrite branch itself is untouched.
1.6.0 — 2026-10-09
Phase 5 self-improvement: runs already leave rich records (audit chain,
QA failures, gate rejections, findings, spend, evals) and now the factory
learns from them. es improve harvest aggregates runs and evals into one
versioned, secret-scrubbed telemetry dataset; es improve distill clusters
recurring failures into reviewable proposals a human applies; the
self-dogfood preset builds this repo from an issue into a draft PR.
The published trio (core/CLI/plugin) releases in lockstep as 1.6.0.
It is the first npm release since 1.1.4: 1.1.5 through 1.5.0 below were
never published on their own and ship here, together with the fixes from
the 1.0 cutover review (#151, remediated in #152).
Security.
- ADR 0002 I3: the CLI signs only what it previewed.
es approvebinds the previewed subject hash and refuses a preview older than 120 s; TUI preview tickets are redeemed once and expire after 120 s. - #143: CLI passphrase attempt limiting. Every CLI human verb shares the TUI's 5-per-10-minute limit per state dir, with audited lockouts.
- Human-only verbs.
es factory run(a spend-bearing headless run) andes-fleet status --token(the bus bearer token) are refused from agent shells. - #99: no "human" agent name bypass. Research tools trust a human
operator only when the CLI builds them with
operator: "human"; an agent namedhumangets the registry check like any other. - #111: one REPORT.md writer per run mode, read from sealed run state; when the mode cannot be read, neither seat may write it.
- SSRF guard resolves DNS. Every fetch hop, redirects included, resolves its host and refuses when any address is non-routable (fail closed); each hop gets its own timeout.
- #135: secret values are scrubbed, not just secret-named keys:
NAME=valuepairs,Bearercredentials, known token shapes (dashedsk-proj-…bodies included) and PEM private keys. - Control files.
.factory/improve/**is deny-write for agents; the self-dogfood preset writes its control files atomically under lock, then rebaselines and audits. - Fleet. Request headers parse into a
Map(CodeQL #84, prototype pollution); package-boundary gaps closed (web→core and plugin→fleet imports, inlinetypeimports that still load at runtime).
Behaviour changes.
- Headless turn metrics print only at
--log-level debugor to--events jsonl; default output is unchanged from before #120. es-fleet startasks for confirmation with--foregroundtoo; a background start waits for the daemon's pidfile before reporting.- A seat whose configured model is missing on the host is refused on every tool call, primaries included (#96).
New.
- #135: telemetry harvester over runs and evals. Read-only
es improve harvest --runs <dir>[,<dir>] [--evals <dir>[,<dir>]] --out <file>(agent-safe) producing the versionedTelemetrySchemadataset: phases with replans and failure counts, halts with reasons, spend, gate rejections by rule, audit findings by kind/severity, eval results withmodelLimited, and the audit-chain verification. A broken chain is reported, never repaired; env-like values are scrubbed and state-dir paths collapsed. Schemas render toschemas/anddocs/SCHEMAS.md. - #136: distillation into reviewable proposals. Deterministic
clustering keyed on (kind, label) with defaults of 3 occurrences across
2 runs; each surviving cluster becomes one proposal under
.factory/improve/proposals/<id>/—prompt-guidance(a version-bumped patch that passesgit apply --checkand the assets drift check),gate-tuning(an explanation only;gates.jsonstays a human-applied control file) ordomain-pack(validated againstDomainPackSchema). The "code disposes" gate drops proposals whose evidence is not a verbatim harvester quote or whose model numerals the telemetry never recorded.es improve distill --telemetry <file> --out <dir>is agent-safe;--open-pris human-run (refused without a terminal) and drafts from a topic branch without pushing the base. - #137: self-dogfood preset.
es factory init --preset self-dogfood --issue <n>(human-only) seeds.factory/from versioned preset assets — project config (audit.phase: required), the real merge gate (bun install --frozen-lockfile,bun run check,bun run docs:check), a roadmap seed pinningbaseBranch: rewrite, and the issue as the idea note — then reminds aboutes trust, the $15 spend ceiling and the frontier/spec approvals.docs/SELF-DOGFOOD.mdis the runbook (prerequisites, flow, review, abort); one human-run validation session to a draft PR is tracked on #137. - #138: release 1.6.0. Version bump, changelog and status line; draft
release PR from
integration/phase-5torewrite.
Fixes.
- #122: a plain
es-fleet startnow daemonizes; the detached child used to fail the TTY check while the parent printed "starting". - #147: a failed landing merge aborts only a real conflict and keeps the original error otherwise.
- Fleet worktrees:
gccan no longer remove a worktree mid-allocation, and a second allocator of the same task refuses instead of dropping the first one's record. - #137: a preset run's release base is pinned end to end (the grill
cannot drop it, and the PR opener refuses
--base main). - #120: tool metrics carry
msandseat. - #130: the web task page shows run liveness (headline, stage, seats, research progress).
- #136: clusters key on (seat, failure kind, rule or category) with evidence links; dropped proposals are reported with their reason.
- #109: the darkharvest grader reads the run the case produced; loopback is allowed only for fixture-server eval cases.
- #111:
es research deepand/research deepno longer send the deep-researcher prompt twice.
1.5.0 — 2026-10-09
Phase 4 web control plane: the fleet daemon serves a browser UI on
loopback behind a one-time URL — a fleet dashboard, frontier/spec
approvals in the browser (ADR 0002 option b), a preview-only config
editor, and an evidence explorer with range-highlighted quotes and seal
statuses. packages/web stays private and is served from the repo (the
fleet daemon is private too, so no asset-shipping decision is needed);
the published trio (core/CLI/plugin) release in lockstep as 1.5.0.
Security.
- #129: the web UI is localhost-only behind a single-use ticket
exchange.
es-fleet web(human-only, refused underES_SANDBOX) mints a 32-byte ticket (TTL 120 s, atomic-rename claim) that the first load redeems for anHttpOnly; SameSite=Strictsession cookie; wrong Host (DNS-rebinding defense) and non-loopback Origin are refused, and every web response carries a strict CSP (default-src 'self', no inline scripts,frame-ancestors 'none'). - #131: browser approvals sign only what was previewed. Preview
returns the subject, files and hashes with a single-use ticket bound
to
hashJson(subject); submit needs the session cookie, a loopback Origin and the session CSRF token, then re-derives the subject (409 on mismatch), unlocks the sealed key in-process, records with channelweb, and destroys the signer. Five wrong passphrases lock the web surface with an auditedapproval.lockout; the passphrase lives in one page-local variable and appears in no log, event, response or state file (probed). The ADR 0002 adversarial-review checklist for the browser path passes 9/9 applicable probes (posted on #131); I8 stays user-confirmable (option b implemented). Trust, waive, resume, key seal, config set and export are untouched and stay terminal-only. - #133: hostile source text is inert. Quotes render through text
nodes split by verified ranges into
<mark>spans (never HTML parsing, probed with<script>/event-handler payloads); seal status (sealed/unsealed/invalid/unknown) shows on every source, with tampered bytes refused by their content hash.
Behaviour changes.
fleet.statuspending entries now carry the approvablestage, enriched from each worktree's pending list (#131); snapshot tasks carrytitleanddepsfor the DAG (#130).bun run testruns the web suite first under browser conditions (the client Solid build), then every other package (#130).
New.
- #129:
packages/web(private, never published). SolidJS + Vite (ADR 0003: shared signals with the TUI, 15 kB hello build), served by the daemon from the bus port; declareddeps.tsboundaries and a path-filtered CI job. - #130: fleet dashboard. Columns-by-depth task DAG, task table, spend against the ceiling, pending list, per-task pages and a live WS stream with reconnect refetch and a 5 s stale banner — read-only throughout, status always in words beside colour.
- #131: approvals pages.
#/approvalslist and#/approve/<task>/<stage>page (masked, non-reactive input cleared on submit; remaining-attempt and lockout-delay alerts). - #132: config editor, preview-only. Project/gates tabs with
strict-schema validation, exact hash diffs and copyable terminal
commands over read-only
fleet.config.get/fleet.config.plan; the bus has no apply method and the UI no apply button. Browser apply is deferred to #145 (needs #131's pattern plus the user's ADR 0002 extension). - #133: evidence explorer. Claim/source graph with tag/status/tier
filters, inspector (rank explanation, retractions, history), source
viewer with verified quote highlights, and Markdown/HTML dossier
exports through the #112 renderers — read-only, capped payloads.
Core gains
locateQuote(index-mapped ranges, self-checked).
Evals and CI.
- Web tests render with the client Solid build under happy-dom
(
bun --conditions=browser test packages/web). - Full
bun run test: the same 8 pre-existing bwrap-overlay sandbox failures as 1.4.0 (identical set fails on the base; green in CI where bwrap works).
Dependencies.
packages/webshares the TUI'ssolid-js1.9.15 lockfile entry; new stock npm needs arevite,vite-plugin-solidand dev-onlyhappy-dom. Zero vendored code in the phase.
1.4.0 — 2026-10-09
Phase 3 fleet: concurrent task DAGs run on one machine under a human-only
es-fleet daemon — a deterministic scheduler, isolated git worktrees per
task with gated landings onto an integration branch, one headless run per
task with per-task spend ceilings, and a read-only localhost telemetry bus
with an es-fleet watch dashboard. @heretek-ai/es-fleet ships from the
repo only (private) until its RPC is stable; the published trio
(core/CLI/plugin) release in lockstep as 1.4.0.
Security.
- #122: starting or stopping the fleet is human-only, by policy and in
the binary. The policy's binary matcher knows
es-fleet, and the whole binary is human-only exceptstatus/--help(fail-closed flag resolution);startadditionally refuses agent sandboxes, requires a TTY plus a typed confirmation, and takes a mandatory fleet-wide spend ceiling. Fleet state lives under the sandbox-masked state dir. - #124: task worktrees are isolated by policy.
.fleet/is deny-write for every agent outside its own task worktree, and seats may not name other tasks'.fleet/paths in the shell. The base branch is never checked out, reset or merged — asserted in every worktree test. - #126: the telemetry bus is read-only, localhost-only and token-authenticated. Host allowlist (DNS-rebinding defense), Origin checks on WebSocket upgrades, strict schemas that reject extra fields, and payload scrubbing (secret keys and known secret values never appear).
Behaviour changes.
es-fleetrefuses to start without a positive--max-usdceiling, which caps the summed task ceilings.es factory run --headlesstakes no--max-usd(verified): workers provision each task's ceiling into its run state, where the factory guard enforces it.- A landing conflict reopens the task as
waiting-human— the one transition allowed out ofdone— and the daemon retries it after human repair.
New.
- #122:
packages/fleet(@heretek-ai/es-fleet, private). State helpers, inode-bound socket guard, pidfile lifecycle with stale recovery,es-fleet start/stop/status, boundaries inscripts/deps.tsand a path-filtered CI job. - #123: task model and deterministic DAG scheduler.
all_success/one_successtriggers, mandatory ceilings,fail/retry(n)/replanpolicies,waiting-humancapacity relief, pureschedule()with a property test over random DAGs,es-fleet task add/list/cancel. - #124: worktree coordinator and gated integration branch.
Two-phase allocation, salvage refs, orphan
gc, transactional landing (gates first,--no-ffmerge in a throwaway worktree, verified rollback on conflict) ontofleet/integration/<dag>. - #125: workers. Argv-only headless runs, event folding with spend and
token tracking, no-double-start supervision with restart recovery,
StillDown + mass-death circuit breaker, and the daemon tick loop
(
schedule → allocate → launch → land → release) with a SIGTERM kill switch recording resumable cancellations. - #126: telemetry bus and
es-fleet watch. Strict-schema RPC (fleet.status/task/pending/eventswith monotonic backlog replay), coalesced WebSocket stream, 0600 token, TTY dashboard. - #127: merge-blocking fleet integration suite. A→B+C on the real host
with the fake model proving ordering, overlap, output ownership (and no
.factory/leakage across branches), failure/retry/cancel, conflict repair and stop/salvage/gc — plus break probes proving the suite bites.
Evals and CI.
- #127 runs in
bun run check(~10 s, 5/5 deterministic locally). - Full
bun run test: 8 failures are the pre-existing bwrap-overlay sandbox failures of containers (identical set fails on the base; green in CI where bwrap works).
1.3.0 — 2026-10-09
Phase 2 approvals everywhere: frontier and spec approvals complete in the OpenCode TUI as well as the CLI, through one shared core service, under the threat model and invariants of ADR 0002. The headless runner gains the fleet entrypoint: a versioned JSONL event stream with per-turn metrics, graceful cancellation and turn timeouts, and worktree validation.
Security.
- #116: ADR 0002 (proposed) puts approvals on every surface. Threat model (5 actors), normative invariants I1–I8, a 25-row inventory of terminal-only enforcement points, and the adversarial-review checklist gating the TUI (#119) and browser (#131) builds. Trust, waive, resume, key seal, config set and export stay terminal-only.
- #119: frontier and spec approvals complete in the OpenCode TUI.
A masked passphrase dialog (plaintext only in a closure-scoped buffer,
zeroed on submit/cancel) unlocks the sealed human key and signs
in-process through the core
approveStageservice (channel: "tui"). No passphrase and no approval cross RPC (no approve/trust/resume RPC exists); previews bind the signed subject through a single-use ticket (TTL ≤ 120 s); 5 wrong passphrases per 10 minutes lock the TUI surface out with an audited lockout. The masked-input spike (#118) verdict is GO with headless-renderer evidence. - #117: one approval code path in core.
approveStagere-derives the subject with a preview-hash check, signs, clears pending and begins research under its locks; re-approval of an unchanged subject is a side-effect-ensuring no-op.HumanSigner.destroy()ends signing.ChannelSchemais nowcli | tui | web, shared by approvals and waivers.
Behaviour changes.
- Approval status messages name
/es-approvefirst; the TUI pending panel and the liveness lines point at the TUI with the terminal as the fallback. schemas/approval-channel.schema.jsonis replaced byschemas/channel.schema.json(same shape, plusweb).- Headless runs without the new flags print as before, plus a
turn-metricsline per turn at info level and above.
New.
- #120: fleet-ready headless runner.
--events jsonl(versioned envelope per line:JsonlEnvelope/HeadlessJsonlSchemaexported from the CLI;--events-fileredirects to a file), per-turnturn-metrics(sealed spend delta, tool activity, opportunistic tokens), SIGINT/SIGTERM cancellation (exit 130, resumable),--turn-timeout, and--cwdvalidation (other runs' seat worktrees and detached HEADs refused; the root is indexed). Seedocs/HEADLESS.md.
1.2.0 — 2026-10-09
Phase 1 epistemic layer: research, brainstorm and harvest work outside the fixed factory flow. Backends fail over with the gateway leading, the grill and the factory fan out brainstorms and verdict-check harvest targets themselves, deep research runs thesis/antithesis/synthesis to a grounded report anywhere, dossiers render to Markdown and HTML, and domain-pack tiers weight the score. A merge-blocking research-fires suite pins the whole loop.
Security.
- #106: provider API keys are masked in seat sandboxes.
BRAVE_API_KEYandFIRECRAWL_API_KEYjoinSECRET_ENV, so agent shells never see them; backends run in the plugin process. - #107: the gateway token never leaves its header. It comes only from
ES_SCRAPER_SWARM_TOKEN, is masked in sandboxes, and never reaches.factory/, logs or error messages.
Behaviour changes.
- Research completion in research-mode runs ends at DONE (build runs still move to SPEC); deferred frontier facts are required only in build runs.
FETCHEDsnapshots are capability-derived (fetch-capable backends count); legacyfetch/webfetchentries still do.- Prior-art records are keyed per brainstorm run; legacy global records satisfy any run.
- Brainstorm and harvest artifacts live under
runs/<run>/(the human's flows stay thedefaultrun); legacy top-level files still read.
New.
- #106: ordered source-backend failover (
SourceBackend,research.backends, per-backend cooldowns with 429 Retry-After;blockedsafety refusals never fail over;searchProviderkept as an alias). - #107: Scraper-Swarm gateway backend (JSON-RPC
web_search/fetch_pageoverPOST /mcp, contract v1 withcontent_sha256verification, leading the default order when configured; recorded-fixture contract tests). - #108: callable brainstorm fan-out (run-scoped store, grill/factory callers at depth 1, shortlist JSON, lean budgets).
- #109: callable harvest target and shared prior art
(
es_harvest_targetverdicts for grill/factory/scout/harvester, run-scoped harvest plans,PriorArtSearchSchema). - #110: research-only runs (
beginResearchRun, objective + ceiling, no frontier/approvals/git needed). - #111: deep-research coordinator (
deep-researcher+ synthesizer seats, human-onlyes research deep, interactive/research deep). - #112: dossier renders (deterministic Markdown + self-contained HTML,
XSS-tested; agent-safe
es research render). - #113: domain-pack tiers reach claims (deterministic source
classification sealed in
SourceMeta,ClaimSchema.tier, tier-weighted scores; unknowns stay__default__).
Evals and CI.
- #114: merge-blocking research-fires suite (grounded quotes, failover,
sealing, degradation, renders; break-probe verified) plus a
reported-never-blocking
deep-researcheval case.
1.1.5 — 2026-10-09
Phase 0 hardening: every trust boundary the 1.1.x series left soft is now sealed, pinned or tested — source-cache seals on every reader, MCP caller identity, CLI/policy argv parity, a registry-generated scoping suite, fail-closed seat models, and consistency cleanup. No human-only verb changed.
Security.
- #98: every source-cache reader verifies seals. Scout advisories, brief export, retract and audit dossiers went through unsealed caches, so planted entries read as evidence. All constructions now go through the sealed constructor, planted entries are refused, and a misuse-guard test fails any new unsealed construction.
- #99: MCP caller identity is pinned, research tools gain core seat
checks. A piped
agentargument could claim any seat overes mcp; identity now comes from the adapter environment (ES_MCP_AGENT, else legacyES_AGENT), defaulting to seat-lessmcp.es_research_search,es_research_fetchandes_research_auditenforce the registry grants in core. The research tools are not on the MCP surface at all.
Behaviour changes.
- #96: seat models fail closed. Malformed refs and unknown
models.agentskeys are rejected at config load; a configured model missing on the host refuses that seat at launch with remediation (naming the key andes config set) and shows ines_status. Unset tiers still inherit the session default, explicitly. - #101:
es_request_approvaladmits factory and grill only. The manager seat was accepted against the registry's grants. - #97 precision: known boolean flags read single-way in the human-only rule, cutting false denials with zero lost denials (property-gated).
New.
- #100: registry-generated permission matrix and bypass probes
(
packages/opencode/test/scoping.test.ts). OpenCode'sPermission.evaluate+Wildcard.match(MIT) are vendored into the testkit; every seat's compiled rules are asserted against its registry spec, and each restriction class is probed on the real host, including the post-#99 MCP pin. - #102: one workspace package list (
bun scripts/packages.ts): the typecheck loop,pack-smoke.sh,publish.ymlanddeps.tsread it; new packages declareesRelease.orderandBOUNDARIES.
Fixes.
- #101 registry consistency: factory tool union equals
ALL_ES_TOOLSwith single registration (tested both halves);confirmationCodeand the ignoredrecordApprovalstateDirremoved; waivers comment corrected to Ed25519; subagentspawnsstay empty (depth 1, tested). - #139: the
auditor-thesiseval stages an open audit run, graded deterministically on the verdict record instead of narration luck. - #103 hygiene:
.claude/CLAUDE.mdis a pointer to AGENTS.md (deadrunner/paths gone); README and DOGFOOD gain the 0.7 options note.
Evals and CI.
- Seeded argv-parity property (3 × 2,000 cases) plus HELP-marker parity, both with recorded break probes (#97).
docs/CONFIG.mddocuments the nestedmodels.*keys (#96).- CI pattern for future packages documented in ADR 0001 (path-filtered
workflows;
checkstays unfiltered) (#102).
Dependencies. @opentui/core + @opentui/solid 0.5.14 → 0.5.17: the
nested @babel/core 7.28.0 pin is gone (7.29.7).
1.1.4 — 2026-10-08
A security fix for the human-only shell rule, plus the E2E feedback fixes (#85). This closes the 1.1.x proof-of-work phase (#35); the user waived the dogfood and the local real-model run.
Security.
- #88: a flag before the verb slipped past the human-only shell rule.
The rule read only the word right after the es binary, but the CLI takes
--flag,--flag value,--flag=valueand--anywhere. Soes --cwd . approve spec,es -- approve spec,es --run <id> factory resumeandes factory --cwd . resumewere allowed for every agent, factory seats included.- Approvals and keys stayed guarded by the masked key and the
terminal-only passphrase. Spend-bearing
auditandscoutruns andfactory resumewere not. - The rule now finds the verb the way the CLI parser does. A bare
--flagcounts both as a boolean and as taking a value. - Upgrade from any earlier version.
- Approvals and keys stayed guarded by the masked key and the
terminal-only passphrase. Spend-bearing
Fixes.
- #86: refusals for text that only names a guarded verb. The rule stays
quote-blind, so a here-doc, a commit message or a
--bodyargument that mentions a human-only verb is still refused. The refusal now says how to pass such text by file (gh … --body-file,git commit -F). - The grill skill's first turn asks and never records (#85). The seat had been writing the frontier before asking anything.
Evals and CI (#85).
- The
programmercase stages a BUILD run with a phase worktree, so it can pass (#66). - Step caps were re-budgeted from observed need, and the
ES_EVAL_MAX_STEPSceiling went from 16 to 24 (#67). e2e-feedbackfails only when a historically stable case fails (scripts/e2e-gate.ts, #68).audit-firesis marked model-limited on the free CI model.- Grading reads completed tool outputs, except the raw fetch tools, whose verbatim quoting is the skill under test.
- Kept workspaces mirror
.factory/tokeep/factory/, because the artifact upload drops dot-dirs.
Dependencies. @babel/core 7.29.6, dev only (GHSA-4x5r-pxfx-6jf8).
1.1.3 — 2026-10-08
Live-run visibility and seat discipline, from the 1.1.2 dogfood (#63): a human could not tell a working run from a frozen one, and the factory relaunched live research seats as second writers.
Behaviour changes.
- Factory seats launch seats in the foreground only.
subagentwithbackground: truefrom a seat is refused, and so is launching a seat that is still running. A pair (QA, auditors, brainstorm lenses) is several calls in one message, which the host runs in parallel. RESEARCH runs alpha, then beta. - One writer per research file. Alpha writes only
research/alpha.md, beta onlyresearch/beta.md, and only the factory writesresearch/REPORT.md. - Prompts: factory v7, research alpha/beta v3, brainstormer v2.
es factory run --headlessemitsprogressevents.stalledcarries evidence, and the turn cap is its ownturn-capevent. The default output is one line per tool call (--log-level quiet|info|debug).
Fixes.
-
#60: the false stall and the duplicate writer. Three causes:
- The in-host continuation re-prompted the factory right after it launched background seats.
- The headless driver's own turns suspended those seats.
- Neither counted research artifacts as progress.
Progress is now a shared fingerprint over the stage machine, research artifacts, seat outcomes and the audit head. The continuation waits while a seat runs, and announces its pause instead of going silent.
-
#59: the signature-mismatch dead end.
es statusfrom an agent shell minted a throwaway engine key in the sandbox's masked state dir and called the run state forged.- Verifiers never create the key. A missing key gets its own message
(use the
es_statustool in an agent shell; otherwise setES_STATE_DIR), and sandboxes setES_SANDBOX. es resealnames the key it checks and refuses to sign without it.- Sidecars are written atomically.
- Verifiers never create the key. A missing key gets its own message
(use the
-
#59:
--help. A plaines <command> --helpis allowed for agents, and prints that command's usage. The seat block on control paths points at the read tool, glob, grep andes_status. -
#57: the dashboard. It shows the headline, the run header, seats, research progress, phases (no dangling
Phases:), what waits on you and recent events. It opens beside the session:Esc/qcloses,ftoggles fullscreen,rrefreshes, and/es-closecloses it too. -
#62: the RPC
changedevent is emitted. It fires afteres_*tools and seat transitions (coalesced to one a second) and with pause notices. The TUI toasts only stage changes and notices.
New (#58, #61).
es statusleads with a plain sentence, then the run id, stage, project path and age, seats, research progress and recent events.--jsongives the same data to scripts.--run <id>targets another project's run.- It hints when another project's run is fresher.
es runs [--all] [--json]lists recent runs across projects, from a per-user index under the state dir.es watch [--interval S]redrawses statusin the terminal;qquits.es_statusand/statusadd the headline, last activity, seats and research progress. The<factory-state>block injected into prompts is unchanged.- The TUI prompt footer shows
ES · <stage> · <seat> running · <age>, or what waits on you. - Seat records live in
.factory/runtime/seats.json(advisory, written by the plugin).
1.1.2 — 2026-10-07
Proof-of-work follow-up to the 1.1.1 security release (#54).
audit.phase: optional|required(#33). Defaultoptionalkeeps 1.1.x behaviour;es config set audit.phase requiredrefuses merges of QA-passed phases without a passed or human-dismissed audit. The factory prompt (v6) opens the phase audit as the phase enters QA when required.@@CHILDtestkit directive (#34). Delegated child sessions receive scripted tool calls through the parent's subagent prompt; the parent's@@CALLscript no longer consumes them.- Pipeline A. Deterministic real-host factory loop (grill → research with a deferred fact → spec → two phases with build/QA/audit, a QA fail and a STOP/resume → release → DONE), with required audits reached through delegation; merge-blocking in CI.
- B eval cases. research, thesis auditor, programmer, adversarial QA and
designer cases with staged fixtures and a localhost fixture server
(
{{SERVE_URL}}); validated locally, scored nightly. - Signed sidecars.
.factory/runtime/state.jsoncarries an HMAC sidecar under the masked engine key; reads refuse pre-seeded or tampered state and only a human re-signs reviewed files (es reseal --sign).
1.1.1 — 2026-10-07
Security release (#35). The 1.1.0 adversarial audit broke the text-matched shell policy six ways, forged VERIFIED claims through the shell, and drove approvals through a stealable service password; 1.1.1 moves that enforcement into the OS, the crypto and the sandbox. Published 1.1.0 is deprecated.
Breaking.
-
Re-approve, re-trust and re-waive after
es key seal: v1 HMAC records were MACed with a key agents could read; they are refused with the re-record hint. -
Bubblewrap is required for factory seats (refused a shell without it) and factory gate runs (halt with
gates/sandbox-missing); CI, nightly, E2E and publish install it and allow unprivileged user namespaces. -
Approvals, waivers, trust and resume happen at a terminal only: the approve/trust/resume RPCs no longer exist and the TUI only previews, then points at the terminal command.
-
S1: quotes are evidence fragment by fragment (#38, #46, #48). Every ellipsis fragment must be at least 12 characters on its own; code excerpts are one contiguous verbatim span of the cited lines (at most 60 lines); a thesis pass needs at least one witnessed invariant that holds; the audit/scout/harvest fire graders are exact (plants cited within 3 lines, no extra or duplicate rows).
-
S2: argv-aware shell policy (#37, #40–#45, #50, #51). Quotes and escapes are stripped before matching, human-only verbs are found behind wrappers, git subcommands past global options, and control paths match case-insensitively; any
.factory/mention needs a provably read-only command. This is defence in depth and the only layer for the user's own agents without bubblewrap — documented as weaker. -
S3: every agent shell and gate run is sandboxed by bubblewrap. Kinds:
user,seat,programmer,readonlyandgate; cached-web seats get--unshare-net; the private state dir and service credentials are masked in every kind. Seats lose Code Modeexecute; the shell is re-checked by the last hook after the hook bridge. -
S4: passphrase-sealed Ed25519 human key, terminal-only approvals (#39).
es key seal(asked twice, at least 10 characters) seals the key with scrypt + AES-256-GCM; every human action unlocks it with a passphrase at a TTY. A wrong or empty passphrase records nothing. -
#49: no approval RPC for a stolen service password. Verified: the mutating RPC methods are gone (previews still work) and
service.jsonis masked in every agent sandbox. -
#52: engine-sealed source cache. Each entry's metadata carries an HMAC-SHA256 seal from a key in the masked state dir; unsealed (planted) entries are refused on read.
-
#32: per-file control re-pin.
es_frontier_writere-pins onlyfrontier.jsonwhen its baseline matches, so a concurrent hand edit to another control file still halts as drift instead of being absorbed. -
#31: host web caching only for factory seats in a factory project. Without
.factory/, nothing is cached and no.factory/is created; the user's agent never caches. -
M1: eval harness that can pass (#25–#29, #36). Case caps authoritative under a ceiling of 16,
toolsUsedcounts completed calls, spend read fromstep_finishcost underES_EVAL_MAX_USD, failed workspaces kept and uploaded, nightly evals off push, agent feedback uses PWD.
1.1.0 — 2026-10-07
"Dialectic Restoration" (#20) brings back the best of the 0.7 research harness, ported to TypeScript inside the 1.x trust model. Milestones: M1 foundation (#21), M2 seats (#22), M3 rigor (#23).
Breaking, no migration. The frontier schema moves from 1.0 to 1.1. 1.0.x
frontiers are not migrated: a 1.0 .factory/frontier.json is refused with
the fresh-run instruction, so 1.1 needs fresh runs.
M1: foundation (#21)
-
Security: cached evidence is tool-only. Before this release, a research or factory seat could write
.factory/research/sources/<sha256>.mdwith made-up text. The cache's only tamper check is "content hashes to the file name", which a forgery passes by construction, so the seat could then cite its own text as VERIFIED. The source cache,coverage.json, the research dossier, the signed brief and.factory/claims/are now control files: no agent may write them, and seats may not mention them from the shell. -
Claim stack (
packages/core/src/claims/):- Claims have content-hash ids and both an epistemic tag and a lifecycle status.
- The witness re-checks every VERIFIED quote against the cache, and every code location (file, line range and verbatim excerpt) against the file on disk.
- Dossiers refuse any claim whose witness fails.
es_research_completenow writes.factory/research/dossier.json. - Retracted sources make their claims STALE, and revised ones SUSPECT
(
es research retract, human-only). ClaimStoreindexes the dossiers.- A deterministic, lexicographic ranker orders rival claims and dossiers.
-
Proof-carrying research brief.
es research exportwrites a signed.factory/research/brief.pcrb.json, andes research verify-briefchecks source identity, the manifest (it notices deleted members), the signature and the quotes. -
Design tree (frontier 1.1). Nodes gain
kind(decision or fact),recommendedandround.es_frontier_writechecks each save against the previous one:- no deleted nodes;
- no silent edits to settled answers (reopen first);
- no going back a round.
It also returns the next round's questions.
<factory-state>gains a tree progress line, and the factory panel shows it too. -
Facts versus decisions. The grill settles repo facts itself and defers web facts as
kind: "fact"nodes.es_research_completerefuses until every deferred fact is answered on a grounded claim line marked(fact:<id>). -
Prompts.
grillgoes from v1 to v2: frontier rounds, round-1 premise inversion, the freeze procedure.factorygoes from v3 to v4: deferred facts and research depth. The 1.0.5 no-run routing is kept. -
Search as policy. Research seats no longer get the host
websearchorwebfetchtools; every web fact goes throughes_research_searchandes_research_fetch. Fetches are keyed by canonical URL (ported exactly from the 0.7 webcache), and a fresh full-page snapshot is served from the cache. The freshness window is 7 days, or 30 for documentation hosts;refresh: truerefetches. -
Configure.
- New
research.depth(1–4, advisory),research.cacheTtlDays,research.searchTimeoutSandresearch.searxngUrl(global only). es config set <key> <value> [--global]is human-only, validated against the schema and confirmed with a typed code. It refuses to accept drift in other control files, and it re-pins the project config.
- New
-
The research auditor's
ClaimStatustype is renamedClaimAuditStatus.
M2: seats (#22)
- Breaking: the factory state goes from version 1 to version 2. 1.0.x run states are refused with the fresh-run instruction; there is no migration.
- Code-audit pair. The hidden
es-auditor-thesisseat maps invariants and the hiddenes-auditor-antithesisseat red-teams them with CWE ids.- The line-pointer law:
es_audit_verdictchecks every finding against the file on disk (it must exist inside the target, the lines must be in range, the excerpt must be verbatim). A hallucinated reference refuses the whole verdict. - Audits block. A phase audit holds the merge until it passes, and a failed one sends the phase back to the programmer. An open or failed path audit refuses the next stage transition.
- Splits go to the manager:
es_tiebreakgainsaudit. Only a human can dismiss an audit (es audit dismiss). - Each round writes
.factory/audits/<id>/{records,dossier}.jsonand a deterministicREPORT.md.
- The line-pointer law:
- OSS scout (
/scout). The scout plans, discovers (sharing darkharvest's search), scans (darkharvest's fail-closed license detection), checks OSV advisories (the responses are cached and cited) and records witnessed assessments. Core recomputes every verdict, keepingadoptonly for a verified, whitelisted, permissive license, flags severe advisories, ranks the candidates and writes.factory/scout/REPORT.md. Adoption stays a human decision. - CLI:
es audit <target>(plusshowanddismiss), andes scout "<feature>"(plusshow). Both are headless, honour STOP and the spend ceiling, and, with no run, start one at a terminal with--max-usd N. Agents cannot launch them from a shell. - A halted run now stops every seat tool except
es_status. Previously a seat's ownes_*tools kept running after a halt. - Fires. The deterministic
audit-firesandscout-firessuites run on the real host in CI. The same graders score the nightly model runs (evals/cases/*-fires.json; cases can now seed files). - New ENFORCED capability rows:
claims,audit,scout. Prompts:auditor-thesisandauditor-antithesisv1,scoutv1,factoryv4 → v5,managerv1 → v2. - When research completes, pruning the cache keeps every source that any dossier cites.
M3: rigor (#23)
- Domain packs, the full legacy port.
quant,biopharmaandlegalconstitutions (tier weights incl.__default__, negative-knowledge bonus, reject penalty, accept threshold, banned domains, mandatory tags, standard or zero-tolerance retraction), selected withconfig.domainPack(for examplees config set domainPack biopharma). With a pack active,es_research_completerejects claims that break the constitution — a banned source domain, a missing tag, a retracted source — and refuses a score below the pack's accept threshold; unknown packs fail closed. Without a pack nothing changes. Claims now carry their source URL, and the summary shows the active pack during RESEARCH. - All five fire suites are merge-blocking.
grill-fires(no deleted nodes, no silent settled edits, no round regress; deferred facts gate research),factory-gate(the build starts only through the approvals; STOP and the spend ceiling halt,es_statusstays reportable when halted) anddarkharvest-fires(core keepsdependonly for verified permissive licences, whatever the harvester proposes) joinaudit-firesandscout-fireson the real host. The same graders score the nightly model-backed runs. - Drift CI with a canary.
docs:checkalso fails on prompt, skill and registry drift: a prompt whose frontmatter id or seat disagrees with the registry, an orphaned prompt file or skill directory, a skill without itsSKILL.md, a spawn naming no agent, an unknownes_*tool, or a duplicate agent id. The canary proves every class is caught. - Queereye phases 02 and 03. The designer seat now renders the full
design surface under
.factory/design/(paths adapted from the legacy.queereye/):es_design_specs(phase 02): behaviour-first component specs forbutton,dialog,form-input,table,navandtoast, the pinned MITwebref.jsonsnapshot, the headlesscsf.jsonplay harness and deterministictui-notes.md, with drift, coverage, freshness and play-suite gates (check:truere-checks only).es_design_harvest(phase 03): the full skill-harvest ledger (harvest.json: rows, SPDX blocks, transitive closure, negative knowledge) with the fail-closed MIT/Apache-2.0/BSD-3-Clause/ISC whitelist, the skill bundle and the factory cite-gate receipt, which is verified against the live tokens and ledger. The bundle check script is TypeScript againstes-core; no Python is vendored.
- Post-audit hardening (shell control files). An adversarial audit found
that a non-seat agent could still write control files through interpreter
one-liners (
python3 -c,node -e, …), which the shell rule never matched. A control-file mention is now allowed in an agent's shell command only when the command is provably read-only (allowlisted segments; no redirection, here-doc or substitution); seats keep the stricter no-mention rule, and the forge test now covers the shell path. - Post-audit parity hardening. A parity audit against 0.7.25 found two
port drifts, both fixed:
NEGATIVE_KNOWLEDGEclaims keep a full-key hash (nkKey, sha256 of the cleaned pre-truncate query/finding pair) so distinct past-2k rows stay distinct in ids and scoring while the stored fields stay capped (legacy R11); and the pack constitution carries the legacy structural rules again (VERIFIED needs its hash + quote or a code location; INFERRED its reasoning; HYPOTHESIS its falsification; NK query and finding). The legacy INFERRED "parents non-empty" rule is documented as not applicable to 1.x REPORT.md claims. - System architecture doc.
SYSTEM_ARCHITECTURE.mdnow describes the pipeline, the seats, the claim flow and the trust invariants in one place.
1.0.5 — 2026-10-07
Run-lifecycle gaps from dogfooding 1.0.4 (#19):
es … --helpis now side-effect free on every subcommand: it prints usage and exits 0 without minting runs or writing files. Previouslyes factory begin --helpminted a phantomrun-…GRILL state./factorywith no run no longer dead-ends the agent: the command itself replies "No factory run here yet — run /grill first."- A missing or unsettled frontier now points at the recording step instead of
a bare "missing artifact" error:
approvalSubjectandes_request_approvaldirect the human to/grill(ores factory begin+ grill flow). No new write path: agents stay deny-write onfrontier.json, approvals stay human-only. factoryprompt v2 → v3: stop and route to/grillwhen<factory-state>reports no run.
1.0.4 — 2026-10-07
The 1.0 cutover replaces the Python research harness with the TypeScript
Epistemic Swarm monorepo (@heretek-ai/es-core, @heretek-ai/es-cli,
@heretek-ai/epistemic-swarm). This is a breaking, one-way change:
- No migration. Python-era
.research/and.factory/state is not imported. The legacy harness is preserved at thelegacy-finaltag (v0.7.25) and receives no further support after cutover. - The product is now an AI build factory: grill → research → spec → build
⇄ QA → release, enforced by a code state machine, hash-pinned gates, a
signed audit chain, a mandatory spend ceiling and a
.factory/STOPkill switch. Approvals, waivers and trust are human-only. - Delivery is OpenCode v2 first; the Claude Code (1.1), Pi (1.2) and Antigravity (1.3) adapters follow, each publishing capability-matrix rows with smoke tests.
- Platform: Linux, Node ≥ 22 or Bun. No Python.
- Darkharvest licence verdicts are fail-closed: permissive only on a full-text SPDX template match, every licence file and SPDX header counted, harvested content never executed and confined to the project for agents.
- Packages publish from
bun pm packtarballs (real versions, noworkspace:) thatscripts/pack-smoke.shinstalls and runs first.