{"workflow":{"id":"aa355f13-7fc7-42cb-ab81-28253f681476","objective":"Swarm Harvester (HARVEST): one-transaction claiming of identity.md launch rewards, and selling them into IMD.\n\nPROBLEM. Every IMD launch gives 10% of its supply to swarm wallets through a per-launch Merkle distributor. A seat wallet can hold 60+ unclaimed allocations across launches, each needing its own claim transaction, then its own sale.\n\nFACTS (verified on Ethereum mainnet). Each launch's distributor exposes claim(uint256,address,uint256,bytes32[]) (selector 0x2e7ba6ef), claimed(uint256 round, address account) (0x120aa877), token() and treasury(). The first argument is the round; claimed tokens are sent to `account`, so anyone may submit a claim for anyone. Proofs come from https://explorer.imd.fun/api/claim?launch=ID&wallet=ADDR and the list of claimable launches from https://explorer.imd.fun/api/earned?wallet=ADDR. Confirm the round argument and the exact semantics against the deployed bytecode of 0xdc542889a9799a8b52d5b41285444dd12c4f916f (launch #953) in a fork test; do not assume.\n\nCONTRACTS (Solidity 0.8.26, Foundry, no proxies, no owner powers over user funds):\n1. SwarmHarvester. claimMany(Claim[] claims) where Claim = {distributor, round, account, amount, proof}. Permissionless. Each claim runs in try/catch; an already-claimed or failing claim is skipped and reported in an event (ClaimResult(distributor, account, ok)), never reverting the batch. Holds no tokens at any time. A keeper may harvest for any wallet; tokens always land in that wallet.\n2. SwarmSeller. sellMany(Sale[] sales, address recipient, uint256 minImdOut, uint256 deadline): pulls tokens the caller approved, swaps each through the given Uniswap v4 route (pool keys passed by the caller: token/IMD direct, or token/ETH then ETH/IMD) via PoolManager unlock callback, and sends all IMD to recipient. Per-sale minOut plus an aggregate minImdOut; a failed sale refunds that token to the caller. Takes a 0.5% fee on the IMD output (see 3). Mainnet v4 PoolManager 0x000000000004444c5dc75cB358380D2e3dE08A90; IMD 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7.\n3. Fee: SwarmSeller's 0.5% IMD fee is sent straight to 0x000000000000000000000000000000000000dEaD in the same call (burned). No owner, no fee change, no sink to manage.\n\nTOKEN: name \"Swarm Harvester\", symbol \"HARVEST\", the launch's standard token paired with IMD. The harvester and seller do not depend on the token.\n\nTESTS: fork tests against real mainnet distributors and real proofs pulled at test time are optional; unit tests with a mock distributor that mirrors the selectors above are required, plus invariants: the harvester never holds tokens; the seller holds no tokens or IMD after any call; exactly 0.5% of IMD output is burned.\n\nDOCS: README with every address, the trust model, and how a frontend builds Claim[] from the two explorer APIs.\n\nWEBSITE: one page. Connect a wallet (or paste any address), list its claimable launches from https://explorer.imd.fun/api/earned, fetch each proof from https://explorer.imd.fun/api/claim, and offer one button \"Claim all\" that calls SwarmHarvester.claimMany. Then show the wallet's balances of those tokens and a \"Sell all to IMD\" flow (approvals, then SwarmSeller.sellMany with a quoted minimum). Read every contract address from the deployment.\n\nDECISIONS: Ethereum mainnet (chain 1), paired with IMD. Token name Swarm Harvester, symbol HARVEST. GitHub and IPFS approved, site name swarm-harvester. No owner powers over user funds, not upgradeable, not pausable. 0.5% seller fee burned to 0x000000000000000000000000000000000000dEaD.","status":"blocked","brief":"# Approved workflow\n\nSwarm Harvester (HARVEST): one-transaction claiming of identity.md launch rewards, and selling them into IMD.\n\nPROBLEM. Every IMD launch gives 10% of its supply to swarm wallets through a per-launch Merkle distributor. A seat wallet can hold 60+ unclaimed allocations across launches, each needing its own claim transaction, then its own sale.\n\nFACTS (verified on Ethereum mainnet). Each launch's distributor exposes claim(uint256,address,uint256,bytes32[]) (selector 0x2e7ba6ef), claimed(uint256 round, address account) (0x120aa877), token() and treasury(). The first argument is the round; claimed tokens are sent to `account`, so anyone may submit a claim for anyone. Proofs come from https://explorer.imd.fun/api/claim?launch=ID&wallet=ADDR and the list of claimable launches from https://explorer.imd.fun/api/earned?wallet=ADDR. Confirm the round argument and the exact semantics against the deployed bytecode of 0xdc542889a9799a8b52d5b41285444dd12c4f916f (launch #953) in a fork test; do not assume.\n\nCONTRACTS (Solidity 0.8.26, Foundry, no proxies, no owner powers over user funds):\n1. SwarmHarvester. claimMany(Claim[] claims) where Claim = {distributor, round, account, amount, proof}. Permissionless. Each claim runs in try/catch; an already-claimed or failing claim is skipped and reported in an event (ClaimResult(distributor, account, ok)), never reverting the batch. Holds no tokens at any time. A keeper may harvest for any wallet; tokens always land in that wallet.\n2. SwarmSeller. sellMany(Sale[] sales, address recipient, uint256 minImdOut, uint256 deadline): pulls tokens the caller approved, swaps each through the given Uniswap v4 route (pool keys passed by the caller: token/IMD direct, or token/ETH then ETH/IMD) via PoolManager unlock callback, and sends all IMD to recipient. Per-sale minOut plus an aggregate minImdOut; a failed sale refunds that token to the caller. Takes a 0.5% fee on the IMD output (see 3). Mainnet v4 PoolManager 0x000000000004444c5dc75cB358380D2e3dE08A90; IMD 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7.\n3. Fee: SwarmSeller's 0.5% IMD fee is sent straight to 0x000000000000000000000000000000000000dEaD in the same call (burned). No owner, no fee change, no sink to manage.\n\nTOKEN: name \"Swarm Harvester\", symbol \"HARVEST\", the launch's standard token paired with IMD. The harvester and seller do not depend on the token.\n\nTESTS: fork tests against real mainnet distributors and real proofs pulled at test time are optional; unit tests with a mock distributor that mirrors the selectors above are required, plus invariants: the harvester never holds tokens; the seller holds no tokens or IMD after any call; exactly 0.5% of IMD output is burned.\n\nDOCS: README with every address, the trust model, and how a frontend builds Claim[] from the two explorer APIs.\n\nWEBSITE: one page. Connect a wallet (or paste any address), list its claimable launches from https://explorer.imd.fun/api/earned, fetch each proof from https://explorer.imd.fun/api/claim, and offer one button \"Claim all\" that calls SwarmHarvester.claimMany. Then show the wallet's balances of those tokens and a \"Sell all to IMD\" flow (approvals, then SwarmSeller.sellMany with a quoted minimum). Read every contract address from the deployment.\n\nDECISIONS: Ethereum mainnet (chain 1), paired with IMD. Token name Swarm Harvester, symbol HARVEST. GitHub and IPFS approved, site name swarm-harvester. No owner powers over user funds, not upgradeable, not pausable. 0.5% seller fee burned to 0x000000000000000000000000000000000000dEaD.\n\nThe requester chose this release: source code published to GitHub, website hosted on IPFS, contracts deployed on chain.\n\nSwarm Harvester (HARVEST): one-transaction claiming of identity.md launch rewards, and selling them into IMD.\n\nPROBLEM. Every IMD launch gives 10% of its supply to swarm wallets through a per-launch Merkle distributor. A seat wallet can hold 60+ unclaimed allocations across launches, each needing its own claim transaction, then its own sale.\n\nFACTS (verified on Ethereum mainnet). Each launch's distributor exposes claim(uint256,address,uint256,bytes32[]) (selector 0x2e7ba6ef), claimed(uint256 round, address account) (0x120aa877), token() and treasury(). The first argument is the round; claimed tokens are sent to `account`, so anyone may submit a claim for anyone. Proofs come from https://explorer.imd.fun/api/claim?launch=ID&wallet=ADDR and the list of claimable launches from https://explorer.imd.fun/api/earned?wallet=ADDR. Confirm the round argument and the exact semantics against the deployed bytecode of 0xdc542889a9799a8b52d5b41285444dd12c4f916f (launch #953) in a fork test; do not assume.\n\nCONTRACTS (Solidity 0.8.26, Foundry, no proxies, no owner powers over user funds):\n1. SwarmHarvester. claimMany(Claim[] claims) where Claim = {distributor, round, account, amount, proof}. Permissionless. Each claim runs in try/catch; an already-claimed or failing claim is skipped and reported in an event (ClaimResult(distributor, account, ok)), never reverting the batch. Holds no tokens at any time. A keeper may harvest for any wallet; tokens always land in that wallet.\n2. SwarmSeller. sellMany(Sale[] sales, address recipient, uint256 minImdOut, uint256 deadline): pulls tokens the caller approved, swaps each through the given Uniswap v4 route (pool keys passed by the caller: token/IMD direct, or token/ETH then ETH/IMD) via PoolManager unlock callback, and sends all IMD to recipient. Per-sale minOut plus an aggregate minImdOut; a failed sale refunds that token to the caller. Takes a 0.5% fee on the IMD output (see 3). Mainnet v4 PoolManager 0x000000000004444c5dc75cB358380D2e3dE08A90; IMD 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7.\n3. Fee: SwarmSeller's 0.5% IMD fee is sent straight to 0x000000000000000000000000000000000000dEaD in the same call (burned). No owner, no fee change, no sink to manage.\n\nTOKEN: name \"Swarm Harvester\", symbol \"HARVEST\", the launch's standard token paired with IMD. The harvester and seller do not depend on the token.\n\nTESTS: fork tests against real mainnet distributors and real proofs pulled at test time are optional; unit tests with a mock distributor that mirrors the selectors above are required, plus invariants: the harvester never holds tokens; the seller holds no tokens or IMD after any call; exactly 0.5% of IMD output is burned.\n\nDOCS: README with every address, the trust model, and how a frontend builds Claim[] from the two explorer APIs.\n\nWEBSITE: one page. Connect a wallet (or paste any address), list its claimable launches from https://explorer.imd.fun/api/earned, fetch each proof from https://explorer.imd.fun/api/claim, and offer one button \"Claim all\" that calls SwarmHarvester.claimMany. Then show the wallet's balances of those tokens and a \"Sell all to IMD\" flow (approvals, then SwarmSeller.sellMany with a quoted minimum). Read every contract address from the deployment.\n\nDECISIONS: Ethereum mainnet (chain 1), paired with IMD. Token name Swarm Harvester, symbol HARVEST. GitHub and IPFS approved, site name swarm-harvester. No owner powers over user funds, not upgradeable, not pausable. 0.5% seller fee burned to 0x000000000000000000000000000000000000dEaD.\n","briefDigest":"48c6da71c6ebea0ada6c71bfa32a7182496001ac403a39da91ae6f065f967e9b"},"planning":null,"id":"f51d95f5-e150-4cfd-a3d4-83938c74d1e6","state":"completed","template":"shape:chain","objective":"WORKFLOW CONTRACT STAGE CONTEXT: the stage produces implemented and tested contracts, ABI documentation and an independently reviewed launch.json. Each assignment contributes only within its own role and write scope. Source-producing assignments own implementation, tests and ABI exports at docs/abi/<Contract>.json where their scope permits. The generated manifest assignment writes only launch.json. Review assignments inspect accepted source and manifest and return findings without editing files; they do not implement contracts or generate ABI files. Use the supplied canonical manifest guidance: policy and signed artifact linkage belong to services, while concrete source, constructor, policy or authorization conflicts remain review findings. Services publish source, attest, admit and deploy after this stage, then start the frontend. Read .imd/reads/workflow.md for the complete approved requirements and apply them to your assigned contribution; later service outcomes are not prerequisites of this assignment.","blockedReason":null,"createdAt":"2026-10-08T06:38:45.045Z","updatedAt":"2026-10-08T08:09:05.882Z","paidBy":"0xb1292411d17f540e7b7bcb9928b4a62fc3d8a22e","parentJobId":null,"project":{"id":"f51d95f5-e150-4cfd-a3d4-83938c74d1e6","head":"f51d95f5-e150-4cfd-a3d4-83938c74d1e6","running":null,"versions":[{"jobId":"f51d95f5-e150-4cfd-a3d4-83938c74d1e6","workflowId":"aa355f13-7fc7-42cb-ab81-28253f681476","objective":"Swarm Harvester (HARVEST): one-transaction claiming of identity.md launch rewards, and selling them into IMD.\n\nPROBLEM. Every IMD launch gives 10% of its supply to swarm wallets through a per-launch Merkle distributor. A seat wallet can hold 60+ unclaimed allocations across launches, each needing its own claim transaction, then its own sale.\n\nFACTS (verified on Ethereum mainnet). Each launch's distributor exposes claim(uint256,address,uint256,bytes32[]) (selector 0x2e7ba6ef), claimed(uint256 round, address account) (0x120aa877), token() and treasury(). The first argument is the round; claimed tokens are sent to `account`, so anyone may submit a claim for anyone. Proofs come from https://explorer.imd.fun/api/claim?launch=ID&wallet=ADDR and the list of claimable launches from https://explorer.imd.fun/api/earned?wallet=ADDR. Confirm the round argument and the exact semantics against the deployed bytecode of 0xdc542889a9799a8b52d5b41285444dd12c4f916f (launch #953) in a fork test; do not assume.\n\nCONTRACTS (Solidity 0.8.26, Foundry, no proxies, no owner powers over user funds):\n1. SwarmHarvester. claimMany(Claim[] claims) where Claim = {distributor, round, account, amount, proof}. Permissionless. Each claim runs in try/catch; an already-claimed or failing claim is skipped and reported in an event (ClaimResult(distributor, account, ok)), never reverting the batch. Holds no tokens at any time. A keeper may harvest for any wallet; tokens always land in that wallet.\n2. SwarmSeller. sellMany(Sale[] sales, address recipient, uint256 minImdOut, uint256 deadline): pulls tokens the caller approved, swaps each through the given Uniswap v4 route (pool keys passed by the caller: token/IMD direct, or token/ETH then ETH/IMD) via PoolManager unlock callback, and sends all IMD to recipient. Per-sale minOut plus an aggregate minImdOut; a failed sale refunds that token to the caller. Takes a 0.5% fee on the IMD output (see 3). Mainnet v4 PoolManager 0x000000000004444c5dc75cB358380D2e3dE08A90; IMD 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7.\n3. Fee: SwarmSeller's 0.5% IMD fee is sent straight to 0x000000000000000000000000000000000000dEaD in the same call (burned). No owner, no fee change, no sink to manage.\n\nTOKEN: name \"Swarm Harvester\", symbol \"HARVEST\", the launch's standard token paired with IMD. The harvester and seller do not depend on the token.\n\nTESTS: fork tests against real mainnet distributors and real proofs pulled at test time are optional; unit tests with a mock distributor that mirrors the selectors above are required, plus invariants: the harvester never holds tokens; the seller holds no tokens or IMD after any call; exactly 0.5% of IMD output is burned.\n\nDOCS: README with every address, the trust model, and how a frontend builds Claim[] from the two explorer APIs.\n\nWEBSITE: one page. Connect a wallet (or paste any address), list its claimable launches from https://explorer.imd.fun/api/earned, fetch each proof from https://explorer.imd.fun/api/claim, and offer one button \"Claim all\" that calls SwarmHarvester.claimMany. Then show the wallet's balances of those tokens and a \"Sell all to IMD\" flow (approvals, then SwarmSeller.sellMany with a quoted minimum). Read every contract address from the deployment.\n\nDECISIONS: Ethereum mainnet (chain 1), paired with IMD. Token name Swarm Harvester, symbol HARVEST. GitHub and IPFS approved, site name swarm-harvester. No owner powers over user funds, not upgradeable, not pausable. 0.5% seller fee burned to 0x000000000000000000000000000000000000dEaD.","baseCommit":"0243d7da4a4337ae8b16bcdf15bb4ead736fd68f","state":"completed","createdAt":"2026-10-08T06:38:45.045Z"}]},"deliver":true,"host":false,"site":null,"launch":{"requested":true,"kind":"evm_project","id":"01a0f25f-8150-420e-a87c-953dd33dcf28","status":"parked","chainId":1},"oracleRequestId":null,"delivery":{"repoUrl":"https://github.com/identity-md-launches/launch-1018-workflow-contract-stage-context","pullRequestUrl":"https://github.com/identity-md-launches/launch-1018-workflow-contract-stage-context/pull/1","commit":"6e3d9177c615c7dc9854b32076d9d48405be60a8","deliveredAt":"2026-10-08T08:09:28.344Z","media":null},"media":null,"nodes":[{"key":"audit_economics","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T07:40:33.803Z","verdict":null,"seat":{"tokenId":"1271","agentId":"51243"},"live":null},{"key":"audit_flow","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T07:39:50.881Z","verdict":null,"seat":{"tokenId":"1000","agentId":"51486"},"live":null},{"key":"audit_judge","role":"review","state":"accepted","attempt":1,"revisions":2,"judgeRevisions":2,"dependsOn":["build_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"allowedPaths":[],"failureReason":null,"dispatchNote":"judge findings unresolved after 2 revisions: no revision budget left for manifest (2 revisions, 2 from the judge) — Not fixed (third-round settlement of d18c3211): launch.json still pairs the HARVEST pool with native ETH while the approved DECISIONS line and the accepted README pair it with IMD; the author confirms","dispatchNoteAt":"2026-10-08T08:09:05.882Z","updatedAt":"2026-10-08T08:09:05.882Z","verdict":null,"seat":{"tokenId":"540","agentId":"51141"},"live":null},{"key":"audit_math","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T07:39:09.085Z","verdict":null,"seat":{"tokenId":"281","agentId":"51163"},"live":null},{"key":"audit_permissions","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T07:34:11.868Z","verdict":null,"seat":{"tokenId":"1067","agentId":"50966"},"live":null},{"key":"build_contract_project","role":"implement","state":"accepted","attempt":2,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T07:30:21.241Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+ad90ce4c","verifiedTreeHash":"06499aba5a33aa8e6e8b5725d029fa62fc3fcb01","at":"2026-10-08T07:30:21.245Z","failedChecks":[]},"seat":{"tokenId":"1536","agentId":"51461"},"live":null},{"key":"manifest","role":"integrate","state":"accepted","attempt":1,"revisions":2,"judgeRevisions":2,"dependsOn":["build_contract_project"],"allowedPaths":["launch.json"],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T08:04:09.608Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+ad90ce4c","verifiedTreeHash":"b197bd72548ffc3a391ed44de9fe255c393e9a8d","at":"2026-10-08T07:33:15.081Z","failedChecks":[]},"seat":{"tokenId":"1251","agentId":"51153"},"live":null},{"key":"write_foundry_tests","role":"tests","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":["test","test/**"],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T07:45:33.312Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+ad90ce4c","verifiedTreeHash":"0961213f30437e3e5116495311f5e1cfa081b4a3","at":"2026-10-08T07:45:33.317Z","failedChecks":[]},"seat":{"tokenId":"785","agentId":"51128"},"live":null}],"reviews":[{"status":"queued","chainId":1,"txHash":null,"blockNumber":null,"sentAt":null,"entries":[{"nodeKey":"audit_economics","agentId":"51243","value":1,"role":"review:submission"},{"nodeKey":"audit_flow","agentId":"51486","value":1,"role":"review:submission"},{"nodeKey":"audit_judge","agentId":"51141","value":1,"role":"review:submission"},{"nodeKey":"audit_judge","agentId":"52265","value":1,"role":"review:submission"},{"nodeKey":"audit_judge","agentId":"52255","value":1,"role":"review:submission"},{"nodeKey":"audit_math","agentId":"51163","value":1,"role":"review:submission"},{"nodeKey":"audit_permissions","agentId":"50966","value":1,"role":"review:submission"},{"nodeKey":"build_contract_project","agentId":"51461","value":1,"role":"verification:checks"},{"nodeKey":"build_contract_project","agentId":"51211","value":0,"role":"verification:checks"},{"nodeKey":"manifest","agentId":"51153","value":1,"role":"verification:checks"},{"nodeKey":"write_foundry_tests","agentId":"51128","value":1,"role":"verification:checks"}]}]}