@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,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: choose-observable
|
|
3
|
+
description: Use when writing a probe, when a measurement is noisy, or when deciding what audio can prove a behaviour.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Choose the observable (one job: measure the signal that can prove it)
|
|
7
|
+
|
|
8
|
+
<constraints>
|
|
9
|
+
Always do:
|
|
10
|
+
1. Check preconditions: renders bit-identical, start state checked, stale frames drained, the program found by name.
|
|
11
|
+
2. Take the best rung: a pure gain (exact), pulse width, a stereo difference with a hard zero, pitch through the phase null, a filter, a comb's energy.
|
|
12
|
+
3. On pitch, keep the depth tiny: the law is exponential, and the error accumulates.
|
|
13
|
+
4. On a sampler, take the median of consecutive gaps.
|
|
14
|
+
5. If it cannot see phase, say so. Assert the offset does not move, and log the open item.
|
|
15
|
+
|
|
16
|
+
Never do:
|
|
17
|
+
- Measure phase through a comb, or trust a filter's lowest point as its vertex.
|
|
18
|
+
</constraints>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: measure-a-law
|
|
3
|
+
description: Use when fitting or checking a law against a machine or a reference recording.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Measure a law (one job: a fit you can defend)
|
|
7
|
+
|
|
8
|
+
<constraints>
|
|
9
|
+
Always do:
|
|
10
|
+
1. Use a sine at the frequency you read. A filter slope read on a saw was off by 2.3 dB per octave.
|
|
11
|
+
2. Write a filter's law in the units its procedure uses.
|
|
12
|
+
3. Fix it with two anchors.
|
|
13
|
+
4. Keep fitted constants scripted, tagged, and rerunnable.
|
|
14
|
+
5. Write disproofs down.
|
|
15
|
+
|
|
16
|
+
Never do:
|
|
17
|
+
- Fit a single point.
|
|
18
|
+
</constraints>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: measure-reverb
|
|
3
|
+
description: Use when measuring or calibrating a reverb or a decay time.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Measure a reverb (one job: a decay time you can trust)
|
|
7
|
+
|
|
8
|
+
<constraints>
|
|
9
|
+
Always do:
|
|
10
|
+
1. Mute dry and early reflections, and zero the pre-delay.
|
|
11
|
+
2. Use Schroeder T30, or a least-squares fit of the tail.
|
|
12
|
+
3. Measure over a long enough render for the longest setting.
|
|
13
|
+
4. Read the law in the units its procedure uses.
|
|
14
|
+
5. Compare with the printed figure.
|
|
15
|
+
|
|
16
|
+
Never do:
|
|
17
|
+
- Read a time off the peak level.
|
|
18
|
+
- Inherit a sibling machine's law: reverb times were once 20 to 45% short that way.
|
|
19
|
+
</constraints>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spread-probe
|
|
3
|
+
description: Use when presets sound alike, when a bank is finished, or when an algorithm list is built.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Measure the spread (one job: the programs really differ)
|
|
7
|
+
|
|
8
|
+
<constraints>
|
|
9
|
+
Always do:
|
|
10
|
+
1. Render every program with the same excitations, chosen to excite what differs.
|
|
11
|
+
2. Measure the difference between programs, per algorithm and across the bank, as medians.
|
|
12
|
+
3. Count the effectively distinct sounds, and report it next to the total.
|
|
13
|
+
4. Check the upstream causes first: an invented global, programs loading defaults, an algorithm with min equal to max.
|
|
14
|
+
5. Share one probe across units, so a number means the same on every machine.
|
|
15
|
+
|
|
16
|
+
Never do:
|
|
17
|
+
- Accept "they all sound the same" as an opinion. It is a testable report: 625 presets once measured as 146.
|
|
18
|
+
</constraints>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "no-keyboard-focus",
|
|
3
|
+
"why": "Stellix 3a: no dropdown, button or readout ever takes keyboard focus; QWERTY always plays.",
|
|
4
|
+
"rule": ".claude/rules/stellix-deterministic-world.md",
|
|
5
|
+
"concepts": [
|
|
6
|
+
"ui"
|
|
7
|
+
],
|
|
8
|
+
"pattern": "setWantsKeyboardFocus\\s*\\(\\s*true|grabKeyboardFocus\\s*\\(|setMouseClickGrabsKeyboardFocus\\s*\\(\\s*true",
|
|
9
|
+
"code": true,
|
|
10
|
+
"bad": "presetBox.setWantsKeyboardFocus (true);",
|
|
11
|
+
"good": "presetBox.setWantsKeyboardFocus (false);"
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "one-seeded-random",
|
|
3
|
+
"why": "Stellix rule 4: formulas by default; the only randomness is the world's one seeded generator (RANDOM, 6.6). No other random call may exist in the engine, the world or the drawing.",
|
|
4
|
+
"rule": ".claude/rules/stellix-deterministic-world.md",
|
|
5
|
+
"concepts": [
|
|
6
|
+
"cpp"
|
|
7
|
+
],
|
|
8
|
+
"exclude": [
|
|
9
|
+
"@seeded_random",
|
|
10
|
+
"**/tests/**"
|
|
11
|
+
],
|
|
12
|
+
"pattern": "(?<![\\w.])(?:std::)?(?:s?rand|random|drand48|lrand48|arc4random(?:_uniform)?)\\s*\\(|\\b(?:random_device|mt19937(?:_64)?|minstd_rand0?|default_random_engine|ranlux\\w+|knuth_b)\\b|\\b\\w+_distribution\\b|\\bjuce::Random\\b|(?<![\\w:])Random\\s*(?:::|\\w+\\s*[;({=])|\\bgetSystemRandom\\b|\\bSecRandomCopyBytes\\b|\\bRAND_bytes\\b",
|
|
13
|
+
"code": true,
|
|
14
|
+
"bad": "float jitter = juce::Random::getSystemRandom().nextFloat();\nstd::mt19937 g (42);\nstd::uniform_real_distribution<float> d (0, 1);\nuint32_t v = arc4random_uniform (8);",
|
|
15
|
+
"good": "float jitter = world.seeded().next01();\nauto n = randomSource.next(); int operand (int); bool israndom;\ninline float hash (int i) { return std::sin (float (i) * 12.98f) * 43758.5f; }"
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "world-never-includes-painter",
|
|
3
|
+
"why": "Stellix 8: the world is coordinates, not graphics. The audio side includes nothing from the painter or any GPU API; it publishes a plain-data snapshot and nothing else.",
|
|
4
|
+
"rule": ".claude/rules/stellix-world-snapshot.md",
|
|
5
|
+
"concepts": [
|
|
6
|
+
"world",
|
|
7
|
+
"audio"
|
|
8
|
+
],
|
|
9
|
+
"pattern": "#\\s*(include|import)\\s*[<\"][^>\"]*(painter|Painter|gpu/|render/|Renderer|juce_opengl|OpenGL|Metal/|MetalKit|QuartzCore|bgfx|webgpu)[^>\"]*[>\"]",
|
|
10
|
+
"bad": "#include \"../painter/PlanetMesh.h\"",
|
|
11
|
+
"good": "#include \"WorldSnapshot.h\""
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "world-no-libm",
|
|
3
|
+
"why": "libm sin/cos/exp/pow differ in the last bits between Apple, MSVC and glibc; the world must replay bit-identically on Mac and Windows. Use the house world-math functions.",
|
|
4
|
+
"rule": ".claude/rules/world-fp-determinism.md",
|
|
5
|
+
"concepts": [
|
|
6
|
+
"world"
|
|
7
|
+
],
|
|
8
|
+
"exclude": [
|
|
9
|
+
"@world_math"
|
|
10
|
+
],
|
|
11
|
+
"pattern": "\\bstd::(sin|cos|tan|asin|acos|atan2?|exp2?|expm1|log(2|10|1p)?|pow|sinh|cosh|tanh|hypot|cbrt)\\s*\\(|(?<![\\w:.>])(sinf?|cosf?|tanf?|atan2f?|expf?|logf?|powf?)\\s*\\(",
|
|
12
|
+
"code": true,
|
|
13
|
+
"bad": "const double a = std::sin (phase) * radius;",
|
|
14
|
+
"good": "const double a = wm::sin (phase) * radius;"
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "world-no-unordered",
|
|
3
|
+
"why": "Hash-container iteration order differs between libc++ and the MSVC STL; the world must be ordered by stable ID to replay identically on every platform.",
|
|
4
|
+
"rule": ".claude/rules/world-fp-determinism.md",
|
|
5
|
+
"concepts": ["world"],
|
|
6
|
+
"pattern": "\\bstd::unordered_(map|set|multimap|multiset)\\b",
|
|
7
|
+
"code": true,
|
|
8
|
+
"bad": "std::unordered_map<int, Moon> moonsById;",
|
|
9
|
+
"good": "std::array<Moon, kMaxMoons> moons; // ordered by stable id"
|
|
10
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Nothing is ever pre-rendered (Stellix spec 0.2). No image file may be added to the source or
|
|
3
|
+
// resources (fonts are allowed: data, not pictures). Test output and goldens live outside them.
|
|
4
|
+
// A project sets its own scope in .claude/layout.json "guards": { "images": { "guarded": [globs],
|
|
5
|
+
// "allowed": [globs] } }: "guarded" replaces the code folders (["**"]: anywhere in the repo), "allowed"
|
|
6
|
+
// replaces the default allowed folders (Stellix: design/reference/** and build/pictures/** only).
|
|
7
|
+
// PreToolUse (Write|Edit|MultiEdit|NotebookEdit|Bash): blocks writing, copying or moving an image into a guarded
|
|
8
|
+
// folder by any route (lib/writes.mjs), and a download or conversion that names one (curl, convert, sips ...).
|
|
9
|
+
// --git-staged: run from a git pre-commit hook; fails if a staged added file is an image.
|
|
10
|
+
// --selftest: proves it.
|
|
11
|
+
import { execFileSync } from 'node:child_process';
|
|
12
|
+
import { readFileSync } from 'node:fs';
|
|
13
|
+
import { join, resolve } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { matchesAny } from './lib/glob.mjs';
|
|
16
|
+
import { codeFolders, readLayout } from './lib/layout.mjs';
|
|
17
|
+
import { claudeRoot, commandLeavesProject, insideProject, relInCheckout } from './lib/project.mjs';
|
|
18
|
+
import { writesOf } from './lib/writes.mjs';
|
|
19
|
+
import { bashOf, runHook, scratchProject, verdicts, writeOf } from './lib/selftest.mjs';
|
|
20
|
+
import { asHook, isMain } from './lib/hook-log.mjs';
|
|
21
|
+
|
|
22
|
+
const ROOT = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
23
|
+
const IMAGE = /\.(png|jpe?g|gif|bmp|tiff?|webp|heic|ico|icns|svg|psd|tga|exr|hdr|ktx2?|dds|astc)$/i;
|
|
24
|
+
// Guarded: every code folder in the layout, plus anything that would be bundled as a resource.
|
|
25
|
+
const guarded = (root) => readLayout(root).guards?.images?.guarded ?? [...new Set(['src/**', 'Resources/**', 'resources/**', 'assets/**', ...codeFolders(readLayout(root)).map((f) => `${f}/**`)])];
|
|
26
|
+
const ALLOWED = ['tests/**', '**/tests/**', 'goldens/**', '**/goldens/**', 'docs/**', 'captures/**', 'build/**'];
|
|
27
|
+
const allowed = (root) => readLayout(root).guards?.images?.allowed ?? ALLOWED;
|
|
28
|
+
|
|
29
|
+
// A path is judged in its own checkout, so an image written into an agent worktree is caught too.
|
|
30
|
+
const isBlocked = (p, base = ROOT) => {
|
|
31
|
+
const abs = resolve(base, p);
|
|
32
|
+
if (!IMAGE.test(abs) || !insideProject(abs)) return false;
|
|
33
|
+
const rel = relInCheckout(abs).replace(/^\.claude\/worktrees\/[^/]+\//, '');
|
|
34
|
+
const root = claudeRoot(abs);
|
|
35
|
+
return !rel.startsWith('.claude/') && matchesAny(rel, guarded(root)) && !matchesAny(rel, allowed(root));
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function fail(files) {
|
|
39
|
+
process.stderr.write(
|
|
40
|
+
`BLOCKED by no-shipped-images: ${files.join(', ')}\n` +
|
|
41
|
+
'Nothing is pre-rendered: draw it in code; a picture check renders off-screen, from the app itself, into an allowed folder (guards.images.allowed in .claude/layout.json).\n',
|
|
42
|
+
);
|
|
43
|
+
return 2;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function gitStaged() {
|
|
47
|
+
const out = execFileSync('git', ['diff', '--cached', '--name-only', '--diff-filter=AR'], { cwd: ROOT, encoding: 'utf8' });
|
|
48
|
+
const bad = out.split('\n').filter((f) => f && isBlocked(f));
|
|
49
|
+
return bad.length ? (fail(bad), 1) : 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function main(text) {
|
|
53
|
+
let payload;
|
|
54
|
+
try {
|
|
55
|
+
payload = JSON.parse(text);
|
|
56
|
+
} catch {
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
const input = payload.tool_input ?? {};
|
|
60
|
+
const bad = writesOf(payload, payload.cwd ?? ROOT).filter((w) => w.op !== 'delete' && isBlocked(w.path)).map((w) => w.path);
|
|
61
|
+
if (payload.tool_name === 'Bash' && !commandLeavesProject(input.command)) {
|
|
62
|
+
const tokens = (input.command ?? '').split(/\s+/).map((t) => t.replace(/^['"]|['"]$/g, ''));
|
|
63
|
+
if (/\b(curl|wget|convert|magick|sips|rsvg-convert|ffmpeg)\b/.test(input.command ?? '')) bad.push(...tokens.filter((t) => t && isBlocked(t, payload.cwd ?? ROOT)));
|
|
64
|
+
}
|
|
65
|
+
return bad.length ? fail([...new Set(bad)]) : 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function selftest() {
|
|
69
|
+
const me = fileURLToPath(import.meta.url);
|
|
70
|
+
const dir = scratchProject({}, { folders: { app: { path: 'lib/app/src', purpose: 'app' }, docs: { path: 'docs', purpose: 'docs' } }, concepts: {} });
|
|
71
|
+
const w = (file) => runHook(me, dir, writeOf(join(dir, file), 'x'));
|
|
72
|
+
return verdicts('no-shipped-images', [
|
|
73
|
+
['an image in a code folder', w('lib/app/src/logo.png'), 2],
|
|
74
|
+
['an image in src/', w('src/icon.svg'), 2],
|
|
75
|
+
['an image in resources/', w('resources/knob.webp'), 2],
|
|
76
|
+
['a font is data, not a picture', w('resources/Inter.ttf'), 0],
|
|
77
|
+
['a golden render under tests/', w('tests/goldens/panel.png'), 0],
|
|
78
|
+
['a picture in docs/', w('docs/shot.png'), 0],
|
|
79
|
+
['cp of an image into a code folder', runHook(me, dir, bashOf('cp /tmp/a.png lib/app/src/a.png', dir)), 2],
|
|
80
|
+
['cp into tests/', runHook(me, dir, bashOf('cp /tmp/a.png tests/goldens/a.png', dir)), 0],
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const hook = main; // run-hooks.mjs calls it with the event's text (KWB-24)
|
|
85
|
+
if (isMain(import.meta.url)) {
|
|
86
|
+
const arg = process.argv.slice(2);
|
|
87
|
+
process.exit(arg.includes('--selftest') ? selftest() : arg.includes('--git-staged') ? gitStaged() : await asHook('no-shipped-images', main));
|
|
88
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stellix",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Stellix spec laws: the world, determinism, generated reset, no shipped images.",
|
|
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/stellix"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"synth"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"claude-packs": ">=0.19.0"
|
|
19
|
+
},
|
|
20
|
+
"folders": {
|
|
21
|
+
"world": {
|
|
22
|
+
"path": "src/world",
|
|
23
|
+
"purpose": "the world: coordinates, travellers, hits, pushes, the snapshot writer, the seeded generator, world maths"
|
|
24
|
+
},
|
|
25
|
+
"records": {
|
|
26
|
+
"path": "records",
|
|
27
|
+
"purpose": "layout and state records: every piece of state declared once with its starting value"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"concepts": {
|
|
31
|
+
"world": [
|
|
32
|
+
"world"
|
|
33
|
+
],
|
|
34
|
+
"records": [
|
|
35
|
+
"records"
|
|
36
|
+
],
|
|
37
|
+
"params": [
|
|
38
|
+
"records"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"skillsIn": null,
|
|
42
|
+
"hooks": {
|
|
43
|
+
"PreToolUse": [
|
|
44
|
+
{
|
|
45
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|Bash",
|
|
46
|
+
"hooks": [
|
|
47
|
+
{
|
|
48
|
+
"type": "command",
|
|
49
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/no-shipped-images.mjs\"",
|
|
50
|
+
"timeout": 10
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"files": {
|
|
57
|
+
"seeded_random": "src/world/seeded_random.h",
|
|
58
|
+
"world_math": "src/world/world_math.h",
|
|
59
|
+
"snapshot": "src/world/snapshot.h"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: world, audio, painter, ui, tests
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Same playing from the same state gives the same sound and the same picture
|
|
8
|
+
|
|
9
|
+
From spec §0 rule 4, §6.1, §6.3, §7.3.
|
|
10
|
+
|
|
11
|
+
<constraints>
|
|
12
|
+
Always do:
|
|
13
|
+
- Work out every path, bounce, impact and shatter by formula from what was played, where it hits, and the world's settings.
|
|
14
|
+
- Use the world's one seeded generator as the only randomness (RANDOM, opt-in, off in INIT and every factory patch). It may reach modulation and effects only, never pitch, wave, tone, level, filter type or a SOUND choice. Under FOLLOW THE SONG its seed restarts with the song position.
|
|
15
|
+
- Run the world at a fixed 240 Hz tick, independent of buffer size and sample rate. Solve crossings and touches inside the tick and place each event at its exact sample.
|
|
16
|
+
- Keep looking separate from sound: hovering, zooming and moving the camera never change the sound (unless FROM VIEW is on, where the camera becomes patch data).
|
|
17
|
+
|
|
18
|
+
Never do:
|
|
19
|
+
- Call any random source other than the seeded generator. `.claude/checks/one-seeded-random.json` blocks it.
|
|
20
|
+
- Let the frame rate, the window being open, or the host buffer size change what is heard.
|
|
21
|
+
- Let a control take keyboard focus. QWERTY always plays (`no-keyboard-focus.json`).
|
|
22
|
+
</constraints>
|
|
23
|
+
|
|
24
|
+
## Check
|
|
25
|
+
Gates, each proven red by a planted fault:
|
|
26
|
+
- **Bounce repeat:** the same MIDI from INIT renders bit-identical twice, at buffer sizes 64, 512 and 2048 and at 44.1, 48 and 96 kHz.
|
|
27
|
+
- **View:** with FROM VIEW off, a camera move or a hover leaves the render bit-identical.
|
|
28
|
+
- **Four tempos:** HITS and BEATS notes land on their exact samples.
|
|
29
|
+
- **Settle:** after a hard passage the world comes to rest once playing stops.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: records, params, world
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Reset is generated from the records, never written by hand
|
|
8
|
+
|
|
9
|
+
From spec §0 rule 5.
|
|
10
|
+
|
|
11
|
+
<constraints>
|
|
12
|
+
Always do:
|
|
13
|
+
- Declare every piece of patch state once in the records, with its starting value. The reset is generated from that list, and state without a starting value must not compile.
|
|
14
|
+
- Treat a patch load as a reset followed by an apply, so nothing survives from the previous patch.
|
|
15
|
+
- Make reset clear motion too: every mover, note in flight and shatter piece. Every held note gets its note-off.
|
|
16
|
+
- Keep MAIN volume, octave, the wheel positions, LIMIT and SETTINGS outside the patch, as the patch law says.
|
|
17
|
+
|
|
18
|
+
Never do:
|
|
19
|
+
- Write a reset by hand, or add a field to a hand-made list.
|
|
20
|
+
- Plant state in a member variable that isn't declared in the records.
|
|
21
|
+
</constraints>
|
|
22
|
+
|
|
23
|
+
## Check
|
|
24
|
+
Reset gate: move every control and every piece of patch state away from its start, set the world moving with notes in flight, then reset. The render must be bit-identical to a fresh INIT. Plant the fault (one field outside the list) and the gate must show red.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: world, painter, audio
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# The painter sees the world only through one plain-data snapshot
|
|
8
|
+
|
|
9
|
+
From spec §8 and §7.3.
|
|
10
|
+
|
|
11
|
+
<constraints>
|
|
12
|
+
Always do:
|
|
13
|
+
- Keep the world as coordinates on the audio side: a traveller is a position and a velocity; a moon is a position, a radius and a border; a planet is a position and a radius. Each 240 Hz tick moves travellers, checks distances and turns hits into pushes, as arithmetic only.
|
|
14
|
+
- Publish one plain-data snapshot per tick (positions, pushes, hits) behind a single atomic index. Use double or triple buffering, whichever keeps the reader from ever seeing a half-written one.
|
|
15
|
+
- Let the painter read only the snapshot, at its own frame rate. It may extrapolate between ticks with the same formulas, but when they differ the snapshot wins.
|
|
16
|
+
- Compute predictions (ghost paths, "cutoff +12%") with the engine's own formula code on a copy of the world's state, never with a second version of the formulas.
|
|
17
|
+
|
|
18
|
+
Never do:
|
|
19
|
+
- Include anything from the painter, a GPU API or JUCE OpenGL in world, engine or voice code. `.claude/checks/world-never-includes-painter.json` blocks it.
|
|
20
|
+
- Do camera, perspective, lighting, mesh, bloom or path drawing work inside the world tick. The look-only test's 17 ms demo step is the example of what this forbids.
|
|
21
|
+
- Let the audio thread wait for, lock against or allocate for the painter.
|
|
22
|
+
</constraints>
|
|
23
|
+
|
|
24
|
+
## Check
|
|
25
|
+
- Torn-snapshot gate: a reader hammering the snapshot while the world writes at full rate must never see a mixed one. Plant the fault by writing in place, and the gate goes red.
|
|
26
|
+
- Prediction gate: play a passage; every predicted hit happens, and no unpredicted hit occurs.
|
|
27
|
+
- The realtime-guard hook blocks GPU calls in audio-thread code.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: world, tests
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Every hit inside a tick is found exactly once and placed at its sample
|
|
8
|
+
|
|
9
|
+
From spec 6.0 and 7.3: the tick never quantises time.
|
|
10
|
+
|
|
11
|
+
<constraints>
|
|
12
|
+
Always do:
|
|
13
|
+
- Sweep each traveller across the tick. A formula curve is split into a fixed number K of substeps (fixed K keeps it deterministic), and each chord is swept against every sphere in reach.
|
|
14
|
+
- Solve segment against sphere with the numerically stable quadratic: `q = −½(b + sign(b)·√disc)`, roots `c'/q` and `q/a` (Ericson, *Real-Time Collision Detection* §5.3). Take the smallest `t` in [0, 1).
|
|
15
|
+
- Keep a contact state per traveller/planet pair. A hit fires on the *entering* transition only; a traveller starting inside counts once, at t = 0.
|
|
16
|
+
- Use a skin tolerance relative to the radius, and settle simultaneous hits by pair ID.
|
|
17
|
+
- Convert `t` to a sample with integer or fixed-point arithmetic: `tickStartSample + floor(t · samplesPerTick)`.
|
|
18
|
+
|
|
19
|
+
Never do:
|
|
20
|
+
- Test only the end position of a tick (fast travellers tunnel through small moons).
|
|
21
|
+
- Let a resting contact fire again every tick.
|
|
22
|
+
</constraints>
|
|
23
|
+
|
|
24
|
+
## Check
|
|
25
|
+
- Test: a traveller at 10x the fastest launch speed crosses a sphere of the smallest radius. Exactly one event, at the analytically expected sample, ±0.
|
|
26
|
+
- Test: grazing paths (tangent, ±1 skin) give the same verdict on both platforms (part of the cross-platform event-log gate).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: world, build
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# The world gives bit-identical results on Mac and Windows
|
|
8
|
+
|
|
9
|
+
The world (travellers, hits, pushes, event samples) must replay identically on ARM64 and x86-64. Audio DSP only needs to be identical per platform.
|
|
10
|
+
|
|
11
|
+
<constraints>
|
|
12
|
+
Always do:
|
|
13
|
+
- Build world sources with `-ffp-contract=off` (clang and clang-cl) and `/fp:precise` without `/fp:contract` (MSVC). Clang fuses multiply-adds by default (`-ffp-contract=on`), and Apple clang on ARM64 emits `fmadd`.
|
|
14
|
+
- Use only `+ − × ÷ sqrt` in the world. IEEE-754 rounds those five exactly, so they match everywhere. Build `sin`, `cos`, `exp` and `pow` from the house polynomial versions (range reduction plus Horner) in one world-math file.
|
|
15
|
+
- Keep world state in fixed arrays ordered by stable ID, and break sort ties by ID.
|
|
16
|
+
- Keep time as integers: sample timestamps as `int64`, and the tick phase as an integer ratio (48 kHz/240 Hz is exactly 200 samples, but 44.1 kHz/240 Hz is 183.75, so accumulate the remainder exactly).
|
|
17
|
+
- Design out denormals in the world: snap magnitudes below 1e-30 to zero explicitly rather than relying on CPU flush modes, which differ between ARM and x86.
|
|
18
|
+
- Consider 64-bit fixed point (e.g. Q32.32) for positions. It removes compiler and flag risk entirely (house option, decided in the world plan).
|
|
19
|
+
|
|
20
|
+
Never do:
|
|
21
|
+
- Call libm (`std::sin`, `std::exp`, `std::pow`…) in world code. Apple libm, the MSVC UCRT and glibc differ in the last bits.
|
|
22
|
+
- Use `std::unordered_*` or iterate anything in hash order in the world.
|
|
23
|
+
- Use fast-math or FMA-contraction flags anywhere (`no-fast-math` check).
|
|
24
|
+
</constraints>
|
|
25
|
+
|
|
26
|
+
## Check
|
|
27
|
+
- `.claude/checks/world-no-libm.json` and `world-no-unordered.json` block libm calls and unordered containers in world code.
|
|
28
|
+
- Cross-platform gate: render N seconds from a saved state on both CI platforms. The world event log (event, sample index, payload hash) must be byte-identical between Mac and Windows; the audio hash must be identical between runs on each platform.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "no-raw-html-from-data",
|
|
3
|
+
"why": "HTML put on a page by hand skips the sanitize step: stored markdown can carry a script. The only HTML inserted raw is the renderer's output.",
|
|
4
|
+
"rule": ".claude/rules/stored-text-renders-once.md",
|
|
5
|
+
"globs": [
|
|
6
|
+
"**/*.ts",
|
|
7
|
+
"**/*.tsx",
|
|
8
|
+
"**/*.js",
|
|
9
|
+
"**/*.jsx",
|
|
10
|
+
"**/*.mjs",
|
|
11
|
+
"**/*.vue",
|
|
12
|
+
"**/*.svelte",
|
|
13
|
+
"**/*.html"
|
|
14
|
+
],
|
|
15
|
+
"exclude": [
|
|
16
|
+
"**/node_modules/**",
|
|
17
|
+
"**/dist/**",
|
|
18
|
+
"**/build/**",
|
|
19
|
+
".claude/**",
|
|
20
|
+
"**/.claude/**",
|
|
21
|
+
"**/*.test.*",
|
|
22
|
+
"**/*.spec.*",
|
|
23
|
+
"**/test/**",
|
|
24
|
+
"**/tests/**",
|
|
25
|
+
"**/stored-text.*"
|
|
26
|
+
],
|
|
27
|
+
"strings": true,
|
|
28
|
+
"pattern": "dangerouslySetInnerHTML=\\{\\{\\s*__html:(?!\\s*renderStored\\()|\\.(?:innerHTML|outerHTML)\\s*\\+?=(?!\\s*(?:renderStored\\(|['\"`]{2}))|\\bv-html=\"(?!renderStored\\()",
|
|
29
|
+
"bad": "<div dangerouslySetInnerHTML={{ __html: row.body }} />\n",
|
|
30
|
+
"good": "<StoredText source={row.body} />\n<div dangerouslySetInnerHTML={{ __html: renderStored(row.body) }} />\nel.innerHTML = '';\n"
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "stored-text-libs-only-in-renderer",
|
|
3
|
+
"why": "A second place that parses markdown or highlights code is a second place that forgets to sanitize, and pages start to differ. These libraries are imported only in stored-text.*.",
|
|
4
|
+
"rule": ".claude/rules/stored-text-renders-once.md",
|
|
5
|
+
"globs": [
|
|
6
|
+
"**/*.ts",
|
|
7
|
+
"**/*.tsx",
|
|
8
|
+
"**/*.js",
|
|
9
|
+
"**/*.jsx",
|
|
10
|
+
"**/*.mjs",
|
|
11
|
+
"**/*.vue",
|
|
12
|
+
"**/*.svelte"
|
|
13
|
+
],
|
|
14
|
+
"exclude": [
|
|
15
|
+
"**/node_modules/**",
|
|
16
|
+
"**/dist/**",
|
|
17
|
+
"**/build/**",
|
|
18
|
+
".claude/**",
|
|
19
|
+
"**/.claude/**",
|
|
20
|
+
"**/*.test.*",
|
|
21
|
+
"**/*.spec.*",
|
|
22
|
+
"**/test/**",
|
|
23
|
+
"**/tests/**",
|
|
24
|
+
"**/stored-text.*",
|
|
25
|
+
"**/scripts/**"
|
|
26
|
+
],
|
|
27
|
+
"strings": true,
|
|
28
|
+
"pattern": "(?:\\bfrom\\s+|\\bimport\\s+|\\brequire\\(\\s*|\\bimport\\(\\s*)['\"](?:marked|markdown-it|micromark|react-markdown|remark[\\w-]*|rehype[\\w-]*|shiki|highlight\\.js|prismjs|dompurify|isomorphic-dompurify|sanitize-html)(?:/[^'\"]*)?['\"]",
|
|
29
|
+
"bad": "import { marked } from 'marked';\nconst html = marked.parse(row.body);\n",
|
|
30
|
+
"good": "import { renderStored } from '../lib/stored-text.js';\nconst html = renderStored(row.body);\n"
|
|
31
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "stored-text-renderer-complete",
|
|
3
|
+
"why": "The renderer is the one place stored text is made safe and readable, so it does all four jobs: line endings, markdown, highlighted code, sanitizing. One missing means every page shows raw symbols, a grey code block, stray characters or a script.",
|
|
4
|
+
"rule": ".claude/rules/stored-text-renders-once.md",
|
|
5
|
+
"concepts": [
|
|
6
|
+
"stored-text-renderer"
|
|
7
|
+
],
|
|
8
|
+
"globs": [],
|
|
9
|
+
"exclude": [
|
|
10
|
+
"**/*.test.*",
|
|
11
|
+
"**/*.spec.*"
|
|
12
|
+
],
|
|
13
|
+
"strings": true,
|
|
14
|
+
"mode": "needs",
|
|
15
|
+
"pattern": "\\bexport\\b",
|
|
16
|
+
"needs": [
|
|
17
|
+
"\\\\r",
|
|
18
|
+
"marked|markdown-it|micromark|remark|react-markdown|unified",
|
|
19
|
+
"shiki|highlight\\.js|hljs|prism|rehype-highlight|rehype-pretty-code",
|
|
20
|
+
"sanitize|DOMPurify|dompurify"
|
|
21
|
+
],
|
|
22
|
+
"bad": "import { marked } from 'marked';\nexport const renderStored = (text: string) => marked.parse(text);\n",
|
|
23
|
+
"good": "import { marked } from 'marked';\nimport { codeToHtml } from 'shiki';\nimport sanitizeHtml from 'sanitize-html';\nexport const renderStored = (text: string) => sanitizeHtml(marked.parse(text.replace(/\\r\\n?/g, '\\n')));\n"
|
|
24
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "stored-text-through-renderer",
|
|
3
|
+
"why": "A stored document put straight into markup shows its markdown as symbols, its code as one grey block and its \\r as stray characters. It goes through the renderer. A field that truly is plain gets a `plain text:` comment on its line.",
|
|
4
|
+
"rule": ".claude/rules/stored-text-renders-once.md",
|
|
5
|
+
"concepts": [
|
|
6
|
+
"stored-text-ui"
|
|
7
|
+
],
|
|
8
|
+
"globs": [],
|
|
9
|
+
"exclude": [
|
|
10
|
+
"**/node_modules/**",
|
|
11
|
+
"**/dist/**",
|
|
12
|
+
"**/build/**",
|
|
13
|
+
".claude/**",
|
|
14
|
+
"**/.claude/**",
|
|
15
|
+
"**/*.test.*",
|
|
16
|
+
"**/*.spec.*",
|
|
17
|
+
"**/test/**",
|
|
18
|
+
"**/tests/**",
|
|
19
|
+
"**/stored-text.*"
|
|
20
|
+
],
|
|
21
|
+
"pattern": "^(?![^\\n]*plain text:)[^\\n]*(?:>\\s*\\{\\s*[\\w$.?]*(?:\\?\\.|\\.)(?:content|body|markdown|transcript|prompt|reply|output|summary)\\s*\\}|\\$\\{\\s*(?:(?:esc\\w*|escapeHtml)\\(\\s*)?[\\w$.?]*(?<!\\breq)(?<!\\brequest)(?:\\?\\.|\\.)(?:content|body|markdown|transcript|prompt|reply|output|summary)\\b[^}\\n]*\\})",
|
|
22
|
+
"flags": "m",
|
|
23
|
+
"bad": "<p>{row.body}</p>\nconst h = `<li>${esc(row.note ?? row.tool)}</li>`;\n",
|
|
24
|
+
"good": "<StoredText source={row.body} />\nconst page = html`<div>${raw(renderStored(row.body))}</div>`;\n<td>{row.title}</td>\n<td>{row.content}</td> {/* plain text: a short label from an enum */}\nconst u = `${req.body}`;\n"
|
|
25
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stored-text",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Text from a database reaches the page through one renderer: line endings normalised, markdown parsed, code highlighted, HTML sanitized.",
|
|
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/stored-text"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"markdown",
|
|
16
|
+
"sanitize",
|
|
17
|
+
"ui"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"claude-packs": ">=0.19.0"
|
|
21
|
+
},
|
|
22
|
+
"folders": {},
|
|
23
|
+
"concepts": {
|
|
24
|
+
"stored-text-ui": [
|
|
25
|
+
"**/*.tsx",
|
|
26
|
+
"**/*.jsx",
|
|
27
|
+
"**/*.vue",
|
|
28
|
+
"**/*.svelte",
|
|
29
|
+
"**/ui/**/*.ts",
|
|
30
|
+
"**/views/**/*.ts",
|
|
31
|
+
"**/templates/**/*.ts",
|
|
32
|
+
"**/render*.ts",
|
|
33
|
+
"**/*.view.ts"
|
|
34
|
+
],
|
|
35
|
+
"stored-text-renderer": [
|
|
36
|
+
"**/stored-text.*"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"skillsIn": null,
|
|
40
|
+
"hooks": {}
|
|
41
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: stored-text-ui, stored-text-renderer
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Text from a database reaches the page through one renderer
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Render every field a person or a tool wrote (a message, a note, a description, a transcript, a tool's output) through the project's one renderer, in a file named `stored-text.*` (the `render-stored-text` skill builds it).
|
|
12
|
+
- Keep its order: normalise line endings; parse markdown with raw HTML off; highlight fenced code by its language; sanitize last, with an allowlist.
|
|
13
|
+
- Normalise `\r\n` and a lone `\r` to `\n`. A terminal's output is the exception: there a lone `\r` overwrites the line, so keep what follows the last one.
|
|
14
|
+
- Treat a backslash and an `r` showing as text as a write bug: the value was encoded twice. Fix it where it is written, and repair the stored rows.
|
|
15
|
+
- Highlight on the server, so no highlighter ships to the browser. An unknown language renders as plain, escaped code; never guess one.
|
|
16
|
+
- Keep labels, ids and enum values plain and escaped: they are not documents. Mark such a field with a `plain text:` comment on its line when its name reads like a document.
|
|
17
|
+
|
|
18
|
+
Never do:
|
|
19
|
+
- Show stored text with `{row.body}` or `${esc(row.body)}`: the markdown shows as symbols and the code as one grey block.
|
|
20
|
+
- Put HTML on a page by `dangerouslySetInnerHTML`, `innerHTML` or `v-html` unless it is the renderer's output. Markdown can carry a script; only the sanitize step stops it.
|
|
21
|
+
- Import a markdown, highlight or sanitize library anywhere but the renderer.
|
|
22
|
+
- Normalise or strip `\r` when saving: the stored text stays as it came.
|
|
23
|
+
</constraints>
|
|
24
|
+
|
|
25
|
+
## Check
|
|
26
|
+
`stored-text-renderer-complete`, `stored-text-libs-only-in-renderer`, `no-raw-html-from-data` and `stored-text-through-renderer` (lesson checks). The last reads field names, not data flow: a field with another name gets past it, so review what a new page shows.
|