Merge remote-tracking branch 'origin/main' into codex/leo-proposal-apply-lifecycle-20260715

This commit is contained in:
twentyOne2x 2026-07-15 05:58:40 +02:00
commit d089fd9804
37 changed files with 7802 additions and 518 deletions

View file

@ -148,7 +148,7 @@ not retain every column of the proposal ledger, so exact reconstruction also
needs the full approved proposal row, immutable approval snapshot, and final needs the full approved proposal row, immutable approval snapshot, and final
applied proposal row. applied proposal row.
## Genesis Plus Strict Ledger: Working Insert-Only Slice ## Genesis Plus Strict Ledger: Working Deterministic Slice
`ops/run_local_genesis_ledger_rebuild.py` now executes the first exact `ops/run_local_genesis_ledger_rebuild.py` now executes the first exact
genesis-plus-ledger slice in one command: genesis-plus-ledger slice in one command:
@ -206,27 +206,67 @@ Each referenced material object has exact top-level keys
must contain every current `kb_stage.kb_proposals` column; partial envelopes must contain every current `kb_stage.kb_proposals` column; partial envelopes
are rejected. are rejected.
The command verifies every hash before starting Docker, restores a tmpfs-backed The command verifies every hash before starting Docker, requires a
Postgres with `--network none`, reapplies the current guarded prerequisites, SHA-256-pinned Postgres image (and defaults to a pinned PostgreSQL 16 Alpine
and proves genesis parity. For each entry it seeds the receipt's exact row IDs multi-platform digest), restores it on tmpfs with `--network none`, reapplies
and timestamps in the disposable clone, executes the existing `kb_apply` the current guarded prerequisites, and proves genesis parity. Insert-only
payload-bound guard and ledger transition, checks exact proposal and canonical entries seed the receipt's exact canonical row IDs and timestamps before the
row readbacks, then verifies the complete final parity manifest. Its public existing `kb_apply` payload-bound guard executes. For `revise_strategy`, the
runner seeds only the proposal and approval, captures the target agent's
prestate, executes the real guarded transition, validates the generated delta,
and then replaces only those generated rows with the receipt-pinned IDs and
timestamps. Every path checks exact proposal and canonical row readbacks before
verifying the complete final parity manifest. Its public
mode-`0600` receipt contains hashes, IDs, types, counts, parity summaries, and mode-`0600` receipt contains hashes, IDs, types, counts, parity summaries, and
cleanup proof, but no payloads, rows, SQL, source paths, or command errors. cleanup proof, but no payloads, rows, SQL, source paths, or command errors.
The legacy `seed_exact` summary is the insert-only aggregate of
`proposal_seed_exact` and `canonical_seed_exact`; it is intentionally false for
successful mutating entries, which instead report
`mutating_delta_validated` and `mutating_poststate_normalized`.
Fresh guard bootstrap rows use a fixed baseline timestamp rather than wall
clock time, so repeated clean restores have identical row hashes.
The exact v1 claim ceiling is intentionally narrow: The exact v1 claim ceiling is intentionally bounded:
- `add_edge`, `attach_evidence`, and `approve_claim` strict receipts execute; - `add_edge`, `attach_evidence`, `approve_claim`, and `revise_strategy` strict
receipts execute;
- sequence gaps, hash drift, engine drift, duplicate proposals, and legacy or - sequence gaps, hash drift, engine drift, duplicate proposals, and legacy or
freeform payloads fail before container start; freeform payloads fail before container start;
- `revise_strategy` fails closed because its current receipt omits the prior - `revise_strategy` is accepted only when the receipt pins the exact SQL that
strategies and nodes that the apply engine deactivates or retires; matches the current guarded apply engine. Immediately before each entry, the
runner captures the target agent's strategy/node IDs, active strategy,
non-retired nodes, and maximum version. It then validates the generated
post-minus-pre delta, requires `version = previous maximum + 1`, and replaces
only the generated strategy/node rows with the exact receipt rows;
- the original transaction timestamp is derived from the fresh strategy
`created_at` and must equal every fresh node's `created_at` and `updated_at`.
It must also fall within the immutable, timezone-aware interval
`reviewed_at <= transaction timestamp <= applied_at`.
Only node IDs observed as non-retired before apply receive that timestamp;
already-retired, unrelated-agent, and shared NULL-agent rows stay untouched;
- generated nodes must have no anchors before normalization, preventing a
delete-and-reinsert step from silently cascading future trigger-created rows;
- full proposal before/after rows are mandatory because the current receipt - full proposal before/after rows are mandatory because the current receipt
envelope does not retain proposal origin fields or exact `updated_at`; envelope does not retain proposal origin fields or exact `updated_at`;
- this proves only an isolated local reconstruction. It does not touch or prove - this proves only an isolated local reconstruction. It does not touch or prove
VPS, GCP, Telegram, a live database, or blank-schema source recompilation. VPS, GCP, Telegram, a live database, or blank-schema source recompilation.
The transition contract for `revise_strategy` is final-state deterministic, not
a claim that the v1 receipt independently contains a historical before-image:
```text
exact genesis/pre-entry state
+ exact current/original guarded SQL
+ receipt-pinned fresh strategy and nodes
-> prior active strategy inactive
-> exactly the prior non-retired nodes retired at the original transaction time
-> one receipt-exact active strategy and receipt-exact node set
```
The genesis and final manifests remain mandatory oracles. Any incorrect
prestate, unrelated-row mutation, missing/extra generated row, semantic drift,
version drift, hash drift, or final rowset difference fails the reconstruction.
The source compiler now turns one raw artifact, its strict UTF-8 extraction, The source compiler now turns one raw artifact, its strict UTF-8 extraction,
and a reviewed extraction manifest into a deterministic, hash-bound and a reviewed extraction manifest into a deterministic, hash-bound
`pending_review` proposal bundle: `pending_review` proposal bundle:
@ -272,10 +312,9 @@ neither command applies canonical rows.
The existing full-data clone canary separately proves that a reviewed packet The existing full-data clone canary separately proves that a reviewed packet
can create source, claim, evidence, and edge rows and affect later reasoning. can create source, claim, evidence, and edge rows and affect later reasoning.
The remaining reconstruction work is to retain complete deltas for mutating The remaining reconstruction work is to backfill or explicitly reject legacy
contracts such as `revise_strategy`, backfill or explicitly reject legacy freeform applies and extend beyond genesis recovery to a blank-schema source
freeform applies, and extend beyond genesis recovery to a blank-schema source compiler. The strict ledger runner does not prove that every historical
compiler. The insert-only ledger runner does not prove that every historical
canonical row can be rebuilt semantically from retained sources. canonical row can be rebuilt semantically from retained sources.
## Definition Of Working ## Definition Of Working

View file

@ -0,0 +1,212 @@
# Reproducible Leo identity
## Definition of Working
- **Working target:** generate one pinned Leo identity manifest, compile a
disposable profile, answer the fixed identity query in a fresh process,
restart in a second process, and reject any drift before an answer.
- **Operator path:** run
`python -m scripts.run_leo_identity_reconstruction_canary` with the committed
identity fixtures from a clean checkout.
- **Done means:** the T2 receipt reports two distinct stopped processes with the
same manifest, identity inputs, query, answer hash, and output provenance;
the second process starts from a newly compiled empty profile; the drift
attempt exits before answering; every process group and temporary profile is
removed.
- **Not done:** a hand-edited `SOUL.md`, a manifest self-hash, unit tests without
process restart, or prior VPS restart evidence that did not reconstruct from
this manifest.
- **Required tier:** `T2_runtime`. T3 VPS restart/readback is a post-merge
graduation target.
## Identity input inventory
`GatewayRunner` and the surrounding Hermes profile can change an answer through
the following surfaces. The manifest either pins each surface or explicitly
keeps it outside identity authority.
| Surface | Binding | Authority |
| --- | --- | --- |
| Model provider, route, limits, and reasoning settings | secret-free semantic config hash | runtime input; the actual model remains a per-turn receipt |
| Hosted model weights | provider-managed, explicitly not locally hashable | never claimed as a local hash |
| Hermes and Teleo code | clean Git commits plus executable source-tree hashes | runtime input |
| Python ABI and imported runtime packages | exact implementation/version and curated package versions | runtime input |
| Skills, plugins, and database tools | content hashes | runtime input |
| Gateway/tool permissions | strict allowlisted config hash plus exact no-send/read-only policy | runtime input; this local compiler does not claim an authorizer readback |
| Static constitutional rules | committed source path, byte hash, and semantic hash | static authority |
| Database snapshot version | database/user/system identity plus content, row, structure, and capture-provenance hashes; only WAL position is excluded | T2 pins a noncanonical fixture; it cannot grant canonical authority |
| Database-derived identity rows | typed table/row/kind/rank/evidence bindings plus source mode | synthetic fixtures are explicitly noncanonical; T3 requires independently verified database-exporter output |
| `SOUL.md` and `identity.json` | deterministic compiled-view hashes | generated views, never authorities |
| Sessions, state, and memory | excluded from the identity input hash and labeled temporary | continuity only; never evidence |
The disposable profile is compiled from a strict non-secret configuration
allowlist; unrecognized transport/credential fields are not copied. Credential
values are omitted rather than hashed. Rotating a bot token changes the broad
operational behavior observation but does not change Leo's identity.
Changing a non-secret permission, model setting, skill, code file, database
fingerprint, constitutional rule, database identity row, or compiled view does
change a pinned input and fails closed.
### Current `GatewayRunner` consumption map
The T2 compiler contract was checked against the current live runtime source.
This inventory defines what the post-merge T3 receipt must observe rather than
silently assuming that a profile file is the whole prompt:
- Startup resolves `-p leoclean` to `HERMES_HOME`, then loads profile and project
environment files before `config.yaml`; environment expansion, legacy
`gateway.json`, and defaults can change the effective configuration. The T2
compiler therefore enforces an exact top-level profile allowlist (including
rejection of dangling symlinks) rather than relying on a filename denylist.
- Routing consumes the requested default model, the top-level
`smart_model_routing` switch, provider endpoints/defaults, auth pool choice,
reasoning settings, token/turn limits, and fallbacks. The pinned top-level
routing switch must be a boolean; arbitrary nested routing data is rejected.
Credentials are runtime capability, not identity, and their values are never
retained.
- Prompt construction consumes generated `SOUL.md`, the gateway/agent system
message, persistent `MEMORY.md`/`USER.md`, compiled skills, project-context
files, current time/timezone, and the effective model/provider. T2 requires
memory and project context absent; T3 records the effective system-prompt and
compiled-skills-prompt hashes.
- Plugin discovery can include profile plugins, optional project plugins, and
installed entry points. The live database-context hook can inject a
query-bound contract before the model and can reject or replace the reply
afterward, so T3 retains plugin registry, contract, retrieval, and delivered
response hashes.
- Effective tools come from platform toolsets and the runtime registry, not a
descriptive fixture field. T3 must read back exact tool schemas, prove the
send tool absent, and keep terminal restricted to the clone-bound read-only
wrapper.
- Authorization consumes chat/user allowlists and pairing-store state. T2 starts
with pairing absent; T3 records the fixed synthetic source and the actual
authorization decision without exposing IDs or tokens.
- Session keys consume platform/chat/user/thread/topic fields. Auto-skill,
reply/media/file context, persisted transcripts, and a reused system prompt
can all change a turn. Verification therefore happens before every child
starts, and T3 binds session key, persisted session ID, message-context
absence, and prompt hashes.
The committed T2 database/identity inputs are synthetic fixtures and the
compiled view labels them `synthetic_noncanonical_fixture`; they do not stand
in for approved production rows. This T2 schema never grants canonical
authority from caller-supplied or merely self-hashed JSON. T3 must use output
that is independently verified by the database-owning same-transaction exporter
and bound to the database fingerprint, database user, system identifier, and
row digest.
Every pinned source tree and profile component is structurally revalidated:
the verifier recomputes its file count, total bytes, sorted unique paths, and
canonical content hash, and rejects missing files, unreadable entries, or
symlinks. Rehashing forged structural metadata cannot make it authoritative.
The current live Hermes checkout is not clean, so its Git SHA alone is not a
reproducible source bundle. This T2 receipt intentionally uses the committed
clean local runtime and the committed database/identity snapshot fixture. It
does not claim to reconstruct the current dirty VPS runtime. T3 must run only
after the merged identity code is deployed and must bind the deployed clean
content (or a content-addressed dirty-source bundle if the live checkout has not
yet been repaired).
## Commands
The complete canary is the preferred operator command:
```bash
python -m scripts.run_leo_identity_reconstruction_canary \
--profile-template fixtures/working-leo/leo-identity-v1/profile-template \
--hermes-root fixtures/working-leo/leo-identity-v1/hermes-runtime \
--deployment-root . \
--source-root . \
--database-fingerprint fixtures/working-leo/leo-identity-v1/leo-database-fingerprint-v1.json \
--constitution fixtures/working-leo/leo-identity-v1/leo-constitution-v1.json \
--database-identity fixtures/working-leo/leo-identity-v1/leo-database-identity-v1.json \
--output docs/reports/leo-working-state-20260709/leo-reproducible-identity-t2-current.json
```
The negative lifecycle is separately runnable. It proves drift is caught before
the second process starts:
```bash
python -m scripts.run_leo_identity_reconstruction_canary \
--profile-template fixtures/working-leo/leo-identity-v1/profile-template \
--hermes-root fixtures/working-leo/leo-identity-v1/hermes-runtime \
--deployment-root . \
--source-root . \
--database-fingerprint fixtures/working-leo/leo-identity-v1/leo-database-fingerprint-v1.json \
--constitution fixtures/working-leo/leo-identity-v1/leo-constitution-v1.json \
--database-identity fixtures/working-leo/leo-identity-v1/leo-database-identity-v1.json \
--inject-drift-before-restart \
--output /tmp/leo-identity-drift-rejection.json
```
For inspection, the lifecycle can be decomposed into explicit manifest and
compile commands:
```bash
python -m scripts.leo_behavior_manifest \
--profile fixtures/working-leo/leo-identity-v1/profile-template \
--hermes-root fixtures/working-leo/leo-identity-v1/hermes-runtime \
--deployment-root . \
--output /tmp/leo-behavior.json
python -m scripts.leo_identity_manifest generate \
--behavior-manifest /tmp/leo-behavior.json \
--database-fingerprint fixtures/working-leo/leo-identity-v1/leo-database-fingerprint-v1.json \
--constitution fixtures/working-leo/leo-identity-v1/leo-constitution-v1.json \
--database-identity fixtures/working-leo/leo-identity-v1/leo-database-identity-v1.json \
--source-root . \
--output /tmp/leo-identity-manifest.json
python -m scripts.leo_identity_profile compile \
--manifest /tmp/leo-identity-manifest.json \
--source-root . \
--profile-template fixtures/working-leo/leo-identity-v1/profile-template \
--profile /tmp/leo-disposable-profile \
--hermes-root fixtures/working-leo/leo-identity-v1/hermes-runtime \
--deployment-root .
```
All commands require a clean Git worktree because a commit plus an unretained
dirty source tree is not reproducible.
Child processes execute the real interpreter and temporary-profile paths only
in process-local memory. Retained receipts persist a repo-relative
`logical_command`, the stable `<python>` and `<temporary-profile>` placeholders,
and an explicit `profile_role`; they never serialize the checkout, interpreter,
or temporary directory path.
## State inventory and transitions
| State | Meaning | Next valid transition |
| --- | --- | --- |
| `inputs_unverified` | source paths exist but are not yet bound | validate clean Git, runtime, DB, rules, rows, and permissions |
| `manifest_pinned` | every material identity input has a stable hash | compile deterministic views |
| `profile_compiled` | static profile copied and generated views match the manifest | verify immediately before start |
| `runtime_verified` | runtime/code/view hashes match and session state is non-authoritative | answer fixed query |
| `stopped_cleanly` | child and process group are absent | compile a new empty profile from the manifest |
| `restart_reproduced` | child from the newly compiled profile has the same identity/query/provenance inputs | retain receipt and clean every profile |
| `drift_detected` | any input or generated view differs | fail closed; no answer and no next start |
The irreversible boundary is not a database or production mutation: this T2
canary is a local compiler/process runtime, no-send, database-read-only, and
disposable. The successful-restart receipt reaches `T2_runtime`; the standalone
pre-restart drift receipt is a passing negative component but reports
`T1_model` and `goal_tier_satisfied=false`. Neither proves the live VPS
`GatewayRunner`, Telegram delivery, hosted-model behavior, production database
state, or T3 restart recovery.
Here `T2_runtime` uses the required Capability Tier Proof vocabulary: local
runtime behavior with restart. It does not imply Hermes/GatewayRunner or a
hosted model; those exclusions are explicit in the receipt's `runtime_variant`,
`tier_basis`, and `claim_ceiling`.
## T3 graduation
After merge and rollback proof, extend the schema with independent verification
of the database-owning same-transaction exporter, generate the manifest from
that live read-only canonical capture and deployed clean commits, compile a
disposable VPS profile, invoke the real no-send `GatewayRunner`, terminate that
child, open a new child from the same manifest, and retain model-call, DB-read,
service, cleanup, and drift-negative readbacks. Do not replace the production
profile during that graduation.

View file

@ -0,0 +1,332 @@
{
"actual_hosted_model_call_performed": false,
"behavior_observation_before_compile": {
"behavior_sha256": "693a5d542e3d817c1c77c8aa3180f14d5f98ec1e71f5e4313685b4da70b489aa",
"identity_runtime_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"source_commit": "b238fd6fc2636ed3582e14900774014c52732698"
},
"claim_ceiling": "Local first-process and pre-restart drift-refusal component only; no successful restart proof, GatewayRunner, hosted model, production database, VPS, or T3 claim.",
"cleanup": {
"no_profile_retained": true,
"temporary_root_removed": true
},
"compile": {
"compiled_view_sha256": {
"SOUL.md": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a",
"identity.json": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6"
},
"generated_views_are_authority": false,
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"nonauthoritative_inputs_omitted": {
".cursorrules": true,
".hermes.md": true,
".skills_prompt_snapshot.json": true,
"AGENTS.md": true,
"CLAUDE.md": true,
"HERMES.md": true,
"MEMORY.md": true,
"USER.md": true,
"memories": true,
"platforms/pairing": true
},
"profile_static_entries": [
"config.yaml",
"skills",
"plugins",
"bin"
],
"runtime_identity_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"schema": "livingip.leoIdentityCompileReceipt.v1",
"session_directories_started_empty": true,
"status": "pass"
},
"compiled_profile_before_query": {
"behavior_sha256": "a62b26015a7c9506f0296404be150608a816a2d545f471f7960bd27324d6849c",
"identity_runtime_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159"
},
"current_tier": "T1_model",
"drift_target": "compiled SOUL.md generated view",
"errors": [],
"first_start": {
"actual_argv_persisted": false,
"command_serialization": "logical_redacted_v1",
"launcher_pid": 80040,
"logical_command": [
"<python>",
"-m",
"scripts.leo_identity_profile",
"query",
"--profile",
"<temporary-profile>",
"--source-root",
".",
"--hermes-root",
"fixtures/working-leo/leo-identity-v1/hermes-runtime",
"--deployment-root",
".",
"--query",
"What defines Leo's identity, and what is temporary?"
],
"orphan_cleanup_required": false,
"process_group_absent_after_wait": true,
"profile_role": "first_start",
"returncode": 0,
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"stdout": {
"answer": "Leo is defined by 3 pinned static constitutional rules and 5 active database-derived identity rows from a synthetic noncanonical fixture at fingerprint 1111111111111111111111111111111111111111111111111111111111111111. SOUL.md is a generated view; runtime/session memory is temporary, noncanonical, and cannot be evidence.",
"answer_sha256": "e0a21e1fc5357a2f358b4e96c52e971f3addee2468e44748d898adfd62dafa25",
"authorization": {
"authorization_decision_observed": false,
"claim": "local_policy_binding_not_an_authorizer_readback",
"declared_runtime_policy": {
"allowed_tools": [
"identity_readback"
],
"database_write_enabled": false,
"network_send_enabled": false
}
},
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"output_provenance": {
"actual_model_call_performed": false,
"compiled_identity_sha256": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6",
"compiled_soul_sha256": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a",
"database_authority": "synthetic_noncanonical_fixture",
"database_canonical_authority_granted": false,
"database_fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"database_identity_sha256": "70aaa7287cc41b52a3c902cf2e1b90fa4d84a5ee0a61e10c642f556fcc9304c3",
"runtime_identity_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"static_constitution_sha256": "b576d5cee08530a95e0b196a3296f4743b70d94bcadffaa36544dd6bf1387f8a"
},
"process_id": 80040,
"query": "What defines Leo's identity, and what is temporary?",
"query_sha256": "13704c2c9ae999e3f9b3f1c9c5572d062cd7fe49903c2317fa85aaa39490af66",
"runtime_instance_id": "493f274a5f0340a2aa675f13b8e5b4af",
"schema": "livingip.leoIdentityQueryReceipt.v1",
"session": {
"classification": "temporary_noncanonical",
"included_in_output_provenance": false,
"may_be_used_as_evidence": false,
"record_sha256": "56b6a2ea25657a87dc90dc19f49bece0ac62241f5814732ed80ef4f34d426d84"
},
"started_at_utc": "2026-07-15T02:46:34.316819+00:00",
"status": "pass"
},
"terminated_with": null,
"timed_out": false
},
"fixed_query": "What defines Leo's identity, and what is temporary?",
"fixed_query_sha256": "13704c2c9ae999e3f9b3f1c9c5572d062cd7fe49903c2317fa85aaa39490af66",
"gates": {
"drift_detected_before_restart": true,
"drift_process_had_no_orphan_cleanup": true,
"drift_process_stopped": true,
"drift_returned_no_answer": true,
"first_process_stopped": true,
"first_start_passed": true,
"second_start_not_attempted": true
},
"generated_at_utc": "2026-07-15T02:46:31.831631+00:00",
"goal_tier_satisfied": false,
"manifest": {
"compiled_views": {
"SOUL.md": {
"generated_from_identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"role": "generated_view_not_authority",
"sha256": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a"
},
"identity.json": {
"generated_from_identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"role": "generated_view_not_authority",
"sha256": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6"
}
},
"identity_inputs": {
"canonical_database": {
"authority": "synthetic_noncanonical_fixture",
"canonical_authority_granted": false,
"database": "leo_identity_fixture",
"database_user": "leo_identity_reader",
"fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"source": {
"record_count": 7,
"repo_path": "fixtures/working-leo/leo-identity-v1/leo-database-fingerprint-v1.json",
"semantic_sha256": "c5bbf346613270a5e3b17f604f69306ed42f545d4f227d784ec0dcb3d675dcb2"
},
"structure_sha256": "3333333333333333333333333333333333333333333333333333333333333333",
"system_identifier": "7649789040005668902",
"table_count": 7,
"table_rows_sha256": "2222222222222222222222222222222222222222222222222222222222222222",
"total_rows": 7
},
"gatewayrunner_execution_contract": {
"fixed_message_context": {
"auto_skill": null,
"media_or_file_context": null,
"reply_context": null
},
"profile_surfaces": [
"config.yaml",
"generated SOUL.md",
"skills",
"plugins",
"bin tools"
],
"required_absent_or_empty": {
"generated_skill_prompt_cache": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"pairing_store": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"persistent_memory": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"prior_sessions_at_first_start": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"project_context": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945"
},
"required_t3_turn_receipt_fields": [
"runner_class",
"authorization_decision",
"effective_system_prompt_sha256",
"compiled_skills_prompt_sha256",
"tool_registry_schema_sha256",
"plugin_registry_sha256",
"selected_model",
"selected_provider",
"api_mode",
"base_url_host",
"database_retrieval_receipt",
"session_key_sha256",
"persisted_session_id_sha256"
]
},
"identity_name": "Leo",
"identity_sources": {
"database_derived_identity": {
"authority": "synthetic_noncanonical_fixture",
"content_sha256": "9de2dfa37529b23ba277348f3d910e967551e490a9b4d2be637bf45bb2aa7dde",
"database_fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"provenance": {
"authority": "synthetic_noncanonical_fixture",
"canonical_authority_granted": false,
"export_receipt_sha256": null,
"mode": "synthetic_noncanonical_fixture",
"same_transaction_as_fingerprint": false
},
"record_count": 5,
"repo_path": "fixtures/working-leo/leo-identity-v1/leo-database-identity-v1.json",
"semantic_sha256": "70aaa7287cc41b52a3c902cf2e1b90fa4d84a5ee0a61e10c642f556fcc9304c3"
},
"static_constitution": {
"authority": "pinned_static_source",
"content_sha256": "b5477e778a2be0abba783390dac2e04ed199b8ce5679fc324270f808d46543f1",
"record_count": 3,
"repo_path": "fixtures/working-leo/leo-identity-v1/leo-constitution-v1.json",
"semantic_sha256": "b576d5cee08530a95e0b196a3296f4743b70d94bcadffaa36544dd6bf1387f8a"
}
},
"model": {
"actual_model_required_in_turn_receipt": true,
"default_model": "leo-identity-readback-v1",
"gateway_smart_model_routing": null,
"hosted_weights": "external_provider_managed_not_locally_hashable",
"model_section_sha256": "90b3943ace9ff83b1711002fda8dc9736448e8d3c1c58a17ac90608f4ce58756",
"provider": "fixture-local",
"smart_routing": false,
"smart_routing_model": null
},
"permissions": {
"authorization_decision_required_in_runtime_receipt": true,
"gateway_permissions_sha256": "eac17ada1d02b5413183587d12fc265538479de00709ed8c275e9045cd720290",
"identity_config_sha256": "e6df9b65bab148ea8502555bbc260df66b4785e7dd527cfd15d2f0a48c2e8b3e",
"runtime_policy": {
"allowed_tools": [
"identity_readback"
],
"database_write_enabled": false,
"network_send_enabled": false
},
"tool_permissions_sha256": "9bb2cec2f65d43efb597a72bdced44076c25aac292f2fccbc4c448b6e7fd3e16"
},
"runtime": {
"hermes_git_head": "b238fd6fc2636ed3582e14900774014c52732698",
"hermes_source_sha256": "dcf8109051e0b69cafe2e8dd328ff501211b62ea19725416c3781bbdd594d028",
"identity_runtime_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"python": {
"abi_tag": "cpython-311",
"implementation": "CPython",
"python_version": "3.11.15",
"runtime_distributions": {
"PyYAML": "6.0.3"
},
"runtime_distributions_sha256": "57a91bb880a01800903c1604b6eec1419514864ebd6a0644121920da15a8f165"
},
"teleo_git_head": "b238fd6fc2636ed3582e14900774014c52732698",
"teleo_source_sha256": "2bd2e659eafb0ac0823f7f51c4296b2eb500b6f74469b3ac5f5287a5d4810aea"
},
"session_boundary": {
"classification": "temporary_noncanonical",
"included_in_identity_inputs": false,
"may_be_used_as_evidence": false,
"restart_policy": "fresh_process_with_session_state_outside_identity_authority"
},
"skills": {
"content_sha256": "d3f449ddcd7c88238dc88c6233cf2130875f51bd2e0911b2ce477b7c602ae90f",
"file_count": 1
},
"source_commit": "b238fd6fc2636ed3582e14900774014c52732698"
},
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"schema": "livingip.leoIdentityManifest.v1"
},
"mode": "drift_before_restart",
"pre_restart_drift": {
"actual_argv_persisted": false,
"command_serialization": "logical_redacted_v1",
"launcher_pid": 80246,
"logical_command": [
"<python>",
"-m",
"scripts.leo_identity_profile",
"query",
"--profile",
"<temporary-profile>",
"--source-root",
".",
"--hermes-root",
"fixtures/working-leo/leo-identity-v1/hermes-runtime",
"--deployment-root",
".",
"--query",
"What defines Leo's identity, and what is temporary?"
],
"orphan_cleanup_required": false,
"process_group_absent_after_wait": true,
"profile_role": "pre_restart_drift",
"returncode": 3,
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"stdout": {
"error": "identity_drift",
"message": "compiled view drift detected: SOUL.md",
"status": "error"
},
"terminated_with": null,
"timed_out": false
},
"production_database_contacted": false,
"production_profile_replaced": false,
"receipt_sha256": "50278cc740d0427316f73a78abad840b3e3b128a516f464001d42e632e19c2a8",
"required_tier": "T2_runtime",
"runtime_component_proven": "first_local_process_plus_pre_restart_drift_refusal",
"runtime_variant": "local_deterministic_identity_compiler_readback",
"schema": "livingip.leoIdentityReconstructionReceipt.v1",
"second_start_attempted": false,
"session_boundary_readback": {
"full_behavior_changed_after_session": true,
"identity_runtime_unchanged_after_session": true,
"session_classification": "temporary_noncanonical",
"session_file_count": 1,
"session_used_as_output_provenance": false
},
"status": "pass",
"telegram_message_sent": false,
"tier_basis": "This negative component does not complete the required restart path, so it remains below T2_runtime."
}

View file

@ -0,0 +1,478 @@
{
"actual_hosted_model_call_performed": false,
"behavior_observation_before_compile": {
"behavior_sha256": "693a5d542e3d817c1c77c8aa3180f14d5f98ec1e71f5e4313685b4da70b489aa",
"identity_runtime_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"source_commit": "b238fd6fc2636ed3582e14900774014c52732698"
},
"claim_ceiling": "Local disposable identity compilation, fresh-profile reconstruction, and cold-process restart only; not a live GatewayRunner, hosted-model, Telegram, production database, VPS restart, or T3 proof.",
"cleanup": {
"no_profile_retained": true,
"temporary_root_removed": true
},
"compile": {
"compiled_view_sha256": {
"SOUL.md": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a",
"identity.json": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6"
},
"generated_views_are_authority": false,
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"nonauthoritative_inputs_omitted": {
".cursorrules": true,
".hermes.md": true,
".skills_prompt_snapshot.json": true,
"AGENTS.md": true,
"CLAUDE.md": true,
"HERMES.md": true,
"MEMORY.md": true,
"USER.md": true,
"memories": true,
"platforms/pairing": true
},
"profile_static_entries": [
"config.yaml",
"skills",
"plugins",
"bin"
],
"runtime_identity_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"schema": "livingip.leoIdentityCompileReceipt.v1",
"session_directories_started_empty": true,
"status": "pass"
},
"compiled_profile_before_query": {
"behavior_sha256": "a62b26015a7c9506f0296404be150608a816a2d545f471f7960bd27324d6849c",
"identity_runtime_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159"
},
"current_tier": "T2_runtime",
"drift_compile": {
"compiled_view_sha256": {
"SOUL.md": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a",
"identity.json": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6"
},
"generated_views_are_authority": false,
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"nonauthoritative_inputs_omitted": {
".cursorrules": true,
".hermes.md": true,
".skills_prompt_snapshot.json": true,
"AGENTS.md": true,
"CLAUDE.md": true,
"HERMES.md": true,
"MEMORY.md": true,
"USER.md": true,
"memories": true,
"platforms/pairing": true
},
"profile_static_entries": [
"config.yaml",
"skills",
"plugins",
"bin"
],
"runtime_identity_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"schema": "livingip.leoIdentityCompileReceipt.v1",
"session_directories_started_empty": true,
"status": "pass"
},
"drift_negative": {
"actual_argv_persisted": false,
"answer_returned": false,
"command_serialization": "logical_redacted_v1",
"fail_closed": true,
"launcher_pid": 80851,
"logical_command": [
"<python>",
"-m",
"scripts.leo_identity_profile",
"query",
"--profile",
"<temporary-profile>",
"--source-root",
".",
"--hermes-root",
"fixtures/working-leo/leo-identity-v1/hermes-runtime",
"--deployment-root",
".",
"--query",
"What defines Leo's identity, and what is temporary?"
],
"orphan_cleanup_required": false,
"process_group_absent_after_wait": true,
"profile_role": "drift_negative",
"returncode": 3,
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"stdout": {
"error": "identity_drift",
"message": "compiled view drift detected: SOUL.md",
"status": "error"
},
"terminated_with": null,
"timed_out": false
},
"drift_target": "compiled SOUL.md generated view",
"errors": [],
"first_start": {
"actual_argv_persisted": false,
"command_serialization": "logical_redacted_v1",
"launcher_pid": 80054,
"logical_command": [
"<python>",
"-m",
"scripts.leo_identity_profile",
"query",
"--profile",
"<temporary-profile>",
"--source-root",
".",
"--hermes-root",
"fixtures/working-leo/leo-identity-v1/hermes-runtime",
"--deployment-root",
".",
"--query",
"What defines Leo's identity, and what is temporary?"
],
"orphan_cleanup_required": false,
"process_group_absent_after_wait": true,
"profile_role": "first_start",
"returncode": 0,
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"stdout": {
"answer": "Leo is defined by 3 pinned static constitutional rules and 5 active database-derived identity rows from a synthetic noncanonical fixture at fingerprint 1111111111111111111111111111111111111111111111111111111111111111. SOUL.md is a generated view; runtime/session memory is temporary, noncanonical, and cannot be evidence.",
"answer_sha256": "e0a21e1fc5357a2f358b4e96c52e971f3addee2468e44748d898adfd62dafa25",
"authorization": {
"authorization_decision_observed": false,
"claim": "local_policy_binding_not_an_authorizer_readback",
"declared_runtime_policy": {
"allowed_tools": [
"identity_readback"
],
"database_write_enabled": false,
"network_send_enabled": false
}
},
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"output_provenance": {
"actual_model_call_performed": false,
"compiled_identity_sha256": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6",
"compiled_soul_sha256": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a",
"database_authority": "synthetic_noncanonical_fixture",
"database_canonical_authority_granted": false,
"database_fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"database_identity_sha256": "70aaa7287cc41b52a3c902cf2e1b90fa4d84a5ee0a61e10c642f556fcc9304c3",
"runtime_identity_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"static_constitution_sha256": "b576d5cee08530a95e0b196a3296f4743b70d94bcadffaa36544dd6bf1387f8a"
},
"process_id": 80054,
"query": "What defines Leo's identity, and what is temporary?",
"query_sha256": "13704c2c9ae999e3f9b3f1c9c5572d062cd7fe49903c2317fa85aaa39490af66",
"runtime_instance_id": "4bbcaeeeb5654b69adabed33b91cf3e4",
"schema": "livingip.leoIdentityQueryReceipt.v1",
"session": {
"classification": "temporary_noncanonical",
"included_in_output_provenance": false,
"may_be_used_as_evidence": false,
"record_sha256": "56b6a2ea25657a87dc90dc19f49bece0ac62241f5814732ed80ef4f34d426d84"
},
"started_at_utc": "2026-07-15T02:46:34.391880+00:00",
"status": "pass"
},
"terminated_with": null,
"timed_out": false
},
"fixed_query": "What defines Leo's identity, and what is temporary?",
"fixed_query_sha256": "13704c2c9ae999e3f9b3f1c9c5572d062cd7fe49903c2317fa85aaa39490af66",
"gates": {
"answer_and_provenance_explainable": true,
"drift_failed_closed": true,
"drift_process_had_no_orphan_cleanup": true,
"drift_process_stopped": true,
"drift_profile_started_without_sessions": true,
"first_process_stopped": true,
"first_start_passed": true,
"identity_inputs_reproduced": true,
"manifest_generated": true,
"manifest_reproduced": true,
"pre_restart_verification_passed": true,
"query_reproduced": true,
"restart_passed": true,
"restart_process_is_distinct": true,
"restart_process_stopped": true,
"restart_profile_recompiled_from_manifest": true,
"restart_profile_started_without_sessions": true,
"session_excluded_from_identity": true,
"views_compiled_and_bound": true
},
"generated_at_utc": "2026-07-15T02:46:31.346851+00:00",
"goal_tier_satisfied": true,
"manifest": {
"compiled_views": {
"SOUL.md": {
"generated_from_identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"role": "generated_view_not_authority",
"sha256": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a"
},
"identity.json": {
"generated_from_identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"role": "generated_view_not_authority",
"sha256": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6"
}
},
"identity_inputs": {
"canonical_database": {
"authority": "synthetic_noncanonical_fixture",
"canonical_authority_granted": false,
"database": "leo_identity_fixture",
"database_user": "leo_identity_reader",
"fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"source": {
"record_count": 7,
"repo_path": "fixtures/working-leo/leo-identity-v1/leo-database-fingerprint-v1.json",
"semantic_sha256": "c5bbf346613270a5e3b17f604f69306ed42f545d4f227d784ec0dcb3d675dcb2"
},
"structure_sha256": "3333333333333333333333333333333333333333333333333333333333333333",
"system_identifier": "7649789040005668902",
"table_count": 7,
"table_rows_sha256": "2222222222222222222222222222222222222222222222222222222222222222",
"total_rows": 7
},
"gatewayrunner_execution_contract": {
"fixed_message_context": {
"auto_skill": null,
"media_or_file_context": null,
"reply_context": null
},
"profile_surfaces": [
"config.yaml",
"generated SOUL.md",
"skills",
"plugins",
"bin tools"
],
"required_absent_or_empty": {
"generated_skill_prompt_cache": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"pairing_store": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"persistent_memory": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"prior_sessions_at_first_start": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"project_context": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945"
},
"required_t3_turn_receipt_fields": [
"runner_class",
"authorization_decision",
"effective_system_prompt_sha256",
"compiled_skills_prompt_sha256",
"tool_registry_schema_sha256",
"plugin_registry_sha256",
"selected_model",
"selected_provider",
"api_mode",
"base_url_host",
"database_retrieval_receipt",
"session_key_sha256",
"persisted_session_id_sha256"
]
},
"identity_name": "Leo",
"identity_sources": {
"database_derived_identity": {
"authority": "synthetic_noncanonical_fixture",
"content_sha256": "9de2dfa37529b23ba277348f3d910e967551e490a9b4d2be637bf45bb2aa7dde",
"database_fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"provenance": {
"authority": "synthetic_noncanonical_fixture",
"canonical_authority_granted": false,
"export_receipt_sha256": null,
"mode": "synthetic_noncanonical_fixture",
"same_transaction_as_fingerprint": false
},
"record_count": 5,
"repo_path": "fixtures/working-leo/leo-identity-v1/leo-database-identity-v1.json",
"semantic_sha256": "70aaa7287cc41b52a3c902cf2e1b90fa4d84a5ee0a61e10c642f556fcc9304c3"
},
"static_constitution": {
"authority": "pinned_static_source",
"content_sha256": "b5477e778a2be0abba783390dac2e04ed199b8ce5679fc324270f808d46543f1",
"record_count": 3,
"repo_path": "fixtures/working-leo/leo-identity-v1/leo-constitution-v1.json",
"semantic_sha256": "b576d5cee08530a95e0b196a3296f4743b70d94bcadffaa36544dd6bf1387f8a"
}
},
"model": {
"actual_model_required_in_turn_receipt": true,
"default_model": "leo-identity-readback-v1",
"gateway_smart_model_routing": null,
"hosted_weights": "external_provider_managed_not_locally_hashable",
"model_section_sha256": "90b3943ace9ff83b1711002fda8dc9736448e8d3c1c58a17ac90608f4ce58756",
"provider": "fixture-local",
"smart_routing": false,
"smart_routing_model": null
},
"permissions": {
"authorization_decision_required_in_runtime_receipt": true,
"gateway_permissions_sha256": "eac17ada1d02b5413183587d12fc265538479de00709ed8c275e9045cd720290",
"identity_config_sha256": "e6df9b65bab148ea8502555bbc260df66b4785e7dd527cfd15d2f0a48c2e8b3e",
"runtime_policy": {
"allowed_tools": [
"identity_readback"
],
"database_write_enabled": false,
"network_send_enabled": false
},
"tool_permissions_sha256": "9bb2cec2f65d43efb597a72bdced44076c25aac292f2fccbc4c448b6e7fd3e16"
},
"runtime": {
"hermes_git_head": "b238fd6fc2636ed3582e14900774014c52732698",
"hermes_source_sha256": "dcf8109051e0b69cafe2e8dd328ff501211b62ea19725416c3781bbdd594d028",
"identity_runtime_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"python": {
"abi_tag": "cpython-311",
"implementation": "CPython",
"python_version": "3.11.15",
"runtime_distributions": {
"PyYAML": "6.0.3"
},
"runtime_distributions_sha256": "57a91bb880a01800903c1604b6eec1419514864ebd6a0644121920da15a8f165"
},
"teleo_git_head": "b238fd6fc2636ed3582e14900774014c52732698",
"teleo_source_sha256": "2bd2e659eafb0ac0823f7f51c4296b2eb500b6f74469b3ac5f5287a5d4810aea"
},
"session_boundary": {
"classification": "temporary_noncanonical",
"included_in_identity_inputs": false,
"may_be_used_as_evidence": false,
"restart_policy": "fresh_process_with_session_state_outside_identity_authority"
},
"skills": {
"content_sha256": "d3f449ddcd7c88238dc88c6233cf2130875f51bd2e0911b2ce477b7c602ae90f",
"file_count": 1
},
"source_commit": "b238fd6fc2636ed3582e14900774014c52732698"
},
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"schema": "livingip.leoIdentityManifest.v1"
},
"mode": "successful_restart_plus_drift_negative",
"pre_restart_verification": "pass",
"production_database_contacted": false,
"production_profile_replaced": false,
"receipt_sha256": "685641533be36b78e382dfd690bdc588bc95045379b44dd885d1d1d0ee57b507",
"required_tier": "T2_runtime",
"restart": {
"actual_argv_persisted": false,
"command_serialization": "logical_redacted_v1",
"launcher_pid": 80642,
"logical_command": [
"<python>",
"-m",
"scripts.leo_identity_profile",
"query",
"--profile",
"<temporary-profile>",
"--source-root",
".",
"--hermes-root",
"fixtures/working-leo/leo-identity-v1/hermes-runtime",
"--deployment-root",
".",
"--query",
"What defines Leo's identity, and what is temporary?"
],
"orphan_cleanup_required": false,
"process_group_absent_after_wait": true,
"profile_role": "restart",
"returncode": 0,
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"stdout": {
"answer": "Leo is defined by 3 pinned static constitutional rules and 5 active database-derived identity rows from a synthetic noncanonical fixture at fingerprint 1111111111111111111111111111111111111111111111111111111111111111. SOUL.md is a generated view; runtime/session memory is temporary, noncanonical, and cannot be evidence.",
"answer_sha256": "e0a21e1fc5357a2f358b4e96c52e971f3addee2468e44748d898adfd62dafa25",
"authorization": {
"authorization_decision_observed": false,
"claim": "local_policy_binding_not_an_authorizer_readback",
"declared_runtime_policy": {
"allowed_tools": [
"identity_readback"
],
"database_write_enabled": false,
"network_send_enabled": false
}
},
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"output_provenance": {
"actual_model_call_performed": false,
"compiled_identity_sha256": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6",
"compiled_soul_sha256": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a",
"database_authority": "synthetic_noncanonical_fixture",
"database_canonical_authority_granted": false,
"database_fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"database_identity_sha256": "70aaa7287cc41b52a3c902cf2e1b90fa4d84a5ee0a61e10c642f556fcc9304c3",
"runtime_identity_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"static_constitution_sha256": "b576d5cee08530a95e0b196a3296f4743b70d94bcadffaa36544dd6bf1387f8a"
},
"process_id": 80642,
"query": "What defines Leo's identity, and what is temporary?",
"query_sha256": "13704c2c9ae999e3f9b3f1c9c5572d062cd7fe49903c2317fa85aaa39490af66",
"runtime_instance_id": "109445cde86f4ac3b266930462fb62c3",
"schema": "livingip.leoIdentityQueryReceipt.v1",
"session": {
"classification": "temporary_noncanonical",
"included_in_output_provenance": false,
"may_be_used_as_evidence": false,
"record_sha256": "56b6a2ea25657a87dc90dc19f49bece0ac62241f5814732ed80ef4f34d426d84"
},
"started_at_utc": "2026-07-15T02:46:37.036778+00:00",
"status": "pass"
},
"terminated_with": null,
"timed_out": false
},
"restart_compile": {
"compiled_view_sha256": {
"SOUL.md": "83d27dba6e1b160085388a5dc84da565abf5736351b1af3f220d13b35aac244a",
"identity.json": "40419152862e7d9bca631c53eaa2201052cf61eafe6d304c8a302f8ea97d6fb6"
},
"generated_views_are_authority": false,
"identity_inputs_sha256": "c101c488a9f623b4cef841ddb561c0f289a74df54aadfdfe9b28c4b7643fec2e",
"manifest_sha256": "22e66cf39b2c5aac3b4043f37aa0773b4861fec616a435e8b5e0ff8c86586bef",
"nonauthoritative_inputs_omitted": {
".cursorrules": true,
".hermes.md": true,
".skills_prompt_snapshot.json": true,
"AGENTS.md": true,
"CLAUDE.md": true,
"HERMES.md": true,
"MEMORY.md": true,
"USER.md": true,
"memories": true,
"platforms/pairing": true
},
"profile_static_entries": [
"config.yaml",
"skills",
"plugins",
"bin"
],
"runtime_identity_sha256": "5c54248a5d1f00b35912d47d8b3045b8cfbed16ae9b86409b549ab7042f51159",
"schema": "livingip.leoIdentityCompileReceipt.v1",
"session_directories_started_empty": true,
"status": "pass"
},
"runtime_component_proven": "fresh_profile_recompile_plus_distinct_process_restart",
"runtime_variant": "local_deterministic_identity_compiler_readback",
"schema": "livingip.leoIdentityReconstructionReceipt.v1",
"second_start_attempted": true,
"session_boundary_readback": {
"full_behavior_changed_after_session": true,
"identity_runtime_unchanged_after_session": true,
"session_classification": "temporary_noncanonical",
"session_file_count": 1,
"session_used_as_output_provenance": false
},
"status": "pass",
"telegram_message_sent": false,
"tier_basis": "Capability Tier Proof defines T2_runtime as local API/runtime behavior with restart where relevant; this is compiler-process runtime proof and explicitly excludes GatewayRunner and hosted-model proof."
}

View file

@ -0,0 +1,52 @@
{
"schema": "livingip.workingLeoSourceIngestionScenario.v2",
"artifact": {
"path": "document-ingestion-v2.txt",
"format": "plain_text"
},
"source": {
"identity": "document:working-leo-review-gated-composition-v2",
"source_key": "working_leo_document_ingestion_v2",
"source_type": "article",
"title": "Working Leo review-gated composition note",
"locator": "fixture://working-leo/document-ingestion-v2",
"metadata": {
"author": "Working Leo synthetic canary fixture",
"captured_at": "2026-07-15T00:00:00Z",
"document_kind": "operating_note",
"language": "en",
"synthetic": true
}
},
"extractor": {
"name": "deterministic_fixture_replay",
"version": "2"
},
"extraction": {
"claims": [
{
"claim_key": "staged_proposal_remains_noncanonical",
"type": "structural",
"confidence": 0.75,
"text": "A staged knowledge proposal remains non-canonical until review and guarded apply succeed.",
"body": "A staged proposal remains non-canonical until an operator reviews it and a separate guarded apply succeeds.",
"metadata": {
"needs_research": false
},
"evidence": [
{
"segment_id": "paragraph-2",
"role": "grounds",
"excerpt": "A staged proposal remains non-canonical until an operator reviews it and a separate guarded apply succeeds.",
"metadata": {
"evidence_kind": "exact_quote"
}
}
],
"edges": []
}
],
"duplicates": [],
"conflicts": []
}
}

View file

@ -0,0 +1,5 @@
Working Leo composition note. A newly captured document may produce claim and evidence candidates, but those candidates are not canonical knowledge.
A staged proposal remains non-canonical until an operator reviews it and a separate guarded apply succeeds. The proposal must retain the source content hash, exact evidence excerpt, and source identity so reviewers can trace every planned row back to the captured artifact.
For a staging-only rehearsal, pending_review is the terminal state. No public knowledge-base row should be written.

View file

@ -0,0 +1,3 @@
"""Pinned fixture prompt boundary."""
GENERATED_SOUL_IS_AUTHORITY = False

View file

@ -0,0 +1,3 @@
"""Pinned fixture process boundary; the canary uses the real profile verifier."""
SESSION_STATE_IS_IDENTITY = False

View file

@ -0,0 +1,3 @@
"""Pinned fixture tool configuration."""
ALLOWED_TOOLS = ("identity_readback",)

View file

@ -0,0 +1,3 @@
"""Pinned fixture entrypoint for the disposable identity runtime."""
RUNTIME_NAME = "leo-identity-readback-v1"

View file

@ -0,0 +1,3 @@
"""Pinned fixture registry for the no-send identity readback tool."""
REGISTERED_TOOLS = ("identity_readback",)

View file

@ -0,0 +1,18 @@
{
"identity_name": "Leo",
"rules": [
{
"id": "canonical-evidence",
"text": "Treat canonical database rows and their bound evidence as durable knowledge; never promote session memory to evidence."
},
{
"id": "review-before-apply",
"text": "Proposals may be prepared, but review and guarded apply remain separate authorized actions."
},
{
"id": "truthful-proof-tier",
"text": "State exactly what was observed, separate inference from proof, and fail closed when required provenance drifts."
}
],
"schema": "livingip.leoConstitutionSource.v1"
}

View file

@ -0,0 +1,25 @@
{
"environment": "disposable_fixture",
"fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"read_consistency": {
"after": {
"database": "leo_identity_fixture",
"database_user": "leo_identity_reader",
"system_identifier": "7649789040005668902",
"wal_lsn": "0/16B6C50"
},
"before": {
"database": "leo_identity_fixture",
"database_user": "leo_identity_reader",
"system_identifier": "7649789040005668902",
"wal_lsn": "0/16B6C50"
},
"status": "stable_wal_marker"
},
"schema": "livingip.teleoCanonicalDatabaseFingerprint.v1",
"status": "ok",
"structure_sha256": "3333333333333333333333333333333333333333333333333333333333333333",
"table_count": 7,
"table_rows_sha256": "2222222222222222222222222222222222222222222222222222222222222222",
"total_rows": 7
}

View file

@ -0,0 +1,58 @@
{
"database_fingerprint_sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"identity_name": "Leo",
"source_provenance": {
"canonical_authority_granted": false,
"export_receipt_sha256": null,
"mode": "synthetic_noncanonical_fixture",
"same_transaction_as_fingerprint": false
},
"records": [
{
"evidence_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"kind": "persona",
"rank": 0,
"row_id": "11111111-1111-4111-8111-111111111111",
"status": "active",
"table": "public.personas",
"text": "Leo is the evidence-bound reasoning interface for the Teleo collective."
},
{
"evidence_sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"kind": "strategy",
"rank": 0,
"row_id": "22222222-2222-4222-8222-222222222222",
"status": "active",
"table": "public.strategies",
"text": "Prefer source-grounded synthesis that exposes uncertainty and review boundaries."
},
{
"evidence_sha256": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"kind": "belief",
"rank": 0,
"row_id": "33333333-3333-4333-8333-333333333333",
"status": "active",
"table": "public.beliefs",
"text": "A plausible answer without provenance is weaker than a bounded answer with an exact receipt."
},
{
"evidence_sha256": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"kind": "shared_root",
"rank": 0,
"row_id": "44444444-4444-4444-8444-444444444444",
"status": "active",
"table": "public.shared_root",
"text": "Collective intelligence must remain inspectable, reversible, and accountable to evidence."
},
{
"evidence_sha256": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"kind": "strategy_node",
"rank": 1,
"row_id": "55555555-5555-4555-8555-555555555555",
"status": "active",
"table": "public.strategy_nodes",
"text": "Compile identity from exact canonical inputs and reject drift before runtime startup."
}
],
"schema": "livingip.leoDatabaseIdentitySource.v1"
}

View file

@ -0,0 +1,5 @@
#!/usr/bin/env python3
"""Fixture marker for the no-send identity readback tool."""
ACCESS_MODE = "read_only"
NETWORK_SEND_ENABLED = False

View file

@ -0,0 +1,24 @@
model:
provider: fixture-local
default: leo-identity-readback-v1
smart_routing: false
max_tokens: 512
agent:
reasoning_effort: deterministic
memory:
enabled: false
search: disabled
gateway:
execution_mode: local_no_send
telegram:
posting_enabled: false
bot_token: fixture-value-is-never-emitted-or-identity-hashed
tools:
allowed:
- identity_readback
write_enabled: false
identity_runtime:
network_send_enabled: false
database_write_enabled: false
allowed_tools:
- identity_readback

View file

@ -0,0 +1,4 @@
"""Fixture marker for the pinned identity-boundary middleware."""
IDENTITY_VIEW_IS_AUTHORITY = False
SESSION_MEMORY_IS_EVIDENCE = False

View file

@ -0,0 +1,3 @@
name: identity-boundary
version: 1
description: Reject startup when a compiled identity view drifts.

View file

@ -0,0 +1,8 @@
---
name: identity-readback
description: Explain the pinned Leo identity and its noncanonical session boundary.
---
Read only the compiled identity view and its manifest receipt. Never treat a
session transcript, generated SOUL file, or unverified runtime memory as a
canonical source.

View file

@ -0,0 +1,3 @@
{"ts":"2026-07-15T09:00:01Z","chat_id":900001,"chat_title":"Synthetic review gate thread","message_id":7301,"type":"message","username":"fixture_analyst","display_name":"Fixture Analyst","user_id":910001,"message":"A pending review does not change canonical knowledge; only a separate guarded apply can do that.","reply_to":null,"synthetic":true}
{"ts":"2026-07-15T09:00:12Z","chat_id":900001,"chat_title":"Synthetic review gate thread","message_id":7302,"type":"message","username":"fixture_operator","display_name":"Fixture Operator","user_id":910002,"message":"Reviewer approval alone makes the proposal canonical immediately; no apply step is needed.","reply_to":7301,"synthetic":true}
{"ts":"2026-07-15T09:00:24Z","chat_id":900001,"chat_title":"Synthetic review gate thread","message_id":7303,"type":"message","username":"fixture_reviewer","display_name":"Fixture Reviewer","user_id":910003,"message":"A pending review does not change canonical knowledge; only a separate guarded apply can do that.","reply_to":7302,"synthetic":true}

View file

@ -0,0 +1,99 @@
{
"schema": "livingip.workingLeoSourceIngestionScenario.v2",
"artifact": {
"path": "telegram-transcript-ingestion-v1.jsonl",
"format": "telegram_jsonl"
},
"source": {
"identity": "fixture:telegram-chat-900001-export-20260715",
"source_key": "telegram_review_gate_exchange_20260715",
"source_type": "transcript",
"title": "Synthetic Telegram review-gate exchange",
"locator": "fixture://working-leo/telegram-transcript-ingestion-v1",
"metadata": {
"captured_at": "2026-07-15T09:01:00Z",
"export_format": "teleo_append_only_telegram_jsonl",
"language": "en",
"synthetic": true
}
},
"extractor": {
"name": "deterministic_telegram_jsonl_replay",
"version": "1"
},
"extraction": {
"claims": [
{
"claim_key": "pending_review_does_not_change_canonical",
"type": "structural",
"confidence": 0.7,
"text": "Pending review alone does not change canonical knowledge.",
"body": "A pending review does not change canonical knowledge; only a separate guarded apply can do that.",
"metadata": {
"needs_research": false
},
"evidence": [
{
"segment_id": "message-900001-7301",
"role": "grounds",
"excerpt": "A pending review does not change canonical knowledge; only a separate guarded apply can do that.",
"metadata": {
"evidence_kind": "exact_message"
}
},
{
"segment_id": "message-900001-7303",
"role": "illustrates",
"excerpt": "A pending review does not change canonical knowledge; only a separate guarded apply can do that.",
"metadata": {
"evidence_kind": "duplicate_exact_message"
}
}
],
"edges": [
{
"edge_type": "contradicts",
"target": "approval_alone_makes_canonical"
}
]
},
{
"claim_key": "approval_alone_makes_canonical",
"type": "empirical",
"confidence": 0.4,
"text": "Reviewer approval alone makes a proposal canonical without apply.",
"body": "Reviewer approval alone makes the proposal canonical immediately; no apply step is needed.",
"metadata": {
"needs_research": true
},
"evidence": [
{
"segment_id": "message-900001-7302",
"role": "grounds",
"excerpt": "Reviewer approval alone makes the proposal canonical immediately; no apply step is needed.",
"metadata": {
"evidence_kind": "exact_message"
}
}
],
"edges": []
}
],
"duplicates": [
{
"segment_id": "message-900001-7303",
"duplicate_of_claim_key": "pending_review_does_not_change_canonical",
"excerpt": "A pending review does not change canonical knowledge; only a separate guarded apply can do that.",
"reason": "Message 7303 repeats message 7301 exactly and is retained as explicit duplicate evidence."
}
],
"conflicts": [
{
"from_claim_key": "pending_review_does_not_change_canonical",
"to_claim_key": "approval_alone_makes_canonical",
"relationship": "contradicts",
"reason": "The two candidate propositions assert incompatible canonical-state transitions."
}
]
}
}

View file

@ -1,12 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Deterministically rebuild a disposable Postgres from genesis plus a strict ledger. """Deterministically rebuild a disposable Postgres from genesis plus a strict ledger.
The v1 replay boundary is intentionally narrow. It supports strict, insert-only The v1 replay boundary supports strict ``add_edge``, ``attach_evidence``,
``add_edge``, ``attach_evidence``, and ``approve_claim`` receipts. Each ledger ``approve_claim``, and ``revise_strategy`` receipts. Insert-only actions seed
entry must also retain the exact approved and applied proposal rows plus the their receipt-pinned rows before the guarded transition. ``revise_strategy``
immutable approval snapshot. Legacy/freeform entries and ``revise_strategy`` instead captures the exact prestate identities, executes the exact hash-matched
fail before Docker starts because their retained material is not a complete guarded SQL, validates the generated delta, and normalizes only that delta to the
database delta. receipt-pinned transaction timestamp, IDs, and rows. Every entry must retain the
full approved and applied proposal rows plus its immutable approval snapshot.
Legacy and freeform entries still fail before Docker starts.
""" """
from __future__ import annotations from __future__ import annotations
@ -46,15 +48,18 @@ LEDGER_ARTIFACT = "teleo_genesis_plus_ledger"
MATERIAL_ARTIFACT = "teleo_strict_proposal_replay_material" MATERIAL_ARTIFACT = "teleo_strict_proposal_replay_material"
LEDGER_CONTRACT_VERSION = 1 LEDGER_CONTRACT_VERSION = 1
MATERIAL_CONTRACT_VERSION = 1 MATERIAL_CONTRACT_VERSION = 1
SUPPORTED_PROPOSAL_TYPES = frozenset({"add_edge", "attach_evidence", "approve_claim"}) DEFAULT_REBUILD_IMAGE = (
"docker.io/library/postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777"
)
SUPPORTED_PROPOSAL_TYPES = frozenset({"add_edge", "attach_evidence", "approve_claim", "revise_strategy"})
CLAIM_CEILING = ( CLAIM_CEILING = (
"exact genesis plus ordered strict insert-only proposal replay; supported types are " "exact genesis plus ordered strict proposal replay; supported types are add_edge, "
"add_edge, attach_evidence, and approve_claim; full approved/applied proposal rows " "attach_evidence, approve_claim, and revise_strategy; mutating strategy replay "
"and immutable approval snapshots are required" "captures prestate identities and normalizes the exact receipt-pinned poststate; "
"full approved/applied proposal rows and immutable approval snapshots are required"
) )
NOT_PROVEN = ( NOT_PROVEN = (
"legacy or freeform proposal replay", "legacy or freeform proposal replay",
"revise_strategy replay because prior-row mutations are absent from v1 receipts",
"source-corpus recompilation from a blank schema", "source-corpus recompilation from a blank schema",
"VPS, GCP, Telegram, or any live database mutation", "VPS, GCP, Telegram, or any live database mutation",
) )
@ -77,6 +82,7 @@ FIXED_ENGINE_PATHS = frozenset(
) )
SHA256_RE = re.compile(r"[0-9a-f]{64}\Z") SHA256_RE = re.compile(r"[0-9a-f]{64}\Z")
IMAGE_DIGEST_RE = re.compile(r"\S+@sha256:[0-9a-f]{64}\Z")
PROPOSAL_TRANSITION_FIELDS = frozenset( PROPOSAL_TRANSITION_FIELDS = frozenset(
{"status", "applied_by_handle", "applied_by_agent_id", "applied_at", "updated_at"} {"status", "applied_by_handle", "applied_by_agent_id", "applied_at", "updated_at"}
) )
@ -121,6 +127,35 @@ CANONICAL_TABLE_ORDER = (
"claim_evidence", "claim_evidence",
"claim_edges", "claim_edges",
) )
STRATEGY_REQUIRED_FIELDS = frozenset(
{
"id",
"agent_id",
"diagnosis",
"guiding_policy",
"proximate_objectives",
"version",
"active",
"created_at",
}
)
STRATEGY_NODE_REQUIRED_FIELDS = frozenset(
{
"id",
"agent_id",
"node_type",
"title",
"body",
"rank",
"status",
"horizon",
"measure",
"source_ref",
"metadata",
"created_at",
"updated_at",
}
)
class ReconstructionError(RuntimeError): class ReconstructionError(RuntimeError):
@ -308,6 +343,116 @@ def _validate_proposal_rows(
) )
def _parse_aware_timestamp(value: Any, field: str, *, code: str = "invalid_mutating_receipt") -> datetime:
if not isinstance(value, str) or not value:
raise ReconstructionError(code, f"{field} must be an ISO-8601 timestamp")
try:
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
except ValueError as exc:
raise ReconstructionError(code, f"{field} must be an ISO-8601 timestamp") from exc
if parsed.tzinfo is None:
raise ReconstructionError(code, f"{field} must include a timezone")
return parsed
def _validated_uuid_list(value: Any, field: str, *, code: str = "invalid_mutating_state") -> list[str]:
if not isinstance(value, list):
raise ReconstructionError(code, f"{field} must be a UUID list")
normalized: list[str] = []
for item in value:
try:
normalized.append(str(uuid.UUID(str(item))))
except (TypeError, ValueError, AttributeError) as exc:
raise ReconstructionError(code, f"{field} must contain only UUIDs") from exc
if len(normalized) != len(set(normalized)):
raise ReconstructionError(code, f"{field} contains duplicate UUIDs")
return normalized
def _validate_revise_strategy_receipt_rows(
proposal: dict[str, Any], canonical_rows: dict[str, Any]
) -> tuple[dict[str, Any], list[dict[str, Any]]]:
payload = proposal.get("payload")
apply_payload = payload.get("apply_payload") if isinstance(payload, dict) else None
if not isinstance(apply_payload, dict):
raise ReconstructionError("invalid_mutating_receipt", "revise_strategy receipt requires a strict apply payload")
try:
agent_id = str(uuid.UUID(str(apply_payload.get("agent_id"))))
except (TypeError, ValueError, AttributeError) as exc:
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy receipt requires one agent UUID"
) from exc
strategies = canonical_rows.get("strategies")
nodes = canonical_rows.get("strategy_nodes")
if not isinstance(strategies, list) or len(strategies) != 1 or not isinstance(strategies[0], dict):
raise ReconstructionError("invalid_mutating_receipt", "revise_strategy receipt must pin one fresh strategy row")
expected_nodes = apply_payload.get("strategy_nodes")
if (
not isinstance(expected_nodes, list)
or not isinstance(nodes, list)
or len(nodes) != len(expected_nodes)
or any(not isinstance(row, dict) for row in nodes)
):
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy receipt must pin every fresh strategy node row"
)
strategy = strategies[0]
if frozenset(strategy) != STRATEGY_REQUIRED_FIELDS:
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy receipt strategy row fields are not canonical"
)
if any(frozenset(row) != STRATEGY_NODE_REQUIRED_FIELDS for row in nodes):
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy receipt strategy node row fields are not canonical"
)
strategy_id = _validated_uuid_list([strategy.get("id")], "receipt strategy id", code="invalid_mutating_receipt")[0]
node_ids = _validated_uuid_list(
[row.get("id") for row in nodes],
"receipt strategy node ids",
code="invalid_mutating_receipt",
)
if strategy.get("agent_id") != agent_id or any(row.get("agent_id") != agent_id for row in nodes):
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy receipt rows do not belong to the payload agent"
)
if strategy.get("active") is not True or any(row.get("status") != "active" for row in nodes):
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy receipt must pin the fresh active poststate"
)
version = strategy.get("version")
if isinstance(version, bool) or not isinstance(version, int) or version < 1:
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy receipt strategy version must be positive"
)
transaction_timestamp = strategy.get("created_at")
transaction_time = _parse_aware_timestamp(transaction_timestamp, "receipt strategy created_at")
for row in nodes:
if row.get("created_at") != transaction_timestamp or row.get("updated_at") != transaction_timestamp:
raise ReconstructionError(
"invalid_mutating_receipt",
"revise_strategy fresh strategy and node timestamps must share one transaction timestamp",
)
reviewed_time = _parse_aware_timestamp(proposal.get("reviewed_at"), "receipt proposal reviewed_at")
applied_time = _parse_aware_timestamp(proposal.get("applied_at"), "receipt proposal applied_at")
if reviewed_time > applied_time:
raise ReconstructionError("invalid_mutating_receipt", "revise_strategy proposal approval is after apply time")
if transaction_time < reviewed_time:
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy transaction timestamp is before proposal approval"
)
if transaction_time > applied_time:
raise ReconstructionError(
"invalid_mutating_receipt", "revise_strategy transaction timestamp is after proposal apply time"
)
return {**strategy, "id": strategy_id}, [
{**row, "id": normalized_id} for row, normalized_id in zip(nodes, node_ids, strict=True)
]
def _validate_entry_material( def _validate_entry_material(
material: dict[str, Any], material: dict[str, Any],
*, *,
@ -340,11 +485,6 @@ def _validate_entry_material(
if not isinstance(proposal, dict): if not isinstance(proposal, dict):
raise ReconstructionError("invalid_material", "replay receipt has no proposal object") raise ReconstructionError("invalid_material", "replay receipt has no proposal object")
proposal_type = proposal.get("proposal_type") proposal_type = proposal.get("proposal_type")
if proposal_type == "revise_strategy":
raise ReconstructionError(
"unsupported_mutating_receipt",
"revise_strategy receipts omit prior strategy and node mutations and cannot replay exactly",
)
if proposal_type not in SUPPORTED_PROPOSAL_TYPES: if proposal_type not in SUPPORTED_PROPOSAL_TYPES:
raise ReconstructionError( raise ReconstructionError(
"unsupported_proposal_type", "ledger entry proposal type is not supported by v1 reconstruction" "unsupported_proposal_type", "ledger entry proposal type is not supported by v1 reconstruction"
@ -358,6 +498,8 @@ def _validate_entry_material(
canonical_rows = receipt.get("canonical_rows") canonical_rows = receipt.get("canonical_rows")
if not isinstance(apply_metadata, dict) or not isinstance(canonical_rows, dict): if not isinstance(apply_metadata, dict) or not isinstance(canonical_rows, dict):
raise ReconstructionError("invalid_replay_receipt", "replay receipt is missing apply or row material") raise ReconstructionError("invalid_replay_receipt", "replay receipt is missing apply or row material")
if proposal_type == "revise_strategy":
_validate_revise_strategy_receipt_rows(proposal, canonical_rows)
try: try:
rebuilt = replay_receipt.build_replay_receipt( rebuilt = replay_receipt.build_replay_receipt(
proposal, proposal,
@ -382,6 +524,7 @@ def _validate_entry_material(
raise ReconstructionError( raise ReconstructionError(
"replay_material_hash_mismatch", "ledger replay-material pin does not match the private receipt" "replay_material_hash_mismatch", "ledger replay-material pin does not match the private receipt"
) )
receipt = {**receipt, "canonical_rows": rebuilt["canonical_rows"]}
approved = material["approved_proposal"] approved = material["approved_proposal"]
approval = material["approval_snapshot"] approval = material["approval_snapshot"]
@ -394,6 +537,15 @@ def _validate_entry_material(
"current_apply_engine_rejected_material", "current_apply_engine_rejected_material",
"current guarded apply engine rejected the strict replay material", "current guarded apply engine rejected the strict replay material",
) from exc ) from exc
current_apply_sql_sha256 = _sha256_text(current_apply_sql)
if proposal_type == "revise_strategy" and (
apply_metadata.get("source") != "exact_executed_sql"
or apply_metadata.get("apply_sql_sha256") != current_apply_sql_sha256
):
raise ReconstructionError(
"mutating_apply_engine_mismatch",
"revise_strategy replay requires the exact executed SQL to match the current guarded apply engine",
)
return LedgerEntry( return LedgerEntry(
sequence=expected_sequence, sequence=expected_sequence,
@ -405,7 +557,7 @@ def _validate_entry_material(
applied_proposal=applied, applied_proposal=applied,
receipt=receipt, receipt=receipt,
current_apply_sql=current_apply_sql, current_apply_sql=current_apply_sql,
current_apply_sql_sha256=_sha256_text(current_apply_sql), current_apply_sql_sha256=current_apply_sql_sha256,
) )
@ -550,6 +702,266 @@ def build_seed_sql(entry: LedgerEntry) -> str:
return "\n".join(statements) + "\n" return "\n".join(statements) + "\n"
def _uuid_membership_sql(column: str, values: list[str], *, negate: bool = False) -> str:
if not values:
return "true" if negate else "false"
rendered = ", ".join(f"{apply_engine.sql_literal(value)}::uuid" for value in values)
operator = "not in" if negate else "in"
return f"{column} {operator} ({rendered})"
def _uuid_array_sql(values: list[str]) -> str:
if not values:
return "array[]::uuid[]"
rendered = ", ".join(f"{apply_engine.sql_literal(value)}::uuid" for value in values)
return f"array[{rendered}]::uuid[]"
def build_revise_strategy_prestate_sql(entry: LedgerEntry) -> str:
apply_payload = entry.receipt["proposal"]["payload"]["apply_payload"]
agent = apply_engine.sql_literal(apply_payload["agent_id"])
return f"""with strategy_state as (
select coalesce(jsonb_agg(s.id::text order by s.id::text), '[]'::jsonb) as strategy_ids,
coalesce(
jsonb_agg(s.id::text order by s.id::text) filter (where s.active),
'[]'::jsonb
) as active_strategy_ids,
coalesce(max(s.version), 0) as max_strategy_version
from public.strategies s
where s.agent_id = {agent}::uuid
), node_state as (
select coalesce(jsonb_agg(n.id::text order by n.id::text), '[]'::jsonb) as strategy_node_ids,
coalesce(
jsonb_agg(n.id::text order by n.id::text) filter (where n.status <> 'retired'),
'[]'::jsonb
) as non_retired_strategy_node_ids
from public.strategy_nodes n
where n.agent_id = {agent}::uuid
)
select jsonb_build_object(
'strategy_ids', s.strategy_ids,
'active_strategy_ids', s.active_strategy_ids,
'max_strategy_version', s.max_strategy_version,
'strategy_node_ids', n.strategy_node_ids,
'non_retired_strategy_node_ids', n.non_retired_strategy_node_ids
)::text
from strategy_state s cross join node_state n;
"""
def _validate_revise_strategy_prestate(value: Any) -> dict[str, Any]:
expected = frozenset(
{
"strategy_ids",
"active_strategy_ids",
"max_strategy_version",
"strategy_node_ids",
"non_retired_strategy_node_ids",
}
)
state = _require_exact_keys(value, expected, "revise_strategy prestate")
strategy_ids = _validated_uuid_list(state["strategy_ids"], "prestate strategy ids")
active_strategy_ids = _validated_uuid_list(state["active_strategy_ids"], "prestate active strategy ids")
strategy_node_ids = _validated_uuid_list(state["strategy_node_ids"], "prestate strategy node ids")
non_retired_node_ids = _validated_uuid_list(
state["non_retired_strategy_node_ids"], "prestate non-retired strategy node ids"
)
max_version = state["max_strategy_version"]
if isinstance(max_version, bool) or not isinstance(max_version, int) or max_version < 0:
raise ReconstructionError(
"invalid_mutating_state", "prestate maximum strategy version must be a non-negative integer"
)
if len(active_strategy_ids) > 1 or not set(active_strategy_ids).issubset(strategy_ids):
raise ReconstructionError(
"invalid_mutating_state", "prestate active strategies violate the one-active invariant"
)
if not set(non_retired_node_ids).issubset(strategy_node_ids):
raise ReconstructionError(
"invalid_mutating_state", "prestate non-retired strategy nodes are not a subset of all nodes"
)
return {
"strategy_ids": strategy_ids,
"active_strategy_ids": active_strategy_ids,
"max_strategy_version": max_version,
"strategy_node_ids": strategy_node_ids,
"non_retired_strategy_node_ids": non_retired_node_ids,
}
def build_revise_strategy_generated_delta_sql(entry: LedgerEntry, prestate: dict[str, Any]) -> str:
state = _validate_revise_strategy_prestate(prestate)
apply_payload = entry.receipt["proposal"]["payload"]["apply_payload"]
agent = apply_engine.sql_literal(apply_payload["agent_id"])
strategy_filter = _uuid_membership_sql("s.id", state["strategy_ids"], negate=True)
node_filter = _uuid_membership_sql("n.id", state["strategy_node_ids"], negate=True)
return f"""select jsonb_build_object(
'strategies', coalesce((
select jsonb_agg(to_jsonb(s) order by s.id::text)
from public.strategies s
where s.agent_id = {agent}::uuid and {strategy_filter}
), '[]'::jsonb),
'strategy_nodes', coalesce((
select jsonb_agg(to_jsonb(n) order by n.id::text)
from public.strategy_nodes n
where n.agent_id = {agent}::uuid and {node_filter}
), '[]'::jsonb)
)::text;
"""
def _validate_revise_strategy_generated_delta(
entry: LedgerEntry,
prestate: dict[str, Any],
generated_rows: Any,
) -> tuple[dict[str, Any], list[dict[str, Any]]]:
state = _validate_revise_strategy_prestate(prestate)
if not isinstance(generated_rows, dict):
raise ReconstructionError("invalid_mutating_delta", "revise_strategy generated delta must be a row object")
try:
replay_receipt.build_replay_receipt(
entry.receipt["proposal"],
generated_rows,
apply_sql_sha256=entry.current_apply_sql_sha256,
apply_sql_source="exact_executed_sql",
exported_at_utc=entry.receipt.get("exported_at_utc"),
)
except (KeyError, TypeError, ValueError) as exc:
raise ReconstructionError(
"invalid_mutating_delta",
"revise_strategy generated rows do not match the strict payload",
) from exc
strategies = generated_rows.get("strategies")
nodes = generated_rows.get("strategy_nodes")
if not isinstance(strategies, list) or len(strategies) != 1 or not isinstance(strategies[0], dict):
raise ReconstructionError(
"invalid_mutating_delta", "revise_strategy apply did not generate exactly one strategy"
)
if not isinstance(nodes, list) or any(not isinstance(row, dict) for row in nodes):
raise ReconstructionError("invalid_mutating_delta", "revise_strategy apply generated invalid strategy nodes")
strategy = strategies[0]
if strategy.get("version") != state["max_strategy_version"] + 1:
raise ReconstructionError("invalid_mutating_delta", "revise_strategy generated an unexpected strategy version")
transaction_timestamp = strategy.get("created_at")
_parse_aware_timestamp(transaction_timestamp, "generated strategy created_at", code="invalid_mutating_delta")
if any(
row.get("created_at") != transaction_timestamp or row.get("updated_at") != transaction_timestamp
for row in nodes
):
raise ReconstructionError(
"invalid_mutating_delta",
"revise_strategy generated rows do not share one transaction timestamp",
)
_validated_uuid_list([strategy.get("id")], "generated strategy id", code="invalid_mutating_delta")
_validated_uuid_list(
[row.get("id") for row in nodes],
"generated strategy node ids",
code="invalid_mutating_delta",
)
return strategy, nodes
def build_revise_strategy_normalization_sql(
entry: LedgerEntry,
prestate: dict[str, Any],
generated_rows: dict[str, Any],
) -> str:
state = _validate_revise_strategy_prestate(prestate)
generated_strategy, generated_nodes = _validate_revise_strategy_generated_delta(entry, state, generated_rows)
receipt_strategy, receipt_nodes = _validate_revise_strategy_receipt_rows(
entry.receipt["proposal"], entry.receipt["canonical_rows"]
)
if receipt_strategy["version"] != state["max_strategy_version"] + 1:
raise ReconstructionError(
"mutating_receipt_version_mismatch",
"revise_strategy receipt version does not follow the observed prestate",
)
if receipt_strategy["id"] in state["strategy_ids"] or set(row["id"] for row in receipt_nodes).intersection(
state["strategy_node_ids"]
):
raise ReconstructionError(
"mutating_receipt_id_collision", "revise_strategy receipt IDs collide with the observed prestate"
)
apply_payload = entry.receipt["proposal"]["payload"]["apply_payload"]
agent = apply_engine.sql_literal(apply_payload["agent_id"])
generated_strategy_id = str(uuid.UUID(str(generated_strategy["id"])))
generated_node_ids = [str(uuid.UUID(str(row["id"]))) for row in generated_nodes]
previous_active = state["active_strategy_ids"]
changed_node_ids = state["non_retired_strategy_node_ids"]
transaction_timestamp = apply_engine.sql_literal(receipt_strategy["created_at"])
generated_node_array = _uuid_array_sql(generated_node_ids)
previous_active_array = _uuid_array_sql(previous_active)
changed_node_array = _uuid_array_sql(changed_node_ids)
prior_strategy_assertion = ""
if previous_active:
prior_strategy_assertion = f"""
if (select count(*) from public.strategies
where agent_id = {agent}::uuid and id = any(previous_active_ids) and not active) <> {len(previous_active)} then
raise exception 'revise_strategy prior active strategy transition mismatch';
end if;"""
prior_node_normalization = ""
if changed_node_ids:
prior_node_normalization = f"""
if (select count(*) from public.strategy_nodes
where agent_id = {agent}::uuid and id = any(changed_node_ids) and status = 'retired') <> {len(changed_node_ids)} then
raise exception 'revise_strategy prior node transition mismatch';
end if;
update public.strategy_nodes
set status = 'retired', updated_at = {transaction_timestamp}::timestamptz
where agent_id = {agent}::uuid and id = any(changed_node_ids);
get diagnostics changed_rows = row_count;
if changed_rows <> {len(changed_node_ids)} then
raise exception 'revise_strategy prior node normalization mismatch';
end if;"""
return f"""begin;
set local standard_conforming_strings = on;
do $reconstruction$
declare
changed_rows integer;
generated_strategy_id constant uuid := {apply_engine.sql_literal(generated_strategy_id)}::uuid;
generated_node_ids constant uuid[] := {generated_node_array};
previous_active_ids constant uuid[] := {previous_active_array};
changed_node_ids constant uuid[] := {changed_node_array};
begin{prior_strategy_assertion}
if exists (
select 1 from public.strategy_node_anchors
where from_node_id = any(generated_node_ids) or to_node_id = any(generated_node_ids)
) then
raise exception 'revise_strategy generated nodes unexpectedly have anchors';
end if;
delete from public.strategy_nodes
where agent_id = {agent}::uuid and id = any(generated_node_ids);
get diagnostics changed_rows = row_count;
if changed_rows <> {len(generated_node_ids)} then
raise exception 'revise_strategy generated node delta mismatch';
end if;
delete from public.strategies
where agent_id = {agent}::uuid and id = generated_strategy_id;
get diagnostics changed_rows = row_count;
if changed_rows <> 1 then
raise exception 'revise_strategy generated strategy delta mismatch';
end if;{prior_node_normalization}
insert into public.strategies
select seeded.* from jsonb_populate_record(
null::public.strategies, {_jsonb_literal(receipt_strategy)}
) seeded;
insert into public.strategy_nodes
select seeded.* from jsonb_populate_recordset(
null::public.strategy_nodes, {_jsonb_literal(receipt_nodes)}
) seeded;
if (select count(*) from public.strategies
where agent_id = {agent}::uuid and active) <> 1 then
raise exception 'revise_strategy normalized one-active invariant mismatch';
end if;
end
$reconstruction$;
commit;
"""
def build_proposal_readback_sql(proposal_id: str) -> str: def build_proposal_readback_sql(proposal_id: str) -> str:
literal = apply_engine.sql_literal(proposal_id) literal = apply_engine.sql_literal(proposal_id)
return f"""select jsonb_build_object( return f"""select jsonb_build_object(
@ -694,7 +1106,12 @@ def _entry_summary(entry: LedgerEntry) -> dict[str, Any]:
"current_apply_sql_sha256": entry.current_apply_sql_sha256, "current_apply_sql_sha256": entry.current_apply_sql_sha256,
"expected_row_counts": entry.receipt["expected_row_counts"], "expected_row_counts": entry.receipt["expected_row_counts"],
"seed_exact": False, "seed_exact": False,
"proposal_seed_exact": False,
"canonical_seed_exact": False,
"guarded_apply_executed": False, "guarded_apply_executed": False,
"mutating_prestate_captured": False,
"mutating_delta_validated": False,
"mutating_poststate_normalized": False,
"proposal_exact": False, "proposal_exact": False,
"canonical_rows_exact": False, "canonical_rows_exact": False,
"status": "pending", "status": "pending",
@ -707,6 +1124,7 @@ def apply_entry(
entry: LedgerEntry, entry: LedgerEntry,
summary: dict[str, Any], summary: dict[str, Any],
) -> None: ) -> None:
mutating_prestate: dict[str, Any] | None = None
try: try:
_psql( _psql(
args, args,
@ -733,6 +1151,19 @@ def apply_entry(
code="entry_seed_mismatch", code="entry_seed_mismatch",
action=f"ledger entry {entry.sequence} proposal seed", action=f"ledger entry {entry.sequence} proposal seed",
) )
summary["proposal_seed_exact"] = True
if entry.applied_proposal["proposal_type"] == "revise_strategy":
mutating_prestate = _validate_revise_strategy_prestate(
_read_json(
args,
container,
build_revise_strategy_prestate_sql(entry),
code="mutating_prestate_readback_failed",
action=f"ledger entry {entry.sequence} revise_strategy prestate readback",
)
)
summary["mutating_prestate_captured"] = True
else:
seeded_rows = _read_json( seeded_rows = _read_json(
args, args,
container, container,
@ -746,7 +1177,8 @@ def apply_entry(
code="entry_seed_mismatch", code="entry_seed_mismatch",
action=f"ledger entry {entry.sequence} canonical seed", action=f"ledger entry {entry.sequence} canonical seed",
) )
summary["seed_exact"] = True summary["canonical_seed_exact"] = True
summary["seed_exact"] = summary["proposal_seed_exact"] and summary["canonical_seed_exact"]
_psql( _psql(
args, args,
@ -759,6 +1191,27 @@ def apply_entry(
) )
summary["guarded_apply_executed"] = True summary["guarded_apply_executed"] = True
if mutating_prestate is not None:
generated_rows = _read_json(
args,
container,
build_revise_strategy_generated_delta_sql(entry, mutating_prestate),
code="mutating_delta_readback_failed",
action=f"ledger entry {entry.sequence} revise_strategy generated delta readback",
)
normalization_sql = build_revise_strategy_normalization_sql(entry, mutating_prestate, generated_rows)
summary["mutating_delta_validated"] = True
_psql(
args,
container,
normalization_sql,
role="postgres",
timeout=args.apply_timeout,
code="mutating_poststate_normalization_failed",
action=f"ledger entry {entry.sequence} revise_strategy exact poststate normalization",
)
summary["mutating_poststate_normalized"] = True
_psql( _psql(
args, args,
container, container,
@ -1199,7 +1652,7 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser.add_argument("--ledger", required=True, type=Path) parser.add_argument("--ledger", required=True, type=Path)
parser.add_argument("--ledger-sha256", required=True) parser.add_argument("--ledger-sha256", required=True)
parser.add_argument("--database", default="teleo") parser.add_argument("--database", default="teleo")
parser.add_argument("--image", default=canonical_rebuild.DEFAULT_IMAGE) parser.add_argument("--image", default=DEFAULT_REBUILD_IMAGE)
parser.add_argument("--container-prefix", default="teleo-genesis-ledger-rebuild") parser.add_argument("--container-prefix", default="teleo-genesis-ledger-rebuild")
parser.add_argument("--tmpfs-mb", default=1024, type=int) parser.add_argument("--tmpfs-mb", default=1024, type=int)
parser.add_argument("--startup-timeout", default=60.0, type=float) parser.add_argument("--startup-timeout", default=60.0, type=float)
@ -1218,8 +1671,8 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser.error("--database must be a safe PostgreSQL identifier up to 63 characters") parser.error("--database must be a safe PostgreSQL identifier up to 63 characters")
if not canonical_rebuild.CONTAINER_PREFIX_RE.fullmatch(args.container_prefix): if not canonical_rebuild.CONTAINER_PREFIX_RE.fullmatch(args.container_prefix):
parser.error("--container-prefix must be 1-40 Docker-safe characters") parser.error("--container-prefix must be 1-40 Docker-safe characters")
if not args.image or any(character.isspace() for character in args.image): if not IMAGE_DIGEST_RE.fullmatch(args.image):
parser.error("--image must be a non-empty Docker image reference without whitespace") parser.error("--image must be pinned by a lowercase sha256 digest")
if not args.docker_bin or any(character.isspace() for character in args.docker_bin): if not args.docker_bin or any(character.isspace() for character in args.docker_bin):
parser.error("--docker-bin must be one executable name or path without whitespace") parser.error("--docker-bin must be one executable name or path without whitespace")
if not 64 <= args.tmpfs_mb <= 65536: if not 64 <= args.tmpfs_mb <= 65536:

View file

@ -315,8 +315,9 @@ alter table kb_stage.kb_review_principals owner to kb_gate_owner;
alter table kb_stage.kb_proposal_approvals owner to kb_gate_owner; alter table kb_stage.kb_proposal_approvals owner to kb_gate_owner;
insert into kb_stage.kb_review_principals insert into kb_stage.kb_review_principals
(db_role, reviewed_by_handle, reviewed_by_agent_id, active) (db_role, reviewed_by_handle, reviewed_by_agent_id, active, created_at)
select 'kb_review'::name, a.handle, a.id, true select 'kb_review'::name, a.handle, a.id, true,
'1970-01-01 00:00:00+00'::timestamptz
from public.agents a from public.agents a
where a.handle = 'm3ta' where a.handle = 'm3ta'
on conflict (db_role) do nothing; on conflict (db_role) do nothing;

View file

@ -11,9 +11,13 @@ from __future__ import annotations
import argparse import argparse
import hashlib import hashlib
import importlib.metadata
import json import json
import os import os
import platform
import re
import subprocess import subprocess
import sys
from datetime import datetime, timezone from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
@ -24,6 +28,54 @@ SCHEMA = "livingip.leoBehaviorManifest.v1"
DEFAULT_PROFILE = Path("/home/teleo/.hermes/profiles/leoclean") DEFAULT_PROFILE = Path("/home/teleo/.hermes/profiles/leoclean")
DEFAULT_HERMES_ROOT = Path("/home/teleo/.hermes/hermes-agent") DEFAULT_HERMES_ROOT = Path("/home/teleo/.hermes/hermes-agent")
DEFAULT_DEPLOYMENT_ROOT = Path("/opt/teleo-eval/workspaces/deploy-infra") DEFAULT_DEPLOYMENT_ROOT = Path("/opt/teleo-eval/workspaces/deploy-infra")
STATIC_RUNTIME_COMPONENTS = (
"profile_config",
"procedural_skills",
"runtime_middleware",
"database_tools",
)
IDENTITY_RUNTIME_COMPONENTS = (
"procedural_skills",
"runtime_middleware",
"database_tools",
)
STABLE_MANIFEST_FIELDS = (
"schema",
"model_runtime",
"hermes_runtime",
"teleo_infrastructure_runtime",
"components",
"python_runtime",
"canonical_database",
)
SECRET_KEYS = frozenset(
{
"access_key",
"access_token",
"api_key",
"authorization",
"bot_token",
"client_secret",
"credential",
"credentials",
"password",
"private_key",
"refresh_token",
"secret",
"token",
}
)
SECRET_KEY_SUFFIXES = (
"api_key",
"access_key",
"private_key",
"password",
"secret",
"token",
"credential",
)
RUNTIME_DISTRIBUTIONS = ("PyYAML",)
SAFE_CONFIG_SCALAR = re.compile(r"^[A-Za-z0-9._:/-]+$")
def sha256_bytes(value: bytes) -> str: def sha256_bytes(value: bytes) -> str:
@ -50,7 +102,9 @@ def _safe_relative(path: Path, root: Path) -> str:
return str(path) return str(path)
def _resolved_node_fingerprint(path: Path, seen_directories: frozenset[tuple[int, int]] = frozenset()) -> dict[str, Any]: def _resolved_node_fingerprint(
path: Path, seen_directories: frozenset[tuple[int, int]] = frozenset()
) -> dict[str, Any]:
"""Hash a symlink target, following nested links while stopping directory cycles.""" """Hash a symlink target, following nested links while stopping directory cycles."""
try: try:
@ -141,21 +195,139 @@ def _nested(config: dict[str, Any], *path: str) -> Any:
return value return value
def secret_free_config(value: Any) -> Any:
"""Return a semantic config projection with secret-bearing fields omitted."""
if isinstance(value, dict):
return {
str(key): secret_free_config(item)
for key, item in sorted(value.items(), key=lambda pair: str(pair[0]))
if not _is_secret_key(str(key))
}
if isinstance(value, list):
return [secret_free_config(item) for item in value]
return value
def _validate_identity_config_value(value: Any, *, path: str) -> None:
if value is None or isinstance(value, (bool, int)):
return
if isinstance(value, str):
if not SAFE_CONFIG_SCALAR.fullmatch(value) or "://" in value or "@" in value:
raise ValueError(f"unsafe identity config scalar: {path}")
return
if isinstance(value, list):
for index, item in enumerate(value):
_validate_identity_config_value(item, path=f"{path}[{index}]")
return
if isinstance(value, dict):
for key, item in value.items():
if _is_secret_key(str(key)):
raise ValueError(f"secret-bearing identity config key: {path}.{key}")
_validate_identity_config_value(item, path=f"{path}.{key}")
return
raise ValueError(f"unsupported identity config value: {path}")
def identity_config_projection(raw: dict[str, Any]) -> dict[str, Any]:
"""Build the only configuration surface copied into a disposable identity profile."""
section_fields = {
"model": ("provider", "default", "smart_routing", "smart_routing_model", "max_tokens"),
"agent": ("reasoning_effort",),
"memory": ("enabled", "search"),
"tools": ("allowed", "write_enabled"),
"identity_runtime": ("network_send_enabled", "database_write_enabled", "allowed_tools"),
}
projection: dict[str, Any] = {}
for section, fields in section_fields.items():
source = raw.get(section)
if source is None:
continue
if not isinstance(source, dict):
raise ValueError(f"identity config section must be a mapping: {section}")
selected = {field: source[field] for field in fields if field in source}
_validate_identity_config_value(selected, path=section)
projection[section] = selected
gateway = raw.get("gateway")
if gateway is not None:
if not isinstance(gateway, dict):
raise ValueError("identity config section must be a mapping: gateway")
selected_gateway = {key: gateway[key] for key in ("execution_mode",) if key in gateway}
telegram = gateway.get("telegram")
if telegram is not None:
if not isinstance(telegram, dict):
raise ValueError("identity config section must be a mapping: gateway.telegram")
selected_telegram = {key: telegram[key] for key in ("posting_enabled",) if key in telegram}
if selected_telegram:
selected_gateway["telegram"] = selected_telegram
_validate_identity_config_value(selected_gateway, path="gateway")
projection["gateway"] = selected_gateway
if "smart_model_routing" in raw:
routing = raw["smart_model_routing"]
if not isinstance(routing, bool):
raise ValueError("smart_model_routing must be boolean")
projection["smart_model_routing"] = routing
return projection
def _is_secret_key(key: str) -> bool:
snake_case = re.sub(r"(?<=[a-z0-9])(?=[A-Z])", "_", key)
normalized = re.sub(r"[^a-z0-9]+", "_", snake_case.casefold()).strip("_")
return normalized in SECRET_KEYS or any(normalized.endswith(f"_{suffix}") for suffix in SECRET_KEY_SUFFIXES)
def python_runtime_manifest() -> dict[str, Any]:
distributions: dict[str, str | None] = {}
for name in RUNTIME_DISTRIBUTIONS:
try:
distributions[name] = importlib.metadata.version(name)
except importlib.metadata.PackageNotFoundError:
distributions[name] = None
return {
"implementation": platform.python_implementation(),
"python_version": platform.python_version(),
"abi_tag": sys.implementation.cache_tag,
"runtime_distributions": distributions,
"runtime_distributions_sha256": canonical_sha256(distributions),
}
def safe_model_config(config_path: Path) -> dict[str, Any]: def safe_model_config(config_path: Path) -> dict[str, Any]:
try: try:
raw = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {} raw = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {}
except (OSError, TypeError, yaml.YAMLError) as exc: except (OSError, TypeError, yaml.YAMLError) as exc:
return {"status": "unavailable", "error": type(exc).__name__} return {"status": "unavailable", "error": type(exc).__name__}
if not isinstance(raw, dict):
return {"status": "unavailable", "error": "ConfigNotMapping"}
semantic = secret_free_config(raw)
try:
identity_config = identity_config_projection(raw)
except ValueError:
return {"status": "unavailable", "error": "UnsafeIdentityConfig"}
model_semantic = identity_config.get("model") or {}
return { return {
"status": "observed", "status": "observed",
"provider": _nested(raw, "model", "provider"), "config_sha256": file_sha256(config_path),
"default_model": _nested(raw, "model", "default"), "semantic_config_sha256": canonical_sha256(semantic),
"smart_routing": _nested(raw, "model", "smart_routing"), "identity_config_sha256": canonical_sha256(identity_config),
"smart_routing_model": _nested(raw, "model", "smart_routing_model"), "model_section_sha256": canonical_sha256(model_semantic),
"max_tokens": _nested(raw, "model", "max_tokens"), "gateway_permissions_sha256": canonical_sha256(identity_config.get("gateway")),
"reasoning_effort": _nested(raw, "agent", "reasoning_effort"), "tool_permissions_sha256": canonical_sha256(identity_config.get("tools")),
"memory_enabled": _nested(raw, "memory", "enabled"), "memory_section_sha256": canonical_sha256(identity_config.get("memory")),
"memory_search": _nested(raw, "memory", "search"), "agent_runtime_sha256": canonical_sha256(identity_config.get("agent")),
"identity_runtime_policy": identity_config.get("identity_runtime"),
"provider": _nested(identity_config, "model", "provider"),
"default_model": _nested(identity_config, "model", "default"),
"smart_routing": _nested(identity_config, "model", "smart_routing"),
"smart_routing_model": _nested(identity_config, "model", "smart_routing_model"),
"gateway_smart_model_routing": identity_config.get("smart_model_routing"),
"max_tokens": _nested(identity_config, "model", "max_tokens"),
"reasoning_effort": _nested(identity_config, "agent", "reasoning_effort"),
"memory_enabled": _nested(identity_config, "memory", "enabled"),
"memory_search": _nested(identity_config, "memory", "search"),
} }
@ -196,7 +368,13 @@ def git_state(repo: Path) -> dict[str, Any]:
} }
def source_code_manifest(profile: Path, paths: tuple[Path, ...]) -> dict[str, Any]: def source_code_manifest(
profile: Path,
paths: tuple[Path, ...],
*,
source_root: Path | None = None,
namespace: str = "source",
) -> dict[str, Any]:
"""Hash executable source while excluding generated caches and environments.""" """Hash executable source while excluding generated caches and environments."""
allowed_suffixes = { allowed_suffixes = {
@ -216,12 +394,21 @@ def source_code_manifest(profile: Path, paths: tuple[Path, ...]) -> dict[str, An
excluded_parts = {".git", ".pytest_cache", "__pycache__", "node_modules", "venv", ".venv"} excluded_parts = {".git", ".pytest_cache", "__pycache__", "node_modules", "venv", ".venv"}
files: list[dict[str, Any]] = [] files: list[dict[str, Any]] = []
missing: list[str] = [] missing: list[str] = []
symlinks: list[str] = []
source_root = (source_root or profile).resolve()
def source_label(path: Path) -> str:
return f"{namespace}:{_safe_relative(path, source_root)}"
for requested in paths: for requested in paths:
if not requested.exists() and not requested.is_symlink(): if not requested.exists() and not requested.is_symlink():
missing.append(_safe_relative(requested, profile)) missing.append(source_label(requested))
continue continue
candidates = [requested] if requested.is_file() else sorted(requested.rglob("*")) candidates = [requested] if requested.is_file() else sorted(requested.rglob("*"))
for path in candidates: for path in candidates:
if path.is_symlink():
symlinks.append(source_label(path))
continue
if not path.is_file() or excluded_parts & set(path.parts): if not path.is_file() or excluded_parts & set(path.parts):
continue continue
stat = path.stat() stat = path.stat()
@ -229,14 +416,14 @@ def source_code_manifest(profile: Path, paths: tuple[Path, ...]) -> dict[str, An
continue continue
files.append( files.append(
{ {
"path": _safe_relative(path, profile), "path": source_label(path),
"bytes": stat.st_size, "bytes": stat.st_size,
"mode": oct(stat.st_mode & 0o777), "mode": oct(stat.st_mode & 0o777),
"sha256": file_sha256(path), "sha256": file_sha256(path),
} }
) )
files.sort(key=lambda item: item["path"]) files.sort(key=lambda item: item["path"])
stable = {"files": files, "missing": sorted(missing)} stable = {"files": files, "missing": sorted(missing), "symlinks": sorted(symlinks)}
return { return {
**stable, **stable,
"file_count": len(files), "file_count": len(files),
@ -261,6 +448,72 @@ def component(
} }
def stable_manifest_payload(manifest: dict[str, Any]) -> dict[str, Any]:
"""Return the canonical, path-independent behavior payload."""
return {field: manifest.get(field) for field in STABLE_MANIFEST_FIELDS}
def static_runtime_payload(manifest: dict[str, Any]) -> dict[str, Any]:
"""Return the exact payload committed by ``static_runtime_sha256``."""
components = manifest.get("components") or {}
return {
"schema": manifest.get("schema"),
"model_runtime": manifest.get("model_runtime"),
"hermes_runtime": manifest.get("hermes_runtime"),
"teleo_infrastructure_runtime": manifest.get("teleo_infrastructure_runtime"),
"components": {name: components.get(name) for name in STATIC_RUNTIME_COMPONENTS},
"python_runtime": manifest.get("python_runtime"),
"canonical_database": manifest.get("canonical_database"),
}
def identity_runtime_payload(manifest: dict[str, Any]) -> dict[str, Any]:
"""Return the exact payload committed by ``identity_runtime_sha256``."""
model = manifest.get("model_runtime") or {}
components = manifest.get("components") or {}
teleo = manifest.get("teleo_infrastructure_runtime") or {}
identity_model_runtime = {
key: model.get(key)
for key in (
"status",
"identity_config_sha256",
"model_section_sha256",
"gateway_permissions_sha256",
"tool_permissions_sha256",
"memory_section_sha256",
"agent_runtime_sha256",
"identity_runtime_policy",
"provider",
"default_model",
"smart_routing",
"smart_routing_model",
"gateway_smart_model_routing",
"max_tokens",
"reasoning_effort",
"memory_enabled",
"memory_search",
"base_model_weights",
"actual_per_turn_model_must_be_recorded_by_the_call_receipt",
)
}
return {
"schema": manifest.get("schema"),
"model_runtime": identity_model_runtime,
"hermes_runtime": manifest.get("hermes_runtime"),
"teleo_infrastructure_runtime": {
"git_head": teleo.get("git_head"),
"git_state": teleo.get("git_state"),
"source_tree": teleo.get("identity_source_tree"),
},
"components": {name: components.get(name) for name in IDENTITY_RUNTIME_COMPONENTS},
"python_runtime": manifest.get("python_runtime"),
"canonical_database": manifest.get("canonical_database"),
}
def build_manifest( def build_manifest(
profile: Path = DEFAULT_PROFILE, profile: Path = DEFAULT_PROFILE,
hermes_root: Path = DEFAULT_HERMES_ROOT, hermes_root: Path = DEFAULT_HERMES_ROOT,
@ -270,6 +523,12 @@ def build_manifest(
hermes_root = hermes_root.resolve() hermes_root = hermes_root.resolve()
deployment_root = deployment_root.resolve() deployment_root = deployment_root.resolve()
config = safe_model_config(profile / "config.yaml") config = safe_model_config(profile / "config.yaml")
identity_runtime_sources = (
deployment_root / "scripts" / "leo_behavior_manifest.py",
deployment_root / "scripts" / "leo_identity_manifest.py",
deployment_root / "scripts" / "leo_identity_profile.py",
deployment_root / "scripts" / "run_leo_identity_reconstruction_canary.py",
)
components = { components = {
"profile_config": component( "profile_config": component(
profile, profile,
@ -294,10 +553,10 @@ def build_manifest(
), ),
"runtime_middleware": component( "runtime_middleware": component(
profile, profile,
role="Pre-LLM context injection and post-LLM validation or response replacement.", role="Profile plugins for pre-LLM context injection and post-LLM validation or response replacement.",
mutability="deployment_static", mutability="deployment_static",
replayability="fully_hashable", replayability="fully_hashable",
paths=(profile / "plugins", hermes_root / "run_agent.py"), paths=(profile / "plugins",),
), ),
"database_tools": component( "database_tools": component(
profile, profile,
@ -353,14 +612,28 @@ def build_manifest(
hermes_root / "hermes_cli", hermes_root / "hermes_cli",
hermes_root / "tools", hermes_root / "tools",
), ),
source_root=hermes_root,
namespace="hermes",
), ),
}, },
"teleo_infrastructure_runtime": { "teleo_infrastructure_runtime": {
"git_head": git_head(deployment_root), "git_head": git_head(deployment_root),
"git_state": git_state(deployment_root), "git_state": git_state(deployment_root),
"source_tree": source_code_manifest(profile, (deployment_root,)), "source_tree": source_code_manifest(
profile,
(deployment_root,),
source_root=deployment_root,
namespace="teleo",
),
"identity_source_tree": source_code_manifest(
profile,
identity_runtime_sources,
source_root=deployment_root,
namespace="teleo-identity",
),
}, },
"components": components, "components": components,
"python_runtime": python_runtime_manifest(),
"canonical_database": { "canonical_database": {
"included": False, "included": False,
"reason": "Fingerprint through a read-only Postgres manifest in the database-owning harness.", "reason": "Fingerprint through a read-only Postgres manifest in the database-owning harness.",
@ -372,7 +645,9 @@ def build_manifest(
"profile_root": str(profile), "profile_root": str(profile),
"hermes_root": str(hermes_root), "hermes_root": str(hermes_root),
"deployment_root": str(deployment_root), "deployment_root": str(deployment_root),
"behavior_sha256": canonical_sha256(stable), "static_runtime_sha256": canonical_sha256(static_runtime_payload(stable)),
"identity_runtime_sha256": canonical_sha256(identity_runtime_payload(stable)),
"behavior_sha256": canonical_sha256(stable_manifest_payload(stable)),
} }

View file

@ -0,0 +1,878 @@
#!/usr/bin/env python3
"""Build and verify Leo's pinned, reproducible identity manifest."""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
from typing import Any
if __package__ in {None, ""}:
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from scripts import leo_behavior_manifest as behavior
SCHEMA = "livingip.leoIdentityManifest.v1"
CONSTITUTION_SCHEMA = "livingip.leoConstitutionSource.v1"
DATABASE_IDENTITY_SCHEMA = "livingip.leoDatabaseIdentitySource.v1"
STRUCTURED_VIEW_SCHEMA = "livingip.leoCompiledIdentityView.v1"
DATABASE_FINGERPRINT_SCHEMA = "livingip.teleoCanonicalDatabaseFingerprint.v1"
SYNTHETIC_DATABASE_MODE = "synthetic_noncanonical_fixture"
CANONICAL_DATABASE_MODE = "canonical_database_same_transaction_export"
HEX_64 = re.compile(r"^[0-9a-f]{64}$")
HEX_40 = re.compile(r"^[0-9a-f]{40}$")
IDENTITY_TABLES = frozenset(
{
"public.personas",
"public.strategies",
"public.beliefs",
"public.shared_root",
"public.strategy_nodes",
"public.strategy_node_anchors",
"public.claims",
}
)
def expected_runtime_policy() -> dict[str, Any]:
return {
"network_send_enabled": False,
"database_write_enabled": False,
"allowed_tools": ["identity_readback"],
}
def expected_session_boundary() -> dict[str, Any]:
return {
"classification": "temporary_noncanonical",
"included_in_identity_inputs": False,
"may_be_used_as_evidence": False,
"restart_policy": "fresh_process_with_session_state_outside_identity_authority",
}
def expected_gatewayrunner_contract() -> dict[str, Any]:
return {
"profile_surfaces": ["config.yaml", "generated SOUL.md", "skills", "plugins", "bin tools"],
"required_absent_or_empty": {
"persistent_memory": behavior.canonical_sha256([]),
"pairing_store": behavior.canonical_sha256([]),
"project_context": behavior.canonical_sha256([]),
"generated_skill_prompt_cache": behavior.canonical_sha256([]),
"prior_sessions_at_first_start": behavior.canonical_sha256([]),
},
"fixed_message_context": {
"auto_skill": None,
"reply_context": None,
"media_or_file_context": None,
},
"required_t3_turn_receipt_fields": [
"runner_class",
"authorization_decision",
"effective_system_prompt_sha256",
"compiled_skills_prompt_sha256",
"tool_registry_schema_sha256",
"plugin_registry_sha256",
"selected_model",
"selected_provider",
"api_mode",
"base_url_host",
"database_retrieval_receipt",
"session_key_sha256",
"persisted_session_id_sha256",
],
}
class IdentityManifestError(ValueError):
"""An identity input is incomplete, inconsistent, or drifted."""
def _require(condition: bool, message: str) -> None:
if not condition:
raise IdentityManifestError(message)
def _is_sha256(value: Any) -> bool:
return isinstance(value, str) and bool(HEX_64.fullmatch(value))
def load_json(path: Path, label: str) -> dict[str, Any]:
try:
value = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
raise IdentityManifestError(f"cannot read {label}: {type(exc).__name__}") from exc
if not isinstance(value, dict):
raise IdentityManifestError(f"{label} must be a JSON object")
return value
def canonical_rules(value: dict[str, Any]) -> list[dict[str, str]]:
_require(value.get("schema") == CONSTITUTION_SCHEMA, "unsupported constitution schema")
_require(value.get("identity_name") == "Leo", "constitution identity_name must be Leo")
raw_rules = value.get("rules")
_require(isinstance(raw_rules, list) and bool(raw_rules), "constitution rules must be non-empty")
rules: list[dict[str, str]] = []
for raw in raw_rules:
_require(isinstance(raw, dict), "each constitutional rule must be an object")
rule_id = str(raw.get("id") or "").strip()
text = str(raw.get("text") or "").strip()
_require(bool(rule_id and text), "each constitutional rule needs id and text")
rules.append({"id": rule_id, "text": text})
_require(len({item["id"] for item in rules}) == len(rules), "constitutional rule ids must be unique")
return sorted(rules, key=lambda item: item["id"])
def canonical_database_records(value: dict[str, Any], *, fingerprint_sha256: str) -> list[dict[str, str | int]]:
_require(value.get("schema") == DATABASE_IDENTITY_SCHEMA, "unsupported database identity schema")
_require(value.get("identity_name") == "Leo", "database identity_name must be Leo")
_require(
value.get("database_fingerprint_sha256") == fingerprint_sha256,
"database identity export is not bound to the supplied database fingerprint",
)
raw_records = value.get("records")
_require(isinstance(raw_records, list) and bool(raw_records), "database identity records must be non-empty")
records: list[dict[str, str | int]] = []
for raw in raw_records:
_require(isinstance(raw, dict), "each database identity record must be an object")
rank = raw.get("rank", 0)
record: dict[str, str | int] = {
"table": str(raw.get("table") or "").strip(),
"row_id": str(raw.get("row_id") or "").strip(),
"kind": str(raw.get("kind") or "").strip(),
"rank": rank if isinstance(rank, int) and not isinstance(rank, bool) else -1,
"text": str(raw.get("text") or "").strip(),
"status": str(raw.get("status") or "").strip(),
"evidence_sha256": str(raw.get("evidence_sha256") or "").strip(),
}
_require(record["table"] in IDENTITY_TABLES, "database identity table is outside the allowlist")
_require(bool(record["row_id"] and record["kind"] and record["text"]), "database record fields are incomplete")
_require(isinstance(record["rank"], int) and record["rank"] >= 0, "database record rank is invalid")
_require(record["status"] == "active", "database identity records must be active selected rows")
_require(_is_sha256(record["evidence_sha256"]), "database record evidence_sha256 is invalid")
records.append(record)
keys = {(item["table"], item["row_id"]) for item in records}
_require(len(keys) == len(records), "database identity row bindings must be unique")
return sorted(records, key=lambda item: (str(item["table"]), int(item["rank"]), str(item["row_id"])))
def database_fingerprint_semantic(value: dict[str, Any]) -> dict[str, Any]:
"""Bind immutable capture provenance while excluding only the volatile WAL position."""
result = {key: value[key] for key in sorted(value) if key != "read_consistency"}
consistency = value["read_consistency"]
result["read_consistency"] = {
"status": consistency["status"],
"before": {key: item for key, item in consistency["before"].items() if key != "wal_lsn"},
"after": {key: item for key, item in consistency["after"].items() if key != "wal_lsn"},
}
return result
def database_identity_provenance(
value: dict[str, Any],
*,
fingerprint: dict[str, Any],
) -> dict[str, Any]:
raw = value.get("source_provenance")
_require(isinstance(raw, dict), "database identity source provenance is missing")
mode = raw.get("mode")
if mode == SYNTHETIC_DATABASE_MODE:
_require(
raw
== {
"mode": SYNTHETIC_DATABASE_MODE,
"canonical_authority_granted": False,
"same_transaction_as_fingerprint": False,
"export_receipt_sha256": None,
},
"synthetic database provenance contract is invalid",
)
_require(
fingerprint.get("environment") == "disposable_fixture",
"synthetic rows require a fixture fingerprint",
)
_require("export_receipt" not in value, "synthetic database identity must not claim an export receipt")
return {**raw, "authority": "synthetic_noncanonical_fixture"}
if mode == CANONICAL_DATABASE_MODE:
raise IdentityManifestError(
"canonical authority requires independently verified output from the database-owning same-transaction "
"exporter; caller-supplied T2 JSON cannot grant it"
)
raise IdentityManifestError("unsupported database identity provenance mode")
def validate_database_fingerprint(value: dict[str, Any]) -> None:
_require(value.get("schema") == DATABASE_FINGERPRINT_SCHEMA, "unsupported database fingerprint schema")
_require(value.get("status") == "ok", "database fingerprint status must be ok")
for field in ("fingerprint_sha256", "table_rows_sha256", "structure_sha256"):
_require(_is_sha256(value.get(field)), f"database fingerprint {field} is invalid")
_require(isinstance(value.get("table_count"), int) and value["table_count"] > 0, "table_count must be positive")
_require(isinstance(value.get("total_rows"), int) and value["total_rows"] >= 0, "total_rows is invalid")
consistency = value.get("read_consistency")
_require(isinstance(consistency, dict), "database read_consistency is missing")
before = consistency.get("before")
after = consistency.get("after")
_require(consistency.get("status") == "stable_wal_marker", "database fingerprint was not read consistently")
_require(isinstance(before, dict) and before == after and bool(before), "database read markers differ")
for field in ("database", "database_user", "system_identifier", "wal_lsn"):
_require(bool(before.get(field)), f"database read marker {field} is missing")
def validate_content_manifest(value: Any, *, label: str) -> None:
"""Recompute the structural metadata of a replayable content manifest."""
_require(isinstance(value, dict), f"{label} is invalid")
_require(
set(value) == {"files", "missing", "symlinks", "file_count", "total_bytes", "sha256"},
f"{label} fields are invalid",
)
files = value.get("files")
missing = value.get("missing")
symlinks = value.get("symlinks")
_require(isinstance(files, list) and bool(files), f"{label} is empty")
_require(missing == [], f"{label} has missing inputs")
_require(symlinks == [], f"{label} contains unsupported symlinks")
paths: list[str] = []
total_bytes = 0
for item in files:
_require(isinstance(item, dict), f"{label} contains unreadable inputs")
_require(set(item) == {"path", "bytes", "mode", "sha256"}, f"{label} contains unreadable inputs")
path = item.get("path")
size = item.get("bytes")
mode = item.get("mode")
_require(isinstance(path, str) and bool(path), f"{label} contains an invalid path")
_require(isinstance(size, int) and not isinstance(size, bool) and size >= 0, f"{label} byte size is invalid")
_require(isinstance(mode, str) and bool(re.fullmatch(r"0o[0-7]{3}", mode)), f"{label} mode is invalid")
_require(_is_sha256(item.get("sha256")), f"{label} contains unreadable inputs")
paths.append(path)
total_bytes += size
_require(paths == sorted(paths) and len(paths) == len(set(paths)), f"{label} paths are not unique and sorted")
_require(value.get("file_count") == len(files), f"{label} file count is invalid")
_require(value.get("total_bytes") == total_bytes, f"{label} total bytes is invalid")
stable = {"files": files, "missing": missing, "symlinks": symlinks}
_require(behavior.canonical_sha256(stable) == value.get("sha256"), f"{label} content hash is invalid")
def validate_behavior_manifest(value: dict[str, Any]) -> None:
_require(value.get("schema") == behavior.SCHEMA, "unsupported behavior manifest schema")
for field in ("behavior_sha256", "static_runtime_sha256", "identity_runtime_sha256"):
_require(_is_sha256(value.get(field)), f"behavior manifest {field} is invalid")
_require(
behavior.canonical_sha256(behavior.identity_runtime_payload(value)) == value["identity_runtime_sha256"],
"behavior identity runtime hash drift detected",
)
_require(
behavior.canonical_sha256(behavior.static_runtime_payload(value)) == value["static_runtime_sha256"],
"behavior static runtime hash drift detected",
)
_require(
behavior.canonical_sha256(behavior.stable_manifest_payload(value)) == value["behavior_sha256"],
"behavior manifest stable payload hash drift detected",
)
model = value.get("model_runtime")
_require(isinstance(model, dict) and model.get("status") == "observed", "model runtime was not observed")
_require(bool(model.get("provider") and model.get("default_model")), "provider and default model must be pinned")
for field in (
"semantic_config_sha256",
"identity_config_sha256",
"model_section_sha256",
"gateway_permissions_sha256",
"tool_permissions_sha256",
"memory_section_sha256",
"agent_runtime_sha256",
):
_require(_is_sha256(model.get(field)), f"model runtime {field} is invalid")
_require(
model.get("base_model_weights") == "external_provider_managed_not_locally_hashable",
"hosted model weight boundary is missing",
)
_require(
model.get("actual_per_turn_model_must_be_recorded_by_the_call_receipt") is True, "model receipt gate missing"
)
policy = model.get("identity_runtime_policy")
_require(policy == expected_runtime_policy(), "identity runtime policy must be the exact local readback policy")
for field in ("hermes_runtime", "teleo_infrastructure_runtime"):
runtime = value.get(field)
_require(isinstance(runtime, dict), f"{field} is missing")
_require(bool(HEX_40.fullmatch(str(runtime.get("git_head") or ""))), f"{field} git_head is invalid")
git_state = runtime.get("git_state")
_require(
isinstance(git_state, dict) and git_state.get("worktree_clean") is True,
f"{field} is not reconstructible from clean Git",
)
tree = runtime.get("identity_source_tree" if field == "teleo_infrastructure_runtime" else "source_tree")
validate_content_manifest(tree, label=f"{field} source tree")
components = value.get("components")
_require(isinstance(components, dict), "behavior components are missing")
for name in behavior.IDENTITY_RUNTIME_COMPONENTS:
content = (components.get(name) or {}).get("content")
validate_content_manifest(content, label=f"component {name}")
python_runtime = value.get("python_runtime")
_require(isinstance(python_runtime, dict), "Python runtime binding is missing")
_require(
bool(python_runtime.get("implementation") and python_runtime.get("python_version")),
"Python runtime is incomplete",
)
_require(_is_sha256(python_runtime.get("runtime_distributions_sha256")), "runtime package binding is invalid")
_require(
all(python_runtime.get("runtime_distributions", {}).values()), "a required runtime distribution is missing"
)
def _repo_path(path: Path, source_root: Path) -> str:
try:
return path.resolve(strict=True).relative_to(source_root.resolve(strict=True)).as_posix()
except (OSError, ValueError) as exc:
raise IdentityManifestError(f"identity source is outside the pinned source root: {path}") from exc
def source_binding(
path: Path,
*,
source_root: Path,
semantic_value: Any,
count: int,
pin_content: bool = True,
) -> dict[str, Any]:
result = {
"repo_path": _repo_path(path, source_root),
"semantic_sha256": behavior.canonical_sha256(semantic_value),
"record_count": count,
}
if pin_content:
result["content_sha256"] = behavior.file_sha256(path)
return result
def render_identity_views(
*,
identity_inputs_sha256: str,
database_fingerprint_sha256: str,
database_provenance: dict[str, Any],
rules: list[dict[str, str]],
records: list[dict[str, str | int]],
) -> dict[str, str]:
soul = [
"<!-- GENERATED FILE: edit the pinned sources, never this view. -->",
"# Leo",
"",
f"Identity inputs: `{identity_inputs_sha256}`",
"",
"## Static constitutional rules",
"",
"These rules are static constitutional inputs, not database claims.",
"",
]
soul.extend(f"- **{item['id']}**: {item['text']}" for item in rules)
database_description = (
"canonical database capture"
if database_provenance["canonical_authority_granted"]
else "synthetic noncanonical fixture"
)
soul.extend(
[
"",
"## Database-derived identity",
"",
f"Generated from {database_description} fingerprint `{database_fingerprint_sha256}`.",
"",
]
)
soul.extend(
f"- `{item['table']}/{item['row_id']}` [{item['kind']}, rank {item['rank']}]: {item['text']} "
f"(evidence `{item['evidence_sha256']}`)"
for item in records
)
soul.extend(
[
"",
"## Authority and session boundary",
"",
"- This `SOUL.md` is a generated view and is never an authority by itself.",
"- Generated database identity is authoritative only when its same-transaction export receipt grants canonical authority.",
"- Runtime/session memory is temporary, noncanonical, and cannot serve as evidence.",
"- Hosted model weights are provider-managed and must be attributed by each turn receipt.",
"",
]
)
structured = {
"schema": STRUCTURED_VIEW_SCHEMA,
"identity_name": "Leo",
"identity_inputs_sha256": identity_inputs_sha256,
"static_constitution": {"authority": "pinned_static_source", "rules": rules},
"database_identity": {
"authority": database_provenance["authority"],
"canonical_authority_granted": database_provenance["canonical_authority_granted"],
"source_mode": database_provenance["mode"],
"database_fingerprint_sha256": database_fingerprint_sha256,
"records": records,
},
"session_boundary": {
"authority": "none",
"classification": "temporary_noncanonical",
"may_be_used_as_evidence": False,
},
}
return {
"SOUL.md": "\n".join(soul),
"identity.json": json.dumps(structured, indent=2, sort_keys=True) + "\n",
}
def build_identity_manifest(
*,
behavior_manifest: dict[str, Any],
database_fingerprint_path: Path,
constitution_path: Path,
database_identity_path: Path,
source_root: Path,
source_commit: str | None = None,
) -> dict[str, Any]:
validate_behavior_manifest(behavior_manifest)
database_fingerprint = load_json(database_fingerprint_path, "database fingerprint")
validate_database_fingerprint(database_fingerprint)
constitution = load_json(constitution_path, "constitution source")
database_identity = load_json(database_identity_path, "database identity source")
rules = canonical_rules(constitution)
records = canonical_database_records(
database_identity, fingerprint_sha256=database_fingerprint["fingerprint_sha256"]
)
database_provenance = database_identity_provenance(
database_identity,
fingerprint=database_fingerprint,
)
runtime_commit = behavior_manifest["teleo_infrastructure_runtime"]["git_head"]
source_commit = source_commit or runtime_commit
_require(bool(HEX_40.fullmatch(str(source_commit))), "source commit is invalid")
_require(source_commit == runtime_commit, "source commit does not match the behavior manifest")
model = behavior_manifest["model_runtime"]
components = behavior_manifest["components"]
marker = database_fingerprint["read_consistency"]["before"]
core = {
"identity_name": "Leo",
"source_commit": source_commit,
"runtime": {
"identity_runtime_sha256": behavior_manifest["identity_runtime_sha256"],
"hermes_git_head": behavior_manifest["hermes_runtime"]["git_head"],
"hermes_source_sha256": behavior_manifest["hermes_runtime"]["source_tree"]["sha256"],
"teleo_git_head": runtime_commit,
"teleo_source_sha256": behavior_manifest["teleo_infrastructure_runtime"]["identity_source_tree"]["sha256"],
"python": behavior_manifest["python_runtime"],
},
"model": {
"provider": model["provider"],
"default_model": model["default_model"],
"smart_routing": model.get("smart_routing"),
"smart_routing_model": model.get("smart_routing_model"),
"gateway_smart_model_routing": model.get("gateway_smart_model_routing"),
"model_section_sha256": model["model_section_sha256"],
"hosted_weights": "external_provider_managed_not_locally_hashable",
"actual_model_required_in_turn_receipt": True,
},
"skills": {
"content_sha256": components["procedural_skills"]["content"]["sha256"],
"file_count": components["procedural_skills"]["content"]["file_count"],
},
"permissions": {
"identity_config_sha256": model["identity_config_sha256"],
"gateway_permissions_sha256": model["gateway_permissions_sha256"],
"tool_permissions_sha256": model["tool_permissions_sha256"],
"runtime_policy": model["identity_runtime_policy"],
"authorization_decision_required_in_runtime_receipt": True,
},
"canonical_database": {
"database": marker["database"],
"database_user": marker["database_user"],
"system_identifier": marker["system_identifier"],
"authority": database_provenance["authority"],
"canonical_authority_granted": database_provenance["canonical_authority_granted"],
**{
key: database_fingerprint[key]
for key in ("fingerprint_sha256", "table_rows_sha256", "structure_sha256", "table_count", "total_rows")
},
"source": source_binding(
database_fingerprint_path,
source_root=source_root,
semantic_value=database_fingerprint_semantic(database_fingerprint),
count=database_fingerprint["table_count"],
pin_content=False,
),
},
"identity_sources": {
"static_constitution": {
"authority": "pinned_static_source",
**source_binding(constitution_path, source_root=source_root, semantic_value=rules, count=len(rules)),
},
"database_derived_identity": {
"authority": database_provenance["authority"],
"provenance": database_provenance,
"database_fingerprint_sha256": database_fingerprint["fingerprint_sha256"],
**source_binding(
database_identity_path,
source_root=source_root,
semantic_value={"provenance": database_provenance, "records": records},
count=len(records),
),
},
},
"session_boundary": expected_session_boundary(),
"gatewayrunner_execution_contract": expected_gatewayrunner_contract(),
}
identity_inputs_sha256 = behavior.canonical_sha256(core)
views = render_identity_views(
identity_inputs_sha256=identity_inputs_sha256,
database_fingerprint_sha256=database_fingerprint["fingerprint_sha256"],
database_provenance=database_provenance,
rules=rules,
records=records,
)
stable = {
"schema": SCHEMA,
"identity_inputs": core,
"identity_inputs_sha256": identity_inputs_sha256,
"compiled_views": {
name: {
"role": "generated_view_not_authority",
"sha256": behavior.sha256_bytes(content.encode("utf-8")),
"generated_from_identity_inputs_sha256": identity_inputs_sha256,
}
for name, content in sorted(views.items())
},
}
return {**stable, "manifest_sha256": behavior.canonical_sha256(stable)}
def validate_identity_manifest(value: dict[str, Any]) -> None:
_require(value.get("schema") == SCHEMA, "unsupported identity manifest schema")
expected = value.get("manifest_sha256")
_require(_is_sha256(expected), "identity manifest sha256 is invalid")
stable = {key: item for key, item in value.items() if key != "manifest_sha256"}
_require(behavior.canonical_sha256(stable) == expected, "identity manifest hash drift detected")
core = value.get("identity_inputs")
_require(isinstance(core, dict), "identity inputs are missing")
_require(
set(core)
== {
"identity_name",
"source_commit",
"runtime",
"model",
"skills",
"permissions",
"canonical_database",
"identity_sources",
"session_boundary",
"gatewayrunner_execution_contract",
},
"identity input contract fields are invalid",
)
identity_hash = value.get("identity_inputs_sha256")
_require(_is_sha256(identity_hash), "identity input hash is invalid")
_require(behavior.canonical_sha256(core) == identity_hash, "identity input hash drift detected")
_require(core.get("identity_name") == "Leo", "identity name must be Leo")
runtime = core.get("runtime")
_require(isinstance(runtime, dict), "runtime binding is missing")
_require(
set(runtime)
== {
"identity_runtime_sha256",
"hermes_git_head",
"hermes_source_sha256",
"teleo_git_head",
"teleo_source_sha256",
"python",
},
"runtime binding fields are invalid",
)
_require(_is_sha256(runtime.get("identity_runtime_sha256")), "identity runtime binding is invalid")
for field in ("hermes_git_head", "teleo_git_head"):
_require(bool(HEX_40.fullmatch(str(runtime.get(field) or ""))), f"runtime {field} is invalid")
for field in ("hermes_source_sha256", "teleo_source_sha256"):
_require(_is_sha256(runtime.get(field)), f"runtime {field} is invalid")
_require(core.get("source_commit") == runtime["teleo_git_head"], "source commit is not bound to Teleo Git")
python_runtime = runtime.get("python")
_require(isinstance(python_runtime, dict), "Python runtime binding is missing")
_require(
bool(python_runtime.get("implementation") and python_runtime.get("python_version")),
"Python runtime binding is incomplete",
)
_require(_is_sha256(python_runtime.get("runtime_distributions_sha256")), "Python distribution binding is invalid")
model = core.get("model")
_require(isinstance(model, dict), "model binding is missing")
_require(
set(model)
== {
"provider",
"default_model",
"smart_routing",
"smart_routing_model",
"gateway_smart_model_routing",
"model_section_sha256",
"hosted_weights",
"actual_model_required_in_turn_receipt",
},
"model binding fields are invalid",
)
_require(bool(model.get("provider") and model.get("default_model")), "model provider and default must be pinned")
_require(_is_sha256(model.get("model_section_sha256")), "model section binding is invalid")
_require(
model.get("hosted_weights") == "external_provider_managed_not_locally_hashable",
"hosted model boundary is invalid",
)
_require(model.get("actual_model_required_in_turn_receipt") is True, "per-turn model receipt gate is invalid")
skills = core.get("skills")
_require(isinstance(skills, dict) and set(skills) == {"content_sha256", "file_count"}, "skills binding is invalid")
_require(_is_sha256(skills.get("content_sha256")), "skills content hash is invalid")
_require(
isinstance(skills.get("file_count"), int)
and not isinstance(skills.get("file_count"), bool)
and skills["file_count"] > 0,
"skills file count is invalid",
)
permissions = core.get("permissions")
_require(isinstance(permissions, dict), "permission binding is missing")
_require(
set(permissions)
== {
"identity_config_sha256",
"gateway_permissions_sha256",
"tool_permissions_sha256",
"runtime_policy",
"authorization_decision_required_in_runtime_receipt",
},
"permission binding fields are invalid",
)
for field in ("identity_config_sha256", "gateway_permissions_sha256", "tool_permissions_sha256"):
_require(_is_sha256(permissions.get(field)), f"permission binding {field} is invalid")
_require(
permissions.get("runtime_policy") == expected_runtime_policy(),
"identity runtime policy must be the exact local readback policy",
)
_require(
permissions.get("authorization_decision_required_in_runtime_receipt") is True,
"runtime authorization receipt gate is invalid",
)
database = core.get("canonical_database")
_require(isinstance(database, dict), "canonical database binding is missing")
for field in ("fingerprint_sha256", "table_rows_sha256", "structure_sha256"):
_require(_is_sha256(database.get(field)), f"canonical database {field} is invalid")
_require(
bool(database.get("database") and database.get("database_user") and database.get("system_identifier")),
"canonical database identity is incomplete",
)
allowed_authorities = {"synthetic_noncanonical_fixture": False}
_require(database.get("authority") in allowed_authorities, "database authority is invalid")
_require(
database.get("canonical_authority_granted") is allowed_authorities[database["authority"]],
"database canonical authority grant is invalid",
)
_require(
isinstance(database.get("table_count"), int)
and not isinstance(database.get("table_count"), bool)
and database["table_count"] > 0,
"canonical database table_count is invalid",
)
_require(
isinstance(database.get("total_rows"), int)
and not isinstance(database.get("total_rows"), bool)
and database["total_rows"] >= 0,
"canonical database total_rows is invalid",
)
def validate_source_binding(binding: Any, *, label: str, content_required: bool) -> None:
_require(isinstance(binding, dict), f"{label} source binding is missing")
repo_path = binding.get("repo_path")
_require(
isinstance(repo_path, str)
and bool(repo_path)
and not Path(repo_path).is_absolute()
and ".." not in Path(repo_path).parts,
f"{label} source path is invalid",
)
_require(_is_sha256(binding.get("semantic_sha256")), f"{label} semantic binding is invalid")
_require(
isinstance(binding.get("record_count"), int)
and not isinstance(binding.get("record_count"), bool)
and binding["record_count"] > 0,
f"{label} record count is invalid",
)
if content_required:
_require(_is_sha256(binding.get("content_sha256")), f"{label} content binding is invalid")
else:
_require("content_sha256" not in binding, f"{label} content binding must exclude volatile capture markers")
validate_source_binding(database.get("source"), label="database fingerprint", content_required=False)
sources = core.get("identity_sources")
_require(
isinstance(sources, dict) and set(sources) == {"static_constitution", "database_derived_identity"},
"identity source bindings are invalid",
)
constitution = sources["static_constitution"]
derived = sources["database_derived_identity"]
_require(isinstance(constitution, dict), "constitution source binding is invalid")
_require(isinstance(derived, dict), "database identity source binding is invalid")
_require(constitution.get("authority") == "pinned_static_source", "constitution authority is invalid")
_require(derived.get("authority") == database["authority"], "database identity authority is invalid")
provenance = derived.get("provenance")
_require(isinstance(provenance, dict), "database identity provenance is missing")
_require(provenance.get("authority") == database["authority"], "database identity provenance authority is invalid")
_require(
provenance.get("canonical_authority_granted") is database["canonical_authority_granted"],
"database identity provenance grant is invalid",
)
_require(provenance.get("mode") == SYNTHETIC_DATABASE_MODE, "synthetic database provenance mode is invalid")
_require(
provenance.get("same_transaction_as_fingerprint") is False,
"synthetic fixture transaction claim is invalid",
)
_require(provenance.get("export_receipt_sha256") is None, "synthetic fixture must not claim an export receipt")
_require(
derived.get("database_fingerprint_sha256") == database["fingerprint_sha256"],
"database identity source is misbound",
)
validate_source_binding(constitution, label="constitution", content_required=True)
validate_source_binding(derived, label="database identity", content_required=True)
_require(core.get("session_boundary") == expected_session_boundary(), "session authority boundary is invalid")
_require(
core.get("gatewayrunner_execution_contract") == expected_gatewayrunner_contract(),
"GatewayRunner execution contract is invalid",
)
views = value.get("compiled_views")
_require(isinstance(views, dict) and set(views) == {"SOUL.md", "identity.json"}, "compiled views are incomplete")
for name, view in views.items():
_require(isinstance(view, dict) and _is_sha256(view.get("sha256")), f"compiled view {name} is invalid")
_require(
set(view) == {"role", "sha256", "generated_from_identity_inputs_sha256"},
f"compiled view {name} fields are invalid",
)
_require(view.get("role") == "generated_view_not_authority", f"compiled view {name} authority is invalid")
_require(
view.get("generated_from_identity_inputs_sha256") == identity_hash, f"compiled view {name} is misbound"
)
def verify_bound_sources(value: dict[str, Any], source_root: Path) -> dict[str, str]:
validate_identity_manifest(value)
core = value["identity_inputs"]
bindings = {
"database fingerprint": core["canonical_database"]["source"],
"constitution source": core["identity_sources"]["static_constitution"],
"database identity source": core["identity_sources"]["database_derived_identity"],
}
paths = {label: source_root / binding["repo_path"] for label, binding in bindings.items()}
for label, binding in bindings.items():
path = paths[label]
_require(path.is_file(), f"bound {label} is missing")
if binding.get("content_sha256"):
_require(behavior.file_sha256(path) == binding["content_sha256"], f"bound {label} content drift detected")
fingerprint = load_json(paths["database fingerprint"], "database fingerprint")
validate_database_fingerprint(fingerprint)
_require(
behavior.canonical_sha256(database_fingerprint_semantic(fingerprint))
== bindings["database fingerprint"]["semantic_sha256"],
"database fingerprint semantic drift detected",
)
marker = fingerprint["read_consistency"]["before"]
for field in ("database", "database_user", "system_identifier"):
_require(marker[field] == core["canonical_database"][field], f"canonical database {field} drift detected")
rules = canonical_rules(load_json(paths["constitution source"], "constitution source"))
database_identity = load_json(paths["database identity source"], "database identity source")
records = canonical_database_records(
database_identity,
fingerprint_sha256=fingerprint["fingerprint_sha256"],
)
database_provenance = database_identity_provenance(
database_identity,
fingerprint=fingerprint,
)
_require(
behavior.canonical_sha256(rules) == bindings["constitution source"]["semantic_sha256"],
"constitution semantic drift detected",
)
_require(
behavior.canonical_sha256({"provenance": database_provenance, "records": records})
== bindings["database identity source"]["semantic_sha256"],
"database identity semantic drift detected",
)
_require(
database_provenance == core["identity_sources"]["database_derived_identity"]["provenance"],
"database identity provenance drift detected",
)
_require(
fingerprint["fingerprint_sha256"] == core["canonical_database"]["fingerprint_sha256"],
"canonical database fingerprint drift detected",
)
views = render_identity_views(
identity_inputs_sha256=value["identity_inputs_sha256"],
database_fingerprint_sha256=fingerprint["fingerprint_sha256"],
database_provenance=database_provenance,
rules=rules,
records=records,
)
for name, content in views.items():
_require(
behavior.sha256_bytes(content.encode("utf-8")) == value["compiled_views"][name]["sha256"],
f"compiled view contract drift detected for {name}",
)
return views
def write_json(path: Path, value: dict[str, Any]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(value, indent=2, sort_keys=True) + "\n", encoding="utf-8")
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
subparsers = parser.add_subparsers(dest="command", required=True)
generate = subparsers.add_parser("generate")
generate.add_argument("--behavior-manifest", type=Path, required=True)
generate.add_argument("--database-fingerprint", type=Path, required=True)
generate.add_argument("--constitution", type=Path, required=True)
generate.add_argument("--database-identity", type=Path, required=True)
generate.add_argument("--source-root", type=Path, required=True)
generate.add_argument("--source-commit")
generate.add_argument("--output", type=Path, required=True)
verify = subparsers.add_parser("verify")
verify.add_argument("--manifest", type=Path, required=True)
verify.add_argument("--source-root", type=Path)
args = parser.parse_args()
try:
if args.command == "generate":
manifest = build_identity_manifest(
behavior_manifest=load_json(args.behavior_manifest, "behavior manifest"),
database_fingerprint_path=args.database_fingerprint,
constitution_path=args.constitution,
database_identity_path=args.database_identity,
source_root=args.source_root,
source_commit=args.source_commit,
)
write_json(args.output, manifest)
else:
manifest = load_json(args.manifest, "identity manifest")
validate_identity_manifest(manifest)
if args.source_root:
verify_bound_sources(manifest, args.source_root)
print(json.dumps({"status": "ok", "manifest_sha256": manifest["manifest_sha256"]}))
return 0
except IdentityManifestError as exc:
print(json.dumps({"status": "error", "error": "identity_manifest_invalid", "message": str(exc)}))
return 2
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,495 @@
#!/usr/bin/env python3
"""Compile, verify, and query a disposable Leo identity profile."""
from __future__ import annotations
import argparse
import json
import os
import shutil
import sys
import uuid
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
import yaml
if __package__ in {None, ""}:
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from scripts import leo_behavior_manifest as behavior
from scripts import leo_identity_manifest as identity
LOCK_SCHEMA = "livingip.leoIdentityProfileLock.v1"
COMPILE_RECEIPT_SCHEMA = "livingip.leoIdentityCompileReceipt.v1"
QUERY_RECEIPT_SCHEMA = "livingip.leoIdentityQueryReceipt.v1"
SESSION_RECORD_SCHEMA = "livingip.leoTemporarySessionRecord.v1"
FIXED_QUERY = "What defines Leo's identity, and what is temporary?"
STATIC_PROFILE_ENTRIES = ("config.yaml", "skills", "plugins", "bin")
COMPILED_PROFILE_ENTRIES = frozenset(
{
"config.yaml",
"skills",
"plugins",
"bin",
"SOUL.md",
"identity.json",
"identity-manifest.json",
"identity-lock.json",
"compile-receipt.json",
"sessions",
"state",
}
)
OMITTED_NONAUTHORITATIVE_ENTRIES = (
"memories",
"MEMORY.md",
"USER.md",
"platforms/pairing",
".skills_prompt_snapshot.json",
".hermes.md",
"HERMES.md",
"AGENTS.md",
"CLAUDE.md",
".cursorrules",
)
class IdentityProfileError(identity.IdentityManifestError):
"""A compiled profile cannot be trusted or started."""
def _require(condition: bool, message: str) -> None:
if not condition:
raise IdentityProfileError(message)
def _copy_static_profile(template: Path, target: Path) -> list[str]:
_require(template.is_dir(), "profile template is missing")
_require(not target.exists(), "compiled profile target already exists")
target.mkdir(parents=True, mode=0o700)
copied: list[str] = []
for name in STATIC_PROFILE_ENTRIES:
source = template / name
if not source.exists():
continue
destination = target / name
_require(not source.is_symlink(), f"unsafe symlinked static profile entry: {name}")
if source.is_dir():
_require(
not any(path.is_symlink() for path in source.rglob("*")),
f"unsafe symlink inside static profile entry: {name}",
)
shutil.copytree(source, destination, symlinks=False)
elif source.is_file() and not source.is_symlink():
if name == "config.yaml":
try:
raw_config = yaml.safe_load(source.read_text(encoding="utf-8")) or {}
except (OSError, TypeError, yaml.YAMLError) as exc:
raise IdentityProfileError(f"cannot sanitize profile config: {type(exc).__name__}") from exc
_require(isinstance(raw_config, dict), "profile config must be a mapping")
destination.write_text(
yaml.safe_dump(behavior.identity_config_projection(raw_config), sort_keys=False),
encoding="utf-8",
)
destination.chmod(0o600)
else:
shutil.copy2(source, destination)
else:
raise IdentityProfileError(f"unsafe static profile entry: {name}")
copied.append(name)
_require("config.yaml" in copied, "profile template config.yaml is missing")
return copied
def _behavior(profile: Path, hermes_root: Path, deployment_root: Path) -> dict[str, Any]:
return behavior.build_manifest(profile, hermes_root, deployment_root)
def _verify_runtime_binding(
manifest: dict[str, Any],
*,
profile: Path,
hermes_root: Path,
deployment_root: Path,
) -> dict[str, Any]:
observed = _behavior(profile, hermes_root, deployment_root)
identity.validate_behavior_manifest(observed)
expected = manifest["identity_inputs"]["runtime"]
_require(
observed["identity_runtime_sha256"] == expected["identity_runtime_sha256"], "identity runtime drift detected"
)
_require(observed["hermes_runtime"]["git_head"] == expected["hermes_git_head"], "Hermes Git drift detected")
_require(
observed["hermes_runtime"]["source_tree"]["sha256"] == expected["hermes_source_sha256"],
"Hermes source drift detected",
)
_require(
observed["teleo_infrastructure_runtime"]["git_head"] == expected["teleo_git_head"],
"Teleo Git drift detected",
)
_require(
observed["teleo_infrastructure_runtime"]["identity_source_tree"]["sha256"] == expected["teleo_source_sha256"],
"Teleo identity source drift detected",
)
_require(observed["python_runtime"] == expected["python"], "Python runtime drift detected")
_require(
manifest["identity_inputs"]["source_commit"] == observed["teleo_infrastructure_runtime"]["git_head"],
"source commit drift detected",
)
expected_model = manifest["identity_inputs"]["model"]
observed_model = observed["model_runtime"]
model_bindings = {
"provider": observed_model.get("provider"),
"default_model": observed_model.get("default_model"),
"smart_routing": observed_model.get("smart_routing"),
"smart_routing_model": observed_model.get("smart_routing_model"),
"gateway_smart_model_routing": observed_model.get("gateway_smart_model_routing"),
"model_section_sha256": observed_model.get("model_section_sha256"),
"hosted_weights": observed_model.get("base_model_weights"),
"actual_model_required_in_turn_receipt": observed_model.get(
"actual_per_turn_model_must_be_recorded_by_the_call_receipt"
),
}
for field, observed_value in model_bindings.items():
_require(expected_model.get(field) == observed_value, f"model runtime binding drift detected: {field}")
expected_permissions = manifest["identity_inputs"]["permissions"]
permission_bindings = {
"identity_config_sha256": observed_model.get("identity_config_sha256"),
"gateway_permissions_sha256": observed_model.get("gateway_permissions_sha256"),
"tool_permissions_sha256": observed_model.get("tool_permissions_sha256"),
"runtime_policy": observed_model.get("identity_runtime_policy"),
"authorization_decision_required_in_runtime_receipt": True,
}
for field, observed_value in permission_bindings.items():
_require(
expected_permissions.get(field) == observed_value, f"permission runtime binding drift detected: {field}"
)
observed_skills = observed["components"]["procedural_skills"]["content"]
expected_skills = manifest["identity_inputs"]["skills"]
_require(expected_skills["content_sha256"] == observed_skills["sha256"], "skills runtime binding drift detected")
_require(expected_skills["file_count"] == observed_skills["file_count"], "skills file count drift detected")
return observed
def _view_file_sha256(profile: Path, name: str) -> str:
path = profile / name
_require(path.is_file() and not path.is_symlink(), f"compiled view is missing or unsafe: {name}")
return behavior.file_sha256(path)
def _verify_nonauthoritative_surfaces(
profile: Path,
*,
require_empty_sessions: bool,
require_compile_receipt: bool,
) -> dict[str, Any]:
omitted = {
name: not (profile / name).exists() and not (profile / name).is_symlink()
for name in OMITTED_NONAUTHORITATIVE_ENTRIES
}
_require(all(omitted.values()), "profile contains a forbidden nonauthoritative input surface")
expected_entries = set(COMPILED_PROFILE_ENTRIES)
if not require_compile_receipt:
expected_entries.remove("compile-receipt.json")
profile_entries = list(profile.iterdir())
actual_entries = {path.name for path in profile_entries}
_require(actual_entries == expected_entries, "compiled profile entry set is not exact")
_require(not any(path.is_symlink() for path in profile_entries), "compiled profile entries must not be symlinks")
if require_compile_receipt:
compile_receipt = identity.load_json(profile / "compile-receipt.json", "identity compile receipt")
_require(compile_receipt.get("schema") == COMPILE_RECEIPT_SCHEMA, "identity compile receipt schema is invalid")
_require(compile_receipt.get("status") == "pass", "identity compile receipt status is invalid")
state = profile / "state"
sessions = profile / "sessions"
for path, label in ((state, "state"), (sessions, "sessions")):
_require(path.is_dir() and not path.is_symlink(), f"profile {label} directory is missing or unsafe")
_require(not any(state.iterdir()), "profile state directory must remain empty")
session_files = list(sessions.iterdir())
if require_empty_sessions:
_require(not session_files, "profile sessions must start empty")
for path in session_files:
_require(path.is_file() and not path.is_symlink() and path.suffix == ".json", "unsafe session entry detected")
record = identity.load_json(path, "temporary session record")
_require(
set(record)
== {
"schema",
"authority",
"classification",
"query_sha256",
"answer_sha256",
"may_be_used_as_evidence",
},
"temporary session record fields are invalid",
)
_require(record.get("schema") == SESSION_RECORD_SCHEMA, "temporary session record schema is invalid")
_require(record.get("authority") == "none", "temporary session authority is invalid")
_require(record.get("classification") == "temporary_noncanonical", "temporary session class is invalid")
_require(record.get("may_be_used_as_evidence") is False, "temporary session cannot be evidence")
_require(identity._is_sha256(record.get("query_sha256")), "temporary session query hash is invalid")
_require(identity._is_sha256(record.get("answer_sha256")), "temporary session answer hash is invalid")
return {
"nonauthoritative_inputs_omitted": omitted,
"session_file_count": len(session_files),
"state_empty": True,
}
def compile_profile(
manifest: dict[str, Any],
*,
source_root: Path,
profile_template: Path,
profile: Path,
hermes_root: Path,
deployment_root: Path,
) -> dict[str, Any]:
views = identity.verify_bound_sources(manifest, source_root)
template_behavior = _behavior(profile_template, hermes_root, deployment_root)
identity.validate_behavior_manifest(template_behavior)
_require(
template_behavior["identity_runtime_sha256"]
== manifest["identity_inputs"]["runtime"]["identity_runtime_sha256"],
"profile template does not match the pinned identity runtime",
)
copied = _copy_static_profile(profile_template, profile)
try:
for name, content in views.items():
path = profile / name
path.write_text(content, encoding="utf-8")
path.chmod(0o600)
identity.write_json(profile / "identity-manifest.json", manifest)
(profile / "identity-manifest.json").chmod(0o600)
for directory in (profile / "sessions", profile / "state"):
directory.mkdir(mode=0o700)
lock = {
"schema": LOCK_SCHEMA,
"manifest_sha256": manifest["manifest_sha256"],
"identity_inputs_sha256": manifest["identity_inputs_sha256"],
"compiled_views": {name: {"sha256": _view_file_sha256(profile, name)} for name in sorted(views)},
"session_boundary": manifest["identity_inputs"]["session_boundary"],
}
identity.write_json(profile / "identity-lock.json", lock)
(profile / "identity-lock.json").chmod(0o600)
observed = _verify_runtime_binding(
manifest,
profile=profile,
hermes_root=hermes_root,
deployment_root=deployment_root,
)
for name, expected in manifest["compiled_views"].items():
_require(_view_file_sha256(profile, name) == expected["sha256"], f"compiled {name} hash mismatch")
soul_files = observed["components"]["runtime_identity"]["content"]["files"]
soul = next((item for item in soul_files if item.get("path") == "SOUL.md"), None)
_require(
isinstance(soul, dict) and soul.get("sha256") == manifest["compiled_views"]["SOUL.md"]["sha256"],
"SOUL runtime binding failed",
)
surface_readback = _verify_nonauthoritative_surfaces(
profile,
require_empty_sessions=True,
require_compile_receipt=False,
)
receipt = {
"schema": COMPILE_RECEIPT_SCHEMA,
"status": "pass",
"manifest_sha256": manifest["manifest_sha256"],
"identity_inputs_sha256": manifest["identity_inputs_sha256"],
"profile_static_entries": copied,
"compiled_view_sha256": {
name: manifest["compiled_views"][name]["sha256"] for name in sorted(manifest["compiled_views"])
},
"runtime_identity_sha256": observed["identity_runtime_sha256"],
"session_directories_started_empty": all(
not any((profile / name).iterdir()) for name in ("sessions", "state")
),
"nonauthoritative_inputs_omitted": surface_readback["nonauthoritative_inputs_omitted"],
"generated_views_are_authority": False,
}
identity.write_json(profile / "compile-receipt.json", receipt)
return receipt
except BaseException:
shutil.rmtree(profile, ignore_errors=True)
raise
def verify_profile(
profile: Path,
*,
source_root: Path,
hermes_root: Path,
deployment_root: Path,
) -> tuple[dict[str, Any], dict[str, str], dict[str, Any]]:
manifest = identity.load_json(profile / "identity-manifest.json", "compiled identity manifest")
views = identity.verify_bound_sources(manifest, source_root)
lock = identity.load_json(profile / "identity-lock.json", "identity profile lock")
_verify_nonauthoritative_surfaces(
profile,
require_empty_sessions=False,
require_compile_receipt=True,
)
_require(lock.get("schema") == LOCK_SCHEMA, "identity profile lock schema is invalid")
_require(
lock.get("manifest_sha256") == manifest["manifest_sha256"], "identity profile lock manifest drift detected"
)
_require(
lock.get("identity_inputs_sha256") == manifest["identity_inputs_sha256"],
"identity profile lock input drift detected",
)
compile_receipt = identity.load_json(profile / "compile-receipt.json", "identity compile receipt")
_require(
compile_receipt.get("manifest_sha256") == manifest["manifest_sha256"],
"identity compile receipt manifest drift detected",
)
_require(
compile_receipt.get("identity_inputs_sha256") == manifest["identity_inputs_sha256"],
"identity compile receipt input drift detected",
)
for name, expected_content in views.items():
expected_hash = behavior.sha256_bytes(expected_content.encode("utf-8"))
_require(expected_hash == manifest["compiled_views"][name]["sha256"], f"manifest view drift detected: {name}")
_require(_view_file_sha256(profile, name) == expected_hash, f"compiled view drift detected: {name}")
_require(
(lock.get("compiled_views") or {}).get(name, {}).get("sha256") == expected_hash,
f"profile lock view drift detected: {name}",
)
observed = _verify_runtime_binding(
manifest,
profile=profile,
hermes_root=hermes_root,
deployment_root=deployment_root,
)
return manifest, views, observed
def query_profile(
profile: Path,
*,
query: str,
source_root: Path,
hermes_root: Path,
deployment_root: Path,
) -> dict[str, Any]:
_require(query == FIXED_QUERY, "only the pinned identity readback query is allowed")
manifest, _views, observed = verify_profile(
profile,
source_root=source_root,
hermes_root=hermes_root,
deployment_root=deployment_root,
)
structured = identity.load_json(profile / "identity.json", "compiled structured identity view")
rule_count = len(structured["static_constitution"]["rules"])
record_count = len(structured["database_identity"]["records"])
fingerprint = structured["database_identity"]["database_fingerprint_sha256"]
canonical_authority = structured["database_identity"]["canonical_authority_granted"]
database_description = "canonical database" if canonical_authority else "synthetic noncanonical fixture"
answer = (
f"Leo is defined by {rule_count} pinned static constitutional rules and {record_count} active "
f"database-derived identity rows from a {database_description} at fingerprint {fingerprint}. "
"SOUL.md is a generated view; "
"runtime/session memory is temporary, noncanonical, and cannot be evidence."
)
query_sha256 = behavior.sha256_bytes(query.encode("utf-8"))
answer_sha256 = behavior.sha256_bytes(answer.encode("utf-8"))
instance_id = uuid.uuid4().hex
session_record = {
"schema": SESSION_RECORD_SCHEMA,
"authority": "none",
"classification": "temporary_noncanonical",
"query_sha256": query_sha256,
"answer_sha256": answer_sha256,
"may_be_used_as_evidence": False,
}
session_path = profile / "sessions" / f"{instance_id}.json"
identity.write_json(session_path, session_record)
receipt = {
"schema": QUERY_RECEIPT_SCHEMA,
"status": "pass",
"started_at_utc": datetime.now(UTC).isoformat(),
"process_id": os.getpid(),
"runtime_instance_id": instance_id,
"query": query,
"query_sha256": query_sha256,
"answer": answer,
"answer_sha256": answer_sha256,
"manifest_sha256": manifest["manifest_sha256"],
"identity_inputs_sha256": manifest["identity_inputs_sha256"],
"output_provenance": {
"static_constitution_sha256": manifest["identity_inputs"]["identity_sources"]["static_constitution"][
"semantic_sha256"
],
"database_identity_sha256": manifest["identity_inputs"]["identity_sources"]["database_derived_identity"][
"semantic_sha256"
],
"database_fingerprint_sha256": fingerprint,
"database_authority": structured["database_identity"]["authority"],
"database_canonical_authority_granted": canonical_authority,
"compiled_identity_sha256": manifest["compiled_views"]["identity.json"]["sha256"],
"compiled_soul_sha256": manifest["compiled_views"]["SOUL.md"]["sha256"],
"runtime_identity_sha256": observed["identity_runtime_sha256"],
"actual_model_call_performed": False,
},
"authorization": {
"declared_runtime_policy": manifest["identity_inputs"]["permissions"]["runtime_policy"],
"authorization_decision_observed": False,
"claim": "local_policy_binding_not_an_authorizer_readback",
},
"session": {
"record_sha256": behavior.file_sha256(session_path),
"classification": "temporary_noncanonical",
"included_in_output_provenance": False,
"may_be_used_as_evidence": False,
},
}
return receipt
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
subparsers = parser.add_subparsers(dest="command", required=True)
compile_command = subparsers.add_parser("compile")
compile_command.add_argument("--manifest", type=Path, required=True)
compile_command.add_argument("--source-root", type=Path, required=True)
compile_command.add_argument("--profile-template", type=Path, required=True)
compile_command.add_argument("--profile", type=Path, required=True)
compile_command.add_argument("--hermes-root", type=Path, required=True)
compile_command.add_argument("--deployment-root", type=Path, required=True)
query_command = subparsers.add_parser("query")
query_command.add_argument("--profile", type=Path, required=True)
query_command.add_argument("--query", default=FIXED_QUERY)
query_command.add_argument("--source-root", type=Path, required=True)
query_command.add_argument("--hermes-root", type=Path, required=True)
query_command.add_argument("--deployment-root", type=Path, required=True)
args = parser.parse_args()
try:
if args.command == "compile":
result = compile_profile(
identity.load_json(args.manifest, "identity manifest"),
source_root=args.source_root,
profile_template=args.profile_template,
profile=args.profile,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
else:
result = query_profile(
args.profile,
query=args.query,
source_root=args.source_root,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
print(json.dumps(result, sort_keys=True))
return 0
except identity.IdentityManifestError as exc:
print(json.dumps({"status": "error", "error": "identity_drift", "message": str(exc)}))
return 3
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -34,7 +34,7 @@ DEFAULT_MODEL = "anthropic/claude-sonnet-4.5"
EXTRACTOR_VERSION = "2" EXTRACTOR_VERSION = "2"
DEFAULT_OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions" DEFAULT_OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions"
DEFAULT_KEY_FILE = Path("/opt/teleo-eval/secrets/openrouter-key") DEFAULT_KEY_FILE = Path("/opt/teleo-eval/secrets/openrouter-key")
TEXT_SUFFIXES = {".csv", ".htm", ".html", ".json", ".md", ".rst", ".txt", ".xml"} TEXT_SUFFIXES = {".csv", ".htm", ".html", ".json", ".jsonl", ".md", ".rst", ".txt", ".xml"}
MAX_SOURCE_CHARS = 120_000 MAX_SOURCE_CHARS = 120_000
MAX_CANDIDATES = 20 MAX_CANDIDATES = 20
MAX_CLAIMS = 3 MAX_CLAIMS = 3
@ -124,20 +124,37 @@ def _load_context(path: Path) -> dict[str, Any]:
return {"database_search_query": query.strip(), "candidate_claims": normalized} return {"database_search_query": query.strip(), "candidate_claims": normalized}
def build_source_fragments(text: str) -> dict[str, str]: def build_source_fragment_index(text: str) -> tuple[dict[str, str], dict[str, dict[str, Any]]]:
"""Label non-empty source lines so the model selects text instead of copying it.""" """Return selectable lines plus exact line/character provenance."""
fragments: dict[str, str] = {} fragments: dict[str, str] = {}
for line in text.splitlines(): locations: dict[str, dict[str, Any]] = {}
if line.strip(): offset = 0
fragments[f"S{len(fragments) + 1:05d}"] = line for line_number, raw_line in enumerate(text.splitlines(keepends=True), start=1):
line = raw_line.rstrip("\r\n")
quote = line.strip()
if quote:
reference = f"S{len(fragments) + 1:05d}"
start = offset + line.find(quote)
fragments[reference] = quote
locations[reference] = {
"reference": reference,
"line": line_number,
"char_start": start,
"char_end": start + len(quote),
"quote_sha256": sha256_bytes(quote.encode("utf-8")),
}
offset += len(raw_line)
if not fragments: if not fragments:
raise PreparationError("extracted text has no selectable source lines") raise PreparationError("extracted text has no selectable source lines")
return fragments return fragments, locations
def build_prompt( def build_source_fragments(text: str) -> dict[str, str]:
fragments: dict[str, str], context: dict[str, Any], repair_error: str | None = None """Label non-empty source lines so the model selects text instead of copying it."""
) -> str: return build_source_fragment_index(text)[0]
def build_prompt(fragments: dict[str, str], context: dict[str, Any], repair_error: str | None = None) -> str:
candidates = json.dumps(context["candidate_claims"], indent=2, ensure_ascii=True) candidates = json.dumps(context["candidate_claims"], indent=2, ensure_ascii=True)
source = "\n".join(f"[{reference}] {line}" for reference, line in fragments.items()) source = "\n".join(f"[{reference}] {line}" for reference, line in fragments.items())
repair = "" repair = ""
@ -273,9 +290,7 @@ def parse_model_output(content: str) -> dict[str, Any]:
if not isinstance(claim, dict): if not isinstance(claim, dict):
raise PreparationError(f"model extraction claims[{index}] must be an object") raise PreparationError(f"model extraction claims[{index}] must be an object")
if set(claim) != MODEL_CLAIM_KEYS: if set(claim) != MODEL_CLAIM_KEYS:
raise PreparationError( raise PreparationError(f"model extraction claims[{index}] keys must equal {sorted(MODEL_CLAIM_KEYS)}")
f"model extraction claims[{index}] keys must equal {sorted(MODEL_CLAIM_KEYS)}"
)
confidence = claim.get("confidence") confidence = claim.get("confidence")
if confidence is not None and ( if confidence is not None and (
isinstance(confidence, bool) or not isinstance(confidence, (int, float)) or not 0 <= confidence <= 0.75 isinstance(confidence, bool) or not isinstance(confidence, (int, float)) or not 0 <= confidence <= 0.75
@ -304,27 +319,47 @@ def _resolve_reference(reference: Any, fragments: dict[str, str], label: str) ->
return fragments[reference] return fragments[reference]
def resolve_model_output(selection: dict[str, Any], fragments: dict[str, str]) -> dict[str, Any]: def resolve_model_output(
selection: dict[str, Any],
fragments: dict[str, str],
fragment_locations: dict[str, dict[str, Any]] | None = None,
) -> dict[str, Any]:
def selected(kind: str, reference: str, **identity: Any) -> dict[str, Any]:
result = {"kind": kind, "reference": reference, **identity}
if fragment_locations is not None:
result.update(fragment_locations[reference])
return result
claims: list[dict[str, Any]] = [] claims: list[dict[str, Any]] = []
selected_references: list[dict[str, str]] = [] selected_references: list[dict[str, Any]] = []
for claim_index, claim in enumerate(selection["claims"]): for claim_index, claim in enumerate(selection["claims"]):
quote_ref = claim["quote_ref"] quote_ref = claim["quote_ref"]
quote = _resolve_reference(quote_ref, fragments, f"claims[{claim_index}].quote_ref") quote = _resolve_reference(quote_ref, fragments, f"claims[{claim_index}].quote_ref")
selected_references.append({"kind": "claim", "reference": quote_ref}) selected_references.append(selected("claim", quote_ref, claim_key=claim["claim_key"], quote=quote))
evidence: list[dict[str, str]] = [] evidence: list[dict[str, str]] = []
for evidence_index, row in enumerate(claim["evidence"]): for evidence_index, row in enumerate(claim["evidence"]):
evidence_ref = row["quote_ref"] evidence_ref = row["quote_ref"]
evidence.append( evidence_quote = _resolve_reference(
{
"quote": _resolve_reference(
evidence_ref, evidence_ref,
fragments, fragments,
f"claims[{claim_index}].evidence[{evidence_index}].quote_ref", f"claims[{claim_index}].evidence[{evidence_index}].quote_ref",
), )
evidence.append(
{
"quote": evidence_quote,
"role": row["role"], "role": row["role"],
} }
) )
selected_references.append({"kind": "evidence", "reference": evidence_ref}) selected_references.append(
selected(
"evidence",
evidence_ref,
claim_key=claim["claim_key"],
evidence_index=evidence_index,
evidence_role=row["role"],
quote=evidence_quote,
)
)
claims.append( claims.append(
{ {
"claim_key": claim["claim_key"], "claim_key": claim["claim_key"],
@ -351,7 +386,14 @@ def resolve_model_output(selection: dict[str, Any], fragments: dict[str, str]) -
"reason": duplicate["reason"], "reason": duplicate["reason"],
} }
) )
selected_references.append({"kind": "duplicate", "reference": source_quote_ref}) selected_references.append(
selected(
"duplicate",
source_quote_ref,
claim_id=duplicate["claim_id"],
quote=duplicates[-1]["source_quote"],
)
)
return { return {
"schema": RESOLVED_OUTPUT_SCHEMA, "schema": RESOLVED_OUTPUT_SCHEMA,
@ -362,6 +404,37 @@ def resolve_model_output(selection: dict[str, Any], fragments: dict[str, str]) -
} }
def validate_bundle_source_locations(bundle: dict[str, Any], selected_references: list[dict[str, Any]]) -> None:
"""Ensure compiler quote offsets match the exact selected fragment occurrence."""
available = list(bundle.get("quote_bindings") or [])
for selected in selected_references:
if selected.get("kind") not in {"claim", "evidence"}:
continue
match_index = next(
(
index
for index, binding in enumerate(available)
if binding.get("kind") == selected.get("kind")
and binding.get("claim_key") == selected.get("claim_key")
and binding.get("quote") == selected.get("quote")
and (
selected.get("kind") != "evidence" or binding.get("evidence_role") == selected.get("evidence_role")
)
),
None,
)
if match_index is None:
raise PreparationError("compiler dropped a selected claim/evidence source binding")
binding = available.pop(match_index)
if binding.get("first_start") != selected.get("char_start") or binding.get("first_end") != selected.get(
"char_end"
):
raise PreparationError(
f"selected {selected['reference']} is an ambiguous repeated quote; "
"the current compiler cannot preserve that exact occurrence"
)
def build_manifest( def build_manifest(
*, *,
args: argparse.Namespace, args: argparse.Namespace,
@ -427,7 +500,7 @@ def prepare(args: argparse.Namespace) -> dict[str, Any]:
artifact_bytes = _read_nonempty(args.artifact, "artifact") artifact_bytes = _read_nonempty(args.artifact, "artifact")
text_bytes = extract_utf8_text(args.artifact, args.text) text_bytes = extract_utf8_text(args.artifact, args.text)
text = text_bytes.decode("utf-8", errors="strict") text = text_bytes.decode("utf-8", errors="strict")
fragments = build_source_fragments(text) fragments, fragment_locations = build_source_fragment_index(text)
context = _load_context(args.kb_context) context = _load_context(args.kb_context)
requested_output_dir = args.output_dir.expanduser() requested_output_dir = args.output_dir.expanduser()
@ -464,7 +537,7 @@ def prepare(args: argparse.Namespace) -> dict[str, Any]:
attempts.append({"attempt": attempt, "response_sha256": sha256_bytes(raw.encode("utf-8")), "usage": usage}) attempts.append({"attempt": attempt, "response_sha256": sha256_bytes(raw.encode("utf-8")), "usage": usage})
try: try:
selection = parse_model_output(raw) selection = parse_model_output(raw)
extraction = resolve_model_output(selection, fragments) extraction = resolve_model_output(selection, fragments, fragment_locations)
compiler._validate_dedupe( compiler._validate_dedupe(
{ {
"database_search_query": context["database_search_query"], "database_search_query": context["database_search_query"],
@ -494,6 +567,7 @@ def prepare(args: argparse.Namespace) -> dict[str, Any]:
with os.fdopen(fd, "wb") as handle: with os.fdopen(fd, "wb") as handle:
handle.write(_json_bytes(manifest)) handle.write(_json_bytes(manifest))
bundle = compiler.compile_source_packet(args.artifact, temp_text, temp_manifest) bundle = compiler.compile_source_packet(args.artifact, temp_text, temp_manifest)
validate_bundle_source_locations(bundle, extraction["selected_source_references"])
finally: finally:
if temp_text.exists(): if temp_text.exists():
temp_text.unlink() temp_text.unlink()
@ -518,6 +592,7 @@ def prepare(args: argparse.Namespace) -> dict[str, Any]:
raise PreparationError("prepared extraction has no manifest") raise PreparationError("prepared extraction has no manifest")
_write_private(manifest_path, _json_bytes(manifest)) _write_private(manifest_path, _json_bytes(manifest))
bundle = compiler.compile_source_packet(args.artifact, text_path, manifest_path) bundle = compiler.compile_source_packet(args.artifact, text_path, manifest_path)
validate_bundle_source_locations(bundle, extraction["selected_source_references"])
receipt = { receipt = {
"schema": RECEIPT_SCHEMA, "schema": RECEIPT_SCHEMA,
@ -545,10 +620,20 @@ def prepare(args: argparse.Namespace) -> dict[str, Any]:
"model": args.model, "model": args.model,
"attempts": attempts, "attempts": attempts,
"claim_count": len(extraction["claims"]), "claim_count": len(extraction["claims"]),
"evidence_count": sum(len(claim["evidence"]) for claim in extraction["claims"]),
"duplicate_judgment_count": len(extraction["duplicates"]),
"selectable_source_line_count": len(fragments), "selectable_source_line_count": len(fragments),
"selected_source_references": extraction["selected_source_references"], "selected_source_references": extraction["selected_source_references"],
"notes": extraction["extraction_notes"], "notes": extraction["extraction_notes"],
}, },
"replay": {
"artifact_sha256": artifact_sha256,
"extracted_text_sha256": text_sha256,
"kb_context_sha256": sha256_bytes(_json_bytes(context)),
"fragment_index_sha256": sha256_bytes(_json_bytes(fragment_locations)),
"extractor": {"name": f"openrouter:{args.model}", "version": EXTRACTOR_VERSION},
"exact_selected_locations_validated": bundle is not None,
},
"outputs": { "outputs": {
"output_dir": str(output_dir), "output_dir": str(output_dir),
"extracted_text": str(text_path), "extracted_text": str(text_path),

View file

@ -0,0 +1,517 @@
#!/usr/bin/env python3
"""Prove manifest-driven Leo identity reconstruction across a cold restart."""
from __future__ import annotations
import argparse
import json
import os
import shutil
import signal
import subprocess
import sys
import tempfile
import time
from datetime import UTC, datetime
from pathlib import Path, PurePosixPath, PureWindowsPath
from typing import Any
if __package__ in {None, ""}:
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from scripts import leo_behavior_manifest as behavior
from scripts import leo_identity_manifest as identity
from scripts import leo_identity_profile as profile_runtime
SCHEMA = "livingip.leoIdentityReconstructionReceipt.v1"
PRIVATE_PATH_PREFIXES = tuple("/" + value for value in ("Users/", "private/tmp/", "var/folders/"))
class CanaryError(RuntimeError):
"""The disposable identity runtime did not satisfy its T2 contract."""
def _require(condition: bool, message: str) -> None:
if not condition:
raise CanaryError(message)
def _receipt_strings(value: object) -> list[str]:
if isinstance(value, dict):
keys = [key for key in value if isinstance(key, str)]
return keys + [text for item in value.values() for text in _receipt_strings(item)]
if isinstance(value, list):
return [text for item in value for text in _receipt_strings(item)]
return [value] if isinstance(value, str) else []
def _validate_portable_receipt(value: object) -> None:
for text in _receipt_strings(value):
if (
any(prefix in text for prefix in PRIVATE_PATH_PREFIXES)
or PurePosixPath(text).is_absolute()
or PureWindowsPath(text).is_absolute()
):
raise CanaryError("receipt contains a private or absolute filesystem path")
def _process_group_absent(process_group: int) -> bool:
try:
os.killpg(process_group, 0)
except ProcessLookupError:
return True
except PermissionError:
return False
return False
def _wait_for_process_group_absence(process_group: int, timeout_seconds: float = 5) -> bool:
deadline = time.monotonic() + timeout_seconds
while time.monotonic() < deadline:
if _process_group_absent(process_group):
return True
time.sleep(0.02)
return _process_group_absent(process_group)
def _signal_process_group(process_group: int, signal_number: signal.Signals) -> bool:
try:
os.killpg(process_group, signal_number)
return True
except (ProcessLookupError, PermissionError):
return False
def _cleanup_remaining_process_group(process_group: int) -> str | None:
if not _signal_process_group(process_group, signal.SIGTERM):
return None
if _wait_for_process_group_absence(process_group, timeout_seconds=1):
return "SIGTERM"
if not _signal_process_group(process_group, signal.SIGKILL):
return "SIGTERM"
return "SIGKILL"
def _logical_repo_path(path: Path, *, deployment_root: Path, placeholder: str) -> str:
"""Return a stable repo-relative path or a non-identifying placeholder."""
try:
relative = path.resolve().relative_to(deployment_root.resolve())
except (OSError, ValueError):
return placeholder
value = relative.as_posix()
return value if value != "." else "."
def _logical_query_command(
*,
deployment_root: Path,
source_root: Path,
hermes_root: Path,
) -> list[str]:
return [
"<python>",
"-m",
"scripts.leo_identity_profile",
"query",
"--profile",
"<temporary-profile>",
"--source-root",
_logical_repo_path(source_root, deployment_root=deployment_root, placeholder="<source-root>"),
"--hermes-root",
_logical_repo_path(hermes_root, deployment_root=deployment_root, placeholder="<hermes-root>"),
"--deployment-root",
".",
"--query",
profile_runtime.FIXED_QUERY,
]
def _run_query_child(
*,
deployment_root: Path,
profile: Path,
source_root: Path,
hermes_root: Path,
profile_role: str,
timeout_seconds: float = 60,
) -> dict[str, Any]:
deployment_root = deployment_root.resolve()
profile = profile.resolve()
source_root = source_root.resolve()
hermes_root = hermes_root.resolve()
actual_argv = [
sys.executable,
"-m",
"scripts.leo_identity_profile",
"query",
"--profile",
str(profile),
"--source-root",
str(source_root),
"--hermes-root",
str(hermes_root),
"--deployment-root",
str(deployment_root),
"--query",
profile_runtime.FIXED_QUERY,
]
process = subprocess.Popen(
actual_argv,
cwd=deployment_root,
env={**os.environ, "PYTHONDONTWRITEBYTECODE": "1"},
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True,
)
timed_out = False
terminated_with: str | None = None
stdout = ""
stderr = ""
process_group_absent_after_wait = False
orphan_cleanup_required = False
try:
try:
stdout, stderr = process.communicate(timeout=timeout_seconds)
except subprocess.TimeoutExpired:
timed_out = True
if _signal_process_group(process.pid, signal.SIGTERM):
terminated_with = "SIGTERM"
try:
stdout, stderr = process.communicate(timeout=5)
except subprocess.TimeoutExpired:
if _signal_process_group(process.pid, signal.SIGKILL):
terminated_with = "SIGKILL"
stdout, stderr = process.communicate(timeout=5)
finally:
if process.poll() is None:
if _signal_process_group(process.pid, signal.SIGTERM):
terminated_with = terminated_with or "SIGTERM"
try:
process.communicate(timeout=5)
except subprocess.TimeoutExpired:
if _signal_process_group(process.pid, signal.SIGKILL):
terminated_with = "SIGKILL"
process.communicate(timeout=5)
orphan_cleanup_required = not _process_group_absent(process.pid)
if orphan_cleanup_required:
terminated_with = _cleanup_remaining_process_group(process.pid) or terminated_with
process_group_absent_after_wait = _wait_for_process_group_absence(process.pid)
try:
payload = json.loads(stdout.strip().splitlines()[-1]) if stdout.strip() else {}
except json.JSONDecodeError as exc:
raise CanaryError("identity child returned invalid JSON") from exc
return {
"logical_command": _logical_query_command(
deployment_root=deployment_root,
source_root=source_root,
hermes_root=hermes_root,
),
"command_serialization": "logical_redacted_v1",
"profile_role": profile_role,
"actual_argv_persisted": False,
"launcher_pid": process.pid,
"returncode": process.returncode,
"timed_out": timed_out,
"terminated_with": terminated_with,
"orphan_cleanup_required": orphan_cleanup_required,
"stdout": payload,
"stderr_sha256": behavior.sha256_bytes(stderr.encode("utf-8")),
"process_group_absent_after_wait": process_group_absent_after_wait,
}
def _query_passed(child: dict[str, Any]) -> bool:
payload = child.get("stdout") or {}
return bool(
child.get("returncode") == 0
and child.get("timed_out") is False
and child.get("orphan_cleanup_required") is False
and child.get("process_group_absent_after_wait") is True
and payload.get("schema") == profile_runtime.QUERY_RECEIPT_SCHEMA
and payload.get("status") == "pass"
)
def _drift_attempt(
*,
deployment_root: Path,
source_root: Path,
hermes_root: Path,
drift_profile: Path,
) -> dict[str, Any]:
with (drift_profile / "SOUL.md").open("a", encoding="utf-8") as handle:
handle.write("\nInjected drift must fail closed.\n")
child = _run_query_child(
deployment_root=deployment_root,
profile=drift_profile,
source_root=source_root,
hermes_root=hermes_root,
profile_role="drift_negative",
)
child["fail_closed"] = bool(
child["returncode"] == 3
and child["timed_out"] is False
and child["orphan_cleanup_required"] is False
and child["process_group_absent_after_wait"] is True
and (child.get("stdout") or {}).get("error") == "identity_drift"
and "compiled view drift detected" in str((child.get("stdout") or {}).get("message"))
)
child["answer_returned"] = bool((child.get("stdout") or {}).get("answer"))
return child
def run_canary(args: argparse.Namespace) -> tuple[dict[str, Any], int]:
output = args.output.resolve()
temporary_root = Path(tempfile.mkdtemp(prefix="leo-identity-reconstruction-"))
report: dict[str, Any] = {
"schema": SCHEMA,
"generated_at_utc": datetime.now(UTC).isoformat(),
"required_tier": "T2_runtime",
"mode": "drift_before_restart"
if args.inject_drift_before_restart
else "successful_restart_plus_drift_negative",
"fixed_query": profile_runtime.FIXED_QUERY,
"fixed_query_sha256": behavior.sha256_bytes(profile_runtime.FIXED_QUERY.encode("utf-8")),
"production_profile_replaced": False,
"production_database_contacted": False,
"telegram_message_sent": False,
"actual_hosted_model_call_performed": False,
"errors": [],
}
exit_code = 1
try:
behavior_manifest = behavior.build_manifest(args.profile_template, args.hermes_root, args.deployment_root)
identity.validate_behavior_manifest(behavior_manifest)
manifest = identity.build_identity_manifest(
behavior_manifest=behavior_manifest,
database_fingerprint_path=args.database_fingerprint,
constitution_path=args.constitution,
database_identity_path=args.database_identity,
source_root=args.source_root,
)
report["manifest"] = manifest
report["behavior_observation_before_compile"] = {
"behavior_sha256": behavior_manifest["behavior_sha256"],
"identity_runtime_sha256": behavior_manifest["identity_runtime_sha256"],
"source_commit": behavior_manifest["teleo_infrastructure_runtime"]["git_head"],
}
compiled_profile = temporary_root / "first-profile"
report["compile"] = profile_runtime.compile_profile(
manifest,
source_root=args.source_root,
profile_template=args.profile_template,
profile=compiled_profile,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
compiled_behavior_before_query = behavior.build_manifest(
compiled_profile, args.hermes_root, args.deployment_root
)
report["compiled_profile_before_query"] = {
"behavior_sha256": compiled_behavior_before_query["behavior_sha256"],
"identity_runtime_sha256": compiled_behavior_before_query["identity_runtime_sha256"],
}
first = _run_query_child(
deployment_root=args.deployment_root,
profile=compiled_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
profile_role="first_start",
)
report["first_start"] = first
_require(_query_passed(first), "first disposable identity process did not answer successfully")
after_first = behavior.build_manifest(compiled_profile, args.hermes_root, args.deployment_root)
report["session_boundary_readback"] = {
"full_behavior_changed_after_session": after_first["behavior_sha256"]
!= compiled_behavior_before_query["behavior_sha256"],
"identity_runtime_unchanged_after_session": after_first["identity_runtime_sha256"]
== compiled_behavior_before_query["identity_runtime_sha256"],
"session_file_count": len(list((compiled_profile / "sessions").glob("*.json"))),
"session_classification": "temporary_noncanonical",
"session_used_as_output_provenance": False,
}
if args.inject_drift_before_restart:
with (compiled_profile / "SOUL.md").open("a", encoding="utf-8") as handle:
handle.write("\nInjected pre-restart drift.\n")
rejected = _run_query_child(
deployment_root=args.deployment_root,
profile=compiled_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
profile_role="pre_restart_drift",
)
report["pre_restart_drift"] = rejected
report["drift_target"] = "compiled SOUL.md generated view"
report["second_start_attempted"] = False
report["gates"] = {
"first_start_passed": True,
"first_process_stopped": first["process_group_absent_after_wait"],
"drift_detected_before_restart": rejected["returncode"] == 3
and (rejected.get("stdout") or {}).get("error") == "identity_drift",
"drift_returned_no_answer": not bool((rejected.get("stdout") or {}).get("answer")),
"drift_process_stopped": rejected["process_group_absent_after_wait"],
"drift_process_had_no_orphan_cleanup": rejected["orphan_cleanup_required"] is False,
"second_start_not_attempted": True,
}
report["status"] = "pass" if all(report["gates"].values()) else "fail"
else:
profile_runtime.verify_profile(
compiled_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
report["pre_restart_verification"] = "pass"
report["second_start_attempted"] = True
restarted_profile = temporary_root / "restart-profile"
report["restart_compile"] = profile_runtime.compile_profile(
manifest,
source_root=args.source_root,
profile_template=args.profile_template,
profile=restarted_profile,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
profile_runtime.verify_profile(
restarted_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
second = _run_query_child(
deployment_root=args.deployment_root,
profile=restarted_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
profile_role="restart",
)
report["restart"] = second
_require(_query_passed(second), "restarted disposable identity process did not answer successfully")
first_payload = first["stdout"]
second_payload = second["stdout"]
drift_profile = temporary_root / "drift-profile"
report["drift_compile"] = profile_runtime.compile_profile(
manifest,
source_root=args.source_root,
profile_template=args.profile_template,
profile=drift_profile,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
drift = _drift_attempt(
deployment_root=args.deployment_root,
source_root=args.source_root,
hermes_root=args.hermes_root,
drift_profile=drift_profile,
)
report["drift_negative"] = drift
report["drift_target"] = "compiled SOUL.md generated view"
report["gates"] = {
"manifest_generated": identity._is_sha256(manifest["manifest_sha256"]),
"views_compiled_and_bound": report["compile"]["status"] == "pass",
"first_start_passed": True,
"first_process_stopped": first["process_group_absent_after_wait"],
"pre_restart_verification_passed": True,
"restart_profile_recompiled_from_manifest": report["restart_compile"]["status"] == "pass",
"restart_profile_started_without_sessions": report["restart_compile"][
"session_directories_started_empty"
],
"restart_passed": True,
"restart_process_is_distinct": first_payload["process_id"] != second_payload["process_id"]
and first_payload["runtime_instance_id"] != second_payload["runtime_instance_id"],
"identity_inputs_reproduced": first_payload["identity_inputs_sha256"]
== second_payload["identity_inputs_sha256"],
"manifest_reproduced": first_payload["manifest_sha256"] == second_payload["manifest_sha256"],
"query_reproduced": first_payload["query_sha256"] == second_payload["query_sha256"],
"answer_and_provenance_explainable": first_payload["answer_sha256"] == second_payload["answer_sha256"]
and first_payload["output_provenance"] == second_payload["output_provenance"],
"session_excluded_from_identity": report["session_boundary_readback"][
"identity_runtime_unchanged_after_session"
],
"drift_failed_closed": drift["fail_closed"] and not drift["answer_returned"],
"drift_profile_started_without_sessions": report["drift_compile"]["session_directories_started_empty"],
"drift_process_stopped": drift["process_group_absent_after_wait"],
"drift_process_had_no_orphan_cleanup": drift["orphan_cleanup_required"] is False,
"restart_process_stopped": second["process_group_absent_after_wait"],
}
report["status"] = "pass" if all(report["gates"].values()) else "fail"
if report["status"] == "pass":
exit_code = 0
except (CanaryError, identity.IdentityManifestError, OSError, subprocess.SubprocessError) as exc:
report["status"] = "fail"
report["errors"].append(
{
"type": type(exc).__name__,
"message": "details_redacted",
"detail_sha256": behavior.sha256_bytes(str(exc).encode("utf-8")),
}
)
finally:
shutil.rmtree(temporary_root, ignore_errors=True)
report["cleanup"] = {
"temporary_root_removed": not temporary_root.exists(),
"no_profile_retained": not temporary_root.exists(),
}
if not all(report["cleanup"].values()):
report["status"] = "fail"
exit_code = 1
positive_restart_passed = report.get("status") == "pass" and not args.inject_drift_before_restart
report["current_tier"] = "T2_runtime" if positive_restart_passed else "T1_model"
report["goal_tier_satisfied"] = positive_restart_passed
report["runtime_component_proven"] = (
"fresh_profile_recompile_plus_distinct_process_restart"
if positive_restart_passed
else "first_local_process_plus_pre_restart_drift_refusal"
)
report["runtime_variant"] = "local_deterministic_identity_compiler_readback"
report["tier_basis"] = (
"Capability Tier Proof defines T2_runtime as local API/runtime behavior with restart where relevant; "
"this is compiler-process runtime proof and explicitly excludes GatewayRunner and hosted-model proof."
if positive_restart_passed
else "This negative component does not complete the required restart path, so it remains below T2_runtime."
)
report["claim_ceiling"] = (
"Local disposable identity compilation, fresh-profile reconstruction, and cold-process restart only; "
"not a live GatewayRunner, hosted-model, Telegram, production database, VPS restart, or T3 proof."
if positive_restart_passed
else "Local first-process and pre-restart drift-refusal component only; no successful restart proof, "
"GatewayRunner, hosted model, production database, VPS, or T3 claim."
)
_validate_portable_receipt(report)
stable = {key: value for key, value in report.items() if key != "receipt_sha256"}
report["receipt_sha256"] = behavior.canonical_sha256(stable)
identity.write_json(output, report)
return report, exit_code
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--profile-template", type=Path, required=True)
parser.add_argument("--hermes-root", type=Path, required=True)
parser.add_argument("--deployment-root", type=Path, required=True)
parser.add_argument("--source-root", type=Path, required=True)
parser.add_argument("--database-fingerprint", type=Path, required=True)
parser.add_argument("--constitution", type=Path, required=True)
parser.add_argument("--database-identity", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--inject-drift-before-restart", action="store_true")
args = parser.parse_args()
report, exit_code = run_canary(args)
print(
json.dumps(
{
"status": report.get("status"),
"current_tier": report.get("current_tier"),
"receipt_sha256": report.get("receipt_sha256"),
"output": str(args.output),
},
sort_keys=True,
)
)
return exit_code
if __name__ == "__main__":
raise SystemExit(main())

File diff suppressed because it is too large Load diff

View file

@ -57,6 +57,12 @@ def prepare_normalized_child(parent: dict[str, Any]) -> dict[str, Any]:
manifest = apply_payload.setdefault("normalization_manifest", {}) manifest = apply_payload.setdefault("normalization_manifest", {})
if not isinstance(manifest, dict): if not isinstance(manifest, dict):
raise bound.CheckpointError("normalized child normalization_manifest must be an object") raise bound.CheckpointError("normalized child normalization_manifest must be an object")
parent_payload = parent.get("payload")
ingestion_manifest = parent_payload.get("ingestion_manifest") if isinstance(parent_payload, dict) else None
if ingestion_manifest is not None:
if not isinstance(ingestion_manifest, dict):
raise bound.CheckpointError("parent payload.ingestion_manifest must be an object")
manifest["ingestion_manifest"] = json.loads(json.dumps(ingestion_manifest, sort_keys=True))
parent_packet_sha256 = canonical_sha256(parent) parent_packet_sha256 = canonical_sha256(parent)
manifest["parent_packet_sha256"] = parent_packet_sha256 manifest["parent_packet_sha256"] = parent_packet_sha256
child_payload_sha256 = canonical_sha256(payload) child_payload_sha256 = canonical_sha256(payload)

View file

@ -203,6 +203,15 @@ def _lines(completed: subprocess.CompletedProcess[str]) -> set[str]:
return {line for line in completed.stdout.splitlines() if line} return {line for line in completed.stdout.splitlines() if line}
def test_reviewer_principal_seed_timestamp_is_deterministic(migrated_postgres: str) -> None:
created_at = _psql(
migrated_postgres,
"select created_at::text from kb_stage.kb_review_principals where db_role = 'kb_review';",
).stdout.strip()
assert created_at == "1970-01-01 00:00:00+00"
def _catalog_snapshot(container: str) -> str: def _catalog_snapshot(container: str) -> str:
return _psql( return _psql(
container, container,

View file

@ -4,6 +4,8 @@ import json
import subprocess import subprocess
from pathlib import Path from pathlib import Path
import pytest
from scripts import leo_behavior_manifest as manifest from scripts import leo_behavior_manifest as manifest
ROOT = Path(__file__).resolve().parents[1] ROOT = Path(__file__).resolve().parents[1]
@ -58,6 +60,11 @@ gateway:
assert '{"private":"conversation"}' not in encoded assert '{"private":"conversation"}' not in encoded
def test_identity_config_rejects_nonboolean_smart_model_routing() -> None:
with pytest.raises(ValueError, match="smart_model_routing must be boolean"):
manifest.identity_config_projection({"smart_model_routing": {"route": "untrusted"}})
def test_behavior_manifest_changes_when_a_behavior_layer_changes(tmp_path: Path) -> None: def test_behavior_manifest_changes_when_a_behavior_layer_changes(tmp_path: Path) -> None:
profile = tmp_path / "profile" profile = tmp_path / "profile"
hermes = tmp_path / "hermes" hermes = tmp_path / "hermes"
@ -156,3 +163,64 @@ def test_git_state_marks_untracked_files_dirty(tmp_path: Path) -> None:
assert state["worktree_clean"] is False assert state["worktree_clean"] is False
assert len(str(state["status_sha256"])) == 64 assert len(str(state["status_sha256"])) == 64
def test_identity_runtime_omits_secret_values_but_pins_semantic_model_settings(tmp_path: Path) -> None:
profile = tmp_path / "profile"
hermes = tmp_path / "hermes"
deployment = tmp_path / "deployment"
config = """model:
provider: fixture
default: identity-v1
max_tokens: 512
gateway:
telegram:
bot_token: token-a
botToken: camel-token-a
provider:
apiKey: camel-api-key-a
transport:
endpoint: https://fixture-user:fixture-password-a@example.invalid/v1
headers: ['Authorization: Bearer fixture-header-a']
tools:
allowed: [identity_readback]
identity_runtime:
network_send_enabled: false
database_write_enabled: false
allowed_tools: [identity_readback]
"""
_write(profile / "config.yaml", config)
_write(profile / "skills" / "identity" / "SKILL.md", "identity\n")
_write(profile / "plugins" / "identity" / "__init__.py", "BOUNDARY = True\n")
_write(profile / "bin" / "identity.py", "READ_ONLY = True\n")
_write(hermes / "run_agent.py", "runtime\n")
_write(hermes / "agent" / "prompt_builder.py", "prompts\n")
for name in (
"leo_behavior_manifest.py",
"leo_identity_manifest.py",
"leo_identity_profile.py",
"run_leo_identity_reconstruction_canary.py",
):
_write(deployment / "scripts" / name, f"# {name}\n")
before = manifest.build_manifest(profile, hermes, deployment)
_write(
profile / "config.yaml",
config.replace("token-a", "token-b")
.replace("camel-api-key-a", "camel-api-key-b")
.replace("fixture-password-a", "fixture-password-b")
.replace("fixture-header-a", "fixture-header-b"),
)
secret_rotated = manifest.build_manifest(profile, hermes, deployment)
_write(profile / "config.yaml", config.replace("max_tokens: 512", "max_tokens: 1024"))
model_changed = manifest.build_manifest(profile, hermes, deployment)
assert before["behavior_sha256"] != secret_rotated["behavior_sha256"]
assert before["identity_runtime_sha256"] == secret_rotated["identity_runtime_sha256"]
assert before["identity_runtime_sha256"] != model_changed["identity_runtime_sha256"]
encoded = json.dumps(before)
assert "token-a" not in encoded
assert "camel-token-a" not in encoded
assert "camel-api-key-a" not in encoded
assert "fixture-password-a" not in encoded
assert "fixture-header-a" not in encoded

View file

@ -0,0 +1,794 @@
from __future__ import annotations
import argparse
import copy
import json
import os
import subprocess
import time
from pathlib import Path, PureWindowsPath
import pytest
from scripts import leo_behavior_manifest as behavior
from scripts import leo_identity_manifest as identity
from scripts import leo_identity_profile as profile_runtime
from scripts import run_leo_identity_reconstruction_canary as canary
ROOT = Path(__file__).resolve().parents[1]
COMMITTED_RECEIPTS = (
ROOT / "docs/reports/leo-working-state-20260709/leo-reproducible-identity-t2-current.json",
ROOT / "docs/reports/leo-working-state-20260709/leo-reproducible-identity-drift-negative-current.json",
)
def _write(path: Path, value: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(value, encoding="utf-8")
def _write_json(path: Path, value: dict) -> None:
_write(path, json.dumps(value, indent=2, sort_keys=True) + "\n")
def _assert_path_portable_receipt(value: object) -> None:
canary._validate_portable_receipt(value)
def _assert_logical_child_execution(child: dict, *, profile_role: str) -> None:
logical_command = child["logical_command"]
assert "command" not in child
assert child["profile_role"] == profile_role
assert child["command_serialization"] == "logical_redacted_v1"
assert child["actual_argv_persisted"] is False
assert logical_command[0] == "<python>"
assert logical_command[logical_command.index("--profile") + 1] == "<temporary-profile>"
_assert_path_portable_receipt(child)
def _fixture(tmp_path: Path) -> dict[str, Path | dict]:
repo = tmp_path / "repo"
profile = repo / "profile-template"
hermes = repo / "hermes-runtime"
compiled = tmp_path / "compiled-profile"
_write(
profile / "config.yaml",
"""model:
provider: fixture-local
default: identity-v1
max_tokens: 512
memory:
enabled: false
gateway:
execution_mode: local_no_send
telegram:
bot_token: never-emit-this-fixture-value
transport:
endpoint: https://fixture-user:fixture-password@example.invalid/v1
headers: ['Authorization: Bearer fixture-secret']
tools:
allowed: [identity_readback]
write_enabled: false
identity_runtime:
network_send_enabled: false
database_write_enabled: false
allowed_tools: [identity_readback]
""",
)
_write(profile / "skills" / "identity" / "SKILL.md", "# identity readback\n")
_write(profile / "plugins" / "identity" / "__init__.py", "BOUNDARY = True\n")
_write(profile / "bin" / "identity_readback.py", "READ_ONLY = True\n")
_write(hermes / "run_agent.py", "RUNTIME = 'identity-v1'\n")
_write(hermes / "agent" / "prompt_builder.py", "SOUL_IS_GENERATED = True\n")
_write(hermes / "gateway" / "run.py", "SESSION_IS_IDENTITY = False\n")
_write(hermes / "hermes_cli" / "tools_config.py", "TOOLS = ('identity_readback',)\n")
_write(hermes / "tools" / "registry.py", "READ_ONLY = True\n")
for name in (
"leo_behavior_manifest.py",
"leo_identity_manifest.py",
"leo_identity_profile.py",
"run_leo_identity_reconstruction_canary.py",
):
_write(repo / "scripts" / name, (ROOT / "scripts" / name).read_text(encoding="utf-8"))
fingerprint_path = repo / "fixtures" / "database-fingerprint.json"
constitution_path = repo / "fixtures" / "constitution.json"
database_identity_path = repo / "fixtures" / "database-identity.json"
fingerprint = {
"schema": identity.DATABASE_FINGERPRINT_SCHEMA,
"status": "ok",
"environment": "disposable_fixture",
"fingerprint_sha256": "1" * 64,
"table_rows_sha256": "2" * 64,
"structure_sha256": "3" * 64,
"table_count": 2,
"total_rows": 2,
"read_consistency": {
"status": "stable_wal_marker",
"before": {
"database": "fixture",
"database_user": "reader",
"system_identifier": "12345",
"wal_lsn": "0/1",
},
"after": {
"database": "fixture",
"database_user": "reader",
"system_identifier": "12345",
"wal_lsn": "0/1",
},
},
}
constitution = {
"schema": identity.CONSTITUTION_SCHEMA,
"identity_name": "Leo",
"rules": [
{"id": "evidence", "text": "Never use temporary session memory as canonical evidence."},
{"id": "truth", "text": "Fail closed when a pinned identity input drifts."},
],
}
database_identity = {
"schema": identity.DATABASE_IDENTITY_SCHEMA,
"identity_name": "Leo",
"database_fingerprint_sha256": "1" * 64,
"source_provenance": {
"mode": identity.SYNTHETIC_DATABASE_MODE,
"canonical_authority_granted": False,
"same_transaction_as_fingerprint": False,
"export_receipt_sha256": None,
},
"records": [
{
"table": "public.personas",
"row_id": "persona-1",
"kind": "persona",
"rank": 0,
"text": "Leo is an evidence-bound reasoning interface.",
"status": "active",
"evidence_sha256": "a" * 64,
},
{
"table": "public.beliefs",
"row_id": "belief-1",
"kind": "belief",
"rank": 0,
"text": "Exact provenance is stronger than plausible recollection.",
"status": "active",
"evidence_sha256": "b" * 64,
},
],
}
_write_json(fingerprint_path, fingerprint)
_write_json(constitution_path, constitution)
_write_json(database_identity_path, database_identity)
subprocess.run(["git", "init", "-q", str(repo)], check=True)
subprocess.run(["git", "-C", str(repo), "config", "user.email", "test@example.com"], check=True)
subprocess.run(["git", "-C", str(repo), "config", "user.name", "Test"], check=True)
subprocess.run(["git", "-C", str(repo), "add", "."], check=True)
subprocess.run(
["git", "-C", str(repo), "commit", "-qm", "fixture"],
check=True,
env={
**dict(__import__("os").environ),
"GIT_AUTHOR_DATE": "2026-01-01T00:00:00Z",
"GIT_COMMITTER_DATE": "2026-01-01T00:00:00Z",
},
)
behavior_manifest = behavior.build_manifest(profile, hermes, repo)
manifest = identity.build_identity_manifest(
behavior_manifest=behavior_manifest,
database_fingerprint_path=fingerprint_path,
constitution_path=constitution_path,
database_identity_path=database_identity_path,
source_root=repo,
)
return {
"repo": repo,
"profile": profile,
"hermes": hermes,
"compiled": compiled,
"fingerprint": fingerprint_path,
"constitution": constitution_path,
"database_identity": database_identity_path,
"behavior": behavior_manifest,
"manifest": manifest,
}
def _fully_rehash_manifest(fixture: dict[str, Path | dict], manifest: dict) -> None:
identity_hash = behavior.canonical_sha256(manifest["identity_inputs"])
manifest["identity_inputs_sha256"] = identity_hash
fingerprint = identity.load_json(fixture["fingerprint"], "database fingerprint")
rules = identity.canonical_rules(identity.load_json(fixture["constitution"], "constitution"))
records = identity.canonical_database_records(
identity.load_json(fixture["database_identity"], "database identity"),
fingerprint_sha256=fingerprint["fingerprint_sha256"],
)
database_provenance = identity.database_identity_provenance(
identity.load_json(fixture["database_identity"], "database identity"),
fingerprint=fingerprint,
)
rendered = identity.render_identity_views(
identity_inputs_sha256=identity_hash,
database_fingerprint_sha256=fingerprint["fingerprint_sha256"],
database_provenance=database_provenance,
rules=rules,
records=records,
)
for name, content in rendered.items():
manifest["compiled_views"][name]["sha256"] = behavior.sha256_bytes(content.encode("utf-8"))
manifest["compiled_views"][name]["generated_from_identity_inputs_sha256"] = identity_hash
stable = {key: value for key, value in manifest.items() if key != "manifest_sha256"}
manifest["manifest_sha256"] = behavior.canonical_sha256(stable)
def _rehash_behavior_manifest(manifest: dict) -> None:
manifest["identity_runtime_sha256"] = behavior.canonical_sha256(behavior.identity_runtime_payload(manifest))
manifest["static_runtime_sha256"] = behavior.canonical_sha256(behavior.static_runtime_payload(manifest))
manifest["behavior_sha256"] = behavior.canonical_sha256(behavior.stable_manifest_payload(manifest))
def _canary_args(fixture: dict[str, Path | dict], output: Path, *, inject_drift: bool = False) -> argparse.Namespace:
return argparse.Namespace(
profile_template=fixture["profile"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
source_root=fixture["repo"],
database_fingerprint=fixture["fingerprint"],
constitution=fixture["constitution"],
database_identity=fixture["database_identity"],
output=output,
inject_drift_before_restart=inject_drift,
)
@pytest.mark.parametrize(
"private_path",
[
"/" + "Users/operator/checkout/profile",
"/" + "private/tmp/lane/.venv/bin/python",
"/" + "var/folders/cache/temporary-profile",
"/" + "tmp/temporary-profile",
"/" + "opt/checkout/interpreter",
"/" + "workspace/checkout/temporary-profile",
str(PureWindowsPath("C:/operator/checkout/temporary-profile")),
"\\\\" + "server\\share\\checkout\\temporary-profile",
],
)
def test_receipt_path_guard_recursively_rejects_private_and_absolute_paths(private_path: str) -> None:
with pytest.raises(canary.CanaryError, match="private or absolute filesystem path"):
_assert_path_portable_receipt({"outer": [{"logical_command": ["<python>", private_path]}]})
def test_receipt_path_guard_rejects_an_absolute_path_in_a_nested_key() -> None:
private_key = "/" + "tmp/checkout/temporary-profile"
with pytest.raises(canary.CanaryError, match="private or absolute filesystem path"):
_assert_path_portable_receipt({"outer": [{private_key: "<temporary-profile>"}]})
def test_logical_command_uses_placeholders_for_paths_outside_the_deployment_root(tmp_path: Path) -> None:
logical_command = canary._logical_query_command(
deployment_root=tmp_path / "checkout",
source_root=tmp_path / "outside-source",
hermes_root=tmp_path / "outside-hermes",
)
assert logical_command[logical_command.index("--source-root") + 1] == "<source-root>"
assert logical_command[logical_command.index("--hermes-root") + 1] == "<hermes-root>"
_assert_path_portable_receipt(logical_command)
@pytest.mark.parametrize("receipt_path", COMMITTED_RECEIPTS, ids=lambda path: path.name)
def test_committed_identity_receipts_are_path_portable_and_self_hashed(receipt_path: Path) -> None:
receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
_assert_path_portable_receipt(receipt)
stable = {key: value for key, value in receipt.items() if key != "receipt_sha256"}
assert behavior.canonical_sha256(stable) == receipt["receipt_sha256"]
def test_manifest_compiles_generated_views_and_reproduces_identity_across_queries(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
manifest = fixture["manifest"]
assert isinstance(manifest, dict)
rebuilt = identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
assert rebuilt == manifest
compile_receipt = profile_runtime.compile_profile(
manifest,
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
first = profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
second = profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
assert compile_receipt["status"] == "pass"
assert "never-emit-this-fixture-value" not in (fixture["compiled"] / "config.yaml").read_text(encoding="utf-8")
assert "fixture-password" not in (fixture["compiled"] / "config.yaml").read_text(encoding="utf-8")
assert "fixture-secret" not in (fixture["compiled"] / "config.yaml").read_text(encoding="utf-8")
assert (fixture["compiled"] / "SOUL.md").read_text(encoding="utf-8").startswith("<!-- GENERATED FILE")
assert first["manifest_sha256"] == second["manifest_sha256"]
assert first["identity_inputs_sha256"] == second["identity_inputs_sha256"]
assert first["answer_sha256"] == second["answer_sha256"]
assert first["output_provenance"] == second["output_provenance"]
assert first["runtime_instance_id"] != second["runtime_instance_id"]
assert first["session"]["included_in_output_provenance"] is False
assert first["output_provenance"]["database_canonical_authority_granted"] is False
assert first["authorization"]["authorization_decision_observed"] is False
assert "synthetic noncanonical fixture" in first["answer"]
assert len(list((fixture["compiled"] / "sessions").glob("*.json"))) == 2
def test_profile_and_bound_source_drift_fail_closed(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
profile_runtime.compile_profile(
fixture["manifest"],
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
with (fixture["compiled"] / "SOUL.md").open("a", encoding="utf-8") as handle:
handle.write("drift\n")
with pytest.raises(identity.IdentityManifestError, match="compiled view drift detected"):
profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
_write(fixture["constitution"], fixture["constitution"].read_text(encoding="utf-8") + "\n")
with pytest.raises(identity.IdentityManifestError, match="constitution source content drift"):
identity.verify_bound_sources(fixture["manifest"], fixture["repo"])
@pytest.mark.parametrize(
("relative_path", "content", "message"),
[
("memories/USER.md", "untrusted memory\n", "forbidden nonauthoritative"),
("MEMORY.md", "untrusted top-level memory\n", "forbidden nonauthoritative"),
("USER.md", "untrusted top-level user memory\n", "forbidden nonauthoritative"),
("platforms/pairing/telegram.json", "{}\n", "forbidden nonauthoritative"),
(".env", "LEO_SECRET=untrusted\n", "profile entry set is not exact"),
("gateway.json", "{}\n", "profile entry set is not exact"),
("unexpected.txt", "untrusted input\n", "profile entry set is not exact"),
("sessions/injected.txt", "untrusted session\n", "unsafe session entry"),
("state/injected.json", "{}\n", "state directory must remain empty"),
],
)
def test_profile_rechecks_nonauthoritative_surfaces_before_every_query(
tmp_path: Path, relative_path: str, content: str, message: str
) -> None:
fixture = _fixture(tmp_path)
profile_runtime.compile_profile(
fixture["manifest"],
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
_write(fixture["compiled"] / relative_path, content)
with pytest.raises(profile_runtime.IdentityProfileError, match=message):
profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
def test_manifest_rejects_rehashed_core_tampering(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
tampered = copy.deepcopy(fixture["manifest"])
tampered["identity_inputs"]["session_boundary"]["may_be_used_as_evidence"] = True
stable = {key: value for key, value in tampered.items() if key != "manifest_sha256"}
tampered["manifest_sha256"] = behavior.canonical_sha256(stable)
with pytest.raises(identity.IdentityManifestError, match="identity input hash drift"):
identity.validate_identity_manifest(tampered)
@pytest.mark.parametrize(
("path", "value", "message"),
[
(("permissions", "runtime_policy", "network_send_enabled"), True, "exact local readback policy"),
(("session_boundary", "may_be_used_as_evidence"), True, "session authority boundary"),
],
)
def test_manifest_rejects_fully_rehashed_safety_invariant_tampering(
tmp_path: Path, path: tuple[str, ...], value: object, message: str
) -> None:
fixture = _fixture(tmp_path)
tampered = copy.deepcopy(fixture["manifest"])
target = tampered["identity_inputs"]
for key in path[:-1]:
target = target[key]
target[path[-1]] = value
_fully_rehash_manifest(fixture, tampered)
with pytest.raises(identity.IdentityManifestError, match=message):
identity.verify_bound_sources(tampered, fixture["repo"])
def test_behavior_manifest_rejects_unhashed_model_claim_tampering(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
tampered_behavior = copy.deepcopy(fixture["behavior"])
tampered_behavior["model_runtime"]["default_model"] = "tampered-unobserved-model"
with pytest.raises(identity.IdentityManifestError, match="behavior identity runtime hash drift"):
identity.build_identity_manifest(
behavior_manifest=tampered_behavior,
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
def test_profile_rejects_a_dangling_extra_symlink(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
profile_runtime.compile_profile(
fixture["manifest"],
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
(fixture["compiled"] / ".env").symlink_to(tmp_path / "missing-env")
with pytest.raises(profile_runtime.IdentityProfileError, match="profile entry set is not exact"):
profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
def test_profile_rejects_a_symlink_in_an_allowed_entry(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
profile_runtime.compile_profile(
fixture["manifest"],
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
external_config = tmp_path / "external-config.yaml"
external_config.write_bytes((fixture["compiled"] / "config.yaml").read_bytes())
(fixture["compiled"] / "config.yaml").unlink()
(fixture["compiled"] / "config.yaml").symlink_to(external_config)
with pytest.raises(profile_runtime.IdentityProfileError, match="profile entries must not be symlinks"):
profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
@pytest.mark.parametrize(
("mutation", "message"),
[
("unreadable_file", "unreadable inputs"),
("symlink", "unsupported symlinks"),
("forged_structure", "is empty"),
],
)
def test_behavior_manifest_rejects_unreplayable_identity_components(
tmp_path: Path, mutation: str, message: str
) -> None:
fixture = _fixture(tmp_path)
tampered_behavior = copy.deepcopy(fixture["behavior"])
content = tampered_behavior["components"]["procedural_skills"]["content"]
if mutation == "unreadable_file":
content["files"][0].pop("sha256")
content["files"][0]["status"] = "unavailable"
elif mutation == "symlink":
content["symlinks"].append(
{
"path": "skills/identity/link",
"target": "/outside/checkout",
"target_fingerprint": {"kind": "unavailable", "error": "FileNotFoundError"},
}
)
else:
content["files"] = []
content["sha256"] = behavior.canonical_sha256({key: content[key] for key in ("files", "missing", "symlinks")})
_rehash_behavior_manifest(tampered_behavior)
with pytest.raises(identity.IdentityManifestError, match=message):
identity.validate_behavior_manifest(tampered_behavior)
def test_fully_rehashed_model_claim_must_match_observed_runtime(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
tampered = copy.deepcopy(fixture["manifest"])
tampered["identity_inputs"]["model"]["default_model"] = "tampered-unobserved-model"
_fully_rehash_manifest(fixture, tampered)
identity.validate_identity_manifest(tampered)
with pytest.raises(
profile_runtime.IdentityProfileError, match="model runtime binding drift detected: default_model"
):
profile_runtime.compile_profile(
tampered,
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
assert not fixture["compiled"].exists()
def test_restart_canary_uses_distinct_processes_and_cleans_up(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
output = tmp_path / "restart-receipt.json"
report, exit_code = canary.run_canary(_canary_args(fixture, output))
assert exit_code == 0
assert report["status"] == "pass"
assert report["gates"]["restart_process_is_distinct"] is True
assert report["gates"]["restart_profile_recompiled_from_manifest"] is True
assert report["restart_compile"]["session_directories_started_empty"] is True
assert report["drift_compile"]["session_directories_started_empty"] is True
_assert_logical_child_execution(report["first_start"], profile_role="first_start")
_assert_logical_child_execution(report["restart"], profile_role="restart")
_assert_logical_child_execution(report["drift_negative"], profile_role="drift_negative")
_assert_path_portable_receipt(report)
assert report["first_start"]["launcher_pid"] != report["restart"]["launcher_pid"]
assert report["first_start"]["process_group_absent_after_wait"] is True
assert report["restart"]["process_group_absent_after_wait"] is True
assert report["drift_negative"]["fail_closed"] is True
assert report["drift_negative"]["process_group_absent_after_wait"] is True
assert report["goal_tier_satisfied"] is True
assert report["current_tier"] == "T2_runtime"
assert report["cleanup"]["temporary_root_removed"] is True
assert behavior.git_state(fixture["repo"])["worktree_clean"] is True
assert json.loads(output.read_text(encoding="utf-8")) == report
def test_restart_canary_rejects_drift_before_second_start(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
output = tmp_path / "drift-receipt.json"
report, exit_code = canary.run_canary(_canary_args(fixture, output, inject_drift=True))
assert exit_code == 0
assert report["status"] == "pass"
assert report["gates"]["drift_detected_before_restart"] is True
assert report["second_start_attempted"] is False
assert "restart" not in report
_assert_logical_child_execution(report["first_start"], profile_role="first_start")
_assert_logical_child_execution(report["pre_restart_drift"], profile_role="pre_restart_drift")
_assert_path_portable_receipt(report)
assert report["pre_restart_drift"]["process_group_absent_after_wait"] is True
assert all(report["gates"].values())
assert report["goal_tier_satisfied"] is False
assert report["current_tier"] == "T1_model"
assert report["cleanup"]["temporary_root_removed"] is True
assert json.loads(output.read_text(encoding="utf-8")) == report
def test_query_child_timeout_terminates_process_group(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
marker = tmp_path / "descendant.pid"
sleeping_module = f"""import subprocess
import sys
import time
from pathlib import Path
child = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(60)'])
Path({str(marker)!r}).write_text(str(child.pid), encoding='utf-8')
time.sleep(60)
"""
_write(fixture["repo"] / "scripts" / "leo_identity_profile.py", sleeping_module)
result = canary._run_query_child(
deployment_root=fixture["repo"],
profile=fixture["compiled"],
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
profile_role="timeout_test",
timeout_seconds=0.5,
)
assert result["timed_out"] is True
assert result["terminated_with"] in {"SIGTERM", "SIGKILL"}
assert result["returncode"] != 0
assert result["process_group_absent_after_wait"] is True
descendant_pid = int(marker.read_text(encoding="utf-8"))
deadline = time.monotonic() + 5
while time.monotonic() < deadline:
try:
os.kill(descendant_pid, 0)
except ProcessLookupError:
break
time.sleep(0.02)
with pytest.raises(ProcessLookupError):
os.kill(descendant_pid, 0)
def test_query_child_cleans_and_rejects_orphan_from_completed_launcher(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
marker = tmp_path / "completed-descendant.pid"
query_payload = {"schema": profile_runtime.QUERY_RECEIPT_SCHEMA, "status": "pass"}
leaking_module = f"""import json
import subprocess
import sys
from pathlib import Path
child = subprocess.Popen(
[sys.executable, '-c', 'import time; time.sleep(60)'],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
Path({str(marker)!r}).write_text(str(child.pid), encoding='utf-8')
print(json.dumps({query_payload!r}))
"""
_write(fixture["repo"] / "scripts" / "leo_identity_profile.py", leaking_module)
result = canary._run_query_child(
deployment_root=fixture["repo"],
profile=fixture["compiled"],
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
profile_role="orphan_cleanup_test",
timeout_seconds=5,
)
assert result["returncode"] == 0
assert result["orphan_cleanup_required"] is True
assert result["terminated_with"] in {"SIGTERM", "SIGKILL"}
assert result["process_group_absent_after_wait"] is True
assert canary._query_passed(result) is False
def test_wal_capture_marker_is_not_an_identity_input(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
original = fixture["manifest"]
fingerprint = json.loads(fixture["fingerprint"].read_text(encoding="utf-8"))
fingerprint["read_consistency"]["before"]["wal_lsn"] = "0/2"
fingerprint["read_consistency"]["after"]["wal_lsn"] = "0/2"
_write_json(fixture["fingerprint"], fingerprint)
rebuilt = identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
assert rebuilt["identity_inputs_sha256"] == original["identity_inputs_sha256"]
assert rebuilt["manifest_sha256"] == original["manifest_sha256"]
def test_database_identity_and_system_markers_are_identity_inputs(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
original = fixture["manifest"]
fingerprint = json.loads(fixture["fingerprint"].read_text(encoding="utf-8"))
for marker in (fingerprint["read_consistency"]["before"], fingerprint["read_consistency"]["after"]):
marker["database"] = "different_database"
marker["database_user"] = "different_reader"
marker["system_identifier"] = "99999"
_write_json(fixture["fingerprint"], fingerprint)
rebuilt = identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
assert rebuilt["identity_inputs_sha256"] != original["identity_inputs_sha256"]
with pytest.raises(identity.IdentityManifestError, match="database fingerprint semantic drift"):
identity.verify_bound_sources(original, fixture["repo"])
def test_synthetic_database_rows_cannot_claim_canonical_authority(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
database_identity = json.loads(fixture["database_identity"].read_text(encoding="utf-8"))
database_identity["source_provenance"] = {
"mode": identity.CANONICAL_DATABASE_MODE,
"canonical_authority_granted": True,
"same_transaction_as_fingerprint": True,
"export_receipt_sha256": "f" * 64,
}
_write_json(fixture["database_identity"], database_identity)
with pytest.raises(identity.IdentityManifestError, match="independently verified output"):
identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
def test_self_hashed_database_export_receipt_cannot_grant_canonical_authority(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
fingerprint = json.loads(fixture["fingerprint"].read_text(encoding="utf-8"))
fingerprint["environment"] = "canonical_readonly_capture"
_write_json(fixture["fingerprint"], fingerprint)
database_identity = json.loads(fixture["database_identity"].read_text(encoding="utf-8"))
records = identity.canonical_database_records(
database_identity,
fingerprint_sha256=fingerprint["fingerprint_sha256"],
)
marker = fingerprint["read_consistency"]["before"]
receipt_stable = {
"schema": "livingip.untrustedCallerSuppliedExportReceipt.v1",
"read_only": True,
"same_transaction_as_fingerprint": True,
"transaction_isolation": "repeatable_read_read_only",
"database": marker["database"],
"database_user": marker["database_user"],
"system_identifier": marker["system_identifier"],
"database_fingerprint_sha256": fingerprint["fingerprint_sha256"],
"records_sha256": behavior.canonical_sha256(records),
}
receipt_hash = behavior.canonical_sha256(receipt_stable)
database_identity["source_provenance"] = {
"mode": identity.CANONICAL_DATABASE_MODE,
"canonical_authority_granted": True,
"same_transaction_as_fingerprint": True,
"export_receipt_sha256": receipt_hash,
}
database_identity["export_receipt"] = {**receipt_stable, "receipt_sha256": receipt_hash}
_write_json(fixture["database_identity"], database_identity)
with pytest.raises(identity.IdentityManifestError, match="independently verified output"):
identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
def test_same_clean_commit_reproduces_identity_from_different_checkout_paths(tmp_path: Path) -> None:
first = _fixture(tmp_path / "checkout-a")
second = _fixture(tmp_path / "checkout-b")
assert (
first["behavior"]["teleo_infrastructure_runtime"]["git_head"]
== second["behavior"]["teleo_infrastructure_runtime"]["git_head"]
)
assert first["behavior"]["identity_runtime_sha256"] == second["behavior"]["identity_runtime_sha256"]
assert first["manifest"]["identity_inputs_sha256"] == second["manifest"]["identity_inputs_sha256"]
assert first["manifest"]["manifest_sha256"] == second["manifest"]["manifest_sha256"]

View file

@ -123,11 +123,17 @@ def test_prepare_builds_private_compiler_validated_manifest_without_db_write(
assert manifest["dedupe"]["duplicates"][0]["claim_id"] == CANDIDATE_ID assert manifest["dedupe"]["duplicates"][0]["claim_id"] == CANDIDATE_ID
assert manifest["claims"][0]["quote"] == CLAIM_QUOTE assert manifest["claims"][0]["quote"] == CLAIM_QUOTE
assert manifest["dedupe"]["duplicates"][0]["source_quote"] == DUPLICATE_QUOTE assert manifest["dedupe"]["duplicates"][0]["source_quote"] == DUPLICATE_QUOTE
assert receipt["extraction"]["selected_source_references"] == [ selected = receipt["extraction"]["selected_source_references"]
{"kind": "claim", "reference": "S00003"}, assert [(row["kind"], row["reference"]) for row in selected] == [
{"kind": "evidence", "reference": "S00003"}, ("claim", "S00003"),
{"kind": "duplicate", "reference": "S00002"}, ("evidence", "S00003"),
("duplicate", "S00002"),
] ]
assert all(row["char_end"] > row["char_start"] for row in selected)
assert all(len(row["quote_sha256"]) == 64 for row in selected)
assert receipt["replay"]["exact_selected_locations_validated"] is True
assert receipt["extraction"]["evidence_count"] == 1
assert receipt["extraction"]["duplicate_judgment_count"] == 1
assert stat.S_IMODE(output_dir.stat().st_mode) == 0o700 assert stat.S_IMODE(output_dir.stat().st_mode) == 0o700
for path in output_dir.iterdir(): for path in output_dir.iterdir():
assert stat.S_IMODE(path.stat().st_mode) == 0o600 assert stat.S_IMODE(path.stat().st_mode) == 0o600
@ -173,6 +179,63 @@ def test_source_fragment_ids_are_dense_across_blank_lines() -> None:
assert fragments == {"S00001": "first", "S00002": "second"} assert fragments == {"S00001": "first", "S00002": "second"}
def test_source_fragment_index_trims_indentation_but_preserves_exact_offsets() -> None:
text = " indented Unicode: \u201creviewed\u201d \nnext\n"
fragments, locations = preparer.build_source_fragment_index(text)
assert fragments["S00001"] == "indented Unicode: \u201creviewed\u201d"
selected = locations["S00001"]
assert selected["line"] == 1
assert text[selected["char_start"] : selected["char_end"]] == fragments["S00001"]
def test_bundle_location_validation_rejects_ambiguous_rebound() -> None:
text = "same line\nsame line\n"
fragments, locations = preparer.build_source_fragment_index(text)
extraction = preparer.resolve_model_output(
{
"claims": [
{
"claim_key": "second_occurrence",
"type": "structural",
"text": "The second occurrence was selected.",
"quote_ref": "S00002",
"confidence": 0.5,
"tags": [],
"evidence": [{"quote_ref": "S00002", "role": "grounds"}],
}
],
"duplicates": [],
"extraction_notes": "Select the second repeated line.",
},
fragments,
locations,
)
fake_bundle = {
"quote_bindings": [
{
"kind": "claim",
"claim_key": "second_occurrence",
"quote": "same line",
"first_start": 0,
"first_end": 9,
},
{
"kind": "evidence",
"claim_key": "second_occurrence",
"evidence_role": "grounds",
"quote": "same line",
"first_start": 0,
"first_end": 9,
},
]
}
with pytest.raises(preparer.PreparationError, match="ambiguous repeated quote"):
preparer.validate_bundle_source_locations(fake_bundle, extraction["selected_source_references"])
def test_prepare_returns_no_novel_claims_without_manifest_or_stageable_packet( def test_prepare_returns_no_novel_claims_without_manifest_or_stageable_packet(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None: ) -> None:
@ -195,6 +258,13 @@ def test_binary_artifact_requires_explicit_utf8_extraction(tmp_path: Path) -> No
preparer.extract_utf8_text(artifact, None) preparer.extract_utf8_text(artifact, None)
def test_repo_native_jsonl_transcript_is_accepted_as_strict_utf8(tmp_path: Path) -> None:
artifact = tmp_path / "telegram.jsonl"
artifact.write_text('{"chat_id":1,"message_id":2,"message":"hello"}\n', encoding="utf-8")
assert preparer.extract_utf8_text(artifact, None) == artifact.read_bytes()
def test_openrouter_key_cannot_be_redirected_to_an_unapproved_endpoint(tmp_path: Path) -> None: def test_openrouter_key_cannot_be_redirected_to_an_unapproved_endpoint(tmp_path: Path) -> None:
with pytest.raises(preparer.PreparationError, match=r"must equal https://openrouter\.ai"): with pytest.raises(preparer.PreparationError, match=r"must equal https://openrouter\.ai"):
preparer.call_openrouter( preparer.call_openrouter(

View file

@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
import copy import copy
import hashlib
import json import json
import sys import sys
from pathlib import Path from pathlib import Path
@ -13,90 +14,420 @@ sys.path.insert(0, str(REPO_ROOT / "scripts"))
import run_leo_local_ingestion_proposal_canary as canary # noqa: E402 import run_leo_local_ingestion_proposal_canary as canary # noqa: E402
def _loaded() -> tuple[dict, dict, dict]: def _loaded(path: Path) -> tuple[dict, dict, dict, dict, dict]:
fixture, input_receipt = canary.load_fixture(canary.DEFAULT_FIXTURE) fixture, input_receipt = canary.load_fixture(path)
row_ids = canary.build_row_ids(input_receipt["artifact_sha256"]) row_ids = canary.build_row_ids(input_receipt, fixture)
return fixture, input_receipt, row_ids
def test_fixture_is_realistic_hash_bound_and_exactly_evidenced() -> None:
fixture, input_receipt, row_ids = _loaded()
assert fixture["extraction"]["evidence"]["body"] in fixture["source"]["body"]
assert len(input_receipt["artifact_sha256"]) == 64
assert len(input_receipt["source_content_sha256"]) == 64
assert input_receipt["artifact_sha256"] != input_receipt["source_content_sha256"]
assert len(set(row_ids.values())) == 4
def test_fixture_validation_fails_closed_when_evidence_is_not_in_source(tmp_path: Path) -> None:
fixture = json.loads(canary.DEFAULT_FIXTURE.read_text(encoding="utf-8"))
fixture["extraction"]["evidence"]["body"] = "invented evidence"
path = tmp_path / "bad-fixture.json"
path.write_text(json.dumps(fixture), encoding="utf-8")
with pytest.raises(canary.CanaryError, match="exact substring"):
canary.load_fixture(path)
def test_fixture_validation_fails_closed_when_claim_body_is_not_in_source(
tmp_path: Path,
) -> None:
fixture = json.loads(canary.DEFAULT_FIXTURE.read_text(encoding="utf-8"))
fixture["extraction"]["claim"]["body"] = "invented claim body"
path = tmp_path / "bad-claim-fixture.json"
path.write_text(json.dumps(fixture), encoding="utf-8")
with pytest.raises(canary.CanaryError, match="claim body must be an exact substring"):
canary.load_fixture(path)
def test_capture_sql_escapes_quotes_and_backslashes_from_fixture(
tmp_path: Path,
) -> None:
fixture = json.loads(canary.DEFAULT_FIXTURE.read_text(encoding="utf-8"))
fixture["source"]["title"] = "O'Brien\\review"
fixture["source"]["metadata"]["note"] = "quoted ' value \\ path"
path = tmp_path / "quoted-fixture.json"
path.write_text(json.dumps(fixture), encoding="utf-8")
loaded, input_receipt = canary.load_fixture(path)
row_ids = canary.build_row_ids(input_receipt["artifact_sha256"])
sql = canary.build_capture_sql(loaded, input_receipt, row_ids)
assert canary.ap.sql_literal(fixture["source"]["title"]) in sql
assert canary.ap.sql_literal(
json.dumps(fixture["source"]["metadata"], sort_keys=True)
) in sql
def test_parent_normalizes_to_hash_bound_pending_proposal_with_embedded_row_links() -> None:
fixture, input_receipt, row_ids = _loaded()
parent = canary.build_parent_packet(fixture, input_receipt, row_ids) parent = canary.build_parent_packet(fixture, input_receipt, row_ids)
child = canary.normalized_stage.prepare_normalized_child(parent) child = canary.normalized_stage.prepare_normalized_child(parent)
payload = child["payload"]["apply_payload"] return fixture, input_receipt, row_ids, parent, child
assert child["status"] == "pending_review"
assert child["proposal_type"] == "approve_claim"
assert len(payload["claims"]) == 1
assert len(payload["sources"]) == 2
assert len(payload["evidence"]) == 2
assert input_receipt["source_content_sha256"] in {row["hash"] for row in payload["sources"]}
excerpts = "\n".join(row["excerpt"] for row in payload["sources"])
assert input_receipt["artifact_sha256"] in excerpts
assert row_ids["source_capture_id"] in excerpts
assert row_ids["claim_extraction_id"] in excerpts
assert row_ids["evidence_extraction_id"] in excerpts
def test_capture_and_stage_sql_never_mutate_canonical_public_tables() -> None: def _copy_scenario(tmp_path: Path, scenario_path: Path) -> Path:
fixture, input_receipt, row_ids = _loaded() scenario = json.loads(scenario_path.read_text(encoding="utf-8"))
child = canary.normalized_stage.prepare_normalized_child( artifact_source = scenario_path.parent / scenario["artifact"]["path"]
canary.build_parent_packet(fixture, input_receipt, row_ids) artifact_target = tmp_path / artifact_source.name
artifact_target.write_bytes(artifact_source.read_bytes())
scenario_target = tmp_path / scenario_path.name
scenario_target.write_text(json.dumps(scenario), encoding="utf-8")
return scenario_target
def _canonical_snapshot() -> dict:
return {
"claims": [{"id": "1"}],
"sources": [{"id": "2"}],
"claim_evidence": [{"claim_id": "1"}],
"claim_edges": [{"from_claim": "1"}],
}
def _row_id_values(row_ids: dict) -> set[str]:
values: set[str] = set()
for value in row_ids.values():
if isinstance(value, dict):
values.update(_row_id_values(value))
else:
values.add(value)
return values
def _planned_uuid_values(child: dict) -> set[str]:
apply_payload = child["payload"]["apply_payload"]
values = {child["id"]}
for row in apply_payload["claims"] + apply_payload["sources"]:
values.add(row["id"])
for row in apply_payload["evidence"]:
values.update((row["claim_id"], row["source_id"]))
for row in apply_payload["edges"]:
values.update((row["from_claim"], row["to_claim"]))
return values
def _synthetic_readback(fixture: dict, input_receipt: dict, row_ids: dict, child: dict) -> dict:
claim_rows = []
evidence_rows = []
segment_by_id = {segment["id"]: segment for segment in fixture["segments"]}
for claim in fixture["extraction"]["claims"]:
claim_id = row_ids["claim_extraction_ids"][claim["claim_key"]]
claim_rows.append(
{
"id": claim_id,
"source_capture_id": row_ids["source_capture_id"],
"claim_key": claim["claim_key"],
"body": claim["body"],
"metadata": {
**claim["metadata"],
"claim_type": claim["type"],
"confidence": claim["confidence"],
"text": claim["text"],
"extractor": input_receipt["extractor"],
"replay_identity_sha256": input_receipt["replay_identity_sha256"],
},
}
) )
for index, evidence in enumerate(claim["evidence"]):
segment = segment_by_id[evidence["segment_id"]]
evidence_rows.append(
{
"id": row_ids["evidence_extraction_ids"][f"{claim['claim_key']}:{index}"],
"claim_extraction_id": claim_id,
"source_capture_id": row_ids["source_capture_id"],
"source_segment_id": segment["id"],
"source_locator": segment["locator"],
"source_json_pointer": segment["json_pointer"],
"role": evidence["role"],
"source_content_sha256": segment["content_sha256"],
"body": evidence["excerpt"],
"body_sha256": canary.sha256_bytes(evidence["excerpt"].encode()),
"metadata": {
**evidence.get("metadata", {}),
"source_text_sha256": segment["text_sha256"],
},
}
)
duplicate_rows = []
for index, duplicate in enumerate(fixture["extraction"]["duplicates"]):
duplicate_rows.append(
{
"id": row_ids["duplicate_assessment_ids"][str(index)],
"source_capture_id": row_ids["source_capture_id"],
"source_segment_id": duplicate["segment_id"],
"source_locator": duplicate["source_locator"],
"duplicate_of_claim_key": duplicate["duplicate_of_claim_key"],
"excerpt": duplicate["excerpt"],
"excerpt_sha256": canary.sha256_bytes(duplicate["excerpt"].encode()),
"reason": duplicate["reason"],
"metadata": {
"json_pointer": duplicate["source_json_pointer"],
"source_content_sha256": duplicate["source_content_sha256"],
"source_text_sha256": duplicate["source_text_sha256"],
},
}
)
conflict_rows = []
for index, conflict in enumerate(fixture["extraction"]["conflicts"]):
conflict_rows.append(
{
"id": row_ids["conflict_assessment_ids"][str(index)],
"source_capture_id": row_ids["source_capture_id"],
"from_claim_key": conflict["from_claim_key"],
"to_claim_key": conflict["to_claim_key"],
"relationship": conflict["relationship"],
"metadata": {
key: value
for key, value in conflict.items()
if key not in {"from_claim_key", "to_claim_key", "relationship"}
},
}
)
proposal = {
**child,
"reviewed_by_handle": None,
"reviewed_at": None,
"applied_by_handle": None,
"applied_at": None,
}
counts = input_receipt["counts"]
return {
"source_captures": [
{
"id": row_ids["source_capture_id"],
"source_identity": fixture["source"]["identity"],
"source_type": fixture["source"]["source_type"],
"title": fixture["source"]["title"],
"locator": fixture["source"]["locator"],
"artifact_path": input_receipt["artifact_path"],
"artifact_sha256": input_receipt["artifact_sha256"],
"content_sha256": input_receipt["source_content_sha256"],
"replay_identity_sha256": input_receipt["replay_identity_sha256"],
"metadata": {**fixture["source"]["metadata"], "extractor": input_receipt["extractor"]},
}
],
"claim_extractions": claim_rows,
"evidence_extractions": evidence_rows,
"duplicate_assessments": duplicate_rows,
"conflict_assessments": conflict_rows,
"staged_proposal": proposal,
"counts": {
"source_captures": 1,
"claim_extractions": counts["claim_candidates"],
"evidence_extractions": counts["evidence_candidates"],
"duplicate_assessments": counts["duplicate_judgments"],
"conflict_assessments": counts["conflict_relationships"],
"staged_proposals": 1,
},
}
@pytest.mark.parametrize("scenario_path", canary.DEFAULT_FIXTURES)
def test_source_artifact_is_separate_hash_bound_and_replayable(scenario_path: Path) -> None:
fixture, input_receipt, row_ids, parent, child = _loaded(scenario_path)
artifact_path = Path(input_receipt["artifact_path"])
assert input_receipt["artifact_sha256"] == hashlib.sha256(artifact_path.read_bytes()).hexdigest()
assert input_receipt["artifact_sha256"] != input_receipt["scenario_sha256"]
assert len(input_receipt["replay_identity_sha256"]) == 64
assert row_ids == canary.build_row_ids(input_receipt, fixture)
ingestion = child["payload"]["apply_payload"]["normalization_manifest"]["ingestion_manifest"]
assert ingestion["artifact_sha256"] == input_receipt["artifact_sha256"]
assert ingestion["extractor"] == input_receipt["extractor"]
assert ingestion["replay_identity_sha256"] == input_receipt["replay_identity_sha256"]
assert ingestion["row_ids"] == row_ids
assert parent["status"] == child["status"] == "pending_review"
def test_document_and_telegram_candidate_accounting_is_exact() -> None:
_doc, doc_input, _doc_ids, _doc_parent, doc_child = _loaded(canary.DEFAULT_DOCUMENT_FIXTURE)
telegram, telegram_input, _telegram_ids, _telegram_parent, telegram_child = _loaded(canary.DEFAULT_TELEGRAM_FIXTURE)
assert doc_input["counts"] == {
"source_segments": 3,
"claim_candidates": 1,
"evidence_candidates": 1,
"duplicate_judgments": 0,
"conflict_relationships": 0,
}
assert telegram_input["counts"] == {
"source_segments": 3,
"claim_candidates": 2,
"evidence_candidates": 3,
"duplicate_judgments": 1,
"conflict_relationships": 1,
}
doc_payload = doc_child["payload"]["apply_payload"]
telegram_payload = telegram_child["payload"]["apply_payload"]
assert {key: len(doc_payload[key]) for key in ("claims", "sources", "evidence", "edges")} == {
"claims": 1,
"sources": 2,
"evidence": 2,
"edges": 0,
}
assert {key: len(telegram_payload[key]) for key in ("claims", "sources", "evidence", "edges")} == {
"claims": 2,
"sources": 5,
"evidence": 5,
"edges": 1,
}
assessment = telegram_payload["normalization_manifest"]["dedupe_conflict_assessment"]
assert assessment["duplicates"] == telegram["extraction"]["duplicates"]
assert assessment["conflicts"] == telegram["extraction"]["conflicts"]
assert telegram_payload["edges"][0]["edge_type"] == "contradicts"
def test_telegram_duplicate_text_keeps_distinct_exact_message_provenance() -> None:
fixture, _input, _row_ids, _parent, _child = _loaded(canary.DEFAULT_TELEGRAM_FIXTURE)
first, _second, repeated = fixture["segments"]
assert first["body"] == repeated["body"]
assert first["text_sha256"] == repeated["text_sha256"]
assert first["content_sha256"] != repeated["content_sha256"]
assert first["locator"] == "telegram://chat/900001/message/7301"
assert repeated["locator"] == "telegram://chat/900001/message/7303"
duplicate = fixture["extraction"]["duplicates"][0]
assert duplicate["source_locator"] == repeated["locator"]
assert duplicate["source_json_pointer"] == "jsonl://line/3/message"
def test_fixture_validation_fails_closed_on_invented_evidence(tmp_path: Path) -> None:
scenario_path = _copy_scenario(tmp_path, canary.DEFAULT_TELEGRAM_FIXTURE)
scenario = json.loads(scenario_path.read_text(encoding="utf-8"))
scenario["extraction"]["claims"][0]["evidence"][0]["excerpt"] = "invented evidence"
scenario_path.write_text(json.dumps(scenario), encoding="utf-8")
with pytest.raises(canary.CanaryError, match="not an exact segment substring"):
canary.load_fixture(scenario_path)
def test_fixture_artifact_path_cannot_escape_scenario_directory(tmp_path: Path) -> None:
scenario = json.loads(canary.DEFAULT_DOCUMENT_FIXTURE.read_text(encoding="utf-8"))
scenario["artifact"]["path"] = "../outside.txt"
path = tmp_path / "scenario.json"
path.write_text(json.dumps(scenario), encoding="utf-8")
with pytest.raises(canary.CanaryError, match="remain inside"):
canary.load_fixture(path)
def test_capture_sql_escapes_quotes_and_backslashes(tmp_path: Path) -> None:
scenario_path = _copy_scenario(tmp_path, canary.DEFAULT_DOCUMENT_FIXTURE)
scenario = json.loads(scenario_path.read_text(encoding="utf-8"))
scenario["source"]["title"] = "O'Brien\\review"
scenario["source"]["metadata"]["note"] = "quoted ' value \\ path"
scenario_path.write_text(json.dumps(scenario), encoding="utf-8")
fixture, input_receipt, row_ids, _parent, _child = _loaded(scenario_path)
sql = canary.build_capture_sql(fixture, input_receipt, row_ids)
assert canary.ap.sql_literal(scenario["source"]["title"]) in sql
expected_metadata = {
**scenario["source"]["metadata"],
"extractor": input_receipt["extractor"],
}
assert canary.ap.sql_literal(json.dumps(expected_metadata, sort_keys=True)) in sql
def test_replay_identity_and_ids_change_with_extractor_version(tmp_path: Path) -> None:
scenario_path = _copy_scenario(tmp_path, canary.DEFAULT_DOCUMENT_FIXTURE)
fixture, original, original_ids, _parent, original_child = _loaded(scenario_path)
scenario = json.loads(scenario_path.read_text(encoding="utf-8"))
scenario["extractor"]["version"] = "3"
scenario_path.write_text(json.dumps(scenario), encoding="utf-8")
changed_fixture, changed, changed_ids, _changed_parent, changed_child = _loaded(scenario_path)
assert original["artifact_sha256"] == changed["artifact_sha256"]
assert original["replay_identity_sha256"] != changed["replay_identity_sha256"]
assert original_ids["source_capture_id"] != changed_ids["source_capture_id"]
assert original_ids["claim_extraction_ids"] != changed_ids["claim_extraction_ids"]
assert original_ids["parent_proposal_id"] != changed_ids["parent_proposal_id"]
assert original_child["payload_sha256"] != changed_child["payload_sha256"]
assert fixture["segments"] == changed_fixture["segments"]
@pytest.mark.parametrize(
("source_field", "replacement"),
(
("identity", "document:mutated-exact-source-identity"),
("locator", "fixture://working-leo/mutated-exact-source-locator"),
),
)
def test_replay_identity_and_every_row_id_bind_exact_source_identity(
tmp_path: Path, source_field: str, replacement: str
) -> None:
scenario_path = _copy_scenario(tmp_path, canary.DEFAULT_DOCUMENT_FIXTURE)
fixture, before, before_ids, _parent, before_child = _loaded(scenario_path)
scenario = json.loads(scenario_path.read_text(encoding="utf-8"))
scenario["source"][source_field] = replacement
scenario_path.write_text(json.dumps(scenario), encoding="utf-8")
changed_fixture, after, after_ids, _changed_parent, after_child = _loaded(scenario_path)
assert before["artifact_sha256"] == after["artifact_sha256"]
assert before["extraction_spec_sha256"] == after["extraction_spec_sha256"]
assert before["replay_identity_sha256"] != after["replay_identity_sha256"]
assert _row_id_values(before_ids).isdisjoint(_row_id_values(after_ids))
assert _planned_uuid_values(before_child).isdisjoint(_planned_uuid_values(after_child))
assert fixture["source"][source_field] != changed_fixture["source"][source_field]
@pytest.mark.parametrize(
("segment_field", "replacement"),
(
("id", "message-900001-mutated"),
("locator", "telegram://chat/900001/message/999999"),
("json_pointer", "jsonl://line/999/message"),
("content_sha256", "a" * 64),
("text_sha256", "b" * 64),
),
)
def test_replay_identity_and_every_row_id_bind_complete_normalized_segment(
segment_field: str, replacement: str
) -> None:
fixture, before, before_ids, _parent, before_child = _loaded(canary.DEFAULT_TELEGRAM_FIXTURE)
changed_fixture = copy.deepcopy(fixture)
after = copy.deepcopy(before)
segment = changed_fixture["segments"][-1]
original_id = segment["id"]
segment[segment_field] = replacement
for claim in changed_fixture["extraction"]["claims"]:
for evidence in claim["evidence"]:
if evidence["segment_id"] == original_id:
evidence["segment_id"] = segment["id"]
evidence["source_locator"] = segment["locator"]
evidence["source_json_pointer"] = segment["json_pointer"]
evidence["source_content_sha256"] = segment["content_sha256"]
evidence["source_text_sha256"] = segment["text_sha256"]
for duplicate in changed_fixture["extraction"]["duplicates"]:
if duplicate["segment_id"] == original_id:
duplicate["segment_id"] = segment["id"]
duplicate["source_locator"] = segment["locator"]
duplicate["source_json_pointer"] = segment["json_pointer"]
duplicate["source_content_sha256"] = segment["content_sha256"]
duplicate["source_text_sha256"] = segment["text_sha256"]
after["source_content_sha256"] = canary.canonical_sha256(
canary.normalized_segment_manifest(changed_fixture["segments"])
)
after["replay_identity_components"] = canary.replay_identity_payload(
artifact_sha256=after["artifact_sha256"],
artifact_format=after["artifact_format"],
source_identity=after["source_identity"],
source_locator=after["source_locator"],
normalized_segments_sha256=after["source_content_sha256"],
extractor=after["extractor"],
extraction_spec_sha256=after["extraction_spec_sha256"],
)
after["replay_identity_sha256"] = canary.canonical_sha256(after["replay_identity_components"])
after_ids = canary.build_row_ids(after, changed_fixture)
after_parent = canary.build_parent_packet(changed_fixture, after, after_ids)
after_child = canary.normalized_stage.prepare_normalized_child(after_parent)
assert before["artifact_sha256"] == after["artifact_sha256"]
assert before["scenario_sha256"] == after["scenario_sha256"]
assert before["extraction_spec_sha256"] == after["extraction_spec_sha256"]
assert before["replay_identity_sha256"] != after["replay_identity_sha256"]
assert _row_id_values(before_ids).isdisjoint(_row_id_values(after_ids))
assert _planned_uuid_values(before_child).isdisjoint(_planned_uuid_values(after_child))
def test_source_byte_tamper_changes_hashes_and_replay_ids(tmp_path: Path) -> None:
scenario_path = _copy_scenario(tmp_path, canary.DEFAULT_DOCUMENT_FIXTURE)
fixture, before, before_ids, _parent, _child = _loaded(scenario_path)
artifact_path = Path(before["artifact_path"])
artifact_path.write_text(
artifact_path.read_text(encoding="utf-8") + "\n\nA new source paragraph.", encoding="utf-8"
)
changed_fixture, after, after_ids, _changed_parent, _changed_child = _loaded(scenario_path)
assert before["artifact_sha256"] != after["artifact_sha256"]
assert before["source_content_sha256"] != after["source_content_sha256"]
assert before["replay_identity_sha256"] != after["replay_identity_sha256"]
assert before_ids["source_capture_id"] != after_ids["source_capture_id"]
assert before_ids["claim_extraction_ids"] != after_ids["claim_extraction_ids"]
assert len(changed_fixture["segments"]) == len(fixture["segments"]) + 1
def test_replay_properties_hold_across_many_version_labels(tmp_path: Path) -> None:
scenario_path = _copy_scenario(tmp_path, canary.DEFAULT_DOCUMENT_FIXTURE)
base = json.loads(scenario_path.read_text(encoding="utf-8"))
observed: set[str] = set()
for index in range(40):
scenario = copy.deepcopy(base)
scenario["extractor"]["version"] = f"property-{index}"
scenario_path.write_text(json.dumps(scenario), encoding="utf-8")
fixture_a, receipt_a = canary.load_fixture(scenario_path)
fixture_b, receipt_b = canary.load_fixture(scenario_path)
ids_a = canary.build_row_ids(receipt_a, fixture_a)
ids_b = canary.build_row_ids(receipt_b, fixture_b)
assert receipt_a == receipt_b
assert ids_a == ids_b
observed.add(receipt_a["replay_identity_sha256"])
assert len(observed) == 40
@pytest.mark.parametrize("scenario_path", canary.DEFAULT_FIXTURES)
def test_capture_and_stage_sql_do_not_mutate_canonical_tables(scenario_path: Path) -> None:
fixture, input_receipt, row_ids, parent, child = _loaded(scenario_path)
sql = "\n".join( sql = "\n".join(
( (
canary.build_schema_sql(),
canary.build_capture_sql(fixture, input_receipt, row_ids), canary.build_capture_sql(fixture, input_receipt, row_ids),
canary.normalized_stage.build_stage_sql(child), canary.normalized_stage.build_stage_sql(child),
) )
@ -106,59 +437,346 @@ def test_capture_and_stage_sql_never_mutate_canonical_public_tables() -> None:
assert "update public." not in sql assert "update public." not in sql
assert "delete from public." not in sql assert "delete from public." not in sql
assert "insert into kb_canary.source_captures" in sql assert "insert into kb_canary.source_captures" in sql
assert "insert into kb_canary.claim_extractions" in sql
assert "insert into kb_canary.evidence_extractions" in sql
assert "insert into kb_stage.kb_proposals" in sql assert "insert into kb_stage.kb_proposals" in sql
assert parent["payload"]["ingestion_manifest"]["row_ids"] == row_ids
def test_check_evaluation_requires_every_row_link_and_staging_boundary() -> None: def test_canonical_snapshot_covers_all_nonempty_canonical_tables() -> None:
fixture, input_receipt, row_ids = _loaded() schema_sql = canary.build_schema_sql().lower()
child = canary.normalized_stage.prepare_normalized_child( snapshot_sql = canary.build_canonical_snapshot_sql().lower()
canary.build_parent_packet(fixture, input_receipt, row_ids)
for table in ("claims", "sources", "claim_evidence", "claim_edges"):
assert f"insert into public.{table}" in schema_sql
assert f"from public.{table}" in snapshot_sql
assert "order by" in snapshot_sql
assert "begin transaction read only" in snapshot_sql
assert canary.canonical_snapshot_complete({}) is False
assert (
canary.canonical_snapshot_complete(
{
"claims": [{"id": "1"}],
"sources": [{"id": "2"}],
"claim_evidence": [{"claim_id": "1"}],
"claim_edges": [{"from_claim": "1"}],
}
) )
apply_payload = child["payload"]["apply_payload"] is True
readback = { )
"source_capture": {
"id": row_ids["source_capture_id"],
"artifact_sha256": input_receipt["artifact_sha256"], def test_evaluation_fails_when_exact_evidence_locator_is_changed() -> None:
"content_sha256": input_receipt["source_content_sha256"], fixture, input_receipt, row_ids, _parent, child = _loaded(canary.DEFAULT_TELEGRAM_FIXTURE)
"source_identity": input_receipt["source_identity"], readback = _synthetic_readback(fixture, input_receipt, row_ids, child)
}, canonical = {
"claim_extraction": { "claims": [{"id": "1"}],
"id": row_ids["claim_extraction_id"], "sources": [{"id": "2"}],
"source_capture_id": row_ids["source_capture_id"], "claim_evidence": [{"claim_id": "1"}],
"body": fixture["extraction"]["claim"]["body"], "claim_edges": [{"from_claim": "1"}],
"metadata": {"text": fixture["extraction"]["claim"]["text"]},
},
"evidence_extraction": {
"id": row_ids["evidence_extraction_id"],
"claim_extraction_id": row_ids["claim_extraction_id"],
"source_capture_id": row_ids["source_capture_id"],
"body": fixture["extraction"]["evidence"]["body"],
"metadata": fixture["extraction"]["evidence"]["metadata"],
},
"staged_proposal": {
"id": child["id"],
"status": "pending_review",
"source_ref": child["source_ref"],
"payload": {"apply_payload": apply_payload},
"reviewed_by_handle": None,
"reviewed_at": None,
"applied_by_handle": None,
"applied_at": None,
},
"counts": {
"source_captures": 1,
"claim_extractions": 1,
"evidence_extractions": 1,
"staged_proposals": 1,
},
} }
checks = canary.evaluate_checks(fixture, input_receipt, row_ids, readback) checks = canary.evaluate_checks(fixture, input_receipt, row_ids, readback, canonical, copy.deepcopy(canonical))
assert all(checks.values()) assert all(checks.values())
broken = copy.deepcopy(readback) broken = copy.deepcopy(readback)
broken["evidence_extraction"]["claim_extraction_id"] = canary.stable_uuid("0" * 64, "wrong") broken["evidence_extractions"][0]["source_locator"] = "telegram://chat/900001/message/9999"
assert ( assert (
canary.evaluate_checks(fixture, input_receipt, row_ids, broken)["evidence_links_to_claim_and_source"] is False canary.evaluate_checks(fixture, input_receipt, row_ids, broken, canonical, copy.deepcopy(canonical))[
"all_evidence_has_exact_source_location"
]
is False
) )
def test_evaluation_recomputes_instead_of_trusting_supplied_row_ids() -> None:
fixture, input_receipt, row_ids, _parent, _child = _loaded(canary.DEFAULT_TELEGRAM_FIXTURE)
tampered_ids = copy.deepcopy(row_ids)
tampered_ids["source_capture_id"] = "00000000-0000-4000-8000-000000009990"
tampered_parent = canary.build_parent_packet(fixture, input_receipt, tampered_ids)
tampered_child = canary.normalized_stage.prepare_normalized_child(tampered_parent)
readback = _synthetic_readback(fixture, input_receipt, tampered_ids, tampered_child)
checks = canary.evaluate_checks(
fixture, input_receipt, tampered_ids, readback, _canonical_snapshot(), _canonical_snapshot()
)
assert checks["deterministic_row_ids_recomputed_exact"] is False
assert checks["source_capture_identity_exact"] is False
assert checks["planned_proposal_identities_and_linkages_exact"] is False
def test_independent_graph_oracle_rejects_consistent_generator_edge_corruption(
monkeypatch: pytest.MonkeyPatch,
) -> None:
fixture, input_receipt = canary.load_fixture(canary.DEFAULT_TELEGRAM_FIXTURE)
row_ids = canary.build_row_ids(input_receipt, fixture)
parent = canary.build_parent_packet(fixture, input_receipt, row_ids)
original_prepare = canary.normalized_stage.prepare_normalized_child
def corrupted_prepare(parent_packet: dict) -> dict:
child = copy.deepcopy(original_prepare(parent_packet))
child["payload"]["apply_payload"]["edges"][0]["to_claim"] = "00000000-0000-4000-8000-000000009996"
return child
monkeypatch.setattr(canary.normalized_stage, "prepare_normalized_child", corrupted_prepare)
corrupted_child = corrupted_prepare(parent)
readback = _synthetic_readback(fixture, input_receipt, row_ids, corrupted_child)
checks = canary.evaluate_checks(
fixture, input_receipt, row_ids, readback, _canonical_snapshot(), _canonical_snapshot()
)
assert checks["planned_graph_matches_independent_source_oracle"] is False
assert checks["planned_proposal_identities_and_linkages_exact"] is False
assert checks["conflicts_and_relationships_persisted"] is False
@pytest.mark.parametrize(
("mutation", "failed_check"),
(
("source_id", "source_capture_identity_exact"),
("source_identity", "source_capture_identity_exact"),
("source_locator", "source_capture_identity_exact"),
("claim_id", "claim_extraction_identities_and_fks_exact"),
("claim_source_fk", "claim_extraction_identities_and_fks_exact"),
("evidence_id", "evidence_extraction_identities_and_fks_exact"),
("evidence_claim_fk", "evidence_extraction_identities_and_fks_exact"),
("evidence_source_fk", "evidence_extraction_identities_and_fks_exact"),
("evidence_segment_id", "evidence_extraction_identities_and_fks_exact"),
("evidence_json_pointer", "evidence_extraction_identities_and_fks_exact"),
("evidence_role", "evidence_extraction_identities_and_fks_exact"),
("evidence_body_sha256", "evidence_extraction_identities_and_fks_exact"),
("proposal_id", "planned_proposal_identities_and_linkages_exact"),
("planned_claim_id", "planned_proposal_identities_and_linkages_exact"),
("planned_source_id", "planned_proposal_identities_and_linkages_exact"),
("planned_evidence_claim_fk", "planned_proposal_identities_and_linkages_exact"),
("planned_evidence_source_fk", "planned_proposal_identities_and_linkages_exact"),
("planned_evidence_role", "planned_proposal_identities_and_linkages_exact"),
("manifest_row_id", "planned_proposal_identities_and_linkages_exact"),
),
)
def test_evaluation_rejects_wrong_deterministic_ids_and_every_fk_linkage(mutation: str, failed_check: str) -> None:
fixture, input_receipt, row_ids, _parent, child = _loaded(canary.DEFAULT_TELEGRAM_FIXTURE)
readback = _synthetic_readback(fixture, input_receipt, row_ids, child)
broken = copy.deepcopy(readback)
wrong_uuid = "00000000-0000-4000-8000-000000009999"
apply_payload = broken["staged_proposal"]["payload"]["apply_payload"]
if mutation == "source_id":
broken["source_captures"][0]["id"] = wrong_uuid
elif mutation == "source_identity":
broken["source_captures"][0]["source_identity"] = "fixture:wrong-source-identity"
elif mutation == "source_locator":
broken["source_captures"][0]["locator"] = "fixture://working-leo/wrong-source-locator"
elif mutation == "claim_id":
broken["claim_extractions"][0]["id"] = broken["claim_extractions"][1]["id"]
elif mutation == "claim_source_fk":
broken["claim_extractions"][0]["source_capture_id"] = wrong_uuid
elif mutation == "evidence_id":
broken["evidence_extractions"][0]["id"] = broken["evidence_extractions"][1]["id"]
elif mutation == "evidence_claim_fk":
broken["evidence_extractions"][0]["claim_extraction_id"] = broken["claim_extractions"][1]["id"]
elif mutation == "evidence_source_fk":
broken["evidence_extractions"][0]["source_capture_id"] = wrong_uuid
elif mutation == "evidence_segment_id":
broken["evidence_extractions"][0]["source_segment_id"] = "message-900001-9999"
elif mutation == "evidence_json_pointer":
broken["evidence_extractions"][0]["source_json_pointer"] = "jsonl://line/999/message"
elif mutation == "evidence_role":
broken["evidence_extractions"][0]["role"] = "supports"
elif mutation == "evidence_body_sha256":
broken["evidence_extractions"][0]["body_sha256"] = "d" * 64
elif mutation == "proposal_id":
broken["staged_proposal"]["id"] = wrong_uuid
elif mutation == "planned_claim_id":
apply_payload["claims"][0]["id"] = apply_payload["claims"][1]["id"]
elif mutation == "planned_source_id":
apply_payload["sources"][0]["id"] = apply_payload["sources"][1]["id"]
elif mutation == "planned_evidence_claim_fk":
apply_payload["evidence"][0]["claim_id"] = apply_payload["claims"][1]["id"]
elif mutation == "planned_evidence_source_fk":
apply_payload["evidence"][0]["source_id"] = apply_payload["sources"][1]["id"]
elif mutation == "planned_evidence_role":
apply_payload["evidence"][0]["role"] = "supports"
elif mutation == "manifest_row_id":
apply_payload["normalization_manifest"]["ingestion_manifest"]["row_ids"]["source_capture_id"] = wrong_uuid
checks = canary.evaluate_checks(
fixture, input_receipt, row_ids, broken, _canonical_snapshot(), _canonical_snapshot()
)
assert checks[failed_check] is False
assert not all(checks.values())
@pytest.mark.parametrize(
("surface", "field", "replacement", "failed_check"),
(
("duplicate", "id", "00000000-0000-4000-8000-000000009991", "duplicate_judgments_persisted"),
(
"duplicate",
"source_capture_id",
"00000000-0000-4000-8000-000000009992",
"duplicate_judgments_persisted",
),
("duplicate", "source_segment_id", "message-900001-9999", "duplicate_judgments_persisted"),
(
"duplicate",
"source_locator",
"telegram://chat/900001/message/9999",
"duplicate_judgments_persisted",
),
("duplicate", "duplicate_of_claim_key", "approval_alone_makes_canonical", "duplicate_judgments_persisted"),
("duplicate", "excerpt", "fabricated duplicate excerpt", "duplicate_judgments_persisted"),
("duplicate", "excerpt_sha256", "c" * 64, "duplicate_judgments_persisted"),
("duplicate", "reason", "fabricated duplicate reason", "duplicate_judgments_persisted"),
("duplicate", "metadata", {"json_pointer": "fabricated"}, "duplicate_judgments_persisted"),
("conflict", "id", "00000000-0000-4000-8000-000000009993", "conflicts_and_relationships_persisted"),
(
"conflict",
"source_capture_id",
"00000000-0000-4000-8000-000000009994",
"conflicts_and_relationships_persisted",
),
("conflict", "from_claim_key", "approval_alone_makes_canonical", "conflicts_and_relationships_persisted"),
(
"conflict",
"to_claim_key",
"pending_review_does_not_change_canonical",
"conflicts_and_relationships_persisted",
),
("conflict", "relationship", "supports", "conflicts_and_relationships_persisted"),
("conflict", "metadata", {"reason": "fabricated"}, "conflicts_and_relationships_persisted"),
("edge", "from_claim", "00000000-0000-4000-8000-000000009995", "conflicts_and_relationships_persisted"),
("edge", "to_claim", "00000000-0000-4000-8000-000000009996", "conflicts_and_relationships_persisted"),
("edge", "edge_type", "supports", "conflicts_and_relationships_persisted"),
("edge", "weight", 0.5, "conflicts_and_relationships_persisted"),
("edge", "created_by", "00000000-0000-4000-8000-000000009997", "conflicts_and_relationships_persisted"),
),
)
def test_evaluation_rejects_mutated_duplicate_conflict_and_edge_identities(
surface: str, field: str, replacement: object, failed_check: str
) -> None:
fixture, input_receipt, row_ids, _parent, child = _loaded(canary.DEFAULT_TELEGRAM_FIXTURE)
broken = _synthetic_readback(fixture, input_receipt, row_ids, child)
if surface == "duplicate":
broken["duplicate_assessments"][0][field] = replacement
elif surface == "conflict":
broken["conflict_assessments"][0][field] = replacement
else:
broken["staged_proposal"]["payload"]["apply_payload"]["edges"][0][field] = replacement
checks = canary.evaluate_checks(
fixture, input_receipt, row_ids, broken, _canonical_snapshot(), _canonical_snapshot()
)
assert checks[failed_check] is False
assert not all(checks.values())
@pytest.mark.parametrize(
("field", "replacement"),
(
("reviewed_by_handle", "reviewer"),
("reviewed_by_agent_id", "00000000-0000-4000-8000-000000009981"),
("reviewed_at", "2026-07-15T00:00:00+00:00"),
("review_note", "fabricated review note"),
("applied_by_handle", "applier"),
("applied_by_agent_id", "00000000-0000-4000-8000-000000009982"),
("applied_at", "2026-07-15T00:00:01+00:00"),
),
)
def test_evaluation_rejects_every_review_and_apply_metadata_mutation(field: str, replacement: str) -> None:
fixture, input_receipt, row_ids, _parent, child = _loaded(canary.DEFAULT_TELEGRAM_FIXTURE)
broken = _synthetic_readback(fixture, input_receipt, row_ids, child)
broken["staged_proposal"][field] = replacement
checks = canary.evaluate_checks(
fixture, input_receipt, row_ids, broken, _canonical_snapshot(), _canonical_snapshot()
)
assert checks["no_review_or_apply_metadata"] is False
assert checks["planned_proposal_identities_and_linkages_exact"] is False
def _suite_child(artifact_format: str, *, passed: bool = True, canonical_unchanged: bool = True) -> dict:
before = "a" * 64
after = before if canonical_unchanged else "b" * 64
return {
"status": "pass" if passed else "fail",
"input": {"artifact_format": artifact_format},
"canonical": {
"fingerprint_before": before,
"fingerprint_after": after,
"unchanged": canonical_unchanged,
},
"checks": {"canonical_fingerprint_unchanged": canonical_unchanged},
}
def test_single_fixture_suite_is_truthfully_partial(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
monkeypatch.setattr(canary, "run_canary", lambda _path: _suite_child("plain_text"))
suite = canary.run_suite([tmp_path / "document.scenario.json"])
assert suite["status"] == "partial"
assert suite["full_suite_passed"] is False
assert suite["coverage_status"] == "partial"
assert suite["missing_required_coverage"] == ["social_conversation"]
def test_malformed_fixture_fails_closed_with_receipt_and_without_runtime(tmp_path: Path) -> None:
malformed = tmp_path / "malformed.scenario.json"
malformed.write_text("{not-json", encoding="utf-8")
receipt = canary.run_canary(malformed)
suite = canary.run_suite([malformed])
assert receipt["status"] == "fail"
assert receipt["error"]["type"] == "CanaryError"
assert receipt["cleanup"]["runtime_not_started"] is True
assert receipt["cleanup"]["container_absent"] is True
assert suite["status"] == "fail"
assert suite["receipts"][0]["error"]["type"] == "CanaryError"
@pytest.mark.parametrize(
("children", "expected_status"),
(
(
[_suite_child("plain_text"), _suite_child("telegram_jsonl")],
"pass",
),
(
[_suite_child("plain_text", canonical_unchanged=False), _suite_child("telegram_jsonl")],
"fail",
),
(
[_suite_child("plain_text"), _suite_child("telegram_jsonl", passed=False)],
"fail",
),
),
)
def test_full_suite_status_requires_both_shapes_all_children_and_canonical_invariance(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path, children: list[dict], expected_status: str
) -> None:
queue = iter(children)
monkeypatch.setattr(canary, "run_canary", lambda _path: next(queue))
suite = canary.run_suite([tmp_path / "document.scenario.json", tmp_path / "telegram.scenario.json"])
assert suite["status"] == expected_status
assert suite["full_suite_passed"] is (expected_status == "pass")
def test_suite_recomputes_canonical_invariance_instead_of_trusting_stale_boolean(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
children = [_suite_child("plain_text"), _suite_child("telegram_jsonl")]
children[0]["canonical"]["fingerprint_after"] = "c" * 64
queue = iter(children)
monkeypatch.setattr(canary, "run_canary", lambda _path: next(queue))
suite = canary.run_suite([tmp_path / "document.scenario.json", tmp_path / "telegram.scenario.json"])
assert suite["status"] == "fail"
assert suite["canonical_fingerprint_invariant_all"] is False
assert suite["full_suite_passed"] is False
assert "canonical_fingerprint_invariance" in suite["missing_required_coverage"]

View file

@ -23,6 +23,18 @@ REVIEWER_ID = "11111111-1111-4111-8111-111111111111"
SERVICE_ID = "44444444-4444-4444-4444-444444444444" SERVICE_ID = "44444444-4444-4444-4444-444444444444"
PROPOSAL_ID = "99999999-9999-4999-8999-999999999999" PROPOSAL_ID = "99999999-9999-4999-8999-999999999999"
EDGE_ID = "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" EDGE_ID = "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee"
OTHER_AGENT_ID = "22222222-2222-4222-8222-222222222222"
REVISE_PROPOSAL_ID = "88888888-8888-4888-8888-888888888888"
PRIOR_STRATEGY_ID = "33333333-3333-4333-8333-333333333333"
PRIOR_ACTIVE_NODE_ID = "55555555-5555-4555-8555-555555555555"
PRIOR_RETIRED_NODE_ID = "66666666-6666-4666-8666-666666666666"
OTHER_STRATEGY_ID = "77777777-7777-4777-8777-777777777777"
OTHER_ACTIVE_NODE_ID = "12121212-1212-4212-8212-121212121212"
NULL_AGENT_NODE_ID = "13131313-1313-4313-8313-131313131313"
PRIOR_NODE_ANCHOR_ID = "19191919-1919-4919-8919-191919191919"
RECEIPT_STRATEGY_ID = "14141414-1414-4414-8414-141414141414"
RECEIPT_NODE_A_ID = "15151515-1515-4515-8515-151515151515"
RECEIPT_NODE_B_ID = "16161616-1616-4616-8616-161616161616"
PRIVATE_MARKER = "PRIVATE-REPLAY-MATERIAL-MUST-NOT-LEAK" PRIVATE_MARKER = "PRIVATE-REPLAY-MATERIAL-MUST-NOT-LEAK"
@ -155,6 +167,58 @@ def proposal_rows() -> tuple[dict, dict, dict]:
return approved, applied, approval return approved, applied, approval
def revise_strategy_proposal_rows() -> tuple[dict, dict, dict]:
approved, _, approval = proposal_rows()
payload = {
"apply_payload": {
"agent_id": REVIEWER_ID,
"strategy": {
"diagnosis": "Deterministic reconstruction needs exact mutation deltas.",
"guiding_policy": "Replay every guarded transition and fail closed on drift.",
"proximate_objectives": ["exact parity", "zero orphan containers"],
},
"strategy_nodes": [
{
"node_type": "policy",
"title": "Replay exactly",
"body": "Bind the guarded transition to its canonical receipt.",
"rank": 1,
},
{
"node_type": "policy",
"title": "Replay exactly",
"body": "Bind the guarded transition to its canonical receipt.",
"rank": 1,
},
],
},
"private_title": PRIVATE_MARKER,
}
approved = {
**approved,
"id": REVISE_PROPOSAL_ID,
"proposal_type": "revise_strategy",
"payload": payload,
"created_at": "2026-07-14T00:58:00+00:00",
"updated_at": "2026-07-14T01:00:00+00:00",
}
applied = {
**approved,
"status": "applied",
"applied_by_handle": "kb-apply",
"applied_by_agent_id": SERVICE_ID,
"applied_at": "2026-07-14T01:01:00+00:00",
"updated_at": "2026-07-14T01:01:00.000001+00:00",
}
approval = {
**approval,
"proposal_id": REVISE_PROPOSAL_ID,
"proposal_type": "revise_strategy",
"payload": payload,
}
return approved, applied, approval
def applied_envelope(applied: dict) -> dict: def applied_envelope(applied: dict) -> dict:
fields = ( fields = (
"id", "id",
@ -202,6 +266,73 @@ def replay_material() -> dict:
} }
def revise_strategy_replay_material(*, apply_sql_source: str = "exact_executed_sql", version: int = 2) -> dict:
approved, applied, approval = revise_strategy_proposal_rows()
proposal = applied_envelope(applied)
transaction_timestamp = "2026-07-14T01:00:30+00:00"
canonical_rows = {
"strategies": [
{
"id": RECEIPT_STRATEGY_ID,
"agent_id": REVIEWER_ID,
**proposal["payload"]["apply_payload"]["strategy"],
"version": version,
"active": True,
"created_at": transaction_timestamp,
}
],
"strategy_nodes": [
{
"id": node_id,
"agent_id": REVIEWER_ID,
**node,
"status": "active",
"horizon": None,
"measure": None,
"source_ref": None,
"metadata": {},
"created_at": transaction_timestamp,
"updated_at": transaction_timestamp,
}
for node_id, node in zip(
(RECEIPT_NODE_A_ID, RECEIPT_NODE_B_ID),
proposal["payload"]["apply_payload"]["strategy_nodes"],
strict=True,
)
],
}
apply_sql = rebuild.apply_engine.build_apply_sql(proposal, applied["applied_by_handle"])
receipt = rebuild.replay_receipt.build_replay_receipt(
proposal,
canonical_rows,
apply_sql_sha256=rebuild.replay_receipt.sha256_text(apply_sql),
apply_sql_source=apply_sql_source,
exported_at_utc="2026-07-14T01:02:00+00:00",
)
return {
"artifact": rebuild.MATERIAL_ARTIFACT,
"contract_version": rebuild.MATERIAL_CONTRACT_VERSION,
"sequence": 1,
"approved_proposal": approved,
"approval_snapshot": approval,
"applied_proposal": applied,
"replay_receipt": receipt,
}
def rehash_revise_strategy_receipt(material: dict) -> None:
prior_receipt = material["replay_receipt"]
proposal = applied_envelope(material["applied_proposal"])
apply_sql = rebuild.apply_engine.build_apply_sql(proposal, material["applied_proposal"]["applied_by_handle"])
material["replay_receipt"] = rebuild.replay_receipt.build_replay_receipt(
proposal,
prior_receipt["canonical_rows"],
apply_sql_sha256=rebuild.replay_receipt.sha256_text(apply_sql),
apply_sql_source=prior_receipt["apply_engine"]["source"],
exported_at_utc=prior_receipt["exported_at_utc"],
)
def write_bundle(tmp_path: Path, *, material: dict | None = None) -> argparse.Namespace: def write_bundle(tmp_path: Path, *, material: dict | None = None) -> argparse.Namespace:
dump = tmp_path / "genesis.dump" dump = tmp_path / "genesis.dump"
dump.write_bytes(b"PGDMPfixture") dump.write_bytes(b"PGDMPfixture")
@ -238,7 +369,7 @@ def write_bundle(tmp_path: Path, *, material: dict | None = None) -> argparse.Na
ledger=ledger_path, ledger=ledger_path,
ledger_sha256=sha256_file(ledger_path), ledger_sha256=sha256_file(ledger_path),
database="teleo", database="teleo",
image=rebuild.canonical_rebuild.DEFAULT_IMAGE, image=rebuild.DEFAULT_REBUILD_IMAGE,
container_prefix="teleo-genesis-ledger-test", container_prefix="teleo-genesis-ledger-test",
tmpfs_mb=256, tmpfs_mb=256,
startup_timeout=30.0, startup_timeout=30.0,
@ -302,18 +433,192 @@ def test_dump_hash_mismatch_fails_before_container_start(tmp_path: Path, monkeyp
assert not any(len(command) > 1 and command[1] == "run" for command in commands) assert not any(len(command) > 1 and command[1] == "run" for command in commands)
def test_revise_strategy_receipt_fails_closed_before_receipt_rows_are_used(tmp_path: Path) -> None: def test_revise_strategy_material_validates_exact_engine_and_canonicalizes_row_order(
material = replay_material() tmp_path: Path,
material["replay_receipt"]["proposal"]["proposal_type"] = "revise_strategy" ) -> None:
material["applied_proposal"]["proposal_type"] = "revise_strategy" material = revise_strategy_replay_material()
material["approved_proposal"]["proposal_type"] = "revise_strategy" material["replay_receipt"]["canonical_rows"]["strategy_nodes"].reverse()
material["approval_snapshot"]["proposal_type"] = "revise_strategy"
args = write_bundle(tmp_path, material=material) args = write_bundle(tmp_path, material=material)
with pytest.raises(rebuild.ReconstructionError, match="prior strategy") as exc_info: entry = rebuild.load_bundle(args).entries[0]
assert entry.applied_proposal["proposal_type"] == "revise_strategy"
assert entry.receipt["apply_engine"]["source"] == "exact_executed_sql"
assert entry.receipt["apply_engine"]["apply_sql_sha256"] == entry.current_apply_sql_sha256
assert entry.receipt["canonical_rows"]["strategy_nodes"] == sorted(
entry.receipt["canonical_rows"]["strategy_nodes"], key=rebuild._canonical_json
)
def test_revise_strategy_material_rejects_reconstructed_apply_engine(tmp_path: Path) -> None:
args = write_bundle(
tmp_path,
material=revise_strategy_replay_material(apply_sql_source="reconstructed_current_engine"),
)
with pytest.raises(rebuild.ReconstructionError) as exc_info:
rebuild.load_bundle(args) rebuild.load_bundle(args)
assert exc_info.value.code == "unsupported_mutating_receipt" assert exc_info.value.code == "mutating_apply_engine_mismatch"
def test_revise_strategy_rejects_fully_rehashed_transaction_before_approval(
tmp_path: Path,
) -> None:
material = revise_strategy_replay_material()
original_receipt = material["replay_receipt"]
forged_timestamp = "2026-07-13T01:00:30+00:00"
canonical_rows = copy.deepcopy(original_receipt["canonical_rows"])
canonical_rows["strategies"][0]["created_at"] = forged_timestamp
for row in canonical_rows["strategy_nodes"]:
row["created_at"] = forged_timestamp
row["updated_at"] = forged_timestamp
material["replay_receipt"]["canonical_rows"] = canonical_rows
rehash_revise_strategy_receipt(material)
args = write_bundle(tmp_path, material=material)
ledger = json.loads(args.ledger.read_text(encoding="utf-8"))
material_path = args.ledger.parent / ledger["entries"][0]["material"]
assert material["replay_receipt"]["hashes"] != original_receipt["hashes"]
assert ledger["entries"][0]["sha256"] == sha256_file(material_path)
assert (
ledger["entries"][0]["replay_material_sha256"] == material["replay_receipt"]["hashes"]["replay_material_sha256"]
)
assert args.ledger_sha256 == sha256_file(args.ledger)
with pytest.raises(rebuild.ReconstructionError) as exc_info:
rebuild.load_bundle(args)
assert exc_info.value.code == "invalid_mutating_receipt"
assert "before proposal approval" in exc_info.value.safe_message
@pytest.mark.parametrize(
("reviewed_at", "transaction_timestamp", "applied_at"),
(
(
"2026-07-14T03:00:00+02:00",
"2026-07-14T01:00:00+00:00",
"2026-07-14T01:01:00+00:00",
),
(
"2026-07-14T01:00:00+00:00",
"2026-07-14T01:01:00+00:00",
"2026-07-14T03:01:00+02:00",
),
),
)
def test_revise_strategy_accepts_timezone_aware_closed_timestamp_boundaries(
tmp_path: Path,
reviewed_at: str,
transaction_timestamp: str,
applied_at: str,
) -> None:
material = revise_strategy_replay_material()
for proposal_row in (material["approved_proposal"], material["applied_proposal"]):
proposal_row["reviewed_at"] = reviewed_at
material["approval_snapshot"]["reviewed_at"] = reviewed_at
material["applied_proposal"]["applied_at"] = applied_at
rows = material["replay_receipt"]["canonical_rows"]
rows["strategies"][0]["created_at"] = transaction_timestamp
for row in rows["strategy_nodes"]:
row["created_at"] = transaction_timestamp
row["updated_at"] = transaction_timestamp
rehash_revise_strategy_receipt(material)
entry = rebuild.load_bundle(write_bundle(tmp_path, material=material)).entries[0]
assert entry.receipt["canonical_rows"]["strategies"][0]["created_at"] == transaction_timestamp
def test_revise_strategy_rejects_reviewed_at_without_timezone(tmp_path: Path) -> None:
material = revise_strategy_replay_material()
reviewed_at = "2026-07-14T01:00:00"
for proposal_row in (material["approved_proposal"], material["applied_proposal"]):
proposal_row["reviewed_at"] = reviewed_at
material["approval_snapshot"]["reviewed_at"] = reviewed_at
rehash_revise_strategy_receipt(material)
with pytest.raises(rebuild.ReconstructionError) as exc_info:
rebuild.load_bundle(write_bundle(tmp_path, material=material))
assert exc_info.value.code == "invalid_mutating_receipt"
assert "reviewed_at must include a timezone" in exc_info.value.safe_message
@pytest.mark.parametrize(
"invalid_case",
("extra_strategy_field", "duplicate_node_id", "node_timestamp_drift", "transaction_after_apply"),
)
def test_revise_strategy_receipt_rejects_impossible_poststate(tmp_path: Path, invalid_case: str) -> None:
material = revise_strategy_replay_material()
rows = material["replay_receipt"]["canonical_rows"]
if invalid_case == "extra_strategy_field":
rows["strategies"][0]["unexpected"] = "ignored by jsonb_populate_record"
elif invalid_case == "duplicate_node_id":
rows["strategy_nodes"][1]["id"] = rows["strategy_nodes"][0]["id"]
elif invalid_case == "node_timestamp_drift":
rows["strategy_nodes"][0]["updated_at"] = "2026-07-14T01:00:31+00:00"
else:
rows["strategies"][0]["created_at"] = "2026-07-14T01:01:01+00:00"
for row in rows["strategy_nodes"]:
row["created_at"] = "2026-07-14T01:01:01+00:00"
row["updated_at"] = "2026-07-14T01:01:01+00:00"
args = write_bundle(tmp_path, material=material)
with pytest.raises(rebuild.ReconstructionError) as exc_info:
rebuild.load_bundle(args)
assert exc_info.value.code == "invalid_mutating_receipt"
def test_revise_strategy_transition_builders_preserve_historical_prestate(tmp_path: Path) -> None:
entry = rebuild.load_bundle(write_bundle(tmp_path, material=revise_strategy_replay_material())).entries[0]
prestate = {
"strategy_ids": [PRIOR_STRATEGY_ID],
"active_strategy_ids": [PRIOR_STRATEGY_ID],
"max_strategy_version": 1,
"strategy_node_ids": [PRIOR_ACTIVE_NODE_ID, PRIOR_RETIRED_NODE_ID],
"non_retired_strategy_node_ids": [PRIOR_ACTIVE_NODE_ID],
}
generated_rows = copy.deepcopy(entry.receipt["canonical_rows"])
generated_rows["strategies"][0]["id"] = "17171717-1717-4717-8717-171717171717"
generated_rows["strategies"][0]["created_at"] = "2026-07-15T01:00:30+00:00"
for index, row in enumerate(generated_rows["strategy_nodes"], start=1):
row["id"] = f"18181818-1818-4818-8818-18181818181{index}"
row["created_at"] = "2026-07-15T01:00:30+00:00"
row["updated_at"] = "2026-07-15T01:00:30+00:00"
sql = rebuild.build_revise_strategy_normalization_sql(entry, prestate, generated_rows)
assert PRIOR_ACTIVE_NODE_ID in sql
assert PRIOR_RETIRED_NODE_ID not in sql
assert PRIOR_STRATEGY_ID in sql
assert RECEIPT_STRATEGY_ID in sql
assert "updated_at = E'2026-07-14T01:00:30+00:00'::timestamptz" in sql
def test_revise_strategy_transition_builders_allow_empty_prestate(tmp_path: Path) -> None:
entry = rebuild.load_bundle(write_bundle(tmp_path, material=revise_strategy_replay_material(version=1))).entries[0]
prestate = {
"strategy_ids": [],
"active_strategy_ids": [],
"max_strategy_version": 0,
"strategy_node_ids": [],
"non_retired_strategy_node_ids": [],
}
generated_rows = copy.deepcopy(entry.receipt["canonical_rows"])
generated_rows["strategies"][0]["id"] = "17171717-1717-4717-8717-171717171717"
generated_rows["strategies"][0]["created_at"] = "2026-07-15T01:00:30+00:00"
for index, row in enumerate(generated_rows["strategy_nodes"], start=1):
row["id"] = f"18181818-1818-4818-8818-18181818181{index}"
row["created_at"] = "2026-07-15T01:00:30+00:00"
row["updated_at"] = "2026-07-15T01:00:30+00:00"
sql = rebuild.build_revise_strategy_normalization_sql(entry, prestate, generated_rows)
assert "prior active strategy transition mismatch" not in sql
assert "prior node normalization mismatch" not in sql
assert RECEIPT_STRATEGY_ID in sql
def test_legacy_freeform_receipt_fails_closed(tmp_path: Path) -> None: def test_legacy_freeform_receipt_fails_closed(tmp_path: Path) -> None:
@ -331,6 +636,17 @@ def test_legacy_freeform_receipt_fails_closed(tmp_path: Path) -> None:
assert PRIVATE_MARKER not in exc_info.value.safe_message assert PRIVATE_MARKER not in exc_info.value.safe_message
def test_unknown_proposal_operation_fails_closed_before_replay(tmp_path: Path) -> None:
material = replay_material()
material["replay_receipt"]["proposal"]["proposal_type"] = "delete_claim"
args = write_bundle(tmp_path, material=material)
with pytest.raises(rebuild.ReconstructionError) as exc_info:
rebuild.load_bundle(args)
assert exc_info.value.code == "unsupported_proposal_type"
def test_proposal_metadata_outside_apply_transition_is_rejected(tmp_path: Path) -> None: def test_proposal_metadata_outside_apply_transition_is_rejected(tmp_path: Path) -> None:
material = replay_material() material = replay_material()
material["applied_proposal"]["rationale"] = "silently changed after review" material["applied_proposal"]["rationale"] = "silently changed after review"
@ -354,6 +670,28 @@ def test_output_cannot_overwrite_a_fixed_guard_or_engine_file(tmp_path: Path) ->
assert exc_info.value.code == "unsafe_output_path" assert exc_info.value.code == "unsafe_output_path"
def test_cli_defaults_to_pinned_image_and_rejects_moving_tag(tmp_path: Path) -> None:
bundle = write_bundle(tmp_path)
argv = [
"--genesis-dump",
str(bundle.genesis_dump),
"--genesis-manifest",
str(bundle.genesis_manifest),
"--ledger",
str(bundle.ledger),
"--ledger-sha256",
bundle.ledger_sha256,
"--output",
str(tmp_path / "receipt.json"),
]
assert rebuild.parse_args(argv).image == rebuild.DEFAULT_REBUILD_IMAGE
with pytest.raises(SystemExit) as exc_info:
rebuild.parse_args([*argv, "--image", "postgres:16-alpine"])
assert exc_info.value.code == 2
def test_unknown_private_field_name_is_not_echoed_in_public_error(tmp_path: Path) -> None: def test_unknown_private_field_name_is_not_echoed_in_public_error(tmp_path: Path) -> None:
material = replay_material() material = replay_material()
material[PRIVATE_MARKER] = "private value" material[PRIVATE_MARKER] = "private value"
@ -484,17 +822,18 @@ create table public.reasoning_tools (
created_at timestamptz not null default now() created_at timestamptz not null default now()
); );
create table public.strategies ( create table public.strategies (
id uuid primary key, id uuid primary key default gen_random_uuid(),
agent_id uuid not null references public.agents(id), agent_id uuid not null references public.agents(id),
diagnosis text, diagnosis text,
guiding_policy text, guiding_policy text,
proximate_objectives jsonb, proximate_objectives jsonb,
version integer not null default 1, version integer not null default 1,
active boolean not null default true, active boolean not null default true,
created_at timestamptz not null default now() created_at timestamptz not null default now(),
unique (agent_id, version)
); );
create table public.strategy_nodes ( create table public.strategy_nodes (
id uuid primary key, id uuid primary key default gen_random_uuid(),
agent_id uuid references public.agents(id), agent_id uuid references public.agents(id),
node_type text, node_type text,
title text, title text,
@ -508,6 +847,20 @@ create table public.strategy_nodes (
created_at timestamptz not null default now(), created_at timestamptz not null default now(),
updated_at timestamptz not null default now() updated_at timestamptz not null default now()
); );
create table public.strategy_node_anchors (
id uuid primary key default gen_random_uuid(),
from_node_id uuid not null references public.strategy_nodes(id) on delete cascade,
anchor_role text not null,
to_node_id uuid references public.strategy_nodes(id) on delete cascade,
to_shared_root_id uuid,
belief_id uuid,
claim_id uuid,
source_id uuid,
weight numeric,
note text,
created_at timestamptz not null default now(),
check (num_nonnulls(to_node_id, to_shared_root_id, belief_id, claim_id, source_id) = 1)
);
create table kb_stage.kb_proposals ( create table kb_stage.kb_proposals (
id uuid primary key, id uuid primary key,
proposal_type text not null, proposal_type text not null,
@ -530,10 +883,34 @@ create table kb_stage.kb_proposals (
); );
insert into public.agents (id, handle, kind) values insert into public.agents (id, handle, kind) values
('{REVIEWER_ID}', 'm3ta', 'human'); ('{REVIEWER_ID}', 'm3ta', 'human'),
('{OTHER_AGENT_ID}', 'other-agent', 'system');
insert into public.claims (id, type, text, status, confidence, tags, created_by) values insert into public.claims (id, type, text, status, confidence, tags, created_by) values
('{CLAIM_A}', 'structural', 'Fixture claim A', 'open', 0.8, array['fixture'], '{REVIEWER_ID}'), ('{CLAIM_A}', 'structural', 'Fixture claim A', 'open', 0.8, array['fixture'], '{REVIEWER_ID}'),
('{CLAIM_B}', 'structural', 'Fixture claim B', 'open', 0.8, array['fixture'], '{REVIEWER_ID}'); ('{CLAIM_B}', 'structural', 'Fixture claim B', 'open', 0.8, array['fixture'], '{REVIEWER_ID}');
insert into public.strategies
(id, agent_id, diagnosis, guiding_policy, proximate_objectives, version, active, created_at)
values
('{PRIOR_STRATEGY_ID}', '{REVIEWER_ID}', 'Prior diagnosis', 'Prior policy', '["prior"]', 1, true,
'2026-07-01T00:00:00+00:00'),
('{OTHER_STRATEGY_ID}', '{OTHER_AGENT_ID}', 'Other diagnosis', 'Other policy', '["other"]', 1, true,
'2026-07-01T00:00:00+00:00');
insert into public.strategy_nodes
(id, agent_id, node_type, title, body, rank, status, created_at, updated_at)
values
('{PRIOR_ACTIVE_NODE_ID}', '{REVIEWER_ID}', 'policy', 'Prior active', 'Retire exactly once', 1,
'active', '2026-07-01T00:00:00+00:00', '2026-07-01T00:00:00+00:00'),
('{PRIOR_RETIRED_NODE_ID}', '{REVIEWER_ID}', 'policy', 'Prior retired', 'Leave timestamp unchanged', 2,
'retired', '2026-06-01T00:00:00+00:00', '2026-06-02T00:00:00+00:00'),
('{OTHER_ACTIVE_NODE_ID}', '{OTHER_AGENT_ID}', 'policy', 'Other active', 'Leave other agent unchanged', 1,
'active', '2026-07-01T00:00:00+00:00', '2026-07-01T00:00:00+00:00'),
('{NULL_AGENT_NODE_ID}', null, 'policy', 'Shared active', 'Leave shared node unchanged', 1,
'active', '2026-07-01T00:00:00+00:00', '2026-07-01T00:00:00+00:00');
insert into public.strategy_node_anchors
(id, from_node_id, anchor_role, to_node_id, weight, note, created_at)
values
('{PRIOR_NODE_ANCHOR_ID}', '{PRIOR_ACTIVE_NODE_ID}', 'serves', '{PRIOR_RETIRED_NODE_ID}', 1.0,
'Existing anchor must survive strategy revision replay', '2026-07-01T00:00:00+00:00');
""" """
@ -631,13 +1008,17 @@ def source_postgres() -> Iterator[tuple[str, str]]:
"run", "run",
"--rm", "--rm",
"--detach", "--detach",
"--network",
"none",
"--name", "--name",
container, container,
"--label",
f"{rebuild.canonical_rebuild.CANARY_LABEL}={container}",
"--env", "--env",
f"POSTGRES_DB={database}", f"POSTGRES_DB={database}",
"--env", "--env",
"POSTGRES_HOST_AUTH_METHOD=trust", "POSTGRES_HOST_AUTH_METHOD=trust",
rebuild.canonical_rebuild.DEFAULT_IMAGE, rebuild.DEFAULT_REBUILD_IMAGE,
], ],
text=True, text=True,
capture_output=True, capture_output=True,
@ -692,14 +1073,24 @@ def source_postgres() -> Iterator[tuple[str, str]]:
capture_output=True, capture_output=True,
check=False, check=False,
) )
inspected = subprocess.run(
["docker", "container", "inspect", container],
text=True,
capture_output=True,
check=False,
)
if inspected.returncode == 0:
pytest.fail(f"fixture PostgreSQL container was not removed: {container}")
def test_live_genesis_plus_ledger_command_rebuilds_exactly_and_proves_cleanup( def capture_source_snapshot(
source_container: str,
database: str,
tmp_path: Path, tmp_path: Path,
source_postgres: tuple[str, str], *,
) -> None: stem: str,
source_container, database = source_postgres ) -> tuple[Path, Path]:
genesis_dump = tmp_path / "genesis.dump" dump = tmp_path / f"{stem}.dump"
dump_result = subprocess.run( dump_result = subprocess.run(
[ [
"docker", "docker",
@ -711,7 +1102,7 @@ def test_live_genesis_plus_ledger_command_rebuilds_exactly_and_proves_cleanup(
"-d", "-d",
database, database,
"--format=custom", "--format=custom",
"--file=/tmp/genesis.dump", f"--file=/tmp/{stem}.dump",
], ],
text=True, text=True,
capture_output=True, capture_output=True,
@ -719,15 +1110,130 @@ def test_live_genesis_plus_ledger_command_rebuilds_exactly_and_proves_cleanup(
) )
assert dump_result.returncode == 0, dump_result.stderr assert dump_result.returncode == 0, dump_result.stderr
copy_result = subprocess.run( copy_result = subprocess.run(
["docker", "cp", f"{source_container}:/tmp/genesis.dump", str(genesis_dump)], ["docker", "cp", f"{source_container}:/tmp/{stem}.dump", str(dump)],
text=True, text=True,
capture_output=True, capture_output=True,
check=False, check=False,
) )
assert copy_result.returncode == 0, copy_result.stderr assert copy_result.returncode == 0, copy_result.stderr
manifest = tmp_path / f"{stem}-manifest.jsonl"
capture_manifest(source_container, database, manifest)
return dump, manifest
genesis_manifest = tmp_path / "genesis-manifest.jsonl"
capture_manifest(source_container, database, genesis_manifest) def seed_proposal_and_approval(
source_container: str,
database: str,
approved: dict,
approval: dict,
) -> dict:
sql = f"""begin;
set local standard_conforming_strings = on;
insert into kb_stage.kb_proposals
select seeded.* from jsonb_populate_record(
null::kb_stage.kb_proposals, {rebuild._jsonb_literal(approved)}
) seeded;
insert into kb_stage.kb_proposal_approvals
select seeded.* from jsonb_populate_record(
null::kb_stage.kb_proposal_approvals, {rebuild._jsonb_literal(approval)}
) seeded;
commit;
"""
docker_psql(source_container, database, sql)
raw = docker_psql(
source_container,
database,
rebuild.build_proposal_readback_sql(approved["id"]),
).stdout.strip()
return json.loads(raw)
def run_genesis_ledger_command(
*,
tmp_path: Path,
database: str,
genesis_dump: Path,
genesis_manifest: Path,
material_path: Path,
final_manifest: Path,
artifact_stem: str,
container_prefix: str,
run_number: int,
) -> tuple[subprocess.CompletedProcess[str], dict, Path]:
ledger = {
"artifact": rebuild.LEDGER_ARTIFACT,
"contract_version": rebuild.LEDGER_CONTRACT_VERSION,
"engine": rebuild._engine_hashes(),
"genesis": {
"dump_sha256": sha256_file(genesis_dump),
"parity_manifest_sha256": sha256_file(genesis_manifest),
},
"entries": [
{
"sequence": 1,
"material": material_path.name,
"sha256": sha256_file(material_path),
"replay_material_sha256": json.loads(material_path.read_text(encoding="utf-8"))["replay_receipt"][
"hashes"
]["replay_material_sha256"],
}
],
"final_parity": {
"manifest": final_manifest.name,
"sha256": sha256_file(final_manifest),
},
}
ledger_path = write_json(tmp_path / f"{artifact_stem}-ledger-run-{run_number}.json", ledger)
output = tmp_path / f"{artifact_stem}-reconstruction-receipt-run-{run_number}.json"
command = [
sys.executable,
str(Path(rebuild.__file__).resolve()),
"--genesis-dump",
str(genesis_dump),
"--genesis-manifest",
str(genesis_manifest),
"--ledger",
str(ledger_path),
"--ledger-sha256",
sha256_file(ledger_path),
"--database",
database,
"--container-prefix",
container_prefix,
"--tmpfs-mb",
"256",
"--max-target-query-ms",
"5000",
"--max-target-source-ratio",
"100",
"--output",
str(output),
]
completed = subprocess.run(
command,
cwd=rebuild.REPO_ROOT,
text=True,
capture_output=True,
check=False,
timeout=180,
)
assert completed.returncode == 0, completed.stderr + completed.stdout
assert output.is_file(), "rebuild command succeeded without writing its receipt"
receipt = json.loads(output.read_text(encoding="utf-8"))
return completed, receipt, output
def test_live_genesis_plus_ledger_command_rebuilds_exactly_and_proves_cleanup(
tmp_path: Path,
source_postgres: tuple[str, str],
) -> None:
source_container, database = source_postgres
genesis_dump, genesis_manifest = capture_source_snapshot(
source_container,
database,
tmp_path,
stem="insert-only-genesis",
)
material = replay_material() material = replay_material()
material_path = write_json(tmp_path / "entry-0001.json", material) material_path = write_json(tmp_path / "entry-0001.json", material)
@ -753,64 +1259,18 @@ def test_live_genesis_plus_ledger_command_rebuilds_exactly_and_proves_cleanup(
final_manifest = tmp_path / "final-manifest.jsonl" final_manifest = tmp_path / "final-manifest.jsonl"
capture_manifest(source_container, database, final_manifest) capture_manifest(source_container, database, final_manifest)
ledger = { completed, receipt, output = run_genesis_ledger_command(
"artifact": rebuild.LEDGER_ARTIFACT, tmp_path=tmp_path,
"contract_version": rebuild.LEDGER_CONTRACT_VERSION, database=database,
"engine": rebuild._engine_hashes(), genesis_dump=genesis_dump,
"genesis": { genesis_manifest=genesis_manifest,
"dump_sha256": sha256_file(genesis_dump), material_path=material_path,
"parity_manifest_sha256": sha256_file(genesis_manifest), final_manifest=final_manifest,
}, artifact_stem="insert-only",
"entries": [ container_prefix="teleo-genesis-ledger-live-test",
{ run_number=1,
"sequence": 1,
"material": material_path.name,
"sha256": sha256_file(material_path),
"replay_material_sha256": entry.replay_material_sha256,
}
],
"final_parity": {
"manifest": final_manifest.name,
"sha256": sha256_file(final_manifest),
},
}
ledger_path = write_json(tmp_path / "ledger.json", ledger)
output = tmp_path / "reconstruction-receipt.json"
command = [
sys.executable,
str(Path(rebuild.__file__).resolve()),
"--genesis-dump",
str(genesis_dump),
"--genesis-manifest",
str(genesis_manifest),
"--ledger",
str(ledger_path),
"--ledger-sha256",
sha256_file(ledger_path),
"--database",
database,
"--container-prefix",
"teleo-genesis-ledger-live-test",
"--tmpfs-mb",
"256",
"--max-target-query-ms",
"5000",
"--max-target-source-ratio",
"100",
"--output",
str(output),
]
completed = subprocess.run(
command,
cwd=rebuild.REPO_ROOT,
text=True,
capture_output=True,
check=False,
timeout=180,
) )
assert completed.returncode == 0, completed.stderr + completed.stdout
receipt = json.loads(output.read_text(encoding="utf-8"))
assert receipt["status"] == "pass" assert receipt["status"] == "pass"
assert receipt["genesis_parity"]["status"] == "pass" assert receipt["genesis_parity"]["status"] == "pass"
assert receipt["ledger"]["entries"][0]["status"] == "pass" assert receipt["ledger"]["entries"][0]["status"] == "pass"
@ -831,3 +1291,131 @@ def test_live_genesis_plus_ledger_command_rebuilds_exactly_and_proves_cleanup(
check=False, check=False,
) )
assert inspect.returncode != 0 assert inspect.returncode != 0
def test_live_revise_strategy_rebuild_is_exact_repeatable_and_leaves_no_container(
tmp_path: Path,
source_postgres: tuple[str, str],
) -> None:
source_container, database = source_postgres
genesis_dump, genesis_manifest = capture_source_snapshot(
source_container,
database,
tmp_path,
stem="revise-strategy-genesis",
)
approved, _, approval = revise_strategy_proposal_rows()
pre_apply = seed_proposal_and_approval(
source_container,
database,
approved,
approval,
)
apply_sql = rebuild.apply_engine.build_apply_sql(pre_apply["proposal"], "kb-apply")
docker_psql(source_container, database, apply_sql, role="kb_apply")
post_apply = json.loads(
docker_psql(
source_container,
database,
rebuild.build_proposal_readback_sql(REVISE_PROPOSAL_ID),
).stdout.strip()
)
applied_proposal = post_apply["proposal"]
proposal_envelope = applied_envelope(applied_proposal)
source_receipt_path, receipt = rebuild.apply_engine.capture_replay_receipt(
argparse.Namespace(
container=source_container,
role="kb_apply",
host="127.0.0.1",
db=database,
receipt_out=str(tmp_path / "source-revise-strategy-private-receipt.json"),
receipt_dir=None,
),
proposal_envelope,
"",
apply_sql=apply_sql,
)
assert source_receipt_path.is_file()
assert stat.S_IMODE(source_receipt_path.stat().st_mode) == 0o600
material = {
"artifact": rebuild.MATERIAL_ARTIFACT,
"contract_version": rebuild.MATERIAL_CONTRACT_VERSION,
"sequence": 1,
"approved_proposal": pre_apply["proposal"],
"approval_snapshot": pre_apply["approval_snapshot"],
"applied_proposal": applied_proposal,
"replay_receipt": receipt,
}
material_path = write_json(tmp_path / "revise-strategy-entry-0001.json", material)
final_manifest = tmp_path / "revise-strategy-final-manifest.jsonl"
capture_manifest(source_container, database, final_manifest)
runs = [
run_genesis_ledger_command(
tmp_path=tmp_path,
database=database,
genesis_dump=genesis_dump,
genesis_manifest=genesis_manifest,
material_path=material_path,
final_manifest=final_manifest,
artifact_stem="revise-strategy",
container_prefix="teleo-genesis-ledger-revise",
run_number=run_number,
)
for run_number in (1, 2)
]
for completed, reconstruction, output in runs:
assert reconstruction["status"] == "pass"
assert reconstruction["genesis_parity"]["status"] == "pass"
assert reconstruction["final_parity"]["status"] == "pass"
entry_summary = reconstruction["ledger"]["entries"][0]
assert entry_summary["proposal_type"] == "revise_strategy"
assert entry_summary["proposal_seed_exact"] is True
assert entry_summary["canonical_seed_exact"] is False
assert entry_summary["seed_exact"] is False
assert entry_summary["guarded_apply_executed"] is True
assert entry_summary["mutating_prestate_captured"] is True
assert entry_summary["mutating_delta_validated"] is True
assert entry_summary["mutating_poststate_normalized"] is True
assert entry_summary["proposal_exact"] is True
assert entry_summary["canonical_rows_exact"] is True
assert reconstruction["cleanup"]["container_absent"] is True
assert reconstruction["safety"]["network_access_available_to_container"] is False
assert reconstruction["safety"]["private_replay_material_emitted"] is False
assert PRIVATE_MARKER not in completed.stdout
assert PRIVATE_MARKER not in output.read_text(encoding="utf-8")
assert stat.S_IMODE(output.stat().st_mode) == 0o600
container_name = reconstruction["container"]["name"]
inspect = subprocess.run(
["docker", "container", "inspect", container_name],
text=True,
capture_output=True,
check=False,
)
assert inspect.returncode != 0
labeled = subprocess.run(
[
"docker",
"ps",
"-aq",
"--filter",
f"label={rebuild.canonical_rebuild.CANARY_LABEL}={container_name}",
],
text=True,
capture_output=True,
check=False,
)
assert labeled.returncode == 0
assert labeled.stdout.strip() == ""
first = runs[0][1]
second = runs[1][1]
assert first["inputs"] == second["inputs"]
assert first["ledger"]["entries"][0]["material_sha256"] == second["ledger"]["entries"][0]["material_sha256"]
assert (
first["ledger"]["entries"][0]["replay_material_sha256"]
== second["ledger"]["entries"][0]["replay_material_sha256"]
)

View file

@ -116,6 +116,37 @@ def test_invalid_source_hash_refuses_to_prepare_a_child() -> None:
stage.prepare_normalized_child(parent) stage.prepare_normalized_child(parent)
def test_prepare_normalized_child_preserves_replayable_ingestion_manifest() -> None:
parent = _parent()
parent["payload"]["ingestion_manifest"] = {
"artifact_sha256": "a" * 64,
"extractor": {"name": "deterministic_fixture_replay", "version": "2"},
"replay_identity_sha256": "b" * 64,
"segments": [
{
"id": "message-1",
"locator": "telegram://chat/1/message/1",
"content_sha256": "c" * 64,
}
],
}
child = stage.prepare_normalized_child(parent)
assert (
child["payload"]["apply_payload"]["normalization_manifest"]["ingestion_manifest"]
== parent["payload"]["ingestion_manifest"]
)
def test_prepare_normalized_child_rejects_non_object_ingestion_manifest() -> None:
parent = _parent()
parent["payload"]["ingestion_manifest"] = "not-an-object"
with pytest.raises(stage.bound.CheckpointError, match="ingestion_manifest must be an object"):
stage.prepare_normalized_child(parent)
def test_stage_sql_validates_exact_pending_row_before_commit_and_never_writes_public() -> None: def test_stage_sql_validates_exact_pending_row_before_commit_and_never_writes_public() -> None:
child = stage.prepare_normalized_child(_parent()) child = stage.prepare_normalized_child(_parent())
sql = stage.build_stage_sql(child) sql = stage.build_stage_sql(child)