Two steps, one worker each; a worker sees only this objective and its own step text. Do only your step; the other step's text is deliberately not here, so never ask for it. Project: Sworn (symbol SWORN), an ownerless ERC-721 registry of facts about wallets, Foundry, three contracts (Registry, Composer, Renderer), continuing the project's newest job (its result is your starting tree). Two corrections to the burn rule in src/Registry.sol plus one test gap, all found by the independent verification of that job; nothing else changes.
CORRECTION 1, preview gas. _burnOrRefund reads burnExecutor.previewBridge() in try/catch with a 200,000 gas cap. Measured against the real IMD BurnExecutor V2 (0xe29386719C155B6847aD5a4E97C6674f10ffc750) on 2026-10-16: eth_call at block 26,202,500 returns (0,0,0) below about 293,000 outer gas (about 272,000 at the CALL), because the executor catches its inner OFT quote running out of gas, and the real quote (454.94 IMD, native fee 0.000219 ETH) above it; a fork trace at block 26,202,203 shows the cold call consuming 264,408 gas. So the delivered rule never burns on mainnet (the amount reads below BURN_MIN; silent refund). The delivered fork test hides it: it reads the uncapped quote first in the same function, so the capped read runs warm (EIP-2929), while a mainnet claim reaches the executor cold. Fix: uint256 internal constant PREVIEW_GAS = 600_000; as the gas argument of that call (2.2 times the measured need, below BURN_GAS); nothing else in the rule moves.
CORRECTION 2, executor without code. try/catch catches only a revert of the external call; the three return words are decoded outside it, so an executor address with no code (a mistyped deployment argument) reverts claimSponsored and upgradeSponsored for every wallet for ever, and an ownerless registry cannot repair it. Fix: in the constructor, when burnExecutor_ is not zero, revert ExecutorHasNoCode() if burnExecutor_.code.length == 0 (zero stays allowed and means no burn rule, which the Sepolia rehearsal uses). A coded executor returning fewer than three words still reverts a claim: document it as the residual; add no low-level call for it.
TEST GAP. test_paidFunctionsRemainNonpayableAndNeverTriggerBurn spends the caller's IMD first and accepts any revert, so making upgrade() payable survives the whole suite (measured: 165 passed). Step 1 replaces it with a funded regression.
RULES. Touch only src/Registry.sol, test/BurnRule.t.sol, test/mocks/MockBurnExecutor.sol (its gas fixture and its refund path only), test/fork/BurnRule.fork.t.sol, test/NOTES.md, README.md, CONCEPT.md, INTEGRATION.md, DISCLOSURE.md. Composer, Renderer, Types, the generator, the goldens, Deploy.s.sol, foundry.toml and every other test stay byte-equal. No new production contract (test-only helpers under test/ are fine), no compiler-setting change, no removed behaviour; local factoring of the pool paths and fixed small codes only if the Registry would not fit otherwise. SIZE: the Registry's runtime is 24,495 B (81 B under EIP-170) before this job and both corrections are known to fit without factoring; measure after the change with forge build --sizes and report it; if it does not fit, stop and report instead of removing behaviour. CHECKS for every step: forge build, forge fmt --check, forge test (offline, 165 pass today, 15 fork tests skipped), python3 tools/gen_template.py --check (28 artifacts), python3 -m unittest discover -s tools (18 tests). FORK TESTS: test/fork/BurnRule.fork.t.sol stays opt-in exactly as it is (forge test --match-contract BurnRuleForkTest --fork-url --fork-block-number 26202203; no environment reads in the offline suite); if no mainnet archive RPC answers, say so rather than weakening a test. Never publish anything.
DOCS (step 1). README 'Free claims and the burn rule', INTEGRATION section 5b, CONCEPT, DISCLOSURE and test/NOTES.md must say what is true after the change: PREVIEW_GAS 600,000 and why (the measurement above, with block and date); at the pinned block the corrected preview returns the real quote and the fork test burns; the constructor rejects a nonzero executor without code; a claimant should attach exactly the fee quoted in the same block, because the executor re-quotes when it bridges and keeps the whole attachment if the quote rose; and the residuals: short return data from a coded executor, the executor owner's authority over token, OFT, destination, options and minimum, a future quote above PREVIEW_GAS or BURN_FEE_CAP, the asynchronous Base burn. The rule stays best effort: remove every sentence that says the capped preview returns zero at the pinned block, but promise no future liveness.