voidmachine 0.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +123 -4
- package/bin/void-harness.mjs +12 -0
- package/bin/void-machine.mjs +12 -0
- package/core-assets/.claude-plugin/plugin.json +253 -0
- package/core-assets/.gitkeep +0 -0
- package/core-assets/PHILOSOPHY.md +218 -0
- package/core-assets/PROJECT-DOCTRINE.template.md +14 -0
- package/core-assets/adapters/security/manifest.yaml +96 -0
- package/core-assets/agents/.gitkeep +0 -0
- package/core-assets/agents/accessibility-specialist.md +59 -0
- package/core-assets/agents/api-integration-engineer.md +59 -0
- package/core-assets/agents/code-explorer.md +94 -0
- package/core-assets/agents/code-explorer.source +7 -0
- package/core-assets/agents/data-migration-engineer.md +59 -0
- package/core-assets/agents/devex-docs-engineer.md +57 -0
- package/core-assets/agents/doctrine-critic.md +91 -0
- package/core-assets/agents/doctrine-critic.source +11 -0
- package/core-assets/agents/domain-architect.md +56 -0
- package/core-assets/agents/experience-designer.md +59 -0
- package/core-assets/agents/frontend-engineer.md +60 -0
- package/core-assets/agents/independent-code-reviewer.md +61 -0
- package/core-assets/agents/migration-planner.md +97 -0
- package/core-assets/agents/migration-planner.source +7 -0
- package/core-assets/agents/observability-sre-engineer.md +59 -0
- package/core-assets/agents/pdf-specialist.md +58 -0
- package/core-assets/agents/performance-engineer.md +58 -0
- package/core-assets/agents/product-challenger.md +55 -0
- package/core-assets/agents/security-engineer.md +66 -0
- package/core-assets/agents/silent-failure-hunter.md +94 -0
- package/core-assets/agents/silent-failure-hunter.source +8 -0
- package/core-assets/agents/solution-architect.md +57 -0
- package/core-assets/agents/test-qa-engineer.md +60 -0
- package/core-assets/agents/type-design-analyzer.md +93 -0
- package/core-assets/agents/type-design-analyzer.source +8 -0
- package/core-assets/agents/visual-craft-director.md +62 -0
- package/core-assets/codex/hooks.json +157 -0
- package/core-assets/contract-history/visual-craft-director/v2.yaml +43 -0
- package/core-assets/data/catalog.v3.json +10479 -0
- package/core-assets/data/certification.json +1800 -0
- package/core-assets/data/identity.json +8 -0
- package/core-assets/data/model.json +4226 -0
- package/core-assets/enforce/ci-enforce.sh +183 -0
- package/core-assets/hooks/_checks.sh +145 -0
- package/core-assets/hooks/_hooklib.sh +163 -0
- package/core-assets/hooks/_syntax-worker.cjs +503 -0
- package/core-assets/hooks/_void-hook.mjs +5459 -0
- package/core-assets/hooks/activation-meter.sh +13 -0
- package/core-assets/hooks/anti-ai-slop-grep.sh +38 -0
- package/core-assets/hooks/auto-format.sh +9 -0
- package/core-assets/hooks/axe-precommit.sh +35 -0
- package/core-assets/hooks/block-dangerous-bash.sh +10 -0
- package/core-assets/hooks/block-protected-push.sh +81 -0
- package/core-assets/hooks/boundary-direction-check.sh +10 -0
- package/core-assets/hooks/control-character-grep.sh +10 -0
- package/core-assets/hooks/fowler-refactors.txt +71 -0
- package/core-assets/hooks/large-cl-grep.sh +9 -0
- package/core-assets/hooks/llm-cost-precommit.sh +55 -0
- package/core-assets/hooks/migration-lint.sh +58 -0
- package/core-assets/hooks/migration-pr-template.sh +55 -0
- package/core-assets/hooks/no-ai-design-slop.sh +10 -0
- package/core-assets/hooks/no-any-grep.sh +10 -0
- package/core-assets/hooks/no-as-cast-grep.sh +10 -0
- package/core-assets/hooks/no-console-log-grep.sh +10 -0
- package/core-assets/hooks/no-null-grep.sh +10 -0
- package/core-assets/hooks/no-only-no-skip.sh +10 -0
- package/core-assets/hooks/outcome-meter.sh +13 -0
- package/core-assets/hooks/pre-PR-review-evidence.sh +47 -0
- package/core-assets/hooks/protect-sensitive-files.sh +10 -0
- package/core-assets/hooks/refactor-named-grep.sh +49 -0
- package/core-assets/hooks/secret-in-content.sh +10 -0
- package/core-assets/hooks/sessionstart-context.sh +9 -0
- package/core-assets/hooks/stop-typecheck.sh +9 -0
- package/core-assets/hooks/tdd-guard.md +90 -0
- package/core-assets/hooks/tdd-guard.sh +10 -0
- package/core-assets/hooks/test-name-lint.sh +10 -0
- package/core-assets/hooks/tidying-commit-prefix.sh +37 -0
- package/core-assets/hooks/trim-large-output.sh +9 -0
- package/core-assets/hooks/tsc-noemit-precommit.sh +22 -0
- package/core-assets/hooks/ubiquitous-language-lint.sh +58 -0
- package/core-assets/hooks/viewport-screenshot-gate.sh +48 -0
- package/core-assets/modules/.gitkeep +0 -0
- package/core-assets/packs/pack-mobile/skills/void-eas-build-profile/.source +7 -0
- package/core-assets/packs/pack-mobile/skills/void-eas-build-profile/SKILL.md +164 -0
- package/core-assets/packs/pack-mobile/skills/void-eas-build-profile/harness.yaml +14 -0
- package/core-assets/packs/pack-mobile/skills/void-expo-config-plugins/.source +7 -0
- package/core-assets/packs/pack-mobile/skills/void-expo-config-plugins/SKILL.md +178 -0
- package/core-assets/packs/pack-mobile/skills/void-expo-config-plugins/harness.yaml +14 -0
- package/core-assets/packs/pack-mobile/skills/void-expo-router-pattern/.source +8 -0
- package/core-assets/packs/pack-mobile/skills/void-expo-router-pattern/SKILL.md +209 -0
- package/core-assets/packs/pack-mobile/skills/void-expo-router-pattern/harness.yaml +14 -0
- package/core-assets/packs/pack-mobile/skills/void-ota-update-strategy/.source +7 -0
- package/core-assets/packs/pack-mobile/skills/void-ota-update-strategy/SKILL.md +194 -0
- package/core-assets/packs/pack-mobile/skills/void-ota-update-strategy/harness.yaml +14 -0
- package/core-assets/packs/pack-monorepo/skills/void-dependency-direction/.source +5 -0
- package/core-assets/packs/pack-monorepo/skills/void-dependency-direction/SKILL.md +160 -0
- package/core-assets/packs/pack-monorepo/skills/void-dependency-direction/harness.yaml +14 -0
- package/core-assets/packs/pack-monorepo/skills/void-package-extraction/.source +5 -0
- package/core-assets/packs/pack-monorepo/skills/void-package-extraction/SKILL.md +70 -0
- package/core-assets/packs/pack-monorepo/skills/void-package-extraction/harness.yaml +14 -0
- package/core-assets/packs/pack-monorepo/skills/void-service-package/.source +5 -0
- package/core-assets/packs/pack-monorepo/skills/void-service-package/SKILL.md +122 -0
- package/core-assets/packs/pack-monorepo/skills/void-service-package/harness.yaml +14 -0
- package/core-assets/packs/pack-monorepo/skills/void-turbo-pipeline-tuning/.source +7 -0
- package/core-assets/packs/pack-monorepo/skills/void-turbo-pipeline-tuning/SKILL.md +116 -0
- package/core-assets/packs/pack-monorepo/skills/void-turbo-pipeline-tuning/harness.yaml +14 -0
- package/core-assets/packs/pack-nextjs/skills/void-cache-component-pattern/.source +5 -0
- package/core-assets/packs/pack-nextjs/skills/void-cache-component-pattern/SKILL.md +162 -0
- package/core-assets/packs/pack-nextjs/skills/void-cache-component-pattern/harness.yaml +14 -0
- package/core-assets/packs/pack-nextjs/skills/void-instrumentation-setup/.source +5 -0
- package/core-assets/packs/pack-nextjs/skills/void-instrumentation-setup/SKILL.md +161 -0
- package/core-assets/packs/pack-nextjs/skills/void-instrumentation-setup/harness.yaml +14 -0
- package/core-assets/packs/pack-nextjs/skills/void-loading-error-boundaries/.source +5 -0
- package/core-assets/packs/pack-nextjs/skills/void-loading-error-boundaries/SKILL.md +176 -0
- package/core-assets/packs/pack-nextjs/skills/void-loading-error-boundaries/harness.yaml +14 -0
- package/core-assets/packs/pack-nextjs/skills/void-parallel-routes-slots/.source +5 -0
- package/core-assets/packs/pack-nextjs/skills/void-parallel-routes-slots/SKILL.md +129 -0
- package/core-assets/packs/pack-nextjs/skills/void-parallel-routes-slots/harness.yaml +14 -0
- package/core-assets/packs/pack-nextjs/skills/void-route-group-decision/.source +5 -0
- package/core-assets/packs/pack-nextjs/skills/void-route-group-decision/SKILL.md +107 -0
- package/core-assets/packs/pack-nextjs/skills/void-route-group-decision/harness.yaml +14 -0
- package/core-assets/packs/pack-pwa/skills/void-install-prompt-ux/.source +5 -0
- package/core-assets/packs/pack-pwa/skills/void-install-prompt-ux/SKILL.md +153 -0
- package/core-assets/packs/pack-pwa/skills/void-install-prompt-ux/harness.yaml +14 -0
- package/core-assets/packs/pack-pwa/skills/void-manifest-checklist/.source +5 -0
- package/core-assets/packs/pack-pwa/skills/void-manifest-checklist/SKILL.md +204 -0
- package/core-assets/packs/pack-pwa/skills/void-manifest-checklist/harness.yaml +14 -0
- package/core-assets/packs/pack-pwa/skills/void-offline-first-mutation/.source +8 -0
- package/core-assets/packs/pack-pwa/skills/void-offline-first-mutation/SKILL.md +266 -0
- package/core-assets/packs/pack-pwa/skills/void-offline-first-mutation/harness.yaml +14 -0
- package/core-assets/packs/pack-pwa/skills/void-service-worker-strategy/.source +5 -0
- package/core-assets/packs/pack-pwa/skills/void-service-worker-strategy/SKILL.md +178 -0
- package/core-assets/packs/pack-pwa/skills/void-service-worker-strategy/harness.yaml +14 -0
- package/core-assets/packs/pack-react/skills/void-accessibility-check/.source +8 -0
- package/core-assets/packs/pack-react/skills/void-accessibility-check/SKILL.md +136 -0
- package/core-assets/packs/pack-react/skills/void-accessibility-check/harness.yaml +14 -0
- package/core-assets/packs/pack-react/skills/void-client-vs-server-component/.source +5 -0
- package/core-assets/packs/pack-react/skills/void-client-vs-server-component/SKILL.md +116 -0
- package/core-assets/packs/pack-react/skills/void-client-vs-server-component/harness.yaml +14 -0
- package/core-assets/packs/pack-react/skills/void-form-pattern/.source +7 -0
- package/core-assets/packs/pack-react/skills/void-form-pattern/SKILL.md +157 -0
- package/core-assets/packs/pack-react/skills/void-form-pattern/harness.yaml +14 -0
- package/core-assets/packs/pack-react/skills/void-state-architecture/.source +5 -0
- package/core-assets/packs/pack-react/skills/void-state-architecture/SKILL.md +160 -0
- package/core-assets/packs/pack-react/skills/void-state-architecture/harness.yaml +14 -0
- package/core-assets/packs/pack-server/skills/void-background-job-pattern/.source +6 -0
- package/core-assets/packs/pack-server/skills/void-background-job-pattern/SKILL.md +214 -0
- package/core-assets/packs/pack-server/skills/void-background-job-pattern/harness.yaml +14 -0
- package/core-assets/packs/pack-server/skills/void-drizzle-migration-safe/.source +6 -0
- package/core-assets/packs/pack-server/skills/void-drizzle-migration-safe/SKILL.md +168 -0
- package/core-assets/packs/pack-server/skills/void-drizzle-migration-safe/harness.yaml +14 -0
- package/core-assets/packs/pack-server/skills/void-env-validation/.source +6 -0
- package/core-assets/packs/pack-server/skills/void-env-validation/SKILL.md +131 -0
- package/core-assets/packs/pack-server/skills/void-env-validation/harness.yaml +14 -0
- package/core-assets/packs/pack-server/skills/void-rate-limit-strategy/.source +6 -0
- package/core-assets/packs/pack-server/skills/void-rate-limit-strategy/SKILL.md +149 -0
- package/core-assets/packs/pack-server/skills/void-rate-limit-strategy/harness.yaml +14 -0
- package/core-assets/packs/pack-server/skills/void-server-action/.source +7 -0
- package/core-assets/packs/pack-server/skills/void-server-action/SKILL.md +181 -0
- package/core-assets/packs/pack-server/skills/void-server-action/harness.yaml +14 -0
- package/core-assets/packs/pack-server/skills/void-testing-server-modules/.source +7 -0
- package/core-assets/packs/pack-server/skills/void-testing-server-modules/SKILL.md +73 -0
- package/core-assets/packs/pack-server/skills/void-testing-server-modules/harness.yaml +14 -0
- package/core-assets/packs/pack-server/skills/void-webhook-handler-pattern/.source +7 -0
- package/core-assets/packs/pack-server/skills/void-webhook-handler-pattern/SKILL.md +205 -0
- package/core-assets/packs/pack-server/skills/void-webhook-handler-pattern/harness.yaml +14 -0
- package/core-assets/policies/core.yaml +95 -0
- package/core-assets/policies/ui.yaml +23 -0
- package/core-assets/profiles/base.yaml +29 -0
- package/core-assets/profiles/expo-config.yaml +36 -0
- package/core-assets/profiles/expo.yaml +35 -0
- package/core-assets/profiles/monorepo.yaml +33 -0
- package/core-assets/profiles/nextjs-config.yaml +31 -0
- package/core-assets/profiles/nextjs.yaml +31 -0
- package/core-assets/profiles/node-server.yaml +31 -0
- package/core-assets/profiles/pwa.yaml +33 -0
- package/core-assets/profiles/react.yaml +39 -0
- package/core-assets/profiles/sql.yaml +39 -0
- package/core-assets/profiles/typescript.yaml +39 -0
- package/core-assets/skills/.gitkeep +0 -0
- package/core-assets/skills/void-accessibility/.source +15 -0
- package/core-assets/skills/void-accessibility/SKILL.md +275 -0
- package/core-assets/skills/void-accessibility/harness.yaml +17 -0
- package/core-assets/skills/void-api-and-interface-design/.source +13 -0
- package/core-assets/skills/void-api-and-interface-design/SKILL.md +231 -0
- package/core-assets/skills/void-api-and-interface-design/harness.yaml +16 -0
- package/core-assets/skills/void-async-safety/.source +13 -0
- package/core-assets/skills/void-async-safety/SKILL.md +287 -0
- package/core-assets/skills/void-async-safety/harness.yaml +16 -0
- package/core-assets/skills/void-audit/.source +15 -0
- package/core-assets/skills/void-audit/SKILL.md +83 -0
- package/core-assets/skills/void-audit/harness.yaml +14 -0
- package/core-assets/skills/void-autopilot/.source +21 -0
- package/core-assets/skills/void-autopilot/SKILL.md +358 -0
- package/core-assets/skills/void-autopilot/harness.yaml +14 -0
- package/core-assets/skills/void-brainstorm/.source +14 -0
- package/core-assets/skills/void-brainstorm/SKILL.md +271 -0
- package/core-assets/skills/void-brainstorm/harness.yaml +14 -0
- package/core-assets/skills/void-checkpoint/.source +39 -0
- package/core-assets/skills/void-checkpoint/SKILL.md +227 -0
- package/core-assets/skills/void-checkpoint/harness.yaml +14 -0
- package/core-assets/skills/void-claude-md/.source +15 -0
- package/core-assets/skills/void-claude-md/SKILL.md +180 -0
- package/core-assets/skills/void-claude-md/harness.yaml +14 -0
- package/core-assets/skills/void-code-review/.source +14 -0
- package/core-assets/skills/void-code-review/SKILL.md +232 -0
- package/core-assets/skills/void-code-review/harness.yaml +15 -0
- package/core-assets/skills/void-commit-discipline/.source +9 -0
- package/core-assets/skills/void-commit-discipline/SKILL.md +211 -0
- package/core-assets/skills/void-commit-discipline/harness.yaml +15 -0
- package/core-assets/skills/void-context/.source +15 -0
- package/core-assets/skills/void-context/SKILL.md +167 -0
- package/core-assets/skills/void-context/harness.yaml +14 -0
- package/core-assets/skills/void-debug/.source +11 -0
- package/core-assets/skills/void-debug/SKILL.md +211 -0
- package/core-assets/skills/void-debug/harness.yaml +14 -0
- package/core-assets/skills/void-decide/.source +9 -0
- package/core-assets/skills/void-decide/SKILL.md +147 -0
- package/core-assets/skills/void-decide/harness.yaml +14 -0
- package/core-assets/skills/void-devex-audit/.source +8 -0
- package/core-assets/skills/void-devex-audit/SKILL.md +113 -0
- package/core-assets/skills/void-devex-audit/harness.yaml +15 -0
- package/core-assets/skills/void-doctor/.source +15 -0
- package/core-assets/skills/void-doctor/SKILL.md +83 -0
- package/core-assets/skills/void-doctor/harness.yaml +14 -0
- package/core-assets/skills/void-domain-driven-design/.source +13 -0
- package/core-assets/skills/void-domain-driven-design/SKILL.md +292 -0
- package/core-assets/skills/void-domain-driven-design/harness.yaml +15 -0
- package/core-assets/skills/void-frontend-design/.source +19 -0
- package/core-assets/skills/void-frontend-design/SKILL.md +274 -0
- package/core-assets/skills/void-frontend-design/harness.yaml +17 -0
- package/core-assets/skills/void-functional/.source +14 -0
- package/core-assets/skills/void-functional/SKILL.md +312 -0
- package/core-assets/skills/void-functional/harness.yaml +15 -0
- package/core-assets/skills/void-graph/.source +15 -0
- package/core-assets/skills/void-graph/SKILL.md +80 -0
- package/core-assets/skills/void-graph/harness.yaml +14 -0
- package/core-assets/skills/void-hexagonal-architecture/.source +12 -0
- package/core-assets/skills/void-hexagonal-architecture/SKILL.md +276 -0
- package/core-assets/skills/void-hexagonal-architecture/harness.yaml +15 -0
- package/core-assets/skills/void-implement/.source +39 -0
- package/core-assets/skills/void-implement/SKILL.md +183 -0
- package/core-assets/skills/void-implement/harness.yaml +14 -0
- package/core-assets/skills/void-learn/.source +13 -0
- package/core-assets/skills/void-learn/SKILL.md +226 -0
- package/core-assets/skills/void-learn/harness.yaml +14 -0
- package/core-assets/skills/void-llm-cost-discipline/.source +13 -0
- package/core-assets/skills/void-llm-cost-discipline/SKILL.md +299 -0
- package/core-assets/skills/void-llm-cost-discipline/harness.yaml +15 -0
- package/core-assets/skills/void-make-pdf/.source +9 -0
- package/core-assets/skills/void-make-pdf/SKILL.md +52 -0
- package/core-assets/skills/void-make-pdf/harness.yaml +15 -0
- package/core-assets/skills/void-merge/.source +8 -0
- package/core-assets/skills/void-merge/SKILL.md +111 -0
- package/core-assets/skills/void-merge/harness.yaml +14 -0
- package/core-assets/skills/void-migrations/.source +13 -0
- package/core-assets/skills/void-migrations/SKILL.md +264 -0
- package/core-assets/skills/void-migrations/harness.yaml +17 -0
- package/core-assets/skills/void-observability/.source +12 -0
- package/core-assets/skills/void-observability/SKILL.md +245 -0
- package/core-assets/skills/void-observability/harness.yaml +15 -0
- package/core-assets/skills/void-plan/.source +15 -0
- package/core-assets/skills/void-plan/SKILL.md +239 -0
- package/core-assets/skills/void-plan/harness.yaml +14 -0
- package/core-assets/skills/void-plan-review/.source +12 -0
- package/core-assets/skills/void-plan-review/SKILL.md +128 -0
- package/core-assets/skills/void-plan-review/harness.yaml +15 -0
- package/core-assets/skills/void-qa/.source +15 -0
- package/core-assets/skills/void-qa/SKILL.md +103 -0
- package/core-assets/skills/void-qa/harness.yaml +15 -0
- package/core-assets/skills/void-refactor/.source +9 -0
- package/core-assets/skills/void-refactor/SKILL.md +220 -0
- package/core-assets/skills/void-refactor/harness.yaml +15 -0
- package/core-assets/skills/void-retrospective/.source +9 -0
- package/core-assets/skills/void-retrospective/SKILL.md +71 -0
- package/core-assets/skills/void-retrospective/harness.yaml +15 -0
- package/core-assets/skills/void-security-audit/.source +12 -0
- package/core-assets/skills/void-security-audit/SKILL.md +138 -0
- package/core-assets/skills/void-security-audit/harness.yaml +15 -0
- package/core-assets/skills/void-security-guidance/.source +12 -0
- package/core-assets/skills/void-security-guidance/SKILL.md +255 -0
- package/core-assets/skills/void-security-guidance/harness.yaml +15 -0
- package/core-assets/skills/void-source-driven-development/.source +12 -0
- package/core-assets/skills/void-source-driven-development/SKILL.md +158 -0
- package/core-assets/skills/void-source-driven-development/harness.yaml +15 -0
- package/core-assets/skills/void-tdd/.source +15 -0
- package/core-assets/skills/void-tdd/SKILL.md +394 -0
- package/core-assets/skills/void-tdd/harness.yaml +15 -0
- package/core-assets/skills/void-testing/.source +19 -0
- package/core-assets/skills/void-testing/SKILL.md +301 -0
- package/core-assets/skills/void-testing/harness.yaml +17 -0
- package/core-assets/skills/void-ticket/.source +18 -0
- package/core-assets/skills/void-ticket/SKILL.md +239 -0
- package/core-assets/skills/void-ticket/harness.yaml +14 -0
- package/core-assets/skills/void-typescript-strict/.source +10 -0
- package/core-assets/skills/void-typescript-strict/SKILL.md +294 -0
- package/core-assets/skills/void-typescript-strict/harness.yaml +17 -0
- package/core-assets/skills/void-ui-review/.source +12 -0
- package/core-assets/skills/void-ui-review/SKILL.md +97 -0
- package/core-assets/skills/void-ui-review/harness.yaml +15 -0
- package/core-assets/skills/void-verify/.source +12 -0
- package/core-assets/skills/void-verify/SKILL.md +184 -0
- package/core-assets/skills/void-verify/harness.yaml +15 -0
- package/core-assets/specialists/accessibility-specialist.source +11 -0
- package/core-assets/specialists/accessibility-specialist.yaml +30 -0
- package/core-assets/specialists/api-integration-engineer.source +11 -0
- package/core-assets/specialists/api-integration-engineer.yaml +30 -0
- package/core-assets/specialists/data-migration-engineer.source +11 -0
- package/core-assets/specialists/data-migration-engineer.yaml +30 -0
- package/core-assets/specialists/devex-docs-engineer.source +11 -0
- package/core-assets/specialists/devex-docs-engineer.yaml +29 -0
- package/core-assets/specialists/domain-architect.source +11 -0
- package/core-assets/specialists/domain-architect.yaml +28 -0
- package/core-assets/specialists/experience-designer.source +15 -0
- package/core-assets/specialists/experience-designer.yaml +38 -0
- package/core-assets/specialists/frontend-engineer.source +11 -0
- package/core-assets/specialists/frontend-engineer.yaml +32 -0
- package/core-assets/specialists/independent-code-reviewer.source +10 -0
- package/core-assets/specialists/independent-code-reviewer.yaml +37 -0
- package/core-assets/specialists/migrations.json +15 -0
- package/core-assets/specialists/observability-sre-engineer.source +11 -0
- package/core-assets/specialists/observability-sre-engineer.yaml +30 -0
- package/core-assets/specialists/pdf-specialist.source +11 -0
- package/core-assets/specialists/pdf-specialist.yaml +29 -0
- package/core-assets/specialists/performance-engineer.source +11 -0
- package/core-assets/specialists/performance-engineer.yaml +29 -0
- package/core-assets/specialists/product-challenger.source +10 -0
- package/core-assets/specialists/product-challenger.yaml +27 -0
- package/core-assets/specialists/security-engineer.source +13 -0
- package/core-assets/specialists/security-engineer.yaml +41 -0
- package/core-assets/specialists/solution-architect.source +13 -0
- package/core-assets/specialists/solution-architect.yaml +32 -0
- package/core-assets/specialists/test-qa-engineer.source +14 -0
- package/core-assets/specialists/test-qa-engineer.yaml +35 -0
- package/core-assets/specialists/visual-craft-director.source +17 -0
- package/core-assets/specialists/visual-craft-director.yaml +60 -0
- package/core-assets/templates/github/dependency-audit.mjs +54 -0
- package/core-assets/templates/github/void-dependency-audit.yml +35 -0
- package/core-assets/templates/github/void-security.yml +85 -0
- package/dist/main.js +57001 -0
- package/package.json +66 -4
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: void-merge
|
|
3
|
+
description: Vider la file des PR ouvertes sans casser le dépôt. Ordre par déblocage plutôt que par date, CI verte ET à jour, artefacts générés régénérés, conflits de contenu rendus à leur auteur. Use when merging pull requests.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# merge — voidcorp craftsman edition
|
|
7
|
+
|
|
8
|
+
`void-implement` s'arrête à la PR ouverte. `void-autopilot` laisse à une personne les PR qu'il ne peut
|
|
9
|
+
pas armer. Personne ne dit comment vider la file. Ce geste a l'air trivial jusqu'au moment où il ne l'est pas.
|
|
10
|
+
|
|
11
|
+
**Attribution**: see `.source`.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Ce que ce n'est pas
|
|
16
|
+
|
|
17
|
+
Ce n'est pas une revue. Une PR entrant dans la file est supposée revue par un humain : cette skill
|
|
18
|
+
décide de **mécanique**, jamais de qualité. Elle ne lit pas le diff pour juger le code.
|
|
19
|
+
|
|
20
|
+
Elle ne force rien : pas de `--admin`, pas de force-push, pas de merge d'une PR rouge.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Étape 1 — Lire la file, et savoir ce qui n'y entre pas
|
|
25
|
+
|
|
26
|
+
Lister toutes les PR ouvertes vers la base visée, avec pour chacune : état de mergeabilité,
|
|
27
|
+
conclusion de chaque check, base, brouillon ou non, auteur.
|
|
28
|
+
|
|
29
|
+
Sortent de la file, sans discussion :
|
|
30
|
+
|
|
31
|
+
- **La PR qui existe pour rester ouverte.** Une promotion permanente vers la branche de release
|
|
32
|
+
est verte et mergeable en continu ; la merger est la décision de contenu du cycle, et elle
|
|
33
|
+
appartient à un humain. La nommer dans le rapport, ne jamais la merger.
|
|
34
|
+
- **Les brouillons.**
|
|
35
|
+
- **Ce que l'utilisateur n'a pas visé** quand il a nommé un périmètre.
|
|
36
|
+
|
|
37
|
+
Une file vide est un résultat, pas un échec : le dire et s'arrêter.
|
|
38
|
+
|
|
39
|
+
## Étape 2 — Ordonner par déblocage, jamais par date
|
|
40
|
+
|
|
41
|
+
L'ordre correct n'a aucun rapport avec le numéro ni l'ancienneté.
|
|
42
|
+
|
|
43
|
+
1. **Une PR dont le contenu supprime la cause du conflit d'une autre passe avant elle.** Le cas
|
|
44
|
+
qui a motivé cette skill : la PR réparant le workflow de back-merge était en conflit
|
|
45
|
+
précisément parce que ce back-merge n'avait jamais tourné. Sans le back-merge d'abord, elle
|
|
46
|
+
restait bloquée pour toujours.
|
|
47
|
+
2. À défaut de relation, **le moindre conflit d'abord** : ce qui se merge sans rien toucher, puis
|
|
48
|
+
ce qui demande une régénération.
|
|
49
|
+
|
|
50
|
+
Chercher la relation explicitement : une PR en conflit avec la base, dont une autre PR ouverte (ou
|
|
51
|
+
un geste manquant) explique le conflit, attend cette autre.
|
|
52
|
+
|
|
53
|
+
## Étape 3 — Trois conditions pour merger, toutes nécessaires
|
|
54
|
+
|
|
55
|
+
| Condition | Ce qu'elle écarte |
|
|
56
|
+
|---|---|
|
|
57
|
+
| Tous les checks **verts** | Un merge qui casse la base |
|
|
58
|
+
| La branche **à jour** avec sa base | Des checks qui ont tourné sur une base disparue |
|
|
59
|
+
| Le merge **propre** | Une résolution faite dans le noir |
|
|
60
|
+
|
|
61
|
+
`BEHIND` n'est pas un feu vert. C'est le piège le plus courant : la CI est verte et la PR est
|
|
62
|
+
mergeable, mais les checks portent sur un état qui n'existe plus. Remettre la branche à jour,
|
|
63
|
+
**réattendre la CI**, puis merger.
|
|
64
|
+
|
|
65
|
+
Ne jamais contourner un refus de la protection de branche : c'est le garde-fou, au bon endroit,
|
|
66
|
+
et le seul qui connaisse l'état réel côté serveur.
|
|
67
|
+
|
|
68
|
+
## Étape 4 — Résoudre le mécanique, rendre le contenu
|
|
69
|
+
|
|
70
|
+
Deux natures de conflit, une seule automatisable.
|
|
71
|
+
|
|
72
|
+
**Mécanique — un artefact généré.** Bundles, catalogues, index dérivés. On **régénère depuis les
|
|
73
|
+
sources fusionnées**, jamais on ne choisit un côté. Un artefact choisi passe la CI et ment
|
|
74
|
+
ensuite : il ne correspond plus à ses sources.
|
|
75
|
+
|
|
76
|
+
**De contenu — deux intentions se croisent.** La boucle s'arrête sur cette PR et le dit. C'est un
|
|
77
|
+
travail d'auteur.
|
|
78
|
+
|
|
79
|
+
**Cas mixte** : un fichier généré qui porte aussi une décision, comme une version dans un
|
|
80
|
+
manifeste. C'est du **contenu**. Le sens de la valeur décide, pas l'emplacement du fichier. Une
|
|
81
|
+
version en particulier n'est jamais choisie à la main quand un outil de release la possède : la
|
|
82
|
+
question devient « quelle branche fait autorité sur cette valeur », et elle se pose à l'humain.
|
|
83
|
+
|
|
84
|
+
## Étape 5 — Boucler, puis rendre compte
|
|
85
|
+
|
|
86
|
+
Merger une PR rend les suivantes `BEHIND` : la file bouge à chaque tour. Reprendre à l'étape 1
|
|
87
|
+
tant qu'une PR **devient** mergeable.
|
|
88
|
+
|
|
89
|
+
S'arrêter quand plus rien ne progresse, et rendre alors, pour chaque PR restante, la raison exacte
|
|
90
|
+
du blocage — jamais « n'a pas pu être mergée ».
|
|
91
|
+
|
|
92
|
+
Après le dernier merge, vérifier que la base est saine : la suite, les gates du dépôt, et l'état
|
|
93
|
+
de la branche locale.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Anti-rules
|
|
98
|
+
|
|
99
|
+
- MUST NOT merger une PR dont un check n'est pas vert.
|
|
100
|
+
- MUST NOT merger une PR `BEHIND` sans l'avoir remise à jour et avoir réattendu la CI.
|
|
101
|
+
- MUST NOT merger la promotion vers la branche de release.
|
|
102
|
+
- MUST NOT résoudre un conflit de contenu, ni choisir un côté d'un artefact généré.
|
|
103
|
+
- MUST NOT utiliser `--admin`, ni force-pusher une branche protégée.
|
|
104
|
+
- MUST NOT juger la qualité du code : la revue est un geste humain, déjà fait.
|
|
105
|
+
|
|
106
|
+
## Composition
|
|
107
|
+
|
|
108
|
+
- **Amont — `void-implement`** ouvre les PR que cette skill draine ; **`void-autopilot`** lui laisse celles qu'il
|
|
109
|
+
rend à une personne (chemin protégé, verdict non prouvé, branche qui déploie).
|
|
110
|
+
- **Avec `void-verify`** : après le dernier merge, la base se prouve, elle ne se suppose pas.
|
|
111
|
+
- **Avec `void-commit-discipline`** : un commit de merge dit pourquoi il a lieu, comme les autres.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Harness metadata for this skill. Not part of the Agent Skills
|
|
2
|
+
# specification, and never copied into a consumer project: the SKILL.md
|
|
3
|
+
# beside it stays portable and validates against the official six fields.
|
|
4
|
+
# Read by this repository's graph, and by the installer for `runtimes`.
|
|
5
|
+
kind: action
|
|
6
|
+
owner: folpe
|
|
7
|
+
runtimes: [claude, codex]
|
|
8
|
+
enforcement:
|
|
9
|
+
floor: ci
|
|
10
|
+
inline:
|
|
11
|
+
claude: active
|
|
12
|
+
codex: active
|
|
13
|
+
hermes: ci-only
|
|
14
|
+
eval_targets: [claude/anthropic/opus]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Sources for `void-migrations` skill (see `docs/plans/skill-audits/void-migrations.md` for full audit):
|
|
2
|
+
|
|
3
|
+
- GoCardless "Zero-Downtime Postgres Migrations" — https://gocardless.com/blog/zero-downtime-postgres-migrations-the-hard-parts/ — foundation, locking analysis + two-phase patterns
|
|
4
|
+
- Strong Migrations (Rails) — https://github.com/ankane/strong_migrations — rule catalog ported to TS/Drizzle
|
|
5
|
+
- Drizzle migrations docs — https://orm.drizzle.team/docs/migrations — tactical syntax
|
|
6
|
+
- Neon branching — https://neon.tech/docs/introduction/branching — test on dev branch first
|
|
7
|
+
- Supabase migration patterns — https://supabase.com/docs/guides/cli/local-development
|
|
8
|
+
- pgroll (Xata) — https://github.com/xataio/pgroll — multi-version online schema escape hatch
|
|
9
|
+
- Postgres ALTER TABLE locking docs — https://www.postgresql.org/docs/current/sql-altertable.html
|
|
10
|
+
|
|
11
|
+
Strategy: original. No single TS source covers this; combined the disciplined narrative (GoCardless) with the rule catalog (Strong Migrations) and the void-stack tactical layer (Drizzle + Neon).
|
|
12
|
+
|
|
13
|
+
Companion hooks: migration-lint, migration-pr-template.
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: void-migrations
|
|
3
|
+
description: Zero-downtime Postgres migrations. Two-phase changes, batched backfills, locking analysis, banned DDL patterns, CONCURRENTLY indexes, dev branch test, immutable after merge. Use on DB schema changes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# migrations — voidcorp craftsman edition
|
|
7
|
+
|
|
8
|
+
A "simple" `ALTER TABLE ADD COLUMN NOT NULL DEFAULT 'x'` on a 10M-row Postgres table locks writes for minutes. A "harmless" `RENAME COLUMN` breaks active requests. This skill encodes the lessons so the first migration in a new project gets them too.
|
|
9
|
+
|
|
10
|
+
**Attribution**: see `.source`. Foundation: GoCardless "Zero-Downtime Postgres Migrations" + Strong Migrations (Ruby) + Drizzle docs + Neon branching.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## The two-phase change pattern
|
|
15
|
+
|
|
16
|
+
Risky DDL goes through TWO migrations + a deploy step in between:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
1. Migration A — backwards-compatible schema change
|
|
20
|
+
(add nullable column / add new column / drop NOT NULL constraint)
|
|
21
|
+
2. Deploy code that handles both shapes (old AND new)
|
|
22
|
+
3. Backfill (batched, with progress logs)
|
|
23
|
+
4. Migration B — tighten the constraint
|
|
24
|
+
(add NOT NULL / drop legacy column / rename / type swap)
|
|
25
|
+
5. Deploy code that uses only the new shape
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Doing it in one migration = lock contention + downtime.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Migration PR body — mandatory template
|
|
33
|
+
|
|
34
|
+
Every migration PR includes:
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
## Migration safety
|
|
38
|
+
|
|
39
|
+
- **Table affected**: <name>
|
|
40
|
+
- **Approximate row count**: <number or "< 1k" / "10k–100k" / "100k–1M" / "1M+">
|
|
41
|
+
- **Locking impact**: <AccessExclusiveLock / ShareLock / RowExclusiveLock>
|
|
42
|
+
- Estimated lock duration: <seconds / minutes — be conservative>
|
|
43
|
+
- Acceptable during business hours: <yes / no — if no, schedule>
|
|
44
|
+
- **Backfill strategy**: <none / batched 10k per tx / online via pgroll>
|
|
45
|
+
- **Rollback plan**: <how to back this out if it fails in prod>
|
|
46
|
+
- **Tested on dev branch**: <Neon branch SHA / "pglite — table tiny" / N/A>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If any section is missing, the PR is incomplete. The companion hook `migration-pr-template` warns; `void-code-review` blocks.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Banned DDL patterns
|
|
54
|
+
|
|
55
|
+
### `NOT NULL` direct add — banned
|
|
56
|
+
|
|
57
|
+
```sql
|
|
58
|
+
-- banned
|
|
59
|
+
ALTER TABLE orders ADD COLUMN status TEXT NOT NULL DEFAULT 'pending';
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Two-phase:
|
|
63
|
+
|
|
64
|
+
```sql
|
|
65
|
+
-- migration A
|
|
66
|
+
ALTER TABLE orders ADD COLUMN status TEXT;
|
|
67
|
+
-- backfill (batched)
|
|
68
|
+
UPDATE orders SET status = 'pending' WHERE status IS NULL AND id BETWEEN $1 AND $2;
|
|
69
|
+
-- migration B
|
|
70
|
+
ALTER TABLE orders ALTER COLUMN status SET NOT NULL;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### `RENAME COLUMN` direct — banned
|
|
74
|
+
|
|
75
|
+
```sql
|
|
76
|
+
-- banned
|
|
77
|
+
ALTER TABLE users RENAME COLUMN email TO email_address;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Two-phase:
|
|
81
|
+
|
|
82
|
+
```sql
|
|
83
|
+
-- migration A
|
|
84
|
+
ALTER TABLE users ADD COLUMN email_address TEXT;
|
|
85
|
+
-- deploy code that dual-writes both columns
|
|
86
|
+
-- backfill
|
|
87
|
+
UPDATE users SET email_address = email WHERE email_address IS NULL AND id BETWEEN $1 AND $2;
|
|
88
|
+
-- deploy code that reads from email_address
|
|
89
|
+
-- migration B
|
|
90
|
+
ALTER TABLE users DROP COLUMN email;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Column type change on a large table — banned
|
|
94
|
+
|
|
95
|
+
Forces a full table rewrite + AccessExclusiveLock. Two-phase via new column + backfill + swap + drop.
|
|
96
|
+
|
|
97
|
+
### `DROP COLUMN` referenced by active code — banned
|
|
98
|
+
|
|
99
|
+
Deploy code that ignores the column FIRST. Then DROP in a separate migration.
|
|
100
|
+
|
|
101
|
+
### `CREATE INDEX` (blocking) on large table — banned
|
|
102
|
+
|
|
103
|
+
```sql
|
|
104
|
+
-- banned
|
|
105
|
+
CREATE INDEX orders_status_idx ON orders (status);
|
|
106
|
+
-- allowed
|
|
107
|
+
CREATE INDEX CONCURRENTLY orders_status_idx ON orders (status);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`CONCURRENTLY` does not block reads/writes. Slower; safer.
|
|
111
|
+
|
|
112
|
+
### Modifying a merged migration — banned
|
|
113
|
+
|
|
114
|
+
Fix forward via a new migration. Existing environments have already applied the original; mutating it would diverge state.
|
|
115
|
+
|
|
116
|
+
The companion hook `migration-lint` blocks edits to migration files whose SHA is in the merged history.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Backfill discipline
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// pseudo-code — actual: in a Drizzle migration script
|
|
124
|
+
async function backfillOrderStatus(db: Database) {
|
|
125
|
+
const batchSize = 10_000;
|
|
126
|
+
let lastId = 0;
|
|
127
|
+
while (true) {
|
|
128
|
+
const rows = await db.execute(sql`
|
|
129
|
+
UPDATE orders
|
|
130
|
+
SET status = 'pending'
|
|
131
|
+
WHERE status IS NULL AND id > ${lastId}
|
|
132
|
+
ORDER BY id ASC
|
|
133
|
+
LIMIT ${batchSize}
|
|
134
|
+
RETURNING id
|
|
135
|
+
`);
|
|
136
|
+
if (rows.length === 0) break;
|
|
137
|
+
lastId = rows[rows.length - 1].id;
|
|
138
|
+
logger.info({ lastId, batchCount: rows.length }, 'backfill_progress');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- Each batch is its own transaction.
|
|
144
|
+
- Batch size: 10k by default (tune per table).
|
|
145
|
+
- Progress logged via structured logger (composes with `void-observability`).
|
|
146
|
+
- Idempotent: rerunning resumes from `lastId`.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Drizzle workflow
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# generate from schema change
|
|
154
|
+
drizzle-kit generate
|
|
155
|
+
|
|
156
|
+
# HAND-REVIEW the produced SQL — drizzle-kit does not encode locking-aware patterns
|
|
157
|
+
# adjust to two-phase where needed, add CONCURRENTLY for indexes, etc.
|
|
158
|
+
|
|
159
|
+
# apply to dev branch
|
|
160
|
+
bunx drizzle-kit migrate --config drizzle.dev.config.ts
|
|
161
|
+
|
|
162
|
+
# integration test the migration (composes with void-tdd)
|
|
163
|
+
bunx vitest run tests/migrations/
|
|
164
|
+
|
|
165
|
+
# PR with the template
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Auto-generated migrations are starting points, not deliverables.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Testing migrations
|
|
173
|
+
|
|
174
|
+
### Integration tests (composes with `void-tdd`)
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
test('migration 0042 preserves existing order data', async () => {
|
|
178
|
+
const db = await createTestDb({ seed: 'pre-0042-snapshot.sql' });
|
|
179
|
+
await applyMigration('0042');
|
|
180
|
+
const order = await db.select().from(orders).where(eq(orders.id, knownId)).get();
|
|
181
|
+
expect(order.status).toBe('pending');
|
|
182
|
+
// ... assertions on preserved fields ...
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Tests run on pglite for small tables, on Neon dev branch for large ones.
|
|
187
|
+
|
|
188
|
+
### Lock-impact dry run
|
|
189
|
+
|
|
190
|
+
For migrations on tables > 100k rows, run on the dev branch with `pg_stat_activity` snapshot during the migration. Verify the actual lock acquired matches the predicted one.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Rollback
|
|
195
|
+
|
|
196
|
+
Forward-only is the default — but every migration PR states a rollback plan, even if it is "create a new migration that reverses the change."
|
|
197
|
+
|
|
198
|
+
Some changes cannot be cleanly reversed (data loss on `DROP COLUMN`). Document that explicitly: "Rollback: only via point-in-time restore; this migration is one-way."
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## When to escalate to online schema change tooling
|
|
203
|
+
|
|
204
|
+
For tables > 100M rows or critical 24/7 surface, even two-phase may have a window of concern. Options:
|
|
205
|
+
|
|
206
|
+
- **pgroll** (Xata) — multi-version schema, allows reading old shape while new shape exists
|
|
207
|
+
- **pg_repack** — for table rewrites without lock
|
|
208
|
+
- **pt-osc** — Percona, MySQL-flavor (we are Postgres, so less relevant)
|
|
209
|
+
|
|
210
|
+
These are escape hatches. Default discipline (two-phase + batched backfill + CONCURRENTLY) covers > 95% of cases.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Composition with other skills
|
|
215
|
+
|
|
216
|
+
- **With `void-tdd`**: integration tests on pglite or Neon dev branch BEFORE merge.
|
|
217
|
+
- **With `void-observability`**: structured logs at backfill progress; capture `pg_stat_activity` for long migrations.
|
|
218
|
+
- **With `void-security-guidance`**: migration logs MUST NOT include PII.
|
|
219
|
+
- **With `void-code-review`**: dimension `correctness` includes "lock analysis present, banned patterns absent, two-phase where required."
|
|
220
|
+
- **With `void-commit-discipline`**: migration commits' "why" mentions the linked plan + the two-phase decomposition if applicable.
|
|
221
|
+
- **With `void-plan`**: multi-migration schema changes flow through brainstorm + plans.
|
|
222
|
+
- **With `void-domain-driven-design`**: schema changes are downstream of aggregate / value object decisions.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Companion hooks
|
|
227
|
+
|
|
228
|
+
- `migration-lint` (pre-commit on `<config.paths.migrations>`) — greps SQL for banned patterns; tags `// migration-allow: <reason>` for surgical exceptions. See `../../hooks/`.
|
|
229
|
+
- `migration-pr-template` (pre-push when touching migrations) — warns if PR body lacks required sections.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Anti-rules
|
|
234
|
+
|
|
235
|
+
- MUST NOT auto-apply migrations on push to main (manual deploy approval).
|
|
236
|
+
- MUST NOT amend a merged migration.
|
|
237
|
+
- MUST NOT decide schema design (DDD's call).
|
|
238
|
+
- MUST NOT skip the PR body template, even for "tiny" migrations.
|
|
239
|
+
- MUST NOT silently allow banned DDL patterns.
|
|
240
|
+
- MUST NOT skip the dev-branch test step.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## When you are stuck
|
|
245
|
+
|
|
246
|
+
| Problem | Solution |
|
|
247
|
+
|---|---|
|
|
248
|
+
| Migration too risky for two-phase | Consider pgroll for multi-version schema. |
|
|
249
|
+
| Backfill takes hours | Smaller batch size, run during off-peak, or pgroll. |
|
|
250
|
+
| Cannot test on dev branch (no snapshot) | Use anonymized prod snapshot via Neon branching, or pglite for small tables. |
|
|
251
|
+
| Need to fix a merged migration | Forward only — new migration that fixes. |
|
|
252
|
+
| Locking analysis unclear | Run on dev branch with `pg_stat_activity` snapshot. |
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Final rule
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
Every migration → two-phase if risky, batched backfill, CONCURRENTLY for index, banned patterns absent,
|
|
260
|
+
dev branch tested, PR template complete, immutable after merge.
|
|
261
|
+
Otherwise → it is not voidcorp migrations.
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The cheapest place to catch a downtime-inducing migration is before merge.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Harness metadata for this skill. Not part of the Agent Skills
|
|
2
|
+
# specification, and never copied into a consumer project: the SKILL.md
|
|
3
|
+
# beside it stays portable and validates against the official six fields.
|
|
4
|
+
# Read by this repository's graph, and by the installer for `runtimes`.
|
|
5
|
+
kind: standard
|
|
6
|
+
activation: always
|
|
7
|
+
triggers:
|
|
8
|
+
globs: ["**/migrations/**", "**/*.sql"]
|
|
9
|
+
owner: folpe
|
|
10
|
+
runtimes: [claude, codex]
|
|
11
|
+
enforcement:
|
|
12
|
+
floor: ci
|
|
13
|
+
inline:
|
|
14
|
+
claude: pretooluse
|
|
15
|
+
codex: pretooluse
|
|
16
|
+
hermes: ci-only
|
|
17
|
+
eval_targets: [claude/anthropic/opus]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Sources for `void-observability` skill (see `docs/plans/skill-audits/void-observability.md` for full audit):
|
|
2
|
+
|
|
3
|
+
- pino — https://getpino.io — structured logger, fast, dev-pretty mode
|
|
4
|
+
- OpenTelemetry semantic conventions — https://opentelemetry.io/docs/specs/semconv/ — attribute naming, trace/span model, W3C TraceContext
|
|
5
|
+
- Charity Majors "Observability Engineering" — https://www.honeycomb.io/oreilly-observability-engineering — foundation: events over metrics, high-cardinality
|
|
6
|
+
- Sentry best practices — https://docs.sentry.io — breadcrumbs, scopes, fingerprinting, beforeSend redaction
|
|
7
|
+
- Cindy Sridharan "Distributed Systems Observability" — https://www.oreilly.com/library/view/distributed-systems-observability/9781492033431/ — three pillars composed not siloed
|
|
8
|
+
- citypaul/.dotfiles observability notes — logger-only discipline, no console.log
|
|
9
|
+
|
|
10
|
+
Strategy: distill. Stack-specific integration code in pack-nextjs-pwa (Sentry + pino + Vercel Analytics defaults). Skill mandates the discipline.
|
|
11
|
+
|
|
12
|
+
Companion hook: no-console-log-grep.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: void-observability
|
|
3
|
+
description: Structured logs (no string interp), trace IDs end-to-end, error boundaries at async boundaries, anonymized user scope, no PII/secrets ever. Use @repo/core/logger not console.log. Use for prod code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# observability — voidcorp craftsman edition
|
|
7
|
+
|
|
8
|
+
Production debugging starts where observability ended. If you cannot see what happened, you cannot fix it; if you can only guess, you fix the symptom and the bug recurs. This skill codifies what to log, what to trace, what to measure — and just as critically, what NEVER to log (PII, secrets).
|
|
9
|
+
|
|
10
|
+
**Attribution**: see `.source`. Foundation: pino + OpenTelemetry semantic conventions + Charity Majors "Observability Engineering" + Sentry best practices + Sridharan three pillars.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Structured logs only
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// banned
|
|
18
|
+
console.log('user ' + userId + ' did ' + action);
|
|
19
|
+
logger.info(`user ${userId} did ${action}`);
|
|
20
|
+
|
|
21
|
+
// allowed
|
|
22
|
+
logger.info({ userId, action, durationMs }, 'user_action');
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Structured logs are queryable. String-interpolated logs are searchable at best.
|
|
26
|
+
|
|
27
|
+
The companion hook `no-console-log-grep` blocks `console.log` / `console.error` / `console.warn` in business code.
|
|
28
|
+
|
|
29
|
+
### Use `@repo/core/logger` (pino)
|
|
30
|
+
|
|
31
|
+
Provided by `pack-monorepo`. Business code imports `logger`, not pino directly — the adapter pattern lets us swap the backend later without business-code edits.
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { logger } from '@repo/core/logger';
|
|
35
|
+
|
|
36
|
+
logger.info({ userId, orderId }, 'checkout_started');
|
|
37
|
+
logger.error({ err, orderId }, 'payment_failed');
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Levels (standard set, no custom levels)
|
|
41
|
+
|
|
42
|
+
| Level | When |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `fatal` | Unrecoverable — process must exit |
|
|
45
|
+
| `error` | Operation failed; user impact |
|
|
46
|
+
| `warn` | Unexpected but handled |
|
|
47
|
+
| `info` | Significant business event |
|
|
48
|
+
| `void-debug` | Developer-time signal |
|
|
49
|
+
| `trace` | Very granular (rarely committed) |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Trace IDs propagate end-to-end
|
|
54
|
+
|
|
55
|
+
A user request crosses HTTP → service → DB → external API → response. The trace ID follows.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// in pack-nextjs Server Action wrapper
|
|
59
|
+
import { withTraceContext } from '@repo/observability';
|
|
60
|
+
|
|
61
|
+
export const checkoutAction = withTraceContext(async (input: CheckoutInput) => {
|
|
62
|
+
const traceId = getTraceId();
|
|
63
|
+
logger.info({ traceId, cartId: input.cartId }, 'checkout_action');
|
|
64
|
+
// every downstream log inherits traceId via logger.child({ traceId })
|
|
65
|
+
return checkoutCart(deps, input);
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Composes with `void-async-safety` — the trace propagates across job / webhook / queue boundaries via the message envelope.
|
|
70
|
+
|
|
71
|
+
### Default trace format
|
|
72
|
+
|
|
73
|
+
W3C TraceContext (the OpenTelemetry default). Compatible with future vendor swaps (Sentry, Honeycomb, Datadog, OTel collector).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Error boundaries at every async boundary
|
|
78
|
+
|
|
79
|
+
### Client side (React)
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
<ErrorBoundary
|
|
83
|
+
fallback={<ErrorView />}
|
|
84
|
+
onError={(err, info) => Sentry.captureException(err, { extra: info })}
|
|
85
|
+
>
|
|
86
|
+
<Checkout />
|
|
87
|
+
</ErrorBoundary>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Server side
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
async function callStripe(...): Promise<Result<Charge, StripeError>> {
|
|
94
|
+
try {
|
|
95
|
+
const charge = await stripe.charges.create(...);
|
|
96
|
+
return ok(translateCharge(charge));
|
|
97
|
+
} catch (err) {
|
|
98
|
+
logger.error({ err, customerId }, 'stripe_charge_failed');
|
|
99
|
+
return err({ kind: 'stripe_error', cause: serializeError(err) });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The adapter (per `void-hexagonal-architecture`) is where the catch lives. The error is logged WITH context. Then re-rethrown as a typed `Result` error, OR (for truly unexpected) re-rethrown raw so Sentry catches it at the top.
|
|
105
|
+
|
|
106
|
+
### Silent error swallowing — Red Flag
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
// banned
|
|
110
|
+
try { await doSomething(); } catch (e) { /* swallow */ }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Either log it, or rethrow, or both. `catch (e) {}` is rejected.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## High-cardinality attributes are valuable
|
|
118
|
+
|
|
119
|
+
Majors' rule. Log:
|
|
120
|
+
|
|
121
|
+
- User ID (anonymized — `userId: hash(realId)` for Sentry; raw in internal logs only if compliance allows)
|
|
122
|
+
- Org / tenant ID
|
|
123
|
+
- Feature flags active
|
|
124
|
+
- Session ID
|
|
125
|
+
- Browser / device / region
|
|
126
|
+
- Business-meaningful tags (plan tier, signup source, conversion path)
|
|
127
|
+
|
|
128
|
+
The cost is small. The benefit during investigation is "I can filter to the exact 12 users hit by this bug." Cardinality is not the enemy; pre-aggregation is.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Metrics — what to emit
|
|
133
|
+
|
|
134
|
+
| Metric | Why |
|
|
135
|
+
|---|---|
|
|
136
|
+
| Latency p50 / p95 / p99 per endpoint | User-perceived experience |
|
|
137
|
+
| Error rate per endpoint | SLO tracking |
|
|
138
|
+
| Business event counts (signup, checkout, conversion, churn) | Growth signal |
|
|
139
|
+
| Queue depth / lag (jobs, webhooks) | Backlog detection |
|
|
140
|
+
| Cost per business event (LLM tokens, third-party calls) | Composes with `void-llm-cost-discipline` |
|
|
141
|
+
|
|
142
|
+
The skill mandates WHAT. The pack (`pack-nextjs`) provides HOW (Vercel Analytics + Sentry + custom emitters).
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Sentry integration (default)
|
|
147
|
+
|
|
148
|
+
Provided by `pack-nextjs`. Defaults:
|
|
149
|
+
|
|
150
|
+
- `Sentry.setUser({ id: hash(userId) })` — anonymized scope
|
|
151
|
+
- `Sentry.addBreadcrumb` at every business event
|
|
152
|
+
- `beforeSend` redacts known-secret keys + PII attributes
|
|
153
|
+
- Fingerprinting by error class + message hash (deduplicates noise)
|
|
154
|
+
- Performance monitoring at 10% sampling (head-based) in prod, 100% in dev
|
|
155
|
+
|
|
156
|
+
Switch via `voidcorp.config.json` if a project chooses Highlight / OpenObserve / vendor X.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## No PII, no secrets, ever (composes with `void-security-guidance`)
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
// banned
|
|
164
|
+
logger.info(`user ${user.email} signed in with password ${password}`);
|
|
165
|
+
|
|
166
|
+
// allowed
|
|
167
|
+
logger.info({ userId: user.id, event: 'sign_in_success' });
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Logger config redacts at serialization
|
|
171
|
+
|
|
172
|
+
`pack-monorepo` provides:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const logger = pino({
|
|
176
|
+
redact: ['password', 'token', 'apiKey', 'secret', 'authorization', '*.email', '*.phone'],
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Defense in depth. The discipline says "don't log it." The config says "even if you slip, the serialized output drops it." Both layers must hold.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## What NOT to log
|
|
185
|
+
|
|
186
|
+
- Full request bodies (PII / secrets / massive payloads). Log specific fields with explicit allowlist.
|
|
187
|
+
- Passwords, tokens, API keys, session IDs, JWTs (composes with `void-security-guidance`)
|
|
188
|
+
- Email addresses unredacted in production logs (consider hashing or partial redaction depending on compliance)
|
|
189
|
+
- Full database rows (PII risk)
|
|
190
|
+
- LLM full prompts / responses (PII + cost) — log token counts and structural metadata, not content
|
|
191
|
+
- Stack traces with embedded secrets (some Node errors include the secret in the stack)
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Composition with other skills
|
|
196
|
+
|
|
197
|
+
- **With `void-security-guidance`**: PII / secret redaction at log time. Logger config layer is defense in depth.
|
|
198
|
+
- **With `void-debug`**: if visibility is the gap, FIX IT FIRST — add the missing logs / traces — then debug with real signal.
|
|
199
|
+
- **With `void-async-safety`**: trace propagation across job / webhook / queue boundaries.
|
|
200
|
+
- **With `void-hexagonal-architecture`**: error boundaries live at adapter boundaries; structured logging at use-case entry/exit.
|
|
201
|
+
- **With `void-llm-cost-discipline`**: token counts logged at every LLM call site. Cache hit rate logged.
|
|
202
|
+
- **With `void-code-review`**: flags missing observability (no log at use-case entry, no breadcrumb at business event, error swallowing).
|
|
203
|
+
- **With `void-commit-discipline`**: `feat:` commits adding business logic mention the observability surface added.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Companion hooks
|
|
208
|
+
|
|
209
|
+
- `no-console-log-grep` (pre-commit) — fails if `console.log` / `console.error` / `console.warn` in staged business code. Allowed in `scripts/`, `**/*.test.{ts,tsx}` (with explicit allowlist marker). See `../../hooks/`.
|
|
210
|
+
|
|
211
|
+
(Sentry / pino / OTel integration code lives in `pack-nextjs` because stack-specific.)
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Anti-rules
|
|
216
|
+
|
|
217
|
+
- MUST NOT decide alerting policy (ops concern).
|
|
218
|
+
- MUST NOT decide retention windows (compliance concern).
|
|
219
|
+
- MUST NOT silently allow `console.log` in business code.
|
|
220
|
+
- MUST NOT log PII or secrets.
|
|
221
|
+
- MUST NOT swallow errors silently.
|
|
222
|
+
- MUST NOT use custom log levels.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## When you are stuck
|
|
227
|
+
|
|
228
|
+
| Problem | Solution |
|
|
229
|
+
|---|---|
|
|
230
|
+
| Cannot reproduce a bug in prod | Add observability first (logs / breadcrumbs / traces). Wait for next occurrence. |
|
|
231
|
+
| Logger output is overwhelming | Add structured filters in the query, not at the source. The signal you do not log is the one you wish you had. |
|
|
232
|
+
| Logging slows down a hot path | Async / batched log writes via the logger config. Pino is fast; the bottleneck is rarely the logger itself. |
|
|
233
|
+
| Sentry too noisy | Fingerprint better, not "drop the breadcrumb." Noise is a tuning problem, not a discipline problem. |
|
|
234
|
+
| LLM prompts too big to log | Log token counts + structural metadata (kind, length). Never the content. |
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Final rule
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
Production code → structured logs via @repo/core/logger, trace ID propagated, error boundaries present, no PII no secrets.
|
|
242
|
+
Otherwise → it is not voidcorp observability.
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Visibility is the precondition for everything. Earn it once; benefit forever.
|