@erclx/canon 5.49.0 → 5.51.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +4024 -0
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/auto-ship/references/fan-in.md +20 -6
  4. package/claude/skills/canon-cli/SKILL.md +9 -7
  5. package/claude/skills/canvas-board/REQUIREMENT.md +4 -3
  6. package/claude/skills/canvas-board/SKILL.md +8 -9
  7. package/claude/skills/ci-workflow/REQUIREMENT.md +3 -3
  8. package/claude/skills/ci-workflow/SKILL.md +26 -1
  9. package/claude/skills/ci-workflow/references/workflows.md +28 -0
  10. package/claude/skills/context-fold/references/context.md +4 -3
  11. package/claude/skills/design-record/REQUIREMENT.md +33 -0
  12. package/claude/skills/design-record/SKILL.md +84 -0
  13. package/claude/skills/design-record/references/folder.md +69 -0
  14. package/claude/skills/design-taste/SKILL.md +3 -2
  15. package/claude/skills/git-followup/SKILL.md +1 -0
  16. package/claude/skills/git-pr/references/pr.md +1 -1
  17. package/claude/skills/markdown-craft/REQUIREMENT.md +1 -0
  18. package/claude/skills/markdown-craft/SKILL.md +6 -1
  19. package/claude/skills/markdown-craft/references/markdown.md +3 -3
  20. package/claude/skills/markdown-craft/references/tables.md +30 -0
  21. package/claude/skills/pick-by-eye/SKILL.md +10 -8
  22. package/claude/skills/plan-feature/SKILL.md +13 -1
  23. package/claude/skills/plan-feature/references/batches.md +1 -1
  24. package/claude/skills/session-worktree/SKILL.md +1 -1
  25. package/claude/skills/target-check/references/domains.md +8 -6
  26. package/docs/agents/index.md +2 -2
  27. package/docs/agents/markdown-audit.md +5 -2
  28. package/docs/agents/migrate.md +2 -0
  29. package/docs/agents/targets.md +8 -1
  30. package/docs/target/migrations.md +8 -1
  31. package/docs/target/projects.md +1 -1
  32. package/docs/workflow/parallel-features.md +1 -1
  33. package/docs/workflow/skill-map.md +2 -1
  34. package/docs/workflow/visual-design-workflow.md +2 -1
  35. package/governance/detect.toml +1 -1
  36. package/governance/ledger/tooling/ci-workflow.md +6 -0
  37. package/governance/ledger/ui/design-reference.md +8 -12
  38. package/governance/rules/tooling/ci-workflow.md +4 -0
  39. package/governance/rules/ui/design-reference.md +4 -6
  40. package/package.json +2 -1
  41. package/scripts/ci/check-browsers.sh +13 -0
  42. package/scripts/ci/delete-previews.sh +34 -0
  43. package/scripts/ci/publish-check.sh +29 -0
  44. package/scripts/ci/refresh-frames-pr.sh +63 -0
  45. package/scripts/ci/report-baseline.sh +23 -0
  46. package/scripts/ci/stack-issues.sh +24 -0
  47. package/scripts/ci/verify-npm-token.sh +14 -0
  48. package/src/claude/cases/misc.ts +5 -0
  49. package/src/cli/help.ts +1 -0
  50. package/src/cli.ts +2 -0
  51. package/src/commands/changelog.ts +146 -0
  52. package/src/commands/claude.ts +26 -1
  53. package/src/commands/gate.ts +57 -16
  54. package/src/commands/hooks.ts +7 -5
  55. package/src/commands/markdown.ts +98 -19
  56. package/src/commands/migrate.ts +77 -0
  57. package/src/commands/worktrees.ts +273 -0
  58. package/src/context/audit.ts +6 -5
  59. package/src/design/budget.ts +1 -1
  60. package/src/design/components.ts +1 -1
  61. package/src/design/document.ts +1 -1
  62. package/src/design/regen.ts +1 -1
  63. package/src/design/render.ts +1 -1
  64. package/src/gate/hand-suite.ts +52 -0
  65. package/src/gate/measures.ts +9 -2
  66. package/src/gate/sequencer.ts +17 -8
  67. package/src/gov/detect.ts +28 -10
  68. package/src/hooks/post-merge.ts +45 -6
  69. package/src/markdown/gated.ts +5 -7
  70. package/src/markdown/scope.ts +60 -10
  71. package/src/markdown/structure.ts +1 -1
  72. package/src/markdown/tables.ts +150 -0
  73. package/src/migrate/status.ts +128 -0
  74. package/src/tasks/validate.ts +15 -12
  75. package/src/version/changelog.ts +156 -0
  76. package/src/worktrees/members.ts +540 -0
  77. package/tooling/base/configs/.husky/post-merge +7 -6
  78. package/tooling/claude/reference.md +1 -0
  79. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +11 -1
  80. package/tooling/claude/seeds/CLAUDE.md +9 -0
  81. package/tooling/cloudflare/configs/.github/workflows/deploy.yml +10 -28
  82. package/tooling/cloudflare/configs/scripts/delete-previews.sh +36 -0
  83. package/tooling/cloudflare/reference.md +7 -4
  84. package/tooling/web/reference.md +5 -0
  85. package/tooling/web/seeds/canon/design/index.md +23 -0
  86. /package/claude/skills/{canvas-board → design-record}/references/design.md +0 -0
@@ -1,16 +1,17 @@
1
1
  #!/usr/bin/env sh
2
2
 
3
3
  # Runs the post-merge steps through `canon hooks post-merge`: archive the task a
4
- # merged pull request closed, push the records, reclaim merged worktrees,
5
- # reinstall the CLI, and update the plugin cache. The verb owns the order and
6
- # each line it prints.
4
+ # merged pull request closed, push the records, retire the fan-in members a
5
+ # merged integrator named, reclaim merged worktrees, reinstall the CLI, and
6
+ # update the plugin cache. The verb owns the order and each line it prints.
7
7
  #
8
- # CANON_SKIP_RECLAIM=1 turns off the worktree reclaim.
8
+ # CANON_SKIP_RECLAIM=1 turns off the member retirement and the worktree
9
+ # reclaim, since both remove worktrees.
9
10
  # CANON_SKIP_UPGRADE=1 turns off the CLI reinstall.
10
11
  # CANON_SKIP_PLUGIN_UPDATE=1 turns off the plugin cache update.
11
12
  #
12
- # The reclaim reads merge state through `gh`, so a machine without it on PATH
13
- # reclaims nothing and says nothing. Install `gh` to turn it on.
13
+ # Both read merge state through `gh`, so a machine without it on PATH retires
14
+ # and reclaims nothing and says nothing. Install `gh` to turn them on.
14
15
  #
15
16
  # Husky runs this as `sh -e`, and `post-rewrite` sources it on a rebase, so
16
17
  # every test sits inside an `if` or an `||` and nothing here exits non-zero.
@@ -57,6 +57,7 @@ A project installed before the board became a folder still holds `.claude/TASKS.
57
57
 
58
58
  - Fill in the seed's placeholder project name, description, and key paths after init
59
59
  - Keep its sections `Context`, `Commands`, and `Key paths`, since skills detect, extend, or skip by heading
60
+ - Group `Key paths` under H3s, each opening on a lead sentence, before it runs past 5 bullets. `canon markdown audit` and `canon claude sync` both report a longer run.
60
61
  - Keep the `Context` section to one line pointing at the state docs, since `plan-feature` does the parallel read when invoked
61
62
 
62
63
  ## Seed docs
@@ -81,6 +81,11 @@ colons=$(printf '%s' "$record" |
81
81
  density=$(printf '%s' "$record" |
82
82
  jq -r '.entries[]?.density[]? | ":\(.line) \(.kind) " + (if .limit == null then "opens with neither a paragraph nor a table" else "\(.value) past \(.limit)" end) + (if .gating then " gating" else "" end)' 2>/dev/null)
83
83
 
84
+ # Table findings report and never gate, so each kind is handed back with the
85
+ # fix its shape takes rather than the seam a density finding splits at.
86
+ tables=$(printf '%s' "$record" |
87
+ jq -r '.entries[]?.tables[]? | ":\(.line) \(.kind) " + (if .limit == null then "a list follows the table with no lead sentence" else "\(.value) past \(.limit)" end)' 2>/dev/null)
88
+
84
89
  # A page marked `kind: reference` carries reference shape findings, handed back
85
90
  # whole the same way, since a gated one fails the push like a density finding.
86
91
  shape=$(printf '%s' "$record" |
@@ -92,7 +97,7 @@ shape=$(printf '%s' "$record" |
92
97
  empty=$(printf '%s' "$record" |
93
98
  jq -r '[.bans.emptySets[]?] | join(", ")' 2>/dev/null)
94
99
 
95
- [ -z "$hits" ] && [ -z "$headings" ] && [ -z "$colons" ] && [ -z "$density" ] && [ -z "$shape" ] && [ -z "$unread" ] && [ -z "$empty" ] && exit 0
100
+ [ -z "$hits" ] && [ -z "$headings" ] && [ -z "$colons" ] && [ -z "$density" ] && [ -z "$tables" ] && [ -z "$shape" ] && [ -z "$unread" ] && [ -z "$empty" ] && exit 0
96
101
 
97
102
  nl=$'\n'
98
103
  msg=""
@@ -125,6 +130,11 @@ if [ -n "$density" ]; then
125
130
  msg="${msg:+$msg$nl}$found"
126
131
  fi
127
132
 
133
+ if [ -n "$tables" ]; then
134
+ found=$(printf 'Standards-audit: %s breaks the markdown table limits, being a 120-character cell, 8 body rows, a list directly after a table, and a code span holding a run past 30 characters. These report and never fail a push. Move a long cell into a bullet under the table'"'"'s lead, split a long table into groups each under a lead sentence, give a trailing list its own lead sentence, and move a wide token out of the table.\n%s' "$file" "$tables")
135
+ msg="${msg:+$msg$nl}$found"
136
+ fi
137
+
128
138
  if [ -n "$shape" ]; then
129
139
  found=$(printf 'Standards-audit: %s is marked kind: reference and breaks its shape, being an opening, then Output, Refusals, and See also, each at most once and in that order, no H3, and no flag table. Point at the command'"'"'s own --help for flags. A finding marked gating fails the push.\n%s' "$file" "$shape")
130
140
  msg="${msg:+$msg$nl}$found"
@@ -15,5 +15,14 @@
15
15
 
16
16
  ## Key paths
17
17
 
18
+ ### Code
19
+
20
+ [One sentence on what the code paths below hold]
21
+
18
22
  - `src/`: [description]
23
+
24
+ ### Content
25
+
26
+ [One sentence on what the content paths below hold]
27
+
19
28
  - `canon/DESIGN.md`: visual intent, pointing at the stylesheet that holds the values
@@ -130,36 +130,18 @@ jobs:
130
130
  if: github.event_name == 'pull_request'
131
131
  runs-on: ubuntu-latest
132
132
  steps:
133
- # Deployments are listed through the REST API rather than wrangler, whose
134
- # listing carries no branch filter. `force=true` is what lets a deployment
135
- # still holding its branch alias be deleted. An absent secret skips the
136
- # job the way the deploy's own guard does.
133
+ # The default branch, since a closed pull request may have no merge ref to
134
+ # check out, and the script that holds the Cloudflare token should not
135
+ # come from the branch being closed.
136
+ - name: Checkout
137
+ uses: actions/checkout@v7
138
+ with:
139
+ ref: ${{ github.event.repository.default_branch }}
140
+
137
141
  - name: Delete preview deployments
138
142
  env:
139
143
  CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
140
144
  CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
141
- # Fill in the same Pages project name the Publish step deploys to.
142
- PROJECT_NAME: REPLACE_WITH_PROJECT_NAME
143
145
  BRANCH: ${{ github.head_ref }}
144
- run: |
145
- if [ -z "$CLOUDFLARE_API_TOKEN" ] || [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then
146
- echo "::notice::CLOUDFLARE_API_TOKEN or CLOUDFLARE_ACCOUNT_ID is not set, skipping preview cleanup."
147
- exit 0
148
- fi
149
- api="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$PROJECT_NAME/deployments"
150
- auth="Authorization: Bearer $CLOUDFLARE_API_TOKEN"
151
- page=1
152
- ids=""
153
- while :; do
154
- listing=$(curl -fsS -H "$auth" "$api?env=preview&per_page=25&page=$page")
155
- [ "$(echo "$listing" | jq '.result | length')" -eq 0 ] && break
156
- ids="$ids $(echo "$listing" | jq -r --arg branch "$BRANCH" '.result[] | select(.deployment_trigger.metadata.branch == $branch) | .id')"
157
- page=$((page + 1))
158
- done
159
- deleted=0
160
- for id in $ids; do
161
- curl -fsS -X DELETE -H "$auth" "$api/$id?force=true" >/dev/null
162
- echo "Deleted $id"
163
- deleted=$((deleted + 1))
164
- done
165
- echo "Deleted $deleted preview deployments for $BRANCH."
146
+ # Fill in the same Pages project name the Publish step deploys to.
147
+ run: bash scripts/delete-previews.sh REPLACE_WITH_PROJECT_NAME "$BRANCH"
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env bash
2
+ # Deletes the Cloudflare Pages preview deployments minted for one branch, called
3
+ # by the cleanup-preview job in .github/workflows/deploy.yml with the Pages
4
+ # project name and the branch. CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID
5
+ # come from the step env, and an absent secret skips the job the way the
6
+ # deploy's own guard does.
7
+ #
8
+ # Deployments are listed through the REST API rather than wrangler, whose
9
+ # listing carries no branch filter. `force=true` is what lets a deployment
10
+ # still holding its branch alias be deleted.
11
+ set -e
12
+
13
+ PROJECT_NAME=$1
14
+ BRANCH=$2
15
+
16
+ if [ -z "$CLOUDFLARE_API_TOKEN" ] || [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then
17
+ echo "::notice::CLOUDFLARE_API_TOKEN or CLOUDFLARE_ACCOUNT_ID is not set, skipping preview cleanup."
18
+ exit 0
19
+ fi
20
+ api="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$PROJECT_NAME/deployments"
21
+ auth="Authorization: Bearer $CLOUDFLARE_API_TOKEN"
22
+ page=1
23
+ ids=""
24
+ while :; do
25
+ listing=$(curl -fsS -H "$auth" "$api?env=preview&per_page=25&page=$page")
26
+ [ "$(echo "$listing" | jq '.result | length')" -eq 0 ] && break
27
+ ids="$ids $(echo "$listing" | jq -r --arg branch "$BRANCH" '.result[] | select(.deployment_trigger.metadata.branch == $branch) | .id')"
28
+ page=$((page + 1))
29
+ done
30
+ deleted=0
31
+ for id in $ids; do
32
+ curl -fsS -X DELETE -H "$auth" "$api/$id?force=true" >/dev/null
33
+ echo "Deleted $id"
34
+ deleted=$((deleted + 1))
35
+ done
36
+ echo "Deleted $deleted preview deployments for $BRANCH."
@@ -2,7 +2,9 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- The cloudflare stack ships one parameterized GitHub Actions workflow that deploys a static build to Cloudflare Pages. It is keyed on host rather than on framework and carries no dependencies, seeds, or scripts of its own, so it syncs onto a project already carrying `astro`, `vite-react`, or any other stack without colliding.
5
+ The cloudflare stack ships one parameterized GitHub Actions workflow that deploys a static build to Cloudflare Pages. It is keyed on host rather than on framework and carries no dependencies or seeds of its own, so it syncs onto a project already carrying `astro`, `vite-react`, or any other stack without colliding.
6
+
7
+ It ships one script, `scripts/delete-previews.sh`, which the cleanup job calls and which overwrites a project's own file of that name on every sync.
6
8
 
7
9
  ## Deploy workflow
8
10
 
@@ -28,7 +30,8 @@ Every branch gets a preview URL rather than only `main`.
28
30
 
29
31
  A `pull_request` trigger on `closed` runs only the `cleanup-preview` job, which deletes every preview deployment Cloudflare holds for that branch.
30
32
 
31
- - It lists them through the Pages REST API, because the wrangler listing has no branch filter.
33
+ - It checks out the default branch and runs `scripts/delete-previews.sh` with the Pages project name and the closing branch as arguments.
34
+ - The script lists them through the Pages REST API, because the wrangler listing has no branch filter.
32
35
  - It deletes each with `force=true`, so a deployment still holding the branch alias goes too.
33
36
  - It skips with a notice when the secrets are absent, the same as the deploy job.
34
37
 
@@ -38,9 +41,9 @@ Three values in the seeded file have no generic default, and a project sets them
38
41
 
39
42
  - The `paths:` filter under the `push` trigger ships as a single `src/**` glob. Widen it to every path the build reads when the build draws on catalogs or generated content outside `src/`.
40
43
  - The `concurrency.group` name ships as `deploy-${{ github.ref_name }}`, enough for one deploy. Rename the `deploy` prefix only for a second deploy workflow, and keep the ref suffix.
41
- - The Pages project name appears twice as `REPLACE_WITH_PROJECT_NAME`, in the `--project-name` flag and as `PROJECT_NAME` in the cleanup job.
44
+ - The Pages project name appears twice as `REPLACE_WITH_PROJECT_NAME`, in the `--project-name` flag and as the first argument to `scripts/delete-previews.sh` in the cleanup job.
42
45
  - Set both to the name the `deploy-app` skill creates the project under.
43
46
 
44
47
  ## Re-sync
45
48
 
46
- `configs/` is golden and always overwrites. Re-running `canon tooling sync cloudflare . --write` after hand-editing any of the three parameters above discards that edit and restores the shipped defaults. Re-fill the parameters after any re-sync rather than expecting the file to preserve them.
49
+ `configs/` is golden and always overwrites, `scripts/delete-previews.sh` included. Re-running `canon tooling sync cloudflare . --write` after hand-editing any of the three parameters above discards that edit and restores the shipped defaults. Re-fill the parameters after any re-sync rather than expecting the file to preserve them.
@@ -86,6 +86,11 @@ The web layer covers the tooling shared across Vite + React, Astro, and Next.js.
86
86
  - `.github/workflows/verify.yml` runs `static-checks`, `unit-tests`, `build-verify`, and `e2e-tests`. `unit-tests` installs Chromium and runs `test:browser` only when the project defines that script.
87
87
  - Read `governance/rules/tooling/ci-workflow.md` for when a workflow's commit-back is right and when a report is
88
88
 
89
+ ## Design references
90
+
91
+ - Expect a seeded `canon/design/index.md` stub carrying `auto: false`, copied only when missing, so a project's own index is never replaced
92
+ - Expect `governance/rules/ui/design-reference.md` to install once a group folder sits under `canon/design/`, since the stub alone is no reference
93
+
89
94
  ## Ports
90
95
 
91
96
  - Derive every served port from `scripts/worktree-port.sh`, never a port literal in a script string, since two worktrees of one repository otherwise attach to one server
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: Design references
3
+ description: The accepted design frames a build matches, grouped by app part, with the code each group governs
4
+ auto: false
5
+ ---
6
+
7
+ # Design references
8
+
9
+ Each group holds accepted frames a build matches, light and dark. The `design-record` skill carries the folder standard, so load it before adding, redrawing, or removing a reference.
10
+
11
+ ## Layout
12
+
13
+ - Give each app part one plain kebab-case folder, such as `home` or `inspector`
14
+ - Put tokens, colors, and the logo under `foundations/`
15
+ - Name each file `<name>-dark` or `<name>-light`, a PNG beside its frame HTML
16
+ - Put what every frame loads under `kit/`
17
+
18
+ ## Groups
19
+
20
+ One row per group, `foundations` included. List no files, since the tree answers what exists.
21
+
22
+ | Group | What the user sees | Code | States |
23
+ | ----- | ------------------ | ---- | ------ |