agent-bober 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/.claude-plugin/plugin.json +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +495 -0
  4. package/agents/bober-evaluator.md +323 -0
  5. package/agents/bober-generator.md +245 -0
  6. package/agents/bober-planner.md +248 -0
  7. package/dist/cli/commands/eval.d.ts +6 -0
  8. package/dist/cli/commands/eval.d.ts.map +1 -0
  9. package/dist/cli/commands/eval.js +129 -0
  10. package/dist/cli/commands/eval.js.map +1 -0
  11. package/dist/cli/commands/init.d.ts +5 -0
  12. package/dist/cli/commands/init.d.ts.map +1 -0
  13. package/dist/cli/commands/init.js +547 -0
  14. package/dist/cli/commands/init.js.map +1 -0
  15. package/dist/cli/commands/plan.d.ts +5 -0
  16. package/dist/cli/commands/plan.d.ts.map +1 -0
  17. package/dist/cli/commands/plan.js +87 -0
  18. package/dist/cli/commands/plan.js.map +1 -0
  19. package/dist/cli/commands/run.d.ts +5 -0
  20. package/dist/cli/commands/run.d.ts.map +1 -0
  21. package/dist/cli/commands/run.js +120 -0
  22. package/dist/cli/commands/run.js.map +1 -0
  23. package/dist/cli/commands/sprint.d.ts +6 -0
  24. package/dist/cli/commands/sprint.d.ts.map +1 -0
  25. package/dist/cli/commands/sprint.js +206 -0
  26. package/dist/cli/commands/sprint.js.map +1 -0
  27. package/dist/cli/index.d.ts +3 -0
  28. package/dist/cli/index.d.ts.map +1 -0
  29. package/dist/cli/index.js +124 -0
  30. package/dist/cli/index.js.map +1 -0
  31. package/dist/config/defaults.d.ts +15 -0
  32. package/dist/config/defaults.d.ts.map +1 -0
  33. package/dist/config/defaults.js +226 -0
  34. package/dist/config/defaults.js.map +1 -0
  35. package/dist/config/index.d.ts +4 -0
  36. package/dist/config/index.d.ts.map +1 -0
  37. package/dist/config/index.js +8 -0
  38. package/dist/config/index.js.map +1 -0
  39. package/dist/config/loader.d.ts +18 -0
  40. package/dist/config/loader.d.ts.map +1 -0
  41. package/dist/config/loader.js +189 -0
  42. package/dist/config/loader.js.map +1 -0
  43. package/dist/config/schema.d.ts +904 -0
  44. package/dist/config/schema.d.ts.map +1 -0
  45. package/dist/config/schema.js +181 -0
  46. package/dist/config/schema.js.map +1 -0
  47. package/dist/contracts/eval-result.d.ts +205 -0
  48. package/dist/contracts/eval-result.d.ts.map +1 -0
  49. package/dist/contracts/eval-result.js +87 -0
  50. package/dist/contracts/eval-result.js.map +1 -0
  51. package/dist/contracts/index.d.ts +4 -0
  52. package/dist/contracts/index.d.ts.map +1 -0
  53. package/dist/contracts/index.js +16 -0
  54. package/dist/contracts/index.js.map +1 -0
  55. package/dist/contracts/spec.d.ts +101 -0
  56. package/dist/contracts/spec.d.ts.map +1 -0
  57. package/dist/contracts/spec.js +51 -0
  58. package/dist/contracts/spec.js.map +1 -0
  59. package/dist/contracts/sprint-contract.d.ts +141 -0
  60. package/dist/contracts/sprint-contract.d.ts.map +1 -0
  61. package/dist/contracts/sprint-contract.js +80 -0
  62. package/dist/contracts/sprint-contract.js.map +1 -0
  63. package/dist/evaluators/builtin/api-check.d.ts +13 -0
  64. package/dist/evaluators/builtin/api-check.d.ts.map +1 -0
  65. package/dist/evaluators/builtin/api-check.js +152 -0
  66. package/dist/evaluators/builtin/api-check.js.map +1 -0
  67. package/dist/evaluators/builtin/build-check.d.ts +17 -0
  68. package/dist/evaluators/builtin/build-check.d.ts.map +1 -0
  69. package/dist/evaluators/builtin/build-check.js +155 -0
  70. package/dist/evaluators/builtin/build-check.js.map +1 -0
  71. package/dist/evaluators/builtin/command-runner.d.ts +26 -0
  72. package/dist/evaluators/builtin/command-runner.d.ts.map +1 -0
  73. package/dist/evaluators/builtin/command-runner.js +114 -0
  74. package/dist/evaluators/builtin/command-runner.js.map +1 -0
  75. package/dist/evaluators/builtin/lint.d.ts +17 -0
  76. package/dist/evaluators/builtin/lint.d.ts.map +1 -0
  77. package/dist/evaluators/builtin/lint.js +264 -0
  78. package/dist/evaluators/builtin/lint.js.map +1 -0
  79. package/dist/evaluators/builtin/playwright.d.ts +16 -0
  80. package/dist/evaluators/builtin/playwright.d.ts.map +1 -0
  81. package/dist/evaluators/builtin/playwright.js +238 -0
  82. package/dist/evaluators/builtin/playwright.js.map +1 -0
  83. package/dist/evaluators/builtin/typescript-check.d.ts +12 -0
  84. package/dist/evaluators/builtin/typescript-check.d.ts.map +1 -0
  85. package/dist/evaluators/builtin/typescript-check.js +155 -0
  86. package/dist/evaluators/builtin/typescript-check.js.map +1 -0
  87. package/dist/evaluators/builtin/unit-test.d.ts +18 -0
  88. package/dist/evaluators/builtin/unit-test.d.ts.map +1 -0
  89. package/dist/evaluators/builtin/unit-test.js +279 -0
  90. package/dist/evaluators/builtin/unit-test.js.map +1 -0
  91. package/dist/evaluators/index.d.ts +11 -0
  92. package/dist/evaluators/index.d.ts.map +1 -0
  93. package/dist/evaluators/index.js +13 -0
  94. package/dist/evaluators/index.js.map +1 -0
  95. package/dist/evaluators/plugin-interface.d.ts +50 -0
  96. package/dist/evaluators/plugin-interface.d.ts.map +1 -0
  97. package/dist/evaluators/plugin-interface.js +2 -0
  98. package/dist/evaluators/plugin-interface.js.map +1 -0
  99. package/dist/evaluators/plugin-loader.d.ts +18 -0
  100. package/dist/evaluators/plugin-loader.d.ts.map +1 -0
  101. package/dist/evaluators/plugin-loader.js +107 -0
  102. package/dist/evaluators/plugin-loader.js.map +1 -0
  103. package/dist/evaluators/registry.d.ts +78 -0
  104. package/dist/evaluators/registry.d.ts.map +1 -0
  105. package/dist/evaluators/registry.js +238 -0
  106. package/dist/evaluators/registry.js.map +1 -0
  107. package/dist/index.d.ts +17 -0
  108. package/dist/index.d.ts.map +1 -0
  109. package/dist/index.js +22 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/orchestrator/context-handoff.d.ts +543 -0
  112. package/dist/orchestrator/context-handoff.d.ts.map +1 -0
  113. package/dist/orchestrator/context-handoff.js +133 -0
  114. package/dist/orchestrator/context-handoff.js.map +1 -0
  115. package/dist/orchestrator/evaluator-agent.d.ts +15 -0
  116. package/dist/orchestrator/evaluator-agent.d.ts.map +1 -0
  117. package/dist/orchestrator/evaluator-agent.js +233 -0
  118. package/dist/orchestrator/evaluator-agent.js.map +1 -0
  119. package/dist/orchestrator/generator-agent.d.ts +16 -0
  120. package/dist/orchestrator/generator-agent.d.ts.map +1 -0
  121. package/dist/orchestrator/generator-agent.js +147 -0
  122. package/dist/orchestrator/generator-agent.js.map +1 -0
  123. package/dist/orchestrator/pipeline.d.ts +24 -0
  124. package/dist/orchestrator/pipeline.d.ts.map +1 -0
  125. package/dist/orchestrator/pipeline.js +290 -0
  126. package/dist/orchestrator/pipeline.js.map +1 -0
  127. package/dist/orchestrator/planner-agent.d.ts +10 -0
  128. package/dist/orchestrator/planner-agent.d.ts.map +1 -0
  129. package/dist/orchestrator/planner-agent.js +187 -0
  130. package/dist/orchestrator/planner-agent.js.map +1 -0
  131. package/dist/state/helpers.d.ts +5 -0
  132. package/dist/state/helpers.d.ts.map +1 -0
  133. package/dist/state/helpers.js +8 -0
  134. package/dist/state/helpers.js.map +1 -0
  135. package/dist/state/history.d.ts +39 -0
  136. package/dist/state/history.d.ts.map +1 -0
  137. package/dist/state/history.js +162 -0
  138. package/dist/state/history.js.map +1 -0
  139. package/dist/state/index.d.ts +8 -0
  140. package/dist/state/index.d.ts.map +1 -0
  141. package/dist/state/index.js +22 -0
  142. package/dist/state/index.js.map +1 -0
  143. package/dist/state/plan-state.d.ts +21 -0
  144. package/dist/state/plan-state.d.ts.map +1 -0
  145. package/dist/state/plan-state.js +108 -0
  146. package/dist/state/plan-state.js.map +1 -0
  147. package/dist/state/sprint-state.d.ts +20 -0
  148. package/dist/state/sprint-state.d.ts.map +1 -0
  149. package/dist/state/sprint-state.js +98 -0
  150. package/dist/state/sprint-state.js.map +1 -0
  151. package/dist/utils/fs.d.ts +31 -0
  152. package/dist/utils/fs.d.ts.map +1 -0
  153. package/dist/utils/fs.js +67 -0
  154. package/dist/utils/fs.js.map +1 -0
  155. package/dist/utils/git.d.ts +35 -0
  156. package/dist/utils/git.d.ts.map +1 -0
  157. package/dist/utils/git.js +84 -0
  158. package/dist/utils/git.js.map +1 -0
  159. package/dist/utils/index.d.ts +4 -0
  160. package/dist/utils/index.d.ts.map +1 -0
  161. package/dist/utils/index.js +4 -0
  162. package/dist/utils/index.js.map +1 -0
  163. package/dist/utils/logger.d.ts +45 -0
  164. package/dist/utils/logger.d.ts.map +1 -0
  165. package/dist/utils/logger.js +73 -0
  166. package/dist/utils/logger.js.map +1 -0
  167. package/hooks/hooks.json +10 -0
  168. package/package.json +67 -0
  169. package/scripts/detect-stack.sh +287 -0
  170. package/scripts/init-project.sh +206 -0
  171. package/scripts/run-eval.sh +175 -0
  172. package/skills/bober.anchor/SKILL.md +365 -0
  173. package/skills/bober.anchor/references/anchor-guide.md +567 -0
  174. package/skills/bober.brownfield/SKILL.md +422 -0
  175. package/skills/bober.brownfield/references/codebase-analysis.md +304 -0
  176. package/skills/bober.eval/SKILL.md +235 -0
  177. package/skills/bober.eval/references/eval-strategies.md +407 -0
  178. package/skills/bober.eval/references/feedback-format.md +182 -0
  179. package/skills/bober.plan/SKILL.md +244 -0
  180. package/skills/bober.plan/references/clarification-guide.md +124 -0
  181. package/skills/bober.plan/references/spec-schema.md +253 -0
  182. package/skills/bober.react/SKILL.md +330 -0
  183. package/skills/bober.react/references/react-scaffold.md +344 -0
  184. package/skills/bober.run/SKILL.md +303 -0
  185. package/skills/bober.solidity/SKILL.md +416 -0
  186. package/skills/bober.solidity/references/solidity-guide.md +487 -0
  187. package/skills/bober.sprint/SKILL.md +280 -0
  188. package/skills/bober.sprint/references/contract-schema.md +251 -0
  189. package/templates/base/CLAUDE.md +20 -0
  190. package/templates/base/bober.config.json +35 -0
  191. package/templates/brownfield/CLAUDE.md +34 -0
  192. package/templates/brownfield/bober.config.json +37 -0
  193. package/templates/presets/anchor/CLAUDE.md +163 -0
  194. package/templates/presets/anchor/bober.config.json +9 -0
  195. package/templates/presets/api-node/CLAUDE.md +153 -0
  196. package/templates/presets/api-node/bober.config.json +10 -0
  197. package/templates/presets/nextjs/CLAUDE.md +82 -0
  198. package/templates/presets/nextjs/bober.config.json +14 -0
  199. package/templates/presets/python-api/CLAUDE.md +202 -0
  200. package/templates/presets/python-api/bober.config.json +9 -0
  201. package/templates/presets/react-vite/CLAUDE.md +71 -0
  202. package/templates/presets/react-vite/bober.config.json +53 -0
  203. package/templates/presets/react-vite/scaffold/package.json +45 -0
  204. package/templates/presets/react-vite/scaffold/server/index.ts +38 -0
  205. package/templates/presets/react-vite/scaffold/server/tsconfig.json +24 -0
  206. package/templates/presets/react-vite/scaffold/src/App.tsx +37 -0
  207. package/templates/presets/react-vite/scaffold/src/index.html +12 -0
  208. package/templates/presets/react-vite/scaffold/src/main.tsx +12 -0
  209. package/templates/presets/react-vite/scaffold/tsconfig.json +27 -0
  210. package/templates/presets/react-vite/scaffold/vite.config.ts +34 -0
  211. package/templates/presets/solidity/CLAUDE.md +106 -0
  212. package/templates/presets/solidity/bober.config.json +9 -0
@@ -0,0 +1,71 @@
1
+ # Project Guide
2
+
3
+ ## Architecture
4
+
5
+ This is a React + Express full-stack TypeScript application.
6
+
7
+ ```
8
+ src/ React frontend (Vite)
9
+ App.tsx Root component
10
+ main.tsx Entry point
11
+ index.html HTML template
12
+ server/ Express backend
13
+ index.ts Server entry point with API routes
14
+ ```
15
+
16
+ **Frontend:** React 19, TypeScript, Vite 6, bundled with `@vitejs/plugin-react`.
17
+ **Backend:** Express 5, TypeScript, running on Node with `tsx` in development.
18
+
19
+ The Vite dev server proxies `/api/*` requests to the Express server at `localhost:3001`.
20
+
21
+ ## Running the Project
22
+
23
+ ```bash
24
+ npm install # install all dependencies
25
+ npm run dev # start both frontend (5173) and backend (3001)
26
+ npm run dev:client # start only the Vite dev server
27
+ npm run dev:server # start only the Express server
28
+ ```
29
+
30
+ ## Building
31
+
32
+ ```bash
33
+ npm run build # builds both client and server
34
+ npm run build:client # vite build -> dist/client/
35
+ npm run build:server # tsc -> dist/server/
36
+ ```
37
+
38
+ ## Testing
39
+
40
+ ```bash
41
+ npm test # run unit tests with Vitest
42
+ npm run test:watch # run Vitest in watch mode
43
+ npm run test:e2e # run Playwright end-to-end tests
44
+ ```
45
+
46
+ Unit tests live alongside source files as `*.test.ts` or `*.test.tsx`. Use `@testing-library/react` for component tests. Use `vitest` globals (`describe`, `it`, `expect`).
47
+
48
+ ## Linting and Type Checking
49
+
50
+ ```bash
51
+ npm run lint # ESLint across all .ts/.tsx files
52
+ npm run typecheck # tsc --noEmit for both client and server
53
+ ```
54
+
55
+ ## Coding Conventions
56
+
57
+ - **TypeScript strict mode** is enabled everywhere. No `any` unless absolutely necessary.
58
+ - **ESM only** (`"type": "module"` in package.json). Use `import`/`export`, never `require`.
59
+ - **Functional React components** with hooks. No class components.
60
+ - **Path aliases:** Use `@/` to import from `src/` in frontend code.
61
+ - **API routes** are prefixed with `/api/`. All API responses are JSON.
62
+ - **Error handling:** API endpoints must return appropriate HTTP status codes and structured error objects (`{ error: string, details?: unknown }`).
63
+ - **No default exports** except for React page/route components and the Express app.
64
+ - **File naming:** `kebab-case.ts` for utilities, `PascalCase.tsx` for React components.
65
+
66
+ ## Key Decisions
67
+
68
+ - Vite is used instead of Next.js for simplicity and separation of concerns.
69
+ - The backend is a standalone Express server, not a serverless function layer.
70
+ - Vitest is used for unit tests (Vite-native, fast, compatible API).
71
+ - Playwright handles E2E testing against the running application.
@@ -0,0 +1,53 @@
1
+ {
2
+ "project": {
3
+ "name": "",
4
+ "mode": "greenfield",
5
+ "preset": "react-vite",
6
+ "description": "React + Vite frontend with Express backend"
7
+ },
8
+ "planner": {
9
+ "maxClarifications": 5,
10
+ "model": "opus",
11
+ "contextFiles": [
12
+ "package.json",
13
+ "tsconfig.json",
14
+ "vite.config.ts",
15
+ "server/index.ts"
16
+ ]
17
+ },
18
+ "generator": {
19
+ "model": "sonnet",
20
+ "maxTurnsPerSprint": 50,
21
+ "autoCommit": true,
22
+ "branchPattern": "bober/{feature-name}"
23
+ },
24
+ "evaluator": {
25
+ "model": "sonnet",
26
+ "strategies": [
27
+ { "type": "typecheck", "required": true },
28
+ { "type": "lint", "required": true },
29
+ { "type": "build", "required": true },
30
+ { "type": "unit-test", "required": true },
31
+ { "type": "playwright", "required": false }
32
+ ],
33
+ "maxIterations": 3
34
+ },
35
+ "sprint": {
36
+ "maxSprints": 10,
37
+ "requireContracts": true,
38
+ "sprintSize": "medium"
39
+ },
40
+ "pipeline": {
41
+ "maxIterations": 20,
42
+ "requireApproval": false,
43
+ "contextReset": "always"
44
+ },
45
+ "commands": {
46
+ "install": "npm install",
47
+ "build": "npm run build",
48
+ "test": "npm test",
49
+ "lint": "npm run lint",
50
+ "dev": "npm run dev",
51
+ "typecheck": "npx tsc --noEmit"
52
+ }
53
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "concurrently \"npm run dev:client\" \"npm run dev:server\"",
8
+ "dev:client": "vite",
9
+ "dev:server": "tsx watch server/index.ts",
10
+ "build": "npm run build:client && npm run build:server",
11
+ "build:client": "vite build",
12
+ "build:server": "tsc -p server/tsconfig.json",
13
+ "preview": "vite preview",
14
+ "test": "vitest run",
15
+ "test:watch": "vitest",
16
+ "test:e2e": "playwright test",
17
+ "lint": "eslint . --ext .ts,.tsx",
18
+ "typecheck": "tsc --noEmit && tsc -p server/tsconfig.json --noEmit"
19
+ },
20
+ "dependencies": {
21
+ "express": "^5.0.1",
22
+ "react": "^19.0.0",
23
+ "react-dom": "^19.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@eslint/js": "^9.19.0",
27
+ "@playwright/test": "^1.50.0",
28
+ "@testing-library/jest-dom": "^6.6.3",
29
+ "@testing-library/react": "^16.2.0",
30
+ "@types/express": "^5.0.0",
31
+ "@types/node": "^22.13.0",
32
+ "@types/react": "^19.0.8",
33
+ "@types/react-dom": "^19.0.3",
34
+ "@vitejs/plugin-react": "^4.3.4",
35
+ "concurrently": "^9.1.2",
36
+ "eslint": "^9.19.0",
37
+ "globals": "^15.14.0",
38
+ "jsdom": "^26.0.0",
39
+ "tsx": "^4.19.2",
40
+ "typescript": "^5.7.3",
41
+ "typescript-eslint": "^8.22.0",
42
+ "vite": "^6.0.11",
43
+ "vitest": "^3.0.5"
44
+ }
45
+ }
@@ -0,0 +1,38 @@
1
+ import express from "express";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ const app = express();
7
+ const PORT = Number(process.env.PORT) || 3001;
8
+
9
+ // -- Middleware ----------------------------------------------------------
10
+ app.use(express.json());
11
+
12
+ // -- API Routes ----------------------------------------------------------
13
+
14
+ app.get("/api/health", (_req, res) => {
15
+ res.json({
16
+ status: "ok",
17
+ timestamp: new Date().toISOString(),
18
+ });
19
+ });
20
+
21
+ // -- Static Serving (production) -----------------------------------------
22
+ // In production, serve the built Vite client from dist/client.
23
+ if (process.env.NODE_ENV === "production") {
24
+ const clientDist = path.resolve(__dirname, "../client");
25
+ app.use(express.static(clientDist));
26
+
27
+ // SPA fallback: serve index.html for any non-API route.
28
+ app.get("*", (_req, res) => {
29
+ res.sendFile(path.join(clientDist, "index.html"));
30
+ });
31
+ }
32
+
33
+ // -- Start ---------------------------------------------------------------
34
+ app.listen(PORT, () => {
35
+ console.log(`Server running at http://localhost:${PORT}`);
36
+ });
37
+
38
+ export default app;
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "../dist/server",
8
+ "rootDir": ".",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "sourceMap": true,
16
+ "isolatedModules": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noImplicitReturns": true,
20
+ "noFallthroughCasesInSwitch": true
21
+ },
22
+ "include": ["./**/*.ts"],
23
+ "exclude": ["node_modules"]
24
+ }
@@ -0,0 +1,37 @@
1
+ import { useState, useEffect } from "react";
2
+
3
+ interface HealthStatus {
4
+ status: string;
5
+ timestamp: string;
6
+ }
7
+
8
+ export default function App() {
9
+ const [health, setHealth] = useState<HealthStatus | null>(null);
10
+
11
+ useEffect(() => {
12
+ fetch("/api/health")
13
+ .then((res) => res.json())
14
+ .then((data: HealthStatus) => setHealth(data))
15
+ .catch(() => setHealth(null));
16
+ }, []);
17
+
18
+ return (
19
+ <main style={{ maxWidth: 640, margin: "0 auto", padding: "2rem" }}>
20
+ <h1>Welcome to Your App</h1>
21
+ <p>
22
+ Edit <code>src/App.tsx</code> to get started.
23
+ </p>
24
+ <section>
25
+ <h2>API Status</h2>
26
+ {health ? (
27
+ <p>
28
+ Server is <strong>{health.status}</strong> (checked at{" "}
29
+ {new Date(health.timestamp).toLocaleTimeString()})
30
+ </p>
31
+ ) : (
32
+ <p>Connecting to server...</p>
33
+ )}
34
+ </section>
35
+ </main>
36
+ );
37
+ }
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>App</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,12 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import App from "./App.tsx";
4
+
5
+ const rootEl = document.getElementById("root");
6
+ if (!rootEl) throw new Error("Missing #root element in index.html");
7
+
8
+ createRoot(rootEl).render(
9
+ <StrictMode>
10
+ <App />
11
+ </StrictMode>,
12
+ );
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "Bundler",
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noImplicitReturns": true,
18
+ "noFallthroughCasesInSwitch": true,
19
+ "allowImportingTsExtensions": true,
20
+ "baseUrl": ".",
21
+ "paths": {
22
+ "@/*": ["src/*"]
23
+ }
24
+ },
25
+ "include": ["src/**/*", "vite-env.d.ts"],
26
+ "exclude": ["node_modules", "dist", "server"]
27
+ }
@@ -0,0 +1,34 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import path from "node:path";
4
+
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ root: "src",
8
+ publicDir: path.resolve(__dirname, "public"),
9
+ resolve: {
10
+ alias: {
11
+ "@": path.resolve(__dirname, "src"),
12
+ },
13
+ },
14
+ server: {
15
+ port: 5173,
16
+ proxy: {
17
+ "/api": {
18
+ target: "http://localhost:3001",
19
+ changeOrigin: true,
20
+ },
21
+ },
22
+ },
23
+ build: {
24
+ outDir: path.resolve(__dirname, "dist/client"),
25
+ emptyOutDir: true,
26
+ sourcemap: true,
27
+ },
28
+ test: {
29
+ globals: true,
30
+ environment: "jsdom",
31
+ setupFiles: [],
32
+ css: true,
33
+ },
34
+ });
@@ -0,0 +1,106 @@
1
+ # Solidity Project Guide
2
+
3
+ ## Architecture
4
+
5
+ This is an EVM smart contract project using Hardhat (or Foundry).
6
+
7
+ ```
8
+ contracts/ Solidity source files
9
+ interfaces/ Interface definitions
10
+ libraries/ Shared library contracts
11
+ test/ Test files (Chai/Mocha for Hardhat, Forge tests for Foundry)
12
+ scripts/ Deployment and utility scripts
13
+ hardhat.config.ts Hardhat configuration
14
+ ```
15
+
16
+ ## Hardhat Setup
17
+
18
+ ```bash
19
+ npx hardhat compile # compile all contracts
20
+ npx hardhat test # run the test suite
21
+ npx hardhat test --grep "transfer" # run tests matching a pattern
22
+ npx hardhat node # start a local Hardhat node
23
+ npx hardhat run scripts/deploy.ts --network localhost # deploy locally
24
+ ```
25
+
26
+ If using Foundry alongside Hardhat:
27
+
28
+ ```bash
29
+ forge build # compile with Foundry
30
+ forge test # run Foundry tests
31
+ forge test -vvv # run with verbose output (traces)
32
+ ```
33
+
34
+ ## Contract Structure
35
+
36
+ - Each contract goes in its own file under `contracts/`.
37
+ - Use a consistent naming convention: `ContractName.sol` matches the contract name inside.
38
+ - Inherit from OpenZeppelin contracts where possible instead of reimplementing standard functionality.
39
+ - Define interfaces in `contracts/interfaces/` and implement them in concrete contracts.
40
+
41
+ ## OpenZeppelin Usage
42
+
43
+ - Import OpenZeppelin contracts from `@openzeppelin/contracts`.
44
+ - Common imports: `ERC20`, `ERC721`, `ERC1155`, `Ownable`, `AccessControl`, `ReentrancyGuard`, `Pausable`.
45
+ - For upgradeable contracts, use `@openzeppelin/contracts-upgradeable` and initialize in an `initialize()` function instead of a constructor.
46
+
47
+ ## Testing
48
+
49
+ - Write tests in TypeScript using Chai assertions and Mocha structure (`describe`, `it`).
50
+ - Use `ethers.getSigners()` to get test accounts.
51
+ - Use `loadFixture` from `@nomicfoundation/hardhat-toolbox` to snapshot and revert state between tests.
52
+ - Test all success paths, revert conditions, event emissions, and edge cases.
53
+ - Use `expect(...).to.be.revertedWith("message")` or `revertedWithCustomError` for revert testing.
54
+
55
+ ```typescript
56
+ import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers";
57
+ import { expect } from "chai";
58
+ import hre from "hardhat";
59
+
60
+ describe("MyContract", function () {
61
+ async function deployFixture() {
62
+ const [owner, other] = await hre.ethers.getSigners();
63
+ const MyContract = await hre.ethers.getContractFactory("MyContract");
64
+ const contract = await MyContract.deploy();
65
+ return { contract, owner, other };
66
+ }
67
+
68
+ it("should do something", async function () {
69
+ const { contract, owner } = await loadFixture(deployFixture);
70
+ expect(await contract.owner()).to.equal(owner.address);
71
+ });
72
+ });
73
+ ```
74
+
75
+ ## Deployment Scripts
76
+
77
+ - Place deployment scripts in `scripts/`.
78
+ - Use `hardhat-deploy` plugin or write custom scripts with `ethers`.
79
+ - Always verify contracts on block explorers after deployment.
80
+
81
+ ## Gas Optimization
82
+
83
+ - Use `uint256` instead of smaller uint types unless packing structs.
84
+ - Prefer `calldata` over `memory` for external function parameters that are read-only.
85
+ - Use `immutable` for variables set once in the constructor.
86
+ - Use `constant` for compile-time constants.
87
+ - Minimize storage writes (SSTORE is the most expensive opcode).
88
+ - Use events for data that does not need on-chain reads.
89
+ - Batch operations where possible to amortize base transaction costs.
90
+
91
+ ## Security Patterns
92
+
93
+ - **Reentrancy**: Use `ReentrancyGuard` or follow checks-effects-interactions pattern.
94
+ - **Overflow/Underflow**: Solidity 0.8+ has built-in overflow checks. Be careful with `unchecked` blocks.
95
+ - **Access Control**: Use `Ownable` for simple ownership or `AccessControl` for role-based permissions.
96
+ - **Input Validation**: Validate all external inputs with `require` statements at the top of functions.
97
+ - **Frontrunning**: Consider commit-reveal schemes or use flashbots for sensitive transactions.
98
+ - **Upgradability**: If using proxies, follow the UUPS or Transparent Proxy pattern. Never leave an implementation uninitialized.
99
+
100
+ ## Linting
101
+
102
+ ```bash
103
+ npx solhint 'contracts/**/*.sol' # lint Solidity files
104
+ ```
105
+
106
+ Configure rules in `.solhint.json`. Recommended rules: `compiler-version`, `no-unused-vars`, `reason-string`, `func-visibility`.
@@ -0,0 +1,9 @@
1
+ {
2
+ "project": { "name": "my-contracts", "mode": "greenfield", "preset": "solidity" },
3
+ "evaluator": { "model": "sonnet", "strategies": [
4
+ { "type": "build", "required": true },
5
+ { "type": "lint", "required": true },
6
+ { "type": "unit-test", "required": true }
7
+ ], "maxIterations": 3 },
8
+ "commands": { "build": "npx hardhat compile", "test": "npx hardhat test", "lint": "npx solhint 'contracts/**/*.sol'" }
9
+ }