Skip to content

Verification & Anti-Lying Machinery

Vita's dominant systemic failure is not bugs β€” it is instrumentation lying: a surface that reports success it can't back, a fix claimed done that never went live, a working-memory file that recites a stale fact as current. The deepest form is recursive: shipped mitigations and completed-fix claims are themselves instruments that can lie.

This page collects the antibodies. They share one design rule:

A check that can cry wolf, or that reports clean when it can't actually tell, is itself a lying instrument. Every guard here either proves its claim or says it couldn't.

Status: active. Most legs run inside /sleep nightly; the deploy guards run inside ./run.

The standing rules these mechanize

Three calibration rules live in working memory and are enforced (or partly enforced) by code:

  1. A fix is not done at commit. An in-process fix to a ./run service requires restart + live re-check of the fixed path, same cycle.
  2. But an agent cannot restart the service hosting its own turn. Doing so tears down the process carrying the in-flight turn. Delegate the deploy.
  3. A fix is done only when verified against primary source or lived experience β€” and lived experience outranks the instrument.

Rules 1 and 2 are in direct tension, which is why rule 2 needed a mechanical guard rather than a prompt reminder.

Self-restart-kill guard

scripts/deploy/self_restart_guard.py, wired into ./run <svc> restart.

On 2026-07-19 an agent ran ./run api restart && ./run telegram restart to deploy its own just-committed fix β€” and tore down the bot hosting its in-flight turn. The turn self-cancelled mid-work, leaving the deploy in an indeterminate state (issue f4f04228; sibling c1edfe54, where a --wait client was SIGTERM-reaped and cancelled its own server-side job).

The guard detects the self-dependency before teardown using two independent signals, either of which fires:

  • VITA_HOST_SERVICE (comma-separated env stamp) β€” the forward-looking explicit signal, works with zero pidfiles.
  • Process ancestry β€” if the live pid in a service's ./run pidfile is an ancestor of the current process, that service hosts this turn. Works today with no stamping at all.

It also knows that ./run couples the two API processes: restarting either api or public-api bounces both, so hosting either makes restarting the other lethal.

Detection is fail-open by design. It refuses only when it can confidently prove the current turn is hosted by a service the restart would tear down. Any uncertainty β€” missing pidfile, unreadable /proc, internal error β€” allows the restart. A false positive merely delegates a restart that would have worked in-turn, which is safe; a false negative kills a turn.

$ ./run telegram restart          # from inside a telegram-hosted turn
Restart refused by self-restart-kill guard
(set VITA_ALLOW_SELF_RESTART=1 to override from an unhosted process).

Shipped 2026-07-24 (53b58c40d), 12 tests. The out-of-band delegated-deploy path β€” a queue an unhosted actor drains β€” remains unbuilt; today a refused restart tells the caller to delegate, and nothing drains automatically.

Code-freshness gate

scripts/verification/service_freshness.py β†’ is_service_fresh().

A committed fix is not live until the process reloads it. This gate compares the bytecode a running service holds against the source on disk and fails closed on doubt β€” if it cannot tell, it reports stale, not fresh.

Phase 3 wires code_fresh.* rows into the nightly data-source-health rollup, so a service sitting on a committed-but-not-loaded fix is visible without anyone remembering to check:

code_fresh.api: STALE β€” running process holds STALE bytecode (1 module,
e.g. scripts/utils.py) β€” a committed fix is not live; restart owed
(delegate, never self-restart mid-turn: f4f04228)

The two guards compose: the code-fresh gate tells you a restart is owed, and the self-restart guard stops you from performing it in a way that kills your own turn.

Fold-leg contract

scripts/sleep/fold_assertion.py.

data/executive/identity-state.md is the ambient working-memory file imported into every Claude invocation. /sleep's reflect step is supposed to fold each night's findings into it. On 2026-07-09 a completely clean /sleep run silently skipped the fold β€” the file rendered as freshly-maintained truth while carrying two-day-stale claims. The leg passed by attention, not structure.

The contract makes a silent no-op impossible. After reflect, identity-state must either:

  • have changed in content since the pre-sleep git snapshot (a content diff, not mtime β€” deliberately anti-Goodhart), or
  • the reflect output must carry an explicit honest no-op: "fold": {"status": "no-op", "reason": "one honest sentence"}

Anything else is a FOLD_MISS: the step fails loudly, a row lands in the ledger, and the result reaches the staging family the next night's reflect reads. Two consecutive misses set escalate=true β€” the standing rule being that two misses after a ship is a bug report, not a shrug.

A companion, check_fold_time_facts, fact-checks the fold's dated assertions against live sources β€” the sleep-gate state and the training-goal component set. A stale week-tally in the fold gets flagged, not just a dead pointer.

Deliberately deterministic Python, not agent prose, and explicitly not a writer: the reflect/revise passes keep sole write authority over identity-state.

Completion-claim auditor

scripts/audit/completion_claim_audit.py, staged nightly.

Measures how often executive-loop cycles claim a fix "done / verified / durable" without same-cycle primary-source backing, by joining cycle β†’ session β†’ Claude transcript (the only place the real tool sequence survives).

The interesting part is what it deliberately doesn't do. Retrospective measurement was chosen over an inline gate at the act step, for two reasons:

  • The mechanical detector's own precision is roughly 33% β€” it over-flags cycles that closed honestly or verified against a database.
  • It cannot catch the real failure. Cycle 284 grepped the actual exec log and still lied (issue 3a2786fd) β€” a proxy check that looks primary. An inline guard would just be a new lying instrument.

So the raw rate is never recited as a finding; flagged cycles are adjudicated against transcripts. Two advisory annotations speed that adjudication without being able to mask anything:

  • hedge_markers β€” explicit honest non-claims ("uncommitted", "deferred", "source-committed-not-live").
  • verification_markers β€” explicit named primary-source checks ("verified against the raw ledger").

Both are purely additive: they never change backed, the unbacked rate, or the flagged set. The worst list is deduped by topic, so one carried-forward item surfaces once with a topic_repetitions count rather than reading as N distinct lies.

Staleness detector v2

Part of /sleep's preprocess step. Audits the ambient instruction layer itself:

  • dated headers older than 14 days in ambient files
  • dead instruction-layer pointers (references to files that no longer exist)
  • ambient-size threshold (identity-state rides into every invocation, so bloat is a real metabolic cost)
  • semantic claim grading β€” the sleep-gate state asserted in prose inside identity-state is checked against the live gate, so a stale "gate BLOCKED/CLEAR" sentence gets flagged, not just a dead date
  • proposal header-status divergence β€” a proposal whose header contradicts reality (see the self-improvement loop)

Before 2026-06-10 the v1 report was written nightly and read by nothing β€” a lying instrument in its own right. It is now consumed by the reflect prompt with defined actions.

The detector was itself de-lied on 2026-06-24: the OODA-freshness watchdog false-alarmed on the normal overnight idle gap (the exec cron is idle by design between evening and morning, so the ~8h gap always tripped a 4h rule). Fixed to never alert overnight, plus a morning-grace cap, with 8 regression tests. An immune sensor that cries wolf is itself a lying instrument.

Render-side freshness contract

The largest antibody has its own page: Render-Side Freshness Contract. Where the mechanisms above verify claims about work, the freshness contract verifies numbers on surfaces β€” one shared rule that a figure whose source is missing, stale, or suspect renders "unknown", never a real value.

Its own build produced the sharpest instance of the recursive problem: the guard it was meant to add had already shipped a month earlier, with passing tests and no consumers. A primitive nobody calls is indistinguishable from no primitive.

Informed pre-send gate

Applies the same discipline to outbound claims. Before a proactive message asserts that bio-zack still owes something, the obligation is re-checked against live done-ness β€” and an unreachable source yields (status unverified), never a silent drop or a confident assertion. See Proactive Outreach.

Honest gaps

  • The delegated-deploy path is unbuilt: a refused self-restart tells you to delegate, but nothing drains a deploy queue out-of-band.
  • The completion-claim auditor is detection-only and low-precision by construction; it speeds human adjudication rather than replacing it.
  • The fold contract detects, it does not repair β€” a FOLD_MISS fails the step and surfaces next night; nothing re-runs the fold.
  • code_fresh.* rows are nightly, not real-time. A fix can sit committed-not-live for most of a day before the rollup notices.