@thedecipherist/claude-packs 0.0.0-stage → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +754 -0
- package/LICENSE +21 -0
- package/README.md +573 -2
- package/bin/claude-packs.mjs +212 -0
- package/configurations/base/config.json +85 -0
- package/configurations/cpp/config.json +93 -0
- package/configurations/full-stack/config.json +153 -0
- package/configurations/go/config.json +98 -0
- package/configurations/node/config.json +102 -0
- package/configurations/python/config.json +99 -0
- package/configurations/rust/config.json +106 -0
- package/configurations/synth-creator/config.json +148 -0
- package/global/hooks/gnu-shell.mjs +131 -0
- package/global/hooks/lib/shell-writes.mjs +2 -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/build-queue.mjs +22 -0
- package/lib/claude-md.mjs +60 -0
- package/lib/config-cli.mjs +36 -0
- package/lib/configs.mjs +145 -0
- package/lib/coverage.mjs +94 -0
- package/lib/custom-packs.mjs +93 -0
- package/lib/doctor.mjs +126 -0
- package/lib/fix-plan.mjs +72 -0
- package/lib/found-folders.mjs +25 -0
- package/lib/git-tokens.mjs +64 -0
- package/lib/global.mjs +125 -0
- package/lib/hook-proof.mjs +45 -0
- package/lib/hook-timing.mjs +42 -0
- package/lib/hover-gate.mjs +29 -0
- package/lib/kit-command.mjs +14 -0
- package/lib/kit-lock.mjs +149 -0
- package/lib/layout.mjs +99 -0
- package/lib/logs.mjs +109 -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 +109 -0
- package/lib/planner.mjs +59 -0
- package/lib/repeats.mjs +65 -0
- package/lib/repo-weight.mjs +28 -0
- package/lib/rule-tests.mjs +42 -0
- package/lib/rules.mjs +40 -0
- package/lib/scan-detect.mjs +130 -0
- package/lib/scan.mjs +171 -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 +31 -0
- package/lib/switches.mjs +44 -0
- package/lib/symmetry-doctor.mjs +26 -0
- package/lib/sync.mjs +133 -0
- package/lib/workorder.mjs +26 -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 +172 -0
- package/packs/audio-core/hooks/realtime-guard.mjs +67 -0
- package/packs/audio-core/pack.json +192 -0
- package/packs/audio-core/rules/a-control-is-proved-through-its-input.md +26 -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 +28 -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 +23 -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 +35 -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 +25 -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 +99 -0
- package/packs/base/hooks/dispatch-once.mjs +124 -0
- package/packs/base/hooks/file-size-guard.mjs +61 -0
- package/packs/base/hooks/folder-law.mjs +77 -0
- package/packs/base/hooks/git-guard.mjs +202 -0
- package/packs/base/hooks/lesson-checks.mjs +182 -0
- package/packs/base/hooks/lib/apply-edit.mjs +20 -0
- package/packs/base/hooks/lib/code-shapes.mjs +142 -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/crash-policy.mjs +47 -0
- package/packs/base/hooks/lib/dup-index.mjs +204 -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 +68 -0
- package/packs/base/hooks/lib/function-shapes.mjs +90 -0
- package/packs/base/hooks/lib/git-adds.mjs +21 -0
- package/packs/base/hooks/lib/git-auth.mjs +44 -0
- package/packs/base/hooks/lib/git-guard-selftest.mjs +192 -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 +69 -0
- package/packs/base/hooks/lib/layout.mjs +58 -0
- package/packs/base/hooks/lib/making-check-selftest.mjs +112 -0
- package/packs/base/hooks/lib/near-copies.mjs +76 -0
- package/packs/base/hooks/lib/program-read.mjs +199 -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/rust-scan.mjs +139 -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-lists.mjs +31 -0
- package/packs/base/hooks/lib/shape-prose.mjs +78 -0
- package/packs/base/hooks/lib/shape.mjs +273 -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 +86 -0
- package/packs/base/hooks/lib/unread-writes.mjs +24 -0
- package/packs/base/hooks/lib/writes.mjs +71 -0
- package/packs/base/hooks/making-check.mjs +248 -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 +140 -0
- package/packs/base/hooks/secrets-guard.mjs +99 -0
- package/packs/base/hooks/shape-law.mjs +140 -0
- package/packs/base/hooks/suite-once.mjs +96 -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 +19 -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 +23 -0
- package/packs/base/rules/unattended-runs.md +15 -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/new-project/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/skills/write-a-workorder/SKILL.md +41 -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 +26 -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 +29 -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/postgres/checks/pg-bind-values.json +33 -0
- package/packs/postgres/checks/pg-concurrently-in-txn.json +18 -0
- package/packs/postgres/checks/pg-fk-not-valid.json +18 -0
- package/packs/postgres/checks/pg-index-concurrently.json +18 -0
- package/packs/postgres/checks/pg-no-float-money.json +19 -0
- package/packs/postgres/checks/pg-no-money.json +18 -0
- package/packs/postgres/checks/pg-no-required-column.json +18 -0
- package/packs/postgres/checks/pg-no-volatile-default.json +18 -0
- package/packs/postgres/checks/pg-not-exists.json +18 -0
- package/packs/postgres/checks/pg-timestamptz.json +18 -0
- package/packs/postgres/hooks/db-wipe-guard.mjs +95 -0
- package/packs/postgres/pack.json +48 -0
- package/packs/postgres/rules/postgres-migrations-never-stop-traffic.md +28 -0
- package/packs/postgres/rules/postgres-one-pool-per-process.md +21 -0
- package/packs/postgres/rules/postgres-queries-are-null-safe-and-bounded.md +26 -0
- package/packs/postgres/rules/postgres-types-say-what-they-hold.md +22 -0
- package/packs/postgres/rules/postgres-values-are-bound.md +130 -0
- package/packs/postgres/skills/postgres-safe-migration/SKILL.md +45 -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 +22 -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 +22 -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/rust/checks/rust-allow-needs-reason.json +16 -0
- package/packs/rust/checks/rust-blocking-in-async.json +32 -0
- package/packs/rust/checks/rust-if-chain-is-a-match.json +32 -0
- package/packs/rust/checks/rust-static-mut.json +32 -0
- package/packs/rust/checks/rust-string-as-error.json +34 -0
- package/packs/rust/checks/rust-stub-left-in.json +32 -0
- package/packs/rust/checks/rust-unsafe-needs-safety.json +31 -0
- package/packs/rust/checks/rust-unwrap-in-library.json +34 -0
- package/packs/rust/checks/rust-wildcard-dependency.json +16 -0
- package/packs/rust/clippy.toml +5 -0
- package/packs/rust/pack.json +27 -0
- package/packs/rust/rules/rust-async-never-blocks.md +20 -0
- package/packs/rust/rules/rust-borrow-before-you-clone.md +19 -0
- package/packs/rust/rules/rust-errors-are-returned.md +22 -0
- package/packs/rust/rules/rust-lints-are-the-gate.md +23 -0
- package/packs/rust/rules/rust-repeats-become-templates.md +28 -0
- package/packs/rust/rules/rust-unsafe-is-proved.md +21 -0
- package/packs/rust/skills/rust-extract-template/SKILL.md +50 -0
- package/packs/rust/skills/rust-port/SKILL.md +22 -0
- package/packs/rust/skills/rust-review/SKILL.md +24 -0
- package/packs/rust/tools/rust-lints.toml +19 -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/bounce-a-plugin/SKILL.md +40 -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/sound-design/tools/vst3host/build.sh +73 -0
- package/packs/sound-design/tools/vst3host/host_events.h +101 -0
- package/packs/sound-design/tools/vst3host/options.h +172 -0
- package/packs/sound-design/tools/vst3host/render.cpp +245 -0
- package/packs/sound-design/tools/vst3host/session.h +241 -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 +175 -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 +21 -0
- package/packs/synth-creator/tools/buildq.mjs +74 -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
- package/prompts/workorder/PROMPT.md +53 -0
- package/prompts/workorder/run.sh +36 -0
- package/prompts/workorder/workorder.md +59 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "node",
|
|
3
|
+
"description": "A Node.js or TypeScript service, web app, CLI, library, MCP server or edge proxy: base, plus the packs its stack needs (js-ts, mongo, fastify, ai, docker, shell-hooks, html-ui, web, tui, nginx). The presets pick them.",
|
|
4
|
+
"packs": {
|
|
5
|
+
"always": [
|
|
6
|
+
"base",
|
|
7
|
+
"writing",
|
|
8
|
+
"hook-proof"
|
|
9
|
+
],
|
|
10
|
+
"choose": [
|
|
11
|
+
"js-ts",
|
|
12
|
+
"mongo",
|
|
13
|
+
"postgres",
|
|
14
|
+
"fastify",
|
|
15
|
+
"ai",
|
|
16
|
+
"docker",
|
|
17
|
+
"shell-hooks",
|
|
18
|
+
"html-ui",
|
|
19
|
+
"web",
|
|
20
|
+
"tui",
|
|
21
|
+
"nginx",
|
|
22
|
+
"stored-text",
|
|
23
|
+
"ui-craft",
|
|
24
|
+
"python",
|
|
25
|
+
"shell",
|
|
26
|
+
"cpp",
|
|
27
|
+
"http-api",
|
|
28
|
+
"react",
|
|
29
|
+
"multi-tenant",
|
|
30
|
+
"websocket",
|
|
31
|
+
"host-agent",
|
|
32
|
+
"go",
|
|
33
|
+
"rust",
|
|
34
|
+
"ci",
|
|
35
|
+
"dynamic-data",
|
|
36
|
+
"zod",
|
|
37
|
+
"content-site"
|
|
38
|
+
],
|
|
39
|
+
"default": [
|
|
40
|
+
"js-ts"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"layout": {
|
|
44
|
+
"folders": {
|
|
45
|
+
"docs": {
|
|
46
|
+
"path": "docs",
|
|
47
|
+
"purpose": "spec, decisions, versions.md"
|
|
48
|
+
},
|
|
49
|
+
"src": {
|
|
50
|
+
"path": "src",
|
|
51
|
+
"purpose": "the code: the entry, routes, handlers, the database gateway, schemas"
|
|
52
|
+
},
|
|
53
|
+
"test": {
|
|
54
|
+
"path": "test",
|
|
55
|
+
"purpose": "tests"
|
|
56
|
+
},
|
|
57
|
+
"tools": {
|
|
58
|
+
"path": "tools",
|
|
59
|
+
"purpose": "scripts that never ship"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"kinds": {
|
|
63
|
+
"tests": {
|
|
64
|
+
"what": "tests",
|
|
65
|
+
"in": "test",
|
|
66
|
+
"concepts": [
|
|
67
|
+
"js-tests"
|
|
68
|
+
],
|
|
69
|
+
"files": [
|
|
70
|
+
"**/*.test.*",
|
|
71
|
+
"**/*.spec.*"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"docs": {
|
|
75
|
+
"what": "the spec, decisions, research, versions.md",
|
|
76
|
+
"in": "docs",
|
|
77
|
+
"concepts": [
|
|
78
|
+
"docs-folder"
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
"tools": {
|
|
82
|
+
"what": "scripts that never ship",
|
|
83
|
+
"in": "tools"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"sourceFiles": "\\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs)$",
|
|
88
|
+
"preamble": {
|
|
89
|
+
"always": [
|
|
90
|
+
"Ask the user before inventing a new folder. A new folder goes into `.claude/layout.json` first.",
|
|
91
|
+
"When a hook, check or guard blocks work that is correct, stop and report its exact message. A blocking hook is a red check: fix the hook first, with a selftest, then continue.",
|
|
92
|
+
"When a command is refused or fails, the step fails loudly. Never report a refused write or a failed command as done.",
|
|
93
|
+
"claude-packs (`@thedecipherist/claude-packs`) is the source of truth for every rule, check, hook and skill this project's configuration installs. A fix to one of them is made in the kit, with its test, and comes here with `npx --no-install @thedecipherist/claude-packs update`. A project edits its installed copy only to try a fix before it goes into the kit."
|
|
94
|
+
],
|
|
95
|
+
"never": [
|
|
96
|
+
"Create source files outside these folders, or put a kind of thing anywhere but its place. The folder-law and placement-law hooks refuse both.",
|
|
97
|
+
"Edit files in `.claude/rules`, `.claude/checks` or `.claude/hooks` to get past a block. Fix the code, or ask the user to change the law.",
|
|
98
|
+
"Route around a block: no override variables, no writing through the shell after a refusal, no parking files in a scratchpad, no putting new code into an unrelated existing file.",
|
|
99
|
+
"Point at a document by line number. Cite a fixed anchor (`{#id}`) or a symbol name; lines move."
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "python",
|
|
3
|
+
"description": "Python projects: universal engineering and the python pack.",
|
|
4
|
+
"packs": {
|
|
5
|
+
"always": [
|
|
6
|
+
"base",
|
|
7
|
+
"writing",
|
|
8
|
+
"hook-proof"
|
|
9
|
+
],
|
|
10
|
+
"choose": [
|
|
11
|
+
"python",
|
|
12
|
+
"shell",
|
|
13
|
+
"docker",
|
|
14
|
+
"ai",
|
|
15
|
+
"mongo",
|
|
16
|
+
"postgres",
|
|
17
|
+
"js-ts",
|
|
18
|
+
"cpp",
|
|
19
|
+
"http-api",
|
|
20
|
+
"multi-tenant",
|
|
21
|
+
"ci",
|
|
22
|
+
"go",
|
|
23
|
+
"rust",
|
|
24
|
+
"dynamic-data",
|
|
25
|
+
"web",
|
|
26
|
+
"ui-craft",
|
|
27
|
+
"content-site"
|
|
28
|
+
],
|
|
29
|
+
"default": [
|
|
30
|
+
"python"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"layout": {
|
|
34
|
+
"folders": {
|
|
35
|
+
"docs": {
|
|
36
|
+
"path": "docs",
|
|
37
|
+
"purpose": "spec, laws, licences, work orders, decisions"
|
|
38
|
+
},
|
|
39
|
+
"src": {
|
|
40
|
+
"path": "src",
|
|
41
|
+
"purpose": "all source code, only inside the subfolders below"
|
|
42
|
+
},
|
|
43
|
+
"tests": {
|
|
44
|
+
"path": "tests",
|
|
45
|
+
"purpose": "unit tests, gates with planted faults, golden files"
|
|
46
|
+
},
|
|
47
|
+
"tools": {
|
|
48
|
+
"path": "tools",
|
|
49
|
+
"purpose": "scripts and research tooling (not shipped)"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"kinds": {
|
|
53
|
+
"tests": {
|
|
54
|
+
"what": "tests, gates with planted faults, golden renders",
|
|
55
|
+
"in": "tests",
|
|
56
|
+
"concepts": [
|
|
57
|
+
"tests"
|
|
58
|
+
],
|
|
59
|
+
"files": [
|
|
60
|
+
"**/*_test.*",
|
|
61
|
+
"**/*Test.cpp",
|
|
62
|
+
"**/*Tests.cpp",
|
|
63
|
+
"**/test_*.*",
|
|
64
|
+
"**/*.test.*"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
"docs": {
|
|
68
|
+
"what": "the spec, laws.md, decisions, research, work orders",
|
|
69
|
+
"in": "docs",
|
|
70
|
+
"concepts": [
|
|
71
|
+
"docs-folder"
|
|
72
|
+
],
|
|
73
|
+
"files": [
|
|
74
|
+
"**/laws.md",
|
|
75
|
+
"**/*-spec.md"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"tools": {
|
|
79
|
+
"what": "scripts and research tools that never ship",
|
|
80
|
+
"in": "tools"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"preamble": {
|
|
85
|
+
"always": [
|
|
86
|
+
"Ask the user before inventing a new folder. A new folder goes into `.claude/layout.json` first.",
|
|
87
|
+
"When a hook, check or guard blocks work that is correct, stop and report its exact message. A blocking hook is a red check: fix the hook first, with a selftest, then continue.",
|
|
88
|
+
"When a command is refused or fails, the step fails loudly. Never report a refused write or a failed command as done.",
|
|
89
|
+
"claude-packs (`@thedecipherist/claude-packs`) is the source of truth for every rule, check, hook and skill this project's configuration installs. A fix to one of them is made in the kit, with its test, and comes here with `npx --no-install @thedecipherist/claude-packs update`. A project edits its installed copy only to try a fix before it goes into the kit."
|
|
90
|
+
],
|
|
91
|
+
"never": [
|
|
92
|
+
"Create source files outside these folders, or put a kind of thing anywhere but its place. The folder-law and placement-law hooks refuse both.",
|
|
93
|
+
"Edit files in `.claude/rules`, `.claude/checks` or `.claude/hooks` to get past a block. Fix the code, or ask the user to change the law.",
|
|
94
|
+
"Route around a block: no override variables, no writing through the shell after a refusal, no parking files in a scratchpad, no putting new code into an unrelated existing file.",
|
|
95
|
+
"Point at a document by line number. Cite a fixed anchor (`{#id}`) or a symbol name; lines move."
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
"sourceFiles": "\\.(?:py|pyi)$"
|
|
99
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rust",
|
|
3
|
+
"description": "Rust projects: universal engineering and the rust pack.",
|
|
4
|
+
"packs": {
|
|
5
|
+
"always": [
|
|
6
|
+
"base",
|
|
7
|
+
"writing",
|
|
8
|
+
"hook-proof"
|
|
9
|
+
],
|
|
10
|
+
"choose": [
|
|
11
|
+
"rust",
|
|
12
|
+
"go",
|
|
13
|
+
"shell",
|
|
14
|
+
"docker",
|
|
15
|
+
"postgres",
|
|
16
|
+
"http-api",
|
|
17
|
+
"multi-tenant",
|
|
18
|
+
"websocket",
|
|
19
|
+
"host-agent",
|
|
20
|
+
"ci",
|
|
21
|
+
"js-ts",
|
|
22
|
+
"python",
|
|
23
|
+
"dynamic-data",
|
|
24
|
+
"web",
|
|
25
|
+
"ui-craft",
|
|
26
|
+
"content-site"
|
|
27
|
+
],
|
|
28
|
+
"default": [
|
|
29
|
+
"rust"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"layout": {
|
|
33
|
+
"folders": {
|
|
34
|
+
"docs": {
|
|
35
|
+
"path": "docs",
|
|
36
|
+
"purpose": "spec, laws, licences, work orders, decisions"
|
|
37
|
+
},
|
|
38
|
+
"src": {
|
|
39
|
+
"path": "src",
|
|
40
|
+
"purpose": "the source of a single crate"
|
|
41
|
+
},
|
|
42
|
+
"tests": {
|
|
43
|
+
"path": "tests",
|
|
44
|
+
"purpose": "integration tests (unit tests live beside their code, in a #[cfg(test)] module)"
|
|
45
|
+
},
|
|
46
|
+
"tools": {
|
|
47
|
+
"path": "tools",
|
|
48
|
+
"purpose": "scripts and research tooling (not shipped)"
|
|
49
|
+
},
|
|
50
|
+
"crates": {
|
|
51
|
+
"path": "crates",
|
|
52
|
+
"purpose": "the crates of a workspace, each with its own src/ and tests/",
|
|
53
|
+
"planned": true
|
|
54
|
+
},
|
|
55
|
+
"benches": {
|
|
56
|
+
"path": "benches",
|
|
57
|
+
"purpose": "benchmarks",
|
|
58
|
+
"planned": true
|
|
59
|
+
},
|
|
60
|
+
"examples": {
|
|
61
|
+
"path": "examples",
|
|
62
|
+
"purpose": "runnable examples",
|
|
63
|
+
"planned": true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"kinds": {
|
|
67
|
+
"tests": {
|
|
68
|
+
"what": "integration tests",
|
|
69
|
+
"in": "tests",
|
|
70
|
+
"concepts": [
|
|
71
|
+
"tests"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"docs": {
|
|
75
|
+
"what": "the spec, laws.md, decisions, research, work orders",
|
|
76
|
+
"in": "docs",
|
|
77
|
+
"concepts": [
|
|
78
|
+
"docs-folder"
|
|
79
|
+
],
|
|
80
|
+
"files": [
|
|
81
|
+
"**/laws.md",
|
|
82
|
+
"**/*-spec.md"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"tools": {
|
|
86
|
+
"what": "scripts and research tools that never ship",
|
|
87
|
+
"in": "tools"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"preamble": {
|
|
92
|
+
"always": [
|
|
93
|
+
"Ask the user before inventing a new folder. A new folder goes into `.claude/layout.json` first.",
|
|
94
|
+
"When a hook, check or guard blocks work that is correct, stop and report its exact message. A blocking hook is a red check: fix the hook first, with a selftest, then continue.",
|
|
95
|
+
"When a command is refused or fails, the step fails loudly. Never report a refused write or a failed command as done.",
|
|
96
|
+
"claude-packs (`@thedecipherist/claude-packs`) is the source of truth for every rule, check, hook and skill this project's configuration installs. A fix to one of them is made in the kit, with its test, and comes here with `npx --no-install @thedecipherist/claude-packs update`. A project edits its installed copy only to try a fix before it goes into the kit."
|
|
97
|
+
],
|
|
98
|
+
"never": [
|
|
99
|
+
"Create source files outside these folders, or put a kind of thing anywhere but its place. The folder-law and placement-law hooks refuse both.",
|
|
100
|
+
"Edit files in `.claude/rules`, `.claude/checks` or `.claude/hooks` to get past a block. Fix the code, or ask the user to change the law.",
|
|
101
|
+
"Route around a block: no override variables, no writing through the shell after a refusal, no parking files in a scratchpad, no putting new code into an unrelated existing file.",
|
|
102
|
+
"Point at a document by line number. Cite a fixed anchor (`{#id}`) or a symbol name; lines move."
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"sourceFiles": "(?<!/build)\\.rs$"
|
|
106
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "synth-creator",
|
|
3
|
+
"description": "JUCE synths and effects units: realtime audio, the sound engines, the Dawn GPU painter, Stellix. Everything the kit installed before configurations existed.",
|
|
4
|
+
"packs": {
|
|
5
|
+
"always": [
|
|
6
|
+
"base",
|
|
7
|
+
"synth-creator",
|
|
8
|
+
"writing",
|
|
9
|
+
"hook-proof"
|
|
10
|
+
],
|
|
11
|
+
"choose": [
|
|
12
|
+
"cpp",
|
|
13
|
+
"audio-core",
|
|
14
|
+
"gpu-painter",
|
|
15
|
+
"stellix",
|
|
16
|
+
"python",
|
|
17
|
+
"shell",
|
|
18
|
+
"ci",
|
|
19
|
+
"reverse-engineering",
|
|
20
|
+
"midi",
|
|
21
|
+
"sound-design",
|
|
22
|
+
"instrument-shell"
|
|
23
|
+
],
|
|
24
|
+
"default": [
|
|
25
|
+
"cpp",
|
|
26
|
+
"audio-core"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"layout": {
|
|
30
|
+
"folders": {
|
|
31
|
+
"docs": {
|
|
32
|
+
"path": "docs",
|
|
33
|
+
"purpose": "spec, laws, licences, work orders, decisions"
|
|
34
|
+
},
|
|
35
|
+
"src": {
|
|
36
|
+
"path": "src",
|
|
37
|
+
"purpose": "all source code, only inside the subfolders below"
|
|
38
|
+
},
|
|
39
|
+
"tests": {
|
|
40
|
+
"path": "tests",
|
|
41
|
+
"purpose": "unit tests, gates with planted faults, golden files"
|
|
42
|
+
},
|
|
43
|
+
"tools": {
|
|
44
|
+
"path": "tools",
|
|
45
|
+
"purpose": "scripts and research tooling (not shipped)"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"kinds": {
|
|
49
|
+
"tests": {
|
|
50
|
+
"what": "tests, gates with planted faults, golden renders",
|
|
51
|
+
"in": "tests",
|
|
52
|
+
"concepts": [
|
|
53
|
+
"tests"
|
|
54
|
+
],
|
|
55
|
+
"files": [
|
|
56
|
+
"**/*_test.*",
|
|
57
|
+
"**/*Test.cpp",
|
|
58
|
+
"**/*Tests.cpp",
|
|
59
|
+
"**/test_*.*",
|
|
60
|
+
"**/*.test.*"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
"docs": {
|
|
64
|
+
"what": "the spec, laws.md, decisions, research, work orders",
|
|
65
|
+
"in": "docs",
|
|
66
|
+
"concepts": [
|
|
67
|
+
"docs-folder"
|
|
68
|
+
],
|
|
69
|
+
"files": [
|
|
70
|
+
"**/laws.md",
|
|
71
|
+
"**/*-spec.md"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"tools": {
|
|
75
|
+
"what": "scripts and research tools that never ship",
|
|
76
|
+
"in": "tools"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"hookOrder": {
|
|
81
|
+
"PreToolUse Write|Edit|MultiEdit|NotebookEdit|Bash": [
|
|
82
|
+
"lesson-checks.mjs",
|
|
83
|
+
"file-size-guard.mjs",
|
|
84
|
+
"frozen-files.mjs",
|
|
85
|
+
"placement-law.mjs",
|
|
86
|
+
"protect-vendor.mjs",
|
|
87
|
+
"spec-lock.mjs",
|
|
88
|
+
"folder-law.mjs",
|
|
89
|
+
"shape-law.mjs",
|
|
90
|
+
"brief-guard.mjs",
|
|
91
|
+
"once-only.mjs",
|
|
92
|
+
"secrets-guard.mjs",
|
|
93
|
+
"untrusted-boundary.mjs",
|
|
94
|
+
"realtime-guard.mjs",
|
|
95
|
+
"browser-guard.py",
|
|
96
|
+
"no-shipped-images.mjs"
|
|
97
|
+
],
|
|
98
|
+
"PreToolUse Agent|Task": [
|
|
99
|
+
"brief-guard.mjs"
|
|
100
|
+
],
|
|
101
|
+
"PreToolUse Bash": [
|
|
102
|
+
"stage-guard.mjs",
|
|
103
|
+
"git-guard.mjs",
|
|
104
|
+
"build-guard.mjs"
|
|
105
|
+
],
|
|
106
|
+
"PreToolUse *": [
|
|
107
|
+
"time-guard.mjs"
|
|
108
|
+
],
|
|
109
|
+
"PostToolUse *": [
|
|
110
|
+
"time-guard.mjs"
|
|
111
|
+
],
|
|
112
|
+
"Stop": [
|
|
113
|
+
"idle-wake.mjs",
|
|
114
|
+
"making-check.mjs",
|
|
115
|
+
"git-guard.mjs"
|
|
116
|
+
],
|
|
117
|
+
"SessionStart compact": [
|
|
118
|
+
"user-asks.mjs"
|
|
119
|
+
],
|
|
120
|
+
"SessionStart": [
|
|
121
|
+
"build-sweep.mjs"
|
|
122
|
+
],
|
|
123
|
+
"SubagentStop": [
|
|
124
|
+
"build-sweep.mjs"
|
|
125
|
+
],
|
|
126
|
+
"UserPromptSubmit": [
|
|
127
|
+
"making.mjs"
|
|
128
|
+
],
|
|
129
|
+
"PostToolUse Write|Edit|MultiEdit|NotebookEdit|Bash": [
|
|
130
|
+
"param-id-lock.mjs"
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
"preamble": {
|
|
134
|
+
"always": [
|
|
135
|
+
"Ask the user before inventing a new folder. A new folder goes into `.claude/layout.json` first.",
|
|
136
|
+
"When a hook, check or guard blocks work that is correct, stop and report its exact message. A blocking hook is a red check: fix the hook first, with a selftest, then continue.",
|
|
137
|
+
"When a command is refused or fails, the step fails loudly. Never report a refused write or a failed command as done.",
|
|
138
|
+
"claude-packs (`@thedecipherist/claude-packs`) is the source of truth for every rule, check, hook and skill used to build synths. A fix to one of them, or a lesson that should hold in every synth, is made in the kit, with its test, and comes here with `npx --no-install @thedecipherist/claude-packs update`, so every synth gets it. A project edits its installed copy only to try a fix before it goes into the kit."
|
|
139
|
+
],
|
|
140
|
+
"never": [
|
|
141
|
+
"Create source files outside these folders, or put a kind of thing anywhere but its place. The folder-law and placement-law hooks refuse both.",
|
|
142
|
+
"Put drawing code in audio or world folders, or audio and world logic in the painter or UI folders.",
|
|
143
|
+
"Edit files in `.claude/rules`, `.claude/checks` or `.claude/hooks` to get past a block. Fix the code, or ask the user to change the law.",
|
|
144
|
+
"Route around a block: no override variables, no writing through the shell after a refusal, no parking files in a scratchpad, no putting new code into an unrelated existing file.",
|
|
145
|
+
"Point at a document by line number. Cite a fixed anchor (`{#id}`) or a symbol name; lines move."
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// gnu-shell (SessionStart; global by design): the Bash tool runs bash 5 with the GNU tools, not zsh with the BSD ones.
|
|
3
|
+
//
|
|
4
|
+
// "can you do a proper skill/hook for zsh because this seems to happen alot?". Claude Code's Bash tool runs
|
|
5
|
+
// the login shell, zsh on this Mac: `$VAR` holding several words is not split, an unmatched glob is an error, and
|
|
6
|
+
// `sed -i`, `date -d`, `stat -c` are the BSD tools'. The fix has two halves:
|
|
7
|
+
// 1. THE SHELL: settings.json `env` sets CLAUDE_CODE_SHELL and SHELL to /opt/homebrew/bin/bash (Homebrew's bash 5).
|
|
8
|
+
// 2. THE TOOLS: this hook writes one `export PATH=...` to the file CLAUDE_ENV_FILE names, which Claude Code sources
|
|
9
|
+
// before every Bash call: ~/.claude/bin first (buildq, the machine-wide build queue), then the `libexec/gnubin`
|
|
10
|
+
// folder of every GNU formula installed, so sed, date, stat, awk, tar, find, xargs, which are the GNU builds; and a
|
|
11
|
+
// line that warns on EVERY command while the session runs zsh (WB-41). The user's own terminal is not touched.
|
|
12
|
+
// It says so at the session's start when it cannot deliver: no Homebrew, a formula missing, the shell not bash 5.
|
|
13
|
+
// On Linux (KWB-27) the system's sed, date, stat and awk are the GNU builds already: no Homebrew is looked for, the PATH line
|
|
14
|
+
// puts only ~/.claude/bin first, and the shell is still checked for bash 5 (any bash 5, not Homebrew's).
|
|
15
|
+
// node gnu-shell.mjs --selftest
|
|
16
|
+
import { execFileSync } from 'node:child_process';
|
|
17
|
+
import { appendFileSync, chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { basename, join } from 'node:path';
|
|
20
|
+
|
|
21
|
+
export const FORMULAS = ['coreutils', 'findutils', 'gawk', 'gnu-sed', 'gnu-tar', 'gnu-which', 'grep'];
|
|
22
|
+
const BASH = '/opt/homebrew/bin/bash';
|
|
23
|
+
const isDir = (p) => { try { return statSync(p).isDirectory(); } catch { return false; } };
|
|
24
|
+
const gnubin = (pre, f) => join(pre, 'opt', f, 'libexec', 'gnubin');
|
|
25
|
+
|
|
26
|
+
// Homebrew's prefix, found on the disk, not by asking brew (a hook started by an app may not have brew on PATH).
|
|
27
|
+
export function prefix() {
|
|
28
|
+
return ['/opt/homebrew', '/usr/local'].find((p) => isDir(join(p, 'opt')) && FORMULAS.some((f) => isDir(gnubin(p, f)))) ?? null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function bashMajor(path) {
|
|
32
|
+
try { return Number(execFileSync(path, ['--version'], { encoding: 'utf8', timeout: 5000 }).match(/version (\d+)\./)?.[1] ?? 0); } catch { return 0; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const shellSaid = (sh, mac) => `gnu-shell: the Bash tool's shell is ${sh || 'unknown'}, not ${mac ? `Homebrew's bash 5 (${BASH})` : 'bash 5'}: ` +
|
|
36
|
+
'`$VAR` lists do not split (use ${=VAR} or an array) and an unmatched glob is an error. The env block in .claude/settings.json takes effect from the next session.';
|
|
37
|
+
const shellOk = (sh) => basename(sh ?? '') === 'bash' && bashMajor(sh) >= 5;
|
|
38
|
+
const ZSH_WARNING = '[ -n "$ZSH_VERSION" ] && echo "gnu-shell: THIS SESSION RUNS ZSH, not bash 5 (variables are not split into words, an unmatched glob is an error). Restart Claude Code to get bash 5." >&2\n';
|
|
39
|
+
|
|
40
|
+
// Linux: the tools are GNU already; ~/.claude/bin first, the zsh warning, and the shell checked.
|
|
41
|
+
function runLinux(envFile, shell) {
|
|
42
|
+
const said = [];
|
|
43
|
+
if (envFile) {
|
|
44
|
+
appendFileSync(envFile, 'export PATH="$HOME/.claude/bin:${PATH}"\n');
|
|
45
|
+
appendFileSync(envFile, ZSH_WARNING);
|
|
46
|
+
} else said.push('gnu-shell: CLAUDE_ENV_FILE is not set, so ~/.claude/bin could not be put first on the Bash tool\'s PATH.');
|
|
47
|
+
if (!shellOk(shell)) said.push(shellSaid(shell, false));
|
|
48
|
+
return said;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Writes the PATH line; returns what must be said (empty when all is as it should be).
|
|
52
|
+
export function run(envFile, shell, { platform = process.platform, pre } = {}) {
|
|
53
|
+
if (platform !== 'darwin') return runLinux(envFile, shell);
|
|
54
|
+
if (pre === undefined) pre = prefix();
|
|
55
|
+
const said = [];
|
|
56
|
+
if (!pre) {
|
|
57
|
+
return ["gnu-shell: no Homebrew found (/opt/homebrew or /usr/local): this session's sed, date, stat and awk are the macOS (BSD) builds, " +
|
|
58
|
+
"not GNU. Write BSD-safe commands (sed -i '' ..., no date -d)."];
|
|
59
|
+
}
|
|
60
|
+
const have = FORMULAS.filter((f) => isDir(gnubin(pre, f))).map((f) => gnubin(pre, f));
|
|
61
|
+
const missing = FORMULAS.filter((f) => !isDir(gnubin(pre, f)));
|
|
62
|
+
if (envFile && have.length) {
|
|
63
|
+
appendFileSync(envFile, `export PATH="$HOME/.claude/bin:${have.join(':')}:\${PATH}"\n`);
|
|
64
|
+
appendFileSync(envFile, ZSH_WARNING);
|
|
65
|
+
}
|
|
66
|
+
if (missing.length) {
|
|
67
|
+
said.push(`gnu-shell: GNU formula(s) not installed: ${missing.join(', ')}; those tools are the macOS (BSD) builds this session. ` +
|
|
68
|
+
`Install them with: brew install ${missing.join(' ')}`);
|
|
69
|
+
}
|
|
70
|
+
if (!envFile) said.push('gnu-shell: CLAUDE_ENV_FILE is not set, so the GNU tools could not be put first on the Bash tool\'s PATH.');
|
|
71
|
+
if (!shellOk(shell)) said.push(shellSaid(shell, true));
|
|
72
|
+
return said;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// A fake bash that reports the given version: the selftest never depends on this machine's /bin/bash (KWB-27).
|
|
76
|
+
function fakeBash(dir, version) {
|
|
77
|
+
const file = join(dir, `bash-${version}`, 'bash');
|
|
78
|
+
mkdirSync(join(dir, `bash-${version}`), { recursive: true });
|
|
79
|
+
writeFileSync(file, `#!/bin/sh\necho 'GNU bash, version ${version}(1)-release'\n`);
|
|
80
|
+
chmodSync(file, 0o755);
|
|
81
|
+
return file;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function selftest() {
|
|
85
|
+
const bad = [];
|
|
86
|
+
const expect = (name, ok) => { if (!ok) bad.push(name); };
|
|
87
|
+
const d = mkdtempSync(join(tmpdir(), 'gnu-shell-'));
|
|
88
|
+
const bash5 = fakeBash(d, '5.2.37');
|
|
89
|
+
const bash32 = fakeBash(d, '3.2.57');
|
|
90
|
+
const notBash5 = (said) => said.some((s) => s.includes('not ') && s.includes('bash 5'));
|
|
91
|
+
// macOS
|
|
92
|
+
const pre = join(d, 'brew');
|
|
93
|
+
for (const f of FORMULAS) mkdirSync(gnubin(pre, f), { recursive: true });
|
|
94
|
+
const mac = (file, shell) => run(join(d, file), shell, { platform: 'darwin', pre });
|
|
95
|
+
const said = mac('env.sh', bash5);
|
|
96
|
+
const text = readFileSync(join(d, 'env.sh'), 'utf8');
|
|
97
|
+
const line = text.split('\n')[0];
|
|
98
|
+
expect("mac: every formula's gnubin written first on PATH", FORMULAS.every((f) => line.includes(`/opt/${f}/libexec/gnubin`)) && line.endsWith(':${PATH}"'));
|
|
99
|
+
expect('mac: ~/.claude/bin first', line.startsWith('export PATH="$HOME/.claude/bin:'));
|
|
100
|
+
expect('mac: a zsh session is warned on every command (WB-41)', text.includes('[ -n "$ZSH_VERSION" ]') && text.toUpperCase().includes('RESTART'));
|
|
101
|
+
expect('mac: bash 5 and every formula: nothing said', said.length === 0);
|
|
102
|
+
expect('mac: no Homebrew is said', run(join(d, 'e1.sh'), bash5, { platform: 'darwin', pre: null }).some((s) => s.includes('no Homebrew')));
|
|
103
|
+
expect("mac: zsh as the shell is said", mac('e3.sh', '/bin/zsh').some((s) => s.includes("not Homebrew's bash 5")));
|
|
104
|
+
expect("mac: Apple's bash 3.2 is said", mac('e4.sh', bash32).some((s) => s.includes("not Homebrew's bash 5")));
|
|
105
|
+
rmSync(gnubin(pre, 'gnu-sed'), { recursive: true });
|
|
106
|
+
expect('mac: a missing formula is said, by name', mac('e2.sh', bash5).some((s) => s.includes('gnu-sed')));
|
|
107
|
+
// Linux (KWB-27): the system tools are GNU; no Homebrew is looked for, even when one is there
|
|
108
|
+
const linux = (file, shell) => run(join(d, file), shell, { platform: 'linux', pre });
|
|
109
|
+
const lsaid = linux('l1.sh', bash5);
|
|
110
|
+
const ltext = readFileSync(join(d, 'l1.sh'), 'utf8');
|
|
111
|
+
expect('linux: bash 5: nothing said (no Homebrew, no BSD tools)', lsaid.length === 0);
|
|
112
|
+
expect('linux: ~/.claude/bin first, no gnubin', ltext.split('\n')[0] === 'export PATH="$HOME/.claude/bin:${PATH}"');
|
|
113
|
+
expect('linux: a zsh session is warned on every command', ltext.includes('[ -n "$ZSH_VERSION" ]'));
|
|
114
|
+
expect('linux: zsh as the shell is said', notBash5(linux('l2.sh', '/usr/bin/zsh')));
|
|
115
|
+
expect('linux: bash 3.2 is said', notBash5(linux('l3.sh', bash32)));
|
|
116
|
+
expect('linux: no env file is said', run(undefined, bash5, { platform: 'linux' }).some((s) => s.includes('CLAUDE_ENV_FILE')));
|
|
117
|
+
rmSync(d, { recursive: true, force: true });
|
|
118
|
+
for (const b of bad) console.error(`FAIL ${b}`);
|
|
119
|
+
console.log(`gnu-shell selftest: ${bad.length ? `${bad.length} wrong` : 'OK'}`);
|
|
120
|
+
return bad.length ? 1 : 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function main() {
|
|
124
|
+
if (process.argv.includes('--selftest')) return selftest();
|
|
125
|
+
try { readFileSync(0, 'utf8'); } catch { /* no stdin */ }
|
|
126
|
+
const said = run(process.env.CLAUDE_ENV_FILE, process.env.CLAUDE_CODE_SHELL || process.env.SHELL);
|
|
127
|
+
if (said.length) console.log(said.join('\n')); // SessionStart: what is printed reaches the session's context
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
process.exit(main());
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// shell-traps (PreToolUse, Bash; global by design): refuses the shell traps that cost time on this Mac, with the right form.
|
|
3
|
+
//
|
|
4
|
+
// "make a skill that triggers the moment you touch bash" (the skill: shell-rules). A skill is read only
|
|
5
|
+
// when remembered; this hook sees every command. It refuses (exit 2):
|
|
6
|
+
// - BSD flags on the GNU tools first on PATH: `date -r <seconds>`, `stat -f`, `sed -i ''` (WB-23);
|
|
7
|
+
// - an in-place perl edit of a code file (apprack B-135: twice it wrote its text at the top of the file);
|
|
8
|
+
// - a `for` loop over an unquoted variable while the session runs zsh (the words are not split there, WB-41);
|
|
9
|
+
// - `;` chaining a destructive step (checkout --detach, rm -rf, kill) after another command (WB-19).
|
|
10
|
+
// Text inside heredoc bodies and quoted strings is ignored.
|
|
11
|
+
// node shell-traps.mjs --selftest
|
|
12
|
+
import { readFileSync } from 'node:fs';
|
|
13
|
+
import { basename } from 'node:path';
|
|
14
|
+
|
|
15
|
+
export function noHeredocs(cmd) {
|
|
16
|
+
const out = [];
|
|
17
|
+
const lines = cmd.split('\n');
|
|
18
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
19
|
+
out.push(lines[i]);
|
|
20
|
+
const m = lines[i].match(/<<-?\s*['"]?(\w+)['"]?/);
|
|
21
|
+
if (m) { i += 1; while (i < lines.length && lines[i].trim() !== m[1]) i += 1; }
|
|
22
|
+
}
|
|
23
|
+
return out.join('\n');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const bodyOf = (cmd) => noHeredocs(cmd).replace(/'[^']*'|"(?:\\.|[^"\\])*"/g, "''");
|
|
27
|
+
const zshSession = () => basename(process.env.SHELL ?? '').includes('zsh') && !(process.env.CLAUDE_CODE_SHELL ?? '').includes('bash');
|
|
28
|
+
|
|
29
|
+
export function verdict(cmd, zsh = zshSession()) {
|
|
30
|
+
const b = bodyOf(cmd);
|
|
31
|
+
if (/(^|[\s;&|(])date\s+(-\w*\s+)*-r\s+\$?\(?[\d@$]/.test(b)) {
|
|
32
|
+
return "`date -r <seconds>` is the BSD form; here date is GNU (-r means a FILE's time). Use: date -d @<seconds> '+%Y-%m-%d %H:%M %Z'";
|
|
33
|
+
}
|
|
34
|
+
if (/(^|[\s;&|(])stat\s+(-\w+\s+)*-f\s/.test(b)) {
|
|
35
|
+
return '`stat -f` is the BSD form; here stat is GNU (-f is file-SYSTEM info). Use `stat -c %Y file`, or better Python os.stat for a measurement (WB-23).';
|
|
36
|
+
}
|
|
37
|
+
if (/(^|[\s;&|(])sed\s+-i\s+(''|"")(\s|$)/.test(noHeredocs(cmd))) return "`sed -i ''` is the BSD form; here sed is GNU: `sed -i 's/a/b/' file`."; // the real quotes
|
|
38
|
+
if (/(^|[\s;&|(])perl\s+(-\w+\s+)*-\w*i\w*\b[^;&|]*\.(ts|tsx|js|mjs|cpp|cc|c|h|hpp|py|cmake)\b/.test(b)) {
|
|
39
|
+
return 'an in-place perl edit of a code file: twice it wrote its text at the top of the file instead of in place (apprack B-135). Change code with the Edit tool; perl -pi stays for data files.';
|
|
40
|
+
}
|
|
41
|
+
if (zsh && /\bfor\s+\w+\s+in\s+\$\w+\s*;/.test(b)) {
|
|
42
|
+
return 'this session runs zsh: `for x in $VAR` does not split words. Use `${=VAR}`, an explicit list, or a script file run with bash. Restart Claude Code to get bash 5 (WB-41).';
|
|
43
|
+
}
|
|
44
|
+
if (/;\s*(GUARD_OK=1\s+)?git\s+checkout\s+-q?\s*--detach|;\s*rm\s+-rf\s|;\s*kill\s/.test(b)) {
|
|
45
|
+
return 'a destructive step chained with `;` runs even when the step before it failed (WB-19). Chain with `&&`, or run it as its own command after checking the first.';
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function selftest() {
|
|
51
|
+
const cases = [
|
|
52
|
+
["TZ=America/New_York date -r 1797000000 '+%F'", false, true], ["date -d @1797000000 '+%F'", false, false],
|
|
53
|
+
["stat -f '%m %N' x", false, true], ['stat -c %Y x', false, false], ["sed -i '' 's/a/b/' f", false, true],
|
|
54
|
+
["sed -i 's/a/b/' f", false, false], ['for t in $LIST; do echo $t; done', true, true],
|
|
55
|
+
['for t in $LIST; do echo $t; done', false, false], ['for t in a b; do echo $t; done', true, false],
|
|
56
|
+
['python3 x.py; GUARD_OK=1 git checkout -q --detach', false, true], ['python3 x.py && git checkout -q --detach', false, false],
|
|
57
|
+
["echo 'date -r 5 and stat -f'", false, false], ["cat <<'EOF'\nsed -i '' x\nEOF", false, false],
|
|
58
|
+
["perl -0pi -e 's|a|b|' src/readonly.ts", false, true], ["cd x && perl -pi -e 's/a/b/' lib/a.cpp", false, true],
|
|
59
|
+
["perl -pi -e 's/a/b/' docs/not-carried.md", false, false], ["perl -0pi -e 's/a/b/' build.json", false, false],
|
|
60
|
+
["perl -ne 'print' src/a.ts", false, false],
|
|
61
|
+
];
|
|
62
|
+
const bad = cases.filter(([cmd, zsh, want]) => (verdict(cmd, zsh) !== null) !== want);
|
|
63
|
+
for (const [cmd, zsh, want] of bad) console.error(`shell-traps selftest FAILED: ${want ? 'not refused' : 'wrongly refused'}: ${cmd.replace(/\n/g, ' / ')}${zsh ? ' (zsh)' : ''}`);
|
|
64
|
+
if (!bad.length) console.log(`shell-traps selftest: OK (${cases.length} cases)`);
|
|
65
|
+
return bad.length ? 1 : 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function main() {
|
|
69
|
+
if (process.argv.includes('--selftest')) return selftest();
|
|
70
|
+
let ev;
|
|
71
|
+
try { ev = JSON.parse(readFileSync(0, 'utf8')); } catch { return 0; }
|
|
72
|
+
if (ev.tool_name !== 'Bash') return 0;
|
|
73
|
+
const v = verdict(String(ev.tool_input?.command ?? ''));
|
|
74
|
+
if (!v) return 0;
|
|
75
|
+
process.stderr.write(`shell-traps: ${v}\n`);
|
|
76
|
+
return 2;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
process.exit(main());
|