{
  "version": 1,
  "sharedInterfaces": "Handoff from contracts to review, launch and frontend (Sepolia, chainId 11155111). Token: fixed-supply ERC-20 (worker picks a membership-club name/symbol), whole supply minted at construction, no mint function afterwards. Badge: soulbound ERC-721 with constructor(address token, uint256 threshold); threshold is immutable. Functions: mint() mints exactly one badge to msg.sender when token.balanceOf(msg.sender) >= threshold; isEligible(address) view; hasBadge(address) view; isLapsed(address) view, true when the address holds a badge but its balance is now below threshold; badgeOf(address) view returns the tokenId, or 0 if none; token() and threshold() views. Every transfer or approval path reverts except the mint. Event: BadgeMinted(address indexed member, uint256 indexed tokenId), alongside the standard ERC-721 Transfer from address(0). ABI JSON in docs/abi/MembershipToken.json and docs/abi/MembershipBadge.json; integration notes in docs/contracts.md. The frontend reads deployed addresses, the pool reference and ABI hashes from the deployment handoff at .imd/reads/deployment.json, never from hardcoded values.",
  "steps": [
    {
      "key": "contracts",
      "skill": "build-contract-project",
      "paths": [
        "src/**",
        "test/**",
        "script/**",
        "lib/**",
        "foundry.toml",
        "remappings.txt",
        ".gitignore",
        "README.md",
        "docs/abi/**",
        "docs/contracts.md"
      ],
      "dependsOn": [],
      "objective": "Start from the empty tree and create the complete Foundry project. Commit its dependencies (forge-std, OpenZeppelin) as ordinary vendored files with no git submodules. Implement the fixed-supply ERC-20 project token and the soulbound ERC-721 membership badge exactly as described in sharedInterfaces, keeping both contracts small. Write thorough Foundry tests. Export ABI JSON to docs/abi/ and write docs/contracts.md covering constructor parameters, the eligibility and lapsed semantics, and the event the site uses to list members. Deployment on Sepolia, pool seeding and publication belong to the control plane's evm_project launch; do not deploy.",
      "acceptanceCriteria": [
        "forge build and forge test pass offline using only committed files, with no submodules",
        "The token has a fixed supply minted once at construction and cannot be minted again",
        "The badge allows one mint per address and only when balance >= the threshold set at deployment; a second mint and a mint below the threshold both revert",
        "Every transfer and approval path on the badge reverts; tests prove the badge stays after the holder's balance falls below the threshold and isLapsed then reports true",
        "isEligible, hasBadge and isLapsed are public views, and each mint emits BadgeMinted(member, tokenId)",
        "docs/abi/MembershipToken.json, docs/abi/MembershipBadge.json and docs/contracts.md match the compiled contracts"
      ]
    },
    {
      "key": "review",
      "skill": "adversarial-review",
      "dependsOn": [
        "contracts"
      ],
      "objective": "Final independent review of the launch, run after the control plane generates the launch manifest and before deployment. Review the token and badge contracts and their tests as an attacker would, independently of the writer: mint bypasses, double mints, soulbound bypasses (transferFrom, safeTransferFrom, approve, setApprovalForAll), wrong eligibility or lapsed logic, and supply inflation. Finish by inspecting the source, docs/abi, docs/contracts.md and the generated launch manifest (Sepolia evm_project, token and badge constructor arguments, pool seeding) for consistency. Write nothing.",
      "acceptanceCriteria": [
        "Findings cite the specific functions and the tests that cover them, or name the tests that are missing",
        "The review confirms the ABI JSON, docs/contracts.md and the generated launch manifest are consistent with the source and target Sepolia (chainId 11155111)",
        "It gives a clear blocking/non-blocking verdict for the launch"
      ]
    },
    {
      "key": "frontend",
      "skill": "frontend-for-contract",
      "paths": [
        "web/**",
        "web/.gitignore",
        "dist/**",
        "docs/web/**"
      ],
      "dependsOn": [
        "review"
      ],
      "objective": "After deployment, build a static Vite and React site under web/ with its export at repository-root dist/. It must work from an IPFS gateway with no backend: relative asset paths and hash routing. Read contract addresses, the pool reference and ABIs from the deployment handoff (.imd/reads/deployment.json) and docs/abi/. Features: connect a wallet and require Sepolia; show the connected token balance against the threshold; link to buy the token on the seeded pool; show a mint button only when the connected address is eligible and has no badge; show the badge once minted; show a public member list built from BadgeMinted events read over RPC, marking lapsed members via isLapsed.",
      "acceptanceCriteria": [
        "The site builds to dist/ and loads from a gateway subpath with no backend or server routes",
        "Addresses and ABIs come from the deployment handoff and docs/abi, with nothing hardcoded that deviates from them",
        "It prompts a network switch when the wallet is not on chainId 11155111",
        "Tests cover the eligibility and mint-button states, the badge display, and building the member list from mint events with lapsed marking"
      ]
    }
  ],
  "questions": []
}
