@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.
- package/CHANGELOG.md +4024 -0
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/references/fan-in.md +20 -6
- package/claude/skills/canon-cli/SKILL.md +9 -7
- package/claude/skills/canvas-board/REQUIREMENT.md +4 -3
- package/claude/skills/canvas-board/SKILL.md +8 -9
- package/claude/skills/ci-workflow/REQUIREMENT.md +3 -3
- package/claude/skills/ci-workflow/SKILL.md +26 -1
- package/claude/skills/ci-workflow/references/workflows.md +28 -0
- package/claude/skills/context-fold/references/context.md +4 -3
- package/claude/skills/design-record/REQUIREMENT.md +33 -0
- package/claude/skills/design-record/SKILL.md +84 -0
- package/claude/skills/design-record/references/folder.md +69 -0
- package/claude/skills/design-taste/SKILL.md +3 -2
- package/claude/skills/git-followup/SKILL.md +1 -0
- package/claude/skills/git-pr/references/pr.md +1 -1
- package/claude/skills/markdown-craft/REQUIREMENT.md +1 -0
- package/claude/skills/markdown-craft/SKILL.md +6 -1
- package/claude/skills/markdown-craft/references/markdown.md +3 -3
- package/claude/skills/markdown-craft/references/tables.md +30 -0
- package/claude/skills/pick-by-eye/SKILL.md +10 -8
- package/claude/skills/plan-feature/SKILL.md +13 -1
- package/claude/skills/plan-feature/references/batches.md +1 -1
- package/claude/skills/session-worktree/SKILL.md +1 -1
- package/claude/skills/target-check/references/domains.md +8 -6
- package/docs/agents/index.md +2 -2
- package/docs/agents/markdown-audit.md +5 -2
- package/docs/agents/migrate.md +2 -0
- package/docs/agents/targets.md +8 -1
- package/docs/target/migrations.md +8 -1
- package/docs/target/projects.md +1 -1
- package/docs/workflow/parallel-features.md +1 -1
- package/docs/workflow/skill-map.md +2 -1
- package/docs/workflow/visual-design-workflow.md +2 -1
- package/governance/detect.toml +1 -1
- package/governance/ledger/tooling/ci-workflow.md +6 -0
- package/governance/ledger/ui/design-reference.md +8 -12
- package/governance/rules/tooling/ci-workflow.md +4 -0
- package/governance/rules/ui/design-reference.md +4 -6
- package/package.json +2 -1
- package/scripts/ci/check-browsers.sh +13 -0
- package/scripts/ci/delete-previews.sh +34 -0
- package/scripts/ci/publish-check.sh +29 -0
- package/scripts/ci/refresh-frames-pr.sh +63 -0
- package/scripts/ci/report-baseline.sh +23 -0
- package/scripts/ci/stack-issues.sh +24 -0
- package/scripts/ci/verify-npm-token.sh +14 -0
- package/src/claude/cases/misc.ts +5 -0
- package/src/cli/help.ts +1 -0
- package/src/cli.ts +2 -0
- package/src/commands/changelog.ts +146 -0
- package/src/commands/claude.ts +26 -1
- package/src/commands/gate.ts +57 -16
- package/src/commands/hooks.ts +7 -5
- package/src/commands/markdown.ts +98 -19
- package/src/commands/migrate.ts +77 -0
- package/src/commands/worktrees.ts +273 -0
- package/src/context/audit.ts +6 -5
- package/src/design/budget.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/design/document.ts +1 -1
- package/src/design/regen.ts +1 -1
- package/src/design/render.ts +1 -1
- package/src/gate/hand-suite.ts +52 -0
- package/src/gate/measures.ts +9 -2
- package/src/gate/sequencer.ts +17 -8
- package/src/gov/detect.ts +28 -10
- package/src/hooks/post-merge.ts +45 -6
- package/src/markdown/gated.ts +5 -7
- package/src/markdown/scope.ts +60 -10
- package/src/markdown/structure.ts +1 -1
- package/src/markdown/tables.ts +150 -0
- package/src/migrate/status.ts +128 -0
- package/src/tasks/validate.ts +15 -12
- package/src/version/changelog.ts +156 -0
- package/src/worktrees/members.ts +540 -0
- package/tooling/base/configs/.husky/post-merge +7 -6
- package/tooling/claude/reference.md +1 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +11 -1
- package/tooling/claude/seeds/CLAUDE.md +9 -0
- package/tooling/cloudflare/configs/.github/workflows/deploy.yml +10 -28
- package/tooling/cloudflare/configs/scripts/delete-previews.sh +36 -0
- package/tooling/cloudflare/reference.md +7 -4
- package/tooling/web/reference.md +5 -0
- package/tooling/web/seeds/canon/design/index.md +23 -0
- /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,
|
|
5
|
-
#
|
|
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
|
|
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
|
-
#
|
|
13
|
-
# reclaims nothing and says nothing. Install `gh` to turn
|
|
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
|
-
#
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
|
|
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
|
-
|
|
145
|
-
|
|
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
|
|
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
|
|
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 `
|
|
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.
|
package/tooling/web/reference.md
CHANGED
|
@@ -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
|
+
| ----- | ------------------ | ---- | ------ |
|
|
File without changes
|