Skip to content

native-fault-behaviour: rebind the receipt to the released engine (2026-09-25 paper run, two independent observations) - #278

Merged
seathatflowsinourveins merged 7 commits into
mainfrom
claude/native-fault-behaviour-20260925
Sep 26, 2026
Merged

seathatflowsinourveins merged 7 commits into
mainfrom
claude/native-fault-behaviour-20260925

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

What

This PR re-runs the native-faults plan (C01, C02, C05, C04) once on the released adaptive-paper engine and rebinds the native-fault-behaviour gate receipt to that engine. The gate's 2026-09-24 binding amendment requires this re-run before the gate can be cited for the released engine. The gate status does not change (it stays established) and no gate flips.

  • receipt.json now holds one Alpaca paper run, 2026-09-25 18:25:13Z to 18:25:15Z. It ran from a clean worktree at origin/main ae3d3d37, on the paper account assigned to this gate lane as its only order writer. Result: native_faults_passed, process exit code 0 (retained).
  • The previous receipt (the 2026-09-24 18:58Z run on the pre-release engine 3b7ae710) is kept byte-for-byte as receipt-20260924t185811.json.
  • Also added: two independent observations of the run (table below), a sanitized run record, the run's host-clock evidence, a README section, and a dated "Rebinding, 2026-09-25 (status unchanged)" paragraph at the start of the gate note. The broker-state-failures entry of catalogs/us-equities/runtime-target.json records the same rebinding.
  • scripts/trading_gates.py now reports, without failing, when a file this receipt binds changes.
  • The branch contains current main 2b96f782 (merge commits 8db8be5f and f656308f, both without conflicts). None of the commits on main since ae3d3d37 touch the bound files. All 57 entries of adaptive-paper/source-hashes.json (075dab0e… on main since Paper alert: scrape only registered adaptive-paper exporters, and alert only on a registered silent one #284) equal the tree at this head.

Commits:

SOTA sources

Each change and the maintained repository or published reference it installs or follows. Every URL below returned HTTP 200 on 2026-09-25. The Alpaca, chrony, pathlib, SQLite and Launchpad pages were also read for the content cited. Package versions are the ones installed on the run host.

  • Native paper run, receipts and GET probes (the unchanged harness native-faults/harness.py and the engine at ae3d3d37): alpaca-py tag v0.44.0 (commit cc4cb3b7ba50ae250e621983c2779047fb16bb28), TradingClient(paper=True). Alpaca Trading API reference: Create an Order (POST /v2/orders), Delete Order by ID, Get Order by Client Order ID, and Orders at Alpaca for the sub-penny rule that C04 exercises.

  • Observation 1: the unchanged observer evidence/observe-native-faults-20260924.py (6f4b1c19…) on alpaca-py v0.44.0.

  • Observation 2 (evidence/observe-native-fault-20260925t184220z.py, GET only): the Python 3.12 standard library urllib.request and sqlite3, opening the ledger with SQLite's mode=ro and immutable=1 URI parameters. The Alpaca endpoints it reads:

    Its structure follows observation 1's script.

  • Host-clock evidence and analysis:

    • The chrony 4.5 documentation, matching the installed chrony 4.5-1ubuntu4.2. chronyc documents the tracking fields, and says a chronyc run as a non-root user falls back from the Unix socket to 127.0.0.1 and then ::1. chrony.conf documents makestep (a negative limit disables the limit), refclock PHC and command port 323.
    • Ubuntu's /usr/share/doc/chrony/README.container, shipped in that package. It documents SYNC_IN_CONTAINER, the -x fallback and that "multiple containers could fight over the system's time" (LP #1589780).
    • Linux v6.18 (commit 7d0a66e4bb9081d75c82ec4957c50034cb0ea449). In drivers/hv/hv_util.c:740-746, ptp_hyperv_info.name is "hyperv" and the clock is read from hv_get_adj_host_time, the Hyper-V host's time. Documentation/ABI/testing/sysfs-ptp documents clock_name.
    • For the read-only captures, the installed ps(1) (procps 2:4.0.4-4ubuntu3.3), ss(8) (iproute2 6.1.0-1ubuntu6.4) and systemctl(1) (systemd 255.4-1ubuntu8.17).
  • Report-only binding check (scripts/trading_gates.py: SOURCE_BINDINGS, bound_path, source_binding):

    • It follows the file's pre-existing source_matches_holds (lines 117-156 at 5b6014eb), which hashes an in-tree file resolved with Path.resolve() and relative_to. It reuses the file's RFC 6901 pointer() and hashes with hashlib.sha256.
    • The second-review fix follows the Path.resolve() documentation: "Changed in version 3.13: Symlink loops are treated like other errors: OSError is raised in strict mode, and no exception is raised in non-strict mode. In previous versions, RuntimeError is raised no matter the value of strict." It also relies on RecursionError being derived from RuntimeError.
    • The tests use unittest, laid out like tests/test_trading_gates.py.
  • As-run procedure (README "Run"): the Alpaca GET endpoints above, and the harness's own interfaces (harness.py:296-310, safety.py:39, safety.py:366).

  • Exemption (the reviewed exemption line that docs/decisions/2026-09-25-top-rule-sota-sources.md allows for a change with no possible upstream): these are this repository's own evidence records and prose:

    • the manifests/evidence.json sha256/bytes entries, maintained with the repository's scripts/validate.py and scripts/evidence_manifest.py;
    • the gate-note text in catalogs/us-equities/gates-20260922.json;
    • the broker-state-failures scope in catalogs/us-equities/runtime-target.json;
    • the text of catalogs/us-equities/README.md, README-safety.md, README-transport.md and native-faults/README.md.

    They follow docs/acceptance-evidence-policy.md. The independent review of this PR accepts or rejects this exemption.

Second review fixes (179ad84f, 967733ae)

The second independent review, at 0d5cde4b, found two major and three minor findings. All five are fixed, and none is rejected.

1. (major) No "SOTA sources" section, and CI had judged an outdated merge ref.

2. (major) runtime-target.json would still call receipt.json the 18:58Z run.

  • The broker-state-failures scope gets a dated sentence, "Rebinding 2026-09-25 (status string unchanged)". It says:
    • receipt.json is the 2026-09-25 18:25:13Z run on ae3d3d37: runner f157be18…, safety 7e00d5bb…, transport 2653682b…, order_contract 57405f75…, harness 19d0a9b9…, plan f276b26c…;
    • the 2026-09-24 receipts are kept as receipt-20260924t185811.json and receipt-20260924t143905.json;
    • the limits are unchanged.
  • README-safety.md and README-transport.md now say the sub-penny 422 was first seen in the 14:39Z run (receipt-20260924t143905.json), then at 18:58Z (receipt-20260924t185811.json) and on 2026-09-25 (receipt.json).
    • The "observed once" wording dates from 2d11464c5 (2026-09-24 15:44Z). That was after the 14:39Z run and before the 18:58Z one.
    • All three receipts record C04 as submit 422, then read 404.
    • Neither README is listed in source-hashes.json.

3. (minor) The Run section.

  • It now opens with why the procedure is needed. The harness has no expected-account input. It locks whichever account the env file names (harness.py:296-301) and refuses only a non-flat account (harness.py:308-310).
  • It then gives the as-run steps:
    1. A GET-only identity probe: sha256(account id)[:12] must equal the lane's private value, and the account must be ACTIVE, not blocked and flat, with the market open.
    2. No STOP file, and no earlier IN_FLIGHT or CLEANUP_REQUIRED marker.
    3. The run itself: in the regular session and never during a ladder session on this host, with a private --out and the exit code kept.
    4. The same probe after the run.
    5. A byte-identical copy into the tree, checked by sha256.
  • It says what the run record shows for the 2026-09-25 run: steps 1, 4 and 5, and step 3's private --out and retained exit code. Step 2 and step 3's no-ladder condition were not recorded separately. That run used a fresh state root, its accepted C01 buy shows that no STOP file was present, and the run lane reported that no harness or engine process was running before it (a worker report, not part of the run record).
  • No account value is committed.

4. (minor) source_binding could raise on a symlink loop.

  • Reproduced. On Python 3.12.3 it raised RuntimeError: Symlink loop from ..., and so did main().

  • Fix. The loop is now one warning: "bound path is a symlink loop; nothing was read". The receipt and manifest reads also catch RuntimeError, which covers the RecursionError a too deeply nested manifest raises.

  • Refinement of the finding. Python 3.13 does not raise OSError here. The pathlib documentation says it raises nothing in non-strict mode. On 3.13.15 the loop is reported as a missing file, both before and after this fix.

  • Tests. Two synthetic tests:

    • a self-referencing runner.py: one warning, status passed, errors [], exit 0;
    • a manifest nested 200,000 deep: one warning naming RecursionError.

    Both pass on Python 3.12.3, 3.13.15 and 3.14.7. As a negative control, both fail with an error against the unfixed checker on 3.12.3.

  • Left as is. The pre-existing source_matches_holds has the same except (OSError, ValueError) around resolve(). It is outside this PR's change, and a loop there fails closed with exit 1.

5. (minor) Four statements went beyond the evidence.

  • (a) Margin. On host time, submitted_at is 1.146 s after the window opens and canceled_at is 0.599 s before it closes. Corrected for the 0.22 to 0.35 s lead, the margins are 1.37 to 1.50 s and 0.25 to 0.38 s. Changed in the README Host clock section and in the run record's host.outcome_dependence.
  • (b) Stepping. The gate note, the run record (host.clock_summary and the limits line) and the README now say what the journal shows:
    • this distribution's NTP daemon stepped the clock 46 times: 45 steps back of 0.100 to 0.497 s, and one step forward of +0.124 s at 18:46:23Z;
    • the PHC0 daemon pulled the clock forward again by a mechanism, slewing or stepping, that was not captured.
  • (c) The ps basis. The run record now says the 21:37Z capture held no ps output, so that reading was not retained.
    • A new file, evidence/host-clock-process-view-20260925t224915z.txt, was captured at 22:49:15Z with read-only commands and nothing redacted. It shows:
      • only chronyd PID 2546733 (the systemd MainPID, started 14:09:44 EDT, which is 18:09:44Z, and the PID in the journal) and one child, 2546736, with the same command line;
      • two command sockets per loopback address;
      • ten queries still alternating between a PHC0 daemon and a second daemon.
    • The 21:37Z file is kept unchanged (25c2c6c9…) instead of appended to, so each file has one capture time.
    • The conclusion is still labelled an inference.
  • (d) Scope. The sentence in catalogs/us-equities/README.md now covers only the gates in SOURCE_BINDINGS (currently native-fault-behaviour). It also mentions drift in the manifest alone and bindings that cannot be checked.

Review fixes (0d5cde4b)

The first independent review (live-gates workflow, at 039ba041) found no blocker or major issue and three minor findings. All three were fixed in 0d5cde4b. One statement below was corrected by 179ad84f and is marked; the host-clock line under Limits was corrected too.

1. Host-clock evidence. The run record kept one chronyc snapshot referenced to PHC0 ("0.0009 s") and dropped the lines of that snapshot that showed instability. Changes:

  • The five chronyc snapshots taken around the run are now committed as byte-identical copies of the lanes' private files, evidence/chrony-20260925t*.txt (table below). They include the ladder lane's chrony-series.txt from 18:55:55Z to 18:57:15Z.

  • evidence/host-clock-diagnosis-20260925.txt is a read-only capture taken at 21:37Z, with the host name redacted.

  • The host section of the run record and a new "Host clock" paragraph in the README state what the evidence shows:

    • Offset during the run. The host clock was 0.22 to 0.35 s ahead of Alpaca's clock. The lower bound comes from c01: the ledger reserved its submit at 18:25:14.702052Z, before the POST was sent (safety.py:1116), and Alpaca stamped it submitted_at 18:25:14.480298Z. The upper bound comes from the GET probes 33 s before and 27 s after the run.
    • Two daemons. Two chronyd daemons steer the one kernel clock:
      • One follows PHC0. That is the Hyper-V PTP clock (/sys/class/ptp/ptp0/clock_name = hyperv), which carries the Windows host's time and runs about 0.27 to 0.29 s fast.
      • The other is this distribution's chronyd, which follows internet NTP. It was restarted at 18:09:44Z with clock control on and makestep 0.1 -1. From then until 19:00Z it logged 45 backward steps of 0.10 to 0.50 s (and one forward step).
    • The earlier "switch" was the two daemons. Ten consecutive chronyc queries alternate between the two daemons. The lane's 18:22:44Z NTP reading and its 18:24:39Z PHC0 reading therefore came from different daemons. Chrony did not switch sources.
    • No step reached the run. That daemon's steps nearest the run were at 18:24:55Z and 18:25:56Z, and the ledger's 21 request times increase monotonically.
  • Correction to the stage brief. The brief said the run "passed the engine's 0.25 s preflight". It did not, because that check is not part of the harness:

    • The check is runner.validate_preflight, clock_drift, at runner.py:703-704.
    • harness.py:42 imports only Controller, credentials, reconcile and save from runner.
    • prepare() (harness.py:296-314) reads the broker clock only for is_open and next_close.

    So the run neither passed nor failed that check. An offset of 0.22 to 0.35 s straddles its 0.25 s tolerance.

  • No case outcome depends on the offset. A clock that runs ahead makes quotes look older, not future-dated. Both observations' broker timestamps fall inside the receipt window. Corrected in 179ad84f: this said "at least 0.6 s of margin at each end". The end margin is 0.599 s on host time, and 0.25 to 0.38 s after the offset correction.

  • Time sync was not changed. It must be made single-source before the next timed paper run on this host, because a backward step during a run raises request_clock_moved_backward (safety.py:1100-1101).

2. Manifest entries. manifests/evidence.json now lists all files under native-faults/evidence/:

  • 5 that main already had but did not list;
  • 5 added by this PR's first two commits;
  • the 6 host-clock files of 0d5cde4b;
  • the process-view capture of 179ad84f.

It also lists the new test and refreshes the entries of every edited file. The file list is sorted with scripts/evidence_manifest.py --write. validate.py now hashes 5760 files.

3. Machine check of the binding. This is a keep-but-compare choice: scripts/trading_gates.py gets a report-only source-binding check.

  • What it compares. For native-fault-behaviour it compares the receipt's engine_sources_sha256 with the tree. That covers runner.py, safety.py, transport.py and ../order-contract/order_contract.py. It does the same for harness_sha256 and plan_sha256. For the three files that source-hashes.json lists, it also compares the receipt's values with that manifest.
  • What it reports. Each difference goes under warnings, and source_bindings carries the counts. Both appear in the default output.
  • It never fails. It does not change a status, rung readiness, errors or the exit code, so an unrelated PR cannot fail CI because of it. Since 179ad84f this also holds for a symlink loop and for a too deeply nested manifest.
  • Tests. tests/test_trading_gates_bindings.py has 12 tests:
    • Synthetic fixtures cover each drift case: a released engine change, drift in the manifest only, a harness, plan or order-contract change, a missing file, an absent binding, keys and symlinks that leave the tree, a symlink loop, a too deeply nested manifest, and an unreadable receipt or manifest.
    • Read-only repository tests keep the table aligned with the harness. They print any stale binding to stderr without failing.
  • Negative control. In a scratch copy with one line appended to safety.py, the checker listed the stale binding with status passed and rc 0. The repository test printed it and passed.
  • Alternatives rejected. A failing check (an error, or a binding member in the flip condition) would fail CI for every engine change until a new paper run. A unit test alone is not read at gate decisions.
  • Overturn condition. Make a stale binding an error for this established gate if a gate decision cites this receipt while the checker lists its binding as stale, or if the user makes a current binding a rung requirement. A dated amendment in the gate note does not clear the warning; only a re-run that rebinds the receipt does.
  • Engine freeze held. No engine module covered by source-hashes.json changed, and no file of this PR's diff against main is listed there. These files are identical at this head: runner.py f157be18…, safety.py 7e00d5bb…, transport.py 2653682b…, order_contract.py 57405f75…, harness.py 19d0a9b9… and plan.json f276b26c….

Evidence

Paths are relative to blueprints/us-equities/adaptive-paper/native-faults/ unless they start with ../, catalogs/, scripts/ or tests/. Hashes are at 967733ae.

Item Path sha256 Evidence class
Receipt (current) receipt.json 31c112e3f1ff4471543b5ca034ef879561467a85e6d456000971f075d605e90d native_paper
Receipt (retained, 2026-09-24 18:58Z, engine 3b7ae710) receipt-20260924t185811.json d7f1cf2f9eff872094ba3e89b8aa6c95247cf47ea98d7551db5a854566f8469c native_paper
Observation 1 record evidence/independent-observation-20260925t182513.json c9976640a3eacd06eb61cdd0a2bd703ad5f736d31ef75131ebc4eb5103185056 independent_observation
Observation 1 stdout (the unchanged alpaca-py observer evidence/observe-native-faults-20260924.py, 6f4b1c19…, 18:25:42Z, same session as the run) evidence/observe-native-faults-20260925t182513.stdout.json 14d71155650cd2afe8a09a3da1ac6789f70f2d24c59d1914752e9b23dae84c6b independent_observation
Observation 2 script (Python standard library only, GET only, redirects refused) evidence/observe-native-fault-20260925t184220z.py 6b9cf04569c16452c4b419e75dc1fd3a15267fc932bb027a535ea7fa386ba518 n/a
Observation 2 stdout (18:46:44Z, a separate session that did not start the run; exit 0, stderr empty) evidence/observe-native-fault-20260925t184220z.stdout.json 19ce56c3139510e449dd5dc6bb9e72395c314774044ed1ce0133457484a587fa independent_observation
Sanitized run record (tree binding, host clock, offline tests, GET checks, ledger readback) evidence/run-20260925t182513.json a096a306db8c31007309574aa339186365996597b11047cc8a98c53ae0a6b2d6 measured_local, with native_paper GETs and broker timestamps
chronyc before the run (18:24:39Z; PHC0 daemon) evidence/chrony-20260925t182439z-before-run.txt 6a5b39db0c87d55ce2ef7f7aa6afb48d45f9af8c683f47df83a132539fb7f31a measured_local (byte-identical copy)
chronyc at observation 2 (18:46:44Z; NTP daemon) evidence/chrony-20260925t184644z-observation-2.txt 911024b76d7df648f37432eac873778fafcde7a3fc08d05dcb84daead3a6e8b7 measured_local (byte-identical copy)
chronyc at the ladder decision (18:55:04Z) evidence/chrony-20260925t185504z-ladder-decision.txt ce0cbfdd5920625a7672bed4a99781ced0be2c890f15950a4134caf38a9ccac5 measured_local (byte-identical copy)
chronyc tracking, sources, sourcestats (18:55:18Z) evidence/chrony-20260925t185518z-ladder-decision.txt 93798e4280c8d630b756c1affc1782c75336bf225a1dec922d44181e1687465a measured_local (byte-identical copy)
chronyc series (18:55:55Z to 18:57:15Z) evidence/chrony-20260925t185555z-series.txt 52a77f3531831af7927876f09ab276f14acc5601c0ef4d665d7a3aa25012ab12 measured_local (byte-identical copy)
Host-clock diagnosis (21:37Z; PTP clock name, chrony configuration change, command sockets, alternating queries, chronyd journal 18:09Z to 19:00Z; host name redacted) evidence/host-clock-diagnosis-20260925.txt 25c2c6c9a797d6c4e43bb02c0f4b5e024d24e704ea2f0b0abb0b6afc8b61f619 measured_local
Host-clock process view (22:49:15Z; ps, systemd MainPID, command sockets, alternating queries; nothing redacted) evidence/host-clock-process-view-20260925t224915z.txt 22e7d6682be7666d9a6abbbd6a98b2299d17085b719ebd03a4d1242f791fedf5 measured_local
README README.md c248a884aa9a251dc6e0b60e2edbde38456e3d14ab390d7a5a2b04fbcc47dac1 n/a
Engine READMEs (sub-penny 422 citations) ../README-safety.md, ../README-transport.md cea19e941f514591c410b28d71909b8f240678074f7c5627b1609ccc74d03e38, 7b7837cd6866ef36271887edf261c0ab1862e04b49ff2dcbb2e3e74262fa6e23 n/a
Gate catalog catalogs/us-equities/gates-20260922.json 1534ffde0c013ee2761f381ce3130d5aefb02709c3ce1696041d1621f9bb5010 n/a
Runtime target (broker-state-failures rebinding) catalogs/us-equities/runtime-target.json a1c69546d898dfcd8790efa573f13d7b5cc797e3ef6b3ee5a1e0c0a4856064af n/a
Trading catalog README catalogs/us-equities/README.md 6c94bd6d4eaefeab854b76f715dba5b7efdb13678a950ebf740a4e66a1e13312 n/a
Gate checker scripts/trading_gates.py 06aadfbca9ee50371aac6e620fcda087f5843508afb3b81124b053673875a152 n/a
Binding-check tests tests/test_trading_gates_bindings.py 645bae30192a44f38495bceb1bd9ea659a4122f198fb4de0366f320f9f8eb272 local integration (synthetic fixtures)

Receipt cases. Every case passed and every case is native_paper:

Case Broker requests and outcome
C01: accept a resting buy (SPY 1 @ 385.67, bid 771.35) submit 200, pending_new, broker id recorded
C02: cancel the resting order cancel 204 plus 5 reads 200; ledger and snapshot canceled, filled 0
C05: cancel again repeat DELETE sent and answered 204, then read 200; no freeze; ledger before equals ledger after
C04: sub-penny rejection (308.5401) submit 422, then client-id read 404; ledger broker_refused {http_status 422, refusal sub_penny_minimum_price_variance}

Run totals: posts_reserved 2 of 4, transport_builds 1, stop_error null, interrupted null. Cleanup was flat, checked with runner.reconcile: 0 open orders, 0 positions, cash delta 0.00. The IN_FLIGHT marker was removed and no CLEANUP_REQUIRED marker was written.

Observation 2 matched the receipt on 29 of 29 checks (all_match: true, no mismatches). It sent 9 GETs, all 200 except the expected 404 for c04. It found:

  • A complete listing since started_at minus 300 s with exactly one order: c01, canceled at 18:25:14.525Z (inside the receipt window), filled 0, no fill activity.
  • c04 lookup 404: no broker order exists for it.
  • No account fill activity in that window, 0 open orders, 0 positions.
  • Cash and equity equal to the pre-run probe (compared, not printed).
  • plan.json equal to the receipt's plan_sha256.
  • A read-only, immutable ledger cross-check: c01's broker id equals the broker's order, and c04 is broker_refused.

Its 8 fields that overlap with observation 1 have identical values.

Engine binding (measured_local, recomputed at this head; scripts/trading_gates.py reports this comparison as source_bindings: {"native-fault-behaviour": {"bound": 6, "stale": 0}}):

File sha256 Equals the receipt Equals source-hashes.json
../runner.py f157be180d0cf19393137e41871318476db24aea775d05a5b3b95ea8bd5dc1a6 yes yes
../safety.py 7e00d5bb60db2f214ffab5966d086e1d2c705ef40489fa147ec24884b802d3ed yes yes
../transport.py 2653682b325f3349465abe1f7d324c49e89e8ae48697c1f4d8802a6cc55d86dc yes yes
../../order-contract/order_contract.py 57405f752fc933a6f09a5b2f0eb46482f94a780aa818dd0b73d7149a1fe58025 yes not listed there
harness.py 19d0a9b97ec5… yes (harness_sha256) n/a
plan.json f276b26c1625… yes (plan_sha256) n/a

At the run, ../source-hashes.json was d14c8d72…. At this head it is 075dab0e… (as on main since #284, which changed only its metrics.py and metrics-test entries), and all 57 of its entries equal the tree.

Broker state. These are GET-only reads of the lane's paper account. Identity was checked by fingerprint comparison, which is not printed, and no balance is recorded.

When (UTC) Source State
18:24:40 (before) run-stage GET probe ACTIVE, not blocked, 0 positions, 0 open orders, market open; no harness or engine process running
18:25:42 (after) run-stage GET probe and observation 1 0 positions, 0 open orders, cash and equity unchanged
18:46:44 observation 2 (separate session) 0 positions, 0 open orders; only the run's own order since the run started
18:55:30 later ladder-1x decision probe (GET only; no order placed) flat: 0 positions, 0 open orders

Checks run

The validators, the targeted tests and gitleaks ran at f656308f (which contains main 2b96f782), and validate.py, evidence_manifest.py --check and gitleaks again at 967733ae, which changes only the README and its manifest entry. The full suite ran at 179ad84f. Each command was prefixed with rtk proxy so the output is raw. No order, trading-API call, market-data read or IB Gateway connection was made for these fixes.

Command Result
python3 scripts/validate.py rc 0: {"components": 69, "hashed_files": 5760, "profiles": 4, "receipts": 149, "status": "passed"}
python3 scripts/evidence_manifest.py --check rc 0: {"files": 5760, "status": "passed"}
python3 scripts/trading_gates.py --check rc 0: status passed, errors [], flip_candidates [], warnings [], source_bindings native-fault-behaviour bound 6 stale 0. native-fault-behaviour stays established. rung_ready sim true, paper true, live false; live blockers unchanged: leverage-ladder-1x/2x/4x, ibkr-local-acceptance, live-go.
python3 scripts/validate_catalogs.py rc 0
The other validate.yml validators: host_receipts.py validate (132 receipts), validate_foundation.py, landscape.py, audit_reports.py --check, validate_convergence.py --all-recorded, build_verdicts.py --check, component_matrix.py --check, new_host_grand_list.py --check, gap_crosswalk.py build --check, gap_wave_ledger.py ... --check, build_ecosystem.py --check all rc 0
python3 -m unittest tests.test_trading_gates tests.test_trading_gates_bindings tests.test_evidence_manifest tests.test_validate tests.test_catalogs 147 tests, OK
<pinned adaptive-paper-20260921 runtime, Python 3.12.3>/bin/python -m unittest tests.test_native_faults_min tests.test_adaptive_paper_source_hashes_manifest tests.test_trading_gates tests.test_trading_gates_bindings 69 tests, OK
tests.test_trading_gates_bindings on Python 3.12.3, 3.13.15 and 3.14.7 12 tests, OK on each
The two new tests against the unfixed checker (Python 3.12.3; negative control) both error: RuntimeError: Symlink loop ... and RecursionError
uvx --offline pyflakes scripts/trading_gates.py tests/test_trading_gates_bindings.py (pyflakes 3.4.0) clean
Full suite, ecosystem-bounded-run python3 -m unittest (the host's bounded wrapper) 5626 tests: 9 failures and 2 errors, all outside this change. All are SIGINT-handling tests in test_adoption_version_probes, test_adoption_launchd and test_adoption_bootstrap_macos; 629 skipped. The same three modules, re-run at 179ad84f without the wrapper: 213 tests, OK (12 skipped). CI runs the full suite at the pushed head.
gitleaks git --log-opts="origin/main..HEAD" --no-banner --redact --exit-code 1 . (guarded ecosystem gitleaks) rc 0 at 967733ae: 5 commits scanned (the two merge commits carry no patch), about 205 KB, no leaks, no exclusions
Privacy grep of the lines added by 179ad84f (223) and 967733ae (home paths, user and host names, emails, key and UUID patterns, balances, private IPv4) 0 matches
GitHub CI at 967733ae 21 checks pass and 3 are skipped by design (zizmor-online, zizmor-sarif-upload, osv-sarif-upload). The validate job (run 36199788802) checked out refs/pull/278/merge = 6dd57d1f, "Merge 967733a… into 2b96f78…", which contains 39e18ed5 and has the same tree as 967733ae; its full unit suite ran 5631 tests, OK (648 skipped). sota-sources logged "SOTA sources section present (5568 characters)." Every check the live ruleset requires (validate, token-report, secret-scan, dependency-review, osv-scanner, verdict-review-gate, validate-macos) passed, and so did sota-sources, which .github/main-ruleset.json requires since #294 but the live ruleset does not list yet. This body edit re-runs validate.yml through its edited trigger.

Recorded at the run and not re-run here (from the run record): the offline suite passed under the pinned runtime before the run (31 OK). Observation 2's synthetic self-test passed 24 of 24: a matching world exits 0, 12 injected mismatches exit 1, a wrong account exits 3, an unsafe env file exits 2 without a request, a redirect is refused, and only GET is sent. The self-test stays in private scratch and is not committed.

Limits

  • One run, on one host, with one paper account, against the paper endpoint only.
  • C05's repeat DELETE was answered 204 again, so the engine's handling of a 404 or 422 cancel refusal is still tested offline only.
  • C04's 422 is paper-endpoint evidence.
  • Ambiguous or in-flight submit faults (timeouts, 429, 5xx, partial fills, restart during a submit) were not exercised natively.
  • The flip condition checks only /status. The binding check in scripts/trading_gates.py is report-only: after a change to runner.py, safety.py, transport.py, order_contract.py, harness.py or plan.json, it lists a warning, but the gate stays established and the check still passes.
  • Both observations use the same broker API and account as the harness. GETs cannot show the run's own HTTP answers or the order of its requests.
  • Observation 1 came from the session that started the run. Observation 2 came from a separate session. The ledger cross-check reads the engine's own record.
  • Host clock: 0.22 to 0.35 s ahead of Alpaca during the run. Outside the run this distribution's NTP daemon stepped it back by 0.10 to 0.50 s about once a minute, and the Hyper-V PHC0 daemon pulled it forward again by a mechanism that was not captured. Time sync was not changed, and it must be made single-source before the next timed paper run on this host.
  • Three points in the host-clock analysis are inferences or transcriptions, labelled as such in the run record:
    • that the PHC0 daemon runs outside this distribution's process view, now based on the 22:49:15Z capture;
    • the tighter 0.2545 s bound, which holds only if Alpaca stamps submitted_at before it answers the POST;
    • the 18:22:44Z reading, which is transcribed from the run lane's notes because its chronyc output was not saved.
  • The as-run procedure is documentation. The harness still has no expected-account input, so the identity probe remains an operator step.
  • Integration: open PR Trading gates: user_decision evidence, readiness that needs holding evidence, and a signed live-go #295 edits the same line of catalogs/us-equities/README.md and also scripts/trading_gates.py, catalogs/us-equities/gates-20260922.json (other gates) and manifests/evidence.json. Whichever PR merges second must keep both sides: Trading gates: user_decision evidence, readiness that needs holding evidence, and a signed live-go #295's text and this PR's SOURCE_BINDINGS sentence, and both checkers' changes, including the warnings and source_bindings keys. It must then recompute the manifest entries and re-run evidence_manifest.py --check, validate.py and trading_gates.py --check.
  • 179ad84f and 967733ae have not yet had their own independent review. Under the standing merge rule, that review is needed before merge.

Not established by this PR

  • No gate status change. native-fault-behaviour was already established, and the checker lists no flip candidate.
  • The live rung is still not ready: leverage-ladder-1x/2x/4x, ibkr-local-acceptance and live-go still block it. Live orders are not authorized, and live-go is untouched.
  • Nothing here covers IBKR or a live endpoint.

🤖 Generated with Claude Code

… run passes C01, C02, C05, C04

receipt.json is now one live Alpaca paper run at 2026-09-25 18:25:13Z on the
released adaptive-paper engine (origin/main ae3d3d3): native_faults_passed,
process exit code 0 retained, 2 of 4 POSTs, one transport build, cleanup flat
(0 open orders, 0 positions, cash delta 0.00). It binds harness 19d0a9b9 and
plan f276b26c (unchanged) and engine sources runner.py f157be18, safety.py
7e00d5bb and transport.py 2653682b, equal to adaptive-paper/source-hashes.json
(all 57 entries matched the tree), plus order_contract.py 57405f75. This is the
re-run the native-fault-behaviour binding amendment of 2026-09-24 requires.
C05's repeat DELETE was answered 204 again; C04's sub-penny submit was answered
422, then the client-id lookup 404, ledger broker_refused.

The 18:58Z order-contract-engine receipt is retained byte-for-byte as
receipt-20260924t185811.json. Adds the independent alpaca-py observation (the
unchanged observer script, exit 0: one prefixed order, c01 canceled unfilled,
no c04 order, flat) and a sanitized run record (tree binding, clock check,
offline tests 31 OK, GET flat checks before and after, ledger readback). No
gate status changes; the gate note gains a dated rebinding paragraph. No
credential, account id, account fingerprint or balance is recorded.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-09-25 run

A second independent observation of the 2026-09-25 18:25Z native-faults paper
run, made at 18:46:44Z by a subagent session that did not start the run:
observe-native-fault-20260925t184220z.py (sha256 6b9cf045..., Python standard
library only, GET only, redirects refused, wrong account exits 3) and its
retained stdout observe-native-fault-20260925t184220z.stdout.json (sha256
19ce56c3...; stderr empty, exit 0). Nine GETs, all 200 except the expected
c04 404; 29 of 29 checks against receipt.json (sha256 31c112e3...) matched:
one prefixed broker order (c01 canceled, filled 0, no fill activity), no c04
order, no account fill activity since started_at minus 300 s, 0 open orders,
0 positions, cash and equity equal to the pre-run probe (compared, not
printed), plan.json equal to plan_sha256, and a read-only ledger cross-check.

The README gains a paragraph on this observation and its limits, the dated
2026-09-25 rebinding paragraph of the native-fault-behaviour gate note gains
one sentence citing it, and manifests/evidence.json carries the new sha256
and bytes of both files. Gate status unchanged (established); no account id,
credential, fingerprint, balance or host path is recorded.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@seathatflowsinourveins seathatflowsinourveins added the lane:trading Trading lane: sim, paper and live north star label Sep 25, 2026
@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Independent review (trading-lane coordinator, a different session from the run and both observers), 2026-09-25: agree. Ready to merge.

Checked against current main (0074a0c):

  • Trial merge. native-fault-behaviour: rebind the receipt to the released engine (2026-09-25 paper run, two independent observations) #278 merged onto main clean, with no conflicts.
  • Checks on the merged tree:
    • validate.py, evidence_manifest.py --check, trading_gates.py --check (passed, no flips) and validate_convergence.py --all-recorded pass.
    • tests.test_native_faults_min, tests.test_adaptive_paper_source_hashes_manifest and tests.test_trading_gates pass on the pinned adaptive-paper runtime: 57 OK.
  • Binding. Each entry of the receipt's engine_sources_sha256 equals the current file on main: runner.py, safety.py, transport.py and order-contract/order_contract.py. So do harness_sha256 and plan_sha256.
  • Retention. receipt-20260924t185811.json is byte-identical to main's previous receipt.json.
  • Gate. The gates-20260922.json edit replaces the 2024-09-24 binding amendment with a dated "Rebinding, 2026-09-25 (status unchanged)" note. native-fault-behaviour stays established, with no flip candidates.
  • Privacy. The added lines contain no home paths, key-shaped strings or UUIDs.

Scope, which matches the PR's own limits: one paper run on one account. C05's repeat DELETE was answered 204, so the 404/422 cancel-refusal handling remains offline-only evidence. Ambiguous submit faults were not exercised natively.

🤖 Generated with Claude Code

@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Trading lane, 2026-09-25: notice before merge.

The session that recorded this run isn't among the active sessions on this host, and the session that asked for a lane label doesn't own it.

Why merge now:

  • All CI checks are green.
  • The PR is mergeable onto current main, and the trial-merge checks pass (independent review above).
  • It changes evidence only: native-fault-behaviour stays established, with no gate flip.

Per the user-approved merge etiquette for idle owners, the trading-lane coordinator will squash-merge it at its next check, unless the owner objects here first.

🤖 Generated with Claude Code

@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Owner session (live-gates workflow), 2026-09-25 21:28Z: please hold the merge.

An independent review of this PR's head (039ba041) by the live-gates workflow raised three minor findings. None is fixed yet:

  1. Host-clock evidence. The run record and README cite chrony's 0.0009 s against PHC0, but they leave out the instability lines from the same snapshot and the later measurements.
  2. Manifest gap. manifests/evidence.json lists none of the files under native-faults/evidence/.
  3. Unchecked rebinding. Nothing machine-checks that the receipt is still bound to the engine files.

Under the standing merge rule, a gate PR merges only after its independent review's findings are resolved and the required checks pass. The fixes are being pushed to this branch now, and the PR body will list them. Please don't merge until that push lands and its CI passes.

🤖 Generated with Claude Code

@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Trading lane, 21:3xZ: holding, as the owner asked. The earlier merge notice is withdrawn. #278 will not be merged by the trading lane. Once your fix push lands and its CI passes, merge it yourself, or ask here and I'll re-check the new head against main first.

🤖 Generated with Claude Code

…ries, report-only binding check

Resolves the three minor findings of the first independent review of this PR.

1. Host clock. Commit the five chronyc snapshots taken around the
   2026-09-25 run. Each is byte-identical to the lane's private file. Also
   commit a read-only diagnosis capture (host name redacted). The run record
   and the README now state:
   - The host clock was 0.22 to 0.35 s ahead of Alpaca during the run.
   - Two chronyd daemons were stepping the clock outside the run: one on
     Hyper-V PHC0, and this distribution's NTP daemon, restarted at 18:09:44Z
     with makestep 0.1 -1.
   - The harness runs no host-clock preflight. The engine's 0.25 s
     clock_drift check is in runner.validate_preflight, which the harness
     does not call.
   - No case outcome depends on the offset.
   Time sync was not changed.

2. Manifest. Add sha256 and bytes entries to manifests/evidence.json for
   all 16 files under native-faults/evidence/ and for the new test. Refresh
   the entries of the edited files, then sort with
   scripts/evidence_manifest.py --write.

3. Binding check. scripts/trading_gates.py now compares the receipt's
   engine_sources_sha256, harness_sha256 and plan_sha256 with the tree and
   with source-hashes.json. It lists each difference under warnings and
   reports source_bindings counts. The check is report-only: it never
   changes a status, rung readiness, errors or the exit code.
   tests/test_trading_gates_bindings.py covers it with synthetic fixtures.

No engine module covered by source-hashes.json is changed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings in #294 (top rule and the required sota-sources check) and the other
main commits since c9d74ea so CI judges this PR against current main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… procedure, symlink-loop warning, evidence wording

- catalogs/us-equities/runtime-target.json (broker-state-failures scope): dated
  2026-09-25 rebinding sentence; receipt.json is the 18:25:13Z run on
  ae3d3d3 and the 2026-09-24 receipts are retained under dated names.
- README-safety.md and README-transport.md: the sub-penny 422 citation now
  points at the retained 2026-09-24 receipts and the 2026-09-25 run.
- native-faults/README.md Run: the as-run procedure (GET-only identity probe,
  STOP and marker check, private --out, retained exit code, byte-identical
  copy) and why the harness needs it (no expected-account input).
- scripts/trading_gates.py source_binding: a symlink loop (RuntimeError on
  Python 3.12) and a too deeply nested manifest (RecursionError) become
  warnings; two synthetic tests, verified on Python 3.12.3, 3.13.15, 3.14.7.
- Evidence wording: end margin 0.599 s on host time, 0.25 to 0.38 s after the
  offset correction; the NTP daemon stepped the clock and the PHC0 daemon's
  mechanism was not captured; the ps basis of the process-view inference was
  not retained at 21:37Z and is now a dated 22:49:15Z capture; the checker
  sentence in catalogs/us-equities/README.md is scoped to SOURCE_BINDINGS.
- manifests/evidence.json: sha256/bytes for the edited files and the capture.

No engine module covered by source-hashes.json changed. No order, trading-API
call or market-data read was made.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Keeps the branch current with main after #296, #297, #291 and #298 so CI
judges it against the current base.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The run record shows steps 1, 4 and 5 and step 3's private --out and exit
code. Step 2 and the no-ladder condition rest on a fresh state root, the
accepted C01 buy (no STOP file) and the run lane's report that no harness or
engine process was running, which is not part of the run record.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@seathatflowsinourveins
seathatflowsinourveins merged commit 564a16a into main Sep 26, 2026
28 checks passed
@seathatflowsinourveins
seathatflowsinourveins deleted the claude/native-fault-behaviour-20260925 branch September 26, 2026 00:00
seathatflowsinourveins added a commit that referenced this pull request Sep 26, 2026
Re-registered on origin/main 564a16a (after #278) with
scripts/host_receipts.py register_file (docs/lanes.md hot-file protocol):
catalogs/us-equities/README.md, catalogs/us-equities/gates-20260922.json,
scripts/trading_gates.py and tests/test_trading_gates.py updated; the decision
record docs/decisions/2026-09-25-live-go-authorship-control.md added.
component_matrix.py --write and new_host_grand_list.py --write left their
reports unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
seathatflowsinourveins added a commit that referenced this pull request Oct 4, 2026
…vidence, and a signed live-go (#295)

* Trading gates: user_decision evidence, readiness that needs holding evidence, and a signed live-go

- scripts/trading_gates.py:
  - Adds the evidence class user_decision. It is valid only for a gate owned
    by user-decision whose flip_condition is null.
  - rung_ready and blocking now count a required gate only while it is
    recorded established and its condition holds. Simulation V1 of the
    2026-09-25 readiness review had shown status failed alongside
    rung_ready.live true.
  - A top-level authorship block names a detached SSH signature per gate,
    checked with `ssh-keygen -Y verify`. The live-go gate must name one, and
    it holds only when that signature verifies. It fails closed in each of
    these cases:
    - the document, signature or allowed_signers file is absent or empty;
    - a path resolves outside the tree;
    - ssh-keygen is missing, times out or exits non-zero.
  - Recorded established, live-go must carry user_decision.
  - The checker writes nothing.
- catalogs/us-equities/gates-20260922.json:
  - Adds live-go's authorship control: docs/decisions/live-go.md.sig,
    docs/decisions/live-go.allowed_signers, principal live-go-signer,
    namespace live-go@native-agent-stack.
  - Adds a dated live-go note.
  - No status, flip condition or evidence class changes.
- tests/test_trading_gates.py: 17 new tests. The real-signature tests use
  throwaway ed25519 keys in temporary directories. The live-go fixture in
  the readiness test now carries its control.
- catalogs/us-equities/README.md: the user's one-time setup and per-go
  steps.
- docs/decisions/2026-09-25-live-go-authorship-control.md: the evidence,
  the alternatives and the conditions that would overturn this choice.

No key, signature, allowed_signers entry or live-go.md was created. live-go
stays user_decision.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Resolve the independent review of the checker hardening

- README per-go steps: re-register the gates file in manifests/evidence.json
  (scripts/validate.py fails on an unregistered edit), run validate.py and
  evidence_manifest.py --check, commit the manifest with the go, rebase per
  the hot-file protocol, and open the PR with the required SOTA sources
  section. The valid-before expiry and revert path carry the same steps.
- gates-20260922.json: the top-level scope now defines readiness as
  established AND holding now, and names live-go (no flip condition, flipped
  only by the user) as the exception to the flip-candidate rule; the
  authorship note lists the symlink-loop case.
- trading_gates.py: resolve(strict=True) in authorship_holds and
  source_matches_holds; a symlink loop (RuntimeError on Python 3.12 and
  earlier, OSError from 3.13) now fails closed with JSON output and no host
  path instead of a traceback. Tests cover both paths and main()'s output.
- Decision record: pin OpenSSH V_9_6_P1 as tag object b24f772e, commit
  8241b9c0 (and git v2.43.0 as tag object c089584a, commit 564d0252); state
  the symlink-loop case and the untested ed25519-sk boundary.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Register the checker-hardening files in manifests/evidence.json

Re-registered on origin/main 564a16a (after #278) with
scripts/host_receipts.py register_file (docs/lanes.md hot-file protocol):
catalogs/us-equities/README.md, catalogs/us-equities/gates-20260922.json,
scripts/trading_gates.py and tests/test_trading_gates.py updated; the decision
record docs/decisions/2026-09-25-live-go-authorship-control.md added.
component_matrix.py --write and new_host_grand_list.py --write left their
reports unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Hot-file protocol: reset manifests/evidence.json to the merge base before the final hot-file commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Reapply this branch's manifests/evidence.json edits on the merge base (hot-file protocol: every hot-file edit in the last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: seathatflowsinourveins <234074349+seathatflowsinourveins@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Scout <scout@local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:trading Trading lane: sim, paper and live north star

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant