@thedecipherist/claude-packs 0.0.0-stage → 1.1.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 (890) hide show
  1. package/CHANGELOG.md +754 -0
  2. package/LICENSE +21 -0
  3. package/README.md +573 -2
  4. package/bin/claude-packs.mjs +212 -0
  5. package/configurations/base/config.json +85 -0
  6. package/configurations/cpp/config.json +93 -0
  7. package/configurations/full-stack/config.json +153 -0
  8. package/configurations/go/config.json +98 -0
  9. package/configurations/node/config.json +102 -0
  10. package/configurations/python/config.json +99 -0
  11. package/configurations/rust/config.json +106 -0
  12. package/configurations/synth-creator/config.json +148 -0
  13. package/global/hooks/gnu-shell.mjs +131 -0
  14. package/global/hooks/lib/shell-writes.mjs +2 -0
  15. package/global/hooks/shell-traps.mjs +79 -0
  16. package/global/hooks/version-pin-guard.mjs +280 -0
  17. package/global/skills/latest-versions/SKILL.md +49 -0
  18. package/lib/backup.mjs +34 -0
  19. package/lib/build-queue.mjs +22 -0
  20. package/lib/claude-md.mjs +60 -0
  21. package/lib/config-cli.mjs +36 -0
  22. package/lib/configs.mjs +145 -0
  23. package/lib/coverage.mjs +94 -0
  24. package/lib/custom-packs.mjs +93 -0
  25. package/lib/doctor.mjs +126 -0
  26. package/lib/fix-plan.mjs +72 -0
  27. package/lib/found-folders.mjs +25 -0
  28. package/lib/git-tokens.mjs +64 -0
  29. package/lib/global.mjs +125 -0
  30. package/lib/hook-proof.mjs +45 -0
  31. package/lib/hook-timing.mjs +42 -0
  32. package/lib/hover-gate.mjs +29 -0
  33. package/lib/kit-command.mjs +14 -0
  34. package/lib/kit-lock.mjs +149 -0
  35. package/lib/layout.mjs +99 -0
  36. package/lib/logs.mjs +109 -0
  37. package/lib/manifest.mjs +24 -0
  38. package/lib/new.mjs +49 -0
  39. package/lib/once-only-report.mjs +54 -0
  40. package/lib/pack-manifest.mjs +20 -0
  41. package/lib/packs.mjs +109 -0
  42. package/lib/planner.mjs +59 -0
  43. package/lib/repeats.mjs +65 -0
  44. package/lib/repo-weight.mjs +28 -0
  45. package/lib/rule-tests.mjs +42 -0
  46. package/lib/rules.mjs +40 -0
  47. package/lib/scan-detect.mjs +130 -0
  48. package/lib/scan.mjs +171 -0
  49. package/lib/selftest-cache.mjs +39 -0
  50. package/lib/settings.mjs +138 -0
  51. package/lib/shape-cli.mjs +76 -0
  52. package/lib/shape.mjs +4 -0
  53. package/lib/suggest.mjs +31 -0
  54. package/lib/switches.mjs +44 -0
  55. package/lib/symmetry-doctor.mjs +26 -0
  56. package/lib/sync.mjs +133 -0
  57. package/lib/workorder.mjs +26 -0
  58. package/package.json +34 -4
  59. package/packs/ai/checks/boundary-computes-its-own-hash.json +30 -0
  60. package/packs/ai/checks/model-call-needs-boundary.json +29 -0
  61. package/packs/ai/checks/model-id-from-config.json +28 -0
  62. package/packs/ai/checks/model-output-validated.json +26 -0
  63. package/packs/ai/pack.json +38 -0
  64. package/packs/ai/rules/ai-input-sha-boundary.md +31 -0
  65. package/packs/ai/rules/llm-pipeline-security.md +26 -0
  66. package/packs/audio-core/checks/denormals-not-in-prepare.json +12 -0
  67. package/packs/audio-core/checks/dsp-without-apvts.json +12 -0
  68. package/packs/audio-core/checks/float-phase-or-rate.json +12 -0
  69. package/packs/audio-core/checks/juce-snap-to-zero-off.json +12 -0
  70. package/packs/audio-core/checks/keep-werror.json +12 -0
  71. package/packs/audio-core/checks/no-fast-math.json +14 -0
  72. package/packs/audio-core/checks/no-locale-change.json +12 -0
  73. package/packs/audio-core/checks/no-march-native.json +14 -0
  74. package/packs/audio-core/clang-tidy +28 -0
  75. package/packs/audio-core/hooks/lib/realtime-checks.mjs +56 -0
  76. package/packs/audio-core/hooks/param-id-lock.mjs +172 -0
  77. package/packs/audio-core/hooks/realtime-guard.mjs +67 -0
  78. package/packs/audio-core/pack.json +192 -0
  79. package/packs/audio-core/rules/a-control-is-proved-through-its-input.md +26 -0
  80. package/packs/audio-core/rules/audio-thread-realtime-safe.md +27 -0
  81. package/packs/audio-core/rules/audio-ui-thread-handoff.md +21 -0
  82. package/packs/audio-core/rules/boundary-tests-cross-the-boundary.md +16 -0
  83. package/packs/audio-core/rules/build-flags-safe.md +20 -0
  84. package/packs/audio-core/rules/cached-parameter-pointers.md +28 -0
  85. package/packs/audio-core/rules/clang-tidy-core-guidelines.md +21 -0
  86. package/packs/audio-core/rules/control-reaches-every-surface.md +23 -0
  87. package/packs/audio-core/rules/cpu-worst-case-per-block.md +28 -0
  88. package/packs/audio-core/rules/dc-block-after-asymmetry.md +22 -0
  89. package/packs/audio-core/rules/discrete-params-snap.md +19 -0
  90. package/packs/audio-core/rules/double-where-precision-matters.md +20 -0
  91. package/packs/audio-core/rules/filters-stable-under-modulation.md +29 -0
  92. package/packs/audio-core/rules/host-parameters-at-scale.md +24 -0
  93. package/packs/audio-core/rules/house-control-behaviours.md +34 -0
  94. package/packs/audio-core/rules/math-domain-guards.md +19 -0
  95. package/packs/audio-core/rules/modulated-delay-interpolation.md +22 -0
  96. package/packs/audio-core/rules/multiband-phase-coherent.md +22 -0
  97. package/packs/audio-core/rules/nonlinear-stages-antialiased.md +28 -0
  98. package/packs/audio-core/rules/note-ledger-and-pedals.md +22 -0
  99. package/packs/audio-core/rules/one-formula-per-value.md +20 -0
  100. package/packs/audio-core/rules/optimisations-are-null-tested.md +23 -0
  101. package/packs/audio-core/rules/oscillators-bandlimited.md +23 -0
  102. package/packs/audio-core/rules/output-limiter.md +23 -0
  103. package/packs/audio-core/rules/parameter-ids-never-change.md +20 -0
  104. package/packs/audio-core/rules/params-and-state-thread-safe.md +19 -0
  105. package/packs/audio-core/rules/params-snapshot-per-block.md +21 -0
  106. package/packs/audio-core/rules/patch-excludes-performance-controls.md +18 -0
  107. package/packs/audio-core/rules/per-sample-code-inlinable.md +22 -0
  108. package/packs/audio-core/rules/prepare-is-repeatable.md +23 -0
  109. package/packs/audio-core/rules/recursive-state-nan-guard.md +20 -0
  110. package/packs/audio-core/rules/reverb-loop-gain-bounded.md +24 -0
  111. package/packs/audio-core/rules/sample-accurate-midi.md +22 -0
  112. package/packs/audio-core/rules/sample-rate-and-block-size-from-host.md +23 -0
  113. package/packs/audio-core/rules/scoped-no-denormals.md +26 -0
  114. package/packs/audio-core/rules/smooth-continuous-parameters.md +22 -0
  115. package/packs/audio-core/rules/state-load-versioned-and-safe.md +22 -0
  116. package/packs/audio-core/rules/straight-on-and-aligned.md +21 -0
  117. package/packs/audio-core/rules/ui-matches-reference-look.md +23 -0
  118. package/packs/audio-core/rules/undo-one-gesture-one-step.md +21 -0
  119. package/packs/audio-core/rules/voice-steal-fades.md +21 -0
  120. package/packs/audio-core/rules/voice-sum-headroom.md +20 -0
  121. package/packs/audio-core/skills/analyse-reference-look/SKILL.md +35 -0
  122. package/packs/audio-core/skills/copy-and-prove/SKILL.md +98 -0
  123. package/packs/audio-core/skills/juce-realtime-audit/SKILL.md +22 -0
  124. package/packs/audio-core/skills/measure-tone/SKILL.md +20 -0
  125. package/packs/audio-core/skills/new-panel-control/SKILL.md +15 -0
  126. package/packs/audio-core/skills/prove-control/SKILL.md +25 -0
  127. package/packs/audio-core/skills/trace-parameter/SKILL.md +29 -0
  128. package/packs/audio-core/tools/lib/spectrum.mjs +112 -0
  129. package/packs/audio-core/tools/lib/wav.mjs +41 -0
  130. package/packs/audio-core/tools/tone-report.mjs +47 -0
  131. package/packs/base/checks/field-map-over-if-runs.json +25 -0
  132. package/packs/base/checks/lookup-over-if-chains.json +25 -0
  133. package/packs/base/checks/lookup-over-ternary-chains.json +20 -0
  134. package/packs/base/checks/no-code-after-midline-comment.json +12 -0
  135. package/packs/base/checks/one-walk-per-template.json +23 -0
  136. package/packs/base/checks/stub-reports-success.json +31 -0
  137. package/packs/base/checks/test-skip-on-failed-setup.json +17 -0
  138. package/packs/base/hooks/brief-guard.mjs +96 -0
  139. package/packs/base/hooks/code-shape.mjs +99 -0
  140. package/packs/base/hooks/dispatch-once.mjs +124 -0
  141. package/packs/base/hooks/file-size-guard.mjs +61 -0
  142. package/packs/base/hooks/folder-law.mjs +77 -0
  143. package/packs/base/hooks/git-guard.mjs +202 -0
  144. package/packs/base/hooks/lesson-checks.mjs +182 -0
  145. package/packs/base/hooks/lib/apply-edit.mjs +20 -0
  146. package/packs/base/hooks/lib/code-shapes.mjs +142 -0
  147. package/packs/base/hooks/lib/content.mjs +14 -0
  148. package/packs/base/hooks/lib/cpp-scan.mjs +94 -0
  149. package/packs/base/hooks/lib/crash-policy.mjs +47 -0
  150. package/packs/base/hooks/lib/dup-index.mjs +204 -0
  151. package/packs/base/hooks/lib/dup.mjs +127 -0
  152. package/packs/base/hooks/lib/elements.mjs +87 -0
  153. package/packs/base/hooks/lib/event-log.mjs +68 -0
  154. package/packs/base/hooks/lib/function-shapes.mjs +90 -0
  155. package/packs/base/hooks/lib/git-adds.mjs +21 -0
  156. package/packs/base/hooks/lib/git-auth.mjs +44 -0
  157. package/packs/base/hooks/lib/git-guard-selftest.mjs +192 -0
  158. package/packs/base/hooks/lib/glob.mjs +33 -0
  159. package/packs/base/hooks/lib/hook-log.mjs +100 -0
  160. package/packs/base/hooks/lib/house.py +77 -0
  161. package/packs/base/hooks/lib/languages.mjs +69 -0
  162. package/packs/base/hooks/lib/layout.mjs +58 -0
  163. package/packs/base/hooks/lib/making-check-selftest.mjs +112 -0
  164. package/packs/base/hooks/lib/near-copies.mjs +76 -0
  165. package/packs/base/hooks/lib/program-read.mjs +199 -0
  166. package/packs/base/hooks/lib/program-writes.mjs +177 -0
  167. package/packs/base/hooks/lib/project.mjs +81 -0
  168. package/packs/base/hooks/lib/prose.mjs +11 -0
  169. package/packs/base/hooks/lib/pushed.mjs +201 -0
  170. package/packs/base/hooks/lib/repo-index.mjs +52 -0
  171. package/packs/base/hooks/lib/rust-scan.mjs +139 -0
  172. package/packs/base/hooks/lib/secret-patterns.mjs +18 -0
  173. package/packs/base/hooks/lib/selftest.mjs +45 -0
  174. package/packs/base/hooks/lib/shape-code.mjs +126 -0
  175. package/packs/base/hooks/lib/shape-lists.mjs +31 -0
  176. package/packs/base/hooks/lib/shape-prose.mjs +78 -0
  177. package/packs/base/hooks/lib/shape.mjs +273 -0
  178. package/packs/base/hooks/lib/shell-writes-selftest.mjs +65 -0
  179. package/packs/base/hooks/lib/shell-writes.mjs +293 -0
  180. package/packs/base/hooks/lib/turn.mjs +86 -0
  181. package/packs/base/hooks/lib/unread-writes.mjs +24 -0
  182. package/packs/base/hooks/lib/writes.mjs +71 -0
  183. package/packs/base/hooks/making-check.mjs +248 -0
  184. package/packs/base/hooks/making.mjs +106 -0
  185. package/packs/base/hooks/once-only.mjs +150 -0
  186. package/packs/base/hooks/placement-law.mjs +84 -0
  187. package/packs/base/hooks/repo-litter.mjs +75 -0
  188. package/packs/base/hooks/reuse-hint.mjs +75 -0
  189. package/packs/base/hooks/run-hooks.mjs +140 -0
  190. package/packs/base/hooks/secrets-guard.mjs +99 -0
  191. package/packs/base/hooks/shape-law.mjs +140 -0
  192. package/packs/base/hooks/suite-once.mjs +96 -0
  193. package/packs/base/hooks/template-law.mjs +148 -0
  194. package/packs/base/hooks/untrusted-boundary.mjs +53 -0
  195. package/packs/base/pack.json +214 -0
  196. package/packs/base/rules/a-control-is-seen-to-fire.md +27 -0
  197. package/packs/base/rules/behaviour-lives-with-its-kind.md +51 -0
  198. package/packs/base/rules/bug-fix-starts-red.md +25 -0
  199. package/packs/base/rules/field-map-over-if-runs.md +47 -0
  200. package/packs/base/rules/finished-work-lands.md +17 -0
  201. package/packs/base/rules/git-right-first-time.md +19 -0
  202. package/packs/base/rules/instances-by-index-identities-by-id.md +54 -0
  203. package/packs/base/rules/lookup-over-if-chains.md +49 -0
  204. package/packs/base/rules/making-line-first.md +14 -0
  205. package/packs/base/rules/open-items-tagged.md +17 -0
  206. package/packs/base/rules/plan-and-logs.md +22 -0
  207. package/packs/base/rules/references-use-anchors.md +19 -0
  208. package/packs/base/rules/refusals-are-judged.md +19 -0
  209. package/packs/base/rules/reuse-before-writing.md +15 -0
  210. package/packs/base/rules/secrets-never-committed.md +16 -0
  211. package/packs/base/rules/skill-writing.md +23 -0
  212. package/packs/base/rules/split-before-the-limit.md +14 -0
  213. package/packs/base/rules/subagent-dispatch.md +26 -0
  214. package/packs/base/rules/test-only-what-changed.md +17 -0
  215. package/packs/base/rules/test-the-template-once.md +23 -0
  216. package/packs/base/rules/unattended-runs.md +15 -0
  217. package/packs/base/rules/untrusted-content-boundary.md +15 -0
  218. package/packs/base/skills/add-lesson-check/SKILL.md +26 -0
  219. package/packs/base/skills/fix-from-scan/SKILL.md +25 -0
  220. package/packs/base/skills/land-branch/SKILL.md +24 -0
  221. package/packs/base/skills/make-it-a-template/SKILL.md +23 -0
  222. package/packs/base/skills/new-project/SKILL.md +23 -0
  223. package/packs/base/skills/pdf-to-md/SKILL.md +25 -0
  224. package/packs/base/skills/pick-tests/SKILL.md +20 -0
  225. package/packs/base/skills/pressure-test-skill/SKILL.md +23 -0
  226. package/packs/base/skills/prove-instances-identical/SKILL.md +37 -0
  227. package/packs/base/skills/write-a-workorder/SKILL.md +41 -0
  228. package/packs/base/tools/shape-symmetry-selftest.mjs +66 -0
  229. package/packs/base/tools/shape-symmetry.mjs +178 -0
  230. package/packs/base/tools/test-verdict.mjs +75 -0
  231. package/packs/ci/checks/ci-permissions-stated.json +18 -0
  232. package/packs/ci/checks/ci-tools-pinned.json +14 -0
  233. package/packs/ci/pack.json +21 -0
  234. package/packs/ci/rules/ci-covers-what-ships.md +20 -0
  235. package/packs/ci/rules/generated-files-have-no-diff.md +15 -0
  236. package/packs/content-site/checks/captcha-is-not-constant.json +27 -0
  237. package/packs/content-site/checks/img-has-size.json +20 -0
  238. package/packs/content-site/checks/page-head-complete.json +26 -0
  239. package/packs/content-site/pack.json +22 -0
  240. package/packs/content-site/rules/content-has-one-source.md +23 -0
  241. package/packs/content-site/rules/media-is-sized.md +24 -0
  242. package/packs/content-site/rules/page-head-is-complete.md +26 -0
  243. package/packs/content-site/rules/public-forms-are-defended.md +27 -0
  244. package/packs/content-site/skills/publish-a-page/SKILL.md +21 -0
  245. package/packs/cpp/checks/cpp-clamp-before-cast.json +16 -0
  246. package/packs/cpp/checks/cpp-find-with-the-library.json +12 -0
  247. package/packs/cpp/checks/cpp-hardened-test-build.json +18 -0
  248. package/packs/cpp/checks/cpp-m-pi-not-standard.json +23 -0
  249. package/packs/cpp/checks/cpp-no-atoi.json +16 -0
  250. package/packs/cpp/checks/cpp-no-const-cast.json +16 -0
  251. package/packs/cpp/checks/cpp-no-float-loop-counter.json +16 -0
  252. package/packs/cpp/checks/cpp-no-getenv-in-product.json +22 -0
  253. package/packs/cpp/checks/cpp-no-mutable-global.json +20 -0
  254. package/packs/cpp/checks/cpp-no-mutable-local-static.json +23 -0
  255. package/packs/cpp/checks/cpp-no-unchecked-fwrite.json +17 -0
  256. package/packs/cpp/checks/cpp-no-using-namespace-in-header.json +19 -0
  257. package/packs/cpp/checks/cpp-no-zero-size-array.json +23 -0
  258. package/packs/cpp/checks/cpp-numbers-pi.json +16 -0
  259. package/packs/cpp/pack.json +22 -0
  260. package/packs/cpp/rules/cpp-absent-and-failed-are-types.md +24 -0
  261. package/packs/cpp/rules/cpp-builds-everywhere.md +26 -0
  262. package/packs/cpp/rules/cpp-faults-only-in-the-test-build.md +21 -0
  263. package/packs/cpp/rules/cpp-find-with-the-library.md +19 -0
  264. package/packs/cpp/rules/cpp-gates-share-one-reader.md +22 -0
  265. package/packs/cpp/rules/cpp-headers-declare.md +22 -0
  266. package/packs/cpp/rules/cpp-numbers-and-casts.md +22 -0
  267. package/packs/cpp/rules/cpp-repeats-become-templates.md +33 -0
  268. package/packs/cpp/rules/cpp-static-analysis-runs.md +22 -0
  269. package/packs/cpp/rules/cpp-thread-contracts-are-code.md +23 -0
  270. package/packs/cpp/skills/cpp-extract-template/SKILL.md +38 -0
  271. package/packs/docker/checks/alpine-with-native-build.json +13 -0
  272. package/packs/docker/checks/compose-db-needs-auth.json +14 -0
  273. package/packs/docker/checks/compose-image-pinned.json +14 -0
  274. package/packs/docker/checks/compose-no-hardcoded-ip.json +12 -0
  275. package/packs/docker/checks/compose-no-host-bind-for-data.json +18 -0
  276. package/packs/docker/checks/compose-no-plaintext-secret.json +13 -0
  277. package/packs/docker/checks/compose-no-swarm-ignored-keys.json +13 -0
  278. package/packs/docker/checks/compose-overlay-not-bridge.json +13 -0
  279. package/packs/docker/checks/compose-service-needs-healthcheck.json +11 -0
  280. package/packs/docker/checks/compose-service-needs-init.json +11 -0
  281. package/packs/docker/checks/copy-needs-chown-with-user.json +17 -0
  282. package/packs/docker/checks/copy-source-before-deps.json +13 -0
  283. package/packs/docker/checks/docker-exec-form.json +16 -0
  284. package/packs/docker/checks/dockerfile-needs-healthcheck.json +17 -0
  285. package/packs/docker/checks/dockerfile-needs-user.json +21 -0
  286. package/packs/docker/checks/dockerignore-has-the-basics.json +21 -0
  287. package/packs/docker/checks/gitattributes-forces-lf.json +17 -0
  288. package/packs/docker/checks/health-checks-nothing.json +25 -0
  289. package/packs/docker/checks/no-crlf-in-scripts.json +15 -0
  290. package/packs/docker/checks/no-latest-base.json +13 -0
  291. package/packs/docker/checks/no-secret-in-image.json +13 -0
  292. package/packs/docker/checks/no-sensitive-file-copy.json +13 -0
  293. package/packs/docker/checks/node-env-before-install.json +13 -0
  294. package/packs/docker/checks/npm-ci-not-install.json +13 -0
  295. package/packs/docker/pack.json +46 -0
  296. package/packs/docker/rules/compose-pinned-and-closed.md +21 -0
  297. package/packs/docker/rules/compose-swarm-safe.md +26 -0
  298. package/packs/docker/rules/docker-exec-form.md +19 -0
  299. package/packs/docker/rules/dockerfile-multistage.md +13 -0
  300. package/packs/docker/rules/dockerfile-production.md +25 -0
  301. package/packs/docker/skills/docker-diagnose/SKILL.md +23 -0
  302. package/packs/dynamic-data/checks/draft-on-the-server.json +27 -0
  303. package/packs/dynamic-data/checks/guard-does-its-job.json +28 -0
  304. package/packs/dynamic-data/checks/key-is-not-a-display-name.json +28 -0
  305. package/packs/dynamic-data/checks/no-code-from-data.json +29 -0
  306. package/packs/dynamic-data/checks/no-collection-from-request.json +27 -0
  307. package/packs/dynamic-data/checks/no-pipeline-from-stored-text.json +27 -0
  308. package/packs/dynamic-data/checks/no-regexp-from-stored-config.json +27 -0
  309. package/packs/dynamic-data/checks/no-template-from-stored-text.json +27 -0
  310. package/packs/dynamic-data/checks/save-takes-named-paths.json +27 -0
  311. package/packs/dynamic-data/pack.json +23 -0
  312. package/packs/dynamic-data/rules/a-list-is-a-saved-query.md +23 -0
  313. package/packs/dynamic-data/rules/definitions-are-validated-data.md +24 -0
  314. package/packs/dynamic-data/rules/every-dynamic-surface-has-a-boundary.md +29 -0
  315. package/packs/dynamic-data/rules/fields-have-owners.md +22 -0
  316. package/packs/dynamic-data/rules/imports-drop-nothing.md +26 -0
  317. package/packs/dynamic-data/rules/one-definition-many-surfaces.md +24 -0
  318. package/packs/dynamic-data/rules/one-fact-one-place.md +28 -0
  319. package/packs/dynamic-data/rules/rules-live-in-the-engine.md +29 -0
  320. package/packs/dynamic-data/rules/saves-are-patches.md +28 -0
  321. package/packs/dynamic-data/rules/tenant-costs-one-document.md +22 -0
  322. package/packs/dynamic-data/skills/design-a-definition/SKILL.md +24 -0
  323. package/packs/fastify/checks/api-routes-versioned.json +28 -0
  324. package/packs/fastify/checks/cookie-host-prefix.json +24 -0
  325. package/packs/fastify/checks/hijack-needs-try.json +28 -0
  326. package/packs/fastify/checks/no-cast-at-route-boundary.json +24 -0
  327. package/packs/fastify/checks/no-db-in-route-file.json +28 -0
  328. package/packs/fastify/checks/no-err-message-to-client.json +24 -0
  329. package/packs/fastify/checks/no-regexp-from-input.json +24 -0
  330. package/packs/fastify/checks/no-trust-proxy-true.json +25 -0
  331. package/packs/fastify/checks/one-error-body.json +26 -0
  332. package/packs/fastify/checks/origin-from-config-not-host.json +31 -0
  333. package/packs/fastify/checks/password-needs-slow-hash.json +30 -0
  334. package/packs/fastify/checks/sec-headers-present.json +28 -0
  335. package/packs/fastify/checks/secrets-compared-constant-time.json +24 -0
  336. package/packs/fastify/checks/sse-needs-error-listener.json +28 -0
  337. package/packs/fastify/checks/user-bytes-need-disposition.json +29 -0
  338. package/packs/fastify/pack.json +41 -0
  339. package/packs/fastify/rules/credentials-and-input.md +23 -0
  340. package/packs/fastify/rules/security-one-switch.md +28 -0
  341. package/packs/fastify/rules/streams-and-hijacks.md +22 -0
  342. package/packs/fastify/rules/tests-use-inject.md +13 -0
  343. package/packs/fastify/rules/three-layers.md +20 -0
  344. package/packs/fastify/rules/trust-config-not-headers.md +24 -0
  345. package/packs/full-stack/checks/no-express-no-vite.json +23 -0
  346. package/packs/full-stack/hooks/stack-guard.mjs +90 -0
  347. package/packs/full-stack/pack.json +76 -0
  348. package/packs/full-stack/rules/stack-is-fastify-and-nextjs.md +20 -0
  349. package/packs/go/checks/go-exec-result-ignored.json +15 -0
  350. package/packs/go/checks/go-unmarshal-error-ignored.json +15 -0
  351. package/packs/go/pack.json +26 -0
  352. package/packs/go/rules/go-errors-are-handled.md +22 -0
  353. package/packs/gpu-painter/checks/dawn-backends-and-validation.json +9 -0
  354. package/packs/gpu-painter/checks/dawn-no-spontaneous.json +10 -0
  355. package/packs/gpu-painter/checks/dawn-present-on-render-thread.json +17 -0
  356. package/packs/gpu-painter/checks/gpu-no-frame-stalls.json +12 -0
  357. package/packs/gpu-painter/checks/no-opengl-link.json +11 -0
  358. package/packs/gpu-painter/checks/no-opengl.json +13 -0
  359. package/packs/gpu-painter/hooks/browser-guard.py +196 -0
  360. package/packs/gpu-painter/pack.json +91 -0
  361. package/packs/gpu-painter/rules/dawn-build-and-shaders.md +27 -0
  362. package/packs/gpu-painter/rules/dawn-device-and-render-thread.md +26 -0
  363. package/packs/gpu-painter/rules/gpu-antialiasing.md +20 -0
  364. package/packs/gpu-painter/rules/gpu-blend-order.md +22 -0
  365. package/packs/gpu-painter/rules/gpu-bloom.md +20 -0
  366. package/packs/gpu-painter/rules/gpu-frame-budget.md +25 -0
  367. package/packs/gpu-painter/rules/gpu-frame-pacing-and-power.md +27 -0
  368. package/packs/gpu-painter/rules/gpu-frame-work.md +30 -0
  369. package/packs/gpu-painter/rules/gpu-golden-images.md +21 -0
  370. package/packs/gpu-painter/rules/gpu-hdr-and-tonemap.md +23 -0
  371. package/packs/gpu-painter/rules/gpu-picking-on-cpu.md +19 -0
  372. package/packs/gpu-painter/rules/gpu-render-lifecycle.md +25 -0
  373. package/packs/gpu-painter/rules/gpu-text-atlas.md +24 -0
  374. package/packs/gpu-painter/rules/gpu-travellers-from-snapshot.md +24 -0
  375. package/packs/gpu-painter/rules/hover-every-pressable.md +25 -0
  376. package/packs/gpu-painter/skills/gpu-capture/SKILL.md +15 -0
  377. package/packs/gpu-painter/skills/gpu-frame-bench/SKILL.md +14 -0
  378. package/packs/gpu-painter/skills/gpu-golden-check/SKILL.md +13 -0
  379. package/packs/gpu-painter/skills/gpu-golden-update/SKILL.md +16 -0
  380. package/packs/gpu-painter/skills/gpu-lifecycle-stress/SKILL.md +15 -0
  381. package/packs/gpu-painter/skills/hover-state/SKILL.md +33 -0
  382. package/packs/hook-proof/checks/hook-catch-must-not-allow.json +16 -0
  383. package/packs/hook-proof/checks/hook-command-no-pipe.json +16 -0
  384. package/packs/hook-proof/checks/hook-exit-1-does-not-block.json +17 -0
  385. package/packs/hook-proof/checks/hook-no-or-true.json +18 -0
  386. package/packs/hook-proof/checks/hook-refusal-on-stderr.json +17 -0
  387. package/packs/hook-proof/pack.json +38 -0
  388. package/packs/hook-proof/rules/a-refusal-is-exit-2.md +28 -0
  389. package/packs/hook-proof/skills/prove-a-hook/SKILL.md +21 -0
  390. package/packs/host-agent/checks/file-path-from-param.json +27 -0
  391. package/packs/host-agent/checks/integrity-check-optional.json +27 -0
  392. package/packs/host-agent/checks/quoted-value-into-config.json +24 -0
  393. package/packs/host-agent/checks/secret-on-argv.json +28 -0
  394. package/packs/host-agent/checks/ssh-verifies-host-key.json +27 -0
  395. package/packs/host-agent/checks/system-file-written-in-place.json +26 -0
  396. package/packs/host-agent/checks/tmp-path-predictable.json +27 -0
  397. package/packs/host-agent/pack.json +22 -0
  398. package/packs/host-agent/rules/root-on-other-machines.md +27 -0
  399. package/packs/html-ui/checks/email-html-escapes.json +25 -0
  400. package/packs/html-ui/checks/external-link-rel.json +21 -0
  401. package/packs/html-ui/checks/no-duplicate-escape.json +26 -0
  402. package/packs/html-ui/checks/no-inline-client-script.json +21 -0
  403. package/packs/html-ui/checks/no-inline-style.json +23 -0
  404. package/packs/html-ui/pack.json +33 -0
  405. package/packs/html-ui/rules/email-html-escapes.md +19 -0
  406. package/packs/html-ui/rules/server-html-escapes-everything.md +22 -0
  407. package/packs/http-api/checks/api-path-versioned.json +31 -0
  408. package/packs/http-api/checks/authz-from-request-body.json +26 -0
  409. package/packs/http-api/checks/client-calls-a-version.json +28 -0
  410. package/packs/http-api/checks/client-ip-not-leftmost-xff.json +28 -0
  411. package/packs/http-api/checks/cors-needs-origin.json +26 -0
  412. package/packs/http-api/checks/csp-not-switched-off.json +28 -0
  413. package/packs/http-api/checks/debug-route-not-shipped.json +26 -0
  414. package/packs/http-api/checks/encrypted-name-plaintext-value.json +26 -0
  415. package/packs/http-api/checks/err-text-stays-server-side.json +27 -0
  416. package/packs/http-api/checks/failure-is-not-empty.json +28 -0
  417. package/packs/http-api/checks/gate-is-not-a-todo.json +27 -0
  418. package/packs/http-api/checks/guard-fails-open.json +28 -0
  419. package/packs/http-api/checks/hmac-over-reserialised-body.json +26 -0
  420. package/packs/http-api/checks/jwt-verify-pins-algorithm.json +26 -0
  421. package/packs/http-api/checks/middleware-skips-without-user.json +26 -0
  422. package/packs/http-api/checks/next-api-route-versioned.json +47 -0
  423. package/packs/http-api/checks/no-security-off-switch.json +28 -0
  424. package/packs/http-api/checks/oauth-state-signed.json +26 -0
  425. package/packs/http-api/checks/one-time-code-compared-raw.json +26 -0
  426. package/packs/http-api/checks/query-cast-is-not-validation.json +28 -0
  427. package/packs/http-api/checks/queue-action-from-client.json +26 -0
  428. package/packs/http-api/checks/rate-limit-one-module.json +28 -0
  429. package/packs/http-api/checks/role-checked-in-one-guard.json +27 -0
  430. package/packs/http-api/checks/route-body-needs-schema.json +31 -0
  431. package/packs/http-api/checks/route-scopes-to-the-caller.json +31 -0
  432. package/packs/http-api/checks/secret-compared-constant-time-any.json +28 -0
  433. package/packs/http-api/checks/secret-in-job-record.json +27 -0
  434. package/packs/http-api/checks/server-fetches-tenant-url.json +30 -0
  435. package/packs/http-api/checks/short-code-needs-limit.json +26 -0
  436. package/packs/http-api/checks/user-url-through-safe-fetch.json +28 -0
  437. package/packs/http-api/checks/webhook-dedupes-event-id.json +30 -0
  438. package/packs/http-api/pack.json +45 -0
  439. package/packs/http-api/rules/adapters-one-db-gateway.md +18 -0
  440. package/packs/http-api/rules/apis-are-versioned.md +27 -0
  441. package/packs/http-api/rules/credentials-handled-safely.md +22 -0
  442. package/packs/http-api/rules/handlers-own-the-work.md +17 -0
  443. package/packs/http-api/rules/health-and-correlation.md +17 -0
  444. package/packs/http-api/rules/one-error-contract.md +17 -0
  445. package/packs/http-api/rules/routes-are-thin.md +17 -0
  446. package/packs/http-api/rules/routes-scope-to-the-caller.md +26 -0
  447. package/packs/http-api/rules/routes-validate-and-answer.md +25 -0
  448. package/packs/http-api/skills/change-an-api/SKILL.md +20 -0
  449. package/packs/http-api/skills/secure-a-route/SKILL.md +21 -0
  450. package/packs/instrument-shell/checks/no-raw-struct-blob.json +23 -0
  451. package/packs/instrument-shell/pack.json +22 -0
  452. package/packs/instrument-shell/rules/fold-keeps-every-route.md +24 -0
  453. package/packs/instrument-shell/rules/quiet-announces-itself.md +22 -0
  454. package/packs/instrument-shell/rules/render-the-extremes.md +25 -0
  455. package/packs/instrument-shell/rules/seams-are-declared.md +27 -0
  456. package/packs/instrument-shell/rules/session-blob-append-only.md +25 -0
  457. package/packs/instrument-shell/skills/gates-from-commit-one/SKILL.md +20 -0
  458. package/packs/instrument-shell/skills/hit-the-painted-control/SKILL.md +18 -0
  459. package/packs/js-ts/checks/async-callback-unguarded.json +26 -0
  460. package/packs/js-ts/checks/background-loop-needs-stop.json +28 -0
  461. package/packs/js-ts/checks/child-process-error-handler.json +28 -0
  462. package/packs/js-ts/checks/entry-registers-shutdown.json +31 -0
  463. package/packs/js-ts/checks/fetch-needs-timeout.json +30 -0
  464. package/packs/js-ts/checks/job-only-in-memory.json +28 -0
  465. package/packs/js-ts/checks/json-only-through-helper.json +29 -0
  466. package/packs/js-ts/checks/line-under-200-chars.json +34 -0
  467. package/packs/js-ts/checks/localhost-default-in-server.json +29 -0
  468. package/packs/js-ts/checks/no-any.json +27 -0
  469. package/packs/js-ts/checks/no-cast-escape-hatches.json +24 -0
  470. package/packs/js-ts/checks/no-console-in-app.json +31 -0
  471. package/packs/js-ts/checks/no-dynamic-import-node-builtin.json +25 -0
  472. package/packs/js-ts/checks/no-inline-binary.json +20 -0
  473. package/packs/js-ts/checks/no-inline-zod-outside-schemas.json +27 -0
  474. package/packs/js-ts/checks/no-local-sleep.json +25 -0
  475. package/packs/js-ts/checks/no-nested-ternary.json +20 -0
  476. package/packs/js-ts/checks/no-secret-in-log.json +24 -0
  477. package/packs/js-ts/checks/no-shell-string-interpolation.json +24 -0
  478. package/packs/js-ts/checks/no-swallowed-errors.json +25 -0
  479. package/packs/js-ts/checks/no-ts-enum.json +20 -0
  480. package/packs/js-ts/checks/process-env-only-in-config.json +31 -0
  481. package/packs/js-ts/checks/race-leaves-work-running.json +23 -0
  482. package/packs/js-ts/checks/reject-as-catch-all-exists.json +24 -0
  483. package/packs/js-ts/checks/secret-has-no-fallback.json +24 -0
  484. package/packs/js-ts/checks/secret-needs-crypto-random.json +24 -0
  485. package/packs/js-ts/checks/server-close-awaited.json +27 -0
  486. package/packs/js-ts/checks/session-user-typed-once.json +24 -0
  487. package/packs/js-ts/checks/switch-is-a-table.json +24 -0
  488. package/packs/js-ts/checks/test-imports-the-source.json +19 -0
  489. package/packs/js-ts/checks/test-name-says-behaviour.json +16 -0
  490. package/packs/js-ts/checks/tsconfig-flags.json +21 -0
  491. package/packs/js-ts/checks/void-needs-catch.json +24 -0
  492. package/packs/js-ts/checks/zod-string-needs-max.json +25 -0
  493. package/packs/js-ts/checks/zod-v4-formats.json +23 -0
  494. package/packs/js-ts/pack.json +84 -0
  495. package/packs/js-ts/rules/await-handled-at-a-boundary.md +66 -0
  496. package/packs/js-ts/rules/env-through-config.md +36 -0
  497. package/packs/js-ts/rules/errors-never-swallowed.md +33 -0
  498. package/packs/js-ts/rules/files-under-300-lines.md +18 -0
  499. package/packs/js-ts/rules/guard-clauses-over-nesting.md +34 -0
  500. package/packs/js-ts/rules/js-repeats-become-templates.md +26 -0
  501. package/packs/js-ts/rules/json-only-through-one-helper.md +62 -0
  502. package/packs/js-ts/rules/named-constants-not-magic-numbers.md +34 -0
  503. package/packs/js-ts/rules/no-any.md +34 -0
  504. package/packs/js-ts/rules/no-console.md +30 -0
  505. package/packs/js-ts/rules/no-floating-promises.md +31 -0
  506. package/packs/js-ts/rules/no-param-mutation.md +28 -0
  507. package/packs/js-ts/rules/no-unsafe-assertions.md +30 -0
  508. package/packs/js-ts/rules/one-logger.md +24 -0
  509. package/packs/js-ts/rules/outbound-calls-have-a-limit.md +20 -0
  510. package/packs/js-ts/rules/parallel-independent-awaits.md +29 -0
  511. package/packs/js-ts/rules/process-lifecycle.md +47 -0
  512. package/packs/js-ts/rules/schema-single-source-of-truth.md +36 -0
  513. package/packs/js-ts/rules/secrets-stay-secret.md +22 -0
  514. package/packs/js-ts/rules/small-functions.md +20 -0
  515. package/packs/js-ts/rules/test-names-describe-behavior.md +28 -0
  516. package/packs/js-ts/rules/tests-can-fail.md +19 -0
  517. package/packs/js-ts/rules/tsconfig-strict.md +32 -0
  518. package/packs/js-ts/rules/typed-exports.md +27 -0
  519. package/packs/js-ts/rules/types-once-at-the-edge.md +18 -0
  520. package/packs/js-ts/rules/unions-over-enums.md +29 -0
  521. package/packs/js-ts/rules/zod-at-route-boundaries.md +40 -0
  522. package/packs/midi/checks/active-sensing-no-pulse.json +24 -0
  523. package/packs/midi/checks/clock-not-at-sample-zero.json +23 -0
  524. package/packs/midi/checks/midi-realtime-first.json +27 -0
  525. package/packs/midi/checks/no-tempo-writeback.json +23 -0
  526. package/packs/midi/checks/position-not-integrated.json +29 -0
  527. package/packs/midi/checks/stub-playhead-advances.json +27 -0
  528. package/packs/midi/checks/sysex-length-literal.json +23 -0
  529. package/packs/midi/checks/sysex-not-on-audio.json +24 -0
  530. package/packs/midi/checks/sysex-survives-realtime.json +27 -0
  531. package/packs/midi/pack.json +22 -0
  532. package/packs/midi/rules/clock-is-a-pulse-stream.md +30 -0
  533. package/packs/midi/rules/imports-count-every-loss.md +25 -0
  534. package/packs/midi/rules/measure-the-clock-in-audio.md +30 -0
  535. package/packs/midi/rules/sync-is-a-mode.md +29 -0
  536. package/packs/midi/rules/sysex-is-a-record.md +29 -0
  537. package/packs/midi/skills/clock-probe/SKILL.md +23 -0
  538. package/packs/midi/skills/clock-probe/clock-law.md +417 -0
  539. package/packs/midi/skills/does-it-sync/SKILL.md +19 -0
  540. package/packs/mongo/checks/bulk-over-many.json +28 -0
  541. package/packs/mongo/checks/created-at-immutable.json +25 -0
  542. package/packs/mongo/checks/driver-outside-gateway.json +24 -0
  543. package/packs/mongo/checks/key-lookup-is-hashed.json +24 -0
  544. package/packs/mongo/checks/mongoclient-cached-and-named.json +34 -0
  545. package/packs/mongo/checks/mongoclient-outside-gateway.json +24 -0
  546. package/packs/mongo/checks/no-count-plus-one-ids.json +25 -0
  547. package/packs/mongo/checks/no-db-write-in-loop.json +25 -0
  548. package/packs/mongo/checks/no-drop-in-code.json +27 -0
  549. package/packs/mongo/checks/no-empty-deletemany.json +26 -0
  550. package/packs/mongo/checks/no-find-reads.json +26 -0
  551. package/packs/mongo/checks/no-input-spread-into-write.json +24 -0
  552. package/packs/mongo/checks/no-mongoose.json +23 -0
  553. package/packs/mongo/checks/no-negation-delete.json +26 -0
  554. package/packs/mongo/checks/no-non-null-after-findone.json +25 -0
  555. package/packs/mongo/checks/objectid-equals.json +26 -0
  556. package/packs/mongo/checks/update-then-reread.json +24 -0
  557. package/packs/mongo/checks/watch-not-poll.json +25 -0
  558. package/packs/mongo/pack.json +52 -0
  559. package/packs/mongo/rules/deletes-name-what-dies.md +21 -0
  560. package/packs/mongo/rules/driver-only-in-gateway.md +26 -0
  561. package/packs/mongo/rules/keys-hashed-input-picked.md +21 -0
  562. package/packs/mongo/rules/one-client-one-pool.md +32 -0
  563. package/packs/mongo/rules/reads-aggregate-writes-bulk.md +25 -0
  564. package/packs/mongo/rules/writes-are-atomic.md +27 -0
  565. package/packs/multi-tenant/checks/role-sees-all-tenants.json +26 -0
  566. package/packs/multi-tenant/checks/tenant-filter-from-url.json +25 -0
  567. package/packs/multi-tenant/pack.json +22 -0
  568. package/packs/multi-tenant/rules/no-role-crosses-a-tenant.md +21 -0
  569. package/packs/multi-tenant/skills/prove-tenant-isolation/SKILL.md +19 -0
  570. package/packs/nginx/checks/modsec-no-blanket-off.json +16 -0
  571. package/packs/nginx/checks/nginx-csp-no-unsafe.json +15 -0
  572. package/packs/nginx/checks/nginx-headers-always.json +15 -0
  573. package/packs/nginx/checks/nginx-keepalive-http11.json +20 -0
  574. package/packs/nginx/checks/nginx-logs-to-stdout.json +15 -0
  575. package/packs/nginx/checks/nginx-no-crlf.json +17 -0
  576. package/packs/nginx/checks/nginx-resolver-ttl.json +19 -0
  577. package/packs/nginx/pack.json +43 -0
  578. package/packs/nginx/rules/modsecurity-tuning.md +22 -0
  579. package/packs/nginx/rules/nginx-production.md +26 -0
  580. package/packs/nginx/skills/waf-rollout/SKILL.md +20 -0
  581. package/packs/postgres/checks/pg-bind-values.json +33 -0
  582. package/packs/postgres/checks/pg-concurrently-in-txn.json +18 -0
  583. package/packs/postgres/checks/pg-fk-not-valid.json +18 -0
  584. package/packs/postgres/checks/pg-index-concurrently.json +18 -0
  585. package/packs/postgres/checks/pg-no-float-money.json +19 -0
  586. package/packs/postgres/checks/pg-no-money.json +18 -0
  587. package/packs/postgres/checks/pg-no-required-column.json +18 -0
  588. package/packs/postgres/checks/pg-no-volatile-default.json +18 -0
  589. package/packs/postgres/checks/pg-not-exists.json +18 -0
  590. package/packs/postgres/checks/pg-timestamptz.json +18 -0
  591. package/packs/postgres/hooks/db-wipe-guard.mjs +95 -0
  592. package/packs/postgres/pack.json +48 -0
  593. package/packs/postgres/rules/postgres-migrations-never-stop-traffic.md +28 -0
  594. package/packs/postgres/rules/postgres-one-pool-per-process.md +21 -0
  595. package/packs/postgres/rules/postgres-queries-are-null-safe-and-bounded.md +26 -0
  596. package/packs/postgres/rules/postgres-types-say-what-they-hold.md +22 -0
  597. package/packs/postgres/rules/postgres-values-are-bound.md +130 -0
  598. package/packs/postgres/skills/postgres-safe-migration/SKILL.md +45 -0
  599. package/packs/python/checks/py-no-bare-except.json +18 -0
  600. package/packs/python/checks/py-no-eval.json +18 -0
  601. package/packs/python/checks/py-no-mutable-default.json +18 -0
  602. package/packs/python/checks/py-no-shell-true.json +18 -0
  603. package/packs/python/checks/py-no-star-import.json +18 -0
  604. package/packs/python/checks/py-no-swallowed-exception.json +18 -0
  605. package/packs/python/checks/py-none-by-is.json +18 -0
  606. package/packs/python/checks/py-open-with-with.json +18 -0
  607. package/packs/python/checks/py-requests-timeout.json +18 -0
  608. package/packs/python/checks/py-subprocess-output-checked.json +18 -0
  609. package/packs/python/checks/py-yaml-safe-load.json +18 -0
  610. package/packs/python/pack.json +26 -0
  611. package/packs/python/rules/python-errors-and-resources.md +26 -0
  612. package/packs/python/rules/python-repeats-become-templates.md +27 -0
  613. package/packs/python/skills/python-extract-template/SKILL.md +35 -0
  614. package/packs/react/checks/dialog-needs-role.json +28 -0
  615. package/packs/react/checks/effect-not-for-derived-state.json +24 -0
  616. package/packs/react/checks/icon-button-needs-name.json +24 -0
  617. package/packs/react/checks/label-needs-a-field.json +24 -0
  618. package/packs/react/checks/ui-failed-fetch-says-so.json +23 -0
  619. package/packs/react/checks/ui-ok-branch-has-an-else.json +23 -0
  620. package/packs/react/pack.json +20 -0
  621. package/packs/react/rules/react-accessible-controls.md +20 -0
  622. package/packs/react/rules/react-state-and-effects.md +23 -0
  623. package/packs/reverse-engineering/checks/ear-constant-tagged.json +23 -0
  624. package/packs/reverse-engineering/checks/no-default-on-distrust.json +24 -0
  625. package/packs/reverse-engineering/checks/no-rom-table-literal.json +29 -0
  626. package/packs/reverse-engineering/checks/prose-never-decides.json +22 -0
  627. package/packs/reverse-engineering/hooks/firmware-out-of-git.mjs +49 -0
  628. package/packs/reverse-engineering/pack.json +35 -0
  629. package/packs/reverse-engineering/rules/a-negative-names-what-was-scanned.md +19 -0
  630. package/packs/reverse-engineering/rules/account-every-term.md +20 -0
  631. package/packs/reverse-engineering/rules/addresses-name-their-space.md +22 -0
  632. package/packs/reverse-engineering/rules/every-law-has-a-source.md +18 -0
  633. package/packs/reverse-engineering/rules/findings-are-withdrawn-in-place.md +17 -0
  634. package/packs/reverse-engineering/rules/firmware-stays-out.md +18 -0
  635. package/packs/reverse-engineering/rules/names-before-code.md +19 -0
  636. package/packs/reverse-engineering/rules/reproduction-or-original.md +18 -0
  637. package/packs/reverse-engineering/rules/two-sources-before-naming.md +21 -0
  638. package/packs/reverse-engineering/skills/bank-census/SKILL.md +18 -0
  639. package/packs/reverse-engineering/skills/gather-sources/SKILL.md +22 -0
  640. package/packs/reverse-engineering/skills/menu-map/SKILL.md +28 -0
  641. package/packs/reverse-engineering/skills/names-first/SKILL.md +41 -0
  642. package/packs/reverse-engineering/skills/re-deliverables/SKILL.md +21 -0
  643. package/packs/reverse-engineering/skills/tripwire-the-law/SKILL.md +19 -0
  644. package/packs/reverse-engineering/tools/lib/unwrap.mjs +115 -0
  645. package/packs/reverse-engineering/tools/names-sweep.mjs +264 -0
  646. package/packs/rust/checks/rust-allow-needs-reason.json +16 -0
  647. package/packs/rust/checks/rust-blocking-in-async.json +32 -0
  648. package/packs/rust/checks/rust-if-chain-is-a-match.json +32 -0
  649. package/packs/rust/checks/rust-static-mut.json +32 -0
  650. package/packs/rust/checks/rust-string-as-error.json +34 -0
  651. package/packs/rust/checks/rust-stub-left-in.json +32 -0
  652. package/packs/rust/checks/rust-unsafe-needs-safety.json +31 -0
  653. package/packs/rust/checks/rust-unwrap-in-library.json +34 -0
  654. package/packs/rust/checks/rust-wildcard-dependency.json +16 -0
  655. package/packs/rust/clippy.toml +5 -0
  656. package/packs/rust/pack.json +27 -0
  657. package/packs/rust/rules/rust-async-never-blocks.md +20 -0
  658. package/packs/rust/rules/rust-borrow-before-you-clone.md +19 -0
  659. package/packs/rust/rules/rust-errors-are-returned.md +22 -0
  660. package/packs/rust/rules/rust-lints-are-the-gate.md +23 -0
  661. package/packs/rust/rules/rust-repeats-become-templates.md +28 -0
  662. package/packs/rust/rules/rust-unsafe-is-proved.md +21 -0
  663. package/packs/rust/skills/rust-extract-template/SKILL.md +50 -0
  664. package/packs/rust/skills/rust-port/SKILL.md +22 -0
  665. package/packs/rust/skills/rust-review/SKILL.md +24 -0
  666. package/packs/rust/tools/rust-lints.toml +19 -0
  667. package/packs/shell/checks/sh-mktemp.json +18 -0
  668. package/packs/shell/checks/sh-no-backticks.json +18 -0
  669. package/packs/shell/checks/sh-no-eval.json +18 -0
  670. package/packs/shell/checks/sh-no-parse-ls.json +18 -0
  671. package/packs/shell/checks/sh-no-pipe-to-shell.json +18 -0
  672. package/packs/shell/checks/sh-no-program-in-heredoc.json +18 -0
  673. package/packs/shell/checks/sh-quote-arguments.json +18 -0
  674. package/packs/shell/checks/sh-rm-guarded.json +18 -0
  675. package/packs/shell/checks/sh-strict-mode.json +20 -0
  676. package/packs/shell/pack.json +28 -0
  677. package/packs/shell/rules/shell-repeats-become-templates.md +23 -0
  678. package/packs/shell/rules/shell-strict-and-quoted.md +27 -0
  679. package/packs/shell/skills/shell-extract-template/SKILL.md +32 -0
  680. package/packs/shell-hooks/checks/gnu-only-in-shell.json +18 -0
  681. package/packs/shell-hooks/checks/hook-command-anchored.json +12 -0
  682. package/packs/shell-hooks/checks/hook-json-by-tool.json +18 -0
  683. package/packs/shell-hooks/checks/no-bash-c-with-variable.json +20 -0
  684. package/packs/shell-hooks/pack.json +36 -0
  685. package/packs/shell-hooks/rules/hooks-portable-anchored-quoted.md +26 -0
  686. package/packs/sound-design/checks/audio-seed-fixed.json +23 -0
  687. package/packs/sound-design/checks/mix-is-a-crossfade.json +30 -0
  688. package/packs/sound-design/checks/no-hash-in-the-signal.json +30 -0
  689. package/packs/sound-design/checks/no-literal-key-anchor.json +30 -0
  690. package/packs/sound-design/checks/test-compares-a-function-with-itself.json +22 -0
  691. package/packs/sound-design/pack.json +22 -0
  692. package/packs/sound-design/rules/algorithms-are-data.md +26 -0
  693. package/packs/sound-design/rules/meter-before-engine.md +27 -0
  694. package/packs/sound-design/rules/neutral-is-exact.md +26 -0
  695. package/packs/sound-design/rules/test-off-the-easy-point.md +28 -0
  696. package/packs/sound-design/rules/unreachable-is-said.md +25 -0
  697. package/packs/sound-design/rules/waveforms-and-octaves.md +24 -0
  698. package/packs/sound-design/skills/bounce-a-plugin/SKILL.md +40 -0
  699. package/packs/sound-design/skills/choose-observable/SKILL.md +18 -0
  700. package/packs/sound-design/skills/measure-a-law/SKILL.md +18 -0
  701. package/packs/sound-design/skills/measure-reverb/SKILL.md +19 -0
  702. package/packs/sound-design/skills/spread-probe/SKILL.md +18 -0
  703. package/packs/sound-design/tools/vst3host/build.sh +73 -0
  704. package/packs/sound-design/tools/vst3host/host_events.h +101 -0
  705. package/packs/sound-design/tools/vst3host/options.h +172 -0
  706. package/packs/sound-design/tools/vst3host/render.cpp +245 -0
  707. package/packs/sound-design/tools/vst3host/session.h +241 -0
  708. package/packs/stellix/checks/no-keyboard-focus.json +12 -0
  709. package/packs/stellix/checks/one-seeded-random.json +16 -0
  710. package/packs/stellix/checks/world-never-includes-painter.json +12 -0
  711. package/packs/stellix/checks/world-no-libm.json +15 -0
  712. package/packs/stellix/checks/world-no-unordered.json +10 -0
  713. package/packs/stellix/hooks/no-shipped-images.mjs +88 -0
  714. package/packs/stellix/pack.json +61 -0
  715. package/packs/stellix/rules/stellix-deterministic-world.md +29 -0
  716. package/packs/stellix/rules/stellix-reset-generated.md +24 -0
  717. package/packs/stellix/rules/stellix-world-snapshot.md +27 -0
  718. package/packs/stellix/rules/world-continuous-collision.md +26 -0
  719. package/packs/stellix/rules/world-fp-determinism.md +28 -0
  720. package/packs/stored-text/checks/no-raw-html-from-data.json +31 -0
  721. package/packs/stored-text/checks/stored-text-libs-only-in-renderer.json +31 -0
  722. package/packs/stored-text/checks/stored-text-renderer-complete.json +24 -0
  723. package/packs/stored-text/checks/stored-text-through-renderer.json +25 -0
  724. package/packs/stored-text/pack.json +41 -0
  725. package/packs/stored-text/rules/stored-text-renders-once.md +26 -0
  726. package/packs/stored-text/skills/render-stored-text/SKILL.md +24 -0
  727. package/packs/synth-creator/checks/timing-from-synthcore.json +24 -0
  728. package/packs/synth-creator/checks/ui-drawn-in-code.json +23 -0
  729. package/packs/synth-creator/hooks/build-guard.mjs +232 -0
  730. package/packs/synth-creator/hooks/build-sweep.mjs +166 -0
  731. package/packs/synth-creator/hooks/frozen-files.mjs +63 -0
  732. package/packs/synth-creator/hooks/idle-wake.mjs +90 -0
  733. package/packs/synth-creator/hooks/protect-vendor.mjs +175 -0
  734. package/packs/synth-creator/hooks/spec-lock.mjs +117 -0
  735. package/packs/synth-creator/hooks/stage-guard.mjs +50 -0
  736. package/packs/synth-creator/hooks/time-guard.mjs +292 -0
  737. package/packs/synth-creator/hooks/user-asks.mjs +165 -0
  738. package/packs/synth-creator/pack.json +136 -0
  739. package/packs/synth-creator/rules/copy-trees-read-only.md +25 -0
  740. package/packs/synth-creator/rules/debug-by-measurement.md +20 -0
  741. package/packs/synth-creator/rules/done-means-fresh-evidence.md +18 -0
  742. package/packs/synth-creator/rules/hooks-and-gates.md +21 -0
  743. package/packs/synth-creator/rules/long-work-in-the-background.md +16 -0
  744. package/packs/synth-creator/rules/timing-from-synthcore.md +16 -0
  745. package/packs/synth-creator/skills/build-step/SKILL.md +125 -0
  746. package/packs/synth-creator/skills/build-through-the-queue/SKILL.md +21 -0
  747. package/packs/synth-creator/tools/buildq.mjs +74 -0
  748. package/packs/synth-creator/tools/freeze.mjs +36 -0
  749. package/packs/tui/checks/tui-entry-restores-terminal.json +27 -0
  750. package/packs/tui/checks/tui-gates-on-tty.json +25 -0
  751. package/packs/tui/checks/tui-no-ris-reset.json +22 -0
  752. package/packs/tui/checks/tui-resize-listener-removed.json +26 -0
  753. package/packs/tui/checks/tui-width-is-state.json +33 -0
  754. package/packs/tui/pack.json +44 -0
  755. package/packs/tui/rules/tui-resize-and-screen.md +25 -0
  756. package/packs/tui/skills/build-tui/SKILL.md +21 -0
  757. package/packs/ui-craft/checks/ui-input-needs-autocomplete.json +23 -0
  758. package/packs/ui-craft/checks/ui-intl-for-dates.json +21 -0
  759. package/packs/ui-craft/checks/ui-no-ai-palette.json +22 -0
  760. package/packs/ui-craft/checks/ui-no-animate-layout.json +22 -0
  761. package/packs/ui-craft/checks/ui-no-assistant-palette.json +23 -0
  762. package/packs/ui-craft/checks/ui-no-bounce-easing.json +22 -0
  763. package/packs/ui-craft/checks/ui-no-custom-cursor.json +22 -0
  764. package/packs/ui-craft/checks/ui-no-emoji-as-ui.json +22 -0
  765. package/packs/ui-craft/checks/ui-no-empty-image.json +21 -0
  766. package/packs/ui-craft/checks/ui-no-eyebrow.json +21 -0
  767. package/packs/ui-craft/checks/ui-no-furniture-text.json +22 -0
  768. package/packs/ui-craft/checks/ui-no-gradient-text.json +22 -0
  769. package/packs/ui-craft/checks/ui-no-index-numbering.json +21 -0
  770. package/packs/ui-craft/checks/ui-no-lorem.json +22 -0
  771. package/packs/ui-craft/checks/ui-no-marketing-buzzword.json +22 -0
  772. package/packs/ui-craft/checks/ui-no-paste-block.json +21 -0
  773. package/packs/ui-craft/checks/ui-no-placeholder-names.json +21 -0
  774. package/packs/ui-craft/checks/ui-no-scroll-hijack.json +21 -0
  775. package/packs/ui-craft/checks/ui-no-side-tab.json +21 -0
  776. package/packs/ui-craft/checks/ui-no-stock-labels.json +22 -0
  777. package/packs/ui-craft/checks/ui-no-transition-all.json +22 -0
  778. package/packs/ui-craft/checks/ui-no-uppercase-table-header.json +21 -0
  779. package/packs/ui-craft/checks/ui-no-zebra-rows.json +22 -0
  780. package/packs/ui-craft/checks/ui-no-zoom-lock.json +21 -0
  781. package/packs/ui-craft/pack.json +43 -0
  782. package/packs/ui-craft/rules/apps-are-not-pages.md +26 -0
  783. package/packs/ui-craft/rules/data-tells-the-truth.md +26 -0
  784. package/packs/ui-craft/rules/dates-and-numbers.md +18 -0
  785. package/packs/ui-craft/rules/forms-never-fight.md +22 -0
  786. package/packs/ui-craft/rules/interface-copy.md +26 -0
  787. package/packs/ui-craft/rules/motion-is-rare.md +31 -0
  788. package/packs/ui-craft/rules/no-generated-look.md +37 -0
  789. package/packs/ui-craft/rules/page-holds-its-frame.md +28 -0
  790. package/packs/ui-craft/rules/page-proved-rendered.md +19 -0
  791. package/packs/ui-craft/rules/pictures-do-a-job.md +25 -0
  792. package/packs/ui-craft/rules/pointer-feedback.md +28 -0
  793. package/packs/ui-craft/rules/screen-answers-one-question.md +24 -0
  794. package/packs/ui-craft/rules/survives-real-data.md +23 -0
  795. package/packs/ui-craft/rules/touch-and-small-screens.md +19 -0
  796. package/packs/ui-craft/rules/type-space-colour.md +26 -0
  797. package/packs/ui-craft/rules/url-holds-the-state.md +19 -0
  798. package/packs/ui-craft/skills/app-screen/SKILL.md +33 -0
  799. package/packs/ui-craft/skills/build-from-reference/SKILL.md +28 -0
  800. package/packs/ui-craft/skills/chart-choice/SKILL.md +34 -0
  801. package/packs/ui-craft/skills/hover-state/SKILL.md +28 -0
  802. package/packs/ui-craft/skills/page-critique/SKILL.md +33 -0
  803. package/packs/ui-craft/skills/prove-page/SKILL.md +23 -0
  804. package/packs/ui-craft/skills/redesign-page/SKILL.md +19 -0
  805. package/packs/ui-craft/skills/ui-code-review/SKILL.md +22 -0
  806. package/packs/ui-craft/skills/write-the-page/SKILL.md +21 -0
  807. package/packs/ui-craft/tools/page-measure.mjs +41 -0
  808. package/packs/web/checks/a11y-img-needs-alt.json +26 -0
  809. package/packs/web/checks/a11y-no-bare-outline-none.json +21 -0
  810. package/packs/web/checks/a11y-no-clickable-div.json +26 -0
  811. package/packs/web/checks/a11y-no-positive-tabindex.json +26 -0
  812. package/packs/web/checks/client-no-api-key.json +29 -0
  813. package/packs/web/checks/client-no-browser-global-at-module-scope.json +28 -0
  814. package/packs/web/checks/client-no-server-import.json +31 -0
  815. package/packs/web/checks/client-no-window-location-nav.json +28 -0
  816. package/packs/web/checks/css-no-inline-style.json +30 -0
  817. package/packs/web/checks/ds-pages-compose-primitives.json +28 -0
  818. package/packs/web/checks/key-from-index.json +23 -0
  819. package/packs/web/checks/prodbuild-no-cdn-runtime-deps.json +21 -0
  820. package/packs/web/checks/prodbuild-no-dev-flags.json +21 -0
  821. package/packs/web/checks/prodbuild-no-remote-fonts.json +22 -0
  822. package/packs/web/checks/rcss-button-cursor.json +30 -0
  823. package/packs/web/checks/rcss-no-100vw.json +21 -0
  824. package/packs/web/checks/rcss-no-fixed-wide-width.json +21 -0
  825. package/packs/web/checks/rcss-viewport-meta.json +28 -0
  826. package/packs/web/checks/secret-not-in-web-storage.json +25 -0
  827. package/packs/web/checks/tw-no-raw-hex-in-markup.json +34 -0
  828. package/packs/web/checks/wp-hero-not-lazy.json +27 -0
  829. package/packs/web/checks/wp-img-needs-dimensions.json +26 -0
  830. package/packs/web/pack.json +73 -0
  831. package/packs/web/rules/accessibility.md +26 -0
  832. package/packs/web/rules/client-boundaries.md +23 -0
  833. package/packs/web/rules/production-build.md +22 -0
  834. package/packs/web/rules/secrets-not-in-the-browser.md +18 -0
  835. package/packs/web/rules/styles-live-in-stylesheets.md +23 -0
  836. package/packs/web/rules/tailwind-v4.md +23 -0
  837. package/packs/web/rules/ui-primitives-one-module.md +30 -0
  838. package/packs/web/rules/web-performance.md +21 -0
  839. package/packs/web/skills/design-direction/SKILL.md +30 -0
  840. package/packs/web/skills/design-review/SKILL.md +28 -0
  841. package/packs/web/skills/pick-rendering-mode/SKILL.md +21 -0
  842. package/packs/web/skills/preflight-build/SKILL.md +23 -0
  843. package/packs/web/skills/seo-audit/SKILL.md +22 -0
  844. package/packs/websocket/checks/no-token-in-query.json +26 -0
  845. package/packs/websocket/checks/stale-socket-deletes-new-entry.json +25 -0
  846. package/packs/websocket/checks/ws-identity-from-message.json +26 -0
  847. package/packs/websocket/pack.json +21 -0
  848. package/packs/websocket/rules/identity-comes-from-the-connection.md +24 -0
  849. package/packs/writing/checks/ascii-no-em-dash.json +17 -0
  850. package/packs/writing/checks/no-copula-dodging.json +18 -0
  851. package/packs/writing/checks/no-dramatic-colon.json +18 -0
  852. package/packs/writing/checks/no-not-x-but-y.json +18 -0
  853. package/packs/writing/checks/no-participial-opener.json +18 -0
  854. package/packs/writing/checks/no-pseudo-wisdom.json +18 -0
  855. package/packs/writing/checks/no-slop-words.json +18 -0
  856. package/packs/writing/checks/no-stock-connectors.json +18 -0
  857. package/packs/writing/checks/no-time-or-date.json +27 -0
  858. package/packs/writing/checks/no-trailing-ing.json +18 -0
  859. package/packs/writing/checks/no-vague-attribution.json +18 -0
  860. package/packs/writing/pack.json +43 -0
  861. package/packs/writing/rules/ascii-no-em-dash.md +21 -0
  862. package/packs/writing/rules/cut-the-padding.md +20 -0
  863. package/packs/writing/rules/direct-voice.md +22 -0
  864. package/packs/writing/rules/no-cargo-cult.md +16 -0
  865. package/packs/writing/rules/no-scaffolding.md +19 -0
  866. package/packs/writing/rules/no-stock-language.md +27 -0
  867. package/packs/writing/rules/no-time-or-date.md +18 -0
  868. package/packs/writing/rules/rhythm-like-talk.md +20 -0
  869. package/packs/writing/rules/write-from-your-own-corner.md +20 -0
  870. package/packs/writing/skills/argument-post/SKILL.md +28 -0
  871. package/packs/writing/skills/humanize/SKILL.md +28 -0
  872. package/packs/writing/skills/launch-post/SKILL.md +38 -0
  873. package/packs/writing/skills/pick-subreddit/SKILL.md +69 -0
  874. package/packs/writing/skills/post-voice/SKILL.md +22 -0
  875. package/packs/writing/skills/reddit-post/SKILL.md +63 -0
  876. package/packs/writing/skills/reddit-title/SKILL.md +23 -0
  877. package/packs/writing/skills/reply-moves/SKILL.md +40 -0
  878. package/packs/writing/skills/reply-stance/SKILL.md +23 -0
  879. package/packs/writing/skills/should-i-reply/SKILL.md +21 -0
  880. package/packs/zod/hooks/schemas-only.mjs +53 -0
  881. package/packs/zod/pack.json +44 -0
  882. package/packs/zod/rules/env-shapes-only.md +14 -0
  883. package/packs/zod/rules/zod-4-schemas.md +14 -0
  884. package/profiles/stellix.layout.json +315 -0
  885. package/profiles/sub37.layout.json +247 -0
  886. package/prompts/scan-review.md +40 -0
  887. package/prompts/survey.md +82 -0
  888. package/prompts/workorder/PROMPT.md +53 -0
  889. package/prompts/workorder/run.sh +36 -0
  890. package/prompts/workorder/workorder.md +59 -0
@@ -0,0 +1,22 @@
1
+ ---
2
+ paths:
3
+ - "**/*.go"
4
+ ---
5
+
6
+ # Every error is handled or returned, wrapped with what was being done
7
+
8
+ <constraints>
9
+ Always do:
10
+ - Return an error wrapped with `%w` and what was being attempted.
11
+ - Take `ctx context.Context` first in anything that does I/O, and honour it.
12
+ - Use the standard library or a maintained client for a protocol.
13
+ - Run `go vet` and `staticcheck` in CI.
14
+
15
+ Never do:
16
+ - Discard an error with `_` on a state change or a parse.
17
+ - Start a goroutine with no way to stop it.
18
+ - Write a function again in another package: `template-law` reads Go.
19
+ </constraints>
20
+
21
+ ## Check
22
+ `go-unmarshal-error-ignored`, `go-exec-result-ignored`.
@@ -0,0 +1,9 @@
1
+ {
2
+ "id": "dawn-backends-and-validation",
3
+ "why": "Only Metal (macOS) and D3D12 (Windows) ship; extra Dawn backends add size and attack surface. skip_validation removes Dawn's safety net and is never used.",
4
+ "rule": ".claude/rules/dawn-build-and-shaders.md",
5
+ "concepts": ["build", "painter"],
6
+ "pattern": "DAWN_(ENABLE_(VULKAN|D3D11|NULL|DESKTOP_GL|OPENGLES)|BUILD_PROTOBUF)[\"']?\\s+(ON|TRUE|1)\\b|skip_validation",
7
+ "bad": "set(DAWN_ENABLE_VULKAN ON CACHE BOOL \"\" FORCE)",
8
+ "good": "set(DAWN_ENABLE_VULKAN OFF CACHE BOOL \"\" FORCE)"
9
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "dawn-no-spontaneous",
3
+ "why": "AllowSpontaneous callbacks fire on any thread and re-entering the API from them is undefined; use AllowProcessEvents or WaitAnyOnly and pump events on the render thread.",
4
+ "rule": ".claude/rules/dawn-device-and-render-thread.md",
5
+ "concepts": ["painter", "ui", "app"],
6
+ "pattern": "CallbackMode::AllowSpontaneous|WGPUCallbackMode_AllowSpontaneous",
7
+ "code": true,
8
+ "bad": "instance.RequestAdapter (&opts, wgpu::CallbackMode::AllowSpontaneous, onAdapter);",
9
+ "good": "instance.RequestAdapter (&opts, wgpu::CallbackMode::AllowProcessEvents, onAdapter);"
10
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "id": "dawn-present-on-render-thread",
3
+ "why": "Getting the surface texture and presenting must happen only on the render thread (Fifo present blocks; encoders are not thread-safe). Keep those calls in the render-thread files.",
4
+ "rule": ".claude/rules/dawn-device-and-render-thread.md",
5
+ "concepts": [
6
+ "painter",
7
+ "ui",
8
+ "app"
9
+ ],
10
+ "exclude": [
11
+ "@render_thread"
12
+ ],
13
+ "pattern": "\\bwgpuSurface(Present|GetCurrentTexture)\\s*\\(|\\.\\s*(Present|GetCurrentTexture)\\s*\\(",
14
+ "code": true,
15
+ "bad": "void Editor::paint (juce::Graphics&) { surface.GetCurrentTexture (&tex); surface.Present(); }",
16
+ "good": "void Editor::paint (juce::Graphics&) { renderThread.requestFrame(); }"
17
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "gpu-no-frame-stalls",
3
+ "why": "Blocking waits, sleeps, timer pacing, the message-thread lock or GPU readbacks on the frame path stall the render thread. Pace from the display link; read back only in tests.",
4
+ "rule": ".claude/rules/gpu-render-lifecycle.md",
5
+ "concepts": [
6
+ "painter"
7
+ ],
8
+ "pattern": "waitUntilCompleted|waitUntilScheduled|Thread::sleep|std::this_thread::sleep|startTimerHz\\s*\\(|MessageManagerLock|\\.\\s*MapAsync\\s*\\(|wgpuBufferMapAsync\\s*\\(",
9
+ "code": true,
10
+ "bad": "void RenderThread::frame() { juce::Thread::sleep (1); buffer.MapAsync (wgpu::MapMode::Read, 0, n, cb); }",
11
+ "good": "void RenderThread::frame() { encodePasses(); surface.Present(); }"
12
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "no-opengl-link",
3
+ "why": "No target of a Dawn-painted app links JUCE's OpenGL module or the OpenGL framework (no-opengl.json holds the sources; Stellix work order F, F7.6).",
4
+ "rule": ".claude/rules/gpu-frame-work.md",
5
+ "concepts": [
6
+ "build"
7
+ ],
8
+ "pattern": "juce_opengl|-framework\\s+OpenGL\\b|OpenGL\\.framework|find_package\\s*\\(\\s*OpenGL\\b|OpenGL::",
9
+ "bad": "target_link_libraries (app_juce INTERFACE \"-framework OpenGL\" juce::juce_opengl)",
10
+ "good": "target_link_libraries (app_juce INTERFACE \"-framework QuartzCore\")"
11
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": "no-opengl",
3
+ "why": "OpenGL is not a drawing path in a Dawn-painted app: Dawn (WebGPU on Metal or D3D12) draws everything through the painter. A GL call, a GL constant, an OpenGL header or JUCE's OpenGL module or classes brings back a second drawing path the picture gates do not judge (Stellix work order F, F7.6, deleted it for good).",
4
+ "rule": ".claude/rules/gpu-frame-work.md",
5
+ "concepts": [
6
+ "cpp",
7
+ "shaders"
8
+ ],
9
+ "pattern": "\\bgl[A-Z][A-Za-z0-9]*\\s*\\(|\\bGL_[A-Z][A-Z0-9_]*\\b|#\\s*include\\s*<\\s*(OpenGL|GL|GLES[0-9]*|juce_opengl)/|\\bjuce_opengl\\b|\\bOpenGL(Context|Renderer|PixelFormat|Version|Profile|ShaderProgram|FrameBuffer|Image|Texture|Helpers|Extensions)\\b",
10
+ "code": true,
11
+ "bad": "class Editor : private juce::OpenGLRenderer { void renderOpenGL() override { glClear (GL_COLOR_BUFFER_BIT); } };",
12
+ "good": "void Frame::draw (const gpu::DrawTarget& t) { beginPass (t.encoder, &rp).End(); }"
13
+ }
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env python3
2
+ """browser-guard: a natively drawn app never starts a browser. Its picture checks come from the app itself, drawn off-screen
3
+ by the same code as the window, never through a browser (the house law for
4
+ every GPU-painted synth).
5
+
6
+ From Tabula 1's browser-guard.py (main 8d5e8b30), made stricter: Tabula allowed one launch script for a batch; this allows
7
+ none. A PreToolUse hook on Bash, Write, Edit and MultiEdit. It exits 2 when the call starts Chrome or Chromium (the binary,
8
+ `open -a`, puppeteer or playwright launching or connecting to one), or writes code that would. Looking at processes (ps,
9
+ pgrep, grep) and words about a browser in .md, .txt, .json pass.
10
+
11
+ The refusal names the project's own picture command: .claude/layout.json "guards": { "browser": { "pictureCommand" } }.
12
+
13
+ Run `browser-guard.py --selftest` to see every rule fire on a planted call and every allowed call pass.
14
+ """
15
+ import json, os, re, sys, time
16
+ T0 = time.perf_counter()
17
+
18
+ sys.dont_write_bytecode = True
19
+ HERE = os.path.dirname(os.path.abspath(__file__))
20
+ sys.path[:0] = [os.path.join(HERE, "lib"), os.path.join(HERE, "..", "..", "base", "hooks", "lib")] # installed; in the package
21
+ import house # noqa: E402
22
+
23
+ DEFAULTS = {"pictureCommand": "the app's own off-screen render (the project's shot or picture program)"}
24
+
25
+
26
+ def way(cfg=None):
27
+ c = {**DEFAULTS, **(cfg or {})}
28
+ return ("This app is drawn natively and never starts a browser. A picture comes from the app's own off-screen render, drawn by "
29
+ f"the same painter code as the window: {c['pictureCommand']}.")
30
+
31
+
32
+ WAY = way()
33
+
34
+ BIN = r"""(?:["']?[^\s"';|&]*(?:Google Chrome(?: for Testing)?(?:\.app/Contents/MacOS/Google Chrome(?: for Testing)?)?|google-chrome(?:-stable)?|chromium(?:-browser)?|chrome-headless-shell|headless_shell)["']?)"""
35
+ LAUNCH_BASH = [
36
+ # the binary as the command of a segment (after env assignments, exec, nohup, timeout N, time)
37
+ re.compile(r"^(?:\s*\w+=\S*\s+)*(?:exec\s+|nohup\s+|time\s+|timeout\s+\S+\s+|/usr/bin/time\s+(?:-p\s+)?)*" + BIN + r"(?:\s|$)", re.I),
38
+ re.compile(r"\bopen\b[^|;&]*-a\s+[\"']?(?:Google Chrome|Chromium)", re.I),
39
+ re.compile(r"\.launch(?:PersistentContext|Server)?\s*\(|\bchrome-launcher\b"),
40
+ re.compile(r"\bnpx\s+(?:puppeteer|playwright)\b"),
41
+ ]
42
+ LOOKING = re.compile(r"^\s*(?:ps|pgrep|pkill|kill|killall|grep|egrep|rg|ag|xargs\s+kill|which|ls|stat|file|mdls|defaults\s+read|echo|printf|cat|head|tail|wc|sed|awk)\b")
43
+ # code that starts Chrome: a process call or launcher near a Chrome name or a headless flag
44
+ CODE = [
45
+ re.compile(r"(?:spawn|spawnSync|execFile|execFileSync|exec|execSync|fork)\s*\([^)]{0,200}(?:chrome|chromium|--headless)", re.I | re.S),
46
+ re.compile(r"subprocess\.(?:run|Popen|call|check_call|check_output)\s*\([^)]{0,300}(?:chrome|chromium|--headless)", re.I | re.S),
47
+ re.compile(r"os\.(?:system|popen)\s*\([^)]{0,300}(?:chrome|chromium|--headless)", re.I | re.S),
48
+ # a driver launching or connecting to a browser
49
+ re.compile(r"\b(?:chromium|firefox|webkit|puppeteer|browserType)\s*\.\s*launch(?:PersistentContext|Server)?\s*\("),
50
+ re.compile(r"\bchrome-launcher\b"),
51
+ re.compile(r"\bconnectOverCDP\b|\bpuppeteer\s*\.\s*connect\s*\("),
52
+ re.compile(r"""['"]--headless(?:=new)?['"]"""),
53
+ re.compile(r"""['"]--screenshot(?:=|['"])"""),
54
+ ]
55
+
56
+ def segments(cmd):
57
+ out, cur, q = [], "", None
58
+ for ch in cmd:
59
+ if q:
60
+ cur += ch
61
+ if ch == q: q = None
62
+ elif ch in "'\"":
63
+ q = ch; cur += ch
64
+ elif ch in ";|&\n":
65
+ out.append(cur); cur = ""
66
+ else:
67
+ cur += ch
68
+ out.append(cur)
69
+ return [s.strip() for s in out if s.strip()]
70
+
71
+ def blank_heredocs(cmd):
72
+ """a heredoc's body is text handed to a program, not a command: blanked before the command scan (WB-20: C++ source
73
+ with w.launch(...) in it, written to a file by cat, was read as a browser launch). A script given to an interpreter
74
+ (node, python with a heredoc) is still read whole, below."""
75
+ out, lines, i = [], cmd.split("\n"), 0
76
+ while i < len(lines):
77
+ out.append(lines[i]); m = re.search(r"<<-?\s*['\"]?(\w+)['\"]?", lines[i]); i += 1
78
+ if m:
79
+ while i < len(lines) and lines[i].strip() != m.group(1): i += 1
80
+ if i < len(lines): out.append(lines[i]); i += 1
81
+ return "\n".join(out)
82
+
83
+ def check_bash(cmd):
84
+ for seg in segments(blank_heredocs(cmd)):
85
+ if LOOKING.match(seg): continue
86
+ for rx in LAUNCH_BASH:
87
+ if rx.search(seg): return f"browser-guard: this starts Chrome directly (`{seg[:90]}`). {WAY}"
88
+ # a script handed to an interpreter inline (node -e, python -c, a heredoc)
89
+ if re.search(r"\b(?:node|python3?|deno|bun)\b", cmd):
90
+ for rx in CODE:
91
+ if rx.search(cmd): return f"browser-guard: this script starts Chrome itself. {WAY}"
92
+ return None
93
+
94
+ def check_code(path, text):
95
+ if not text: return None
96
+ if str(path).endswith("browser-guard.py"): return None # this file names what it catches
97
+ if re.search(r"\.(md|txt|json|csv)$", str(path)): return None # words about Chrome, not code that starts it
98
+ for rx in CODE:
99
+ m = rx.search(text)
100
+ if m: return f"browser-guard: {path} would start Chrome itself (`{m.group(0)[:80]}`). {WAY}"
101
+ return None
102
+
103
+ def inside(path, root):
104
+ """Only this project's files are judged on a write (a worktree's are the project's); a script written in another
105
+ project, a scratchpad or a test fixture starts nothing here (0.6.0: it refused a test that only names a launch)."""
106
+ if root is None: return True
107
+ p = house.main_root(os.path.abspath(os.path.join(root, str(path))))
108
+ return p == root or p.startswith(root.rstrip("/") + "/")
109
+
110
+ def added_text(before, after):
111
+ """The lines a write adds (all of them for a new file), so code that was already there is not judged again."""
112
+ old = set((before or "").splitlines())
113
+ return "\n".join(l for l in (after or "").splitlines() if l not in old)
114
+
115
+ def check(event, root=None):
116
+ tool, inp = event.get("tool_name", ""), event.get("tool_input", {}) or {}
117
+ if tool == "Bash":
118
+ cmd = inp.get("command", "")
119
+ r = check_bash(cmd)
120
+ if r: return r
121
+ # every file the shell writes, by any route (>, >>, tee, sed -i, cp, mv, a heredoc into a file; WB-69)
122
+ for w in house.shell_writes(cmd, event.get("cwd") or root or os.getcwd()) if re.search(r"[>|]|\b(cp|mv|sed|tee|install|rsync)\b", cmd) else []:
123
+ if w.get("after") is not None and inside(w["path"], root):
124
+ r = check_code(w["path"], added_text(w.get("before"), w["after"]))
125
+ if r: return r
126
+ return None
127
+ if tool == "NotebookEdit":
128
+ return check_code(inp.get("notebook_path", ""), inp.get("new_source", "")) if inside(inp.get("notebook_path", ""), root) else None
129
+ if not inside(inp.get("file_path", ""), root): return None
130
+ if tool == "Write": return check_code(inp.get("file_path", ""), inp.get("content", ""))
131
+ if tool == "Edit": return check_code(inp.get("file_path", ""), inp.get("new_string", ""))
132
+ if tool == "MultiEdit": return next((r for e in inp.get("edits", []) if (r := check_code(inp.get("file_path", ""), e.get("new_string", "")))), None)
133
+ return None
134
+
135
+ def selftest():
136
+ G = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
137
+ blocked = [
138
+ ("Bash", {"command": f'"{G}" --headless=new --screenshot=/tmp/a.png file:///tmp/a.html'}),
139
+ ("Bash", {"command": f"cd /tmp && '{G}' --headless --dump-dom file:///x.html > x"}),
140
+ ("Bash", {"command": "CHROME=1 google-chrome --headless --screenshot x"}),
141
+ ("Bash", {"command": "timeout 30 chromium --headless --print-to-pdf a.html"}),
142
+ ("Bash", {"command": 'open -a "Google Chrome" screenshots/a.png'}),
143
+ ("Bash", {"command": "node -e \"const p = require('puppeteer'); p.launch()\""}),
144
+ ("Bash", {"command": "node -e \"import('playwright').then(({chromium}) => chromium.launch())\""}),
145
+ ("Bash", {"command": "python3 - <<'EOF'\nimport subprocess\nsubprocess.run(['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome','--headless'])\nEOF"}),
146
+ ("Write", {"file_path": "/x/tools/shot.mjs", "content": "import { execFile } from 'node:child_process';\nexecFile(chrome, ['--headless=new', '--screenshot=a.png'])"}),
147
+ ("Edit", {"file_path": "/x/kit/synthpanel-creator/src/raster.js", "old_string": "a", "new_string": "execFileSync(chrome, ['--headless=new'])"}),
148
+ ("Write", {"file_path": "/x/tools/a.py", "content": "import subprocess\nsubprocess.run([CHROME, '--headless', url])"}),
149
+ ("Write", {"file_path": "/x/tools/b.js", "content": "import puppeteer from 'puppeteer';\nconst br = await puppeteer.launch();"}),
150
+ ("Write", {"file_path": "/x/onechrome.js", "content": "spawn(chrome, ['--headless=new'])"}),
151
+ ("Write", {"file_path": "/x/tools/d.mjs", "content": "const browser = await chromium.connectOverCDP(endpoint);"}),
152
+ ("Write", {"file_path": "/x/tools/c.mjs", "content": "import { chromium } from 'playwright';\nconst browser = await chromium.launch();"}),
153
+ ]
154
+ allowed = [
155
+ ("Bash", {"command": "ps -axo pid,command | grep -E 'Google Chrome.*--headless' | grep -v grep | awk '{print $1}' | xargs kill -KILL"}),
156
+ ("Bash", {"command": "out/synth_shot --render build/pictures/s3/a.png --size 3584x2016"}),
157
+ ("Bash", {"command": "grep -rn -- '--headless' kit/ | head"}),
158
+ ("Bash", {"command": "git commit -m 'B-382: one Chrome (no more google-chrome --headless per sprite)' -- bugs.md"}),
159
+ ("Write", {"file_path": "/x/bugs.md", "content": "one headless Chrome per sprite, execFile(chrome, ['--headless'])"}),
160
+ ("Edit", {"file_path": "/x/lib/painter/src/draw.cpp", "old_string": "a", "new_string": "panel.setLit (\"expand\", open);"}),
161
+ ("Bash", {"command": "cat > probes/reach/r.cpp <<'EOF'\n w.launch(0, sim::Kind::head, kKey, 1, foot, vel, age);\nEOF\nbash tools/build.sh build r"}), # WB-20
162
+ ]
163
+ blocked.append(("Bash", {"command": "node - <<'EOF'\nconst { chromium } = require('playwright'); await chromium.launch();\nEOF"})) # WB-20: a heredoc node runs still counts
164
+ blocked.append(("Write", {"file_path": "/x/.claude/worktrees/agent-a/tools/e.mjs", "content": "await puppeteer.launch();"})) # a worktree is the project
165
+ allowed.append(("Write", {"file_path": "/elsewhere/scratch/patch.py", "content": "s = 'await puppeteer.launch();'"})) # another project's file
166
+ blocked.append(("Bash", {"command": "cat > /x/tools/s.mjs <<'EOF'\nconst b = await puppeteer.launch();\nEOF"})) # WB-69: a heredoc into a file
167
+ blocked.append(("NotebookEdit", {"notebook_path": "/x/tools/n.ipynb", "new_source": "await chromium.launch()"}))
168
+ bad = 0
169
+ for tool, inp in blocked:
170
+ r = check({"tool_name": tool, "tool_input": inp}, "/x")
171
+ if not r: bad += 1; print(f"NOT BLOCKED: {tool} {json.dumps(inp)[:100]}")
172
+ for tool, inp in allowed:
173
+ r = check({"tool_name": tool, "tool_input": inp}, "/x")
174
+ if r: bad += 1; print(f"WRONGLY BLOCKED: {tool} {json.dumps(inp)[:100]}\n {r[:120]}")
175
+ print(f"browser-guard selftest: {len(blocked)} launches blocked, {len(allowed)} other calls passed: {'PASS' if not bad else f'{bad} wrong'}")
176
+ return 1 if bad else 0
177
+
178
+ def main(event):
179
+ global WAY
180
+ WAY = way(house.guard("browser", DEFAULTS))
181
+ reason = check(event, house.main_root(house.project_root()))
182
+ if reason:
183
+ print(reason, file=sys.stderr)
184
+ return 2
185
+ return 0
186
+
187
+ if __name__ == "__main__":
188
+ if "--selftest" in sys.argv: sys.exit(selftest())
189
+ try: event = json.load(sys.stdin)
190
+ except Exception: sys.exit(0)
191
+ code = 1
192
+ try:
193
+ code = main(event)
194
+ finally: # one timing line per call (KWB-24), through the shared helper
195
+ house.log_hook("browser-guard", event.get("hook_event_name"), (time.perf_counter() - T0) * 1000, code, event.get("tool_name"))
196
+ sys.exit(code)
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "gpu-painter",
3
+ "version": "1.0.0",
4
+ "description": "GPU-drawn UI on Dawn (Metal on Mac, Direct3D 12 on Windows), drawn natively: no OpenGL, no browser.",
5
+ "type": "stock",
6
+ "author": "claude-packs",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/TheDecipherist/claude-packs",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/TheDecipherist/claude-packs.git",
12
+ "directory": "packs/gpu-painter"
13
+ },
14
+ "keywords": [
15
+ "gpu",
16
+ "dawn",
17
+ "webgpu"
18
+ ],
19
+ "engines": {
20
+ "claude-packs": ">=0.19.0"
21
+ },
22
+ "folders": {
23
+ "painter": {
24
+ "path": "src/painter",
25
+ "purpose": "the GPU renderer: Dawn device, surfaces, passes, the snapshot reader"
26
+ },
27
+ "shaders": {
28
+ "path": "src/painter/shaders",
29
+ "purpose": "WGSL shaders"
30
+ },
31
+ "ui": {
32
+ "path": "src/ui",
33
+ "purpose": "input, gestures, camera, picking, undo (no drawing code)"
34
+ }
35
+ },
36
+ "concepts": {
37
+ "painter": [
38
+ "painter"
39
+ ],
40
+ "shaders": [
41
+ "shaders",
42
+ "**/*.wgsl"
43
+ ],
44
+ "ui": [
45
+ "ui"
46
+ ]
47
+ },
48
+ "skillsIn": "painter",
49
+ "hooks": {
50
+ "PreToolUse": [
51
+ {
52
+ "matcher": "Write|Edit|MultiEdit|NotebookEdit|Bash",
53
+ "hooks": [
54
+ {
55
+ "type": "command",
56
+ "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/browser-guard.py\"",
57
+ "timeout": 15
58
+ }
59
+ ]
60
+ }
61
+ ]
62
+ },
63
+ "files": {
64
+ "render_thread": "src/painter/render_thread.cpp"
65
+ },
66
+ "kinds": {
67
+ "gpu-code": {
68
+ "what": "anything that calls Dawn/WebGPU: device, surface, passes, the render thread",
69
+ "in": "painter",
70
+ "concepts": [
71
+ "painter",
72
+ "tests"
73
+ ],
74
+ "content": "\\b(wgpu::|wgpu[A-Z]\\w*\\s*\\(|WGPU[A-Z]\\w+)"
75
+ },
76
+ "shader": {
77
+ "what": "WGSL shaders",
78
+ "in": "shaders",
79
+ "concepts": [
80
+ "painter"
81
+ ],
82
+ "files": [
83
+ "**/*.wgsl"
84
+ ]
85
+ },
86
+ "ui-input": {
87
+ "what": "input, gestures, camera, picking and undo (no drawing code)",
88
+ "in": "ui"
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,27 @@
1
+ ---
2
+ # concepts: build, shaders, painter
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # Dawn is pinned and built by us; shaders are embedded and validated at build time
8
+
9
+ <constraints>
10
+ Always do:
11
+ - Pin one Dawn commit, built from source with CMake (`DAWN_BUILD_MONOLITHIC_LIBRARY`, `find_package(Dawn)`, link `dawn::webgpu_dawn`), and sign it with the plugin. Dawn has no semver, its API changes often, and its GitHub nightlies are unsigned.
12
+ - Build only the backends we ship: Metal on macOS, Direct3D 12 on Windows. Turn off Vulkan, D3D11, the null backend, desktop GL, protobuf, and Tint's tests and command-line tools.
13
+ - Measure what Dawn adds to the plugin binary after dead-stripping, and record it in the build notes.
14
+ - Embed WGSL into the binary at build time, and validate every shader offline in CI with the `tint` command-line tool.
15
+ - Wire Dawn's blob cache (a `DawnCacheDeviceDescriptor` with load/store callbacks) with an isolation key that includes the plugin version, so the second launch skips shader compilation.
16
+ - Ship Dawn's BSD-3-Clause notice and its dependencies' licence notices (Abseil, Apache-2.0) in the credits.
17
+ - Debug builds: Full backend validation, `dump_shaders_on_failure`, `use_user_defined_labels_in_backend`, and labels on every pipeline and pass.
18
+
19
+ Never do:
20
+ - Use the `skip_validation` toggle, even in release builds.
21
+ - Build shader source from strings at runtime.
22
+ - Update the pinned Dawn commit without running the golden-image and frame-bench gates.
23
+ </constraints>
24
+
25
+ ## Check
26
+ - `.claude/checks/dawn-backends-and-validation.json` blocks extra backends and `skip_validation`.
27
+ - CI: `tint` validates every `.wgsl`; the bench shows second-launch pipeline creation under 10% of the first.
@@ -0,0 +1,26 @@
1
+ ---
2
+ # concepts: painter
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # One Dawn device per process, one render thread, and every GPU call on it
8
+
9
+ <constraints>
10
+ Always do:
11
+ - Keep one process-wide, reference-counted `wgpu::Instance` and `wgpu::Device` shared by every plugin instance. The last editor or processor to release it destroys the device and joins Dawn's worker threads, before the plugin bundle can unload.
12
+ - Run every command encoder, `GetCurrentTexture` and `Present` on the one render thread. Encoders are never thread-safe, and a Fifo present blocks its thread.
13
+ - Use `CallbackMode::AllowProcessEvents` or `WaitAnyOnly` for every async call, and pump events on the render thread.
14
+ - Install both the device-lost callback and the uncaptured-error callback. On device loss, rebuild the device and every GPU resource, and the frame must come back on its own.
15
+ - Present with `PresentMode::Fifo`. On Metal, Dawn treats Fifo and Mailbox the same.
16
+
17
+ Never do:
18
+ - Use `CallbackMode::AllowSpontaneous`. Callbacks then fire on any thread, and calling back into the API from them is undefined behaviour.
19
+ - Present or encode on the message thread or the audio thread.
20
+ - Rely on `ImplicitDeviceSynchronization` to make multi-threaded use safe. Dawn's own docs call it heavy-handed, with deadlock risk.
21
+ </constraints>
22
+
23
+ ## Check
24
+ - `.claude/checks/dawn-no-spontaneous.json` and `dawn-present-on-render-thread.json` block the forbidden patterns.
25
+ - Test: force `device.Destroy()` mid-session. Pass: the frame comes back and no errors are left unhandled.
26
+ - `gpu-lifecycle-stress`: zero Dawn threads remain after the last release.
@@ -0,0 +1,20 @@
1
+ ---
2
+ # concepts: shaders, painter
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # Thin lines are antialiased in the shader; MSAA only for silhouettes
8
+
9
+ <constraints>
10
+ Always do:
11
+ - Draw orbit rings, ghost paths, border lines and the UI as instanced quads or signed-distance shapes, with analytic coverage: distance divided by `fwidth`, smoothed over about 1 pixel.
12
+ - Use 4x MSAA only for planet and crystal silhouettes (WebGPU allows 1 or 4). On Apple GPUs, give the MSAA colour and depth attachments transient usage so they stay in tile memory.
13
+
14
+ Never do:
15
+ - Use TAA (ghosting on moving thin lines) or FXAA (blurs text).
16
+ - Draw hairlines as 1-pixel GPU lines and hope.
17
+ </constraints>
18
+
19
+ ## Check
20
+ Golden test: a 0.5–1 px ring at 1x and 2x shows no stair-steps; frame-to-frame FLIP on a slow rotation stays below 0.01 (no shimmer).
@@ -0,0 +1,22 @@
1
+ ---
2
+ # concepts: painter, shaders
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # Draw order: opaque, then additive glows, then sorted transparency, then overlay
8
+
9
+ <constraints>
10
+ Always do, in this order:
11
+ 1. Opaque planet bodies, with depth write.
12
+ 2. Emissive glows, travellers, trails and the nebula as additive blending (One, One), with depth test on and depth write off. Addition doesn't care about order, so these need no sorting.
13
+ 3. The few truly transparent surfaces (the crystal, tags) sorted back to front per object on the CPU.
14
+ 4. The 2D overlay (columns, menus, readouts) last, in its own pass.
15
+
16
+ Never do:
17
+ - Use alpha blending for glows (they need sorting and still go wrong).
18
+ - Add order-independent transparency. Weighted blended OIT is an approximation with tuning cost, only worth it with many overlapping coloured alpha layers, which Stellix doesn't have.
19
+ </constraints>
20
+
21
+ ## Check
22
+ Golden test: the additive set rendered in permuted order gives an identical image.
@@ -0,0 +1,20 @@
1
+ ---
2
+ # concepts: shaders, painter
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # Bloom is a thresholdless mip pyramid with firefly suppression
8
+
9
+ <constraints>
10
+ Always do:
11
+ - Use the Jimenez (Call of Duty: Advanced Warfare) chain: downsample the HDR target over 5–6 levels from half resolution, with the Karis 1/(1+luma) weighted average on the first downsample only; upsample with a 3×3 tent, adding each level as it goes; composite at low strength (around 0.04).
12
+ - In calm mode, use the cheaper dual-Kawase chain at reduced strength.
13
+
14
+ Never do:
15
+ - Use a brightness threshold (pops as values cross it), or a single wide Gaussian at full resolution.
16
+ - Skip the Karis weighting. Small hot pixels (travellers, text glows) flicker without it.
17
+ </constraints>
18
+
19
+ ## Check
20
+ `gpu-frame-bench`: bloom p99 ≤ 0.5 ms GPU on the M1 Pro at 2x (house target), and no frame-to-frame flicker in a slowly moving scene (FLIP between frames below 0.01).
@@ -0,0 +1,25 @@
1
+ ---
2
+ # concepts: painter, bench
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # The space meets its frame budget on the minimum machine, with several copies open
8
+
9
+ From spec §7.3 and §9.
10
+
11
+ <constraints>
12
+ Always do:
13
+ - Judge every budget (world, painter, audio) on the **minimum machine, an Apple M1 Pro (2021)**. The development machine (M5 Max) is never the judge. There's no Intel or Rosetta build.
14
+ - Measure the two budgets separately: the world tick against the audio budget (96 held notes, every border open) and the drawing against the frame budget. A test that runs the world inside the frame reports both numbers, never one.
15
+ - Measure with several copies of Stellix open at once. They share one Dawn device and one render thread, so one slow copy delays the others.
16
+ - Measure GPU time with Dawn's `TimestampQuery` feature at pass boundaries, resolved and read back one or two frames later so the read never stalls. Dawn quantises timestamps by default (`timestamp_quantization` toggle); turn that off in bench and dev builds. Measure render-thread CPU time around the frame.
17
+ - Report GPU time and painter-thread CPU time at p99. A counter that didn't run is *invalid*, never 0 ms.
18
+ - Read the pattern: GPU time low but frame time high means sync, driver wait or present pacing. Times bunched at the display interval mean vsync.
19
+
20
+ Never do:
21
+ - Judge performance on the dev machine, by eye, or by average FPS.
22
+ </constraints>
23
+
24
+ ## Check
25
+ `gpu-frame-bench` on the M1 Pro: p99 within the budget numbers in the work order. House proposal until those are set: GPU ≤ 8 ms and painter CPU ≤ 2 ms at 2x scale, with 4 copies open. The CPU gate from `gpu-frame-work.md` must pass too.
@@ -0,0 +1,27 @@
1
+ ---
2
+ # concepts: painter, ui
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # Frames are drawn only when something changes, at the lowest rate that looks right
8
+
9
+ <constraints>
10
+ Always do:
11
+ - Render only when something changed: a parameter, live audio data (waveform, spectrum), travellers in flight, idle motion, or hover and drag. With nothing changing, present nothing.
12
+ - Run idle animation at 60 Hz. Allow 120 Hz only while the player is dragging or interacting.
13
+ - On Mac, drive frames from the display link (`CAMetalDisplayLink`, macOS 14+) with a preferred frame-rate range on whole-number divisions (120, 60, 30). Respect Low Power Mode and thermal state.
14
+ - Calm mode: 30 Hz, fewer particles, dual-Kawase bloom. Also honour the OS reduce-motion setting.
15
+ - Stop rendering (0 Hz) for hidden or covered editors.
16
+
17
+ Never do:
18
+ - Render continuously at the display maximum by default.
19
+ - Keep the GPU busy for a static, unchanged window.
20
+ </constraints>
21
+
22
+ ## Check
23
+ Bench (house targets):
24
+ - A static idle window presents 0 frames per second.
25
+ - Animated idle costs ≤ 2 ms GPU per frame on the M1 Pro.
26
+ - With 8 editors open, render-thread CPU totals ≤ 5%.
27
+ - Compare GPU power at 60 and 120 Hz with `powermetrics`.
@@ -0,0 +1,30 @@
1
+ ---
2
+ # concepts: painter, shaders
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # Everything is drawn on the graphics card; the CPU only hands over the snapshot
8
+
9
+ From spec §0 rules 1–3 and §9.
10
+
11
+ <constraints>
12
+ Always do:
13
+ - Draw everything on the card: the space, the columns, the controls, the keyboard band, the menus and text (a glyph atlas on the card, built from the shipped font files).
14
+ - Compute geometry, facets, noise, refraction, particles, bloom and tone mapping in shaders. The CPU's drawing job is one thing: upload the snapshot once a frame.
15
+ - Draw each particle system and object set (travellers, shatter pieces, comets, delay balls) with one instanced draw.
16
+ - Upload only what changed: the snapshot, plus waveform rings by sub-range.
17
+ - Keep frames in flight bounded, with per-frame buffers, so the CPU never overwrites what the card is reading.
18
+ - Compile shaders once (at build, or once at startup from embedded source) and cache the pipelines.
19
+ - Draw static controls once into memory when the window opens or resizes. The cache is made at runtime at that size, never shipped, and leaves motion unchanged.
20
+
21
+ Never do:
22
+ - Add a software drawing path or a fallback to one (Tabula's D6 doesn't apply to Stellix).
23
+ - Compute anything per vertex or per pixel on the CPU.
24
+ - Ship any image. The `no-shipped-images` hook refuses image files in source and resources; fonts are allowed.
25
+ - Read GPU results back during normal frames (test harness only).
26
+ </constraints>
27
+
28
+ ## Check
29
+ - CPU gate: time the CPU side of a frame. It goes red if it exceeds the snapshot upload by more than a small fixed margin.
30
+ - Frame bench counters: draw calls and uploaded bytes per frame (house choice: ≤ 50 draw calls in the reference scene).
@@ -0,0 +1,21 @@
1
+ ---
2
+ # concepts: painter, shaders, tests
3
+ paths:
4
+ - "placeholder"
5
+ ---
6
+
7
+ # What the 3D space looks like is proven by golden images
8
+
9
+ <constraints>
10
+ Always do:
11
+ - Render fixed scenes offscreen (fixed seed, fixed time, fixed size) at 1x and 2x scale, with fixed time, fixed seed and dithering off. Read them back in the test harness and compare against stored goldens kept per backend (Metal and Direct3D 12 differ in derivatives and precision). Compare with NVIDIA's ꟻLIP (BSD-3, single-header C++), not PSNR. Pass (house): mean FLIP ≤ 0.01 and 99th percentile ≤ 0.1 per scene; on the same machine and driver, repeat renders are bit-identical.
12
+ - Prove visual changes through the real user-facing path: the standalone with the real editor. Logs or JSON saying "rendered" prove nothing about what the user sees.
13
+ - Update goldens only for an intended visual change, with before and after images shown to the user (`gpu-golden-update` skill).
14
+
15
+ Never do:
16
+ - Mark a visual task done because the code compiles or the logs look right.
17
+ - Regenerate goldens to make a failing test pass.
18
+ </constraints>
19
+
20
+ ## Check
21
+ `gpu-golden-check` skill runs the image-diff tests. They fail over the FLIP thresholds and save the FLIP error heatmap.