@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,139 @@
1
+ // Rust's own reading (KWB-75). C's blanker takes a lifetime for a char literal and blanks the rest of its line, and a generic blanker takes '"' for a
2
+ // string opening. Nested block comments and raw strings have no form in either. Offsets are kept, so a match's line is the file's line.
3
+ // blankRust(src) comments go; a string or char literal keeps two quotes, so it stays one token
4
+ // withoutTests(code) on blanked code: what `#[cfg(test)]` or a `#[test]` attribute marks goes too, since Rust's unit tests live in the file they test
5
+ // ownDefinitions(code) on blanked code: tests, impls and traits go, leaving the free functions
6
+ // lookupMatches(text) every `match` that is a table of literals on one enum, for dispatch-once
7
+ const spaces = (s) => s.replace(/[^\n]/g, ' ');
8
+ const quoted = (s) => (s.length >= 2 ? `"${spaces(s.slice(1, -1))}"` : spaces(s));
9
+
10
+ function commentEnd(src, start) {
11
+ let depth = 1;
12
+ let i = start + 2;
13
+ while (i < src.length && depth > 0) {
14
+ if (src.startsWith('/*', i)) { depth += 1; i += 2; }
15
+ else if (src.startsWith('*/', i)) { depth -= 1; i += 2; }
16
+ else i += 1;
17
+ }
18
+ return i;
19
+ }
20
+
21
+ function stringEnd(src, start) {
22
+ let i = start + 1;
23
+ while (i < src.length && src[i] !== '"') i += src[i] === '\\' ? 2 : 1;
24
+ return Math.min(i + 1, src.length);
25
+ }
26
+
27
+ // r"..", r#".."#, br#".."#, cr#".."#: nothing inside escapes, and the hashes close it. Returns where the opening quote is, and the end, or null.
28
+ function rawString(src, i) {
29
+ if (/\w/.test(src[i - 1] ?? '')) return null;
30
+ const open = src.slice(i, i + 80).match(/^(?:b|c)?r(#*)"/);
31
+ if (!open) return null;
32
+ const close = src.indexOf(`"${open[1]}`, i + open[0].length);
33
+ return { quote: i + open[0].length - 1, end: close === -1 ? src.length : close + 1 + open[1].length };
34
+ }
35
+
36
+ // A quote opens a char literal only when one character, or one escape, then closes it; otherwise it is a lifetime or a label.
37
+ function charEnd(src, i) {
38
+ if (src[i + 1] === '\\') { const e = src.indexOf("'", i + 3); return e === -1 ? null : e + 1; }
39
+ const one = String.fromCodePoint(src.codePointAt(i + 1) ?? 32);
40
+ return src[i + 1 + one.length] === "'" ? i + 2 + one.length : null;
41
+ }
42
+
43
+ export function blankRust(src) {
44
+ let out = '';
45
+ let i = 0;
46
+ const take = (end, shown) => { out += shown(src.slice(i, end)); i = end; };
47
+ while (i < src.length) {
48
+ const raw = src[i] === 'r' || src[i] === 'b' || src[i] === 'c' ? rawString(src, i) : null;
49
+ const char = src[i] === "'" ? charEnd(src, i) : null;
50
+ if (src.startsWith('//', i)) { const e = src.indexOf('\n', i); take(e === -1 ? src.length : e, spaces); }
51
+ else if (src.startsWith('/*', i)) take(commentEnd(src, i), spaces);
52
+ else if (raw) { out += spaces(src.slice(i, raw.quote)); i = raw.quote; take(raw.end, quoted); }
53
+ else if (src[i] === '"') take(stringEnd(src, i), quoted);
54
+ else if (char) take(char, quoted);
55
+ else { out += src[i]; i += 1; }
56
+ }
57
+ return out;
58
+ }
59
+
60
+ const TEST_MARK = /#\[\s*(?:cfg\s*\(\s*(?:all\s*\(\s*)?test\b[^\]]*\)|(?:\w+::)*test\b[^\]]*)\s*\]/g;
61
+
62
+ // The end of the item an attribute marks: its closing brace, or the `;` of an item with no body.
63
+ function itemEnd(code, start) {
64
+ let round = 0;
65
+ for (let i = start; i < code.length; i += 1) {
66
+ const c = code[i];
67
+ if (c === '(' || c === '[') round += 1;
68
+ else if (c === ')' || c === ']') round -= 1;
69
+ else if (c === ';' && round === 0) return i + 1;
70
+ else if (c === '{' && round === 0) {
71
+ let depth = 0;
72
+ for (let j = i; j < code.length; j += 1) {
73
+ if (code[j] === '{') depth += 1;
74
+ else if (code[j] === '}' && --depth === 0) return j + 1;
75
+ }
76
+ return code.length;
77
+ }
78
+ }
79
+ return code.length;
80
+ }
81
+
82
+ function blankItems(code, mark) {
83
+ let out = '';
84
+ let at = 0;
85
+ for (const m of code.matchAll(mark)) {
86
+ if (m.index < at) continue;
87
+ const end = itemEnd(code, m.index + m[0].length);
88
+ out += code.slice(at, m.index) + spaces(code.slice(m.index, end));
89
+ at = end;
90
+ }
91
+ return out + code.slice(at);
92
+ }
93
+
94
+ export const withoutTests = (code) => blankItems(code, TEST_MARK);
95
+
96
+ // A method lives in its type's namespace: `from_str` on a second type is the trait doing its job, and `is_none` on two types is two methods (KWB-81).
97
+ // Only a free function can be made again by name. A method copied is caught by its statements, whatever it is called.
98
+ const TYPE_ITEM = /^[ \t]*(?:pub(?:\([^)]*\))?\s+)?(?:unsafe\s+)?(?:impl|trait)\b[^{;]*(?=\{)/gm;
99
+ export const ownDefinitions = (code) => blankItems(withoutTests(code), TYPE_ITEM);
100
+
101
+ // What a `match` body holds, arm by arm: the patterns, and what the arm gives.
102
+ function armsOf(body) {
103
+ const arms = [];
104
+ let depth = 0;
105
+ let from = 0;
106
+ let head = null;
107
+ for (let i = 0; i < body.length; i += 1) {
108
+ const c = body[i];
109
+ if ('({['.includes(c)) depth += 1;
110
+ else if (')}]'.includes(c)) depth -= 1;
111
+ else if (depth === 0 && head === null && body.startsWith('=>', i)) { head = body.slice(from, i); from = i + 2; i += 1; }
112
+ else if (depth === 0 && head !== null && c === ',') { arms.push({ head, value: body.slice(from, i).trim() }); head = null; from = i + 1; }
113
+ }
114
+ if (head !== null) arms.push({ head, value: body.slice(from).trim() });
115
+ return arms;
116
+ }
117
+
118
+ const LITERAL = /^(?:"\s*"|-?\d[\w.]*)$/; // a table of true and false is a predicate, not data about the kind
119
+ const MIN_VARIANTS = 3;
120
+ const NOT_A_KIND = new Set(['Self', 'Option', 'Result', 'Ordering']); // the standard library's own enums, and an enum inside its own impl
121
+
122
+ // Every `match` that is only a lookup table: each variant of one enum to a plain value. `owned`: this file declares the enum or has its impl.
123
+ // A match that does real work on an enum is good Rust, in any number of files: the compiler holds every one to every variant. A lookup table is
124
+ // data about the kind, and belongs with the kind. Measured on eight crates: a rule on every match would have refused 7 to 12 in 100 of them.
125
+ export function lookupMatches(text) {
126
+ const code = withoutTests(blankRust(text));
127
+ const owns = new Set([...code.matchAll(/\b(?:enum|impl(?:<[^>{]*>)?)\s+([A-Z]\w*)/g)].map((m) => m[1]));
128
+ const found = [];
129
+ for (const m of code.matchAll(/\bmatch\s[^{;]+?(?=\{)/g)) {
130
+ const open = m.index + m[0].length;
131
+ const arms = armsOf(code.slice(open + 1, itemEnd(code, open) - 1));
132
+ if (!arms.length || !arms.every((a) => LITERAL.test(a.value))) continue;
133
+ const paths = arms.flatMap((a) => [...a.head.matchAll(/\b([A-Z]\w*)::([A-Z]\w*)/g)]);
134
+ const kind = paths[0]?.[1];
135
+ const labels = new Set(paths.filter((p) => p[1] === kind).map((p) => p[2]));
136
+ if (kind && labels.size >= MIN_VARIANTS && !NOT_A_KIND.has(kind)) found.push({ kind, labels, owned: owns.has(kind) });
137
+ }
138
+ return found;
139
+ }
@@ -0,0 +1,18 @@
1
+ // What a secret looks like: secrets-guard refuses these in a write, and the logs mask them, so a log can be read and shared.
2
+ // SECRETS: [[name, regex]] maskSecrets(text) -> text with each one replaced by its name
3
+ export const SECRETS = [
4
+ ['a GitHub token', /\b(?:gh[pousr]_[A-Za-z0-9]{30,}|github_pat_[A-Za-z0-9_]{40,})/g],
5
+ ['an Anthropic key', /\bsk-ant-[A-Za-z0-9_-]{20,}/g],
6
+ ['an OpenAI key', /\bsk-(?!ant-)(?:proj-)?[A-Za-z0-9_-]{32,}/g],
7
+ ['an AWS access key', /\bAKIA[0-9A-Z]{16}\b/g],
8
+ ['a Slack token', /\bxox[abprs]-[A-Za-z0-9-]{10,}/g],
9
+ ['a Stripe secret key', /\b[rs]k_live_[A-Za-z0-9]{20,}/g],
10
+ ['a private key', /-----BEGIN (?:[A-Z]+ )?PRIVATE KEY-----\s+[A-Za-z0-9+/=\s]{64,}/g],
11
+ // A key's random part runs unbroken; a long identifier (`cap_Filter_Env_Attack_2`) is short words between underscores.
12
+ ['a prefixed API key', /\b(?!price_|prod_|pk_|[rs]k_live_|github_pat_|gh[pousr]_)(?=[a-z]{2,8}_)(?=[\w-]*[A-Z])(?=[\w-]*\d)(?=[a-z]{2,8}_[\w-]*?[A-Za-z0-9]{20})[a-z]{2,8}_[A-Za-z0-9_-]{24,}\b/g],
13
+ ['a connection string with its password', /\b(?:mongodb(?:\+srv)?|postgres(?:ql)?|mysql|redis|amqp):\/\/[^\s:@/'"`]+:(?!\$\{|\$[A-Za-z_]|<|\*+@|[^\s@]*(?:[Pp]ass(?:word|wd)?|[Cc]hange|[Ee]xample|[Yy]our|[Ss]ecret|[Pp]laceholder|xxx|XXX))[^\s@/'"`]{3,}@/g],
14
+ ];
15
+
16
+ const WORDS = /\b(password|passwd|secret|token|api[_-]?key)(\s*[=:]\s*)(['"]?)[^\s'"&]{4,}/gi;
17
+
18
+ export const maskSecrets = (text) => SECRETS.reduce((t, [name, re]) => t.replace(re, `[${name}]`), String(text)).replace(WORDS, '$1$2$3[masked]');
@@ -0,0 +1,45 @@
1
+ // What a hook's `--selftest` runs on: a throwaway project, the hook run the way Claude Code runs
2
+ // it (payload on stdin, CLAUDE_PROJECT_DIR set) and its exit code judged. Every hook proves its
3
+ // law this way, so nobody probes a hook by pasting payloads into a shell command, where a guard
4
+ // that judges command text can refuse the probe itself (Sub37 WB-4). doctor runs every selftest.
5
+ import { execFileSync, spawnSync } from 'node:child_process';
6
+ import { existsSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
7
+ import { tmpdir } from 'node:os';
8
+ import { dirname, join } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+
11
+ const made = [];
12
+
13
+ export const put = (file, text) => { mkdirSync(dirname(file), { recursive: true }); writeFileSync(file, text); };
14
+ export const git = (cwd, ...a) => execFileSync('git', ['-c', 'user.email=selftest@local', '-c', 'user.name=selftest', ...a], { cwd, stdio: 'ignore' });
15
+
16
+ // files: { "rel/path": "text" }; layout, when given, becomes .claude/layout.json.
17
+ export function scratchProject(files = {}, layout = null) {
18
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), 'cp-selftest-')));
19
+ made.push(dir);
20
+ if (layout) put(join(dir, '.claude/layout.json'), JSON.stringify(layout));
21
+ for (const [rel, text] of Object.entries(files)) put(join(dir, rel), text);
22
+ return dir;
23
+ }
24
+
25
+ // A hook event goes through run-hooks.mjs, the way settings.json runs every kit hook (KWB-24), so each selftest proves the
26
+ // hook inside the runner; a by-hand mode (args, e.g. --init) runs the hook file itself.
27
+ const RUNNER = fileURLToPath(new URL('../run-hooks.mjs', import.meta.url));
28
+ export const runHook = (hook, dir, payload, args = []) =>
29
+ spawnSync(process.execPath, args.length || !existsSync(RUNNER) ? [hook, ...args] : [RUNNER, hook], {
30
+ cwd: dir, input: payload ? JSON.stringify(payload) : '', encoding: 'utf8',
31
+ env: { ...process.env, CLAUDE_PROJECT_DIR: dir },
32
+ }).status;
33
+
34
+ export const writeOf = (file_path, content = '// new\n') => ({ tool_name: 'Write', tool_input: { file_path, content } });
35
+ export const editOf = (file_path, old_string = 'a', new_string = 'b') => ({ tool_name: 'Edit', tool_input: { file_path, old_string, new_string } });
36
+ export const bashOf = (command, cwd) => ({ tool_name: 'Bash', tool_input: { command }, ...(cwd ? { cwd } : {}) });
37
+
38
+ // cases: [label, actual, wanted]. Prints "<name> selftest: OK (n cases)" or each failure; exit code.
39
+ export function verdicts(name, cases) {
40
+ for (const dir of made.splice(0)) rmSync(dir, { recursive: true, force: true });
41
+ const bad = cases.filter(([, got, want]) => got !== want);
42
+ for (const [label, got, want] of bad) console.error(`${name} selftest FAILED: ${label} (got ${got}, wanted ${want})`);
43
+ if (!bad.length) console.log(`${name} selftest: OK (${cases.length} cases)`);
44
+ return bad.length ? 1 : 0;
45
+ }
@@ -0,0 +1,126 @@
1
+ // shape-code: what the shape law reads in code beyond literal instances (lib/shape.mjs holds the number rule).
2
+ // findSelectorDefs(text, file, shape) -> [{ line, text, concept, name, why, kind: 'selector' }]
3
+ // a function whose name joins a concept word with pick/select/for/first/owner, defined here and not listed as a
4
+ // selector (or the generator, or a constant) of that concept in design/shape.json
5
+ // findUnknownTypes(text, file, shape) -> [{ line, text, concept: null, name, why, kind: 'type' }]
6
+ // a new class/struct/enum whose name holds no concept's word and that looks like an instance container (an index
7
+ // member, or it is made N times in an array): its concept has no row yet; a type in the manifest's "values" is skipped
8
+ import { conceptOfName, parts, SHAPE_FILE } from './shape.mjs';
9
+
10
+ export const CODE = /\.(c|cc|cpp|cxx|h|hh|hpp|hxx|inl|mm|m|js|mjs|cjs|ts|tsx|jsx|py|swift|rs|go|java|kt|cs)$/i;
11
+ const KEYWORDS = new Set(['if', 'for', 'while', 'switch', 'catch', 'return', 'sizeof', 'else', 'new', 'delete', 'case', 'throw', 'co_return', 'do', 'function', 'await', 'typeof']);
12
+ const PICKS = [(p) => p.startsWith('pick'), (p) => p.startsWith('select'), (p) => p.startsWith('owner') || p === 'owning', (p) => p === 'for', (p) => p === 'first'];
13
+ const ITERATES = new Set(['each', 'all', 'every', 'count', 'num', 'size']);
14
+
15
+ function definitions(text) {
16
+ const out = [];
17
+ const lines = text.split('\n');
18
+ const RES = [
19
+ /^\s*(?:(?:static|inline|constexpr|consteval|virtual|extern|friend|explicit|const|unsigned|signed|\[\[\w+\]\])\s+)*[A-Za-z_][\w:<>,*&]*\s*[*&]?\s+[*&]?([A-Za-z_]\w*)\s*\([^;{}]*\)\s*(?:const\s*)?(?:noexcept\s*)?(?:override\s*)?(?:->\s*[\w:<>*&\s]+)?\s*(?:\{|;|$)/,
20
+ /\bfunction\s*\*?\s*([A-Za-z_$][\w$]*)\s*\(/,
21
+ /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s*)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/,
22
+ /^\s*(?:static\s+|async\s+|get\s+)*([A-Za-z_$][\w$]*)\s*\([^)]*\)\s*\{/,
23
+ /^\s*(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(/,
24
+ /^\s*(?:pub\s+)?fn\s+([A-Za-z_]\w*)\s*[<(]/,
25
+ ];
26
+ lines.forEach((l, i) => {
27
+ for (const re of RES) {
28
+ const m = l.match(re);
29
+ if (!m || KEYWORDS.has(m[1])) continue;
30
+ const first = l.trim().split(/\s+/)[0];
31
+ if (re === RES[0] && KEYWORDS.has(first)) continue;
32
+ out.push({ line: i + 1, text: l.trim(), name: m[1] });
33
+ break;
34
+ }
35
+ });
36
+ return out;
37
+ }
38
+
39
+ export function findSelectorDefs(text, file, shape) {
40
+ if (!shape || !CODE.test(file ?? '')) return [];
41
+ const out = [];
42
+ for (const d of definitions(text)) {
43
+ const ps = parts(d.name);
44
+ if (!PICKS.some((f) => ps.some(f)) || ps.some((p) => ITERATES.has(p))) continue;
45
+ const concept = conceptOfName(d.name, shape);
46
+ if (!concept) continue;
47
+ const c = shape.concepts[concept];
48
+ if (c.shape !== 'many' || c.selectors.includes(d.name) || c.constants.includes(d.name) || c.generatorName === d.name) continue;
49
+ const listed = c.selectors.length ? `call a listed one (${c.selectors.join(', ')}) or ` : '';
50
+ out.push({ ...d, concept, kind: 'selector', why: `defines ${d.name}, a selector for ${concept} that ${SHAPE_FILE} does not list — example, rule, or constant? (a rule is a named selector: ${listed}add "${d.name}": "<what it picks>" to the ${concept} row's selectors first)` });
51
+ }
52
+ return out;
53
+ }
54
+
55
+ function bodyOf(lines, i, python) {
56
+ if (python) {
57
+ const ind = lines[i].match(/^\s*/)[0].length;
58
+ const body = [];
59
+ for (let k = i + 1; k < lines.length && (lines[k].trim() === '' || lines[k].match(/^\s*/)[0].length > ind); k += 1) body.push(lines[k]);
60
+ return body.join('\n');
61
+ }
62
+ const rest = lines.slice(i).join('\n');
63
+ const open = rest.indexOf('{');
64
+ if (open < 0) return '';
65
+ let depth = 0;
66
+ for (let k = open; k < rest.length; k += 1) {
67
+ if (rest[k] === '{') depth += 1;
68
+ else if (rest[k] === '}' && --depth === 0) return rest.slice(open, k + 1);
69
+ }
70
+ return rest.slice(open);
71
+ }
72
+
73
+ const INDEX_MEMBER = [
74
+ /\b(?:int|size_t|std::size_t|unsigned|uint\w*|int\w*_t|short|long)\s+(?:index|idx|ix)\s*[;={]/,
75
+ /\b(?:int|size_t|std::size_t|unsigned|uint\w*|int\w*_t|short|long)\s+\w*(?:Index|Idx|Ix)\s*[;={]/,
76
+ /\b(?:this|self)\.(?:index|idx|ix|\w*(?:Index|Idx|Ix))\s*=/,
77
+ /^\s*(?:index|idx|ix|\w*(?:Index|Idx|Ix))\s*[:=]/m,
78
+ ];
79
+
80
+ // The type is made N times, N a named count: an array of it (std::array, T name[N], a vector of N, Array.from, a list comprehension). An
81
+ // array whose name or count holds a known concept word is that concept's (Box slot[4] is per slot, known); a table with a
82
+ // filled-in initializer is data, not instances.
83
+ function madeN(text, name, shape) {
84
+ const N = '([A-Za-z_]\\w*|\\d+)';
85
+ const res = [
86
+ new RegExp(`std::array\\s*<\\s*${name}\\s*,\\s*${N}\\s*>\\s*(\\w*)(\\s*=?\\s*\\{[^}]*)?`, 'g'),
87
+ new RegExp(`\\b${name}\\s+(?<arr>\\w+)\\s*\\[\\s*${N}\\s*\\](\\s*=?\\s*\\{[^}]*)?`, 'g'),
88
+ new RegExp(`std::vector\\s*<\\s*${name}\\s*>\\s*(\\w+)\\s*[({]\\s*${N}\\s*[)}]()`, 'g'),
89
+ new RegExp(`(\\w+)\\s*=\\s*Array\\.from\\(\\s*\\{\\s*length\\s*:\\s*${N}\\s*\\}[^)]*new\\s+${name}\\b()`, 'g'),
90
+ new RegExp(`(\\w+)\\s*=\\s*\\[\\s*${name}\\(.*\\)\\s+for\\s+\\w+\\s+in\\s+range\\(\\s*${N}\\s*\\)()`, 'g'),
91
+ ];
92
+ for (const re of res) {
93
+ for (const m of text.matchAll(re)) {
94
+ const [count, arr, init] = re === res[0] ? [m[1], m[2], m[3]] : re === res[1] ? [m[2], m[1], m[3]] : [m[2], m[1], m[3]];
95
+ if (/^\d+$/.test(count)) continue; // a literal size is a capacity or a fixed table; instances are counted by a named count
96
+ if (init && /\{\s*[^}\s]/.test(init)) continue; // a table of values
97
+ if (conceptOfName(arr ?? '', shape) || conceptOfName(count, shape)) continue;
98
+ return true;
99
+ }
100
+ }
101
+ return false;
102
+ }
103
+
104
+ export function findUnknownTypes(text, file, shape) {
105
+ if (!shape || !CODE.test(file ?? '')) return [];
106
+ const python = /\.py$/i.test(file);
107
+ const lines = text.split('\n');
108
+ const out = [];
109
+ lines.forEach((l, i) => {
110
+ const m = python ? l.match(/^\s*class\s+([A-Za-z_]\w*)/) : l.match(/\b(?:class|struct|enum(?:\s+class|\s+struct)?)\s+(?:\[\[\w+\]\]\s+)?(?:alignas\([^)]*\)\s+)?([A-Za-z_]\w*)\s*(?:final\s*)?(?:extends\s+[\w.]+\s*)?(?::[^;{]*)?(?:\{|$)/);
111
+ if (!m || /^\s*(?:\/\/|\*|#)/.test(l) || /\bfriend\b|\btemplate\s*<\s*class\b/.test(l)) return;
112
+ const name = m[1];
113
+ if (conceptOfName(name, shape) || shape.values?.has(name)) return; // a listed value type is not a container (KWB-10)
114
+ const body = bodyOf(lines, i, python);
115
+ const inArray = madeN(text, name, shape);
116
+ if (!INDEX_MEMBER.some((re) => re.test(body)) && !inArray) return;
117
+ out.push({ line: i + 1, text: l.trim(), concept: null, name, kind: 'type', why: `defines ${name}, a container of instances whose concept has no row in ${SHAPE_FILE} — add the row to ${SHAPE_FILE} first (one or many, its generator, its selectors), then build the type` });
118
+ });
119
+ return out;
120
+ }
121
+
122
+ // The definitions an edit adds: names defined after it that were not defined before it.
123
+ export function addedDefs(before, after, find) {
124
+ const had = new Set(find(before ?? '').map((d) => d.name));
125
+ return find(after ?? '').filter((d) => !had.has(d.name));
126
+ }
@@ -0,0 +1,31 @@
1
+ // shape-lists: consecutive lines (or ;/, separated pieces of one line) that differ only in one number running over every instance: a hand-listed set, one line
2
+ // per instance. Split out of shape.mjs at its line limit.
3
+ // handLists(lines, c, out, seen): adds a finding to out for each such set of the concept c
4
+ import { classify, isExampleLine, named, parts } from './shape.mjs';
5
+
6
+ const templatesOf = (t) => [...t.matchAll(/(?<![\w.])\d+(?![\w.])/g)].map((m) => ({ tpl: t.slice(0, m.index) + '#' + t.slice(m.index + m[0].length), v: Number(m[0]) }));
7
+
8
+ export function handLists(lines, c, out, seen) {
9
+ if (!c.count || c.count < 2 || c.shape !== 'many') return;
10
+ const mentions = (t) => parts(t).some((p) => c.words.includes(p)) || c.arrays.some((a) => named(t, a));
11
+ const runOver = (pieces, at, whole = null) => {
12
+ for (let i = 0; i + c.count <= pieces.length; i += 1) {
13
+ for (const first of templatesOf(pieces[i].trim())) {
14
+ if (first.v > 1 || !mentions(whole ?? first.tpl)) continue;
15
+ let ok = true;
16
+ for (let k = 1; k < c.count && ok; k += 1) ok = templatesOf(pieces[i + k].trim()).some((t) => t.tpl === first.tpl && t.v === first.v + k);
17
+ if (ok) return at(i);
18
+ }
19
+ }
20
+ return null;
21
+ };
22
+ const lineNo = runOver(lines, (i) => i);
23
+ if (lineNo !== null && !isExampleLine(lines[lineNo]) && !seen.has(`${lineNo}|${c.name}`)) {
24
+ out.push({ line: lineNo + 1, text: lines[lineNo].trim(), concept: c.name, instance: 'each', why: `a hand-listed set, one line per ${c.name}: write one loop over every ${c.name}, or the generator` });
25
+ }
26
+ lines.forEach((l, i) => {
27
+ if (seen.has(`${i}|${c.name}`) || isExampleLine(l) || classify(l, c, null)) return;
28
+ const pieces = l.split(/[;,]/);
29
+ if (pieces.length >= c.count && runOver(pieces, () => true, l)) out.push({ line: i + 1, text: l.trim(), concept: c.name, instance: 'each', why: `a hand-listed set, one piece per ${c.name}: write one loop over every ${c.name}, or the generator` });
30
+ });
31
+ }
@@ -0,0 +1,78 @@
1
+ // shape-prose: what in a line is English, arithmetic or a name, and so names no instance (KF-13, KF-17, KF-20, KF-28, KF-36: 14 of shape-law's 25 refusals on the
2
+ // MPX 500 were wrong, on words like these). Each test is narrow on purpose: the same line with the bare form stays refused (test/kf-refusals.test.mjs holds both).
3
+ // blankMessages(line, file) -> line with a sentence in a double-quoted string blanked, same length; a short key ("knob 1") stays
4
+ // isFirstMatch(line, m) "the first program with this name", "each bank's first program", the words "first program" in quotes
5
+ // isSourceRole(line, m) a comment quoting a role a source gives: "[MAN] Edit knob 1 selects"
6
+ // isKnownName(role, word, shape) "EDIT knob", when editKnob is a concept or a listed selector
7
+ // isLongerName(line, end) "MIDI Program Change": the word starts a longer proper name
8
+ // isSum(before) "x + 1 == program": the number is an operand, not what is compared
9
+ // isLibraryCall(line, at, shape) juce::MidiMessage::programChange (1, ...): a library's call, or one on a listed value type
10
+ // declaredAmount(root, name, text) a call whose declared first parameter is an amount: turnProgram (int steps, ...)
11
+ import { execFileSync } from 'node:child_process';
12
+ import { extname } from 'node:path';
13
+ import { languageOf } from './languages.mjs';
14
+
15
+ const SENTENCE_WORDS = 3;
16
+ const LIBRARIES = new Set(['juce', 'std', 'boost', 'absl', 'Qt']);
17
+ const AMOUNT = /^(?:steps?|detents?|clicks?|notches|ticks?|amount|delta|by|count|n|offset|increment|distance)$/i;
18
+ const SOURCE_FILES = ['*.h', '*.hh', '*.hpp', '*.c', '*.cc', '*.cpp', '*.mm', '*.js', '*.mjs', '*.ts', '*.tsx', '*.py', '*.go', '*.rs', '*.java', '*.cs', '*.swift', '*.kt'];
19
+
20
+ export function blankMessages(line, file) {
21
+ if (!languageOf(extname(file ?? ''))) return line;
22
+ return line.replace(/"(?:[^"\\]|\\.)*"/g, (s) => (s.trim().split(/\s+/).length >= SENTENCE_WORDS ? ' '.repeat(s.length) : s));
23
+ }
24
+
25
+ export function isFirstMatch(line, m) {
26
+ if (!/^first\b/i.test(m[0])) return false;
27
+ const before = line.slice(0, m.index);
28
+ const after = line.slice(m.index + m[0].length);
29
+ if (before.endsWith('"') && after.startsWith('"')) return true;
30
+ return /(?:'s|\b[Aa]|\b[Ee]ach|\b[Ee]very|\b[Aa]ny)\s+$/.test(before) || /^(?:'s)?\s+(?:with|that|which|whose|where|matching|found|a|an)\b/.test(after);
31
+ }
32
+
33
+ export function isSourceRole(line, m) {
34
+ const isComment = /^\s*(?:\/\/|\/\*|\*|#)/.test(line);
35
+ return isComment && /\[[A-Z]{2,6}\]/.test(line.slice(0, m.index)) && /^\s+[a-z]+s\b/.test(line.slice(m.index + m[0].length));
36
+ }
37
+
38
+ const named = new WeakMap();
39
+ function namesOf(shape) {
40
+ if (!named.has(shape)) {
41
+ const rows = Object.values(shape.concepts);
42
+ named.set(shape, new Set(rows.flatMap((c) => [c.name, ...c.selectors, ...c.constants]).map((n) => n.toLowerCase())));
43
+ }
44
+ return named.get(shape);
45
+ }
46
+ export const isKnownName = (role, word, shape) => namesOf(shape).has(`${role}${word}`.toLowerCase());
47
+
48
+ export const isLongerName = (line, end) => /^\s+[A-Z][a-z]/.test(line.slice(end));
49
+ export const isSum = (before) => /[+\-*/%]\s*$/.test(before);
50
+
51
+ export function isLibraryCall(line, at, shape) {
52
+ const path = line.slice(0, at).match(/([A-Za-z_]\w*)::(?:[A-Za-z_]\w*::)*$/);
53
+ if (!path) return false;
54
+ const last = line.slice(0, at).match(/([A-Za-z_]\w*)::$/)?.[1];
55
+ return LIBRARIES.has(path[1]) || shape.values?.has(last);
56
+ }
57
+
58
+ // The first parameter of each declaration of `name`, from the text being written and the project's files.
59
+ function firstParameters(root, name, text) {
60
+ const shape = new RegExp(`\\b${name}\\s*\\(\\s*(?:const\\s+)?(?:[\\w:<>]+[\\s&*]+)+(\\w+)\\s*[,)=]`, 'g');
61
+ let found = '';
62
+ try {
63
+ found = execFileSync('git', ['-C', root, 'grep', '--untracked', '-hE', `\\b${name}[[:space:]]*\\(`, '--', ...SOURCE_FILES], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 5000 });
64
+ } catch {
65
+ found = ''; // no match, or no repository: nothing declares it, so the call stays an instance
66
+ }
67
+ return [...`${text}\n${found}`.matchAll(shape)].map((m) => m[1]);
68
+ }
69
+
70
+ const amounts = new Map();
71
+ export function declaredAmount(root, name, text) {
72
+ const key = `${root}\0${name}`;
73
+ if (!amounts.has(key)) {
74
+ const params = firstParameters(root, name, text);
75
+ amounts.set(key, params.length > 0 && params.every((p) => AMOUNT.test(p)));
76
+ }
77
+ return amounts.get(key);
78
+ }