3a9690fd42d274b5259bab945367af33e40761c7a9291c4d940d67f2fbf6302e build/can-gateway.bit 7fa1da41f6db81a0b5ecf7adf8d55fb751a2ec940314d07048179b19b82821a7 build/firmware.bin cb2882871d6ca0fb5ed55e11264c6f6cee3c0235c76de00571b0594d0517b8a0 build/firmware.elf e78f5060eb3ee30dd379e1bcb7cdd5989fa548aebe1da1dcad30c879734a9c7a build/build.log e6db982845a32023b5c1d3b13e6022ada053f890176c7f62c792f6833801d491 build/tool-versions.txt 634a337031cd35986c7a5a0f91de787b05cd2ba6385945b45a80005989ad7f8c build/neorv32_imem_image.vhd 53747f9c99464b3fc27d93694709f0b59c80ba6c77851ee40372069c317f17d9 captures/uart-can-gateway-001.txt 26103dbf8f7a57072cd299140ed5af82f2f23b15c5edda2a0e7bbedbe12b93c4 inputs/build.sh 632f23af5d70cf115703da0b14bffff81b0d8958b2aa6a569a03dbbed887ca4c inputs/local-source-sha256.txt e75d05482edf2c55681070f5e27b3b7291aad770ccef4b92e27003bb9196bcbd inputs/run_capture.py 2ab92d325f679fa435839207ff19bee860009616dc30b0338a7953c18e087f3d manifest.json e4306f8015927dbc9d088c217097634b9fedd18b7e67871ddbc0fc64f4244b1d README.md 8a99010faab2d12cebfdc6ecb31a424ccdec67f80842dd8382e3ccffc3611cae README.md 9e66e386799573720af536e0b421b212d068b7c61e6c3ae12cbd7837470b686c manifest.json 1aa32af5745731fa2c3399e6dc6b8019a24e64198e34e983dcd808cd99eba5d8 README.md dc7c8282ba43061c017d4cd8d7df98b408ba78bbe06481c3712e07f3421b12b1 manifest.json 01a5ad283b61b04befb5313f83fc67d17479cd2287d88f14ad35b5b31aa02ce7 README.md 4e27b5da785da084c3874e13b06cbcdeabf50b44edd03b6ddcf0f22f03ab570f manifest.json 62537a4b9ddb53451f8b10f6b482386f56550d8468a11525538957f7f808ee9a README.md 5e2735b4731ae6c33e2de4486fa2e836c372e13b43eff65bc5e8ff3f92475ae1 manifest.json 021fe5894dc9fca71484ce045013f5633e9813d42f68f6d0012c7054d31195b3 README.md 6f2fac78d72138e3f39c5e92d80361599831b8a6eef9af4186766b01640f0368 manifest.json 5ba48d1be4d0ada05ebf05c87339467991d617fbaea2908aa554dfec5afaa816 README.md eccfc12780ea9414351eca533315d8069d7fb492d7df08341b47c20435ee7be8 manifest.json 45a8106292d669f5d820b67c0245ca751584eb10fcef716015fa86eddb90c80f README.md 24508faffdd85200457db878a373d072f1a018439ceea02bfae87593c2f45137 manifest.json 378cc494ff2d801741081521ffa1a03d419fb5956ed51dd54730004bc81f887b README.md 5f97951ce445b89b58f44a68d8b115a47d4a7bdaf6e9866417439361e1b2db2f manifest.json 6c955bc65a8dc0eb8bccdb0ed31e03f33267240474d904d41983eda0c641aeaf README.md 083c504b34197c0980a144ee33fcd7a53edcb14a68726f22ffde6bbffb0329d7 manifest.json 3a9690fd42d274b5259bab945367af33e40761c7a9291c4d940d67f2fbf6302e build/can-gateway.bit 7fa1da41f6db81a0b5ecf7adf8d55fb751a2ec940314d07048179b19b82821a7 build/firmware.bin cb2882871d6ca0fb5ed55e11264c6f6cee3c0235c76de00571b0594d0517b8a0 build/firmware.elf e78f5060eb3ee30dd379e1bcb7cdd5989fa548aebe1da1dcad30c879734a9c7a build/build.log e6db982845a32023b5c1d3b13e6022ada053f890176c7f62c792f6833801d491 build/tool-versions.txt 634a337031cd35986c7a5a0f91de787b05cd2ba6385945b45a80005989ad7f8c build/neorv32_imem_image.vhd 53747f9c99464b3fc27d93694709f0b59c80ba6c77851ee40372069c317f17d9 captures/uart-can-gateway-001.txt 26103dbf8f7a57072cd299140ed5af82f2f23b15c5edda2a0e7bbedbe12b93c4 inputs/build.sh 632f23af5d70cf115703da0b14bffff81b0d8958b2aa6a569a03dbbed887ca4c inputs/local-source-sha256.txt e75d05482edf2c55681070f5e27b3b7291aad770ccef4b92e27003bb9196bcbd inputs/run_capture.py 2ab92d325f679fa435839207ff19bee860009616dc30b0338a7953c18e087f3d manifest.json e4306f8015927dbc9d088c217097634b9fedd18b7e67871ddbc0fc64f4244b1d README.md e198dae603c693a84774f88ba3e9a75af15c1b8b24dfa790bc85b72ad2b447ce build/mediator.bit 2a98a912c010ae2574d6c589f4679d049553d219cd0f9268729a7efb4c787970 build/firmware.bin e5552f39ad3789d6f41f99f7a8898e521d3eb28e59a54bd62aac13477b6289db inputs/run_capture.py 10b9405b21acd749a634ca226a58c30dbe3d47a571244b3bb0994400ebd96479 inputs/build.sh 7df3d04ed936e4a21fbe5b4e472a8b80aafea66b3f2beac90da877449ebaa44c ../../../endstop-cycles/src/bin/board_fuel_costs.rs 4564ef93039dd781741530156cad6568e530d624db2613aea474fba408cec5ee captures/uart-j4.txt 73d780682bde3e19455bbb6f06f99cc0235585a8aef215ce019454d05adaef7e build/firmware.bin 07b91be7e589d81de01313a61c43aac9352c9572c5be3f298f979f9a30d6e294 build/mediator.bit 108b670a29bb978aec5d2129ed99f88bde4de54f127b31df80deeabd6336e80a captures/uart.txt 4888037676c9652915c580f50b2b873fd4cc448f7c36ad7e4796b1991e58be76 inputs/board_fuel_costs.rs 9137b5240aeea81cfb203e135b7ca07ee69e2ad574009a3d7e4b53cc06cf7994 inputs/costs.rs 3e5c407b95b6ceca713e9ed4c9665da15e9cc8b044fe3b26fa8dd65e915e530f inputs/tests.rs c97362048dd0af9e840860496feb82aa35428b8ec3df022b889fa3a86589acbc build/firmware.bin 52fc757b0f03fea55e3973229e5bd44dd081d79559422e38486d45768f72b3af build/mediator.bit 6159066c7c452658d16a650d757ce768e1c07f41cd1838221eb6fb633eb01ad1 captures/uart.txt 567be263c890d9a86d7dcfdfc9dc311d5f9f1d3af6b653f28600cd2cf00653f9 inputs/board_pmp_sweep.rs 984dbe044f78e7b487e6376152364aadd35a228f94207be7ef611b850f6f75e0 build/firmware.bin c7dd2a7bbaf7ca71fedf4d19bbd28b23f39b16eebb25e94dba1458926f6b7aa4 build/mediator.bit 50536e5336a349603c5909edd99ab43f673c13e1977f8915f93f996914e82fff captures/uart.txt 4f7b9cc7300ce73f14ff7dab2442789bc6f5ddd969b345d76a161fe3ff26ba71 inputs/board_cfs_sweep.rs c3a3d9c1f2653d672650dcb98c6f45563446d072bf6530edc55e5c58ba88dbfc inputs/j7_wire_probe.py afaf84dd229c38b722159813462461b0a77521d3054d4ad953b81cfbaf16d808 inputs/lease_rerun.py fcbd80d17793d61034ab5d734b78288ddafe1cc76109aca91d32df8b530ed162 build/firmware.bin dcb27f7a0ffd28935c4a28f73525e64159621a2b6b7bc60e01255f74877f813e build/mediator.bit 318656de3b51811425695f02d148c1dac7a587080434e191c6397e0659520aca captures/uart.txt e0f6e859ffc2e6da01d58b3e99a004f84d8f1d17285851e2817835c8e9609fea inputs/board_vm_jailburn.rs def41c1eb5078a7f6e04fa8645f43de081ad7d7e850c2970cab86f9a3723b09c build/build.log 01ca012362e963817eb22eb33e4da39ddaa5d4050b9561f84968885570c172af build/firmware.bin d3209506f2d070fa5f327eab6371d5011fd2044f60c411ab00c2790a790c76e5 build/firmware.elf db11bb48273b82bc29785a4655859dddf86b57836b50c3f7f646bbf4f08acdc6 build/jailbreak.bit 367bbcbfe7f7ce57ba935c66c41f0d7eb0415a04c177077204629ade445a9ce5 build/neorv32_imem_image.vhd e6db982845a32023b5c1d3b13e6022ada053f890176c7f62c792f6833801d491 build/tool-versions.txt 64c087e5d89607b14598c7dd63f58bf3cc824ccc2e35861d63f83c9dc855c3de captures/uart-jailbreak-001.txt 7ffe6815e2529f8419a4cdf0602e9df97e53cbff8d71360fb77d89b06a2b40aa inputs/build.sh dc58f91400386b1140c2574a33ab290c7af997dd3889699392755ebb771b6430 inputs/run_capture.py d6bf3434eecdaee6a22bb12b9d5bde192f809f9719aa93ab34528fa59d7e30d4 captures/soak/events.jsonl e3ca6d254341411cd15aa12c1d817ae162c3550261e5b20ff377a6530008ed5a captures/soak/report.json 98ec315646738bcc01d609a8a833e6429cfc8de2a56cc21b0198e7fab748b53a captures/soak-control-old/events.jsonl cc443cf003c96c74962fb99f380213837868f28c6a250ce2c19b58b5fc0aa7b5 captures/soak-control-old/report.json 6ed39411c2734556ee6c4f2fc053530311044e8ffa8d109d0b8eb9d13bea7c12 build/mediator.bit e07b9a63f4c83db062fc61fb0facaffb9eec4a9ff9c61703940913d0e9472d46 build/firmware.bin fc9d3850387c65cc2a054597777d17e2343c042227360ca5ce683f669b24445f inputs/split_soak.py 58b64d14f06a727b31f84edf18a6bc4a5918c2db28a0643b94d6f697d33f1ce4 source/endstop-cycles/src/bin/board_mediator_binary.rs { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-can-gateway-001", "status": "completed_pass", "claim_class": "company_authored_engineering_evidence", "hypothesis": "The endstop-can gateway core, compiled by rustc for RV32IMC, reproduces on the physical ECP5 soft core the 8/8 result of the shared scenario suite (endstop_can::suite) that passes on the host (endstop-can/tests/board_suite.rs).", "pass_criterion": "CAN:SUMMARY pass=8 fail=0 on every complete captured boot: S1 32 permitted pairs with every emitted frame inside the envelope; S2 overspeed refused with zero-speed braking frames; S3 deadman; S4 bypass on a foreign command frame; S5 a refusal before engagement emits nothing; S6 a replayed counter is not fresh; S7 a corrupted frame latches; S8 counters advance only when stamped.", "board": { "model": "LFE5UM5G-85F-EVN", "fpga": "LFE5UM5G-85", "jtag_idcode": "0x81113043 (openFPGALoader --detect after the run; not an individual board serial)", "host": "Mac-Studio.local (ssh studio)", "uart": "/dev/cu.usbserial-ABBCGJXO at 1000000 baud" }, "configuration": { "transport": "USB/JTAG openFPGALoader -b ecp5_evn", "persistence": "volatile_sram_only", "configuration_flash_written": false, "product_io_or_actuator_connected": false, "can_controller_present": false, "top": "board_timing_top (NEORV32, 12 MHz)", "firmware_bin": "board-can-gateway" }, "provenance": { "repository_commit_local": "3505a058e4ee03605d9c4b62536675a670607af0 plus uncommitted endstop-can crate and endstop-cycles board-can-gateway bin (93 dirty files in the shared tree); per-file hashes in inputs/local-source-sha256.txt", "neorv32_commit": "99ef4e9f2b0ef5e30549b23adbb11ddd69c05884", "source_synced_to": "Mac Studio ~/Developer/endstop-evidence/2026-09-27-ecp5-can-gateway-001/source", "build": "inputs/build.sh, rc=0 at 22:20; nextpnr-ecp5 seed 1, Fmax 74.69 MHz (PASS at 12 MHz)", "bitstream_sha256": "3a9690fd42d274b5259bab945367af33e40761c7a9291c4d940d67f2fbf6302e", "firmware_bin_sha256": "7fa1da41f6db81a0b5ecf7adf8d55fb751a2ec940314d07048179b19b82821a7", "firmware_elf_sha256": "cb2882871d6ca0fb5ed55e11264c6f6cee3c0235c76de00571b0594d0517b8a0", "tool_versions": "build/tool-versions.txt" }, "observation": { "instrument": "UART0 transcript at 1 Mbaud, captured to captures/uart-can-gateway-001.txt", "capture_sha256": "53747f9c99464b3fc27d93694709f0b59c80ba6c77851ee40372069c317f17d9", "loaded_at": "2026-09-27 22:39 local, after the board had been idle for 6 minutes", "boots_captured": 9, "complete_suites": 8, "summary": "CAN:SUMMARY pass=8 fail=0 on all 8 complete boots, identical; the ninth boot was cut by the capture ending", "cycles_at_12mhz": "ingest one AI frame worst 303 cycles; permitting tick worst 1308 cycles (~109 us at 12 MHz); identical on every boot", "loader_stdout": "not retained (the operator's console tail cut it); the load is evidenced by the image's own CAN:START banner carrying this run ID" }, "scope_and_exclusions": [ "No CAN controller or transceiver: frames are scripted inside the image; this is the gateway logic on the target silicon, not CAN on the wire.", "ERD-1 is a synthetic reference kit, not a vendor protocol.", "No actuator I/O, no configuration flash, no product pins; JTAG SRAM load and UART read only.", "Cycle counts are workload-local mcycle deltas at 12 MHz, not end-to-end latency.", "Same operator, no independent review." ], "review": "Same operator; no independent review", "artifact_base": "../../runs/2026-09-27-ecp5-can-gateway-001" }{ "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j4-001", "status": "completed_cost_model_rail_measured", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J4 of the board jail-break designs: does the provisional NEORV32 admission table (PROVISIONAL_NEORV32_RTL_V1, its capability entries measured on harness stubs) under-charge any instruction class on deployed ECP5 silicon, and by how much does the worst composed tick overrun its credited cycle budget?", "firmware": "board-fuel-costs (endstop-cycles/src/bin/board_fuel_costs.rs, current tree + this fixture): phase A the unchanged 2026-08-27 characterization suite on hardware UART; phase B deployed-callee costs (propose through the real monitor, with and without per-propose UART emission; sense); phase C admission composition under the provisional table with a nominal 65,536-credit budget.", "board": { "model": "LFE5UM5G-85F-EVN", "host": "Mac-Studio.local (ssh studio)", "uart": "/dev/cu.usbserial-ABBCGJXO at 1000000 baud" }, "configuration": { "transport": "USB/JTAG openFPGALoader -b ecp5_evn", "persistence": "volatile_sram_only", "configuration_flash_written": false, "arm_opened": false, "actuator_writes": 0, "bitstream_sha256": "e198dae603c693a84774f88ba3e9a75af15c1b8b24dfa790bc85b72ad2b447ce", "firmware_bin_sha256": "2a98a912c010ae2574d6c589f4679d049553d219cd0f9268729a7efb4c787970" }, "results": { "phase_a_per_step_cycles": { "jump": 341.2, "alu.add.imm": 311.2, "alu.mul.imm": 313.7, "alu.shifts": "319.6-322.0", "load.byte/half/word": "300.2 / 311.7 / 333.7", "store.byte/half/word": "297.2-324.7", "branch.taken": "298.1-308.0", "call.stub": 320.7 }, "board_vs_rtl_sim_2026_08_27": "board 0.2-3.6 percent faster on ordinary classes (e.g. jump.256 87342 vs 90435; load.word 85422 vs 88643); the softcore matches its RTL model within the table's 1.25x engineering margin", "phase_admission_utilization_x1000": { "jump": 791, "alu.add.imm": 790, "load.word": 789, "store.word.imm": 794, "branch.jeq": 715, "call.1.stub": 731, "call.1.deployed": 14758 }, "phase_b_deployed_callee_per_call": { "propose.monitor": 13621, "propose.monitor_plus_emit": 13940, "sense": 1018 } }, "verdict": [ "Every non-call class holds: measured admission utilization 71.5-79.4 percent of charged credits, so the table's 1.25x margin is intact on deployed silicon for all ordinary instructions.", "The capability entries do not hold on the deployed path: a propose through the real monitor costs about 13.6k cycles per call against the 464-credit stub charge, so a call-composed tick overruns its credited budget by 14.76x (65,536 credits consumed 967,243 cycles, about 80.6 ms at 12 MHz versus the intended 5.5 ms).", "This quantifies, on the metal, the caveat the costs module carries in prose: capability entries measured harness stubs; production admission must replace them with bounded deployed-callee measurements before operational use.", "On the deployed 2026-09-26 vm-elbow path this is bounded instead by the mediator's own cycle-deadline check and the 100 ms lease, not by the VM admission table." ], "scope_and_exclusions": [ "Arm-free synthetic holds; no actuator, product I/O or flash.", "The phase-B sense callee measured about 2x its charge in this harness (callee-struct and measurement-context effects); the propose number is the deployed-work measurement and the headline.", "mcycle-based observation, not a WCET claim; single board, single P&R seed, one build; no independent review.", "The emit variant of propose reflects the emulator board's per-propose outward line, not the vm-elbow mediator's reply-per-request amortization." ], "next": "Replace the provisional call entries with bounded deployed-callee measurements (propose ~13.6k, sense ~1.0k, seal pending an endstop-sign-linked measurement) and re-derive the admission margin; the J5 PMP sweep and J6 CFS disarm remain." } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j4-002", "status": "completed_loop_closed", "claim_class": "company_authored_engineering_evidence", "hypothesis": "The found->fixed->verified close-out of the J4 cost-model finding: the seal callee is measured, the admission table's capability entries are replaced with deployed-callee bounds, and the corrected table is verified on the board — every class, including the calls, now runs within its charged credits.", "findings": { "seal_callee": "Ed25519 sign (RFC 8032 test-vector key, default-features crate): 12,262,800 cycles/call, deterministic across two runs (196,204,825 cycles / 16 calls twice). Against the v0 stub charge of 480 this was a 57.9x under-charge (admission ratio1000=57880 observed in the pre-fix run).", "propose_confirmed": "13,621 cycles/call (17,540,71/128 in this build), 14.8x its v0 charge, reconfirmed.", "table_fixed": "PROVISIONAL_NEORV32_RTL_V1 updated to version 2_026_092_801: call entries replaced with sense=1,280 / propose=17,040 / seal=15,328,512 (observed x1.25 rounded up to 16, the table's convention), citing run 2026-09-27-ecp5-j4-001 and this run. The v0 stub-call table is retained as PROVISIONAL_NEORV32_RTL_V0_STUB_CALLS for reproducing the finding. The pinning test updated; endstop-vm 25/25 green." }, "verification": { "before_fix": "admission ratios: ordinary classes 715-794; call.1.stub 731; call.1.deployed 14,848; call.2.deployed 57,880", "after_fix": "ordinary classes unchanged 715-794; call.1.stub 70; call.1.deployed 667; call.2.deployed 50 (credits 61,315,048 = 4 seal charges, cycles 46,070,091)", "verdict": "Every class now runs at 5-79 percent of its charged credits; the admission table holds on the deployed board for all instruction classes including the measured callees.", "banner": "The firmware now derives its table banner from the compiled model (version, per-class charges) rather than a string constant — the pre-fix run's misleading banner is what exposed the first verification attempt using the stale table." }, "scope_and_exclusions": [ "Volatile SRAM only; arm-free; no actuator, product I/O or flash.", "The seal entry bounds one sign of a 32-byte message in the default-features crate configuration (no precomputed basepoint table); a different configuration needs its own measurement.", "The 2026-09-28 serial soak, running concurrently, observed a separate event after this run's board state was superseded: see the soak addendum in evidence/runs/2026-09-27-ecp5-serial-split-001 (16,431 clean then >=3.3 s total TX silence, one stray 0x00, unclassified because the counter probe was lost to a later reload)." ], "bitstream_sha256": "07b91be7e589d81de01313a61c43aac9352c9572c5be3f298f979f9a30d6e294", "firmware_bin_sha256": "73d780682bde3e19455bbb6f06f99cc0235585a8aef215ce019454d05adaef7e" } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j5-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J5 of the board jail-break designs: from user mode behind the locked NAPOT layout, every region boundary access is confined - loads, stores and execution at monitor RAM, the open DMEM word, CFS, UART and GPIO all take exactly their documented outcome.", "firmware": "board-pmp-sweep (endstop-cycles/src/bin/board_pmp_sweep.rs, hash in SHA256SUMS): a straight-line U-mode probe sequence behind the retained locked layout (PMP0 16 KiB no-access monitor RAM, PMP1 DMEM-covering RW, PMP2 IMEM RX), a trap handler that records (mcause, mtval) to a fixed DMEM word outside the protected page and resumes, and an M-mode reporter.", "results": { "loads": "monitor.start, monitor.last, cfs, uart, gpio: all load access faults (mcause 5) with matching mtval; dmem.open and dmem.last: permitted", "stores": "monitor.start, cfs, uart, gpio: all store access faults (mcause 7); dmem.open: permitted", "exec": "jalr into monitor RAM: instruction access fault (mcause 1); the trap fired and the sequence resumed at the terminating ecall. The reporter's expected-mtval check read mtval=0 (NEORV32 does not report the faulting fetch address in mtval), so the row prints FAIL - an expectation artifact, not a wall breach: the fault fired and no execution from the forbidden region occurred.", "summary": "J5:SUMMARY pass=12 fail=1 (the 1 being the mtval artifact above)" }, "verdict": "BOUNDARY HELD - no user-mode access reached monitor RAM, CFS, UART or GPIO, and execution from monitor RAM faulted.", "debugging_findings_retained": [ "The handler must not touch .bss: the linker places it at 0x8000_0000 inside the locked no-access page, which binds M-mode too - the first builds faulted recursively in the handler (retained in the board Mac captures as the '5'/'!' flood builds).", "The asm block must be .option norvc: compressed 2-byte instructions made the mepc+=4 skip land mid-instruction (the '5 2 5 2' illegal-instruction death spiral).", "A fetch fault's mepc is the TARGET, so the skip cannot resume the sequence - the fetch-fault branch resumes at the terminating ecall.", "A load at the unmapped word just past DMEM hung the bus rather than faulting; that probe was dropped (a bus property, not a PMP property)." ], "scope_and_exclusions": [ "Volatile SRAM only; arm-free; no actuator, product I/O or flash.", "The retained single-shot PMP probes could not distinguish M-mode from U-mode faults (their store faults identically in both); this sweep's ecall terminator (mcause 8) proves the sequence ran in U-mode.", "Exec probe: one target (monitor RAM); DMEM-exec and the mtval check are future refinements.", "One board, one build, same operator, no independent review." ], "bitstream_sha256": "52fc757b0f03fea55e3973229e5bd44dd081d79559422e38486d45768f72b3af", "firmware_bin_sha256": "c97362048dd0af9e840860496feb82aa35428b8ec3df022b889fa3a86589acbc" } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j6-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J6: no CFS write sequence from CPU code reaches or sustains fabric authorization without the physical path - the full 16-bit command space plus a maximum-rate refresh hammer, from machine mode.", "firmware": "board-cfs-sweep (hash in SHA256SUMS): all 65,536 proposal+request words written to CFS REG[0] with a status read after each; then the best-permit-shaped word hammered for ~10M cycles.", "results": { "states_observed": "s=16 (fresh-confirmation-missing) for 25,856 words; s=24 (confirm-missing + envelope-reject) for 39,680 - both within the documented 5-bit status set", "permit_hits": 0, "undocumented_bits": 0, "after_sweep": "status=24; the hammer left it unchanged (24 -> 24)", "summary": "J6:SUMMARY PASS permit_hits=0" }, "verdict": "BOUNDARY HELD - the fabric authority cannot be written into from the CPU: no command value reaches permit without the physical SW5-2 confirmation, no undocumented status appears, and rapid writes neither refresh nor clear anything.", "scope_and_exclusions": [ "Volatile SRAM only; arm-free; the board's arm/confirm switch state was not touched (whatever state it held is part of the observation: fresh confirmation was missing throughout, exactly the wall).", "Simulation-first (the fabric_motion_lease and fabric_safety_policy testbenches) was skipped in favor of the exhaustive on-board sweep; both are retained as future work.", "One board, one build, same operator, no independent review." ], "bitstream_sha256": "c7dd2a7bbaf7ca71fedf4d19bbd28b23f39b16eebb25e94dba1458926f6b7aa4", "firmware_bin_sha256": "984dbe044f78e7b487e6376152364aadd35a228f94207be7ef611b850f6f75e0" } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j7-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J7: the deployed wire protocol (the production-format mediator image, lowbaud-002 baud1m bitstream, hash-recorded) admits no stale, replayed, corrupted or forged frame as a permit.", "setup": "PC-side probe scripts (j7_wire_probe.py, lease_rerun.py, hashes in SHA256SUMS) against the retained production image loaded volatile-SRAM-only; the board's own policy/lease/monitor firmware unchanged from the serial-split runs.", "results": { "baseline_permit": "P", "replay_same_frame": "P then Q", "replay_stale_seq": "Q", "feedback_replay": "F", "age_rail": "F", "session_mismatch": "S", "bad_crc_silence": "no reply, and the next good frame still P (no latch from corruption)", "trailing_desync": "the junk-prefixed frame swallowed (silence), the next frame P", "seq_wraparound": "P, P, then Q after the wrap", "lease_expiry": "after a 150 ms gap: T with latched=1; a subsequent frame also T latched=1", "summary": "10/10 shapes PASS" }, "verdict": "BOUNDARY HELD - every forgery shape receives its documented refusal or silence; no acceptance of a stale, replayed, corrupted or forged frame.", "debugging_findings_retained": [ "The first lease-expiry attempt crashed on a script index bug (a 2-tuple indexed as 4); the board's reply was correct throughout. The rerun (lease_rerun.py) passes the shape; both scripts and events are retained." ], "scope_and_exclusions": [ "The CRC-birthday forgery class is bounded by construction here (any crafted frame with its own valid CRC is just a frame - integrity not authenticity); what is tested is that corrupted CRCs are never accepted.", "Arm-free synthetic holds; volatile SRAM only; one board, same operator, no independent review." ] } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j8-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J8 first pass, software-only: the jail-break canary suite holds after ~100 s of full-rate compute (the cheapest available environmental variation; no clock/voltage/EM equipment, no readable temperature on this board).", "firmware": "board-vm-jailburn (hash in SHA256SUMS): the jailbreak-001 canary suite preceded by 12 x 100M-cycle compute soaks (~100 s).", "results": { "summary": "J8:SUMMARY pass=17 fail=0 - identical to the cold baseline (2026-09-27-ecp5-jailbreak-001) after the soak" }, "verdict": "BOUNDARY HELD under the compute-soak variation; the true fault-injection classes (clock/voltage/EM glitch, servo thermal gates) remain equipment-gated and untested.", "scope_and_exclusions": [ "Unquantified thermal elevation (no on-board temperature readout); this bounds only compute-induced variation, not a specified temperature.", "Volatile SRAM only; arm-free; one board, one build, same operator, no independent review." ], "bitstream_sha256": "dcb27f7a0ffd28935c4a28f73525e64159621a2b6b7bc60e01255f74877f813e", "firmware_bin_sha256": "fcbd80d17793d61034ab5d734b78288ddafe1cc76109aca91d32df8b530ed162" } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-jailbreak-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "A loaded VM program cannot touch anything outside its 512-byte window on the deployed NEORV32 image (the rustc/RV32 translation of the proven interpreter): J1 memory-bound escape, J2 window placement, J3 capability-dispatch hammer from redteam/BOARD_JAILBREAK_ATTACK_DESIGN_2026-09-27.md.", "pass_criterion": "All 17 probes report PASS: every OOB shape halts MemBounds with canaries byte-identical, the wrapped read returns window content (not canary data), fuel caps the burn at exactly the budget, the loader rejects malformed programs, and no canary word appears in the proposal sink.", "board": { "model": "LFE5UM5G-85F-EVN", "fpga": "LFE5UM5G-85", "host": "Mac-Studio.local (ssh studio, 192.168.1.82)", "uart": "/dev/cu.usbserial-ABBCGJXO at 1000000 baud" }, "configuration": { "transport": "USB/JTAG openFPGALoader -b ecp5_evn", "persistence": "volatile_sram_only", "configuration_flash_written": false, "product_io_or_actuator_connected": false, "top": "board_timing_top (NEORV32 IMEM-ROM DMEM UART0 CFS SYSINFO, BOOT_MODE_SELECT 2)", "firmware_bin": "board-vm-jailbreak" }, "provenance": { "repository_commit_local": "5ce707e plus uncommitted fixture (endstop-cycles/src/bin/board_vm_jailbreak.rs, Cargo.toml [[bin]] entry)", "neorv32_commit": "99ef4e9f2b0ef5e30549b23adbb11ddd69c05884", "source_synced_to": "Mac Studio ~/Developer/endstop-evidence/2026-09-27-ecp5-jailbreak-001/source", "fixture_sha256": "7d51903af063ac1814c7372c66b618fba66bf8e70d87ede2cfe59f3951bca634", "bitstream_sha256": "db11bb48273b82bc29785a4655859dddf86b57836b50c3f7f646bbf4f08acdc6", "firmware_bin_sha256": "01ca012362e963817eb22eb33e4da39ddaa5d4050b9561f84968885570c172af" }, "observation": { "instrument": "UART0 transcript at 1 Mbaud, captured to captures/uart-jailbreak-001.txt (6143 bytes); LED marker 0x3c observed pass path in firmware", "boots_captured": 6, "complete_suites": ">=5, all identical", "summary": "JB:SUMMARY pass=17 fail=0 on every captured boot" }, "scope_and_exclusions": [ "Interpreter-level confinement only: J1/J2/J3. J4 (cost model), J5 (PMP sweep), J6 (CFS disarm), J7 (wire protocol), J8 (fault injection) designed, not executed.", "Canaries are adjacent to the whole Vm struct (verified adjacent by address arithmetic: pre=0x80000040 vm=0x80000080 delta_post=564=sizeof(Vm)); an escape that lands inside Vm padding or other Vm fields would not be caught.", "No actuator I/O, no configuration flash, no product pins driven; only JTAG SRAM load and UART read.", "UART transcript is not a timing measurement.", "Same operator, no independent review." ], "result": { "fill": "Exit 386 steps; verify: Exit 515 steps r0=0 (all 128 window words intact)", "oob_shapes": "ld_w_512, ld_w_511, ld_h_511, st_w_509, st_h_511, stx_w_512, shifted_base: all MemBounds, canaries intact", "wrap_neg2": "Exit r0=0x1234ABCD (305441741) - the wrapped address read window byte 0, not canary data", "rails": "fp_write WriteToFp; shift_32 ShiftOutOfRange", "cap_hammer": "Exit r0=0, 10 calls, 6 proposals of 0xFFFFFFFF, no canary word among them, canaries intact", "burn": "StepFuelExhausted at exactly 1024 steps", "loader_rejects": "bad_cap, jmp_past_end, no_exit all REJECT", "verdict": "BOUNDARY HELD on hardware under every J1/J2/J3 probe" }, "next": "J4 cost-model rail and J7 wire-protocol forgery are the next executable items; J5/J6 need the PMP and CFS fixture variants." } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-lowbaud-002", "status": "completed_diagnostic_answered", "claim_class": "company_authored_engineering_evidence", "hypothesis": "Execute the prepared 2026-09-15 low-baud isolation (its recorded blocker, board-Mac access, is removed): if serial corruption persists at 500 kbaud, line-rate signaling is excluded as the cause; if it vanishes, the 1 Mbaud link is implicated. A same-flow 1 Mbaud control build re-establishes today's baseline.", "source": "Retained 2026-09-15 source-500k.tgz (2026-09-08 binary source, only UART divisor 5->11); control image differs only by divisor set back to 5. NEORV32 99ef4e9, top board_timing_top, FIRMWARE_BIN=board-mediator-binary, seed 1, same build flow as 2026-09-27-ecp5-jailbreak-001.", "board": { "model": "LFE5UM5G-85F-EVN", "host": "Mac-Studio.local (ssh studio, 192.168.1.82)", "uart": "/dev/cu.usbserial-ABBCGJXO (FTDI 0403:6001, SN ABBCGJXO); driver state captured (captures/driver.log)" }, "configuration": { "transport": "USB/JTAG openFPGALoader -b ecp5_evn, volatile SRAM only", "configuration_flash_written": false, "arm_opened": false, "actuator_writes": 0, "images": { "baud1m": "mediator.bit sha256 7c21681ae391acf8ccac0fbd0f1e714fb9250f2707ab0c6b6a2642afc5be4b48, divisor (5<<6)|1", "baud500k": "mediator.bit sha256 f907668fbb6634c718158f97f3b55f913683f2d807921b3045232acca082fd8a, divisor (11<<6)|1" } }, "protocol": "isolate_board_serial.py as retained: 25 Hz synthetic holds, every exchange CRC/echo/decision-validated, stop at first fault; image reloaded before each mode (the 2026-09-10 sequence; the first pass without per-mode reload is retained as the contaminated pair).", "results": { "baud1m-byte": "1402 valid, then one lost exchange (empty reply within 80 ms), fault 'missing delimiter'", "baud1m-chunk-fresh": "104 valid, then one lost exchange, 'missing delimiter'", "baud500k-byte": "1105 valid, then one lost exchange, 'missing delimiter'", "baud500k-chunk-fresh": "1123 valid, then one lost exchange, 'missing delimiter'", "contaminated_pair": "baud1m-chunk and baud500k-chunk (valid=0) ran without reload after the byte failures; their first replies carried the latched lease timeout, which itself shows the board kept transmitting after each lost exchange.", "audit": "audit_serial_isolation.py (retained independent COBS/CRC audit): exactly one fault per failing run, all 'missing delimiter'; no corrupted-reply faults in this run; TX requests all CRC-valid." }, "conclusions": [ "The prepared low-baud diagnostic is executed: corruption persists at 500 kbaud in both read modes, so line-rate signaling is excluded as the cause.", "The failure is a single lost exchange after 10^2-10^3 clean ones (104-1402 observed), not a fixed count; the board survives each failure and keeps answering (latched-lease replies observed after byte-mode failures), consistent with its documented silent discard of inbound frames failing CRC.", "Today's signature (inbound loss) plus the retained 2026-09-10 signature (outbound corrupted byte, CRC tail consistent with the expected body) together indicate corruption on the shared path - FTDI adapter, USB link, host write/read path, or the board's UART pins - not a baud- or read-mode-dependent effect and not a firmware crash." ], "scope_and_exclusions": [ "Does not locate the corruption physically; adapter/USB/host vs board UART remains open (loopback or logic-analyser follow-up).", "The rebuilt images are not byte-identical to the original 2026-09-08 image (fresh P&R); the 1 M control reproduces the failure class in the fresh build, which bounds that confound for the class comparison.", "Arm-free synthetic holds; no actuator, no product I/O, no flash; same operator, no independent review.", "The 25 Hz pacing and 80 ms reply window are the retained protocol's, not a product timing claim." ], "closes": "Prepared-but-unexecuted 2026-09-15-ecp5-lowbaud-001 (blocker: test-computer access) - executed and answered by this run.", "next": "Physical split of adapter/USB/host vs board UART: FTDI loopback at both bauds (no board) or a logic analyser on the board TX/RX pins during a long run; the CPU-independent transmitter named in the 2026-09-15 plan." } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-serial-split-001", "status": "completed_bursty_confirmed_instrument_ready", "claim_class": "company_authored_engineering_evidence", "hypothesis": "An instrumented mediator image (replies carry a processed-request counter; damaged inbound frames raise an E event instead of the production silent discard) plus a tolerant soak runner classifies every lost exchange as inbound-corruption, request-lost-inbound, or reply-lost-outbound - splitting the unresolved serial corruption by direction without physical access to the rig.", "instrumentation": { "firmware": "board-mediator-binary built from the retained 2026-09-08 source (same tree as 2026-09-27-ecp5-lowbaud-002) with two diagnostic changes: (1) 64-byte reply format adding a u32 processed-request counter, (2) E events (framing-length 'f' / CRC 'c') on damaged inbound frames. Policy, monitor, lease and divisor (1 Mbaud) unchanged. Diff retained as inputs/board_mediator_binary.rs.", "runner": "split_soak.py, tolerant: continues past faults, classifies each fault from the next reply's counter and any E event; 25 Hz; 80 ms reply window; every exchange validated (COBS, CRC32, echo, decision, lease).", "e_validation": "The first attempt sent frames without the CRC trailer by mistake; the board raised an E event for every request, received and decoded correctly - the E path is validated end-to-end (attempt retained as captures/soak-attempt1-nocrc on the board Mac)." }, "results": { "soak_instrumented_image": "45,000/45,000 exchanges clean. Zero faults, zero E events, zero anomalous frames (report: captures/soak-instrumented-report.json).", "soak_control_production_format": "45,000/45,000 exchanges clean with the SAME production-format image (2026-09-27-ecp5-lowbaud-002 baud1m, bitstream 7c21681a...) that failed 4/4 runs at 104-1402 exchanges earlier the same afternoon (report: captures/soak-control-report.json).", "total_clean_today_after_burst": "90,000 consecutive exchanges across two images (about 60 minutes) with zero faults." }, "conclusions": [ "The serial corruption is bursty/environment-dependent, not deterministic: identical image, board, adapter, protocol and host failed 4/4 within 1400 exchanges in one window of the day and then completed 45,000 consecutive clean exchanges twice.", "Deterministic-mechanism hypotheses are excluded: fixed request count, buffer accumulation, and firmware-logic-at-a-threshold all fail to explain both observations.", "The board firmware is excluded as a deterministic cause for this window: the same firmware ran clean for 45,000 exchanges.", "The three-way direction classifier is built and validated (E events proven to fire and decode) and will classify the next burst when one occurs; no natural fault occurred during either soak to exercise it." ], "scope_and_exclusions": [ "Large raw event logs (2x20 MB events.jsonl) are retained on the board Mac at ~/Developer/endstop-evidence/2026-09-27-ecp5-serial-split-001/captures/ with SHA-256 in SHA256SUMS; reports, bitstream, firmware and scripts are mirrored here.", "The burst trigger is unidentified: host/USB state, external interference, or thermal are candidates; correlating bursts with host state is the next investigation.", "Two runner bugs (missing CRC trailer; a format patch half-applied) are retained as failed attempts with their captures; the final runner and firmware are the retained versions hashed here.", "Arm-free synthetic holds; no actuator, product I/O or flash; volatile SRAM only; same operator, no independent review." ], "closes": "Deterministic-mechanism class for the serial corruption (count/buffer/firmware-threshold hypotheses).", "opens": "Burst correlation with host/USB state; direction classification of the next natural burst with the validated instrument." } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-can-gateway-001", "status": "completed_pass", "claim_class": "company_authored_engineering_evidence", "hypothesis": "The endstop-can gateway core, compiled by rustc for RV32IMC, reproduces on the physical ECP5 soft core the 8/8 result of the shared scenario suite (endstop_can::suite) that passes on the host (endstop-can/tests/board_suite.rs).", "pass_criterion": "CAN:SUMMARY pass=8 fail=0 on every complete captured boot: S1 32 permitted pairs with every emitted frame inside the envelope; S2 overspeed refused with zero-speed braking frames; S3 deadman; S4 bypass on a foreign command frame; S5 a refusal before engagement emits nothing; S6 a replayed counter is not fresh; S7 a corrupted frame latches; S8 counters advance only when stamped.", "board": { "model": "LFE5UM5G-85F-EVN", "fpga": "LFE5UM5G-85", "jtag_idcode": "0x81113043 (openFPGALoader --detect after the run; not an individual board serial)", "host": "Mac-Studio.local (ssh studio)", "uart": "/dev/cu.usbserial-ABBCGJXO at 1000000 baud" }, "configuration": { "transport": "USB/JTAG openFPGALoader -b ecp5_evn", "persistence": "volatile_sram_only", "configuration_flash_written": false, "product_io_or_actuator_connected": false, "can_controller_present": false, "top": "board_timing_top (NEORV32, 12 MHz)", "firmware_bin": "board-can-gateway" }, "provenance": { "repository_commit_local": "3505a058e4ee03605d9c4b62536675a670607af0 plus uncommitted endstop-can crate and endstop-cycles board-can-gateway bin (93 dirty files in the shared tree); per-file hashes in inputs/local-source-sha256.txt", "neorv32_commit": "99ef4e9f2b0ef5e30549b23adbb11ddd69c05884", "source_synced_to": "Mac Studio ~/Developer/endstop-evidence/2026-09-27-ecp5-can-gateway-001/source", "build": "inputs/build.sh, rc=0 at 22:20; nextpnr-ecp5 seed 1, Fmax 74.69 MHz (PASS at 12 MHz)", "bitstream_sha256": "3a9690fd42d274b5259bab945367af33e40761c7a9291c4d940d67f2fbf6302e", "firmware_bin_sha256": "7fa1da41f6db81a0b5ecf7adf8d55fb751a2ec940314d07048179b19b82821a7", "firmware_elf_sha256": "cb2882871d6ca0fb5ed55e11264c6f6cee3c0235c76de00571b0594d0517b8a0", "tool_versions": "build/tool-versions.txt" }, "observation": { "instrument": "UART0 transcript at 1 Mbaud, captured to captures/uart-can-gateway-001.txt", "capture_sha256": "53747f9c99464b3fc27d93694709f0b59c80ba6c77851ee40372069c317f17d9", "loaded_at": "2026-09-27 22:39 local, after the board had been idle for 6 minutes", "boots_captured": 9, "complete_suites": 8, "summary": "CAN:SUMMARY pass=8 fail=0 on all 8 complete boots, identical; the ninth boot was cut by the capture ending", "cycles_at_12mhz": "ingest one AI frame worst 303 cycles; permitting tick worst 1308 cycles (~109 us at 12 MHz); identical on every boot", "loader_stdout": "not retained (the operator's console tail cut it); the load is evidenced by the image's own CAN:START banner carrying this run ID" }, "scope_and_exclusions": [ "No CAN controller or transceiver: frames are scripted inside the image; this is the gateway logic on the target silicon, not CAN on the wire.", "ERD-1 is a synthetic reference kit, not a vendor protocol.", "No actuator I/O, no configuration flash, no product pins; JTAG SRAM load and UART read only.", "Cycle counts are workload-local mcycle deltas at 12 MHz, not end-to-end latency.", "Same operator, no independent review." ], "review": "Same operator; no independent review" }{ "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j4-001", "status": "completed_cost_model_rail_measured", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J4 of the board jail-break designs: does the provisional NEORV32 admission table (PROVISIONAL_NEORV32_RTL_V1, its capability entries measured on harness stubs) under-charge any instruction class on deployed ECP5 silicon, and by how much does the worst composed tick overrun its credited cycle budget?", "firmware": "board-fuel-costs (endstop-cycles/src/bin/board_fuel_costs.rs, current tree + this fixture): phase A the unchanged 2026-08-27 characterization suite on hardware UART; phase B deployed-callee costs (propose through the real monitor, with and without per-propose UART emission; sense); phase C admission composition under the provisional table with a nominal 65,536-credit budget.", "board": { "model": "LFE5UM5G-85F-EVN", "host": "Mac-Studio.local (ssh studio)", "uart": "/dev/cu.usbserial-ABBCGJXO at 1000000 baud" }, "configuration": { "transport": "USB/JTAG openFPGALoader -b ecp5_evn", "persistence": "volatile_sram_only", "configuration_flash_written": false, "arm_opened": false, "actuator_writes": 0, "bitstream_sha256": "e198dae603c693a84774f88ba3e9a75af15c1b8b24dfa790bc85b72ad2b447ce", "firmware_bin_sha256": "2a98a912c010ae2574d6c589f4679d049553d219cd0f9268729a7efb4c787970" }, "results": { "phase_a_per_step_cycles": { "jump": 341.2, "alu.add.imm": 311.2, "alu.mul.imm": 313.7, "alu.shifts": "319.6-322.0", "load.byte/half/word": "300.2 / 311.7 / 333.7", "store.byte/half/word": "297.2-324.7", "branch.taken": "298.1-308.0", "call.stub": 320.7 }, "board_vs_rtl_sim_2026_08_27": "board 0.2-3.6 percent faster on ordinary classes (e.g. jump.256 87342 vs 90435; load.word 85422 vs 88643); the softcore matches its RTL model within the table's 1.25x engineering margin", "phase_admission_utilization_x1000": { "jump": 791, "alu.add.imm": 790, "load.word": 789, "store.word.imm": 794, "branch.jeq": 715, "call.1.stub": 731, "call.1.deployed": 14758 }, "phase_b_deployed_callee_per_call": { "propose.monitor": 13621, "propose.monitor_plus_emit": 13940, "sense": 1018 } }, "verdict": [ "Every non-call class holds: measured admission utilization 71.5-79.4 percent of charged credits, so the table's 1.25x margin is intact on deployed silicon for all ordinary instructions.", "The capability entries do not hold on the deployed path: a propose through the real monitor costs about 13.6k cycles per call against the 464-credit stub charge, so a call-composed tick overruns its credited budget by 14.76x (65,536 credits consumed 967,243 cycles, about 80.6 ms at 12 MHz versus the intended 5.5 ms).", "This quantifies, on the metal, the caveat the costs module carries in prose: capability entries measured harness stubs; production admission must replace them with bounded deployed-callee measurements before operational use.", "On the deployed 2026-09-26 vm-elbow path this is bounded instead by the mediator's own cycle-deadline check and the 100 ms lease, not by the VM admission table." ], "scope_and_exclusions": [ "Arm-free synthetic holds; no actuator, product I/O or flash.", "The phase-B sense callee measured about 2x its charge in this harness (callee-struct and measurement-context effects); the propose number is the deployed-work measurement and the headline.", "mcycle-based observation, not a WCET claim; single board, single P&R seed, one build; no independent review.", "The emit variant of propose reflects the emulator board's per-propose outward line, not the vm-elbow mediator's reply-per-request amortization." ], "next": "Replace the provisional call entries with bounded deployed-callee measurements (propose ~13.6k, sense ~1.0k, seal pending an endstop-sign-linked measurement) and re-derive the admission margin; the J5 PMP sweep and J6 CFS disarm remain." } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j4-002", "status": "completed_loop_closed", "claim_class": "company_authored_engineering_evidence", "hypothesis": "The found->fixed->verified close-out of the J4 cost-model finding: the seal callee is measured, the admission table's capability entries are replaced with deployed-callee bounds, and the corrected table is verified on the board — every class, including the calls, now runs within its charged credits.", "findings": { "seal_callee": "Ed25519 sign (RFC 8032 test-vector key, default-features crate): 12,262,800 cycles/call, deterministic across two runs (196,204,825 cycles / 16 calls twice). Against the v0 stub charge of 480 this was a 57.9x under-charge (admission ratio1000=57880 observed in the pre-fix run).", "propose_confirmed": "13,621 cycles/call (17,540,71/128 in this build), 14.8x its v0 charge, reconfirmed.", "table_fixed": "PROVISIONAL_NEORV32_RTL_V1 updated to version 2_026_092_801: call entries replaced with sense=1,280 / propose=17,040 / seal=15,328,512 (observed x1.25 rounded up to 16, the table's convention), citing run 2026-09-27-ecp5-j4-001 and this run. The v0 stub-call table is retained as PROVISIONAL_NEORV32_RTL_V0_STUB_CALLS for reproducing the finding. The pinning test updated; endstop-vm 25/25 green." }, "verification": { "before_fix": "admission ratios: ordinary classes 715-794; call.1.stub 731; call.1.deployed 14,848; call.2.deployed 57,880", "after_fix": "ordinary classes unchanged 715-794; call.1.stub 70; call.1.deployed 667; call.2.deployed 50 (credits 61,315,048 = 4 seal charges, cycles 46,070,091)", "verdict": "Every class now runs at 5-79 percent of its charged credits; the admission table holds on the deployed board for all instruction classes including the measured callees.", "banner": "The firmware now derives its table banner from the compiled model (version, per-class charges) rather than a string constant — the pre-fix run's misleading banner is what exposed the first verification attempt using the stale table." }, "scope_and_exclusions": [ "Volatile SRAM only; arm-free; no actuator, product I/O or flash.", "The seal entry bounds one sign of a 32-byte message in the default-features crate configuration (no precomputed basepoint table); a different configuration needs its own measurement.", "The 2026-09-28 serial soak, running concurrently, observed a separate event after this run's board state was superseded: see the soak addendum in evidence/runs/2026-09-27-ecp5-serial-split-001 (16,431 clean then >=3.3 s total TX silence, one stray 0x00, unclassified because the counter probe was lost to a later reload)." ], "bitstream_sha256": "07b91be7e589d81de01313a61c43aac9352c9572c5be3f298f979f9a30d6e294", "firmware_bin_sha256": "73d780682bde3e19455bbb6f06f99cc0235585a8aef215ce019454d05adaef7e" } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j5-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J5 of the board jail-break designs: from user mode behind the locked NAPOT layout, every region boundary access is confined - loads, stores and execution at monitor RAM, the open DMEM word, CFS, UART and GPIO all take exactly their documented outcome.", "firmware": "board-pmp-sweep (endstop-cycles/src/bin/board_pmp_sweep.rs, hash in SHA256SUMS): a straight-line U-mode probe sequence behind the retained locked layout (PMP0 16 KiB no-access monitor RAM, PMP1 DMEM-covering RW, PMP2 IMEM RX), a trap handler that records (mcause, mtval) to a fixed DMEM word outside the protected page and resumes, and an M-mode reporter.", "results": { "loads": "monitor.start, monitor.last, cfs, uart, gpio: all load access faults (mcause 5) with matching mtval; dmem.open and dmem.last: permitted", "stores": "monitor.start, cfs, uart, gpio: all store access faults (mcause 7); dmem.open: permitted", "exec": "jalr into monitor RAM: instruction access fault (mcause 1); the trap fired and the sequence resumed at the terminating ecall. The reporter's expected-mtval check read mtval=0 (NEORV32 does not report the faulting fetch address in mtval), so the row prints FAIL - an expectation artifact, not a wall breach: the fault fired and no execution from the forbidden region occurred.", "summary": "J5:SUMMARY pass=12 fail=1 (the 1 being the mtval artifact above)" }, "verdict": "BOUNDARY HELD - no user-mode access reached monitor RAM, CFS, UART or GPIO, and execution from monitor RAM faulted.", "debugging_findings_retained": [ "The handler must not touch .bss: the linker places it at 0x8000_0000 inside the locked no-access page, which binds M-mode too - the first builds faulted recursively in the handler (retained in the board Mac captures as the '5'/'!' flood builds).", "The asm block must be .option norvc: compressed 2-byte instructions made the mepc+=4 skip land mid-instruction (the '5 2 5 2' illegal-instruction death spiral).", "A fetch fault's mepc is the TARGET, so the skip cannot resume the sequence - the fetch-fault branch resumes at the terminating ecall.", "A load at the unmapped word just past DMEM hung the bus rather than faulting; that probe was dropped (a bus property, not a PMP property)." ], "scope_and_exclusions": [ "Volatile SRAM only; arm-free; no actuator, product I/O or flash.", "The retained single-shot PMP probes could not distinguish M-mode from U-mode faults (their store faults identically in both); this sweep's ecall terminator (mcause 8) proves the sequence ran in U-mode.", "Exec probe: one target (monitor RAM); DMEM-exec and the mtval check are future refinements.", "One board, one build, same operator, no independent review." ], "bitstream_sha256": "52fc757b0f03fea55e3973229e5bd44dd081d79559422e38486d45768f72b3af", "firmware_bin_sha256": "c97362048dd0af9e840860496feb82aa35428b8ec3df022b889fa3a86589acbc" } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j6-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J6: no CFS write sequence from CPU code reaches or sustains fabric authorization without the physical path - the full 16-bit command space plus a maximum-rate refresh hammer, from machine mode.", "firmware": "board-cfs-sweep (hash in SHA256SUMS): all 65,536 proposal+request words written to CFS REG[0] with a status read after each; then the best-permit-shaped word hammered for ~10M cycles.", "results": { "states_observed": "s=16 (fresh-confirmation-missing) for 25,856 words; s=24 (confirm-missing + envelope-reject) for 39,680 - both within the documented 5-bit status set", "permit_hits": 0, "undocumented_bits": 0, "after_sweep": "status=24; the hammer left it unchanged (24 -> 24)", "summary": "J6:SUMMARY PASS permit_hits=0" }, "verdict": "BOUNDARY HELD - the fabric authority cannot be written into from the CPU: no command value reaches permit without the physical SW5-2 confirmation, no undocumented status appears, and rapid writes neither refresh nor clear anything.", "scope_and_exclusions": [ "Volatile SRAM only; arm-free; the board's arm/confirm switch state was not touched (whatever state it held is part of the observation: fresh confirmation was missing throughout, exactly the wall).", "Simulation-first (the fabric_motion_lease and fabric_safety_policy testbenches) was skipped in favor of the exhaustive on-board sweep; both are retained as future work.", "One board, one build, same operator, no independent review." ], "bitstream_sha256": "c7dd2a7bbaf7ca71fedf4d19bbd28b23f39b16eebb25e94dba1458926f6b7aa4", "firmware_bin_sha256": "984dbe044f78e7b487e6376152364aadd35a228f94207be7ef611b850f6f75e0" } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j7-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J7: the deployed wire protocol (the production-format mediator image, lowbaud-002 baud1m bitstream, hash-recorded) admits no stale, replayed, corrupted or forged frame as a permit.", "setup": "PC-side probe scripts (j7_wire_probe.py, lease_rerun.py, hashes in SHA256SUMS) against the retained production image loaded volatile-SRAM-only; the board's own policy/lease/monitor firmware unchanged from the serial-split runs.", "results": { "baseline_permit": "P", "replay_same_frame": "P then Q", "replay_stale_seq": "Q", "feedback_replay": "F", "age_rail": "F", "session_mismatch": "S", "bad_crc_silence": "no reply, and the next good frame still P (no latch from corruption)", "trailing_desync": "the junk-prefixed frame swallowed (silence), the next frame P", "seq_wraparound": "P, P, then Q after the wrap", "lease_expiry": "after a 150 ms gap: T with latched=1; a subsequent frame also T latched=1", "summary": "10/10 shapes PASS" }, "verdict": "BOUNDARY HELD - every forgery shape receives its documented refusal or silence; no acceptance of a stale, replayed, corrupted or forged frame.", "debugging_findings_retained": [ "The first lease-expiry attempt crashed on a script index bug (a 2-tuple indexed as 4); the board's reply was correct throughout. The rerun (lease_rerun.py) passes the shape; both scripts and events are retained." ], "scope_and_exclusions": [ "The CRC-birthday forgery class is bounded by construction here (any crafted frame with its own valid CRC is just a frame - integrity not authenticity); what is tested is that corrupted CRCs are never accepted.", "Arm-free synthetic holds; volatile SRAM only; one board, same operator, no independent review." ] } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-j8-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "J8 first pass, software-only: the jail-break canary suite holds after ~100 s of full-rate compute (the cheapest available environmental variation; no clock/voltage/EM equipment, no readable temperature on this board).", "firmware": "board-vm-jailburn (hash in SHA256SUMS): the jailbreak-001 canary suite preceded by 12 x 100M-cycle compute soaks (~100 s).", "results": { "summary": "J8:SUMMARY pass=17 fail=0 - identical to the cold baseline (2026-09-27-ecp5-jailbreak-001) after the soak" }, "verdict": "BOUNDARY HELD under the compute-soak variation; the true fault-injection classes (clock/voltage/EM glitch, servo thermal gates) remain equipment-gated and untested.", "scope_and_exclusions": [ "Unquantified thermal elevation (no on-board temperature readout); this bounds only compute-induced variation, not a specified temperature.", "Volatile SRAM only; arm-free; one board, one build, same operator, no independent review." ], "bitstream_sha256": "dcb27f7a0ffd28935c4a28f73525e64159621a2b6b7bc60e01255f74877f813e", "firmware_bin_sha256": "fcbd80d17793d61034ab5d734b78288ddafe1cc76109aca91d32df8b530ed162" } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-jailbreak-001", "status": "completed_boundary_held", "claim_class": "company_authored_engineering_evidence", "hypothesis": "A loaded VM program cannot touch anything outside its 512-byte window on the deployed NEORV32 image (the rustc/RV32 translation of the proven interpreter): J1 memory-bound escape, J2 window placement, J3 capability-dispatch hammer from redteam/BOARD_JAILBREAK_ATTACK_DESIGN_2026-09-27.md.", "pass_criterion": "All 17 probes report PASS: every OOB shape halts MemBounds with canaries byte-identical, the wrapped read returns window content (not canary data), fuel caps the burn at exactly the budget, the loader rejects malformed programs, and no canary word appears in the proposal sink.", "board": { "model": "LFE5UM5G-85F-EVN", "fpga": "LFE5UM5G-85", "host": "Mac-Studio.local (ssh studio, 192.168.1.82)", "uart": "/dev/cu.usbserial-ABBCGJXO at 1000000 baud" }, "configuration": { "transport": "USB/JTAG openFPGALoader -b ecp5_evn", "persistence": "volatile_sram_only", "configuration_flash_written": false, "product_io_or_actuator_connected": false, "top": "board_timing_top (NEORV32 IMEM-ROM DMEM UART0 CFS SYSINFO, BOOT_MODE_SELECT 2)", "firmware_bin": "board-vm-jailbreak" }, "provenance": { "repository_commit_local": "5ce707e plus uncommitted fixture (endstop-cycles/src/bin/board_vm_jailbreak.rs, Cargo.toml [[bin]] entry)", "neorv32_commit": "99ef4e9f2b0ef5e30549b23adbb11ddd69c05884", "source_synced_to": "Mac Studio ~/Developer/endstop-evidence/2026-09-27-ecp5-jailbreak-001/source", "fixture_sha256": "7d51903af063ac1814c7372c66b618fba66bf8e70d87ede2cfe59f3951bca634", "bitstream_sha256": "db11bb48273b82bc29785a4655859dddf86b57836b50c3f7f646bbf4f08acdc6", "firmware_bin_sha256": "01ca012362e963817eb22eb33e4da39ddaa5d4050b9561f84968885570c172af" }, "observation": { "instrument": "UART0 transcript at 1 Mbaud, captured to captures/uart-jailbreak-001.txt (6143 bytes); LED marker 0x3c observed pass path in firmware", "boots_captured": 6, "complete_suites": ">=5, all identical", "summary": "JB:SUMMARY pass=17 fail=0 on every captured boot" }, "scope_and_exclusions": [ "Interpreter-level confinement only: J1/J2/J3. J4 (cost model), J5 (PMP sweep), J6 (CFS disarm), J7 (wire protocol), J8 (fault injection) designed, not executed.", "Canaries are adjacent to the whole Vm struct (verified adjacent by address arithmetic: pre=0x80000040 vm=0x80000080 delta_post=564=sizeof(Vm)); an escape that lands inside Vm padding or other Vm fields would not be caught.", "No actuator I/O, no configuration flash, no product pins driven; only JTAG SRAM load and UART read.", "UART transcript is not a timing measurement.", "Same operator, no independent review." ], "result": { "fill": "Exit 386 steps; verify: Exit 515 steps r0=0 (all 128 window words intact)", "oob_shapes": "ld_w_512, ld_w_511, ld_h_511, st_w_509, st_h_511, stx_w_512, shifted_base: all MemBounds, canaries intact", "wrap_neg2": "Exit r0=0x1234ABCD (305441741) - the wrapped address read window byte 0, not canary data", "rails": "fp_write WriteToFp; shift_32 ShiftOutOfRange", "cap_hammer": "Exit r0=0, 10 calls, 6 proposals of 0xFFFFFFFF, no canary word among them, canaries intact", "burn": "StepFuelExhausted at exactly 1024 steps", "loader_rejects": "bad_cap, jmp_past_end, no_exit all REJECT", "verdict": "BOUNDARY HELD on hardware under every J1/J2/J3 probe" }, "next": "J4 cost-model rail and J7 wire-protocol forgery are the next executable items; J5/J6 need the PMP and CFS fixture variants." } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-lowbaud-002", "status": "completed_diagnostic_answered", "claim_class": "company_authored_engineering_evidence", "hypothesis": "Execute the prepared 2026-09-15 low-baud isolation (its recorded blocker, board-Mac access, is removed): if serial corruption persists at 500 kbaud, line-rate signaling is excluded as the cause; if it vanishes, the 1 Mbaud link is implicated. A same-flow 1 Mbaud control build re-establishes today's baseline.", "source": "Retained 2026-09-15 source-500k.tgz (2026-09-08 binary source, only UART divisor 5->11); control image differs only by divisor set back to 5. NEORV32 99ef4e9, top board_timing_top, FIRMWARE_BIN=board-mediator-binary, seed 1, same build flow as 2026-09-27-ecp5-jailbreak-001.", "board": { "model": "LFE5UM5G-85F-EVN", "host": "Mac-Studio.local (ssh studio, 192.168.1.82)", "uart": "/dev/cu.usbserial-ABBCGJXO (FTDI 0403:6001, SN ABBCGJXO); driver state captured (captures/driver.log)" }, "configuration": { "transport": "USB/JTAG openFPGALoader -b ecp5_evn, volatile SRAM only", "configuration_flash_written": false, "arm_opened": false, "actuator_writes": 0, "images": { "baud1m": "mediator.bit sha256 7c21681ae391acf8ccac0fbd0f1e714fb9250f2707ab0c6b6a2642afc5be4b48, divisor (5<<6)|1", "baud500k": "mediator.bit sha256 f907668fbb6634c718158f97f3b55f913683f2d807921b3045232acca082fd8a, divisor (11<<6)|1" } }, "protocol": "isolate_board_serial.py as retained: 25 Hz synthetic holds, every exchange CRC/echo/decision-validated, stop at first fault; image reloaded before each mode (the 2026-09-10 sequence; the first pass without per-mode reload is retained as the contaminated pair).", "results": { "baud1m-byte": "1402 valid, then one lost exchange (empty reply within 80 ms), fault 'missing delimiter'", "baud1m-chunk-fresh": "104 valid, then one lost exchange, 'missing delimiter'", "baud500k-byte": "1105 valid, then one lost exchange, 'missing delimiter'", "baud500k-chunk-fresh": "1123 valid, then one lost exchange, 'missing delimiter'", "contaminated_pair": "baud1m-chunk and baud500k-chunk (valid=0) ran without reload after the byte failures; their first replies carried the latched lease timeout, which itself shows the board kept transmitting after each lost exchange.", "audit": "audit_serial_isolation.py (retained independent COBS/CRC audit): exactly one fault per failing run, all 'missing delimiter'; no corrupted-reply faults in this run; TX requests all CRC-valid." }, "conclusions": [ "The prepared low-baud diagnostic is executed: corruption persists at 500 kbaud in both read modes, so line-rate signaling is excluded as the cause.", "The failure is a single lost exchange after 10^2-10^3 clean ones (104-1402 observed), not a fixed count; the board survives each failure and keeps answering (latched-lease replies observed after byte-mode failures), consistent with its documented silent discard of inbound frames failing CRC.", "Today's signature (inbound loss) plus the retained 2026-09-10 signature (outbound corrupted byte, CRC tail consistent with the expected body) together indicate corruption on the shared path - FTDI adapter, USB link, host write/read path, or the board's UART pins - not a baud- or read-mode-dependent effect and not a firmware crash." ], "scope_and_exclusions": [ "Does not locate the corruption physically; adapter/USB/host vs board UART remains open (loopback or logic-analyser follow-up).", "The rebuilt images are not byte-identical to the original 2026-09-08 image (fresh P&R); the 1 M control reproduces the failure class in the fresh build, which bounds that confound for the class comparison.", "Arm-free synthetic holds; no actuator, no product I/O, no flash; same operator, no independent review.", "The 25 Hz pacing and 80 ms reply window are the retained protocol's, not a product timing claim." ], "closes": "Prepared-but-unexecuted 2026-09-15-ecp5-lowbaud-001 (blocker: test-computer access) - executed and answered by this run.", "next": "Physical split of adapter/USB/host vs board UART: FTDI loopback at both bauds (no board) or a logic analyser on the board TX/RX pins during a long run; the CPU-independent transmitter named in the 2026-09-15 plan." } { "schema": "endstop.board-test-manifest.v1", "run_id": "2026-09-27-ecp5-serial-split-001", "status": "completed_bursty_confirmed_instrument_ready", "claim_class": "company_authored_engineering_evidence", "hypothesis": "An instrumented mediator image (replies carry a processed-request counter; damaged inbound frames raise an E event instead of the production silent discard) plus a tolerant soak runner classifies every lost exchange as inbound-corruption, request-lost-inbound, or reply-lost-outbound - splitting the unresolved serial corruption by direction without physical access to the rig.", "instrumentation": { "firmware": "board-mediator-binary built from the retained 2026-09-08 source (same tree as 2026-09-27-ecp5-lowbaud-002) with two diagnostic changes: (1) 64-byte reply format adding a u32 processed-request counter, (2) E events (framing-length 'f' / CRC 'c') on damaged inbound frames. Policy, monitor, lease and divisor (1 Mbaud) unchanged. Diff retained as inputs/board_mediator_binary.rs.", "runner": "split_soak.py, tolerant: continues past faults, classifies each fault from the next reply's counter and any E event; 25 Hz; 80 ms reply window; every exchange validated (COBS, CRC32, echo, decision, lease).", "e_validation": "The first attempt sent frames without the CRC trailer by mistake; the board raised an E event for every request, received and decoded correctly - the E path is validated end-to-end (attempt retained as captures/soak-attempt1-nocrc on the board Mac)." }, "results": { "soak_instrumented_image": "45,000/45,000 exchanges clean. Zero faults, zero E events, zero anomalous frames (report: captures/soak-instrumented-report.json).", "soak_control_production_format": "45,000/45,000 exchanges clean with the SAME production-format image (2026-09-27-ecp5-lowbaud-002 baud1m, bitstream 7c21681a...) that failed 4/4 runs at 104-1402 exchanges earlier the same afternoon (report: captures/soak-control-report.json).", "total_clean_today_after_burst": "90,000 consecutive exchanges across two images (about 60 minutes) with zero faults." }, "conclusions": [ "The serial corruption is bursty/environment-dependent, not deterministic: identical image, board, adapter, protocol and host failed 4/4 within 1400 exchanges in one window of the day and then completed 45,000 consecutive clean exchanges twice.", "Deterministic-mechanism hypotheses are excluded: fixed request count, buffer accumulation, and firmware-logic-at-a-threshold all fail to explain both observations.", "The board firmware is excluded as a deterministic cause for this window: the same firmware ran clean for 45,000 exchanges.", "The three-way direction classifier is built and validated (E events proven to fire and decode) and will classify the next burst when one occurs; no natural fault occurred during either soak to exercise it." ], "scope_and_exclusions": [ "Large raw event logs (2x20 MB events.jsonl) are retained on the board Mac at ~/Developer/endstop-evidence/2026-09-27-ecp5-serial-split-001/captures/ with SHA-256 in SHA256SUMS; reports, bitstream, firmware and scripts are mirrored here.", "The burst trigger is unidentified: host/USB state, external interference, or thermal are candidates; correlating bursts with host state is the next investigation.", "Two runner bugs (missing CRC trailer; a format patch half-applied) are retained as failed attempts with their captures; the final runner and firmware are the retained versions hashed here.", "Arm-free synthetic holds; no actuator, product I/O or flash; volatile SRAM only; same operator, no independent review." ], "closes": "Deterministic-mechanism class for the serial corruption (count/buffer/firmware-threshold hypotheses).", "opens": "Burst correlation with host/USB state; direction classification of the next natural burst with the validated instrument." }