@erclx/canon 4.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/LICENSE +21 -0
- package/README.md +129 -0
- package/claude/.claude-plugin/plugin.json +19 -0
- package/claude/skills/bash-cli-script/REQUIREMENT.md +42 -0
- package/claude/skills/bash-cli-script/SKILL.md +48 -0
- package/claude/skills/bash-cli-script/references/template.md +43 -0
- package/claude/skills/bash-script/REQUIREMENT.md +36 -0
- package/claude/skills/bash-script/SKILL.md +100 -0
- package/claude/skills/bash-script/references/patterns.md +349 -0
- package/claude/skills/canon-cli/REQUIREMENT.md +41 -0
- package/claude/skills/canon-cli/SKILL.md +103 -0
- package/claude/skills/canon-feedback-file/REQUIREMENT.md +40 -0
- package/claude/skills/canon-feedback-file/SKILL.md +80 -0
- package/claude/skills/canon-feedback-triage/REQUIREMENT.md +40 -0
- package/claude/skills/canon-feedback-triage/SKILL.md +63 -0
- package/claude/skills/canon-operator/REQUIREMENT.md +61 -0
- package/claude/skills/canon-operator/SKILL.md +108 -0
- package/claude/skills/canon-rollout/REQUIREMENT.md +59 -0
- package/claude/skills/canon-rollout/SKILL.md +147 -0
- package/claude/skills/canon-screencast/REQUIREMENT.md +39 -0
- package/claude/skills/canon-screencast/SKILL.md +167 -0
- package/claude/skills/canon-slides-draft/REQUIREMENT.md +39 -0
- package/claude/skills/canon-slides-draft/SKILL.md +62 -0
- package/claude/skills/ci-workflow/REQUIREMENT.md +40 -0
- package/claude/skills/ci-workflow/SKILL.md +65 -0
- package/claude/skills/ci-workflow/references/workflows.md +98 -0
- package/claude/skills/claude-address-review/REQUIREMENT.md +57 -0
- package/claude/skills/claude-address-review/SKILL.md +212 -0
- package/claude/skills/claude-address-review/references/rebase-conflicts.md +39 -0
- package/claude/skills/claude-autoship/REQUIREMENT.md +50 -0
- package/claude/skills/claude-autoship/SKILL.md +207 -0
- package/claude/skills/claude-design-extract/REQUIREMENT.md +42 -0
- package/claude/skills/claude-design-extract/SKILL.md +102 -0
- package/claude/skills/claude-diagram/REQUIREMENT.md +45 -0
- package/claude/skills/claude-diagram/SKILL.md +177 -0
- package/claude/skills/claude-docs/REQUIREMENT.md +60 -0
- package/claude/skills/claude-docs/SKILL.md +287 -0
- package/claude/skills/claude-docs/references/anchor-sweep.md +58 -0
- package/claude/skills/claude-docs/references/wireframe-sweep.md +45 -0
- package/claude/skills/claude-feature/REQUIREMENT.md +36 -0
- package/claude/skills/claude-feature/SKILL.md +115 -0
- package/claude/skills/claude-groundwork/REQUIREMENT.md +48 -0
- package/claude/skills/claude-groundwork/SKILL.md +142 -0
- package/claude/skills/claude-intake/REQUIREMENT.md +49 -0
- package/claude/skills/claude-intake/SKILL.md +114 -0
- package/claude/skills/claude-intake-answer/REQUIREMENT.md +48 -0
- package/claude/skills/claude-intake-answer/SKILL.md +90 -0
- package/claude/skills/claude-markdown-propose/REQUIREMENT.md +48 -0
- package/claude/skills/claude-markdown-propose/SKILL.md +118 -0
- package/claude/skills/claude-markdown-propose/references/format.md +107 -0
- package/claude/skills/claude-memory-capture/REQUIREMENT.md +50 -0
- package/claude/skills/claude-memory-capture/SKILL.md +101 -0
- package/claude/skills/claude-memory-review/REQUIREMENT.md +50 -0
- package/claude/skills/claude-memory-review/SKILL.md +210 -0
- package/claude/skills/claude-memory-review/references/receipt-format.md +48 -0
- package/claude/skills/claude-orchestrate/REQUIREMENT.md +121 -0
- package/claude/skills/claude-orchestrate/SKILL.md +241 -0
- package/claude/skills/claude-orchestrate/references/orchestrator-dispatch.md +132 -0
- package/claude/skills/claude-orchestrate/references/orchestrator-handoff.md +32 -0
- package/claude/skills/claude-orchestrate/references/orchestrator-parked.md +72 -0
- package/claude/skills/claude-orchestrate/references/orchestrator-poll.md +87 -0
- package/claude/skills/claude-orchestrate/references/orchestrator-resume.md +30 -0
- package/claude/skills/claude-orchestrate/references/orchestrator-sweep.md +21 -0
- package/claude/skills/claude-orchestrate/scripts/poll.sh +373 -0
- package/claude/skills/claude-orchestrate/scripts/watch.sh +181 -0
- package/claude/skills/claude-pr-review/REQUIREMENT.md +47 -0
- package/claude/skills/claude-pr-review/SKILL.md +295 -0
- package/claude/skills/claude-review/REQUIREMENT.md +39 -0
- package/claude/skills/claude-review/SKILL.md +142 -0
- package/claude/skills/claude-seed-sync/REQUIREMENT.md +45 -0
- package/claude/skills/claude-seed-sync/SKILL.md +156 -0
- package/claude/skills/claude-standards-audit/REQUIREMENT.md +33 -0
- package/claude/skills/claude-standards-audit/SKILL.md +99 -0
- package/claude/skills/claude-tasks/REQUIREMENT.md +43 -0
- package/claude/skills/claude-tasks/SKILL.md +161 -0
- package/claude/skills/claude-teach/REQUIREMENT.md +56 -0
- package/claude/skills/claude-teach/SKILL.md +196 -0
- package/claude/skills/claude-teach/references/lesson-craft.md +59 -0
- package/claude/skills/claude-teach/references/pedagogy.md +67 -0
- package/claude/skills/claude-teach/references/promotion.md +54 -0
- package/claude/skills/claude-ui-test/REQUIREMENT.md +40 -0
- package/claude/skills/claude-ui-test/SKILL.md +77 -0
- package/claude/skills/claude-ux-audit/REQUIREMENT.md +40 -0
- package/claude/skills/claude-ux-audit/SKILL.md +79 -0
- package/claude/skills/claude-ux-measure/REQUIREMENT.md +48 -0
- package/claude/skills/claude-ux-measure/SKILL.md +122 -0
- package/claude/skills/claude-worker/REQUIREMENT.md +54 -0
- package/claude/skills/claude-worker/SKILL.md +96 -0
- package/claude/skills/claude-worktree/REQUIREMENT.md +58 -0
- package/claude/skills/claude-worktree/SKILL.md +136 -0
- package/claude/skills/create-rule/REQUIREMENT.md +45 -0
- package/claude/skills/create-rule/SKILL.md +68 -0
- package/claude/skills/create-skill/REQUIREMENT.md +38 -0
- package/claude/skills/create-skill/SKILL.md +32 -0
- package/claude/skills/create-snippet/REQUIREMENT.md +39 -0
- package/claude/skills/create-snippet/SKILL.md +30 -0
- package/claude/skills/create-standard/REQUIREMENT.md +35 -0
- package/claude/skills/create-standard/SKILL.md +29 -0
- package/claude/skills/decision-escalate/REQUIREMENT.md +45 -0
- package/claude/skills/decision-escalate/SKILL.md +79 -0
- package/claude/skills/docs-sync/REQUIREMENT.md +41 -0
- package/claude/skills/docs-sync/SKILL.md +95 -0
- package/claude/skills/git-branch/REQUIREMENT.md +38 -0
- package/claude/skills/git-branch/SKILL.md +60 -0
- package/claude/skills/git-commit/REQUIREMENT.md +36 -0
- package/claude/skills/git-commit/SKILL.md +49 -0
- package/claude/skills/git-followup/REQUIREMENT.md +43 -0
- package/claude/skills/git-followup/SKILL.md +48 -0
- package/claude/skills/git-issue/REQUIREMENT.md +38 -0
- package/claude/skills/git-issue/SKILL.md +65 -0
- package/claude/skills/git-pr/REQUIREMENT.md +50 -0
- package/claude/skills/git-pr/SKILL.md +164 -0
- package/claude/skills/git-pr/references/labels.md +95 -0
- package/claude/skills/git-ship/REQUIREMENT.md +42 -0
- package/claude/skills/git-ship/SKILL.md +55 -0
- package/claude/skills/git-split/REQUIREMENT.md +39 -0
- package/claude/skills/git-split/SKILL.md +162 -0
- package/claude/skills/git-stage/REQUIREMENT.md +39 -0
- package/claude/skills/git-stage/SKILL.md +73 -0
- package/claude/skills/git-worktree/REQUIREMENT.md +38 -0
- package/claude/skills/git-worktree/SKILL.md +130 -0
- package/claude/skills/migration-claude-md/REQUIREMENT.md +40 -0
- package/claude/skills/migration-claude-md/SKILL.md +76 -0
- package/claude/skills/migration-context/REQUIREMENT.md +36 -0
- package/claude/skills/migration-context/SKILL.md +95 -0
- package/claude/skills/migration-standards-drop/REQUIREMENT.md +55 -0
- package/claude/skills/migration-standards-drop/SKILL.md +113 -0
- package/claude/skills/migration-superseded/REQUIREMENT.md +44 -0
- package/claude/skills/migration-superseded/SKILL.md +115 -0
- package/claude/skills/project-commands/REQUIREMENT.md +42 -0
- package/claude/skills/project-commands/SKILL.md +85 -0
- package/claude/skills/restate-plainly/REQUIREMENT.md +41 -0
- package/claude/skills/restate-plainly/SKILL.md +39 -0
- package/claude/skills/session-map/REQUIREMENT.md +57 -0
- package/claude/skills/session-map/SKILL.md +70 -0
- package/claude/skills/session-resume/REQUIREMENT.md +49 -0
- package/claude/skills/session-resume/SKILL.md +51 -0
- package/claude/skills/setup-gov/REQUIREMENT.md +37 -0
- package/claude/skills/setup-gov/SKILL.md +77 -0
- package/claude/skills/setup-indexes/REQUIREMENT.md +45 -0
- package/claude/skills/setup-indexes/SKILL.md +153 -0
- package/claude/skills/setup-init/REQUIREMENT.md +45 -0
- package/claude/skills/setup-init/SKILL.md +127 -0
- package/claude/skills/setup-plugins/REQUIREMENT.md +42 -0
- package/claude/skills/setup-plugins/SKILL.md +81 -0
- package/claude/skills/setup-plugins/references/plugin-catalog.md +53 -0
- package/claude/skills/setup-verify/REQUIREMENT.md +39 -0
- package/claude/skills/setup-verify/SKILL.md +51 -0
- package/claude/skills/systematic-debugging/REQUIREMENT.md +41 -0
- package/claude/skills/systematic-debugging/SKILL.md +70 -0
- package/claude/skills/write-human/REQUIREMENT.md +46 -0
- package/claude/skills/write-human/SKILL.md +68 -0
- package/claude/skills/write-human/references/density.md +38 -0
- package/claude/skills/write-human/references/machine-tells.md +107 -0
- package/claude/skills/write-human/references/source-material.md +37 -0
- package/claude/skills/youtube-transcripts/REQUIREMENT.md +38 -0
- package/claude/skills/youtube-transcripts/SKILL.md +34 -0
- package/docs/agents/audits.md +98 -0
- package/docs/agents/capture.md +37 -0
- package/docs/agents/census.md +23 -0
- package/docs/agents/commands.md +146 -0
- package/docs/agents/comments.md +34 -0
- package/docs/agents/context-audit-checks.md +120 -0
- package/docs/agents/context-audit.md +83 -0
- package/docs/agents/counts.md +76 -0
- package/docs/agents/demo.md +86 -0
- package/docs/agents/docs.md +17 -0
- package/docs/agents/gate.md +84 -0
- package/docs/agents/index.md +47 -0
- package/docs/agents/indexes.md +35 -0
- package/docs/agents/install-and-sync.md +385 -0
- package/docs/agents/intake.md +81 -0
- package/docs/agents/key-changes.md +103 -0
- package/docs/agents/label-coverage.md +73 -0
- package/docs/agents/markdown-audit.md +197 -0
- package/docs/agents/output-shape.md +70 -0
- package/docs/agents/overview.md +26 -0
- package/docs/agents/records.md +170 -0
- package/docs/agents/restated.md +81 -0
- package/docs/agents/review-classification.md +77 -0
- package/docs/agents/routing.md +61 -0
- package/docs/agents/rule-citations.md +98 -0
- package/docs/agents/sandbox.md +71 -0
- package/docs/agents/scripting.md +149 -0
- package/docs/agents/sessions.md +120 -0
- package/docs/agents/skills-audit.md +94 -0
- package/docs/agents/skills-reach.md +64 -0
- package/docs/agents/standards-audit.md +38 -0
- package/docs/agents/state-scoped-risk.md +105 -0
- package/docs/agents/superseded.md +85 -0
- package/docs/agents/targets.md +83 -0
- package/docs/agents/tasks.md +200 -0
- package/docs/agents/teach.md +158 -0
- package/docs/agents/test-order.md +56 -0
- package/docs/agents/worktrees.md +62 -0
- package/docs/ai-workflow.md +317 -0
- package/docs/index.md +23 -0
- package/docs/operating-model.md +223 -0
- package/docs/target-projects.md +258 -0
- package/docs/visual-design-workflow.md +151 -0
- package/docs/zshrc-aliases.md +65 -0
- package/governance/rules/ci/700-ci-workflow.md +44 -0
- package/governance/rules/claude/500-prose.md +15 -0
- package/governance/rules/claude/501-markdown.md +14 -0
- package/governance/rules/claude/510-context.md +28 -0
- package/governance/rules/claude/511-indexes.md +14 -0
- package/governance/rules/claude/520-wireframes.md +12 -0
- package/governance/rules/claude/530-requirements.md +11 -0
- package/governance/rules/claude/540-architecture.md +11 -0
- package/governance/rules/claude/550-design.md +11 -0
- package/governance/rules/claude/555-tasks.md +12 -0
- package/governance/rules/claude/556-groundwork.md +11 -0
- package/governance/rules/claude/557-intake.md +11 -0
- package/governance/rules/claude/558-plan.md +22 -0
- package/governance/rules/claude/559-memory.md +11 -0
- package/governance/rules/claude/560-diagrams.md +18 -0
- package/governance/rules/claude/561-teach.md +13 -0
- package/governance/rules/claude/562-session.md +15 -0
- package/governance/rules/claude/570-skill.md +24 -0
- package/governance/rules/claude/575-hooks.md +17 -0
- package/governance/rules/claude/576-settings.md +14 -0
- package/governance/rules/claude/580-readme.md +11 -0
- package/governance/rules/claude/590-rule-authoring.md +12 -0
- package/governance/rules/claude/591-standard-authoring.md +12 -0
- package/governance/rules/claude/592-claude-md.md +19 -0
- package/governance/rules/core/000-constitution.md +30 -0
- package/governance/rules/core/005-behavior.md +27 -0
- package/governance/rules/core/010-testing.md +35 -0
- package/governance/rules/core/015-output.md +20 -0
- package/governance/rules/core/020-concurrency.md +22 -0
- package/governance/rules/core/025-indexes.md +9 -0
- package/governance/rules/core/030-error-handling.md +31 -0
- package/governance/rules/core/035-tasks.md +13 -0
- package/governance/rules/core/040-performance.md +20 -0
- package/governance/rules/core/045-memory.md +12 -0
- package/governance/rules/core/050-logging.md +20 -0
- package/governance/rules/core/055-scratch.md +9 -0
- package/governance/rules/core/060-naming.md +19 -0
- package/governance/rules/core/065-spelling.md +19 -0
- package/governance/rules/core/070-planning.md +18 -0
- package/governance/rules/core/075-dependencies.md +25 -0
- package/governance/rules/core/080-config-comments.md +22 -0
- package/governance/rules/core/085-worktrees.md +17 -0
- package/governance/rules/core/087-git.md +11 -0
- package/governance/rules/core/090-code-comments.md +39 -0
- package/governance/rules/framework/200-react.md +51 -0
- package/governance/rules/framework/210-astro.md +41 -0
- package/governance/rules/framework/220-fastapi.md +43 -0
- package/governance/rules/framework/230-nextjs.md +48 -0
- package/governance/rules/framework/250-tailwind.md +32 -0
- package/governance/rules/framework/260-shadcn.md +34 -0
- package/governance/rules/lang/100-typescript.md +40 -0
- package/governance/rules/lang/110-python.md +42 -0
- package/governance/rules/lang/120-bash.md +19 -0
- package/governance/rules/lib/300-testing-ts.md +39 -0
- package/governance/rules/lib/305-e2e-reliability.md +34 -0
- package/governance/rules/lib/306-test-scope.md +25 -0
- package/governance/rules/lib/310-zod.md +25 -0
- package/governance/rules/lib/320-tanstack-query.md +32 -0
- package/governance/rules/lib/330-testing-py.md +44 -0
- package/governance/rules/lib/340-pydantic.md +38 -0
- package/governance/rules/lib/350-security-web.md +32 -0
- package/governance/rules/lib/360-security-server.md +39 -0
- package/governance/rules/lib/370-database.md +35 -0
- package/governance/rules/snippets/505-at-references.md +9 -0
- package/governance/rules/ui/400-ui.md +36 -0
- package/governance/rules/ui/410-a11y.md +48 -0
- package/governance/rules/ui/420-forms.md +36 -0
- package/governance/rules/ui/430-ux-completeness.md +65 -0
- package/governance/rules/ui/440-surface-capture.md +34 -0
- package/governance/rules/ui/450-link-behavior.md +19 -0
- package/governance/stacks/astro.toml +2 -0
- package/governance/stacks/base.toml +8 -0
- package/governance/stacks/node-server.toml +2 -0
- package/governance/stacks/node.toml +2 -0
- package/governance/stacks/python-fastapi.toml +2 -0
- package/governance/stacks/python.toml +2 -0
- package/governance/stacks/react.toml +2 -0
- package/package.json +69 -0
- package/scripts/config.sh +11 -0
- package/scripts/core/bootstrap.sh +81 -0
- package/scripts/core/check-color-source.sh +41 -0
- package/scripts/core/check-ignore-parity.sh +162 -0
- package/scripts/core/check-plugin-boundary.sh +45 -0
- package/scripts/core/check-seed-independence.sh +59 -0
- package/scripts/core/check-skill-paths.sh +24 -0
- package/scripts/core/clean.sh +36 -0
- package/scripts/core/install-check.sh +101 -0
- package/scripts/core/list-seed-roots.sh +18 -0
- package/scripts/core/regen-claude-copies.sh +10 -0
- package/scripts/core/regen-hero.sh +217 -0
- package/scripts/core/regen-indexes.sh +10 -0
- package/scripts/core/regen-tooling-paths.sh +61 -0
- package/scripts/core/repair-bare-flag.sh +19 -0
- package/scripts/core/snapshot.sh +134 -0
- package/scripts/core/update.sh +35 -0
- package/scripts/docs/list.sh +165 -0
- package/scripts/lib/frontmatter.sh +30 -0
- package/scripts/lib/gov.sh +14 -0
- package/scripts/lib/sandbox-fixtures.sh +191 -0
- package/scripts/lib/sandbox-git.sh +125 -0
- package/scripts/lib/sandbox-path.sh +206 -0
- package/scripts/lib/tooling.sh +35 -0
- package/scripts/lib/ui.sh +266 -0
- package/scripts/lib/worktree.sh +20 -0
- package/scripts/manage-sandbox.sh +466 -0
- package/scripts/snippets/create.sh +156 -0
- package/scripts/standards/list.sh +115 -0
- package/scripts/tooling/create.sh +109 -0
- package/scripts/tooling/verify.sh +179 -0
- package/snippets/align.md +12 -0
- package/snippets/claude/decision-memo.md +39 -0
- package/snippets/claude/feature-recap.md +19 -0
- package/snippets/claude/figma-steps.md +24 -0
- package/snippets/compact-summary.md +5 -0
- package/snippets/decision-help.md +6 -0
- package/snippets/meta-prompt.md +14 -0
- package/snippets/research-prompt.md +7 -0
- package/snippets/session-notes.md +11 -0
- package/snippets/snippets.toml +5 -0
- package/snippets/step-by-step.md +10 -0
- package/snippets/web-research.md +21 -0
- package/src/audits/baseline.ts +201 -0
- package/src/audits/catalog.ts +876 -0
- package/src/audits/run.ts +204 -0
- package/src/autoship/classify.ts +75 -0
- package/src/autoship/paths.ts +51 -0
- package/src/binary.ts +16 -0
- package/src/browser/engine.ts +40 -0
- package/src/census/count.ts +113 -0
- package/src/claude/cases/all.ts +24 -0
- package/src/claude/cases/authoring.ts +53 -0
- package/src/claude/cases/claude-workflow.ts +158 -0
- package/src/claude/cases/git.ts +44 -0
- package/src/claude/cases/misc.ts +27 -0
- package/src/claude/cases/setup.ts +94 -0
- package/src/claude/gitignore.ts +51 -0
- package/src/claude/routing.ts +283 -0
- package/src/claude/seeds-list.ts +47 -0
- package/src/claude/seeds.ts +150 -0
- package/src/claude/settings.ts +151 -0
- package/src/claude/skills-audit.ts +228 -0
- package/src/claude/skills-drift.ts +156 -0
- package/src/claude/skills-list.ts +99 -0
- package/src/claude/skills-rank.ts +320 -0
- package/src/claude/skills-reach.ts +227 -0
- package/src/cli-run.ts +43 -0
- package/src/cli.ts +200 -0
- package/src/commands/audits.ts +350 -0
- package/src/commands/autoship.ts +129 -0
- package/src/commands/capture.ts +133 -0
- package/src/commands/census.ts +105 -0
- package/src/commands/claude.ts +1286 -0
- package/src/commands/comments.ts +240 -0
- package/src/commands/context.ts +857 -0
- package/src/commands/demo.ts +389 -0
- package/src/commands/deps.ts +173 -0
- package/src/commands/design.ts +36 -0
- package/src/commands/docs.ts +60 -0
- package/src/commands/feedback-format.ts +23 -0
- package/src/commands/feedback.ts +112 -0
- package/src/commands/gate.ts +189 -0
- package/src/commands/gov.ts +1265 -0
- package/src/commands/indexes.ts +184 -0
- package/src/commands/init.ts +113 -0
- package/src/commands/intake.ts +406 -0
- package/src/commands/inventory.ts +256 -0
- package/src/commands/labels.ts +361 -0
- package/src/commands/markdown.ts +544 -0
- package/src/commands/migrate.ts +175 -0
- package/src/commands/pass-through.ts +39 -0
- package/src/commands/pr.ts +411 -0
- package/src/commands/records.ts +728 -0
- package/src/commands/sandbox.ts +468 -0
- package/src/commands/secrets.ts +132 -0
- package/src/commands/serve.ts +159 -0
- package/src/commands/sessions.ts +408 -0
- package/src/commands/slides.ts +126 -0
- package/src/commands/snippets.ts +84 -0
- package/src/commands/standards.ts +247 -0
- package/src/commands/sync.ts +428 -0
- package/src/commands/targets.ts +319 -0
- package/src/commands/tasks.ts +743 -0
- package/src/commands/teach.ts +786 -0
- package/src/commands/tooling.ts +573 -0
- package/src/commands/transcripts.ts +44 -0
- package/src/commands/upgrade.ts +231 -0
- package/src/commands/wiki.ts +100 -0
- package/src/commands/worktrees.ts +191 -0
- package/src/comments/scan.ts +338 -0
- package/src/comments/trend.ts +207 -0
- package/src/comments/vocabulary.ts +85 -0
- package/src/context/architecture.ts +364 -0
- package/src/context/audit.ts +790 -0
- package/src/context/citations.ts +196 -0
- package/src/context/folders.ts +186 -0
- package/src/context/gate.ts +57 -0
- package/src/context/index-drift.ts +64 -0
- package/src/context/narration.ts +99 -0
- package/src/copy.ts +30 -0
- package/src/counts/catalogs.ts +96 -0
- package/src/counts/numbers.ts +79 -0
- package/src/counts/scan.ts +314 -0
- package/src/demo/beats.ts +135 -0
- package/src/demo/compile.ts +326 -0
- package/src/demo/container.ts +63 -0
- package/src/demo/cursors.ts +55 -0
- package/src/demo/drive.ts +357 -0
- package/src/demo/pointer.ts +178 -0
- package/src/demo/theme.ts +112 -0
- package/src/deps/audit.ts +153 -0
- package/src/design/parse.ts +116 -0
- package/src/design/render.ts +249 -0
- package/src/docs/read.ts +77 -0
- package/src/exec.ts +16 -0
- package/src/exempt-marker.ts +43 -0
- package/src/frontmatter.ts +13 -0
- package/src/gate/measures.ts +682 -0
- package/src/gate/sequencer.ts +386 -0
- package/src/gate/stages.ts +412 -0
- package/src/git-env.ts +36 -0
- package/src/git-files.ts +105 -0
- package/src/git-ignore.ts +46 -0
- package/src/github-format.ts +13 -0
- package/src/github.ts +24 -0
- package/src/gov/adapter.ts +103 -0
- package/src/gov/citations.ts +514 -0
- package/src/gov/consumed.ts +129 -0
- package/src/gov/install.ts +132 -0
- package/src/gov/list.ts +106 -0
- package/src/gov/payload.ts +39 -0
- package/src/gov/restated.ts +814 -0
- package/src/gov/stacks.ts +205 -0
- package/src/gov/superseded.ts +415 -0
- package/src/gov/test-order.ts +407 -0
- package/src/indexes/frontmatter.ts +46 -0
- package/src/indexes/regen.ts +84 -0
- package/src/indexes/render.ts +201 -0
- package/src/indexes/walk.ts +83 -0
- package/src/init/flags.ts +60 -0
- package/src/init/plan.ts +114 -0
- package/src/init/run.ts +46 -0
- package/src/init/steps.ts +77 -0
- package/src/intake/folder.ts +320 -0
- package/src/intake/items.ts +174 -0
- package/src/inventory/config.ts +117 -0
- package/src/inventory/group.ts +76 -0
- package/src/inventory/subjects.ts +114 -0
- package/src/inventory/walk.ts +129 -0
- package/src/labels/audit.ts +82 -0
- package/src/labels/coverage.ts +79 -0
- package/src/labels/map.ts +101 -0
- package/src/labels/phase.ts +95 -0
- package/src/markdown/bans.ts +94 -0
- package/src/markdown/files.ts +102 -0
- package/src/markdown/gate.ts +28 -0
- package/src/markdown/scan.ts +295 -0
- package/src/markdown/structure.ts +730 -0
- package/src/migrate/apply.ts +115 -0
- package/src/migrate/plan.ts +103 -0
- package/src/migrate/rename.ts +183 -0
- package/src/pr/bijection.ts +145 -0
- package/src/pr/paths.ts +335 -0
- package/src/process/harness.ts +167 -0
- package/src/project-root.ts +19 -0
- package/src/records/backup.ts +455 -0
- package/src/records/migrate.ts +78 -0
- package/src/records/size.ts +260 -0
- package/src/records/validate.ts +1162 -0
- package/src/sandbox/census.ts +228 -0
- package/src/sandbox/coverage.ts +115 -0
- package/src/sandbox/expect.ts +629 -0
- package/src/sandbox/tree.ts +47 -0
- package/src/secrets/marker.ts +30 -0
- package/src/secrets/patterns.ts +142 -0
- package/src/secrets/scan.ts +123 -0
- package/src/secrets/shipped.ts +111 -0
- package/src/seed-marker.ts +74 -0
- package/src/serve/static.ts +322 -0
- package/src/sessions/claim.ts +85 -0
- package/src/sessions/live.ts +79 -0
- package/src/sessions/registry.ts +137 -0
- package/src/sessions/resolve.ts +333 -0
- package/src/slides/layouts.ts +391 -0
- package/src/slides/open.ts +18 -0
- package/src/slides/parse.ts +84 -0
- package/src/slides/render.ts +88 -0
- package/src/slides/styles.ts +44 -0
- package/src/snippets/categories.ts +66 -0
- package/src/snippets/list.ts +32 -0
- package/src/snippets/presets.ts +50 -0
- package/src/standards/audit.ts +132 -0
- package/src/standards/read.ts +100 -0
- package/src/sync/check.ts +692 -0
- package/src/sync/engine.ts +576 -0
- package/src/sync/git.ts +225 -0
- package/src/sync/history.ts +123 -0
- package/src/sync/layout.ts +140 -0
- package/src/sync/reverse.ts +268 -0
- package/src/sync/seeds-report.ts +126 -0
- package/src/sync/stamp.ts +358 -0
- package/src/sync/target.ts +70 -0
- package/src/sync/workflow.ts +200 -0
- package/src/target.ts +43 -0
- package/src/targets/pulls.ts +250 -0
- package/src/targets/registry.ts +203 -0
- package/src/targets/resolve.ts +145 -0
- package/src/targets/sweep.ts +246 -0
- package/src/tasks/archive.ts +506 -0
- package/src/tasks/record.ts +311 -0
- package/src/tasks/trunk.ts +89 -0
- package/src/tasks/validate.ts +1001 -0
- package/src/teach/lesson.ts +180 -0
- package/src/teach/workspace.ts +842 -0
- package/src/tooling/gitignore.ts +122 -0
- package/src/tooling/inject.ts +193 -0
- package/src/tooling/list.ts +39 -0
- package/src/tooling/manifest.ts +176 -0
- package/src/tooling/package.ts +166 -0
- package/src/tooling/read.ts +65 -0
- package/src/tooling/scan.ts +147 -0
- package/src/tooling/stamp.ts +44 -0
- package/src/transcripts/fetch.ts +156 -0
- package/src/transcripts/metadata.ts +54 -0
- package/src/transcripts/vtt.ts +114 -0
- package/src/ui.ts +266 -0
- package/src/version/compare.ts +53 -0
- package/src/version/installed.ts +40 -0
- package/src/version/manager.ts +67 -0
- package/src/version/skew.ts +192 -0
- package/src/wiki/init.ts +85 -0
- package/src/worktree.ts +143 -0
- package/src/worktrees/reclaim.ts +306 -0
- package/standards/architecture.md +72 -0
- package/standards/branch.md +59 -0
- package/standards/commit.md +72 -0
- package/standards/context.md +151 -0
- package/standards/design.md +93 -0
- package/standards/diagrams.md +152 -0
- package/standards/glossary.md +75 -0
- package/standards/groundwork.md +211 -0
- package/standards/index.md +36 -0
- package/standards/intake.md +192 -0
- package/standards/issue.md +94 -0
- package/standards/markdown.md +137 -0
- package/standards/memory.md +144 -0
- package/standards/plan.md +172 -0
- package/standards/pr.md +139 -0
- package/standards/publish.md +51 -0
- package/standards/readme.md +208 -0
- package/standards/requirements.md +70 -0
- package/standards/rule.md +118 -0
- package/standards/session.md +109 -0
- package/standards/skill.md +300 -0
- package/standards/slug.md +39 -0
- package/standards/snippets.md +76 -0
- package/standards/standard.md +170 -0
- package/standards/tasks.md +254 -0
- package/standards/teach.md +153 -0
- package/standards/versioning.md +71 -0
- package/standards/wireframes.md +113 -0
- package/tooling/astro/configs/astro.config.mjs +31 -0
- package/tooling/astro/configs/eslint.config.js +79 -0
- package/tooling/astro/configs/playwright.config.ts +26 -0
- package/tooling/astro/configs/tsconfig.json +12 -0
- package/tooling/astro/configs/vitest.config.ts +22 -0
- package/tooling/astro/manifest.toml +34 -0
- package/tooling/astro/reference.md +60 -0
- package/tooling/base/configs/.editorconfig +5 -0
- package/tooling/base/configs/.github/pull_request_template.md +18 -0
- package/tooling/base/configs/.github/workflows/verify.yml +35 -0
- package/tooling/base/configs/.husky/commit-msg +1 -0
- package/tooling/base/configs/.husky/post-merge +61 -0
- package/tooling/base/configs/.husky/post-rewrite +21 -0
- package/tooling/base/configs/.husky/pre-commit +1 -0
- package/tooling/base/configs/.husky/pre-push +1 -0
- package/tooling/base/configs/.prettierrc +12 -0
- package/tooling/base/configs/.shellcheckrc +1 -0
- package/tooling/base/configs/.vscode/extensions.json +9 -0
- package/tooling/base/configs/.vscode/settings.json +3 -0
- package/tooling/base/configs/commitlint.config.js +11 -0
- package/tooling/base/configs/scripts/verify.sh +64 -0
- package/tooling/base/manifest.toml +30 -0
- package/tooling/base/reference.md +98 -0
- package/tooling/base/seeds/.claude/context/ci.md +33 -0
- package/tooling/base/seeds/.claude/context/development.md +37 -0
- package/tooling/base/seeds/.claude/context/index.md +11 -0
- package/tooling/base/seeds/.cspell/project-terms.txt +0 -0
- package/tooling/base/seeds/.cspell/tech-stack.txt +19 -0
- package/tooling/base/seeds/.lintstagedrc +8 -0
- package/tooling/base/seeds/.prettierignore +0 -0
- package/tooling/base/seeds/cspell.json +20 -0
- package/tooling/claude/manifest.toml +14 -0
- package/tooling/claude/reference.md +79 -0
- package/tooling/claude/seeds/.claude/ARCHITECTURE.md +13 -0
- package/tooling/claude/seeds/.claude/DESIGN.md +62 -0
- package/tooling/claude/seeds/.claude/REQUIREMENTS.md +18 -0
- package/tooling/claude/seeds/.claude/diagrams/index.md +8 -0
- package/tooling/claude/seeds/.claude/hooks/index-reminder.sh +50 -0
- package/tooling/claude/seeds/.claude/hooks/memory-index.sh +68 -0
- package/tooling/claude/seeds/.claude/hooks/path-form.sh +57 -0
- package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +52 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +86 -0
- package/tooling/claude/seeds/.claude/hooks/tasks-index.sh +71 -0
- package/tooling/claude/seeds/.claude/memory/index.md +8 -0
- package/tooling/claude/seeds/.claude/settings.json +47 -0
- package/tooling/claude/seeds/.claude/tasks/index.md +8 -0
- package/tooling/claude/seeds/.claude/wireframes/index.md +8 -0
- package/tooling/claude/seeds/CLAUDE.md +29 -0
- package/tooling/claude/user/settings.template.json +10 -0
- package/tooling/claude/user/statusline-command.sh +53 -0
- package/tooling/python/configs/.coveragerc +14 -0
- package/tooling/python/configs/.python-version +1 -0
- package/tooling/python/configs/mypy.ini +6 -0
- package/tooling/python/configs/pytest.ini +4 -0
- package/tooling/python/configs/ruff.toml +15 -0
- package/tooling/python/configs/scripts/verify.sh +77 -0
- package/tooling/python/manifest.toml +16 -0
- package/tooling/python/reference.md +66 -0
- package/tooling/python/seeds/.cspell/tech-stack.txt +19 -0
- package/tooling/python/seeds/tests/test_smoke.py +2 -0
- package/tooling/vite-react/configs/playwright.config.ts +26 -0
- package/tooling/vite-react/configs/tsconfig.json +35 -0
- package/tooling/vite-react/configs/vite.config.ts +24 -0
- package/tooling/vite-react/configs/vitest.config.ts +26 -0
- package/tooling/vite-react/manifest.toml +23 -0
- package/tooling/vite-react/reference.md +55 -0
- package/tooling/vite-react/seeds/.cspell/project-terms.txt +1 -0
- package/tooling/vite-react/seeds/.cspell/tech-stack.txt +1 -0
- package/tooling/web/configs/.github/workflows/verify.yml +134 -0
- package/tooling/web/configs/.vscode/extensions.json +13 -0
- package/tooling/web/configs/.vscode/settings.json +10 -0
- package/tooling/web/configs/e2e/home.spec.ts +6 -0
- package/tooling/web/configs/e2e/screenshot.ts +53 -0
- package/tooling/web/configs/eslint.config.js +82 -0
- package/tooling/web/configs/scripts/screenshot.sh +28 -0
- package/tooling/web/configs/scripts/verify.sh +80 -0
- package/tooling/web/configs/scripts/worktree-port.sh +74 -0
- package/tooling/web/configs/src/test/setup.ts +8 -0
- package/tooling/web/manifest.toml +58 -0
- package/tooling/web/reference.md +115 -0
- package/tooling/web/seeds/.cspell/tech-stack.txt +18 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
set -o pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
7
|
+
|
|
8
|
+
GITIGNORE="$PROJECT_ROOT/.gitignore"
|
|
9
|
+
MANIFEST="$PROJECT_ROOT/tooling/claude/manifest.toml"
|
|
10
|
+
SECTION="# Claude"
|
|
11
|
+
|
|
12
|
+
# Divergences this repository has decided to keep, one `<entry>|<reason>` per
|
|
13
|
+
# line, matched after the trailing slash is stripped. Each names a path the
|
|
14
|
+
# enclosing repository ignores and the claude manifest deliberately does not
|
|
15
|
+
# ship, so a target keeps tracking it.
|
|
16
|
+
#
|
|
17
|
+
# This is the canonical list. `.gitignore` and the manifest carry a pointer
|
|
18
|
+
# beside their own entries rather than a second copy of the reason, and
|
|
19
|
+
# `.claude/context/tooling.md` carries the narrative behind both.
|
|
20
|
+
#
|
|
21
|
+
# A sanction that no longer describes a divergence fails the same as an
|
|
22
|
+
# unsanctioned one. An exception outliving its reason is what teaches the next
|
|
23
|
+
# reader to widen the list rather than to read it.
|
|
24
|
+
SANCTIONED=(
|
|
25
|
+
".claude/diagrams|a target that tracks its diagrams keeps the context audit's default coverage of them, which ignoring the folder for every target would take away. This repository backs the folder through its records remote instead."
|
|
26
|
+
".claude/README.md|the landing page a records pull writes back into a repository that set up a records remote. A target has not, so it never receives the file."
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
if [ ! -f "$GITIGNORE" ]; then
|
|
30
|
+
echo "No .gitignore at ${GITIGNORE#"$PROJECT_ROOT/"}, ignore parity unverifiable." >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [ ! -f "$MANIFEST" ]; then
|
|
35
|
+
echo "No claude manifest at ${MANIFEST#"$PROJECT_ROOT/"}, ignore parity unverifiable." >&2
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# A gitignore pattern and a manifest entry describe the same folder whether or
|
|
40
|
+
# not either spells the trailing slash, so presence is compared with it dropped.
|
|
41
|
+
# `.claude/.tmp` and `.claude/.tmp/` are the live instance of that pair.
|
|
42
|
+
normalize() {
|
|
43
|
+
printf '%s\n' "${1%/}"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Every pattern the file carries, comments and blank lines dropped. The whole
|
|
47
|
+
# file rather than one header, because `.claude/teach/` sits under a header of
|
|
48
|
+
# its own and reading the `# Claude` header alone would report it missing from a
|
|
49
|
+
# list that carries it.
|
|
50
|
+
gitignore_patterns() {
|
|
51
|
+
awk '{ sub(/[[:space:]]+$/, "") } $0 ~ /^[[:space:]]*#/ || $0 == "" { next } { print }' "$GITIGNORE"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Every entry of the named array in the manifest's `[gitignore]` table. The
|
|
55
|
+
# array is accumulated to its closing bracket before the quoted strings are read
|
|
56
|
+
# out, so a formatter wrapping it across lines does not silently empty this.
|
|
57
|
+
manifest_entries() {
|
|
58
|
+
awk -v key="\"$SECTION\"" '
|
|
59
|
+
/^\[/ { table = $0 }
|
|
60
|
+
table != "[gitignore]" { next }
|
|
61
|
+
index($0, key) == 1 { collecting = 1; buf = "" }
|
|
62
|
+
collecting { buf = buf $0 }
|
|
63
|
+
collecting && index($0, "]") > 0 {
|
|
64
|
+
collecting = 0
|
|
65
|
+
buf = substr(buf, index(buf, "["))
|
|
66
|
+
count = split(buf, parts, "\"")
|
|
67
|
+
for (i = 2; i <= count; i += 2) print parts[i]
|
|
68
|
+
}
|
|
69
|
+
' "$MANIFEST"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
contains() {
|
|
73
|
+
local needle=$1
|
|
74
|
+
shift
|
|
75
|
+
local candidate
|
|
76
|
+
for candidate in "$@"; do
|
|
77
|
+
[ "$candidate" = "$needle" ] || continue
|
|
78
|
+
return 0
|
|
79
|
+
done
|
|
80
|
+
return 1
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
ignored=()
|
|
84
|
+
while IFS= read -r pattern; do
|
|
85
|
+
[ -n "$pattern" ] || continue
|
|
86
|
+
ignored+=("$(normalize "$pattern")")
|
|
87
|
+
done < <(gitignore_patterns)
|
|
88
|
+
|
|
89
|
+
shipped=()
|
|
90
|
+
while IFS= read -r entry; do
|
|
91
|
+
[ -n "$entry" ] || continue
|
|
92
|
+
shipped+=("$(normalize "$entry")")
|
|
93
|
+
done < <(manifest_entries)
|
|
94
|
+
|
|
95
|
+
# An empty read on either side is a parse that failed rather than a repository
|
|
96
|
+
# ignoring nothing, and reporting parity off it would say the two lists agree
|
|
97
|
+
# having compared none of their entries.
|
|
98
|
+
if [ ${#ignored[@]} -eq 0 ]; then
|
|
99
|
+
echo "No patterns read from .gitignore, ignore parity unverifiable." >&2
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
if [ ${#shipped[@]} -eq 0 ]; then
|
|
104
|
+
echo "No entries read from the \"$SECTION\" array in ${MANIFEST#"$PROJECT_ROOT/"}, ignore parity unverifiable." >&2
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
failures=""
|
|
109
|
+
sanction_notes=""
|
|
110
|
+
|
|
111
|
+
# Entries the manifest ships that this repository does not ignore. A target is
|
|
112
|
+
# told to ignore a folder the toolkit itself tracks, which no decision sanctions,
|
|
113
|
+
# so this direction carries no exception list.
|
|
114
|
+
for entry in "${shipped[@]}"; do
|
|
115
|
+
contains "$entry" "${ignored[@]}" && continue
|
|
116
|
+
failures="$failures $entry is shipped by the manifest and absent from .gitignore"$'\n'
|
|
117
|
+
done
|
|
118
|
+
|
|
119
|
+
# Claude-scoped patterns this repository ignores that the manifest does not
|
|
120
|
+
# ship. Scoped to `.claude/` because the manifest is the claude stack and says
|
|
121
|
+
# nothing about `node_modules/` or `.env`.
|
|
122
|
+
for pattern in "${ignored[@]}"; do
|
|
123
|
+
case "$pattern" in
|
|
124
|
+
.claude/*) ;;
|
|
125
|
+
*) continue ;;
|
|
126
|
+
esac
|
|
127
|
+
contains "$pattern" "${shipped[@]}" && continue
|
|
128
|
+
|
|
129
|
+
matched=false
|
|
130
|
+
for sanction in "${SANCTIONED[@]}"; do
|
|
131
|
+
[ "${sanction%%|*}" = "$pattern" ] || continue
|
|
132
|
+
matched=true
|
|
133
|
+
sanction_notes="$sanction_notes $pattern stays out of the manifest: ${sanction#*|}"$'\n'
|
|
134
|
+
break
|
|
135
|
+
done
|
|
136
|
+
|
|
137
|
+
if [ "$matched" = false ]; then
|
|
138
|
+
failures="$failures $pattern is ignored here and absent from the manifest"$'\n'
|
|
139
|
+
fi
|
|
140
|
+
done
|
|
141
|
+
|
|
142
|
+
# A sanction naming a path that is no longer divergent, either because the
|
|
143
|
+
# manifest took it or because .gitignore dropped it.
|
|
144
|
+
for sanction in "${SANCTIONED[@]}"; do
|
|
145
|
+
entry="${sanction%%|*}"
|
|
146
|
+
if contains "$entry" "${ignored[@]}" && ! contains "$entry" "${shipped[@]}"; then
|
|
147
|
+
continue
|
|
148
|
+
fi
|
|
149
|
+
failures="$failures $entry is sanctioned as a divergence and is no longer one"$'\n'
|
|
150
|
+
done
|
|
151
|
+
|
|
152
|
+
if [ -n "$failures" ]; then
|
|
153
|
+
echo "The ignore set a target receives disagrees with this repository's own:" >&2
|
|
154
|
+
printf '%s' "$failures" >&2
|
|
155
|
+
echo "Add the entry to the \"$SECTION\" array in ${MANIFEST#"$PROJECT_ROOT/"} and to .gitignore, or record it in SANCTIONED in scripts/core/check-ignore-parity.sh with the reason it stays apart." >&2
|
|
156
|
+
exit 1
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
if [ -n "$sanction_notes" ]; then
|
|
160
|
+
echo "Sanctioned divergences from the ignore set a target receives:"
|
|
161
|
+
printf '%s' "$sanction_notes"
|
|
162
|
+
fi
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
set -o pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
7
|
+
|
|
8
|
+
INTERNAL_ROOT="$PROJECT_ROOT/internal"
|
|
9
|
+
PLUGIN_ROOT="$PROJECT_ROOT/claude"
|
|
10
|
+
|
|
11
|
+
# `find` writes to stderr and returns non-zero for a missing root, inside a
|
|
12
|
+
# process substitution whose status nothing reads. Without this the walk covers
|
|
13
|
+
# nothing and the check reports the boundary clean having never measured it.
|
|
14
|
+
if [ ! -d "$PLUGIN_ROOT" ]; then
|
|
15
|
+
echo "No plugin root at ${PLUGIN_ROOT#"$PROJECT_ROOT/"}, boundary unverifiable." >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# `realpath` resolves each walked path below. Absent, `set -e` aborts on the
|
|
20
|
+
# substitution and the stage reports a leak for a tool that is not installed,
|
|
21
|
+
# which is the same unmeasured-tree-with-a-verdict shape the guard above closes.
|
|
22
|
+
if ! command -v realpath >/dev/null 2>&1; then
|
|
23
|
+
echo "realpath is not installed, boundary unverifiable." >&2
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# The plugin reaches `standards/` and `snippets/` through symlinks, which an
|
|
28
|
+
# installer dereferences with no code in the path to filter. Walking the plugin
|
|
29
|
+
# tree with symlinks followed is what an install actually copies, so resolving
|
|
30
|
+
# each file and rejecting anything under `internal/` asserts the boundary at the
|
|
31
|
+
# only place it can be measured.
|
|
32
|
+
leaked=""
|
|
33
|
+
while IFS= read -r file; do
|
|
34
|
+
resolved=$(realpath "$file")
|
|
35
|
+
case "$resolved" in
|
|
36
|
+
"$INTERNAL_ROOT"/*) leaked="$leaked ${file#"$PROJECT_ROOT/"} -> ${resolved#"$PROJECT_ROOT/"}"$'\n' ;;
|
|
37
|
+
esac
|
|
38
|
+
done < <(find -L "$PLUGIN_ROOT" -type f)
|
|
39
|
+
|
|
40
|
+
if [ -n "$leaked" ]; then
|
|
41
|
+
echo "Plugin ships toolkit-internal content:" >&2
|
|
42
|
+
printf '%s' "$leaked" >&2
|
|
43
|
+
echo "Author internal content under internal/, which nothing under claude/ reaches." >&2
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
set -o pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
7
|
+
|
|
8
|
+
source "$PROJECT_ROOT/scripts/lib/tooling.sh"
|
|
9
|
+
|
|
10
|
+
TOOLKIT_TOKEN="canon"
|
|
11
|
+
TOOLING_ROOT="$PROJECT_ROOT/tooling"
|
|
12
|
+
|
|
13
|
+
# `find` writes to stderr and returns non-zero for a missing root, inside a
|
|
14
|
+
# process substitution whose status nothing reads. Without this the walk covers
|
|
15
|
+
# nothing and the check reports the seeds independent having never read one.
|
|
16
|
+
if [ ! -d "$TOOLING_ROOT" ]; then
|
|
17
|
+
echo "No tooling root at ${TOOLING_ROOT#"$PROJECT_ROOT/"}, seed independence unverifiable." >&2
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# An empty discovery is a real state rather than a broken walk, and the Seed
|
|
22
|
+
# standards stage already reports it as a skip. Failing here would have the two
|
|
23
|
+
# stages disagree about what the same condition means.
|
|
24
|
+
seed_roots=$(collect_seed_roots)
|
|
25
|
+
if [ -z "$seed_roots" ]; then
|
|
26
|
+
echo "No seed root carries .claude/, nothing to check." >&2
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# Markdown alone. The seed tree also ships hooks that call the toolkit CLI on
|
|
31
|
+
# purpose, each reporting a named stale-index warning when the binary is absent,
|
|
32
|
+
# and scoping by extension leaves them outside this walk without an exemption
|
|
33
|
+
# list that would have to be maintained against them.
|
|
34
|
+
cited=""
|
|
35
|
+
measured=0
|
|
36
|
+
while IFS= read -r seed_root; do
|
|
37
|
+
while IFS= read -r file; do
|
|
38
|
+
measured=$((measured + 1))
|
|
39
|
+
while IFS= read -r hit; do
|
|
40
|
+
cited="$cited ${file#"$PROJECT_ROOT/"}:$hit"$'\n'
|
|
41
|
+
done < <(grep -n "$TOOLKIT_TOKEN" "$file" || true)
|
|
42
|
+
done < <(find "$PROJECT_ROOT/$seed_root" -type f -name '*.md')
|
|
43
|
+
done <<<"$seed_roots"
|
|
44
|
+
|
|
45
|
+
# Roots resolved and no markdown under any of them is a walk that covered
|
|
46
|
+
# nothing, which is the verdict-without-a-measurement the guards above refuse for
|
|
47
|
+
# a missing tree. Reporting a pass here would say the seeds cite no CLI on the
|
|
48
|
+
# strength of having read no prose.
|
|
49
|
+
if [ "$measured" -eq 0 ]; then
|
|
50
|
+
echo "Seed roots resolved but carry no markdown, seed independence unverifiable." >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
if [ -n "$cited" ]; then
|
|
55
|
+
echo "Seed prose cites the toolkit CLI:" >&2
|
|
56
|
+
printf '%s' "$cited" >&2
|
|
57
|
+
echo "A scaffolded project may not have $TOOLKIT_TOKEN installed. State the capability the line needs rather than the binary that supplies it." >&2
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
set -o pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
7
|
+
|
|
8
|
+
SKILLS_DIR="$PROJECT_ROOT/claude/skills"
|
|
9
|
+
|
|
10
|
+
# A shipped skill runs from a target project, where the toolkit's own wiki/ does
|
|
11
|
+
# not exist. Anchoring on a non-path character keeps a target's .claude/wiki/ legal.
|
|
12
|
+
BANNED_PATH_PATTERN='(^|[^[:alnum:]._/-])wiki/'
|
|
13
|
+
|
|
14
|
+
[ -d "$SKILLS_DIR" ] || exit 0
|
|
15
|
+
|
|
16
|
+
matches=$(grep -rnE "$BANNED_PATH_PATTERN" "$SKILLS_DIR" || true)
|
|
17
|
+
|
|
18
|
+
[ -z "$matches" ] && exit 0
|
|
19
|
+
|
|
20
|
+
echo "Shipped skills reference a repo-local path that does not exist in a target project:"
|
|
21
|
+
echo "$matches" | sed "s|^$PROJECT_ROOT/||"
|
|
22
|
+
echo
|
|
23
|
+
echo "Reach supporting prose through a canon docs command, a standard cited at the flat root, or inlined text."
|
|
24
|
+
exit 1
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
set -o pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
7
|
+
|
|
8
|
+
source "$PROJECT_ROOT/scripts/lib/ui.sh"
|
|
9
|
+
|
|
10
|
+
check_dependencies() {
|
|
11
|
+
command -v bun >/dev/null 2>&1 || log_error "bun is not installed"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
main() {
|
|
15
|
+
check_dependencies
|
|
16
|
+
|
|
17
|
+
echo -e "${GREY}┌${NC}"
|
|
18
|
+
|
|
19
|
+
echo -e "${GREY}├${NC} ${WHITE}Cleaning artifacts${NC}"
|
|
20
|
+
rm -rf node_modules
|
|
21
|
+
|
|
22
|
+
log_rem "node_modules/"
|
|
23
|
+
|
|
24
|
+
log_step "Cleaning cache"
|
|
25
|
+
bun pm cache rm
|
|
26
|
+
log_info "Package manager cache cleared"
|
|
27
|
+
|
|
28
|
+
log_step "Rehydrating project"
|
|
29
|
+
bun install
|
|
30
|
+
log_info "Dependencies installed"
|
|
31
|
+
|
|
32
|
+
echo -e "${GREY}└${NC}\n"
|
|
33
|
+
echo -e "${GREEN}✓ Clean complete${NC}"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
main "$@"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
set -o pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
7
|
+
|
|
8
|
+
source "$PROJECT_ROOT/scripts/lib/ui.sh"
|
|
9
|
+
|
|
10
|
+
TMP_ROOT="$PROJECT_ROOT/.claude/.tmp/install-check"
|
|
11
|
+
CLONE_DIR="$TMP_ROOT/clone"
|
|
12
|
+
TARGET_DIR="$TMP_ROOT/target"
|
|
13
|
+
KEEP=0
|
|
14
|
+
|
|
15
|
+
for arg in "$@"; do
|
|
16
|
+
case "$arg" in
|
|
17
|
+
--keep) KEEP=1 ;;
|
|
18
|
+
--help | -h)
|
|
19
|
+
cat <<HELP
|
|
20
|
+
Usage: scripts/core/install-check.sh [--keep]
|
|
21
|
+
|
|
22
|
+
Verifies the README install path end to end:
|
|
23
|
+
1. Clones this repo into .claude/.tmp/install-check/clone
|
|
24
|
+
2. Runs bun install in the clone
|
|
25
|
+
3. Runs the CLI with --help to confirm it executes
|
|
26
|
+
4. Scaffolds a fresh project in .claude/.tmp/install-check/target
|
|
27
|
+
5. Runs canon init and asserts a scaffold landed
|
|
28
|
+
|
|
29
|
+
Flags:
|
|
30
|
+
--keep Keep the tmp tree on exit for inspection
|
|
31
|
+
HELP
|
|
32
|
+
exit 0
|
|
33
|
+
;;
|
|
34
|
+
esac
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
cleanup() {
|
|
38
|
+
if [ "$KEEP" = "1" ]; then
|
|
39
|
+
log_info "Kept artifacts at $TMP_ROOT"
|
|
40
|
+
else
|
|
41
|
+
rm -rf "$TMP_ROOT"
|
|
42
|
+
fi
|
|
43
|
+
close_timeline
|
|
44
|
+
}
|
|
45
|
+
trap cleanup EXIT
|
|
46
|
+
|
|
47
|
+
rm -rf "$TMP_ROOT"
|
|
48
|
+
mkdir -p "$TMP_ROOT"
|
|
49
|
+
|
|
50
|
+
open_timeline "Install verification"
|
|
51
|
+
|
|
52
|
+
log_step "Clone"
|
|
53
|
+
git clone --quiet "$PROJECT_ROOT" "$CLONE_DIR" 2>&1 | pipe_output || true
|
|
54
|
+
log_info "Cloned to $CLONE_DIR"
|
|
55
|
+
|
|
56
|
+
log_step "Install dependencies"
|
|
57
|
+
(cd "$CLONE_DIR" && bun install --silent 2>&1 | pipe_output) || log_error "bun install failed"
|
|
58
|
+
log_info "Dependencies installed"
|
|
59
|
+
|
|
60
|
+
log_step "Confirm CLI runs"
|
|
61
|
+
(cd "$CLONE_DIR" && bun run src/cli.ts --help >/dev/null) || log_error "canon --help failed"
|
|
62
|
+
log_info "canon --help ran clean"
|
|
63
|
+
|
|
64
|
+
log_step "Scaffold fresh project"
|
|
65
|
+
mkdir -p "$TARGET_DIR"
|
|
66
|
+
(cd "$TARGET_DIR" && git init --quiet)
|
|
67
|
+
log_info "Initialized git in $TARGET_DIR"
|
|
68
|
+
|
|
69
|
+
log_step "Run canon init"
|
|
70
|
+
(cd "$TARGET_DIR" && CANON_NON_INTERACTIVE=1 bun run "$CLONE_DIR/src/cli.ts" init --stack base 2>&1 | pipe_output) || log_error "canon init failed"
|
|
71
|
+
log_info "canon init completed"
|
|
72
|
+
|
|
73
|
+
log_step "Assert scaffold"
|
|
74
|
+
# Every domain canon init installs needs at least one path here. A domain with
|
|
75
|
+
# no assertion can truncate silently: init still exits 0 because run_domain
|
|
76
|
+
# catches a failed domain, and the gate stays green while the target is
|
|
77
|
+
# missing everything that domain provides.
|
|
78
|
+
#
|
|
79
|
+
# Standards and snippets name no path because neither corpus installs into a
|
|
80
|
+
# target. A scaffold reads a standard through `canon standards <name>` and a
|
|
81
|
+
# snippet through the plugin's live `claude/snippets` symlink, both resolving
|
|
82
|
+
# against the toolkit rather than a copy this gate could assert on. The
|
|
83
|
+
# `@`-reference convention rule is the one snippets-domain file that still
|
|
84
|
+
# installs, since `base` carries `governance/rules/snippets/` as a
|
|
85
|
+
# folder-whole entry the same way it does `core` and `claude`.
|
|
86
|
+
for path in "CLAUDE.md" ".claude/wiki/index.md" ".claude" ".claude/context/index.md" ".claude/wireframes/index.md" ".claude/diagrams/index.md" \
|
|
87
|
+
".prettierrc" ".editorconfig" ".lintstagedrc" ".husky/pre-commit" ".github/workflows/verify.yml" "scripts/verify.sh" \
|
|
88
|
+
".claude/rules/core/000-constitution.md" ".claude/rules/snippets/505-at-references.md"; do
|
|
89
|
+
if [ ! -e "$TARGET_DIR/$path" ]; then
|
|
90
|
+
log_error "Missing after canon init: $path"
|
|
91
|
+
fi
|
|
92
|
+
log_info "Found: $path"
|
|
93
|
+
done
|
|
94
|
+
|
|
95
|
+
if [ ! -x "$TARGET_DIR/scripts/verify.sh" ]; then
|
|
96
|
+
log_error "Not executable after canon init: scripts/verify.sh"
|
|
97
|
+
fi
|
|
98
|
+
log_info "Executable: scripts/verify.sh"
|
|
99
|
+
|
|
100
|
+
log_step "Verification passed"
|
|
101
|
+
log_info "Manual check still needed: bun link and global canon invocation"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Prints every seed root carrying a `.claude/`, one per line and relative to
|
|
3
|
+
# the project root.
|
|
4
|
+
#
|
|
5
|
+
# The discovery rule has one definition, `collect_seed_roots` in
|
|
6
|
+
# `scripts/lib/tooling.sh`, which `check-seed-independence.sh` already reads.
|
|
7
|
+
# This file is the route a caller outside bash takes to that same answer, so a
|
|
8
|
+
# stack seeding `.claude/` later reaches both readers and the two stages
|
|
9
|
+
# measuring seed content cannot disagree about which roots exist.
|
|
10
|
+
set -e
|
|
11
|
+
set -o pipefail
|
|
12
|
+
|
|
13
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
14
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
15
|
+
|
|
16
|
+
source "$PROJECT_ROOT/scripts/lib/tooling.sh"
|
|
17
|
+
|
|
18
|
+
collect_seed_roots
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
set -o pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
7
|
+
|
|
8
|
+
# `.claude/rules/` is a subset rather than a mirror, so it resolves through the
|
|
9
|
+
# stack machinery. The record naming the subset is `internal/governance.toml`.
|
|
10
|
+
bun "$PROJECT_ROOT/src/cli.ts" gov regen --root "$PROJECT_ROOT"
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Fills assets/hero.html.tmpl from the CLI catalogs and writes assets/hero.html.
|
|
3
|
+
#
|
|
4
|
+
# Only the HTML regenerates here. The PNG beside it is a chromium render whose
|
|
5
|
+
# bytes move with the browser version, so asserting it in verify.sh would fail
|
|
6
|
+
# on a machine whose chromium differs rather than on a stale count. Rebuild the
|
|
7
|
+
# image with `canon capture assets/hero.html` after this script reports a change.
|
|
8
|
+
# That capture also writes assets/hero.stamp, which records the digest of the
|
|
9
|
+
# markup it rendered and is what the Hero stage compares, so all three files
|
|
10
|
+
# commit together. The frame carries no version. `package.json` is bumped on main by the release
|
|
11
|
+
# tooling, so embedding it drifts every open branch on the next release and the
|
|
12
|
+
# stage then fails for work that touched nothing.
|
|
13
|
+
#
|
|
14
|
+
# Clone-only. `src/capture` is excluded from the published tarball, and this
|
|
15
|
+
# script reads the repository's own catalogs, so a registry install has neither.
|
|
16
|
+
set -e
|
|
17
|
+
set -o pipefail
|
|
18
|
+
|
|
19
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
20
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
21
|
+
|
|
22
|
+
TEMPLATE="$PROJECT_ROOT/assets/hero.html.tmpl"
|
|
23
|
+
OUTPUT="$PROJECT_ROOT/assets/hero.html"
|
|
24
|
+
LISTED=10
|
|
25
|
+
|
|
26
|
+
# `bun src/cli.ts` rather than `canon`, since a globally linked binary resolves to
|
|
27
|
+
# the main checkout no matter which worktree is running.
|
|
28
|
+
catalog() {
|
|
29
|
+
(cd "$PROJECT_ROOT" && CANON_NON_INTERACTIVE=1 bun src/cli.ts "$@" --json 2>/dev/null)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if [ ! -f "$TEMPLATE" ]; then
|
|
33
|
+
echo "regen-hero: missing template at $TEMPLATE" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# The commands have no `--json` catalog of their own, so the count comes from
|
|
38
|
+
# `canon gov counts`, which already reads the registration block in the CLI
|
|
39
|
+
# entry point to judge a document stating its own command count. Reading that
|
|
40
|
+
# figure here rather than re-deriving it with a second regex is what keeps the
|
|
41
|
+
# two readings of `src/cli.ts` from drifting apart unwatched, which is the
|
|
42
|
+
# defect `canon gov counts` itself exists to catch.
|
|
43
|
+
# `gov counts` exits non-zero on an ordinary finding, unlike every `list` verb
|
|
44
|
+
# below, so its output is read past that under `set -e` rather than aborting
|
|
45
|
+
# a hero rebuild for a stale count somewhere unrelated in the tree.
|
|
46
|
+
COUNTS_JSON="$(catalog gov counts || true)"
|
|
47
|
+
SKILLS_JSON="$(catalog claude skills list)"
|
|
48
|
+
GOV_JSON="$(catalog gov list)"
|
|
49
|
+
STANDARDS_JSON="$(catalog standards list)"
|
|
50
|
+
SNIPPETS_JSON="$(catalog snippets list)"
|
|
51
|
+
TOOLING_JSON="$(catalog tooling list)"
|
|
52
|
+
|
|
53
|
+
for payload in "$COUNTS_JSON" "$SKILLS_JSON" "$GOV_JSON" "$STANDARDS_JSON" "$SNIPPETS_JSON" "$TOOLING_JSON"; do
|
|
54
|
+
if [ -z "$payload" ]; then
|
|
55
|
+
echo "regen-hero: a catalog returned nothing, refusing to write a zeroed hero" >&2
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
# The catalogs reach the eval as files rather than as environment entries. Linux
|
|
61
|
+
# caps a single env string at 128KB, and the standards payload crossed it, which
|
|
62
|
+
# fails the exec with E2BIG before any stage can report a stale count. A file
|
|
63
|
+
# path is bounded whatever the catalogs grow to.
|
|
64
|
+
PAYLOAD_DIR="$(mktemp -d)"
|
|
65
|
+
trap 'rm -rf "$PAYLOAD_DIR"' EXIT
|
|
66
|
+
|
|
67
|
+
printf '%s' "$COUNTS_JSON" >"$PAYLOAD_DIR/counts.json"
|
|
68
|
+
printf '%s' "$SKILLS_JSON" >"$PAYLOAD_DIR/skills.json"
|
|
69
|
+
printf '%s' "$GOV_JSON" >"$PAYLOAD_DIR/gov.json"
|
|
70
|
+
printf '%s' "$STANDARDS_JSON" >"$PAYLOAD_DIR/standards.json"
|
|
71
|
+
printf '%s' "$SNIPPETS_JSON" >"$PAYLOAD_DIR/snippets.json"
|
|
72
|
+
printf '%s' "$TOOLING_JSON" >"$PAYLOAD_DIR/tooling.json"
|
|
73
|
+
|
|
74
|
+
export PAYLOAD_DIR
|
|
75
|
+
export TEMPLATE OUTPUT LISTED PROJECT_ROOT
|
|
76
|
+
|
|
77
|
+
bun --eval '
|
|
78
|
+
const { readFileSync } = require("node:fs")
|
|
79
|
+
|
|
80
|
+
const { PAYLOAD_DIR, TEMPLATE, OUTPUT, LISTED, PROJECT_ROOT } = process.env
|
|
81
|
+
|
|
82
|
+
const payload = (name) => readFileSync(PAYLOAD_DIR + "/" + name + ".json", "utf8")
|
|
83
|
+
|
|
84
|
+
const COUNTS_JSON = payload("counts")
|
|
85
|
+
const SKILLS_JSON = payload("skills")
|
|
86
|
+
const GOV_JSON = payload("gov")
|
|
87
|
+
const STANDARDS_JSON = payload("standards")
|
|
88
|
+
const SNIPPETS_JSON = payload("snippets")
|
|
89
|
+
const TOOLING_JSON = payload("tooling")
|
|
90
|
+
|
|
91
|
+
const listed = Number(LISTED)
|
|
92
|
+
const skills = JSON.parse(SKILLS_JSON).skills.map((entry) => entry.name)
|
|
93
|
+
const gov = JSON.parse(GOV_JSON)
|
|
94
|
+
// Rule names carry a numeric prefix that orders the load, not the identity a
|
|
95
|
+
// reader knows them by, so the frame shows the slug alone.
|
|
96
|
+
const slug = (entry) => entry.name.replace(/^\d+-/, "")
|
|
97
|
+
const rules = gov.rules.map(slug)
|
|
98
|
+
// A rule no stack names is opt-in behind `--add`, so featuring one advertises
|
|
99
|
+
// an entry no ordinary `canon gov install` delivers. The column samples the
|
|
100
|
+
// stack-reached subset while its count and remainder describe the whole catalog.
|
|
101
|
+
const stacked = new Set(gov.stacks.flatMap((stack) => stack.rules))
|
|
102
|
+
const deliveredRules = gov.rules.filter((entry) => stacked.has(entry.name)).map(slug)
|
|
103
|
+
const standards = JSON.parse(STANDARDS_JSON).standards.map((entry) => entry.name)
|
|
104
|
+
const snippets = new Set(
|
|
105
|
+
JSON.parse(SNIPPETS_JSON).categories.flatMap((category) => category.entries),
|
|
106
|
+
)
|
|
107
|
+
const toolingStacks = JSON.parse(TOOLING_JSON).stacks
|
|
108
|
+
const commandCount = JSON.parse(COUNTS_JSON).catalogs.commands
|
|
109
|
+
if (!commandCount) {
|
|
110
|
+
console.error("regen-hero: gov counts read no commands catalog, refusing to write a zeroed hero")
|
|
111
|
+
process.exit(1)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const escape = (value) =>
|
|
115
|
+
value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")
|
|
116
|
+
|
|
117
|
+
// Even spacing across the sorted catalog rather than its first N, so a column
|
|
118
|
+
// whose names share a prefix does not read as a narrower catalog than the one
|
|
119
|
+
// that ships. Rules and standards sample. Skills do not, because the even step
|
|
120
|
+
// lands on the entries closest to commodity and on none of the workflow the
|
|
121
|
+
// toolkit exists to carry.
|
|
122
|
+
const sample = (names) => {
|
|
123
|
+
if (names.length <= listed) return names
|
|
124
|
+
const step = names.length / listed
|
|
125
|
+
return Array.from({ length: listed }, (_, i) => names[Math.floor(i * step)])
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// The first seven are the method and exist nowhere else. The last three are
|
|
129
|
+
// recognizable on sight and are what keeps a column of chosen names from
|
|
130
|
+
// reading as an all-`claude-` catalog, which is the failure the sampler above
|
|
131
|
+
// was written against.
|
|
132
|
+
const FEATURED_SKILLS = [
|
|
133
|
+
"claude-feature",
|
|
134
|
+
"claude-groundwork",
|
|
135
|
+
"claude-intake",
|
|
136
|
+
"claude-orchestrate",
|
|
137
|
+
"claude-autoship",
|
|
138
|
+
"claude-pr-review",
|
|
139
|
+
"claude-tasks",
|
|
140
|
+
"git-ship",
|
|
141
|
+
"setup-init",
|
|
142
|
+
"systematic-debugging",
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
// A chosen name is maintained by hand where a sample never goes stale, so a
|
|
146
|
+
// rename has to fail the run rather than quietly shrink the column. This is
|
|
147
|
+
// what makes the trade acceptable.
|
|
148
|
+
//
|
|
149
|
+
// The length is asserted because the `+N more` figure below counts down from
|
|
150
|
+
// `listed` rather than from what this returns, so a list of any other length
|
|
151
|
+
// renders a remainder that is wrong by the difference.
|
|
152
|
+
const featured = (names, chosen) => {
|
|
153
|
+
if (chosen.length !== listed) {
|
|
154
|
+
console.error(`regen-hero: ${chosen.length} featured skills, expected ${listed}`)
|
|
155
|
+
process.exit(1)
|
|
156
|
+
}
|
|
157
|
+
const catalog = new Set(names)
|
|
158
|
+
const missing = chosen.filter((name) => !catalog.has(name))
|
|
159
|
+
if (missing.length > 0) {
|
|
160
|
+
console.error(`regen-hero: featured skills missing from the catalog: ${missing.join(", ")}`)
|
|
161
|
+
process.exit(1)
|
|
162
|
+
}
|
|
163
|
+
return chosen
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const markup = (names) =>
|
|
167
|
+
names
|
|
168
|
+
.map((name) => ` <div class="entry">${escape(name)}</div>`)
|
|
169
|
+
.join("\n")
|
|
170
|
+
|
|
171
|
+
const entries = (names) => markup(sample(names))
|
|
172
|
+
|
|
173
|
+
const remaining = (names) => String(Math.max(0, names.length - listed))
|
|
174
|
+
|
|
175
|
+
// An empty array is well-formed JSON, so the shell guard on an empty payload
|
|
176
|
+
// does not catch a catalog whose tree went missing. A zeroed count would ship a
|
|
177
|
+
// frame claiming the domain has nothing in it.
|
|
178
|
+
for (const [label, list] of [
|
|
179
|
+
["skills", skills], ["rules", rules], ["standards", standards],
|
|
180
|
+
["snippets", [...snippets]], ["tooling stacks", toolingStacks], ["gov stacks", gov.stacks],
|
|
181
|
+
["stack-delivered rules", deliveredRules],
|
|
182
|
+
]) {
|
|
183
|
+
if (list.length === 0) {
|
|
184
|
+
console.error(`regen-hero: the ${label} catalog is empty, refusing to write a zeroed hero`)
|
|
185
|
+
process.exit(1)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const values = {
|
|
190
|
+
SKILL_COUNT: String(skills.length),
|
|
191
|
+
RULE_COUNT: String(rules.length),
|
|
192
|
+
STANDARD_COUNT: String(standards.length),
|
|
193
|
+
SNIPPET_COUNT: String(snippets.size),
|
|
194
|
+
GOV_STACK_COUNT: String(gov.stacks.length),
|
|
195
|
+
TOOLING_STACK_COUNT: String(toolingStacks.length),
|
|
196
|
+
COMMAND_COUNT: String(commandCount),
|
|
197
|
+
SKILL_ENTRIES: markup(featured(skills, FEATURED_SKILLS)),
|
|
198
|
+
RULE_ENTRIES: entries(deliveredRules),
|
|
199
|
+
STANDARD_ENTRIES: entries(standards),
|
|
200
|
+
SKILL_MORE: remaining(skills),
|
|
201
|
+
RULE_MORE: remaining(rules),
|
|
202
|
+
STANDARD_MORE: remaining(standards),
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
let html = await Bun.file(TEMPLATE).text()
|
|
206
|
+
for (const [key, value] of Object.entries(values)) {
|
|
207
|
+
html = html.replaceAll(`{{${key}}}`, value)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const unresolved = html.match(/{{[A-Z_]+}}/g)
|
|
211
|
+
if (unresolved) {
|
|
212
|
+
console.error(`regen-hero: unresolved placeholders ${[...new Set(unresolved)].join(", ")}`)
|
|
213
|
+
process.exit(1)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
await Bun.write(OUTPUT, html)
|
|
217
|
+
'
|