Son of Anton Docs
Self-host

Upgrading

Inspect schema compatibility, drain publication authority, apply guarded migrations and verify the new runtime.

This procedure covers son-of-anton-review on feat/cloudflare-native. Use an authorized source revision and resolve the private-source/license prerequisites before acquiring or redistributing an upgrade. Do not blindly pull into a shared worktree or deploy the operator-parity tree as an engine replacement.

son-of-anton-operator-parity and anton-ui-trace-parity are separate Git worktrees with separate deployment contracts. The native main Worker does not gain their operator API or WorkOS UI through an engine upgrade. Record and assess those versions independently.

Before changing anything

  1. Identify the active engine revision, Worker/container versions, database bindings, publication mode, cron authority and any retained Node fallback. Source files are not proof of the active deployment.
  2. Review the target revision's config and schema changes. The checked-in native config contains estate-specific IDs and explicit live authority; preserve your own deployment settings.
  3. Back up durable state and publication receipts. On Node, use a SQLite-aware backup or stop all writers before copying database files, including any outstanding WAL state. For D1/R2, use the account's approved backup/export process.
  4. For publication, snapshot or lease-fencing changes, pause queue delivery while preserving accepted messages, then drain actual OMP instances and running leases. A Worker config change alone cannot stop existing containers. Coordinate cron writers separately.
  5. Have the integration owner complete release verification before production deployment. No source inspection establishes that a migration has run or a new image is healthy.

Schema inventory

Run D1 commands from the engine root with the explicit native config. First inspect the target, rather than guessing its generation:

wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --command "SELECT name,sql FROM sqlite_master WHERE name IN ('review_traces','review_trace_spans','publish_leases','finding_outcomes','cron_runs','cron_job_state','cron_artifacts','cron_dead_letters');"
FileEffect and guard
schema.sqlCreates base tables, trace schema/indexes, native dispatch fences, outcomes and policy/memory/SCM tables. Re-running does not alter existing table definitions. Does not create cron tables.
001-widen-trace-span-kind.sqlDrops/recreates both trace tables to support wider kinds and the newer columns. Destructive; only for the legacy trace schema after explicit approval and both row counts verified zero.
002-cron-parity.sqlCreates cron_runs, cron_job_state, cron_artifacts, cron_dead_letters and their indexes. Idempotent table/index creation; does not add publish_leases.created_at.
003-runtime-lease-fencing.sqlAdds insert/update triggers rejecting snapshots without the matching running dispatch lease. Re-runnable, but publication-affecting.
004-finding-outcomes.sqlAdds the outcome ledger and repo/evaluation index. Re-runnable.
005-trace-span-name-index.sqlAdds the span-name index used by budget/report queries. Re-runnable.

Fresh database

Use both base and cron schema files:

wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --file cloudflare-native/schema.sql
wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --file cloudflare-native/migrations/002-cron-parity.sql

Do not run migration 001 on a fresh/current database. Migrations 003, 004 and 005 are already represented in the current base schema.

Legacy trace tables

If schema inspection shows the old trace definition, drain writers and check both counts immediately before considering 001:

wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --command "SELECT (SELECT COUNT(*) FROM review_traces) AS traces, (SELECT COUNT(*) FROM review_trace_spans) AS spans;"

Stop if either table contains rows, the query fails, or the schema is uncertain. Migration 001 drops the tables and carries no executable guard. A populated legacy database needs a reviewed copy-forward migration; exporting rows does not make the provided destructive migration preserve them.

Only for a confirmed empty legacy schema, with the destructive change approved:

wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --file cloudflare-native/migrations/001-widen-trace-span-kind.sql
wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --file cloudflare-native/schema.sql
wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --file cloudflare-native/migrations/002-cron-parity.sql

The legacy span table lacks columns such as seq; applying the current schema first can fail at the index creation instead of upgrading it. CREATE TABLE IF NOT EXISTS is not a column migration.

Guard publish_leases.created_at

The current base schema includes this column for newly created tables. An existing old table still needs a separate guarded change:

wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --command "SELECT COUNT(*) AS has_created_at FROM pragma_table_info('publish_leases') WHERE name='created_at';"

Only if the table exists and this returns 0, add the nullable column. If it returns 1, skip the ALTER. Any other result/error is a stop condition.

wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --command "ALTER TABLE publish_leases ADD COLUMN created_at TEXT;"

Backfill only timestamps already evidenced by the row, then repeat the column guard:

wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --command "UPDATE publish_leases SET created_at=COALESCE(started_at,completed_at,failed_at) WHERE created_at IS NULL AND COALESCE(started_at,completed_at,failed_at) IS NOT NULL;"
wrangler d1 execute son-of-anton-review-state --config cloudflare-native/wrangler.jsonc --remote --command "SELECT COUNT(*) AS has_created_at FROM pragma_table_info('publish_leases') WHERE name='created_at';"

Require has_created_at=1 before deploying the consumer: its lease INSERT names this column. Rows without any historical timestamp remain null. Do not invent a current timestamp to hide unknown age, and do not use SQLite's unsupported nonconstant-default ALTER from older instructions.

For an already-compatible base database, apply any missing 002 through 005 files before deploying code that needs them. Use the same explicit --config, --remote and --file command form. Inventory/read back the expected tables, column, triggers and indexes; command exit alone is not a schema inventory.

Deploy and verify the actual image

After schema compatibility and draining are established, deploy the broker first if its code/config changed, then the main Worker:

wrangler deploy --config cloudflare-native/wrangler.key-broker.jsonc
wrangler deploy --config cloudflare-native/wrangler.jsonc

Preserve the OMP repo-root build context and both OMP/Sandbox bindings. Verify the intended container application/image versions as well as the Worker version before resuming delivery. Historical deployment receipts document rollout lag; they do not establish the current rollout state.

Trigger one approved canary with a new manual comment. Match its head SHA to D1 state and actual GitHub review/check receipts. Inspect the applicable trace spans and validation gaps using the native runbook. Do not require an invariant count of seven ok spans: optional lanes and policy/validation skips change the shape, and a successful operation trace does not prove the review found every defect.

The expanded /operator/api/* API is on the parity Worker, not native ingress. Use D1/logs unless a separately configured compatible operator service is available.

Timeout defaults

There is no single universal E2B timeout across the source paths:

Source pathUnset value or checked-in value
collectE2bValidationEvidence parameter default600000 ms (10 minutes)
DEFAULT_REPO_CONFIG.validation.e2b.timeoutMs2700000 ms (45 minutes)
defaultReviewLeaseSeconds E2B fallback2700000 ms, used to size a lease rather than execute validation
Native Wrangler varsExplicit GILF_E2B_TIMEOUT_MS=600000

The runner passes merged per-run/default validation settings into the E2B collector. A stored repo/run timeout can override the collector fallback and a current environment-derived default. Review both the environment and stored config; set the intended value explicitly rather than declaring every Node deployment “now ten minutes.”

There is a second mismatch worth checking: the runner's GILF_CODEX_TIMEOUT_MS fallback is 45 minutes, while the worker lease calculator's model-timeout fallback is 10 minutes. Choose explicit model/validation timeout and lease settings suitable for the deployment instead of treating their fallback calculation as a proof that no lease can expire mid-review.

Model and flag compatibility

For the current Node entrypoint, set GILF_CODEX_PROVIDER and GILF_CODEX_MODEL. It does not call resolveModelConfig() and therefore does not consume the modern helper's role overrides or per-provider defaults. The native entrypoint explicitly supplies GILF_MODEL_PROVIDER / GILF_MODEL instead. Confirm the model recorded by a new run, not only a dashboard selection indicator.

The native container allowlist does not forward swarm/planner, inversion or artifact flags. Adding Worker vars cannot enable those features. Likewise, changing native provider to Codex without replacing the image's placeholder with a real authenticated CLI cannot work.

Node upgrades

  1. Disable the worker schedule, let the current batch finish, and stop other writers before taking a consistent backup. Preserve the webhook-delivery plan during server downtime.
  2. Prepare the approved revision in an operator-controlled release directory; do not overwrite another worker's edits with a blind git pull.
  3. Use Node 25 and npm ci for that checkout. Preserve the service user's Git/gh authentication, protected App key and environment file, absolute DB/queue paths and workspace ownership.
  4. Review schema compatibility. SQLiteStore creates missing tables/indexes on construction; it is not a universal arbitrary-schema migration framework. Do not run the Cloudflare D1 migration files against the Node database.
  5. Start the intended server version, probe the listener, run one approved worker batch, inspect persisted failures and actual GitHub receipts, then restore the schedule. Worker exit 0 alone is insufficient.

See Run on a Node box for example units. No live publication safety comes from setting native-only GILF_PUBLISH_MODE on Node.

Rollback and receipts

A source rollback must remain compatible with the migrated schema and durable publication state. Migrations 002 through 005 are additive in schema terms, but removing lease-fencing expectations can still change behavior; do not assume any older image is safe.

For a model-only rollback, restore the approved model and matching price settings for the correct runtime, then verify a new run. To disable only E2B shadow validation, remove GILF_VALIDATION_SHADOW_EXECUTOR from native vars and redeploy; do not restart a second publisher.

For a full native-to-Node authority rollback, follow the ordered rollback procedure. Preserve uncertain publications and accepted work until reconciled.

Keep the source revision, migration/readback evidence, Worker and image versions, canary head, actual GitHub review/check IDs and trace ID in your approved release record. Runtime state, account entitlements, provider pricing and credentials cannot be verified from this source-only guide.

On this page