@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,428 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import type { Command } from 'commander'
|
|
4
|
+
import { cliPath, cliRun } from '@/cli-run'
|
|
5
|
+
import { PROJECT_ROOT } from '@/project-root'
|
|
6
|
+
import {
|
|
7
|
+
buildCheckReport,
|
|
8
|
+
type CheckReport,
|
|
9
|
+
hasDrift,
|
|
10
|
+
SCANNED_DOMAINS,
|
|
11
|
+
} from '@/sync/check'
|
|
12
|
+
import { createGitRunner, createPullRequestOpener, hasGh } from '@/sync/git'
|
|
13
|
+
import {
|
|
14
|
+
detectDomains,
|
|
15
|
+
installedDomains,
|
|
16
|
+
isTreeClean,
|
|
17
|
+
shouldSync,
|
|
18
|
+
SYNC_DOMAINS,
|
|
19
|
+
type SyncDomain,
|
|
20
|
+
} from '@/sync/target'
|
|
21
|
+
import type { UnclaimedFolder } from '@/sync/reverse'
|
|
22
|
+
import { runGitWorkflow } from '@/sync/workflow'
|
|
23
|
+
import { resolveTarget } from '@/target'
|
|
24
|
+
import {
|
|
25
|
+
intro,
|
|
26
|
+
isNonInteractive,
|
|
27
|
+
logError,
|
|
28
|
+
logInfo,
|
|
29
|
+
logStep,
|
|
30
|
+
logWarn,
|
|
31
|
+
outro,
|
|
32
|
+
palette,
|
|
33
|
+
} from '@/ui'
|
|
34
|
+
import { describeSkew } from '@/version/skew'
|
|
35
|
+
|
|
36
|
+
const SYNC_ARGS: Record<SyncDomain, readonly string[]> = {
|
|
37
|
+
governance: ['gov', 'sync'],
|
|
38
|
+
claude: ['claude', 'sync'],
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface SyncOptions {
|
|
42
|
+
readonly check?: boolean
|
|
43
|
+
readonly json?: boolean
|
|
44
|
+
readonly exitCode?: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function register(program: Command): void {
|
|
48
|
+
program
|
|
49
|
+
.command('sync')
|
|
50
|
+
.description('Sync all installed domains in a project')
|
|
51
|
+
.argument('[target]', 'Target directory', '.')
|
|
52
|
+
.option('--check', 'Report drift without writing anything')
|
|
53
|
+
.option('--json', 'Emit the drift report as JSON on stdout')
|
|
54
|
+
.option('--exit-code', 'Exit 1 when drift is found, for CI')
|
|
55
|
+
.helpOption('-h, --help', 'Show this help message')
|
|
56
|
+
.addHelpText(
|
|
57
|
+
'after',
|
|
58
|
+
[
|
|
59
|
+
'',
|
|
60
|
+
'Examples:',
|
|
61
|
+
' canon sync',
|
|
62
|
+
' canon sync ../my-app',
|
|
63
|
+
' canon sync --check',
|
|
64
|
+
' canon sync --check --json',
|
|
65
|
+
' canon sync --check --exit-code',
|
|
66
|
+
'',
|
|
67
|
+
].join('\n'),
|
|
68
|
+
)
|
|
69
|
+
.action(async (target: string, options: SyncOptions) => {
|
|
70
|
+
process.exitCode =
|
|
71
|
+
options.check === true
|
|
72
|
+
? await runCheck(target, options)
|
|
73
|
+
: await runSync(target)
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Reads the same plan a sync would apply and writes nothing. Drift between
|
|
79
|
+
* syncs is normal, so the default exit stays 0 and CI opts into failing.
|
|
80
|
+
*/
|
|
81
|
+
async function runCheck(target: string, options: SyncOptions): Promise<number> {
|
|
82
|
+
const resolved = resolveTarget(target, PROJECT_ROOT)
|
|
83
|
+
if (typeof resolved === 'number') return resolved
|
|
84
|
+
|
|
85
|
+
const report = await buildCheckReport(PROJECT_ROOT, resolved)
|
|
86
|
+
|
|
87
|
+
if (options.json === true) {
|
|
88
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`)
|
|
89
|
+
} else {
|
|
90
|
+
renderCheck(report)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return options.exitCode === true && hasDrift(report) ? 1 : 0
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function renderCheck(report: CheckReport): void {
|
|
97
|
+
intro('canon sync --check')
|
|
98
|
+
|
|
99
|
+
renderSkew(report)
|
|
100
|
+
|
|
101
|
+
if (report.stampAtLegacyPath) {
|
|
102
|
+
logWarn(
|
|
103
|
+
'Stamp found at a retired path. Move it to .claude/canon/config.json.',
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!report.managed) {
|
|
108
|
+
logStep('Not a toolkit project')
|
|
109
|
+
logWarn('No .claude/ directory and no CLAUDE.md at the target.')
|
|
110
|
+
logInfo(
|
|
111
|
+
'Run `canon init` to install, or /canon:setup-init to resolve a stack.',
|
|
112
|
+
)
|
|
113
|
+
outro()
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
for (const domain of report.domains) {
|
|
118
|
+
logStep(domain.domain)
|
|
119
|
+
|
|
120
|
+
if (domain.commit === undefined) {
|
|
121
|
+
logWarn(
|
|
122
|
+
domain.historyUnavailable
|
|
123
|
+
? 'Not stamped, and this toolkit has no git history. Drift below is reported unattributed.'
|
|
124
|
+
: 'Not stamped. Drift below is attributed from toolkit history.',
|
|
125
|
+
)
|
|
126
|
+
} else {
|
|
127
|
+
logInfo(`Synced from ${domain.commit} on ${domain.syncedAt}`)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
for (const entry of domain.entries) {
|
|
131
|
+
if (entry.state === 'matching' || entry.state === 'orphaned') continue
|
|
132
|
+
logWarn(entry.notice ?? `${entry.rel} (${entry.state})`)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const { stale, customized, drifted, stranded, orphaned, missing } =
|
|
136
|
+
domain.counts
|
|
137
|
+
if (stale + customized + drifted + stranded === 0) {
|
|
138
|
+
logInfo(orphaned === 0 ? 'up to date' : `up to date (${orphaned} local)`)
|
|
139
|
+
}
|
|
140
|
+
// A local file is not a deficiency and a missing rule is, so this never
|
|
141
|
+
// shares the up-to-date line's parenthetical. It prints on its own,
|
|
142
|
+
// regardless of whether anything above needs a sync.
|
|
143
|
+
if (missing > 0) {
|
|
144
|
+
logWarn(`${missing} listed by the stack, not installed`)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for (const commit of domain.upstream) {
|
|
148
|
+
logInfo(`${commit.sha} ${commit.subject}`)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
renderTooling(report)
|
|
153
|
+
|
|
154
|
+
for (const entry of report.unmigrated) {
|
|
155
|
+
logStep(`${entry.domain} (not migrated)`)
|
|
156
|
+
logWarn(
|
|
157
|
+
`${entry.files} files at ${entry.rootPath}/, nothing at ${entry.installPath}/`,
|
|
158
|
+
)
|
|
159
|
+
logInfo('Move the content yourself. No sync command touches these.')
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
renderSeeds(report)
|
|
163
|
+
|
|
164
|
+
if (report.superseded.length > 0) {
|
|
165
|
+
logStep('Superseded by a newer layout')
|
|
166
|
+
for (const entry of report.superseded) {
|
|
167
|
+
logWarn(`${entry.rel} (replaced by ${entry.replacedBy}/)`)
|
|
168
|
+
}
|
|
169
|
+
logInfo('Move the content yourself. No sync command touches these.')
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (report.newSkills.length > 0) {
|
|
173
|
+
logStep('New skills, no sync needed')
|
|
174
|
+
for (const name of report.newSkills) logInfo(name)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Warned where `newSkills` is noted, because a new skill loads live and needs
|
|
178
|
+
// nothing run while a rule reaches the target only when someone installs it.
|
|
179
|
+
// No sync closes any of this, so the remedy names the install command.
|
|
180
|
+
if (report.newRules.length > 0) {
|
|
181
|
+
logStep('New rules, never installed')
|
|
182
|
+
for (const name of report.newRules) logWarn(name)
|
|
183
|
+
// `install` re-resolves the whole stack rather than adding one rule, so
|
|
184
|
+
// the remedy names both routes rather than assuming the reader wants all.
|
|
185
|
+
logInfo(
|
|
186
|
+
'Run `canon gov install <stack>` to take the whole stack again, or `--add <rule>` to take one.',
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
renderUnclaimed(report)
|
|
191
|
+
renderMigrations(report)
|
|
192
|
+
|
|
193
|
+
outro()
|
|
194
|
+
// Scanned domains only. Tooling renders a section on every managed target, so
|
|
195
|
+
// naming it here repeats what that section already said under a second
|
|
196
|
+
// remedy, where a scanned domain nobody installed has no section at all and
|
|
197
|
+
// this line is the only place it appears.
|
|
198
|
+
const unmigrated = report.unmigrated.map((entry) => entry.domain)
|
|
199
|
+
const uncovered = SCANNED_DOMAINS.filter(
|
|
200
|
+
(domain) => !report.covers.includes(domain) && !unmigrated.includes(domain),
|
|
201
|
+
)
|
|
202
|
+
if (uncovered.length === 0) return
|
|
203
|
+
|
|
204
|
+
const { GREY, NC } = palette(process.stderr)
|
|
205
|
+
process.stderr.write(
|
|
206
|
+
`${GREY}Unstamped: ${uncovered.join(', ')}. Run the matching sync to record one.${NC}\n`,
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* The binary reports before any domain does, since a stale binary is what makes
|
|
212
|
+
* every section below it a reading from the wrong toolkit. It prints on all
|
|
213
|
+
* three states rather than only when behind: a check that goes quiet when the
|
|
214
|
+
* registry is unreachable is indistinguishable from one that found nothing.
|
|
215
|
+
*/
|
|
216
|
+
function renderSkew(report: CheckReport): void {
|
|
217
|
+
const { skew } = report
|
|
218
|
+
logStep('toolkit version')
|
|
219
|
+
|
|
220
|
+
if (skew.state === 'behind') {
|
|
221
|
+
logWarn(describeSkew(skew))
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
logInfo(describeSkew(skew))
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Tooling prints whether it was measured before it prints any count, because a
|
|
230
|
+
* target with no chain recorded produces the same zero a current target does.
|
|
231
|
+
* Naming the state is the whole reason the section exists.
|
|
232
|
+
*/
|
|
233
|
+
function renderTooling(report: CheckReport): void {
|
|
234
|
+
const { tooling } = report
|
|
235
|
+
logStep('tooling')
|
|
236
|
+
|
|
237
|
+
if (!tooling.measured) {
|
|
238
|
+
logWarn(
|
|
239
|
+
tooling.chain.length === 0
|
|
240
|
+
? 'Not stamped. No chain recorded, so tooling drift is unmeasured.'
|
|
241
|
+
: `Recorded chain names no stack this toolkit ships: ${tooling.chain.join(' < ')}.`,
|
|
242
|
+
)
|
|
243
|
+
logInfo(
|
|
244
|
+
'Run `canon tooling sync <stack> --write` to record what this target holds.',
|
|
245
|
+
)
|
|
246
|
+
return
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
logInfo(`Chain: ${tooling.chain.join(' < ')}`)
|
|
250
|
+
if (tooling.commit !== undefined) {
|
|
251
|
+
logInfo(`Synced from ${tooling.commit} on ${tooling.syncedAt}`)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (tooling.changes === 0) {
|
|
255
|
+
logInfo('up to date')
|
|
256
|
+
return
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
for (const [category, count] of Object.entries(tooling.counts)) {
|
|
260
|
+
if (count > 0) logWarn(`${count} ${category}`)
|
|
261
|
+
}
|
|
262
|
+
logInfo(
|
|
263
|
+
'Run `canon tooling sync --check` to see which files, `--write` to apply.',
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Seeds print their own section because no sync command applies them. A `stale`
|
|
269
|
+
* seed is safe to take whole and a `drifted` one holds edits, which is the split
|
|
270
|
+
* `claude-seed-sync` reads to decide what needs a section-level merge.
|
|
271
|
+
*/
|
|
272
|
+
function renderSeeds(report: CheckReport): void {
|
|
273
|
+
const notable = report.seeds.entries.filter(
|
|
274
|
+
(entry) => entry.state !== 'matching',
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
if (notable.length === 0) return
|
|
278
|
+
|
|
279
|
+
logStep('seeds')
|
|
280
|
+
if (report.seeds.historyUnavailable) {
|
|
281
|
+
logWarn('This toolkit has no git history. Drift below is unattributed.')
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
for (const entry of notable) {
|
|
285
|
+
logWarn(`${entry.rel} (${entry.state})`)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
logInfo('Run /canon:claude-seed-sync to reconcile these section by section.')
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Names the attribution before the count, the way the tooling section does. A
|
|
293
|
+
* dropped folder and a project-authored one are the same bytes at the same
|
|
294
|
+
* path, so the count alone is the one thing an operator cannot act on.
|
|
295
|
+
*
|
|
296
|
+
* A folder history proved the project owns is dropped from the render and kept
|
|
297
|
+
* in the JSON. Printing it costs a line on every run for a name collision no
|
|
298
|
+
* remedy closes, which is the bar this section had to clear to exist at all.
|
|
299
|
+
*/
|
|
300
|
+
function renderUnclaimed(report: CheckReport): void {
|
|
301
|
+
const { unclaimed, historyUnavailable } = report.reverse
|
|
302
|
+
const notable = unclaimed.filter((entry) => entry.attribution !== 'project')
|
|
303
|
+
|
|
304
|
+
if (notable.length === 0 && !historyUnavailable) return
|
|
305
|
+
|
|
306
|
+
logStep('No longer shipped by the toolkit')
|
|
307
|
+
|
|
308
|
+
if (historyUnavailable) {
|
|
309
|
+
logWarn('This toolkit has no git history, so nothing could be walked.')
|
|
310
|
+
return
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
for (const entry of notable) {
|
|
314
|
+
logWarn(`${entry.rel}/ (${describeUnclaimed(entry)})`)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
logInfo(
|
|
318
|
+
'Decide what happens to these yourself. No sync command touches them.',
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* State first, then the count, then where the content came from. The revision
|
|
324
|
+
* is the commit that published the content the target still holds, never the
|
|
325
|
+
* one that dropped the folder, so it takes a clause of its own. Suffixed onto
|
|
326
|
+
* `dropped upstream` it reads as the date of the drop, and an operator running
|
|
327
|
+
* `git show` on it lands on the commit that added the folder.
|
|
328
|
+
*/
|
|
329
|
+
function describeUnclaimed(entry: UnclaimedFolder): string {
|
|
330
|
+
const state =
|
|
331
|
+
entry.attribution === 'dropped' ? 'dropped upstream' : 'unattributed'
|
|
332
|
+
const counted = `${state}, ${entry.files} files`
|
|
333
|
+
|
|
334
|
+
if (entry.since === undefined) return counted
|
|
335
|
+
|
|
336
|
+
return `${counted}, content published at ${entry.since.slice(0, 7)}`
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* The proposal-only skills no other field reaches.
|
|
341
|
+
*/
|
|
342
|
+
function renderMigrations(report: CheckReport): void {
|
|
343
|
+
const { migrations } = report.reverse
|
|
344
|
+
if (migrations.length === 0) return
|
|
345
|
+
|
|
346
|
+
logStep('Migrations with a case here')
|
|
347
|
+
|
|
348
|
+
for (const candidate of migrations) {
|
|
349
|
+
logWarn(candidate.reason)
|
|
350
|
+
logInfo(`Run /canon:${candidate.skill} for a proposal.`)
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
async function runSync(target: string): Promise<number> {
|
|
355
|
+
intro('canon sync')
|
|
356
|
+
|
|
357
|
+
const resolved = resolveTarget(target, PROJECT_ROOT)
|
|
358
|
+
if (typeof resolved === 'number') return resolved
|
|
359
|
+
|
|
360
|
+
const git = createGitRunner(resolved)
|
|
361
|
+
const { GREY, NC, YELLOW } = palette(process.stderr)
|
|
362
|
+
|
|
363
|
+
logStep('Checking working tree')
|
|
364
|
+
if (!isTreeClean(await git.status([]))) {
|
|
365
|
+
logError(
|
|
366
|
+
'Working tree has uncommitted changes. Commit or stash before syncing.',
|
|
367
|
+
)
|
|
368
|
+
outro()
|
|
369
|
+
return 1
|
|
370
|
+
}
|
|
371
|
+
logInfo('Working tree clean')
|
|
372
|
+
|
|
373
|
+
logStep('Detecting domains')
|
|
374
|
+
const states = detectDomains(resolved)
|
|
375
|
+
for (const state of states) {
|
|
376
|
+
if (state.installed) logInfo(state.domain)
|
|
377
|
+
else logWarn(`${state.domain} (not installed, skipping)`)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (installedDomains(states).length === 0) {
|
|
381
|
+
outro()
|
|
382
|
+
process.stderr.write(
|
|
383
|
+
`\n${YELLOW}! No domains installed in target. Run domain install commands first.${NC}\n`,
|
|
384
|
+
)
|
|
385
|
+
return 0
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
outro()
|
|
389
|
+
process.stderr.write('\n')
|
|
390
|
+
|
|
391
|
+
await runDomainSyncs(resolved)
|
|
392
|
+
|
|
393
|
+
const code = await runGitWorkflow(resolved, {
|
|
394
|
+
git,
|
|
395
|
+
pullRequests: (await hasGh())
|
|
396
|
+
? createPullRequestOpener(resolved)
|
|
397
|
+
: undefined,
|
|
398
|
+
now: new Date(),
|
|
399
|
+
nonInteractive: isNonInteractive(),
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
if (existsSync(join(resolved, '.claude'))) {
|
|
403
|
+
process.stderr.write(
|
|
404
|
+
`${GREY}Tip: run \`/claude-seed-sync\` to audit seed drift per section, preserving local customizations.${NC}\n`,
|
|
405
|
+
)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return code
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Each domain sync runs as its own process. They open their own frames and
|
|
413
|
+
* prompt for their own changes, so stdin stays inherited. Claude is the one
|
|
414
|
+
* exception: it runs headless because the combined pull request preview is the
|
|
415
|
+
* single confirmation gate for the whole sync, and `canon claude sync` writes
|
|
416
|
+
* only `.gitignore`.
|
|
417
|
+
*/
|
|
418
|
+
async function runDomainSyncs(target: string): Promise<void> {
|
|
419
|
+
const path = cliPath(PROJECT_ROOT)
|
|
420
|
+
|
|
421
|
+
for (const domain of SYNC_DOMAINS) {
|
|
422
|
+
if (!shouldSync(target, domain)) continue
|
|
423
|
+
|
|
424
|
+
await cliRun(path, [...SYNC_ARGS[domain], target], {
|
|
425
|
+
nonInteractive: domain === 'claude',
|
|
426
|
+
})()
|
|
427
|
+
}
|
|
428
|
+
}
|