Repository navigation
contacts batch: no infrastructure as contacts (#775), code contacts complete on their own (#777), plain refusals + pending logged as pending (#776, #780), scorer skips its own agent (#781), history-vs-tracked citations (#782), real-wire e2e (#777/#778/#779) - #785
Merged
Merged
Conversation
… as contacts (#775) Sharing traces with a canonical emits a consent:replication grant under the default prefixes, which include chat:, so every node that shares traces listed the canonical as a person (Eric's and Francesco's installs, 2026-10-16); a grant naming the owner's own client key or second node listed the owner as their own contact. list_contacts now skips a subject that is a canonical server (persist's is_canonical, or a directory row naming the canonical role) and a subject that resolves to the owner's fed-ID; the skip is logged at DEBUG. E2E: tests/contacts_chat.rs::a_node_that_consents_to_send_traces_lists_no_ infrastructure_and_no_self_as_contacts — default-prefix grants to the baked canonical and to the owner's identity list ZERO contacts; a person added beside them is listed alone. Proven red with the skips disabled. contacts_chat 36/36. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
… 'auth refused' (#780) refuse/refuse_with logged every answer as 'auth refused: …' at INFO, including the typed NOT-YET 202s (contacts.awaiting_key_body, awaiting_consent, unreachable); Eric and the agent session read the pending contact as a failure. Now the line says pending / refused / unavailable with the status, and a 5xx logs at WARN. Unit-tested classifier. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
…; refusal operator detail moves to the log (#776, server half) #777 — POST /v1/contacts with a code whose key body this node lacks answered 202 contacts.awaiting_key_body with converges_on_its_own: true, yet nothing ever finished the contact: the person had to paste the code again. The add path is now add_contact_for_owner (the handler authorizes, then calls it), and pending_contacts holds the owner's intent (pasted code, owner authorization of that request) and re-runs the SAME path every 10 s once the key is in the directory: a match completes (grant emitted, chat opens), a refusal discards with the reason logged, 24 h expiry. In memory: a restart drops pending entries and the person can paste again. The e2e (two nodes, real wire) is the native harness scenario that follows. #776 — contact_stall_refusal now logs the operator detail (rungs, announce, admission, directory convergence) under the reason_id and answers the person in plain language where the server's text is what they see. The text a person actually reads comes from the CLIENT bundle by reason_id (Eric's 'Admit the key first (peering)… bookmark' is CIRISClient's en.json for contacts.unknown_fed_id), and the localization guard pins the server's fallback to that bundle for the literal ids, so those stay byte-identical until CIRISClient ships the rewrite (CIRISClient#188). Test: refusal_copy_tests::contact_refusals_speak_plainly_to_ people over every LadderStall. contacts_chat 36/36; localization guard passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
…ey/due types Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
…re the work, counted, named (#781) On an agent-hosted node the engine signs as the actor, so the hosted agent's traces carry a key this process wields. The scorer computed the score and only then hit CapacityAttestation::new's self-attestation guard, so every pass on Eric's desktop ended in 'capacity attestation violates CEG §7.5 anti-Goodhart'. Now an agent whose key is the attester or this process's actor identity is skipped BEFORE scoring (DEBUG line naming the rule anti_goodhart_self), counted as self_agents in every pass summary, and accounts for a zero pass instead of raising 'the agents do not account for it'. Test: capacity_scorer::the_agent_this_node_hosts_is_skipped_by_rule_not_erred — attester = the hosted agent's key: Ok(0), the guard is never reached, the rule is named, no zero-pass alarm. Proven red with the skip disabled. capacity_scorer 5/5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
… still tracked (#782) Eric and the agent session read steady-state warnings that cite issue numbers as live bugs; every one quoted had closed months earlier. In this crate's tracing::warn!/error! messages an issue citation now reads 'history: X#N' (closed — why the gate exists) or 'tracked: X#N' (open — work still owed): 45 distinct citations across 29 files, six of them tracked (CIRISServer#372, #601, #602, #630, #678, CIRISNodeCore#38). Gate (offline): tests/log_citations.rs fails on any bare citation in a warn!/error! string. State check (network, run before a cut): tools/check_log_citations.py — tracked must be OPEN, history CLOSED/MERGED; 45 checked, 0 mismatched. lib 632/632. The lines Eric actually saw repeating (item-2 drops, unattributed frames, CRPL source_key_id=None, no-route) are emitted by CIRISEdge — filed there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
…778), add by code before the key is held completes on its own (#777), on the real wire Native-harness scenario modelling production: each person's node joins the mesh the way an agent does (consent to replicate to the canonical — without it the first run reproduced Eric's symptom exactly: the key never reached the canonical, 'receive-axis pull found NO PEERS'). #778: an unknown fed ID is a 404 contacts.unknown_fed_id; after bob announces, the SAME add succeeds (150 s on this box), bob is listed, POST /v1/chat opens. #777: alice pastes carol's v3 code before holding carol's key → 202 contacts.awaiting_key_body → with no second paste carol is listed ~30 s later and the chat opens. PASS. Proven red with the pending completer disabled: the chat answers 403 chat.not_a_contact — Eric's symptom. python -m harness.native contact_edges --binary target/debug/ciris-server --owner-wait 240 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
… rows at the canonical with no replication storm (#779 guard) Canonical + one laptop-class node claimed, announced and joined to the mesh as an agent joins (consent to the canonical). Asserts the canonical holds the owner's key and owner-signed rows within the window, and counts the storm signatures from Eric's 0.5.223 log (item-2 drops, source_key_id=None CRPL drops, round timeouts, occurrence refusals — raw lines plus log_dedup-folded repeats) against ceilings. Measured: PASS on main (owner rows in 52 s; 3/5/3/0) AND on a v0.5.223 test-anchor build (12 s; 3/4/3/0) — a clean fresh claim does not reproduce Eric's storm, which traces to his stranded owner key (#783: never Rooted). Kept as a guard; the regression for the real chain rides #784. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…CC#46)'; its source-scan test keys on that stable phrase — ubuntu CI red on #785 The citation pass rewrote 'WITHOUT the CC#46 analyze grant' to 'WITHOUT the history: CC#46 analyze grant' — awkward mid-sentence, and fold_consent_surface::declining_to_be_scored_states_what_it_costs located the WARN by the old phrase. The citation moves to a parenthetical and the test finds 'WITHOUT the `analyze` grant'. fold_consent_surface 9/9, log_citations 1/1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
… shape both localization scrapers read — ubuntu CI red on #785 localization_gate::rust_and_python_resolvers_agree_on_the_bundle: Rust saw 498 server ids, Python 499. The Rust scraper reads emitter-call argument positions and missed contacts.awaiting_key_body because a comment sat between the id and its message; the two key_pull_unavailable sites passed a block expression as the message, which hid their text from the server-id-text check. Comments move above the call, the operator detail is logged before refuse(), and the fallback text is the client bundle's verbatim (the rewrite is CIRISClient#188). localization_gate 9/9, guard --strict clean, contacts_chat 36/36. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
emooreatx
added a commit
that referenced
this pull request
Oct 16, 2026
…784), the contacts batch (#785) Cargo.toml names the next tag (v0.5.227 is on 21869a6); the evidence rows follow it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
…5-782 # Conflicts: # harness/native/scenarios.py
…ain red on log_citations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
…e warnings cite it as tracked Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb
emooreatx
added a commit
that referenced
this pull request
Oct 16, 2026
…to peer (#177) (#786) * formal: AddDevice.tla — the add-device flow (device-join on the first-contact plane) model-checked with TLC Models a new device B joining as an occurrence of its owner's identity through the owner's existing device A, peer to peer on edge's first-contact opaque plane (CIRISEdge#683, kind 0x0000_0002), against an adversary with unlimited fresh keys that sees every request and injects any answer but cannot forge signatures. Five configurations: safety (8 invariants, 211,849 states, no error), careless owner (Inv_NoAttackerOwned violated — the receiver-derived matching code is load-bearing), liveness (holds), sybil flood without fair admission (liveness violated — availability-only residual), sybil with fair eviction (holds). Found: an answered request must free its pending slot, or a denied flood starves B. README records verdicts and the implementation requirements. For CIRISConstitution review (Eric's ask, 2026-10-16). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb * formal/add_device README: what the model proves (Careful is an oracle, the code's load is the normative receiver derivation), owner presence named as the liveness assumption, a closed window refuses with no answer (CC review) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb * add a device: a new device joins its owner's identity peer to peer, the owner consents on the existing device (CIRISServer#177) The first-run wizard's "Add device" on B takes the person's fedID (QR, long form or short form) and sends a device-join request over edge's first-contact opaque plane (CIRISEdge#683, kind 0x0000_0002), signed by B's node key. A holds it only while the owner has opened "Add a device"; both screens show a matching code A derives from (B's key, challenge). On approve, the owner pen on A signs owner -> B and B's occurrence (persist's content-only form), records both and re-wraps the self DEKs to B. B applies the binding through its own /v1/setup/root (its claim PIN still proves local presence) and stores the occurrence. B mints its own keys; no key material crosses. - FSD/ADD_DEVICE.md: flow, N1-N6, surfaces, refusal ids. - src/add_device.rs: wire types, A's answerer and owner routes, B's setup routes and poll; per-sender, ceiling and closed-window refusals; a decided request frees its slot at once (TLC finding, formal/add_device). - compose: edge gets the federation directory. First contact was dead in the server without it. - owner capsule: an active occurrence of the owner opens it, so B's self room and owner flows work on the occurrence key. - B's device keys use the default device custody (ML-DSA half sealed), so its pen opens through the normal signer path. - harness: `python -m harness.native add_device` passes end to end: closed window refused, two requesters with distinct codes, approve B, B applied and in session, occurrence on both nodes, A's self file opens on B, the stranger denied. - the eleven add_device.* ids are queued for the client bundle; ratchet 19 -> 30. approve is named in SESSION_CLAIMS §2.3 as a re-wrap caller. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb * 0.5.228 opens: add a device, the key that stays where it was sealed (#784), the contacts batch (#785) Cargo.toml names the next tag (v0.5.227 is on 21869a6); the evidence rows follow it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb * one_author_per_row: the add-device occurrence is a verify-produced signed occurrence at millisecond precision, like compose's Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The server half of Eric's contacts report (2026-10-16). Each fix has a test that fails without it.
list_contactsskips canonical servers and the owner's own devices. The traces consent coverschat:by default, so it listed the canonical as a person.contacts_chat::a_node_that_consents_to_send_traces_lists_no_infrastructure_and_no_self_as_contacts; red with the skip disabledawaiting_key_bodycompletes on its own when the key arrives: the same add path re-runs (pending_contacts, 10 s pass, 24 h TTL).contact_edges: 202, then listed about 30 s later with no second paste, then the chat opens; red with the completer off, showing Eric's 403not_a_contactcontact_edges: 404unknown_fed_id, then announce, then the same add succeeds in about 150 s and the chat opensen.json), and the localization guard pins the server's fallback to it, so the rewrite is proposed on CIRISClient#188.refusal_copy_tests::contact_refusals_speak_plainly_to_people; localization guard passespending, 4xxrefused, 5xxunavailable(WARN).answer_class_testscapacity_scorer::the_agent_this_node_hosts_is_skipped_by_rule_not_erred; red with the skip disabledhistory: X#Nortracked: X#N.tests/log_citations.rs(offline gate);tools/check_log_citations.py(state check: 45 checked, 0 mismatched). Edge half: CIRISEdge#875fresh_claimguardLocal: contacts_chat 36/36, capacity_scorer 5/5, lib 632/632, localization guard green. The key fix that likely drives most of Eric's report is #784, which merges first.
🤖 Generated with Claude Code
https://claude.ai/code/session_01WW3mUN8f2rUCYJVmyLwHGb