@erclx/canon 5.37.0 → 5.39.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/README.md +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +12 -9
- package/claude/skills/auto-ship/SKILL.md +43 -23
- package/claude/skills/backlog-triage/SKILL.md +62 -53
- package/claude/skills/backlog-triage/references/apply.md +69 -0
- package/claude/skills/build-in-slices/SKILL.md +8 -4
- package/claude/skills/canon-cli/SKILL.md +5 -1
- package/claude/skills/canon-feedback/SKILL.md +18 -8
- package/claude/skills/canon-feedback-triage/SKILL.md +10 -3
- package/claude/skills/canvas-board/SKILL.md +36 -17
- package/claude/skills/ci-workflow/SKILL.md +5 -4
- package/claude/skills/code-craft/SKILL.md +10 -6
- package/claude/skills/codebase-layout/SKILL.md +3 -5
- package/claude/skills/context-fold/REQUIREMENT.md +4 -4
- package/claude/skills/context-fold/SKILL.md +42 -23
- package/claude/skills/context-fold/references/context-refresh.md +4 -3
- package/claude/skills/context-fold/references/context.md +79 -64
- package/claude/skills/create-rule/SKILL.md +7 -3
- package/claude/skills/create-skill/SKILL.md +27 -7
- package/claude/skills/create-skill/references/skill-reference.md +41 -17
- package/claude/skills/decision-escalate/SKILL.md +8 -5
- package/claude/skills/deploy-app/SKILL.md +1 -1
- package/claude/skills/deprecation-migration/SKILL.md +12 -4
- package/claude/skills/design-taste/SKILL.md +17 -11
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -0
- package/claude/skills/docs-sync/SKILL.md +17 -6
- package/claude/skills/docs-sync/references/docs.md +54 -21
- package/claude/skills/docs-sync/references/readme.md +32 -8
- package/claude/skills/document-health/SKILL.md +3 -4
- package/claude/skills/draft-and-pick/SKILL.md +73 -47
- package/claude/skills/draft-doc/SKILL.md +9 -4
- package/claude/skills/draft-doc/references/context.md +4 -4
- package/claude/skills/draft-doc/references/docs.md +1 -0
- package/claude/skills/draft-doc/references/wiki.md +3 -2
- package/claude/skills/draft-figure/SKILL.md +9 -7
- package/claude/skills/draft-identity/SKILL.md +24 -52
- package/claude/skills/draft-identity/references/card-route.md +46 -0
- package/claude/skills/draft-ready/SKILL.md +19 -7
- package/claude/skills/draft-screencast/SKILL.md +6 -112
- package/claude/skills/draft-screencast/references/beats-template.md +119 -0
- package/claude/skills/draft-slides/SKILL.md +7 -4
- package/claude/skills/git-branch/SKILL.md +3 -3
- package/claude/skills/git-commit/SKILL.md +5 -3
- package/claude/skills/git-followup/SKILL.md +16 -9
- package/claude/skills/git-issue/SKILL.md +6 -5
- package/claude/skills/git-issue/references/issue.md +11 -10
- package/claude/skills/git-pr/SKILL.md +56 -44
- package/claude/skills/git-ship/SKILL.md +43 -34
- package/claude/skills/git-ship/references/ci-watch.md +31 -0
- package/claude/skills/git-split/SKILL.md +28 -100
- package/claude/skills/git-split/references/independent.md +40 -0
- package/claude/skills/git-split/references/stacked.md +73 -0
- package/claude/skills/git-stage/SKILL.md +9 -7
- package/claude/skills/git-worktree/SKILL.md +27 -49
- package/claude/skills/git-worktree/references/cleanup.md +55 -0
- package/claude/skills/markdown-craft/SKILL.md +2 -2
- package/claude/skills/markdown-craft/references/markdown.md +82 -52
- package/claude/skills/plan-feature/SKILL.md +52 -46
- package/claude/skills/plan-feature/references/batches.md +46 -0
- package/claude/skills/plan-groundwork/SKILL.md +60 -74
- package/claude/skills/plan-groundwork/references/groundwork.md +53 -24
- package/claude/skills/plan-groundwork/references/output.md +48 -0
- package/claude/skills/plan-intake/SKILL.md +28 -21
- package/claude/skills/plan-intake-answer/SKILL.md +14 -13
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +31 -11
- package/claude/skills/review-address/SKILL.md +76 -158
- package/claude/skills/review-address/references/rebase-only.md +34 -0
- package/claude/skills/review-craft/SKILL.md +27 -11
- package/claude/skills/review-pr/SKILL.md +91 -40
- package/claude/skills/review-pr/references/post.md +1 -1
- package/claude/skills/review-ui/SKILL.md +62 -37
- package/claude/skills/review-ui/references/hosted-preview.md +30 -0
- package/claude/skills/role-orchestrator/SKILL.md +105 -74
- package/claude/skills/role-orchestrator/references/orchestrator-filing.md +26 -0
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +1 -1
- package/claude/skills/role-planner/SKILL.md +66 -64
- package/claude/skills/role-reviewer/SKILL.md +57 -46
- package/claude/skills/role-worker/SKILL.md +68 -63
- package/claude/skills/search-craft/SKILL.md +7 -5
- package/claude/skills/session-compact/SKILL.md +16 -11
- package/claude/skills/session-map/SKILL.md +31 -10
- package/claude/skills/session-relay/SKILL.md +32 -65
- package/claude/skills/session-resume/SKILL.md +18 -13
- package/claude/skills/session-worktree/SKILL.md +70 -42
- package/claude/skills/systematic-debugging/SKILL.md +6 -1
- package/claude/skills/target-check/SKILL.md +13 -6
- package/claude/skills/target-setup/SKILL.md +41 -30
- package/claude/skills/target-setup/references/verify.md +6 -5
- package/claude/skills/task-board/SKILL.md +68 -60
- package/claude/skills/task-board/references/create-report.md +36 -0
- package/claude/skills/task-board/references/tasks.md +3 -1
- package/claude/skills/task-complete/SKILL.md +20 -18
- package/claude/skills/teach-workspace/SKILL.md +61 -33
- package/claude/skills/test-craft/SKILL.md +2 -1
- package/claude/skills/test-first/SKILL.md +15 -9
- package/claude/skills/ui-checklist/SKILL.md +18 -16
- package/claude/skills/ux-audit/SKILL.md +9 -10
- package/claude/skills/ux-measure/SKILL.md +22 -18
- package/claude/skills/video-craft/SKILL.md +15 -7
- package/claude/skills/write-human/SKILL.md +9 -1
- package/claude/skills/youtube-transcripts/SKILL.md +2 -1
- package/docs/agents/context-audit-checks.md +19 -1
- package/docs/agents/context-audit.md +2 -2
- package/docs/agents/driver.md +1 -1
- package/docs/agents/hooks.md +21 -1
- package/docs/agents/index.md +10 -14
- package/docs/agents/indexes.md +25 -29
- package/docs/agents/install-and-sync.md +124 -235
- package/docs/agents/markdown-audit-density.md +39 -0
- package/docs/agents/markdown-audit-weight.md +9 -7
- package/docs/agents/markdown-audit.md +18 -14
- package/docs/agents/migrate.md +41 -16
- package/docs/agents/output-shape.md +60 -45
- package/docs/agents/overview.md +36 -12
- package/docs/agents/routing.md +1 -1
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/skills-reach.md +1 -1
- package/docs/agents/targets.md +25 -77
- package/docs/target/migrations.md +1 -1
- package/docs/target/projects.md +3 -3
- package/docs/target/scenarios.md +1 -1
- package/docs/workflow/ai-workflow.md +2 -2
- package/docs/workflow/parallel-features.md +2 -2
- package/docs/workflow/skill-map.md +1 -1
- package/docs/workflow/visual-design-workflow.md +1 -1
- package/governance/detect.toml +6 -1
- package/package.json +6 -3
- package/scripts/core/install-check.sh +1 -1
- package/src/commands/claude.ts +1 -2
- package/src/commands/context.ts +106 -7
- package/src/commands/hooks.ts +63 -0
- package/src/commands/markdown.ts +169 -32
- package/src/commands/pr.ts +1 -1
- package/src/commands/records.ts +0 -1
- package/src/context/audit.ts +256 -5
- package/src/context/classify/prompts.ts +1 -1
- package/src/context/gate.ts +23 -7
- package/src/context/shape-gated.ts +28 -0
- package/src/design/document.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/docs/read.ts +15 -21
- package/src/gate/measures.ts +15 -190
- package/src/gate/stages.ts +21 -23
- package/src/hooks/reply-links.ts +110 -0
- package/src/markdown/density.ts +258 -0
- package/src/markdown/gate.ts +57 -18
- package/src/markdown/reference-shape.ts +103 -0
- package/src/markdown/scope.ts +174 -0
- package/src/markdown/structure.ts +10 -60
- package/src/sandbox/equivalence.ts +7 -9
- package/src/shipped/references.ts +1 -1
- package/src/teach/browser/head.ts +2 -2
- package/src/teach/browser/sidebar.ts +3 -3
- package/src/teach/browser/theme.ts +2 -2
- package/src/tooling/inject.ts +2 -2
- package/src/tooling/package.ts +15 -18
- package/src/tooling/verify-stack.ts +6 -3
- package/tooling/astro/configs/.oxfmtrc.json +8 -0
- package/tooling/astro/configs/.prettierrc +13 -0
- package/tooling/astro/manifest.toml +13 -0
- package/tooling/astro/reference.md +15 -5
- package/tooling/base/configs/.oxfmtrc.json +7 -0
- package/tooling/base/configs/scripts/verify.ts +1 -1
- package/tooling/base/manifest.toml +6 -6
- package/tooling/base/reference.md +12 -9
- package/tooling/base/seeds/.lintstagedrc +1 -3
- package/tooling/base/seeds/canon/context/ci.md +3 -3
- package/tooling/base/seeds/canon/context/development.md +2 -2
- package/tooling/claude/manifest.toml +5 -1
- package/tooling/claude/seeds/.claude/hooks/reply-links.sh +72 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +22 -1
- package/tooling/claude/seeds/.claude/settings.json +4 -0
- package/tooling/go/reference.md +2 -2
- package/tooling/nextjs/configs/.oxlintrc.json +223 -0
- package/tooling/nextjs/manifest.toml +2 -5
- package/tooling/nextjs/reference.md +4 -4
- package/tooling/php/manifest.toml +6 -1
- package/tooling/php/reference.md +2 -2
- package/tooling/python/manifest.toml +6 -1
- package/tooling/python/reference.md +4 -4
- package/tooling/vite-react/manifest.toml +1 -4
- package/tooling/vite-react/reference.md +3 -3
- package/tooling/web/configs/.oxlintrc.json +213 -0
- package/tooling/web/manifest.toml +9 -13
- package/tooling/web/reference.md +14 -14
- package/docs/agents/commands.md +0 -154
- package/docs/agents/docs.md +0 -27
- package/docs/agents/drift-surfaces.md +0 -201
- package/docs/agents/gov-detect.md +0 -47
- package/docs/agents/scripting.md +0 -142
- package/src/markdown/growth.ts +0 -43
- package/tooling/base/configs/.prettierrc +0 -12
- package/tooling/base/seeds/.prettierignore +0 -0
- package/tooling/nextjs/configs/eslint.config.js +0 -91
- package/tooling/web/configs/eslint.config.js +0 -82
|
@@ -37,33 +37,41 @@ Every phase runs under `CANON_NON_INTERACTIVE=1` with no TTY. Three phases
|
|
|
37
37
|
otherwise pause, and each takes an argument that answers its prompt ahead of
|
|
38
38
|
time:
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
`--extras <a>,<b>` takes a named set and `--extras none` takes none. With
|
|
46
|
-
neither, and with nobody to answer, both take every proposal and list each in
|
|
47
|
-
the report rather than stopping.
|
|
48
|
-
- `gov` stops on a detected technology with no matching rule. `--skip-gaps`
|
|
49
|
-
proceeds with the matched layer and lists the gap in the report.
|
|
40
|
+
| Phase | Pauses to | Answered ahead by | With neither and no TTY |
|
|
41
|
+
| ------------------- | ------------------------------------------ | ---------------------------------------------------------- | ----------------------------------------------------- |
|
|
42
|
+
| `indexes` | Confirm its folder list | `--all` for every candidate, `--folders <a>,<b>` for a set | Reports its candidates and stops rather than choosing |
|
|
43
|
+
| `install` and `gov` | Confirm the proposed extras | `--extras <a>,<b>` for a set, `--extras none` for none | Takes every proposal and lists each in the report |
|
|
44
|
+
| `gov` | Stop on a detected technology with no rule | `--skip-gaps`, which proceeds and lists the gap | Stops on the gap |
|
|
50
45
|
|
|
51
46
|
Claude Code's tool permission dialog is the confirmation gate for everything
|
|
52
47
|
else. Do not pause for a separate confirmation beyond the extras question.
|
|
53
48
|
|
|
54
49
|
## Scope
|
|
55
50
|
|
|
56
|
-
- This skill and `canon init` run once on a fresh scaffold, never on an existing project
|
|
51
|
+
- This skill and `canon init` run once on a fresh scaffold, never on an existing project, and do not guard against clobbering existing configs
|
|
52
|
+
- Add no guard, mode switch, or existing-project branch here. Extend the per-domain `canon <domain> install` or `canon sync` paths instead.
|
|
57
53
|
- The chain stops at the project edge. `git-commit` also ships, reaching the project's history, and does not run here.
|
|
58
|
-
- Claude Code plugins are a machine concern
|
|
54
|
+
- Claude Code plugins are a machine concern, so no phase installs them. `claude plugin install <name> --scope user` applies in every project on the machine and copies into none.
|
|
59
55
|
|
|
60
56
|
## Declined states
|
|
61
57
|
|
|
62
|
-
Three states reach this skill that the chain does not serve. Name the destination for each, so the refusal routes rather than ends.
|
|
58
|
+
Three states reach this skill that the chain does not serve. Name the destination for each, so the refusal routes rather than ends.
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
### An existing project
|
|
61
|
+
|
|
62
|
+
Stop and hand off to `target-check`, which reports what the target already carries before anything is repaired. This chain never reads that, so a per-domain install picked here is a guess against configs nobody read.
|
|
63
|
+
|
|
64
|
+
### The `.claude/` folder alone
|
|
65
|
+
|
|
66
|
+
Stop. Run `canon claude init` for the seed docs, then the `indexes` phase over the project's own documentation folders. Neither needs the tooling sync the `install` phase runs.
|
|
67
|
+
|
|
68
|
+
### A language with no stack
|
|
69
|
+
|
|
70
|
+
The chain still runs, on `base`, with the fallback marked in the preview. A project wanting none of `base` declines there and takes the `gov` phase, which is language-neutral and drops no `base` development dependencies.
|
|
71
|
+
|
|
72
|
+
Say so at the preview rather than resolving it here, since the fallback is a working default and only the person can say whether it fits.
|
|
73
|
+
|
|
74
|
+
### Route rather than build
|
|
67
75
|
|
|
68
76
|
Do not add a stack, a mode switch, or an existing-project branch to satisfy one of these. Each destination already exists and routing to it costs a line.
|
|
69
77
|
|
|
@@ -91,32 +99,38 @@ CANON_NON_INTERACTIVE=1 canon init \
|
|
|
91
99
|
|
|
92
100
|
Omit any flag whose resolved value is empty.
|
|
93
101
|
|
|
94
|
-
Step 2: `canon tooling sync <tooling-stack> --write` installs stack deps, scripts, gitignore entries, seeds, golden configs, and
|
|
102
|
+
Step 2: `canon tooling sync <tooling-stack> --write` installs stack deps, scripts, gitignore entries, seeds, golden configs, and the reference doc. It walks the extends chain, so `vite-react` also pulls `web` and `base`.
|
|
95
103
|
|
|
96
|
-
|
|
104
|
+
- Skip it if the tooling stack is `base`, which `canon init` already synced
|
|
105
|
+
- `--write` is required. Without it a headless run reports what it would replace and exits 1, since golden configs overwrite the target's files.
|
|
106
|
+
- A fresh target has nothing to lose, so pass `--write` directly rather than reading a report first
|
|
97
107
|
|
|
98
108
|
```bash
|
|
99
109
|
CANON_NON_INTERACTIVE=1 canon tooling sync <tooling-stack> <target> --write
|
|
100
110
|
```
|
|
101
111
|
|
|
102
|
-
Monorepo with multiple language roots
|
|
112
|
+
### Monorepo with multiple language roots
|
|
113
|
+
|
|
114
|
+
Run `canon init` once at the repo root so `base` (husky, oxfmt, commitlint, CI) lands once, then sync each subtree with `--skip base`. Take the subtree commands from the preview's per-root rows rather than picking folders by hand.
|
|
103
115
|
|
|
104
116
|
```bash
|
|
105
117
|
CANON_NON_INTERACTIVE=1 canon tooling sync vite-react ./frontend --skip base --write
|
|
106
118
|
CANON_NON_INTERACTIVE=1 canon tooling sync python ./backend --skip base --write
|
|
107
119
|
```
|
|
108
120
|
|
|
109
|
-
Without `--skip base`, each subtree re-drops husky, and git honors only one `core.hooksPath`, so the extra hook dirs silently break
|
|
121
|
+
- Without `--skip base`, each subtree re-drops husky, and git honors only one `core.hooksPath`, so the extra hook dirs silently break
|
|
122
|
+
- Each subtree keeps its own framework configs, and its stack reference reads through `canon tooling reference <stack>`
|
|
123
|
+
- A subtree sync withholds `.github/`, since GitHub reads workflows only at the root, and names each withheld file with the `working-directory` a root CI job needs
|
|
124
|
+
- A subtree needs its own `bun init` before its scripts and dependencies land, and the sync warns and skips them until then
|
|
110
125
|
|
|
111
|
-
|
|
126
|
+
### Post-sync fixups
|
|
112
127
|
|
|
113
128
|
Step 3: post-sync fixups. Golden configs arrive from sync, so no config generation is required. But a few items may need a one-time touch:
|
|
114
129
|
|
|
115
|
-
- **ESLint version pin.** If `bun create vite` installed `eslint@^10` and the manifest pins `eslint@^9`, sync does not override a present dep. Run `bun add -d eslint@^9` if `bun run lint:fix` fails with `Class extends value undefined`.
|
|
116
130
|
- **File naming.** `bun create vite`'s `App.tsx` violates the `KEBAB_CASE` rule. Rename to `app.tsx` and update the import in `main.tsx`.
|
|
117
131
|
- **Docs.** Run `canon tooling reference <tooling-stack>` and `canon tooling reference web` for any stack-specific follow-ups (Chrome extension overrides, setup script details).
|
|
118
132
|
|
|
119
|
-
Do not generate ESLint, Vitest, or Playwright configs. They ship as golden files. Generating from prose duplicates what sync already installed.
|
|
133
|
+
Do not generate oxlint, ESLint, Vitest, or Playwright configs. They ship as golden files. Generating from prose duplicates what sync already installed.
|
|
120
134
|
|
|
121
135
|
## Phase: gov
|
|
122
136
|
|
|
@@ -148,12 +162,9 @@ Read `${CLAUDE_SKILL_DIR}/references/indexes.md`. It holds the scan, the
|
|
|
148
162
|
frontmatter drafting, the scaffold, the validate step, and the convention seed
|
|
149
163
|
offer.
|
|
150
164
|
|
|
151
|
-
This phase
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
has no markdown-heavy folder yet, so this phase frequently finds nothing to
|
|
155
|
-
present, which its reference defines as its own outcome rather than a failure of
|
|
156
|
-
the chain.
|
|
165
|
+
This is the one phase that pauses to confirm candidate folders with the
|
|
166
|
+
operator, unless `--all` or `--folders` answered it ahead of time. A fresh scaffold usually has no markdown-heavy folder yet, so this phase often
|
|
167
|
+
finds nothing, which its reference defines as an outcome rather than a failure.
|
|
157
168
|
|
|
158
169
|
## Report
|
|
159
170
|
|
|
@@ -161,7 +172,7 @@ After the chain, report:
|
|
|
161
172
|
|
|
162
173
|
- Domains installed, with a check per domain
|
|
163
174
|
- Tooling stack synced, or skipped. Name the layers pulled via the extends chain.
|
|
164
|
-
- Any post-sync fixups applied (
|
|
175
|
+
- Any post-sync fixups applied (filename renames)
|
|
165
176
|
- `verify` outcome, naming the depth it ran at
|
|
166
177
|
|
|
167
178
|
### Outcomes and gaps
|
|
@@ -58,10 +58,11 @@ exit code is the whole verdict.
|
|
|
58
58
|
| Order | Script | Skip if |
|
|
59
59
|
| ----- | ----------- | --------------------------- |
|
|
60
60
|
| 1 | `lint:fix` | absent |
|
|
61
|
-
| 2 | `
|
|
62
|
-
| 3 | `
|
|
63
|
-
| 4 | `
|
|
64
|
-
| 5 | `
|
|
61
|
+
| 2 | `format` | absent |
|
|
62
|
+
| 3 | `typecheck` | absent |
|
|
63
|
+
| 4 | `check` | absent |
|
|
64
|
+
| 5 | `test:run` | absent, fall back to `test` |
|
|
65
|
+
| 6 | `build` | absent |
|
|
65
66
|
|
|
66
67
|
Do not run composite scripts like `check:full`. Do not run `dev`, `preview`,
|
|
67
68
|
`test:e2e`, `test:ui`, or `screenshot` at this depth. They belong to `deep`
|
|
@@ -80,7 +81,7 @@ server, and whether the screenshot harness produces output.
|
|
|
80
81
|
| 3 | `test:e2e` | absent | leaf script: exit code |
|
|
81
82
|
| 4 | `screenshot` | absent | leaf script: exit code |
|
|
82
83
|
|
|
83
|
-
`deep` runs the four above and not the
|
|
84
|
+
`deep` runs the four above and not the six leaf scripts, which the default
|
|
84
85
|
depth already covers. The two sets are disjoint, so running both depths runs
|
|
85
86
|
every declared script exactly once.
|
|
86
87
|
|
|
@@ -7,17 +7,28 @@ metadata:
|
|
|
7
7
|
|
|
8
8
|
# Task board
|
|
9
9
|
|
|
10
|
-
Owns the two operations that decide a task: bringing its file into existence, and declining one decided against. `task-complete` settles a task once its work exists,
|
|
10
|
+
Owns the two operations that decide a task: bringing its file into existence, and declining one decided against. `task-complete` settles a task once its work exists, so do not mark outcomes, archive, or move a plan by hand here.
|
|
11
11
|
|
|
12
12
|
Read `${CLAUDE_SKILL_DIR}/references/tasks.md` before writing any file. It holds the filename convention, the frontmatter contract, and the file format. Do not work them from memory.
|
|
13
13
|
|
|
14
14
|
## Guards
|
|
15
15
|
|
|
16
|
-
- Resolve the board at the main worktree root
|
|
17
|
-
-
|
|
16
|
+
- Resolve the board at the main worktree root with `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo
|
|
17
|
+
- The board is gitignored scratch shared across worktrees, so a linked worktree writing its own `pwd` creates a second board nothing reads
|
|
18
|
+
- A new task file is a main-root write, so it goes out as a heredoc, routed the way `session-worktree` states. Declining runs through `canon tasks decline`, which resolves the root itself.
|
|
18
19
|
- If `.canon/tasks/` does not exist at that root, stop: `❌ No .canon/tasks/ board. Run canon claude init to set it up.`
|
|
19
|
-
-
|
|
20
|
-
|
|
20
|
+
- Never hand-edit `.canon/tasks/index.md`, which a hook regenerates from sibling frontmatter after a write
|
|
21
|
+
|
|
22
|
+
### Routing the request
|
|
23
|
+
|
|
24
|
+
Route on the request rather than on a flag. Creating names work that does not exist yet, and declining names a task decided against.
|
|
25
|
+
|
|
26
|
+
- Archiving or marking outcomes belongs to `task-complete`, so name it and stop
|
|
27
|
+
- If the request fits neither, stop: `❌ Ambiguous. Say whether to create a task or decline one.`
|
|
28
|
+
|
|
29
|
+
### Regenerating the index by hand
|
|
30
|
+
|
|
31
|
+
Do not run the regen command directly, except after a shell write from a linked worktree. The hook matches `Write|Edit|MultiEdit` and nothing fires on `Bash`, so that one case runs `canon indexes regen --no-stage --root <main-root> <main-root>/.canon/tasks/index.md`.
|
|
21
32
|
|
|
22
33
|
## Create
|
|
23
34
|
|
|
@@ -25,99 +36,96 @@ Read `${CLAUDE_SKILL_DIR}/references/tasks.md` before writing any file. It holds
|
|
|
25
36
|
|
|
26
37
|
Every task traces to a plan, a groundwork folder, an intake folder, or a GitHub issue. Ask for it when the request does not carry one, and stop rather than guessing: `❌ No origin. Name the plan, groundwork folder, intake folder, or issue this task comes from.`
|
|
27
38
|
|
|
28
|
-
A task with no origin is
|
|
29
|
-
|
|
30
|
-
Accept work whose origin is the conversation itself only when the user says so explicitly, and record what it was in the intro paragraph instead of writing a link line to a file that does not exist.
|
|
39
|
+
A task with no origin is lost context or work nobody decided to do, and creation is the only moment the invariant is enforceable. Accept an origin in the conversation itself only when the user says so, recording it in the intro paragraph rather than a link line.
|
|
31
40
|
|
|
32
41
|
### Stop a worker before it claims a label
|
|
33
42
|
|
|
34
|
-
A session that asserted `canon:role-worker` this run, or whose own name in `canon sessions list --self --json` starts with `worker-`, stops here. It claims no label and writes no file.
|
|
43
|
+
A session that asserted `canon:role-worker` this run, or whose own name in `canon sessions list --self --json` starts with `worker-`, stops here. It claims no label and writes no file.
|
|
35
44
|
|
|
36
|
-
|
|
45
|
+
- Report the row's title, its origin, and the surface it would take to the controlling session instead, since placing the row is that session's call
|
|
46
|
+
- The guard sits ahead of Step 2 because `--claim` reserves a label on disk, so a later stop leaves a reservation nothing uses
|
|
47
|
+
- It names the worker role alone. A planner closing a groundwork track still writes its task file here and reaches Step 4's roster check.
|
|
37
48
|
|
|
38
49
|
### Step 2: allocate the phase label
|
|
39
50
|
|
|
40
|
-
Run `canon tasks next-label --claim --json` and take its `label` field. The verb reads the live board and its `archive/` sibling together,
|
|
51
|
+
Run `canon tasks next-label --claim --json` and take its `label` field. The verb reads the live board and its `archive/` sibling together, and `--claim` reserves the label under `.canon/ordinal-locks/` so a concurrent session gets the next one.
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
- Branch on the record's `reason` rather than the exit. `label-contended` means re-run the claim.
|
|
54
|
+
- A usage error from an unknown `--claim` means the binary predates the flag. Report the verb unavailable rather than falling back to a bare read, which reopens the race.
|
|
55
|
+
- Do not derive the label from a version file. `${CLAUDE_SKILL_DIR}/../git-commit/references/versioning.md` permits free renumbering, so only the verb's two folders know what a label means.
|
|
43
56
|
|
|
44
57
|
### Step 3: write the file
|
|
45
58
|
|
|
46
|
-
Write `.canon/tasks/vXX.Y-<slug>.md` under the claimed label, reading the file first if a session ever stubbed it, following the format in `${CLAUDE_SKILL_DIR}/references/tasks.md`.
|
|
59
|
+
Write `.canon/tasks/vXX.Y-<slug>.md` under the claimed label, reading the file first if a session ever stubbed it, following the format in `${CLAUDE_SKILL_DIR}/references/tasks.md`. Write it immediately, since Claude Code's tool permission dialog is the confirmation gate.
|
|
47
60
|
|
|
48
|
-
|
|
61
|
+
- Include a link line only when the file or folder it names exists, since a link to an unwritten plan is the broken pointer the archive rules prevent
|
|
62
|
+
- Write `Plan:`, `Groundwork:`, and `Intake:` as markdown links relative to `.canon/tasks/`, as in `Plan: [feature-<slug>](../plans/feature-<slug>.md)`
|
|
63
|
+
- Leave `Issue:` a bare `#NNN`. The older bare-path form still parses, but it leaves the board in two shapes for every later reader.
|
|
64
|
+
- Never write a `Pull request:` line here. `git-pr` adds it when a pull request opens, and a number guessed now points at someone else's work.
|
|
49
65
|
|
|
50
|
-
|
|
66
|
+
### Step 4: place it on a surface
|
|
51
67
|
|
|
52
|
-
|
|
68
|
+
A task file with no row is a dropped task, so name its surface in the same pass that creates it. The test and both file shapes are in `${CLAUDE_SKILL_DIR}/references/board.md`.
|
|
53
69
|
|
|
54
|
-
|
|
70
|
+
| Task | Surface |
|
|
71
|
+
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| Plausibly planned within the next few waves | A row under `## Needs a plan` in `.canon/tasks/priority.md`, positioned against the rows there, with the reason in `Waiting on` |
|
|
73
|
+
| Anything else | A line in `.canon/tasks/backlog.md`, which is unordered |
|
|
55
74
|
|
|
56
|
-
|
|
75
|
+
### Check for a live orchestrator
|
|
57
76
|
|
|
58
|
-
|
|
77
|
+
Check the roster before writing either file. Read `canon sessions list --self --json` for this session's own `sessionId` and `name`, then match a row in `canon sessions list --json` against three tests.
|
|
59
78
|
|
|
60
|
-
|
|
79
|
+
- Its `repository` matches this session's own, and its `sessionId` differs
|
|
80
|
+
- Its `name` starts with `orchestrator-`, the convention every hand-launched controller here uses, which excludes every `worker-` and `planner-` session
|
|
81
|
+
- Treat a refusal from either call the same as a roster read that failed
|
|
61
82
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
| Roster read | Act |
|
|
84
|
+
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
85
|
+
| **Found** | Write neither file. Report the surface and reason, and message that session so it places the row itself |
|
|
86
|
+
| **Not found**, and this session's name starts with `worker-` or `planner-` | Write neither file, since both role bodies ban a board write. Report the row and its surface. |
|
|
87
|
+
| **Not found otherwise**, or the read fails | Write the row directly, through the same heredoc route as the file. A failed read looks like a solo project. |
|
|
65
88
|
|
|
66
|
-
Say which branch fired and why in the report.
|
|
89
|
+
Say which branch fired and why in the report. A placement with no stated reason is one the next sweep re-derives from nothing.
|
|
67
90
|
|
|
68
91
|
### Step 5: report unlinked origins
|
|
69
92
|
|
|
70
93
|
Scan for work that has been decided and would otherwise be forgotten. Three origins carry it, and every run reads all three.
|
|
71
94
|
|
|
72
|
-
List `.canon/groundwork/` and run `gh issue list --state open` when a remote is configured, then grep the board for each track name and issue number
|
|
95
|
+
- List `.canon/groundwork/` and run `gh issue list --state open` when a remote is configured, then grep the board for each track name and issue number
|
|
96
|
+
- Read the dumps through `canon intake list --json`, which reports items, open, unread, and malformed per folder, and parses the contract `${CLAUDE_SKILL_DIR}/../plan-intake/references/intake.md` fixes
|
|
97
|
+
- Grep `.canon/tasks/`, `.canon/tasks/archive/`, and `.canon/tasks/declined/` for each folder slug, since a dump with no live task is usually promoted and settled
|
|
73
98
|
|
|
74
|
-
|
|
99
|
+
A dump is the stronger case for this scan. A track holds one question and stays visible, while a dump holds dozens of verdicts left with nothing carrying them forward.
|
|
75
100
|
|
|
76
|
-
|
|
101
|
+
### The four dump states
|
|
77
102
|
|
|
78
|
-
Those
|
|
103
|
+
Those reads give four states, and the first three earn a line each.
|
|
79
104
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
105
|
+
| State | Report |
|
|
106
|
+
| ----------------------------------------------------------------------- | -------------------------------------------------------------------- |
|
|
107
|
+
| Every item answered, `malformed` at zero, nothing on any board cites it | Decided work nobody promoted, which is what this step exists to find |
|
|
108
|
+
| Unread items | Waiting on the operator rather than forgotten, in its own wording |
|
|
109
|
+
| `malformed` above zero | A file to repair, since no verb reaches an item with no answer slot |
|
|
110
|
+
| The archive cites it | Promoted and shipped, so nothing |
|
|
84
111
|
|
|
85
|
-
|
|
112
|
+
The first state tests two counts because a malformed item is neither unread nor answered. Reading `unread` alone reports a broken file as decided work nobody promoted.
|
|
86
113
|
|
|
87
|
-
|
|
114
|
+
### How to report it
|
|
88
115
|
|
|
89
|
-
|
|
116
|
+
Say which read fired, since "No task points at this" is true of every state and useful about none of them.
|
|
90
117
|
|
|
91
|
-
|
|
118
|
+
- Report rather than prompt. A track can open long after its task would have been written, so an offer per origin is noise on most runs.
|
|
119
|
+
- Say the origins were read even when nothing comes back, since a silent clean pass looks like one that never ran
|
|
92
120
|
|
|
93
121
|
## Decline
|
|
94
122
|
|
|
95
|
-
Read `${CLAUDE_SKILL_DIR}/references/decline.md` when the request names a task decided against. It carries gathering the reason, the `canon tasks decline` call, the route for each refusal, and the prose to clear afterwards.
|
|
123
|
+
Read `${CLAUDE_SKILL_DIR}/references/decline.md` when the request names a task decided against. It carries gathering the reason, the `canon tasks decline` call, the route for each refusal, and the prose to clear afterwards.
|
|
96
124
|
|
|
97
|
-
|
|
125
|
+
Never move the file, edit `priority.md` or `backlog.md`, or regenerate the index by hand, since the command owns all three.
|
|
98
126
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Create:
|
|
102
|
-
|
|
103
|
-
```plaintext
|
|
104
|
-
✅ Created: .canon/tasks/vXX.Y-<slug>.md
|
|
105
|
-
|
|
106
|
-
<label>, next after <highest>.
|
|
107
|
-
<board or backlog, and why it landed there>.
|
|
108
|
-
|
|
109
|
-
**Origin with no task:**
|
|
110
|
-
|
|
111
|
-
- `.canon/groundwork/<slug>/`: open, touched <date>
|
|
112
|
-
- `.canon/intake/<slug>/`: every item answered, nothing promoted
|
|
113
|
-
- #NNN: <issue title>
|
|
114
|
-
|
|
115
|
-
**Waiting on you:**
|
|
116
|
-
|
|
117
|
-
- `.canon/intake/<slug>/`: <n> of <n> items unread
|
|
118
|
-
- `.canon/intake/<slug>/`: <n> items carry no answer slot, so no verb reaches them
|
|
119
|
-
```
|
|
127
|
+
## Output
|
|
120
128
|
|
|
121
|
-
|
|
129
|
+
Emit the full relative path from the project root for every file written or moved, since a bare filename names a file the reader cannot open. A create run reads `${CLAUDE_SKILL_DIR}/references/create-report.md` for the report block and when each part drops. A decline run skips it.
|
|
122
130
|
|
|
123
131
|
A refusal reports the reason and the resolution the mode's reference routes it to under its Step 3, on one line each.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Create report
|
|
3
|
+
description: The report a task-board create run closes on, being the created path, the label and surface lines, and the two blocks Step 5's origin scan fills
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Create report
|
|
7
|
+
|
|
8
|
+
Read from `## Output` of `task-board` when the run created a task. A decline run skips this file and reports through its own reference.
|
|
9
|
+
|
|
10
|
+
## Report block
|
|
11
|
+
|
|
12
|
+
```plaintext
|
|
13
|
+
✅ Created: .canon/tasks/vXX.Y-<slug>.md
|
|
14
|
+
|
|
15
|
+
<label>, next after <highest>.
|
|
16
|
+
<board or backlog, and why it landed there>.
|
|
17
|
+
|
|
18
|
+
**Origin with no task:**
|
|
19
|
+
|
|
20
|
+
- `.canon/groundwork/<slug>/`: open, touched <date>
|
|
21
|
+
- `.canon/intake/<slug>/`: every item answered, nothing promoted
|
|
22
|
+
- #NNN: <issue title>
|
|
23
|
+
|
|
24
|
+
**Waiting on you:**
|
|
25
|
+
|
|
26
|
+
- `.canon/intake/<slug>/`: <n> of <n> items unread
|
|
27
|
+
- `.canon/intake/<slug>/`: <n> items carry no answer slot, so no verb reaches them
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## When a block drops
|
|
31
|
+
|
|
32
|
+
Drop either block when it carries no rows. When both are empty, which is the ordinary result, replace them with one line naming what was read:
|
|
33
|
+
|
|
34
|
+
```plaintext
|
|
35
|
+
Read <n> tracks, <n> dumps, and <n> open issues. Nothing unlinked.
|
|
36
|
+
```
|
|
@@ -82,6 +82,8 @@ Two headings, `## Outcomes` and `## Findings`. Outcomes are future and checkable
|
|
|
82
82
|
|
|
83
83
|
Add no third heading. Status stays inline on an outcome rather than becoming an "In progress" section.
|
|
84
84
|
|
|
85
|
+
Open each finding with a bold label naming its source and date, as in `- **planner, 2026-10-11:** <finding>`, and keep it to a few sentences. Anything longer moves into the plan or the groundwork folder. Outcomes stay a checklist, since the board tools read them by their `- [ ]` line.
|
|
86
|
+
|
|
85
87
|
Size the outcomes so one pull request closes all of them, and split the task before handing it off rather than after. A task closes whole or not at all, so outcomes spanning two pull requests leave the board showing in-progress work no branch carries.
|
|
86
88
|
|
|
87
89
|
A sliced task is the one allowed exception: a task the operator decided to ship across several pull requests on purpose, one slice each. Its `Pull request:` line lists every slice, so the board records which merged work covered which outcomes, and it closes whole when the last slice's merge finds every outcome ticked and no slice left pending.
|
|
@@ -115,7 +117,7 @@ Why this task exists and what it depends on.
|
|
|
115
117
|
|
|
116
118
|
## Findings
|
|
117
119
|
|
|
118
|
-
- What constrains the task
|
|
120
|
+
- **<source>, <YYYY-MM-DD>:** What constrains the task.
|
|
119
121
|
|
|
120
122
|
> Test strategy: <unit | component | e2e | visual | manual>, what is being verified
|
|
121
123
|
```
|
|
@@ -11,9 +11,12 @@ Owns the two operations that settle a task once its work exists: marking the out
|
|
|
11
11
|
|
|
12
12
|
## Guards
|
|
13
13
|
|
|
14
|
-
- Resolve the board at the main worktree root
|
|
15
|
-
-
|
|
16
|
-
-
|
|
14
|
+
- Resolve the board at the main worktree root with `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo
|
|
15
|
+
- The board is gitignored scratch shared across worktrees, so a linked worktree reading its own `pwd` finds no board
|
|
16
|
+
- With no `.canon/tasks/` at that root, Mark reports `⏭️ No .canon/tasks/ board, so no outcomes to mark.` and returns, still running Step 4's sweep
|
|
17
|
+
- `git-ship` invokes Mark on every ship, and a project with no board is not a failed one
|
|
18
|
+
- With no board, Archive stops instead: `❌ No .canon/tasks/ board. Run canon claude init to set it up.`
|
|
19
|
+
- Route on the request rather than on a flag. A shipped task to archive, or a task file the `post-merge` hook left, takes Archive, and every other request takes Mark.
|
|
17
20
|
- Never hand-edit `.canon/tasks/index.md`. A hook regenerates it.
|
|
18
21
|
|
|
19
22
|
## Mark
|
|
@@ -26,21 +29,17 @@ Resolve the base ref once:
|
|
|
26
29
|
git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main 2>/dev/null
|
|
27
30
|
```
|
|
28
31
|
|
|
29
|
-
Take the union of `git diff --name-only <base> HEAD`, `git diff --name-only HEAD`, and `git ls-files --others --exclude-standard
|
|
32
|
+
- Take the union of `git diff --name-only <base> HEAD`, `git diff --name-only HEAD`, and `git ls-files --others --exclude-standard`
|
|
33
|
+
- Read content with `git diff <base> HEAD` and `git diff HEAD`
|
|
34
|
+
- Prefer `origin/main` over local `main`. On `main` itself the local ref resolves to HEAD, so every committed change drops out of the set.
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
The baseline is unusable when no merge base resolves against either ref, or when the base came from local `main` and equals HEAD. On an unusable baseline, read `${CLAUDE_SKILL_DIR}/references/unusable-baseline.md` before Step 2 for what to read instead.
|
|
36
|
+
The baseline is unusable when no merge base resolves against either ref, or when the base came from local `main` and equals HEAD. Then read `${CLAUDE_SKILL_DIR}/references/unusable-baseline.md` before Step 2 for what to read instead.
|
|
34
37
|
|
|
35
38
|
### Step 2: match the diff against the board
|
|
36
39
|
|
|
37
|
-
Read `.canon/tasks/index.md` at the main worktree root, pick the task files whose title or description relates to the changed paths, and read them.
|
|
38
|
-
|
|
39
|
-
Path matching only chooses which files to open. Behavior decides each outcome. For each unchecked outcome, decide whether the diff shipped the behavior that outcome names.
|
|
40
|
-
|
|
41
|
-
Completion is a fact about the repository rather than a fact about the conversation, so the diff decides it and the session does not.
|
|
40
|
+
Read `.canon/tasks/index.md` at the main worktree root, pick the task files whose title or description relates to the changed paths, and read them. Path matching only chooses which files to open.
|
|
42
41
|
|
|
43
|
-
Keep the match conservative:
|
|
42
|
+
For each unchecked outcome, decide whether the diff shipped the behavior it names, since completion is a fact about the repository and not the conversation. Keep the match conservative:
|
|
44
43
|
|
|
45
44
|
- Mark only outcomes already written on the board. Never infer a new task from the diff.
|
|
46
45
|
- Match on the behavior an outcome describes, not on filenames or commit subjects. The path match above only narrowed which task files to open.
|
|
@@ -49,11 +48,12 @@ Keep the match conservative:
|
|
|
49
48
|
|
|
50
49
|
### Step 3: close the matched outcomes
|
|
51
50
|
|
|
52
|
-
Mark each completed outcome `[x]` in the task's own file through `canon tasks outcome <stem> --close <n> --json`, repeating `--close` for each. Positions count every outcome checkbox in file order from 1
|
|
51
|
+
Mark each completed outcome `[x]` in the task's own file through `canon tasks outcome <stem> --close <n> --json`, repeating `--close` for each. Positions count every outcome checkbox in file order from 1.
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Read `ok` and `reason`
|
|
53
|
+
- Do not move or archive the file, even when every outcome reads `[x]`. The pull request has not merged, and the `post-merge` hook archives the task once it does.
|
|
54
|
+
- The verb resolves the board at the main worktree root in-process, the route `session-worktree` states for an edit inside a main-root file
|
|
55
|
+
- Read `ok` and `reason` from the record rather than the exit, since a shell function wrapping `canon` can flatten a refusal to zero
|
|
56
|
+
- A refusal read as success leaves the outcome unmarked, so the board reports shipped work as open and the next session re-plans it
|
|
57
57
|
|
|
58
58
|
### Step 4: sweep consumed receipts
|
|
59
59
|
|
|
@@ -61,7 +61,9 @@ Read `${CLAUDE_SKILL_DIR}/references/receipt-sweep.md` for which review receipts
|
|
|
61
61
|
|
|
62
62
|
## Archive
|
|
63
63
|
|
|
64
|
-
Read `${CLAUDE_SKILL_DIR}/references/archive.md` when the request names a shipped task to archive. It carries the check that the work reached `main`, the `canon tasks archive` call,
|
|
64
|
+
Read `${CLAUDE_SKILL_DIR}/references/archive.md` when the request names a shipped task to archive. It carries the check that the work reached `main`, the `canon tasks archive` call, each refusal's route, and the prose to clear.
|
|
65
|
+
|
|
66
|
+
Never move the file, edit `priority.md`, or regenerate the index by hand, since the command owns all three.
|
|
65
67
|
|
|
66
68
|
## Output
|
|
67
69
|
|