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.
Files changed (341) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +123 -4
  3. package/bin/void-harness.mjs +12 -0
  4. package/bin/void-machine.mjs +12 -0
  5. package/core-assets/.claude-plugin/plugin.json +253 -0
  6. package/core-assets/.gitkeep +0 -0
  7. package/core-assets/PHILOSOPHY.md +218 -0
  8. package/core-assets/PROJECT-DOCTRINE.template.md +14 -0
  9. package/core-assets/adapters/security/manifest.yaml +96 -0
  10. package/core-assets/agents/.gitkeep +0 -0
  11. package/core-assets/agents/accessibility-specialist.md +59 -0
  12. package/core-assets/agents/api-integration-engineer.md +59 -0
  13. package/core-assets/agents/code-explorer.md +94 -0
  14. package/core-assets/agents/code-explorer.source +7 -0
  15. package/core-assets/agents/data-migration-engineer.md +59 -0
  16. package/core-assets/agents/devex-docs-engineer.md +57 -0
  17. package/core-assets/agents/doctrine-critic.md +91 -0
  18. package/core-assets/agents/doctrine-critic.source +11 -0
  19. package/core-assets/agents/domain-architect.md +56 -0
  20. package/core-assets/agents/experience-designer.md +59 -0
  21. package/core-assets/agents/frontend-engineer.md +60 -0
  22. package/core-assets/agents/independent-code-reviewer.md +61 -0
  23. package/core-assets/agents/migration-planner.md +97 -0
  24. package/core-assets/agents/migration-planner.source +7 -0
  25. package/core-assets/agents/observability-sre-engineer.md +59 -0
  26. package/core-assets/agents/pdf-specialist.md +58 -0
  27. package/core-assets/agents/performance-engineer.md +58 -0
  28. package/core-assets/agents/product-challenger.md +55 -0
  29. package/core-assets/agents/security-engineer.md +66 -0
  30. package/core-assets/agents/silent-failure-hunter.md +94 -0
  31. package/core-assets/agents/silent-failure-hunter.source +8 -0
  32. package/core-assets/agents/solution-architect.md +57 -0
  33. package/core-assets/agents/test-qa-engineer.md +60 -0
  34. package/core-assets/agents/type-design-analyzer.md +93 -0
  35. package/core-assets/agents/type-design-analyzer.source +8 -0
  36. package/core-assets/agents/visual-craft-director.md +62 -0
  37. package/core-assets/codex/hooks.json +157 -0
  38. package/core-assets/contract-history/visual-craft-director/v2.yaml +43 -0
  39. package/core-assets/data/catalog.v3.json +10479 -0
  40. package/core-assets/data/certification.json +1800 -0
  41. package/core-assets/data/identity.json +8 -0
  42. package/core-assets/data/model.json +4226 -0
  43. package/core-assets/enforce/ci-enforce.sh +183 -0
  44. package/core-assets/hooks/_checks.sh +145 -0
  45. package/core-assets/hooks/_hooklib.sh +163 -0
  46. package/core-assets/hooks/_syntax-worker.cjs +503 -0
  47. package/core-assets/hooks/_void-hook.mjs +5459 -0
  48. package/core-assets/hooks/activation-meter.sh +13 -0
  49. package/core-assets/hooks/anti-ai-slop-grep.sh +38 -0
  50. package/core-assets/hooks/auto-format.sh +9 -0
  51. package/core-assets/hooks/axe-precommit.sh +35 -0
  52. package/core-assets/hooks/block-dangerous-bash.sh +10 -0
  53. package/core-assets/hooks/block-protected-push.sh +81 -0
  54. package/core-assets/hooks/boundary-direction-check.sh +10 -0
  55. package/core-assets/hooks/control-character-grep.sh +10 -0
  56. package/core-assets/hooks/fowler-refactors.txt +71 -0
  57. package/core-assets/hooks/large-cl-grep.sh +9 -0
  58. package/core-assets/hooks/llm-cost-precommit.sh +55 -0
  59. package/core-assets/hooks/migration-lint.sh +58 -0
  60. package/core-assets/hooks/migration-pr-template.sh +55 -0
  61. package/core-assets/hooks/no-ai-design-slop.sh +10 -0
  62. package/core-assets/hooks/no-any-grep.sh +10 -0
  63. package/core-assets/hooks/no-as-cast-grep.sh +10 -0
  64. package/core-assets/hooks/no-console-log-grep.sh +10 -0
  65. package/core-assets/hooks/no-null-grep.sh +10 -0
  66. package/core-assets/hooks/no-only-no-skip.sh +10 -0
  67. package/core-assets/hooks/outcome-meter.sh +13 -0
  68. package/core-assets/hooks/pre-PR-review-evidence.sh +47 -0
  69. package/core-assets/hooks/protect-sensitive-files.sh +10 -0
  70. package/core-assets/hooks/refactor-named-grep.sh +49 -0
  71. package/core-assets/hooks/secret-in-content.sh +10 -0
  72. package/core-assets/hooks/sessionstart-context.sh +9 -0
  73. package/core-assets/hooks/stop-typecheck.sh +9 -0
  74. package/core-assets/hooks/tdd-guard.md +90 -0
  75. package/core-assets/hooks/tdd-guard.sh +10 -0
  76. package/core-assets/hooks/test-name-lint.sh +10 -0
  77. package/core-assets/hooks/tidying-commit-prefix.sh +37 -0
  78. package/core-assets/hooks/trim-large-output.sh +9 -0
  79. package/core-assets/hooks/tsc-noemit-precommit.sh +22 -0
  80. package/core-assets/hooks/ubiquitous-language-lint.sh +58 -0
  81. package/core-assets/hooks/viewport-screenshot-gate.sh +48 -0
  82. package/core-assets/modules/.gitkeep +0 -0
  83. package/core-assets/packs/pack-mobile/skills/void-eas-build-profile/.source +7 -0
  84. package/core-assets/packs/pack-mobile/skills/void-eas-build-profile/SKILL.md +164 -0
  85. package/core-assets/packs/pack-mobile/skills/void-eas-build-profile/harness.yaml +14 -0
  86. package/core-assets/packs/pack-mobile/skills/void-expo-config-plugins/.source +7 -0
  87. package/core-assets/packs/pack-mobile/skills/void-expo-config-plugins/SKILL.md +178 -0
  88. package/core-assets/packs/pack-mobile/skills/void-expo-config-plugins/harness.yaml +14 -0
  89. package/core-assets/packs/pack-mobile/skills/void-expo-router-pattern/.source +8 -0
  90. package/core-assets/packs/pack-mobile/skills/void-expo-router-pattern/SKILL.md +209 -0
  91. package/core-assets/packs/pack-mobile/skills/void-expo-router-pattern/harness.yaml +14 -0
  92. package/core-assets/packs/pack-mobile/skills/void-ota-update-strategy/.source +7 -0
  93. package/core-assets/packs/pack-mobile/skills/void-ota-update-strategy/SKILL.md +194 -0
  94. package/core-assets/packs/pack-mobile/skills/void-ota-update-strategy/harness.yaml +14 -0
  95. package/core-assets/packs/pack-monorepo/skills/void-dependency-direction/.source +5 -0
  96. package/core-assets/packs/pack-monorepo/skills/void-dependency-direction/SKILL.md +160 -0
  97. package/core-assets/packs/pack-monorepo/skills/void-dependency-direction/harness.yaml +14 -0
  98. package/core-assets/packs/pack-monorepo/skills/void-package-extraction/.source +5 -0
  99. package/core-assets/packs/pack-monorepo/skills/void-package-extraction/SKILL.md +70 -0
  100. package/core-assets/packs/pack-monorepo/skills/void-package-extraction/harness.yaml +14 -0
  101. package/core-assets/packs/pack-monorepo/skills/void-service-package/.source +5 -0
  102. package/core-assets/packs/pack-monorepo/skills/void-service-package/SKILL.md +122 -0
  103. package/core-assets/packs/pack-monorepo/skills/void-service-package/harness.yaml +14 -0
  104. package/core-assets/packs/pack-monorepo/skills/void-turbo-pipeline-tuning/.source +7 -0
  105. package/core-assets/packs/pack-monorepo/skills/void-turbo-pipeline-tuning/SKILL.md +116 -0
  106. package/core-assets/packs/pack-monorepo/skills/void-turbo-pipeline-tuning/harness.yaml +14 -0
  107. package/core-assets/packs/pack-nextjs/skills/void-cache-component-pattern/.source +5 -0
  108. package/core-assets/packs/pack-nextjs/skills/void-cache-component-pattern/SKILL.md +162 -0
  109. package/core-assets/packs/pack-nextjs/skills/void-cache-component-pattern/harness.yaml +14 -0
  110. package/core-assets/packs/pack-nextjs/skills/void-instrumentation-setup/.source +5 -0
  111. package/core-assets/packs/pack-nextjs/skills/void-instrumentation-setup/SKILL.md +161 -0
  112. package/core-assets/packs/pack-nextjs/skills/void-instrumentation-setup/harness.yaml +14 -0
  113. package/core-assets/packs/pack-nextjs/skills/void-loading-error-boundaries/.source +5 -0
  114. package/core-assets/packs/pack-nextjs/skills/void-loading-error-boundaries/SKILL.md +176 -0
  115. package/core-assets/packs/pack-nextjs/skills/void-loading-error-boundaries/harness.yaml +14 -0
  116. package/core-assets/packs/pack-nextjs/skills/void-parallel-routes-slots/.source +5 -0
  117. package/core-assets/packs/pack-nextjs/skills/void-parallel-routes-slots/SKILL.md +129 -0
  118. package/core-assets/packs/pack-nextjs/skills/void-parallel-routes-slots/harness.yaml +14 -0
  119. package/core-assets/packs/pack-nextjs/skills/void-route-group-decision/.source +5 -0
  120. package/core-assets/packs/pack-nextjs/skills/void-route-group-decision/SKILL.md +107 -0
  121. package/core-assets/packs/pack-nextjs/skills/void-route-group-decision/harness.yaml +14 -0
  122. package/core-assets/packs/pack-pwa/skills/void-install-prompt-ux/.source +5 -0
  123. package/core-assets/packs/pack-pwa/skills/void-install-prompt-ux/SKILL.md +153 -0
  124. package/core-assets/packs/pack-pwa/skills/void-install-prompt-ux/harness.yaml +14 -0
  125. package/core-assets/packs/pack-pwa/skills/void-manifest-checklist/.source +5 -0
  126. package/core-assets/packs/pack-pwa/skills/void-manifest-checklist/SKILL.md +204 -0
  127. package/core-assets/packs/pack-pwa/skills/void-manifest-checklist/harness.yaml +14 -0
  128. package/core-assets/packs/pack-pwa/skills/void-offline-first-mutation/.source +8 -0
  129. package/core-assets/packs/pack-pwa/skills/void-offline-first-mutation/SKILL.md +266 -0
  130. package/core-assets/packs/pack-pwa/skills/void-offline-first-mutation/harness.yaml +14 -0
  131. package/core-assets/packs/pack-pwa/skills/void-service-worker-strategy/.source +5 -0
  132. package/core-assets/packs/pack-pwa/skills/void-service-worker-strategy/SKILL.md +178 -0
  133. package/core-assets/packs/pack-pwa/skills/void-service-worker-strategy/harness.yaml +14 -0
  134. package/core-assets/packs/pack-react/skills/void-accessibility-check/.source +8 -0
  135. package/core-assets/packs/pack-react/skills/void-accessibility-check/SKILL.md +136 -0
  136. package/core-assets/packs/pack-react/skills/void-accessibility-check/harness.yaml +14 -0
  137. package/core-assets/packs/pack-react/skills/void-client-vs-server-component/.source +5 -0
  138. package/core-assets/packs/pack-react/skills/void-client-vs-server-component/SKILL.md +116 -0
  139. package/core-assets/packs/pack-react/skills/void-client-vs-server-component/harness.yaml +14 -0
  140. package/core-assets/packs/pack-react/skills/void-form-pattern/.source +7 -0
  141. package/core-assets/packs/pack-react/skills/void-form-pattern/SKILL.md +157 -0
  142. package/core-assets/packs/pack-react/skills/void-form-pattern/harness.yaml +14 -0
  143. package/core-assets/packs/pack-react/skills/void-state-architecture/.source +5 -0
  144. package/core-assets/packs/pack-react/skills/void-state-architecture/SKILL.md +160 -0
  145. package/core-assets/packs/pack-react/skills/void-state-architecture/harness.yaml +14 -0
  146. package/core-assets/packs/pack-server/skills/void-background-job-pattern/.source +6 -0
  147. package/core-assets/packs/pack-server/skills/void-background-job-pattern/SKILL.md +214 -0
  148. package/core-assets/packs/pack-server/skills/void-background-job-pattern/harness.yaml +14 -0
  149. package/core-assets/packs/pack-server/skills/void-drizzle-migration-safe/.source +6 -0
  150. package/core-assets/packs/pack-server/skills/void-drizzle-migration-safe/SKILL.md +168 -0
  151. package/core-assets/packs/pack-server/skills/void-drizzle-migration-safe/harness.yaml +14 -0
  152. package/core-assets/packs/pack-server/skills/void-env-validation/.source +6 -0
  153. package/core-assets/packs/pack-server/skills/void-env-validation/SKILL.md +131 -0
  154. package/core-assets/packs/pack-server/skills/void-env-validation/harness.yaml +14 -0
  155. package/core-assets/packs/pack-server/skills/void-rate-limit-strategy/.source +6 -0
  156. package/core-assets/packs/pack-server/skills/void-rate-limit-strategy/SKILL.md +149 -0
  157. package/core-assets/packs/pack-server/skills/void-rate-limit-strategy/harness.yaml +14 -0
  158. package/core-assets/packs/pack-server/skills/void-server-action/.source +7 -0
  159. package/core-assets/packs/pack-server/skills/void-server-action/SKILL.md +181 -0
  160. package/core-assets/packs/pack-server/skills/void-server-action/harness.yaml +14 -0
  161. package/core-assets/packs/pack-server/skills/void-testing-server-modules/.source +7 -0
  162. package/core-assets/packs/pack-server/skills/void-testing-server-modules/SKILL.md +73 -0
  163. package/core-assets/packs/pack-server/skills/void-testing-server-modules/harness.yaml +14 -0
  164. package/core-assets/packs/pack-server/skills/void-webhook-handler-pattern/.source +7 -0
  165. package/core-assets/packs/pack-server/skills/void-webhook-handler-pattern/SKILL.md +205 -0
  166. package/core-assets/packs/pack-server/skills/void-webhook-handler-pattern/harness.yaml +14 -0
  167. package/core-assets/policies/core.yaml +95 -0
  168. package/core-assets/policies/ui.yaml +23 -0
  169. package/core-assets/profiles/base.yaml +29 -0
  170. package/core-assets/profiles/expo-config.yaml +36 -0
  171. package/core-assets/profiles/expo.yaml +35 -0
  172. package/core-assets/profiles/monorepo.yaml +33 -0
  173. package/core-assets/profiles/nextjs-config.yaml +31 -0
  174. package/core-assets/profiles/nextjs.yaml +31 -0
  175. package/core-assets/profiles/node-server.yaml +31 -0
  176. package/core-assets/profiles/pwa.yaml +33 -0
  177. package/core-assets/profiles/react.yaml +39 -0
  178. package/core-assets/profiles/sql.yaml +39 -0
  179. package/core-assets/profiles/typescript.yaml +39 -0
  180. package/core-assets/skills/.gitkeep +0 -0
  181. package/core-assets/skills/void-accessibility/.source +15 -0
  182. package/core-assets/skills/void-accessibility/SKILL.md +275 -0
  183. package/core-assets/skills/void-accessibility/harness.yaml +17 -0
  184. package/core-assets/skills/void-api-and-interface-design/.source +13 -0
  185. package/core-assets/skills/void-api-and-interface-design/SKILL.md +231 -0
  186. package/core-assets/skills/void-api-and-interface-design/harness.yaml +16 -0
  187. package/core-assets/skills/void-async-safety/.source +13 -0
  188. package/core-assets/skills/void-async-safety/SKILL.md +287 -0
  189. package/core-assets/skills/void-async-safety/harness.yaml +16 -0
  190. package/core-assets/skills/void-audit/.source +15 -0
  191. package/core-assets/skills/void-audit/SKILL.md +83 -0
  192. package/core-assets/skills/void-audit/harness.yaml +14 -0
  193. package/core-assets/skills/void-autopilot/.source +21 -0
  194. package/core-assets/skills/void-autopilot/SKILL.md +358 -0
  195. package/core-assets/skills/void-autopilot/harness.yaml +14 -0
  196. package/core-assets/skills/void-brainstorm/.source +14 -0
  197. package/core-assets/skills/void-brainstorm/SKILL.md +271 -0
  198. package/core-assets/skills/void-brainstorm/harness.yaml +14 -0
  199. package/core-assets/skills/void-checkpoint/.source +39 -0
  200. package/core-assets/skills/void-checkpoint/SKILL.md +227 -0
  201. package/core-assets/skills/void-checkpoint/harness.yaml +14 -0
  202. package/core-assets/skills/void-claude-md/.source +15 -0
  203. package/core-assets/skills/void-claude-md/SKILL.md +180 -0
  204. package/core-assets/skills/void-claude-md/harness.yaml +14 -0
  205. package/core-assets/skills/void-code-review/.source +14 -0
  206. package/core-assets/skills/void-code-review/SKILL.md +232 -0
  207. package/core-assets/skills/void-code-review/harness.yaml +15 -0
  208. package/core-assets/skills/void-commit-discipline/.source +9 -0
  209. package/core-assets/skills/void-commit-discipline/SKILL.md +211 -0
  210. package/core-assets/skills/void-commit-discipline/harness.yaml +15 -0
  211. package/core-assets/skills/void-context/.source +15 -0
  212. package/core-assets/skills/void-context/SKILL.md +167 -0
  213. package/core-assets/skills/void-context/harness.yaml +14 -0
  214. package/core-assets/skills/void-debug/.source +11 -0
  215. package/core-assets/skills/void-debug/SKILL.md +211 -0
  216. package/core-assets/skills/void-debug/harness.yaml +14 -0
  217. package/core-assets/skills/void-decide/.source +9 -0
  218. package/core-assets/skills/void-decide/SKILL.md +147 -0
  219. package/core-assets/skills/void-decide/harness.yaml +14 -0
  220. package/core-assets/skills/void-devex-audit/.source +8 -0
  221. package/core-assets/skills/void-devex-audit/SKILL.md +113 -0
  222. package/core-assets/skills/void-devex-audit/harness.yaml +15 -0
  223. package/core-assets/skills/void-doctor/.source +15 -0
  224. package/core-assets/skills/void-doctor/SKILL.md +83 -0
  225. package/core-assets/skills/void-doctor/harness.yaml +14 -0
  226. package/core-assets/skills/void-domain-driven-design/.source +13 -0
  227. package/core-assets/skills/void-domain-driven-design/SKILL.md +292 -0
  228. package/core-assets/skills/void-domain-driven-design/harness.yaml +15 -0
  229. package/core-assets/skills/void-frontend-design/.source +19 -0
  230. package/core-assets/skills/void-frontend-design/SKILL.md +274 -0
  231. package/core-assets/skills/void-frontend-design/harness.yaml +17 -0
  232. package/core-assets/skills/void-functional/.source +14 -0
  233. package/core-assets/skills/void-functional/SKILL.md +312 -0
  234. package/core-assets/skills/void-functional/harness.yaml +15 -0
  235. package/core-assets/skills/void-graph/.source +15 -0
  236. package/core-assets/skills/void-graph/SKILL.md +80 -0
  237. package/core-assets/skills/void-graph/harness.yaml +14 -0
  238. package/core-assets/skills/void-hexagonal-architecture/.source +12 -0
  239. package/core-assets/skills/void-hexagonal-architecture/SKILL.md +276 -0
  240. package/core-assets/skills/void-hexagonal-architecture/harness.yaml +15 -0
  241. package/core-assets/skills/void-implement/.source +39 -0
  242. package/core-assets/skills/void-implement/SKILL.md +183 -0
  243. package/core-assets/skills/void-implement/harness.yaml +14 -0
  244. package/core-assets/skills/void-learn/.source +13 -0
  245. package/core-assets/skills/void-learn/SKILL.md +226 -0
  246. package/core-assets/skills/void-learn/harness.yaml +14 -0
  247. package/core-assets/skills/void-llm-cost-discipline/.source +13 -0
  248. package/core-assets/skills/void-llm-cost-discipline/SKILL.md +299 -0
  249. package/core-assets/skills/void-llm-cost-discipline/harness.yaml +15 -0
  250. package/core-assets/skills/void-make-pdf/.source +9 -0
  251. package/core-assets/skills/void-make-pdf/SKILL.md +52 -0
  252. package/core-assets/skills/void-make-pdf/harness.yaml +15 -0
  253. package/core-assets/skills/void-merge/.source +8 -0
  254. package/core-assets/skills/void-merge/SKILL.md +111 -0
  255. package/core-assets/skills/void-merge/harness.yaml +14 -0
  256. package/core-assets/skills/void-migrations/.source +13 -0
  257. package/core-assets/skills/void-migrations/SKILL.md +264 -0
  258. package/core-assets/skills/void-migrations/harness.yaml +17 -0
  259. package/core-assets/skills/void-observability/.source +12 -0
  260. package/core-assets/skills/void-observability/SKILL.md +245 -0
  261. package/core-assets/skills/void-observability/harness.yaml +15 -0
  262. package/core-assets/skills/void-plan/.source +15 -0
  263. package/core-assets/skills/void-plan/SKILL.md +239 -0
  264. package/core-assets/skills/void-plan/harness.yaml +14 -0
  265. package/core-assets/skills/void-plan-review/.source +12 -0
  266. package/core-assets/skills/void-plan-review/SKILL.md +128 -0
  267. package/core-assets/skills/void-plan-review/harness.yaml +15 -0
  268. package/core-assets/skills/void-qa/.source +15 -0
  269. package/core-assets/skills/void-qa/SKILL.md +103 -0
  270. package/core-assets/skills/void-qa/harness.yaml +15 -0
  271. package/core-assets/skills/void-refactor/.source +9 -0
  272. package/core-assets/skills/void-refactor/SKILL.md +220 -0
  273. package/core-assets/skills/void-refactor/harness.yaml +15 -0
  274. package/core-assets/skills/void-retrospective/.source +9 -0
  275. package/core-assets/skills/void-retrospective/SKILL.md +71 -0
  276. package/core-assets/skills/void-retrospective/harness.yaml +15 -0
  277. package/core-assets/skills/void-security-audit/.source +12 -0
  278. package/core-assets/skills/void-security-audit/SKILL.md +138 -0
  279. package/core-assets/skills/void-security-audit/harness.yaml +15 -0
  280. package/core-assets/skills/void-security-guidance/.source +12 -0
  281. package/core-assets/skills/void-security-guidance/SKILL.md +255 -0
  282. package/core-assets/skills/void-security-guidance/harness.yaml +15 -0
  283. package/core-assets/skills/void-source-driven-development/.source +12 -0
  284. package/core-assets/skills/void-source-driven-development/SKILL.md +158 -0
  285. package/core-assets/skills/void-source-driven-development/harness.yaml +15 -0
  286. package/core-assets/skills/void-tdd/.source +15 -0
  287. package/core-assets/skills/void-tdd/SKILL.md +394 -0
  288. package/core-assets/skills/void-tdd/harness.yaml +15 -0
  289. package/core-assets/skills/void-testing/.source +19 -0
  290. package/core-assets/skills/void-testing/SKILL.md +301 -0
  291. package/core-assets/skills/void-testing/harness.yaml +17 -0
  292. package/core-assets/skills/void-ticket/.source +18 -0
  293. package/core-assets/skills/void-ticket/SKILL.md +239 -0
  294. package/core-assets/skills/void-ticket/harness.yaml +14 -0
  295. package/core-assets/skills/void-typescript-strict/.source +10 -0
  296. package/core-assets/skills/void-typescript-strict/SKILL.md +294 -0
  297. package/core-assets/skills/void-typescript-strict/harness.yaml +17 -0
  298. package/core-assets/skills/void-ui-review/.source +12 -0
  299. package/core-assets/skills/void-ui-review/SKILL.md +97 -0
  300. package/core-assets/skills/void-ui-review/harness.yaml +15 -0
  301. package/core-assets/skills/void-verify/.source +12 -0
  302. package/core-assets/skills/void-verify/SKILL.md +184 -0
  303. package/core-assets/skills/void-verify/harness.yaml +15 -0
  304. package/core-assets/specialists/accessibility-specialist.source +11 -0
  305. package/core-assets/specialists/accessibility-specialist.yaml +30 -0
  306. package/core-assets/specialists/api-integration-engineer.source +11 -0
  307. package/core-assets/specialists/api-integration-engineer.yaml +30 -0
  308. package/core-assets/specialists/data-migration-engineer.source +11 -0
  309. package/core-assets/specialists/data-migration-engineer.yaml +30 -0
  310. package/core-assets/specialists/devex-docs-engineer.source +11 -0
  311. package/core-assets/specialists/devex-docs-engineer.yaml +29 -0
  312. package/core-assets/specialists/domain-architect.source +11 -0
  313. package/core-assets/specialists/domain-architect.yaml +28 -0
  314. package/core-assets/specialists/experience-designer.source +15 -0
  315. package/core-assets/specialists/experience-designer.yaml +38 -0
  316. package/core-assets/specialists/frontend-engineer.source +11 -0
  317. package/core-assets/specialists/frontend-engineer.yaml +32 -0
  318. package/core-assets/specialists/independent-code-reviewer.source +10 -0
  319. package/core-assets/specialists/independent-code-reviewer.yaml +37 -0
  320. package/core-assets/specialists/migrations.json +15 -0
  321. package/core-assets/specialists/observability-sre-engineer.source +11 -0
  322. package/core-assets/specialists/observability-sre-engineer.yaml +30 -0
  323. package/core-assets/specialists/pdf-specialist.source +11 -0
  324. package/core-assets/specialists/pdf-specialist.yaml +29 -0
  325. package/core-assets/specialists/performance-engineer.source +11 -0
  326. package/core-assets/specialists/performance-engineer.yaml +29 -0
  327. package/core-assets/specialists/product-challenger.source +10 -0
  328. package/core-assets/specialists/product-challenger.yaml +27 -0
  329. package/core-assets/specialists/security-engineer.source +13 -0
  330. package/core-assets/specialists/security-engineer.yaml +41 -0
  331. package/core-assets/specialists/solution-architect.source +13 -0
  332. package/core-assets/specialists/solution-architect.yaml +32 -0
  333. package/core-assets/specialists/test-qa-engineer.source +14 -0
  334. package/core-assets/specialists/test-qa-engineer.yaml +35 -0
  335. package/core-assets/specialists/visual-craft-director.source +17 -0
  336. package/core-assets/specialists/visual-craft-director.yaml +60 -0
  337. package/core-assets/templates/github/dependency-audit.mjs +54 -0
  338. package/core-assets/templates/github/void-dependency-audit.yml +35 -0
  339. package/core-assets/templates/github/void-security.yml +85 -0
  340. package/dist/main.js +57001 -0
  341. package/package.json +66 -4
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: void-client-vs-server-component
3
+ description: Decide which components run on server vs client in a React 19 / Next.js app and place the 'use client' boundary correctly. Server Components by default; client is the exception.
4
+ ---
5
+
6
+ # client-vs-server-component
7
+
8
+ Use when creating any React 19 component in a project that supports Server Components (Next.js App Router, similar). The choice is **not** "type 'use client' if the component is interactive" — that's the lazy heuristic that leads to 80% of the app shipping to the browser.
9
+
10
+ ## The default
11
+
12
+ **Server Component (no `'use client'`) by default.** Add `'use client'` only when you need browser-only APIs:
13
+
14
+ - React state hooks: `useState`, `useReducer`, `useContext`, `useRef`
15
+ - Effects: `useEffect`, `useLayoutEffect`
16
+ - Browser APIs: `window`, `document`, `localStorage`, `IntersectionObserver`
17
+ - Event handlers attached at component level (`onClick`, `onChange`, `onSubmit`)
18
+ - Third-party libraries that use any of the above
19
+
20
+ If your component does **none** of these — even if it ends up inside a Client Component — leave it server. RSC composition lets you pass server-rendered children into client wrappers.
21
+
22
+ ## The boundary placement rule
23
+
24
+ Push `'use client'` **as far down the tree as possible**. Bad pattern:
25
+
26
+ ```tsx
27
+ // ✗ app/dashboard/page.tsx
28
+ 'use client'; // entire page becomes client
29
+ import { useState } from 'react';
30
+ import { UserList } from './UserList'; // also becomes client, even if it didn't need to
31
+
32
+ export default function Page() {
33
+ const [filter, setFilter] = useState('');
34
+ return (
35
+ <>
36
+ <input value={filter} onChange={(e) => setFilter(e.target.value)} />
37
+ <UserList filter={filter} />
38
+ </>
39
+ );
40
+ }
41
+ ```
42
+
43
+ Good pattern — isolate the interactive part:
44
+
45
+ ```tsx
46
+ // ✓ app/dashboard/page.tsx (Server)
47
+ import { UserList } from './UserList'; // stays server
48
+ import { FilterInput } from './FilterInput'; // client island
49
+
50
+ export default function Page() {
51
+ return (
52
+ <>
53
+ <FilterInput />
54
+ <UserList />
55
+ </>
56
+ );
57
+ }
58
+ ```
59
+
60
+ `FilterInput` owns the `useState`. It can either:
61
+ - Push the filter to the URL and let `UserList` re-render server-side via search params
62
+ - Or render `<UserList />` as a child it receives from the server and re-filter client-side from a snapshot
63
+
64
+ The pattern: **client wraps server children**. Server Component as child of Client Component is allowed; the inverse is not.
65
+
66
+ ## State + data: who owns what
67
+
68
+ | Concern | Lives on | Component type |
69
+ |---|---|---|
70
+ | URL params (`?filter=...`) | Server (read via `searchParams`) | Server Component |
71
+ | Persistent server-side data | Server (DB / cache) | Server Component fetching directly |
72
+ | Transient UI state (open/closed, focus, input value) | Client (`useState`) | Client Component |
73
+ | Cross-component client state | Client (URL > Zustand > Context) | Client provider tree |
74
+ | Optimistic updates | Client (capture-queue, see `void-offline-first-mutation`) | Client component |
75
+
76
+ When in doubt, ask: "does this state need to survive a hard refresh?" If yes → server (or URL). If no → client.
77
+
78
+ ## Anti-patterns
79
+
80
+ - ✗ **`'use client'` at the top of `app/layout.tsx`** — destroys server rendering for the whole subtree
81
+ - ✗ **Wrapping all components in client just to use `<Link>`** — Next's `Link` works in Server Components
82
+ - ✗ **`useEffect` to fetch data in a Client Component when a Server Component could fetch it on the server** — slow, waterfall, ugly loading states
83
+ - ✗ **`import { db } from '@repo/db'` in a Client Component** — caught by `no-db-in-components` hook; refactor as a Server Action or Server Component fetch
84
+ - ✗ **Marking a leaf component `'use client'` because its parent is** — children inherit client mode if the parent passes them through children prop into a client wrapper; explicit `'use client'` is only needed where state/effects live
85
+
86
+ ## Forms — special case
87
+
88
+ Use **Server Actions** (`'use server'`) called from a Server Component form. The form HTML is server-rendered. JS hydration adds progressive enhancement:
89
+
90
+ ```tsx
91
+ // app/contact/page.tsx (Server)
92
+ import { sendContact } from './actions';
93
+
94
+ export default function Page() {
95
+ return (
96
+ <form action={sendContact}>
97
+ <input name="email" type="email" required />
98
+ <button type="submit">Send</button>
99
+ </form>
100
+ );
101
+ }
102
+ ```
103
+
104
+ Need controlled state for validation feedback? Wrap just the input in a client component. The form action stays server.
105
+
106
+ ## Performance signal: "JS payload"
107
+
108
+ Open DevTools → Network tab → filter by JS. If your `app/dashboard` route ships > 100KB of JS, you have too much client. Audit which components are `'use client'`. 90% should not be.
109
+
110
+ ## Composition
111
+
112
+ - `void-cache-component-pattern` — Server Components ARE the cache substrate; mark `'use cache'` for caching.
113
+ - `void-state-architecture` — guides client-state placement once you've decided to use Client Components.
114
+ - `void-form-pattern` — react-hook-form + Zod for client-controlled forms (Server Actions otherwise).
115
+ - the `pack-react` doctrine module on components — components are pure UI either way (no DB, no fetch via service).
116
+ - `void-hexagonal-architecture` — Server Components can call services directly (they're the boundary); Client Components call Server Actions.
@@ -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: standard
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,7 @@
1
+ Sources for `void-form-pattern` skill (see `docs/plans/skill-audits/void-form-pattern.md` for the full audit):
2
+
3
+ - react-hook-form docs — canonical controlled-form pattern and skeleton.
4
+ - @hookform/resolvers Zod adapter — schema-sharing resolver pattern.
5
+ - Distilled by repeated form bugs on real projects — the "when NOT to use" and shared-schema discipline.
6
+
7
+ Strategy: distill. Default stack (react-hook-form + Zod resolver + shared schema with Server Action) eliminates the recurring "where does validation live" question.
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: void-form-pattern
3
+ description: "Build forms with react-hook-form + Zod resolver (void-machine default): validation, error UX, submit flow with Server Actions. Composes with server-action."
4
+ ---
5
+
6
+ # form-pattern
7
+
8
+ Use when building any form with > 1 field, any field with validation, or any submit that triggers a mutation. The default in void-machine is **react-hook-form** + **Zod resolver** for client-side controlled forms, paired with **Server Actions** on submit.
9
+
10
+ For a single-field action (search input, toggle, "delete" button), use a Server Action directly — no library needed.
11
+
12
+ ## The default stack
13
+
14
+ - `react-hook-form` — form state, registration, validation orchestration
15
+ - `@hookform/resolvers/zod` — bridge to Zod
16
+ - `zod` — schema (single source of truth: same schema validates client AND server)
17
+ - Server Action (`void-server-action`) — the submit target
18
+
19
+ ## Canonical skeleton
20
+
21
+ ```tsx
22
+ 'use client';
23
+
24
+ import { useForm } from 'react-hook-form';
25
+ import { zodResolver } from '@hookform/resolvers/zod';
26
+ import { z } from 'zod';
27
+ import { saveContact } from '@/actions/contact';
28
+
29
+ const FormSchema = z.object({
30
+ email: z.string().email('Format email invalide'),
31
+ message: z.string().min(10, 'Min 10 caractères').max(2000),
32
+ });
33
+ type FormValues = z.infer<typeof FormSchema>;
34
+
35
+ export function ContactForm() {
36
+ const form = useForm<FormValues>({
37
+ resolver: zodResolver(FormSchema),
38
+ defaultValues: { email: '', message: '' },
39
+ });
40
+
41
+ async function onSubmit(values: FormValues) {
42
+ const result = await saveContact(values);
43
+ if (!result.ok) {
44
+ form.setError('root', { message: result.error });
45
+ return;
46
+ }
47
+ form.reset();
48
+ }
49
+
50
+ return (
51
+ <form onSubmit={form.handleSubmit(onSubmit)} noValidate>
52
+ <label>
53
+ Email
54
+ <input {...form.register('email')} type="email" aria-invalid={!!form.formState.errors.email} />
55
+ {form.formState.errors.email && <span role="alert">{form.formState.errors.email.message}</span>}
56
+ </label>
57
+
58
+ <label>
59
+ Message
60
+ <textarea {...form.register('message')} aria-invalid={!!form.formState.errors.message} />
61
+ {form.formState.errors.message && <span role="alert">{form.formState.errors.message.message}</span>}
62
+ </label>
63
+
64
+ {form.formState.errors.root && <p role="alert">{form.formState.errors.root.message}</p>}
65
+
66
+ <button type="submit" disabled={form.formState.isSubmitting}>
67
+ {form.formState.isSubmitting ? 'Envoi…' : 'Envoyer'}
68
+ </button>
69
+ </form>
70
+ );
71
+ }
72
+ ```
73
+
74
+ Five things to notice:
75
+
76
+ 1. **One Zod schema** — same schema is imported by the Server Action for server-side validation. No drift.
77
+ 2. **`noValidate`** — disable browser default validation (which conflicts with custom error UX).
78
+ 3. **`role="alert"`** on errors — announces to screen readers immediately.
79
+ 4. **`aria-invalid`** — semantic state for AT.
80
+ 5. **`form.formState.isSubmitting`** disables the button — no double-submit, no manual `useState` for loading.
81
+
82
+ ## Schema sharing with the Server Action
83
+
84
+ ```ts
85
+ // schemas/contact.ts (single source of truth)
86
+ import { z } from 'zod';
87
+ export const ContactSchema = z.object({
88
+ email: z.string().email(),
89
+ message: z.string().min(10).max(2000),
90
+ });
91
+
92
+ // app/(actions)/contact.ts
93
+ 'use server';
94
+ import { ContactSchema } from '@/schemas/contact';
95
+
96
+ export async function saveContact(input: unknown) {
97
+ const parsed = ContactSchema.safeParse(input); // ← same schema
98
+ if (!parsed.success) return { ok: false, error: 'invalid-input' };
99
+ /* ... service call ... */
100
+ return { ok: true };
101
+ }
102
+
103
+ // components/ContactForm.tsx
104
+ import { ContactSchema } from '@/schemas/contact';
105
+ // resolver: zodResolver(ContactSchema) ← same schema
106
+ ```
107
+
108
+ Never duplicate the schema in the client and server. Always import from one location.
109
+
110
+ ## Error display patterns
111
+
112
+ - **Field-level errors**: render right after the input (`{errors.field && <span role="alert">`).
113
+ - **Form-level errors** (server rejection): use `form.setError('root', ...)` and render once at top or near submit button.
114
+ - **No `alert()`**, no `toast.error()` for validation — inline is more usable and accessible.
115
+ - **Focus the first invalid field on submit fail** — react-hook-form does this by default via `shouldFocusError: true`.
116
+
117
+ ## When NOT to use react-hook-form
118
+
119
+ - **Single-field form** (search, newsletter signup):
120
+
121
+ ```tsx
122
+ <form action={subscribe}>
123
+ <input name="email" type="email" required />
124
+ <button>Subscribe</button>
125
+ </form>
126
+ ```
127
+
128
+ Native HTML + Server Action. No library. The browser's `required` + `type="email"` covers basic validation; the Server Action does the real check.
129
+
130
+ - **File upload only** — use `<input type="file">` + Server Action; the form library adds no value.
131
+
132
+ > **Repeatable fields in a native form**: when the Server Action reads `FormData` directly (the paths above — multi-select, a checkbox group, `<input multiple>`), do **not** `Object.fromEntries(formData)`: it keeps only the last value and silently drops the rest. Read repeatable fields with `formData.getAll(name)` and validate them with `z.array(...)` in the shared schema. See `void-server-action`.
133
+
134
+ - **Wizard / multi-step** — react-hook-form's `Controller` works but consider XState or a similar state machine for complex flows.
135
+
136
+ ## Anti-patterns
137
+
138
+ - ✗ **`useState` for each field** — that's what react-hook-form replaces; you lose validation, focus management, submit orchestration
139
+ - ✗ **Validation in `onSubmit` only** — users want feedback on blur, not just on submit. Use `mode: 'onBlur'` or `'onTouched'`
140
+ - ✗ **Different schemas client and server** — they drift; bugs slip through. One Zod schema.
141
+ - ✗ **Disabling submit button via `disabled={!form.formState.isValid}`** — confusing UX. Let the user click; show errors after.
142
+ - ✗ **`onSubmit={handler}` directly** — bypasses validation. Always `form.handleSubmit(handler)`.
143
+ - ✗ **Calling `toast.error()` for field validation** — inline errors are the standard a11y pattern.
144
+
145
+ ## Touch + mobile
146
+
147
+ - Use `inputMode="email"` / `inputMode="numeric"` / `inputMode="decimal"` to surface the right mobile keyboard.
148
+ - `autoComplete="email"` / `"current-password"` / `"one-time-code"` for the right autofill behavior. Skip = bad UX.
149
+ - Touch targets ≥ 44×44 (composes with `void-accessibility-check`).
150
+
151
+ ## Composition
152
+
153
+ - `void-server-action` — the submit target; shares the Zod schema.
154
+ - `void-security-guidance` — Zod schema is the trust boundary; server-side re-validates identically.
155
+ - `void-state-architecture` — form state IS local state; lives in the form component, never lifted.
156
+ - `void-accessibility-check` — labels, role="alert", focus management on error.
157
+ - `void-tdd` — form components get `@testing-library/user-event` tests asserting validation + submit + error display.
@@ -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: standard
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,5 @@
1
+ Sources for `void-state-architecture` skill (see `docs/plans/skill-audits/void-state-architecture.md` for the full audit):
2
+
3
+ - No external source audited — native skill authored for void-machine.
4
+
5
+ Strategy: native. Encodes a strict tier order (URL > server > local > lifted > Zustand > React Query) against React-specific state tooling that other UI stacks do not share.
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: void-state-architecture
3
+ description: Decide where state lives — local, lifted, URL, server, client global. The decision tree to avoid useState-in-the-wrong-place sprawl. Default to URL or server before reaching for global stores.
4
+ ---
5
+
6
+ # state-architecture
7
+
8
+ Use when adding any state to a React app. The wrong location is the most common architectural drift: state ends up too high (every input re-renders the page), too low (sibling components can't communicate), or in a global store when URL would have sufficed.
9
+
10
+ ## The decision tree (top → bottom; use the highest that works)
11
+
12
+ ```
13
+ 1. Can it live in the URL? → URL search params or path segment
14
+ 2. Can the server own it? → DB / cache, render via Server Component
15
+ 3. Is it ONE component's concern? → useState in that component
16
+ 4. Is it ≤ 3 sibling components? → lift to closest common parent
17
+ 5. Is it cross-tree client-only? → Zustand (or Jotai for atoms)
18
+ 6. Is it server data with caching? → React Query (TanStack) / SWR
19
+ ```
20
+
21
+ Default to (1) or (2). Reach for (5) last. Context is mentioned below but rarely the right answer.
22
+
23
+ ## (1) URL state — the most under-used
24
+
25
+ State that should survive a refresh, be shareable, or be back-button-friendly belongs in the URL:
26
+
27
+ - Filters, sorts, pagination, tabs
28
+ - "Which item is selected" in a list/detail layout
29
+ - Modal open/closed when the modal is shareable (`?invite=true`)
30
+ - Search queries
31
+
32
+ ```tsx
33
+ // Server Component reading searchParams
34
+ export default function Page({ searchParams }: { searchParams: { sort?: string } }) {
35
+ const sort = searchParams.sort ?? 'newest';
36
+ return <ItemList sort={sort} />;
37
+ }
38
+
39
+ // Client Component pushing to URL
40
+ 'use client';
41
+ import { useRouter, useSearchParams } from 'next/navigation';
42
+ export function SortSelect() {
43
+ const router = useRouter();
44
+ const params = useSearchParams();
45
+ return <select onChange={(e) => router.push(`?${new URLSearchParams({ ...Object.fromEntries(params), sort: e.target.value })}`)}>...</select>;
46
+ }
47
+ ```
48
+
49
+ The benefit: refresh works, share link works, back button works, server can SSR with the right data. Three lines of effort, huge UX win.
50
+
51
+ ## (2) Server state — the second most under-used
52
+
53
+ If the data is in the database (or any server cache), the source of truth is the server. Don't mirror it into `useState`:
54
+
55
+ ```tsx
56
+ // ✗ Client component fetching + storing
57
+ 'use client';
58
+ export function UserCard({ userId }) {
59
+ const [user, setUser] = useState<User | null>(null);
60
+ useEffect(() => { fetch(`/api/users/${userId}`).then(r => r.json()).then(setUser); }, [userId]);
61
+ if (!user) return <Spinner />;
62
+ return <Card>{user.name}</Card>;
63
+ }
64
+
65
+ // ✓ Server Component fetching directly
66
+ export async function UserCard({ userId }: { userId: string }) {
67
+ const user = await userService.getById(userId);
68
+ return <Card>{user.name}</Card>;
69
+ }
70
+ ```
71
+
72
+ When server-fetch isn't feasible (interactive lists with optimistic updates), reach for React Query — but read (1) and (2) first.
73
+
74
+ ## (3) Local state — `useState` in one component
75
+
76
+ For state ONE component cares about (input value, dropdown open, hover, focus):
77
+
78
+ ```tsx
79
+ const [open, setOpen] = useState(false);
80
+ ```
81
+
82
+ Fine. Don't lift it. Don't put it in context. Don't put it in Zustand.
83
+
84
+ ## (4) Lifted state — closest common parent
85
+
86
+ When 2-3 siblings share state, lift to the closest common parent. NOT to the page root, NOT to a layout, NOT to context. The closest common parent.
87
+
88
+ ```tsx
89
+ function TabContainer() { // closest common parent
90
+ const [active, setActive] = useState('overview');
91
+ return (
92
+ <>
93
+ <TabHeader active={active} onChange={setActive} />
94
+ <TabContent active={active} />
95
+ </>
96
+ );
97
+ }
98
+ ```
99
+
100
+ If lifting forces you to drill props through 4+ levels, you have a structural problem — not a state location problem. Refactor the component tree first.
101
+
102
+ ## (5) Client global state — Zustand / Jotai
103
+
104
+ Use **only** when:
105
+
106
+ - State is genuinely cross-tree (consumed by components that don't share a useful common parent — e.g., a toast queue, a command palette open state)
107
+ - And it's client-side only (no server source of truth)
108
+ - And lifting would cross > 5 component levels
109
+
110
+ ```ts
111
+ // stores/toast.ts
112
+ import { create } from 'zustand';
113
+ export const useToast = create<{ items: Toast[]; push(t: Toast): void; dismiss(id: string): void }>(...);
114
+ ```
115
+
116
+ If you can't justify ALL THREE conditions, don't add a store. Zustand is light but each store is a new mental load + a new place to debug.
117
+
118
+ ## When Context is right
119
+
120
+ - Theme (rarely changes, deeply read)
121
+ - Locale / i18n (same)
122
+ - Auth user (Server Components read it from cookies; Client Components get a snapshot via `<UserProvider>`)
123
+
124
+ Anything that **changes frequently** (form state, list selection, hover) in Context **kills perf**: every consumer re-renders on every change. That's not a Context problem, that's a wrong-tool problem.
125
+
126
+ ## Server state caching: React Query vs Server Components
127
+
128
+ If you're on RSC + Server Actions, your "server state" is fetched server-side. React Query becomes useful only for:
129
+
130
+ - Lists with optimistic updates that don't go through a Server Action (rare)
131
+ - Real-time data with explicit refetch needs (e.g., dashboards polling every 5s)
132
+ - Apps that aren't RSC (Vite SPA, Expo)
133
+
134
+ In Next.js App Router with Server Actions, you can mostly skip React Query.
135
+
136
+ ## Anti-patterns
137
+
138
+ - ✗ **Storing form values in a Zustand store** — local state in the form component is correct
139
+ - ✗ **Storing server data in `useState`** — leads to stale data, refetch dance
140
+ - ✗ **Putting `filterValue` in Context** — every consumer re-renders on every keystroke
141
+ - ✗ **Using `useState` for what should be in the URL** — refresh loses state, share-link breaks
142
+ - ✗ **Three different stores for the same feature** (`useUserStore`, `useUserPreferencesStore`, `useUserSessionStore`) — fuse or use selectors
143
+
144
+ ## Workflow
145
+
146
+ For each state you're about to add:
147
+
148
+ 1. **Can it be URL?** If yes, use URL search params.
149
+ 2. **Can it be server?** If yes, fetch in a Server Component.
150
+ 3. **Does ONE component need it?** `useState` there.
151
+ 4. **Do ≤3 siblings need it?** Lift to common parent.
152
+ 5. **Genuinely cross-tree client-only?** Zustand store; one per concern.
153
+ 6. **Server data with caching needs?** React Query, but exhaust 1+2 first.
154
+
155
+ ## Composition
156
+
157
+ - `void-client-vs-server-component` — server state lives in Server Components, client state lives in Client Components.
158
+ - `void-form-pattern` — react-hook-form handles form state; this skill says it's local.
159
+ - `void-offline-first-mutation` — capture-queue uses IndexedDB for offline writes (a 7th tier above Zustand, scoped to writes-pending-sync).
160
+ - `void-cache-component-pattern` — server data caching strategy.
@@ -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: standard
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,6 @@
1
+ Sources for `void-background-job-pattern` skill (see `docs/plans/skill-audits/void-background-job-pattern.md` for the full audit):
2
+
3
+ - No external source audited — native distillation of the void-machine job taxonomy (event-driven vs cron vs one-shot) and per-type wrapper patterns.
4
+ - Tooling referenced (not vendored): Inngest, Trigger.dev, Cloudflare Queues, Vercel Cron.
5
+
6
+ Strategy: distill. Distilled from the harness's own job-type decision table; queue tooling is named but no source skill was copied.