UNI Universal Natural Intelligence

Wiki · Evidence & Verdicts

/lab-team-review MERGED VERDICT — 85b0e8c

Evidence & Verdicts · docs/receipts/lab_team_review_85b0e8c.md @ 44baf03d5041 (gen2-runtime) — opens the published snapshot ac338733bbba

How to read this page

Three ways to read this page. Precise is the document itself, exactly as it is written in the repository. Plain and Clear were written for this website to help you meet that document — they are about it. They are not it, and they are not evidence.

Eighty-seven dated pages: receipts, pre-registrations, handoffs, validation records and review verdicts. A receipt is written at the moment a piece of work was checked. It names what was claimed, the commit and the seed, what was actually run, and the outcome in one of a small set of controlled words. Then it names what the work did not achieve. That last part is what makes it a receipt rather than an announcement. A pre-registration is the same discipline run in advance: the conditions that would count as a pass and the conditions that would falsify the claim are written down before the run, so neither can be adjusted once the numbers arrive.

That is why so many small dated stubs are an audit trail rather than noise. No one of them is meant to be a good read. The value is in the sequence and in the dates, because you can watch a prediction be registered, then the run happen, then the verdict land — sometimes against the prediction. Pages here record a falsified result, a rejected fix, a retracted overclaim, and a green receipt that turned out not to be reproducible from the commit that carried it. A record that carried only successes would be worth a good deal less than this one.

A gentle way in is to read a pre-registration first, so the shape becomes familiar, then a result page, then one of the corrections. This section sits off the main navigation on purpose: it is the record you check the rest of the site against, not the place to begin.

What it is not: documentation, and not a summary. Nothing here has been tidied in hindsight. Every entry reads as of its date, a later entry may overturn an earlier one, and the presence of a page is not a claim that its result stood.

Your browser cannot switch reading levels, so the document itself is shown.

Precise — the source document

This is the document. Rendered from the repository at the commit above, with nothing rewritten for the web. A gate re-renders it on every deploy and fails the build if a single byte differs.


verdict: FAIL evidence_class: C

/lab-team-review MERGED VERDICT — 85b0e8c

  • HEAD SHA: 85b0e8c418d9f4adfbc56bcc9f932132247def69
  • Mode: real (5 independent persona agents reading live repo state — not the scaffold's dryrun template)
  • Runner: manual pass by the OS-agent session (runs/lab_team_review.exs remains scaffold-only; MODE=api is unimplemented, MODE=dryrun only emits placeholders)
  • Spec reviewed: production/mcp/SPEC_uni_self_audit.md (C-C2)

Files reviewed

  • production/mcp/SPEC_uni_self_audit.md
  • production/mcp/server.py
  • lib/sp/runtime/on_chip.ex
  • production/schemas/envelope.schema.json
  • production/schemas/claim_fence.json
  • CLAUDE.md
  • docs/GATES.md

Persona verdicts

math-breaker (Falsifier), lab-team-review panel — docs/lab_team/01_math_breaker.md

  • Verdict: REVISE
  • Rationale: Ran the gauntlet against SPEC_uni_self_audit.md with the actual source files it names, per persona rule 'default verdict is REJECT, earn SIGN.' What checks out: MUTATING_TOOLS (server.py:247-260) genuinely is the single-source-of-truth gating set the spec assumes, approvals.require()-first-then-audit-write is the real mutating pattern, and the underlying novelty_gain FE term itself is not being re-litigated here — it is already gated/reviewed per the Phase-1 novelty precedent (commit 903f885) and genome.ex's default-0.0/byte-identity discipline, so this is not a fresh reward-smuggling or decay-proof problem. What fails is check 1 of the gauntlet ('locate the term, name the slot — where does this number actually come from') applied to the tool's DATA PLUMBING rather than its FE math: the spec's own 'Sources' section (lines 74-78) is demonstrably wrong for on_chip (OnChip.info/0 returns a different key set entirely) and for kins[] (Board.all()/Mind.of() carry none of novelty_gain/genome_lineage/active_organs — two of those three fields require reaching into brain.dna via a different, heavier probe mechanism the spec never names, and genome_lineage has no storage representation anywhere in the codebase to source from at all). Compounding that, the one artifact that most needs a determinism falsifier under this repo's own TRUE-signal/ARBOR discipline — board_snapshot_hash — gets none (no canonicalization spec, no named test), and the memory-sha determinism test that IS promised does not cover the real risk (a torn read racing MC.save/2's non-atomic File.write!). Finally the spec's headline conformance claim — 'conforms to envelope.schema.json' — is checkably false against the only envelope-builder that exists in server.py today (metadata() emits an entirely different top-level shape than the schema requires with additionalProperties:false). None of this is a fundamental math violation (no invariant broken, no reward-smuggling, no unbounded term) — every failure is a fixable provenance/spec-completeness gap — so REJECT is not warranted. But the spec as written cannot produce its own example payload from the sources it cites, and its own promised tests would not catch that. That is a REVISE: rewrite the Sources section against the real read paths (including whatever new probe mechanism is needed for dna-level fields, and its cost/blocking tradeoff vs the O(1) board read), specify board_snapshot_hash's exact canonicalization + a determinism test for it, and either fix or explicitly scope-out the metadata()/envelope.schema.json divergence before this ships.
  • Concerns:
    • Envelope-conformance claim is checkably false against the file it cites. SPEC_uni_self_audit.md:24 says the result 'conforms to production/schemas/envelope.schema.json' and the test list (line 89) promises 'assert result shape validates against the envelope schema.' envelope.schema.json requires top-level {schema_version, envelope, result} with additionalProperties:false (envelope.schema.json:8-9, 41-45). The only envelope-builder in production/mcp/server.py — metadata() (server.py:91-118), which every existing read-only tool calls — emits a flat {ok, tool, data, evidence_class, provenance, help, docs} shape with no schema_version key and no nested envelope/result keys. If uni_self_audit registers the same way every sibling tool does (which the spec's own Registration section assumes), the promised conformance test fails against the real metadata() output. envelope.schema.json:5 even claims to be 'Extracted verbatim from production/mcp/server.py:91-118' — that is false against current code. This is pre-existing drift the spec ships forward uncorrected instead of naming.
    • kins[] provenance is invented, not sourced from what the spec cites. SPEC_uni_self_audit.md:76 says 'kins: iterate SP.Runtime.Board.all/0, filter kin rows.' Board.all/0 (lib/sp/runtime/board.ex:29-34) returns rows built by Agent.publish/1 (lib/sp/runtime/agent.ex:404-416) = Map.merge(Mind.of(brain,senses), %{username,kin,mode,senses,action,count,phase}); Mind.of/2 (lib/sp/runtime/mind.ex:19-30) returns only {context,stress,emotion,confidence,focus,intent,report}. None of novelty_gain, genome_lineage, or active_organs appears in that row anywhere. novelty_gain lives on %SP.Brain.Model{} (model.ex:35, a per-factor sub-model struct — plan.ex:92 reads it per-sub as ng = Map.get(sub, :novelty_gain, 0.0)) and is elsewhere read via a live :sys.get_state probe on the agent process (docs/observability/COLLECTOR_RCON_BRIEF.md:186, 'probe:34') — a different, heavier, blocking mechanism than the O(1) ETS board read the spec cites, and that same doc (collector.md:241) already flags cross-layer novelty_gain disagreement as an 'arm-integrity alarm,' i.e. the team already knows this value is not a clean, single, cheaply-readable scalar. active_organs requires Genome.active_organs(brain.dna) (genome.ex:497) — also dna, not Board. genome_lineage has NO backing field anywhere in the codebase at all: genome.ex has no lineage/genome_lineage key, and SP.Runtime.Lineage (lineage.ex) tracks a kin-group process's generation/fitness archive, not a per-agent genome-constructor tag like 'homeostat_colony'. As specified, the tool cannot produce its own example JSON (SPEC_uni_self_audit.md:37-47) from the sources it names — 3 of 4 kins[] fields have no existing read path, and 1 of those (genome_lineage) has no storage representation to invent a read path FOR.
    • on_chip/jit_flavor do not match SP.Runtime.OnChip.info/0's actual shape. info/0 (lib/sp/runtime/on_chip.ex:20-28) returns %{emu_flavor:, schedulers_online:, logical_processors:, dirty_cpu_schedulers:}. The spec's example (SPEC_uni_self_audit.md:29-36) shows on_chip: {emu_flavor, system_architecture, erts_version, otp_release, elixir_version, smp_support} — four of six keys (system_architecture, erts_version, otp_release, elixir_version, smp_support) do not exist in info/0 at all, while the three keys info/0 actually returns beyond emu_flavor (schedulers_online, logical_processors, dirty_cpu_schedulers) are silently absent from the spec's example. Top-level jit_flavor also isn't a key info/0 returns (it nests emu_flavor inside the map, not jit_flavor at top level). Per the explicit ask: OnChip.info/0 exists, but not with the claimed shape — every other field would have to come from ad hoc :erlang.system_info/1 calls the spec never names.
    • board_snapshot_hash names no canonicalization and carries no falsifier — gauntlet check 8 (paired RED demand) fails outright for this term. SPEC_uni_self_audit.md:76 says only 'sha256 of a stable serialization of the Board snapshot at the call moment' — no serialization format (JSON vs :erlang.term_to_binary), no key-ordering rule, no float-formatting rule, and no stated scope (all Board.all() rows including non-kin/Director rows, or only the kin-filtered subset used to build kins[]?). The Test-coverage section (SPEC_uni_self_audit.md:89) promises a determinism test only for 'memory sha computation,' never for board_snapshot_hash — the one artifact in the payload that most resembles a Merkle-style commitment (directly adjacent to this repo's own ARBOR/Tree-of-True TRUE-signal ledger discipline per root CLAUDE.md §2) ships with zero named falsifier for its own determinism. Two spec-compliant implementations could produce different hashes for identical board state and neither would be 'wrong' by the spec as written.
    • memory_bin_sha256 'determinism' claim ignores an actual torn-read race in the save path it's hashing. SP.Brain.MC.save/2 (lib/sp/brain/mc.ex:552-554) is File.write!(path, :erlang.term_to_binary({brain.dna, brain.model})) — a direct, non-atomic, in-place write (no temp-file + rename) — invoked from each agent's own tick loop on a periodic cadence (lib/sp/runtime/agent.ex:185,195,251,259,310,318,358, gated by rem(count, state.save_every)==0 or at stop/death). uni_self_audit iterates every live kin and reads+hashes each .bin off disk (SPEC_uni_self_audit.md:76) with nothing serializing that read against a concurrent in-flight save/2 on the same path; a read landing mid-write hashes a torn/truncated file. The one test the spec promises ('memory sha computation is deterministic,' SPEC_uni_self_audit.md:89) reads as hash(bytes)-is-a-pure-function-of-bytes — trivially true and not the actual risk. The real claim needing a falsifier — 'the reported sha256 always matches what an independent reader gets from the same .bin under concurrent saves' — is unstated and untested.
    • Secondary/minor, fold into the same revision pass: 'Add uni_self_audit to the read-only tools (not MUTATING_TOOLS)' (SPEC_uni_self_audit.md:68) undersells the actual registration mechanism. MUTATING_TOOLS (server.py:247-254) genuinely is the single source of truth for gating, confirmed accurate — that part of the spec's assumed pattern checks out. But there is no parallel READ_ONLY_TOOLS collection; read-only status is implicit (simply not in MUTATING_TOOLS) plus a separate hardcoded literal read_only = {...} set inline inside _verify_tool_consistency() (server.py:928-932) that a boot-time self-check (server.py:922-945) diffs against help_mod.TOOL_HELP. Decorating the new function without also adding its name to that literal will make create_server() raise RuntimeError (extra_help mismatch) at boot. Worth one sentence in the spec so the implementer doesn't hit it live.

aif-core-theorist (docs/lab_team/02_aif_core_theorist.md)

  • Verdict: REVISE
  • Rationale: Independent read of server.py, on_chip.ex, board.ex, on_chip_test.exs, envelope.schema.json, claim_fence.json, and both CLAUDE.md/GATES.md against SPEC_uni_self_audit.md. What checks out: the read-only-tools / MUTATING_TOOLS / HUMAN_GATED gating pattern the spec assumes for registration is real and correctly described (server.py:235-260, 916-945, 928-932) -- adding uni_self_audit to the read-only set with no approvals wrap is structurally sound, though no colony/board-domain tool exists there yet to model it on. evidence_class="C" is schema-valid, and the result JSON's field names/values (colony_gate, phoenix, kins, board_snapshot_hash, verdict strings) do not trip claim_fence.json's regex families -- no smuggled proof/consciousness/life/experience/over-claim tokens in the actual payload. colony_gate and phoenix sourcing (shell to verify_colony.cjs, HTTP GET producer/health) are correctly named and match CLAUDE.md's own documented gates (CLAUDE.md:99-108) verbatim. But the spec cannot ship as written: its "Sources" section -- the epistemic backbone of a tool whose entire purpose is honest self-attestation -- is factually wrong for on_chip (proven against both on_chip.ex and on_chip_test.exs), unverified for kins/board_snapshot_hash, and names no transport mechanism at all for reaching the Elixir runtime from the Python MCP process. Layered on top, the prose framing ("the being narrates its own state," "ask UNI what is your state") personifies a health-check-and-hash dump in a way the mechanical claim fence does not catch, and a raw novelty_gain float ships to anonymous public callers with no interpretive guard. None of this is a fundamental-idea problem -- a read-only, evidence-class-C, ungated self-attestation verb is a good and well-fitted addition to this architecture -- but the spec needs its Sources section corrected to what the cited functions actually return (or the functions/bridge extended to match), a named Python<->BEAM transport for on_chip/kins, the "being narrates" framing tightened to match the claim-fence discipline already binding on this repo's docs, and a decision on novelty_gain's public exposure, before it is ready for another review pass.
  • Concerns:
    • FABRICATED SOURCE SHAPE (hard finding): SPEC_uni_self_audit.md:74 claims on_chip is sourced from SP.Runtime.OnChip.info/0 (existing in lib/sp/runtime/on_chip.ex). It does not match. Real info/0 (on_chip.ex:21-28) returns emu_flavor, schedulers_online, logical_processors, dirty_cpu_schedulers. The spec's on_chip block (SPEC:29-36) is emu_flavor, system_architecture, erts_version, otp_release, elixir_version, smp_support -- only emu_flavor overlaps; the other five fields do not exist on the cited function and the three real fields are silently dropped. Confirmed independently against test/sp/runtime/on_chip_test.exs:22-28, which only ever asserts info.emu_flavor and info.schedulers_online. A self-attestation tool whose own 'Sources' section misdescribes its source is not a nit -- it is the thing the tool exists to get right.
    • UNGROUNDED TOP-LEVEL FIELD: SPEC:28 "jit_flavor": "jit" at the result's top level has no corresponding producer anywhere in on_chip.ex. OnChip.jit?/0 returns a boolean, not the string "jit"; there is no function returning a jit_flavor key. This looks invented, duplicating (and diverging in name/type from) on_chip.emu_flavor.
    • NO NAMED TRANSPORT for two of five sources: production/mcp/server.py is the Python FastMCP process; SP.Runtime.OnChip.info/0 and SP.Runtime.Board.all/0 live in the Elixir BEAM. Unlike colony_gate and phoenix (SPEC:77-78), which correctly name a concrete mechanism (node viewer/verify_colony.cjs, HTTP GET :4000/producer/health), the Sources section (SPEC:74-76) states on_chip/kins/board_snapshot_hash as if the Python tool can just call the Elixir functions directly. Grepping lib/ and production/mcp/ turns up zero HTTP route, RPC bridge, or shell-out for either function -- 'self_audit' appears nowhere outside the spec and docs. This is a missing integration design, not an implementation detail.
    • UNVERIFIED 'kins' SHAPE: lib/sp/runtime/board.ex:6-8,29-34 documents Board.all/0 as returning whatever generic row 'every live agent writes into' ('a primitive snapshot of its situation + mind beat') -- board.ex itself defines no kin-specific schema. The spec's claim that 'filter kin rows' (SPEC:75) yields objects with genome_lineage/active_organs/novelty_gain/memory_bin_path/memory_bin_sha256 (SPEC:38-46) cites no publisher that actually writes those fields into the board. Softer than the on_chip finding but still an unverified sourcing claim in a spec whose entire job is sourcing accuracy.
    • FRAMING OVERCLAIM THAT SLIPS THE MECHANICAL FENCE: SPEC:11 calls the tool 'the being narrates its own state,' and SPEC:93 frames the public output as what a stranger sees 'when they ask UNI "what is your state right now?"'. This personifies a JSON dump of JIT flags, scheduler counts, health-check verdicts, and file hashes as first-person self-narration -- exactly this persona's Guarded Failure Mode ('Overclaiming awareness: treating a behavioural/organisational measure as evidence of experience', 02_aif_core_theorist.md:28) and CLAUDE.md's own instruction not to surface floats/gate outputs 'as felt states' (CLAUDE.md:135-136). I checked claim_fence.json's token families (proof/consciousness_family/life_family/experience_family/over_claim_family) against this prose: 'being' and 'narrates' are not in any of them, so this framing passes the mechanical fence cleanly while carrying the overclaim the fence exists to catch. The field NAMES/VALUES in the actual result JSON (SPEC:26-64) are clean of fence tokens -- that part is fine -- but the prose framing around the tool is not, and that framing is what will get copied into public docs/stream commentary.
    • novelty_gain EXPOSED RAW ON THE PUBLIC SURFACE WITH NO GUARD: SPEC:42 puts novelty_gain (a Dirichlet parameter-information-gain / W term) into the result, and SPEC:91-93 confirms the identical shape ships on get_self_audit() under uni-public-mcp to anonymous callers. This persona's Guarded Failure Mode #2 is explicit: 'Conflating novelty with preference. A parameter-information-gain term is information, not C.' A bare float labeled novelty_gain, handed to a stranger with zero interpretive text, is an open invitation to read it as curiosity/exploration/awareness -- the spec should either annotate the field's meaning inline or exclude it from the public variant.

systems-architect

  • Verdict: REVISE
  • Rationale: What checks out, cleanly: the gating instinct is right. MUTATING_TOOLS is genuinely documented as the single source of truth for gating (server.py:234-236), the read-only sync + @_threaded pattern (server.py:424-539, e.g. get_show_state/list_sources/approvals_pending) is the real, live pattern for no-approval tools, and the spec correctly keeps uni_self_audit out of MUTATING_TOOLS with no approvals wrap. The Non-goals section (no mutation, no secrets) is consistent with that same read-only family. This isn't an FE-term touching the A/B/C/D/E POMDP engine or the depth-5 Plan decider, so the architect's usual byte-identity / additive-genome-organ / no-Nx checklist doesn't apply here -- correctly, this is a tooling/MCP-surface change, and I scoped the review to server.py's own contract instead, per the task's focus list.

Where it doesn't check out is structural, not cosmetic. Two of the spec's four declared data Sources (OnChip.info/0, Board.all/0) either don't have the claimed shape or have no stated transport from this Python file into the Elixir/BEAM colony process at all -- and this file's only existing adapters (obs/overlays/tts/livekit) are studio-side, not colony-side. The envelope-conformance claim -- the exact thing I was asked to check -- fails against the server's own documented, universal metadata() contract, which every other tool in this file uses. And the registration instruction points at a file both the code and PRODUCTION_MCP_SPEC.md call 'not deployed,' with the real runtime module absent from the repo. Layer the cross-spec rate-limit contradiction on top and this isn't a same-day patch list -- the Sources section needs to be rewritten against what actually exists (or OnChip.info/0 extended first, as its own reviewed change), the transport to the colony's BEAM process needs to be named, and the envelope-shape question needs an explicit answer before this is buildable. Can this be validated without touching Minecraft? Only the shell-out and HTTP-GET sources can; the two Elixir sources currently cannot be validated at all because there's no code path to them yet.

  • Concerns:
    • envelope.schema.json non-conformance: production/mcp/server.py's actual metadata() helper (server.py:91-118, confirmed verbatim by PRODUCTION_MCP_SPEC.md:104-125 as THE fixed contract for this exact server) returns top-level {ok, tool, data, evidence_class, provenance{server,version,git_commit,timestamp}, help, docs, audit_id?}. envelope.schema.json (production/schemas/envelope.schema.json:6-46) requires top-level {schema_version, envelope{server,instrument_version,timestamp,evidence_class,...}, result} with additionalProperties:false at both levels -- structurally incompatible key names AND structure. Every one of the 25 existing tools in this file returns the metadata() shape, which today would fail envelope.schema.json validation. SPEC_uni_self_audit.md:24 claims uni_self_audit 'conforms to envelope.schema.json' but names no wrapper/adapter that bridges metadata()'s real shape to the schema's shape, and doesn't flag that it would be the first tool in the file to diverge from the established pattern.
    • SP.Runtime.OnChip.info/0 shape mismatch: the real function (lib/sp/runtime/on_chip.ex:20-28) returns %{emu_flavor, schedulers_online, logical_processors, dirty_cpu_schedulers}. SPEC_uni_self_audit.md:29-36's on_chip object claims {emu_flavor, system_architecture, erts_version, otp_release, elixir_version, smp_support} -- only emu_flavor actually exists on OnChip.info/0 today; the other five fields are invented. Confirmed: OnChip.info/0 exists but does not have the shape the spec claims.
    • kins[] sourcing is ungrounded: SPEC_uni_self_audit.md:76 cites SP.Runtime.Board.all/0, filtered to kin rows, as the source. The real board row (built in lib/sp/runtime/agent.ex publish/1, agent.ex:404-415) is %{username, kin, mode, senses, action, count, phase} merged with SP.Runtime.Mind.of/2 output. There is no genome_lineage, active_organs, novelty_gain, memory_bin_path, memory_bin_sha256, memory_bin_size_bytes, or last_saved_utc on a board row -- kin itself is a bare integer, not the "id":"UNI-9-2" string shown in the spec's example. genome_lineage is a spawn-time string (agent.ex:210, e.g. "homeostat_colony") that is never published to the board, and any memory .bin artifact is a lineage/population-level concept (nearer SP.Runtime.Lineage, which the spec never names), not a per-board-row field.
    • No Python->Elixir transport exists for 2 of the 4 declared sources: production/mcp/adapters/ contains only obs.py, overlays.py, tts.py, livekit.py -- all Windows/THINKER studio-side integrations. Nothing in this tree calls into the BEAM colony process. This repo's own scripts that read SP.Runtime.Board.all/0 (runs/probe_colony.exs, runs/sample_surface.exs) do it via :rpc.call(node, SP.Runtime.Board, :all, []) from a peer Erlang node with a shared cookie and distributed-Erlang connectivity -- not from Python/FastMCP. SPEC_uni_self_audit.md's Sources section (lines 74-76) names SP.Runtime.OnChip.info/0 and SP.Runtime.Board.all/0 as if this Python tool calls them in-process, with zero mention of the bridge (RPC shim? new Phoenix HTTP endpoint? subprocess elixir --sname invocation?). This is the largest architectural gap: half the declared data sources have no stated, or existing, path from this file to the data.
    • Registration target is explicitly non-deployed reference code: server.py's own docstring (server.py:24, 'DESIGN / REFERENCE only -- not deployed') and PRODUCTION_MCP_SPEC.md:5 ('Status: DESIGN / REFERENCE (v1). Nothing here is deployed') both say so; the real runtime path imports services.control_mcp when importable (server.py:51-56), and that module does not exist anywhere in this repo (verified: no services/control_mcp directory). SPEC_uni_self_audit.md's 'Registration in production/mcp/server.py' (line 66) names only the reference mirror and never addresses the actual deployed twin -- landing this change here alone does not make uni_self_audit live on any running MCP.
    • Rate-limit contradicts its own sibling spec for the identical proxied tool: SPEC_uni_self_audit.md:70/89/93 states '1 call / 5s / source' for the public-surface get_self_audit() proxy. SPEC_uni_public_mcp.md:72 -- the spec that actually defines get_self_audit() -- states 'rate-limited to 1 req / source / 30s', while that same file's own general server-wide limit is '1 req / source / 5s' (SPEC_uni_public_mcp.md:17) and its red-team gate explicitly asserts '429 after 1 req in 5s' (SPEC_uni_public_mcp.md:86). Three different numbers for one tool across two specs; whichever ships, the other document's stated number/test is wrong and needs a reconciling edit.
    • Minor coupling gap: server.py's _verify_tool_consistency() (server.py:922-945) raises RuntimeError at server build time unless every tool name in read_only ∪ MUTATING_TOOLS ∪ SESSION_UNGATED has a matching key in help_mod.TOOL_HELP (production/mcp/help.py). SPEC_uni_self_audit.md's registration note (lines 66-70) never mentions this mandatory help.py entry -- a real mechanical requirement of the exact pattern it says it's following, not optional polish; omitting it means the server fails to boot.

red-experimentalist

  • Verdict: REVISE
  • Rationale: Verdict is REVISE, not SIGN_WITH_CHANGES, because the defects sit in the load-bearing part of the spec -- the Sources section -- not in cosmetic edges. Two of the six kins[] fields (genome_lineage, and by extension the whole per-kin block) and four of the six on_chip fields have literally no source anywhere in the codebase that matches what the spec claims to read them from (SP.Runtime.OnChip.info/0 and SP.Runtime.Board.all/0, both read directly). That's not a wording nit to fix inline; it means the spec's central claim -- 'the being narrates its own state' from real sources -- is currently unbuildable as specified without either extending upstream modules (Board rows, OnChip.info/0) to actually carry that data, or naming a genuinely different source. Either fix is itself a design decision that belongs in the spec, pre-registered, before implementation -- which is exactly this persona's job to insist on before a build starts.\n\nOn the specific assignment (is the named test sufficient; does this need a paired RED launcher): the answer to the RED-launcher half is no, and that's the one part of the spec that's fine as designed. uni_self_audit is read-only, mutates nothing, and triggers no phase/gate transition, so there's no causal 'cure' to isolate with a matched kin-10/kin-11 control across N>=3 seeds -- that whole apparatus doesn't apply to a pure introspection verb, and I'd flag it as scope-creep if someone proposed one. But 'no paired RED launcher needed' does NOT mean 'no falsification discipline needed'. The read-only analogue of an ablation is a provenance/flip test -- pin the underlying source to a known state, prove the reported field moves with it -- and that discipline is exactly what's missing from the three-assertion test file named in the spec. As scoped, the named test can pass on a fabricated-but-schema-valid implementation, which for a self-attestation verb is the single worst failure mode there is. Once the Sources section is corrected to name real, reachable data (or the spec explicitly proposes the small upstream extensions needed to make Board/OnChip.info carry it) and the test list gains field-provenance + degraded-mode + cross-check-against-verify_colony.cjs cases, this is a straightforward SIGN.
  • Concerns:
    • on_chip Sources claim is false as written. Spec line 74 says jit_flavor+on_chip come from SP.Runtime.OnChip.info/0 ('existing in lib/sp/runtime/on_chip.ex'). I read that file: info/0 (on_chip.ex:20-28) returns exactly %{emu_flavor, schedulers_online, logical_processors, dirty_cpu_schedulers}. The spec's own example (SPEC_uni_self_audit.md:29-36) claims on_chip carries system_architecture, erts_version, otp_release, elixir_version, smp_support -- none of those four keys exist in info/0, and no other source is named for them anywhere in the spec. Built literally, someone hand-types those four fields to make the example match -- fabrication dressed as self-attestation, which is exactly the failure mode a 'the being narrates its own state' verb cannot afford.
    • kins[] fields have no real source. Spec says 'iterate SP.Runtime.Board.all/0, filter kin rows' to get genome_lineage, active_organs, novelty_gain, memory_bin_path, memory_bin_sha256, last_saved_utc. I traced the actual publish path: agent.ex:405-413 (publish/1) merges SP.Runtime.Mind.of/2 (mind.ex:19-31: context/stress/emotion/confidence/focus/intent/report) with username/kin/mode/senses/action/count/phase. None of the six kin-metadata fields are on a Board row -- not one. novelty_gain/active_organs live on the (unpublished) brain.dna genome struct; the .bin path convention lives in SP.Runtime.Lineage (lineage.ex:133 -- runs/colony/kin-#{kin}.bin, which does match the spec's example path, so that piece is at least the right convention, just attributed to the wrong source). genome_lineage as a field name has zero hits anywhere in the repo outside this spec (repo-wide grep). Genome constructors (Genome.homeostat_colony/0 etc., genome.ex:171-392) don't tag the struct they build with their own name, so nothing currently exists that could populate it truthfully.
    • Two sibling specs contradict each other on the public rate limit for the same tool. SPEC_uni_self_audit.md:70 says 'rate-limited on the public MCP surface... 1 call / 5s / source'. SPEC_uni_public_mcp.md:72 (the spec that actually owns the public surface and proxies this exact tool as get_self_audit()) says 'rate-limited to 1 req / source / 30s'. These need to agree before either ships; right now neither reviewer can tell which number is authoritative.
    • The Signature block doesn't match the pattern this same server.py actually uses for every read-only tool. All nine existing read-only tools (server.py:424-539: get_show_state, list_sources, list_scenes, list_clips, list_segments, list_guests, caption_status, approvals_pending, approvals_status) are declared @mcp.tool(structured_output=True) immediately followed by @_threaded (server.py:396-406, an async shim that runs the body via asyncio.to_thread so the FastMCP event loop isn't blocked). The spec's Signature (lines 16-17) shows bare '@mcp.tool()' with neither structured_output=True nor @_threaded. Per the spec's own Sources section, uni_self_audit shells out to a subprocess (node viewer/verify_colony.cjs), does an HTTP GET (producer/health), and sha256-hashes one-or-more kin .bin files (the sibling SPEC_uni_housekeeping_status.md's own kin_memory example shows counts like 12 files) -- exactly the blocking I/O @_threaded exists to move off the event loop. As written this would block the server on every call.
    • Registration is not an abstract 'read-only tools' bucket you add a name to -- it's three concrete places in this file that must move together: the @mcp.tool function itself, the literal read_only = {...} set duplicated inside _verify_tool_consistency() (server.py:928-932, which raises RuntimeError at server-build time if TOOL_HELP drifts), and a bijective entry in help.py's TOOL_HELP dict. The spec's one-line registration note ('Add uni_self_audit to the read-only tools (not MUTATING_TOOLS)') names none of these three, and the one named test file doesn't exercise _verify_tool_consistency() either -- so a reviewer reading the spec + test list alone cannot see that this safety net is even in scope.
    • Testability verdict on the named test itself: test/production/mcp/uni_self_audit_test.py (spec lines 87-89) as scoped -- 'result shape validates against the envelope schema, memory sha computation is deterministic, rate limit fires on the public surface' -- is NOT sufficient, and it's insufficient in exactly the way that matters for a self-attestation verb. All three assertions are mechanical/shape checks; none of them pin the underlying source to a known state and assert the emitted field tracks it. Given findings 1-2 above (on_chip and kins fields have no real source for several of their claimed keys), an implementation that hardcodes schema-valid-looking values would PASS every named test while fabricating half of what it claims to observe. Missing test cases: (a) field-provenance tests per section -- stub SP.Runtime.Board with a fixture row, stub OnChip.info/0, stub the verify_colony.cjs subprocess and the producer/health HTTP call, and assert each emitted field is DERIVED from that fixture, not a literal; (b) a flip test -- change one fixture value (e.g. drop RCON player count by one) and assert the corresponding output field and verdict actually change, proving the field is live-wired and not a constant; (c) a degraded-source test -- kill one of the four external dependencies (subprocess fails / HTTP times out / a kin .bin is missing) and assert a named, honest partial-failure shape (every other read-only tool in this file has an explicit try/except -> ok=False, evidence_class='pending', how_to_fix=... on failure, e.g. server.py:428-446, 452-456, 480-489; the spec names no equivalent contract for uni_self_audit and shows only the all-green example); (d) a cross-check test against the same independent authority the tool itself shells out to -- run viewer/verify_colony.cjs directly against a fixture/mock host and assert uni_self_audit()'s colony_gate section agrees byte-for-byte with that direct run, since verify_colony.cjs's own header names the exact divergence bug (2026-07-11 colony_count 0/2/3 vs 19-20 real bots) this tool would silently reproduce if it drifts from its own cited source.
    • No FALSIFIES condition is registered for the audit's own trustworthiness, even though this repo's root CLAUDE.md ('Heavy science-gate discipline' #4) requires every registered claim to carry a pre-registered PASS + FALSIFIES pair before the run, and this spec's own Purpose section frames uni_self_audit as exactly the kind of trust-load-bearing verb that discipline exists for ('It cannot attest its own state... this is that first-class verb'). The natural falsifier -- 'colony_gate/phoenix as reported by uni_self_audit disagrees with a same-moment direct run of viewer/verify_colony.cjs / producer/health against the same host' -- is never named anywhere in the spec.

embodiment-designer

  • Verdict: REVISE
  • Rationale: What checks out first, briefly: the read-only / MUTATING_TOOLS / HUMAN_GATED gating pattern IS real (server.py:235-260, 916-945), and classifying uni_self_audit as an ungated read tool is consistent with existing precedent (get_show_state, list_sources, etc. at server.py:424-499). colony_gate's fields (colony_count, rcon_players, director_present, verdict) reuse verify_colony.cjs's existing gate output, which is already part of this repo's public-facing honest-claim discipline (CLAUDE.md's 3-signal LIVE gate) -- exposing that is not a leak, it's reuse of an already-public artifact. The spec's Non-goals line ('Does NOT include per-tick tensor data') and its choice of active_organs/novelty_gain as the granularity for self-narration show the right instinct -- those are genuinely the correct altitude for 'the being narrates its own state' per my knowledge primitives (structural/functional facts, never felt states). The problem is that the instinct wasn't traced through to the actual data path: the Sources section names APIs that don't produce the documented shape (on_chip.ex and Board rows both diverge from what's claimed), and the one data path it names correctly (Board.all/0) carries, unfiltered, a field (report) that contains the literal string 'feel:' -- the exact claim-fence violation my persona exists to catch, headed straight for a public proxy that doesn't have its own design yet. None of this is fixable with a short list of named tweaks (that would be SIGN_WITH_CHANGES); it requires rewriting the Sources section against the real code, writing an explicit field-level allowlist/redaction for both the internal and public shapes, and deciding the memory_bin_path relativization and the Python-to-BEAM bridge in the same pass -- that is spec rework, hence REVISE.
  • Concerns:
    • CLAIM-FENCE LEAK IN THE DESCRIBED DATA PATH (highest severity): the spec's own Sources section says kins comes from 'iterate SP.Runtime.Board.all/0, filter kin rows' (SPEC_uni_self_audit.md:76). A real Board row (lib/sp/runtime/agent.ex:404-416, publish/1) merges in SP.Runtime.Mind.of/2's fields VERBATIM: context, stress, emotion, confidence, focus, intent, report (lib/sp/runtime/mind.ex:22-30). The report field is built by Awareness.report/1 (lib/sp/brain/awareness.ex:52-54), which literally formats the string 'focus:... . feel:#{b.emotion} . conf:...' -- the word 'feel:' plus a raw emotion atom baked into a field name. If uni_self_audit is implemented per its own stated Sources mapping, this flows unfiltered all the way to get_self_audit() on the public proxy, which the spec itself documents as 'what a stranger sees when they ask UNI what is your state right now' (SPEC:93). This is exactly the guarded failure mode I exist to block ('Surfacing gland floats as feelings... The agent feels hungry -- never') and it directly violates this repo's claim_fence.json (experience_family: feel(s|ings?)?) and CLAUDE.md's claim-fence discipline. The spec's example JSON shows a curated kins[] shape that quietly omits these fields, but never names the redaction step that would be required to get from the real Board row to that curated shape -- an implementer following the Sources section as written would leak raw felt-language to strangers.
    • SOURCES SECTION DOES NOT MATCH THE CODE IT CITES. SP.Runtime.OnChip.info/0 (lib/sp/runtime/on_chip.ex:21-28) actually returns %{emu_flavor, schedulers_online, logical_processors, dirty_cpu_schedulers} -- none of the spec's system_architecture/erts_version/otp_release/elixir_version/smp_support keys exist, and the spec's own top-level jit_flavor field matches no real key or function name in on_chip.ex (the real boolean check is jit?/0, not a field called jit_flavor). Separately, a real Board row (agent.ex:404-414) carries username/kin/mode/senses/action/count/phase plus the Mind fields above -- none of genome_lineage, active_organs, memory_bin_path, memory_bin_sha256, memory_bin_size_bytes, or last_saved_utc exist on a Board row. active_organs and novelty_gain ARE real, correctly-named fields in this codebase (Genome.active_organs/1 used at agent.ex:132/136; novelty_gain on the genome/dna struct, genome.ex:171 etc.) but they live on each agent's own brain.dna, not on the published Board row (agent.ex only pulls phase off state.brain.dna today, nothing else) -- Board.all/0 alone cannot produce this shape. The spec presents these as simple existing accessors when at least two of the three named sources require code that does not exist yet.
    • memory_bin_path AS ACTUALLY COMPUTED IS AN ABSOLUTE HOST FILESYSTEM PATH, not the relative display path in the spec's example. colony.ex:108 builds it as Path.join(@repo_root, "runs/colony/#{username}.bin") where @repo_root = Path.expand("../../..", DIR) (colony.ex:21) -- an absolute path baked in at compile time. The spec's example ("memory_bin_path": "runs/colony/kin-9.bin") implies a relativized value but names no relativization step. Publishing the raw value, especially through the public proxy, discloses host directory layout to a stranger; this needs to be an explicit redaction in the spec, not an assumption.
    • THE PUBLIC-PROXY TRUST BOUNDARY IS BEING PRE-DECIDED BY THIS SPEC WITHOUT ITS OWN DESIGN. uni-public-mcp / E-E1 does not exist anywhere in this repo yet -- no SPEC_uni_public_mcp.md, no rate-limit code anywhere in production/mcp/server.py (grepped, no matches). The spec's line 'Same result shape, envelope-conformant, rate-limited' (SPEC:93) treats the internal-vs-public exposure question as a non-decision. Given that a kins/on_chip field-level leak (concern #1 above) only becomes a public-facing incident once it crosses that proxy, the field-level allowlist between the production-MCP result and the public-proxy result needs to be named explicitly IN THIS SPEC (which fields cross, which don't, and why), not deferred to a future doc that assumes 'same shape.'
    • SECONDARY / FEASIBILITY NOTE FOR THE ARCHITECT LANE, surfaced because it bears on where redaction gets enforced: production/mcp/server.py today only imports adapters for obs/overlays/tts/livekit (server.py:44) -- there is no existing bridge from this Python process into the Elixir/BEAM colony (no call anywhere in this file reaches lib/sp/*). Fetching OnChip.info/0 or Board.all/0 from Python requires a bridge (HTTP endpoint on the Phoenix side, or Erlang distribution) that doesn't exist. That bridge, wherever it lands, is exactly where the field-level redaction from concern #1 should be enforced (curate on the Elixir side before it ever reaches the Python MCP layer), so this should be decided together with the exposure design, not after.

MERGED VERDICT

REVISE

(Merge rule: the worst verdict wins. If ANY persona REJECTS, the merged verdict is REJECT; else if ANY REVISE, REVISE; else if ANY SIGN_WITH_CHANGES, SIGN_WITH_CHANGES; else SIGN.)

Ship-gate artifacts

Per docs/LAB_PROTOCOL.md §II, no FE-touching merge proceeds without SIGN or SIGN_WITH_CHANGES + the three artifacts:

  1. Typed spec: production/mcp/SPEC_uni_self_audit.md (present)
  2. Paired RED launcher: NOT APPLICABLE per this review — uni_self_audit is read-only with no gate transition; confirm this reasoning holds against persona concerns above before treating it as settled
  3. Ship-gate checklist: PENDING — not yet drafted

Frontmatter honesty note

This receipt was produced by 5 independent agent-driven persona reviews reading the actual repo state at 85b0e8c, not the runner's dryrun template. It is still NOT an implementation — production/mcp/server.py has NOT been edited by this pass. Per the handoff's own rule, the code diff may only land after this MERGED VERDICT, and only if the verdict is SIGN or SIGN_WITH_CHANGES.


Superseded by v2: see docs/receipts/lab_team_review_uni_self_audit_85b0e8c_v2.md (post spec-correction re-review).

sha256 93fb180c301c3799 — of the original file, so what was ingested stays checkable.

Plain — written for this website, not the source document

Written for this website — not the document. This is a plain-language retelling, written to help you meet the document. It is not the source, and it is not evidence. It has not yet been checked by a person. (or choose Precise in the reading-level control above)

A review receipt — the file recording what was run — for a proposed tool, produced by five reviewers reading the live repository rather than a template. The merged verdict is revise, under a rule that the worst verdict wins. The core finding is not about the mathematics but about the plumbing. The specification cannot produce its own example from the sources it names. One field has no storage anywhere to source it from, and a conformance claim is checkably false against the file it cites. No code was changed by this pass.

Plain · written 2026-08-01 by claude-opus-5 · not yet checked by a person · about the document whose sha256 is 93fb180c301c3799

Clear — written for this website, not the source document

Written for this website — not the document. This is a clearer retelling, written to help you meet the document. It is not the source, and it is not evidence. It has not yet been checked by a person. (or choose Precise in the reading-level control above)

A review receipt, the file recording what was run, with a merged verdict of revise. Five reviewers read the actual state of the repository at a named commit, rather than the runner's placeholder mode, and the page says so explicitly, along with what that runner can and cannot do today.

The files each reviewer read are listed, which is what makes the findings checkable by somebody else.

The first reviewer's stated default is to reject and make a proposal earn its signature, and the rationale opens with what checks out before turning to what does not. That balance is the useful part. The gating set the proposal assumes really is the single source of truth it takes it for, and the sensitive term is not being re-litigated here, because it is already gated under an earlier precedent.

What fails is the plumbing rather than the mathematics. The section naming where each field comes from is demonstrably wrong. One source returns a different set of keys entirely, and two fields need a heavier probe the specification never names. One field has no storage representation anywhere in the codebase to source it from at all. The reviewer's phrasing is the sharp one: the specification cannot produce its own example payload from the sources it cites, and its own promised tests would not catch that.

Two further gaps are named. The quantity that most needs a determinism check gets none, with no single agreed form specified and no test named for it. And a determinism test that is promised would not cover the real risk, which is a torn read racing a write that is not atomic.

A headline conformance claim is then shown to be false against the only builder that exists today, which emits a different shape from the schema it claims to match. The schema even says it was extracted from that code word for word, which is itself no longer true. The reviewer names this as pre-existing drift that the new proposal carries forward uncorrected instead of flagging.

Because none of that is a broken invariant or a smuggled term, a rejection is judged unwarranted, and the verdict is revise with a specific list attached. Rewrite the sources against the real read paths, and name whatever new mechanism is needed along with its cost. Specify which form is the one that counts, and a test for it, and either fix the divergence or explicitly scope it out.

Another reviewer adds a feasibility note about where a boundary should be enforced, observing that no bridge exists today between the two runtimes. Wherever that bridge lands is exactly where the filtering belongs, so it should be decided together with the exposure design rather than afterwards.

The closing sections state the merge rule plainly, then list the ship-gate artifacts: one present, one argued as not applicable with an instruction to confirm that reasoning rather than assume it, and one still to be drafted. An honesty note records that nothing was implemented and that a change may only land after a signing verdict. A final line says this receipt has since been superseded by a re-review.

Clear · written 2026-08-01 by claude-opus-5 · not yet checked by a person · about the document whose sha256 is 93fb180c301c3799