@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,268 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { execaSync } from 'execa'
|
|
4
|
+
import { gitEnv } from '@/git-env'
|
|
5
|
+
import {
|
|
6
|
+
findInstalledOrigin,
|
|
7
|
+
type HistoryIndex,
|
|
8
|
+
readHistoryIndex,
|
|
9
|
+
toRepoPath,
|
|
10
|
+
} from '@/sync/history'
|
|
11
|
+
|
|
12
|
+
const CLAUDE_DIR = '.claude'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A `CLAUDE.md` past this many lines has more in it than the always-load tier
|
|
16
|
+
* is for. The figure is the checkpoint `standards/context.md` sets for
|
|
17
|
+
* a context entry, raised because `CLAUDE.md` legitimately carries more than
|
|
18
|
+
* one domain. It gates a proposal rather than a failure, so being approximate
|
|
19
|
+
* costs a line an operator can ignore.
|
|
20
|
+
*/
|
|
21
|
+
const CLAUDE_MD_LINES = 250
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Who put an unclaimed folder in the target. A dropped folder and one the
|
|
25
|
+
* project wrote are the same bytes at the same path, so this is traced from the
|
|
26
|
+
* toolkit's own history and never guessed from the filesystem.
|
|
27
|
+
*
|
|
28
|
+
* `unattributed` is a verdict in its own right rather than a soft `dropped`.
|
|
29
|
+
* The toolkit shipped a path of that name and the content matches no version it
|
|
30
|
+
* ever published, which is exactly what history proving nothing looks like. An
|
|
31
|
+
* operator can act on a labelled unknown and cannot act on a guess.
|
|
32
|
+
*/
|
|
33
|
+
export type Attribution = 'dropped' | 'project' | 'unattributed'
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A folder the target holds at a root the toolkit has stopped shipping.
|
|
37
|
+
* Carries no source and queues no change, because only the user can decide what
|
|
38
|
+
* happens to content the toolkit no longer claims.
|
|
39
|
+
*/
|
|
40
|
+
export interface UnclaimedFolder {
|
|
41
|
+
readonly rel: string
|
|
42
|
+
readonly files: number
|
|
43
|
+
readonly attribution: Attribution
|
|
44
|
+
/** Toolkit revision whose version of a file here the target still holds. */
|
|
45
|
+
readonly since?: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A proposal-only skill with a live case in this target. The skills propose and
|
|
50
|
+
* never execute, so the report names one rather than queueing a change.
|
|
51
|
+
*/
|
|
52
|
+
export interface MigrationCandidate {
|
|
53
|
+
readonly skill: string
|
|
54
|
+
/** What was measured, so the proposal is checkable before it is run. */
|
|
55
|
+
readonly reason: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ReverseReport {
|
|
59
|
+
readonly unclaimed: readonly UnclaimedFolder[]
|
|
60
|
+
readonly migrations: readonly MigrationCandidate[]
|
|
61
|
+
/** Set when the walk needed history to run and this toolkit has none. */
|
|
62
|
+
readonly historyUnavailable: boolean
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const EMPTY_REVERSE: ReverseReport = {
|
|
66
|
+
unclaimed: [],
|
|
67
|
+
migrations: [],
|
|
68
|
+
historyUnavailable: false,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Asks the question every other detection surface asks backwards: what does the
|
|
73
|
+
* target hold that no live catalog claims. The forward direction enumerates
|
|
74
|
+
* toolkit-owned keys and tests the target against them, so a folder the toolkit
|
|
75
|
+
* deleted appears in no section at all.
|
|
76
|
+
*
|
|
77
|
+
* Scoped to roots the toolkit itself has dropped rather than to the whole tree.
|
|
78
|
+
* Walking the tree reports every project folder as unclaimed, which is true and
|
|
79
|
+
* useless, and the question here is only what the toolkit put there and then
|
|
80
|
+
* stopped claiming.
|
|
81
|
+
*
|
|
82
|
+
* Reports beside `superseded`, `unmigrated`, and `newSkills` rather than
|
|
83
|
+
* absorbing them. Each of those answers a narrower version of the same question
|
|
84
|
+
* and none is wrong today, so folding them in would change what two shipped
|
|
85
|
+
* sections print in the same change that introduces a third.
|
|
86
|
+
*/
|
|
87
|
+
export function buildReverseReport(
|
|
88
|
+
toolkitRoot: string,
|
|
89
|
+
target: string,
|
|
90
|
+
): ReverseReport {
|
|
91
|
+
const roots = readDroppedRoots(toolkitRoot)
|
|
92
|
+
const migrations = detectMigrations(target)
|
|
93
|
+
|
|
94
|
+
if (roots === undefined) {
|
|
95
|
+
return { unclaimed: [], migrations, historyUnavailable: true }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const unclaimed: UnclaimedFolder[] = []
|
|
99
|
+
|
|
100
|
+
for (const root of roots) {
|
|
101
|
+
for (const rel of [root, join(CLAUDE_DIR, root)]) {
|
|
102
|
+
const files = listFiles(join(target, rel))
|
|
103
|
+
if (files.length === 0) continue
|
|
104
|
+
|
|
105
|
+
unclaimed.push(attributeFolder(toolkitRoot, target, rel, root, files))
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return { unclaimed, migrations, historyUnavailable: false }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function emptyReverseReport(): ReverseReport {
|
|
113
|
+
return EMPTY_REVERSE
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Top-level toolkit paths that history records a deletion under and that no
|
|
118
|
+
* longer exist in the working tree. Both halves are load-bearing: a path with
|
|
119
|
+
* deletions that still exists is a live root the forward direction already
|
|
120
|
+
* covers, and a path that never lost a file was never dropped.
|
|
121
|
+
*
|
|
122
|
+
* Read as one log over the whole repository rather than per candidate, since
|
|
123
|
+
* the candidate set is what the call produces. A root-level file is skipped
|
|
124
|
+
* because this walk matches target folders, and a deleted `README.md` names no
|
|
125
|
+
* folder to look for.
|
|
126
|
+
*/
|
|
127
|
+
function readDroppedRoots(toolkitRoot: string): readonly string[] | undefined {
|
|
128
|
+
const result = execaSync(
|
|
129
|
+
'git',
|
|
130
|
+
[
|
|
131
|
+
'-C',
|
|
132
|
+
toolkitRoot,
|
|
133
|
+
'log',
|
|
134
|
+
'--all',
|
|
135
|
+
'--diff-filter=D',
|
|
136
|
+
'--name-only',
|
|
137
|
+
'--format=',
|
|
138
|
+
],
|
|
139
|
+
{ reject: false, env: gitEnv(), extendEnv: false },
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if (result.exitCode !== 0) return undefined
|
|
143
|
+
|
|
144
|
+
const roots = new Set<string>()
|
|
145
|
+
|
|
146
|
+
for (const line of result.stdout.split('\n')) {
|
|
147
|
+
const trimmed = line.trim()
|
|
148
|
+
const boundary = trimmed.indexOf('/')
|
|
149
|
+
if (boundary <= 0) continue
|
|
150
|
+
|
|
151
|
+
roots.add(trimmed.slice(0, boundary))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return [...roots]
|
|
155
|
+
.filter((root) => !existsSync(join(toolkitRoot, root)))
|
|
156
|
+
.sort()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Splits a found folder three ways against the toolkit's history of the root it
|
|
161
|
+
* sits at. Content matching a published version proves the toolkit put the file
|
|
162
|
+
* there. Names the toolkit shipped with content it never published proves only
|
|
163
|
+
* that the two collided, which is the unattributed case. No name overlap at all
|
|
164
|
+
* is a folder the project owns that happens to share a retired name.
|
|
165
|
+
*
|
|
166
|
+
* Only files whose relative path the toolkit once held are hashed, so a project
|
|
167
|
+
* folder colliding on name costs the walk no reads. The cost is that a file the
|
|
168
|
+
* toolkit shipped and the target renamed goes unmatched, the same limit
|
|
169
|
+
* `countToolkitOwned` carries for the forward direction.
|
|
170
|
+
*/
|
|
171
|
+
function attributeFolder(
|
|
172
|
+
toolkitRoot: string,
|
|
173
|
+
target: string,
|
|
174
|
+
rel: string,
|
|
175
|
+
root: string,
|
|
176
|
+
files: readonly string[],
|
|
177
|
+
): UnclaimedFolder {
|
|
178
|
+
const index = readHistoryIndex(toolkitRoot, [root])
|
|
179
|
+
|
|
180
|
+
if (index === undefined) {
|
|
181
|
+
return { rel, files: files.length, attribution: 'unattributed' }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
let covered = false
|
|
185
|
+
|
|
186
|
+
for (const file of files) {
|
|
187
|
+
const sourceRel = toRepoPath(join(root, file))
|
|
188
|
+
if (!covers(index, sourceRel)) continue
|
|
189
|
+
|
|
190
|
+
covered = true
|
|
191
|
+
const since = findInstalledOrigin(index, sourceRel, join(target, rel, file))
|
|
192
|
+
|
|
193
|
+
if (since !== undefined) {
|
|
194
|
+
return { rel, files: files.length, attribution: 'dropped', since }
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
rel,
|
|
200
|
+
files: files.length,
|
|
201
|
+
attribution: covered ? 'unattributed' : 'project',
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function covers(index: HistoryIndex, sourceRel: string): boolean {
|
|
206
|
+
return index.get(sourceRel) !== undefined
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Live cases for the two proposal-only skills no other report field names.
|
|
211
|
+
* Without this, both are documented and unreachable.
|
|
212
|
+
*
|
|
213
|
+
* Both tests read what the skill itself acts on, so a proposal the report makes
|
|
214
|
+
* is one the skill has work to do for. A context tier that already holds files
|
|
215
|
+
* settles the `docs/` split, whether or not the toolkit is what made it.
|
|
216
|
+
*/
|
|
217
|
+
export function detectMigrations(target: string): MigrationCandidate[] {
|
|
218
|
+
const found: MigrationCandidate[] = []
|
|
219
|
+
const claudeMd = join(target, 'CLAUDE.md')
|
|
220
|
+
|
|
221
|
+
if (existsSync(claudeMd)) {
|
|
222
|
+
const lines = countLines(readFileSync(claudeMd, 'utf8'))
|
|
223
|
+
if (lines > CLAUDE_MD_LINES) {
|
|
224
|
+
found.push({
|
|
225
|
+
skill: 'migration-claude-md',
|
|
226
|
+
reason: `CLAUDE.md carries ${lines} lines, past the ${CLAUDE_MD_LINES} the three-tier split is for`,
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const docs = listFiles(join(target, 'docs')).filter(isMarkdown).length
|
|
232
|
+
const context = listFiles(join(target, CLAUDE_DIR, 'context')).length
|
|
233
|
+
|
|
234
|
+
if (docs > 0 && context === 0) {
|
|
235
|
+
found.push({
|
|
236
|
+
skill: 'migration-context',
|
|
237
|
+
reason: `${docs} markdown files under docs/ with no .claude/context/ tier`,
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return found
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function isMarkdown(rel: string): boolean {
|
|
245
|
+
return rel.endsWith('.md')
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Lines as `wc -l` counts them, so the figure in the reason matches what an
|
|
250
|
+
* operator gets from the shell. Splitting alone overstates a file ending in a
|
|
251
|
+
* newline by one, and the reason states a measurement rather than a rank.
|
|
252
|
+
*/
|
|
253
|
+
function countLines(content: string): number {
|
|
254
|
+
const parts = content.split('\n')
|
|
255
|
+
return parts.at(-1) === '' ? parts.length - 1 : parts.length
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Every file under a directory, dotfiles included. A dropped root can hold any
|
|
260
|
+
* extension, so this does not filter to markdown the way the domain walk does.
|
|
261
|
+
*/
|
|
262
|
+
function listFiles(dir: string): string[] {
|
|
263
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory()) return []
|
|
264
|
+
|
|
265
|
+
return [
|
|
266
|
+
...new Bun.Glob('**/*').scanSync({ cwd: dir, onlyFiles: true, dot: true }),
|
|
267
|
+
].sort()
|
|
268
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { relative } from 'node:path'
|
|
3
|
+
import { planSeeds, type Seed } from '@/claude/seeds'
|
|
4
|
+
import { rewritesOnInstall, stripSeedMarker } from '@/seed-marker'
|
|
5
|
+
import { findInstalledOrigin, readHistoryIndex } from '@/sync/history'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* How an installed seed compares to the seed the toolkit currently ships.
|
|
9
|
+
*
|
|
10
|
+
* `missing` has no counterpart in the domain scan, which walks what a target
|
|
11
|
+
* installed and so cannot see a file that never arrived. Seeds are enumerated
|
|
12
|
+
* from the source instead, which is what makes the absence legible.
|
|
13
|
+
*
|
|
14
|
+
* There is no `customized` here. That verdict needs a stamp, and seeds carry
|
|
15
|
+
* none, so a file history cannot attribute stays `drifted` and a consumer reads
|
|
16
|
+
* it as the local edit it almost always is.
|
|
17
|
+
*/
|
|
18
|
+
export type SeedState = 'matching' | 'stale' | 'drifted' | 'missing'
|
|
19
|
+
|
|
20
|
+
export interface SeedReportEntry {
|
|
21
|
+
readonly state: SeedState
|
|
22
|
+
readonly rel: string
|
|
23
|
+
/** Toolkit revision this file's content came from, when history proved it. */
|
|
24
|
+
readonly since?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface SeedsReport {
|
|
28
|
+
readonly entries: readonly SeedReportEntry[]
|
|
29
|
+
/** Set when a file needed history to attribute it and this toolkit has none. */
|
|
30
|
+
readonly historyUnavailable: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Classifies every seed the toolkit ships against the target's copy, and never
|
|
35
|
+
* returns a change. Seeds are copy-once files a project is expected to edit, so
|
|
36
|
+
* the engine's copy path would overwrite `CLAUDE.md` wholesale. Reporting alone
|
|
37
|
+
* is what lets `claude-seed-sync` merge one section at a time instead.
|
|
38
|
+
*
|
|
39
|
+
* Attribution reuses the history reader rather than the engine's own recovery
|
|
40
|
+
* pass, which is private and takes a `SyncAdapter` seeds have no way to supply.
|
|
41
|
+
*/
|
|
42
|
+
export function buildSeedsReport(
|
|
43
|
+
toolkitRoot: string,
|
|
44
|
+
target: string,
|
|
45
|
+
): SeedsReport {
|
|
46
|
+
const differing: DifferingSeed[] = []
|
|
47
|
+
const entries: SeedReportEntry[] = []
|
|
48
|
+
|
|
49
|
+
for (const { seed, present } of planSeeds(toolkitRoot, target)) {
|
|
50
|
+
const rel = relative(target, seed.dest)
|
|
51
|
+
|
|
52
|
+
if (!present) {
|
|
53
|
+
entries.push({ state: 'missing', rel })
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (sameContent(seed.src, seed.dest)) {
|
|
58
|
+
entries.push({ state: 'matching', rel })
|
|
59
|
+
continue
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
differing.push({ index: entries.length, seed })
|
|
63
|
+
entries.push({ state: 'drifted', rel })
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const historyUnavailable = attribute(toolkitRoot, entries, differing)
|
|
67
|
+
|
|
68
|
+
return { entries, historyUnavailable }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface DifferingSeed {
|
|
72
|
+
readonly index: number
|
|
73
|
+
readonly seed: Seed
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Second pass over the seeds that differ, matching installed content against
|
|
78
|
+
* every version the toolkit ever published. A match proves the file is
|
|
79
|
+
* untouched since it landed, so the toolkit is what moved and the entry becomes
|
|
80
|
+
* `stale`. Runs as one git call for the whole set rather than one per file.
|
|
81
|
+
*/
|
|
82
|
+
function attribute(
|
|
83
|
+
toolkitRoot: string,
|
|
84
|
+
entries: SeedReportEntry[],
|
|
85
|
+
differing: readonly DifferingSeed[],
|
|
86
|
+
): boolean {
|
|
87
|
+
if (differing.length === 0) return false
|
|
88
|
+
|
|
89
|
+
const index = readHistoryIndex(
|
|
90
|
+
toolkitRoot,
|
|
91
|
+
differing.map((file) => relative(toolkitRoot, file.seed.src)),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if (index === undefined) return true
|
|
95
|
+
|
|
96
|
+
for (const file of differing) {
|
|
97
|
+
const since = findInstalledOrigin(
|
|
98
|
+
index,
|
|
99
|
+
relative(toolkitRoot, file.seed.src),
|
|
100
|
+
file.seed.dest,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if (since === undefined) continue
|
|
104
|
+
entries[file.index] = { ...entries[file.index], state: 'stale', since }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Compares the target against what an install would write, not against the seed
|
|
112
|
+
* source. The two differ for a markdown seed carrying the stub marker, which the
|
|
113
|
+
* install strips, so comparing sources would report a file the target never
|
|
114
|
+
* touched as drifted for as long as the marker stays set.
|
|
115
|
+
*/
|
|
116
|
+
function sameContent(source: string, dest: string): boolean {
|
|
117
|
+
const installed = readFileSync(dest)
|
|
118
|
+
|
|
119
|
+
if (!rewritesOnInstall(source)) {
|
|
120
|
+
return readFileSync(source).equals(installed)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
stripSeedMarker(readFileSync(source, 'utf8')) === installed.toString('utf8')
|
|
125
|
+
)
|
|
126
|
+
}
|