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,317 @@
|
|
|
1
|
+
# Context Propagation
|
|
2
|
+
|
|
3
|
+
> Reference document for go-concurrency-reviewer. Loaded on demand via Read tool.
|
|
4
|
+
|
|
5
|
+
## Context Creation
|
|
6
|
+
|
|
7
|
+
| Function | Use When | Example |
|
|
8
|
+
|----------|----------|---------|
|
|
9
|
+
| `context.Background()` | Entry points: main, init, top-level | `main()`, `TestMain()` |
|
|
10
|
+
| `context.TODO()` | Temporary placeholder during refactoring | Grep for these and replace |
|
|
11
|
+
| `context.WithCancel(parent)` | Explicit cancellation needed | Worker lifecycle |
|
|
12
|
+
| `context.WithTimeout(parent, d)` | Operation has time budget | HTTP client call |
|
|
13
|
+
| `context.WithDeadline(parent, t)` | Absolute deadline | "Must complete by 5pm" |
|
|
14
|
+
| `context.WithValue(parent, k, v)` | Request-scoped metadata | Request ID, auth token |
|
|
15
|
+
| `context.WithoutCancel(parent)` | Detach from parent deadline (Go 1.21+) | Async cleanup after response |
|
|
16
|
+
|
|
17
|
+
```go
|
|
18
|
+
// Entry point — Background
|
|
19
|
+
func main() {
|
|
20
|
+
ctx := context.Background()
|
|
21
|
+
if err := run(ctx); err != nil {
|
|
22
|
+
log.Fatal(err)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Cancellation — stops all child goroutines
|
|
27
|
+
func (s *Service) Start(ctx context.Context) {
|
|
28
|
+
ctx, cancel := context.WithCancel(ctx)
|
|
29
|
+
defer cancel() // always defer cancel
|
|
30
|
+
|
|
31
|
+
go s.worker(ctx)
|
|
32
|
+
go s.monitor(ctx)
|
|
33
|
+
|
|
34
|
+
<-ctx.Done()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Timeout — for bounded operations
|
|
38
|
+
func (c *Client) Fetch(ctx context.Context, url string) (*Response, error) {
|
|
39
|
+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
40
|
+
defer cancel() // release resources even if completed early
|
|
41
|
+
|
|
42
|
+
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
|
43
|
+
if err != nil {
|
|
44
|
+
return nil, err
|
|
45
|
+
}
|
|
46
|
+
return c.http.Do(req)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Deadline — absolute time
|
|
50
|
+
func (s *Scheduler) RunBefore(ctx context.Context, deadline time.Time) error {
|
|
51
|
+
ctx, cancel := context.WithDeadline(ctx, deadline)
|
|
52
|
+
defer cancel()
|
|
53
|
+
return s.execute(ctx)
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Cancellation Flow
|
|
58
|
+
|
|
59
|
+
Cancelling a parent context cancels **all** children. This is the core mechanism for graceful shutdown.
|
|
60
|
+
|
|
61
|
+
```go
|
|
62
|
+
// root (Background)
|
|
63
|
+
// |
|
|
64
|
+
// parentCtx (WithCancel)
|
|
65
|
+
// / \
|
|
66
|
+
// child1 child2 (WithTimeout)
|
|
67
|
+
// | |
|
|
68
|
+
// child3 child4
|
|
69
|
+
//
|
|
70
|
+
// cancel(parentCtx) → cancels child1, child2, child3, child4
|
|
71
|
+
// cancel(child2) → cancels child4 only
|
|
72
|
+
|
|
73
|
+
func example() {
|
|
74
|
+
root := context.Background()
|
|
75
|
+
|
|
76
|
+
parentCtx, parentCancel := context.WithCancel(root)
|
|
77
|
+
defer parentCancel()
|
|
78
|
+
|
|
79
|
+
child1, cancel1 := context.WithCancel(parentCtx)
|
|
80
|
+
defer cancel1()
|
|
81
|
+
|
|
82
|
+
child2, cancel2 := context.WithTimeout(parentCtx, 5*time.Second)
|
|
83
|
+
defer cancel2()
|
|
84
|
+
|
|
85
|
+
// Cancelling parent stops everything
|
|
86
|
+
parentCancel() // child1.Done() and child2.Done() both fire
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Timeout Patterns
|
|
91
|
+
|
|
92
|
+
### Server Middleware
|
|
93
|
+
|
|
94
|
+
```go
|
|
95
|
+
func TimeoutMiddleware(timeout time.Duration) func(http.Handler) http.Handler {
|
|
96
|
+
return func(next http.Handler) http.Handler {
|
|
97
|
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
98
|
+
ctx, cancel := context.WithTimeout(r.Context(), timeout)
|
|
99
|
+
defer cancel()
|
|
100
|
+
next.ServeHTTP(w, r.WithContext(ctx))
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Usage
|
|
106
|
+
mux.Handle("POST /api/upload", TimeoutMiddleware(30*time.Second)(uploadHandler))
|
|
107
|
+
mux.Handle("GET /api/users", TimeoutMiddleware(5*time.Second)(listHandler))
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Client Calls with Per-Request Timeout
|
|
111
|
+
|
|
112
|
+
```go
|
|
113
|
+
func (c *APIClient) GetUser(ctx context.Context, id int64) (*User, error) {
|
|
114
|
+
// Respect caller's deadline, but add our own if none exists
|
|
115
|
+
if _, ok := ctx.Deadline(); !ok {
|
|
116
|
+
var cancel context.CancelFunc
|
|
117
|
+
ctx, cancel = context.WithTimeout(ctx, 3*time.Second)
|
|
118
|
+
defer cancel()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
req, err := http.NewRequestWithContext(ctx, "GET",
|
|
122
|
+
fmt.Sprintf("%s/users/%d", c.baseURL, id), nil)
|
|
123
|
+
if err != nil {
|
|
124
|
+
return nil, fmt.Errorf("APIClient.GetUser: %w", err)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
resp, err := c.http.Do(req)
|
|
128
|
+
if err != nil {
|
|
129
|
+
if errors.Is(err, context.DeadlineExceeded) {
|
|
130
|
+
return nil, fmt.Errorf("APIClient.GetUser: %w", domain.ErrTimeout)
|
|
131
|
+
}
|
|
132
|
+
return nil, fmt.Errorf("APIClient.GetUser: %w", err)
|
|
133
|
+
}
|
|
134
|
+
defer resp.Body.Close()
|
|
135
|
+
|
|
136
|
+
var user User
|
|
137
|
+
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
|
|
138
|
+
return nil, fmt.Errorf("APIClient.GetUser: decode: %w", err)
|
|
139
|
+
}
|
|
140
|
+
return &user, nil
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Database Query with Timeout
|
|
145
|
+
|
|
146
|
+
```go
|
|
147
|
+
func (r *Repo) Search(ctx context.Context, query string) ([]*User, error) {
|
|
148
|
+
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
|
149
|
+
defer cancel()
|
|
150
|
+
|
|
151
|
+
rows, err := r.db.Query(ctx,
|
|
152
|
+
"SELECT id, name, email FROM users WHERE name ILIKE $1 LIMIT 100",
|
|
153
|
+
"%"+query+"%")
|
|
154
|
+
if err != nil {
|
|
155
|
+
if errors.Is(err, context.DeadlineExceeded) {
|
|
156
|
+
return nil, fmt.Errorf("Repo.Search: query too slow: %w", domain.ErrTimeout)
|
|
157
|
+
}
|
|
158
|
+
return nil, fmt.Errorf("Repo.Search: %w", err)
|
|
159
|
+
}
|
|
160
|
+
defer rows.Close()
|
|
161
|
+
// ...
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Context Value Keys
|
|
166
|
+
|
|
167
|
+
**Always use typed, unexported keys.** Never use strings or built-in types as keys.
|
|
168
|
+
|
|
169
|
+
```go
|
|
170
|
+
// CORRECT — typed unexported key
|
|
171
|
+
type contextKey struct{}
|
|
172
|
+
|
|
173
|
+
var requestIDKey = contextKey{}
|
|
174
|
+
|
|
175
|
+
func WithRequestID(ctx context.Context, id string) context.Context {
|
|
176
|
+
return context.WithValue(ctx, requestIDKey, id)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
func RequestIDFromContext(ctx context.Context) string {
|
|
180
|
+
id, _ := ctx.Value(requestIDKey).(string)
|
|
181
|
+
return id
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```go
|
|
186
|
+
// WRONG — string key (collisions between packages)
|
|
187
|
+
ctx = context.WithValue(ctx, "request_id", id)
|
|
188
|
+
|
|
189
|
+
// WRONG — exported key (anyone can overwrite)
|
|
190
|
+
var RequestIDKey = "request_id"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Common Context Values
|
|
194
|
+
|
|
195
|
+
```go
|
|
196
|
+
// Each value gets its own key type and accessor pair
|
|
197
|
+
type requestIDKeyType struct{}
|
|
198
|
+
type userIDKeyType struct{}
|
|
199
|
+
type traceIDKeyType struct{}
|
|
200
|
+
|
|
201
|
+
var (
|
|
202
|
+
requestIDKey = requestIDKeyType{}
|
|
203
|
+
userIDKey = userIDKeyType{}
|
|
204
|
+
traceIDKey = traceIDKeyType{}
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
// Middleware sets values
|
|
208
|
+
func AuthMiddleware(next http.Handler) http.Handler {
|
|
209
|
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
210
|
+
userID := extractUserID(r)
|
|
211
|
+
ctx := context.WithValue(r.Context(), userIDKey, userID)
|
|
212
|
+
next.ServeHTTP(w, r.WithContext(ctx))
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Service reads values
|
|
217
|
+
func (s *Service) Process(ctx context.Context) error {
|
|
218
|
+
userID, _ := ctx.Value(userIDKey).(int64)
|
|
219
|
+
requestID, _ := ctx.Value(requestIDKey).(string)
|
|
220
|
+
s.logger.Info("processing",
|
|
221
|
+
"user_id", userID,
|
|
222
|
+
"request_id", requestID,
|
|
223
|
+
)
|
|
224
|
+
// ...
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## context.WithoutCancel (Go 1.21+)
|
|
229
|
+
|
|
230
|
+
Detach a context from its parent's cancellation while preserving values. Useful for operations that must continue after the parent is cancelled.
|
|
231
|
+
|
|
232
|
+
```go
|
|
233
|
+
// Async audit logging — must complete even if request is cancelled
|
|
234
|
+
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
|
235
|
+
if err := h.svc.Delete(r.Context(), id); err != nil {
|
|
236
|
+
respondError(w, err)
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Audit log must succeed even if client disconnects
|
|
241
|
+
auditCtx := context.WithoutCancel(r.Context()) // keeps values, ignores cancel
|
|
242
|
+
go h.audit.Log(auditCtx, AuditEvent{
|
|
243
|
+
Action: "delete",
|
|
244
|
+
UserID: UserIDFromContext(r.Context()),
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
respondOK(w)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Cleanup after response — needs its own timeout
|
|
251
|
+
func (s *Service) Process(ctx context.Context) error {
|
|
252
|
+
result, err := s.doWork(ctx)
|
|
253
|
+
if err != nil {
|
|
254
|
+
return err
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Cleanup with independent timeout
|
|
258
|
+
cleanupCtx := context.WithoutCancel(ctx)
|
|
259
|
+
cleanupCtx, cancel := context.WithTimeout(cleanupCtx, 5*time.Second)
|
|
260
|
+
defer cancel()
|
|
261
|
+
s.cleanup(cleanupCtx, result)
|
|
262
|
+
|
|
263
|
+
return nil
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Anti-Patterns
|
|
268
|
+
|
|
269
|
+
### Storing Context in Structs
|
|
270
|
+
|
|
271
|
+
```go
|
|
272
|
+
// WRONG — context should flow through function calls, not be stored
|
|
273
|
+
type Service struct {
|
|
274
|
+
ctx context.Context // BAD: stale context, can't be per-request
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// CORRECT — context as first parameter
|
|
278
|
+
func (s *Service) Process(ctx context.Context, data Data) error {
|
|
279
|
+
// ctx is per-request, fresh
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Using context.Background() Deep in Call Stack
|
|
284
|
+
|
|
285
|
+
```go
|
|
286
|
+
// WRONG — ignores caller's cancellation/deadline
|
|
287
|
+
func (r *Repo) Save(ctx context.Context, u *User) error {
|
|
288
|
+
_, err := r.db.Exec(context.Background(), query, u.ID) // ignores ctx!
|
|
289
|
+
return err
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// CORRECT — propagate the received context
|
|
293
|
+
func (r *Repo) Save(ctx context.Context, u *User) error {
|
|
294
|
+
_, err := r.db.Exec(ctx, query, u.ID) // respects caller's deadline
|
|
295
|
+
return err
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Overloading Context Values
|
|
300
|
+
|
|
301
|
+
```go
|
|
302
|
+
// WRONG — passing dependencies through context
|
|
303
|
+
ctx = context.WithValue(ctx, "db", db) // use DI instead
|
|
304
|
+
ctx = context.WithValue(ctx, "logger", log) // use struct fields instead
|
|
305
|
+
|
|
306
|
+
// CORRECT — context values are for request-scoped data only
|
|
307
|
+
ctx = context.WithValue(ctx, requestIDKey, reqID) // request ID
|
|
308
|
+
ctx = context.WithValue(ctx, userIDKey, userID) // authenticated user
|
|
309
|
+
ctx = context.WithValue(ctx, traceIDKey, traceID) // distributed trace
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## When to Use
|
|
313
|
+
|
|
314
|
+
Apply when reviewing context usage across function boundaries. Flag violations as:
|
|
315
|
+
- **CRITICAL**: Storing context in struct, using `context.Background()` deep in call stack, string context keys
|
|
316
|
+
- **WARNING**: Missing `defer cancel()`, no timeout on external calls, context values for dependencies
|
|
317
|
+
- **SUGGESTION**: Could use `WithoutCancel` for async cleanup, missing deadline check before expensive operation
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# Data Structures
|
|
2
|
+
|
|
3
|
+
> Reference document for go-reviewer. Loaded on demand via Read tool.
|
|
4
|
+
|
|
5
|
+
## Slices
|
|
6
|
+
|
|
7
|
+
### Append Semantics
|
|
8
|
+
|
|
9
|
+
`append` may allocate a new underlying array. **Always reassign** the result.
|
|
10
|
+
|
|
11
|
+
```go
|
|
12
|
+
// CORRECT — reassign
|
|
13
|
+
s = append(s, item)
|
|
14
|
+
|
|
15
|
+
// BUG — discards potential new allocation
|
|
16
|
+
func addItem(s []int, item int) {
|
|
17
|
+
append(s, item) // result not captured!
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Capacity and Growth
|
|
22
|
+
|
|
23
|
+
```go
|
|
24
|
+
// Pre-allocate when size is known — avoids repeated copying
|
|
25
|
+
users := make([]User, 0, len(ids))
|
|
26
|
+
for _, id := range ids {
|
|
27
|
+
u, err := repo.FindByID(ctx, id)
|
|
28
|
+
if err != nil {
|
|
29
|
+
return nil, err
|
|
30
|
+
}
|
|
31
|
+
users = append(users, *u)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Growth policy: Go runtime doubles small slices, grows ~25% for large ones
|
|
35
|
+
// Check current capacity
|
|
36
|
+
fmt.Println(len(s), cap(s))
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Copy for Safety
|
|
40
|
+
|
|
41
|
+
Slices share underlying arrays. Copy when you need independent data.
|
|
42
|
+
|
|
43
|
+
```go
|
|
44
|
+
// DANGEROUS — modifying returned slice affects internal state
|
|
45
|
+
func (c *Cache) GetIDs() []int64 {
|
|
46
|
+
return c.ids // caller can modify c.ids!
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// SAFE — return a copy
|
|
50
|
+
func (c *Cache) GetIDs() []int64 {
|
|
51
|
+
result := make([]int64, len(c.ids))
|
|
52
|
+
copy(result, c.ids)
|
|
53
|
+
return result
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// SAFE — slices.Clone (Go 1.21+)
|
|
57
|
+
func (c *Cache) GetIDs() []int64 {
|
|
58
|
+
return slices.Clone(c.ids)
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Nil vs Empty Slices
|
|
63
|
+
|
|
64
|
+
```go
|
|
65
|
+
var s []int // nil slice: s == nil, len(s) == 0, json → null
|
|
66
|
+
s = []int{} // empty slice: s != nil, len(s) == 0, json → []
|
|
67
|
+
s = make([]int, 0) // empty slice: s != nil, len(s) == 0, json → []
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Decision table — nil vs empty:**
|
|
71
|
+
|
|
72
|
+
| Context | Use | Why |
|
|
73
|
+
|---------|-----|-----|
|
|
74
|
+
| JSON API response | `[]int{}` or `make` | Clients expect `[]`, not `null` |
|
|
75
|
+
| Internal return, no results | `nil` | Idiomatic, `len`/`append` work on nil |
|
|
76
|
+
| Struct field default | `nil` (zero value) | Initialize on first use |
|
|
77
|
+
| Test assertion | Be explicit | `assert.Nil` vs `assert.Empty` differ |
|
|
78
|
+
|
|
79
|
+
### Slice Tricks
|
|
80
|
+
|
|
81
|
+
```go
|
|
82
|
+
// Delete element at index i (preserves order)
|
|
83
|
+
s = slices.Delete(s, i, i+1) // Go 1.21+
|
|
84
|
+
// or: s = append(s[:i], s[i+1:]...)
|
|
85
|
+
|
|
86
|
+
// Delete without preserving order (fast)
|
|
87
|
+
s[i] = s[len(s)-1]
|
|
88
|
+
s = s[:len(s)-1]
|
|
89
|
+
|
|
90
|
+
// Filter in-place
|
|
91
|
+
s = slices.DeleteFunc(s, func(v int) bool {
|
|
92
|
+
return v < 0
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// Deduplicate sorted slice
|
|
96
|
+
slices.Sort(s)
|
|
97
|
+
s = slices.Compact(s)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Maps
|
|
101
|
+
|
|
102
|
+
### Initialization
|
|
103
|
+
|
|
104
|
+
```go
|
|
105
|
+
// Must initialize before writing — nil map write panics!
|
|
106
|
+
var m map[string]int
|
|
107
|
+
m["key"] = 1 // PANIC: assignment to entry in nil map
|
|
108
|
+
|
|
109
|
+
// CORRECT ways to initialize
|
|
110
|
+
m := make(map[string]int)
|
|
111
|
+
m := make(map[string]int, expectedSize) // pre-size hint
|
|
112
|
+
m := map[string]int{"key": 1} // literal
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Iteration Order
|
|
116
|
+
|
|
117
|
+
Map iteration order is **randomized** by the Go runtime. Never depend on order.
|
|
118
|
+
|
|
119
|
+
```go
|
|
120
|
+
// If you need ordered keys:
|
|
121
|
+
keys := make([]string, 0, len(m))
|
|
122
|
+
for k := range m {
|
|
123
|
+
keys = append(keys, k)
|
|
124
|
+
}
|
|
125
|
+
slices.Sort(keys)
|
|
126
|
+
for _, k := range keys {
|
|
127
|
+
fmt.Println(k, m[k])
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Concurrency
|
|
132
|
+
|
|
133
|
+
| Operation | Safe without sync? |
|
|
134
|
+
|-----------|-------------------|
|
|
135
|
+
| Concurrent reads (no writes) | Yes |
|
|
136
|
+
| Concurrent read + write | NO — data race, may crash |
|
|
137
|
+
| Concurrent writes | NO — data race, may crash |
|
|
138
|
+
|
|
139
|
+
```go
|
|
140
|
+
// WRONG — data race
|
|
141
|
+
go func() { m["a"] = 1 }()
|
|
142
|
+
go func() { _ = m["a"] }()
|
|
143
|
+
|
|
144
|
+
// CORRECT — mutex protection
|
|
145
|
+
type SafeMap struct {
|
|
146
|
+
mu sync.RWMutex
|
|
147
|
+
m map[string]int
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
func (sm *SafeMap) Get(key string) (int, bool) {
|
|
151
|
+
sm.mu.RLock()
|
|
152
|
+
defer sm.mu.RUnlock()
|
|
153
|
+
v, ok := sm.m[key]
|
|
154
|
+
return v, ok
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
func (sm *SafeMap) Set(key string, value int) {
|
|
158
|
+
sm.mu.Lock()
|
|
159
|
+
defer sm.mu.Unlock()
|
|
160
|
+
sm.m[key] = value
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### sync.Map
|
|
165
|
+
|
|
166
|
+
Use **only** when one of these applies:
|
|
167
|
+
- Append-only (keys written once, read many)
|
|
168
|
+
- Disjoint key sets per goroutine
|
|
169
|
+
|
|
170
|
+
**Do not** use sync.Map as a general concurrent map — it's slower for mixed read/write workloads.
|
|
171
|
+
|
|
172
|
+
```go
|
|
173
|
+
var cache sync.Map
|
|
174
|
+
|
|
175
|
+
// Store
|
|
176
|
+
cache.Store("key", value)
|
|
177
|
+
|
|
178
|
+
// Load
|
|
179
|
+
if v, ok := cache.Load("key"); ok {
|
|
180
|
+
user := v.(*User)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// LoadOrStore — atomic get-or-set
|
|
184
|
+
actual, loaded := cache.LoadOrStore("key", newValue)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Arrays vs Slices
|
|
188
|
+
|
|
189
|
+
| Feature | Array | Slice |
|
|
190
|
+
|---------|-------|-------|
|
|
191
|
+
| Type | Value type (copied on assignment) | Reference type (shares backing array) |
|
|
192
|
+
| Size | Fixed, part of type: `[5]int` | Dynamic: `[]int` |
|
|
193
|
+
| Comparison | `==` works | `==` doesn't compile (use `slices.Equal`) |
|
|
194
|
+
| Function args | Copied entirely | Header only (24 bytes) |
|
|
195
|
+
| Common use | Rare (crypto hashes, IP addrs) | Everywhere |
|
|
196
|
+
|
|
197
|
+
```go
|
|
198
|
+
// Array — value type, full copy
|
|
199
|
+
a := [3]int{1, 2, 3}
|
|
200
|
+
b := a // b is an independent copy
|
|
201
|
+
b[0] = 99 // a[0] is still 1
|
|
202
|
+
|
|
203
|
+
// Slice — reference type, shared backing
|
|
204
|
+
s := []int{1, 2, 3}
|
|
205
|
+
t := s // t shares same backing array
|
|
206
|
+
t[0] = 99 // s[0] is now 99!
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Generics (Go 1.18+)
|
|
210
|
+
|
|
211
|
+
### Type Constraints
|
|
212
|
+
|
|
213
|
+
```go
|
|
214
|
+
// Built-in constraints
|
|
215
|
+
func Max[T cmp.Ordered](a, b T) T {
|
|
216
|
+
if a > b {
|
|
217
|
+
return a
|
|
218
|
+
}
|
|
219
|
+
return b
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Custom constraint
|
|
223
|
+
type Number interface {
|
|
224
|
+
~int | ~int32 | ~int64 | ~float32 | ~float64
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
func Sum[T Number](values []T) T {
|
|
228
|
+
var total T
|
|
229
|
+
for _, v := range values {
|
|
230
|
+
total += v
|
|
231
|
+
}
|
|
232
|
+
return total
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Generic Data Structures
|
|
237
|
+
|
|
238
|
+
```go
|
|
239
|
+
type Set[T comparable] struct {
|
|
240
|
+
m map[T]struct{}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
func NewSet[T comparable](items ...T) *Set[T] {
|
|
244
|
+
s := &Set[T]{m: make(map[T]struct{}, len(items))}
|
|
245
|
+
for _, item := range items {
|
|
246
|
+
s.m[item] = struct{}{}
|
|
247
|
+
}
|
|
248
|
+
return s
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
func (s *Set[T]) Contains(item T) bool {
|
|
252
|
+
_, ok := s.m[item]
|
|
253
|
+
return ok
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
func (s *Set[T]) Add(item T) {
|
|
257
|
+
s.m[item] = struct{}{}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### When to Use Generics
|
|
262
|
+
|
|
263
|
+
| Use generics | Don't use generics |
|
|
264
|
+
|--------------|-------------------|
|
|
265
|
+
| Collection utilities (Map, Filter, Reduce) | Business logic (unclear types) |
|
|
266
|
+
| Data structures (Set, Queue, Stack) | When `any` or `interface{}` suffices |
|
|
267
|
+
| Algorithms that work on multiple types | When only 1-2 types will ever be used |
|
|
268
|
+
| Type-safe wrappers | When it hurts readability |
|
|
269
|
+
|
|
270
|
+
## Pointer Types
|
|
271
|
+
|
|
272
|
+
**Decision table — pointer vs value:**
|
|
273
|
+
|
|
274
|
+
| Condition | Use Pointer | Use Value |
|
|
275
|
+
|-----------|-------------|-----------|
|
|
276
|
+
| Struct > 64 bytes | Yes — avoid copy cost | |
|
|
277
|
+
| Needs mutation | Yes | |
|
|
278
|
+
| Implements interface with pointer receiver | Yes | |
|
|
279
|
+
| Optional / nullable field | Yes (`*string`) | |
|
|
280
|
+
| Small struct (< 4 fields, no slices/maps) | | Yes |
|
|
281
|
+
| Immutable data | | Yes |
|
|
282
|
+
| Map key | | Yes (pointers can't be map keys) |
|
|
283
|
+
| Concurrency without sync | | Yes (value copy is safe) |
|
|
284
|
+
|
|
285
|
+
```go
|
|
286
|
+
// Pointer — large struct, needs mutation
|
|
287
|
+
func (s *Service) UpdateUser(ctx context.Context, user *User) error {
|
|
288
|
+
user.UpdatedAt = time.Now()
|
|
289
|
+
return s.repo.Save(ctx, user)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Value — small, immutable
|
|
293
|
+
type Point struct {
|
|
294
|
+
X, Y float64
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
func Distance(a, b Point) float64 {
|
|
298
|
+
dx := a.X - b.X
|
|
299
|
+
dy := a.Y - b.Y
|
|
300
|
+
return math.Sqrt(dx*dx + dy*dy)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Optional fields
|
|
304
|
+
type UpdateInput struct {
|
|
305
|
+
Name *string `json:"name,omitempty"` // nil = don't update
|
|
306
|
+
Email *string `json:"email,omitempty"` // nil = don't update
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## When to Use
|
|
311
|
+
|
|
312
|
+
Apply when reviewing Go data structure usage. Flag violations as:
|
|
313
|
+
- **CRITICAL**: Writing to nil map, not reassigning append result, concurrent map access without sync
|
|
314
|
+
- **WARNING**: Returning internal slice without copy, using sync.Map for general concurrent access
|
|
315
|
+
- **SUGGESTION**: Missing pre-allocation, using arrays instead of slices, unnecessary pointer for small types
|