{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"ecce04a1-96c0-400f-bcc2-d141e6fc7175","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"432bbb83f9326ae0dd30461b2477b9ef9393ee2337778fa1504a0fcff079d3d3","dependsOn":[],"execution":{"mustProduce":["dist/index.html"],"network":true,"optionalTools":["browser"],"profile":"none","requires":["network"],"skillHash":"a60bc8b42446c13d993341179fe13c712a5addb118fc532fb2d15e71f912efc8","skillId":"build-website","tools":[]},"key":"build_website","kind":"code","role":"implement","skillHash":"a60bc8b42446c13d993341179fe13c712a5addb118fc532fb2d15e71f912efc8","skillId":"build-website","state":"accepted"},{"acceptedSubmissionHash":"ae83a3fb9a341c2630c03d8dcbbca3049bc334623fd25cc3a5ee4da82a95516a","dependsOn":["build_website"],"execution":{"network":true,"optionalTools":["browser"],"profile":"none","requires":["network"],"skillHash":"fd33b6741366d364a55a4c0ba2bc4f5d329cec0b62f27a83289dc5b30ab03575","skillId":"design-critic","tools":[]},"key":"design_critic","kind":"code","role":"review","skillHash":"fd33b6741366d364a55a4c0ba2bc4f5d329cec0b62f27a83289dc5b30ab03575","skillId":"design-critic","state":"accepted"},{"acceptedSubmissionHash":"7bc654dee1513c603690e3493520345455e556126a43ec377fff30c6c21b0973","dependsOn":["build_website"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"8189a3059fc9bb774ad7dcee66b87f32e25d781025f0e9f82a4c75182fe0ef19","skillId":"site-content-check","tools":[]},"key":"site_content_check","kind":"code","role":"review","skillHash":"8189a3059fc9bb774ad7dcee66b87f32e25d781025f0e9f82a4c75182fe0ef19","skillId":"site-content-check","state":"accepted"}],"objective":"One step on this project's site, the Sworn registry site (.imd/reads/project.md): implement items 1 to 7 below, rebuild and commit the static export in dist/ so the same site name serves it, then check it. Static as before: no server, key or analytics; tests use a fake EIP-1193 wallet and fake RPC and API answers; nothing is signed or sent. Change nothing else: addresses, chain, ABIs, layout, routes, the eligibility snapshot, the read-back windows and copy stay, except what the items name. Decide, do not ask: a question blocks the job. (1) No reads after a check gives up. Measured on 2026-10-22 against mainnet with the delivered rpc.mjs: with tenderly answering 429, the 601 read of blocks 25090085 to head minus 64 could only be answered by mevblocker, thirdweb refused it for size, and the pool kept halving the range: the check returned 'Could not check eligibility' at its 20 s deadline after 154 to 271 calls, and the pool then made about 400 more calls in the next 60 seconds across all four RPCs. A range is split only when every endpoint that refused it refused it for size; once the caller's deadline has passed, or the page or wallet changed, the pool sends no further request for that read. (2) The 'Requested more than 2 hours ago.' notice follows the clock: it shows when the request's own time is more than 7,200 seconds old, whatever the block count. (3) The site's test notes describe this round and round 7: per item what each test checks and its result, and, from a real browser on the site's origin, which RPC served each kind of read. (4) 'Check older blocks' only when it is needed. In step 02 a fact row shows it only when that row's read failed or the 24-hour window could not settle what the row needs (for example a pending request of this wallet older than the window); otherwise the row shows neither the button nor 'No request found since launch.'. The feed's button for a request older than 2 hours and the shared fact's 'Stored before the last 24 hours' button stay. (5) A 'Mint this fact' button on every step 02 fact row the connected wallet can request (not proven, not pending, not impossible): it opens the same payment dialog as 'Mint selected facts' for that fact alone, with its eligibility check, price and 'Request anyway' rules, and leaves the other rows' selections unchanged. (6) Row order: each fact row reads, left to right on one line, the row's text, then its card preview, then its buttons ('Mint this fact', then 'Check older blocks' when shown). On narrow screens the parts may wrap but keep that order and cause no horizontal overflow. (7) A new page 'Wallet Facts' (menu entry after Claim, hash route #/wallet-facts). The Claim page's 'Swarm progress' section moves there unchanged: the connected wallet's open requests with their live panel progress and the line 'Live panel progress, not proof. Facts and card updates come from the Registry.' Without a wallet the page says 'Connect a wallet to see its requests.'; with no open request 'No open request for this wallet.'. The Claim page no longer draws that section; where it was, while requests are open, it shows one link 'Swarm progress: Wallet Facts'. The payment dialog's own progress stays as it is, and so does step 02's 'Check swarm' block for an undelivered verdict. Wallet Facts also shows the history of the connected wallet's claimed facts: every fact its card holds, catalog and community, each with how it was proven, either direct, frozen at the card's mint (Registry.mintedAtBlock, shown as that block's date), or panel-sworn (Registry.verified: its oracle request id linked to the IMD explorer, its evidence window, and the attested time from api.imd.fun/oracle/requests/<id>, which allows CORS). It reads this from Registry state, not old logs, so it needs no 'Check older blocks'.","parentJobId":"342c6c14-3978-4781-8db1-82ec85f3a75e","planHash":"740827a837e61ce921b763eb8fbc80c685718cb371e7dfd595e71870ab23e78b","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"4f2565af-3ba6-4fde-9444-473ed6b1ee68","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2412-workflow-frontend-stage-context"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51474","feedbackHash":"7cdfd052c166b9d76fe06422787e506b5fa84e309c2f72e869c14c7327b6c4f5","nodeKey":"build_website","submissionHash":"64ce3280d627b06f523ca54c6901bfad1bc6e2873ebeea8a33870b13bd116967","tag1":"verification:structural","tag2":"acceptance-v2","value":1},{"agentId":"51198","feedbackHash":"591a9975d6b8120e336dce4100cc2863adb75d7b153385a30576f46ca7bb4ca3","nodeKey":"build_website","submissionHash":"432bbb83f9326ae0dd30461b2477b9ef9393ee2337778fa1504a0fcff079d3d3","tag1":"verification:structural","tag2":"acceptance-v2","value":1},{"agentId":"50957","feedbackHash":"9afa9bd1a06405515ad545b0b5ab0a9817cd7e069d8efb08f8272113e8f9f35c","nodeKey":"design_critic","submissionHash":"bfaf9c703fd8bf3b0ecd49a4e5a03964299e2ed04497c36036cb0653b94d2bc4","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"53916","feedbackHash":"dffc4a0c2b0ea8339e5e47f7320ceb14b0a6ff61c2116f10436f109a892127ea","nodeKey":"design_critic","submissionHash":"ae83a3fb9a341c2630c03d8dcbbca3049bc334623fd25cc3a5ee4da82a95516a","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51875","feedbackHash":"b06ff9a36f4f5288919a01ec21ea2547f44ced6f212484da225bb68a6666241d","nodeKey":"site_content_check","submissionHash":"7bc654dee1513c603690e3493520345455e556126a43ec377fff30c6c21b0973","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51023","feedbackHash":"2d13b54cdb9ca010e6045aca76001bd515899a1330bf725e6ad3dc30b4ea4219","nodeKey":"site_content_check","submissionHash":"782bbb0fc50fe8a661be043af84c7ecfed80cc989a8f49813e0748ea298c33d9","tag1":"review:submission","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"ab8685c022f38fd244c1f670c265fafc8af1d70b96b0c08ae16abe7f83447cb8","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"0fe108c4c3eb2c198a7036a6542ce96154f00e39f790dcb5349b37ddf0e0f686","device":"29ea8835baa3dfe1","findings":[],"hash":"432bbb83f9326ae0dd30461b2477b9ef9393ee2337778fa1504a0fcff079d3d3","nodeId":"f4db671a-2f92-4c9b-8366-d35e34bf4787","outcome":"completed","summary":"","treeHash":"c44c5e5ce19e408c7cf5a50467aeed7741b02f9d","usage":{"cachedInputTokens":5507294,"inputTokens":104,"model":"claude-opus-5-5","outputTokens":32352,"runtime":"claude","turns":53,"wallClockMs":787496}},{"artifacts":[],"attempt":1,"bundleHash":"90e7af39874ffb766f73d6b34812cc410f9690525a640ed3d760a8932e79392d","device":"0e3b71e2ffcd200b","findings":[],"hash":"64ce3280d627b06f523ca54c6901bfad1bc6e2873ebeea8a33870b13bd116967","nodeId":"f4db671a-2f92-4c9b-8366-d35e34bf4787","outcome":"completed","summary":"","treeHash":"00dca3c68382fdaf9909027d9de3555282634ea2","usage":{"cachedInputTokens":5821297,"inputTokens":104,"model":"claude-opus-5-5","outputTokens":54603,"runtime":"claude","turns":53,"wallClockMs":649254}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"ca080fd306399669","findings":[{"citation":"resolved","description":"The objective's item 3 requires the site's test notes to describe this round and round 7: per item what each test checks and its result, and, from a real browser on the site's origin, which RPC served each kind of read. The delivering commit 5ea5014 changed 20 files (rpc.mjs, claim.tsx, wallet-facts.tsx, swarm.tsx, tests/round8-browser.mjs, tests/rpc-deadline.test.mjs, dist/...) but not web/TEST-NOTES.md, web/README.md or docs/. The notes' most recent section is the round-8 'Current settled-event snapshot (2026-10-22 UTC)'; nothing in the file mentions 'Wallet Facts', 'Mint this fact', the 7,200-second notice, the pool's no-split / no-read-after-deadline rule, mevblocker, or a per-RPC table of served reads. The code for items 1, 2, 4, 5, 6 and 7 is present in the source and the built export (dist/assets/index-BUxF41LC.js contains 'Wallet Facts', 'Mint this fact', 'Connect a wallet to see its requests.', 'No open request for this wallet.', 'Swarm progress: Wallet Facts', 'Requested more than 2 hours ago.', 'Read stopped by its caller.'), so this is a documentation gap, not a hosting risk.","line":1,"path":"web/TEST-NOTES.md","reproduction":"Run `git log --oneline -1 -- web/TEST-NOTES.md` (last change is 967ea75, the round-8 snapshot job, not HEAD 5ea5014). Run `grep -n -i 'wallet facts\\|mint this fact\\|7,200\\|round 7\\|mevblocker.*served' web/TEST-NOTES.md`: no match. Expected: a section for this round listing, per item 1 to 7, the test, its result, and the RPC that served each kind of read from a real browser; actual: none.","severity":"medium","snippet":"# Sworn frontend validation","title":"Item 3 not delivered: web/TEST-NOTES.md has no notes for this round (items 1 to 7) nor for round 7, and no per-RPC 'which RPC served each kind of read' record"},{"citation":"resolved","description":"Item 7 says each panel-sworn fact shows 'its oracle request id linked to the IMD explorer'. In the Attested component the link `https://explorer.imd.fun/jobs/<jobId>` is rendered only if the fetch of `https://api.imd.fun/oracle/requests/<id>` succeeds and its body has a jobId string. If the API request fails (CORS blocked, offline, 5xx), returns a different id, or has no jobId, the row shows 'Oracle request: <uuid>' as plain text with no link, and 'Attested: time unavailable' or 'not recorded'. The Registry's verified() record (oracleRequestId bytes32) is available on chain, so the link could be built from the on-chain id alone; as written the link depends on a live API call. Advisory only.","line":64,"path":"web/src/wallet-facts.tsx","reproduction":"Connect a wallet whose card holds a panel-sworn fact (Registry.verified(wallet, id) returns a non-zero oracleRequestId). Open #/wallet-facts with requests to api.imd.fun blocked (devtools request blocking or offline). Expected per item 7: the oracle request id is a link to the IMD explorer. Actual: the span reads 'Oracle request: <uuid>' with no anchor element and 'Attested: time unavailable'.","severity":"low","snippet":"        {job ? (","title":"Item 7: a panel-sworn fact's oracle request id is linked to the IMD explorer only when api.imd.fun answers with a jobId; otherwise the id is plain text"},{"citation":"resolved","description":"What was checked and seen. Item 1 (web/src/rpc.mjs): logs() splits a range only when `sized = refused > 0 && sizeRefused === refused` (every refusal was a size refusal; 403/429/503 and rate-limit or archive wording are never size refusals), and every fetch carries the caller's AbortSignal with halt() checks before each request; eligibility.mjs scopes its pool to a controller aborted at the 20 s deadline, on return, or on the caller's signal; transactions.tsx aborts checks on wallet change and on unmount of the Claim page. Item 2 (swarm.tsx lines 259 and 317): the notice follows `Date.now()/1000 - requestedAt > 7200`, not a block count. Item 4 (claim.tsx lines 1226 to 1237, 1317 to 1331): 'Check older blocks' shows only when the 24-hour read failed (unproven rows) or a pending request of this wallet is older than the window; 'No request found since launch.' only after that read-back; the feed's and the shared fact's buttons are unchanged. Item 5 (claim.tsx line 1304): 'Mint this fact' on requestable rows calls prepareFacts([id]), the same journal.prepare path as 'Mint selected facts', and the dialog's own effect runs checkPersonal on open; selection state is untouched. Item 6: DOM order label, Card miniId, row-actions; .picker-row is a flex row that wraps below the narrow breakpoint with .row-actions at 100 % basis. Item 7: route /wallet-facts after Claim in ROUTES, Wallet Facts page with the three required texts, Claim shows the 'Swarm progress: Wallet Facts' link while requests are open and no longer renders the feed (the step-02 Check swarm block stays); history reads tokenOf, lookup, mintedAtBlock, getBlock and verified() only. Hosting safety: dist/index.html loads only ./assets/index-BUxF41LC.js and ./assets/index-jTEdvq39.css; the export's outbound hosts are the four read RPCs, api.imd.fun, explorer.imd.fun, wallet-SDK deep links and 4byte.sourcify.dev (viem signature lookup); no remote code, iframe, redirect, key or seed prompt, or analytics was found. Not done: web/node_modules is absent, so npm test, the Playwright pass and the mainnet reads with each RPC blocked in turn were not executed here; the delivered tests (tests/rpc-deadline.test.mjs, tests/round8-browser.mjs) were read, not run.","line":12,"path":"web/package.json","reproduction":"Not a defect. To complete the unexecuted part: in web/ run `npm ci`, `npm run test:unit`, `node tests/round8-browser.mjs`, then open the export in Chromium with each of the four READ_RPCS blocked in turn and record which RPC served eth_getLogs, eth_call and eth_getBlockByNumber.","severity":"info","snippet":"    \"test:browser\": \"node tests/browser.mjs\",","title":"Review limits: items 1 to 7 were checked by reading the source, the built export and the tests; the per-RPC blocked-mainnet browser pass could not be run in this review's time budget"}],"hash":"782bbb0fc50fe8a661be043af84c7ecfed80cc989a8f49813e0748ea298c33d9","nodeId":"a909783f-17d5-4f71-afac-cd9b2b796430","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds three entries. Nothing else in the tree was changed.\n\n**Outcome: nothing blocks hosting.** No critical or high finding. The export's only script and stylesheet are local, outbound hosts are the four read RPCs, api.imd.fun, explorer.imd.fun, wallet deep links and viem's signature lookup, and there is no remote code, iframe, redirect, seed or key prompt, or analytics.\n\n**Findings written**\n\n- **Medium, item 3 missing.** The test notes in `web/TEST-NOTES.md` were not touched by the delivering commit. They contain nothing on this round or round 7, and no record of which RPC served each kind of read from a browser. Reproduction is a grep for the new texts and the file's git history.\n- **Low, item 7 partial.** In `web/src/wallet-facts.tsx` the oracle request id links to the IMD explorer only when the api.imd.fun fetch succeeds and returns a jobId. With the API blocked, the id is plain text and the attested time reads unavailable.\n- **Info, review limits.** Items 1, 2, 4, 5, 6 and 7 were confirmed in source and in the built bundle: no range split unless every refusal was for size, aborted signals stop all pool reads, the two-hour notice follows the clock, conditional older-blocks button, per-row mint through the same dialog, row order and wrapping CSS, the new route and the Claim link. The dependencies are not installed on this machine, so the Playwright pass and the mainnet reads with each RPC blocked in turn were read as tests but not executed.","treeHash":null,"usage":{"cachedInputTokens":1269510,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":13224,"runtime":"claude","turns":16,"wallClockMs":287164}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"672c29f92850efe0","findings":[{"citation":"unresolved","description":"Previous finding c73c0c21 is not fixed. The revision commit eb76ff0 changed dist/, web/src/eligibility.mjs, swarm.tsx, transactions.tsx, wallet-facts.tsx and six test files, but neither web/TEST-NOTES.md, web/README.md nor docs/ (last changed in 967ea75, the round-8 snapshot job). The notes still end with the round-8 'Current settled-event snapshot (2026-10-22 UTC)'. Nothing in the file mentions Wallet Facts, Mint this fact, the 7,200-second notice, the no-split and no-read-after-deadline pool rule, or a per-RPC table of served reads. The objective's item 3 requires exactly that: per item what each test checks and its result, for this round and round 7, and which RPC served each kind of read from a real browser on the site's origin. The code for items 1, 2, 4 to 7 is present and its tests pass (98 unit tests, tests/round8-browser.mjs 10 checks and tests/round8-revision-browser.mjs 4 checks all PASS in Chromium 1248 here), so this remains a documentation gap and not a hosting risk.","line":1,"path":"web/TEST-NOTES.md","reproduction":"Run `git log --oneline -1 -- web/TEST-NOTES.md web/README.md docs` (last change 967ea75, not HEAD eb76ff0 or 5ea5014). Run `grep -n -i 'wallet facts\\|mint this fact\\|7,200\\|round 7' web/TEST-NOTES.md`: no match. Expected: a section for this round listing, per item 1 to 7, the test, its result, and the RPC that served eth_getLogs, eth_call and eth_getBlockByNumber from a real browser; actual: none.","severity":"medium","snippet":"# Sworn frontend test notes","title":"Item 3 still not delivered: web/TEST-NOTES.md has no notes for this round (items 1 to 7) nor for round 7, and no per-RPC record of which RPC served each kind of read from a real browser"},{"citation":"resolved","description":"Previous finding 4339958e stands as written; the revision only reset the Attested state per request id and keyed the component by oracleId. The anchor to explorer.imd.fun is rendered only when the fetch of https://api.imd.fun/oracle/requests/<id> succeeds, returns the same id, and carries a jobId string. If the API is unreachable, blocked or returns no jobId the row shows 'Oracle request: <uuid>' as text with 'Attested: time unavailable'. The delivered test round8-revision-browser.mjs check 'shows the new request's own job and attested time, or unavailability' accepts the unlinked form. If the explorer can only address jobs by jobId this is the best the site can do and the finding can be closed as a known limit; it is advisory only.","line":67,"path":"web/src/wallet-facts.tsx","reproduction":"Connect a wallet whose card holds a panel-sworn fact (Registry.verified(wallet, id) returns a non-zero oracleRequestId). Open #/wallet-facts with requests to api.imd.fun blocked (devtools request blocking). Expected per item 7: the oracle request id is a link to the IMD explorer. Actual: the span reads 'Oracle request: <uuid>' with no anchor element and 'Attested: time unavailable'.","severity":"low","snippet":"        {job ? (\n          <a\n            href={`https://explorer.imd.fun/jobs/${encodeURIComponent(job)}`}","title":"Item 7: a panel-sworn fact's oracle request id is linked to the IMD explorer only when api.imd.fun answers with a jobId; otherwise the id is plain text (unchanged this round)"},{"citation":"resolved","description":"Executed this round (web/node_modules installed with npm ci, Chromium headless shell 1248 with its missing system libraries supplied outside the repository): `npm run test:unit` 98 pass 0 fail; `node tests/round8-browser.mjs` 10 PASS covering items 2, 4, 5, 6, 7; `node tests/round8-revision-browser.mjs` 4 PASS covering items 1, 2, 7; `node scripts/manifest.mjs --check` verified 64 assets. Item 1 against mainnet with the delivered rpc.mjs (test/scratch/pool-mainnet.mjs, a 601-block eth_getLogs on the Registry from head-664 to head-64 with a 20 s deadline, each RPC answering 429 in turn): every run returned 8 logs in 0.7 to 0.8 s with 7 to 9 calls and 0 calls in the 10 s after return. Served reads: none blocked: eth_blockNumber, eth_getBlockByNumber, eth_call by publicnode; eth_getLogs by publicnode and tenderly (two agreeing answers). publicnode blocked: all by tenderly; logs by tenderly and mevblocker. tenderly blocked: all by publicnode; logs by publicnode and mevblocker. mevblocker or thirdweb blocked: as with none blocked. The refused endpoint is tried twice for eth_chainId then paused; no range split occurred because 429 is never counted as a size refusal (`sizeRefusal` excludes 403, 429 and 503 at rpc.mjs line 68 to 72 and the RATE_LIMIT regex). Export: dist/index.html loads only ./assets/index-B-GlkmgB.js and ./assets/index-jTEdvq39.css; the script's outbound hosts are the four read RPCs, api.imd.fun (intake and oracle/requests), explorer.imd.fun, wallet deep links (go.cb-w.com, go.rabby.io, phantom.app), 4byte.sourcify.dev and imd.fun docs links; no remote code load, iframe, redirect, seed or key prompt, or analytics. Real browser on the export against mainnet (test/scratch/browser-blocked.mjs, Chromium, tenderly answering 429): the home route rendered with the menu Catalog, Explorer, Claim, Wallet Facts, Fact vs artifact, Integrate, WhitelistCurator, About, Agents; no page errors; publicnode served eth_chainId 1, eth_getCode 3, eth_call 12, eth_blockNumber 1; no request reached mevblocker or thirdweb.","line":185,"path":"web/src/rpc.mjs","reproduction":"Not a defect. In web/: `npm ci`, `npm run test:unit`, `LD_LIBRARY_PATH=<chromium libs> node tests/round8-browser.mjs`, `node tests/round8-revision-browser.mjs`; from the repository root `node test/scratch/pool-mainnet.mjs tenderly` (and publicnode, mevblocker, thirdweb).","severity":"info","snippet":"    const sized = refused > 0 && sizeRefused === refused;","title":"Review record: items 1 to 7 checked by running the delivered tests in Chromium and reading mainnet with each RPC blocked in turn through the delivered rpc.mjs; no hosting risk found in the export"}],"hash":"7bc654dee1513c603690e3493520345455e556126a43ec377fff30c6c21b0973","nodeId":"a909783f-17d5-4f71-afac-cd9b2b796430","outcome":"completed","summary":"The review is complete. The findings file is valid JSON and no tracked file was changed.\n\n**Outcome.** Nothing in the export blocks hosting. Two of my three earlier findings stand, one is closed by execution.\n\n- **Medium, still open: item 3 test notes.** The revision commit changed source, tests and dist, but not web/TEST-NOTES.md, web/README.md or docs. The notes still end at the round-8 snapshot and have no section for this round or round 7, and no per-RPC record of which RPC served each kind of read. This is a documentation gap only.\n- **Low, unchanged: explorer link for panel-sworn facts.** The Attested component in web/src/wallet-facts.tsx still links the oracle request id to the IMD explorer only when api.imd.fun returns a jobId. With the API blocked the id is plain text. The revision only reset state per request id. Advisory, and may be a known limit if the explorer only addresses jobs by jobId.\n- **Info, now executed.** The earlier review limit is lifted. I installed the web dependencies, supplied the headless Chromium's missing system libraries outside the repository, and ran everything.\n\nWhat ran and what it showed:\n\n| Check | Result |\n|---|---|\n| npm run test:unit | 98 pass, 0 fail |\n| tests/round8-browser.mjs (items 2, 4, 5, 6, 7) | 10 PASS |\n| tests/round8-revision-browser.mjs (items 1, 2, 7) | 4 PASS |\n| scripts/manifest.mjs --check | 64 assets verified |\n| Mainnet 601-block log read with each RPC answering 429 in turn, 20 s deadline | 8 logs in under 1 s each run, 7 to 9 calls, 0 calls after return |\n\nPer-RPC service from the delivered pool: with nothing blocked, publicnode served block, call and block-number reads and publicnode plus tenderly gave the two agreeing log answers. With publicnode blocked, tenderly served everything and mevblocker gave the second log answer. With tenderly blocked, publicnode served and mevblocker seconded. Blocking mevblocker or thirdweb changed nothing. No range split occurred because a 429 is never counted as a size refusal. A real Chromium pass on the built export with tenderly blocked rendered the home page with the Wallet Facts menu entry after Claim, no page errors, and all reads served by publicnode.\n\nExport safety: dist/index.html loads only its own script and stylesheet. Outbound hosts are the four read RPCs, api.imd.fun, explorer.imd.fun, wallet deep links, 4byte.sourcify.dev and imd.fun docs links. No remote code, iframe, redirect, seed or key prompt, or analytics.","treeHash":null,"usage":{"cachedInputTokens":890902,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":17058,"runtime":"claude","turns":35,"wallClockMs":403671}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"505a745a77612e11","findings":[{"citation":"resolved","description":"Now: web/TEST-NOTES.md was not touched by this revision (git log -- web/TEST-NOTES.md ends at 967ea75; the revision commit eb76ff0 changes src, dist and tests only). Its current section is still the settled-event snapshot round, and it has no per-item record for round 7 or this seven-item round: nothing on item 1 (deadline/page-change cancellation, size-only splitting), 2 (clock-based two-hour notice), 4 (Check older blocks only when needed), 5 (Mint this fact), 6 (row order), 7 (Wallet Facts page and claimed-fact history), and no table of which RPC served each kind of read from a real browser on the site's origin. Change to: add a section 'Round 8: seven items (2026-10-22)' above the snapshot section, plus a round 7 section, each with one line per item naming the test file and case (tests/rpc-deadline.test.mjs: 8 pass; tests/round8-browser.mjs; tests/round8-revision-browser.mjs: PASS 1, PASS 2, PASS 7 x2) and its actual result, then a table 'Read kind | RPC that answered | observed from' filled from a real Chromium visit to the served export (health, wallet reads, eligibility 601 range scan, feed log window, Wallet Facts Registry state, api.imd.fun oracle detail). Why: item 3: 'The site's test notes describe this round and round 7: per item what each test checks and its result, and, from a real browser on the site's origin, which RPC served each kind of read.' The assignment also says 'and update the test notes'.","line":5,"path":"web/TEST-NOTES.md","reproduction":"Width: independent of viewport (documentation). Steps: `git log --format=%h -- web/TEST-NOTES.md` prints 967ea75 first, older than both revision commits 5ea5014 and eb76ff0. `grep -n -i 'round 7\\|round 8\\|rpc-deadline\\|round8\\|wallet facts\\|wallet-facts\\|Mint this fact' web/TEST-NOTES.md` prints nothing. Line 5 heads the current section as '## Current settled-event snapshot (2026-10-22 UTC)'. Meanwhile the suites exist and pass: in a clean copy of HEAD, `node --test tests/rpc-deadline.test.mjs` gives 8 pass / 0 fail and `node tests/round8-revision-browser.mjs` prints four PASS lines, none of which is recorded. Expected: per-item results for rounds 7 and 8 and the browser-origin RPC per read kind; actual: absent.","severity":"high","snippet":"## Current settled-event snapshot (2026-10-22 UTC)","title":"fidelity: test notes still omit rounds 7 and 8 and the browser RPC provenance item 3 asks for"}],"hash":"ae83a3fb9a341c2630c03d8dcbbca3049bc334623fd25cc3a5ee4da82a95516a","nodeId":"a1353364-ba5a-4752-950b-2ebcf17c4f7a","outcome":"completed","summary":"Three of my four round-7 findings are fixed; one high finding is still open. The site's test notes (`web/TEST-NOTES.md`) still don't cover this round or round 7.\n\n| Area | Last round | This round |\n|---|---|---|\n| Brief requirements (items 1–7) | 5 met, 2 missing (items 1, 3) | 6 met, 1 missing (item 3), 0 faked |\n| Broken features | 3 (items 1, 2, 7) | 0 |\n| Product on first screen at 390 | yes | yes (layout untouched this round; not re-measured) |\n| taste@1 checks passed | not re-run (fix round) | not re-run (no layout or CSS changes) |\n| Copy findings | 0 | 0 |\n| Share card | present | present |\n\n**What happened to each finding**\n\n- **Fixed: eligibility `specOf` kept retrying after a cancel (`web/src/transactions.tsx:150`).**\n  - `checkEligibility` now hands its own abort signal to `readSpec`, and the dialog sends that read through `scopedClient(site.client, scope)`.\n  - I ran the tests in a clean copy of the commit outside the repo, against the committed `dist/`. In `rpc-deadline.test.mjs`, all 8 tests pass. It logs \"spec deadline: 1 calls before return, 0 after\" and \"spec page change: 2 calls before return, 0 after\".\n  - The browser test `round8-revision-browser.mjs` passes \"a refused specOf(601) in the dialog's check sends nothing after a page change\". That is my original reproduction.\n- **Fixed: the two-hour notice vanished when the progress API failed (`web/src/swarm.tsx`).** The error path now works out `stale` from the Registry's `requestedAt`. The browser test passes \"a 7,201 s old request keeps the two-hour line when the progress API answers 503\".\n- **Fixed: Wallet Facts carried the previous wallet's data across a wallet switch (`web/src/wallet-facts.tsx`).**\n  - Rows are now tied to the wallet they were read for and only show for the connected wallet.\n  - `Attested` resets on a new request id and is keyed by it.\n  - Both of my reproductions pass as browser cases: the previous wallet's facts never show while the new history loads, and a shared fact shows its own job link and attested time, or \"unavailable\".\n- **Still open (high), fidelity: the test notes omit rounds 7 and 8 and the RPC record (`web/TEST-NOTES.md:5`).**\n  - Neither revision commit touched this file; its last change is 967ea75. Its current section is still \"Current settled-event snapshot\".\n  - A search for round 7, round 8, rpc-deadline, round8, Wallet Facts or Mint this fact finds nothing.\n  - So item 3 is still missing. The new suites pass, but their results aren't recorded. There is also no record, from a real browser on the site's origin, of which RPC served each kind of read.\n  - The finding names the sections to add and the results to put in them.\n\n**Requirement list**\n\n1. \"No reads after a check gives up\": met. `eligibility.mjs` scopes the spec read and the range scan to one controller; covered by `rpc-deadline.test.mjs`.\n2. \"Requested more than 2 hours ago… follows the clock\": met (`swarm.tsx`).\n3. \"The site's test notes describe this round and round 7…\": **missing** (`web/TEST-NOTES.md`).\n4. \"Check older blocks only when it is needed\": met. Last round's check stands; no change since.\n5. \"Mint this fact\": met. Last round's check stands, and it is the entry point the passing test 1 uses (`#pick-601`).\n6. Row order and no overflow on narrow screens: met. Last round's check stands; no layout change since.\n7. \"Wallet Facts\" page and claimed-fact history: met (`wallet-facts.tsx`). The wallet-switch problems are fixed.\n\nThe idea in one sentence: Sworn is a registry where a wallet mints facts about itself, and the one visual idea is the fact card each claim fills in.\n\nNothing new turned up this round. `.imd-findings.json` holds the one remaining finding. I changed nothing in the repository: dependencies were installed and the tests run only in a temporary copy.","treeHash":null,"usage":{"cachedInputTokens":522246,"inputTokens":26,"model":"claude-opus-5-5","outputTokens":6204,"runtime":"claude","turns":13,"wallClockMs":87638}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"0256823ae36e7900","findings":[{"citation":"resolved","description":"Now: The current test notes still describe the settled-event snapshot round. They have no per-item results for round 7 or this seven-item round and no real-browser, site-origin record of which RPC served each read kind.\nChange to: Add per-item test descriptions and actual results for both rounds, including the new rpc-deadline and round8 browser suites, and record each read kind’s serving RPC from a real browser on the site origin.\nWhy: Item 3 explicitly requires this evidence; existing snapshot-generator CLI observations and historical fake-response results do not satisfy it.","line":5,"path":"web/TEST-NOTES.md","reproduction":"Width: independent of viewport (documentation). Open web/TEST-NOTES.md: line 5 identifies the current section as the snapshot round; lines 39–50 list snapshot-era commands/results. Search the complete file for round 7, round 8, rpc-deadline, round8-browser, Wallet Facts and the current per-item RPC observations: none are present. web/tests/rpc-deadline.test.mjs and web/tests/round8-browser.mjs identify themselves as round 8, but neither has a result recorded in the notes. Expected: both requested rounds’ per-item outcomes and browser-origin serving endpoints; actual: those records are absent.","severity":"high","snippet":"## Current settled-event snapshot (2026-10-22 UTC)","title":"fidelity: test notes omit rounds 7 and 8 and browser RPC provenance"},{"citation":"resolved","description":"Now: The dialog’s eligibility check reads specOf through the unscoped site.client. checkEligibility scopes its later RPC requests, but cannot cancel this initial readSpec callback, so failed spec reads continue retrying and rotating after the check’s deadline or page change.\nChange to: Route specOf through the same abort signal and deadline-scoped transport as the remaining eligibility reads, and cover a delayed/refused spec read in cancellation tests.\nWhy: Item 1 requires the pool to send no further request for a read once its deadline passes or the page or wallet changes.","line":150,"path":"web/src/transactions.tsx","reproduction":"Width: 390×844, Chromium, committed dist. Install the supplied fake EIP-1193 wallet and fakeChain({token:1n}); serve the export and connect on #/claim. Allow health and wallet reads normally, then intercept only Registry.specOf(601) calls and answer HTTP 503 after 200ms. Click #pick-601 “Mint this fact”; after its payment dialog appears and the first specOf starts, navigate to #/wallet-facts. Expected: no more requests for the cancelled eligibility read. Actual: Wallet Facts renders but seven further specOf(601) calls start approximately 214, 421, 627, 840, 1049, 1260 and 1468ms after navigation, across all four RPCs. An independent checkEligibility test with a 50ms deadline and unscoped failing readSpec also returns unknown before subsequent retries start. No transaction is signed or sent.","severity":"high","snippet":"          (id: number) => read(site.client, site.r, \"Registry\", \"specOf\", [id]),","title":"bug: eligibility spec reads keep retrying after the caller is cancelled"},{"citation":"resolved","description":"Now: the age flag is only included when the optional progress lookup succeeds; its catch path replaces the view without stale, even after Registry supplied the request’s timestamp.\nChange to: calculate overdue from the retained pending.requestedAt independently of the optional API result and include that flag in the failure view as well.\nWhy: item 2 requires “Requested more than 2 hours ago.” once the request’s own age exceeds 7,200 seconds, regardless of block count; an API outage does not invalidate the already-read timestamp.","line":356,"path":"web/src/swarm.tsx","reproduction":"At 1280×900 on dist/#/wallet-facts, connect the fake wallet and return pendingOf(wallet,801)=0x followed by a1 repeated 32 times. Return pendingRequest=[wallet,801,floor(Date.now()/1000)-7201,questionHash], with its matching TraitRequested event at head−200 so it is inside the feed window. Let all RPC reads succeed, but answer both https://api.imd.fun/intake/... and https://api.imd.fun/oracle/requests?q=... with HTTP 503. Actual: the feed displays “progress unavailable”, Retry progress and Check older blocks, while the exact two-hour notice has count 0; the retained Registry timestamp is older than 7,200 seconds. Expected: display the two-hour notice alongside progress unavailability. Reproduced in Chromium against the committed static export; no signing.","severity":"medium","snippet":"            progress: null,\n            message:\n              error instanceof WalletQuestionMismatch\n                ? error.message\n                : \"progress unavailable\",","title":"bug: progress API failures suppress the clock-based two-hour request notice"},{"citation":"resolved","description":"Now: The new wallet’s lookup is published while the previous wallet’s fact rows remain. For a shared fact id, Attested also retains its old API record when oracleId changes, so a failed new API read can leave the previous wallet’s job link and attested time displayed.\nChange to: Clear or owner-scope rows when the connected wallet changes; show Reading your facts… until that wallet’s history is ready. Reset or key the attestation record by oracleId so each job link and date belongs to that request.\nWhy: Item 7 requires the connected wallet’s claimed-fact history and its actual Registry/API provenance.","line":123,"path":"web/src/wallet-facts.tsx","reproduction":"At 1280×900 on dist/#/wallet-facts, use a fake EIP-1193 wallet A=0x2000000000000000000000000000000000000001 with tokenOf=1, traitsOf=[101,801], and a nonzero Registry.verified proof for 801. Wait for #held-801. Emit accountsChanged to B=0x2000000000000000000000000000000000000002; have B answer tokenOf=2 and traitsOf=[101,901] with a nonzero verified proof for 901. Delay only mintedAtBlock(2) by 3,000 ms. Once B’s lookup resolves, the page says Card #2. but #held-801 remains visible and #held-901 has count 0 for the 3-second delay; afterward #held-901 replaces it. Expected: B’s history loading state, never A’s fact 801 or A’s mint block. Second confirmed case at the same width: have A and B both hold fact 801 with distinct nonzero oracle UUIDs, return A’s API detail as {id:A-oracle,jobId:\"wallet-A-job\",attestedAt:\"2026-10-20T08:15:00.000Z\"}, delay B’s mintedAtBlock by 3,000 ms, and return HTTP 503 for B’s oracle detail. After B’s rows finish, the row displays B’s oracle UUID (33474d49-bf7c-40e0-8dad-41636c73ea84) but links to /jobs/wallet-A-job and still displays A’s 2026-10-20 08:15 UTC attested time. Expected: B’s detail or explicit unavailability. Both cases reproduced in Chromium against the committed export with fake wallet/RPC/API responses; no signing.","severity":"medium","snippet":"      setFacts(v);","title":"bug: Wallet Facts carries history and attestation details across wallet switches"}],"hash":"bfaf9c703fd8bf3b0ecd49a4e5a03964299e2ed04497c36036cb0653b94d2bc4","nodeId":"a1353364-ba5a-4752-950b-2ebcf17c4f7a","outcome":"completed","summary":"| Area | Count |\n|---|---:|\n| Requirements, items 1–7 | 3 met, 4 incomplete, 0 faked |\n| Broken features | 3 |\n| Product/action on first screen, 390px | Yes |\n| taste@1 | 14/16 passed |\n| Copy findings | 0 |\n| Share card | Present |\n\nSaved **4 verified findings: 2 high, 2 medium** in [.imd-findings.json](/home/imd-worker/.identitymd/work/ecce04a1-96c0-400f-bcc2-d141e6fc7175/a1353364-ba5a-4752-950b-2ebcf17c4f7a/.imd-findings.json). Site files remain unchanged.\n\n| Requirement | Status and evidence |\n|---|---|\n| 1. “No reads after a check gives up.” | **Missing:** initial `specOf` retries continue after navigation; seven late requests reproduced. Range splitting rules and scoped cancellation pass. `web/src/transactions.tsx:150` |\n| 2. Notice follows request age | **Missing:** an API outage suppresses the notice despite a known age above 7,200 seconds. Healthy timestamp cases pass. `web/src/swarm.tsx:356` |\n| 3. Notes cover this round and round 7 | **Missing:** per-item outcomes and real-browser serving-RPC provenance are absent. `web/TEST-NOTES.md:5` |\n| 4. Conditional older-block controls | **Met:** failed/unresolved rows expose fallback; settled rows omit it and the empty-history sentence. Feed and shared-fact controls remain. `web/src/claim.tsx` |\n| 5. “Mint this fact” | **Met:** qualifying rows open the single-fact dialog with eligibility, price and Request anyway; other selections persist. `web/src/claim.tsx` |\n| 6. Row order and wrapping | **Met:** text, existing preview and buttons retain order; tested widths show no overflow. `web/src/claim.tsx`, `web/src/styles.css` |\n| 7. Wallet Facts | **Missing:** switching wallets can show the previous wallet’s history, explorer link and attested time. Menu placement, route, progress relocation, exact empty states, Claim link, retained dialog/Check swarm controls, and normal Registry-based catalog/community provenance pass. `web/src/wallet-facts.tsx:123` |\n\nStatic behavior, fake-wallet checks, preserved contract configuration/snapshot, and the committed export are **met**. Named-site publication is **after review**.\n\nValidation passed: six RPC tests, ten browser groups, Chromium/WebKit phone interactions, export manifest and pinned ABI hashes. The two taste flags concern preserved uppercase headings and monospace prose.\n\nSworn presents a wallet-fact registry through terminal typography, hive artwork and green status accents.","treeHash":null,"usage":{"cachedInputTokens":3330432,"inputTokens":107168,"model":"gpt-6.1-sol","outputTokens":12267,"runtime":"codex","turns":6,"wallClockMs":508318}}],"verification":[{"checks":[],"detail":"paths and tree verified; no suite was run for this kind of work","evaluation":"structural","profile":"none","status":"accepted","submissionHash":"432bbb83f9326ae0dd30461b2477b9ef9393ee2337778fa1504a0fcff079d3d3","verifiedTreeHash":"c44c5e5ce19e408c7cf5a50467aeed7741b02f9d","verifierVersion":"0.1.0+ead9012e"},{"checks":[],"detail":"paths and tree verified; no suite was run for this kind of work","evaluation":"structural","profile":"none","status":"accepted","submissionHash":"64ce3280d627b06f523ca54c6901bfad1bc6e2873ebeea8a33870b13bd116967","verifiedTreeHash":"00dca3c68382fdaf9909027d9de3555282634ea2","verifierVersion":"0.1.0+ead9012e"}]}