@hivehub/rulebook 1.2.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.
- package/LICENSE +191 -0
- package/README.md +539 -0
- package/dist/agents/claude-code.d.ts +69 -0
- package/dist/agents/claude-code.d.ts.map +1 -0
- package/dist/agents/claude-code.js +180 -0
- package/dist/agents/claude-code.js.map +1 -0
- package/dist/agents/cursor-agent.d.ts +184 -0
- package/dist/agents/cursor-agent.d.ts.map +1 -0
- package/dist/agents/cursor-agent.js +299 -0
- package/dist/agents/cursor-agent.js.map +1 -0
- package/dist/agents/gemini-cli.d.ts +69 -0
- package/dist/agents/gemini-cli.d.ts.map +1 -0
- package/dist/agents/gemini-cli.js +180 -0
- package/dist/agents/gemini-cli.js.map +1 -0
- package/dist/cli/commands.d.ts +57 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +1370 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/docs-prompts.d.ts +3 -0
- package/dist/cli/docs-prompts.d.ts.map +1 -0
- package/dist/cli/docs-prompts.js +45 -0
- package/dist/cli/docs-prompts.js.map +1 -0
- package/dist/cli/prompts.d.ts +6 -0
- package/dist/cli/prompts.d.ts.map +1 -0
- package/dist/cli/prompts.js +376 -0
- package/dist/cli/prompts.js.map +1 -0
- package/dist/core/agent-manager.d.ts +89 -0
- package/dist/core/agent-manager.d.ts.map +1 -0
- package/dist/core/agent-manager.js +546 -0
- package/dist/core/agent-manager.js.map +1 -0
- package/dist/core/auto-fixer.d.ts +14 -0
- package/dist/core/auto-fixer.d.ts.map +1 -0
- package/dist/core/auto-fixer.js +207 -0
- package/dist/core/auto-fixer.js.map +1 -0
- package/dist/core/changelog-generator.d.ts +44 -0
- package/dist/core/changelog-generator.d.ts.map +1 -0
- package/dist/core/changelog-generator.js +222 -0
- package/dist/core/changelog-generator.js.map +1 -0
- package/dist/core/cli-bridge.d.ts +113 -0
- package/dist/core/cli-bridge.d.ts.map +1 -0
- package/dist/core/cli-bridge.js +1094 -0
- package/dist/core/cli-bridge.js.map +1 -0
- package/dist/core/config-manager.d.ts +65 -0
- package/dist/core/config-manager.d.ts.map +1 -0
- package/dist/core/config-manager.js +266 -0
- package/dist/core/config-manager.js.map +1 -0
- package/dist/core/coverage-checker.d.ts +14 -0
- package/dist/core/coverage-checker.d.ts.map +1 -0
- package/dist/core/coverage-checker.js +176 -0
- package/dist/core/coverage-checker.js.map +1 -0
- package/dist/core/custom-templates.d.ts +27 -0
- package/dist/core/custom-templates.d.ts.map +1 -0
- package/dist/core/custom-templates.js +122 -0
- package/dist/core/custom-templates.js.map +1 -0
- package/dist/core/dependency-checker.d.ts +21 -0
- package/dist/core/dependency-checker.d.ts.map +1 -0
- package/dist/core/dependency-checker.js +247 -0
- package/dist/core/dependency-checker.js.map +1 -0
- package/dist/core/detector.d.ts +3 -0
- package/dist/core/detector.d.ts.map +1 -0
- package/dist/core/detector.js +1443 -0
- package/dist/core/detector.js.map +1 -0
- package/dist/core/docs-generator.d.ts +9 -0
- package/dist/core/docs-generator.d.ts.map +1 -0
- package/dist/core/docs-generator.js +531 -0
- package/dist/core/docs-generator.js.map +1 -0
- package/dist/core/generator.d.ts +16 -0
- package/dist/core/generator.d.ts.map +1 -0
- package/dist/core/generator.js +561 -0
- package/dist/core/generator.js.map +1 -0
- package/dist/core/gitignore-generator.d.ts +13 -0
- package/dist/core/gitignore-generator.d.ts.map +1 -0
- package/dist/core/gitignore-generator.js +307 -0
- package/dist/core/gitignore-generator.js.map +1 -0
- package/dist/core/health-scorer.d.ts +22 -0
- package/dist/core/health-scorer.d.ts.map +1 -0
- package/dist/core/health-scorer.js +395 -0
- package/dist/core/health-scorer.js.map +1 -0
- package/dist/core/logger.d.ts +116 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +289 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/merger.d.ts +6 -0
- package/dist/core/merger.d.ts.map +1 -0
- package/dist/core/merger.js +131 -0
- package/dist/core/merger.js.map +1 -0
- package/dist/core/migrator.d.ts +19 -0
- package/dist/core/migrator.d.ts.map +1 -0
- package/dist/core/migrator.js +102 -0
- package/dist/core/migrator.js.map +1 -0
- package/dist/core/minimal-scaffolder.d.ts +8 -0
- package/dist/core/minimal-scaffolder.d.ts.map +1 -0
- package/dist/core/minimal-scaffolder.js +51 -0
- package/dist/core/minimal-scaffolder.js.map +1 -0
- package/dist/core/modern-console-new.d.ts +81 -0
- package/dist/core/modern-console-new.d.ts.map +1 -0
- package/dist/core/modern-console-new.js +340 -0
- package/dist/core/modern-console-new.js.map +1 -0
- package/dist/core/modern-console.d.ts +99 -0
- package/dist/core/modern-console.d.ts.map +1 -0
- package/dist/core/modern-console.js +568 -0
- package/dist/core/modern-console.js.map +1 -0
- package/dist/core/openspec-manager.d.ts +133 -0
- package/dist/core/openspec-manager.d.ts.map +1 -0
- package/dist/core/openspec-manager.js +605 -0
- package/dist/core/openspec-manager.js.map +1 -0
- package/dist/core/openspec-migrator.d.ts +27 -0
- package/dist/core/openspec-migrator.d.ts.map +1 -0
- package/dist/core/openspec-migrator.js +255 -0
- package/dist/core/openspec-migrator.js.map +1 -0
- package/dist/core/task-manager.d.ts +65 -0
- package/dist/core/task-manager.d.ts.map +1 -0
- package/dist/core/task-manager.js +318 -0
- package/dist/core/task-manager.js.map +1 -0
- package/dist/core/test-task-manager.d.ts +49 -0
- package/dist/core/test-task-manager.d.ts.map +1 -0
- package/dist/core/test-task-manager.js +121 -0
- package/dist/core/test-task-manager.js.map +1 -0
- package/dist/core/validator.d.ts +21 -0
- package/dist/core/validator.d.ts.map +1 -0
- package/dist/core/validator.js +177 -0
- package/dist/core/validator.js.map +1 -0
- package/dist/core/version-bumper.d.ts +19 -0
- package/dist/core/version-bumper.d.ts.map +1 -0
- package/dist/core/version-bumper.js +180 -0
- package/dist/core/version-bumper.js.map +1 -0
- package/dist/core/watcher.d.ts +9 -0
- package/dist/core/watcher.d.ts.map +1 -0
- package/dist/core/watcher.js +22 -0
- package/dist/core/watcher.js.map +1 -0
- package/dist/core/workflow-generator.d.ts +10 -0
- package/dist/core/workflow-generator.d.ts.map +1 -0
- package/dist/core/workflow-generator.js +279 -0
- package/dist/core/workflow-generator.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +159 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/handlers/archive-task.d.ts +17 -0
- package/dist/mcp/handlers/archive-task.d.ts.map +1 -0
- package/dist/mcp/handlers/archive-task.js +36 -0
- package/dist/mcp/handlers/archive-task.js.map +1 -0
- package/dist/mcp/handlers/create-task.d.ts +17 -0
- package/dist/mcp/handlers/create-task.d.ts.map +1 -0
- package/dist/mcp/handlers/create-task.js +56 -0
- package/dist/mcp/handlers/create-task.js.map +1 -0
- package/dist/mcp/handlers/list-tasks.d.ts +22 -0
- package/dist/mcp/handlers/list-tasks.d.ts.map +1 -0
- package/dist/mcp/handlers/list-tasks.js +42 -0
- package/dist/mcp/handlers/list-tasks.js.map +1 -0
- package/dist/mcp/handlers/show-task.d.ts +25 -0
- package/dist/mcp/handlers/show-task.d.ts.map +1 -0
- package/dist/mcp/handlers/show-task.js +43 -0
- package/dist/mcp/handlers/show-task.js.map +1 -0
- package/dist/mcp/handlers/update-task.d.ts +17 -0
- package/dist/mcp/handlers/update-task.d.ts.map +1 -0
- package/dist/mcp/handlers/update-task.js +35 -0
- package/dist/mcp/handlers/update-task.js.map +1 -0
- package/dist/mcp/handlers/validate-task.d.ts +15 -0
- package/dist/mcp/handlers/validate-task.d.ts.map +1 -0
- package/dist/mcp/handlers/validate-task.js +27 -0
- package/dist/mcp/handlers/validate-task.js.map +1 -0
- package/dist/mcp/rulebook-config.d.ts +22 -0
- package/dist/mcp/rulebook-config.d.ts.map +1 -0
- package/dist/mcp/rulebook-config.js +65 -0
- package/dist/mcp/rulebook-config.js.map +1 -0
- package/dist/mcp/rulebook-server.d.ts +4 -0
- package/dist/mcp/rulebook-server.d.ts.map +1 -0
- package/dist/mcp/rulebook-server.js +246 -0
- package/dist/mcp/rulebook-server.js.map +1 -0
- package/dist/types.d.ts +190 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/file-system.d.ts +9 -0
- package/dist/utils/file-system.d.ts.map +1 -0
- package/dist/utils/file-system.js +51 -0
- package/dist/utils/file-system.js.map +1 -0
- package/dist/utils/git-hooks.d.ts +8 -0
- package/dist/utils/git-hooks.d.ts.map +1 -0
- package/dist/utils/git-hooks.js +440 -0
- package/dist/utils/git-hooks.js.map +1 -0
- package/dist/utils/rulesignore.d.ts +9 -0
- package/dist/utils/rulesignore.d.ts.map +1 -0
- package/dist/utils/rulesignore.js +42 -0
- package/dist/utils/rulesignore.js.map +1 -0
- package/package.json +106 -0
- package/templates/cli/AIDER.md +49 -0
- package/templates/cli/AMAZON_Q.md +25 -0
- package/templates/cli/AUGGIE.md +32 -0
- package/templates/cli/CLAUDE.md +32 -0
- package/templates/cli/CLAUDE_CODE.md +35 -0
- package/templates/cli/CLINE.md +32 -0
- package/templates/cli/CODEBUDDY.md +20 -0
- package/templates/cli/CODEIUM.md +20 -0
- package/templates/cli/CODEX.md +21 -0
- package/templates/cli/CONTINUE.md +34 -0
- package/templates/cli/CURSOR_CLI.md +28 -0
- package/templates/cli/FACTORY.md +18 -0
- package/templates/cli/GEMINI.md +35 -0
- package/templates/cli/KILOCODE.md +18 -0
- package/templates/cli/OPENCODE.md +18 -0
- package/templates/cli/_GENERIC_TEMPLATE.md +29 -0
- package/templates/commands/rulebook-task-apply.md +67 -0
- package/templates/commands/rulebook-task-archive.md +70 -0
- package/templates/commands/rulebook-task-create.md +93 -0
- package/templates/commands/rulebook-task-list.md +42 -0
- package/templates/commands/rulebook-task-show.md +52 -0
- package/templates/commands/rulebook-task-validate.md +53 -0
- package/templates/core/AGENT_AUTOMATION.md +184 -0
- package/templates/core/DAG.md +304 -0
- package/templates/core/DOCUMENTATION_RULES.md +37 -0
- package/templates/core/QUALITY_ENFORCEMENT.md +68 -0
- package/templates/core/RULEBOOK.md +1874 -0
- package/templates/frameworks/ANGULAR.md +36 -0
- package/templates/frameworks/DJANGO.md +83 -0
- package/templates/frameworks/ELECTRON.md +147 -0
- package/templates/frameworks/FLASK.md +38 -0
- package/templates/frameworks/FLUTTER.md +55 -0
- package/templates/frameworks/JQUERY.md +32 -0
- package/templates/frameworks/LARAVEL.md +38 -0
- package/templates/frameworks/NESTJS.md +43 -0
- package/templates/frameworks/NEXTJS.md +127 -0
- package/templates/frameworks/NUXT.md +40 -0
- package/templates/frameworks/RAILS.md +66 -0
- package/templates/frameworks/REACT.md +38 -0
- package/templates/frameworks/REACT_NATIVE.md +47 -0
- package/templates/frameworks/SPRING.md +39 -0
- package/templates/frameworks/SYMFONY.md +36 -0
- package/templates/frameworks/VUE.md +36 -0
- package/templates/frameworks/ZEND.md +35 -0
- package/templates/git/CI_CD_PATTERNS.md +661 -0
- package/templates/git/GITHUB_ACTIONS.md +728 -0
- package/templates/git/GITLAB_CI.md +730 -0
- package/templates/git/GIT_WORKFLOW.md +1157 -0
- package/templates/git/SECRETS_MANAGEMENT.md +585 -0
- package/templates/hooks/COMMIT_MSG.md +530 -0
- package/templates/hooks/POST_CHECKOUT.md +546 -0
- package/templates/hooks/PREPARE_COMMIT_MSG.md +619 -0
- package/templates/hooks/PRE_COMMIT.md +414 -0
- package/templates/hooks/PRE_PUSH.md +601 -0
- package/templates/hooks/csharp-pre-commit.sh +23 -0
- package/templates/hooks/csharp-pre-push.sh +23 -0
- package/templates/hooks/dart-pre-commit.sh +30 -0
- package/templates/hooks/dart-pre-push.sh +25 -0
- package/templates/hooks/elixir-pre-commit.sh +32 -0
- package/templates/hooks/elixir-pre-push.sh +31 -0
- package/templates/hooks/erlang-pre-commit.sh +30 -0
- package/templates/hooks/erlang-pre-push.sh +37 -0
- package/templates/hooks/go-pre-commit.sh +40 -0
- package/templates/hooks/go-pre-push.sh +31 -0
- package/templates/hooks/haskell-pre-commit.sh +41 -0
- package/templates/hooks/haskell-pre-push.sh +37 -0
- package/templates/hooks/java-pre-commit.sh +34 -0
- package/templates/hooks/java-pre-push.sh +24 -0
- package/templates/hooks/kotlin-pre-commit.sh +32 -0
- package/templates/hooks/kotlin-pre-push.sh +16 -0
- package/templates/hooks/php-pre-commit.sh +36 -0
- package/templates/hooks/php-pre-push.sh +26 -0
- package/templates/hooks/python-pre-commit.sh +51 -0
- package/templates/hooks/python-pre-push.sh +25 -0
- package/templates/hooks/ruby-pre-commit.sh +33 -0
- package/templates/hooks/ruby-pre-push.sh +32 -0
- package/templates/hooks/rust-pre-commit.sh +30 -0
- package/templates/hooks/rust-pre-push.sh +30 -0
- package/templates/hooks/scala-pre-commit.sh +32 -0
- package/templates/hooks/scala-pre-push.sh +24 -0
- package/templates/hooks/swift-pre-commit.sh +25 -0
- package/templates/hooks/swift-pre-push.sh +23 -0
- package/templates/hooks/typescript-pre-commit.sh +37 -0
- package/templates/hooks/typescript-pre-push.sh +36 -0
- package/templates/ides/COPILOT.md +37 -0
- package/templates/ides/CURSOR.md +43 -0
- package/templates/ides/JETBRAINS_AI.md +35 -0
- package/templates/ides/REPLIT.md +36 -0
- package/templates/ides/TABNINE.md +29 -0
- package/templates/ides/VSCODE.md +40 -0
- package/templates/ides/WINDSURF.md +36 -0
- package/templates/ides/ZED.md +32 -0
- package/templates/languages/ADA.md +58 -0
- package/templates/languages/C.md +333 -0
- package/templates/languages/CPP.md +743 -0
- package/templates/languages/CSHARP.md +417 -0
- package/templates/languages/DART.md +332 -0
- package/templates/languages/ELIXIR.md +454 -0
- package/templates/languages/ERLANG.md +361 -0
- package/templates/languages/GO.md +645 -0
- package/templates/languages/HASKELL.md +177 -0
- package/templates/languages/JAVA.md +607 -0
- package/templates/languages/JAVASCRIPT.md +631 -0
- package/templates/languages/JULIA.md +97 -0
- package/templates/languages/KOTLIN.md +511 -0
- package/templates/languages/LISP.md +100 -0
- package/templates/languages/LUA.md +74 -0
- package/templates/languages/OBJECTIVEC.md +90 -0
- package/templates/languages/PHP.md +416 -0
- package/templates/languages/PYTHON.md +682 -0
- package/templates/languages/R.md +350 -0
- package/templates/languages/RUBY.md +421 -0
- package/templates/languages/RUST.md +477 -0
- package/templates/languages/SAS.md +73 -0
- package/templates/languages/SCALA.md +348 -0
- package/templates/languages/SOLIDITY.md +580 -0
- package/templates/languages/SQL.md +137 -0
- package/templates/languages/SWIFT.md +466 -0
- package/templates/languages/TYPESCRIPT.md +591 -0
- package/templates/languages/ZIG.md +265 -0
- package/templates/modules/ATLASSIAN.md +255 -0
- package/templates/modules/CONTEXT7.md +54 -0
- package/templates/modules/FIGMA.md +267 -0
- package/templates/modules/GITHUB_MCP.md +64 -0
- package/templates/modules/GRAFANA.md +328 -0
- package/templates/modules/NOTION.md +247 -0
- package/templates/modules/PLAYWRIGHT.md +90 -0
- package/templates/modules/RULEBOOK_MCP.md +156 -0
- package/templates/modules/SERENA.md +337 -0
- package/templates/modules/SUPABASE.md +223 -0
- package/templates/modules/SYNAP.md +69 -0
- package/templates/modules/VECTORIZER.md +63 -0
- package/templates/services/AZURE_BLOB.md +184 -0
- package/templates/services/CASSANDRA.md +239 -0
- package/templates/services/DYNAMODB.md +308 -0
- package/templates/services/ELASTICSEARCH.md +347 -0
- package/templates/services/GCS.md +178 -0
- package/templates/services/INFLUXDB.md +265 -0
- package/templates/services/KAFKA.md +341 -0
- package/templates/services/MARIADB.md +183 -0
- package/templates/services/MEMCACHED.md +242 -0
- package/templates/services/MINIO.md +201 -0
- package/templates/services/MONGODB.md +268 -0
- package/templates/services/MYSQL.md +358 -0
- package/templates/services/NEO4J.md +247 -0
- package/templates/services/ORACLE.md +290 -0
- package/templates/services/POSTGRESQL.md +326 -0
- package/templates/services/RABBITMQ.md +286 -0
- package/templates/services/REDIS.md +292 -0
- package/templates/services/S3.md +298 -0
- package/templates/services/SQLITE.md +294 -0
- package/templates/services/SQLSERVER.md +294 -0
- package/templates/workflows/codespell.yml +31 -0
- package/templates/workflows/cpp-lint.yml +47 -0
- package/templates/workflows/cpp-publish.yml +119 -0
- package/templates/workflows/cpp-test.yml +77 -0
- package/templates/workflows/dotnet-lint.yml +29 -0
- package/templates/workflows/dotnet-publish.yml +40 -0
- package/templates/workflows/dotnet-test.yml +41 -0
- package/templates/workflows/elixir-lint.yml +45 -0
- package/templates/workflows/elixir-publish.yml +49 -0
- package/templates/workflows/elixir-test.yml +54 -0
- package/templates/workflows/erlang-lint.yml +47 -0
- package/templates/workflows/erlang-test.yml +62 -0
- package/templates/workflows/go-lint.yml +39 -0
- package/templates/workflows/go-publish.yml +95 -0
- package/templates/workflows/go-test.yml +59 -0
- package/templates/workflows/java-lint.yml +60 -0
- package/templates/workflows/java-publish.yml +120 -0
- package/templates/workflows/java-test.yml +85 -0
- package/templates/workflows/kotlin-lint.yml +34 -0
- package/templates/workflows/kotlin-publish.yml +56 -0
- package/templates/workflows/kotlin-test.yml +48 -0
- package/templates/workflows/php-lint.yml +39 -0
- package/templates/workflows/php-publish.yml +50 -0
- package/templates/workflows/php-test.yml +54 -0
- package/templates/workflows/python-lint.yml +47 -0
- package/templates/workflows/python-publish.yml +91 -0
- package/templates/workflows/python-test.yml +59 -0
- package/templates/workflows/rust-lint.yml +54 -0
- package/templates/workflows/rust-publish.yml +66 -0
- package/templates/workflows/rust-test.yml +75 -0
- package/templates/workflows/solidity-lint.yml +41 -0
- package/templates/workflows/solidity-test.yml +47 -0
- package/templates/workflows/swift-lint.yml +32 -0
- package/templates/workflows/swift-publish.yml +58 -0
- package/templates/workflows/swift-test.yml +44 -0
- package/templates/workflows/typescript-lint.yml +61 -0
- package/templates/workflows/typescript-publish.yml +60 -0
- package/templates/workflows/typescript-test.yml +73 -0
- package/templates/workflows/zig-lint.yml +27 -0
- package/templates/workflows/zig-test.yml +40 -0
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
<!-- SOLIDITY:START -->
|
|
2
|
+
# Solidity Project Rules
|
|
3
|
+
|
|
4
|
+
## Agent Automation Commands
|
|
5
|
+
|
|
6
|
+
**CRITICAL**: Execute these commands after EVERY implementation (see AGENT_AUTOMATION module for full workflow).
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Complete quality check sequence (Hardhat):
|
|
10
|
+
npx hardhat compile # Compilation check
|
|
11
|
+
npx hardhat test # All tests (100% pass)
|
|
12
|
+
npx hardhat coverage # Coverage check
|
|
13
|
+
npx slither . # Security analysis
|
|
14
|
+
|
|
15
|
+
# Or with Foundry:
|
|
16
|
+
forge build # Compilation
|
|
17
|
+
forge test # All tests
|
|
18
|
+
forge coverage # Coverage
|
|
19
|
+
slither . # Security scan
|
|
20
|
+
|
|
21
|
+
# Gas optimization check:
|
|
22
|
+
npx hardhat test --gas
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Solidity Configuration
|
|
26
|
+
|
|
27
|
+
**CRITICAL**: Use Solidity 0.8.20+ with strict compiler settings and comprehensive testing.
|
|
28
|
+
|
|
29
|
+
- **Version**: Solidity 0.8.20+
|
|
30
|
+
- **Recommended**: Solidity 0.8.26+
|
|
31
|
+
- **Framework**: Hardhat or Foundry
|
|
32
|
+
- **Testing**: Hardhat tests or Foundry tests
|
|
33
|
+
- **Linter**: Solhint
|
|
34
|
+
- **Formatter**: Prettier with prettier-plugin-solidity
|
|
35
|
+
- **Security**: Slither, Mythril for static analysis
|
|
36
|
+
|
|
37
|
+
### hardhat.config.js Requirements
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
require("@nomicfoundation/hardhat-toolbox");
|
|
41
|
+
require("hardhat-gas-reporter");
|
|
42
|
+
require("solidity-coverage");
|
|
43
|
+
|
|
44
|
+
module.exports = {
|
|
45
|
+
solidity: {
|
|
46
|
+
version: "0.8.26",
|
|
47
|
+
settings: {
|
|
48
|
+
optimizer: {
|
|
49
|
+
enabled: true,
|
|
50
|
+
runs: 200
|
|
51
|
+
},
|
|
52
|
+
viaIR: true,
|
|
53
|
+
outputSelection: {
|
|
54
|
+
"*": {
|
|
55
|
+
"*": ["storageLayout"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
networks: {
|
|
61
|
+
hardhat: {
|
|
62
|
+
chainId: 31337
|
|
63
|
+
},
|
|
64
|
+
localhost: {
|
|
65
|
+
url: "http://127.0.0.1:8545"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
gasReporter: {
|
|
69
|
+
enabled: true,
|
|
70
|
+
currency: "USD",
|
|
71
|
+
outputFile: "gas-report.txt"
|
|
72
|
+
},
|
|
73
|
+
paths: {
|
|
74
|
+
sources: "./contracts",
|
|
75
|
+
tests: "./test",
|
|
76
|
+
cache: "./cache",
|
|
77
|
+
artifacts: "./artifacts"
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### foundry.toml Requirements (Alternative)
|
|
83
|
+
|
|
84
|
+
```toml
|
|
85
|
+
[profile.default]
|
|
86
|
+
src = "src"
|
|
87
|
+
out = "out"
|
|
88
|
+
libs = ["lib"]
|
|
89
|
+
solc = "0.8.26"
|
|
90
|
+
optimizer = true
|
|
91
|
+
optimizer_runs = 200
|
|
92
|
+
via_ir = true
|
|
93
|
+
verbosity = 3
|
|
94
|
+
|
|
95
|
+
[profile.ci]
|
|
96
|
+
fuzz = { runs = 10000 }
|
|
97
|
+
invariant = { runs = 1000 }
|
|
98
|
+
|
|
99
|
+
[fmt]
|
|
100
|
+
line_length = 100
|
|
101
|
+
tab_width = 4
|
|
102
|
+
bracket_spacing = true
|
|
103
|
+
int_types = "long"
|
|
104
|
+
quote_style = "double"
|
|
105
|
+
number_underscore = "thousands"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Code Quality Standards
|
|
109
|
+
|
|
110
|
+
### Mandatory Quality Checks
|
|
111
|
+
|
|
112
|
+
**CRITICAL**: After implementing ANY feature, you MUST run these commands in order.
|
|
113
|
+
|
|
114
|
+
**IMPORTANT**: These commands MUST match your GitHub Actions workflows to prevent CI/CD failures!
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Pre-Commit Checklist - Hardhat (MUST match .github/workflows/*.yml)
|
|
118
|
+
|
|
119
|
+
# 1. Format check (matches workflow)
|
|
120
|
+
npx prettier --check 'contracts/**/*.sol' 'test/**/*.js'
|
|
121
|
+
|
|
122
|
+
# 2. Lint (MUST pass with no warnings - matches workflow)
|
|
123
|
+
npx solhint 'contracts/**/*.sol'
|
|
124
|
+
|
|
125
|
+
# 3. Compile (matches workflow)
|
|
126
|
+
npx hardhat compile
|
|
127
|
+
|
|
128
|
+
# 4. Run all tests (MUST pass 100% - matches workflow)
|
|
129
|
+
npx hardhat test
|
|
130
|
+
|
|
131
|
+
# 5. Gas report (matches workflow)
|
|
132
|
+
REPORT_GAS=true npx hardhat test
|
|
133
|
+
|
|
134
|
+
# 6. Coverage (MUST meet threshold - matches workflow)
|
|
135
|
+
npx hardhat coverage
|
|
136
|
+
|
|
137
|
+
# 7. Security analysis (matches workflow)
|
|
138
|
+
slither .
|
|
139
|
+
# or: mythril analyze contracts/MyContract.sol
|
|
140
|
+
|
|
141
|
+
# Pre-Commit Checklist - Foundry (MUST match .github/workflows/*.yml)
|
|
142
|
+
|
|
143
|
+
# 1. Format check (matches workflow)
|
|
144
|
+
forge fmt --check
|
|
145
|
+
|
|
146
|
+
# 2. Build (matches workflow)
|
|
147
|
+
forge build
|
|
148
|
+
|
|
149
|
+
# 3. Run all tests (MUST pass 100% - matches workflow)
|
|
150
|
+
forge test -vvv
|
|
151
|
+
|
|
152
|
+
# 4. Coverage (matches workflow)
|
|
153
|
+
forge coverage
|
|
154
|
+
|
|
155
|
+
# 5. Gas snapshot (matches workflow)
|
|
156
|
+
forge snapshot --check
|
|
157
|
+
|
|
158
|
+
# 6. Security analysis (matches workflow)
|
|
159
|
+
slither .
|
|
160
|
+
|
|
161
|
+
# If ANY fails: ❌ DO NOT COMMIT - Fix first!
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**If ANY of these fail, you MUST fix the issues before committing.**
|
|
165
|
+
|
|
166
|
+
**Why This Matters:**
|
|
167
|
+
- Running different commands locally than in CI causes deployment failures
|
|
168
|
+
- Smart contract bugs can lead to financial losses
|
|
169
|
+
- Example: Using `prettier --write` locally but `prettier --check` in CI = failure
|
|
170
|
+
- Example: Skipping security analysis locally = vulnerabilities deployed to mainnet
|
|
171
|
+
- Example: Missing gas optimization = expensive contract operations
|
|
172
|
+
|
|
173
|
+
### Security Best Practices
|
|
174
|
+
|
|
175
|
+
**CRITICAL**: Smart contracts handle real value - security is paramount!
|
|
176
|
+
|
|
177
|
+
```solidity
|
|
178
|
+
// ✅ GOOD: Secure patterns
|
|
179
|
+
pragma solidity 0.8.26;
|
|
180
|
+
|
|
181
|
+
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
|
|
182
|
+
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
183
|
+
|
|
184
|
+
contract SecureVault is ReentrancyGuard, Ownable {
|
|
185
|
+
mapping(address => uint256) private balances;
|
|
186
|
+
|
|
187
|
+
event Deposit(address indexed user, uint256 amount);
|
|
188
|
+
event Withdrawal(address indexed user, uint256 amount);
|
|
189
|
+
|
|
190
|
+
// Checks-Effects-Interactions pattern
|
|
191
|
+
function withdraw(uint256 amount) external nonReentrant {
|
|
192
|
+
// Checks
|
|
193
|
+
require(amount > 0, "Amount must be positive");
|
|
194
|
+
require(balances[msg.sender] >= amount, "Insufficient balance");
|
|
195
|
+
|
|
196
|
+
// Effects
|
|
197
|
+
balances[msg.sender] -= amount;
|
|
198
|
+
emit Withdrawal(msg.sender, amount);
|
|
199
|
+
|
|
200
|
+
// Interactions
|
|
201
|
+
(bool success, ) = msg.sender.call{value: amount}("");
|
|
202
|
+
require(success, "Transfer failed");
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function deposit() external payable {
|
|
206
|
+
require(msg.value > 0, "Must deposit positive amount");
|
|
207
|
+
balances[msg.sender] += msg.value;
|
|
208
|
+
emit Deposit(msg.sender, msg.value);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function getBalance(address user) external view returns (uint256) {
|
|
212
|
+
return balances[user];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ❌ BAD: Vulnerable to reentrancy
|
|
217
|
+
contract InsecureVault {
|
|
218
|
+
mapping(address => uint256) public balances;
|
|
219
|
+
|
|
220
|
+
function withdraw(uint256 amount) external {
|
|
221
|
+
require(balances[msg.sender] >= amount);
|
|
222
|
+
|
|
223
|
+
// DANGER: External call before state update!
|
|
224
|
+
(bool success, ) = msg.sender.call{value: amount}("");
|
|
225
|
+
require(success);
|
|
226
|
+
|
|
227
|
+
balances[msg.sender] -= amount; // TOO LATE - already reentered!
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Testing
|
|
233
|
+
|
|
234
|
+
- **Framework**: Hardhat (Mocha/Chai) or Foundry (Forge)
|
|
235
|
+
- **Location**: `/test` directory
|
|
236
|
+
- **Coverage**: Must meet threshold (90%+)
|
|
237
|
+
- **Invariant Testing**: Use property-based testing
|
|
238
|
+
- **Fork Testing**: Test against mainnet forks
|
|
239
|
+
|
|
240
|
+
Example Hardhat test:
|
|
241
|
+
```javascript
|
|
242
|
+
const { expect } = require("chai");
|
|
243
|
+
const { ethers } = require("hardhat");
|
|
244
|
+
|
|
245
|
+
describe("SecureVault", function () {
|
|
246
|
+
let vault;
|
|
247
|
+
let owner;
|
|
248
|
+
let addr1;
|
|
249
|
+
let addr2;
|
|
250
|
+
|
|
251
|
+
beforeEach(async function () {
|
|
252
|
+
[owner, addr1, addr2] = await ethers.getSigners();
|
|
253
|
+
|
|
254
|
+
const Vault = await ethers.getContractFactory("SecureVault");
|
|
255
|
+
vault = await Vault.deploy();
|
|
256
|
+
await vault.deployed();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
describe("Deployment", function () {
|
|
260
|
+
it("Should set the right owner", async function () {
|
|
261
|
+
expect(await vault.owner()).to.equal(owner.address);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
describe("Deposits", function () {
|
|
266
|
+
it("Should accept deposits", async function () {
|
|
267
|
+
const depositAmount = ethers.utils.parseEther("1.0");
|
|
268
|
+
|
|
269
|
+
await expect(vault.connect(addr1).deposit({ value: depositAmount }))
|
|
270
|
+
.to.emit(vault, "Deposit")
|
|
271
|
+
.withArgs(addr1.address, depositAmount);
|
|
272
|
+
|
|
273
|
+
expect(await vault.getBalance(addr1.address)).to.equal(depositAmount);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it("Should reject zero deposits", async function () {
|
|
277
|
+
await expect(
|
|
278
|
+
vault.connect(addr1).deposit({ value: 0 })
|
|
279
|
+
).to.be.revertedWith("Must deposit positive amount");
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
describe("Withdrawals", function () {
|
|
284
|
+
beforeEach(async function () {
|
|
285
|
+
await vault.connect(addr1).deposit({ value: ethers.utils.parseEther("2.0") });
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("Should allow withdrawals", async function () {
|
|
289
|
+
const withdrawAmount = ethers.utils.parseEther("1.0");
|
|
290
|
+
|
|
291
|
+
await expect(vault.connect(addr1).withdraw(withdrawAmount))
|
|
292
|
+
.to.emit(vault, "Withdrawal")
|
|
293
|
+
.withArgs(addr1.address, withdrawAmount);
|
|
294
|
+
|
|
295
|
+
expect(await vault.getBalance(addr1.address))
|
|
296
|
+
.to.equal(ethers.utils.parseEther("1.0"));
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it("Should prevent withdrawal of more than balance", async function () {
|
|
300
|
+
await expect(
|
|
301
|
+
vault.connect(addr1).withdraw(ethers.utils.parseEther("10.0"))
|
|
302
|
+
).to.be.revertedWith("Insufficient balance");
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Example Foundry test:
|
|
309
|
+
```solidity
|
|
310
|
+
// SPDX-License-Identifier: MIT
|
|
311
|
+
pragma solidity 0.8.26;
|
|
312
|
+
|
|
313
|
+
import "forge-std/Test.sol";
|
|
314
|
+
import "../src/SecureVault.sol";
|
|
315
|
+
|
|
316
|
+
contract SecureVaultTest is Test {
|
|
317
|
+
SecureVault public vault;
|
|
318
|
+
address public alice;
|
|
319
|
+
address public bob;
|
|
320
|
+
|
|
321
|
+
function setUp() public {
|
|
322
|
+
vault = new SecureVault();
|
|
323
|
+
alice = makeAddr("alice");
|
|
324
|
+
bob = makeAddr("bob");
|
|
325
|
+
|
|
326
|
+
vm.deal(alice, 100 ether);
|
|
327
|
+
vm.deal(bob, 100 ether);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function testDeposit() public {
|
|
331
|
+
vm.startPrank(alice);
|
|
332
|
+
vault.deposit{value: 1 ether}();
|
|
333
|
+
|
|
334
|
+
assertEq(vault.getBalance(alice), 1 ether);
|
|
335
|
+
vm.stopPrank();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function testWithdraw() public {
|
|
339
|
+
vm.startPrank(alice);
|
|
340
|
+
vault.deposit{value: 2 ether}();
|
|
341
|
+
|
|
342
|
+
uint256 balanceBefore = alice.balance;
|
|
343
|
+
vault.withdraw(1 ether);
|
|
344
|
+
|
|
345
|
+
assertEq(vault.getBalance(alice), 1 ether);
|
|
346
|
+
assertEq(alice.balance, balanceBefore + 1 ether);
|
|
347
|
+
vm.stopPrank();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function testCannotWithdrawMoreThanBalance() public {
|
|
351
|
+
vm.startPrank(alice);
|
|
352
|
+
vault.deposit{value: 1 ether}();
|
|
353
|
+
|
|
354
|
+
vm.expectRevert("Insufficient balance");
|
|
355
|
+
vault.withdraw(2 ether);
|
|
356
|
+
vm.stopPrank();
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Fuzz testing
|
|
360
|
+
function testFuzzDeposit(uint256 amount) public {
|
|
361
|
+
vm.assume(amount > 0 && amount < 100 ether);
|
|
362
|
+
|
|
363
|
+
vm.deal(alice, amount);
|
|
364
|
+
vm.prank(alice);
|
|
365
|
+
vault.deposit{value: amount}();
|
|
366
|
+
|
|
367
|
+
assertEq(vault.getBalance(alice), amount);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Invariant testing
|
|
371
|
+
function invariant_totalBalanceMatchesContract() public {
|
|
372
|
+
assertEq(address(vault).balance, vault.totalDeposits());
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Security Auditing
|
|
378
|
+
|
|
379
|
+
**CRITICAL**: Run multiple security tools before deployment!
|
|
380
|
+
|
|
381
|
+
### Static Analysis Tools
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
# Slither (comprehensive)
|
|
385
|
+
slither . --exclude-optimization --exclude-informational
|
|
386
|
+
|
|
387
|
+
# Mythril (symbolic execution)
|
|
388
|
+
myth analyze contracts/MyContract.sol
|
|
389
|
+
|
|
390
|
+
# Manticore (symbolic execution)
|
|
391
|
+
manticore contracts/MyContract.sol
|
|
392
|
+
|
|
393
|
+
# Echidna (fuzzing)
|
|
394
|
+
echidna-test contracts/MyContract.sol --contract MyContract
|
|
395
|
+
|
|
396
|
+
# Solhint (linting with security rules)
|
|
397
|
+
solhint 'contracts/**/*.sol'
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Manual Review Checklist
|
|
401
|
+
|
|
402
|
+
- [ ] Reentrancy protection (ReentrancyGuard or Checks-Effects-Interactions)
|
|
403
|
+
- [ ] Integer overflow protection (use Solidity 0.8+)
|
|
404
|
+
- [ ] Access control (Ownable, AccessControl)
|
|
405
|
+
- [ ] Input validation (require statements)
|
|
406
|
+
- [ ] Gas optimization reviewed
|
|
407
|
+
- [ ] Event emissions for all state changes
|
|
408
|
+
- [ ] No use of tx.origin (use msg.sender)
|
|
409
|
+
- [ ] No use of block.timestamp for critical logic
|
|
410
|
+
- [ ] No delegatecall to untrusted contracts
|
|
411
|
+
- [ ] No selfdestruct in upgradeable contracts
|
|
412
|
+
|
|
413
|
+
## Gas Optimization
|
|
414
|
+
|
|
415
|
+
```solidity
|
|
416
|
+
// ✅ GOOD: Gas-optimized patterns
|
|
417
|
+
contract Optimized {
|
|
418
|
+
// Use immutable for constants set in constructor
|
|
419
|
+
address public immutable owner;
|
|
420
|
+
|
|
421
|
+
// Pack struct variables
|
|
422
|
+
struct User {
|
|
423
|
+
uint128 balance; // 16 bytes
|
|
424
|
+
uint64 lastUpdated; // 8 bytes
|
|
425
|
+
uint64 nonce; // 8 bytes
|
|
426
|
+
// Total: 32 bytes (1 storage slot)
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Cache storage variables
|
|
430
|
+
function processUsers(uint256[] calldata ids) external {
|
|
431
|
+
User storage user; // Declare once
|
|
432
|
+
for (uint256 i = 0; i < ids.length; i++) {
|
|
433
|
+
user = users[ids[i]]; // Cache
|
|
434
|
+
user.balance += 100;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Use calldata for read-only arrays
|
|
439
|
+
function sum(uint256[] calldata numbers) external pure returns (uint256) {
|
|
440
|
+
uint256 total = 0;
|
|
441
|
+
for (uint256 i = 0; i < numbers.length; i++) {
|
|
442
|
+
total += numbers[i];
|
|
443
|
+
}
|
|
444
|
+
return total;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// ❌ BAD: Gas-inefficient
|
|
449
|
+
contract Inefficient {
|
|
450
|
+
address public owner; // Should be immutable!
|
|
451
|
+
|
|
452
|
+
struct User {
|
|
453
|
+
uint256 balance; // 32 bytes
|
|
454
|
+
uint256 lastUpdated; // 32 bytes
|
|
455
|
+
uint256 nonce; // 32 bytes
|
|
456
|
+
// Total: 96 bytes (3 storage slots!)
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Repeated storage access
|
|
460
|
+
function processUsers(uint256[] memory ids) external {
|
|
461
|
+
for (uint256 i = 0; i < ids.length; i++) {
|
|
462
|
+
users[ids[i]].balance += 100; // SLOAD every iteration!
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Best Practices
|
|
469
|
+
|
|
470
|
+
### DO's ✅
|
|
471
|
+
|
|
472
|
+
- **USE** OpenZeppelin contracts for standard functionality
|
|
473
|
+
- **USE** ReentrancyGuard for functions with external calls
|
|
474
|
+
- **USE** SafeMath patterns or Solidity 0.8+ (automatic overflow checks)
|
|
475
|
+
- **EMIT** events for all state changes
|
|
476
|
+
- **VALIDATE** all inputs with require statements
|
|
477
|
+
- **TEST** with mainnet forks for realistic scenarios
|
|
478
|
+
- **OPTIMIZE** gas usage
|
|
479
|
+
- **DOCUMENT** all public functions with NatSpec
|
|
480
|
+
|
|
481
|
+
### DON'Ts ❌
|
|
482
|
+
|
|
483
|
+
- **NEVER** use tx.origin for authorization
|
|
484
|
+
- **NEVER** use block.timestamp for critical randomness
|
|
485
|
+
- **NEVER** make external calls before state updates (reentrancy!)
|
|
486
|
+
- **NEVER** use delegatecall without extreme caution
|
|
487
|
+
- **NEVER** deploy without security audit
|
|
488
|
+
- **NEVER** use floating pragma (`pragma solidity ^0.8.0`)
|
|
489
|
+
- **NEVER** skip test coverage
|
|
490
|
+
- **NEVER** ignore Slither warnings
|
|
491
|
+
|
|
492
|
+
## NatSpec Documentation
|
|
493
|
+
|
|
494
|
+
```solidity
|
|
495
|
+
/// @title Secure Vault Contract
|
|
496
|
+
/// @author Your Name
|
|
497
|
+
/// @notice This contract allows users to deposit and withdraw ETH
|
|
498
|
+
/// @dev Uses ReentrancyGuard to prevent reentrancy attacks
|
|
499
|
+
contract SecureVault is ReentrancyGuard {
|
|
500
|
+
|
|
501
|
+
/// @notice Deposits ETH into the vault
|
|
502
|
+
/// @dev Emits Deposit event on success
|
|
503
|
+
/// @return success Boolean indicating if deposit was successful
|
|
504
|
+
function deposit() external payable returns (bool success) {
|
|
505
|
+
require(msg.value > 0, "Must deposit positive amount");
|
|
506
|
+
balances[msg.sender] += msg.value;
|
|
507
|
+
emit Deposit(msg.sender, msg.value);
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/// @notice Withdraws ETH from the vault
|
|
512
|
+
/// @dev Uses Checks-Effects-Interactions pattern
|
|
513
|
+
/// @param amount The amount of ETH to withdraw
|
|
514
|
+
/// @custom:security Protected against reentrancy
|
|
515
|
+
function withdraw(uint256 amount) external nonReentrant {
|
|
516
|
+
require(amount > 0, "Amount must be positive");
|
|
517
|
+
require(balances[msg.sender] >= amount, "Insufficient balance");
|
|
518
|
+
|
|
519
|
+
balances[msg.sender] -= amount;
|
|
520
|
+
emit Withdrawal(msg.sender, amount);
|
|
521
|
+
|
|
522
|
+
(bool success, ) = msg.sender.call{value: amount}("");
|
|
523
|
+
require(success, "Transfer failed");
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
## CI/CD Requirements
|
|
529
|
+
|
|
530
|
+
Must include GitHub Actions workflows:
|
|
531
|
+
|
|
532
|
+
1. **Testing** (`solidity-test.yml`):
|
|
533
|
+
- Run Hardhat/Foundry tests
|
|
534
|
+
- Fork testing against mainnet
|
|
535
|
+
- Coverage reporting (90%+ required)
|
|
536
|
+
|
|
537
|
+
2. **Security** (`solidity-security.yml`):
|
|
538
|
+
- Slither static analysis
|
|
539
|
+
- Mythril symbolic execution
|
|
540
|
+
- Gas optimization check
|
|
541
|
+
|
|
542
|
+
3. **Linting** (`solidity-lint.yml`):
|
|
543
|
+
- Solhint checks
|
|
544
|
+
- Prettier formatting
|
|
545
|
+
- Compile verification
|
|
546
|
+
|
|
547
|
+
## Deployment Checklist
|
|
548
|
+
|
|
549
|
+
**CRITICAL**: Before mainnet deployment!
|
|
550
|
+
|
|
551
|
+
- [ ] All tests passing (100%)
|
|
552
|
+
- [ ] Coverage > 90%
|
|
553
|
+
- [ ] Slither audit clean
|
|
554
|
+
- [ ] Mythril audit clean
|
|
555
|
+
- [ ] External security audit completed
|
|
556
|
+
- [ ] Gas optimization reviewed
|
|
557
|
+
- [ ] All functions have NatSpec comments
|
|
558
|
+
- [ ] Deployed to testnet and verified
|
|
559
|
+
- [ ] Contract verified on Etherscan
|
|
560
|
+
- [ ] Multi-sig wallet setup for admin functions
|
|
561
|
+
- [ ] Emergency pause mechanism tested
|
|
562
|
+
- [ ] Upgrade path documented (if upgradeable)
|
|
563
|
+
|
|
564
|
+
## Publishing to NPM (Hardhat)
|
|
565
|
+
|
|
566
|
+
```bash
|
|
567
|
+
# 1. Run all quality checks
|
|
568
|
+
npm run lint
|
|
569
|
+
npm test
|
|
570
|
+
npx hardhat coverage
|
|
571
|
+
|
|
572
|
+
# 2. Update version
|
|
573
|
+
npm version minor
|
|
574
|
+
|
|
575
|
+
# 3. Publish
|
|
576
|
+
npm publish
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
<!-- SOLIDITY:END -->
|
|
580
|
+
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<!-- SQL:START -->
|
|
2
|
+
# SQL Project Rules
|
|
3
|
+
|
|
4
|
+
## Agent Automation Commands
|
|
5
|
+
|
|
6
|
+
**CRITICAL**: Execute these commands after EVERY implementation (see AGENT_AUTOMATION module for full workflow).
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Complete quality check sequence:
|
|
10
|
+
sqlfluff lint migrations/ # SQL linting
|
|
11
|
+
sqlfluff format --check migrations/ # Format check
|
|
12
|
+
# Run migration tests (project-specific)
|
|
13
|
+
# Run pgTAP tests if configured
|
|
14
|
+
|
|
15
|
+
# Migration validation:
|
|
16
|
+
flyway validate # Flyway migrations
|
|
17
|
+
# OR: liquibase validate # Liquibase migrations
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## SQL Configuration
|
|
21
|
+
|
|
22
|
+
**CRITICAL**: Use modern SQL standards with linting and testing.
|
|
23
|
+
|
|
24
|
+
- **Standard**: SQL:2016 or later
|
|
25
|
+
- **Linter**: SQLFluff or SQL Lint
|
|
26
|
+
- **Testing**: pgTAP (PostgreSQL), utPLSQL (Oracle), tSQLt (SQL Server)
|
|
27
|
+
- **Version Control**: All DDL and migrations tracked
|
|
28
|
+
|
|
29
|
+
## Code Quality Standards
|
|
30
|
+
|
|
31
|
+
### Mandatory Quality Checks
|
|
32
|
+
|
|
33
|
+
**CRITICAL**: After implementing ANY change, you MUST run these commands in order.
|
|
34
|
+
|
|
35
|
+
**IMPORTANT**: These commands MUST match your GitHub Actions workflows to prevent CI/CD failures!
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Pre-Commit Checklist (MUST match .github/workflows/*.yml)
|
|
39
|
+
|
|
40
|
+
# 1. Format check (matches workflow)
|
|
41
|
+
sqlfluff format --check .
|
|
42
|
+
|
|
43
|
+
# 2. Lint (MUST pass with no warnings - matches workflow)
|
|
44
|
+
sqlfluff lint .
|
|
45
|
+
|
|
46
|
+
# 3. Run all tests (MUST pass 100% - matches workflow)
|
|
47
|
+
# PostgreSQL:
|
|
48
|
+
psql -d testdb -f tests/test_suite.sql
|
|
49
|
+
|
|
50
|
+
# SQL Server:
|
|
51
|
+
sqlcmd -S localhost -d testdb -i tests/test_suite.sql
|
|
52
|
+
|
|
53
|
+
# 4. Validate migrations (matches workflow)
|
|
54
|
+
# Check migration order and dependencies
|
|
55
|
+
flyway validate
|
|
56
|
+
# or: liquibase validate
|
|
57
|
+
|
|
58
|
+
# If ANY fails: ❌ DO NOT COMMIT - Fix first!
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Why This Matters:**
|
|
62
|
+
- Running different commands locally than in CI causes database deployment failures
|
|
63
|
+
- Example: Using `sqlfluff fix` locally but `sqlfluff format --check` in CI = failure
|
|
64
|
+
- Example: Missing migration validation = broken database deployments
|
|
65
|
+
|
|
66
|
+
### Style Guide
|
|
67
|
+
|
|
68
|
+
Example `.sqlfluff` configuration:
|
|
69
|
+
```ini
|
|
70
|
+
[sqlfluff]
|
|
71
|
+
dialect = postgres
|
|
72
|
+
templater = jinja
|
|
73
|
+
sql_file_exts = .sql,.sql.j2
|
|
74
|
+
max_line_length = 100
|
|
75
|
+
indent_unit = space
|
|
76
|
+
indented_joins = True
|
|
77
|
+
indented_using_on = True
|
|
78
|
+
|
|
79
|
+
[sqlfluff:rules]
|
|
80
|
+
capitalisation.keywords = upper
|
|
81
|
+
capitalisation.identifiers = lower
|
|
82
|
+
capitalisation.functions = upper
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Testing Example (pgTAP)
|
|
86
|
+
|
|
87
|
+
```sql
|
|
88
|
+
BEGIN;
|
|
89
|
+
SELECT plan(3);
|
|
90
|
+
|
|
91
|
+
-- Test table exists
|
|
92
|
+
SELECT has_table('users', 'users table should exist');
|
|
93
|
+
|
|
94
|
+
-- Test function
|
|
95
|
+
SELECT is(
|
|
96
|
+
calculate_total(100, 0.1),
|
|
97
|
+
110.0::numeric,
|
|
98
|
+
'calculate_total should apply 10% markup'
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
-- Test constraint
|
|
102
|
+
SELECT col_is_pk('users', 'id', 'id should be primary key');
|
|
103
|
+
|
|
104
|
+
SELECT * FROM finish();
|
|
105
|
+
ROLLBACK;
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Migration Best Practices
|
|
109
|
+
|
|
110
|
+
```sql
|
|
111
|
+
-- migrations/001_create_users.sql
|
|
112
|
+
-- IDEMPOTENT: Can run multiple times safely
|
|
113
|
+
|
|
114
|
+
-- Create table if not exists
|
|
115
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
116
|
+
id BIGSERIAL PRIMARY KEY,
|
|
117
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
118
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
-- Create index if not exists
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
123
|
+
|
|
124
|
+
-- Add column if not exists (PostgreSQL 9.6+)
|
|
125
|
+
DO $$
|
|
126
|
+
BEGIN
|
|
127
|
+
IF NOT EXISTS (
|
|
128
|
+
SELECT 1 FROM information_schema.columns
|
|
129
|
+
WHERE table_name = 'users' AND column_name = 'updated_at'
|
|
130
|
+
) THEN
|
|
131
|
+
ALTER TABLE users ADD COLUMN updated_at TIMESTAMP WITH TIME ZONE;
|
|
132
|
+
END IF;
|
|
133
|
+
END $$;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
<!-- SQL:END -->
|
|
137
|
+
|