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,301 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: void-testing
|
|
3
|
+
description: How to write a good test. Behavior over implementation, real code over mocks, factories over beforeEach, pyramid respected, pristine output, no snapshot creep. Use when writing or modifying tests.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# testing — voidcorp craftsman edition
|
|
7
|
+
|
|
8
|
+
`void-tdd` provides the cycle (when to write the test). This skill provides the technique (how to write a good one). Mocking is the last resort. Behavior, not implementation. Factories, not `beforeEach`. Pristine output is a passing condition.
|
|
9
|
+
|
|
10
|
+
**Attribution**: see `.source` in this directory.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Core principles
|
|
15
|
+
|
|
16
|
+
### 1. Test the behavior, not the implementation
|
|
17
|
+
|
|
18
|
+
Assertions describe what the user / consumer of the code observes. They do not describe which private method ran, which collaborator was invoked, which exact internal sequence happened.
|
|
19
|
+
|
|
20
|
+
<Good>
|
|
21
|
+
```typescript
|
|
22
|
+
test('retries failed operations 3 times before giving up', async () => {
|
|
23
|
+
let attempts = 0;
|
|
24
|
+
const op = () => {
|
|
25
|
+
attempts++;
|
|
26
|
+
if (attempts < 3) throw new Error('transient');
|
|
27
|
+
return 'success';
|
|
28
|
+
};
|
|
29
|
+
expect(await retryOperation(op)).toBe('success');
|
|
30
|
+
expect(attempts).toBe(3); // observable: how many times the operation ran
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
</Good>
|
|
34
|
+
|
|
35
|
+
<Bad>
|
|
36
|
+
```typescript
|
|
37
|
+
test('retry', () => {
|
|
38
|
+
const spy = vi.fn().mockRejectedValueOnce(...).mockResolvedValueOnce(...);
|
|
39
|
+
retryOperation(spy);
|
|
40
|
+
expect(spy).toHaveBeenCalledTimes(3); // tests the spy, not the behavior
|
|
41
|
+
expect(retryOperation['_internalDelay']).toBeDefined(); // tests internals
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
</Bad>
|
|
45
|
+
|
|
46
|
+
For UI: query by accessible role / label, not by class or `data-testid`. `data-testid` is the escape hatch when no semantic query works, not the default.
|
|
47
|
+
|
|
48
|
+
For interactive UI, pair the accessible query with the user input that proves the contract:
|
|
49
|
+
`userEvent.keyboard` for keyboard paths, pointer input only for pointer behavior, and visible output
|
|
50
|
+
for state transitions. Test loading, empty, error, success, and partial states only when applicable,
|
|
51
|
+
but make that applicability explicit. Component, hook, and store tests stay at their observable
|
|
52
|
+
boundaries; a broad E2E test does not substitute for the focused regression that identifies which
|
|
53
|
+
contract broke.
|
|
54
|
+
|
|
55
|
+
### 2. Sociable tests over solitary tests
|
|
56
|
+
|
|
57
|
+
Let collaborators run inside the test by default. Only mock at infrastructure boundaries:
|
|
58
|
+
|
|
59
|
+
- HTTP → MSW (Mock Service Worker)
|
|
60
|
+
- DB → pglite (in-memory Postgres) or Neon dev branch
|
|
61
|
+
- Filesystem → `memfs` or a temp directory
|
|
62
|
+
- Time → `vi.useFakeTimers()`
|
|
63
|
+
- Randomness → seeded RNG
|
|
64
|
+
|
|
65
|
+
Mocking a collaborator that does pure computation is a code smell. If you find yourself mocking `formatCurrency()` to test `renderInvoice()`, the design is too coupled — or your test should run `formatCurrency` for real.
|
|
66
|
+
|
|
67
|
+
### 3. Nullable infrastructure pattern (Shore)
|
|
68
|
+
|
|
69
|
+
For the infrastructure that DOES need a test double, the wrapper exposes a `createNull()` variant that returns deterministic / empty results. No mocking library invocation; the constructor handles it.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
class StripeClient {
|
|
73
|
+
static create(apiKey: string): StripeClient { /* real */ }
|
|
74
|
+
static createNull(opts?: { charges?: ChargeFixture[] }): StripeClient { /* in-memory */ }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// in tests:
|
|
78
|
+
const stripe = StripeClient.createNull({ charges: [makeCharge({ amount_cents: 1000 })] });
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The nullable variant is production-typed. Tests do not reach into a mocking framework. The boundary is owned by the domain.
|
|
82
|
+
|
|
83
|
+
### 4. Pristine output
|
|
84
|
+
|
|
85
|
+
After a test passes, the output is clean:
|
|
86
|
+
|
|
87
|
+
- No `console.log` from production code
|
|
88
|
+
- No warnings (React act warnings, deprecation warnings, etc.)
|
|
89
|
+
- No leaked unhandled rejections
|
|
90
|
+
- No leaked timers / open handles
|
|
91
|
+
|
|
92
|
+
Pristine output is a passing condition, not a nice-to-have. Vitest config: `onConsoleLog: 'fail'`.
|
|
93
|
+
|
|
94
|
+
### 5. Release E2E proves the shipped artifact
|
|
95
|
+
|
|
96
|
+
Release proof exercises the immutable deployable artifact, not a development compiler. Keep build
|
|
97
|
+
readiness (the process started and became healthy) separate from application assertions, so a slow
|
|
98
|
+
compile cannot consume the assertion budget or hide a failed startup.
|
|
99
|
+
|
|
100
|
+
Fixtures use the lowest faithful boundary that preserves the behavior under test. Establishing an
|
|
101
|
+
authenticated precondition may use a server/API boundary; the authentication UI remains an E2E
|
|
102
|
+
subject when authentication itself is the behavior being proved.
|
|
103
|
+
|
|
104
|
+
External state is namespaced per run/worker and cleanup is idempotent and bounded, including after
|
|
105
|
+
interruption. Browser storage state is sensitive ephemeral output and belongs under the test output
|
|
106
|
+
directory, never in source control.
|
|
107
|
+
|
|
108
|
+
Test-only security overrides are typed, bounded, and paired with independent proof of production
|
|
109
|
+
defaults and denial behavior. A malformed or out-of-range override falls back to safe production
|
|
110
|
+
defaults. No retry-on-failure, quarantine, skip, or assertion-timeout inflation is a flake fix.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Naming
|
|
115
|
+
|
|
116
|
+
Describe the behavior. Imperative. Specific.
|
|
117
|
+
|
|
118
|
+
<Good>
|
|
119
|
+
- `retries failed operations 3 times before giving up`
|
|
120
|
+
- `rejects payment when card balance is below total`
|
|
121
|
+
- `emits user-created event after first successful login`
|
|
122
|
+
</Good>
|
|
123
|
+
|
|
124
|
+
<Bad>
|
|
125
|
+
- `test retry` (vacuous)
|
|
126
|
+
- `should work` (says nothing)
|
|
127
|
+
- `retryOperation` (function name, not behavior)
|
|
128
|
+
- `it should retry` (the "should" is fluff)
|
|
129
|
+
</Bad>
|
|
130
|
+
|
|
131
|
+
The companion hook `test-name-lint` warns on weak patterns (`test`, `works`, `should` as the entire name).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Fixtures and factories
|
|
136
|
+
|
|
137
|
+
### Factories over `beforeEach`
|
|
138
|
+
|
|
139
|
+
`beforeEach` for environment setup (mount DOM, reset DB, install fake timers). NOT for test data.
|
|
140
|
+
|
|
141
|
+
<Good>
|
|
142
|
+
```typescript
|
|
143
|
+
function makeUser(overrides: Partial<User> = {}): User {
|
|
144
|
+
return {
|
|
145
|
+
id: createUserId('usr_test_001'),
|
|
146
|
+
email: 'user@example.com',
|
|
147
|
+
createdAt: new Date('2026-01-01'),
|
|
148
|
+
...overrides,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
test('rejects suspended users', () => {
|
|
153
|
+
const user = makeUser({ suspended: true });
|
|
154
|
+
expect(authorize(user)).toEqual({ ok: false, error: 'suspended' });
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
</Good>
|
|
158
|
+
|
|
159
|
+
<Bad>
|
|
160
|
+
```typescript
|
|
161
|
+
let user: User;
|
|
162
|
+
beforeEach(() => {
|
|
163
|
+
user = { id: '...', email: '...', /* shared mutable state */ };
|
|
164
|
+
});
|
|
165
|
+
test('rejects suspended users', () => {
|
|
166
|
+
user.suspended = true; // mutates shared state, leaks between tests
|
|
167
|
+
expect(authorize(user)).toEqual({ ok: false, error: 'suspended' });
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
</Bad>
|
|
171
|
+
|
|
172
|
+
### Externalize > 5-line fixtures
|
|
173
|
+
|
|
174
|
+
Inline fixtures are fine when small (< 5 lines). Larger fixtures go to `tests/fixtures/<name>.ts`. Each fixture exposes a factory function with overrides.
|
|
175
|
+
|
|
176
|
+
Heavy data (multi-KB JSON, sample images): load from disk, never inline.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Test pyramid
|
|
181
|
+
|
|
182
|
+
Heuristic ratios for a TS/web project:
|
|
183
|
+
|
|
184
|
+
- **~70% unit tests**: pure functions, business logic, schema validation. Run in < 100ms each.
|
|
185
|
+
- **~20% integration tests**: real infrastructure via pglite / MSW / temp filesystem. Run in < 1s each typically.
|
|
186
|
+
- **~10% E2E tests**: Playwright on critical user paths. Run in seconds.
|
|
187
|
+
|
|
188
|
+
Numbers are a heuristic, not a quota. A solopreneur with strong types may run closer to 50/40/10 because integration tests buy more confidence per unit of effort. Adjust by data, not by tradition.
|
|
189
|
+
|
|
190
|
+
**Inverted pyramid is a smell**: if your E2E suite carries the proof and your unit suite is sparse, your design is probably testing badly (too coupled to make unit tests cheap). Fix the design.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Mocking strategy
|
|
195
|
+
|
|
196
|
+
### When to use what
|
|
197
|
+
|
|
198
|
+
| Test target | Boundary technique |
|
|
199
|
+
|---|---|
|
|
200
|
+
| Pure business logic | No mock. Real code. |
|
|
201
|
+
| HTTP client → external API | MSW handlers in `tests/msw/handlers.ts` (or pglite for inbound HTTP if testing a Next.js route handler) |
|
|
202
|
+
| ORM → Postgres | pglite (in-memory) for unit-of-work. Neon dev branch for E2E-like integration |
|
|
203
|
+
| Date / Time | `vi.useFakeTimers()`, advance explicitly |
|
|
204
|
+
| `Math.random` / UUID | seeded RNG passed via parameter (composes with `void-hexagonal-architecture` port pattern) |
|
|
205
|
+
| File system | `memfs` or temp directory |
|
|
206
|
+
| Server Actions | invoke directly; the sandbox is light |
|
|
207
|
+
|
|
208
|
+
### What NOT to mock
|
|
209
|
+
|
|
210
|
+
- A pure function (run it)
|
|
211
|
+
- A business service (compose, do not mock)
|
|
212
|
+
- The framework router (use the framework's testing utilities)
|
|
213
|
+
- The ORM at the unit level (use pglite — see `void-tdd` anti-pattern)
|
|
214
|
+
|
|
215
|
+
The companion hook `no-business-mock` warns on `vi.mock('@/services/...')` patterns.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Banned practices
|
|
220
|
+
|
|
221
|
+
### Snapshot testing — banned by default
|
|
222
|
+
|
|
223
|
+
Snapshots devolve into "update on green" — the test passes regardless of correctness. Allowed only for:
|
|
224
|
+
|
|
225
|
+
- **UI visual regression**: in `**/__visual__/**` directory with documented review process
|
|
226
|
+
- **Compiler output sanity** (`__generated__/` snapshots): same constraint
|
|
227
|
+
|
|
228
|
+
Each snapshot has a reason. No `.toMatchSnapshot()` outside the whitelist without explicit code-review approval.
|
|
229
|
+
|
|
230
|
+
### `.only` / `.skip` / `fdescribe` / `xit`
|
|
231
|
+
|
|
232
|
+
Banned in committed code. They mean "I will not run this." If you mean "this case is intentionally not yet tested," write a `it.todo('description')` — the test runner reports todos.
|
|
233
|
+
|
|
234
|
+
The companion hook `no-only-no-skip` blocks commits with `.only` / `fdescribe` / `xit` in the staged diff (allowed in `**/__skip-on-purpose__/**` whitelist with justifying comment).
|
|
235
|
+
|
|
236
|
+
### Implementation spies as primary assertion
|
|
237
|
+
|
|
238
|
+
`expect(spy).toHaveBeenCalledWith(...)` is for "did the side effect at this boundary happen" — only at infrastructure boundaries. It is not the assertion for business behavior.
|
|
239
|
+
|
|
240
|
+
### `describe.each` for unrelated scenarios
|
|
241
|
+
|
|
242
|
+
`describe.each([...])` is for genuinely parametric tests (boundary values, equivalence classes). It is NOT for grouping 5 different scenarios that share scaffolding — that hides the differences.
|
|
243
|
+
|
|
244
|
+
### Inline DB mocks for business-layer tests
|
|
245
|
+
|
|
246
|
+
Use pglite or dev branch. Mocking Drizzle breaks at every schema change while protecting nothing real.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Composition with other skills
|
|
251
|
+
|
|
252
|
+
- **With `void-tdd`**: `void-tdd` is the cycle (when), `void-testing` is the technique (how). RED step delegates the *how* here.
|
|
253
|
+
- **With the mutation gate** (strict TDD, when the project declares a mutation runner): a high survivor rate is a `void-testing` signal — the tests are not asserting on the right things. KILL step iterates back here.
|
|
254
|
+
- **With `void-typescript-strict`**: tests use branded types from production. A test needing `as any` is signaling a missing factory or brittle type.
|
|
255
|
+
- **With `void-hexagonal-architecture`**: ports tested with nullable infrastructure. In-memory adapters owned by the domain.
|
|
256
|
+
- **With `void-migrations`**: DB migrations have their own discipline; this skill's pyramid does not apply to migration tests.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Companion hooks
|
|
261
|
+
|
|
262
|
+
- **`no-only-no-skip`** — block on `.only` / `fdescribe` / `xit` / `.skip` in staged diff (whitelist: `**/__skip-on-purpose__/**`)
|
|
263
|
+
- **`test-name-lint`** — warn on weak test names matching `/^\s*(test|works|should)\s*$/i`
|
|
264
|
+
- **`no-business-mock`** — warn on `vi.mock\('@/(services|domain)/...'\)` patterns
|
|
265
|
+
- **`no-snapshot-default`** — warn on new `.toMatchSnapshot()` outside `**/__visual__/**` whitelist
|
|
266
|
+
|
|
267
|
+
See `../../hooks/`.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Anti-rules
|
|
272
|
+
|
|
273
|
+
- MUST NOT decide WHETHER a test exists. That is `void-tdd`'s Iron Law.
|
|
274
|
+
- MUST NOT decide coverage thresholds. That is `void-tdd`'s 100%-on-business-layer default + documented exceptions.
|
|
275
|
+
- MUST NOT decide architecture (what is a port, what is an adapter). Hexagonal owns that.
|
|
276
|
+
- MUST NOT decide framework specifics (which Vitest reporter, Playwright trace mode). Pack-level config.
|
|
277
|
+
- MUST NOT silently allow snapshot creep.
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## When you are stuck
|
|
282
|
+
|
|
283
|
+
| Problem | Solution |
|
|
284
|
+
|---|---|
|
|
285
|
+
| Test feels brittle, breaks on refactor | Coupled to implementation. Test the behavior at the boundary instead. |
|
|
286
|
+
| Need to mock 5 things to test 1 thing | Coupling smell. Inject dependencies via parameters. Compose with `void-hexagonal-architecture`. |
|
|
287
|
+
| Fixture is huge | Externalize to `tests/fixtures/`. Use a factory with overrides. |
|
|
288
|
+
| Test name is weak | Describe the behavior, not the function. Imperative. |
|
|
289
|
+
| Snapshot wants to update on every change | Snapshot is wrong. Replace with explicit assertions. |
|
|
290
|
+
| Pyramid feels wrong | Adjust by data after 50+ tests. The 70/20/10 is a heuristic. |
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Final rule
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
A test → asserts behavior, uses real code where possible, runs deterministically, produces pristine output.
|
|
298
|
+
Otherwise → it is not a voidcorp testing test.
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Tests prove behavior. They are a specification, not a record.
|
|
@@ -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: ["**/*.test.ts", "**/*.spec.ts"]
|
|
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,18 @@
|
|
|
1
|
+
Sources for `void-ticket` skill (see `docs/plans/skill-audits/void-ticket.md` for full audit):
|
|
2
|
+
|
|
3
|
+
- loomcrafthq/ticket-craft — reference for the platform-agnostic tracker template
|
|
4
|
+
(Context / Scope / Technical Specs / AC / DoD / Edge Cases) and T-shirt sizing.
|
|
5
|
+
KEEP EXTERNAL as a generic fallback; this skill is the doctrine-aware,
|
|
6
|
+
harness-composing version. Distilled, not vendored.
|
|
7
|
+
- Composes upstream: brainstorm, plan (the thinking
|
|
8
|
+
this skill captures). Downstream: implement (consumes the ticket and
|
|
9
|
+
its declared passes).
|
|
10
|
+
|
|
11
|
+
Strategy: author + distill. Three deliberate additions over ticket-craft:
|
|
12
|
+
1. INGEST-first: the ticket records decisions already made (spec, plan, ADR,
|
|
13
|
+
conversation), it never invents scope.
|
|
14
|
+
2. Estimate + labels + parent are REQUIRED native fields, not optional metadata.
|
|
15
|
+
This is the observed baseline failure (tickets shipped without them).
|
|
16
|
+
3. Two new slots tie it to the harness: a TDD-mode-per-ticket and a
|
|
17
|
+
"runner passes that apply" declaration, so implement does not
|
|
18
|
+
re-derive the conditional passes. Plus an all-angles sweep before saving.
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: void-ticket
|
|
3
|
+
description: Use when turning a finished brainstorm, plan, or design decision into a tracker ticket. Triggers on creating a ticket or issue, logging work, or breaking an approved spec into tickets.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ticket
|
|
7
|
+
|
|
8
|
+
A ticket an implementation agent can execute with zero follow-up questions. It does NOT invent scope: it ingests what was already decided (the brainstorm, the plan, this conversation, the relevant ADR) and renders it as a complete, estimated, labeled work item in the tracker. Downstream, `void-implement` executes it.
|
|
9
|
+
|
|
10
|
+
**Core principle:** the ticket is the contract between the thinking and the building. Every required slot is filled or the ticket is not ready. Estimate and labels are not optional metadata, they are how the backlog stays pilotable.
|
|
11
|
+
|
|
12
|
+
**Attribution**: see `.source`.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## When to invoke
|
|
17
|
+
|
|
18
|
+
- After `void-brainstorm` or `void-plan` produced a decision or spec, to capture it as trackable work.
|
|
19
|
+
- When the user says create a ticket, log this, or break this into tickets.
|
|
20
|
+
- Always writes to the project's tracker (Linear / Jira / GitHub / ...). On a project with a fixed tracker, team, and label conventions, use them and do not re-ask.
|
|
21
|
+
|
|
22
|
+
Do NOT use this to execute a ticket (`void-implement`) or to sequence many steps (`void-plan`).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Ingest first, do not invent
|
|
27
|
+
|
|
28
|
+
Pull from what already exists, in order: the approved spec/plan, the brainstorm decisions, this conversation's decisions, the applicable ADR(s), the code conventions. The ticket RECORDS decisions already made. If a load-bearing decision is missing, go get it or flag it. Do not guess scope into existence.
|
|
29
|
+
|
|
30
|
+
A `docs/specs/*.md` spec with `source: forge` in its frontmatter (the forge→harness artifact contract) is a first-class source: its 18 recon variables, winning design, and critique verdict already answer scope, persona, and constraints — ingest them, do not re-ask. A partial forge spec (missing critique, or an older `forge_version` field) is ingested for what it has, with the gaps listed as the ticket's open questions.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Admission: a finding earns its place or it is dropped
|
|
35
|
+
|
|
36
|
+
Most of what reaches this skill is not a decision someone made, it is a defect someone
|
|
37
|
+
*noticed*. Those arrive without end, because reading code always finds another inconsistency,
|
|
38
|
+
and each one is defensible on its own. A backlog that admits them all stops being pilotable, and
|
|
39
|
+
the objective recedes while every individual step looks correct.
|
|
40
|
+
|
|
41
|
+
So a noticed defect is not admitted on its merits. It is compared against **the unit being built
|
|
42
|
+
right now**, judged against the program's stated objective, and there are three outcomes and one
|
|
43
|
+
slot:
|
|
44
|
+
|
|
45
|
+
1. **It blocks the current unit** — it is fixed inside that unit. No ticket.
|
|
46
|
+
2. **It beats the current unit** — it becomes the next unit, and nothing else starts until it is
|
|
47
|
+
disposed of.
|
|
48
|
+
3. **It loses** — it is dropped. Not filed, not deferred, not "kept for later".
|
|
49
|
+
|
|
50
|
+
Dropped means lost, and that is the point. A genuine defect is rediscoverable by construction:
|
|
51
|
+
a skill that lies will lie to the next reader, and a run will trip on it again. The only thing
|
|
52
|
+
ever written down is **evidence that cannot be reconstructed** — a failure observed once, a
|
|
53
|
+
measurement — as one line carrying the command that replays it. Never the opinion, never the
|
|
54
|
+
proposed fix, because describing the fix is how a finding smuggles in a design.
|
|
55
|
+
|
|
56
|
+
Two things are not admissible at all:
|
|
57
|
+
|
|
58
|
+
- **A reading nobody asked for.** What you noticed in a file you were not convened on does not
|
|
59
|
+
become work. If it matters, it will be found again by someone who was asked.
|
|
60
|
+
- **An ambition claim.** "This would be tenfold better" belongs to `void-brainstorm`, on a named
|
|
61
|
+
subject, deliberately. During execution it is an escape hatch, and it is the one that grows
|
|
62
|
+
plans.
|
|
63
|
+
|
|
64
|
+
State the comparison out loud when you drop something: what you found, and what it lost to. One
|
|
65
|
+
line. An arbitration nobody can see did not happen.
|
|
66
|
+
|
|
67
|
+
**Prose incoherence is a first-class defect**, in four forms: inside one skill, between two
|
|
68
|
+
skills, between the user's stated demand and a skill, and between a skill and the code it
|
|
69
|
+
describes. The last is this repository's repeat offender. It still goes through the comparison
|
|
70
|
+
above like anything else.
|
|
71
|
+
|
|
72
|
+
See the decision on a finding entering only by beating the work in progress.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Search the tracker before you write
|
|
77
|
+
|
|
78
|
+
The backlog already answered part of this. Query it on the **subject**, never on
|
|
79
|
+
the title you are about to write: DEV-591 was called "unstable test suite" and
|
|
80
|
+
DEV-561 "test contention" — no shared word, same question, three days apart.
|
|
81
|
+
Search several phrasings of the thing itself, and include **closed** tickets: one
|
|
82
|
+
closed because the approach was wrong is exactly the one not to reopen unchanged.
|
|
83
|
+
|
|
84
|
+
An overlap means reading that ticket **in full** before deciding, not its title.
|
|
85
|
+
What costs a day is not the duplicate, it is the reasoning that was in the first
|
|
86
|
+
one: DEV-561 had established that an intermittent test is a question nobody has
|
|
87
|
+
answered rather than noise to isolate, and DEV-591 recommended what it forbade.
|
|
88
|
+
|
|
89
|
+
Then exactly one of two things, and creating in silence is neither:
|
|
90
|
+
|
|
91
|
+
- **enrich the existing ticket**, when the subject is the same;
|
|
92
|
+
- **create, linked, naming the difference** in one sentence, when the scope is
|
|
93
|
+
deliberately disjoint.
|
|
94
|
+
|
|
95
|
+
Never merge two tickets on your own: a resemblance is not an identity, and that
|
|
96
|
+
call is the human's. Say what you searched and what came back — a search nobody
|
|
97
|
+
can see did not happen. If the tracker is unreachable, say so and keep writing;
|
|
98
|
+
a handoff blocked on a lookup is worse than a duplicate.
|
|
99
|
+
|
|
100
|
+
Thirty results means the terms were too broad, not the backlog too large.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## The ticket: required slots
|
|
105
|
+
|
|
106
|
+
Render into the tracker description. Every slot is REQUIRED unless marked optional. A missing required slot means the ticket is not ready.
|
|
107
|
+
|
|
108
|
+
- **Title**: `[Verb] [Subject]`, imperative.
|
|
109
|
+
- **Context**: why it exists; link to the broader goal / spec / ADR.
|
|
110
|
+
- **Scope**: in scope / out of scope.
|
|
111
|
+
- **Technical specs**: files and packages touched, applicable ADR, conventions and patterns to follow, third-party docs to ground in. Exhaustive enough that no unknown remains.
|
|
112
|
+
- **Acceptance criteria**: objectively verifiable checkboxes.
|
|
113
|
+
- **Definition of Done**: tests written and green, 0 lint / type errors, 0 regressions, plus ticket-specific items.
|
|
114
|
+
- **Edge cases and gotchas**: boundary behaviors, error / empty / loading states, failure modes. This is the all-angles slot; an empty one means angles were missed.
|
|
115
|
+
- **TDD mode**: defer to `void-tdd`'s path-based auto-selection; note an explicit override to strict only for a business-critical surface (auth, payments, security, money).
|
|
116
|
+
- **Runner passes that apply**: which `void-implement` conditional passes you expect to fire (architecture? migration safety? async/idempotency? E2E? UX/UI? deep security?). This is an accelerator HINT, not authoritative: the runner still evaluates every predicate itself and may add passes you did not list.
|
|
117
|
+
|
|
118
|
+
### Close the link, both ways
|
|
119
|
+
|
|
120
|
+
A ticket that cites its spec is half a link. Do both, in the same change:
|
|
121
|
+
|
|
122
|
+
1. The ticket body opens with the paths of the spec and the plan it comes from.
|
|
123
|
+
2. The `ticket:` field in each of those two files' frontmatter is filled with the
|
|
124
|
+
tracker id just created.
|
|
125
|
+
|
|
126
|
+
Neither direction is optional, because each answers a question the other cannot.
|
|
127
|
+
From the ticket, the reasoning: why this shape, what was rejected, which
|
|
128
|
+
trade-off was taken. From the spec, whether the thinking was ever executed and
|
|
129
|
+
where it landed. A spec with no ticket is a decision nobody carried out, and
|
|
130
|
+
nothing says so today.
|
|
131
|
+
|
|
132
|
+
The asymmetry is deliberate and worth keeping in mind: the spec and the plan
|
|
133
|
+
live in the repository because they belong to the project and must survive the
|
|
134
|
+
tracker, while the ticket is execution state and is mutable by nature. Copying
|
|
135
|
+
the reasoning into the tracker would put it where a workspace change can lose
|
|
136
|
+
it; copying the status into the repository would give it two owners. Only the
|
|
137
|
+
link crosses.
|
|
138
|
+
|
|
139
|
+
If the project has no tracker, say so and stop: there is no ticket to write, and
|
|
140
|
+
the spec plus the plan already hold what would have gone in it.
|
|
141
|
+
|
|
142
|
+
Native tracker fields (REQUIRED, set the real field, not prose):
|
|
143
|
+
|
|
144
|
+
- **Estimate** (points / size). Never leave empty.
|
|
145
|
+
- **Labels** (at least one; reuse existing, create if genuinely new).
|
|
146
|
+
- **Parent epic / project** link.
|
|
147
|
+
- **Dependencies** (`blockedBy`) in the native field, not just text.
|
|
148
|
+
- **Priority**.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Multi-ticket programme handoff
|
|
153
|
+
|
|
154
|
+
After creating a complete pool of two or more tickets intended to run across sessions, create
|
|
155
|
+
`.void/program.md` in the same change. Do this only after the plan and ticket pool are
|
|
156
|
+
human-approved and every native dependency is saved. A single standalone ticket does not need a
|
|
157
|
+
programme descriptor.
|
|
158
|
+
|
|
159
|
+
Use tracker-agnostic routing frontmatter:
|
|
160
|
+
|
|
161
|
+
```yaml
|
|
162
|
+
---
|
|
163
|
+
schemaVersion: 1
|
|
164
|
+
status: executing
|
|
165
|
+
program: <stable-program-slug>
|
|
166
|
+
plan: <repository-relative-plan-path>
|
|
167
|
+
spec: <repository-relative-spec-path>
|
|
168
|
+
progress:
|
|
169
|
+
provider: <adapter capability id>
|
|
170
|
+
scope: <native workspace/project/repository query>
|
|
171
|
+
order: [<ordered immutable work-unit identifiers>]
|
|
172
|
+
states:
|
|
173
|
+
ready: [<native ready states>]
|
|
174
|
+
started: [<native started states>]
|
|
175
|
+
review: [<native review states>]
|
|
176
|
+
done: [<native completed states>]
|
|
177
|
+
humanGates: [<ticket identifiers requiring explicit approval>]
|
|
178
|
+
autopilot:
|
|
179
|
+
schemaVersion: 1
|
|
180
|
+
enabled: <true | false>
|
|
181
|
+
mergeGate: human
|
|
182
|
+
---
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The body states that the plan supplies global intent, the complete provider-native record is the
|
|
186
|
+
executable unit, native blocker relations decide readiness, and `void-implement` owns the per-unit
|
|
187
|
+
lifecycle. `progress.order` is the deterministic tie-break among simultaneously ready units; it is
|
|
188
|
+
scope, not mutable progress. Never store a current or next unit, copied status, assignee, or
|
|
189
|
+
completion checklist in the program or checkpoint.
|
|
190
|
+
|
|
191
|
+
The `void-autopilot` block is required, because consent to autonomous execution is never inferred from silence: a program that does not want it declares `enabled: false`. `mergeGate` takes `human`, or `union-reviewed` with a `deployBranch` naming the branch that ships — that pair IS the consent to a machine merge, and there is no flag for it. Add `clusterSize` (1..4), `base`, `verifyCommands` (argv arrays, run with `shell:false`) and `ownership.sequential` / `ownership.reconcileOnly` only when the program enables autopilot.
|
|
192
|
+
|
|
193
|
+
Do not replace an unrelated executing programme. Stop and surface the collision. When the same
|
|
194
|
+
programme already has a descriptor, preserve its routing unless the user explicitly changes
|
|
195
|
+
programme scope. Automatic selection requires a provider adapter that can read and update status,
|
|
196
|
+
relations, assignee, comments, and review evidence; if those capabilities are unavailable, do not
|
|
197
|
+
claim automatic continuity.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## All-angles sweep before saving
|
|
202
|
+
|
|
203
|
+
Run a quick expert sweep so nothing is missed, then fold what surfaces into Edge cases or the applicable-passes slot:
|
|
204
|
+
|
|
205
|
+
- **Architecture**: boundaries, data model, public types.
|
|
206
|
+
- **Data / migrations**: schema change, backfill, zero-downtime (flags the runner's migration-safety pass).
|
|
207
|
+
- **Security**: trust boundary, untrusted input, tenancy.
|
|
208
|
+
- **Async / idempotency**: email, webhook, job, single-use token, replay (flags the runner's async pass).
|
|
209
|
+
- **QA**: edge / error / empty states, the end-to-end path.
|
|
210
|
+
- **UX**: if a UI surface is involved.
|
|
211
|
+
- **Perf / observability / docs**: cost, logging, doc updates owed in the same change.
|
|
212
|
+
|
|
213
|
+
This is the cheap insurance an expert team would not skip. It is what makes a ticket cover the angles the author would not have thought of alone.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Sizing
|
|
218
|
+
|
|
219
|
+
Map T-shirt to the tracker's native scale: XS (<1h, trivial), S (1-3h), M (3-8h, minor unknowns), L (1-2d, real complexity), XL (>2d, split unless truly indivisible).
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Red flags: STOP, the ticket is not ready
|
|
224
|
+
|
|
225
|
+
| Rationalization | Reality |
|
|
226
|
+
|-----------------|---------|
|
|
227
|
+
| "I will add the estimate later" | Estimate is a required field. An unestimated backlog cannot be planned. |
|
|
228
|
+
| "Labels do not matter for now" | At least one label, always. Filtering and routing depend on it. |
|
|
229
|
+
| "The agent will figure out the edges" | The edge-cases slot is where all-angles coverage lives. Empty = angles missed. |
|
|
230
|
+
| "Scope is obvious from the title" | The implementation agent has none of this conversation. Spell it out. |
|
|
231
|
+
| "No parent, it is standalone" | Orphan tickets rot. Link the epic or project. |
|
|
232
|
+
|
|
233
|
+
A ticket missing a required slot or field is not done, however clear it feels.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Composition
|
|
238
|
+
|
|
239
|
+
Upstream: `void-brainstorm` and `void-plan` produced the thinking (or a `source: forge` spec did — see "Ingest first"); this skill captures it. Downstream: `void-implement` consumes the ticket and the passes it declares. On a project, follow that project's tracker doctrine (team, project, label and estimate conventions) rather than re-deciding them here; this skill stays the harness-doctrine layer (ingest, required slots, runner handoff).
|
|
@@ -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,10 @@
|
|
|
1
|
+
Sources for `void-typescript-strict` skill (see `docs/plans/skill-audits/void-typescript-strict.md` for full audit):
|
|
2
|
+
|
|
3
|
+
- citypaul/.dotfiles tsconfig stance — strict + noUncheckedIndexedAccess + exactOptionalPropertyTypes baseline
|
|
4
|
+
- Anders Hejlsberg + TypeScript handbook — https://www.typescriptlang.org/docs/handbook/ — type system semantics
|
|
5
|
+
- Matt Pocock "Total TypeScript" — https://www.totaltypescript.com — branded types, satisfies operator, generic helpers
|
|
6
|
+
- tkdodo (Dominik Dorfmeister) "TypeScript Tag of Doom" + narrowing series — https://tkdodo.eu/blog/type-script-tag-of-doom — discriminated unions, as const, no-as discipline
|
|
7
|
+
- type-fest — https://github.com/sindresorhus/type-fest — utility library referenced, NOT vendored as default dep
|
|
8
|
+
- Zod — https://zod.dev — boundary validation library composed with this skill
|
|
9
|
+
|
|
10
|
+
Strategy: distill. Author from first principles; rules are common knowledge, discipline is in enforcement (hooks: tsc-noemit-precommit, no-any-grep, no-as-cast-grep).
|