### Task 1: Pin and prove the repository toolchain **Files:** - Modify: `.gitignore` - Create: `.nvmrc` - Create: `.env.example` - Create: `.gitmodules` (generated by `forge install`) - Create: `foundry.lock` (generated by `forge install`) - Create: `foundry.toml` - Create: `remappings.txt` - Create: `Makefile` - Create: `package.json` - Create: `package-lock.json` (generated by npm) - Create: `tools/check-upgrades-cli.mjs` - Create: `web/package.json` - Create: `web/package-lock.json` (generated by npm) - Create: `web/index.html` - Create: `web/tsconfig.json` - Create: `web/tsconfig.app.json` - Create: `web/tsconfig.node.json` - Create: `web/vite.config.ts` - Create: `web/eslint.config.js` - Create: `web/src/test/toolchain.test.ts` **Interfaces:** - Produces `make doctor`, `make setup`, and the initial verification gate that later tasks extend. - Produces exact dependency revisions for every later Solidity and web task. - Consumes no application source. - [ ] Verify host tools and record the expected initial limitation: ```bash forge --version anvil --version node --version npm --version make --version ``` Expected now: Foundry commands may be missing; Node/npm/make print their installed versions. If Foundry is missing during execution, request permission to install Foundry from its official installer, then pin with `foundryup -i 1.7.1`. Do not silently install system-wide tools. - [ ] Extend `.gitignore` with exactly these runtime classes: ```gitignore .env .env.local .demo/ cache/ out/ broadcast/ deployments/*.json deployments/**/*.json !deployments/*.example.json node_modules/ web/node_modules/ web/dist/ web/coverage/ web/public/deployment.json web/src/generated/*.ts !.gitkeep .superpowers/ ``` - [ ] Pin Node/npm in `.nvmrc` and create a private root `package.json` with the same `packageManager`/`engines` fields plus exactly one dev dependency: `"@openzeppelin/upgrades-core": "1.46.0"`. Generate and commit the root lockfile with `npm install --save-exact`. This locally satisfies the plugin’s hard-coded `^1.45.0` range. - [ ] Pin the browser dependencies in `web/package.json`; the package must be private and use only exact versions: ```json { "name": "uups-bank-operations-console", "private": true, "version": "0.1.0", "type": "module", "packageManager": "npm@11.17.0", "engines": { "node": ">=24.18.0 <25", "npm": ">=11.17.0 <12" }, "scripts": { "dev": "vite --host 127.0.0.1", "lint": "eslint . --max-warnings 0", "typecheck": "tsc -b --pretty false", "test": "vitest run", "build": "tsc -b && vite build" } } ``` Add exact runtime dependencies `@tanstack/react-query@5.101.4`, `react@19.2.8`, `react-dom@19.2.8`, `viem@2.55.8`, and `wagmi@3.7.5`. Add exact dev dependencies `@eslint/js@10.0.1`, `@testing-library/dom@10.4.1`, `@testing-library/react@16.3.2`, `@types/node@24.10.0`, `@types/react@19.2.14`, `@types/react-dom@19.2.4`, `@vitejs/plugin-react@6.0.4`, `eslint@10.0.1`, `eslint-plugin-react-hooks@7.1.1`, `eslint-plugin-react-refresh@0.5.3`, `globals@17.7.0`, `jsdom@30.0.1`, `typescript@7.0.2`, `typescript-eslint@8.65.0`, `vite@8.2.0`, and `vitest@4.1.10`. If npm rejects one exact revision because the registry changed, verify the official release before changing both this plan and the package file. - [ ] Configure Foundry in `foundry.toml`: ```toml [profile.default] src = "src" test = "test" script = "script" out = "out" libs = ["lib"] solc_version = "0.8.35" evm_version = "cancun" optimizer = true optimizer_runs = 200 ffi = true ast = true build_info = true extra_output = ["storageLayout"] fs_permissions = [ { access = "read", path = "out" }, { access = "read-write", path = "deployments" } ] [fuzz] runs = 512 seed = "0x5555505342414e4b" [invariant] runs = 128 depth = 64 fail_on_revert = true ``` - [ ] Install exact Solidity dependencies as Git submodules and write canonical remappings: ```bash forge install foundry-rs/forge-std@v1.16.1 forge install OpenZeppelin/openzeppelin-foundry-upgrades@v0.4.1 forge install OpenZeppelin/openzeppelin-contracts-upgradeable@v5.6.1 git submodule update --init --recursive ``` ```text forge-std/=lib/forge-std/src/ openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/ @openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/ @openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/ ``` Do not install a second top-level copy of `openzeppelin-contracts`; the upgradeable submodule’s pinned transitive copy supplies both canonical remappings. - [ ] Create `tools/check-upgrades-cli.mjs`. It must assert that the plugin source contains `UPGRADES_CORE = "^1.45.0"`, the root lockfile resolves `@openzeppelin/upgrades-core` to exactly `1.46.0`, and the locally installed package reports `1.46.0`. Then prove the CLI can start with networking disabled: ```bash npm ci node tools/check-upgrades-cli.mjs npm_config_offline=true npx @openzeppelin/upgrades-core@^1.45.0 validate --help ``` Expected: all commands exit `0` without fetching. Do not patch the vendored OpenZeppelin version constant. - [ ] Create Vite/React/TypeScript/ESLint/Vitest configuration manually so no unpinned scaffold generator is executed. Configure jsdom, `web/src/test/setup.ts`, strict TypeScript, and React refresh. Run: ```bash npm --prefix web install --save-exact npm --prefix web test ``` Expected red: `toolchain.test.ts` cannot import the not-yet-created `src/config/toolchain.ts`. - [ ] Create `web/src/config/toolchain.ts` exporting the display labels `Foundry 1.7.1`, `Solidity 0.8.35`, `OpenZeppelin 5.6.1`, and `UUPS`; make the test assert those exact values. - [ ] Add an initial `Makefile` with shell safety (`SHELL := /bin/bash`, `.SHELLFLAGS := -euo pipefail -c`) and non-destructive targets: ```make .PHONY: doctor setup verify doctor: @./tools/doctor.sh setup: @git submodule update --init --recursive @npm ci @npm --prefix web ci verify: @forge fmt --check @forge clean @npm_config_offline=true forge build --force @npm_config_offline=true forge test --force @npm --prefix web run lint @npm --prefix web run typecheck @npm --prefix web test @npm --prefix web run build ``` Create a temporary minimal `tools/doctor.sh` that reports missing commands and exact expected versions without installing anything; Task 9 replaces it with full port/config checks. - [ ] Run the green foundation checks: ```bash forge fmt --check forge clean npm_config_offline=true forge build --force npm_config_offline=true forge test --force node tools/check-upgrades-cli.mjs npm --prefix web run lint npm --prefix web run typecheck npm --prefix web test npm --prefix web run build ``` Expected: all exit `0`; the empty Solidity source tree builds and the toolchain test passes. - [ ] Commit the foundation: ```bash git add .gitignore .nvmrc .env.example .gitmodules foundry.lock foundry.toml remappings.txt package.json package-lock.json Makefile tools/check-upgrades-cli.mjs tools/doctor.sh lib web git commit -m "build: pin demo toolchains" ``` ---