@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,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// user-asks: everything the user asked, back in front of the session, so nothing discussed is forgotten (2026-10-11:
|
|
3
|
+
// "Sometimes you 'forget' certain things we had discussed ... maybe you also need to check memory at this time?").
|
|
4
|
+
//
|
|
5
|
+
// Every message the user sends is in the session's transcript: a turn of their own (type `user`, their text) or a message sent
|
|
6
|
+
// while the session was working (a `queue-operation` enqueue). This reads them back, with their times, two ways:
|
|
7
|
+
// - a SessionStart hook on `compact`: their asks of the last HOURS hours go back into the context, word for word;
|
|
8
|
+
// - idle-wake.mjs: the wake after their silence carries the same list.
|
|
9
|
+
// THE LEDGER: each ask has a status and its evidence, beside the project's own memory folder
|
|
10
|
+
// (~/.claude/projects/<the project's path, every character not a letter or digit made a dash>/asks-ledger.json), outside
|
|
11
|
+
// git, so compaction cannot touch it. Only OPEN asks come back word for word; done or answered ones are a count; needs-user
|
|
12
|
+
// and planned ones are one line each. Marking takes evidence (a commit, a bug number, a build.md step, or where it is planned):
|
|
13
|
+
// node user-asks.mjs --transcript <path> [--hours 24] [--all]
|
|
14
|
+
// node user-asks.mjs --mark <id> done|answered|planned|needs-user|not-an-ask "<evidence>"
|
|
15
|
+
// node user-asks.mjs --selftest
|
|
16
|
+
import { createHash } from 'node:crypto';
|
|
17
|
+
import { mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { homedir, tmpdir } from 'node:os';
|
|
19
|
+
import { dirname, join, resolve } from 'node:path';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
import { asHook, isMain } from './lib/hook-log.mjs';
|
|
22
|
+
|
|
23
|
+
export const HOURS = Number(process.env.TIMS_ASKS_HOURS ?? 24);
|
|
24
|
+
const STATUSES = new Set(['done', 'answered', 'planned', 'needs-user', 'not-an-ask', 'open']);
|
|
25
|
+
const QUIET = new Set(['done', 'answered', 'not-an-ask']);
|
|
26
|
+
const HEAD = (h, n) => `TIM'S ASKS from the last ${h.toFixed(0)} hours (${n} messages). Compaction may have dropped some of them from what you remember; ` +
|
|
27
|
+
'the ledger below holds which are done, with evidence. Every OPEN one is work: check it is not already done (then mark it with the evidence), ' +
|
|
28
|
+
'finish it, or if it needs the user say so in one line and mark it needs-user. Do not wait to be reminded.';
|
|
29
|
+
|
|
30
|
+
const mainRoot = (p) => p.replace(/\/\.claude\/worktrees\/[^/]+(\/.*)?$/, '');
|
|
31
|
+
export const ledgerFor = (root) => join(homedir(), '.claude', 'projects', mainRoot(resolve(root)).replace(/[^A-Za-z0-9]/g, '-'), 'asks-ledger.json');
|
|
32
|
+
export const LEDGER = process.env.TIMS_ASKS_LEDGER || ledgerFor(process.env.CLAUDE_PROJECT_DIR ?? process.cwd());
|
|
33
|
+
|
|
34
|
+
// The user's own words in a transcript entry, or null (a tool's result, a hook's or the system's text, an agent's report).
|
|
35
|
+
function textOf(e) {
|
|
36
|
+
if (e.type === 'queue-operation' && e.operation === 'enqueue') return typeof e.content === 'string' ? e.content : null;
|
|
37
|
+
if (e.type === 'user' && !e.isMeta && !e.isSidechain) {
|
|
38
|
+
let c = e.message?.content;
|
|
39
|
+
if (Array.isArray(c)) c = c.filter((b) => b && b.type === 'text').map((b) => b.text ?? '').join('\n');
|
|
40
|
+
return typeof c === 'string' ? c : null;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const isSystem = (t) => { const s = t.trimStart(); return !s || /^(<|\[SYSTEM|\[Subagent|idle-wake:|This session is being continued|Caveat:)/.test(s); };
|
|
45
|
+
const squash = (t) => t.split(/\s+/).filter(Boolean).join(' ');
|
|
46
|
+
|
|
47
|
+
export function asks(transcript, hours = HOURS, now = Date.now() / 1000) {
|
|
48
|
+
let text;
|
|
49
|
+
try { text = readFileSync(transcript, 'utf8'); } catch { return []; }
|
|
50
|
+
const out = [];
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
for (const line of text.split('\n')) {
|
|
53
|
+
if (!line.includes('"queue-operation"') && !line.includes('"type":"user"') && !line.includes('"type": "user"')) continue;
|
|
54
|
+
let e;
|
|
55
|
+
try { e = JSON.parse(line); } catch { continue; }
|
|
56
|
+
const t = textOf(e);
|
|
57
|
+
if (!t || isSystem(t)) continue;
|
|
58
|
+
const when = e.timestamp ? Date.parse(e.timestamp) / 1000 : null;
|
|
59
|
+
if (when !== null && !Number.isNaN(when) && now - when > hours * 3600) continue;
|
|
60
|
+
const key = squash(t);
|
|
61
|
+
if (seen.has(key)) continue;
|
|
62
|
+
seen.add(key);
|
|
63
|
+
out.push([Number.isNaN(when) ? null : when, t.trim()]);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const askId = (t) => createHash('sha1').update(squash(t)).digest('hex').slice(0, 8);
|
|
69
|
+
export function loadLedger(path = LEDGER) { try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return {}; } }
|
|
70
|
+
|
|
71
|
+
export function mark(id, status, evidence = '', path = LEDGER) {
|
|
72
|
+
if (!STATUSES.has(status)) throw new Error(`status is one of ${[...STATUSES].sort().join(', ')}`);
|
|
73
|
+
if (status !== 'open' && !evidence.trim()) throw new Error('evidence is required: a commit, a bug number, a build.md step, or where it is planned');
|
|
74
|
+
const led = loadLedger(path);
|
|
75
|
+
led[id] = { status, evidence: evidence.trim(), marked: new Date().toISOString().slice(0, 19) };
|
|
76
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
77
|
+
writeFileSync(`${path}.tmp`, JSON.stringify(led, null, 1));
|
|
78
|
+
renameSync(`${path}.tmp`, path);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function render(items, hours = HOURS, ledger = null, every = false) {
|
|
82
|
+
if (!items.length) return '';
|
|
83
|
+
const led = ledger ?? loadLedger();
|
|
84
|
+
const stamp = (w) => (w ? new Date(w * 1000).toISOString().slice(5, 16).replace('T', ' ') : ' ? ');
|
|
85
|
+
const rows = items.map(([w, t]) => { const id = askId(t); return { w, t, id, st: led[id]?.status ?? 'open', ev: led[id]?.evidence ?? '' }; });
|
|
86
|
+
const open = rows.filter((r) => r.st === 'open');
|
|
87
|
+
const waits = rows.filter((r) => r.st === 'needs-user' || r.st === 'planned');
|
|
88
|
+
const quiet = rows.filter((r) => QUIET.has(r.st));
|
|
89
|
+
const lines = [HEAD(hours, items.length),
|
|
90
|
+
`LEDGER (${LEDGER}): ${quiet.length} done or answered, ${waits.length} waiting on the user or planned, ${open.length} OPEN. Only the open ones are work; ` +
|
|
91
|
+
'do not redo a done one. When one is done, mark it with its evidence: node .claude/hooks/user-asks.mjs --mark <id> done "<commit / bug / step>" ' +
|
|
92
|
+
'(or answered, planned, needs-user, not-an-ask).'];
|
|
93
|
+
if (open.length) { lines.push('OPEN, word for word:'); for (const r of open) lines.push(`- ${r.id} [${stamp(r.w)}] ${squash(r.t).slice(0, 1200)}`); }
|
|
94
|
+
if (waits.length) { lines.push('WAITING (one line each):'); for (const r of waits) lines.push(`- ${r.id} [${stamp(r.w)}] ${r.st}: ${r.ev.slice(0, 160)} <- ${squash(r.t).slice(0, 90)}`); }
|
|
95
|
+
if (every && quiet.length) { lines.push('DONE / ANSWERED:'); for (const r of quiet) lines.push(`- ${r.id} [${stamp(r.w)}] ${r.st}: ${r.ev.slice(0, 120)} <- ${squash(r.t).slice(0, 90)}`); }
|
|
96
|
+
return lines.join('\n');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function selftest() {
|
|
100
|
+
const now = Date.now() / 1000;
|
|
101
|
+
const iso = (dt) => new Date((now - dt) * 1000).toISOString();
|
|
102
|
+
const rows = [
|
|
103
|
+
{ type: 'user', timestamp: iso(3600), message: { content: 'add 20 80s bass arps' } },
|
|
104
|
+
{ type: 'queue-operation', operation: 'enqueue', timestamp: iso(1800), content: 'and make a hook for chrome' },
|
|
105
|
+
{ type: 'queue-operation', operation: 'remove', timestamp: iso(1799), content: 'and make a hook for chrome' },
|
|
106
|
+
{ type: 'user', timestamp: iso(1700), message: { content: [{ type: 'tool_result', content: 'ok' }] } },
|
|
107
|
+
{ type: 'user', timestamp: iso(1600), message: { content: '<task-notification>done</task-notification>' } },
|
|
108
|
+
{ type: 'user', timestamp: iso(1500), isMeta: true, message: { content: 'a meta line' } },
|
|
109
|
+
{ type: 'user', timestamp: iso(90000), message: { content: 'an ask from two days ago' } },
|
|
110
|
+
{ type: 'user', timestamp: iso(60), message: { content: [{ type: 'text', text: 'is it correct the agents still run?' }] } },
|
|
111
|
+
{ type: 'assistant', timestamp: iso(30), message: { content: "Next I'd build P4." } },
|
|
112
|
+
];
|
|
113
|
+
const t = join(tmpdir(), `user-asks-${process.pid}.jsonl`);
|
|
114
|
+
writeFileSync(t, rows.map((r) => JSON.stringify(r)).join('\n'));
|
|
115
|
+
const items = asks(t, 24, now);
|
|
116
|
+
rmSync(t, { force: true });
|
|
117
|
+
const led = `${t}.ledger.json`;
|
|
118
|
+
mark(askId('add 20 80s bass arps'), 'done', 'commit abc123', led);
|
|
119
|
+
const out = render(items, 24, loadLedger(led));
|
|
120
|
+
rmSync(led, { force: true });
|
|
121
|
+
const checks = [
|
|
122
|
+
['a done ask is counted, not listed; the open ones are listed word for word', out.includes('1 done or answered') && out.includes('2 OPEN') && !out.includes('add 20 80s bass arps') && out.includes('and make a hook for chrome')],
|
|
123
|
+
['done without evidence is refused', (() => { try { mark('x', 'done', '', led); return false; } catch { return true; } })()],
|
|
124
|
+
["the user's own words, mid-turn ones too, no tool results, system text, meta lines, their old asks or the assistant",
|
|
125
|
+
JSON.stringify(items.map(([, x]) => x)) === JSON.stringify(['add 20 80s bass arps', 'and make a hook for chrome', 'is it correct the agents still run?'])],
|
|
126
|
+
["the ledger is the project's own, beside its memory, and a worktree's is its project's",
|
|
127
|
+
ledgerFor('/Users/dev/projects/my_synth') === join(homedir(), '.claude/projects/-Users-dev-projects-my-synth/asks-ledger.json') &&
|
|
128
|
+
ledgerFor('/Users/dev/projects/my_synth/.claude/worktrees/agent-x') === ledgerFor('/Users/dev/projects/my_synth')],
|
|
129
|
+
];
|
|
130
|
+
for (const [name, ok] of checks) if (!ok) console.error(`FAIL ${name}`);
|
|
131
|
+
const bad = checks.filter(([, ok]) => !ok).length;
|
|
132
|
+
console.log(`user-asks selftest: ${bad ? 'FAIL' : 'OK'}`);
|
|
133
|
+
return bad ? 1 : 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function main(argv) {
|
|
137
|
+
if (argv.includes('--selftest')) return selftest();
|
|
138
|
+
const i = argv.indexOf('--mark');
|
|
139
|
+
if (i >= 0) {
|
|
140
|
+
try { mark(argv[i + 1], argv[i + 2], argv[i + 3] ?? ''); } catch (e) { console.error(e.message); return 1; }
|
|
141
|
+
console.log(`marked ${argv[i + 1]} ${argv[i + 2]}`);
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
const ti = argv.indexOf('--transcript');
|
|
145
|
+
if (ti >= 0) {
|
|
146
|
+
const h = argv.includes('--hours') ? Number(argv[argv.indexOf('--hours') + 1]) : HOURS;
|
|
147
|
+
console.log(render(asks(argv[ti + 1], h), h, null, argv.includes('--all')));
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
// A HOOK (SessionStart on compact): what it prints is added to the session's context
|
|
151
|
+
return asHook('user-asks', hookMain);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function hookMain(input) {
|
|
155
|
+
let event;
|
|
156
|
+
try { event = JSON.parse(input); } catch { return 0; }
|
|
157
|
+
const text = render(asks(event.transcript_path ?? ''));
|
|
158
|
+
if (text) console.log(text);
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
export const hook = hookMain; // run-hooks.mjs calls it with the event's text (KWB-24)
|
|
162
|
+
|
|
163
|
+
// Run as a hook or a command (not imported by idle-wake). Real paths: /var and /private/var are one folder on a Mac.
|
|
164
|
+
const real = (p) => { try { return realpathSync(p); } catch { return resolve(p); } };
|
|
165
|
+
if (process.argv[1] && real(process.argv[1]) === real(fileURLToPath(import.meta.url))) process.exit(await main(process.argv.slice(2)));
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "synth-creator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "The synth-creator configuration's own laws, installed with it and never by another: the build queue (build-guard), the time watch, the spec lock, frozen fixes, read-only vendored code and copy trees, staging by name, the session watches (idle-wake, user-asks, build-sweep), and the rules and skill a synth build lives by.",
|
|
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/synth-creator"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"synth",
|
|
16
|
+
"build"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"claude-packs": ">=0.19.0"
|
|
20
|
+
},
|
|
21
|
+
"configurationPack": true,
|
|
22
|
+
"folders": {},
|
|
23
|
+
"concepts": {},
|
|
24
|
+
"skillsIn": null,
|
|
25
|
+
"hooks": {
|
|
26
|
+
"PreToolUse": [
|
|
27
|
+
{
|
|
28
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|Bash",
|
|
29
|
+
"hooks": [
|
|
30
|
+
{
|
|
31
|
+
"type": "command",
|
|
32
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/frozen-files.mjs\"",
|
|
33
|
+
"timeout": 10
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "command",
|
|
37
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/protect-vendor.mjs\"",
|
|
38
|
+
"timeout": 10
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"type": "command",
|
|
42
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/spec-lock.mjs\"",
|
|
43
|
+
"timeout": 10
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"matcher": "Bash",
|
|
49
|
+
"hooks": [
|
|
50
|
+
{
|
|
51
|
+
"type": "command",
|
|
52
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/stage-guard.mjs\"",
|
|
53
|
+
"timeout": 10
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "command",
|
|
57
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/build-guard.mjs\"",
|
|
58
|
+
"timeout": 15
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"matcher": "*",
|
|
64
|
+
"hooks": [
|
|
65
|
+
{
|
|
66
|
+
"type": "command",
|
|
67
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/time-guard.mjs\"",
|
|
68
|
+
"timeout": 15
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"PostToolUse": [
|
|
74
|
+
{
|
|
75
|
+
"matcher": "*",
|
|
76
|
+
"hooks": [
|
|
77
|
+
{
|
|
78
|
+
"type": "command",
|
|
79
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/time-guard.mjs\"",
|
|
80
|
+
"timeout": 15
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"Stop": [
|
|
86
|
+
{
|
|
87
|
+
"hooks": [
|
|
88
|
+
{
|
|
89
|
+
"type": "command",
|
|
90
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/idle-wake.mjs\"",
|
|
91
|
+
"asyncRewake": true,
|
|
92
|
+
"timeout": 1000
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"SessionStart": [
|
|
98
|
+
{
|
|
99
|
+
"matcher": "compact",
|
|
100
|
+
"hooks": [
|
|
101
|
+
{
|
|
102
|
+
"type": "command",
|
|
103
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/user-asks.mjs\"",
|
|
104
|
+
"timeout": 15
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"hooks": [
|
|
110
|
+
{
|
|
111
|
+
"type": "command",
|
|
112
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/build-sweep.mjs\"",
|
|
113
|
+
"timeout": 15
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"SubagentStop": [
|
|
119
|
+
{
|
|
120
|
+
"hooks": [
|
|
121
|
+
{
|
|
122
|
+
"type": "command",
|
|
123
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/build-sweep.mjs\"",
|
|
124
|
+
"timeout": 15
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
"optIn": [
|
|
131
|
+
"hooks/user-asks.mjs",
|
|
132
|
+
"hooks/idle-wake.mjs",
|
|
133
|
+
"hooks/build-sweep.mjs",
|
|
134
|
+
"checks/ui-drawn-in-code.json"
|
|
135
|
+
]
|
|
136
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: copy-trees
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Copy trees: copied, pinned, read-only
|
|
8
|
+
|
|
9
|
+
A copy tree is a folder of kind `"copy"` in `.claude/layout.json`: another project's code, copied unchanged and proved
|
|
10
|
+
identical (the `copy-and-prove` skill). This rule loads in every copy tree and in `layout.json`, where one is declared.
|
|
11
|
+
|
|
12
|
+
<constraints>
|
|
13
|
+
Always do:
|
|
14
|
+
- Treat every file here as a copy of another project's file at a named commit. It changes only through the project's copy tools (`guards.copy.tools` in `layout.json`): from its source, unchanged, or as a pinned change the user said yes to and null tests proved.
|
|
15
|
+
- Give every file its origin before it comes in (repo, path, commit, SHA-256, licence row). The licence row in `docs/licences.md` comes first.
|
|
16
|
+
- Prove the copy before anything uses it: the source's own render fingerprinted, the copy IDENTICAL, one coefficient changed in the copy seen DIFFERENT.
|
|
17
|
+
- Fix the code that uses the copy. If the copy itself must change, ask the user and pin the change.
|
|
18
|
+
- Start a new copy tree only in `.claude/layout.json`, as a folder with `"kind": "copy"`. The guard, this rule and the checks then cover it with no other change.
|
|
19
|
+
- Change a file that measured identical only after it is promoted out of the copy tree into the project's own code (a folder of kind `"own"`), with its origin record kept.
|
|
20
|
+
|
|
21
|
+
Never do:
|
|
22
|
+
- Edit, write, move or delete a file here by hand or by shell. The `protect-vendor` hook refuses it; only git and the sanctioned copy tools get through.
|
|
23
|
+
- Put a file here without its origin.
|
|
24
|
+
- Copy hardware, brand or machine names into anything that reaches the product: a program name, a label, a string in the binary.
|
|
25
|
+
</constraints>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: cpp, tests
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Debug by measuring, one hypothesis at a time
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Reproduce first, then measure: render the case offline, read the numbers (`measure-tone`, a probe, a sanitizer, a log), and only then form a cause.
|
|
12
|
+
- State one falsifiable hypothesis ("the click is the filter state reset at voice steal, because the click lines up with sample N of the steal") and test it with one change.
|
|
13
|
+
- Treat "the host is wrong", "it's JUCE", "it's the driver" as a hypothesis to disprove with a minimal probe, never as the answer. Assume our code is wrong until a probe proves otherwise.
|
|
14
|
+
- After three fixes that didn't work, stop changing code. Report what was tried, what each measurement showed, and whether the design itself is the problem.
|
|
15
|
+
|
|
16
|
+
Never do:
|
|
17
|
+
- Change several things at once, then listen.
|
|
18
|
+
- Tweak constants until it "sounds right" without a measurement before and after.
|
|
19
|
+
- Start a fourth fix attempt on the same symptom without telling the user.
|
|
20
|
+
</constraints>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: tests, build
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# "Done" means evidence from this turn
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Before saying done, fixed, passing, faster or "sounds the same", run the command that proves it in this turn and quote its verdict: test-verdict JSON, null-test result in dBFS, benchmark p99, golden-image score.
|
|
12
|
+
- Say exactly what was not verified, and why ("not run on Windows", "listened only, not measured").
|
|
13
|
+
- Treat a subagent's report as a claim. Check its diff and re-run its verdict before passing it on.
|
|
14
|
+
|
|
15
|
+
Never do:
|
|
16
|
+
- Report success from memory of an earlier run, from a build that only compiled, or from "should work".
|
|
17
|
+
- Report a partial pass as a pass.
|
|
18
|
+
</constraints>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: tooling
|
|
3
|
+
paths:
|
|
4
|
+
- "placeholder"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Hooks, gates and tools: each seen red, each fault logged
|
|
8
|
+
|
|
9
|
+
<constraints>
|
|
10
|
+
Always do:
|
|
11
|
+
- Give every hook and gate a `--selftest` that plants its fault, and run it from the project's plants script (the `plants` command in `.claude/layout.json`). A new gate goes in there in the same commit. A gate that has never been seen red proves nothing.
|
|
12
|
+
- Log a workflow fault (a hook, a tool, the build queue, a test run) in `workflow-bugs.md` before fixing it (the `workflow-bugs` skill), and close it with cause, fix and what now catches it.
|
|
13
|
+
- Run Python on files that come from outside with `-I`. Measure files with Python, not with BSD or GNU tool flags.
|
|
14
|
+
- Keep a planted fault in the test build only: one macro or `constexpr` flag that is false in the shipped binary, and a release gate that searches the binary for it (`cpp-faults-only-in-the-test-build`).
|
|
15
|
+
- Treat a hook that blocks correct work as a red check: stop, report its exact message, and log it. The hook is fixed first, with a selftest that plants the right case and the wrong one; the work resumes after.
|
|
16
|
+
- Make a fix to a hook, rule, check or skill that every synth uses in claude-packs, with its test, then take it in with `npx --no-install @thedecipherist/claude-packs update`. Only a law that is about this project alone stays in this project's `.claude/`.
|
|
17
|
+
|
|
18
|
+
Never do:
|
|
19
|
+
- Route around a block: no code put into an unrelated existing file, no file pushed past the line limit, no write through the shell after a refusal, no override variable.
|
|
20
|
+
- Change a hook so that its own selftest passes while the fault it exists for gets through.
|
|
21
|
+
</constraints>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
# hook: time-guard.mjs
|
|
3
|
+
---
|
|
4
|
+
# Long work runs in the background, and a warning about time is acted on
|
|
5
|
+
|
|
6
|
+
<constraints>
|
|
7
|
+
Always do:
|
|
8
|
+
- Start anything over about two minutes as a background job with its output in a file; you are told when it ends. Do other work meanwhile.
|
|
9
|
+
- When `time-guard` says something is slow, look at it now: find what is running, say so, and stop it if it is not needed.
|
|
10
|
+
- Commit an agent's work when `time-guard` says it has gone unsaved.
|
|
11
|
+
|
|
12
|
+
Never do:
|
|
13
|
+
- Wait in a `sleep`, `until` or `pgrep` loop, or poll a job's output file.
|
|
14
|
+
- Start a second copy of a job that is still running, or start it again without reading why the first one ended.
|
|
15
|
+
- Treat a slow job as normal because the last one was slow too.
|
|
16
|
+
</constraints>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
# concepts: cpp
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Time and keys come from synthcore: one clock, written once
|
|
6
|
+
|
|
7
|
+
<constraints>
|
|
8
|
+
Always do:
|
|
9
|
+
- Link `synthcore` for tempo, MIDI clock, transport, sync modes, QWERTY and the focus rule. Subclass `core::CoreHost`, and make `host.readTransport (getPlayHead(), midi, n);` the first line of `processBlock`.
|
|
10
|
+
- Have every tempo-synced thing read the one master clock. Tap tempo sets the same `bpm` parameter the clock reads.
|
|
11
|
+
- Fix a fault in the clock in `synthcore`, once, with its test, and take it in everywhere.
|
|
12
|
+
|
|
13
|
+
Never do:
|
|
14
|
+
- Read the play head, count MIDI clock bytes or work out a tempo in a unit. `timing-from-synthcore` refuses it.
|
|
15
|
+
- Copy `synthcore`'s code into a unit, or write a second clock because one thing needs it.
|
|
16
|
+
</constraints>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-step
|
|
3
|
+
description: Use when work begins on a step of a synth's build.md, when a step's "done when" may be met, when a session starts or ends in a repo with a build.md, or when someone asks where the build is. Also /build-step.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# One build step: its own branch, from start to merge
|
|
7
|
+
|
|
8
|
+
The canonical text is the repo's own `build.md` ("Rules for this file") and its `CLAUDE.md`. This file is the operating
|
|
9
|
+
summary. Where they disagree, the repo wins. The step tool is the project's (the `step` command in `.claude/layout.json`,
|
|
10
|
+
usually `python3 tools/step.py`); if the repo has none, copy `tools/step.py` and `tools/hooks/` from a sibling synth that
|
|
11
|
+
has them before doing any of this by hand.
|
|
12
|
+
|
|
13
|
+
The house rule: **every build task is built in a new branch. Once completed it is merged into the
|
|
14
|
+
trunk. We must not be able to lose any work.** MegaSynth lost two days of panel work to one checkout, more to work nobody
|
|
15
|
+
had written down as started, and more to steps called done because the code compiled. A step is a promise with a
|
|
16
|
+
measurement on the end, and a pushed branch is what a dead session leaves behind.
|
|
17
|
+
|
|
18
|
+
## 0. Before acting on a paste from the user
|
|
19
|
+
|
|
20
|
+
- If the project's spec carries an edition line ("Spec edition: ..." at the top of `docs/*-spec.md`) and the paste names an
|
|
21
|
+
edition, check the file shows it. Older, or no line: **stop and say so**, naming both editions.
|
|
22
|
+
- Every file a paste names must be there. One missing or older: **stop and tell the user**, naming the file and what was found;
|
|
23
|
+
do not carry on with the parts that do not depend on it.
|
|
24
|
+
|
|
25
|
+
## 1. At the start of a session
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
python3 tools/step.py status
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
It prints the count, the current step, the branch you are on, uncommitted changes and every branch not yet merged, with
|
|
32
|
+
its last commit. An unmerged branch is unfinished work: read its last commit message and its In-progress row before
|
|
33
|
+
starting anything else. Read `bugs.md`'s Open table too.
|
|
34
|
+
|
|
35
|
+
**If the work in front of you is not a step in build.md, stop and ask the user whether the plan has changed.** A bug fix or a
|
|
36
|
+
change of plan the user has agreed goes on `start --work <name> "task"` and is merged with `land`.
|
|
37
|
+
|
|
38
|
+
## 2. Start: the branch comes first
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
python3 tools/step.py start <STEP> "<the task, smaller than the step>"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This makes the step's branch from the trunk, writes the task under "In progress" with its start time (date, time, zone),
|
|
45
|
+
commits and pushes the branch. Nothing is committed straight onto the trunk; `git-guard` refuses it.
|
|
46
|
+
|
|
47
|
+
Read the step's "done when" now and decide how it will be measured. If it cannot be measured or seen in the opened app,
|
|
48
|
+
say so before building.
|
|
49
|
+
|
|
50
|
+
### The shape comes first (KWB-1)
|
|
51
|
+
|
|
52
|
+
Before any code, name every concept the step touches and find its row in `design/shape.json` (ONE with its frozen id, or
|
|
53
|
+
MANY with its count, generator, selectors and declared constants).
|
|
54
|
+
|
|
55
|
+
- **A concept the step introduces gets its row first, as the step's first commit** (`step.py save "shape: <concept> row"`
|
|
56
|
+
with only `design/shape.json` in it), before any code that uses it. `shape-law` refuses an instance type with no row.
|
|
57
|
+
- Build for the shape: one loop over every instance, or the generator. Test the behaviour once, on the template (`test-the-template-once`). An instance a bug was seen in goes on a `seen in:`
|
|
58
|
+
line; a rule that picks one is a selector listed in the row; a fixed one is a named constant there. Anything else is
|
|
59
|
+
refused with "example, rule, or constant?".
|
|
60
|
+
- **Every subagent brief quotes the manifest row of every concept it touches, word for word**, and names the shape and
|
|
61
|
+
the generator, never an instance (`brief-guard` refuses "drive slot 2"; "seen in: slot 2, build for all slots" passes).
|
|
62
|
+
- `npx --no-install @thedecipherist/claude-packs shape scan` lists what the repo already names by instance; a step that touches such a file fixes its
|
|
63
|
+
lines or leaves them as they were, never adds to them.
|
|
64
|
+
|
|
65
|
+
## 3. While working: save often
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
python3 tools/step.py save "<what state it is in>" [--paths <new files>]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Commits everything changed and pushes the branch. Run it after every unit of work, before any risky command, and
|
|
72
|
+
**always before a session ends**, saying if the work was interrupted and what is half done. It lists new files it was not
|
|
73
|
+
told about; name them or ignore them, never leave them floating.
|
|
74
|
+
|
|
75
|
+
- A bug goes into `bugs.md` the moment it is found, before it is fixed.
|
|
76
|
+
- A red tripwire gate stops all other work.
|
|
77
|
+
- Steps that run side by side each have their own branch. Switch with `start`; it refuses to switch over uncommitted work.
|
|
78
|
+
|
|
79
|
+
## 4. Is it done?
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
python3 tools/step.py check
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
It runs the mechanical checks and prints the repo's "Runs through every step" list to walk by eye. Run the project's
|
|
86
|
+
plants script (the `plants` command) before ticking: every planted fault red. Then the step's own "done when":
|
|
87
|
+
|
|
88
|
+
- **Measured or seen in the opened app.** Rebuilt, opened, pressed. Not "wired", not "compiles", not "the test I just
|
|
89
|
+
wrote passes".
|
|
90
|
+
- A gate that passed first time is suspect. Plant the fault it exists to catch and watch it fail.
|
|
91
|
+
- Say which artefact was checked: the standalone, a probe, a picture the app rendered itself.
|
|
92
|
+
|
|
93
|
+
If any part is not met, the step is not done. Say which part, `save`, and keep working or ask. The branch stays open;
|
|
94
|
+
that is what it is for.
|
|
95
|
+
|
|
96
|
+
## 5. Finish: merge into the trunk
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
python3 tools/step.py finish <STEP> --proof "<what was measured, with numbers>" [--paths <new files>]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
On the step's branch. It brings the trunk into the branch first, ticks and dates the step, moves its In-progress row to
|
|
103
|
+
the log with the finish time and what the step took, updates "Where we are" and the count, commits, merges into the trunk
|
|
104
|
+
with a merge commit, writes that commit's short hash into the log line in a second commit, and pushes the trunk and the
|
|
105
|
+
branch.
|
|
106
|
+
|
|
107
|
+
It refuses an empty proof, a step that is not the current one (side-by-side steps take `--out-of-order`), and unnamed new
|
|
108
|
+
files. If a merge conflicts it stops with both sides intact: resolve by hand, never by throwing a side away, and ask the user
|
|
109
|
+
if it is not obvious which line is right. If it prints NOT PUSHED, push with the command it shows. A step is not finished
|
|
110
|
+
until the trunk is pushed.
|
|
111
|
+
|
|
112
|
+
## 6. Tell the user
|
|
113
|
+
|
|
114
|
+
Conclusion first, in plain language: the step, what proved it, the new count, the next step. Show the changed `build.md`.
|
|
115
|
+
Never claim a step works that has not been built, opened and measured.
|
|
116
|
+
|
|
117
|
+
## Never
|
|
118
|
+
|
|
119
|
+
- Delete a branch, here or on GitHub. Rebase, amend, squash or force-push. `git add -A`.
|
|
120
|
+
- `checkout`, `restore`, `stash` or `reset --hard` over uncommitted work. `save` first.
|
|
121
|
+
- Commit straight onto the trunk. Pass `--no-verify`.
|
|
122
|
+
- Delete a step from build.md: strike it through with the reason and the date. A reopened step keeps its line, marked
|
|
123
|
+
REOPENED.
|
|
124
|
+
- Tick from memory of an earlier session. Measure again.
|
|
125
|
+
- Soften a red test in a commit message.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-through-the-queue
|
|
3
|
+
description: Use when about to compile, run ctest, or run a program from a build folder, or when build-guard refused a command.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build through the queue (one job: no build takes the whole machine)
|
|
7
|
+
|
|
8
|
+
<constraints>
|
|
9
|
+
Always do:
|
|
10
|
+
1. Use the project's wrapper first: the `build` and `test` commands in `.claude/layout.json`. Otherwise run `buildq <command>` (`~/.claude/bin/buildq`).
|
|
11
|
+
2. The queue runs two at a time and waits for a slot by itself; `buildq --status` shows the slots. Run it in the foreground, or as a background job.
|
|
12
|
+
3. As an agent, build only the targets the change needs (`--target X --target Y`) and run only its tests (`-R 'pattern'`, at most 30).
|
|
13
|
+
4. An agent started as `KIND: light` does not build or run tests: do the light part, and say in the report what needs building.
|
|
14
|
+
|
|
15
|
+
Never do:
|
|
16
|
+
- Run `cmake --build`, `ctest`, `make`, `ninja`, `xcodebuild`, or a program from a build folder straight from the shell.
|
|
17
|
+
- Wrap a build in a wait loop.
|
|
18
|
+
- Build every target from an agent: the whole build runs once, before landing.
|
|
19
|
+
</constraints>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Freeze the files that define "fixed" before changing the code that must satisfy them.
|
|
3
|
+
// node .claude/tools/freeze.mjs on "<reason>" <file-or-glob>...
|
|
4
|
+
// node .claude/tools/freeze.mjs off
|
|
5
|
+
// node .claude/tools/freeze.mjs status
|
|
6
|
+
// The frozen-files hook refuses edits to anything on the list until it is turned off.
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
|
|
10
|
+
const ROOT = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
11
|
+
const STATE = join(ROOT, '.claude', 'state', 'frozen.json');
|
|
12
|
+
const [cmd, reason, ...files] = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
const USAGE = 'usage: freeze.mjs on "<reason>" <files...> | off | status';
|
|
15
|
+
|
|
16
|
+
function on() {
|
|
17
|
+
if (!reason || files.length === 0) {
|
|
18
|
+
console.error('usage: freeze.mjs on "<reason>" <file-or-glob>...');
|
|
19
|
+
return 2;
|
|
20
|
+
}
|
|
21
|
+
mkdirSync(join(ROOT, '.claude', 'state'), { recursive: true });
|
|
22
|
+
const prev = existsSync(STATE) ? JSON.parse(readFileSync(STATE, 'utf8')).files ?? [] : [];
|
|
23
|
+
const all = [...new Set([...prev, ...files])];
|
|
24
|
+
writeFileSync(STATE, `${JSON.stringify({ reason, files: all, since: new Date().toISOString() }, null, 2)}\n`);
|
|
25
|
+
console.log(`frozen (${reason}):\n${all.map((f) => ` ${f}`).join('\n')}`);
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const COMMANDS = {
|
|
30
|
+
on,
|
|
31
|
+
off: () => (rmSync(STATE, { force: true }), console.log('nothing frozen'), 0),
|
|
32
|
+
status: () => (console.log(existsSync(STATE) ? readFileSync(STATE, 'utf8') : 'nothing frozen'), 0),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const run = Object.hasOwn(COMMANDS, cmd) ? COMMANDS[cmd] : () => (console.error(USAGE), 2);
|
|
36
|
+
process.exit(run());
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "tui-entry-restores-terminal",
|
|
3
|
+
"why": "Entering the alternate screen or raw mode without an exit handler that restores them strands the user in a broken terminal after a crash. process.once('exit', restore), registered before the first render.",
|
|
4
|
+
"rule": ".claude/rules/tui-resize-and-screen.md",
|
|
5
|
+
"concepts": [
|
|
6
|
+
"tui",
|
|
7
|
+
"tui-entry"
|
|
8
|
+
],
|
|
9
|
+
"exclude": [
|
|
10
|
+
"**/node_modules/**",
|
|
11
|
+
"**/dist/**",
|
|
12
|
+
"**/build/**",
|
|
13
|
+
".claude/**",
|
|
14
|
+
"**/.claude/**",
|
|
15
|
+
"**/*.test.*",
|
|
16
|
+
"**/test/**"
|
|
17
|
+
],
|
|
18
|
+
"code": false,
|
|
19
|
+
"mode": "needs",
|
|
20
|
+
"pattern": "\\?1049h|setRawMode\\s*\\(\\s*true\\s*\\)",
|
|
21
|
+
"needs": [
|
|
22
|
+
"\\?1049l|setRawMode\\s*\\(\\s*(?:false|wasRaw|prev\\w*|was\\w*)\\s*\\)",
|
|
23
|
+
"process\\.(?:once|on)\\s*\\(\\s*['\\\"](?:exit|SIGINT)['\\\"]"
|
|
24
|
+
],
|
|
25
|
+
"bad": "process.stdout.write('\\x1B[?1049h\\x1B[?25l');\nconst { waitUntilExit } = render(<App />);",
|
|
26
|
+
"good": "process.stdout.write('\\x1B[?1049h\\x1B[?25l');\nconst restore = () => process.stdout.write('\\x1B[?25h\\x1B[?1049l');\nprocess.once('exit', restore);\nconst { waitUntilExit } = render(<App />);"
|
|
27
|
+
}
|