{"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":"2b605b5d-856d-4f60-ab44-e2eb020c4b45","kind":"skill:build-website","nodes":[{"acceptedSubmissionHash":"5d9e0560ac1d2d36a1047014dcc27b35d7455eb6f483474f91ac35552c2d4f7c","dependsOn":[],"execution":{"mustProduce":["dist/index.html"],"network":true,"optionalTools":["browser"],"profile":"none","requires":["network"],"skillHash":"f2817f61355cd4a8a61a97c2607875f024f0ba742034dd6b90594af69c53b207","skillId":"build-website","tools":[]},"key":"build_website","kind":"code","role":"implement","skillHash":"f2817f61355cd4a8a61a97c2607875f024f0ba742034dd6b90594af69c53b207","skillId":"build-website","state":"accepted"},{"acceptedSubmissionHash":"438a3fb623e8bd74b2dff57ec09763f8610e1edae7006d77a8d6d4018b1cdd4f","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"}],"objective":"0x49c95a6ee32e9c0dc7a353c078e6158304bbce9f","parentJobId":"f708c332-034f-47b3-b204-318734811863","planHash":"3696167ceb59b9c358c20c4892c73de4ed056b6c322c6169a291725c692e1cdc","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"f708c332-034f-47b3-b204-318734811863","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1566-starknet"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51473","feedbackHash":"fdb50c4e53a7ecfb503d324d4a3cf08c1a1dfd51c9f3909c1ca6fdc6bc998d06","nodeKey":"build_website","submissionHash":"5d9e0560ac1d2d36a1047014dcc27b35d7455eb6f483474f91ac35552c2d4f7c","tag1":"verification:structural","tag2":"acceptance-v2","value":1},{"agentId":"51083","feedbackHash":"5142feeade8ce05c590ab745a991d356f66b4a934f82db107df543ceb7e99f4f","nodeKey":"design_critic","submissionHash":"438a3fb623e8bd74b2dff57ec09763f8610e1edae7006d77a8d6d4018b1cdd4f","tag1":"review:submission","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"9d86a68ea2cceaf7188d8161bf27ca4baa5a60981e07b83f6a76515db5c3e69c","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"dc7103e773ea194a","findings":[{"citation":"resolved","description":"Now: the note beside the launch remainder address reads \"requester's 2% allocation\". deployment.json gives poolBps 8800 and remainderTo, never a remainder share; the 2% is inferred from today's balance (20,000,000 of 1,000,000,000), which the requester can move at any time, after which the static note is false while the stat above it (\"Launch remainder holds\", computed from balanceOf) stays true.\nChange to: note=\"launch remainder\" (or delete the note; the row head keeps its label and the address line does not move). If a share must be shown, compute it in TokenStats from state.remainderBalance / state.totalSupply the way poolShare is, and show it only there.\nWhy: replacement copy must stay true: no count that will change unless the page computes it, and no address or fact that is not in deployment.json.","line":16,"path":"web/src/Contracts.tsx","reproduction":"Width 1440 or 390. Load dist/index.html, scroll to \"Contracts and addresses\", row \"Launch remainder recipient\": the note reads \"requester's 2% allocation\" (static text in Contracts.tsx:16). Search .imd/reads/deployment.json for a remainder share: only poolBps 8800 and remainderTo exist. The \"On chain now\" card at the same time shows \"Launch remainder holds 20,000,000 STARKNET\", a live balanceOf read; the moment that account transfers tokens the two lines disagree.","severity":"medium","snippet":"        <AddressRow label=\"Launch remainder recipient\" address={ECONOMICS.remainderTo} note=\"requester's 2% allocation\" />","title":"copy: the contracts list states a fixed \"2% allocation\" that nothing in the deployment gives and the balance will not keep"},{"citation":"resolved","description":"Now: the \"Held by the pool\" value prints formatAmount(poolBalance, 18, 0), which rounds 879,999,999.99… up to \"880,000,000 STARKNET\", then a share computed with integer division in basis points, which truncates 8799.99… to 8799 and prints \"(87.99%)\". The two numbers on one line contradict each other: 880,000,000 of 1,000,000,000 is 88.00%, and the deployment's poolBps is 8800.\nChange to: round instead of truncating, at the precision shown: const poolShare = state && state.totalSupply > 0n ? (Number(state.poolBalance) / Number(state.totalSupply) * 100).toFixed(1) : null, so the line reads \"880,000,000 STARKNET (88.0%)\".\nWhy: a data line is read to reach a decision; two roundings of the same quantity on one line make the reader doubt both.","line":9,"path":"web/src/TokenStats.tsx","reproduction":"Width 1440. Load dist/index.html with the public RPC reachable; wait for \"On chain now\" to fill. Measured in headless Chromium at block 26,183,969: the \"Held by the pool\" line reads \"880,000,000 STARKNET (87.99%)\" (test/scratch/taste/shots/1440.png). Expected 88.0% for a balance that prints as 880,000,000.","severity":"low","snippet":"  const poolShare = state && state.totalSupply > 0n ? Number((state.poolBalance * 10000n) / state.totalSupply) / 100 : null","title":"bug: pool share truncates to 87.99% beside an amount rounded to 880,000,000"},{"citation":"resolved","description":"Now: Disconnect clears React state only. The effect at WalletPanel.tsx:30-47 keeps the accountsChanged listener and, on every load, calls eth_accounts and re-adopts the first authorised account, so the chip and the transfer form return on reload, and an accountsChanged event re-connects the panel without a click.\nChange to: keep a `disconnected` flag (useState, or sessionStorage so it survives reload) that disconnect sets and connect clears; skip the eth_accounts auto-adopt and ignore accountsChanged while it is set. No change to the connector, chain or transaction code.\nWhy: a state must say only what the app knows; a visitor who pressed Disconnect and sees \"Connect wallet\" is told the site forgot them, and it did not.","line":92,"path":"web/src/WalletPanel.tsx","reproduction":"Width 390, Chromium with an injected EIP-1193 provider whose eth_accounts returns one account on chain 0x1. Load dist/index.html: header shows \"0x49c9…Ce9F\". Press Disconnect in the \"Your STARKNET\" card: header shows \"Connect wallet\". Reload the page: header shows \"0x49c9…Ce9F\" again without any click (measured with a Playwright script: after disconnect: Connect wallet; after reload: 0x49c9…Ce9F).","severity":"low","snippet":"  const disconnect = useCallback(() => {\n    setAccount(null)\n    setError('')\n  }, [])","title":"bug: Disconnect only forgets the account until the next reload"},{"citation":"resolved","description":"Now: all six dd values in the \"On chain now\" card render the literal '—' (TokenStats.tsx:20, 24, 28, 32, 36, 40) until readTokenState resolves, and forever when the RPC fails, while the status line below already says \"Reading Ethereum…\" or the error with Retry. The probe passes glyphs only because the data had loaded when it measured.\nChange to: render an empty string in each dd (`: ''`) and give `.stats dd` a `min-height: 1.5em` in styles.css so the card keeps its height and nothing moves when the values arrive; the status line is the one place that says what is happening.\nWhy: the bar says no em dashes in the site's own text, and a state says only what the app knows; the status line already does.","line":20,"path":"web/src/TokenStats.tsx","reproduction":"Width 390. Block requests to ethereum-rpc.publicnode.com and eth.drpc.org (or load on a slow connection) and open dist/index.html. The \"On chain now\" card reads \"Total supply — Pool price per STARKNET — Market value at pool price — Held by the pool — Pool fee — Launch remainder holds —\" with \"Unable to read Ethereum right now. HTTP request failed. Retry\" beneath (measured with Playwright route-abort; screenshot /tmp/imdprobe/390-rpcdown.png).","severity":"low","snippet":"          <dd className=\"num\">{state ? `${formatAmount(state.totalSupply, state.decimals, 0)} ${state.symbol}` : '—'}</dd>","title":"taste: six em dashes stand in for the stats while the chain is read or unreachable"},{"citation":"resolved","description":"Now: the headline pair is \"Starknet. Fixed supply.\" over a two-sentence lede whose second sentence, \"Check a balance or send tokens.\", is a direction. Both actions are already named by the cards directly under it (\"Connect a wallet to see your balance and send tokens.\" and \"Check any balance\").\nChange to: <p className=\"lede\">One billion STARKNET on Ethereum, no owner and no mint.</p>; the lede drops from two lines to one at 390 and the \"Your STARKNET\" card moves up about 25px.\nWhy: the line under the headline is one plain sentence saying what this is; directions go next to the control they explain, and here they already are.","line":53,"path":"web/src/App.tsx","reproduction":"Width 390. Load dist/index.html: the lede wraps to two lines, \"One billion STARKNET on Ethereum, no owner / and no mint. Check a balance or send tokens.\" (test/scratch/taste/shots/390.png), with the same two actions repeated in the two cards below within the first screen. Probe copy-budget: 37 prose words on the first screen at 390, 72 at 1440.","severity":"low","snippet":"          <p className=\"lede\">One billion STARKNET on Ethereum, no owner and no mint. Check a balance or send tokens.</p>","title":"copy: the hero lede carries a direction that belongs beside the controls"}],"hash":"438a3fb623e8bd74b2dff57ec09763f8610e1edae7006d77a8d6d4018b1cdd4f","nodeId":"1e8d1bc5-6edb-49fc-8df4-6ec25d40496b","outcome":"completed","summary":"Review complete. The findings file holds five findings, none high. The tree is otherwise unchanged.\n\n| Area | Count |\n| --- | --- |\n| Brief requirements | 6 met, 0 missing, 0 faked, 1 after review |\n| Broken features | 0 |\n| Product on first screen at 390 | yes |\n| taste@1 checks passed | 16 of 16 |\n| Copy findings | 2 |\n| Share card | present: title, favicon, og:title, og:image, description |\n\n**Requirements.** The brief for this website job is only the requester's address, so the requirements come from the reference's build instructions and the deployment.\n\n- \"read their state\": met. The \"On chain now\" card reads name, symbol, decimals, totalSupply, two balances and the Uniswap v4 slot0 and liquidity through the multicall in `web/src/chain.ts`.\n- \"offer their main actions through the visitor's wallet\": met. The transfer form in `web/src/WalletPanel.tsx` builds an ERC-20 transfer, with wrong-network, pending, confirming, success, revert and cancelled states all exercised with an injected provider.\n- \"Never hard-code an address that is not in deployment.json\": met. Every address in `web/src/config.ts` matches deployment.json or network.json, chain id 1.\n- \"Derive ABIs from the pinned source and check them against the abiHash\": met by the builder's claim in `web/src/abi.ts`. I did not recompute the hash in the time available.\n- Title, favicon, og:title, og:image: met, in `web/index.html`.\n- Balance lookup without a wallet: met, verified against the live RPC at 320 wide with a correct 20,000,000 STARKNET result.\n- Hosting and a live URL: after review.\n\n**Idea.** A quiet dark ledger for one fixed-supply token, carried by a single gold accent that marks the one action in each card.\n\n**Findings written to .imd-findings.json.**\n\n- Medium, copy. The contracts list hard-codes \"requester's 2% allocation\", a share nothing in the deployment gives and the live balance will not keep.\n- Low, bug. The pool share prints 87.99% beside an amount rounded to 880,000,000, because basis points truncate while the amount rounds.\n- Low, bug. Disconnect only clears React state. A reload re-adopts the authorised account without a click.\n- Low, taste. Six em dashes fill the stats while the chain loads or the RPC is down.\n- Low, copy. The hero lede carries a direction, \"Check a balance or send tokens\", already stated by the two cards beneath it.\n\n**Caveats.** The probe ran in Chromium only, after symlinking the cached browser build, since the Playwright download is blocked here. WebKit is not installed on this machine, so the Safari pass did not run. The CSS uses no feature current WebKit lacks, but the oldest Safari without overflow-wrap: anywhere would let a full address overflow at 320.","treeHash":null,"usage":{"cachedInputTokens":1567667,"inputTokens":770,"model":"claude-fable-5-1","outputTokens":20253,"runtime":"claude","turns":25,"wallClockMs":584109}},{"artifacts":[],"attempt":1,"bundleHash":"9884f120ac18d02b5b2f4a23ecac560d546c94e363edeeb0184d377389d39097","device":"dc34db8e17664ebd","findings":[],"hash":"5d9e0560ac1d2d36a1047014dcc27b35d7455eb6f483474f91ac35552c2d4f7c","nodeId":"a0195420-e248-444f-9714-8935e08ff847","outcome":"completed","summary":"Done. The deliverable is complete and verified on the final source.\n\n**What was built**\n\nThe brief named only the launch's remainder address, which is the requester's 2% allocation in deployment.json, so I built the token's website as a single-page Vite + React + TypeScript dapp in `web/`, exported to `dist/` with relative asset URLs. It reads STARKNET state from Ethereum mainnet over the two public RPCs: supply, Uniswap v4 pool price in IMD, pool holdings, fee and the remainder address's balance. A visitor can check any address's balance without a wallet, or connect an EIP-1193 browser wallet to see their balance, switch to Ethereum if needed, send STARKNET, and add the token to their wallet. Every address comes from deployment.json or network.json, and the ABI built from the pinned source matches the deployment's abiHash with sorted-key keccak. Swapping is not offered because the hooked v4 router path could not be verified without a wallet; this is recorded as a limitation.\n\n**Checks on the final source**\n\n| Check | Result |\n| --- | --- |\n| tsc typecheck | exit 0 |\n| vite build | exit 0, 452 kB JS (140 kB gzip) |\n| dist static checks (relative URLs, files, title, favicon, description, og:title, og:image) | all pass |\n| design-critic probe at 320/390/1440 | 16/16 |\n| Playwright interaction script, Chromium, 390 and 1440 | 28/28 |\n\nThe interaction script, kept at `web/scripts/interact.mjs`, drives the real export with a mocked wallet provider and real RPC reads: validation and focus, keyboard order, connect, wrong network, transfer validation, cancelled signature, pending state with Etherscan link, add to wallet. The 390 screenshot shows the headline, one-line description and Connect wallet button on the first screen.\n\n**Better Interface review**\n\nAll six domains were checked. Fixed findings: price line read as all-caps, header button counted as a kicker above the headline, a vague error for a wrong-checksum address, a stray 14px size, and a missing group boundary above the send form. Details, coverage and limitations are in `artifacts/validation.md`.\n\n**Documentation**\n\n`DESIGN.md` documents the tokens, type scale, layout, components and responsive behaviour from the source. The README has a Website section with install, dev, build, preview and check commands plus the recorded results.\n\n**Limitations**\n\nNo real transaction was sent. WebKit could not launch on this host, so Safari is unchecked. Screen reader, forced-colors, zoom and physical-device checks were not performed. The MCP browser tool offered no preview of dist, so the Playwright script served as the browser inspection.\n\n`web/node_modules` was removed and the MCP browser's stray snapshot folder deleted. The new source plus export totals about 0.9 MB, well inside the 8 MiB budget. Nothing was committed; the working tree holds the changes.\n\nNot delivered: artifacts/validation.md. Under artifacts/, only this step's named outputs leave the machine.","treeHash":"1e4b7a138a077811b923b49763f914ddd252bb26","usage":{"cachedInputTokens":2724192,"inputTokens":802,"model":"claude-fable-5-1","outputTokens":69213,"runtime":"claude","turns":68,"wallClockMs":1134510}}],"verification":[{"checks":[],"detail":"paths and tree verified; no suite was run for this kind of work","evaluation":"structural","profile":"none","status":"accepted","submissionHash":"5d9e0560ac1d2d36a1047014dcc27b35d7455eb6f483474f91ac35552c2d4f7c","verifiedTreeHash":"1e4b7a138a077811b923b49763f914ddd252bb26","verifierVersion":"0.1.0+327e1e9f"}]}