Skip to content
GitHubBook a demo

How it works

Self-improvement

How 0 learns from past work and evaluates changes to itself, and where each change is allowed to take effect.

0 keeps memory from earlier work, benchmarks its own variants and evaluates proposed changes to detection workers. It is not an unattended loop that finds its own ground truth and rewrites itself. Each mechanism keeps observations, proposes a change, evaluates it against criteria you own, and selects an exact version for later work. A candidate’s own success claim is never an independent verifier.

Internal contracts (artifact schemas, registry events, worker protocol) live in packages/engine/src/improvement/.

NeedEntry pointDefault
Keep notes about a codebaseThe agent’s remember_codebase tool, or the Memory page in the browser appMemory is untrusted hints. Verifiers exclude them.
Benchmark variants and gate regressions0 lab improve bench runNeeds a labeled corpus.
Evaluate and promote a detection worker0 lab improve evolve run --config evolution.jsonSource access and auto-promotion are off.
Use an evolved finder in a review0 scan deep ./repo --evolution-config evolution.jsonOpt in per review.
Check task routing offline0 lab improve routing-qualifyFixture mode makes no API calls.
Evolve finder prompts from curated misses0 lab research lens-synthNeeds a curated corpus. Promotion needs approval.
Let the agent write its own toolsself_extend toolSee Plugins and Plugin security.

Model credentials pay for proposal generation. Guest images pay for execution. Neither replaces the other.

Open Memory in the browser app (/memory).

  • Memory entries are source-linked notes saved with remember_codebase in authorized local CLI and app threads. Before each model request, matching entries have their cited file hashes rechecked. Changed files and disabled entries are excluded. Matching bytes do not prove that dependencies, build flags or runtime are unchanged, so revalidate affected conclusions when those change.
Terminal window
0 memory list
0 memory disable <id>
0 memory export -o memory.json
0 memory import memory.json --preview

0 memory import always shows what would be imported first, and imported memories start disabled. These are the Memory page’s entries. False-positive and evaluation memories stay under 0 findings triage memory.

Finished threads stay history. They are not memory entries or vulnerability labels, and they are not model training. ZERO_DISABLE_HUNT_MEMORY=1 disables source memory.

Terminal window
0 lab improve learning status --json
0 lab improve learning process --limit 25 --json
0 lab improve learning evolve --config ./evolution.json \
--project /absolute/path/to/repo --json

All three use the local control database (ZERO_DB_PATH selects another one). --project <id> filters. Processing a local repo also imports its current source notes. The app processes pending work in small batches every five seconds, and the queue resumes after a restart. The default worker records activity without model calls. It does not spend provider credits on its own. learning evolve runs the source evolution below and mirrors its snapshots and receipts into the learning records. Its evaluations are labeled output-fixture. Passing expected-output tests does not show better vulnerability discovery.

Saving an automation creates an immutable revision. Each run keeps its original definition. Restoring an older revision creates a new one, and stale edits are rejected. A restored definition does not authorize new targets, tools or credentials. Schedules need review after a definition changes.

The app has no screen for reviewing automation changes proposed from run history. To go back to an earlier version, restore it from the automation’s Versions section. A good earlier run is operational evidence, not proof of better security.

Workbench VM threads can save bounded, source-linked memory on the host before teardown. A fresh VM requests current memory for its approved directory before model calls. Both sides check file hashes. Memory stays out of saved thread history and grant no permissions. Host memory stores, database handles and provider credentials are never sent to the guest.

The control database, queue and knowledge stay on the selected computer. Nothing is exported automatically.

Terminal window
0 lab improve bench run --integration core --variants ./variants.json --gate
0 lab improve bench diff <run-a> <run-b>
0 lab improve bench scoreboard --out ./scoreboard

bench run runs a variant tournament over a labeled corpus and records it in a ledger. Useful options: --integration core|xbow|cybergym, --manifest <path>, --pass-at-k <n>, --max-turns <n> (default 40), --cost-ceiling <usd> per attempt, --ci-subset, --ledger <path>, --format terminal|json. With --gate, the run exits non-zero if success rate drops more than --max-success-drop (default 0.05) or the false-positive rate rises more than --max-fp-rise (default 0.05) against the last green run. See Benchmarks.

Source evolution proposes edits to a copy of a source snapshot, runs them in a fresh Docker container or local smolvm guest, evaluates them, and keeps immutable versions.

Terminal window
0 lab improve evolve run --config ./evolution.json \
--allow-source-access --no-auto-promote --json
0 lab improve evolve status --store ./.evolution-store --json
0 lab improve evolve promote --store ./.evolution-store \
--version <candidate-id> --json
0 lab improve evolve exec --config ./evolution.json --run-id <id> \
--input '{"n":12}' --json
0 lab improve evolve rollback --store ./.evolution-store \
--version <active-version-id>
CommandEffect
runPropose, evaluate and optionally promote. --watch repeats passes, and --max-passes <n> bounds them. A failed pass stops the watch. Budgets accumulate only within that process.
statusActive, canary and parent versions, snapshot and receipt identities, registry events.
promoteRun the required canaries against the stored candidate and activate that exact version. It does not regenerate anything.
execRun a pinned snapshot in an isolated worker with no network.
rollbackRetire the named active or canary version and restore its parent. --version is the version to retire, not the destination.
reconcileSettle an interrupted dispatch from observed cost and an immutable receipt digest.
feedback capture, approve, status, releaseQueue evidence-backed observations, approve them with curated fixtures, and free a claim held by a stopped worker.

Exit code 0 does not mean a promotion happened. A run can keep rejected proposals or an awaiting_approval candidate.

evolution.json (schema version 1) needs a sourceRoot, a storePath outside it, a Docker image (evolution never pulls images), sourcePaths, editablePaths inside them, a command, an objective, computeUsdPerSecond, and cases. The cases are split into lanes: development, held-out and negative-control, each with at least promotionPolicy.minimumCases distinct cases (10 by default, 3 at the lowest). Budgets are maxModelCostUsd, maxEvaluationCostUsd and maxIterations. canaryTrials, repeats, allowModelSourceAccess and autoPromote are optional. The schema is packages/engine/src/improvement/config.ts.

A minimal config, which exercises the lifecycle and is not a security benchmark:

{
"schemaVersion": 1,
"sourceRoot": "./worker",
"storePath": "./.evolution-store",
"image": "node:22-alpine",
"kind": "source",
"sourcePaths": ["src"],
"editablePaths": ["src/checker.cjs"],
"command": ["node", "src/checker.cjs"],
"objective": "Classify every integer as even or odd; classify non-integer inputs as error.",
"allowModelSourceAccess": false,
"autoPromote": false,
"canaryTrials": 2,
"repeats": 3,
"maxIterations": 3,
"maxModelCostUsd": 5,
"maxEvaluationCostUsd": 5,
"computeUsdPerSecond": 0.0005,
"cases": [ "... at least 3 per lane, with id, lane, input and expected ..." ],
"promotionPolicy": { "minimumCases": 3 }
}

The low sample floor is for a demo only. Meaningful evaluation needs larger corpora curated independently of the model.

By default a candidate is rejected unless every check passes.

GateRequirement
Identity and artifactsCandidate ID matches the sealed result. Base and candidate artifacts have distinct SHA-256 digests.
ExecutionComplete, repeatable runs. Every case the baseline passed is kept.
EvaluatorIdentical evaluator digest before and after.
EvidenceAt least one retained evidence reference.
Sample sizeAt least 10 distinct cases per lane by default.
Development liftAt least +5 percentage points in success rate.
Held-out liftAt least +3 percentage points.
PrecisionNegative-control false-positive rate rises by at most 0 points.
CostFinite cost per success, at most 1.5 times the champion’s.

A passing source candidate still needs autoPromote: true or your approval. Promotion changes which worker future runs select. It never changes the process that is running.

Candidate code runs with a sealed input and explicit command, in a fresh container or guest, with no engagement credentials and no production-target network access. CPU, time, disk and model spend are bounded. Stdout, stderr, evaluator receipts and artifact digests are kept.

Terminal window
0 scan deep ./repo --evolution-config ./evolution.json

Each finder call in that review inherits the parent’s pinned snapshot. Verification and host policy are not rewritten. --models cannot be combined with --evolution-config.

0 lab research lens-synth evolves additive finder lenses from curated misses.

Terminal window
0 lab research lens-synth --miss-input ./misses.json --promote
0 lab research lens-synth --status
0 lab research lens-synth --rollback <lens-id>

Other options: --registry <path>, --max-register <n>, -m <model>, --watch, --poll-interval <ms>, --json. A promoted lens changes a prompt-backed detector for newly started hunts. It does not change FoxGuard’s compiled rules. Active hunts keep the lens they started with. Observation capture is not truth: source consent and curated positive, held-out and clean-control fixtures still gate synthesis.

PathWhat changesWhat stays fixed
Finder lens overlayNew hunts load promoted lens content.Active hunts keep their captured lens.
Source evolutionevolve run --watch --auto-promote selects a new accepted snapshot for later evolve exec runs.Existing run IDs keep their snapshot and config.
Evolved finderscan deep --evolution-config picks the active snapshot for each new review.Verification and host policy.
Skills and routerTraining installs exact authorized artifact bytes.A model already loaded in another process.
Executable pluginAn enabled agent submits or evolves code. Later calls use the active retained version.An invocation pins its version and declared capabilities. Admission is not measured improvement.
Development sourceA development console with allowDevSourceUpdates loads changed source between turns.The UI shell, injected clients and shared dependencies. A failed build or checkpoint keeps the current computer.
Live harness generationA session replaces its agent.driver and ui.view at a checkpoint.History and accounting survive. This is not durable campaign recovery.

Two of these run host code. The development source path needs a console started with ZERO_DEV_SOURCE_ROOT and the global allowDevSourceUpdates setting. It defaults off and a project cannot grant it. Workspace-trusted ESM for self-extension is a separate acknowledged grant. Neither grant gives sandboxed model-written code host access, and allowModelSelfExtension does not enable either one. See Configuration.

Rules that hold on every path:

  • Keep version identities, observations and receipts across changes.
  • Keep evaluation answers and credentials out of candidate snapshots.
  • Do not replay tool effects that were already issued after a driver fails.
  • Model-supported claims and model-only rejections stay unresolved in the shared hunt ledger.

Lifecycle checks measure orchestration. Provider behavior, sandbox execution and detection quality need their own checks.