@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.
- package/CHANGELOG.md +680 -0
- package/LICENSE +21 -0
- package/README.md +316 -2
- package/bin/claude-packs.mjs +204 -0
- package/configurations/base/config.json +85 -0
- package/configurations/cpp/config.json +92 -0
- package/configurations/full-stack/config.json +152 -0
- package/configurations/go/config.json +96 -0
- package/configurations/node/config.json +100 -0
- package/configurations/python/config.json +97 -0
- package/configurations/synth-creator/config.json +148 -0
- package/global/hooks/gnu-shell.mjs +131 -0
- package/global/hooks/lib/program-read.mjs +196 -0
- package/global/hooks/lib/program-writes.mjs +177 -0
- package/global/hooks/lib/shell-writes.mjs +293 -0
- package/global/hooks/shell-traps.mjs +79 -0
- package/global/hooks/version-pin-guard.mjs +280 -0
- package/global/skills/latest-versions/SKILL.md +49 -0
- package/lib/backup.mjs +34 -0
- package/lib/claude-md.mjs +58 -0
- package/lib/config-cli.mjs +36 -0
- package/lib/configs.mjs +145 -0
- package/lib/coverage.mjs +86 -0
- package/lib/custom-packs.mjs +93 -0
- package/lib/doctor.mjs +115 -0
- package/lib/fix-plan.mjs +71 -0
- package/lib/git-tokens.mjs +64 -0
- package/lib/global.mjs +125 -0
- package/lib/hook-proof.mjs +28 -0
- package/lib/hook-timing.mjs +42 -0
- package/lib/hover-gate.mjs +29 -0
- package/lib/kit-lock.mjs +149 -0
- package/lib/layout.mjs +75 -0
- package/lib/logs.mjs +69 -0
- package/lib/manifest.mjs +24 -0
- package/lib/new.mjs +49 -0
- package/lib/once-only-report.mjs +54 -0
- package/lib/pack-manifest.mjs +20 -0
- package/lib/packs.mjs +107 -0
- package/lib/planner.mjs +59 -0
- package/lib/repeats.mjs +65 -0
- package/lib/repo-weight.mjs +28 -0
- package/lib/rules.mjs +40 -0
- package/lib/scan-detect.mjs +94 -0
- package/lib/scan.mjs +168 -0
- package/lib/selftest-cache.mjs +39 -0
- package/lib/settings.mjs +138 -0
- package/lib/shape-cli.mjs +76 -0
- package/lib/shape.mjs +4 -0
- package/lib/suggest.mjs +18 -0
- package/lib/switches.mjs +44 -0
- package/lib/symmetry-doctor.mjs +26 -0
- package/lib/sync.mjs +130 -0
- package/package.json +34 -4
- package/packs/ai/checks/boundary-computes-its-own-hash.json +30 -0
- package/packs/ai/checks/model-call-needs-boundary.json +29 -0
- package/packs/ai/checks/model-id-from-config.json +28 -0
- package/packs/ai/checks/model-output-validated.json +26 -0
- package/packs/ai/pack.json +38 -0
- package/packs/ai/rules/ai-input-sha-boundary.md +31 -0
- package/packs/ai/rules/llm-pipeline-security.md +26 -0
- package/packs/audio-core/checks/denormals-not-in-prepare.json +12 -0
- package/packs/audio-core/checks/dsp-without-apvts.json +12 -0
- package/packs/audio-core/checks/float-phase-or-rate.json +12 -0
- package/packs/audio-core/checks/juce-snap-to-zero-off.json +12 -0
- package/packs/audio-core/checks/keep-werror.json +12 -0
- package/packs/audio-core/checks/no-fast-math.json +14 -0
- package/packs/audio-core/checks/no-locale-change.json +12 -0
- package/packs/audio-core/checks/no-march-native.json +14 -0
- package/packs/audio-core/clang-tidy +28 -0
- package/packs/audio-core/hooks/lib/realtime-checks.mjs +56 -0
- package/packs/audio-core/hooks/param-id-lock.mjs +129 -0
- package/packs/audio-core/hooks/realtime-guard.mjs +67 -0
- package/packs/audio-core/pack.json +187 -0
- package/packs/audio-core/rules/audio-thread-realtime-safe.md +27 -0
- package/packs/audio-core/rules/audio-ui-thread-handoff.md +21 -0
- package/packs/audio-core/rules/boundary-tests-cross-the-boundary.md +16 -0
- package/packs/audio-core/rules/build-flags-safe.md +20 -0
- package/packs/audio-core/rules/cached-parameter-pointers.md +28 -0
- package/packs/audio-core/rules/clang-tidy-core-guidelines.md +21 -0
- package/packs/audio-core/rules/control-reaches-every-surface.md +23 -0
- package/packs/audio-core/rules/cpu-worst-case-per-block.md +26 -0
- package/packs/audio-core/rules/dc-block-after-asymmetry.md +22 -0
- package/packs/audio-core/rules/discrete-params-snap.md +19 -0
- package/packs/audio-core/rules/double-where-precision-matters.md +20 -0
- package/packs/audio-core/rules/filters-stable-under-modulation.md +29 -0
- package/packs/audio-core/rules/host-parameters-at-scale.md +24 -0
- package/packs/audio-core/rules/house-control-behaviours.md +34 -0
- package/packs/audio-core/rules/math-domain-guards.md +19 -0
- package/packs/audio-core/rules/modulated-delay-interpolation.md +22 -0
- package/packs/audio-core/rules/multiband-phase-coherent.md +22 -0
- package/packs/audio-core/rules/nonlinear-stages-antialiased.md +28 -0
- package/packs/audio-core/rules/note-ledger-and-pedals.md +22 -0
- package/packs/audio-core/rules/one-formula-per-value.md +20 -0
- package/packs/audio-core/rules/optimisations-are-null-tested.md +23 -0
- package/packs/audio-core/rules/oscillators-bandlimited.md +23 -0
- package/packs/audio-core/rules/output-limiter.md +23 -0
- package/packs/audio-core/rules/parameter-ids-never-change.md +20 -0
- package/packs/audio-core/rules/params-and-state-thread-safe.md +19 -0
- package/packs/audio-core/rules/params-snapshot-per-block.md +21 -0
- package/packs/audio-core/rules/patch-excludes-performance-controls.md +18 -0
- package/packs/audio-core/rules/per-sample-code-inlinable.md +22 -0
- package/packs/audio-core/rules/prepare-is-repeatable.md +23 -0
- package/packs/audio-core/rules/recursive-state-nan-guard.md +20 -0
- package/packs/audio-core/rules/reverb-loop-gain-bounded.md +24 -0
- package/packs/audio-core/rules/sample-accurate-midi.md +22 -0
- package/packs/audio-core/rules/sample-rate-and-block-size-from-host.md +23 -0
- package/packs/audio-core/rules/scoped-no-denormals.md +26 -0
- package/packs/audio-core/rules/smooth-continuous-parameters.md +22 -0
- package/packs/audio-core/rules/state-load-versioned-and-safe.md +22 -0
- package/packs/audio-core/rules/straight-on-and-aligned.md +21 -0
- package/packs/audio-core/rules/ui-matches-reference-look.md +21 -0
- package/packs/audio-core/rules/undo-one-gesture-one-step.md +21 -0
- package/packs/audio-core/rules/voice-steal-fades.md +21 -0
- package/packs/audio-core/rules/voice-sum-headroom.md +20 -0
- package/packs/audio-core/skills/analyse-reference-look/SKILL.md +21 -0
- package/packs/audio-core/skills/copy-and-prove/SKILL.md +98 -0
- package/packs/audio-core/skills/juce-realtime-audit/SKILL.md +22 -0
- package/packs/audio-core/skills/measure-tone/SKILL.md +20 -0
- package/packs/audio-core/skills/new-panel-control/SKILL.md +15 -0
- package/packs/audio-core/skills/prove-control/SKILL.md +23 -0
- package/packs/audio-core/skills/trace-parameter/SKILL.md +29 -0
- package/packs/audio-core/tools/lib/spectrum.mjs +112 -0
- package/packs/audio-core/tools/lib/wav.mjs +41 -0
- package/packs/audio-core/tools/tone-report.mjs +47 -0
- package/packs/base/checks/field-map-over-if-runs.json +25 -0
- package/packs/base/checks/lookup-over-if-chains.json +25 -0
- package/packs/base/checks/lookup-over-ternary-chains.json +20 -0
- package/packs/base/checks/no-code-after-midline-comment.json +12 -0
- package/packs/base/checks/one-walk-per-template.json +23 -0
- package/packs/base/checks/stub-reports-success.json +31 -0
- package/packs/base/checks/test-skip-on-failed-setup.json +17 -0
- package/packs/base/hooks/brief-guard.mjs +96 -0
- package/packs/base/hooks/code-shape.mjs +95 -0
- package/packs/base/hooks/dispatch-once.mjs +87 -0
- package/packs/base/hooks/file-size-guard.mjs +61 -0
- package/packs/base/hooks/folder-law.mjs +74 -0
- package/packs/base/hooks/git-guard.mjs +289 -0
- package/packs/base/hooks/lesson-checks.mjs +174 -0
- package/packs/base/hooks/lib/apply-edit.mjs +20 -0
- package/packs/base/hooks/lib/code-shapes.mjs +137 -0
- package/packs/base/hooks/lib/content.mjs +14 -0
- package/packs/base/hooks/lib/cpp-scan.mjs +94 -0
- package/packs/base/hooks/lib/dup-index.mjs +199 -0
- package/packs/base/hooks/lib/dup.mjs +127 -0
- package/packs/base/hooks/lib/elements.mjs +87 -0
- package/packs/base/hooks/lib/event-log.mjs +67 -0
- package/packs/base/hooks/lib/function-shapes.mjs +90 -0
- package/packs/base/hooks/lib/git-adds.mjs +20 -0
- package/packs/base/hooks/lib/git-guard-selftest.mjs +99 -0
- package/packs/base/hooks/lib/glob.mjs +33 -0
- package/packs/base/hooks/lib/hook-log.mjs +100 -0
- package/packs/base/hooks/lib/house.py +77 -0
- package/packs/base/hooks/lib/languages.mjs +66 -0
- package/packs/base/hooks/lib/layout.mjs +54 -0
- package/packs/base/hooks/lib/making-check-selftest.mjs +109 -0
- package/packs/base/hooks/lib/near-copies.mjs +76 -0
- package/packs/base/hooks/lib/program-read.mjs +196 -0
- package/packs/base/hooks/lib/program-writes.mjs +177 -0
- package/packs/base/hooks/lib/project.mjs +81 -0
- package/packs/base/hooks/lib/prose.mjs +11 -0
- package/packs/base/hooks/lib/pushed.mjs +201 -0
- package/packs/base/hooks/lib/repo-index.mjs +52 -0
- package/packs/base/hooks/lib/secret-patterns.mjs +18 -0
- package/packs/base/hooks/lib/selftest.mjs +45 -0
- package/packs/base/hooks/lib/shape-code.mjs +126 -0
- package/packs/base/hooks/lib/shape.mjs +294 -0
- package/packs/base/hooks/lib/shell-writes-selftest.mjs +65 -0
- package/packs/base/hooks/lib/shell-writes.mjs +293 -0
- package/packs/base/hooks/lib/turn.mjs +81 -0
- package/packs/base/hooks/lib/writes.mjs +71 -0
- package/packs/base/hooks/making-check.mjs +243 -0
- package/packs/base/hooks/making.mjs +106 -0
- package/packs/base/hooks/once-only.mjs +150 -0
- package/packs/base/hooks/placement-law.mjs +84 -0
- package/packs/base/hooks/repo-litter.mjs +75 -0
- package/packs/base/hooks/reuse-hint.mjs +75 -0
- package/packs/base/hooks/run-hooks.mjs +132 -0
- package/packs/base/hooks/secrets-guard.mjs +99 -0
- package/packs/base/hooks/shape-law.mjs +133 -0
- package/packs/base/hooks/suite-once.mjs +80 -0
- package/packs/base/hooks/template-law.mjs +148 -0
- package/packs/base/hooks/untrusted-boundary.mjs +53 -0
- package/packs/base/pack.json +214 -0
- package/packs/base/rules/a-control-is-seen-to-fire.md +27 -0
- package/packs/base/rules/behaviour-lives-with-its-kind.md +51 -0
- package/packs/base/rules/bug-fix-starts-red.md +25 -0
- package/packs/base/rules/field-map-over-if-runs.md +47 -0
- package/packs/base/rules/finished-work-lands.md +17 -0
- package/packs/base/rules/git-right-first-time.md +19 -0
- package/packs/base/rules/instances-by-index-identities-by-id.md +54 -0
- package/packs/base/rules/lookup-over-if-chains.md +49 -0
- package/packs/base/rules/making-line-first.md +14 -0
- package/packs/base/rules/open-items-tagged.md +17 -0
- package/packs/base/rules/plan-and-logs.md +22 -0
- package/packs/base/rules/references-use-anchors.md +19 -0
- package/packs/base/rules/refusals-are-judged.md +18 -0
- package/packs/base/rules/reuse-before-writing.md +15 -0
- package/packs/base/rules/secrets-never-committed.md +16 -0
- package/packs/base/rules/skill-writing.md +23 -0
- package/packs/base/rules/split-before-the-limit.md +14 -0
- package/packs/base/rules/subagent-dispatch.md +26 -0
- package/packs/base/rules/test-only-what-changed.md +17 -0
- package/packs/base/rules/test-the-template-once.md +22 -0
- package/packs/base/rules/untrusted-content-boundary.md +15 -0
- package/packs/base/skills/add-lesson-check/SKILL.md +26 -0
- package/packs/base/skills/fix-from-scan/SKILL.md +25 -0
- package/packs/base/skills/land-branch/SKILL.md +24 -0
- package/packs/base/skills/make-it-a-template/SKILL.md +23 -0
- package/packs/base/skills/pdf-to-md/SKILL.md +25 -0
- package/packs/base/skills/pick-tests/SKILL.md +20 -0
- package/packs/base/skills/pressure-test-skill/SKILL.md +23 -0
- package/packs/base/skills/prove-instances-identical/SKILL.md +37 -0
- package/packs/base/tools/shape-symmetry-selftest.mjs +66 -0
- package/packs/base/tools/shape-symmetry.mjs +178 -0
- package/packs/base/tools/test-verdict.mjs +75 -0
- package/packs/ci/checks/ci-permissions-stated.json +18 -0
- package/packs/ci/checks/ci-tools-pinned.json +14 -0
- package/packs/ci/pack.json +21 -0
- package/packs/ci/rules/ci-covers-what-ships.md +20 -0
- package/packs/ci/rules/generated-files-have-no-diff.md +15 -0
- package/packs/content-site/checks/captcha-is-not-constant.json +27 -0
- package/packs/content-site/checks/img-has-size.json +20 -0
- package/packs/content-site/checks/page-head-complete.json +26 -0
- package/packs/content-site/pack.json +22 -0
- package/packs/content-site/rules/content-has-one-source.md +23 -0
- package/packs/content-site/rules/media-is-sized.md +24 -0
- package/packs/content-site/rules/page-head-is-complete.md +26 -0
- package/packs/content-site/rules/public-forms-are-defended.md +27 -0
- package/packs/content-site/skills/publish-a-page/SKILL.md +21 -0
- package/packs/cpp/checks/cpp-clamp-before-cast.json +16 -0
- package/packs/cpp/checks/cpp-find-with-the-library.json +12 -0
- package/packs/cpp/checks/cpp-hardened-test-build.json +18 -0
- package/packs/cpp/checks/cpp-m-pi-not-standard.json +23 -0
- package/packs/cpp/checks/cpp-no-atoi.json +16 -0
- package/packs/cpp/checks/cpp-no-const-cast.json +16 -0
- package/packs/cpp/checks/cpp-no-float-loop-counter.json +16 -0
- package/packs/cpp/checks/cpp-no-getenv-in-product.json +22 -0
- package/packs/cpp/checks/cpp-no-mutable-global.json +20 -0
- package/packs/cpp/checks/cpp-no-mutable-local-static.json +23 -0
- package/packs/cpp/checks/cpp-no-unchecked-fwrite.json +17 -0
- package/packs/cpp/checks/cpp-no-using-namespace-in-header.json +19 -0
- package/packs/cpp/checks/cpp-no-zero-size-array.json +23 -0
- package/packs/cpp/checks/cpp-numbers-pi.json +16 -0
- package/packs/cpp/pack.json +22 -0
- package/packs/cpp/rules/cpp-absent-and-failed-are-types.md +24 -0
- package/packs/cpp/rules/cpp-builds-everywhere.md +26 -0
- package/packs/cpp/rules/cpp-faults-only-in-the-test-build.md +21 -0
- package/packs/cpp/rules/cpp-find-with-the-library.md +19 -0
- package/packs/cpp/rules/cpp-gates-share-one-reader.md +22 -0
- package/packs/cpp/rules/cpp-headers-declare.md +22 -0
- package/packs/cpp/rules/cpp-numbers-and-casts.md +22 -0
- package/packs/cpp/rules/cpp-repeats-become-templates.md +33 -0
- package/packs/cpp/rules/cpp-static-analysis-runs.md +22 -0
- package/packs/cpp/rules/cpp-thread-contracts-are-code.md +23 -0
- package/packs/cpp/skills/cpp-extract-template/SKILL.md +38 -0
- package/packs/docker/checks/alpine-with-native-build.json +13 -0
- package/packs/docker/checks/compose-db-needs-auth.json +14 -0
- package/packs/docker/checks/compose-image-pinned.json +14 -0
- package/packs/docker/checks/compose-no-hardcoded-ip.json +12 -0
- package/packs/docker/checks/compose-no-host-bind-for-data.json +18 -0
- package/packs/docker/checks/compose-no-plaintext-secret.json +13 -0
- package/packs/docker/checks/compose-no-swarm-ignored-keys.json +13 -0
- package/packs/docker/checks/compose-overlay-not-bridge.json +13 -0
- package/packs/docker/checks/compose-service-needs-healthcheck.json +11 -0
- package/packs/docker/checks/compose-service-needs-init.json +11 -0
- package/packs/docker/checks/copy-needs-chown-with-user.json +17 -0
- package/packs/docker/checks/copy-source-before-deps.json +13 -0
- package/packs/docker/checks/docker-exec-form.json +16 -0
- package/packs/docker/checks/dockerfile-needs-healthcheck.json +17 -0
- package/packs/docker/checks/dockerfile-needs-user.json +21 -0
- package/packs/docker/checks/dockerignore-has-the-basics.json +21 -0
- package/packs/docker/checks/gitattributes-forces-lf.json +17 -0
- package/packs/docker/checks/health-checks-nothing.json +25 -0
- package/packs/docker/checks/no-crlf-in-scripts.json +15 -0
- package/packs/docker/checks/no-latest-base.json +13 -0
- package/packs/docker/checks/no-secret-in-image.json +13 -0
- package/packs/docker/checks/no-sensitive-file-copy.json +13 -0
- package/packs/docker/checks/node-env-before-install.json +13 -0
- package/packs/docker/checks/npm-ci-not-install.json +13 -0
- package/packs/docker/pack.json +46 -0
- package/packs/docker/rules/compose-pinned-and-closed.md +21 -0
- package/packs/docker/rules/compose-swarm-safe.md +26 -0
- package/packs/docker/rules/docker-exec-form.md +19 -0
- package/packs/docker/rules/dockerfile-multistage.md +13 -0
- package/packs/docker/rules/dockerfile-production.md +25 -0
- package/packs/docker/skills/docker-diagnose/SKILL.md +23 -0
- package/packs/dynamic-data/checks/draft-on-the-server.json +27 -0
- package/packs/dynamic-data/checks/guard-does-its-job.json +28 -0
- package/packs/dynamic-data/checks/key-is-not-a-display-name.json +28 -0
- package/packs/dynamic-data/checks/no-code-from-data.json +29 -0
- package/packs/dynamic-data/checks/no-collection-from-request.json +27 -0
- package/packs/dynamic-data/checks/no-pipeline-from-stored-text.json +27 -0
- package/packs/dynamic-data/checks/no-regexp-from-stored-config.json +27 -0
- package/packs/dynamic-data/checks/no-template-from-stored-text.json +27 -0
- package/packs/dynamic-data/checks/save-takes-named-paths.json +27 -0
- package/packs/dynamic-data/pack.json +23 -0
- package/packs/dynamic-data/rules/a-list-is-a-saved-query.md +23 -0
- package/packs/dynamic-data/rules/definitions-are-validated-data.md +24 -0
- package/packs/dynamic-data/rules/every-dynamic-surface-has-a-boundary.md +29 -0
- package/packs/dynamic-data/rules/fields-have-owners.md +22 -0
- package/packs/dynamic-data/rules/imports-drop-nothing.md +26 -0
- package/packs/dynamic-data/rules/one-definition-many-surfaces.md +24 -0
- package/packs/dynamic-data/rules/one-fact-one-place.md +28 -0
- package/packs/dynamic-data/rules/rules-live-in-the-engine.md +29 -0
- package/packs/dynamic-data/rules/saves-are-patches.md +28 -0
- package/packs/dynamic-data/rules/tenant-costs-one-document.md +22 -0
- package/packs/dynamic-data/skills/design-a-definition/SKILL.md +24 -0
- package/packs/fastify/checks/api-routes-versioned.json +28 -0
- package/packs/fastify/checks/cookie-host-prefix.json +24 -0
- package/packs/fastify/checks/hijack-needs-try.json +28 -0
- package/packs/fastify/checks/no-cast-at-route-boundary.json +24 -0
- package/packs/fastify/checks/no-db-in-route-file.json +28 -0
- package/packs/fastify/checks/no-err-message-to-client.json +24 -0
- package/packs/fastify/checks/no-regexp-from-input.json +24 -0
- package/packs/fastify/checks/no-trust-proxy-true.json +25 -0
- package/packs/fastify/checks/one-error-body.json +26 -0
- package/packs/fastify/checks/origin-from-config-not-host.json +31 -0
- package/packs/fastify/checks/password-needs-slow-hash.json +30 -0
- package/packs/fastify/checks/sec-headers-present.json +28 -0
- package/packs/fastify/checks/secrets-compared-constant-time.json +24 -0
- package/packs/fastify/checks/sse-needs-error-listener.json +28 -0
- package/packs/fastify/checks/user-bytes-need-disposition.json +29 -0
- package/packs/fastify/pack.json +41 -0
- package/packs/fastify/rules/credentials-and-input.md +23 -0
- package/packs/fastify/rules/security-one-switch.md +28 -0
- package/packs/fastify/rules/streams-and-hijacks.md +22 -0
- package/packs/fastify/rules/tests-use-inject.md +13 -0
- package/packs/fastify/rules/three-layers.md +20 -0
- package/packs/fastify/rules/trust-config-not-headers.md +24 -0
- package/packs/full-stack/checks/no-express-no-vite.json +23 -0
- package/packs/full-stack/hooks/stack-guard.mjs +90 -0
- package/packs/full-stack/pack.json +76 -0
- package/packs/full-stack/rules/stack-is-fastify-and-nextjs.md +20 -0
- package/packs/go/checks/go-exec-result-ignored.json +15 -0
- package/packs/go/checks/go-unmarshal-error-ignored.json +15 -0
- package/packs/go/pack.json +21 -0
- package/packs/go/rules/go-errors-are-handled.md +22 -0
- package/packs/gpu-painter/checks/dawn-backends-and-validation.json +9 -0
- package/packs/gpu-painter/checks/dawn-no-spontaneous.json +10 -0
- package/packs/gpu-painter/checks/dawn-present-on-render-thread.json +17 -0
- package/packs/gpu-painter/checks/gpu-no-frame-stalls.json +12 -0
- package/packs/gpu-painter/checks/no-opengl-link.json +11 -0
- package/packs/gpu-painter/checks/no-opengl.json +13 -0
- package/packs/gpu-painter/hooks/browser-guard.py +196 -0
- package/packs/gpu-painter/pack.json +91 -0
- package/packs/gpu-painter/rules/dawn-build-and-shaders.md +27 -0
- package/packs/gpu-painter/rules/dawn-device-and-render-thread.md +26 -0
- package/packs/gpu-painter/rules/gpu-antialiasing.md +20 -0
- package/packs/gpu-painter/rules/gpu-blend-order.md +22 -0
- package/packs/gpu-painter/rules/gpu-bloom.md +20 -0
- package/packs/gpu-painter/rules/gpu-frame-budget.md +25 -0
- package/packs/gpu-painter/rules/gpu-frame-pacing-and-power.md +27 -0
- package/packs/gpu-painter/rules/gpu-frame-work.md +30 -0
- package/packs/gpu-painter/rules/gpu-golden-images.md +21 -0
- package/packs/gpu-painter/rules/gpu-hdr-and-tonemap.md +23 -0
- package/packs/gpu-painter/rules/gpu-picking-on-cpu.md +19 -0
- package/packs/gpu-painter/rules/gpu-render-lifecycle.md +25 -0
- package/packs/gpu-painter/rules/gpu-text-atlas.md +24 -0
- package/packs/gpu-painter/rules/gpu-travellers-from-snapshot.md +24 -0
- package/packs/gpu-painter/rules/hover-every-pressable.md +25 -0
- package/packs/gpu-painter/skills/gpu-capture/SKILL.md +15 -0
- package/packs/gpu-painter/skills/gpu-frame-bench/SKILL.md +14 -0
- package/packs/gpu-painter/skills/gpu-golden-check/SKILL.md +13 -0
- package/packs/gpu-painter/skills/gpu-golden-update/SKILL.md +16 -0
- package/packs/gpu-painter/skills/gpu-lifecycle-stress/SKILL.md +15 -0
- package/packs/gpu-painter/skills/hover-state/SKILL.md +33 -0
- package/packs/hook-proof/checks/hook-catch-must-not-allow.json +16 -0
- package/packs/hook-proof/checks/hook-command-no-pipe.json +16 -0
- package/packs/hook-proof/checks/hook-exit-1-does-not-block.json +17 -0
- package/packs/hook-proof/checks/hook-no-or-true.json +18 -0
- package/packs/hook-proof/checks/hook-refusal-on-stderr.json +17 -0
- package/packs/hook-proof/pack.json +38 -0
- package/packs/hook-proof/rules/a-refusal-is-exit-2.md +28 -0
- package/packs/hook-proof/skills/prove-a-hook/SKILL.md +21 -0
- package/packs/host-agent/checks/file-path-from-param.json +27 -0
- package/packs/host-agent/checks/integrity-check-optional.json +27 -0
- package/packs/host-agent/checks/quoted-value-into-config.json +24 -0
- package/packs/host-agent/checks/secret-on-argv.json +28 -0
- package/packs/host-agent/checks/ssh-verifies-host-key.json +27 -0
- package/packs/host-agent/checks/system-file-written-in-place.json +26 -0
- package/packs/host-agent/checks/tmp-path-predictable.json +27 -0
- package/packs/host-agent/pack.json +22 -0
- package/packs/host-agent/rules/root-on-other-machines.md +27 -0
- package/packs/html-ui/checks/email-html-escapes.json +25 -0
- package/packs/html-ui/checks/external-link-rel.json +21 -0
- package/packs/html-ui/checks/no-duplicate-escape.json +26 -0
- package/packs/html-ui/checks/no-inline-client-script.json +21 -0
- package/packs/html-ui/checks/no-inline-style.json +23 -0
- package/packs/html-ui/pack.json +33 -0
- package/packs/html-ui/rules/email-html-escapes.md +19 -0
- package/packs/html-ui/rules/server-html-escapes-everything.md +22 -0
- package/packs/http-api/checks/api-path-versioned.json +31 -0
- package/packs/http-api/checks/authz-from-request-body.json +26 -0
- package/packs/http-api/checks/client-calls-a-version.json +28 -0
- package/packs/http-api/checks/client-ip-not-leftmost-xff.json +28 -0
- package/packs/http-api/checks/cors-needs-origin.json +26 -0
- package/packs/http-api/checks/csp-not-switched-off.json +28 -0
- package/packs/http-api/checks/debug-route-not-shipped.json +26 -0
- package/packs/http-api/checks/encrypted-name-plaintext-value.json +26 -0
- package/packs/http-api/checks/err-text-stays-server-side.json +27 -0
- package/packs/http-api/checks/failure-is-not-empty.json +28 -0
- package/packs/http-api/checks/gate-is-not-a-todo.json +27 -0
- package/packs/http-api/checks/guard-fails-open.json +28 -0
- package/packs/http-api/checks/hmac-over-reserialised-body.json +26 -0
- package/packs/http-api/checks/jwt-verify-pins-algorithm.json +26 -0
- package/packs/http-api/checks/middleware-skips-without-user.json +26 -0
- package/packs/http-api/checks/next-api-route-versioned.json +47 -0
- package/packs/http-api/checks/no-security-off-switch.json +28 -0
- package/packs/http-api/checks/oauth-state-signed.json +26 -0
- package/packs/http-api/checks/one-time-code-compared-raw.json +26 -0
- package/packs/http-api/checks/query-cast-is-not-validation.json +28 -0
- package/packs/http-api/checks/queue-action-from-client.json +26 -0
- package/packs/http-api/checks/rate-limit-one-module.json +28 -0
- package/packs/http-api/checks/role-checked-in-one-guard.json +27 -0
- package/packs/http-api/checks/route-body-needs-schema.json +31 -0
- package/packs/http-api/checks/route-scopes-to-the-caller.json +31 -0
- package/packs/http-api/checks/secret-compared-constant-time-any.json +28 -0
- package/packs/http-api/checks/secret-in-job-record.json +27 -0
- package/packs/http-api/checks/server-fetches-tenant-url.json +30 -0
- package/packs/http-api/checks/short-code-needs-limit.json +26 -0
- package/packs/http-api/checks/user-url-through-safe-fetch.json +28 -0
- package/packs/http-api/checks/webhook-dedupes-event-id.json +30 -0
- package/packs/http-api/pack.json +45 -0
- package/packs/http-api/rules/adapters-one-db-gateway.md +18 -0
- package/packs/http-api/rules/apis-are-versioned.md +27 -0
- package/packs/http-api/rules/credentials-handled-safely.md +22 -0
- package/packs/http-api/rules/handlers-own-the-work.md +17 -0
- package/packs/http-api/rules/health-and-correlation.md +17 -0
- package/packs/http-api/rules/one-error-contract.md +17 -0
- package/packs/http-api/rules/routes-are-thin.md +17 -0
- package/packs/http-api/rules/routes-scope-to-the-caller.md +26 -0
- package/packs/http-api/rules/routes-validate-and-answer.md +25 -0
- package/packs/http-api/skills/change-an-api/SKILL.md +20 -0
- package/packs/http-api/skills/secure-a-route/SKILL.md +21 -0
- package/packs/instrument-shell/checks/no-raw-struct-blob.json +23 -0
- package/packs/instrument-shell/pack.json +22 -0
- package/packs/instrument-shell/rules/fold-keeps-every-route.md +24 -0
- package/packs/instrument-shell/rules/quiet-announces-itself.md +22 -0
- package/packs/instrument-shell/rules/render-the-extremes.md +25 -0
- package/packs/instrument-shell/rules/seams-are-declared.md +27 -0
- package/packs/instrument-shell/rules/session-blob-append-only.md +25 -0
- package/packs/instrument-shell/skills/gates-from-commit-one/SKILL.md +20 -0
- package/packs/instrument-shell/skills/hit-the-painted-control/SKILL.md +18 -0
- package/packs/js-ts/checks/async-callback-unguarded.json +26 -0
- package/packs/js-ts/checks/background-loop-needs-stop.json +28 -0
- package/packs/js-ts/checks/child-process-error-handler.json +28 -0
- package/packs/js-ts/checks/entry-registers-shutdown.json +31 -0
- package/packs/js-ts/checks/fetch-needs-timeout.json +30 -0
- package/packs/js-ts/checks/job-only-in-memory.json +28 -0
- package/packs/js-ts/checks/json-only-through-helper.json +29 -0
- package/packs/js-ts/checks/line-under-200-chars.json +34 -0
- package/packs/js-ts/checks/localhost-default-in-server.json +29 -0
- package/packs/js-ts/checks/no-any.json +27 -0
- package/packs/js-ts/checks/no-cast-escape-hatches.json +24 -0
- package/packs/js-ts/checks/no-console-in-app.json +31 -0
- package/packs/js-ts/checks/no-dynamic-import-node-builtin.json +25 -0
- package/packs/js-ts/checks/no-inline-binary.json +20 -0
- package/packs/js-ts/checks/no-inline-zod-outside-schemas.json +27 -0
- package/packs/js-ts/checks/no-local-sleep.json +25 -0
- package/packs/js-ts/checks/no-nested-ternary.json +20 -0
- package/packs/js-ts/checks/no-secret-in-log.json +24 -0
- package/packs/js-ts/checks/no-shell-string-interpolation.json +24 -0
- package/packs/js-ts/checks/no-swallowed-errors.json +25 -0
- package/packs/js-ts/checks/no-ts-enum.json +20 -0
- package/packs/js-ts/checks/process-env-only-in-config.json +31 -0
- package/packs/js-ts/checks/race-leaves-work-running.json +23 -0
- package/packs/js-ts/checks/reject-as-catch-all-exists.json +24 -0
- package/packs/js-ts/checks/secret-has-no-fallback.json +24 -0
- package/packs/js-ts/checks/secret-needs-crypto-random.json +24 -0
- package/packs/js-ts/checks/server-close-awaited.json +27 -0
- package/packs/js-ts/checks/session-user-typed-once.json +24 -0
- package/packs/js-ts/checks/switch-is-a-table.json +24 -0
- package/packs/js-ts/checks/test-imports-the-source.json +19 -0
- package/packs/js-ts/checks/test-name-says-behaviour.json +16 -0
- package/packs/js-ts/checks/tsconfig-flags.json +21 -0
- package/packs/js-ts/checks/void-needs-catch.json +24 -0
- package/packs/js-ts/checks/zod-string-needs-max.json +25 -0
- package/packs/js-ts/checks/zod-v4-formats.json +23 -0
- package/packs/js-ts/pack.json +84 -0
- package/packs/js-ts/rules/await-handled-at-a-boundary.md +66 -0
- package/packs/js-ts/rules/env-through-config.md +36 -0
- package/packs/js-ts/rules/errors-never-swallowed.md +33 -0
- package/packs/js-ts/rules/files-under-300-lines.md +18 -0
- package/packs/js-ts/rules/guard-clauses-over-nesting.md +34 -0
- package/packs/js-ts/rules/js-repeats-become-templates.md +26 -0
- package/packs/js-ts/rules/json-only-through-one-helper.md +62 -0
- package/packs/js-ts/rules/named-constants-not-magic-numbers.md +34 -0
- package/packs/js-ts/rules/no-any.md +34 -0
- package/packs/js-ts/rules/no-console.md +30 -0
- package/packs/js-ts/rules/no-floating-promises.md +31 -0
- package/packs/js-ts/rules/no-param-mutation.md +28 -0
- package/packs/js-ts/rules/no-unsafe-assertions.md +30 -0
- package/packs/js-ts/rules/one-logger.md +24 -0
- package/packs/js-ts/rules/outbound-calls-have-a-limit.md +20 -0
- package/packs/js-ts/rules/parallel-independent-awaits.md +29 -0
- package/packs/js-ts/rules/process-lifecycle.md +47 -0
- package/packs/js-ts/rules/schema-single-source-of-truth.md +36 -0
- package/packs/js-ts/rules/secrets-stay-secret.md +22 -0
- package/packs/js-ts/rules/small-functions.md +20 -0
- package/packs/js-ts/rules/test-names-describe-behavior.md +28 -0
- package/packs/js-ts/rules/tests-can-fail.md +19 -0
- package/packs/js-ts/rules/tsconfig-strict.md +32 -0
- package/packs/js-ts/rules/typed-exports.md +27 -0
- package/packs/js-ts/rules/types-once-at-the-edge.md +18 -0
- package/packs/js-ts/rules/unions-over-enums.md +29 -0
- package/packs/js-ts/rules/zod-at-route-boundaries.md +40 -0
- package/packs/midi/checks/active-sensing-no-pulse.json +24 -0
- package/packs/midi/checks/clock-not-at-sample-zero.json +23 -0
- package/packs/midi/checks/midi-realtime-first.json +27 -0
- package/packs/midi/checks/no-tempo-writeback.json +23 -0
- package/packs/midi/checks/position-not-integrated.json +25 -0
- package/packs/midi/checks/stub-playhead-advances.json +27 -0
- package/packs/midi/checks/sysex-length-literal.json +23 -0
- package/packs/midi/checks/sysex-not-on-audio.json +24 -0
- package/packs/midi/checks/sysex-survives-realtime.json +27 -0
- package/packs/midi/pack.json +22 -0
- package/packs/midi/rules/clock-is-a-pulse-stream.md +30 -0
- package/packs/midi/rules/imports-count-every-loss.md +25 -0
- package/packs/midi/rules/measure-the-clock-in-audio.md +30 -0
- package/packs/midi/rules/sync-is-a-mode.md +29 -0
- package/packs/midi/rules/sysex-is-a-record.md +29 -0
- package/packs/midi/skills/clock-probe/SKILL.md +23 -0
- package/packs/midi/skills/clock-probe/clock-law.md +417 -0
- package/packs/midi/skills/does-it-sync/SKILL.md +19 -0
- package/packs/mongo/checks/bulk-over-many.json +28 -0
- package/packs/mongo/checks/created-at-immutable.json +25 -0
- package/packs/mongo/checks/driver-outside-gateway.json +24 -0
- package/packs/mongo/checks/key-lookup-is-hashed.json +24 -0
- package/packs/mongo/checks/mongoclient-cached-and-named.json +34 -0
- package/packs/mongo/checks/mongoclient-outside-gateway.json +24 -0
- package/packs/mongo/checks/no-count-plus-one-ids.json +25 -0
- package/packs/mongo/checks/no-db-write-in-loop.json +25 -0
- package/packs/mongo/checks/no-drop-in-code.json +27 -0
- package/packs/mongo/checks/no-empty-deletemany.json +26 -0
- package/packs/mongo/checks/no-find-reads.json +26 -0
- package/packs/mongo/checks/no-input-spread-into-write.json +24 -0
- package/packs/mongo/checks/no-mongoose.json +23 -0
- package/packs/mongo/checks/no-negation-delete.json +26 -0
- package/packs/mongo/checks/no-non-null-after-findone.json +25 -0
- package/packs/mongo/checks/objectid-equals.json +26 -0
- package/packs/mongo/checks/update-then-reread.json +24 -0
- package/packs/mongo/checks/watch-not-poll.json +25 -0
- package/packs/mongo/pack.json +52 -0
- package/packs/mongo/rules/deletes-name-what-dies.md +21 -0
- package/packs/mongo/rules/driver-only-in-gateway.md +26 -0
- package/packs/mongo/rules/keys-hashed-input-picked.md +21 -0
- package/packs/mongo/rules/one-client-one-pool.md +32 -0
- package/packs/mongo/rules/reads-aggregate-writes-bulk.md +25 -0
- package/packs/mongo/rules/writes-are-atomic.md +27 -0
- package/packs/multi-tenant/checks/role-sees-all-tenants.json +26 -0
- package/packs/multi-tenant/checks/tenant-filter-from-url.json +25 -0
- package/packs/multi-tenant/pack.json +22 -0
- package/packs/multi-tenant/rules/no-role-crosses-a-tenant.md +21 -0
- package/packs/multi-tenant/skills/prove-tenant-isolation/SKILL.md +19 -0
- package/packs/nginx/checks/modsec-no-blanket-off.json +16 -0
- package/packs/nginx/checks/nginx-csp-no-unsafe.json +15 -0
- package/packs/nginx/checks/nginx-headers-always.json +15 -0
- package/packs/nginx/checks/nginx-keepalive-http11.json +20 -0
- package/packs/nginx/checks/nginx-logs-to-stdout.json +15 -0
- package/packs/nginx/checks/nginx-no-crlf.json +17 -0
- package/packs/nginx/checks/nginx-resolver-ttl.json +19 -0
- package/packs/nginx/pack.json +43 -0
- package/packs/nginx/rules/modsecurity-tuning.md +22 -0
- package/packs/nginx/rules/nginx-production.md +26 -0
- package/packs/nginx/skills/waf-rollout/SKILL.md +20 -0
- package/packs/python/checks/py-no-bare-except.json +18 -0
- package/packs/python/checks/py-no-eval.json +18 -0
- package/packs/python/checks/py-no-mutable-default.json +18 -0
- package/packs/python/checks/py-no-shell-true.json +18 -0
- package/packs/python/checks/py-no-star-import.json +18 -0
- package/packs/python/checks/py-no-swallowed-exception.json +18 -0
- package/packs/python/checks/py-none-by-is.json +18 -0
- package/packs/python/checks/py-open-with-with.json +18 -0
- package/packs/python/checks/py-requests-timeout.json +18 -0
- package/packs/python/checks/py-subprocess-output-checked.json +18 -0
- package/packs/python/checks/py-yaml-safe-load.json +18 -0
- package/packs/python/pack.json +26 -0
- package/packs/python/rules/python-errors-and-resources.md +26 -0
- package/packs/python/rules/python-repeats-become-templates.md +27 -0
- package/packs/python/skills/python-extract-template/SKILL.md +35 -0
- package/packs/react/checks/dialog-needs-role.json +28 -0
- package/packs/react/checks/effect-not-for-derived-state.json +24 -0
- package/packs/react/checks/icon-button-needs-name.json +24 -0
- package/packs/react/checks/label-needs-a-field.json +24 -0
- package/packs/react/checks/ui-failed-fetch-says-so.json +23 -0
- package/packs/react/checks/ui-ok-branch-has-an-else.json +23 -0
- package/packs/react/pack.json +20 -0
- package/packs/react/rules/react-accessible-controls.md +20 -0
- package/packs/react/rules/react-state-and-effects.md +23 -0
- package/packs/reverse-engineering/checks/ear-constant-tagged.json +23 -0
- package/packs/reverse-engineering/checks/no-default-on-distrust.json +24 -0
- package/packs/reverse-engineering/checks/no-rom-table-literal.json +29 -0
- package/packs/reverse-engineering/checks/prose-never-decides.json +22 -0
- package/packs/reverse-engineering/hooks/firmware-out-of-git.mjs +49 -0
- package/packs/reverse-engineering/pack.json +35 -0
- package/packs/reverse-engineering/rules/a-negative-names-what-was-scanned.md +19 -0
- package/packs/reverse-engineering/rules/account-every-term.md +20 -0
- package/packs/reverse-engineering/rules/addresses-name-their-space.md +21 -0
- package/packs/reverse-engineering/rules/every-law-has-a-source.md +18 -0
- package/packs/reverse-engineering/rules/findings-are-withdrawn-in-place.md +17 -0
- package/packs/reverse-engineering/rules/firmware-stays-out.md +18 -0
- package/packs/reverse-engineering/rules/names-before-code.md +19 -0
- package/packs/reverse-engineering/rules/reproduction-or-original.md +18 -0
- package/packs/reverse-engineering/rules/two-sources-before-naming.md +21 -0
- package/packs/reverse-engineering/skills/bank-census/SKILL.md +18 -0
- package/packs/reverse-engineering/skills/gather-sources/SKILL.md +21 -0
- package/packs/reverse-engineering/skills/menu-map/SKILL.md +28 -0
- package/packs/reverse-engineering/skills/names-first/SKILL.md +41 -0
- package/packs/reverse-engineering/skills/re-deliverables/SKILL.md +21 -0
- package/packs/reverse-engineering/skills/tripwire-the-law/SKILL.md +19 -0
- package/packs/reverse-engineering/tools/lib/unwrap.mjs +115 -0
- package/packs/reverse-engineering/tools/names-sweep.mjs +264 -0
- package/packs/shell/checks/sh-mktemp.json +18 -0
- package/packs/shell/checks/sh-no-backticks.json +18 -0
- package/packs/shell/checks/sh-no-eval.json +18 -0
- package/packs/shell/checks/sh-no-parse-ls.json +18 -0
- package/packs/shell/checks/sh-no-pipe-to-shell.json +18 -0
- package/packs/shell/checks/sh-no-program-in-heredoc.json +18 -0
- package/packs/shell/checks/sh-quote-arguments.json +18 -0
- package/packs/shell/checks/sh-rm-guarded.json +18 -0
- package/packs/shell/checks/sh-strict-mode.json +20 -0
- package/packs/shell/pack.json +28 -0
- package/packs/shell/rules/shell-repeats-become-templates.md +23 -0
- package/packs/shell/rules/shell-strict-and-quoted.md +27 -0
- package/packs/shell/skills/shell-extract-template/SKILL.md +32 -0
- package/packs/shell-hooks/checks/gnu-only-in-shell.json +18 -0
- package/packs/shell-hooks/checks/hook-command-anchored.json +12 -0
- package/packs/shell-hooks/checks/hook-json-by-tool.json +18 -0
- package/packs/shell-hooks/checks/no-bash-c-with-variable.json +20 -0
- package/packs/shell-hooks/pack.json +36 -0
- package/packs/shell-hooks/rules/hooks-portable-anchored-quoted.md +26 -0
- package/packs/sound-design/checks/audio-seed-fixed.json +23 -0
- package/packs/sound-design/checks/mix-is-a-crossfade.json +30 -0
- package/packs/sound-design/checks/no-hash-in-the-signal.json +30 -0
- package/packs/sound-design/checks/no-literal-key-anchor.json +30 -0
- package/packs/sound-design/checks/test-compares-a-function-with-itself.json +22 -0
- package/packs/sound-design/pack.json +22 -0
- package/packs/sound-design/rules/algorithms-are-data.md +26 -0
- package/packs/sound-design/rules/meter-before-engine.md +27 -0
- package/packs/sound-design/rules/neutral-is-exact.md +26 -0
- package/packs/sound-design/rules/test-off-the-easy-point.md +28 -0
- package/packs/sound-design/rules/unreachable-is-said.md +25 -0
- package/packs/sound-design/rules/waveforms-and-octaves.md +24 -0
- package/packs/sound-design/skills/choose-observable/SKILL.md +18 -0
- package/packs/sound-design/skills/measure-a-law/SKILL.md +18 -0
- package/packs/sound-design/skills/measure-reverb/SKILL.md +19 -0
- package/packs/sound-design/skills/spread-probe/SKILL.md +18 -0
- package/packs/stellix/checks/no-keyboard-focus.json +12 -0
- package/packs/stellix/checks/one-seeded-random.json +16 -0
- package/packs/stellix/checks/world-never-includes-painter.json +12 -0
- package/packs/stellix/checks/world-no-libm.json +15 -0
- package/packs/stellix/checks/world-no-unordered.json +10 -0
- package/packs/stellix/hooks/no-shipped-images.mjs +88 -0
- package/packs/stellix/pack.json +61 -0
- package/packs/stellix/rules/stellix-deterministic-world.md +29 -0
- package/packs/stellix/rules/stellix-reset-generated.md +24 -0
- package/packs/stellix/rules/stellix-world-snapshot.md +27 -0
- package/packs/stellix/rules/world-continuous-collision.md +26 -0
- package/packs/stellix/rules/world-fp-determinism.md +28 -0
- package/packs/stored-text/checks/no-raw-html-from-data.json +31 -0
- package/packs/stored-text/checks/stored-text-libs-only-in-renderer.json +31 -0
- package/packs/stored-text/checks/stored-text-renderer-complete.json +24 -0
- package/packs/stored-text/checks/stored-text-through-renderer.json +25 -0
- package/packs/stored-text/pack.json +41 -0
- package/packs/stored-text/rules/stored-text-renders-once.md +26 -0
- package/packs/stored-text/skills/render-stored-text/SKILL.md +24 -0
- package/packs/synth-creator/checks/timing-from-synthcore.json +24 -0
- package/packs/synth-creator/checks/ui-drawn-in-code.json +23 -0
- package/packs/synth-creator/hooks/build-guard.mjs +232 -0
- package/packs/synth-creator/hooks/build-sweep.mjs +166 -0
- package/packs/synth-creator/hooks/frozen-files.mjs +63 -0
- package/packs/synth-creator/hooks/idle-wake.mjs +90 -0
- package/packs/synth-creator/hooks/protect-vendor.mjs +174 -0
- package/packs/synth-creator/hooks/spec-lock.mjs +117 -0
- package/packs/synth-creator/hooks/stage-guard.mjs +50 -0
- package/packs/synth-creator/hooks/time-guard.mjs +292 -0
- package/packs/synth-creator/hooks/user-asks.mjs +165 -0
- package/packs/synth-creator/pack.json +136 -0
- package/packs/synth-creator/rules/copy-trees-read-only.md +25 -0
- package/packs/synth-creator/rules/debug-by-measurement.md +20 -0
- package/packs/synth-creator/rules/done-means-fresh-evidence.md +18 -0
- package/packs/synth-creator/rules/hooks-and-gates.md +21 -0
- package/packs/synth-creator/rules/long-work-in-the-background.md +16 -0
- package/packs/synth-creator/rules/timing-from-synthcore.md +16 -0
- package/packs/synth-creator/skills/build-step/SKILL.md +125 -0
- package/packs/synth-creator/skills/build-through-the-queue/SKILL.md +19 -0
- package/packs/synth-creator/tools/freeze.mjs +36 -0
- package/packs/tui/checks/tui-entry-restores-terminal.json +27 -0
- package/packs/tui/checks/tui-gates-on-tty.json +25 -0
- package/packs/tui/checks/tui-no-ris-reset.json +22 -0
- package/packs/tui/checks/tui-resize-listener-removed.json +26 -0
- package/packs/tui/checks/tui-width-is-state.json +33 -0
- package/packs/tui/pack.json +44 -0
- package/packs/tui/rules/tui-resize-and-screen.md +25 -0
- package/packs/tui/skills/build-tui/SKILL.md +21 -0
- package/packs/ui-craft/checks/ui-input-needs-autocomplete.json +23 -0
- package/packs/ui-craft/checks/ui-intl-for-dates.json +21 -0
- package/packs/ui-craft/checks/ui-no-ai-palette.json +22 -0
- package/packs/ui-craft/checks/ui-no-animate-layout.json +22 -0
- package/packs/ui-craft/checks/ui-no-assistant-palette.json +23 -0
- package/packs/ui-craft/checks/ui-no-bounce-easing.json +22 -0
- package/packs/ui-craft/checks/ui-no-custom-cursor.json +22 -0
- package/packs/ui-craft/checks/ui-no-emoji-as-ui.json +22 -0
- package/packs/ui-craft/checks/ui-no-empty-image.json +21 -0
- package/packs/ui-craft/checks/ui-no-eyebrow.json +21 -0
- package/packs/ui-craft/checks/ui-no-furniture-text.json +22 -0
- package/packs/ui-craft/checks/ui-no-gradient-text.json +22 -0
- package/packs/ui-craft/checks/ui-no-index-numbering.json +21 -0
- package/packs/ui-craft/checks/ui-no-lorem.json +22 -0
- package/packs/ui-craft/checks/ui-no-marketing-buzzword.json +22 -0
- package/packs/ui-craft/checks/ui-no-paste-block.json +21 -0
- package/packs/ui-craft/checks/ui-no-placeholder-names.json +21 -0
- package/packs/ui-craft/checks/ui-no-scroll-hijack.json +21 -0
- package/packs/ui-craft/checks/ui-no-side-tab.json +21 -0
- package/packs/ui-craft/checks/ui-no-stock-labels.json +22 -0
- package/packs/ui-craft/checks/ui-no-transition-all.json +22 -0
- package/packs/ui-craft/checks/ui-no-uppercase-table-header.json +21 -0
- package/packs/ui-craft/checks/ui-no-zebra-rows.json +22 -0
- package/packs/ui-craft/checks/ui-no-zoom-lock.json +21 -0
- package/packs/ui-craft/pack.json +43 -0
- package/packs/ui-craft/rules/apps-are-not-pages.md +26 -0
- package/packs/ui-craft/rules/data-tells-the-truth.md +26 -0
- package/packs/ui-craft/rules/dates-and-numbers.md +18 -0
- package/packs/ui-craft/rules/forms-never-fight.md +22 -0
- package/packs/ui-craft/rules/interface-copy.md +26 -0
- package/packs/ui-craft/rules/motion-is-rare.md +31 -0
- package/packs/ui-craft/rules/no-generated-look.md +37 -0
- package/packs/ui-craft/rules/page-holds-its-frame.md +28 -0
- package/packs/ui-craft/rules/page-proved-rendered.md +19 -0
- package/packs/ui-craft/rules/pictures-do-a-job.md +25 -0
- package/packs/ui-craft/rules/pointer-feedback.md +28 -0
- package/packs/ui-craft/rules/screen-answers-one-question.md +24 -0
- package/packs/ui-craft/rules/survives-real-data.md +23 -0
- package/packs/ui-craft/rules/touch-and-small-screens.md +19 -0
- package/packs/ui-craft/rules/type-space-colour.md +26 -0
- package/packs/ui-craft/rules/url-holds-the-state.md +19 -0
- package/packs/ui-craft/skills/app-screen/SKILL.md +33 -0
- package/packs/ui-craft/skills/build-from-reference/SKILL.md +28 -0
- package/packs/ui-craft/skills/chart-choice/SKILL.md +34 -0
- package/packs/ui-craft/skills/hover-state/SKILL.md +28 -0
- package/packs/ui-craft/skills/page-critique/SKILL.md +33 -0
- package/packs/ui-craft/skills/prove-page/SKILL.md +23 -0
- package/packs/ui-craft/skills/redesign-page/SKILL.md +19 -0
- package/packs/ui-craft/skills/ui-code-review/SKILL.md +22 -0
- package/packs/ui-craft/skills/write-the-page/SKILL.md +21 -0
- package/packs/ui-craft/tools/page-measure.mjs +41 -0
- package/packs/web/checks/a11y-img-needs-alt.json +26 -0
- package/packs/web/checks/a11y-no-bare-outline-none.json +21 -0
- package/packs/web/checks/a11y-no-clickable-div.json +26 -0
- package/packs/web/checks/a11y-no-positive-tabindex.json +26 -0
- package/packs/web/checks/client-no-api-key.json +29 -0
- package/packs/web/checks/client-no-browser-global-at-module-scope.json +28 -0
- package/packs/web/checks/client-no-server-import.json +31 -0
- package/packs/web/checks/client-no-window-location-nav.json +28 -0
- package/packs/web/checks/css-no-inline-style.json +30 -0
- package/packs/web/checks/ds-pages-compose-primitives.json +28 -0
- package/packs/web/checks/key-from-index.json +23 -0
- package/packs/web/checks/prodbuild-no-cdn-runtime-deps.json +21 -0
- package/packs/web/checks/prodbuild-no-dev-flags.json +21 -0
- package/packs/web/checks/prodbuild-no-remote-fonts.json +22 -0
- package/packs/web/checks/rcss-button-cursor.json +30 -0
- package/packs/web/checks/rcss-no-100vw.json +21 -0
- package/packs/web/checks/rcss-no-fixed-wide-width.json +21 -0
- package/packs/web/checks/rcss-viewport-meta.json +28 -0
- package/packs/web/checks/secret-not-in-web-storage.json +25 -0
- package/packs/web/checks/tw-no-raw-hex-in-markup.json +34 -0
- package/packs/web/checks/wp-hero-not-lazy.json +27 -0
- package/packs/web/checks/wp-img-needs-dimensions.json +26 -0
- package/packs/web/pack.json +73 -0
- package/packs/web/rules/accessibility.md +26 -0
- package/packs/web/rules/client-boundaries.md +23 -0
- package/packs/web/rules/production-build.md +22 -0
- package/packs/web/rules/secrets-not-in-the-browser.md +18 -0
- package/packs/web/rules/styles-live-in-stylesheets.md +23 -0
- package/packs/web/rules/tailwind-v4.md +23 -0
- package/packs/web/rules/ui-primitives-one-module.md +30 -0
- package/packs/web/rules/web-performance.md +21 -0
- package/packs/web/skills/design-direction/SKILL.md +30 -0
- package/packs/web/skills/design-review/SKILL.md +28 -0
- package/packs/web/skills/pick-rendering-mode/SKILL.md +21 -0
- package/packs/web/skills/preflight-build/SKILL.md +23 -0
- package/packs/web/skills/seo-audit/SKILL.md +22 -0
- package/packs/websocket/checks/no-token-in-query.json +26 -0
- package/packs/websocket/checks/stale-socket-deletes-new-entry.json +25 -0
- package/packs/websocket/checks/ws-identity-from-message.json +26 -0
- package/packs/websocket/pack.json +21 -0
- package/packs/websocket/rules/identity-comes-from-the-connection.md +24 -0
- package/packs/writing/checks/ascii-no-em-dash.json +17 -0
- package/packs/writing/checks/no-copula-dodging.json +18 -0
- package/packs/writing/checks/no-dramatic-colon.json +18 -0
- package/packs/writing/checks/no-not-x-but-y.json +18 -0
- package/packs/writing/checks/no-participial-opener.json +18 -0
- package/packs/writing/checks/no-pseudo-wisdom.json +18 -0
- package/packs/writing/checks/no-slop-words.json +18 -0
- package/packs/writing/checks/no-stock-connectors.json +18 -0
- package/packs/writing/checks/no-time-or-date.json +27 -0
- package/packs/writing/checks/no-trailing-ing.json +18 -0
- package/packs/writing/checks/no-vague-attribution.json +18 -0
- package/packs/writing/pack.json +43 -0
- package/packs/writing/rules/ascii-no-em-dash.md +21 -0
- package/packs/writing/rules/cut-the-padding.md +20 -0
- package/packs/writing/rules/direct-voice.md +22 -0
- package/packs/writing/rules/no-cargo-cult.md +16 -0
- package/packs/writing/rules/no-scaffolding.md +19 -0
- package/packs/writing/rules/no-stock-language.md +27 -0
- package/packs/writing/rules/no-time-or-date.md +18 -0
- package/packs/writing/rules/rhythm-like-talk.md +20 -0
- package/packs/writing/rules/write-from-your-own-corner.md +20 -0
- package/packs/writing/skills/argument-post/SKILL.md +28 -0
- package/packs/writing/skills/humanize/SKILL.md +28 -0
- package/packs/writing/skills/launch-post/SKILL.md +38 -0
- package/packs/writing/skills/pick-subreddit/SKILL.md +69 -0
- package/packs/writing/skills/post-voice/SKILL.md +22 -0
- package/packs/writing/skills/reddit-post/SKILL.md +63 -0
- package/packs/writing/skills/reddit-title/SKILL.md +23 -0
- package/packs/writing/skills/reply-moves/SKILL.md +40 -0
- package/packs/writing/skills/reply-stance/SKILL.md +23 -0
- package/packs/writing/skills/should-i-reply/SKILL.md +21 -0
- package/packs/zod/hooks/schemas-only.mjs +53 -0
- package/packs/zod/pack.json +44 -0
- package/packs/zod/rules/env-shapes-only.md +14 -0
- package/packs/zod/rules/zod-4-schemas.md +14 -0
- package/profiles/stellix.layout.json +315 -0
- package/profiles/sub37.layout.json +247 -0
- package/prompts/scan-review.md +40 -0
- package/prompts/survey.md +82 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Locks parameter IDs: once seen, an ID may never disappear from the source.
|
|
3
|
+
// node param-id-lock.mjs --init create .claude/param-ids.lock.json from the current repo
|
|
4
|
+
// (as PostToolUse hook) fail (exit 2) if a locked ID is gone; add new IDs to the lock. Every route that
|
|
5
|
+
// writes is judged (Write, Edit, MultiEdit, NotebookEdit, and the shell's >, >>, tee,
|
|
6
|
+
// sed -i, cp, mv, rm, a heredoc; lib/writes.mjs): an id deleted by `sed -i` is gone too.
|
|
7
|
+
// node param-id-lock.mjs --selftest proves it
|
|
8
|
+
// Where IDs are read: .claude/param-ids.config.json, else layout.json "paramIds", else JUCE
|
|
9
|
+
// ParameterID / AudioParameter* string literals. Both forms: { "extensions": "<regex>", "patterns": ["<regex with one group>"] }.
|
|
10
|
+
// A file is judged in its own checkout: an agent worktree is scanned, and keeps its lock, on its own.
|
|
11
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
12
|
+
import { dirname, join, relative } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { readLayout } from './lib/layout.mjs';
|
|
15
|
+
import { checkoutRoot, claudeRoot, insideProject } from './lib/project.mjs';
|
|
16
|
+
import { writesOf } from './lib/writes.mjs';
|
|
17
|
+
import { put, runHook, scratchProject, verdicts, writeOf } from './lib/selftest.mjs';
|
|
18
|
+
import { asHook, isMain } from './lib/hook-log.mjs';
|
|
19
|
+
|
|
20
|
+
const ROOT = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
21
|
+
// .claude is skipped so the worktrees under .claude/worktrees/ never stand in for this checkout's code.
|
|
22
|
+
const SKIP_DIRS = /(^|\/)(build|Builds|JuceLibraryCode|JUCE|node_modules|\.git|\.claude|cmake-build[^/]*)(\/|$)/;
|
|
23
|
+
|
|
24
|
+
const DEFAULT_PATTERNS = [
|
|
25
|
+
'ParameterID\\s*(?:[A-Za-z_]\\w*\\s*)?[({]\\s*"([^"]+)"',
|
|
26
|
+
'AudioParameter(?:Float|Int|Bool|Choice)\\s*>?\\s*\\(\\s*"([^"]+)"',
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
function loadConfig(root) {
|
|
30
|
+
const file = join(root, '.claude', 'param-ids.config.json');
|
|
31
|
+
const cfg = existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : readLayout(root).paramIds ?? {};
|
|
32
|
+
return {
|
|
33
|
+
extensions: new RegExp(cfg.extensions ?? '\\.(cpp|h|hpp|cc|mm)$'),
|
|
34
|
+
patterns: (cfg.patterns ?? DEFAULT_PATTERNS).map((p) => new RegExp(p, 'g')),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function collectIds(root, { extensions, patterns }) {
|
|
39
|
+
const ids = new Set();
|
|
40
|
+
for (const entry of readdirSync(root, { recursive: true })) {
|
|
41
|
+
const rel = String(entry);
|
|
42
|
+
if (SKIP_DIRS.test(rel) || !extensions.test(rel)) continue;
|
|
43
|
+
const text = readFileSync(join(root, rel), 'utf8');
|
|
44
|
+
for (const re of patterns) {
|
|
45
|
+
re.lastIndex = 0;
|
|
46
|
+
let m;
|
|
47
|
+
while ((m = re.exec(text)) !== null) ids.add(m[1]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return ids;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const lockFile = (root) => join(root, '.claude', 'param-ids.lock.json');
|
|
54
|
+
const save = (root, ids) => writeFileSync(lockFile(root), JSON.stringify([...ids].sort(), null, 2) + '\n');
|
|
55
|
+
|
|
56
|
+
function main(text) {
|
|
57
|
+
if (process.argv.includes('--init')) {
|
|
58
|
+
const ids = collectIds(ROOT, loadConfig(ROOT));
|
|
59
|
+
save(ROOT, ids);
|
|
60
|
+
console.log(`Locked ${ids.size} parameter IDs in ${relative(ROOT, lockFile(ROOT))}`);
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let payload = {};
|
|
65
|
+
try {
|
|
66
|
+
payload = JSON.parse(text || '{}');
|
|
67
|
+
} catch {
|
|
68
|
+
// run by hand without stdin
|
|
69
|
+
}
|
|
70
|
+
// Run by hand (no tool): the main checkout. Otherwise every checkout a write of an id file landed in.
|
|
71
|
+
const files = payload.tool_name ? writesOf(payload).map((w) => w.path).filter((f) => insideProject(f)) : [null];
|
|
72
|
+
const seen = new Set();
|
|
73
|
+
for (const file of files) {
|
|
74
|
+
const root = file ? checkoutRoot(file) : ROOT;
|
|
75
|
+
if (seen.has(root)) continue;
|
|
76
|
+
const config = loadConfig(file ? claudeRoot(file) : ROOT);
|
|
77
|
+
if (file && !config.extensions.test(file)) continue; // not a file ids are written in
|
|
78
|
+
seen.add(root);
|
|
79
|
+
const code = judge(root, config);
|
|
80
|
+
if (code) return code;
|
|
81
|
+
}
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The checkout's own lock only: main's lock may hold ids a worktree branch never had.
|
|
86
|
+
function judge(root, config) {
|
|
87
|
+
if (!existsSync(lockFile(root))) return 0;
|
|
88
|
+
const current = collectIds(root, config);
|
|
89
|
+
|
|
90
|
+
const locked = new Set(JSON.parse(readFileSync(lockFile(root), 'utf8')));
|
|
91
|
+
const missing = [...locked].filter((id) => !current.has(id));
|
|
92
|
+
if (missing.length > 0) {
|
|
93
|
+
process.stderr.write(
|
|
94
|
+
`Parameter IDs removed or renamed: ${missing.join(', ')}\n` +
|
|
95
|
+
'IDs never change once assigned (saved patches and host automation use them). ' +
|
|
96
|
+
'Restore them; if a control changed meaning, add a NEW ID and migrate old patches in setStateInformation. ' +
|
|
97
|
+
'See .claude/rules/parameter-ids-never-change.md\n',
|
|
98
|
+
);
|
|
99
|
+
return 2;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const added = [...current].filter((id) => !locked.has(id));
|
|
103
|
+
if (added.length > 0) save(root, new Set([...locked, ...added]));
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function selftest() {
|
|
108
|
+
const hook = fileURLToPath(import.meta.url);
|
|
109
|
+
const params = (...ids) => ids.map((id) => `auto p_${id} = juce::ParameterID { "${id}", 1 };`).join('\n') + '\n';
|
|
110
|
+
const dir = scratchProject({ 'src/params/Params.h': params('cutoff', 'res') }, { folders: {}, concepts: {} });
|
|
111
|
+
const unlocked = scratchProject({ 'src/params/Params.h': params('cutoff') });
|
|
112
|
+
const file = join(dir, 'src/params/Params.h');
|
|
113
|
+
const post = (text) => (put(file, text), runHook(hook, dir, writeOf(file, text)));
|
|
114
|
+
const initStatus = runHook(hook, dir, null, ['--init']);
|
|
115
|
+
const locked = () => JSON.parse(readFileSync(join(dir, '.claude/param-ids.lock.json'), 'utf8'));
|
|
116
|
+
const cases = [
|
|
117
|
+
['--init writes the lock', initStatus === 0 && locked().join() === 'cutoff,res', true],
|
|
118
|
+
['an id removed', post(params('cutoff')), 2],
|
|
119
|
+
['an id renamed', post(params('cutoff', 'resonance')), 2],
|
|
120
|
+
['an id added', post(params('cutoff', 'res', 'drive')), 0],
|
|
121
|
+
['the new id joins the lock', locked().includes('drive'), true],
|
|
122
|
+
['a project with no lock', runHook(hook, unlocked, writeOf(join(unlocked, 'src/params/Params.h'))), 0],
|
|
123
|
+
['another project is not ours', runHook(hook, dir, writeOf(join(dirname(dir), 'elsewhere/Params.h'))), 0],
|
|
124
|
+
];
|
|
125
|
+
return verdicts('param-id-lock', cases);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const hook = main; // run-hooks.mjs calls it with the event's text (KWB-24)
|
|
129
|
+
if (isMain(import.meta.url)) process.exit(process.argv.includes('--selftest') ? selftest() : process.argv.includes('--init') ? main('') : await asHook('param-id-lock', main));
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PreToolUse hook (Write|Edit|MultiEdit|NotebookEdit|Bash, every route: lib/writes.mjs): blocks writes that ADD realtime-unsafe code to
|
|
3
|
+
// audio-thread functions in C++ files. Exit 2 = block, stderr goes back to Claude. `--selftest` proves it.
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { writesOf } from './lib/writes.mjs';
|
|
6
|
+
import { findViolations, violationKey } from './lib/realtime-checks.mjs';
|
|
7
|
+
import { insideProject } from './lib/project.mjs';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
10
|
+
import { editOf, runHook, scratchProject, verdicts, writeOf } from './lib/selftest.mjs';
|
|
11
|
+
import { asHook, isMain } from './lib/hook-log.mjs';
|
|
12
|
+
|
|
13
|
+
const CPP = /\.(cpp|cc|cxx|h|hh|hpp|mm)$/;
|
|
14
|
+
|
|
15
|
+
function main(text) {
|
|
16
|
+
let payload;
|
|
17
|
+
try {
|
|
18
|
+
payload = JSON.parse(text);
|
|
19
|
+
} catch {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
for (const w of writesOf(payload)) {
|
|
23
|
+
if (w.after === null || !CPP.test(w.path) || !insideProject(w.path)) continue;
|
|
24
|
+
const code = judge(w.path, w);
|
|
25
|
+
if (code) return code;
|
|
26
|
+
}
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function judge(file, result) {
|
|
31
|
+
const input = { file_path: file };
|
|
32
|
+
|
|
33
|
+
const existing = new Set(findViolations(result.before).map(violationKey));
|
|
34
|
+
const added = findViolations(result.after).filter((v) => !existing.has(violationKey(v)));
|
|
35
|
+
if (added.length === 0) return 0;
|
|
36
|
+
|
|
37
|
+
const lines = added.slice(0, 12).map((v) => ` line ${v.line} in ${v.func}(): ${v.why}\n ${v.text}`);
|
|
38
|
+
const more = added.length > 12 ? `\n ...and ${added.length - 12} more` : '';
|
|
39
|
+
process.stderr.write(
|
|
40
|
+
`BLOCKED by realtime-guard: this edit adds realtime-unsafe code to audio-thread functions in ${input.file_path}\n` +
|
|
41
|
+
`${lines.join('\n')}${more}\n\n` +
|
|
42
|
+
'Fix: pre-allocate in prepareToPlay(), cache parameter pointers in the constructor, hand data to the UI via atomics/AbstractFifo + Timer.\n' +
|
|
43
|
+
'If a line is a deliberate safe exception, end it with `// rt-ok: <reason>`.\n' +
|
|
44
|
+
'See .claude/rules/audio-thread-realtime-safe.md.\n',
|
|
45
|
+
);
|
|
46
|
+
return 2;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function selftest() {
|
|
50
|
+
const hook = fileURLToPath(import.meta.url);
|
|
51
|
+
const block = (body) => `void Voice::processBlock (juce::AudioBuffer<float>& b, juce::MidiBuffer& m)\n{\n juce::ScopedNoDenormals nd;\n${body}\n}\n`;
|
|
52
|
+
const old = block(' auto* x = new float[64]; // legacy');
|
|
53
|
+
const dir = scratchProject({ 'src/audio/Old.cpp': old });
|
|
54
|
+
const w = (file, body) => runHook(hook, dir, writeOf(join(dir, file), block(body)));
|
|
55
|
+
return verdicts('realtime-guard', [
|
|
56
|
+
['new in processBlock', w('src/audio/Voice.cpp', ' auto* x = new float[64];'), 2],
|
|
57
|
+
['a lock in processBlock', w('src/audio/Voice.cpp', ' const juce::ScopedLock sl (lock);'), 2],
|
|
58
|
+
['plain arithmetic', w('src/audio/Voice.cpp', ' b.applyGain (0.5f);'), 0],
|
|
59
|
+
['an rt-ok exception', w('src/audio/Voice.cpp', ' auto* x = new float[64]; // rt-ok: test only'), 0],
|
|
60
|
+
['a fault already there is not added', runHook(hook, dir, editOf(join(dir, 'src/audio/Old.cpp'), 'ScopedNoDenormals nd;', 'ScopedNoDenormals noDenormals;')), 0],
|
|
61
|
+
['not C++', runHook(hook, dir, writeOf(join(dir, 'tools/x.py'), 'x = [1]\n')), 0],
|
|
62
|
+
['another project is not ours', runHook(hook, dir, writeOf(join(dirname(dir), 'elsewhere/Voice.cpp'), block(' auto* x = new float[64];'))), 0],
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const hook = main; // run-hooks.mjs calls it with the event's text (KWB-24)
|
|
67
|
+
if (isMain(import.meta.url)) process.exit(process.argv.includes('--selftest') ? selftest() : await asHook('realtime-guard', main));
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "audio-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Any JUCE synth or effect: realtime safety, DSP quality, state, parameters, performance.",
|
|
5
|
+
"type": "stock",
|
|
6
|
+
"author": "claude-packs",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/TheDecipherist/claude-packs",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/TheDecipherist/claude-packs.git",
|
|
12
|
+
"directory": "packs/audio-core"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"juce",
|
|
16
|
+
"audio",
|
|
17
|
+
"dsp"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"claude-packs": ">=0.19.0"
|
|
21
|
+
},
|
|
22
|
+
"synth": true,
|
|
23
|
+
"folders": {
|
|
24
|
+
"app": {
|
|
25
|
+
"path": "src/app",
|
|
26
|
+
"purpose": "plugin and standalone entry, processor shell, editor shell"
|
|
27
|
+
},
|
|
28
|
+
"audio": {
|
|
29
|
+
"path": "src/audio",
|
|
30
|
+
"purpose": "audio-thread code: block processing, voices, note ledger, parameter snapshot"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"path": "src/engines",
|
|
34
|
+
"purpose": "sound engines (one folder per oscillator kind)"
|
|
35
|
+
},
|
|
36
|
+
"dsp": {
|
|
37
|
+
"path": "src/dsp",
|
|
38
|
+
"purpose": "filters, effects, dynamics and shared DSP blocks"
|
|
39
|
+
},
|
|
40
|
+
"params": {
|
|
41
|
+
"path": "src/params",
|
|
42
|
+
"purpose": "parameter definitions, IDs, patches, presets, state load and save"
|
|
43
|
+
},
|
|
44
|
+
"bench": {
|
|
45
|
+
"path": "bench",
|
|
46
|
+
"purpose": "benchmarks (release build, worst block)"
|
|
47
|
+
},
|
|
48
|
+
"data": {
|
|
49
|
+
"path": "data",
|
|
50
|
+
"purpose": "factory bank (factory.csv), params.csv, records and derived tables"
|
|
51
|
+
},
|
|
52
|
+
"panel": {
|
|
53
|
+
"path": "panel",
|
|
54
|
+
"purpose": "panel.json, bindings.json and the theme (rendered by synthpanel-creator)"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"concepts": {
|
|
58
|
+
"audio": [
|
|
59
|
+
"audio",
|
|
60
|
+
"app"
|
|
61
|
+
],
|
|
62
|
+
"dsp": [
|
|
63
|
+
"dsp",
|
|
64
|
+
"engines"
|
|
65
|
+
],
|
|
66
|
+
"params": [
|
|
67
|
+
"params"
|
|
68
|
+
],
|
|
69
|
+
"ui": [
|
|
70
|
+
"app"
|
|
71
|
+
],
|
|
72
|
+
"bench": [
|
|
73
|
+
"bench"
|
|
74
|
+
],
|
|
75
|
+
"presets": [
|
|
76
|
+
"data/factory.csv",
|
|
77
|
+
"data/params.csv",
|
|
78
|
+
"presets/**",
|
|
79
|
+
"banks/**"
|
|
80
|
+
],
|
|
81
|
+
"panel-spec": [
|
|
82
|
+
"panel",
|
|
83
|
+
"**/bindings.json"
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
"skillsIn": null,
|
|
87
|
+
"hooks": {
|
|
88
|
+
"PreToolUse": [
|
|
89
|
+
{
|
|
90
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|Bash",
|
|
91
|
+
"hooks": [
|
|
92
|
+
{
|
|
93
|
+
"type": "command",
|
|
94
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/realtime-guard.mjs\"",
|
|
95
|
+
"timeout": 10
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"PostToolUse": [
|
|
101
|
+
{
|
|
102
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|Bash",
|
|
103
|
+
"hooks": [
|
|
104
|
+
{
|
|
105
|
+
"type": "command",
|
|
106
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/param-id-lock.mjs\"",
|
|
107
|
+
"timeout": 20
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
"kinds": {
|
|
114
|
+
"audio-entry": {
|
|
115
|
+
"what": "processBlock, voices, voice allocation, the note ledger, the parameter snapshot",
|
|
116
|
+
"in": "audio",
|
|
117
|
+
"concepts": [
|
|
118
|
+
"audio",
|
|
119
|
+
"dsp",
|
|
120
|
+
"tests"
|
|
121
|
+
],
|
|
122
|
+
"content": "\\b(processBlock|renderNextBlock|getNextAudioBlock)\\s*\\("
|
|
123
|
+
},
|
|
124
|
+
"dsp-block": {
|
|
125
|
+
"what": "a filter, effect, dynamics stage or shared DSP block (one folder per block)",
|
|
126
|
+
"in": "dsp"
|
|
127
|
+
},
|
|
128
|
+
"engine": {
|
|
129
|
+
"what": "an oscillator or sound engine (one folder per kind)",
|
|
130
|
+
"in": "engines"
|
|
131
|
+
},
|
|
132
|
+
"params": {
|
|
133
|
+
"what": "parameter IDs and layout, patch and state load/save",
|
|
134
|
+
"in": "params",
|
|
135
|
+
"concepts": [
|
|
136
|
+
"params"
|
|
137
|
+
],
|
|
138
|
+
"files": [
|
|
139
|
+
"**/*ParameterIDs.*",
|
|
140
|
+
"**/*Params.h",
|
|
141
|
+
"**/*Params.cpp",
|
|
142
|
+
"**/*Parameters.h",
|
|
143
|
+
"**/*Parameters.cpp"
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
"editor": {
|
|
147
|
+
"what": "the plugin and standalone entry, processor shell, editor and UI components",
|
|
148
|
+
"in": "app",
|
|
149
|
+
"concepts": [
|
|
150
|
+
"ui",
|
|
151
|
+
"painter",
|
|
152
|
+
"app",
|
|
153
|
+
"tests"
|
|
154
|
+
],
|
|
155
|
+
"content": "\\bvoid\\s+(?:\\w+::)*paint\\s*\\(\\s*(?:juce::)?Graphics\\b",
|
|
156
|
+
"contentWas": [
|
|
157
|
+
"\\bvoid\\s+paint\\s*\\(\\s*(juce::)?Graphics\\b"
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
"bank": {
|
|
161
|
+
"what": "the factory bank and the parameter table",
|
|
162
|
+
"in": "data",
|
|
163
|
+
"concepts": [
|
|
164
|
+
"presets"
|
|
165
|
+
],
|
|
166
|
+
"files": [
|
|
167
|
+
"**/factory.csv",
|
|
168
|
+
"**/params.csv"
|
|
169
|
+
]
|
|
170
|
+
},
|
|
171
|
+
"panel": {
|
|
172
|
+
"what": "the panel spec, bindings and theme",
|
|
173
|
+
"in": "panel",
|
|
174
|
+
"concepts": [
|
|
175
|
+
"panel-spec"
|
|
176
|
+
],
|
|
177
|
+
"files": [
|
|
178
|
+
"**/panel.json",
|
|
179
|
+
"**/bindings.json"
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
"bench": {
|
|
183
|
+
"what": "benchmarks (Release, worst block)",
|
|
184
|
+
"in": "bench"
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: audio
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# The audio thread never allocates, locks, waits or does I/O
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Allocate every buffer, delay line, voice and table in `prepareToPlay()` (or the constructor), sized for the worst case.
|
|
12
|
+
- Treat everything `processBlock()` calls (`renderNextBlock`, voice code, `processSample`, effect `process`) as audio-thread code too.
|
|
13
|
+
- Mark audio-thread functions outside the standard names with `[[clang::nonblocking]]`, so both the hook and RealtimeSanitizer cover them.
|
|
14
|
+
- Write `// rt-ok: <reason>` at the end of a line that is a deliberate, safe exception (e.g. `setSize(..., avoidReallocating = true)` within reserved capacity).
|
|
15
|
+
|
|
16
|
+
Never do (inside audio-thread code):
|
|
17
|
+
- `new`, `delete`, `malloc`, `free`, `make_unique`, `make_shared` (placement `new (ptr) T` is fine).
|
|
18
|
+
- Container growth: `push_back`, `emplace_back`, `insert`, `resize`, `reserve`, `assign`.
|
|
19
|
+
- Locks or waits: `ScopedLock`, `CriticalSection`, `std::mutex`, `lock_guard`, `unique_lock`, `scoped_lock`, condition variables, `sleep`.
|
|
20
|
+
- I/O or logging: `File`, streams, `fopen`, `DBG`, `std::cout`, `printf`, `Logger`.
|
|
21
|
+
- Building strings: `juce::String`, `std::string`, `std::to_string`.
|
|
22
|
+
- `throw`.
|
|
23
|
+
</constraints>
|
|
24
|
+
|
|
25
|
+
## Check
|
|
26
|
+
- **Hook (blocks the edit):** `.claude/hooks/realtime-guard.mjs` scans the bodies of `processBlock`, `processBlockBypassed`, `renderNextBlock`, `processSample` and every `[[clang::nonblocking]]` function. It blocks only violations the edit *adds*, so existing code doesn't stall unrelated work.
|
|
27
|
+
- **Runtime (catches what grep can't, such as allocations inside called functions):** build a debug standalone with Clang's RealtimeSanitizer (`-fsanitize=realtime`, LLVM 20+). It aborts with a stack trace on any allocation or lock inside a `nonblocking` function. Xcode's Apple clang does not support it, so on macOS use Homebrew LLVM for that debug build (or the rtsan standalone library, which its authors describe as fragile).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: audio, ui
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Audio and UI threads talk only through atomics and lock-free FIFOs
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- UI → audio: write plain values to `std::atomic<T>` (with `is_always_lock_free` true), or go through the parameter system.
|
|
12
|
+
- Audio → UI (meters, playheads, matrix position, scope data): the audio thread writes atomics or pushes into a pre-sized `juce::AbstractFifo` ring; a `juce::Timer` on the message thread polls and repaints.
|
|
13
|
+
- Pass complex objects (a rebuilt wavetable, a new route list) by building them on the message thread and handing over a pointer through a lock-free swap or FIFO. Free the old one on the message thread.
|
|
14
|
+
|
|
15
|
+
Never do:
|
|
16
|
+
- Call `repaint()`, touch the editor, `getActiveEditor()`, `MessageManager`, `callAsync`, `sendChangeMessage()` or `triggerAsyncUpdate()` from the audio thread. `triggerAsyncUpdate()` posts to the OS message queue when an update isn't already pending, and that path isn't guaranteed lock- or allocation-free.
|
|
17
|
+
- Share a `std::vector`, `juce::Array` or `ValueTree` between threads where one side may modify it.
|
|
18
|
+
</constraints>
|
|
19
|
+
|
|
20
|
+
## Check
|
|
21
|
+
The realtime-guard hook flags these UI and message calls inside audio-thread bodies. For cross-thread container sharing, use ThreadSanitizer in a debug build (`-fsanitize=thread`), which reports the data race at runtime.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: audio, ui
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# A thread or process boundary is tested from both sides at once
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- For every handoff between the audio thread and the UI (lock-free FIFO, snapshot ring, atomics), write at least one test that runs both sides together: the audio side publishes, and the test asserts the UI side observes exactly that (value, order, no drops at the stated rate).
|
|
12
|
+
- Do the same for anything that crosses a process (a render probe the test spawns, a plugin host): assert the parent sees what the child recorded.
|
|
13
|
+
|
|
14
|
+
Never do:
|
|
15
|
+
- Count two one-sided tests (the producer writes, the consumer reads a fake) as covering the boundary. That is how a flag set on one side never reaches the other.
|
|
16
|
+
</constraints>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: build
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Build flags: warnings are errors, no fast-math
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Build your own targets with `-Wall -Wextra -Wpedantic -Werror` (not JUCE's modules, which aren't warning-clean). Use `juce::juce_recommended_warning_flags` plus `-Werror` on your own sources.
|
|
12
|
+
- Keep sanitizer builds as presets: ASan + UBSan, TSan, and an RTSan debug standalone built with Homebrew LLVM 20+ (Apple clang has no RealtimeSanitizer).
|
|
13
|
+
|
|
14
|
+
Never do:
|
|
15
|
+
- Add `-ffast-math`, `-Ofast` or `/fp:fast`. They let the compiler assume NaN and Inf never happen, which silently deletes `isfinite` guards and breaks compensated sums.
|
|
16
|
+
</constraints>
|
|
17
|
+
|
|
18
|
+
## Check
|
|
19
|
+
- `.claude/checks/no-fast-math.json` blocks fast-math flags being added.
|
|
20
|
+
- `.claude/checks/keep-werror.json` blocks an edit that removes `-Werror` from a CMake file that had it.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: audio
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Parameter pointers are looked up once, never per block
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- In the processor constructor, cache `std::atomic<float>*` from `apvts.getRawParameterValue(id)` (or the typed `AudioParameterFloat*` etc.), and `jassert` that each one is non-null.
|
|
12
|
+
- In audio code, read with `->load()` once per block, then smooth (see smooth-continuous-parameters).
|
|
13
|
+
|
|
14
|
+
Never do:
|
|
15
|
+
- Call `getRawParameterValue()`, `getParameter()` or any lookup by string ID inside `processBlock` or anything it calls. Those are string compares and map lookups, every block, on the audio thread.
|
|
16
|
+
</constraints>
|
|
17
|
+
|
|
18
|
+
```cpp
|
|
19
|
+
// constructor
|
|
20
|
+
cutoff = apvts.getRawParameterValue (ids::cutoff.getParamID());
|
|
21
|
+
jassert (cutoff != nullptr);
|
|
22
|
+
|
|
23
|
+
// processBlock
|
|
24
|
+
const auto target = cutoff->load();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Check
|
|
28
|
+
The realtime-guard hook flags `getRawParameterValue(` and `getParameter(` inside audio-thread bodies.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: cpp
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# General C++ hygiene is checked by clang-tidy, not by memory
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Keep the `.clang-tidy` from this pack at the repo root and run it on your own sources in CI and before merging (`run-clang-tidy -p build -header-filter='.*/(Source|src|lib|include)/.*'`). Export `compile_commands.json` from CMake.
|
|
12
|
+
- Fix what it reports: C-style casts, narrowing conversions, `NULL`/`0` as a pointer, missing `override`, implicit single-argument constructors, Rule of Zero/Five violations, `using namespace` in headers, copying range-for loops, by-value parameters that should be `const&`, `std::move` that blocks return-value elision.
|
|
13
|
+
- Mark leaf classes `final`.
|
|
14
|
+
|
|
15
|
+
Never do:
|
|
16
|
+
- Apply general C++ advice on locking, `shared_ptr` or exceptions to audio-thread code. The realtime rules win there (`audio-thread-realtime-safe.md`).
|
|
17
|
+
- Run clang-tidy on JUCE's own modules or `JuceLibraryCode`.
|
|
18
|
+
</constraints>
|
|
19
|
+
|
|
20
|
+
## Check
|
|
21
|
+
`run-clang-tidy` with `WarningsAsErrors: '*'` fails the build on any finding. Sources: the C++ Core Guidelines checklist (ECC cpp-coding-standards, jeffallan cpp-pro) and the efficient-code-cpp gotchas, turned into tool checks.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: params, ui
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# A new or changed control is proven at every surface it has
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- For every control you add or change, prove each surface it has with a real invocation, not a unit call:
|
|
12
|
+
1. host automation: set the parameter by its ID, render, and the sound changes;
|
|
13
|
+
2. the editor widget moves the same parameter, and shows the value the host set;
|
|
14
|
+
3. patch save and load round-trips the exact value;
|
|
15
|
+
4. the init patch and the reset value match the spec;
|
|
16
|
+
5. MIDI CC or learn, if the control has one;
|
|
17
|
+
6. undo restores it, as one step per gesture.
|
|
18
|
+
- Record the evidence for each surface in the step or bug log (command plus result). Use the `prove-control` skill.
|
|
19
|
+
|
|
20
|
+
Never do:
|
|
21
|
+
- Call a control done because the DSP function passes its unit test. "The function works" and "the knob reaches the function" are different claims.
|
|
22
|
+
- Add a control that exists in the editor but not in the parameter tree, or the other way round, unless the spec says it's performance-only.
|
|
23
|
+
</constraints>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: audio, bench
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# CPU is judged by the worst block, not the average
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Gate on p99, p99.9 and maximum block time, plus the count of blocks over their deadline (`numSamples / sampleRate`), at 1, 8, 32 and 96 voices, with the heaviest patch and every row of the matrix moving.
|
|
12
|
+
- Include digital silence and "identical left and right" as their own cases. Silence can cost more than signal (denormals, gates).
|
|
13
|
+
- Label every CPU figure with what it measures (callback duty, one core, or process CPU), sample rate, block size, and whether the editor was open.
|
|
14
|
+
- Attribute cost before optimising: compare editor closed vs open, bypassed vs active, silence vs signal.
|
|
15
|
+
- Build the benchmark with the plugin's exact compile and link flags (including LTO), constructing the engine the same way it ships (heap, not stack).
|
|
16
|
+
- Touch every pre-allocated buffer once in `prepareToPlay` so the first callbacks don't stall on page faults.
|
|
17
|
+
- Look at the curve across voice counts. Anything worse than linear growth is a bug.
|
|
18
|
+
|
|
19
|
+
Never do:
|
|
20
|
+
- Report average CPU as the performance figure.
|
|
21
|
+
- Compare numbers from different benchmark-harness versions. When the harness changes, re-time the old build with the new harness.
|
|
22
|
+
- Time code with anything that logs from inside `processBlock` (JUCE's `PerformanceCounter` writes to the logger).
|
|
23
|
+
</constraints>
|
|
24
|
+
|
|
25
|
+
## Check
|
|
26
|
+
Benchmark test, offline render: 96 voices at 48 kHz with 64-sample blocks. Pass (house choice): p99.9 under 50% of the deadline, and zero overruns.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: dsp
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Asymmetric stages are followed by a DC blocker
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Put a one-pole DC blocker (corner about 5–10 Hz, coefficient computed from the sample rate) after every asymmetric shaper, folder, rectifier or crusher, and inside any feedback loop that contains one.
|
|
12
|
+
- Put a ~5 Hz high-pass after any integrator or leaky accumulator.
|
|
13
|
+
|
|
14
|
+
Never do:
|
|
15
|
+
- Hard-code the blocker's pole (e.g. `0.995`). It must follow the sample rate.
|
|
16
|
+
</constraints>
|
|
17
|
+
|
|
18
|
+
## Why
|
|
19
|
+
Even-order distortion creates DC. It eats headroom, shifts the bias of the next nonlinearity, and clicks when the voice stops.
|
|
20
|
+
|
|
21
|
+
## Check
|
|
22
|
+
Feed a 1 kHz sine with +0.3 offset through the stage for 1 s. Pass (house choice): the mean of the output (`tone-report` prints it) is below −80 dBFS.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: params
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Stepped parameters store the step, never the raw host value
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Make bool, choice and integer parameters snap any incoming normalised value to the nearest step, and store and report the snapped value. A host may send 0.37 to an on/off switch.
|
|
12
|
+
- Restore exactly the stepped value from saved state.
|
|
13
|
+
|
|
14
|
+
Never do:
|
|
15
|
+
- Rely on `juce::AudioParameterBool` keeping the snapped value. pluginval 2.0's strict discrete-parameter test fails it because it keeps the raw value. Wrap or replace it.
|
|
16
|
+
</constraints>
|
|
17
|
+
|
|
18
|
+
## Check
|
|
19
|
+
Unit test per stepped parameter: set normalised 0.37, save state, restore it. Pass: the value equals the stepped value both before and after the round trip.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: dsp, world
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Phase, sample rate and coefficients are computed in `double`
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Keep the sample rate, phase accumulators, phase increments and tempo/clock positions in `double`.
|
|
12
|
+
- Compute filter coefficients in `double`. Store them as `float` only after they're normalised.
|
|
13
|
+
- Use a `double` accumulator (or pairwise summation) for RMS, energy, metering and any long running sum.
|
|
14
|
+
|
|
15
|
+
Never do:
|
|
16
|
+
- Declare `float sampleRate`, `float phase` or `float phaseInc`. Float phase drifts audibly over long notes and slow LFOs; sixteen clocks synced to tempo need the precision.
|
|
17
|
+
</constraints>
|
|
18
|
+
|
|
19
|
+
## Check
|
|
20
|
+
`.claude/checks/float-phase-or-rate.json` (lesson-checks hook) blocks new `float` declarations of sample rate, phase or phase increment.
|