@thedecipherist/claude-packs 0.0.0-stage → 1.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 (827) hide show
  1. package/CHANGELOG.md +680 -0
  2. package/LICENSE +21 -0
  3. package/README.md +316 -2
  4. package/bin/claude-packs.mjs +204 -0
  5. package/configurations/base/config.json +85 -0
  6. package/configurations/cpp/config.json +92 -0
  7. package/configurations/full-stack/config.json +152 -0
  8. package/configurations/go/config.json +96 -0
  9. package/configurations/node/config.json +100 -0
  10. package/configurations/python/config.json +97 -0
  11. package/configurations/synth-creator/config.json +148 -0
  12. package/global/hooks/gnu-shell.mjs +131 -0
  13. package/global/hooks/lib/program-read.mjs +196 -0
  14. package/global/hooks/lib/program-writes.mjs +177 -0
  15. package/global/hooks/lib/shell-writes.mjs +293 -0
  16. package/global/hooks/shell-traps.mjs +79 -0
  17. package/global/hooks/version-pin-guard.mjs +280 -0
  18. package/global/skills/latest-versions/SKILL.md +49 -0
  19. package/lib/backup.mjs +34 -0
  20. package/lib/claude-md.mjs +58 -0
  21. package/lib/config-cli.mjs +36 -0
  22. package/lib/configs.mjs +145 -0
  23. package/lib/coverage.mjs +86 -0
  24. package/lib/custom-packs.mjs +93 -0
  25. package/lib/doctor.mjs +115 -0
  26. package/lib/fix-plan.mjs +71 -0
  27. package/lib/git-tokens.mjs +64 -0
  28. package/lib/global.mjs +125 -0
  29. package/lib/hook-proof.mjs +28 -0
  30. package/lib/hook-timing.mjs +42 -0
  31. package/lib/hover-gate.mjs +29 -0
  32. package/lib/kit-lock.mjs +149 -0
  33. package/lib/layout.mjs +75 -0
  34. package/lib/logs.mjs +69 -0
  35. package/lib/manifest.mjs +24 -0
  36. package/lib/new.mjs +49 -0
  37. package/lib/once-only-report.mjs +54 -0
  38. package/lib/pack-manifest.mjs +20 -0
  39. package/lib/packs.mjs +107 -0
  40. package/lib/planner.mjs +59 -0
  41. package/lib/repeats.mjs +65 -0
  42. package/lib/repo-weight.mjs +28 -0
  43. package/lib/rules.mjs +40 -0
  44. package/lib/scan-detect.mjs +94 -0
  45. package/lib/scan.mjs +168 -0
  46. package/lib/selftest-cache.mjs +39 -0
  47. package/lib/settings.mjs +138 -0
  48. package/lib/shape-cli.mjs +76 -0
  49. package/lib/shape.mjs +4 -0
  50. package/lib/suggest.mjs +18 -0
  51. package/lib/switches.mjs +44 -0
  52. package/lib/symmetry-doctor.mjs +26 -0
  53. package/lib/sync.mjs +130 -0
  54. package/package.json +34 -4
  55. package/packs/ai/checks/boundary-computes-its-own-hash.json +30 -0
  56. package/packs/ai/checks/model-call-needs-boundary.json +29 -0
  57. package/packs/ai/checks/model-id-from-config.json +28 -0
  58. package/packs/ai/checks/model-output-validated.json +26 -0
  59. package/packs/ai/pack.json +38 -0
  60. package/packs/ai/rules/ai-input-sha-boundary.md +31 -0
  61. package/packs/ai/rules/llm-pipeline-security.md +26 -0
  62. package/packs/audio-core/checks/denormals-not-in-prepare.json +12 -0
  63. package/packs/audio-core/checks/dsp-without-apvts.json +12 -0
  64. package/packs/audio-core/checks/float-phase-or-rate.json +12 -0
  65. package/packs/audio-core/checks/juce-snap-to-zero-off.json +12 -0
  66. package/packs/audio-core/checks/keep-werror.json +12 -0
  67. package/packs/audio-core/checks/no-fast-math.json +14 -0
  68. package/packs/audio-core/checks/no-locale-change.json +12 -0
  69. package/packs/audio-core/checks/no-march-native.json +14 -0
  70. package/packs/audio-core/clang-tidy +28 -0
  71. package/packs/audio-core/hooks/lib/realtime-checks.mjs +56 -0
  72. package/packs/audio-core/hooks/param-id-lock.mjs +129 -0
  73. package/packs/audio-core/hooks/realtime-guard.mjs +67 -0
  74. package/packs/audio-core/pack.json +187 -0
  75. package/packs/audio-core/rules/audio-thread-realtime-safe.md +27 -0
  76. package/packs/audio-core/rules/audio-ui-thread-handoff.md +21 -0
  77. package/packs/audio-core/rules/boundary-tests-cross-the-boundary.md +16 -0
  78. package/packs/audio-core/rules/build-flags-safe.md +20 -0
  79. package/packs/audio-core/rules/cached-parameter-pointers.md +28 -0
  80. package/packs/audio-core/rules/clang-tidy-core-guidelines.md +21 -0
  81. package/packs/audio-core/rules/control-reaches-every-surface.md +23 -0
  82. package/packs/audio-core/rules/cpu-worst-case-per-block.md +26 -0
  83. package/packs/audio-core/rules/dc-block-after-asymmetry.md +22 -0
  84. package/packs/audio-core/rules/discrete-params-snap.md +19 -0
  85. package/packs/audio-core/rules/double-where-precision-matters.md +20 -0
  86. package/packs/audio-core/rules/filters-stable-under-modulation.md +29 -0
  87. package/packs/audio-core/rules/host-parameters-at-scale.md +24 -0
  88. package/packs/audio-core/rules/house-control-behaviours.md +34 -0
  89. package/packs/audio-core/rules/math-domain-guards.md +19 -0
  90. package/packs/audio-core/rules/modulated-delay-interpolation.md +22 -0
  91. package/packs/audio-core/rules/multiband-phase-coherent.md +22 -0
  92. package/packs/audio-core/rules/nonlinear-stages-antialiased.md +28 -0
  93. package/packs/audio-core/rules/note-ledger-and-pedals.md +22 -0
  94. package/packs/audio-core/rules/one-formula-per-value.md +20 -0
  95. package/packs/audio-core/rules/optimisations-are-null-tested.md +23 -0
  96. package/packs/audio-core/rules/oscillators-bandlimited.md +23 -0
  97. package/packs/audio-core/rules/output-limiter.md +23 -0
  98. package/packs/audio-core/rules/parameter-ids-never-change.md +20 -0
  99. package/packs/audio-core/rules/params-and-state-thread-safe.md +19 -0
  100. package/packs/audio-core/rules/params-snapshot-per-block.md +21 -0
  101. package/packs/audio-core/rules/patch-excludes-performance-controls.md +18 -0
  102. package/packs/audio-core/rules/per-sample-code-inlinable.md +22 -0
  103. package/packs/audio-core/rules/prepare-is-repeatable.md +23 -0
  104. package/packs/audio-core/rules/recursive-state-nan-guard.md +20 -0
  105. package/packs/audio-core/rules/reverb-loop-gain-bounded.md +24 -0
  106. package/packs/audio-core/rules/sample-accurate-midi.md +22 -0
  107. package/packs/audio-core/rules/sample-rate-and-block-size-from-host.md +23 -0
  108. package/packs/audio-core/rules/scoped-no-denormals.md +26 -0
  109. package/packs/audio-core/rules/smooth-continuous-parameters.md +22 -0
  110. package/packs/audio-core/rules/state-load-versioned-and-safe.md +22 -0
  111. package/packs/audio-core/rules/straight-on-and-aligned.md +21 -0
  112. package/packs/audio-core/rules/ui-matches-reference-look.md +21 -0
  113. package/packs/audio-core/rules/undo-one-gesture-one-step.md +21 -0
  114. package/packs/audio-core/rules/voice-steal-fades.md +21 -0
  115. package/packs/audio-core/rules/voice-sum-headroom.md +20 -0
  116. package/packs/audio-core/skills/analyse-reference-look/SKILL.md +21 -0
  117. package/packs/audio-core/skills/copy-and-prove/SKILL.md +98 -0
  118. package/packs/audio-core/skills/juce-realtime-audit/SKILL.md +22 -0
  119. package/packs/audio-core/skills/measure-tone/SKILL.md +20 -0
  120. package/packs/audio-core/skills/new-panel-control/SKILL.md +15 -0
  121. package/packs/audio-core/skills/prove-control/SKILL.md +23 -0
  122. package/packs/audio-core/skills/trace-parameter/SKILL.md +29 -0
  123. package/packs/audio-core/tools/lib/spectrum.mjs +112 -0
  124. package/packs/audio-core/tools/lib/wav.mjs +41 -0
  125. package/packs/audio-core/tools/tone-report.mjs +47 -0
  126. package/packs/base/checks/field-map-over-if-runs.json +25 -0
  127. package/packs/base/checks/lookup-over-if-chains.json +25 -0
  128. package/packs/base/checks/lookup-over-ternary-chains.json +20 -0
  129. package/packs/base/checks/no-code-after-midline-comment.json +12 -0
  130. package/packs/base/checks/one-walk-per-template.json +23 -0
  131. package/packs/base/checks/stub-reports-success.json +31 -0
  132. package/packs/base/checks/test-skip-on-failed-setup.json +17 -0
  133. package/packs/base/hooks/brief-guard.mjs +96 -0
  134. package/packs/base/hooks/code-shape.mjs +95 -0
  135. package/packs/base/hooks/dispatch-once.mjs +87 -0
  136. package/packs/base/hooks/file-size-guard.mjs +61 -0
  137. package/packs/base/hooks/folder-law.mjs +74 -0
  138. package/packs/base/hooks/git-guard.mjs +289 -0
  139. package/packs/base/hooks/lesson-checks.mjs +174 -0
  140. package/packs/base/hooks/lib/apply-edit.mjs +20 -0
  141. package/packs/base/hooks/lib/code-shapes.mjs +137 -0
  142. package/packs/base/hooks/lib/content.mjs +14 -0
  143. package/packs/base/hooks/lib/cpp-scan.mjs +94 -0
  144. package/packs/base/hooks/lib/dup-index.mjs +199 -0
  145. package/packs/base/hooks/lib/dup.mjs +127 -0
  146. package/packs/base/hooks/lib/elements.mjs +87 -0
  147. package/packs/base/hooks/lib/event-log.mjs +67 -0
  148. package/packs/base/hooks/lib/function-shapes.mjs +90 -0
  149. package/packs/base/hooks/lib/git-adds.mjs +20 -0
  150. package/packs/base/hooks/lib/git-guard-selftest.mjs +99 -0
  151. package/packs/base/hooks/lib/glob.mjs +33 -0
  152. package/packs/base/hooks/lib/hook-log.mjs +100 -0
  153. package/packs/base/hooks/lib/house.py +77 -0
  154. package/packs/base/hooks/lib/languages.mjs +66 -0
  155. package/packs/base/hooks/lib/layout.mjs +54 -0
  156. package/packs/base/hooks/lib/making-check-selftest.mjs +109 -0
  157. package/packs/base/hooks/lib/near-copies.mjs +76 -0
  158. package/packs/base/hooks/lib/program-read.mjs +196 -0
  159. package/packs/base/hooks/lib/program-writes.mjs +177 -0
  160. package/packs/base/hooks/lib/project.mjs +81 -0
  161. package/packs/base/hooks/lib/prose.mjs +11 -0
  162. package/packs/base/hooks/lib/pushed.mjs +201 -0
  163. package/packs/base/hooks/lib/repo-index.mjs +52 -0
  164. package/packs/base/hooks/lib/secret-patterns.mjs +18 -0
  165. package/packs/base/hooks/lib/selftest.mjs +45 -0
  166. package/packs/base/hooks/lib/shape-code.mjs +126 -0
  167. package/packs/base/hooks/lib/shape.mjs +294 -0
  168. package/packs/base/hooks/lib/shell-writes-selftest.mjs +65 -0
  169. package/packs/base/hooks/lib/shell-writes.mjs +293 -0
  170. package/packs/base/hooks/lib/turn.mjs +81 -0
  171. package/packs/base/hooks/lib/writes.mjs +71 -0
  172. package/packs/base/hooks/making-check.mjs +243 -0
  173. package/packs/base/hooks/making.mjs +106 -0
  174. package/packs/base/hooks/once-only.mjs +150 -0
  175. package/packs/base/hooks/placement-law.mjs +84 -0
  176. package/packs/base/hooks/repo-litter.mjs +75 -0
  177. package/packs/base/hooks/reuse-hint.mjs +75 -0
  178. package/packs/base/hooks/run-hooks.mjs +132 -0
  179. package/packs/base/hooks/secrets-guard.mjs +99 -0
  180. package/packs/base/hooks/shape-law.mjs +133 -0
  181. package/packs/base/hooks/suite-once.mjs +80 -0
  182. package/packs/base/hooks/template-law.mjs +148 -0
  183. package/packs/base/hooks/untrusted-boundary.mjs +53 -0
  184. package/packs/base/pack.json +214 -0
  185. package/packs/base/rules/a-control-is-seen-to-fire.md +27 -0
  186. package/packs/base/rules/behaviour-lives-with-its-kind.md +51 -0
  187. package/packs/base/rules/bug-fix-starts-red.md +25 -0
  188. package/packs/base/rules/field-map-over-if-runs.md +47 -0
  189. package/packs/base/rules/finished-work-lands.md +17 -0
  190. package/packs/base/rules/git-right-first-time.md +19 -0
  191. package/packs/base/rules/instances-by-index-identities-by-id.md +54 -0
  192. package/packs/base/rules/lookup-over-if-chains.md +49 -0
  193. package/packs/base/rules/making-line-first.md +14 -0
  194. package/packs/base/rules/open-items-tagged.md +17 -0
  195. package/packs/base/rules/plan-and-logs.md +22 -0
  196. package/packs/base/rules/references-use-anchors.md +19 -0
  197. package/packs/base/rules/refusals-are-judged.md +18 -0
  198. package/packs/base/rules/reuse-before-writing.md +15 -0
  199. package/packs/base/rules/secrets-never-committed.md +16 -0
  200. package/packs/base/rules/skill-writing.md +23 -0
  201. package/packs/base/rules/split-before-the-limit.md +14 -0
  202. package/packs/base/rules/subagent-dispatch.md +26 -0
  203. package/packs/base/rules/test-only-what-changed.md +17 -0
  204. package/packs/base/rules/test-the-template-once.md +22 -0
  205. package/packs/base/rules/untrusted-content-boundary.md +15 -0
  206. package/packs/base/skills/add-lesson-check/SKILL.md +26 -0
  207. package/packs/base/skills/fix-from-scan/SKILL.md +25 -0
  208. package/packs/base/skills/land-branch/SKILL.md +24 -0
  209. package/packs/base/skills/make-it-a-template/SKILL.md +23 -0
  210. package/packs/base/skills/pdf-to-md/SKILL.md +25 -0
  211. package/packs/base/skills/pick-tests/SKILL.md +20 -0
  212. package/packs/base/skills/pressure-test-skill/SKILL.md +23 -0
  213. package/packs/base/skills/prove-instances-identical/SKILL.md +37 -0
  214. package/packs/base/tools/shape-symmetry-selftest.mjs +66 -0
  215. package/packs/base/tools/shape-symmetry.mjs +178 -0
  216. package/packs/base/tools/test-verdict.mjs +75 -0
  217. package/packs/ci/checks/ci-permissions-stated.json +18 -0
  218. package/packs/ci/checks/ci-tools-pinned.json +14 -0
  219. package/packs/ci/pack.json +21 -0
  220. package/packs/ci/rules/ci-covers-what-ships.md +20 -0
  221. package/packs/ci/rules/generated-files-have-no-diff.md +15 -0
  222. package/packs/content-site/checks/captcha-is-not-constant.json +27 -0
  223. package/packs/content-site/checks/img-has-size.json +20 -0
  224. package/packs/content-site/checks/page-head-complete.json +26 -0
  225. package/packs/content-site/pack.json +22 -0
  226. package/packs/content-site/rules/content-has-one-source.md +23 -0
  227. package/packs/content-site/rules/media-is-sized.md +24 -0
  228. package/packs/content-site/rules/page-head-is-complete.md +26 -0
  229. package/packs/content-site/rules/public-forms-are-defended.md +27 -0
  230. package/packs/content-site/skills/publish-a-page/SKILL.md +21 -0
  231. package/packs/cpp/checks/cpp-clamp-before-cast.json +16 -0
  232. package/packs/cpp/checks/cpp-find-with-the-library.json +12 -0
  233. package/packs/cpp/checks/cpp-hardened-test-build.json +18 -0
  234. package/packs/cpp/checks/cpp-m-pi-not-standard.json +23 -0
  235. package/packs/cpp/checks/cpp-no-atoi.json +16 -0
  236. package/packs/cpp/checks/cpp-no-const-cast.json +16 -0
  237. package/packs/cpp/checks/cpp-no-float-loop-counter.json +16 -0
  238. package/packs/cpp/checks/cpp-no-getenv-in-product.json +22 -0
  239. package/packs/cpp/checks/cpp-no-mutable-global.json +20 -0
  240. package/packs/cpp/checks/cpp-no-mutable-local-static.json +23 -0
  241. package/packs/cpp/checks/cpp-no-unchecked-fwrite.json +17 -0
  242. package/packs/cpp/checks/cpp-no-using-namespace-in-header.json +19 -0
  243. package/packs/cpp/checks/cpp-no-zero-size-array.json +23 -0
  244. package/packs/cpp/checks/cpp-numbers-pi.json +16 -0
  245. package/packs/cpp/pack.json +22 -0
  246. package/packs/cpp/rules/cpp-absent-and-failed-are-types.md +24 -0
  247. package/packs/cpp/rules/cpp-builds-everywhere.md +26 -0
  248. package/packs/cpp/rules/cpp-faults-only-in-the-test-build.md +21 -0
  249. package/packs/cpp/rules/cpp-find-with-the-library.md +19 -0
  250. package/packs/cpp/rules/cpp-gates-share-one-reader.md +22 -0
  251. package/packs/cpp/rules/cpp-headers-declare.md +22 -0
  252. package/packs/cpp/rules/cpp-numbers-and-casts.md +22 -0
  253. package/packs/cpp/rules/cpp-repeats-become-templates.md +33 -0
  254. package/packs/cpp/rules/cpp-static-analysis-runs.md +22 -0
  255. package/packs/cpp/rules/cpp-thread-contracts-are-code.md +23 -0
  256. package/packs/cpp/skills/cpp-extract-template/SKILL.md +38 -0
  257. package/packs/docker/checks/alpine-with-native-build.json +13 -0
  258. package/packs/docker/checks/compose-db-needs-auth.json +14 -0
  259. package/packs/docker/checks/compose-image-pinned.json +14 -0
  260. package/packs/docker/checks/compose-no-hardcoded-ip.json +12 -0
  261. package/packs/docker/checks/compose-no-host-bind-for-data.json +18 -0
  262. package/packs/docker/checks/compose-no-plaintext-secret.json +13 -0
  263. package/packs/docker/checks/compose-no-swarm-ignored-keys.json +13 -0
  264. package/packs/docker/checks/compose-overlay-not-bridge.json +13 -0
  265. package/packs/docker/checks/compose-service-needs-healthcheck.json +11 -0
  266. package/packs/docker/checks/compose-service-needs-init.json +11 -0
  267. package/packs/docker/checks/copy-needs-chown-with-user.json +17 -0
  268. package/packs/docker/checks/copy-source-before-deps.json +13 -0
  269. package/packs/docker/checks/docker-exec-form.json +16 -0
  270. package/packs/docker/checks/dockerfile-needs-healthcheck.json +17 -0
  271. package/packs/docker/checks/dockerfile-needs-user.json +21 -0
  272. package/packs/docker/checks/dockerignore-has-the-basics.json +21 -0
  273. package/packs/docker/checks/gitattributes-forces-lf.json +17 -0
  274. package/packs/docker/checks/health-checks-nothing.json +25 -0
  275. package/packs/docker/checks/no-crlf-in-scripts.json +15 -0
  276. package/packs/docker/checks/no-latest-base.json +13 -0
  277. package/packs/docker/checks/no-secret-in-image.json +13 -0
  278. package/packs/docker/checks/no-sensitive-file-copy.json +13 -0
  279. package/packs/docker/checks/node-env-before-install.json +13 -0
  280. package/packs/docker/checks/npm-ci-not-install.json +13 -0
  281. package/packs/docker/pack.json +46 -0
  282. package/packs/docker/rules/compose-pinned-and-closed.md +21 -0
  283. package/packs/docker/rules/compose-swarm-safe.md +26 -0
  284. package/packs/docker/rules/docker-exec-form.md +19 -0
  285. package/packs/docker/rules/dockerfile-multistage.md +13 -0
  286. package/packs/docker/rules/dockerfile-production.md +25 -0
  287. package/packs/docker/skills/docker-diagnose/SKILL.md +23 -0
  288. package/packs/dynamic-data/checks/draft-on-the-server.json +27 -0
  289. package/packs/dynamic-data/checks/guard-does-its-job.json +28 -0
  290. package/packs/dynamic-data/checks/key-is-not-a-display-name.json +28 -0
  291. package/packs/dynamic-data/checks/no-code-from-data.json +29 -0
  292. package/packs/dynamic-data/checks/no-collection-from-request.json +27 -0
  293. package/packs/dynamic-data/checks/no-pipeline-from-stored-text.json +27 -0
  294. package/packs/dynamic-data/checks/no-regexp-from-stored-config.json +27 -0
  295. package/packs/dynamic-data/checks/no-template-from-stored-text.json +27 -0
  296. package/packs/dynamic-data/checks/save-takes-named-paths.json +27 -0
  297. package/packs/dynamic-data/pack.json +23 -0
  298. package/packs/dynamic-data/rules/a-list-is-a-saved-query.md +23 -0
  299. package/packs/dynamic-data/rules/definitions-are-validated-data.md +24 -0
  300. package/packs/dynamic-data/rules/every-dynamic-surface-has-a-boundary.md +29 -0
  301. package/packs/dynamic-data/rules/fields-have-owners.md +22 -0
  302. package/packs/dynamic-data/rules/imports-drop-nothing.md +26 -0
  303. package/packs/dynamic-data/rules/one-definition-many-surfaces.md +24 -0
  304. package/packs/dynamic-data/rules/one-fact-one-place.md +28 -0
  305. package/packs/dynamic-data/rules/rules-live-in-the-engine.md +29 -0
  306. package/packs/dynamic-data/rules/saves-are-patches.md +28 -0
  307. package/packs/dynamic-data/rules/tenant-costs-one-document.md +22 -0
  308. package/packs/dynamic-data/skills/design-a-definition/SKILL.md +24 -0
  309. package/packs/fastify/checks/api-routes-versioned.json +28 -0
  310. package/packs/fastify/checks/cookie-host-prefix.json +24 -0
  311. package/packs/fastify/checks/hijack-needs-try.json +28 -0
  312. package/packs/fastify/checks/no-cast-at-route-boundary.json +24 -0
  313. package/packs/fastify/checks/no-db-in-route-file.json +28 -0
  314. package/packs/fastify/checks/no-err-message-to-client.json +24 -0
  315. package/packs/fastify/checks/no-regexp-from-input.json +24 -0
  316. package/packs/fastify/checks/no-trust-proxy-true.json +25 -0
  317. package/packs/fastify/checks/one-error-body.json +26 -0
  318. package/packs/fastify/checks/origin-from-config-not-host.json +31 -0
  319. package/packs/fastify/checks/password-needs-slow-hash.json +30 -0
  320. package/packs/fastify/checks/sec-headers-present.json +28 -0
  321. package/packs/fastify/checks/secrets-compared-constant-time.json +24 -0
  322. package/packs/fastify/checks/sse-needs-error-listener.json +28 -0
  323. package/packs/fastify/checks/user-bytes-need-disposition.json +29 -0
  324. package/packs/fastify/pack.json +41 -0
  325. package/packs/fastify/rules/credentials-and-input.md +23 -0
  326. package/packs/fastify/rules/security-one-switch.md +28 -0
  327. package/packs/fastify/rules/streams-and-hijacks.md +22 -0
  328. package/packs/fastify/rules/tests-use-inject.md +13 -0
  329. package/packs/fastify/rules/three-layers.md +20 -0
  330. package/packs/fastify/rules/trust-config-not-headers.md +24 -0
  331. package/packs/full-stack/checks/no-express-no-vite.json +23 -0
  332. package/packs/full-stack/hooks/stack-guard.mjs +90 -0
  333. package/packs/full-stack/pack.json +76 -0
  334. package/packs/full-stack/rules/stack-is-fastify-and-nextjs.md +20 -0
  335. package/packs/go/checks/go-exec-result-ignored.json +15 -0
  336. package/packs/go/checks/go-unmarshal-error-ignored.json +15 -0
  337. package/packs/go/pack.json +21 -0
  338. package/packs/go/rules/go-errors-are-handled.md +22 -0
  339. package/packs/gpu-painter/checks/dawn-backends-and-validation.json +9 -0
  340. package/packs/gpu-painter/checks/dawn-no-spontaneous.json +10 -0
  341. package/packs/gpu-painter/checks/dawn-present-on-render-thread.json +17 -0
  342. package/packs/gpu-painter/checks/gpu-no-frame-stalls.json +12 -0
  343. package/packs/gpu-painter/checks/no-opengl-link.json +11 -0
  344. package/packs/gpu-painter/checks/no-opengl.json +13 -0
  345. package/packs/gpu-painter/hooks/browser-guard.py +196 -0
  346. package/packs/gpu-painter/pack.json +91 -0
  347. package/packs/gpu-painter/rules/dawn-build-and-shaders.md +27 -0
  348. package/packs/gpu-painter/rules/dawn-device-and-render-thread.md +26 -0
  349. package/packs/gpu-painter/rules/gpu-antialiasing.md +20 -0
  350. package/packs/gpu-painter/rules/gpu-blend-order.md +22 -0
  351. package/packs/gpu-painter/rules/gpu-bloom.md +20 -0
  352. package/packs/gpu-painter/rules/gpu-frame-budget.md +25 -0
  353. package/packs/gpu-painter/rules/gpu-frame-pacing-and-power.md +27 -0
  354. package/packs/gpu-painter/rules/gpu-frame-work.md +30 -0
  355. package/packs/gpu-painter/rules/gpu-golden-images.md +21 -0
  356. package/packs/gpu-painter/rules/gpu-hdr-and-tonemap.md +23 -0
  357. package/packs/gpu-painter/rules/gpu-picking-on-cpu.md +19 -0
  358. package/packs/gpu-painter/rules/gpu-render-lifecycle.md +25 -0
  359. package/packs/gpu-painter/rules/gpu-text-atlas.md +24 -0
  360. package/packs/gpu-painter/rules/gpu-travellers-from-snapshot.md +24 -0
  361. package/packs/gpu-painter/rules/hover-every-pressable.md +25 -0
  362. package/packs/gpu-painter/skills/gpu-capture/SKILL.md +15 -0
  363. package/packs/gpu-painter/skills/gpu-frame-bench/SKILL.md +14 -0
  364. package/packs/gpu-painter/skills/gpu-golden-check/SKILL.md +13 -0
  365. package/packs/gpu-painter/skills/gpu-golden-update/SKILL.md +16 -0
  366. package/packs/gpu-painter/skills/gpu-lifecycle-stress/SKILL.md +15 -0
  367. package/packs/gpu-painter/skills/hover-state/SKILL.md +33 -0
  368. package/packs/hook-proof/checks/hook-catch-must-not-allow.json +16 -0
  369. package/packs/hook-proof/checks/hook-command-no-pipe.json +16 -0
  370. package/packs/hook-proof/checks/hook-exit-1-does-not-block.json +17 -0
  371. package/packs/hook-proof/checks/hook-no-or-true.json +18 -0
  372. package/packs/hook-proof/checks/hook-refusal-on-stderr.json +17 -0
  373. package/packs/hook-proof/pack.json +38 -0
  374. package/packs/hook-proof/rules/a-refusal-is-exit-2.md +28 -0
  375. package/packs/hook-proof/skills/prove-a-hook/SKILL.md +21 -0
  376. package/packs/host-agent/checks/file-path-from-param.json +27 -0
  377. package/packs/host-agent/checks/integrity-check-optional.json +27 -0
  378. package/packs/host-agent/checks/quoted-value-into-config.json +24 -0
  379. package/packs/host-agent/checks/secret-on-argv.json +28 -0
  380. package/packs/host-agent/checks/ssh-verifies-host-key.json +27 -0
  381. package/packs/host-agent/checks/system-file-written-in-place.json +26 -0
  382. package/packs/host-agent/checks/tmp-path-predictable.json +27 -0
  383. package/packs/host-agent/pack.json +22 -0
  384. package/packs/host-agent/rules/root-on-other-machines.md +27 -0
  385. package/packs/html-ui/checks/email-html-escapes.json +25 -0
  386. package/packs/html-ui/checks/external-link-rel.json +21 -0
  387. package/packs/html-ui/checks/no-duplicate-escape.json +26 -0
  388. package/packs/html-ui/checks/no-inline-client-script.json +21 -0
  389. package/packs/html-ui/checks/no-inline-style.json +23 -0
  390. package/packs/html-ui/pack.json +33 -0
  391. package/packs/html-ui/rules/email-html-escapes.md +19 -0
  392. package/packs/html-ui/rules/server-html-escapes-everything.md +22 -0
  393. package/packs/http-api/checks/api-path-versioned.json +31 -0
  394. package/packs/http-api/checks/authz-from-request-body.json +26 -0
  395. package/packs/http-api/checks/client-calls-a-version.json +28 -0
  396. package/packs/http-api/checks/client-ip-not-leftmost-xff.json +28 -0
  397. package/packs/http-api/checks/cors-needs-origin.json +26 -0
  398. package/packs/http-api/checks/csp-not-switched-off.json +28 -0
  399. package/packs/http-api/checks/debug-route-not-shipped.json +26 -0
  400. package/packs/http-api/checks/encrypted-name-plaintext-value.json +26 -0
  401. package/packs/http-api/checks/err-text-stays-server-side.json +27 -0
  402. package/packs/http-api/checks/failure-is-not-empty.json +28 -0
  403. package/packs/http-api/checks/gate-is-not-a-todo.json +27 -0
  404. package/packs/http-api/checks/guard-fails-open.json +28 -0
  405. package/packs/http-api/checks/hmac-over-reserialised-body.json +26 -0
  406. package/packs/http-api/checks/jwt-verify-pins-algorithm.json +26 -0
  407. package/packs/http-api/checks/middleware-skips-without-user.json +26 -0
  408. package/packs/http-api/checks/next-api-route-versioned.json +47 -0
  409. package/packs/http-api/checks/no-security-off-switch.json +28 -0
  410. package/packs/http-api/checks/oauth-state-signed.json +26 -0
  411. package/packs/http-api/checks/one-time-code-compared-raw.json +26 -0
  412. package/packs/http-api/checks/query-cast-is-not-validation.json +28 -0
  413. package/packs/http-api/checks/queue-action-from-client.json +26 -0
  414. package/packs/http-api/checks/rate-limit-one-module.json +28 -0
  415. package/packs/http-api/checks/role-checked-in-one-guard.json +27 -0
  416. package/packs/http-api/checks/route-body-needs-schema.json +31 -0
  417. package/packs/http-api/checks/route-scopes-to-the-caller.json +31 -0
  418. package/packs/http-api/checks/secret-compared-constant-time-any.json +28 -0
  419. package/packs/http-api/checks/secret-in-job-record.json +27 -0
  420. package/packs/http-api/checks/server-fetches-tenant-url.json +30 -0
  421. package/packs/http-api/checks/short-code-needs-limit.json +26 -0
  422. package/packs/http-api/checks/user-url-through-safe-fetch.json +28 -0
  423. package/packs/http-api/checks/webhook-dedupes-event-id.json +30 -0
  424. package/packs/http-api/pack.json +45 -0
  425. package/packs/http-api/rules/adapters-one-db-gateway.md +18 -0
  426. package/packs/http-api/rules/apis-are-versioned.md +27 -0
  427. package/packs/http-api/rules/credentials-handled-safely.md +22 -0
  428. package/packs/http-api/rules/handlers-own-the-work.md +17 -0
  429. package/packs/http-api/rules/health-and-correlation.md +17 -0
  430. package/packs/http-api/rules/one-error-contract.md +17 -0
  431. package/packs/http-api/rules/routes-are-thin.md +17 -0
  432. package/packs/http-api/rules/routes-scope-to-the-caller.md +26 -0
  433. package/packs/http-api/rules/routes-validate-and-answer.md +25 -0
  434. package/packs/http-api/skills/change-an-api/SKILL.md +20 -0
  435. package/packs/http-api/skills/secure-a-route/SKILL.md +21 -0
  436. package/packs/instrument-shell/checks/no-raw-struct-blob.json +23 -0
  437. package/packs/instrument-shell/pack.json +22 -0
  438. package/packs/instrument-shell/rules/fold-keeps-every-route.md +24 -0
  439. package/packs/instrument-shell/rules/quiet-announces-itself.md +22 -0
  440. package/packs/instrument-shell/rules/render-the-extremes.md +25 -0
  441. package/packs/instrument-shell/rules/seams-are-declared.md +27 -0
  442. package/packs/instrument-shell/rules/session-blob-append-only.md +25 -0
  443. package/packs/instrument-shell/skills/gates-from-commit-one/SKILL.md +20 -0
  444. package/packs/instrument-shell/skills/hit-the-painted-control/SKILL.md +18 -0
  445. package/packs/js-ts/checks/async-callback-unguarded.json +26 -0
  446. package/packs/js-ts/checks/background-loop-needs-stop.json +28 -0
  447. package/packs/js-ts/checks/child-process-error-handler.json +28 -0
  448. package/packs/js-ts/checks/entry-registers-shutdown.json +31 -0
  449. package/packs/js-ts/checks/fetch-needs-timeout.json +30 -0
  450. package/packs/js-ts/checks/job-only-in-memory.json +28 -0
  451. package/packs/js-ts/checks/json-only-through-helper.json +29 -0
  452. package/packs/js-ts/checks/line-under-200-chars.json +34 -0
  453. package/packs/js-ts/checks/localhost-default-in-server.json +29 -0
  454. package/packs/js-ts/checks/no-any.json +27 -0
  455. package/packs/js-ts/checks/no-cast-escape-hatches.json +24 -0
  456. package/packs/js-ts/checks/no-console-in-app.json +31 -0
  457. package/packs/js-ts/checks/no-dynamic-import-node-builtin.json +25 -0
  458. package/packs/js-ts/checks/no-inline-binary.json +20 -0
  459. package/packs/js-ts/checks/no-inline-zod-outside-schemas.json +27 -0
  460. package/packs/js-ts/checks/no-local-sleep.json +25 -0
  461. package/packs/js-ts/checks/no-nested-ternary.json +20 -0
  462. package/packs/js-ts/checks/no-secret-in-log.json +24 -0
  463. package/packs/js-ts/checks/no-shell-string-interpolation.json +24 -0
  464. package/packs/js-ts/checks/no-swallowed-errors.json +25 -0
  465. package/packs/js-ts/checks/no-ts-enum.json +20 -0
  466. package/packs/js-ts/checks/process-env-only-in-config.json +31 -0
  467. package/packs/js-ts/checks/race-leaves-work-running.json +23 -0
  468. package/packs/js-ts/checks/reject-as-catch-all-exists.json +24 -0
  469. package/packs/js-ts/checks/secret-has-no-fallback.json +24 -0
  470. package/packs/js-ts/checks/secret-needs-crypto-random.json +24 -0
  471. package/packs/js-ts/checks/server-close-awaited.json +27 -0
  472. package/packs/js-ts/checks/session-user-typed-once.json +24 -0
  473. package/packs/js-ts/checks/switch-is-a-table.json +24 -0
  474. package/packs/js-ts/checks/test-imports-the-source.json +19 -0
  475. package/packs/js-ts/checks/test-name-says-behaviour.json +16 -0
  476. package/packs/js-ts/checks/tsconfig-flags.json +21 -0
  477. package/packs/js-ts/checks/void-needs-catch.json +24 -0
  478. package/packs/js-ts/checks/zod-string-needs-max.json +25 -0
  479. package/packs/js-ts/checks/zod-v4-formats.json +23 -0
  480. package/packs/js-ts/pack.json +84 -0
  481. package/packs/js-ts/rules/await-handled-at-a-boundary.md +66 -0
  482. package/packs/js-ts/rules/env-through-config.md +36 -0
  483. package/packs/js-ts/rules/errors-never-swallowed.md +33 -0
  484. package/packs/js-ts/rules/files-under-300-lines.md +18 -0
  485. package/packs/js-ts/rules/guard-clauses-over-nesting.md +34 -0
  486. package/packs/js-ts/rules/js-repeats-become-templates.md +26 -0
  487. package/packs/js-ts/rules/json-only-through-one-helper.md +62 -0
  488. package/packs/js-ts/rules/named-constants-not-magic-numbers.md +34 -0
  489. package/packs/js-ts/rules/no-any.md +34 -0
  490. package/packs/js-ts/rules/no-console.md +30 -0
  491. package/packs/js-ts/rules/no-floating-promises.md +31 -0
  492. package/packs/js-ts/rules/no-param-mutation.md +28 -0
  493. package/packs/js-ts/rules/no-unsafe-assertions.md +30 -0
  494. package/packs/js-ts/rules/one-logger.md +24 -0
  495. package/packs/js-ts/rules/outbound-calls-have-a-limit.md +20 -0
  496. package/packs/js-ts/rules/parallel-independent-awaits.md +29 -0
  497. package/packs/js-ts/rules/process-lifecycle.md +47 -0
  498. package/packs/js-ts/rules/schema-single-source-of-truth.md +36 -0
  499. package/packs/js-ts/rules/secrets-stay-secret.md +22 -0
  500. package/packs/js-ts/rules/small-functions.md +20 -0
  501. package/packs/js-ts/rules/test-names-describe-behavior.md +28 -0
  502. package/packs/js-ts/rules/tests-can-fail.md +19 -0
  503. package/packs/js-ts/rules/tsconfig-strict.md +32 -0
  504. package/packs/js-ts/rules/typed-exports.md +27 -0
  505. package/packs/js-ts/rules/types-once-at-the-edge.md +18 -0
  506. package/packs/js-ts/rules/unions-over-enums.md +29 -0
  507. package/packs/js-ts/rules/zod-at-route-boundaries.md +40 -0
  508. package/packs/midi/checks/active-sensing-no-pulse.json +24 -0
  509. package/packs/midi/checks/clock-not-at-sample-zero.json +23 -0
  510. package/packs/midi/checks/midi-realtime-first.json +27 -0
  511. package/packs/midi/checks/no-tempo-writeback.json +23 -0
  512. package/packs/midi/checks/position-not-integrated.json +25 -0
  513. package/packs/midi/checks/stub-playhead-advances.json +27 -0
  514. package/packs/midi/checks/sysex-length-literal.json +23 -0
  515. package/packs/midi/checks/sysex-not-on-audio.json +24 -0
  516. package/packs/midi/checks/sysex-survives-realtime.json +27 -0
  517. package/packs/midi/pack.json +22 -0
  518. package/packs/midi/rules/clock-is-a-pulse-stream.md +30 -0
  519. package/packs/midi/rules/imports-count-every-loss.md +25 -0
  520. package/packs/midi/rules/measure-the-clock-in-audio.md +30 -0
  521. package/packs/midi/rules/sync-is-a-mode.md +29 -0
  522. package/packs/midi/rules/sysex-is-a-record.md +29 -0
  523. package/packs/midi/skills/clock-probe/SKILL.md +23 -0
  524. package/packs/midi/skills/clock-probe/clock-law.md +417 -0
  525. package/packs/midi/skills/does-it-sync/SKILL.md +19 -0
  526. package/packs/mongo/checks/bulk-over-many.json +28 -0
  527. package/packs/mongo/checks/created-at-immutable.json +25 -0
  528. package/packs/mongo/checks/driver-outside-gateway.json +24 -0
  529. package/packs/mongo/checks/key-lookup-is-hashed.json +24 -0
  530. package/packs/mongo/checks/mongoclient-cached-and-named.json +34 -0
  531. package/packs/mongo/checks/mongoclient-outside-gateway.json +24 -0
  532. package/packs/mongo/checks/no-count-plus-one-ids.json +25 -0
  533. package/packs/mongo/checks/no-db-write-in-loop.json +25 -0
  534. package/packs/mongo/checks/no-drop-in-code.json +27 -0
  535. package/packs/mongo/checks/no-empty-deletemany.json +26 -0
  536. package/packs/mongo/checks/no-find-reads.json +26 -0
  537. package/packs/mongo/checks/no-input-spread-into-write.json +24 -0
  538. package/packs/mongo/checks/no-mongoose.json +23 -0
  539. package/packs/mongo/checks/no-negation-delete.json +26 -0
  540. package/packs/mongo/checks/no-non-null-after-findone.json +25 -0
  541. package/packs/mongo/checks/objectid-equals.json +26 -0
  542. package/packs/mongo/checks/update-then-reread.json +24 -0
  543. package/packs/mongo/checks/watch-not-poll.json +25 -0
  544. package/packs/mongo/pack.json +52 -0
  545. package/packs/mongo/rules/deletes-name-what-dies.md +21 -0
  546. package/packs/mongo/rules/driver-only-in-gateway.md +26 -0
  547. package/packs/mongo/rules/keys-hashed-input-picked.md +21 -0
  548. package/packs/mongo/rules/one-client-one-pool.md +32 -0
  549. package/packs/mongo/rules/reads-aggregate-writes-bulk.md +25 -0
  550. package/packs/mongo/rules/writes-are-atomic.md +27 -0
  551. package/packs/multi-tenant/checks/role-sees-all-tenants.json +26 -0
  552. package/packs/multi-tenant/checks/tenant-filter-from-url.json +25 -0
  553. package/packs/multi-tenant/pack.json +22 -0
  554. package/packs/multi-tenant/rules/no-role-crosses-a-tenant.md +21 -0
  555. package/packs/multi-tenant/skills/prove-tenant-isolation/SKILL.md +19 -0
  556. package/packs/nginx/checks/modsec-no-blanket-off.json +16 -0
  557. package/packs/nginx/checks/nginx-csp-no-unsafe.json +15 -0
  558. package/packs/nginx/checks/nginx-headers-always.json +15 -0
  559. package/packs/nginx/checks/nginx-keepalive-http11.json +20 -0
  560. package/packs/nginx/checks/nginx-logs-to-stdout.json +15 -0
  561. package/packs/nginx/checks/nginx-no-crlf.json +17 -0
  562. package/packs/nginx/checks/nginx-resolver-ttl.json +19 -0
  563. package/packs/nginx/pack.json +43 -0
  564. package/packs/nginx/rules/modsecurity-tuning.md +22 -0
  565. package/packs/nginx/rules/nginx-production.md +26 -0
  566. package/packs/nginx/skills/waf-rollout/SKILL.md +20 -0
  567. package/packs/python/checks/py-no-bare-except.json +18 -0
  568. package/packs/python/checks/py-no-eval.json +18 -0
  569. package/packs/python/checks/py-no-mutable-default.json +18 -0
  570. package/packs/python/checks/py-no-shell-true.json +18 -0
  571. package/packs/python/checks/py-no-star-import.json +18 -0
  572. package/packs/python/checks/py-no-swallowed-exception.json +18 -0
  573. package/packs/python/checks/py-none-by-is.json +18 -0
  574. package/packs/python/checks/py-open-with-with.json +18 -0
  575. package/packs/python/checks/py-requests-timeout.json +18 -0
  576. package/packs/python/checks/py-subprocess-output-checked.json +18 -0
  577. package/packs/python/checks/py-yaml-safe-load.json +18 -0
  578. package/packs/python/pack.json +26 -0
  579. package/packs/python/rules/python-errors-and-resources.md +26 -0
  580. package/packs/python/rules/python-repeats-become-templates.md +27 -0
  581. package/packs/python/skills/python-extract-template/SKILL.md +35 -0
  582. package/packs/react/checks/dialog-needs-role.json +28 -0
  583. package/packs/react/checks/effect-not-for-derived-state.json +24 -0
  584. package/packs/react/checks/icon-button-needs-name.json +24 -0
  585. package/packs/react/checks/label-needs-a-field.json +24 -0
  586. package/packs/react/checks/ui-failed-fetch-says-so.json +23 -0
  587. package/packs/react/checks/ui-ok-branch-has-an-else.json +23 -0
  588. package/packs/react/pack.json +20 -0
  589. package/packs/react/rules/react-accessible-controls.md +20 -0
  590. package/packs/react/rules/react-state-and-effects.md +23 -0
  591. package/packs/reverse-engineering/checks/ear-constant-tagged.json +23 -0
  592. package/packs/reverse-engineering/checks/no-default-on-distrust.json +24 -0
  593. package/packs/reverse-engineering/checks/no-rom-table-literal.json +29 -0
  594. package/packs/reverse-engineering/checks/prose-never-decides.json +22 -0
  595. package/packs/reverse-engineering/hooks/firmware-out-of-git.mjs +49 -0
  596. package/packs/reverse-engineering/pack.json +35 -0
  597. package/packs/reverse-engineering/rules/a-negative-names-what-was-scanned.md +19 -0
  598. package/packs/reverse-engineering/rules/account-every-term.md +20 -0
  599. package/packs/reverse-engineering/rules/addresses-name-their-space.md +21 -0
  600. package/packs/reverse-engineering/rules/every-law-has-a-source.md +18 -0
  601. package/packs/reverse-engineering/rules/findings-are-withdrawn-in-place.md +17 -0
  602. package/packs/reverse-engineering/rules/firmware-stays-out.md +18 -0
  603. package/packs/reverse-engineering/rules/names-before-code.md +19 -0
  604. package/packs/reverse-engineering/rules/reproduction-or-original.md +18 -0
  605. package/packs/reverse-engineering/rules/two-sources-before-naming.md +21 -0
  606. package/packs/reverse-engineering/skills/bank-census/SKILL.md +18 -0
  607. package/packs/reverse-engineering/skills/gather-sources/SKILL.md +21 -0
  608. package/packs/reverse-engineering/skills/menu-map/SKILL.md +28 -0
  609. package/packs/reverse-engineering/skills/names-first/SKILL.md +41 -0
  610. package/packs/reverse-engineering/skills/re-deliverables/SKILL.md +21 -0
  611. package/packs/reverse-engineering/skills/tripwire-the-law/SKILL.md +19 -0
  612. package/packs/reverse-engineering/tools/lib/unwrap.mjs +115 -0
  613. package/packs/reverse-engineering/tools/names-sweep.mjs +264 -0
  614. package/packs/shell/checks/sh-mktemp.json +18 -0
  615. package/packs/shell/checks/sh-no-backticks.json +18 -0
  616. package/packs/shell/checks/sh-no-eval.json +18 -0
  617. package/packs/shell/checks/sh-no-parse-ls.json +18 -0
  618. package/packs/shell/checks/sh-no-pipe-to-shell.json +18 -0
  619. package/packs/shell/checks/sh-no-program-in-heredoc.json +18 -0
  620. package/packs/shell/checks/sh-quote-arguments.json +18 -0
  621. package/packs/shell/checks/sh-rm-guarded.json +18 -0
  622. package/packs/shell/checks/sh-strict-mode.json +20 -0
  623. package/packs/shell/pack.json +28 -0
  624. package/packs/shell/rules/shell-repeats-become-templates.md +23 -0
  625. package/packs/shell/rules/shell-strict-and-quoted.md +27 -0
  626. package/packs/shell/skills/shell-extract-template/SKILL.md +32 -0
  627. package/packs/shell-hooks/checks/gnu-only-in-shell.json +18 -0
  628. package/packs/shell-hooks/checks/hook-command-anchored.json +12 -0
  629. package/packs/shell-hooks/checks/hook-json-by-tool.json +18 -0
  630. package/packs/shell-hooks/checks/no-bash-c-with-variable.json +20 -0
  631. package/packs/shell-hooks/pack.json +36 -0
  632. package/packs/shell-hooks/rules/hooks-portable-anchored-quoted.md +26 -0
  633. package/packs/sound-design/checks/audio-seed-fixed.json +23 -0
  634. package/packs/sound-design/checks/mix-is-a-crossfade.json +30 -0
  635. package/packs/sound-design/checks/no-hash-in-the-signal.json +30 -0
  636. package/packs/sound-design/checks/no-literal-key-anchor.json +30 -0
  637. package/packs/sound-design/checks/test-compares-a-function-with-itself.json +22 -0
  638. package/packs/sound-design/pack.json +22 -0
  639. package/packs/sound-design/rules/algorithms-are-data.md +26 -0
  640. package/packs/sound-design/rules/meter-before-engine.md +27 -0
  641. package/packs/sound-design/rules/neutral-is-exact.md +26 -0
  642. package/packs/sound-design/rules/test-off-the-easy-point.md +28 -0
  643. package/packs/sound-design/rules/unreachable-is-said.md +25 -0
  644. package/packs/sound-design/rules/waveforms-and-octaves.md +24 -0
  645. package/packs/sound-design/skills/choose-observable/SKILL.md +18 -0
  646. package/packs/sound-design/skills/measure-a-law/SKILL.md +18 -0
  647. package/packs/sound-design/skills/measure-reverb/SKILL.md +19 -0
  648. package/packs/sound-design/skills/spread-probe/SKILL.md +18 -0
  649. package/packs/stellix/checks/no-keyboard-focus.json +12 -0
  650. package/packs/stellix/checks/one-seeded-random.json +16 -0
  651. package/packs/stellix/checks/world-never-includes-painter.json +12 -0
  652. package/packs/stellix/checks/world-no-libm.json +15 -0
  653. package/packs/stellix/checks/world-no-unordered.json +10 -0
  654. package/packs/stellix/hooks/no-shipped-images.mjs +88 -0
  655. package/packs/stellix/pack.json +61 -0
  656. package/packs/stellix/rules/stellix-deterministic-world.md +29 -0
  657. package/packs/stellix/rules/stellix-reset-generated.md +24 -0
  658. package/packs/stellix/rules/stellix-world-snapshot.md +27 -0
  659. package/packs/stellix/rules/world-continuous-collision.md +26 -0
  660. package/packs/stellix/rules/world-fp-determinism.md +28 -0
  661. package/packs/stored-text/checks/no-raw-html-from-data.json +31 -0
  662. package/packs/stored-text/checks/stored-text-libs-only-in-renderer.json +31 -0
  663. package/packs/stored-text/checks/stored-text-renderer-complete.json +24 -0
  664. package/packs/stored-text/checks/stored-text-through-renderer.json +25 -0
  665. package/packs/stored-text/pack.json +41 -0
  666. package/packs/stored-text/rules/stored-text-renders-once.md +26 -0
  667. package/packs/stored-text/skills/render-stored-text/SKILL.md +24 -0
  668. package/packs/synth-creator/checks/timing-from-synthcore.json +24 -0
  669. package/packs/synth-creator/checks/ui-drawn-in-code.json +23 -0
  670. package/packs/synth-creator/hooks/build-guard.mjs +232 -0
  671. package/packs/synth-creator/hooks/build-sweep.mjs +166 -0
  672. package/packs/synth-creator/hooks/frozen-files.mjs +63 -0
  673. package/packs/synth-creator/hooks/idle-wake.mjs +90 -0
  674. package/packs/synth-creator/hooks/protect-vendor.mjs +174 -0
  675. package/packs/synth-creator/hooks/spec-lock.mjs +117 -0
  676. package/packs/synth-creator/hooks/stage-guard.mjs +50 -0
  677. package/packs/synth-creator/hooks/time-guard.mjs +292 -0
  678. package/packs/synth-creator/hooks/user-asks.mjs +165 -0
  679. package/packs/synth-creator/pack.json +136 -0
  680. package/packs/synth-creator/rules/copy-trees-read-only.md +25 -0
  681. package/packs/synth-creator/rules/debug-by-measurement.md +20 -0
  682. package/packs/synth-creator/rules/done-means-fresh-evidence.md +18 -0
  683. package/packs/synth-creator/rules/hooks-and-gates.md +21 -0
  684. package/packs/synth-creator/rules/long-work-in-the-background.md +16 -0
  685. package/packs/synth-creator/rules/timing-from-synthcore.md +16 -0
  686. package/packs/synth-creator/skills/build-step/SKILL.md +125 -0
  687. package/packs/synth-creator/skills/build-through-the-queue/SKILL.md +19 -0
  688. package/packs/synth-creator/tools/freeze.mjs +36 -0
  689. package/packs/tui/checks/tui-entry-restores-terminal.json +27 -0
  690. package/packs/tui/checks/tui-gates-on-tty.json +25 -0
  691. package/packs/tui/checks/tui-no-ris-reset.json +22 -0
  692. package/packs/tui/checks/tui-resize-listener-removed.json +26 -0
  693. package/packs/tui/checks/tui-width-is-state.json +33 -0
  694. package/packs/tui/pack.json +44 -0
  695. package/packs/tui/rules/tui-resize-and-screen.md +25 -0
  696. package/packs/tui/skills/build-tui/SKILL.md +21 -0
  697. package/packs/ui-craft/checks/ui-input-needs-autocomplete.json +23 -0
  698. package/packs/ui-craft/checks/ui-intl-for-dates.json +21 -0
  699. package/packs/ui-craft/checks/ui-no-ai-palette.json +22 -0
  700. package/packs/ui-craft/checks/ui-no-animate-layout.json +22 -0
  701. package/packs/ui-craft/checks/ui-no-assistant-palette.json +23 -0
  702. package/packs/ui-craft/checks/ui-no-bounce-easing.json +22 -0
  703. package/packs/ui-craft/checks/ui-no-custom-cursor.json +22 -0
  704. package/packs/ui-craft/checks/ui-no-emoji-as-ui.json +22 -0
  705. package/packs/ui-craft/checks/ui-no-empty-image.json +21 -0
  706. package/packs/ui-craft/checks/ui-no-eyebrow.json +21 -0
  707. package/packs/ui-craft/checks/ui-no-furniture-text.json +22 -0
  708. package/packs/ui-craft/checks/ui-no-gradient-text.json +22 -0
  709. package/packs/ui-craft/checks/ui-no-index-numbering.json +21 -0
  710. package/packs/ui-craft/checks/ui-no-lorem.json +22 -0
  711. package/packs/ui-craft/checks/ui-no-marketing-buzzword.json +22 -0
  712. package/packs/ui-craft/checks/ui-no-paste-block.json +21 -0
  713. package/packs/ui-craft/checks/ui-no-placeholder-names.json +21 -0
  714. package/packs/ui-craft/checks/ui-no-scroll-hijack.json +21 -0
  715. package/packs/ui-craft/checks/ui-no-side-tab.json +21 -0
  716. package/packs/ui-craft/checks/ui-no-stock-labels.json +22 -0
  717. package/packs/ui-craft/checks/ui-no-transition-all.json +22 -0
  718. package/packs/ui-craft/checks/ui-no-uppercase-table-header.json +21 -0
  719. package/packs/ui-craft/checks/ui-no-zebra-rows.json +22 -0
  720. package/packs/ui-craft/checks/ui-no-zoom-lock.json +21 -0
  721. package/packs/ui-craft/pack.json +43 -0
  722. package/packs/ui-craft/rules/apps-are-not-pages.md +26 -0
  723. package/packs/ui-craft/rules/data-tells-the-truth.md +26 -0
  724. package/packs/ui-craft/rules/dates-and-numbers.md +18 -0
  725. package/packs/ui-craft/rules/forms-never-fight.md +22 -0
  726. package/packs/ui-craft/rules/interface-copy.md +26 -0
  727. package/packs/ui-craft/rules/motion-is-rare.md +31 -0
  728. package/packs/ui-craft/rules/no-generated-look.md +37 -0
  729. package/packs/ui-craft/rules/page-holds-its-frame.md +28 -0
  730. package/packs/ui-craft/rules/page-proved-rendered.md +19 -0
  731. package/packs/ui-craft/rules/pictures-do-a-job.md +25 -0
  732. package/packs/ui-craft/rules/pointer-feedback.md +28 -0
  733. package/packs/ui-craft/rules/screen-answers-one-question.md +24 -0
  734. package/packs/ui-craft/rules/survives-real-data.md +23 -0
  735. package/packs/ui-craft/rules/touch-and-small-screens.md +19 -0
  736. package/packs/ui-craft/rules/type-space-colour.md +26 -0
  737. package/packs/ui-craft/rules/url-holds-the-state.md +19 -0
  738. package/packs/ui-craft/skills/app-screen/SKILL.md +33 -0
  739. package/packs/ui-craft/skills/build-from-reference/SKILL.md +28 -0
  740. package/packs/ui-craft/skills/chart-choice/SKILL.md +34 -0
  741. package/packs/ui-craft/skills/hover-state/SKILL.md +28 -0
  742. package/packs/ui-craft/skills/page-critique/SKILL.md +33 -0
  743. package/packs/ui-craft/skills/prove-page/SKILL.md +23 -0
  744. package/packs/ui-craft/skills/redesign-page/SKILL.md +19 -0
  745. package/packs/ui-craft/skills/ui-code-review/SKILL.md +22 -0
  746. package/packs/ui-craft/skills/write-the-page/SKILL.md +21 -0
  747. package/packs/ui-craft/tools/page-measure.mjs +41 -0
  748. package/packs/web/checks/a11y-img-needs-alt.json +26 -0
  749. package/packs/web/checks/a11y-no-bare-outline-none.json +21 -0
  750. package/packs/web/checks/a11y-no-clickable-div.json +26 -0
  751. package/packs/web/checks/a11y-no-positive-tabindex.json +26 -0
  752. package/packs/web/checks/client-no-api-key.json +29 -0
  753. package/packs/web/checks/client-no-browser-global-at-module-scope.json +28 -0
  754. package/packs/web/checks/client-no-server-import.json +31 -0
  755. package/packs/web/checks/client-no-window-location-nav.json +28 -0
  756. package/packs/web/checks/css-no-inline-style.json +30 -0
  757. package/packs/web/checks/ds-pages-compose-primitives.json +28 -0
  758. package/packs/web/checks/key-from-index.json +23 -0
  759. package/packs/web/checks/prodbuild-no-cdn-runtime-deps.json +21 -0
  760. package/packs/web/checks/prodbuild-no-dev-flags.json +21 -0
  761. package/packs/web/checks/prodbuild-no-remote-fonts.json +22 -0
  762. package/packs/web/checks/rcss-button-cursor.json +30 -0
  763. package/packs/web/checks/rcss-no-100vw.json +21 -0
  764. package/packs/web/checks/rcss-no-fixed-wide-width.json +21 -0
  765. package/packs/web/checks/rcss-viewport-meta.json +28 -0
  766. package/packs/web/checks/secret-not-in-web-storage.json +25 -0
  767. package/packs/web/checks/tw-no-raw-hex-in-markup.json +34 -0
  768. package/packs/web/checks/wp-hero-not-lazy.json +27 -0
  769. package/packs/web/checks/wp-img-needs-dimensions.json +26 -0
  770. package/packs/web/pack.json +73 -0
  771. package/packs/web/rules/accessibility.md +26 -0
  772. package/packs/web/rules/client-boundaries.md +23 -0
  773. package/packs/web/rules/production-build.md +22 -0
  774. package/packs/web/rules/secrets-not-in-the-browser.md +18 -0
  775. package/packs/web/rules/styles-live-in-stylesheets.md +23 -0
  776. package/packs/web/rules/tailwind-v4.md +23 -0
  777. package/packs/web/rules/ui-primitives-one-module.md +30 -0
  778. package/packs/web/rules/web-performance.md +21 -0
  779. package/packs/web/skills/design-direction/SKILL.md +30 -0
  780. package/packs/web/skills/design-review/SKILL.md +28 -0
  781. package/packs/web/skills/pick-rendering-mode/SKILL.md +21 -0
  782. package/packs/web/skills/preflight-build/SKILL.md +23 -0
  783. package/packs/web/skills/seo-audit/SKILL.md +22 -0
  784. package/packs/websocket/checks/no-token-in-query.json +26 -0
  785. package/packs/websocket/checks/stale-socket-deletes-new-entry.json +25 -0
  786. package/packs/websocket/checks/ws-identity-from-message.json +26 -0
  787. package/packs/websocket/pack.json +21 -0
  788. package/packs/websocket/rules/identity-comes-from-the-connection.md +24 -0
  789. package/packs/writing/checks/ascii-no-em-dash.json +17 -0
  790. package/packs/writing/checks/no-copula-dodging.json +18 -0
  791. package/packs/writing/checks/no-dramatic-colon.json +18 -0
  792. package/packs/writing/checks/no-not-x-but-y.json +18 -0
  793. package/packs/writing/checks/no-participial-opener.json +18 -0
  794. package/packs/writing/checks/no-pseudo-wisdom.json +18 -0
  795. package/packs/writing/checks/no-slop-words.json +18 -0
  796. package/packs/writing/checks/no-stock-connectors.json +18 -0
  797. package/packs/writing/checks/no-time-or-date.json +27 -0
  798. package/packs/writing/checks/no-trailing-ing.json +18 -0
  799. package/packs/writing/checks/no-vague-attribution.json +18 -0
  800. package/packs/writing/pack.json +43 -0
  801. package/packs/writing/rules/ascii-no-em-dash.md +21 -0
  802. package/packs/writing/rules/cut-the-padding.md +20 -0
  803. package/packs/writing/rules/direct-voice.md +22 -0
  804. package/packs/writing/rules/no-cargo-cult.md +16 -0
  805. package/packs/writing/rules/no-scaffolding.md +19 -0
  806. package/packs/writing/rules/no-stock-language.md +27 -0
  807. package/packs/writing/rules/no-time-or-date.md +18 -0
  808. package/packs/writing/rules/rhythm-like-talk.md +20 -0
  809. package/packs/writing/rules/write-from-your-own-corner.md +20 -0
  810. package/packs/writing/skills/argument-post/SKILL.md +28 -0
  811. package/packs/writing/skills/humanize/SKILL.md +28 -0
  812. package/packs/writing/skills/launch-post/SKILL.md +38 -0
  813. package/packs/writing/skills/pick-subreddit/SKILL.md +69 -0
  814. package/packs/writing/skills/post-voice/SKILL.md +22 -0
  815. package/packs/writing/skills/reddit-post/SKILL.md +63 -0
  816. package/packs/writing/skills/reddit-title/SKILL.md +23 -0
  817. package/packs/writing/skills/reply-moves/SKILL.md +40 -0
  818. package/packs/writing/skills/reply-stance/SKILL.md +23 -0
  819. package/packs/writing/skills/should-i-reply/SKILL.md +21 -0
  820. package/packs/zod/hooks/schemas-only.mjs +53 -0
  821. package/packs/zod/pack.json +44 -0
  822. package/packs/zod/rules/env-shapes-only.md +14 -0
  823. package/packs/zod/rules/zod-4-schemas.md +14 -0
  824. package/profiles/stellix.layout.json +315 -0
  825. package/profiles/sub37.layout.json +247 -0
  826. package/prompts/scan-review.md +40 -0
  827. package/prompts/survey.md +82 -0
@@ -0,0 +1,25 @@
1
+ ---
2
+ paths:
3
+ - "**/*.cpp"
4
+ - "**/*.cc"
5
+ - "**/*.h"
6
+ - "**/*.hpp"
7
+ - "**/*.mm"
8
+ - "**/*.py"
9
+ - "**/*.ts"
10
+ - "**/*.js"
11
+ - "**/*.mjs"
12
+ ---
13
+
14
+ # An import counts every loss, and the wire is not the storage
15
+
16
+ <constraints>
17
+ Always do:
18
+ - Count and print each lossy step of an import. Refuse overflow, and say why a result is empty.
19
+ - Check every UI range holds every corpus value.
20
+ - Treat a controller's edit semantics as separate from the stored byte.
21
+ - Test a published spec against firmware and the corpus.
22
+
23
+ Never do:
24
+ - Clamp a value in silence: 383 of 433 clamped once, and nothing said so.
25
+ </constraints>
@@ -0,0 +1,30 @@
1
+ ---
2
+ paths:
3
+ - "**/*.cpp"
4
+ - "**/*.cc"
5
+ - "**/*.h"
6
+ - "**/*.hpp"
7
+ - "**/*.mm"
8
+ - "**/*.py"
9
+ - "**/*.ts"
10
+ - "**/*.js"
11
+ - "**/*.mjs"
12
+ ---
13
+
14
+ # A clock is proved in the audio, by changing the tempo
15
+
16
+ <constraints>
17
+ Always do:
18
+ - Measure the audio, not the arithmetic. Push an impulse through the real processor.
19
+ - Change the tempo to catch a dead clock. Every division test passes on a clock that never arrives.
20
+ - Test the raw-pulse path alone: no playhead, just `0xF8`.
21
+ - Test internal against a host with two tempo pairs, one the mirror of the other.
22
+ - Assert absolute beat alignment. A spacing test cannot see a phase error.
23
+ - Give a stub playhead an advancing position.
24
+ - Derive position from the host. An integrated position is wrong for ever after a jump.
25
+ - Use 90 and 140 BPM as well as 120: 120 lands on whole samples and passes with wrong arithmetic.
26
+
27
+ Never do:
28
+ - Write the resolved tempo into the unit's own BPM field. It makes external sync look perfect and quietly turns internal into the host's tempo.
29
+ - Place every clock byte at sample zero of a block.
30
+ </constraints>
@@ -0,0 +1,29 @@
1
+ ---
2
+ paths:
3
+ - "**/*.cpp"
4
+ - "**/*.cc"
5
+ - "**/*.h"
6
+ - "**/*.hpp"
7
+ - "**/*.mm"
8
+ - "**/*.py"
9
+ - "**/*.ts"
10
+ - "**/*.js"
11
+ - "**/*.mjs"
12
+ ---
13
+
14
+ # Sync is a mode, and OFF is a sound
15
+
16
+ <constraints>
17
+ Always do:
18
+ - Give a synth three states: OFF, INT, EXT. Most effects get two, since a delay always has a time.
19
+ - Say which clock you mean. A setter that resolves OFF to INT cannot fail, so the caller never hears.
20
+ - Follow the host's transport when there is one: a unit in a session follows the session.
21
+ - Keep the sync switch a system setting, and the divisions in the program.
22
+ - Leave each destination's division off by default: it overrides a stored value.
23
+ - Declare each destination's minimum and maximum, by value and not by byte order, and show what cannot be reached.
24
+ - Key stored divisions to a destination's name when its list is dynamic.
25
+
26
+ Never do:
27
+ - Collapse "where our clock comes from" and "whether this unit is slaved to it".
28
+ - Put divisions on the transport bar: a master clock has no say in what a slave does with its pulses.
29
+ </constraints>
@@ -0,0 +1,29 @@
1
+ ---
2
+ paths:
3
+ - "**/*.cpp"
4
+ - "**/*.cc"
5
+ - "**/*.h"
6
+ - "**/*.hpp"
7
+ - "**/*.mm"
8
+ - "**/*.py"
9
+ - "**/*.ts"
10
+ - "**/*.js"
11
+ - "**/*.mjs"
12
+ ---
13
+
14
+ # A program is records: keep them together, and round-trip every byte
15
+
16
+ <constraints>
17
+ Always do:
18
+ - Expect a program to be several messages, in any order. Key each by bank and program, and merge.
19
+ - Take a record's length from its type, never from a constant.
20
+ - Keep unknown bytes verbatim, and prove a byte-exact round trip over every patch.
21
+ - Test 7-bit packing with known plaintext: the usual scheme can give the right length with every byte wrong.
22
+ - Prove per machine whether the sysex layout is the RAM layout.
23
+ - Decode off the audio thread.
24
+ - Watch for bytes that change what their neighbours mean: flag bytes, shared enums, bit fields.
25
+
26
+ Never do:
27
+ - Parse only the first message of a program: every effects knob sat at its default for weeks.
28
+ - Assume `F0` to `F7` runs uninterrupted.
29
+ </constraints>
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: clock-probe
3
+ description: Use when adding sync to a unit, when a delay or LFO should follow tempo, or when a clock test passes and the unit may still be deaf.
4
+ ---
5
+
6
+ # Prove the clock (one job: the unit follows tempo, measured in its audio)
7
+
8
+ <constraints>
9
+ Read `clock-law.md` beside this file for the full law.
10
+
11
+ Always do:
12
+ 1. Choose the observable: a pure gain first, then pulse width, a stereo null, pitch, a filter, a comb.
13
+ 2. Measure at 120, 90 and 140 BPM, in the audio.
14
+ 3. Drive raw `0xF8` pulses with no playhead. Tempo reads back, and Stop releases the lock.
15
+ 4. Set the unit's field to 120 against a host at 90, then the mirror at 150. It must keep its own tempo when internal.
16
+ 5. Assert the beat alignment, not only the spacing.
17
+ 6. Check two renders are bit-identical apart from the thing under test.
18
+ 7. Plant the fault, see it red, and revert at once.
19
+
20
+ Never do:
21
+ - Call a division test proof of a clock.
22
+ - Widen a tolerance to hide an offset. Assert it does not move, and log the open item.
23
+ </constraints>
@@ -0,0 +1,417 @@
1
+ # MIDI clock and sync: the law
2
+
3
+ Everything we know about clock, gathered in one place because it decides how
4
+ every unit behaves and because getting it wrong is silent. Nine effects units
5
+ shipped deaf to the transport with every test green.
6
+
7
+ Provenance tags are the usual ones: `[MIDI]` the published spec, `[FW]`
8
+ firmware with an address, `[SCH]` a schematic sheet, `[MAN]` a manual page,
9
+ `[PUB]` a published source, `[EAR]` fitted by ear, `[COR]` the corpus.
10
+
11
+ ---
12
+
13
+ ## 1. What MIDI actually sends
14
+
15
+ **There is no tempo message.** None. No byte anywhere says "120 BPM". The
16
+ master fires a Timing Clock byte, `0xF8`, **24 times per quarter note**, and
17
+ the tempo IS the rate they arrive at. Faster pulses, faster tempo. A slave
18
+ measures the gap between them and works it out. `[MIDI]`
19
+
20
+ That is the whole mechanism: literally just a clock.
21
+
22
+ Four transport messages travel with the pulses:
23
+
24
+ | Byte | Message | Meaning |
25
+ |------|---------|---------|
26
+ | `0xF8` | Timing Clock | one pulse; 24 make a quarter note |
27
+ | `0xFA` | Start | go to the beginning and run |
28
+ | `0xFB` | Continue | resume from where we were |
29
+ | `0xFC` | Stop | halt |
30
+ | `0xF2` | Song Position Pointer | where "where we were" is: a 14-bit count of MIDI beats, and a MIDI beat is a **sixteenth note = 6 clocks** |
31
+
32
+ `0xFE` is Active Sensing. It also arrives constantly and has nothing to do
33
+ with tempo. A parser that treats the whole real-time range alike will read it
34
+ as a pulse and report a nonsense tempo.
35
+
36
+ ## 2. Clock has NO CHANNEL
37
+
38
+ The most misunderstood thing about it, and it changes how you write a parser
39
+ and how you read a manual.
40
+
41
+ `0xF8` is a System Real-Time status byte. Its low nibble is part of the
42
+ message's identity, not a channel number. There is no channel field to read,
43
+ so a device's channel setting cannot filter clock, and there is **one clock
44
+ stream per PORT**. `[MIDI]`
45
+
46
+ Consequences:
47
+
48
+ - **Never channel-filter real-time bytes.** A receive path that switches on the
49
+ channel nibble and drops what does not match will eat every clock byte.
50
+ Real-time bytes come out before any channel test.
51
+ - **They may appear anywhere**, including in the middle of another message and
52
+ inside a SysEx dump. That is deliberate and it is what keeps timing accurate.
53
+ A parser assuming `F0` to `F7` runs uninterrupted will corrupt a dump the
54
+ moment a clock byte lands in it. JUCE handles this; a hand-written parser in
55
+ a ROM often does not, which is worth remembering when reading firmware.
56
+ - **A "sync channel" setting is almost never a channel.** Look again: it is
57
+ usually the PORT on a machine with more than one MIDI In, or the MMC device
58
+ ID (different thing, own numbering), or it governs Song Select and Song
59
+ Position rather than clock.
60
+ - **Duplicate clock is a real failure mode.** A unit reachable by two paths
61
+ receives two streams and runs at an exact integer multiple of the right
62
+ tempo. When you see 2x, suspect the clock before the division table.
63
+
64
+ ## 3. Divisions: count in 192nds, not in clocks
65
+
66
+ 24 PPQN was chosen because it divides by 2, 3, 4, 6, 8 and 12, so every common
67
+ division lands on a whole number of pulses. But **write the table in ticks at
68
+ 192 per quarter**, which is 8 MIDI clocks, and here is why: the Virus's own
69
+ division table is in 1/192 units and includes 1/64, which is one and a half
70
+ MIDI clocks. `[PUB]` A machine with an internal divider follows a sub-clock
71
+ division perfectly well; a slave counting raw pulses cannot. The table has to
72
+ be finer than the wire.
73
+
74
+ | division | ticks (192/qn) | MIDI clocks |
75
+ |---|---|---|
76
+ | 32 bar | 24576 | 3072 |
77
+ | 16 bar | 12288 | 1536 |
78
+ | 8 bar | 6144 | 768 |
79
+ | 4 bar | 3072 | 384 |
80
+ | 2 bar | 1536 | 192 |
81
+ | 1/1. | 1152 | 144 |
82
+ | 1/1 (one 4/4 bar) | 768 | 96 |
83
+ | 1/2. | 576 | 72 |
84
+ | 1/1T | 512 | 64 |
85
+ | 1/2 | 384 | 48 |
86
+ | 1/4. | 288 | 36 |
87
+ | 1/2T | 256 | 32 |
88
+ | 1/4 | 192 | 24 |
89
+ | 1/8. | 144 | 18 |
90
+ | 1/4T | 128 | 16 |
91
+ | 1/8 | 96 | 12 |
92
+ | 1/16. | 72 | 9 |
93
+ | 1/8T | 64 | 8 |
94
+ | 1/16 | 48 | 6 |
95
+ | 1/32 | 24 | 3 |
96
+ | 1/16T | 32 | 4 |
97
+ | 1/32T | 16 | 2 |
98
+ | 1/64 | 12 | **1.5** |
99
+
100
+ Ten divisions is not enough for any real machine. A survey of eighteen found
101
+ every one of them needed more, and mostly LONGER: bars and measures, not finer
102
+ subdivisions. The JP-8000 counts in MEASURES up to 8; the Nord Lead 3 goes to
103
+ 32 bars. Make the list append-only, since a unit stores the index, and sort it
104
+ separately for a menu.
105
+
106
+ Machines name these differently and a user follows their manual, not ours. The
107
+ Virus writes a dotted eighth as 3/16 and a triplet as 1/6; the H3000 counts in
108
+ n/24; Lexicon uses N:M ratios over a settable beat value; the Nord Lead 2's
109
+ display shows a bare 1 to 7. Carry the machine's own vocabulary per
110
+ destination.
111
+
112
+ ## 4. Pre-MIDI sync, and the factor of two
113
+
114
+ A machine with no MIDI socket can still be slaved. The pre-MIDI boxes that
115
+ needed to run in time already had a standard.
116
+
117
+ | machine or standard | rate | provenance |
118
+ |---|---|---|
119
+ | MIDI clock | 24 PPQN, fixed | `[MIDI]` |
120
+ | Roland DIN sync (Sync24) | 24 PPQN | `[SCH]` TB-303, TEMPO 8 ms +/- 1 at 300 BPM against 200/24 = 8.333 |
121
+ | Korg analogue sync | **48 PPQN** | `[PUB]` |
122
+ | Linn LM-1 / LinnDrum | 48 PPQN | `[PUB]` |
123
+ | Oberheim DX / DMX | 48 PPQN | `[PUB]` (same Z80 sample-playback lineage as the Linn) |
124
+ | SCI DrumTraks | **switchable 24 / 48 / 96**, and no DIN sync jack at all | `[PUB]` |
125
+ | Yamaha RX11 | **switchable 24 / 48 / 96**, out through the TAPE OUT jack, explicitly to match "Roland or Korg" format | `[MAN]` RX11 owner's manual p28 |
126
+ | Korg Polysix, Mono/Poly | **no PPQN at all** - ARPEGGIO TRIG IN is one trigger, one step; a footswitch is a listed source | `[MAN]` rear panel and arpeggiator chapter |
127
+ | Roland TR-909 | 24 out on the wire, **48 internally** | `[SVC]` tape sync: the output changes state "at every half-period of T which is 1/24 of the time required for most of Roland products to process a quarter note" |
128
+
129
+ **The difference is a factor of two and it bites.** Plug a TB-303 into a Korg
130
+ DDM-110 and the 303 runs at double speed. `[PUB]`
131
+
132
+ **But check the SOCKET before you apply a rate, because sometimes there is no
133
+ rate at all.** I asserted here that our Polysix and Mono/Poly would need Korg's
134
+ 48 because they are Korg machines with arpeggiator clock inputs. That was
135
+ wrong, and the machines' own manuals overruled it: **neither has a DIN sync jack
136
+ at all.** What they have is ARPEGGIO TRIG IN, and it is not a PPQN clock -
137
+ **one trigger advances the arpeggiator by ONE STEP**. The Mono/Poly manual
138
+ settles it by listing the sources: *"footswitches (momentary, normally
139
+ open-type such as Korg PS-1, S-1, etc.), sequencers, rhythmers"* `[MAN]`, and no
140
+ footswitch sends 48 pulses to a quarter note. Korg's 48 belongs to the DIN
141
+ sockets on its sequencers and rhythm boxes; these two synths have none.
142
+
143
+ So there are two different things behind a sync jack and they need different
144
+ models: a **pulse count** (a rate, where N pulses make a quarter) and a **step
145
+ trigger** (one edge, one step). Read the jack's own documentation before
146
+ assuming which. The test differs too: a PPQN model is proved by counting pulses
147
+ per quarter, a step model by halving the division and requiring exactly twice
148
+ the notes.
149
+
150
+ **But do not treat the rate as a property of the brand.** The RX11 and the
151
+ DrumTraks both SWITCH between 24, 48 and 96, and the RX11's manual names Roland
152
+ and Korg as the formats it is matching, which tells you the incompatibility was
153
+ well enough known that Yamaha shipped a fix for it. So the rate is a property of
154
+ the MACHINE, sometimes user-selectable, and the manual settles it. Look it up
155
+ per unit; the brand is a hint, not an answer.
156
+
157
+ Note also that a machine can support a rate and still have no way to receive it:
158
+ the DrumTraks handles all three PPQN rates over MIDI and has no DIN sync jack,
159
+ so it cannot be slaved by a Roland at all. Check the JACK as well as the rate.
160
+
161
+ 96 PPQN is 4x MIDI clock and 192nds divide it exactly, so the shared division
162
+ table covers 24, 48 and 96 without special cases.
163
+
164
+ **And a machine can carry two rates at once.** The TR-909's internal counter is
165
+ **48** ticks per quarter while every clock it exchanges with the outside is
166
+ **24**, one event every second tick. Confusing those two is the same factor of
167
+ two seen from the inside, and it is the easier mistake because both numbers are
168
+ correct and documented.
169
+
170
+ Same signature as duplicate clock: an exact integer multiple of the right tempo
171
+ means suspect the RATE, not the divisions. But see the meter traps in section 9
172
+ first - filter resonance puts two level peaks in every LFO cycle, so a period
173
+ reads exactly half and looks precisely like a wrong rate while being nothing of
174
+ the kind.
175
+
176
+ So the prior: **if a machine has anything that runs in time, assume it syncs,
177
+ and hold a "no" to a high standard.** "The firmware discards every real-time
178
+ byte" answers the MIDI question and says nothing about a Sync24 jack, a tape
179
+ sync input or a trigger input.
180
+
181
+ ## 5. Sync is a MODE, and OFF is a sound
182
+
183
+ Not a parameter, and not a checkbox. On the hardware, sync is the box's clock
184
+ SOURCE, and while it is slaved everything with a time base follows, each at its
185
+ own division.
186
+
187
+ | state | what it means |
188
+ |---|---|
189
+ | **OFF** | nothing follows anything. Every time and rate is the stored value, and modulators drift against each other the way analogue hardware does. A legitimate sound somebody chose, not a degraded version of being synced |
190
+ | **INT** | everything follows one clock generated in the machine, so an LFO on 1/4 and a delay on 1/8 hold a fixed relationship forever. This mutual coherence is the musical point, and it holds with no cable anywhere near the unit |
191
+ | **EXT** | everything follows a master outside. With none sending, nothing moves |
192
+
193
+ **Synths get three states; most effects get two.** An effect's timing is always
194
+ something, since a delay has a delay time whether or not it follows a clock, so
195
+ its panel offers only the source. Let the machine declare which shape it has.
196
+
197
+ **Asking for OFF on a machine that has none is silently granted as INTERNAL,
198
+ and it has cost more than any other single line in this area.** `setSyncMode
199
+ (syncOff)` cannot fail - the shell resolves it, because an effect must be on
200
+ some clock - so the caller gets a machine that is still synced and never hears
201
+ about it. Once, three of four effects units had red clock probes from
202
+ exactly this, and all three ENGINES were correct:
203
+
204
+ | unit | asked for | actually measured | what it looked like |
205
+ |---|---|---|---|
206
+ | pcm80 | `setSyncMode(syncOff)` for an "unsynced" reverb-core baseline | 504 ms - the 4 ms core plus a quarter at the internal 120 | every later reading 500 ms low; nine false MISMATCHes and two false "INTERNAL FOLLOWED THE HOST" |
207
+ | h3000 | `setSyncMode(syncOff)` before checking a stored 180 ms delay | 250 ms - a 1/8 at the internal 120 | a value fault in the raw-to-ms law, which is where the note sent the next reader |
208
+ | h3500 | `setSyncEnabled(true)` before measuring against a transport | a quarter at the internal 120, at every transport tempo | a delay frozen at 500 ms |
209
+
210
+ So: **say which clock you mean.** `setSyncMode (syncExternal)` when a transport
211
+ is what you are measuring, and `setAllSyncDivisionsOff()` when nothing should be
212
+ following. Never `setSyncMode (syncOff)` on an effect, and never
213
+ `setSyncEnabled`, which resolves to EXTERNAL or INTERNAL depending on whether a
214
+ transport happens to be playing at that instant - h3500's section 3 passed and
215
+ section 2 failed on nothing but the order they ran in.
216
+
217
+ Per-destination OFF is not a workaround for the missing state, it IS the
218
+ hardware's off: Lexicon carries an Absolute-or-Tempo bit per PARAMETER `[MAN]`.
219
+ One call that turns every division off works on both shapes, so a probe need
220
+ not ask what shape the machine is first.
221
+
222
+ Two levels, and collapsing them is a real bug that made a standalone go silent:
223
+
224
+ 1. **Where OUR clock comes from** (our BPM field, a DAW playhead, `0xF8` on a
225
+ cable). One pulse stream that never stops. The master does not need
226
+ permission to run.
227
+ 2. **Whether the UNIT is slaved to it.** This is where "external disables
228
+ internal" applies, and what it disables is the unit's OWN timing: its preset
229
+ delay time, its rate knobs, which the synced values override while it is on.
230
+
231
+ ## 6. Every unit follows an external clock
232
+
233
+ The law, and the one most easily got wrong by asking the wrong question.
234
+
235
+ "Did this 1988 machine have a MIDI clock facility" is the MIMICRY question. It
236
+ decides what gets tagged `[EAR]`. It is NOT the question of what our plugin
237
+ should do. Every unit runs as a VST inside a host, and **a host transport is
238
+ always the master when there is one**. A unit dropped into a session follows
239
+ the session with no user action, or its delays are not in time with the track.
240
+
241
+ So a machine with no OFF position resolves to EXTERNAL while a transport runs
242
+ and to its own clock otherwise. The Virus ships exactly that as a real setting
243
+ (Disable / Auto / Send) `[MAN]`, so it is hardware precedent rather than an
244
+ invention.
245
+
246
+ **What stays off by default is each DESTINATION's division.** A division
247
+ OVERRIDES the stored value, and a Lexicon preset's 247 ms delay must not
248
+ silently become 500 ms because the project is at 120 BPM. Slaved and ready,
249
+ overriding nothing until asked.
250
+
251
+ ## 7. What belongs where
252
+
253
+ The hardware splits this and so do we.
254
+
255
+ - The **switch** is a system setting. It belongs to the installation, not the
256
+ sound, and survives a program change.
257
+ - The **divisions** are musical content and live in the program. The Virus
258
+ keeps LFO Clock in the patch; Lexicon keeps the rhythmic value in the preset.
259
+ `[MAN]`
260
+
261
+ And the divisions belong on the UNIT's panel, never on the transport bar. A
262
+ master clock sends pulses; it has no business choosing what a slave does with
263
+ them, any more than a DAW's transport picks your delay's note value. The PCM 91
264
+ is the clearest case: it chooses which parameters follow tempo PER PARAMETER,
265
+ each with its own Flags bit. `[FW]`
266
+
267
+ **A destination must declare its range.** The Reverb 4000's pre-delay tops out
268
+ at 300 ms, so a quarter at 120 BPM (500 ms) silently clamps: the panel reads
269
+ 1/4 while the box sits at its ceiling. Show what cannot be reached, greyed,
270
+ rather than pretending.
271
+
272
+ **And `lo` and `hi` are a MINIMUM and a MAXIMUM, not a bottom byte and a top
273
+ byte.** On a machine whose law counts downward those are opposite things: the
274
+ JX-8P family's LFO byte indexes the shared time table with its COMPLEMENT, so a
275
+ bigger byte is FASTER, and writing the two ends in byte order declared lo
276
+ 24.375 Hz against hi 0.011. Take `std::min` and `std::max` of the two extremes and
277
+ the direction of the law stops mattering. A byte value that means STOPPED is not
278
+ the bottom of a rate range either - the OB-8's increment table entry 0 is zero and
279
+ the Pulse's speed 0 is the sample-and-hold trigger, so both ranges start at 1.
280
+
281
+ **Where a machine's destination list is dynamic, key stored divisions to the
282
+ destination's NAME, not its index.** The H3000 declares its destinations from
283
+ the current algorithm's own parameter objects, so index 0 means a different
284
+ delay after an algorithm change and would silently inherit the previous
285
+ setting. Same class of bug as renumbering an enum.
286
+
287
+ ## 8. Naming: the MASTER trap
288
+
289
+ Every manufacturer named the same idea differently, and a user follows their
290
+ machine's manual.
291
+
292
+ | vocabulary | seen on |
293
+ |---|---|
294
+ | INT / EXT | Nord Lead 3 Master Clock menu, and the most common pair |
295
+ | MASTER / SLAVE | various |
296
+ | Internal / MIDI Clock | Lexicon PCM 91 Tempo Source |
297
+ | MIDI CLK | small displays |
298
+ | SOURCE | the parameter's name rather than its values |
299
+ | Disable / Auto / Send | Virus, which folds clock OUT into the same parameter |
300
+ | HOST | plugins, for a DAW transport |
301
+
302
+ **"MASTER" appears on BOTH sides of this.** Some panels label the source they
303
+ follow as the master ("sync to master"); others label the machine's own role.
304
+ Read which one a manual means before copying the word, or a unit ends up
305
+ printing MASTER while it is the slave.
306
+
307
+ **Our transport bar is ALWAYS the master.** It may itself be following a DAW or
308
+ a cable, but the unit is never our master.
309
+
310
+ ## 9. How to verify, and every trap we hit
311
+
312
+ **Measure the AUDIO, not the arithmetic.** Push an impulse through the real
313
+ processor and measure the gap between echoes; for a rate destination, measure
314
+ the modulation period. A test of the division maths passes while the clock
315
+ never reaches the engine, which is exactly how nine units shipped.
316
+
317
+ **The check that catches a dead clock is a TEMPO change, never a division
318
+ change.** The TC 2290 had 1/4, 1/8, 1/16, 1/8. and 1/8T all measuring exactly
319
+ right, and read 500 ms at 120 BPM and still 500 ms at 90. Every division test
320
+ passed the whole time.
321
+
322
+ | tempo | 1/4 | 1/8 | 1/16 |
323
+ |---|---|---|---|
324
+ | 120 BPM | 500.00 ms | 250.00 ms | 125.00 ms |
325
+ | 90 BPM | 666.67 ms | 333.33 ms | 166.67 ms |
326
+ | 140 BPM | 428.57 ms | 214.29 ms | 107.14 ms |
327
+
328
+ **Test the raw-pulse path separately.** No playhead, just `0xF8` at 24 per
329
+ quarter. Tempo reads back, and Stop releases the lock.
330
+
331
+ **Never write the resolved tempo back into the unit's own BPM field.** The
332
+ subtlest failure here, found in three units at once. A processor doing
333
+ `bpm.store(tempo)` each block writes the resolved tempo, which while a DAW
334
+ plays is the DAW's, into the field that IS the machine's internal clock. SYNC
335
+ INTERNAL then quietly becomes the host's tempo. It looks perfect under every
336
+ external measurement, because the write-back is what makes external work. Test
337
+ it as: field at 120 against a host playing 90 must still measure 500 ms.
338
+
339
+ **Use two tempo pairs on that check, never one.** With only 120-against-90, a
340
+ unit whose internal tempo happens to BE 90 passes while reading the host. Add
341
+ the mirror at 150.
342
+
343
+ **A spacing measurement cannot see a phase error.** Measure a synced
344
+ modulator's rate by the gap between peaks and a constant offset cancels out of
345
+ the arithmetic entirely, so every test passes while the modulator sits a full
346
+ block early on every beat. The D-50's LFOs were exactly that. Spacing tests
347
+ rate; only an absolute beat-alignment assertion tests phase.
348
+
349
+ **Give a stub playhead an ADVANCING ppq.** A frozen position pins the clock.
350
+ Invisible to a delay, which wants a length; obvious to anything wanting a
351
+ position. It presents as "the modulation is broken and the delay is fine".
352
+
353
+ **Three meter faults that all present as engine faults**, from measuring four
354
+ rhythm boxes in one night:
355
+ - An RMS window shorter than the oscillator's period reads the WAVEFORM rather
356
+ than the envelope.
357
+ - A single-threshold null detector chatters and reports a third of the period.
358
+ - **Filter resonance puts two level peaks in every LFO cycle**, so the period
359
+ reads exactly half. That is an exact integer multiple, which is the classic
360
+ wrong-clock-rate signature, and it was nothing of the kind. Rule out the meter
361
+ before believing a factor of two.
362
+
363
+ **Peak-picking an envelope reads about 2% fast at every tempo.** It looks
364
+ exactly like an engine bug and it is the meter. Use RMS over whole periods. A
365
+ meter wrong by a consistent percentage survives every cross-check that compares
366
+ measurements to each other; only an absolute expected value exposes it.
367
+
368
+ **Verify a check can FAIL, and clean up immediately.** Inject the bug the check
369
+ exists to catch, run it, revert from a saved copy, and never leave the process
370
+ between those two steps. A session that dies in the middle leaves an injected
371
+ bug that looks identical to a real failure. That happened, and cost a
372
+ diagnosis.
373
+
374
+ **Gate it in ctest.** A shared conformance check fails a build when a unit
375
+ declares no destinations, reports a value while sync is off, uses a division off
376
+ the grid, lies about a range, or does not follow a tempo change. It cannot see
377
+ the write-back, because it never calls `processBlock`, so that check belongs in
378
+ each unit's own audio probe.
379
+
380
+ **Test the gate itself.** A shared check that is not itself checked is a shared
381
+ bug. Ours silently inverted into passing nothing and failing eleven healthy
382
+ units. Run it against a known-good host AND a known-bad one.
383
+
384
+ ## 9a. Choosing the observable
385
+
386
+ Measuring the audio is the rule; WHICH audio decides what the measurement can
387
+ prove. Fourteen machines were put on the clock, and this was the whole of the
388
+ difficulty. The ladder, best first:
389
+
390
+ | rung | route | why | measured |
391
+ |---|---|---|---|
392
+ | 1 | a pure GAIN - AMD, a matrix to VCA or VOLUME, a VCA CV | two renders differ by a scalar, so `sum(a*b)/sum(b*b)` is EXACT and frame alignment is irrelevant | TX81Z within 0.01 ms on every division |
393
+ | 2 | PULSE WIDTH | a memory-free null: width does not touch phase and there is no filter state to converge | OB-8 read 719 ms through pitch, 666.78 through PWM |
394
+ | 3 | a stereo difference with a hard zero | the MN3009 reads `base +/- dep*tri`, so L-R is exactly zero at the sweep's zero | JX-8P beat alignment -0.474 ms |
395
+ | 4 | PITCH, via the accumulated-phase null | two renders differ by the INTEGRAL of the frequency deviation; a sine's returns to zero once a cycle, ON the beat | Mirage every division within 10 ms - but see the caveat |
396
+ | 5 | a FILTER | memory smears the null AND the energy is a soft asymmetric function of cutoff, so the sweep's lowest point is not its vertex | JX-8P read the modulation 70 ms early while the rate was exact |
397
+ | 6 | a COMB's energy | measures the rate; CANNOT measure the phase, because the energy depends on where a notch lands among the harmonics | PSR-730, -352 ms of offset that belongs to the voice |
398
+
399
+ **The pitch caveat, which cost three attempts.** The pitch law is exponential, so
400
+ the frequency deviation `2^v - 1` has a POSITIVE mean, second order in the depth,
401
+ and it ACCUMULATES in the phase error. At a quarter of the mod wheel the Mirage
402
+ read a 1/4 at 140 BPM as 521 ms instead of 428; at three hundredths, 429.07. Keep
403
+ the depth tiny and the baseline short, and on a SAMPLER take the MEDIAN of
404
+ consecutive gaps rather than a long baseline - a recorded wave's slope is not
405
+ constant, so one null in eight lands a fraction of a cycle out.
406
+
407
+ **Two renders must be BIT-IDENTICAL apart from the thing under test.** On five of
408
+ fourteen machines they were not: `prepareToPlay` left oscillator phases, LFO
409
+ phases, delay counters and noise seeds wherever the last run stopped. Free-running
410
+ against the KEYBOARD is the analogue behaviour and stays; carrying a phase across
411
+ a `prepareToPlay` is not that. On the Jupiter-8 it read as 92 ms of LFO drift.
412
+
413
+ **When the observable cannot see the phase, say so.** The TS-22 and the PSR-730
414
+ both have a constant offset their probes cannot attribute. Neither got a wide
415
+ tolerance to hide it: both assert that the offset does not MOVE across half a
416
+ minute - which is what a modulator come loose from the clock would break - and
417
+ both log the open item.
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: does-it-sync
3
+ description: Use when deciding whether a machine or unit can be slaved, or how it should sync.
4
+ ---
5
+
6
+ # Find out how a machine syncs (one job: what it slaves, over which socket, at what rate)
7
+
8
+ <constraints>
9
+ Always do:
10
+ 1. Assume anything that runs in time syncs. Hold a "no" to a high standard.
11
+ 2. Find the real-time compare early in the firmware's input handler.
12
+ 3. Read every socket: MIDI, DIN sync, tape, trigger in. "The firmware discards real-time bytes" says nothing about a sync jack.
13
+ 4. Read the rate from the machine's own manual. It may be switchable, or two rates at once.
14
+ 5. Decide if the jack is a pulse count or a step trigger.
15
+ 6. Write down each destination, with its range.
16
+
17
+ Never do:
18
+ - Take the rate from the brand.
19
+ </constraints>
@@ -0,0 +1,28 @@
1
+ {
2
+ "id": "bulk-over-many",
3
+ "why": "Multi-document writes go through one bulkWrite built from an ops array. insertMany/updateMany are the smell this exists to catch; a deliberate one-off says why in a comment on the same line.",
4
+ "rule": ".claude/rules/reads-aggregate-writes-bulk.md",
5
+ "concepts": [
6
+ "db-gateway",
7
+ "db-scripts"
8
+ ],
9
+ "exclude": [
10
+ "**/node_modules/**",
11
+ "**/dist/**",
12
+ "**/build/**",
13
+ "**/.next/**",
14
+ ".claude/**",
15
+ "**/.claude/**",
16
+ "**/*.test.*",
17
+ "**/*.spec.*",
18
+ "**/test/**",
19
+ "**/tests/**",
20
+ "**/gateway.*",
21
+ "**/gateway/**"
22
+ ],
23
+ "code": false,
24
+ "pattern": "^(?!.*//).*\\.(insertMany|updateMany)\\s*\\(",
25
+ "flags": "m",
26
+ "bad": "await col.insertMany(docs);",
27
+ "good": "await col.bulkWrite(docs.map((d) => ({ insertOne: { document: d } })));\nawait col.updateMany(f, u); // mongo: one-off backfill, idempotent"
28
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "id": "created-at-immutable",
3
+ "why": "Rewriting created_at to re-sort a queue destroys the audit trail. Add queued_at and sort on that.",
4
+ "rule": ".claude/rules/writes-are-atomic.md",
5
+ "concepts": [
6
+ "db-gateway",
7
+ "db-scripts"
8
+ ],
9
+ "exclude": [
10
+ "**/node_modules/**",
11
+ "**/dist/**",
12
+ "**/build/**",
13
+ "**/.next/**",
14
+ ".claude/**",
15
+ "**/.claude/**",
16
+ "**/*.test.*",
17
+ "**/*.spec.*",
18
+ "**/test/**",
19
+ "**/tests/**"
20
+ ],
21
+ "code": true,
22
+ "pattern": "\\$set\\s*:\\s*\\{[^}]*\\bcreated_at\\s*:",
23
+ "bad": "{ $set: { status: 'open', created_at: now } }",
24
+ "good": "{ $set: { status: 'open', queued_at: now } }"
25
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "id": "driver-outside-gateway",
3
+ "why": "MongoClient, db.collection() and getDb() belong to the gateway. A raw collection here bypasses session scoping, id rehydration and the one place that knows the collections; use the gateway's exported functions or its typed scope.",
4
+ "rule": ".claude/rules/driver-only-in-gateway.md",
5
+ "concepts": [
6
+ "db-callers"
7
+ ],
8
+ "exclude": [
9
+ "**/node_modules/**",
10
+ "**/dist/**",
11
+ "**/build/**",
12
+ "**/.next/**",
13
+ ".claude/**",
14
+ "**/.claude/**",
15
+ "**/*.test.*",
16
+ "**/*.spec.*",
17
+ "**/test/**",
18
+ "**/tests/**"
19
+ ],
20
+ "code": true,
21
+ "pattern": "\\.collection\\s*(?:<[^>]*>)?\\s*\\(|\\bgetDb\\s*\\(\\s*\\)\\s*\\.|\\bclient\\.db\\s*\\(|\\b\\w+(?:Col|Coll|Collection)\\s*\\(\\s*\\)\\s*\\.\\s*(?:find|insert|update|delete|aggregate|bulkWrite)",
22
+ "bad": "const rows = await getDb().collection('sessions').find({}).toArray();\nconst r = await sessionsCollection().findOne({ id });\n",
23
+ "good": "const rows = await listSessions(ownerId);\nawait scope.experiments.insertOne(doc);"
24
+ }