Add the lab-only Tally write surface behind five gates - #407
Merged
Merged
Conversation
Audit-sprint 2026-09-14 Phase 3.1. Not a default feature; adds no dependencies. A CI gate test (next commit) fails the build if any .github/workflows file ever enables it. Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Gate G4 (audit-sprint 2026-09-14 Phase 3.1). Scans every .github/workflows/*.yml|yaml for the feature name (either spelling) or --all-features and fails with the offending line if found. Runs unconditionally, independent of which features the test binary itself was built with. Includes a tripwire test proving the check can fail. Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Audit-sprint 2026-09-14 Phase 3.1. Adds the agent_lab module declaration (cfg-gated on lab-writes) and, additive alongside the existing tools, the lab_read_inventory dispatch arm and catalog entry. Registration requires both the compiled feature and BRIDGE_LAB_WRITES=1 (checked fresh per catalog build, not cached at startup); the internal tool registry hides it from existence checks the same way when the env var is unset, and tool_payload additionally refuses in-process calls with lab_writes_disabled. No change to any production write path (build_import_xml/post_import/agent_import_post.rs/approved_import.rs). Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Audit-sprint 2026-09-14 Phase 3.1/3.2. Adds render_agent_lab_inventory_vouchers, a thin lab-only wrapper over the existing render_windowed_vouchers machinery with an ALLINVENTORYENTRIES.* FETCH list in place of vouchers'/ledger_movement's ALLLEDGERENTRIES.* -- reuses the same windowing (and therefore the same window_honoured corroboration path) rather than a parallel one. Compiled only behind lab-writes. Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Audit-sprint 2026-09-14 Phase 3.1/3.2. Additive, lab-writes-only module: - Runtime guards, all fail-closed with explicit error codes: BRIDGE_LAB_WRITES=1, BRIDGE_TALLY_PORT=9001, BRIDGE_LAB_TARGET_GUID and BRIDGE_LAB_DENY_GUIDS (comma list, both well-formed GUIDs). - admit_lab_target: reserved for the Phase 3.5 lab writer -- re-verifies the port/env guards, that the observed loaded-company set includes the target and excludes every deny GUID (lab_source_company_loaded/lab_target_not_loaded), and the target identity (4 fields) via the existing verified_company. Every request this module builds renders SVCURRENTCOMPANY from that verified identity's exact display name, making the SVCURRENTCOMPANY-equals- target requirement structural rather than a separate check. Not called by lab_read_inventory (a read does not need the target to be the company read, or to be the company currently loaded) -- kept for the next pass to reuse. - lab_read_inventory (read-only): units, godowns, stock groups, stock items (parent, base unit, opening qty/rate/value, GST/HSN fields as returned, unclassified -- no signed compatibility evidence exists yet for any of them), and inventory entries per voucher (with nested batch allocations) for a date window, reusing window_honoured. - Every lab request/response persisted under data_dir/lab/, named and manifested by their own sha256 (contrast egress_log, which never persists raw bodies). - Unit tests on synthetic fixtures only (BRIDGE CORPUS GST-style shapes), no client data, no live Tally connection. Does not modify agent_import_post.rs or approved_import.rs. Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Audit-sprint 2026-09-14 Phase 3.4/3.5 groundwork. Adds TallyRuntime::post_lab_import, a lab-only method that posts already-built import XML directly to the Tally XML gateway through the same serialized session queue and retry policy as every other operation (post_probe_xml), but without the native-approval / durable-dispatch-ledger machinery post_approved_import layers on top for the production Journal path. That machinery is the production path's safety (one human-approved Journal at a time); the lab writer's safety is its caller's admit_lab_target re-check before every batch, not this method. Compiled only behind the lab-writes feature. Does not modify agent_import_post.rs or tally/approved_import.rs. Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Audit-sprint 2026-09-14. Two lab-only write tools, feature+env gated the same way as lab_read_inventory, both re-verifying admit_lab_target's loaded-company/deny-list/target-identity guard before every batch: - lab_import_masters: creates units, godowns, stock groups, groups, ledgers, stock items (in that plan order) from the book model's masters section. Refuses before any write if the target already carries a same-name master under any requested kind (the Create-overwrite trap, TALLY_PROTOCOL_ REFERENCE.md Sec 9.4), using the master-name fold measured on licensed TallyPrime 7.1 (Sec 9.4d). Batches of <=200; every batch is read back field-by-field (name, parent, opening balance/qty, GST fields) and the call stops on the first mismatch. - lab_import_vouchers: creates Journal/Payment/Receipt/Contra (own renderer, not agent_import.rs's -- see module doc for why) plus accounting- and invoice-mode Sales/Purchase/Credit Note/Debit Note, sorted by date and batched at <=100. Before sending a batch, reads its date window back and matches every voucher by type/date/ledger-amount plus a narration marker or voucher number; a fully-matched batch is skipped (resume), a partial match stops rather than guessing, only an unmatched batch is sent. Every sent batch is read back the same way; stops on the first mismatch. Group/Unit/Godown/StockGroup/StockItem master XML and every invoice type but Sales are UNVERIFIED for the gateway (no live capture in this repository) -- documented in the module's own doc comment and this worker's receipt/report. Unit tests (agent_lab_import_tests.rs, 33 tests): golden XML fixtures for every master kind and every voucher shape, the Sec 9.4d name-fold (including the negative cases: en dash/underscore not folded, NFC/NFD not normalised), read-back mismatch detection, resume matching (marker, voucher number, cancelled-voucher exclusion, content-only rejection per Sec 9.3), and the book-model parser (inline JSON and book_path file). cargo test --features lab-writes --lib: 962 passed, 0 failed. clippy -D warnings clean both feature states. cargo fmt clean. Release bridge_mcp --features lab-writes built; sha256 recorded in the worker receipt. Does not modify agent_import_post.rs or tally/approved_import.rs (diff against origin/master is empty). Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
…se 3.4) lab_import_masters previously refused on ANY same-name master, including Tally's own auto-created defaults every new company already has (ledger Cash under Cash-in-Hand, Profit & Loss A/c under the reserved primary root, and any reserved Group) -- the first live rehearsal attempt hit exactly this refusing on Cash/Profit & Loss A/c collisions with zero writes made. - is_default_ledger/is_default_group: recognise a default by name *and* observed parent/RESERVEDNAME, so a renamed or relocated same-name master still falls through to the ordinary collision refusal. - A default is never (re-)Created (Create-overwrite trap); for Ledger, a partial Alter carries only a genuinely-changed writable field (OPENINGBALANCE only -- GST fields are Alter-inert per §8.3, never offered). Defaults are included in the mandatory read-back diff. - Parent comparison normalises Tally's reserved-primary marker via bridge_tally_protocol::is_tally_reserved_root (reused, not reinvented) without ever writing the marker back. - New guard found while inspecting the rehearsal book: a requested Group literally named with the sanitized U+0004 marker (the self-referential root, mis-captured by build_book.py as a "custom" group) is refused outright -- it never collision-matches Tally's own plainly-named "Primary" row, so without this it would have been silently Created with a garbled name. 10 new unit tests (default skip, default opening alter, true collision still refused, reserved parent normalisation, reserved-root name guard). Production write guards (agent_import_post.rs, approved_import.rs) untouched -- diff vs origin/master is empty.
…eporting The 2026-09-14 10:10 IST rehearsal sent 17 ledger Creates to BRIDGE REHEARSAL and Tally answered CREATED=0 ERRORS=0 EXCEPTIONS=17 (no mutation). Diffing the sent request against the shape this exact company's masters were live-created with on TallyPrime 7.1 (babul-masters-complete.xml) found four divergences, all fixed in the master renderers (ledgers, and the same conventions applied to groups/units/godowns/stock groups/stock items and the default-ledger partial Alter): - every renderer now includes a <NAME> child mirroring the NAME attribute (missing before) - <ISBILLWISEON> is now always explicit (defaulting to No), never omitted - <OPENINGBALANCE>/<OPENINGVALUE> are only emitted when non-zero, matching the proven capture's zero-balance ledgers - <TAXTYPE> is only emitted when the book value is a real GST/duty classification (not empty/"Others") and the ledger's parent is Duties & Taxes -- the rehearsal request sent TAXTYPE=Others on every ledger including a bank account and a wages ledger - xmlns:UDF="TallyUDF" is dropped everywhere: nothing here ever emits a UDF-namespaced element, so the declaration bound to nothing Also: lab_import_masters/lab_import_vouchers now check the import response's ERRORS/EXCEPTIONS counters immediately after posting, before the mandatory read-back, and report an outright rejection explicitly as state "tally_rejected" with the full counter set and any <LINEERROR> text -- instead of proceeding to a read-back whose only signal is "not found", indistinguishable from a request that was never sent. Golden XML tests updated to the proven shape, with three new fixtures derived byte-for-byte from babul-masters-complete.xml (HDFC Bank 1649, Sales, Sri Ram Cables Private Limited), plus a TAXTYPE-suppression test and coverage for the new tally_rejected reporting path using the exact captured rehearsal response. CODE ONLY -- no live Tally writes performed by this change. cargo test --features lab-writes: 985 lib + 4 + 2 passed, 0 failed cargo test (no feature): passed, 0 failed cargo clippy --features lab-writes --all-targets -- -D warnings: clean cargo clippy --all-targets -- -D warnings: clean (module is feature-gated out entirely without lab-writes) cargo fmt -- --check: clean Production write guards (agent_import.rs, agent_import_post.rs, tally/approved_import.rs): unchanged vs origin/master Release build (bridge_mcp --features lab-writes): sha256 485289ff2b2a4bafec0ddeb87ae8b8bca7b3ba295db56803dc4f15d2319905c5 Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
…master resume Live rehearsal follow-up (2026-09-14): the prior commit's shape fix worked -- Tally CREATED all 17 ledgers, counters clean -- but the run then stopped on false mismatches from the lab read-back parser: parents observed as "Duties Taxes" / "Loans Advances (Asset)" (note the double space -- the `&` entity dropped entirely, not left literal). Production `ledger_masters` against the same company correctly reports "Duties & Taxes"; the bug was local to the lab read-back parsers. Root cause: quick_xml delivers a general entity/character reference (`&`, ``, ...) as its own `Event::GeneralRef`, separate from the surrounding `Event::Text` events -- every other native-collection parser in this crate (agent_voucher_parse.rs, agent_change_parse.rs, agent_company_checkpoint.rs, source_draft_xml.rs) already handles this event via `decoded_agent_reference`; the lab read-back parsers did not, so the reference was silently dropped by their catch-all match arm. Fixed in all three lab read-back parsers (agent_lab.rs's parse_lab_master_rows and parse_lab_inventory_vouchers, agent_lab_import.rs's parse_voucher_readback_nested) by adding the identical GeneralRef-handling arm the production parsers already use. find_readback_row/readback_mismatches needed no change -- they consume already-decoded rows, so fixing the parser fixes them too. Also, idempotent resume for lab_import_masters: a same-name master already in the target is no longer an automatic collision. If it matches the book on every field this tool would itself have written (parent, bill-wise flag, opening balance, and GST fields only where the book specifies a real classification -- new already_present_verified_mismatches/ledger_already_present_mismatches, reusing diff_unit/diff_parented/diff_stock_item for non-ledger kinds), it is reported as already_present_verified and excluded from the Create batch rather than refused or re-Created. Any field difference still falls through to the ordinary lab_master_already_exists refusal. An all-already_present_verified result still reports ok:true with nothing new created, so a resumed run proceeds straight to vouchers. run_rehearsal.py (Brain, not part of this repo): added operator-visible logging for the already_present_verified/idempotent-resume case: the existing `ok` gate already treats it as success, this only narrates it instead of looking like a suspiciously quiet masters step. New tests: entity-decoding coverage for parent names (master read-back, using the exact "Duties & Taxes"/"Loans & Advances (Asset)" case) and for party/ledger names and narration (voucher read-back); idempotent- resume coverage for a clean match, a bill-wise mismatch, an opening- balance mismatch, a real-GST-type mismatch, TAXTYPE="Others" correctly ignored outside Duties & Taxes, a non-ledger kind via the shared diff functions, and an end-to-end classification test mirroring the precheck loop for both the match and the mismatch path. CODE ONLY -- no live Tally writes performed by this change. cargo test --features lab-writes --lib: 994 passed, 0 failed (77 in agent::lab::*::tests, up from 68) cargo test --features lab-writes (full): passed, 0 failed cargo clippy --features lab-writes --all-targets -- -D warnings: clean cargo clippy --all-targets -- -D warnings: clean (lab module is feature-gated out entirely without lab-writes) cargo fmt -- --check: clean Production write guards (agent_import.rs, agent_import_post.rs, tally/approved_import.rs): unchanged vs origin/master Release build (bridge_mcp --features lab-writes): sha256 1abab7b71b99780cb8cc087616171815ffe7ec55e1491ce28dfe9fbbf20bca43 Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
…rtial Alter Second live rehearsal (2026-09-14): the prior commit's entity-decoding fix worked -- lab read-back no longer drops the & entity -- but the run then refused with lab_master_already_exists on Ledger:Profit & Loss A/c. Root cause: that same fix now correctly decodes the XML numeric reference  to its literal Unicode scalar value (raw U+0004), but is_default_ledger's reserved-primary check called bridge_tally_protocol::is_tally_reserved_root, which only strips its own sanitized placeholder ("\u{fffd}#4;"), not the raw control character -- so a live-correct read-back of "\u{4} Primary" no longer matched, and Profit & Loss A/c was misclassified as a true collision instead of Tally's own default. book.json separately carries a third spelling ("\u{fffd}#4; Primary", literally that placeholder text) via its own Python-side reimplementation. Fixed with is_reserved_root_any_spelling, a new function local to agent_lab_import.rs recognising all three spellings (raw control character, sanitized placeholder, undecoded "" text) and wired into both of this module's reserved-root comparisons. Deliberately NOT a change to bridge_tally_protocol::is_tally_reserved_root itself: that function's narrower definition is a considered, tested choice for the production group-ancestry walk (group_ancestry.rs's own every_refusal_is_distinguishable_and_none_is_an_answer test pins an unrecognised raw marker there as a safe refusal), so widening the shared function would have silently changed behaviour for every one of its other consumers. build_book.py's own is_tally_reserved_root is widened the same way (no equivalent narrower-by-design split to preserve on the Python side). Also, a real data gap the coordinator found: book.json had is_billwise_on=null for every ledger (the source snapshot never fetched ISBILLWISEON), so the 17 created ledgers were bill-wise No in Tally while 53 voucher lines carry bill allocations against two of them -- importing vouchers would have silently dropped those bills. Fixed: - snapshot.py/direct_read.py now fetch ISBILLWISEON/ISCOSTCENTRESON/GST fields directly from Tally for future snapshots (a raw Ledger Export request, bypassing the ledger_masters MCP tool's fields=compliance profile, which does not return them at all). - For the already-closed rehearsal source, build_book.py infers is_billwise_on=true for any ledger with voucher bill allocations (Tally would never have accepted BILLALLOCATIONS.LIST against a bill-wise-No ledger), records is_billwise_on_basis for provenance, and gained a new validator rule (find_billwise_violations) failing the build if any ledger with bill allocations is not bill-wise Yes. book.json.gz regenerated from the existing (source-closed) snapshot -- no live Tally read -- TB validator still passes, exactly the two parties the coordinator named now resolve to is_billwise_on=true. Finally, lab_import_masters can now reconcile an existing target ledger via partial Alter instead of refusing it, when the difference is confined to writable fields (parent already matches): ledger_alter_fields is widened from OPENINGBALANCE-only to also offer ISBILLWISEON, PARTYGSTIN, and TAXTYPE (gated as at Create) -- excluding only GSTDUTYHEAD, which TALLY_PROTOCOL_REFERENCE.md §8.3 specifically measured as settable at Create but silently not updated at Alter. The three newly-offered fields have no equivalent citation; an earlier version of this function excluded them anyway, generalising the one measured field to three unmeasured ones, so they are now attempted and the mandatory post-Alter read-back (via ledger_already_present_mismatches, the same full-equality check the idempotent-resume precheck uses) is what actually proves whether Tally applied them. A parent difference (ledger_parent_mismatch) still refuses unconditionally. The Tally-default-ledger Alter path (Cash/Profit & Loss A/c) is unified with this same mechanism rather than kept as a separate, narrower implementation. Tool result now reports created/already_present_verified/altered_verified per master name; refused masters remain reported via the existing lab_master_already_exists error path (collisions are collected across every kind before any single refusal is returned). CODE ONLY -- no live Tally writes performed by this change. cargo test --features lab-writes --lib: 1001 passed, 0 failed (84 in agent::lab::*::tests, up from 77) cargo clippy --features lab-writes --all-targets -- -D warnings: clean cargo clippy --all-targets -- -D warnings: clean (lab module is feature-gated out entirely without lab-writes) cargo fmt -- --check: clean Production write guards (agent_import.rs, agent_import_post.rs, tally/approved_import.rs): unchanged vs origin/master Release build (bridge_mcp --features lab-writes): sha256 04cca1188b488d8c26bcd8e2b1600c4b921e15ac7a9ccf7277385f798809c4b9 Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
…ucher mismatch detail 2026-09-14 rehearsal batch 1 stopped with `readback_mismatch`, `verified_on_readback: 89` and no per-voucher detail. Root-caused all 11 misses: every field Tally stored (date, type, ledger lines, amounts, narration) was correct; only VOUCHERNUMBER differed from the book's requested value, exactly per brain/10-domains/11-tally/ tally-rewrites-what-you-import.md #6 (TallyPrime silently reassigns VOUCHERNUMBER to its own per-type sequential series in receipt order, supplied value discarded). Two same-date groups in the batch (Payment 20250518 #98-106, Contra 20250609 #9-11) cross a power-of-10 boundary, and `lab_import_vouchers`'s own batch sort compared `voucher_number` as a string ("100" before "98"), scrambling the order those vouchers were POSTED in -- so Tally's receipt-order renumbering landed on different values than the book's for exactly those 11. Three fixes: - `voucher_sort_key`: sort `voucher_number` numerically within a date, not lexicographically, so posting order matches the book's own order and Tally's receipt-order renumbering keeps lining up with it going forward. - `lab_marker_id`: the narration marker embedded via `narration_with_marker` is now a deterministic UUIDv5 of `source_guid`, not a fresh `Uuid::new_v4()` discarded once the write call returns. The old scheme could never be reconstructed on a later precheck/readback, so `voucher_already_verified`'s marker branch was permanently dead code in practice -- confirmed by this rehearsal's own evidence. `voucher_already_verified` also gained a third alternate identity key, `narration_text` (the stored narration minus any `[BRIDGE-LAB:...]` suffix), so vouchers already posted under the pre-fix random marker -- like the 89 verified and the 11 unverified from this run -- can still be recognised on resume without relying on Tally's reassigned VOUCHERNUMBER. - `voucher_mismatch_detail`: `lab_import_vouchers` now reports, for every unverified voucher, the closest observed candidate and exactly which fields (voucher_number / narration_marker / narration_text / each ledger line) differ from the book -- both on `readback_mismatch` and on `partially_verified_uncertain`. Previously only a bare count was reported. Verified against the rehearsal evidence (~/Library/Application Support/Bridge/lab/, batch 1 write request + readback response, sha256 a30a9617.../c6332bf8...): all 100 batch-0 and 100 batch-1 vouchers are present in BRIDGE REHEARSAL exactly once, no duplicates, no cancellations; the 11 differ from the book only in VOUCHERNUMBER, matching the receipt-order mapping the scrambled posting order predicts exactly. 8 new tests (agent_lab_import_tests.rs): `lab_marker_id` determinism, marker-only and narration-text-only resume matches, a narration-text collision still refused without matching ledger content, numeric `voucher_sort_key` ordering (the exact 98/99/100 boundary), and `voucher_mismatch_detail`'s not-found and field-diff shapes. cargo test --features lab-writes --lib: 1009 passed, 0 failed. cargo check --lib (default features, lab-writes off): clean -- guard unchanged. cargo clippy --features lab-writes --lib -- -D warnings: clean. cargo fmt: clean. Release binary rebuilt (bridge_mcp, --features lab-writes): sha256 d337663039a912f11f9803a97a95ee865132c778011d63151c63f87c359c3bfc. No Tally writes performed; diagnosis is read-only evidence analysis plus this code fix. See brain/50-projects/audit-sprint-2026-09-14/snap/rehearsal/batch1_diagnosis.md for the full per-voucher table and resume plan. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
# Conflicts: # src-tauri/Cargo.toml
…inventory This branch had edited five pinned files without resealing, and added a dependency without regenerating the third-party inventory. Both are gates, so the branch was failing CI on its own: a control run on the bare base failed job-for-job identically to a pull request stacked on it, which made a stacked PR's own result unreadable. - `scripts/reseal.sh` (ordinary sequence; the pin list itself did not change, only the contents of already-pinned files). `rehash-surface` reported exactly 5 changed hashes, matching an independent hash of all 212 pinned entries against the manifest: `agent.rs`, `agent_read_profiles.rs`, `tally/runtime.rs`, `Cargo.toml`, `Cargo.lock`. - `scripts/generate-rust-licenses.mjs` for the inventory, which had been missing `sha1_smol 1.0.1` since this branch added it. Now matches 365 locked components. The lab module's own files are deliberately not pinned: the surface attests compatibility claims, and this module states in its own header that no signed evidence exists for anything it reads. Order checked rather than assumed: regenerating the inventory rewrites `THIRD_PARTY_LICENSES_RUST.txt`, which would invalidate a reseal done before it, but that file is not among the pinned entries and `reseal.sh --verify` still reports the surface current afterwards. Verified: `tools` workspace 24/24 on the surface-coverage test that was the dominant failure, `cargo fmt --check` clean, default-feature lib suite 915 passing, dependency inventory clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three parsers in the lab surface tracked a bare `current_tag` and appended every text event to it, choosing the owning row from a depth-shifted `path`. Two properties of real Tally responses defeat that, and no fixture in the module had either, because every one was compact: - Responses are CRLF-indented, so `trim_text(false)` delivers the whitespace between every pair of siblings as its own `Text` event -- 398 such runs in one captured inventory entry. - They are dense with self-closing elements -- 274 in that same entry -- which arrive as `Event::Empty` and never updated `current_tag`. One stale tag therefore absorbed a whole indentation run: an entry's `AMOUNT` read back with forty-odd `"\r\n "` fragments, a `GODOWNNAME` picked up the whitespace closing the batch below it, and master rows grew phantom whitespace-only fields. Separately, a master row was seeded from its `NAME=` attribute and then had the `<NAME>` child appended onto it, giving `KgsKgs`. Replaced with a buffer that holds an element's text and releases it only when that element closes with no child having intervened, resolving row ownership at `End` where the path is unambiguous. `Text`, `GeneralRef` and `CData` all feed one buffer, so a value split across any combination rejoins in order. The `NAME=` attribute became the fallback for a row with no `<NAME>` element. Deliberately not a trim: Tally left-pads a quantity with one real space to hold the sign position, on every `ACTUALQTY` and `BILLEDQTY` in the captured days. Trimming would corrupt correct output while making the symptom vanish. The fixtures carry that shape and assert it exactly. `parse_voucher_readback_nested` in `agent_lab_import.rs` carried the identical defect and is what the import mismatch report compares, so an `AMOUNT` growing an indentation tail reported a false mismatch against a voucher Tally had stored correctly. Converted to the same buffer. Eight regression tests, each confirmed to fail against the parser as it stood and pass after. Verified beyond the fixtures by replaying the fixed parser over three captured inventory days -- 42 vouchers, 46 entries, 17 batch allocations, no accumulation -- where the previous parser fails on the first entry. Those captures are client data and stay outside the repository. Two independent reviews. The first found `Event::CData` was being dropped, which is what turned up the third parser. The second found the read-back test used a nested element no assertion read, so it passed against the broken parser; it now collides with a field the entry binds. Does not close bridge#379: this lands on the lab branch, not master.
# Conflicts: # docs/tally/compatibility/compatibility-matrix.json # docs/tally/compatibility/compatibility-surface.json
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
added 2 commits
September 16, 2026 00:53
# Conflicts: # docs/tally/compatibility/compatibility-matrix.json # docs/tally/compatibility/compatibility-surface.json
# Conflicts: # docs/tally/compatibility/compatibility-matrix.json # docs/tally/compatibility/compatibility-surface.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings the audit-sprint lab surface onto master. It has been developed on a
branch that was deliberately kept local until it was tested and its safety
gates were verified.
What this is
A lab-only, additive surface for driving a Tally instance during the audit
sprint: guard machinery, one read tool (
lab_read_inventory), and two writetools (
lab_import_masters,lab_import_vouchers).It cannot execute a write for anyone who does not deliberately enable it
Five independent gates, each checked against this branch's tree rather than
taken from a comment:
src-tauri/Cargo.tomlhas nodefault = [...]list at all;
lab-writes = []is pure opt-in and nothing pulls it in.feature or uses
--all-features.src-tauri/tests/lab_writes_ci_gate.rsfails thebuild if any workflow ever does, runs unconditionally regardless of which
features the test binary was built with, and includes a tripwire proving
the check itself can fail.
agent.rsdeclares the module under#[cfg(feature = "lab-writes")], so a default build does not compile it.BRIDGE_LAB_WRITES=1, the endpoint pinned to port 9001, andBRIDGE_LAB_TARGET_GUID/BRIDGE_LAB_DENY_GUIDSboth present andwell-formed — re-read on every call, not cached. Every write batch
re-verifies the loaded-company set and the target's identity immediately
before dispatch.
Production write guards (
agent_import.rs,agent_import_post.rs,approved_import.rs) are untouched; this adds a parallel surface rather thanchanging those.
Read-path defects this found, already on master
Building it against a real book surfaced four defects that no synthetic
fixture could reach, each losing an entire window rather than one voucher.
Three are already fixed on master (#378/#389, #387 and #388 via #393); the
fourth, #379, is fixed on this branch by the most recent merge here and stays
open until this lands.
Notes for review
by four entries in Decide which proposed vouchers are already in the book #294.
scripts/reseal.sh --verifyreports current.sha1_smolwithout it. Matches 365 locked components.compatibility surface: that surface attests compatibility claims, and this
module states in its own header that no signed evidence exists for anything
it reads.
Local verification:
cargo fmt --checkclean, 936 default-feature tests,1036 with
--features lab-writes, tools workspace 13/13 suites, dependencyinventory clean.
🤖 Generated with Claude Code