Skip to content

Organic-invocation E2E v1.1: protocol, pilot spec and the promptfoo-driven harness (run of record smoke-20261006c) - #786

Closed
seathatflowsinourveins wants to merge 42 commits into
mainfrom
claude/ns2604-organic-harness-20261005
Closed

seathatflowsinourveins wants to merge 42 commits into
mainfrom
claude/ns2604-organic-harness-20261005

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes:
    • It adds the organic-invocation E2E protocol v1.1 (kept verbatim) and its pilot spec as evidence artifacts in evidence/artifacts/organic-e2e-20261005/.
    • It adds the command center's dated v1.1 decisions, AMENDMENT-v1.1-20261006.md.
    • It adds the promptfoo-driven harness that runs and grades the protocol (17 files under harness/, with isolation.py, netfilter.py and the focused test module), changed to follow those decisions.
    • It registers the 20 files in manifests/evidence.json.
    • It installs nothing, changes no host or client configuration and runs nothing on merge. An operator starts the harness by hand from a clean login shell (PILOT-SPEC-v1.1.md).
  • Base commit: c1300c15b42f1a6643f3dc4172f40c01d99abdcd (origin/main after fix: relock production dependencies and preserve captured evidence #765).
    • The 27 harness commits were built on 9e955327 and rebased without conflict.
    • git range-diff 9e955327..9835f66c c1300c15..31ff1227 shows all 27 patches identical (=).
    • These follow, in order:
      • the decisions commit 2da785c2;
      • the confirmations commit 4d490a86;
      • e55864b5, the fixes for the GPT read of 5aa2bfd;
      • b8c0699c, round 3 (the GPT micro-check of 87f9f1d and the CC's 12:30Z rulings, with two review passes folded in; it replaces 8594ec2b, 1c04fc79 and d0e5350a);
      • 10aa02c0, round 4: the structural G13 (CC item task-ns2604-coop-20261006T132948Z) and the P3 of the GPT micro-check of 1f81d64;
      • 5a9a4cdb, round 5: the CC's 14:38Z and 14:42Z items and the accepted parts of the GPT read of 2044b2a (CC item task-ns2604-coop-20261006T151719Z, C1);
      • 8f09f230, round 5's P2-2 (host execution brokers), upheld at 15:17Z and kept as a commit of its own;
      • 4a34ffba, round 6: the Gate 0 cache amendment and a network namespace per trial (CC items task-ns2604-coop-20261006T155742Z and ...164313Z), with the GPT read of a513616 folded in;
      • 4bd4b725, round 6's answer-channel closure, a separate commit the CC can drop;
      • bdd8dea9, round 6b: forwards for the tools under test, NOT-TESTABLE cells and the call-id calibration cell (CC item task-ns2604-coop-20261006T170607Z);
      • c00d39d4, round 6c: the GPT read of 80be148 (G11 requires every required call; SocratiCode's closure confirmed);
      • 72b98b09, round 6d: the GPT read of 50752dd (the Qdrant operation allowlist and body selectors, the own-name listing, the strict call-id key, the calibration cell first);
      • 1416d046, round 6e: the GPT read of b2d44f7 (every admitted model call counted, so one without a request id fails G11 and the calibration; the calibration first on the retry path too);
      • 7ade6c2f, round 6e's listing-compression fix, a separate commit the CC can drop;
      • the registry commit 2fb12a99, last (docs/lanes.md hot-file protocol). It replaces b2d44f73.
    • origin/main has since moved to 0d5e6506. Its 1fa86506, 9f3af37d, b0df1fb0 and 0d5e6506 also change manifests/evidence.json, so before merge the registry commit needs the same re-take on the new main.
  • Lane: lane:foundation
  • Owned paths touched:
    • evidence/artifacts/organic-e2e-20261005/**: 20 new files;
    • manifests/evidence.json: 20 new files[] entries, in the last commit only.

SOTA sources

Each source is cited as PROTOCOL-v1.1.md §3 and §7 cite it. Where the run of record's run.json recorded a different binary, both are given.

  • promptfoo 0.123.1, the runner (AGENTS.md names promptfoo for LLM A/B):
    • https://github.com/promptfoo/promptfoo, tag 0.123.1 (34f74d34e140b5e17d23770dfb2340057b1936b8), the manifests/stack.json pin.
    • One promptfoo eval per cell, with --repeat, -j and --no-cache.
    • The cells use the exec: provider ScriptCompletionProvider (installed dist/src/providers-BUaNtf-O.js:19297-19358), with retries off through provider.config.maxRetries: 0 (shared-CzEItb8B.js:308-313, :331-340, :939-955).
    • The app-server cell uses the openai:codex-app-server provider (codex-app-server-B9-ncut6.js).
  • Claude Code stream-json and transcripts: https://github.com/anthropics/claude-code.
    • The protocol reads the flags from claude --help on 2.1.289: --session-id, --include-hook-events, --settings, --setting-sources.
    • The run of record ran 2.1.291 (release v2.1.291).
    • The primary signal is the stream-json tool_use/tool_result pair (§7). Subagent and Workflow calls come from the child transcripts, because on 2.1.290 and 2.1.291 those turns never carried parent_tool_use_id in the stream.
    • The decisions commit also reads, from the same stream:
      • the rate_limit_event status (allowed, allowed_warning, rejected) and its windows' resetsAt;
      • the background-task system events;
      • the main thread's final assistant text (stop_reason is unset on 2.1.291 stream-json assistant events).
  • Codex exec JSONL and rollouts: https://github.com/openai/codex, tag rust-v0.160.0 (the manifests/stack.json pin; sources as cited in v1).
    • The SDK cells use @openai/codex-sdk 0.160.0 (index.d.ts:219-240, :247-258), and the per-trial rules are checked with codex execpolicy check.
    • The join is thread id = rollout session_meta id = Loki conversation.id.
    • The rollout's world_state skills catalog is the session's own skill listing for decision 2.
    • The run of record's CLI was codex-cli 0.160.1 (tag rust-v0.160.1), with SDK 0.160.0.
  • claude-agent-sdk 0.2.163 (Python), for CL6: https://github.com/anthropics/claude-agent-sdk-python, tag v0.2.163 (types.py options; subprocess_cli.py:655-778).
  • Loki and OTel: Grafana Loki 3.7.8 (https://github.com/grafana/loki, v3.7.8) behind opentelemetry-collector-contrib 0.161.0 (https://github.com/open-telemetry/opentelemetry-collector-contrib, v0.161.0).
  • skill_usage, for the rollout lanes: this repository's tools/skill-usage/skill_usage.py --lanes --codex-root --since --until --json --call-ledger (tools/skill-usage/README.md:152-208). The shell-text rules come from executed_text (:202-208).
  • agentsview 0.43.0: https://github.com/kenn-io/agentsview, tag v0.43.0. The harness runs export sessions --agent --active-since --include-automated --include-one-shot --include-children --json and session tool-calls <id> --json (§7).
  • Gateway call logs (OmniRoute): GET /api/usage/call-logs and /api/usage/call-logs/<id>, as the protocol cites them (docs/harness-defaults.md:180). Decision 8 keeps only pipelinePayloads.providerRequest effort fields from them.
  • Native surfaces for decision 2:
  • bubblewrap 0.11.1, the structural G13's wrapper: https://github.com/containers/bubblewrap, tag v0.11.1, installed as Ubuntu bubblewrap 0.11.1-1ubuntu0.3 (/usr/bin/bwrap, unprivileged).
    • Options relied on, as the installed bwrap --help describes them: --args, --ro-bind, --bind, --bind-try, --dev-bind, --tmpfs, --perms (round 5), --proc, --unshare-pid, --unshare-ipc (round 5), --die-with-parent, --chdir, --info-fd.
    • The --info-fd record names ipc-namespace when bwrap makes one (observed on 0.11.1).
  • ai-memory 2.5.2 (round 5, per-trial scope): https://github.com/akitaonrails/ai-memory, tag v2.5.2.
    • docs/marker-file.md: one .ai-memory.toml marker carries the scope for the lifecycle hooks (they walk up from the cwd) and for static MCP clients (workspace and project on every project-scoped call).
    • The installed ai-memory hook --help has no scope flag. hook --check-capture reports the marker without contacting the server.
  • OmniRoute v3.8.51 (round 5, the gateway's cache, logs and Codex tier): https://github.com/diegosouzapw/OmniRoute, tag v3.8.51:
    • src/lib/semanticCache.ts: isCacheableForRead and isCacheableForWrite require an explicit temperature: 0;
    • open-sse/handlers/chatCore/semanticCache.ts: the cache check, and cacheSource: "semantic" on a hit;
    • src/lib/idempotencyLayer.ts: keyed by the Idempotency-Key or X-Request-Id header;
    • src/lib/providers/codexFastTier.ts and open-sse/handlers/chatCore/serviceTier.ts: the request's tier first, then the global Codex mode, then the connection default;
    • src/app/api/usage/call-logs/route.ts: the call-log API.
  • The repository's command guard: scripts/hooks/secret_path_guard.py, K4_GW_ROWS. These are the gateway routes an agent command may read; the harness reads only GET /api/cache and the call logs.
  • Codex rust-v0.160.0 (round 5):
    • codex-rs/protocol/src/openai_models.rs, service_tier_for_request (lines 1004 to 1009), with its test service_tier_for_request_omits_explicit_default_tier. An explicit default tier is left out of the request.
    • codex-rs/protocol/src/config_types.rs:537: SERVICE_TIER_DEFAULT_REQUEST_VALUE is "default".
    • codex-rs/codex-api/src/common.rs, ResponsesApiRequest (lines 279 to 304): no temperature field.
  • anthropics/sandbox-runtime v0.0.78, README.md: the reference pattern for the network-namespace closure this round proposes to the CC. It is cited, not adopted.
    • Line 108: on Linux, bubblewrap with network namespace isolation.
    • Line 124: the network namespace is removed, and traffic goes through proxies on the host over Unix sockets bound into the sandbox.
    • Line 365: an allowlist entry may be an IP literal.
    • Line 553: socat bridges the proxies.
  • systemd 259 and polkit (round 5, P2-2):
    • systemd-run(1): the manager runs the command, and --pipe returns its streams.
    • /usr/share/polkit-1/actions/org.freedesktop.systemd1.policy: manage-units is auth_admin (auth_admin_keep when active), so the system manager is no broker for a trial.
  • setns(2) and proc(5) (round 5): joining a mount namespace needs CAP_SYS_ADMIN in its owning user namespace. /proc/<pid>/stat field 22 is the start time the CL7b census compares.
    • The R2a replay's isolation (readiness-20261005/jobs/R2a-e2-replay-20261006, outside the repository) is the pattern: bwrap --unshare-all --die-with-parent --new-session --clearenv --ro-bind /usr .... The trial wrapper keeps its read-only runtime and leaves out what a client cannot run without: the network, the environment and the home.
  • systemd 259 (systemctl --version: 259.5-0ubuntu3.4), systemd.exec(5) InaccessiblePaths=: the item's fallback in a transient user unit. It is not used, because bwrap hosts every launch path.
  • Linux man-pages:
    • mount_namespaces(7), installed: a namespace below the trial's gets its mounts locked, so a nested sandbox cannot unmount a hidden tmpfs;
    • fanotify_init(2) (man7.org): an unprivileged listener may mark only inodes and gets no event pid, so the optional pid-filtered audit needs root.
  • Method sources kept from v1:
  • Round 6 sources:
    • anthropics/sandbox-runtime v0.0.78, README.md: the pattern the network namespace follows, adopted as glue only where it lacks a path filter.
      • Lines 108 and 124: bubblewrap with the sandboxed process's network namespace removed, and traffic through proxies on the host over Unix sockets bound in.
      • Line 365: IP-literal allowlist entries.
      • Line 553: socat (installed: socat 1.8.1.1).
    • bubblewrap 0.11.1 --unshare-net, --setenv, --overlay-src and --tmp-overlay (installed bwrap --help; the temporary overlay of the home folder was observed to work unprivileged on this host).
    • OmniRoute v3.8.51 src/shared/constants/headers.ts (X-OmniRoute-Request-Id, X-OmniRoute-Cache, X-OmniRoute-Cache-Hit). The running composition's affinity patch (evidence/artifacts/omniroute-wire-effort-20261005/patches/045aa81f3.patch) and PR 15167's file list touch no cache code.
    • ai-memory v2.5.2 crates/ai-memory-hooks/src/router.rs:605-611 (POST /hook, POST /hook/batch, GET /handoff), crates/ai-memory-cli/src/commands/hook_spool.rs (the batch body), crates/ai-memory-mcp/src/server.rs (the tool names whose response contracts the grader reads).
    • Claude Code 2.1.291, the installed binary's BASE_API_URL (https://api.anthropic.com) and TOKEN_URL (https://platform.claude.com/v1/oauth/token), and its HTTPS_PROXY and NO_PROXY support.
    • codex rust-v0.160.1 codex-rs/codex-api/src/common.rs:279-304, identical to 0.160.0 (no temperature field).
    • SocratiCode 1.15.0 (the installed npm release of github.com/giancarloerra/socraticode tag v1.15.0, commit 0f5a8658):
      • dist/constants.js:59-66 and dist/config.js:193-226 (QDRANT_COLLECTION_PREFIX on every collection);
      • dist/services/qdrant.js:1067 (the metadata collection is prefixed too);
      • :105-118 and :1090-1100 (the collections are listed before one is created);
      • :93, :99 (no version check).
    • Qdrant 1.19.1 (127.0.0.1:21633 answers its title and version) and vLLM (127.0.0.1:28231): the local dependencies the round-6b forwards serve.
    • chrome-devtools-mcp 1.10.1: already in the home's npm cache; npx -y [email protected] --version prints 1.10.1 with npm_config_offline=true.

Evidence-class table

Claim Evidence class Command / receipt
1416d046 counts every admitted model call and puts the calibration first on the retry path; 7ade6c2f keeps the collection listing readable when the client asks for compression local_integration, red-green, with no client start test_isolation with client starts skipped: 109 run, 1 skipped, exit 0 (108 run at 1416d046). On b2d44f73's harness, 12 of the 46 tests in the five touched classes are red (9 fail, 3 error). The read's counterexample was reproduced on b2d44f73 first (coverage ok, G11 true, calibration passed). isolation.py selftest --clients was NOT re-run at 2fb12a99: no Codex process may run during the co-op's Codex window.
4a34ffba implements round 6 (A) and (B) and the GPT read of a513616 local_integration, a wrapper-only smoke with no model call, red-green test_isolation: 76 of 76 pass at 4a34ffba. On the round-5 head a513616: 4 fail and 16 error (the network class cannot set up). Self-test: 18 of 18 network expectations over 10 sampled local listeners, 49 probes ENOENT, 7 of 7 clients. Read-only re-grade of smoke-20261006c: run root unchanged, no gate's pass changed against its 10:48Z grade.
bdd8dea9 adds the tools-under-test forwards, NOT-TESTABLE and the calibration cell local_integration, a wrapper-only smoke, red-green 93 of 93 pass. On 4bd4b725 exactly its 7 tests are red (1 fails, 6 error). Self-test: 27 of 27 network expectations, including another trial's Qdrant collection, unprefixed collections and other vLLM routes refused, and the trial's own collections reached. 79 probes ENOENT, 7 of 7 clients.
4bd4b725 closes the answer channels local_integration, a wrapper-only smoke, red-green 87 of 87 pass; on 4a34ffba exactly its 11 closure tests are red (9 fail, 2 error). Self-test: 79 probes ENOENT (30 in the closed stores), Claude's history 0 bytes inside, home writes kept in the namespace, a kept project not writable.
The 16 builder files rebased without change local_integration git range-diff: 27 of 27 =. The organic tree was dcce4881 before and after the rebase. The first registry's hashes equal the builder's evidence-files-snippet.json, 16 of 16.
The decisions and confirmations commits implement the 8 decisions and the 5 confirmed points as AMENDMENT-v1.1-20261006.md describes source_review and synthetic The diffs of 2da785c2 and 4d490a86, plus 95 synthetic checks of the decision helpers, all passing. 36 of them cover the 11:43Z confirmations. They include each re-baseline key class that is never absorbed, the absorbed concurrent exit and the CL7b re-run rule. Eight checks run on smoke-20261006c's own streams and rollout, and one reads its run.json. The script was kept outside the repository and was lost when the host restarted at 13:47Z; it was not re-run in round 4.
e55864b5 fixes the seven P2 findings of the GPT read of 5aa2bfd synthetic, red-green 10 checks, one or more per finding: all 10 fail on the harness at 536487a4 and all 10 pass on this head. The script was kept outside the repository and was lost when the host restarted at 13:47Z; it was not re-run in round 4.
b8c0699c fixes the four P2s of the 87f9f1d micro-check and adds the 12:30Z Codex timing synthetic and local_integration, red-green 12 checks in two scripts: 0 of 12 pass on the harness at 87f9f1d7, 7 at feebace4 and 9 at 1c04fc79 (the two earlier pushes of this round), and all 12 on this head. Besides the original nine, they cover piped and sequenced listings, xargs options and multi-action find, and everyday agent commands. They include a real timeout --kill-after SIGKILL (rc 137), a real printf Codex event stream through the launcher, and a read-only re-grade of smoke-20261006c in which all 11 Codex trials carry both times. The scripts were kept outside the repository and were lost when the host restarted at 13:47Z; they were not re-run in round 4.
10aa02c0 hides every listed answer source from each trial's mount namespace, makes G13 a check of the receipt and the classifier a diagnostic, and fixes the 1f81d64 P3 local_integration, a wrapper-only smoke with no model call, red-green harness/test_isolation.py, committed: 26 of 26 pass on this head. On the harness at 1f81d645, 3 of its 20 runnable tests fail and 16 error. The stage-1 self-test: 43 probes, each a real file in a hidden location (this run's sibling trial included), return ENOENT in the namespace and read outside it. The own inputs, the native client configuration and a project outside the experiment stay readable. 7 client start checks pass: claude and codex --version, Codex's sandbox nested in bwrap, the CL6 and CL7 SDK imports, and codex app-server --help through the CL7b wrapper. An S7 snapshot before and after the self-test is equal.
5a9a4cdb implements the 14:38Z and 14:42Z items and the accepted P2-1 and P3 of the GPT read of 2044b2a, with --unshare-ipc and CL7b's census local_integration, a wrapper-only smoke with no model call, red-green harness/test_isolation.py at 5a9a4cdb: 52 of 52 pass, client starts included. The same 52 tests on 2044b2a: 11 fail, 16 error and 25 pass. Self-test: 49 probes ENOENT, 7 of 7 client checks, IPC namespaces distinct from the host's, no home path or home slug in the report.
8f09f230 (P2-2) makes the user manager, rootless Docker and WSL interop unreachable from a trial local_integration, a wrapper-only smoke with no model call, red-green 59 of 59 pass. The same 59 tests on 5a9a4cdb: exactly P2-2's 8 checks are red (7 fail, 1 error) and the other 51 pass; on 2044b2a, 17 fail and 17 error. Inside the namespace, each connection attempt fails: systemd-run --user (cannot connect to the user scope bus), Docker's /_ping over docker.sock (curl exit 7), and cmd.exe /c ver (interop connect failed). Outside, the user manager answered degraded and Docker OK.
The gateway's cache and logs, read-only (returned to the CC) local_integration, read-only, allowlisted routes only 15:30Z: GET /api/cache gave semanticCacheEnabled: true with 0 hits and 0 entries. GET /api/usage/call-logs?limit=20 answered without credentials: 1 of the 20 rows stores request and response bodies, and 0 have pipeline details. From a trial's namespace, /api/health and /api/usage/call-logs?limit=1 answered 200 without credentials.
The meter recalibration's operator step works on real data local_integration, offline grade.py meter-calibration --run-root <smoke-20261006c>: exit 0, read-only, p90 0.06 five-hour and 0.01 seven-day over 3 organic Claude trials. --write was run on a scratch copy of the ledger only.
Every harness module parses and imports, with no undefined global names local_integration ast.parse and import of all 13 .py files; a stdlib symtable scan (pyflakes is not installed): 0 names; node --check sdk_codex.mjs: exit 0.
The new grader runs on real data and changes only what the decisions change local_integration, offline over a development run A read-only grade_run() of smoke-20261006c with grade.py sha256 272baae2…; the output was written outside the run root, which it left unchanged. Every gate matches the 10:48Z grade. G13 fails under the structural rule for want of receipts, since that run predates the wrapper, and 0 of its 16 launched trials are valid. The classifier's diagnostic still tags 3 trials and finds no answer-source read.
The registry and the repository integrity checks pass on the real branch local_integration nice -n 19 python3 scripts/validate.py: exit 0, hashed_files 10334. git diff --check origin/main...HEAD: exit 0.
The harness ran end to end on NativeStack2604 (smoke-20261006c, 15 graded trials) native_proven, as a development run only, not acceptance Run root ~/.local/state/native-agent-stack/coordination/ns2604-coop/organic-e2e-20261005/v11/smoke-20261006c/ (private, outside the repository): run.json, gate0.json, grades/grade-2026-10-06T104807Z.json.
The launcher's, block's and pilot's new paths: final turn, hold, headroom start, rate-limit re-run, in-run re-baseline with its cost check and in-lock reconciliation, block-end STOP, meter recalibration, orphan reconciliation, CL7b fresh attempts, clone trust comparison and rate-limit marking, the Codex timing record in live runs, and every client session under the structural G13's wrapper, with its rollout publishing synthetic or wrapper-only (not run live with a model) Covered only by the synthetic checks above. The first pilot or smoke under these commits will be their first execution.

Local commands run

$ git rebase c1300c15b42f1a6643f3dc4172f40c01d99abdcd
exit 0 (27 of 27 commits, no conflict)
$ git range-diff 9e955327..9835f66c c1300c15..31ff1227
exit 0 (27 of 27 "=")
$ nice -n 19 python3 -B check_decisions.py          # scratch, outside the repository
exit 0 (95 of 95 checks passed)
$ nice -n 19 python3 -B check_p3.py <harness> --real ; nice -n 19 python3 -B check_p3b.py <harness>    # scratch; harness at 87f9f1d7, feebace4, 1c04fc79, this head
exit 1 (0 + 0 of 9 + 3: red) ; exit 1 (7 + 0) ; exit 1 (9 + 0) ; exit 0 (9 + 3 of 9 + 3: green)
$ nice -n 19 python3 -B check_p2.py <harness at 536487a4> ; nice -n 19 python3 -B check_p2.py <this harness>    # scratch
exit 1 (0 of 10 passed: red) ; exit 0 (10 of 10 passed: green)
$ nice -n 19 python3 -B regrade.py <scratch>/regrade-smoke-20261006c.json    # grade_run(), read-only
exit 0 (run root unchanged; gates as at 10:48Z except G13 False -> True)
$ git reset --soft HEAD~1 ; git checkout HEAD -- manifests/evidence.json ; git commit (decisions), later --amend (decision-7 fixes)
exit 0 (decisions commit 2da785c2)
$ git reset --soft HEAD~1 ; git checkout HEAD -- manifests/evidence.json ; git commit (11:43Z confirmations)
exit 0 (confirmations commit 4d490a86)
$ git reset --soft HEAD~1 ; git checkout HEAD -- manifests/evidence.json ; git commit (P2 fixes)
exit 0 (fix commit e55864b5)
$ git reset --soft HEAD~1 ; git checkout HEAD -- manifests/evidence.json ; git commit (round 3), later --amend three times (two review passes, then a spacing fix)
exit 0 (round-3 commit b8c0699c, replacing 8594ec2b, 1c04fc79 and d0e5350a)
$ nice -n 19 python3 -B grade.py meter-calibration --run-root <smoke-20261006c>    # read-only
exit 0 {"expected_usage": {"five_hour": 0.06, "seven_day": 0.01}, "trials": 3, "written": false}
$ python3 -c '<docs/lanes.md register_file loop>' $(git diff --name-only --diff-filter=AM c1300c15...HEAD)
exit 0 (17 entries, 85 added lines; files[] sorted and unique; hashes recomputed and equal)
$ nice -n 19 python3 scripts/component_matrix.py --check
exit 0 {"rows": 32, "status": "checked"}  (inputs unchanged, so no --write)
$ nice -n 19 python3 scripts/new_host_grand_list.py --check
exit 0 {"status": "passed", "layers": 32, "winners": 66}  (no --write)
$ nice -n 19 python3 scripts/validate.py
exit 0 {"components": 69, "hashed_files": 10332, "profiles": 4, "receipts": 212, "status": "passed"}
$ git diff --check origin/main...HEAD
exit 0
$ git push --force-with-lease=claude/ns2604-organic-harness-20261005:<previous head> origin claude/ns2604-organic-harness-20261005
exit 0 (7dc41ecd...5085150d, 5085150d...5aa2bfdc, 5aa2bfdc...536487a4, 536487a4...87f9f1d7, 87f9f1d7...feebace4, feebace4...8807fc9c, 8807fc9c...80b24f24, then 80b24f24...1f81d645)
$ cd evidence/artifacts/organic-e2e-20261005/harness && nice -n 19 python3 -B -m unittest -v test_isolation    # round 4
exit 0 (26 of 26) ; on the harness at 1f81d645: exit 1 (3 failures and 16 errors of 20)
$ nice -n 19 python3 -B isolation.py selftest --clients    # wrapper-only smoke, no model call
exit 0 (pass: 43 probes hidden, all ENOENT; 7 client checks)
$ nice -n 19 python3 -B <round-4 regrade> smoke-20261006c    # grade_run(), read-only
exit 0 (run root unchanged; every gate as at 10:48Z; G13 False for want of receipts; 0 of 16 valid)
$ git reset --soft b8c0699c ; git commit (round 4, squashing its local safe-point commits)
exit 0 (round-4 commit 10aa02c0, after one hardening amend of 934b1721)
$ python3 -c '<docs/lanes.md register_file loop>' $(git diff --name-only --diff-filter=AM c1300c15...HEAD)
exit 0 (19 entries, 95 added lines)
$ nice -n 19 python3 scripts/component_matrix.py --check ; nice -n 19 python3 scripts/new_host_grand_list.py --check
exit 0 ; exit 0
$ nice -n 19 python3 scripts/validate.py
exit 0 {"components": 69, "hashed_files": 10334, "profiles": 4, "receipts": 212, "status": "passed"}
$ git diff --check origin/main...HEAD
exit 0
$ git push --force-with-lease=claude/ns2604-organic-harness-20261005:1f81d645f9ec535d5525a3a5102c3ec72399bd80 origin HEAD:claude/ns2604-organic-harness-20261005
exit 0 (1f81d645...9d4214e2, then 9d4214e2...2044b2ab)
$ cd evidence/artifacts/organic-e2e-20261005/harness && nice -n 19 python3 -B -m unittest test_isolation    # round 5
exit 0 (59 of 59 at 8f09f230; 52 of 52 at 5a9a4cdb)
$ <the same tests on exported harnesses, with tools/skill-usage>    # red runs
exit 1 (on 5a9a4cdb: P2-2's 8 checks red, 7 failures and 1 error) ; exit 1 (on 2044b2ab: 17 failures and 17 errors of 59; 11 and 16 of round 5's first 52)
$ nice -n 19 python3 -B isolation.py selftest --clients    # wrapper-only smoke, no model call
exit 0 (pass: 49 probes hidden, all ENOENT; 7 client checks; 5 broker sockets absent and 3 broker attempts failed inside; runtime folder 0700 and empty; IPC namespaces distinct)
$ nice -n 19 python3 -B <round-5 regrade> smoke-20261006c    # grade_run(), read-only
exit 0 (run root unchanged; no gate's pass changes against 10:48Z; G13 lists 1 unverifiable ai-memory page)
$ python3 -c 'import common; common.gateway_cache_state(); common.gateway_log_exposure()'    # allowlisted GET /api/cache and GET /api/usage/call-logs?limit=20
exit 0 (semantic cache on, 0 hits, 0 entries; call logs answered without credentials, 1 of 20 rows with bodies)
$ git reset --soft 10aa02c0 ; git commit (round 5, squashing its local safe-point commits) ; git commit --amend (a red-run count, then the port reading)
exit 0 (round-5 commit 5a9a4cdb)
$ git commit (P2-2, on its own)
exit 0 (8f09f230)
$ git checkout c1300c15 -- manifests/evidence.json ; python3 -c '<docs/lanes.md register_file loop>' $(git diff --name-only --diff-filter=AM c1300c15...HEAD)
exit 0 (19 entries, 95 added lines)
$ nice -n 19 python3 scripts/component_matrix.py --check ; nice -n 19 python3 scripts/new_host_grand_list.py --check
exit 0 {"rows": 32, "status": "checked"} ; exit 0 {"status": "passed", "layers": 32, "winners": 66}
$ nice -n 19 python3 scripts/validate.py
exit 0 {"components": 69, "hashed_files": 10334, "profiles": 4, "receipts": 212, "status": "passed"}
$ git diff --check origin/main...HEAD
exit 0
$ git push --force-with-lease=claude/ns2604-organic-harness-20261005:2044b2abb86cfb74f07d262c1ab13e4906e143b3 origin HEAD:claude/ns2604-organic-harness-20261005
exit 0 (2044b2ab...1f343630, then 1f343630...a513616d after a correction to the amendment's port reading)
$ cd evidence/artifacts/organic-e2e-20261005/harness && nice -n 19 python3 -B -m unittest test_isolation    # round 6
exit 0 (87 of 87 at 80be1483; 76 of 76 at 4a34ffba)
$ <the same tests on exported harnesses, with tools/skill-usage>    # red runs
exit 1 (on 4a34ffba: the 11 closure tests red) ; exit 1 (round 6's 76 on a513616d: 4 failures, 16 errors)
$ nice -n 19 python3 -B isolation.py selftest --clients    # wrapper-only smoke, no model call
exit 0 (79 probes ENOENT; 7 of 7 clients; 18 of 18 network expectations; brokers absent; closed files empty)
$ nice -n 19 python3 -B <round-6 regrade> smoke-20261006c    # grade_run(), read-only
exit 0 (run root unchanged; no gate's pass changed against 10:48Z; G13 closure evidence missing for that older run; G11 tier evidence failing for its 11 Codex trials, fail closed)
$ git reset --soft 8f09f230 ; git checkout 8f09f230 -- manifests/evidence.json ; git commit (round 6) ; git commit (the closure)
exit 0 (4a34ffba, 4bd4b725)
$ git checkout c1300c15 -- manifests/evidence.json ; python3 -c '<docs/lanes.md register_file loop>' $(git diff --name-only --diff-filter=AM c1300c15...HEAD)
exit 0 (20 entries, 100 added lines)
$ nice -n 19 python3 scripts/component_matrix.py --check ; nice -n 19 python3 scripts/new_host_grand_list.py --check
exit 0 ; exit 0
$ nice -n 19 python3 scripts/validate.py
exit 0 {"components": 69, "hashed_files": 10335, "profiles": 4, "receipts": 212, "status": "passed"}
$ git diff --check origin/main...HEAD
exit 0
$ git push --force-with-lease=claude/ns2604-organic-harness-20261005:a513616d067ac4adf0372f8f29c54b6bada7ea6f origin HEAD:claude/ns2604-organic-harness-20261005
exit 0 (a513616d...80be1483)
$ cd evidence/artifacts/organic-e2e-20261005/harness && nice -n 19 python3 -B -m unittest test_isolation    # round 6b
exit 0 (93 of 93) ; on 4bd4b725: exit 1 (the 7 round-6b tests red)
$ nice -n 19 python3 -B isolation.py selftest --clients
exit 0 (27 of 27 network expectations; 79 probes ENOENT; 7 of 7 clients; socraticode NOT-TESTABLE in Claude cells)
$ nice -n 19 python3 -B <round-6b regrade> smoke-20261006c    # read-only
exit 0 (run root unchanged; no gate's pass changed; G11 calibration record missing, G11 failed closed)
$ git checkout c1300c15 -- manifests/evidence.json ; <register_file loop> ; component_matrix --check ; new_host_grand_list --check ; validate.py
exit 0 ; exit 0 ; exit 0 ; exit 0 {"hashed_files": 10335, "status": "passed"}
$ git push --force-with-lease=claude/ns2604-organic-harness-20261005:80be14831062992a3a974722e65c164eeb6a441a origin HEAD:claude/ns2604-organic-harness-20261005
exit 0 (80be1483...50752dde)
$ cd evidence/artifacts/organic-e2e-20261005/harness && nice -n 19 python3 -B -m unittest test_isolation    # round 6c
exit 0 (95 of 95) ; on bdd8dea9: exit 1 (the 3 round-6c tests red)
$ nice -n 19 python3 -B isolation.py selftest --clients
exit 0 (79 probes ENOENT; 7 of 7 clients; 27 of 27 network expectations)
$ <register_file loop> ; component_matrix --check ; new_host_grand_list --check ; validate.py (nice 19) ; git diff --check
exit 0 ; exit 0 ; exit 0 ; exit 0 {"hashed_files": 10335, "status": "passed"} ; exit 0
$ git push --force-with-lease=claude/ns2604-organic-harness-20261005:50752ddee6fbecf5863ea55fd43a8361eb76cf13 origin HEAD:claude/ns2604-organic-harness-20261005
exit 0 (50752dde...aa3107ca)
$ cd evidence/artifacts/organic-e2e-20261005/harness && nice -n 19 python3 -B -m unittest test_isolation    # round 6d
exit 0 (100 of 100) ; on c00d39d4: exit 1 (the 6 round-6d tests red)
$ nice -n 19 python3 -B isolation.py selftest --clients
exit 0 (30 of 30 network expectations; 79 probes ENOENT; 7 of 7 clients)
$ <register_file loop> ; component_matrix --check ; new_host_grand_list --check ; validate.py (nice 19) ; git diff --check
exit 0 ; exit 0 ; exit 0 ; exit 0 {"hashed_files": 10335, "status": "passed"} ; exit 0
$ git push --force-with-lease=claude/ns2604-organic-harness-20261005:aa3107ca956a4b5e4d1b11cae5a78771079f1f20 origin HEAD:claude/ns2604-organic-harness-20261005
exit 0 (aa3107ca...b2d44f73)
$ cd evidence/artifacts/organic-e2e-20261005/harness && ISOLATION_SKIP_CLIENTS=1 nice -n 19 python3 -B -m unittest test_isolation    # round 6e, client starts skipped
exit 0 (109 run, 1 skipped; 108 run at 1416d046) ; on b2d44f73's harness, the 5 touched classes: exit 1 (12 of 46 red: 9 fail, 3 error)
$ <the read's counterexample on b2d44f73's harness: 2 admitted /v1/responses calls, only A's response with a request id>
exit 0 (1 id in the summary; coverage ok; G11 true; calibration passed: the defect, reproduced before the fix)
$ curl -s -D- -o /dev/null -H 'Accept-Encoding: gzip' http://127.0.0.1:21633/collections ; node -e "fetch(<the same URL>)"    # read-only
content-encoding: gzip ; node v24.21.0, fetch with its default headers: content-encoding gzip
$ nice -n 19 python3 -B isolation.py selftest --clients
NOT RUN at 2fb12a99 (no Codex process may run during the co-op's Codex window; last run at b2d44f73)
$ <register_file loop> ; component_matrix --check ; new_host_grand_list --check ; validate.py (nice 19) ; git diff --check
exit 0 ; exit 0 ; exit 0 ; exit 0 {"hashed_files": 10335, "status": "passed"} ; exit 0
$ git push --force-with-lease=claude/ns2604-organic-harness-20261005:b2d44f73eb96a5fedad2119aad9e4b43e08c5176 origin HEAD:claude/ns2604-organic-harness-20261005
exit 0 (b2d44f73...2fb12a99)

Deliberately not run:

  • at 2fb12a99, the client starts (isolation.py selftest --clients and the module's client-start test): no Codex process may run on the host during the co-op's Codex window;
  • the repository's full unittest suite: no repository test imports the harness (below), and the harness's own focused module ran instead;
  • any pilot, smoke or live trial. The self-tests run the wrapper with cat, the clients' --version and --help, and the broker probes only, with no model call.
  • the lost scratch suites of rounds 1 to 3 (as the 14:38Z item directs).

No repository test imports the harness (git grep organic-e2e-20261005 -- tests/ scripts/: no match). The builder reported earlier, on exported copies, the same unittest failure sets for base 9e955327 and for 37417f4f plus the manifest entries. That is the builder's report and was not rerun here.

Run of record: smoke-20261006c

Run conditions:

  • Prepared at 37417f4f (now 1332376f), two commits before the pre-decision harness head.
  • It ran on a development allowance. The Claude completion policy was complete-at-result, pending finding 3, with T = 900 s.
  • Clients: Claude Code 2.1.291, codex-cli 0.160.1 and @openai/codex-sdk 0.160.0.
  • The grade of record is 10:48Z, by grade.py 4f2c07b6…. That grader is now superseded by round 5's (5a9a4cdb); the re-grade results are noted below.

Passed:

  • gate 0: 8 of 8.
  • G2 joins: 15 of 15 graded trials, including all 4 required cells and CL6, CL7 and CL7b.
  • G3: 0 disagreements between stream and Loki. claude-native had 24 calls, 16 of them from child transcripts; codex-native 48 = 48; codex-env 77 = 77.
  • G4: trust-table hashes unchanged, with 0 new trust entries.
  • G8: 17 of 17 fixture directories, 16 draft copies and 16 manifests kept.
  • G5, G6, G7, G9, G10, G12 and G14.
  • G15 records observations, not a pass verdict; all five were made.
  • The CL6, CL7 and CL7b SDK cells ran live for the first time.

Did not pass:

  • Both required Claude cells were censored at T = 900 s.
    • claude-native's final turn ended at about 576 s (578.7 s from launch, by the re-grade's stream reading), but a background Workflow held the result event until SIGTERM, at 900.7 s.
    • claude-env never ended its final turn: its last main-thread event was a tool call. It produced no result, as in smoke-20261005f and smoke-20261006a.
    • The Claude rows show that the instrumentation works, but they carry no organic outcome.
  • G11 fails on every Codex trial. The call logs exposed no pipeline details: 127 calls, none with them. Requested, thread-start and gateway-received effort are all max.
  • G13 failed under the old rule. Native workflow agents read a trading runtime's virtualenv under ~/projects, and the env arms read ~/code/native-agent-stack and ~/.codex/RTK.md.
    • Under decision 3 these are tags: 3 trials tagged, host-checkout 3 and user-harness-file 1.
    • No trial read a gold or answer source, so round 3's re-grade passed G13.
    • Under the structural G13 (round 4) the re-grade fails G13 again, for want of receipts. This run was prepared before the wrapper existed, so none of its 16 launched trials is valid. That is expected: the first run prepared under round 4 records a receipt for every trial.

Not yet run live:

  • the result-before-T rule (fee6e6df);
  • every launcher path of the decisions commit;
  • the CL4 cell (codex-native-ultra);
  • the stage-3 oracle cells, which have run only with stand-in clients;
  • a reviewed routing-file registry.

R4 labels are also still pending: label_vector_sha256 is null.

Decided (CC 10:55Z)

Command-center item task-ns2604-coop-20261006T105529Z decided the open questions. AMENDMENT-v1.1-20261006.md records each decision with its number, and 2da785c2 implements them. PROTOCOL-v1.1.md stays verbatim.

  1. Finding 3, censoring.
    • T is 1,800 s, and complete-at-result is the stage-1 default.
    • Every trial records its final turn end and its result event (Codex too, since the 12:30Z ruling); only a result event before T completes a Claude cell.
    • A trial with no result by T writes a no_result_diagnosis and holds its cell (HOLD.<cell>) until the operator has diagnosed it.
  2. Finding 17, exposure. A CLI is exposed only through a native surface its own upstream installer put in place, checked on each session's own listing: MinerU's skill, Worktrunk's plugins. PATH-only targets stay out of OIR (not_exposed_path_only).
  3. G13.
    • Host-checkout and other reads are tags, with an untagged and a tagged OIR stratum.
    • A trial is invalid only when it reads the task's gold or a fixture answer source: the harness's stores, or another same-task trial's fixture or transcript.
    • Superseded at 13:29Z by the structural G13 (round 4 below): the reads stay tags, and the answer-source reads are a diagnostic that never invalidates a trial.
  4. chrome-devtools. Watcher-only logging; no pre-execution deny.
  5. G10. The gateway entry is confirmed as best-effort. The grade records that call logs undercount clients that exit fast.
  6. The §9.1 meter guard.
    • A start compares the trial's expected usage (run.json, default 0.15) with the remaining headroom of both windows, and a reset window counts as fresh.
    • The quiet-account prior, the kill thresholds and the rise guard are gone.
    • A trial that hits a rate limit is marked rate_limited and re-run.
  7. In-run re-baseline.
    • Adopted with one re-baseline per run. Only the trials in flight are re-run: one Claude trial and up to -j trials of the Codex cell in flight (3 for codex-native and codex-env in the pilot), plus a CL7b trial that ran across it.
    • A re-baseline never absorbs trust-bearing keys (Codex hooks_state, the project tables, trusted sets, trust fields, removed projects), ~/.claude/settings.json (the probe's hash) or the arm-defining files. Those, any second change, and a change seen only at a block's end still stop the run.
  8. RP4, for G11.
    • The co-op turns the pipeline details on only for pilot runs.
    • Receipts keep only the forwarded effort fields.
    • run.json records the operator's on/off, and the grade reports what the call logs showed.

Confirmed (CC 11:43Z), by item task-ns2604-coop-20261006T114319Z and implemented in 4d490a86:

  1. The no-result hold applies to every Claude cell. holds_cell() depends only on the client and the deadline evidence (the elapsed time and when the result arrived), never on the cell, arm, kind or stage.
  2. gh counts as PATH-only. It is also reported in a "vendor-skill surface" stratum, for tools a client vendor's official skills repository reaches (gh through openai/skills). The stratum is kept out of OIR, with its own counts and use rate.
  3. The answer-source list stands.
    • Added: grader expected-output files outside oracles.json (the coordination state, the whole fixture cache, this experiment's published non-source files, prepare.py --answer-source-path) and earlier graded smoke or pilot receipts.
    • Same-task trials also match by trial id.
    • Sources, and a host checkout's copy of an oracle input, stay tags. So do the 2026-10-04 E2E receipts, which three suite tasks use as input.
  4. The re-baseline cost holds: one Claude trial plus one Codex cell, the arm's concurrency unit. rebaseline_cost_ok() enforces it at every re-run, with one trial per arm as the fallback, and the run stops past it.
  5. 0.15 of a window per trial is the starting default.
    • pilot.py recalibrates it to the measured per-window p90 after the first stage-4 Claude block with usable readings, writing meter-calibration.json.
    • The operator step is grade.py meter-calibration.
    • Every trial records the value it started with.

Not in this PR:

  • Decision 9 (Codex standalone web search returns 404 through the gateway) is a host wiring change for the co-op.
  • The item's ack ledger row is the co-op's to append.

Verification still due:

  • The GPT first-pass read of 5aa2bfdc (seven P2s) and the micro-check of 87f9f1d7 (four P2s) are fixed in e55864b5 and b8c0699c (see below). Round 6's commits, 4a34ffba, 4bd4b725, bdd8dea9, c00d39d4 and 72b98b09 (on 8f09f230), are the new delta for the co-op's GPT read, before the command center's ACK.
  • Round 5's gateway decisions are settled by round 6. The cache stays on under the Gate 0 amendment, and the network namespace closes the log routes. The gateway's tier setting is with the user (CC 15:57Z).
  • The 10 commits b83c8794..70d46df6 (were 6e912b0d..16ff012b) were checked through live smokes and self-tests, not reread line by line.
  • Free space on ~/.cache for about 80 fixtures of about 228 MB each is unchecked.
  • No pilot runs before that ACK.

Round 6: the Gate 0 cache amendment, a network namespace per trial, the channel closure (CC 15:57Z and 16:43Z)

AMENDMENT-v1.1-20261006.md ("Round 6") records each item in full.

1. The Gate 0 amendment (CC item 155742Z (A), dated 2026-10-06):

  • The semantic cache stays on. Gate 0 accepts the source evidence, pinned to the builds it was read at: OmniRoute v3.8.51 caches only explicit temperature-0 requests, and codex 0.160.0 and 0.160.1 send no temperature.
  • Every trial reads GET /api/cache before and after it. A hit at either reading, an entry change, or a missing or failed reading voids it.

2. A network namespace per trial with explicit forwards only (item 155742Z (B)):

Forward Client Rule
gateway 127.0.0.1:21128 Codex HTTP path filter: /v1/... only
otlp 127.0.0.1:21318 both POST /v1/logs, /v1/metrics, /v1/traces
ai-memory 127.0.0.1:29374 both /mcp; the hook routes, which must name the trial's own scope
model egress 127.0.0.1:3128 Claude CONNECT to api.anthropic.com:443 and platform.claude.com:443, through HTTPS_PROXY
  • Every other local listener and all other egress are unreachable. A login on the management routes is not used, as the user's rule is passwordless.
  • The CC's negative tests check, from inside a trial: /api/usage/call-logs and /api/health refused by the filter (the gateway never sees them), sampled listeners refusing the connection, no gateway port for Claude, and /v1 still answering.
  • Treatment boundary: web tools, gh, npm and socraticode's backends are not forwarded. Any further forward goes into NET_FORWARDS with its reason.

3. The GPT read of a513616 (CHANGES_REQUESTED), folded in:

  • P1. Call-log details are read only for the trial's own call ids (X-OmniRoute-Request-Id, recorded by its gateway forward), on the coordinator side, keeping only grading fields. A test checks that a foreign id is never requested. That header and the call log's id match is read from source, not yet observed; with no match, G11 stays failed.
  • P2. Gate 0 (network-closure) and G13 require the self-test's 13 verified denials.
  • P2. G11 fails closed: the launch tier must be default, and every call's forwarded tier default or none. Missing or unrecognized evidence fails, with the call ids.
  • P2. ai-memory pages are detected by each tool's response contract, with envelopes normalized apart. Validity and G13 share one predicate. Scalar reads and empty queries are tested in both clients.

Round 6e (1416d046, and 7ade6c2f as a separate commit; the GPT read of b2d44f7, two P2s):

  • Client checks NOT re-run at this head. isolation.py selftest --clients and the module's client-start test start codex, and no Codex process may run on the host during the co-op's Codex window. Their last run was at b2d44f73 (7 of 7 clients). Everything below ran with client starts skipped.
  • P2, a model call without a request id.
    • The forward's access log now gets an admitted row for every admitted HTTP request, before the upstream is contacted. Each outcome row names the same connection.
    • The summary counts the gateway's model calls from those rows and lists the calls without an id: a response without the header, a call with no outcome row, a gateway that was down, a relay that failed.
    • The collector carries the count and the list into the trial's gateway record. Nothing is looked up for a call without an id.
    • G11's coverage and the calibration fail closed unless the calls are counted, the count equals the request ids, no call lacks an id, no log row was unreadable and no id is shared. The calls are listed in both.
    • Regression: netfilter's own Filter runs behind a stand-in gateway (A with its id, B without). The result then goes through gateway_calls_for_trial, call_coverage, g11_trial_ok, and call_id_calibration on the written record. No test exercises collect.py's main passing the forward record, or grade_run reading the exit row.
    • The read's counterexample was reproduced on b2d44f73 first: 2 admitted calls, 1 id, coverage ok, G11 true, calibration passed.
  • P2, the retry path. pilot.calibrate_first is now the one sequence for stage 2's initial path and its --rerun-gate0-failures path: run the calibration's pending work, collect, run grade.py calibration, and stop with exit 2 unless it passed.
    • On the retry path a failed G1 test runs first, and the check runs even when G1 passed. The other retries follow in the stage's cell order.
    • A passing record is never read again. A record from an earlier run that does not pass gets one fresh read.
    • The control-flow tests drive pilot.main itself with a recording step, with G1 and a prompted check both failed among the cases. No process starts.
  • Listing compression (7ade6c2f, droppable). Measured on this host: Qdrant 1.19.1 compresses the listing on request, and Node's fetch asks by default. Round 6d's filter then answered 502, so SocratiCode's listing would have failed in Codex cells while the self-test's probe passed.
    • The listing request now goes upstream without Accept-Encoding, and a listing compressed anyway gets 502.
    • The required probe and the two-trial test now ask as the client does.
    • SocratiCode itself was not started in a trial.
  • Limit, unchanged: a required call is a request on /v1/responses, /v1/chat/completions or /v1/completions. Any other admitted /v1 request is not required to carry an id.
  • Tests: 109 run, 1 skipped (the client starts). On b2d44f73's harness, 12 of the 46 tests in the five touched classes are red (9 fail, 3 error).

Round 6d (72b98b09, the GPT read of 50752dd, one P1 and three P2s):

  • P1, Qdrant routes and bodies.
    • Only the Qdrant operations SocratiCode 1.15.0 performs are admitted, on the trial's own collections.
    • Grouped, batch, search, recommend, discover, snapshot and alias routes are refused.
    • Every body is parsed, and every collection it names (with_lookup in both forms, lookup_from at any depth) must carry the trial's prefix.
    • New required probes: a foreign body selector is refused, and so are grouped queries.
  • P2, the collection listing. GET /collections answers with the trial's own names only. The envelope is kept and the framing recomputed. A required probe shows 0 foreign names inside against 5 outside, and a two-trial test confirms the same.
  • P2, the call-id key. Strict equality with the call log's id, with no correlation-id substitution, and a negative case for it.
  • P2, calibration order. pilot.py runs codex-native-gate0 first, then collects it and runs grade.py calibration before any other cell. A failure stops the pilot.
  • Tests: 100 of 100 pass. On c00d39d4 exactly the 6 new tests are red; there, the two-trial test shows trial B seeing trial A's collection. The self-test meets 30 of 30 network expectations.

Round 6c (c00d39d4, the GPT read of 80be148, two P2s):

  • P2-1, G11 coverage. G11 fails closed unless every required call has collected tier and effort evidence. A missing or incomplete call is listed by id.
    • The required calls are the trial's own model-call request ids, logged by its gateway forward.
    • A failed detail keeps a placeholder, unresolved ids are listed, and collect.py no longer drops calls by thread.
    • Tests: 95 of 95 pass; on bdd8dea9, exactly the 3 new tests are red.
  • P2-2, SocratiCode's backends. Closed for Codex cells by the round-6b forwards. Recorded as NOT-TESTABLE for Claude cells: their configuration points SocratiCode at ports 16333 and 8231, where nothing listens.

4. Round 6b (bdd8dea9, CC item 170607Z):

  • Forwards. The only new forwards are for the tools under test and their local dependencies:

    • vLLM: POST /v1/embeddings and GET /v1/models;
    • Qdrant: GET /healthz, GET /collections (names only; SocratiCode cannot create its collections without it), and data operations on /collections/<the trial's own QDRANT_COLLECTION_PREFIX>* only.

    Each forward records its reason, filter and tool, and has negative tests.

  • chrome-devtools starts from the home's npm cache, offline; there is no npm forward.

  • Web tools and gh stay off. Claude's server-side web search is a treatment fact, reached through the API forward.

  • NOT-TESTABLE. A tool that cannot run in a trial gets its cells marked NOT-TESTABLE with the cause, never NOT-READY. On this host, SocratiCode in Claude cells is NOT-TESTABLE: Claude's configuration points it at ports where nothing listens.

  • The calibration cell. The pilot's first Codex trial (gate0-G1) calibrates the call-id key. Gate 0 and G11 require it, with no foreign-id fallback.

5. The answer-channel closure (4bd4b725, droppable):

  • The home folder is a temporary overlay. Writes reach the host only through explicit binds: the trial's own files, and Claude's credentials, kept because an OAuth refresh rotates the token.
  • Kept projects are read-only.
  • Empty in the namespace:
    • ai-memory's store and spool;
    • agentsview's archive;
    • codebase-memory's and jcodemunch's indexes, and Serena's logs;
    • Claude's plans, tasks and paste cache;
    • Codex's own folder (history, session index, logs, memories, goals, queue). The entries a clone links to come back as temporary overlays.
  • Claude's history reads empty.
  • Tests: one negative test per channel.

Round 5: residual channels, the normal tier and the GPT read of 2044b2a (CC 14:38Z, 14:42Z and 15:17Z)

AMENDMENT-v1.1-20261006.md ("Round 5") records each item in full. Two gateway items need the command center first.

1. The gateway's response cache is not confirmed off (14:38Z item):

  • Readings at 14:56Z and 15:30Z: semanticCacheEnabled: true, with 0 hits and 0 entries.
  • By source, it cannot answer a Codex trial. OmniRoute v3.8.51 reads or stores a response only for a request with an explicit temperature: 0, and codex-cli 0.160.0's Responses request has no temperature field.
  • Gate 0's gateway-cache check passes only while the cache is off. G13 fails a trial whose hit count rose or whose call logs show cacheSource: "semantic".
  • Decision needed: the co-op switches the cache off, or the CC accepts the source evidence with an amendment that relaxes the gate-0 check.

2. The gateway's logs and management routes, returned to the CC (15:17Z item):

  • Payloads are stored. Call-log payload storage is on: 1 of the latest 20 rows stores request and response bodies.
  • No credentials needed. The log API answered without credentials, from the host and from inside a trial's namespace (/api/health and /api/usage/call-logs?limit=1 both answered 200).
  • What it allows. A trial could read another trial's stored request and response. This was not exercised on a trial's payload.
  • Minimal closure, proposed; nothing was changed:
    • a per-trial network namespace (bwrap --unshare-net) whose only routes out are explicit forwards for what the treatment needs: the gateway's inference path, the OTLP collector, the ai-memory server and the URL-configured MCP servers. The pattern is anthropics/sandbox-runtime v0.0.78;
    • a path rule for port 21128, where /v1 and /api share one port. Either the forward admits /v1/... only, or OmniRoute's management routes require authentication during trial runs.
  • Other loopback services. The same network reaches every other service on the host's loopback, and the closure covers them too: Dagu, Serena's MCP servers (execute_shell_command), hcom, the codebase-memory daemon, agentsview, Loki and Grafana, among 110 TCP ports listening at 15:47Z.
  • Until then, the grader tags such commands (gateway-management-api, local-service-http) as diagnostics.
  • Correction, recorded in the amendment. Earlier this round I read /api/settings and /api/settings/cache-config through script files. The command guard does not allowlist either route, and both return decrypted secrets. Only cache keys and key names were printed, and nothing was stored. The harness reads only the allowlisted routes.

3. The normal service tier (14:42Z item):

  • Every Codex cell sets service_tier=default explicitly: CL3, CL4 and the prompted cells on the line, CL7 in the runner's configOverrides, and CL7b in the provider's cli_config.
  • Checks: stage 1 refuses a run without it, the launcher and block.py refuse a launch without it and record it in each launched row, and G11 reports it.
  • The client setting does not decide the tier through OmniRoute. codex-cli 0.160.0 leaves an explicit default out of the request, so OmniRoute's own Codex tier settings decide what goes out. G11 therefore also fails on a forwarded priority tier (pipeline details, which are on only for pilot runs).
  • Unread: the gateway's codexServiceTier value is in /api/settings, which agents may not read. The operator can read it in a terminal.

4. Residual channels (14:38Z item, extended by the GPT read):

  • Private temporary folders and IPC. /tmp, /var/tmp and /dev/shm are private per trial. Each trial also gets its own IPC namespace (--unshare-ipc), and G13 fails a trial without one.
  • ai-memory stays, scoped per trial.
    • A marker with workspace organic-e2e and project <trial_id> is bound above the fixture in the namespace only.
    • The grader checks every ai-memory call's returned scope. A page of another trial's scope invalidates the trial, and so does a page an implicit-scope call returned, since its scope cannot be checked.
    • Global queries are tagged. Masking files cannot close ai-memory, whose server answers over HTTP, so this ruled scope check is the closure.
  • Tags, as diagnostics: user systemd, Docker, WSL interop, ai-memory HTTP, the gateway's management routes and other loopback HTTP.
  • fanotify stays an optional audit.

5. The GPT read of 2044b2a (15:17Z item, C1):

  • P2-1, accepted. G13 checks each bind as an exact (operation, source, destination) triple of the plan.
    • The private folder is derived from the trial id. So the shared work/last bound onto the trial's own fails, as do a private store bound from the shared store and a receipt naming another private folder.
    • No bind may re-expose an earlier cover, declared answer sources included.
    • The receipt's options must match its operations.
    • The negative cases are in test_isolation.G13Check.
  • P3, accepted. The public receipt also hashes every home-derived name (-home-<user>-... slugs) wherever it sits. The exact mount operations stay private: the ledger is 0600, and CL7b's options file and the self-test report are 0600.
  • P2-2, upheld, in its own commit 8f09f230.
    • Each trial gets an empty private runtime folder (--perms 0700 --tmpfs /run/user/$UID) and an empty /run/WSL.
    • So the user manager's and the session bus's sockets, rootless Docker's socket, the ssh-agent's and gpg-agent's sockets, and WSL interop (found this round: a Windows program reads the distribution from outside the namespace) are absent.
    • Nothing is passed through, and the amendment gives the evidence.
    • The negative tests (test_isolation.HostBrokers) attempt systemd-run --user, Docker's /_ping over docker.sock and cmd.exe inside a trial's namespace, and expect failure. The stage-1 self-test probes the same.
  • The verification gap. CL7b's tree now gets the launcher's census, sampled every 2 s from bwrap's namespace record. The limit is stated: a process that starts and ends between two samples is not seen, and the namespace record and the locked mounts do not depend on the census.

The wrapper's argv in round 5, for a Codex trial. As before, a process listing shows only /usr/bin/bwrap --args <fd> -- bash -lc <line>. This is the public form: the 68 projects outside the experiment become a count and a hash.

/usr/bin/bwrap --ro-bind / / --dev-bind /dev /dev --proc /proc --bind-try ~ ~ --perms 0700 --tmpfs /run/user/1000 --tmpfs /run/WSL --tmpfs /tmp --tmpfs /var/tmp --tmpfs /dev/shm --bind-try /tmp/.X11-unix /tmp/.X11-unix --tmpfs ~/.local/state/native-agent-stack/coordination --tmpfs ~/.cache/ns2604-organic-fixtures --tmpfs ~/.cache/ws --bind ~/.cache/ws/<fixture> ~/.cache/ws/<fixture> --ro-bind ~/.cache/wsr/<run>/iso/<trial_id>/ai-memory.toml ~/.cache/ws/.ai-memory.toml --tmpfs ~/.cache/wsr --ro-bind ~/.cache/wsr/<run>/bin ~/.cache/wsr/<run>/bin --ro-bind ~/.cache/wsr/<run>/prompts/<trial_id>.txt ~/.cache/wsr/<run>/prompts/<trial_id>.txt --bind ~/.cache/wsr/<run>/clones/<trial_id> ~/.cache/wsr/<run>/clones/<trial_id> --bind ~/.cache/wsr/<run>/iso/<trial_id>/last ~/.cache/wsr/<run>/last --tmpfs ~/.claude/projects [68 --bind-try of projects outside the experiment; sha256 of their names 50f5505ab263b60e56ba80db7e54fb2176f62493b1a18091af60689b60a9da6b] --bind ~/.cache/wsr/<run>/iso/<trial_id>/codex-sessions ~/.codex/sessions --bind ~/.cache/wsr/<run>/iso/<trial_id>/claude-file-history ~/.claude/file-history --bind ~/.cache/wsr/<run>/iso/<trial_id>/claude-context-mode-sessions ~/.claude/context-mode/sessions --bind ~/.cache/wsr/<run>/iso/<trial_id>/claude-context-mode-content ~/.claude/context-mode/content --bind ~/.cache/wsr/<run>/iso/<trial_id>/codex-context-mode-sessions ~/.codex/context-mode/sessions --bind ~/.cache/wsr/<run>/iso/<trial_id>/codex-context-mode-content ~/.codex/context-mode/content --bind ~/.cache/wsr/<run>/iso/<trial_id>/claude-tmp /tmp/claude-1000 --unshare-pid --unshare-ipc --die-with-parent --chdir ~/.cache/ws/<fixture> --info-fd <fd> -- bash -lc <line>

Without 8f09f230, the runtime folder is bound in (--bind-try /run/user/1000 /run/user/1000) and /run/WSL stays visible.

Residual channels after round 5:

  • Loopback services, the gateway's management routes among them: the network-namespace proposal above.
  • ai-memory's _global scope: a page another trial wrote there is not caught; a write to it is tagged.
  • The Windows drives: they are visible read-only, and a copy of a hidden root there would not be hidden. They were not searched.

Round 4: the structural G13 (CC 13:29Z) and the 1f81d64 P3

Command-center item task-ns2604-coop-20261006T132948Z decided that a classifier of the commands a model typed cannot converge, because shell grammar always has another form. G13 is now structural, in harness/isolation.py (10aa02c0):

  1. Every listed answer source is hidden from each trial's mount namespace. The launcher (every CLI and SDK cell, the prompted and gate-0 cells) and block.py (CL7b, through the provider's codex_path_override, which points at a per-attempt wrapper) run each client's process tree under bwrap.
    • Empty tmpfs: the coordination state, with every run root (oracle runs, other trials' drafts, grades), the suite cards and the v1 captures; and the fixture cache, with oracles.json.
    • Empty tmpfs with the trial's own entries bound back: ~/.cache/ws (its own fixture), ~/.cache/wsr (its own prompt, settings, clone and -o file, and the run's neutral binaries), and ~/.claude/projects (the projects outside the experiment, and its own).
    • A fresh per-trial folder over each: the shared Codex sessions folder, which the clone's alias points at; Claude's file history; context-mode's per-project stores; and Claude's /tmp area. The trial's rollouts are published to the native sessions folder after it exits; a failed publish is recorded as finish_error and never costs the trial's exit row.
    • Unchanged: the native home and the client configuration stay visible and writable, and the network and the environment are as before. The system runtime is read-only.
  2. G13 checks what was hidden. The launched row's receipt carries the wrapper's argv, its mount operations and the hidden list, with each path's sha256 and, for a file, its content's. G13 passes when:
    • every listed location is covered;
    • nothing but the trial's own entries is bound back into a hidden root;
    • the client tree ran in its own mount namespace (--info-fd);
    • no process the launcher sampled was in the host's namespace;
    • stage 1's wrapper-only self-test passed.
      Gate 0 requires the self-test and each stage-2 trial's check, and a trial is valid only if its own check passes.
  3. The fanotify audit stays optional and is never a gate. Its pid filter needs root, and the harness runs no sudo.
  4. The command classifier is a diagnostic tag only. The GPT micro-check of 1f81d64's two P2s, F1 (patterns and unrelated listings taken for reads, content searches missed) and F4 (the own clone's sessions alias exempted before classification), concern it, and are recorded as superseded.
  5. The P3 is fixed. The hold, the result-before-T rule, the censoring reason and the grader's completion re-check read the unrounded offsets. The one-decimal fields are presentation only, so a result at 1799.96 s in a session that ran 1800.02 s is complete, not held.

The wrapper's argv in round 4 (superseded by round 5's, above), as bwrap parses it for a Codex trial (a process listing in the namespace shows only /usr/bin/bwrap --args <fd> -- bash -lc <line>):

/usr/bin/bwrap --ro-bind / / --dev-bind /dev /dev --proc /proc --bind-try ~ ~ --bind-try /tmp /tmp --bind-try /var/tmp /var/tmp --bind-try /run/user/1000 /run/user/1000 --tmpfs ~/.local/state/native-agent-stack/coordination --tmpfs ~/.cache/ns2604-organic-fixtures --tmpfs ~/.cache/ws --bind ~/.cache/ws/<fixture> ~/.cache/ws/<fixture> --tmpfs ~/.cache/wsr --ro-bind ~/.cache/wsr/<run>/bin ~/.cache/wsr/<run>/bin --ro-bind ~/.cache/wsr/<run>/prompts/<trial_id>.txt ~/.cache/wsr/<run>/prompts/<trial_id>.txt --bind ~/.cache/wsr/<run>/clones/<trial_id> ~/.cache/wsr/<run>/clones/<trial_id> --bind ~/.cache/wsr/<run>/iso/<trial_id>/last ~/.cache/wsr/<run>/last --tmpfs ~/.claude/projects [one --bind per project outside the experiment: 68 on this host today] --bind ~/.cache/wsr/<run>/iso/<trial_id>/codex-sessions ~/.codex/sessions --bind ~/.cache/wsr/<run>/iso/<trial_id>/claude-file-history ~/.claude/file-history --bind ~/.cache/wsr/<run>/iso/<trial_id>/claude-context-mode-sessions ~/.claude/context-mode/sessions --bind ~/.cache/wsr/<run>/iso/<trial_id>/claude-context-mode-content ~/.claude/context-mode/content --bind ~/.cache/wsr/<run>/iso/<trial_id>/codex-context-mode-sessions ~/.codex/context-mode/sessions --bind ~/.cache/wsr/<run>/iso/<trial_id>/codex-context-mode-content ~/.codex/context-mode/content --bind ~/.cache/wsr/<run>/iso/<trial_id>/claude-tmp /tmp/claude-1000 --unshare-pid --die-with-parent --chdir ~/.cache/ws/<fixture> --info-fd <fd> -- bash -lc <line>

A Claude trial has its settings file instead of the clone, and its own project bound back after the tmpfs over ~/.claude/projects. CL7b's wrapper execs bwrap with the same options and the real codex.

Limits in round 4 (round 5 narrows them, above):

  • Services reached over a socket run outside the namespace: the ai-memory server, MCP servers configured by URL, the OmniRoute gateway, and a user systemd or Docker daemon.
  • /tmp and /dev/shm stay shared outside Claude's own area.
  • sudo does not work inside the user namespace.
  • Nested sandboxes run below the trial's namespace, with its mounts locked.

Round 3: the GPT micro-check of 87f9f1d and the CC's 12:30Z rulings

Findings 1 and 4 below tune the classifier. The GPT micro-check of 1f81d64 found them still partial, and round 4 supersedes them; findings 2 and 3 stand.

The micro-check requested changes for four P2s, all fixed in b8c0699c:

  1. Access by arguments and output mode.
    • Tags: listings, stat, realpath, wc, rg --files/-l/-c, git ls-files, cp/mv, Glob, the Grep tool's name and count modes, and find -exec grep -l or xargs grep -l. find and xargs are judged by the programs they run: every find action, with xargs options read as the installed GNU findutils xargs 4.10.0 --help lists them.
    • A filter fed by a pipe that names no file (ls <dir> | head -n 5, | sort, | grep x) reads the listing, not a file, so it is no read.
    • Answer sources: only successful content access that returned content (cat, head, rg printing lines, xargs cat, find -exec cat, git show after global options such as -C <dir>, the Read tool, the Grep tool in content mode).
  2. CL7b repetitions: I chose the smaller correct change, which rejects a repeat above 1. block.py refuses such a block, and prepare.py refuses --repeat-override above 1 while codex-app-server is among the cells. That holds until each repetition gets its own attempt; a re-run is a new block with a fresh attempt.
  3. Hold by evidence: a Claude session that reached T with no result before T holds its cell however it ended. That includes the timeout's SIGKILL (rc 137, now timeout_killed); a kill before T does not hold.
  4. Same-task Codex transcripts: each trial's main and collected child thread ids are mapped. A successful content read of such a rollout is an answer source, whether it reads the native original, a clone alias or a collected copy. For a glob or directory-wide read, the returned content is scanned for same-task trial and thread ids. The scan runs only when the read itself reaches a G13 location: its operands, an earlier cd in the command, and, for an operand another command produced or a heredoc program, every path the command names. A listing beside or piped into a read is therefore not scanned. Known limits: a script file (python3 x.py) and a cd from an earlier call are not followed. Other tasks' rollouts stay tags.

Confirmed (CC 12:30Z), item task-ns2604-coop-20261006T123036Z:

  • (a) The 2026-10-04 E2E receipts stay sources, with no code change. They would become answer sources only if a file there held a graded output of this experiment's own trials.
  • (b) Every cell now records the final-turn and result-event times.
    • Codex cells through the launcher (the last agent message with no tool item after it, and turn.completed).
    • CL7b and older runs through the main rollout (AgentMessage, task_complete).
    • The grade reports completion_times for every trial and timing_record for the Codex ones. On smoke-20261006c all 11 Codex trials carry both times.

Fixes from the GPT first-pass read of 5aa2bfd

The read requested changes for seven P2 findings. All are fixed in e55864b5, and AMENDMENT-v1.1-20261006.md records them:

  1. Clone trust: a hook or project trust change in a trial's own clone is now persistent on its own. The launcher stops the run for it and no re-baseline absorbs it. G4 fails on it for every trial, and CL7b compares its clone's trust per attempt.
  2. Concurrent exits: the re-baseline is reconciled inside the lock against the baseline in force. An exit whose change another exit already absorbed is re-run, not stopped, and its S7 judgement is refreshed. Only an additional or refused change stops the run.
  3. Resume: an attempt counts only when its last exit is terminal and not carried, or while it is still running.
    • Ended orphans get an interrupted exit, and a launcher failure after launch gets launcher_error_after_launch; both are carried forward.
    • Every Claude launch stays in the session-cap count.
  4. CL7b rate limits: the block keeps a sanitized provider error class. A rate limit marks the attempt rate_limited, sets STOP.codex and is carried forward. Gateway counts alone never mark a trial.
  5. CL7b attempts: each later attempt gets a fresh trial id, fixture, clone and provider config under the same ref. Attempts are counted per trial id, and G10 reads the re-run.
  6. G13 reads: only a successful read that returned content counts as reading an answer source. Mentions, listings, writes and failed or empty reads stay tags.
  7. G11: an observed, nonempty forwarded-effort value is required. Pipeline exposure is reported apart, with the calls that have no value listed.

The same commit also tightens the meter calibration (point 5): trials with fewer than two readings, and windows that rolled over mid-trial, are left out.

Decision record

evidence/artifacts/organic-e2e-20261005/AMENDMENT-v1.1-20261006.md records the command center's dated decisions (items task-ns2604-coop-20261006T105529Z, ...114319Z, ...123036Z, ...132948Z (the structural G13), ...143846Z, ...144256Z and ...151719Z (round 5), ...155742Z, ...164313Z and ...170607Z (round 6)). For each decision it gives the change, the points to confirm and the offline evidence. PROTOCOL-v1.1.md §13 lists the decisions as they stood before.

Host evidence

Not applicable: this PR adds or changes nothing under evidence/hosts/.

Checklist

  • New/changed GitHub Actions are pinned to a full commit SHA with a version comment (no floating tags). Not applicable: no workflow changes.
  • New/changed workflows declare top-level permissions: {} and grant each job only what it needs. Not applicable: no workflow changes.
  • No secrets are printed, logged or committed, and no new required secret was added. A token-pattern scan of all 19 files matched only CC item ids, and validate.py passes.
  • No new paid hosting, subscription or billing surface was introduced.
  • Peer-owned untracked files and worktrees were preserved (not deleted, moved or overwritten).

🤖 Generated with Claude Code

Open findings at 2fb12a9 (not fixed; the harness is shelved)

Under the evaluation rule of 2026-10-06 (the decision record in #802) this harness runs no trial as a gate, and the re-scoped S4 read-back does not use it. No further round follows. The PR stays a draft at this head.

Two P2 findings of the cross-family read at this head stay open. Fix both, with their regressions, before the harness is ever used as a runnable tool:

  1. A supported route alias is outside model-call accounting. The pinned gateway build rewrites /v1/v1/<path> to the same routes, so /v1/v1/responses is admitted by the forwarder but is not counted as a model call (netfilter.py: admission against MODEL_CALL_PATHS in summarize). Coverage and calibration can pass on the canonical call alone. Fix: refuse unsupported aliases before connecting, or canonicalize and count every admitted alias; add a good-canonical plus alias-without-id case and an alias-in-flight case.
  2. Bulk collection overwrites accepted calibration evidence. calibrate_first keeps a passing gateway record; the general stage-2 collection then re-fetches and overwrites it (pilot.py, collect.py), so a later list failure can fail Gate 0 on evidence that had passed. Fix: preserve validated calibration snapshots across later bulk collection, handle an empty trial selection explicitly, and add a regression with a saved passing G1, an unrelated retry and unavailable historical rows.

Recorded limitations, not findings of that read: a required call is a request on the three canonical model routes only; the duplicate-key and method-override gaps of the earlier read are untouched; whether the gateway's request-id header equals the call log's id is unobserved; calibrate_first skips with a log entry when a restricted run has no calibration cell; no test covers collect.py's main passing the gateway record.

State of checks at this head: the client self-test and the isolation test module pass (109 run, none skipped); validate is green; osv-scanner fails on an advisory in two lockfiles this PR does not touch, which #797 fixes. The registry must be redone on the then-current main before any merge.

seathatflowsinourveins and others added 27 commits October 6, 2026 07:01
…e promptfoo-driven harness

Adds evidence/artifacts/organic-e2e-20261005/: the delivered protocol v1.1 and
pilot spec (home prefix written as ~ for the publication scan; the delivered
bytes are hash-referenced in each file's header comment), and the harness that
implements the pilot spec on promptfoo 0.123.1 exec: providers:

- prepare.py (stage 1): fixture from git archive 9e95532, stripped and gated,
  setup files from local git objects, deterministic tar, D oracles in a scratch
  extraction, routing-registry candidates, R2 lint, per-trial Claude settings
  (8.1 deny list), Codex rules (codex execpolicy check per rule), clone gates,
  S7 baseline, meter, quota gate, seeded promptfoo configs per cell.
- launcher.py: the exec: launcher contract (ledger rows, NEUTRAL_ROOT fixture,
  per-trial clone or settings, shared flock with the meter read inside it,
  clean login shell, stream tail with the 9.1 kill rule, nested-client watch,
  draft copy and fixture manifest, always exit 0 with one JSON line).
- block.py, collect.py, grade.py: gates around one eval, stage-5 collection
  (Loki, rollouts, skill_usage --lanes --call-ledger, gateway call logs joined
  on client_metadata.thread_id, agentsview), stage-6 grading (joins, stream and
  Loki agreement, marker scan, R1 provenance tags, watcher, OIR with Wilson
  intervals) and the stage-0 replay over the v1 captures.
- sdk_claude.py (CL6) and sdk_codex.mjs (CL7): written, not yet run.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- prepare.py --prompted builds prompted cells (prompted-<base cell>) on lane
  organic-e2e-prompted with their own fixtures, as R10 requires for probes,
  canaries and oracle runs. The stage-2 canaries of the pilot spec are in
  harness/stage2-canaries.json.
- grade.py keeps prompted lanes out of OIR.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…actor scope

Findings from the first live smoke (run smoke-20261005b) fixed in the grader:

- Every call, result and hook output carries its event index (Claude) or tool
  ordinal (Codex, shared by the exec stream and the rollout), so a block only
  tags uses that come after it.
- Hook blocks are the hook's own output (additionalContext, systemMessage),
  never the hook event's input; ai-memory and handoff injections are store
  blocks, other tool-native hook context is hook-nudged.
- Store and hook blocks, and consulted skill bodies, apply within one actor; a
  subagent or child thread has its own context.
- An item's own output (ctx_search text naming ctx_* tools, a ctx_* wrapper
  around an auto-memory read) does not direct that item; plain-English aliases
  such as "search first" no longer name an item in a block.
- A consulted skill's body is its SKILL.md, not a command output that may hold
  several skills.
- RTK PreToolUse rewrites (updatedInput) of main-stream Bash calls become
  hook-rewritten rtk uses; S6 reports the rewritten share and hook sources.
- G3 also checks child-transcript MCP and Skill calls; calls killed before a
  result agree only when Loki has none either.
- G13 does not count reads of the trial's own auto-memory directory (exempt,
  logged as own_auto_memory_reads); the env arm's harness text is the text the
  client loaded.
- prepare.py records MCP tool names by server for the Codex tagger.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- harness/pilot.py runs the pilot spec's stage order as one command: the
  stage-0 replay (G1 must hold), prepare, the stage-2 probes and canaries and
  the gate-0 G1 trial, then the Codex blocks C1-C5 and the Claude schedule in
  parallel chains, collect and grade. It sequences block.py calls only; each
  block keeps its own gates, and a refusal stops that chain.
- When a host harness file no longer matches the protocol's hashes, one
  Claude probe is added and prepare.py --skip-tests drops G1|claude-sdk (the
  give-way rule), so the Claude total stays 14.
- stage2-canaries.json adds the two Codex probes; the marker scan, not the
  prompt, decides each probe.
- Exercised end to end with stand-in clients (17 trials, no model call).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
CL7b (promptfoo's openai:codex-app-server) has no launcher and no exec
stream. collect.py now takes its thread from Loki (env = trial_id), copies the
thread's rollouts, copies ./draft/ and hash-manifests the fixture, as the
protocol's CL7b entry assigns to stage 5. grade.py reads that thread's rollout
as the primary source when no exec stream exists and records which source it
used. Written from the observed shapes; not yet run against a live CL7b trial.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A process listing shows a client's argv to the model, and the smoke's launch
lines carried run-root paths that name the experiment (the per-trial settings
file, the -o file and the CODEX_HOME clone). R2 (f) covers every launch string
the model can see, so prepare.py now creates a neutral per-run directory
(~/.cache/wsr/<8 hex>) for settings, prompts, -o files, clones and the SDK
launchers (bin/run.py on the base interpreter with the SDK venv first on
sys.path, bin/run.mjs, bin/sdk), and records it as run.json trial_root.
Records stay in the run root. A stand-in self-test confirms the launch lines
keep no run-root path; the protocol's own lane tag (ecosystem.lane=organic-e2e
in OTEL_RESOURCE_ATTRIBUTES) is the remaining experiment word in a client's
environment.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…enance)

Fixes the independent verifier's findings on 8d43ec6f:

- GitHub credential (finding 6): the Codex clone adds GH_CONFIG_DIR to
  every stdio MCP server's env as well as the shell policy, gated by a
  parsed diff of config.toml; the CL3 line, the CL7 launcher and CL7b's
  cli_env carry it too. A second gh canary runs through
  ctx_batch_execute.
- Stage 2 is a gate: pilot.py runs the Codex probes and canaries, the
  gate-0 G1 trial (its own cell) and the Claude probe, then collect.py
  on those trials and grade.py gate0; stage 4 refuses unless gate0.json
  passes.
- Claude completion: run.json claude_completion (censor-at-T as written,
  or complete-at-result with a grace) and any T change need an
  amendment reference; the launcher records the result event's arrival,
  time-to-result and post-result time, and the grader splits spend
  before and after the result. The Claude chain refuses while the policy
  is undecided.
- Session cap: the launcher counts launched Claude sessions inside the
  lock and refuses at 14; stage 1 refuses a larger Claude schedule;
  resume runs only tests short of their repeat; a pre-launch meter or
  lock refusal writes DEFER.claude and the test is carried forward.
- Rollouts are found by thread id across local and UTC date folders;
  stage 0 reads the v1 captures' Loki rows over their own window, saved
  once into the coordination tree.
- Grader: child transcripts take their actor type from their meta
  files, Workflow calls are agent-type uses, spawn prompts and Codex
  forks are provenance sources; RTK rewrites come from transcript hook
  attachments joined by tool_use id over every actor; hook text is
  classed tool-native or harness by command; tool results carrying a
  harness marker tag later uses harness-read; G13 also covers host
  checkouts, user-level harness files, trial roots and other fixtures;
  a process-table read detector; task-induced reads the call's input;
  Claude validity needs the transcript.
- Neutral argv: opaque cell codes and test refs, configs, shims,
  runner link and interpreter links under the trial root, the pilot
  re-executes through bin/p.py, and the launcher lints every ancestor's
  argv before a trial starts.
- Gates: G10 (SDK parity) and G12 (D oracles recomputed in a fresh
  extraction at stage 1) are implemented; G7 needs the canaries; G11
  needs the forwarded effort; G6 reads each trial's own first in-stream
  reading, and the launcher applies the prior to it.
- Minor: S7 before-snapshot after the lock, the currency due file in
  S7, prompted entries on a base cell no stage runs are refused, and the
  registry takes a reviewed list (--registry-review); organic trials
  refuse while it is provisional unless a development run records an
  allowance.

Exercised with stand-in clients (selftest-fix-b) and synthetic grader
checks; the live 4-cell smoke follows.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ows the run's T

The clone's new env tables for MCP servers that had none keep Codex's
default variables: openai/[email protected]
codex-rs/rmcp-client/src/utils.rs:16-39 adds a server's env to
DEFAULT_ENV_VARS (HOME, PATH, :163-166). CL7b's turn_timeout_ms now
comes from the run's T instead of the constant.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The live smoke-20261005c stage 2 showed the launcher's post-exit S7
snapshot racing Codex's own marketplace upgrade, which writes temporary
git objects into the per-trial CODEX_HOME clone after the client exits:
the walk hit a vanished file, the exception escaped and the trial was
left without an exit row (gate 0 then failed it, as it should). The tree
manifest now records a vanished or locked file as unreadable, post-exit
bookkeeping failures are written into the exit row, and G4 requires
every launcher trial's own host comparison instead of defaulting a
missing one to equal.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The live smoke-20261005d stage 2 stopped on a host view that one
trial's before-snapshot caught mid-write: Codex sessions re-sync the
remote curated plugins into the shared ~/.codex/plugins/cache at start
(the clone symlinks plugins, protocol 4.3), and with three trials in
flight another session's sync was half done. The listing was back at
the stage-1 baseline after the trial. Trial and block snapshots are now
read until they hold still, a STOP needs a view that differs from the
baseline after the trial (or a new trust entry), and a before-only
difference is recorded as a transient. G4 and gate 0 use the same
judgement.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
pilot.py --from-stage 2 --rerun-gate0-failures runs once more each
stage-2 test whose gate-0 check failed (a Claude probe stopped by the
meter goes in the next 5-hour window), then collects and checks gate 0
again; DEFER.claude is cleared at the start of stage 2 as well as 4
once the newest meter reading allows a start.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
prepare.py and pilot.py accept cell@item_id:INSTANCE beside the
global item_id:INSTANCE pairs, so a smoke can run CL7 and CL7b on G1
without adding a Claude session.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Codex and Claude chains run in parallel in stage 4, so a trial's
snapshot can meet another session's plugin sync; up to eight reads,
two seconds apart, before a view counts as unsettled.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
… in both Codex arms

G10 (SDK parity) now holds only when CL6, CL7 and CL7b were each
exercised and passed: a cell with no graded trial is listed under
not_exercised and the gate reads None, never a pass; a failed check
still fails it. The stage-2 ctx_batch_execute gh canary also runs in
the env clone (canary-gh-auth-ctx-env on codex-env), the arm where the
verifier observed the host gh login (finding 6); gate 0 and G7 require it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…L7/CL7b take the omniroute profile as --config

The live smoke-20261005f exposed two launch defects.

- The claude-native trial was killed as a nested client when the model
  ran `find / -xdev -type f ...`: Claude Code's native binary is
  multi-call (run as argv[0] bfs, ugrep or rg it is the embedded find,
  grep or ripgrep; checked on 2.1.290 with exec -a), and the bfs
  process's `-type` passed the print-flag test. A nested Claude session
  now also needs argv[0] to name the client; an exe beside the trial's
  binary in the versions directory counts as Claude, and any exe named
  codex as Codex, so a client updated mid-run is still seen.
- CL7 and CL7b exited at start: codex-cli 0.160.0 refuses
  `profile = "omniroute"` through --config ("legacy ... no longer
  supported; use `--profile omniroute`"), and neither the Codex SDK
  0.160.0 nor promptfoo's codex-app-server provider can pass --profile
  (`codex -p omniroute features list` also says --profile does not
  apply to app-server). Stage 1 now freezes the profile file's keys,
  minus model and model_reasoning_effort that every launch sets, as
  run.json codex_profile_layer; CL7 passes them as the SDK config
  object and CL7b as cli_config. `codex features list` with those -c
  pairs loads them (standalone_web_search true), and the legacy key
  fails to load. This settles the protocol's [nv] on CL7's profile.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…read at max effort

The live devcheck-cl7-20261006a run (CL3 reference, CL7 and CL7b on G1
at ae032cf9) passed joins, G3 and the Codex half of G10, with two
parity gaps on CL7b: its launched row had no gateway build, so G11
could never hold for it, and codex.conversation_starts reported the
host config's ultra because the provider sets effort per turn only.
block.py now records the build on CL7b's launched row (the grader reads
it there when the pre-launch row has none), and CL7b's cli_config sets
model_reasoning_effort max as CL3's -c does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…rried forward

Finding 4 left one path consuming a Claude test without an observation:
the launcher writes the launched row before the client starts, so a
trial it kills at its own first in-stream rate_limit_event (the 9.1
prior, when no reading 30 minutes old existed at the lock) counted as
run, and resume never ran its test again. pilot.py now carries such a
test forward like a pre-launch refusal; the session still counts
toward the cap of 14, because the launcher counts every launched
Claude session. The grader keeps these trials out of the
session-content gates (G2, G3, G5, G6) and lists them; G4, G7, G8,
G13 and G14 still apply.

Checked with stand-in clients (selftest-h at 16ff012b plus this
change): the first Claude trial was killed at 1.0 s with
meter_prior_first_event, DEFER.claude stopped the chain, the resume
cleared it and ran the carried test again, and both Claude trials then
ended by the complete-at-result grace kill (result at 3.1 s, killed
5.1 s later, not censored); every host trust view equalled the
stage-1 baseline.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The chrome-devtools MCP server joined both clients' MCP lists after the
protocol was written (it is pending at Claude init and configured as a
stdio server in the Codex config). It runs outside the Codex sandbox
and reaches the network, and R8 has no pre-execution rule for it. The
watcher now logs each of its calls in both clients (never a halt), so a
trial's browser use shows in the report. A pre-execution deny would be
a treatment change, so it stays a decision for the command center.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
G15's "verified negative" was always unset, so the gate could never
show it. R4 makes G1 to G6' should_not for every item, so a valid trial
on a control task whose joins and stream-Loki agreement hold checks its
non-use of every item against the raw sources. G15 now counts such a
trial as the verified negative and lists, per trial, the items it did
use: those are should_not uses, a measurement rather than an
instrumentation failure. Regraded in memory: smoke-20261005f's gate-0
G1 trial and devcheck-cl7-20261006a's three G1 trials qualify, and each
shows a context-mode use on G1.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ells

The pilot spec's stage 3 (ten prompted oracle runs on Codex) had a
mechanism (--prompted) but no inputs, and the entries would have joined
the stage-2 prompted cells: they ran before gate 0 was checked, gate 0
then required each of them to complete (a censored oracle run, which
only drops a positive, would have stopped stage 4), and an entry's
task_id and instance replaced the organic task's prompt in tasks.json,
so the grader would have tagged that task's organic uses explicit.

- prepare.py: a prompted entry takes "stage" 2 (probes and canaries,
  cell prompted-<base>) or 3 (oracle runs, cell oracle-<base>); keys
  must be unique; a prompted task's own id is always prompted/<key>,
  and an entry's task_id and instance are kept as oracle_for.
- pilot.py: stages 3 and 4 both need gate0.json passing; stage 3 runs
  each oracle cell as one block before stage 4.
- stage3-oracles.json: the pilot spec's ten oracle runs (jcodemunch.P1,
  headroom.P2, semble.P1, socraticode.P1, context-mode.P1,
  search-first.P1, skill-creator.P1, variant-analysis.P1,
  diagnosing-bugs.P1, ast-grep.P1) on codex-native with C1's sandboxes,
  each the organic prompt after one line naming the item (the MCP
  server, $skill or sg). Frozen with the harness at stage 1.

Checked with stand-in clients (selftest-j): gate 0 graded the eight
stage-2 trials only, stage 3 refused while gate 0 failed, and with a
forged passing gate0.json it ran the ten oracle trials on lane
organic-e2e-prompted, one attempt each.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…te 0

The previous commit moved the gate-0 check ahead of stage 3, where it
also refused a resume at stage 5 or 6 that only collects and grades.
The check now applies only when stage 3 or 4 sessions would run.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…behind its header)

The live smoke-20261006a CL6 trial (Claude Agent SDK, jcodemunch.P1)
exited after 1.0 s with rc 1: prepare.py writes bin/run.py as a
two-line sys.path header (the SDK venv's site-packages, kept out of
argv because its path names an experiment word) followed by
sdk_claude.py, whose `from __future__ import annotations` must be the
first statement, so the file was a SyntaxError. That was CL6's first
live run; the self-tests stood in for the CLI, not for this file.

sdk_claude.py drops the future import (it needs none on Python 3.13),
and stage 1 now compiles bin/run.py and refuses the run if it does not
compile. Checked: header plus sdk_claude.py compiles, imports
claude-agent-sdk 0.2.163 from the venv's site-packages (its
ClaudeAgentOptions has effort and session_id) and parses its argv.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ted one

smoke-20261006a's G12 failed on context-mode.P1: stage 1 reused the
fixture template that a self-test (prepare.py --skip-oracle-tests) had
built a few minutes earlier for the same builder hash, so the frozen
D oracle for that card was null, and G12's recomputation with the tests
differed. A template built without the oracle tests now has its own
cache directory (suffix -nt), records oracle_tests_run, and is reused
only by a run with the same setting.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
smoke-20261006a stopped mid-run when another lane edited
~/.codex/omniroute.config.toml at 05:01Z: the only change was the
profile's default model (cx/gpt-6-astra to cx/gpt-6.1-sol), which
every Codex cell overrides (CL3 -m, CL7 and CL7b model; the frozen CL7
and CL7b profile layer already omits it). Protocol S7 does not list the
profile; the harness had added its raw bytes to the gated view. The
gated view now holds the parsed profile without the keys each launch
sets (model, model_reasoning_effort; one constant in common.py that
prepare.py's profile layer uses too), and the raw file hash moves to an
ungated info record. The 30-minute settle rule still reads the file's
mtime, as section 9.1 words it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…arrives before T

smoke-20261006c's claude-native trial (search-first.P1) started a
background Workflow and ended its turn at 576 s with "I'll write the
recommendation when it reports back". Claude Code in print mode held
the result event while the workflow ran (task_progress events until the
end) and wrote it only on the timeout's SIGTERM, at 900.7 s, with
duration_ms 575920. The launcher's complete-at-result rule compared the
result with its own kills only, so the trial was recorded complete
(rc 124, censored false).

- launcher.py: a result counts only if it reached the stream before T
  (result_before_t); one written at or after T censors as
  timeout_after_result.
- grade.py: effective_exit re-checks the rule on every exit row, so a
  run whose frozen launcher predates it is graded the same way, and
  the record names the override (grader_override).

Unit-checked: result at 900.7 s with T 900 -> timeout_after_result;
result at 524 s then the grace kill -> complete; no result -> timeout.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…eway entry is best-effort

Two G3 and G10 failures in the live smoke-20261006c were artifacts of
how a trial ends and of the gateway's known logging race, not of the
instrumentation:

- G3: the claude-env trial's ctx_batch_execute started at 10:30:06Z and
  was still running when the timeout ended the trial; the transcript
  then holds a "Connection closed" result written at 10:43:17Z, as the
  client exited, and Loki has no row for it. A call whose result was
  written at or after the trial's termination (the launcher's kill time,
  or launched time plus T for rc 124) is now marked terminated: never a
  completed use, and unresolved in G3 (agreement.unresolved_terminated),
  like a call with no result.
- G10: CL7b's three /v1/responses rows in the gateway call log have
  status 0 and their detail returns 404, the unfinished rows of a client
  that exits right after response.completed, so no thread join is
  possible. The command center's telemetry caveat (item
  task-ns2604-coop-20261005T200956Z) makes call logs best-effort and
  client-side telemetry the source. G10 now rests the route on the
  rollout's omniroute provider, records the joined gateway entry as
  gateway_entry_best_effort, and lists a missing one as a G10 gap.

Regraded in memory with this grader: smoke-20261006c passes G2-G10,
G12 and G14; G11 fails (forwarded effort not exposed) and G13 fails
(env-arm reads of host checkouts), both with their recorded gaps.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 6, 2026
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/ns2604-organic-harness-20261005 branch from 7dc41ec to 5085150 Compare October 6, 2026 11:33
…k-ns2604-coop-20261006T105529Z)

AMENDMENT-v1.1-20261006.md records decisions 1-8 with the item id beside the
protocol, which stays verbatim; the harness now follows them:

1. Censoring: T = 1,800 s and complete-at-result by default; each Claude trial
   records its final turn end and its result event; no result by T writes a
   no_result_diagnosis and holds the cell (HOLD.<cell>) for the operator.
2. Exposure: a CLI is exposed only through a native surface its own upstream
   installer put in place (mineru's skill, worktrunk's plugins); PATH-only
   targets stay out of OIR (not_exposed_path_only).
3. G13: host-checkout and other reaches are tags with their own OIR stratum;
   only gold or answer-source reads invalidate a trial or fail G13.
4. chrome-devtools: watcher-only logging, no pre-execution deny.
5. G10: the gateway entry is best-effort; fast-exit undercount recorded.
6. Meter: expected usage against remaining headroom (resetsAt honoured), no
   account-wide kills; rate-limited trials are marked and re-run.
7. One in-run re-baseline per run, never for trust-bearing keys, the Claude
   settings file or the arm-defining files; the trials in flight (one Claude
   trial, up to -j trials of the Codex cell, a straddled CL7b trial) are re-run;
   a change seen only at a block's end, or any second change, still stops it.
8. RP4: only the forwarded effort fields of pipeline details are kept; the
   operator's on/off record and the observed state are reported.

Decision 9 (gateway web-search wiring) is a host change and is not here.
Checked offline only: module imports, a symtable undefined-name scan, 56
synthetic helper checks and a read-only re-grade of smoke-20261006c.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
seathatflowsinourveins added a commit that referenced this pull request Oct 6, 2026
…k-ns2604-coop-20261006T132948Z) and the 1f81d64 P3

The command center decided at 13:29Z that a classifier of the commands a model
typed cannot converge, so G13 is now structural (harness/isolation.py):

1. Every listed answer source is hidden from each trial's mount namespace.
   The launcher (every CLI and SDK cell, the prompted and gate-0 cells) and
   block.py (CL7b, through the provider's codex_path_override, which points at
   a per-attempt wrapper) run the client's process tree under bubblewrap 0.11.1
   (/usr/bin/bwrap, unprivileged). Empty tmpfs: the coordination state (run
   roots with oracle runs, other trials' drafts and grades; the suite cards; the
   v1 captures) and the fixture cache (oracles.json). Empty tmpfs with the
   trial's own entries bound back: ~/.cache/ws (own fixture), ~/.cache/wsr (own
   prompt, settings, clone, -o file, the run's neutral binaries) and
   ~/.claude/projects (projects outside the experiment, and the own one). A
   fresh per-trial folder over the shared Codex sessions folder (the clone's
   alias), Claude's file history, context-mode's per-project stores and
   Claude's /tmp area; the trial's rollouts are published to the native
   sessions folder after it exits. The native home and client configuration
   stay visible and writable, the system runtime is read-only, the network and
   environment are unchanged. Options pass through --args (a memfd), so the
   namespace's PID 1 shows none; no --new-session, so the launcher's TERM
   reaches the client (it signals the tree below the wrapper, then KILLs the
   group after 30 s). systemd's InaccessiblePaths= fallback (systemd 259) is
   not needed: bwrap hosts every launch path.
2. G13 checks what was hidden (isolation.check): the launched row's receipt
   (wrapper argv, mount operations, hidden list with path and content sha256s)
   covers every listed location, nothing is bound back into a hidden root but
   the trial's own entries, the client tree ran in its own mount namespace
   (--info-fd), no sampled process was in the host's (nested sandboxes are
   counted apart), and stage 1's wrapper-only self-test passed
   (isolation-selftest.json; prepare refuses on a failure, gate 0 requires it
   and each stage-2 trial's receipt check). A trial is valid only if its own
   check passes.
3. The optional fanotify audit stays documented: a pid filter needs
   CAP_SYS_ADMIN (fanotify_init(2)), and the harness runs no sudo.
4. The command classifier (grade.reach) is a diagnostic tag only, reported
   under G13's classifier_diagnostic. The GPT micro-check of 1f81d64's F1 and
   F4 P2s concern it and are recorded as superseded.

The P3 of that micro-check: the deadline and completion decisions (the hold,
result-before-T, the censoring reason, the grader's effective_exit and its
no-result list) read the unrounded offsets (duration_exact_s,
time_to_result_exact_s, common.decision_times); the one-decimal fields are
presentation only.

Checked offline, no model call: harness/test_isolation.py, 23 of 23 (on the
harness at 1f81d64, 3 of its 17 runnable tests fail and 14 error); the
wrapper-only self-test, 43 probes hidden with ENOENT and 7 client start checks
(an S7 snapshot before and after it is equal); a symtable undefined-name scan
and imports; and a read-only re-grade of smoke-20261006c: every gate matches
the 10:48Z grade, G13 failing for want of receipts (that run predates the
wrapper), 0 of 16 trials valid.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/ns2604-organic-harness-20261005 branch from 1f81d64 to 9d4214e Compare October 6, 2026 14:27
…k-ns2604-coop-20261006T132948Z) and the 1f81d64 P3

The command center decided at 13:29Z that a classifier of the commands a model
typed cannot converge, so G13 is now structural (harness/isolation.py):

1. Every listed answer source is hidden from each trial's mount namespace.
   The launcher (every CLI and SDK cell, the prompted and gate-0 cells) and
   block.py (CL7b, through the provider's codex_path_override, which points at
   a per-attempt wrapper) run the client's process tree under bubblewrap 0.11.1
   (/usr/bin/bwrap, unprivileged). Empty tmpfs: the coordination state (run
   roots with oracle runs, other trials' drafts and grades; the suite cards; the
   v1 captures) and the fixture cache (oracles.json). Empty tmpfs with the
   trial's own entries bound back: ~/.cache/ws (own fixture), ~/.cache/wsr (own
   prompt, settings, clone, -o file, the run's neutral binaries) and
   ~/.claude/projects (projects outside the experiment, and the own one). A
   fresh per-trial folder over the shared Codex sessions folder (the clone's
   alias), Claude's file history, context-mode's per-project stores and
   Claude's /tmp area; the trial's rollouts are published to the native
   sessions folder after it exits. The native home and client configuration
   stay visible and writable, the system runtime is read-only, the network and
   environment are unchanged; a failed publish is recorded (finish_error),
   never the trial's loss. Options pass through --args (a memfd), so the
   namespace's PID 1 shows none; no --new-session, so the launcher's TERM
   reaches the client (it signals the tree below the wrapper, then KILLs the
   group after 30 s). systemd's InaccessiblePaths= fallback (systemd 259) is
   not needed: bwrap hosts every launch path.
2. G13 checks what was hidden (isolation.check): the launched row's receipt
   (wrapper argv, mount operations, hidden list with path and content sha256s)
   covers every listed location, nothing is bound back into a hidden root but
   the trial's own entries, the client tree ran in its own mount namespace
   (--info-fd), no sampled process was in the host's (nested sandboxes are
   counted apart), and stage 1's wrapper-only self-test passed
   (isolation-selftest.json; prepare refuses on a failure, gate 0 requires it
   and each stage-2 trial's receipt check). A trial is valid only if its own
   check passes.
3. The optional fanotify audit stays documented: a pid filter needs
   CAP_SYS_ADMIN (fanotify_init(2)), and the harness runs no sudo.
4. The command classifier (grade.reach) is a diagnostic tag only, reported
   under G13's classifier_diagnostic. The GPT micro-check of 1f81d64's F1 and
   F4 P2s concern it and are recorded as superseded.

The P3 of that micro-check: the deadline and completion decisions (the hold,
result-before-T, the censoring reason, the grader's effective_exit and its
no-result list) read the unrounded offsets (duration_exact_s,
time_to_result_exact_s, common.decision_times); the one-decimal fields are
presentation only.

Checked offline, no model call: harness/test_isolation.py, 26 of 26 (on the
harness at 1f81d64, 3 of its 20 runnable tests fail and 16 error); the
wrapper-only self-test, 43 probes hidden with ENOENT and 7 client start checks
(an S7 snapshot before and after it is equal); a symtable undefined-name scan
and imports; and a read-only re-grade of smoke-20261006c: every gate matches
the 10:48Z grade, G13 failing for want of receipts (that run predates the
wrapper), 0 of 16 trials valid.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/ns2604-organic-harness-20261005 branch 2 times, most recently from 2044b2a to 1f34363 Compare October 6, 2026 15:45
seathatflowsinourveins and others added 2 commits October 6, 2026 11:47
…e, normal tier, bind triples, public receipts

CC item task-ns2604-coop-20261006T143846Z:
- private /tmp, /var/tmp and /dev/shm per trial (bwrap tmpfs; Claude's /tmp area bound into the private /tmp);
- a per-trial ai-memory marker (workspace organic-e2e, project <trial_id>) bound above the fixture in the trial's
  namespace only; the grader checks every ai-memory call's returned scope: a page of another trial's scope, or a page
  an implicit-scope call returned (unverifiable), invalidates the trial; global queries are tagged;
- host-service tags (user systemd, Docker, WSL interop, ai-memory HTTP, gateway management routes, other loopback
  HTTP), diagnostic only;
- published receipts carry only the count and sha256 of the kept project names;
- the gateway's response cache is read from the allowlisted GET /api/cache only; gate 0 passes only with the semantic
  cache off; G13 fails a Codex trial with a semantic-cache hit or a call log marked cacheSource "semantic".

CC item task-ns2604-coop-20261006T144256Z: service_tier=default on every Codex cell (CLI line, SDK runner, CL7b
provider config), checked at stage 1, at launch and in G11, which also fails on a forwarded "priority" tier.

CC item task-ns2604-coop-20261006T151719Z (C1), GPT read of 2044b2a:
- P2-1: G13 validates every bind as an exact (operation, source, destination) triple of the plan, with the private
  folder derived from the trial id; no bind may re-expose an earlier cover; the receipt's options must match its
  operations;
- P3: the public receipt hashes every home-derived name; CL7b's options file and the self-test report are 0600;
- residual channels: --unshare-ipc; the gateway's call-log payload storage and reachability without credentials are
  recorded (counts and HTTP status only) for the command center;
- verification gap: CL7b's process tree gets the launcher's census (isolation.AppServerCensus).

AMENDMENT-v1.1-20261006.md records the rulings, the gateway findings the command center must decide, and the
verification. No pilot, smoke or live trial ran.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…om a trial (private runtime folder, no WSL interop)

The GPT read of 2044b2a, P2-2, upheld by CC item task-ns2604-coop-20261006T151719Z (C1), in a commit of its own:
- each trial gets an empty private runtime folder (bwrap --perms 0700 --tmpfs /run/user/$UID) and an empty /run/WSL,
  so the user manager's and session bus's sockets (systemd-run --user), rootless Docker's socket, the ssh-agent and
  gpg-agent sockets, and WSL interop (a Windows program would read the distribution from outside) are absent in its
  namespace; nothing is passed through (RUNTIME_PASS_THROUGH records the evidence);
- G13 lists the runtime folder and /run/WSL, so a receipt without their tmpfs, or one binding the host's runtime folder
  in, fails;
- negative tests (test_isolation.HostBrokers) attempt each connection inside a trial's namespace and expect failure;
  the stage-1 self-test probes the same (host_broker_probes), failing closed without contacting a reachable broker;
- the systemd and Docker tags stay as diagnostics.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
seathatflowsinourveins and others added 2 commits October 6, 2026 12:55
… per trial, the GPT read of a513616

CC item task-ns2604-coop-20261006T155742Z, section 2, approved by item task-ns2604-coop-20261006T164313Z:
- (A) Gate 0 amendment: the semantic cache stays on. The source evidence (OmniRoute v3.8.51 caches only explicit
  temperature-0 requests; codex 0.160.x sends no temperature) is pinned to the builds it was read at, and every trial
  records GET /api/cache before and after it: a hit, an entry change, or a missing reading voids the trial
  (common.gateway_cache_window, grade.gateway_cache_gate);
- (B) each trial runs with --unshare-net; its only routes out are explicit forwards, each with its reason
  (isolation.NET_FORWARDS): the gateway's /v1 only (netfilter.py, an HTTP path filter), OTLP exports, ai-memory's
  /mcp and scope-checked hook routes, and Claude's model egress to api.anthropic.com and platform.claude.com. G13
  requires the plan's network record, a namespace of the trial's own and the forwarder's record.

The GPT read of a513616 (CHANGES_REQUESTED), folded in:
- P1: call-log details only for ids the trial's own responses carried (X-OmniRoute-Request-Id), on the coordinator
  side, keeping only grading fields (common.gateway_calls_for_trial);
- P2: gate 0 and G13 require the self-test's verified denials (grade.closure_evidence);
- P2: G11 fails closed on missing or unrecognized forwarded-tier evidence (grade.tier_evidence);
- P2: ai-memory pages detected by each tool's response contract, envelopes normalized apart (grade.pages_returned).

Tests: 76 of 76 pass, client starts included (network negative tests, filter rules, cache-rule and tier negatives,
ai-memory contracts in both clients, the collector's own-id rule); the stage-1 self-test passes with 18 of 18 network
expectations. No pilot, smoke or live trial ran.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
… overlay, closed stores (separate, droppable)

CC item task-ns2604-coop-20261006T164313Z, section 3 (c):
- the home folder is a temporary overlay (bwrap --overlay-src ~ --tmp-overlay ~): nothing a trial writes there
  outlives it, except through explicit binds (its own fixture, clone, -o file, transcripts and private stores, and
  Claude Code's credentials, whose OAuth refresh rotates the stored token); projects outside the experiment are bound
  back read-only;
- empty tmpfs over each store holding other sessions' or trials' content: ai-memory's store and hook spool,
  agentsview's archive, codebase-memory's and jcodemunch's indexes, Serena's logs, Claude's plans, tasks and paste
  cache, and Codex's own folder (history, session index, logs, memories, goals, queue), whose entries a clone links
  to come back as temporary overlays; Claude's history is an empty private file;
- G13 lists every closure; one negative test per channel (test_isolation.ChannelClosure).

Tests: 87 of 87 pass; on the round-6 commit without this one, exactly its 11 closure tests are red. The stage-1
self-test passes: 79 probes ENOENT (30 in the closed stores), 7 of 7 clients, 18 of 18 network expectations.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/ns2604-organic-harness-20261005 branch from a513616 to 80be148 Compare October 6, 2026 17:03
…TABLE cells, the call-id calibration cell

CC item task-ns2604-coop-20261006T170607Z:
- (1) forwards only for the tools under test and their local dependencies, each with its reason, path filter, tool
  and negative test (isolation.NET_FORWARDS): vLLM 127.0.0.1:28231 (POST /v1/embeddings, GET /v1/models) and Qdrant
  127.0.0.1:21633 (GET /healthz, GET /collections, and data operations on /collections/<the trial's own
  QDRANT_COLLECTION_PREFIX>* only; socraticode 1.15.0 prefixes every collection and lists them before creating its
  own: dist/config.js:193-226, dist/services/qdrant.js:105-118, :1067, :1090-1100). [email protected]
  starts from the home's npm cache with npm_config_offline=true (no registry forward). Web tools and gh stay off;
  Claude's server-side web search is a treatment fact through the API forward. A tool under test that cannot run in a
  trial has its cells marked NOT-TESTABLE with the cause (isolation.tool_testability, grade.mark_testability), never
  NOT-READY;
- (2) the pilot's first Codex trial (gate0-G1) is the designated call-id calibration cell
  (grade.call_id_calibration, recorded in run.json), required by gate 0 and G11, with no foreign-id fallback.

Tests: 93 of 93 pass; on the round-6 head exactly the 7 round-6b tests are red. Self-test: 27 of 27 network
expectations, 79 probes ENOENT, 7 of 7 clients. No pilot, smoke or live trial ran.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/ns2604-organic-harness-20261005 branch from 80be148 to 50752dd Compare October 6, 2026 17:16
…ode closure confirmed (GPT read of 80be148)

The GPT read of 80be148 (CHANGES_REQUESTED, two P2s):
- P2-1, fixed: G11 fails closed unless every required call of the trial (its gateway forward's model-call
  X-OmniRoute-Request-Id log, netfilter.MODEL_CALL_PATHS) has collected tier and effort evidence
  (grade.call_coverage, required by g11_trial_ok). The collector keeps a placeholder for a failed detail, lists the
  unresolved ids and tags every call with its request id; collect.py no longer filters by thread. A missing or
  incomplete call fails G11 and is listed by id. Regressions: A good and B detail failed, A good and B unmatched, and a
  required call from another thread kept.
- P2-2: closed for Codex cells by the round-6b forwards (vLLM 28231, Qdrant 21633 prefix-scoped); recorded as
  NOT-TESTABLE for Claude cells, whose configuration points SocratiCode at 16333 and 8231 (nothing listens there).

Tests: 95 of 95 pass; on the round-6b head exactly the 3 round-6c tests are red. Self-test: 79 probes ENOENT, 7 of 7
clients, 27 of 27 network expectations. No pilot, smoke or live trial ran.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/ns2604-organic-harness-20261005 branch from 50752dd to aa3107c Compare October 6, 2026 17:34
…ors, own-name listing, strict call-id key, calibration first

The GPT read of 50752dd (CHANGES_REQUESTED, one P1 and three P2s):
- P1: only the Qdrant operations socraticode 1.15.0 performs are admitted (netfilter.judge_qdrant: collection get,
  create, delete, payload index, upsert, retrieve, delete, scroll and query on the trial's own prefix); grouped,
  batch, search, recommend, discover, snapshot and alias routes are refused; every body is parsed and every collection
  it names (with_lookup in both forms, lookup_from at any depth) must carry the trial's prefix
  (qdrant_selectors_ok). New required probes: a foreign body selector and grouped queries refused.
- P2: GET /collections answers with the trial's own names only, envelope kept, framing recomputed
  (filter_collection_list); a required probe (0 foreign names inside, 5 outside) and a two-trial test.
- P2: the call-id key is strict equality with the call log's id, with no correlationId substitution; negative case.
- P2: pilot.py runs codex-native-gate0 first, collects it and runs `grade.py calibration` (exit non-zero unless it
  passed, calibration.json 0600) before any other cell; a failure stops the pilot.
SocratiCode's NOT-TESTABLE cause for Claude cells now states the probed host ports.

Tests: 100 of 100 pass; on the round-6c head exactly the 6 round-6d tests are red. Self-test: 30 of 30 network
expectations, 79 probes ENOENT, 7 of 7 clients. No pilot, smoke or live trial ran.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/ns2604-organic-harness-20261005 branch from aa3107c to b2d44f7 Compare October 6, 2026 17:52
seathatflowsinourveins and others added 3 commits October 6, 2026 14:48
…tion first on the retry path (GPT read of b2d44f7)

P2, a model call without a request id disappeared from G11's coverage. netfilter.py now writes an admission row for every admitted HTTP request, before the upstream is contacted, and each outcome row names the same connection. summarize() counts the gateway forward's model calls from those rows (gateway_model_requests), keeps the request ids, and lists the calls whose response carried no id (gateway_model_calls_without_id: connection, time, method, path, outcome, status). A call with no outcome row, an unreachable gateway and a failed relay are calls without an id; a missing log gives null counts. The collector carries the count and the list into the trial's gateway record. grade.call_coverage and grade.call_id_calibration fail closed unless the admitted calls are counted, the count equals the request ids, no call lacks an id, no access-log row was unreadable and no id is shared; the calls are listed in G11's call_coverage and in calibration.json.

P2, --rerun-gate0-failures could advance before the calibration passed. pilot.calibrate_first is now the one sequence for stage 2's initial path and its retry path: run the calibration cell's pending work (the cell, or the failed G1 test), collect, run grade.py calibration, and stop with exit 2 unless it passed. On the retry path a failed G1 test runs first, the check runs even when G1 passed, and the other retries follow in the stage's cell order. A passing record is never read again; a record from an earlier run that does not pass gets one fresh read.

Tests (test_isolation.py, 108 with the client-start test skipped): netfilter's own Filter in front of a stand-in gateway (A with its id, B without, a call in flight, a gateway that is down), then collection and grading; and PilotStage2, which drives pilot.main with a recording step and no process. On b2d44f7's harness 10 of the 39 tests in the touched classes are red (8 fail, 2 error). The client starts (isolation.py selftest --clients) were not run for this commit: no Codex process may run on the host during the co-op's Codex window.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…g is read and filtered when the client asks for compression (separate commit)

Found while measuring the compression gap the GPT read of b2d44f7 left to validate. On this host Qdrant 1.19.1 answers GET /collections with Content-Encoding gzip (or br) when asked, and Node v24.21.0's fetch, which @qdrant/js-client-rest 1.18.0 uses, asks by default. Round 6d's listing filter could not read a compressed answer and replied 502: no foreign name passed, but SocratiCode's getCollections would have failed in every Codex cell while the self-test's probe, which sent no Accept-Encoding, reported the tool testable.

netfilter.py: a request whose answer the filter rewrites goes upstream without Accept-Encoding, and an answer that arrives compressed anyway is refused with 502, never passed through unread. Other routes are relayed as before. isolation.qdrant_listing_probe now asks as the client does, so the required listing expectation fails unless the listing was read and filtered.

Tests: netfilter's own Filter in front of a stand-in Qdrant that compresses on request (the listing is filtered, another route keeps the header, a listing compressed anyway gets 502), and the two-trial test asks with Accept-Encoding against this host's Qdrant. Module: 109 run, 1 skipped (client starts, not run during the co-op's Codex window). On b2d44f7's harness both new checks are red (502).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…vidence.json

Re-registers the branch's 20 new files under evidence/artifacts/organic-e2e-20261005/ (the protocol, the pilot spec, the 2026-10-06 amendment notes and the harness, with isolation.py, netfilter.py and the focused test module) on main's manifest (c1300c1) with scripts/host_receipts.py register_file, as the docs/lanes.md hot-file protocol requires. component_matrix.py --check and new_host_grand_list.py --check pass, so neither generated report is rewritten.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/ns2604-organic-harness-20261005 branch from b2d44f7 to 2fb12a9 Compare October 6, 2026 18:59
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Closed with a record, by the command center's ruling of 2026-10-07 on the open pull requests that had no recorded owner. Not merged; the branch claude/ns2604-organic-harness-20261005 stays on origin at 2fb12a9.

What it holds: the organic-invocation E2E v1.1 protocol, its pilot specification and amendment, and the promptfoo-driven harness with its run of record (21 files). The protocol text stays readable on the branch as history.

Superseded by: docs/decisions/2026-10-06-upstream-evidence-over-local-evaluation.md:61 on main (the code-navigation trial matrix row, which names this pull request and says to start no pilot or trial runs), and by the retention rule under review in #833, which replaces this harness with a bounded check in an upstream harness.

State at closing: the last cross-family read at this head asked for changes, and two findings remain open: A supported Responses alias is admitted but omitted from model-call coverage; Bulk collection overwrites accepted calibration evidence. No fix round is planned.

Reopen trigger: a dated decision that reinstates a paired organic-invocation protocol for the foundation. Reopen with gh pr reopen 786.

@seathatflowsinourveins
seathatflowsinourveins deleted the claude/ns2604-organic-harness-20261005 branch October 8, 2026 17:05
seathatflowsinourveins added a commit that referenced this pull request Oct 11, 2026
Codex's GitHub review of de4eed8 (4 P1, 3 P2), in both copies of the job:

- Correction: GitHub stores descriptions over 65,536 characters (REST
  update probes up to 1,048,577 stored whole; #786 has 75,726). The bound
  is the gate's own, 262,144 code points.
- The four decoders compose: every order of every subset, each at most
  once along a chain (65 forms).
- validate.py and the gate take gitleaks's private-key header form, so
  PKCS #8 ENCRYPTED and OpenPGP key blocks are caught.
- The gate does not read the graph-id form inside an http(s) URL; the
  graph-id name runs at most 256 characters to -code- in both scans
  (a quadratic 21-93 s run is now 0.05-0.1 s).
- macos-user-path takes any number of leading slashes.
- A test fails when validate.py gains a rule the gate does not carry.
- Publication order is answered in the record: the gate is the
  backstop; prevention is scanning before gh pr create or edit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
seathatflowsinourveins added a commit that referenced this pull request Oct 11, 2026
Codex's GitHub review of de4eed8 (4 P1, 3 P2), in both copies of the job:

- Correction: GitHub stores descriptions over 65,536 characters (its REST
  update keeps up to 262,144 UTF-8 bytes; #786 has 75,726). The bound
  is the gate's own, 262,144 code points.
- The four decoders compose: every order of every subset, each at most
  once along a chain (65 forms).
- validate.py and the gate take gitleaks's private-key header form, so
  PKCS #8 ENCRYPTED and OpenPGP key blocks are caught.
- The gate does not read the graph-id form inside an http(s) URL; the
  graph-id name runs at most 256 characters to -code- in both scans
  (a quadratic 21-93 s run is now 0.05-0.1 s).
- macos-user-path takes any number of leading slashes.
- A test fails when validate.py gains a rule the gate does not carry.
- Publication order is answered in the record: the gate is the
  backstop; prevention is scanning before gh pr create or edit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
seathatflowsinourveins added a commit that referenced this pull request Oct 11, 2026
Codex's GitHub review of de4eed8 (4 P1, 3 P2), in both copies of the job:

- Correction: GitHub stores descriptions over 65,536 characters (its REST
  update keeps up to 262,144 UTF-8 bytes; #786 has 75,726). The bound
  is the gate's own, 262,144 code points.
- The four decoders compose: every order of every subset, each at most
  once along a chain (65 forms).
- validate.py and the gate take gitleaks's private-key header form, so
  PKCS #8 ENCRYPTED and OpenPGP key blocks are caught.
- The gate does not read the graph-id form inside an http(s) URL; the
  graph-id name runs at most 256 characters to -code- in both scans
  (a quadratic 21-93 s run is now 0.05-0.1 s).
- macos-user-path takes any number of leading slashes.
- A test fails when validate.py gains a rule the gate does not carry.
- Publication order is answered in the record: the gate is the
  backstop; prevention is scanning before gh pr create or edit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
seathatflowsinourveins added a commit that referenced this pull request Oct 12, 2026
Codex's GitHub review of de4eed8 (4 P1, 3 P2), in both copies of the job:

- Correction: GitHub stores descriptions over 65,536 characters (its REST
  update keeps up to 262,144 UTF-8 bytes; #786 has 75,726). The bound
  is the gate's own, 262,144 code points.
- The four decoders compose: every order of every subset, each at most
  once along a chain (65 forms).
- validate.py and the gate take gitleaks's private-key header form, so
  PKCS #8 ENCRYPTED and OpenPGP key blocks are caught.
- The gate does not read the graph-id form inside an http(s) URL; the
  graph-id name runs at most 256 characters to -code- in both scans
  (a quadratic 21-93 s run is now 0.05-0.1 s).
- macos-user-path takes any number of leading slashes.
- A test fails when validate.py gains a rule the gate does not carry.
- Publication order is answered in the record: the gate is the
  backstop; prevention is scanning before gh pr create or edit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant