claude-code-superkit 0.0.0-stage → 1.5.3
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 +21 -0
- package/README.md +374 -2
- package/bin/cli.js +153 -0
- package/bin/inject-tokens.js +224 -0
- package/bin/measure-tokens.js +17 -0
- package/bin/superkit-counts-verify.sh +30 -0
- package/lib/codex.js +246 -0
- package/lib/docs-scaffold.js +147 -0
- package/lib/installer.js +499 -0
- package/lib/prompts.js +51 -0
- package/lib/settings-builder.js +51 -0
- package/lib/superpowers.js +99 -0
- package/lib/utils.js +117 -0
- package/lib/validator.js +84 -0
- package/package.json +49 -4
- package/packages/codex/AGENTS.md +396 -0
- package/packages/codex/INSTALL.md +342 -0
- package/packages/codex/config.toml +22 -0
- package/packages/codex/hooks/superkit.mjs +203 -0
- package/packages/codex/hooks.json +30 -0
- package/packages/codex/legacy-baseline.json +88 -0
- package/packages/codex/native-skills.txt +65 -0
- package/packages/codex/rules/default.rules +565 -0
- package/packages/codex/skills/ai-slop-cleaner/SKILL.md +44 -0
- package/packages/codex/skills/api-contract-sync/SKILL.md +96 -0
- package/packages/codex/skills/architect/SKILL.md +49 -0
- package/packages/codex/skills/audit-backend/SKILL.md +80 -0
- package/packages/codex/skills/audit-frontend/SKILL.md +82 -0
- package/packages/codex/skills/audit-infra/SKILL.md +87 -0
- package/packages/codex/skills/audit-orchestrator/SKILL.md +114 -0
- package/packages/codex/skills/behavioral-nudge-engine/SKILL.md +110 -0
- package/packages/codex/skills/benchmark/SKILL.md +49 -0
- package/packages/codex/skills/bot-reviewer/SKILL.md +94 -0
- package/packages/codex/skills/code-reviewer/SKILL.md +67 -0
- package/packages/codex/skills/codebase-onboarding-engineer/SKILL.md +46 -0
- package/packages/codex/skills/comment-rot-analyzer/SKILL.md +75 -0
- package/packages/codex/skills/commit-helper/SKILL.md +101 -0
- package/packages/codex/skills/critic/SKILL.md +56 -0
- package/packages/codex/skills/database-reviewer/SKILL.md +79 -0
- package/packages/codex/skills/debug-observer/SKILL.md +107 -0
- package/packages/codex/skills/dependency-checker/SKILL.md +69 -0
- package/packages/codex/skills/design-system-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/dev-orchestrator/SKILL.md +304 -0
- package/packages/codex/skills/docs-reviewer/SKILL.md +86 -0
- package/packages/codex/skills/drizzle-orm-expert/SKILL.md +246 -0
- package/packages/codex/skills/e2e-test-generator/SKILL.md +95 -0
- package/packages/codex/skills/evaluator/SKILL.md +63 -0
- package/packages/codex/skills/frontend-perf-reviewer/SKILL.md +95 -0
- package/packages/codex/skills/frontend-ui-color-reviewer/SKILL.md +68 -0
- package/packages/codex/skills/frontend-ui-design-critic/SKILL.md +99 -0
- package/packages/codex/skills/frontend-ui-interaction-reviewer/SKILL.md +102 -0
- package/packages/codex/skills/frontend-ui-motion-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/frontend-ui-reviewer/SKILL.md +81 -0
- package/packages/codex/skills/frontend-ui-typography-reviewer/SKILL.md +62 -0
- package/packages/codex/skills/gltf-debugging/SKILL.md +128 -0
- package/packages/codex/skills/go-benchmark/SKILL.md +217 -0
- package/packages/codex/skills/go-concurrency-reviewer/SKILL.md +113 -0
- package/packages/codex/skills/go-error-reviewer/SKILL.md +107 -0
- package/packages/codex/skills/go-grpc-patterns/SKILL.md +285 -0
- package/packages/codex/skills/go-modernizer/SKILL.md +111 -0
- package/packages/codex/skills/go-observability-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/go-performance-reviewer/SKILL.md +112 -0
- package/packages/codex/skills/go-reviewer/SKILL.md +109 -0
- package/packages/codex/skills/go-samber-do/SKILL.md +158 -0
- package/packages/codex/skills/go-samber-lo/SKILL.md +178 -0
- package/packages/codex/skills/go-samber-oops/SKILL.md +174 -0
- package/packages/codex/skills/goal-verifier/SKILL.md +53 -0
- package/packages/codex/skills/health-checker/SKILL.md +109 -0
- package/packages/codex/skills/html-to-3d-texture/SKILL.md +153 -0
- package/packages/codex/skills/impeccable-craft/SKILL.md +101 -0
- package/packages/codex/skills/lint-runner/SKILL.md +85 -0
- package/packages/codex/skills/migrate/SKILL.md +60 -0
- package/packages/codex/skills/migration-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/minimal-change-engineer/SKILL.md +44 -0
- package/packages/codex/skills/new-migration/SKILL.md +59 -0
- package/packages/codex/skills/nextjs-supabase-auth/SKILL.md +227 -0
- package/packages/codex/skills/output-enforcement/SKILL.md +71 -0
- package/packages/codex/skills/plan-checker/SKILL.md +53 -0
- package/packages/codex/skills/postgresql-optimization/SKILL.md +159 -0
- package/packages/codex/skills/pre-deploy-validator/SKILL.md +111 -0
- package/packages/codex/skills/presentation-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/product-3d-lighting/SKILL.md +137 -0
- package/packages/codex/skills/project-architecture/SKILL.md +52 -0
- package/packages/codex/skills/py-reviewer/SKILL.md +100 -0
- package/packages/codex/skills/r3f-scene-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/r3f-scroll-driven-3d/SKILL.md +162 -0
- package/packages/codex/skills/reality-checker/SKILL.md +61 -0
- package/packages/codex/skills/redis-patterns/SKILL.md +260 -0
- package/packages/codex/skills/review-orchestrator/SKILL.md +151 -0
- package/packages/codex/skills/rs-reviewer/SKILL.md +98 -0
- package/packages/codex/skills/ru-text/SKILL.md +132 -0
- package/packages/codex/skills/scaffold-endpoint/SKILL.md +44 -0
- package/packages/codex/skills/security-scanner/SKILL.md +94 -0
- package/packages/codex/skills/silent-failure-hunter/SKILL.md +176 -0
- package/packages/codex/skills/telegram-bot-builder/SKILL.md +120 -0
- package/packages/codex/skills/test-generator/SKILL.md +79 -0
- package/packages/codex/skills/test-runner/SKILL.md +101 -0
- package/packages/codex/skills/threejs-color-management/SKILL.md +97 -0
- package/packages/codex/skills/tree-generator/SKILL.md +63 -0
- package/packages/codex/skills/ts-reviewer/SKILL.md +90 -0
- package/packages/codex/skills/ui-design-reviewer/SKILL.md +89 -0
- package/packages/codex/skills/ui-reviewer/SKILL.md +103 -0
- package/packages/codex/skills/visual-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/writing-agents/SKILL.md +165 -0
- package/packages/codex/skills/writing-commands/SKILL.md +173 -0
- package/packages/core/CLAUDE.md +118 -0
- package/packages/core/INTERNAL-FILES +16 -0
- package/packages/core/agents/ai-slop-cleaner.md +187 -0
- package/packages/core/agents/api-contract-sync.md +127 -0
- package/packages/core/agents/architect.md +205 -0
- package/packages/core/agents/audit-backend.md +137 -0
- package/packages/core/agents/audit-frontend.md +129 -0
- package/packages/core/agents/audit-infra.md +182 -0
- package/packages/core/agents/behavioral-nudge-engine.md +170 -0
- package/packages/core/agents/code-reviewer.md +195 -0
- package/packages/core/agents/codebase-onboarding-engineer.md +172 -0
- package/packages/core/agents/comment-rot-analyzer.md +115 -0
- package/packages/core/agents/critic.md +172 -0
- package/packages/core/agents/database-reviewer.md +201 -0
- package/packages/core/agents/debug-observer.md +261 -0
- package/packages/core/agents/dependency-checker.md +199 -0
- package/packages/core/agents/docs-reviewer.md +206 -0
- package/packages/core/agents/e2e-test-generator.md +261 -0
- package/packages/core/agents/evaluator.md +141 -0
- package/packages/core/agents/goal-verifier.md +130 -0
- package/packages/core/agents/health-checker.md +194 -0
- package/packages/core/agents/migration-reviewer.md +161 -0
- package/packages/core/agents/minimal-change-engineer.md +219 -0
- package/packages/core/agents/plan-checker.md +139 -0
- package/packages/core/agents/pre-deploy-validator.md +189 -0
- package/packages/core/agents/reality-checker.md +175 -0
- package/packages/core/agents/scaffold-endpoint.md +162 -0
- package/packages/core/agents/security-scanner.md +236 -0
- package/packages/core/agents/silent-failure-hunter.md +276 -0
- package/packages/core/agents/test-generator.md +146 -0
- package/packages/core/agents/tree-generator.md +141 -0
- package/packages/core/agents/ui-reviewer.md +172 -0
- package/packages/core/agents/visual-reviewer.md +211 -0
- package/packages/core/commands/audit.md +166 -0
- package/packages/core/commands/benchmark.md +130 -0
- package/packages/core/commands/commit.md +148 -0
- package/packages/core/commands/dev.md +302 -0
- package/packages/core/commands/docs-init.md +75 -0
- package/packages/core/commands/lint.md +137 -0
- package/packages/core/commands/migrate.md +146 -0
- package/packages/core/commands/new-migration.md +182 -0
- package/packages/core/commands/pair.md +209 -0
- package/packages/core/commands/review.md +195 -0
- package/packages/core/commands/security-scan.md +142 -0
- package/packages/core/commands/superkit-evolve.md +231 -0
- package/packages/core/commands/superkit-init.md +274 -0
- package/packages/core/commands/test.md +108 -0
- package/packages/core/commands/workflow.md +150 -0
- package/packages/core/docs/guide/01-getting-started.md +41 -0
- package/packages/core/docs-templates/README.md +33 -0
- package/packages/core/docs-templates/adr-template.md +62 -0
- package/packages/core/docs-templates/architecture/api-contracts.md +26 -0
- package/packages/core/docs-templates/architecture/api-reference.md +48 -0
- package/packages/core/docs-templates/architecture/auth-and-sessions.md +38 -0
- package/packages/core/docs-templates/architecture/backend-layers.md +42 -0
- package/packages/core/docs-templates/architecture/data-flow.md +26 -0
- package/packages/core/docs-templates/architecture/database-schema.md +51 -0
- package/packages/core/docs-templates/architecture/deployment.md +41 -0
- package/packages/core/docs-templates/architecture/frontend-state.md +46 -0
- package/packages/core/helpers/statusline.cjs +370 -0
- package/packages/core/hooks/CHAIN-SEMANTICS.md +84 -0
- package/packages/core/hooks/audit-settings-source.sh +98 -0
- package/packages/core/hooks/audit-trail.sh +120 -0
- package/packages/core/hooks/block-dangerous-git.sh +189 -0
- package/packages/core/hooks/bundle-import-check.sh +64 -0
- package/packages/core/hooks/compact-state-inject.sh +84 -0
- package/packages/core/hooks/config-protection.sh +68 -0
- package/packages/core/hooks/console-log-warning.sh +28 -0
- package/packages/core/hooks/context-monitor.sh +35 -0
- package/packages/core/hooks/dev-edit-counter.sh +59 -0
- package/packages/core/hooks/dev-marker-set.sh +55 -0
- package/packages/core/hooks/dev-required-on-commit.sh +426 -0
- package/packages/core/hooks/doc-check-on-commit.sh +396 -0
- package/packages/core/hooks/edit-streak-check.sh +63 -0
- package/packages/core/hooks/evolve-check.sh +78 -0
- package/packages/core/hooks/gateguard-pre-edit.sh +154 -0
- package/packages/core/hooks/gateguard-record-facts.sh +37 -0
- package/packages/core/hooks/intake-classifier.py +449 -0
- package/packages/core/hooks/lib/profile.sh +141 -0
- package/packages/core/hooks/loop-guard.sh +75 -0
- package/packages/core/hooks/migration-safety.sh +56 -0
- package/packages/core/hooks/plan-completion-gate.sh +61 -0
- package/packages/core/hooks/pre-compact-save.sh +89 -0
- package/packages/core/hooks/security-patterns.sh +119 -0
- package/packages/core/hooks/session-context-restore.sh +76 -0
- package/packages/core/hooks/subagent-stop-validate.sh +73 -0
- package/packages/core/hooks/superkit-counts-verify.sh +346 -0
- package/packages/core/hooks/superkit-update.sh +367 -0
- package/packages/core/hooks/tests/README.md +42 -0
- package/packages/core/hooks/tests/audit-trail-chain_test.sh +62 -0
- package/packages/core/hooks/tests/block-dangerous-git_test.sh +144 -0
- package/packages/core/hooks/tests/chain-semantics/h1.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/h2.sh +9 -0
- package/packages/core/hooks/tests/chain-semantics/h3.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/run-experiment.sh +65 -0
- package/packages/core/hooks/tests/chain-semantics/settings-experiment.json +15 -0
- package/packages/core/hooks/tests/counts-verify_test.sh +118 -0
- package/packages/core/hooks/tests/dev-required-on-commit_test.sh +207 -0
- package/packages/core/hooks/tests/dev-required-wip-on-main_test.sh +20 -0
- package/packages/core/hooks/tests/doc-check-on-commit_test.sh +122 -0
- package/packages/core/hooks/tests/edit-streak-check_test.sh +106 -0
- package/packages/core/hooks/tests/internal-manifest_test.sh +130 -0
- package/packages/core/hooks/tests/json-path_test.sh +108 -0
- package/packages/core/hooks/tests/mirror-invariants_test.sh +139 -0
- package/packages/core/hooks/tests/nudge-throttle_test.sh +95 -0
- package/packages/core/hooks/tests/profile-helper_test.sh +21 -0
- package/packages/core/hooks/tests/run-all.sh +47 -0
- package/packages/core/hooks/tests/session-key-helper_test.sh +17 -0
- package/packages/core/hooks/tests/superkit-update_test.sh +311 -0
- package/packages/core/hooks/tests/warn-visibility_test.sh +59 -0
- package/packages/core/hooks/user-intent-detect.sh +44 -0
- package/packages/core/hooks/verify-hooks.sh +69 -0
- package/packages/core/rules/auto-commands.md +124 -0
- package/packages/core/rules/coding-style.md +68 -0
- package/packages/core/rules/dev-workflow.md +77 -0
- package/packages/core/rules/documentation.md +106 -0
- package/packages/core/rules/frontend-aesthetics.md +53 -0
- package/packages/core/rules/git-workflow.md +14 -0
- package/packages/core/rules/security.md +29 -0
- package/packages/core/rules/superkit-integrity.md +114 -0
- package/packages/core/settings.json +229 -0
- package/packages/core/skills/drizzle-orm-expert/SKILL.md +260 -0
- package/packages/core/skills/nextjs-supabase-auth/SKILL.md +259 -0
- package/packages/core/skills/postgresql-optimization/SKILL.md +150 -0
- package/packages/core/skills/project-architecture/SKILL.md +31 -0
- package/packages/core/skills/project-scanner/SKILL.md +132 -0
- package/packages/core/skills/redis-patterns/SKILL.md +261 -0
- package/packages/core/skills/ru-text/SKILL.md +156 -0
- package/packages/core/skills/telegram-bot-builder/SKILL.md +145 -0
- package/packages/core/skills/writing-agents/SKILL.md +220 -0
- package/packages/core/skills/writing-commands/SKILL.md +176 -0
- package/packages/core/skills/writing-hooks/SKILL.md +335 -0
- package/packages/extras/bot-reviewer.md +279 -0
- package/packages/extras/design-system-reviewer.md +234 -0
- package/packages/extras/red-blue-auditor/README.md +117 -0
- package/packages/extras/red-blue-auditor/agent.md +128 -0
- package/packages/extras/red-blue-auditor/patterns/agent-config.txt +4 -0
- package/packages/extras/red-blue-auditor/patterns/hook-injection.txt +8 -0
- package/packages/extras/red-blue-auditor/patterns/mcp-risk.txt +5 -0
- package/packages/extras/red-blue-auditor/patterns/permission-abuse.txt +6 -0
- package/packages/extras/red-blue-auditor/patterns/secrets.txt +17 -0
- package/packages/extras/red-blue-auditor/scan.sh +88 -0
- package/packages/extras/skillsmp-search/SKILL.md +134 -0
- package/packages/frontend-3d/README.md +62 -0
- package/packages/frontend-3d/agents/frontend-perf-reviewer.md +164 -0
- package/packages/frontend-3d/agents/presentation-reviewer.md +146 -0
- package/packages/frontend-3d/agents/r3f-scene-reviewer.md +128 -0
- package/packages/frontend-3d/agents/ui-design-reviewer.md +169 -0
- package/packages/frontend-3d/commands/capture-screen.md +166 -0
- package/packages/frontend-3d/hooks/bundle-size-warn.sh +93 -0
- package/packages/frontend-3d/hooks/gsap-pattern-check.sh +74 -0
- package/packages/frontend-3d/hooks/r3f-color-check.sh +76 -0
- package/packages/frontend-3d/hooks/tailwind-version-guard.sh +98 -0
- package/packages/frontend-3d/rules/frontend-aesthetics-3d.md +81 -0
- package/packages/frontend-3d/rules/gsap-conventions.md +129 -0
- package/packages/frontend-3d/rules/threejs-conventions.md +116 -0
- package/packages/frontend-3d/skills/gltf-debugging/SKILL.md +145 -0
- package/packages/frontend-3d/skills/html-to-3d-texture/SKILL.md +183 -0
- package/packages/frontend-3d/skills/output-enforcement/SKILL.md +79 -0
- package/packages/frontend-3d/skills/product-3d-lighting/SKILL.md +166 -0
- package/packages/frontend-3d/skills/r3f-scroll-driven-3d/SKILL.md +209 -0
- package/packages/frontend-3d/skills/threejs-color-management/SKILL.md +111 -0
- package/packages/frontend-ui/NOTICE.md +99 -0
- package/packages/frontend-ui/README.md +59 -0
- package/packages/frontend-ui/agents/ui-color-reviewer.md +174 -0
- package/packages/frontend-ui/agents/ui-design-critic.md +198 -0
- package/packages/frontend-ui/agents/ui-interaction-reviewer.md +259 -0
- package/packages/frontend-ui/agents/ui-motion-reviewer.md +266 -0
- package/packages/frontend-ui/agents/ui-reviewer.md +251 -0
- package/packages/frontend-ui/agents/ui-typography-reviewer.md +222 -0
- package/packages/frontend-ui/hooks/tests/ui-animation-easing-check_test.sh +78 -0
- package/packages/frontend-ui/hooks/tests/ui-banned-fonts-check_test.sh +77 -0
- package/packages/frontend-ui/hooks/tests/ui-color-check_test.sh +75 -0
- package/packages/frontend-ui/hooks/ui-animation-easing-check.sh +86 -0
- package/packages/frontend-ui/hooks/ui-banned-fonts-check.sh +90 -0
- package/packages/frontend-ui/hooks/ui-color-check.sh +102 -0
- package/packages/frontend-ui/rules/color-and-contrast.md +230 -0
- package/packages/frontend-ui/rules/frontend-design-aesthetics.md +124 -0
- package/packages/frontend-ui/rules/interaction-polish.md +335 -0
- package/packages/frontend-ui/rules/motion-and-animation.md +283 -0
- package/packages/frontend-ui/rules/spatial-and-layout.md +212 -0
- package/packages/frontend-ui/rules/typography-guidelines.md +185 -0
- package/packages/frontend-ui/rules/ui-anti-patterns.md +309 -0
- package/packages/frontend-ui/settings.json +24 -0
- package/packages/frontend-ui/skills/impeccable-craft/SKILL.md +187 -0
- package/packages/gan/README.md +232 -0
- package/packages/gan/agents/gan-evaluator.md +214 -0
- package/packages/gan/agents/gan-generator.md +171 -0
- package/packages/gan/agents/gan-planner.md +206 -0
- package/packages/gan/rubrics/functionality.md +66 -0
- package/packages/gan/rubrics/ui-quality.md +77 -0
- package/packages/gan/skills/gan-evaluator/SKILL.md +91 -0
- package/packages/gan/skills/gan-generator/SKILL.md +72 -0
- package/packages/gan/skills/gan-planner/SKILL.md +93 -0
- package/packages/stack-agents/go/go-concurrency-reviewer.md +210 -0
- package/packages/stack-agents/go/go-error-reviewer.md +187 -0
- package/packages/stack-agents/go/go-modernizer.md +160 -0
- package/packages/stack-agents/go/go-observability-reviewer.md +185 -0
- package/packages/stack-agents/go/go-performance-reviewer.md +160 -0
- package/packages/stack-agents/go/go-reviewer.md +277 -0
- package/packages/stack-agents/go/references/benchmark-methodology.md +280 -0
- package/packages/stack-agents/go/references/channel-patterns.md +384 -0
- package/packages/stack-agents/go/references/cli-cobra-viper.md +190 -0
- package/packages/stack-agents/go/references/code-style.md +262 -0
- package/packages/stack-agents/go/references/context-propagation.md +317 -0
- package/packages/stack-agents/go/references/data-structures.md +315 -0
- package/packages/stack-agents/go/references/database-patterns.md +334 -0
- package/packages/stack-agents/go/references/design-patterns.md +411 -0
- package/packages/stack-agents/go/references/di-frameworks.md +146 -0
- package/packages/stack-agents/go/references/error-creation.md +251 -0
- package/packages/stack-agents/go/references/error-inspection.md +348 -0
- package/packages/stack-agents/go/references/error-wrapping.md +230 -0
- package/packages/stack-agents/go/references/gopls-driving.md +62 -0
- package/packages/stack-agents/go/references/goroutine-lifecycle.md +351 -0
- package/packages/stack-agents/go/references/graphql-patterns.md +221 -0
- package/packages/stack-agents/go/references/grpc-patterns.md +373 -0
- package/packages/stack-agents/go/references/modernize-guide.md +522 -0
- package/packages/stack-agents/go/references/module-management.md +191 -0
- package/packages/stack-agents/go/references/naming-conventions.md +176 -0
- package/packages/stack-agents/go/references/observability-pipeline.md +352 -0
- package/packages/stack-agents/go/references/performance-profiling.md +250 -0
- package/packages/stack-agents/go/references/refactoring-mechanics.md +127 -0
- package/packages/stack-agents/go/references/rest-openapi-patterns.md +160 -0
- package/packages/stack-agents/go/references/samber-do.md +201 -0
- package/packages/stack-agents/go/references/samber-libraries.md +363 -0
- package/packages/stack-agents/go/references/samber-lo.md +260 -0
- package/packages/stack-agents/go/references/samber-oops.md +200 -0
- package/packages/stack-agents/go/references/security-checklist.md +441 -0
- package/packages/stack-agents/go/references/standard-stdlib-now.md +181 -0
- package/packages/stack-agents/go/references/stay-updated.md +147 -0
- package/packages/stack-agents/go/references/structs-interfaces.md +312 -0
- package/packages/stack-agents/go/references/sync-primitives.md +395 -0
- package/packages/stack-agents/go/references/testing-patterns.md +483 -0
- package/packages/stack-agents/go/references/troubleshooting.md +98 -0
- package/packages/stack-agents/python/py-reviewer.md +194 -0
- package/packages/stack-agents/rust/rs-reviewer.md +188 -0
- package/packages/stack-agents/typescript/ts-reviewer.md +135 -0
- package/packages/stack-hooks/go/go-context-check-on-edit.sh +56 -0
- package/packages/stack-hooks/go/go-error-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-format-on-edit.sh +32 -0
- package/packages/stack-hooks/go/go-safety-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-vet-on-edit.sh +61 -0
- package/packages/stack-hooks/go/golangci-lint-on-edit.sh +54 -0
- package/packages/stack-hooks/python/ruff-on-edit.sh +67 -0
- package/packages/stack-hooks/rust/cargo-check-on-edit.sh +64 -0
- package/packages/stack-hooks/typescript/typecheck-on-edit.sh +76 -0
- package/packages/stack-rules/go/go-conventions.md +44 -0
- package/packages/stack-rules/go/go-safety.md +35 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
# Modernize Guide
|
|
2
|
+
|
|
3
|
+
> Reference document for go-modernizer. Loaded on demand via Read tool.
|
|
4
|
+
|
|
5
|
+
## Go Version Feature Matrix
|
|
6
|
+
|
|
7
|
+
### Go 1.18 — Generics
|
|
8
|
+
|
|
9
|
+
**Risk: LOW** — well-tested, widely adopted.
|
|
10
|
+
|
|
11
|
+
**Before:**
|
|
12
|
+
```go
|
|
13
|
+
func ContainsInt(s []int, v int) bool {
|
|
14
|
+
for _, item := range s {
|
|
15
|
+
if item == v {
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
func ContainsString(s []string, v string) bool {
|
|
23
|
+
for _, item := range s {
|
|
24
|
+
if item == v {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**After:**
|
|
33
|
+
```go
|
|
34
|
+
func Contains[T comparable](s []T, v T) bool {
|
|
35
|
+
for _, item := range s {
|
|
36
|
+
if item == v {
|
|
37
|
+
return true
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Migration recipe:**
|
|
45
|
+
1. Identify duplicated functions that differ only by type
|
|
46
|
+
2. Replace with generic version using type constraints
|
|
47
|
+
3. Update all call sites (usually type inference handles it)
|
|
48
|
+
4. Run tests — generics can change escape analysis behavior
|
|
49
|
+
|
|
50
|
+
### Go 1.20 — errors.Join, Multi-Error Wrapping
|
|
51
|
+
|
|
52
|
+
**Risk: LOW** — drop-in replacement for custom multi-error types.
|
|
53
|
+
|
|
54
|
+
**Before:**
|
|
55
|
+
```go
|
|
56
|
+
type MultiError struct {
|
|
57
|
+
Errors []error
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func (m *MultiError) Error() string {
|
|
61
|
+
msgs := make([]string, len(m.Errors))
|
|
62
|
+
for i, e := range m.Errors {
|
|
63
|
+
msgs[i] = e.Error()
|
|
64
|
+
}
|
|
65
|
+
return strings.Join(msgs, "; ")
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
func validate(u *User) error {
|
|
69
|
+
var me MultiError
|
|
70
|
+
if u.Name == "" {
|
|
71
|
+
me.Errors = append(me.Errors, errors.New("name required"))
|
|
72
|
+
}
|
|
73
|
+
if u.Email == "" {
|
|
74
|
+
me.Errors = append(me.Errors, errors.New("email required"))
|
|
75
|
+
}
|
|
76
|
+
if len(me.Errors) > 0 {
|
|
77
|
+
return &me
|
|
78
|
+
}
|
|
79
|
+
return nil
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**After:**
|
|
84
|
+
```go
|
|
85
|
+
func validate(u *User) error {
|
|
86
|
+
var errs []error
|
|
87
|
+
if u.Name == "" {
|
|
88
|
+
errs = append(errs, errors.New("name required"))
|
|
89
|
+
}
|
|
90
|
+
if u.Email == "" {
|
|
91
|
+
errs = append(errs, errors.New("email required"))
|
|
92
|
+
}
|
|
93
|
+
return errors.Join(errs...) // nil if empty
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Migration recipe:**
|
|
98
|
+
1. Find custom multi-error types
|
|
99
|
+
2. Replace with `errors.Join`
|
|
100
|
+
3. Verify callers using `errors.Is`/`errors.As` still work (they do — Join supports both)
|
|
101
|
+
|
|
102
|
+
### Go 1.21 — slog, slices, maps, min/max, WithoutCancel
|
|
103
|
+
|
|
104
|
+
**Risk: LOW-MEDIUM** — slog is a larger migration, slices/maps are straightforward.
|
|
105
|
+
|
|
106
|
+
#### slog (structured logging)
|
|
107
|
+
|
|
108
|
+
**Before:**
|
|
109
|
+
```go
|
|
110
|
+
import "go.uber.org/zap"
|
|
111
|
+
|
|
112
|
+
logger, _ := zap.NewProduction()
|
|
113
|
+
logger.Info("user created",
|
|
114
|
+
zap.Int64("user_id", user.ID),
|
|
115
|
+
zap.String("email", user.Email),
|
|
116
|
+
)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**After:**
|
|
120
|
+
```go
|
|
121
|
+
import "log/slog"
|
|
122
|
+
|
|
123
|
+
slog.Info("user created",
|
|
124
|
+
"user_id", user.ID,
|
|
125
|
+
"email", user.Email,
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Migration recipe:**
|
|
130
|
+
1. Replace `zap.NewProduction()` with `slog.New(slog.NewJSONHandler(os.Stdout, opts))`
|
|
131
|
+
2. Replace typed fields (`zap.String`, `zap.Int64`) with key-value pairs
|
|
132
|
+
3. Replace `logger.With(...)` with `slog.With(...)`
|
|
133
|
+
4. Custom handlers can wrap slog.Handler for sampling, routing
|
|
134
|
+
|
|
135
|
+
#### slices and maps packages
|
|
136
|
+
|
|
137
|
+
**Before:**
|
|
138
|
+
```go
|
|
139
|
+
sort.Slice(users, func(i, j int) bool {
|
|
140
|
+
return users[i].Name < users[j].Name
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
found := false
|
|
144
|
+
for _, u := range users {
|
|
145
|
+
if u.ID == targetID {
|
|
146
|
+
found = true
|
|
147
|
+
break
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**After:**
|
|
153
|
+
```go
|
|
154
|
+
slices.SortFunc(users, func(a, b User) int {
|
|
155
|
+
return cmp.Compare(a.Name, b.Name)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
found := slices.ContainsFunc(users, func(u User) bool {
|
|
159
|
+
return u.ID == targetID
|
|
160
|
+
})
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### min/max builtins
|
|
164
|
+
|
|
165
|
+
**Before:**
|
|
166
|
+
```go
|
|
167
|
+
func min(a, b int) int {
|
|
168
|
+
if a < b {
|
|
169
|
+
return a
|
|
170
|
+
}
|
|
171
|
+
return b
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**After:**
|
|
176
|
+
```go
|
|
177
|
+
result := min(a, b) // builtin, works with any ordered type
|
|
178
|
+
result := max(a, b, c) // variadic!
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Migration recipe:**
|
|
182
|
+
1. Delete custom `min`/`max` helper functions
|
|
183
|
+
2. Replace `sort.Slice` with `slices.SortFunc`
|
|
184
|
+
3. Replace manual search loops with `slices.Contains`/`slices.ContainsFunc`
|
|
185
|
+
|
|
186
|
+
#### context.WithoutCancel
|
|
187
|
+
|
|
188
|
+
**Before:**
|
|
189
|
+
```go
|
|
190
|
+
// Hacky: create new context with just values
|
|
191
|
+
asyncCtx := context.Background()
|
|
192
|
+
asyncCtx = context.WithValue(asyncCtx, requestIDKey, RequestIDFromContext(ctx))
|
|
193
|
+
asyncCtx = context.WithValue(asyncCtx, userIDKey, UserIDFromContext(ctx))
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**After:**
|
|
197
|
+
```go
|
|
198
|
+
asyncCtx := context.WithoutCancel(ctx) // keeps all values, ignores parent cancel
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Go 1.22 — Range-Over-Int, Loop Variable Fix, Enhanced ServeMux
|
|
202
|
+
|
|
203
|
+
**Risk: LOW** — most are drop-in improvements.
|
|
204
|
+
|
|
205
|
+
#### Range over integers
|
|
206
|
+
|
|
207
|
+
**Before:**
|
|
208
|
+
```go
|
|
209
|
+
for i := 0; i < n; i++ {
|
|
210
|
+
process(i)
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**After:**
|
|
215
|
+
```go
|
|
216
|
+
for i := range n {
|
|
217
|
+
process(i)
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### Loop variable fix
|
|
222
|
+
|
|
223
|
+
**Before (Go < 1.22 — bug):**
|
|
224
|
+
```go
|
|
225
|
+
for _, item := range items {
|
|
226
|
+
go func() {
|
|
227
|
+
process(item) // BUG: all goroutines see last item
|
|
228
|
+
}()
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Workaround:
|
|
232
|
+
for _, item := range items {
|
|
233
|
+
item := item // capture
|
|
234
|
+
go func() {
|
|
235
|
+
process(item)
|
|
236
|
+
}()
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**After (Go 1.22+):**
|
|
241
|
+
```go
|
|
242
|
+
for _, item := range items {
|
|
243
|
+
go func() {
|
|
244
|
+
process(item) // FIXED: each iteration has its own variable
|
|
245
|
+
}()
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Migration recipe:**
|
|
250
|
+
1. Remove `item := item` shadow copies in range loops
|
|
251
|
+
2. This is automatic with Go 1.22+ toolchain
|
|
252
|
+
|
|
253
|
+
#### Enhanced ServeMux
|
|
254
|
+
|
|
255
|
+
**Before:**
|
|
256
|
+
```go
|
|
257
|
+
mux.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
|
|
258
|
+
switch r.Method {
|
|
259
|
+
case "GET":
|
|
260
|
+
listUsers(w, r)
|
|
261
|
+
case "POST":
|
|
262
|
+
createUser(w, r)
|
|
263
|
+
default:
|
|
264
|
+
http.Error(w, "method not allowed", 405)
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**After:**
|
|
270
|
+
```go
|
|
271
|
+
mux.HandleFunc("GET /api/users", listUsers)
|
|
272
|
+
mux.HandleFunc("POST /api/users", createUser)
|
|
273
|
+
mux.HandleFunc("GET /api/users/{id}", getUser) // path parameters!
|
|
274
|
+
mux.HandleFunc("DELETE /api/users/{id}", deleteUser)
|
|
275
|
+
|
|
276
|
+
// Access path parameter:
|
|
277
|
+
func getUser(w http.ResponseWriter, r *http.Request) {
|
|
278
|
+
id := r.PathValue("id")
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### math/rand/v2
|
|
283
|
+
|
|
284
|
+
**Before:**
|
|
285
|
+
```go
|
|
286
|
+
import "math/rand"
|
|
287
|
+
|
|
288
|
+
rand.Seed(time.Now().UnixNano()) // required before Go 1.20
|
|
289
|
+
n := rand.Intn(100)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**After:**
|
|
293
|
+
```go
|
|
294
|
+
import "math/rand/v2"
|
|
295
|
+
|
|
296
|
+
n := rand.IntN(100) // auto-seeded, better API
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Go 1.23 — Iterator Functions, unique Package
|
|
300
|
+
|
|
301
|
+
**Risk: MEDIUM** — iterators are a new paradigm.
|
|
302
|
+
|
|
303
|
+
**Before:**
|
|
304
|
+
```go
|
|
305
|
+
func (db *DB) Users() ([]*User, error) {
|
|
306
|
+
// loads ALL users into memory
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**After:**
|
|
311
|
+
```go
|
|
312
|
+
func (db *DB) Users() iter.Seq2[*User, error] {
|
|
313
|
+
return func(yield func(*User, error) bool) {
|
|
314
|
+
rows, err := db.Query(ctx, "SELECT ...")
|
|
315
|
+
if err != nil {
|
|
316
|
+
yield(nil, err)
|
|
317
|
+
return
|
|
318
|
+
}
|
|
319
|
+
defer rows.Close()
|
|
320
|
+
for rows.Next() {
|
|
321
|
+
var u User
|
|
322
|
+
if err := rows.Scan(&u.ID, &u.Name); err != nil {
|
|
323
|
+
if !yield(nil, err) {
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
continue
|
|
327
|
+
}
|
|
328
|
+
if !yield(&u, nil) {
|
|
329
|
+
return
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Usage
|
|
336
|
+
for user, err := range db.Users() {
|
|
337
|
+
if err != nil {
|
|
338
|
+
return err
|
|
339
|
+
}
|
|
340
|
+
process(user)
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Go 1.24 — testing/synctest, omitzero, Weak Pointers, runtime.AddCleanup
|
|
345
|
+
|
|
346
|
+
**Risk: LOW-MEDIUM** — synctest is test-only, omitzero is targeted.
|
|
347
|
+
|
|
348
|
+
Use synctest.Test in Go 1.25+; synctest.Run was the Go 1.24 experimental API (behind GOEXPERIMENT=synctest).
|
|
349
|
+
|
|
350
|
+
#### testing/synctest
|
|
351
|
+
|
|
352
|
+
```go
|
|
353
|
+
// See testing-patterns.md for full example
|
|
354
|
+
synctest.Test(t, func(t *testing.T) {
|
|
355
|
+
// Deterministic goroutine scheduling
|
|
356
|
+
// time.Sleep is virtual (instant)
|
|
357
|
+
// synctest.Wait() blocks until all goroutines are blocked
|
|
358
|
+
})
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### omitzero JSON tag
|
|
362
|
+
|
|
363
|
+
**Before:**
|
|
364
|
+
```go
|
|
365
|
+
type Event struct {
|
|
366
|
+
Name string `json:"name"`
|
|
367
|
+
Timestamp time.Time `json:"timestamp,omitempty"` // omitempty doesn't work for time.Time!
|
|
368
|
+
}
|
|
369
|
+
// {"name":"test","timestamp":"0001-01-01T00:00:00Z"} — zero time still serialized
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**After:**
|
|
373
|
+
```go
|
|
374
|
+
type Event struct {
|
|
375
|
+
Name string `json:"name"`
|
|
376
|
+
Timestamp time.Time `json:"timestamp,omitzero"` // omits if IsZero() returns true
|
|
377
|
+
}
|
|
378
|
+
// {"name":"test"} — zero time omitted
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
#### Weak Pointers
|
|
382
|
+
|
|
383
|
+
```go
|
|
384
|
+
import "weak"
|
|
385
|
+
|
|
386
|
+
type Cache[K comparable, V any] struct {
|
|
387
|
+
mu sync.Mutex
|
|
388
|
+
items map[K]weak.Pointer[V]
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Allows GC to collect values when no strong references exist
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
#### runtime.AddCleanup
|
|
395
|
+
|
|
396
|
+
Replaces `runtime.SetFinalizer` for releasing non-GC resources. Unlike finalizers, cleanups attach to any pointer, run concurrently, and don't resurrect the object.
|
|
397
|
+
|
|
398
|
+
```go
|
|
399
|
+
import "runtime"
|
|
400
|
+
|
|
401
|
+
func NewFile(fd int) *File {
|
|
402
|
+
f := &File{fd: fd}
|
|
403
|
+
// Release the OS descriptor once f is unreachable.
|
|
404
|
+
runtime.AddCleanup(f, func(fd int) { syscall.Close(fd) }, fd)
|
|
405
|
+
return f
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Rules: `arg` must not equal `ptr` (`AddCleanup` panics), and neither `cleanup` nor `arg` may reference `ptr` (that keeps it alive forever, so the cleanup never runs). Prefer explicit `Close()`/`defer` — cleanups are a safety net, not a guarantee, and may not run before program exit.
|
|
410
|
+
|
|
411
|
+
### Go 1.25 — sync.WaitGroup.Go, reflect.TypeAssert, synctest stable
|
|
412
|
+
|
|
413
|
+
**Risk: LOW** — additive APIs; no behavior change to existing code.
|
|
414
|
+
|
|
415
|
+
#### sync.WaitGroup.Go
|
|
416
|
+
|
|
417
|
+
Collapses the `Add(1)` / `go` / `defer Done()` triad into one call.
|
|
418
|
+
|
|
419
|
+
**Before:**
|
|
420
|
+
```go
|
|
421
|
+
var wg sync.WaitGroup
|
|
422
|
+
for _, item := range items {
|
|
423
|
+
wg.Add(1)
|
|
424
|
+
go func() {
|
|
425
|
+
defer wg.Done()
|
|
426
|
+
process(item)
|
|
427
|
+
}()
|
|
428
|
+
}
|
|
429
|
+
wg.Wait()
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**After:**
|
|
433
|
+
```go
|
|
434
|
+
var wg sync.WaitGroup
|
|
435
|
+
for _, item := range items {
|
|
436
|
+
wg.Go(func() { process(item) }) // Add + goroutine + Done in one call
|
|
437
|
+
}
|
|
438
|
+
wg.Wait()
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
`f` must not panic, and `wg.Go` propagates no error or cancellation — reach for `errgroup.WithContext` when you need either. See `sync-primitives.md`.
|
|
442
|
+
|
|
443
|
+
#### reflect.TypeAssert
|
|
444
|
+
|
|
445
|
+
```go
|
|
446
|
+
// Go 1.25: assert a concrete type straight off a reflect.Value
|
|
447
|
+
v, ok := reflect.TypeAssert[*User](rv) // was: rv.Interface().(*User)
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Avoids the `interface{}` boxing of `Value.Interface()` on hot reflection paths.
|
|
451
|
+
|
|
452
|
+
#### Container-aware GOMAXPROCS
|
|
453
|
+
|
|
454
|
+
Go 1.25 defaults `GOMAXPROCS` to the cgroup CPU limit when running in a container — drop `go.uber.org/automaxprocs`, it's now redundant.
|
|
455
|
+
|
|
456
|
+
#### testing/synctest.Test now stable
|
|
457
|
+
|
|
458
|
+
`synctest.Test` graduated from the 1.24 experiment (`GOEXPERIMENT=synctest`, `synctest.Run`) — no build flag needed. See `testing-patterns.md`.
|
|
459
|
+
|
|
460
|
+
### Go 1.26 — errors.AsType, slog.NewMultiHandler, ReverseProxy.Rewrite
|
|
461
|
+
|
|
462
|
+
**Risk: LOW** — additive APIs plus one deprecation to migrate off.
|
|
463
|
+
|
|
464
|
+
#### errors.AsType
|
|
465
|
+
|
|
466
|
+
Generic typed extraction — drops the pointer-to-target dance of `errors.As`.
|
|
467
|
+
|
|
468
|
+
```go
|
|
469
|
+
// Before (Go <1.26)
|
|
470
|
+
var verr *ValidationError
|
|
471
|
+
if errors.As(err, &verr) { use(verr) }
|
|
472
|
+
|
|
473
|
+
// After (Go 1.26+)
|
|
474
|
+
if verr, ok := errors.AsType[*ValidationError](err); ok { use(verr) }
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
Signature: `func AsType[E error](err error) (E, bool)`. Keep `errors.As` while you still build against Go <1.26. See `error-inspection.md`.
|
|
478
|
+
|
|
479
|
+
#### slog.NewMultiHandler
|
|
480
|
+
|
|
481
|
+
```go
|
|
482
|
+
// Stdlib fan-out — one record to several handlers
|
|
483
|
+
logger := slog.New(slog.NewMultiHandler(jsonHandler, sentryHandler))
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Covers simple fan-out without `samber/slog-multi`; keep slog-multi for middleware/routing depth.
|
|
487
|
+
|
|
488
|
+
#### httputil.ReverseProxy.Rewrite
|
|
489
|
+
|
|
490
|
+
`ReverseProxy.Director` is deprecated in favor of `.Rewrite`, which receives a `*httputil.ProxyRequest` (both inbound `In` and outbound `Out`).
|
|
491
|
+
|
|
492
|
+
```go
|
|
493
|
+
// Before: proxy.Director = func(req *http.Request) { ... }
|
|
494
|
+
proxy.Rewrite = func(r *httputil.ProxyRequest) {
|
|
495
|
+
r.SetURL(backend) // route the outbound request to backend (*url.URL)
|
|
496
|
+
r.SetXForwarded() // set X-Forwarded-For / -Host / -Proto
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
#### Green Tea GC now the default
|
|
501
|
+
|
|
502
|
+
The Green Tea garbage collector (experimental in 1.25 behind `GOEXPERIMENT=greenteagc`) is on by default — no code change; expect lower GC overhead on allocation-heavy workloads.
|
|
503
|
+
|
|
504
|
+
## Version Migration Decision Table
|
|
505
|
+
|
|
506
|
+
| Current Version | Target | Priority Items | Risk |
|
|
507
|
+
|-----------------|--------|---------------|------|
|
|
508
|
+
| 1.17 or below | 1.18+ | Generics for utility code | LOW |
|
|
509
|
+
| 1.18-1.19 | 1.21+ | slog, slices, maps, min/max | LOW-MED |
|
|
510
|
+
| 1.20 | 1.21+ | errors.Join already available, add slog/slices | LOW |
|
|
511
|
+
| 1.21 | 1.22+ | Enhanced ServeMux, range-over-int | LOW |
|
|
512
|
+
| 1.22 | 1.23+ | Iterators (if needed), unique package | MEDIUM |
|
|
513
|
+
| 1.23 | 1.24+ | synctest for tests, omitzero, weak pointers | LOW |
|
|
514
|
+
| 1.24 | 1.25+ | wg.Go, reflect.TypeAssert, synctest.Test stable, drop automaxprocs | LOW |
|
|
515
|
+
| 1.25 | 1.26+ | errors.AsType, slog.NewMultiHandler, ReverseProxy.Rewrite (Director deprecated) | LOW |
|
|
516
|
+
|
|
517
|
+
## When to Use
|
|
518
|
+
|
|
519
|
+
Apply when reviewing Go projects for modernization opportunities. Flag findings as:
|
|
520
|
+
- **CRITICAL**: Using deprecated APIs (math/rand.Seed, custom min/max with Go 1.21+)
|
|
521
|
+
- **WARNING**: Manual ServeMux routing with Go 1.22+, loop variable capture workarounds with Go 1.22+
|
|
522
|
+
- **SUGGESTION**: Could use slices package, slog instead of third-party logger, range-over-int
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Go Module Management
|
|
2
|
+
|
|
3
|
+
`go.mod` / `go.sum` discipline. Covers `go mod`, versioning, vendor, monorepo workspaces.
|
|
4
|
+
|
|
5
|
+
## go.mod essentials
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
module github.com/org/project
|
|
9
|
+
|
|
10
|
+
go 1.23
|
|
11
|
+
|
|
12
|
+
require (
|
|
13
|
+
github.com/jackc/pgx/v5 v5.5.0
|
|
14
|
+
go.uber.org/fx v1.20.1
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
require (
|
|
18
|
+
github.com/jackc/pgpassfile v1.0.0 // indirect
|
|
19
|
+
// ...
|
|
20
|
+
)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- First `require` block: direct dependencies
|
|
24
|
+
- Second `require` block: indirect (pulled in by direct deps)
|
|
25
|
+
- `// indirect` marker is auto-managed by `go mod tidy`
|
|
26
|
+
|
|
27
|
+
## Daily commands
|
|
28
|
+
|
|
29
|
+
| Command | Purpose |
|
|
30
|
+
|---------|---------|
|
|
31
|
+
| `go mod tidy` | Add missing, remove unused; updates go.sum |
|
|
32
|
+
| `go mod download` | Pre-fetch deps for CI / build cache |
|
|
33
|
+
| `go mod vendor` | Copy deps into `vendor/` (rarely needed) |
|
|
34
|
+
| `go list -m all` | List all module deps with versions |
|
|
35
|
+
| `go list -m -u all` | Show available updates |
|
|
36
|
+
| `go get pkg@latest` | Upgrade to latest |
|
|
37
|
+
| `go get pkg@v1.2.3` | Pin to specific version |
|
|
38
|
+
| `go mod why pkg` | Explain why a module is in the graph |
|
|
39
|
+
| `go mod graph` | Print dep graph (machine-readable) |
|
|
40
|
+
|
|
41
|
+
## Versioning
|
|
42
|
+
|
|
43
|
+
- **v0.x.y** — pre-stable, breaking changes allowed
|
|
44
|
+
- **v1.x.y** — stable, semver
|
|
45
|
+
- **v2.x.y+** — major version is part of the import path: `github.com/org/proj/v2`
|
|
46
|
+
|
|
47
|
+
Go's "major version in path" rule means upgrading to v2 of a library requires updating import statements.
|
|
48
|
+
|
|
49
|
+
## Pinning vs latest
|
|
50
|
+
|
|
51
|
+
```go
|
|
52
|
+
// Pinned (recommended)
|
|
53
|
+
require github.com/jackc/pgx/v5 v5.5.0
|
|
54
|
+
|
|
55
|
+
// Range (avoid in production)
|
|
56
|
+
require github.com/jackc/pgx/v5 v5.5.0 // indirect
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Always commit `go.sum` — it's the integrity checklist. Without it, builds aren't reproducible.
|
|
60
|
+
|
|
61
|
+
## Replace directives
|
|
62
|
+
|
|
63
|
+
```go
|
|
64
|
+
require example.com/lib v1.2.3
|
|
65
|
+
replace example.com/lib => ../local-fork
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Use cases:
|
|
69
|
+
- Local fork for debugging
|
|
70
|
+
- Monorepo modules pointing at sibling packages
|
|
71
|
+
- Patched upstream waiting on release
|
|
72
|
+
|
|
73
|
+
**Caution:** `replace` doesn't propagate to consumers. Anyone importing your module gets the original, not the replacement.
|
|
74
|
+
|
|
75
|
+
## Workspaces (Go 1.18+)
|
|
76
|
+
|
|
77
|
+
For monorepos with multiple modules:
|
|
78
|
+
|
|
79
|
+
```go
|
|
80
|
+
// go.work
|
|
81
|
+
go 1.23
|
|
82
|
+
|
|
83
|
+
use (
|
|
84
|
+
./api
|
|
85
|
+
./shared
|
|
86
|
+
./worker
|
|
87
|
+
)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Each subdirectory has its own `go.mod`. Workspace mode unifies builds without `replace`.
|
|
91
|
+
|
|
92
|
+
## Private modules
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Tell go to skip the proxy for private repos
|
|
96
|
+
export GOPRIVATE=github.com/org/*
|
|
97
|
+
export GONOPROXY=github.com/org/*
|
|
98
|
+
export GONOSUMCHECK=github.com/org/*
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
For SSH-based git: `git config --global url.git@github.com:.insteadOf https://github.com/`.
|
|
102
|
+
|
|
103
|
+
## Build tags
|
|
104
|
+
|
|
105
|
+
Conditional compilation:
|
|
106
|
+
|
|
107
|
+
```go
|
|
108
|
+
//go:build linux && amd64
|
|
109
|
+
|
|
110
|
+
package main
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
For test-only files: `//go:build integration` then `go test -tags=integration ./...`.
|
|
114
|
+
|
|
115
|
+
## Pinning executable tools (Go 1.24+)
|
|
116
|
+
|
|
117
|
+
Build-time tools (linters, code generators, `govulncheck`, `modernize`) should be version-pinned in `go.mod` so every checkout and CI run uses the same binary. Go 1.24 added first-class `tool` directives for this.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Add a tool — records it in go.mod and pins the version in go.sum
|
|
121
|
+
go get -tool golang.org/x/vuln/cmd/govulncheck@latest
|
|
122
|
+
|
|
123
|
+
# Run a pinned tool (builds from the pinned module, not $PATH)
|
|
124
|
+
go tool govulncheck ./...
|
|
125
|
+
|
|
126
|
+
# Install every tool directive into $GOBIN (e.g. in CI images)
|
|
127
|
+
go install tool
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
This writes a `tool` block to `go.mod`:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
tool (
|
|
134
|
+
golang.org/x/vuln/cmd/govulncheck
|
|
135
|
+
golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize
|
|
136
|
+
)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Rule:** Go 1.24+ → use `tool` directives. On older toolchains, fall back to the `tools.go` pattern (a build-tagged file with blank imports plus a matching `require`):
|
|
140
|
+
|
|
141
|
+
```go
|
|
142
|
+
//go:build tools
|
|
143
|
+
|
|
144
|
+
package tools
|
|
145
|
+
|
|
146
|
+
import _ "golang.org/x/vuln/cmd/govulncheck"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Either way the goal is a reproducible, pinned tool version — never rely on `go install ...@latest` on a shared machine, which silently drifts.
|
|
150
|
+
|
|
151
|
+
## Vulnerability scan
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Quick one-off (unpinned)
|
|
155
|
+
go install golang.org/x/vuln/cmd/govulncheck@latest
|
|
156
|
+
govulncheck ./...
|
|
157
|
+
|
|
158
|
+
# Reproducible default: pin as a tool directive (Go 1.24+), run via `go tool`
|
|
159
|
+
go get -tool golang.org/x/vuln/cmd/govulncheck
|
|
160
|
+
go tool govulncheck ./...
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Run in CI; failures are usually CVEs in deps that need an upgrade.
|
|
164
|
+
|
|
165
|
+
## Common issues
|
|
166
|
+
|
|
167
|
+
| Symptom | Fix |
|
|
168
|
+
|---------|-----|
|
|
169
|
+
| `verifying X: checksum mismatch` | `rm go.sum && go mod tidy` (only if you trust the source) |
|
|
170
|
+
| `missing go.sum entry` | `go mod tidy` |
|
|
171
|
+
| `module declares its path as X but was required as Y` | The dep changed its module path; update the import |
|
|
172
|
+
| Slow CI builds | Cache `~/go/pkg/mod` and `~/.cache/go-build` |
|
|
173
|
+
| `replace` ignored | Replace only works in the main module, not transitively |
|
|
174
|
+
|
|
175
|
+
## Anti-patterns
|
|
176
|
+
|
|
177
|
+
- **Committing `vendor/` without need** — bloats repo; only commit if you need air-gapped builds
|
|
178
|
+
- **Ignoring `go.sum`** — destroys build reproducibility
|
|
179
|
+
- **Range-version requires** (`v1.0.0`) — pins should be exact
|
|
180
|
+
- **Stale `go mod tidy`** — run it on every PR
|
|
181
|
+
- **Mixing `replace` and `workspace`** — pick one
|
|
182
|
+
|
|
183
|
+
## CI checklist
|
|
184
|
+
|
|
185
|
+
```yaml
|
|
186
|
+
- run: go mod download
|
|
187
|
+
- run: go mod tidy && git diff --exit-code go.mod go.sum # fail if tidy changed anything
|
|
188
|
+
- run: govulncheck ./...
|
|
189
|
+
- run: go vet ./...
|
|
190
|
+
- run: go test -race ./...
|
|
191
|
+
```
|