@erclx/canon 4.6.1 → 4.8.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 (145) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/canon-feedback-file/SKILL.md +3 -3
  3. package/claude/skills/canon-feedback-triage/SKILL.md +1 -1
  4. package/claude/skills/canon-rollout/SKILL.md +1 -1
  5. package/claude/skills/canon-screencast/SKILL.md +5 -5
  6. package/claude/skills/canon-slides-draft/SKILL.md +1 -1
  7. package/claude/skills/claude-address-review/SKILL.md +4 -4
  8. package/claude/skills/claude-autoship/SKILL.md +17 -17
  9. package/claude/skills/claude-design-extract/SKILL.md +2 -2
  10. package/claude/skills/claude-diagram/SKILL.md +13 -13
  11. package/claude/skills/claude-docs/SKILL.md +23 -23
  12. package/claude/skills/claude-feature/SKILL.md +6 -6
  13. package/claude/skills/claude-groundwork/SKILL.md +16 -16
  14. package/claude/skills/claude-intake/SKILL.md +8 -8
  15. package/claude/skills/claude-intake-answer/SKILL.md +1 -1
  16. package/claude/skills/claude-markdown-propose/REQUIREMENT.md +2 -2
  17. package/claude/skills/claude-markdown-propose/SKILL.md +8 -8
  18. package/claude/skills/claude-markdown-propose/references/format.md +3 -3
  19. package/claude/skills/claude-memory-capture/SKILL.md +13 -13
  20. package/claude/skills/claude-memory-review/SKILL.md +28 -28
  21. package/claude/skills/claude-memory-review/references/receipt-format.md +1 -1
  22. package/claude/skills/claude-orchestrate/SKILL.md +9 -9
  23. package/claude/skills/claude-orchestrate/references/orchestrator-dispatch.md +1 -1
  24. package/claude/skills/claude-orchestrate/references/orchestrator-parked.md +1 -1
  25. package/claude/skills/claude-orchestrate/references/orchestrator-poll.md +1 -1
  26. package/claude/skills/claude-orchestrate/references/orchestrator-resume.md +1 -1
  27. package/claude/skills/claude-orchestrate/scripts/poll.sh +1 -1
  28. package/claude/skills/claude-planner/REQUIREMENT.md +1 -1
  29. package/claude/skills/claude-planner/SKILL.md +6 -6
  30. package/claude/skills/claude-pr-review/SKILL.md +5 -5
  31. package/claude/skills/claude-review/SKILL.md +4 -4
  32. package/claude/skills/claude-seed-sync/SKILL.md +2 -2
  33. package/claude/skills/claude-tasks/SKILL.md +16 -16
  34. package/claude/skills/claude-teach/SKILL.md +9 -9
  35. package/claude/skills/claude-ui-test/SKILL.md +3 -3
  36. package/claude/skills/claude-ux-audit/SKILL.md +5 -5
  37. package/claude/skills/claude-ux-measure/SKILL.md +3 -3
  38. package/claude/skills/claude-worker/SKILL.md +2 -2
  39. package/claude/skills/claude-worktree/SKILL.md +3 -3
  40. package/claude/skills/git-issue/SKILL.md +4 -4
  41. package/claude/skills/git-pr/SKILL.md +6 -6
  42. package/claude/skills/git-ship/SKILL.md +3 -3
  43. package/claude/skills/git-split/REQUIREMENT.md +1 -1
  44. package/claude/skills/git-split/SKILL.md +20 -20
  45. package/claude/skills/migration-superseded/SKILL.md +4 -4
  46. package/claude/skills/session-map/SKILL.md +2 -2
  47. package/claude/skills/session-resume/SKILL.md +8 -8
  48. package/docs/agents/capture.md +17 -11
  49. package/docs/agents/commands.md +8 -5
  50. package/docs/agents/demo.md +2 -2
  51. package/docs/agents/driver.md +2 -2
  52. package/docs/agents/index.md +1 -1
  53. package/docs/agents/indexes.md +1 -1
  54. package/docs/agents/install-and-sync.md +1 -1
  55. package/docs/agents/intake.md +1 -1
  56. package/docs/agents/key-changes.md +1 -1
  57. package/docs/agents/records.md +12 -9
  58. package/docs/agents/restated.md +2 -2
  59. package/docs/agents/rule-citations.md +1 -1
  60. package/docs/agents/sandbox.md +1 -1
  61. package/docs/agents/state-scoped-risk.md +1 -1
  62. package/docs/agents/tasks.md +6 -6
  63. package/docs/agents/teach.md +4 -4
  64. package/docs/ai-workflow.md +26 -19
  65. package/docs/operating-model.md +3 -3
  66. package/docs/target-projects.md +22 -2
  67. package/docs/visual-design-workflow.md +1 -1
  68. package/governance/rules/claude/555-tasks.md +3 -3
  69. package/governance/rules/claude/556-groundwork.md +2 -2
  70. package/governance/rules/claude/557-intake.md +2 -2
  71. package/governance/rules/claude/558-plan.md +3 -3
  72. package/governance/rules/claude/559-memory.md +2 -2
  73. package/governance/rules/claude/560-diagrams.md +3 -3
  74. package/governance/rules/claude/561-teach.md +2 -2
  75. package/governance/rules/claude/562-session.md +2 -2
  76. package/governance/rules/core/035-tasks.md +2 -2
  77. package/governance/rules/core/045-memory.md +3 -3
  78. package/governance/rules/core/055-scratch.md +2 -1
  79. package/governance/rules/core/085-worktrees.md +1 -1
  80. package/package.json +1 -2
  81. package/scripts/core/check-ignore-parity.sh +24 -51
  82. package/scripts/core/install-check.sh +4 -4
  83. package/scripts/core/regen-hero.sh +6 -3
  84. package/scripts/core/snapshot.sh +1 -1
  85. package/scripts/manage-sandbox.sh +1 -1
  86. package/scripts/tooling/verify.sh +2 -2
  87. package/snippets/claude/decision-memo.md +1 -1
  88. package/snippets/claude/feature-recap.md +1 -1
  89. package/src/audits/catalog.ts +1 -1
  90. package/src/capture/render.ts +166 -0
  91. package/src/capture/sources.ts +42 -0
  92. package/src/capture/stamp.ts +52 -0
  93. package/src/claude/cases/all.ts +1 -1
  94. package/src/claude/seeds.ts +13 -2
  95. package/src/claude/skills-rank.ts +1 -1
  96. package/src/cli.ts +5 -5
  97. package/src/commands/capture.ts +52 -41
  98. package/src/commands/demo.ts +1 -1
  99. package/src/commands/design.ts +1 -1
  100. package/src/commands/feedback.ts +5 -5
  101. package/src/commands/gov.ts +17 -6
  102. package/src/commands/intake.ts +1 -1
  103. package/src/commands/migrate.ts +173 -2
  104. package/src/commands/pr.ts +1 -1
  105. package/src/commands/records.ts +1 -1
  106. package/src/commands/serve.ts +2 -2
  107. package/src/commands/slides.ts +1 -1
  108. package/src/commands/tasks.ts +5 -5
  109. package/src/commands/teach.ts +1 -1
  110. package/src/context/audit.ts +1 -1
  111. package/src/demo/compile.ts +1 -1
  112. package/src/demo/drive.ts +5 -8
  113. package/src/driver/drive.ts +7 -8
  114. package/src/gate/measures.ts +1 -1
  115. package/src/gate/stages.ts +1 -1
  116. package/src/gov/citations.ts +1 -1
  117. package/src/gov/restated.ts +3 -3
  118. package/src/inventory/walk.ts +3 -3
  119. package/src/migrate/apply.ts +67 -1
  120. package/src/migrate/records.ts +276 -0
  121. package/src/paths.ts +1 -1
  122. package/src/pr/paths.ts +1 -1
  123. package/src/record-root.ts +77 -27
  124. package/src/records/backup.ts +71 -17
  125. package/src/records/validate.ts +1 -1
  126. package/src/sync/layout.ts +11 -2
  127. package/src/tasks/answers.ts +1 -1
  128. package/src/tasks/archive.ts +20 -3
  129. package/standards/diagrams.md +4 -4
  130. package/standards/glossary.md +1 -1
  131. package/standards/groundwork.md +3 -3
  132. package/standards/index.md +2 -2
  133. package/standards/intake.md +3 -3
  134. package/standards/memory.md +2 -2
  135. package/standards/plan.md +3 -3
  136. package/standards/session.md +2 -2
  137. package/standards/standard.md +1 -1
  138. package/standards/tasks.md +9 -9
  139. package/standards/teach.md +2 -2
  140. package/standards/versioning.md +1 -1
  141. package/tooling/base/configs/.husky/post-merge +1 -1
  142. package/tooling/base/reference.md +1 -1
  143. package/tooling/claude/manifest.toml +13 -3
  144. package/tooling/claude/reference.md +28 -15
  145. package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +8 -8
@@ -25,10 +25,10 @@ session's review are different passes, and how a feature is sized.
25
25
 
26
26
  Read the board in parallel, resolving the paths at the main worktree root per Worktrees in `CLAUDE.md`:
27
27
 
28
- - `.claude/tasks/priority.md`: execution order and what each task is waiting on
29
- - `.claude/tasks/backlog.md`: what is not being scheduled, when the file exists
30
- - `.claude/tasks/index.md`: what is queued
31
- - `.claude/plans/*.md`: features already planned and ready to hand off
28
+ - `.canon/tasks/priority.md`: execution order and what each task is waiting on
29
+ - `.canon/tasks/backlog.md`: what is not being scheduled, when the file exists
30
+ - `.canon/tasks/index.md`: what is queued
31
+ - `.canon/plans/*.md`: features already planned and ready to hand off
32
32
  - open PRs via `gh pr list --json number,title,headRefName,isDraft`
33
33
 
34
34
  Then output the state of play so the human knows what to launch, review, and merge.
@@ -59,7 +59,7 @@ Orchestrator ready.
59
59
  Ready to build (hand each to its own worker):
60
60
 
61
61
  <feature>
62
- plan: .claude/plans/feature-<slug>.md
62
+ plan: .canon/plans/feature-<slug>.md
63
63
  → /claude-autoship
64
64
 
65
65
  <feature>
@@ -85,7 +85,7 @@ Omit any section with nothing in it. Recommend a handoff only for a plan whose f
85
85
 
86
86
  `In flight` covers the state between the other two, which lasts ten to thirty minutes and is most of what an operator sees once this session dispatches its own workers. Before it existed, a session holding running workers reported them under no section and invented a shape per report, which the block below forbids two paragraphs down while giving it no term to use. Read the progress figures off each worker's worktree rather than from the worker, since a busy status says a session is alive and nothing about whether it is moving, and name the model because a dispatcher now picks one per row.
87
87
 
88
- Leave a plan out of `Ready to build` once a row in flight names it. The plan file stays in `.claude/plans/` for the whole build, so listing it there recommends handing off work already underway, and the disjointness rule below withdraws the recommendation only for a reader who already knows what is running.
88
+ Leave a plan out of `Ready to build` once a row in flight names it. The plan file stays in `.canon/plans/` for the whole build, so listing it there recommends handing off work already underway, and the disjointness rule below withdraws the recommendation only for a reader who already knows what is running.
89
89
 
90
90
  The block opens on the board rather than on a version, because no committed file states one. Adding a version line here would restate what a reader can already see on the rows, dated by nothing, which is how the retired sequencing surface produced an unsourced claim on every run.
91
91
 
@@ -164,7 +164,7 @@ It counts unclaimed plans against workers rather than reading the reserve in ste
164
164
  3. Archive what closed.
165
165
  - A task whose outcomes are all `[x]` runs `claude-docs` for the plan sweep, then `claude-tasks` to archive
166
166
  - A task whose outcomes describe standing policy rather than a deliverable never closes on its own, so hand it to a worker to encode the policy where it is enforced, then cut the outcomes with the reason recorded and archive once that branch merges. Encoding it from this session would write a tracked file, which Boundaries forbids.
167
- 4. Read `.claude/tasks/priority.md` and count entries under its `## Run now` heading that carry a written plan. Keep one in reserve beyond what is running.
167
+ 4. Read `.canon/tasks/priority.md` and count entries under its `## Run now` heading that carry a written plan. Keep one in reserve beyond what is running.
168
168
  5. Promote from the top of `## Needs a plan`, which is where the last sweep recorded what to plan next. Depart from that order when something has changed under it and say what changed, since a position nobody honors is the ordering going stale on the surface built to hold it. What sets the order in the first place is whether a task establishes functionality rather than how old it is, so prefer a task that adds or proves a mechanism over one that trims, tidies, or audits an existing surface.
169
169
  - Re-take the board-or-backlog call while the file is open. A row that has stopped being near-term moves to `backlog.md`, and a backlogged task the last wave made near-term moves onto the board. Both are one line removed from one surface and written to the other, and the standard states the test.
170
170
  6. Before promoting a candidate, list the files it touches against every task already running, per Parallelism below. Name the overlap and serialize when the sets are not disjoint.
@@ -191,7 +191,7 @@ Do not promote a task to fill the queue when nothing qualifies. A thin queue is
191
191
 
192
192
  ### Writing the board
193
193
 
194
- Promoting, demoting, and archiving a row all write `.claude/tasks/priority.md`, and this session is the only writer apart from `canon tasks archive`. Moving a task between the board and `.claude/tasks/backlog.md` writes both files, and this session is that file's only writer.
194
+ Promoting, demoting, and archiving a row all write `.canon/tasks/priority.md`, and this session is the only writer apart from `canon tasks archive`. Moving a task between the board and `.canon/tasks/backlog.md` writes both files, and this session is that file's only writer.
195
195
 
196
196
  - Edit the file with the file-editing tool. A shell stream editor and an inline string replace both exit clean on a non-match, so a promotion that matched nothing leaves the board wrong with nothing reporting it, and the file-editing tool errors instead.
197
197
  - Write both halves of a move before reporting it. A row removed from one surface and not written to the other leaves a task file nothing names, and the folder is gitignored with no history to recover the row from. `canon tasks validate` reports that state, so run it after any move.
@@ -201,7 +201,7 @@ Promoting, demoting, and archiving a row all write `.claude/tasks/priority.md`,
201
201
  - Re-resolve every Plan pointer after anything archives a plan
202
202
  - Read the file back after writing it, since the row that lands is the row a worker acts on
203
203
 
204
- A Plan pointer goes stale from a branch this board never sees. `claude-docs` moves a plan to `.claude/plans/archive/` and rewrites the citation in the task file alone, so a row for a task still on the board keeps pointing into `.claude/plans/` at a file that has moved. Workers running the ship chain on their own branches archive plans this board still cites, and the board reads as correct until a pointer is followed.
204
+ A Plan pointer goes stale from a branch this board never sees. `claude-docs` moves a plan to `.canon/plans/archive/` and rewrites the citation in the task file alone, so a row for a task still on the board keeps pointing into `.canon/plans/` at a file that has moved. Workers running the ship chain on their own branches archive plans this board still cites, and the board reads as correct until a pointer is followed.
205
205
 
206
206
  ## Parallelism
207
207
 
@@ -17,7 +17,7 @@ Run `canon tasks plan-answers <plan> --json` and read `launchable` off the recor
17
17
 
18
18
  - `launchable: true`: the plan answers itself, so proceed to the branch check.
19
19
  - `launchable: false`: the row is not dispatchable. Report every entry in `open`, each carrying the question label and the reason its suggestion gave for needing a person, and hand the row to the human-launch line below. Never fill the slot on the operator's behalf, which is the one move the plan standard forbids outright.
20
- - `reason: archived`: the row's plan sits in `.claude/plans/archive/` and describes work that already shipped. Repoint the row at a live plan rather than dispatching, since `claude-autoship` Step 1 refuses the same file and the worker would meet that refusal after the launch spent.
20
+ - `reason: archived`: the row's plan sits in `.canon/plans/archive/` and describes work that already shipped. Repoint the row at a live plan rather than dispatching, since `claude-autoship` Step 1 refuses the same file and the worker would meet that refusal after the launch spent.
21
21
  - The command refuses for any other reason, or the record carries no `launchable` key: treat the row as unverified rather than clear, name what could not be read, and fall back to the human. A gate that reads nothing and proceeds is the gate not running.
22
22
 
23
23
  Branch on `launchable` rather than on the exit code, which a shell function wrapping `canon` can flatten to zero and so read a held row as a clear one.
@@ -15,7 +15,7 @@ The sweep's own question stays distinct from this one. It asks which parked row
15
15
 
16
16
  ## Scope
17
17
 
18
- Every row under `## Up next` and `## Needs a plan` in `.claude/tasks/priority.md`. A `## Run now` row carries no blocker by definition, so the pass skips it. Resolve the board and each task file at the main worktree root, per Worktrees in `CLAUDE.md`.
18
+ Every row under `## Up next` and `## Needs a plan` in `.canon/tasks/priority.md`. A `## Run now` row carries no blocker by definition, so the pass skips it. Resolve the board and each task file at the main worktree root, per Worktrees in `CLAUDE.md`.
19
19
 
20
20
  Take the rows in board order and finish one before opening the next. Clearing a row changes what the next row collides with, so a pass that measures every row first and writes afterwards writes against a board it has already invalidated.
21
21
 
@@ -54,7 +54,7 @@ Every classification line names a pull request and a state. A line starting `pol
54
54
 
55
55
  The script exits non-zero and classifies nothing when the open pull request list itself fails to load. That case would otherwise report every tracked pull request as merged, so the baseline is left untouched and the run says so.
56
56
 
57
- The baseline lives at `.claude/.tmp/pr-poll/baseline.txt` under the main worktree root and is per-machine. A first run against a board already in flight reports each open pull request once before it settles.
57
+ The baseline lives at `.canon/tmp/pr-poll/baseline.txt` under the main worktree root and is per-machine. A first run against a board already in flight reports each open pull request once before it settles.
58
58
 
59
59
  The five review headings the script matches are written by `claude-pr-review` and `claude-address-review`, and the whole set is stated once in the first. A project that posts its reviews under different headings edits the jq filters in the script to match, or every pull request reads as never reviewed.
60
60
 
@@ -6,7 +6,7 @@ description: What to read back after a compaction, and how to treat a groundwork
6
6
  Resume as orchestrator after a compaction. Read the board and the groundwork behind the live work before answering anything, because a compaction summary keeps conclusions and drops the reasoning that produced them.
7
7
 
8
8
  1. Resolve the main worktree root with `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd`. Every path below resolves against it.
9
- 2. Read `.claude/tasks/priority.md` for the ordering and what each task waits on. Read the newest `.claude/tasks/session-*.md` when one exists, per `${CLAUDE_SKILL_DIR}/../../standards/session.md`, and treat it as the previous session's scratch rather than a source.
9
+ 2. Read `.canon/tasks/priority.md` for the ordering and what each task waits on. Read the newest `.canon/tasks/session-*.md` when one exists, per `${CLAUDE_SKILL_DIR}/../../standards/session.md`, and treat it as the previous session's scratch rather than a source.
10
10
  3. Read the task file for every entry under `## Run now`, plus any entry a live pull request names.
11
11
  4. Read the groundwork folder each of those tasks cites. Read `README.md` for the file map, then `06-decision.md` when the track is closed, or `07-next-session.md` and the numbered topic files when it is open. A task's Findings section is a lossy summary of its track, so planning against the summary re-derives what the folder already settled.
12
12
  5. Run `gh pr list --state open` and `git log --oneline -5` to see what shipped since the folder was written.
@@ -18,7 +18,7 @@ if [ -z "$MAIN_ROOT" ]; then
18
18
  echo "poll: not a git repository, so nothing is classified" >&2
19
19
  exit 1
20
20
  fi
21
- STATE_DIR="$MAIN_ROOT/.claude/.tmp/pr-poll"
21
+ STATE_DIR="$MAIN_ROOT/.canon/tmp/pr-poll"
22
22
  mkdir -p "$STATE_DIR"
23
23
  STATE="$STATE_DIR/baseline.txt"
24
24
  touch "$STATE"
@@ -42,7 +42,7 @@ before what, and whether a row should run at all stay with the controlling
42
42
  session, and no body states that boundary for the planning side.
43
43
 
44
44
  Nothing scans a plan for banned words either. `.gitignore` ignores
45
- `.claude/plans/`, and the audit's default path set is what git lists, so no gate
45
+ `.canon/plans/`, and the audit's default path set is what git lists, so no gate
46
46
  ever opens one. Six ban hits landed across the four trial plans and three of the
47
47
  four carried at least one, caught only because the planner ran
48
48
  `canon markdown audit` unprompted.
@@ -21,9 +21,9 @@ from here.
21
21
 
22
22
  ## Where the session stands
23
23
 
24
- - Write one file, the plan, at `.claude/plans/feature-<slug>.md` on the main worktree root. Everything else this session touches is a read.
24
+ - Write one file, the plan, at `.canon/plans/feature-<slug>.md` on the main worktree root. Everything else this session touches is a read.
25
25
  - Never enter a worktree, never create a branch, and never write a tracked file. A planner that builds has stopped being one, and the row loses the independent read the worker's own session was going to bring to it.
26
- - Resolve `.claude/plans/`, `.claude/tasks/`, and `.claude/review/` at the main worktree root. Those folders are gitignored, so a copy beside a linked worktree is absent rather than empty.
26
+ - Resolve `.canon/plans/`, `.canon/tasks/`, and `.canon/review/` at the main worktree root. Those folders are gitignored, so a copy beside a linked worktree is absent rather than empty.
27
27
  - Plan the row the launch named. Report a second row met while reading rather than planning it, since which rows run is the controller's call.
28
28
 
29
29
  ## What to read before deciding
@@ -33,9 +33,9 @@ Each item below is something a plan needed and a launch string did not carry.
33
33
  - The task file, and its `## Findings` before deciding anything. A row can carry its own disproof under a title that still states the original claim, which is how one trial nearly planned against a premise the file had already recorded as dead.
34
34
  - The source files themselves, opened rather than summarized. Never a count quoted from the task file, which was wrong or stale in ten places across four plans.
35
35
  - `CLAUDE.md` and `.claude/ARCHITECTURE.md`, for the decision and the alternative it was taken against rather than for the decision alone.
36
- - The plan of any row this one is sequenced behind, including one already moved to `.claude/plans/archive/`. Reading a shipped plan produced the strongest constraint in the first trial and no brief asked for it.
37
- - `.claude/tasks/priority.md` for the row's Touches column and its stated blocker. That column is the file set the dispatch disjointness gate already reads.
38
- - `${CLAUDE_SKILL_DIR}/../../standards/plan.md` for the shape, then `canon records validate plans` and `canon markdown audit <the plan file>` on the file once it is written. Nothing else opens a plan, since `.claude/plans/` is gitignored and the audit's default path set is what git lists.
36
+ - The plan of any row this one is sequenced behind, including one already moved to `.canon/plans/archive/`. Reading a shipped plan produced the strongest constraint in the first trial and no brief asked for it.
37
+ - `.canon/tasks/priority.md` for the row's Touches column and its stated blocker. That column is the file set the dispatch disjointness gate already reads.
38
+ - `${CLAUDE_SKILL_DIR}/../../standards/plan.md` for the shape, then `canon records validate plans` and `canon markdown audit <the plan file>` on the file once it is written. Nothing else opens a plan, since `.canon/plans/` is gitignored and the audit's default path set is what git lists.
39
39
 
40
40
  ## Read what is in flight rather than inferring it
41
41
 
@@ -46,7 +46,7 @@ Each item below is something a plan needed and a launch string did not carry.
46
46
 
47
47
  ## The board is read-only
48
48
 
49
- - Never write `.claude/tasks/priority.md` or `.claude/tasks/backlog.md`. Both are gitignored, so an overwrite drops a row with no history to recover it from.
49
+ - Never write `.canon/tasks/priority.md` or `.canon/tasks/backlog.md`. Both are gitignored, so an overwrite drops a row with no history to recover it from.
50
50
  - Never write the task file either. The plan is the whole output, and a row edited from here changes what the controller reads back as the state of the board.
51
51
  - Report what the row got wrong rather than repairing it. A stale count, a moved line, or a path that no longer resolves goes into the plan and into the handback, and the controller decides which of the two carries the correction.
52
52
  - Leave the cross-feature call alone. Which rows collide, what merges before what, and whether a row should run at all stay with the controller. `priority.md` shows blockers and file sets and is enough to write a confident merge order off a partial picture, which is the failure this boundary exists to prevent.
@@ -36,8 +36,8 @@ Read these in parallel from the project root, skipping any that do not exist:
36
36
  - `CLAUDE.md`: project type, conventions, and commands
37
37
  - `.claude/REQUIREMENTS.md`: feature scope and non-goals
38
38
  - `.claude/ARCHITECTURE.md`: technical design decisions
39
- - `.claude/tasks/priority.md`: where this feature sits on the board and what each neighboring row waits on. Resolve this one at the main worktree root per Worktrees in `CLAUDE.md`, since the board is gitignored and a linked worktree holds no copy of it
40
- - `.claude/plans/feature-<slug>.md` for the branch, when present: the intent the PR should satisfy
39
+ - `.canon/tasks/priority.md`: where this feature sits on the board and what each neighboring row waits on. Resolve this one at the main worktree root per Worktrees in `CLAUDE.md`, since the board is gitignored and a linked worktree holds no copy of it
40
+ - `.canon/plans/feature-<slug>.md` for the branch, when present: the intent the PR should satisfy
41
41
 
42
42
  Coding standards from `.claude/rules/` are auto-loaded by Claude Code.
43
43
 
@@ -141,7 +141,7 @@ Use severity: `critical` (blocks merge), `should-fix` (fix before merge), `minor
141
141
 
142
142
  ## Step 4: post to the PR
143
143
 
144
- Write the comment to `.claude/.tmp/pr-review/body-<number>-<short-sha>.md`, which the rest of this step calls `<body-file>`. The PR number stops two sessions reviewing different pull requests from overwriting each other between the write and the post. The head commit stops a second pass overwriting the first one's body, and leaves the folder a record of which commit each review covered.
144
+ Write the comment to `.canon/tmp/pr-review/body-<number>-<short-sha>.md`, which the rest of this step calls `<body-file>`. The PR number stops two sessions reviewing different pull requests from overwriting each other between the write and the post. The head commit stops a second pass overwriting the first one's body, and leaves the folder a record of which commit each review covered.
145
145
 
146
146
  Derive both segments from Step 1. Never pick a suffix by hand, and never reuse a name the folder already holds.
147
147
 
@@ -228,12 +228,12 @@ The `What is right` section is optional, capped at three bullets, and included o
228
228
 
229
229
  Close the body with `🤖 Reviewed by Claude Code` on its own line so the review reads as an independent machine pass, not a human sign-off.
230
230
 
231
- Before posting, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the body. The hook skips `.claude/.tmp/`, so this scan is the only gate on the published comment. A finding phrased against an internal phase label is what the label half of the scan catches here.
231
+ Before posting, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the body. The hook skips `.canon/tmp/`, so this scan is the only gate on the published comment. A finding phrased against an internal phase label is what the label half of the scan catches here.
232
232
 
233
233
  Do not run the command below when `<prior-heading>` from Step 2 reads `## Review closed` and this pass carries nothing owed. That pass replaces the standing comment rather than adding one, under `### A close-out that repeats the standing one` at the end of this step. Posting first and reaching that section afterward leaves two close-outs both naming the new head, which is worse than the pair the guard exists against.
234
234
 
235
235
  ```bash
236
- gh pr review <number> --comment --body-file .claude/.tmp/pr-review/body-<number>-<short-sha>.md
236
+ gh pr review <number> --comment --body-file .canon/tmp/pr-review/body-<number>-<short-sha>.md
237
237
  ```
238
238
 
239
239
  A pass carrying nothing at all takes `## Review closed` and a short body, with the footer line included either way. On a first pass, post `✅ No findings. Reviewed against project docs and the board.` On a later pass, post `✅ Prior findings addressed. Re-reviewed <short-sha>, N commits since the prior pass.`
@@ -120,13 +120,13 @@ If nothing is wrong, use: `✅ No findings.`
120
120
 
121
121
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
122
122
 
123
- Write the full report directly to `.claude/review/branch/review-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
123
+ Write the full report directly to `.canon/review/branch/review-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
124
124
 
125
125
  From a linked worktree the file-editing tools refuse that path, so the report goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
126
126
 
127
127
  If there are no findings, write `✅ No findings.` to the file with a timestamp.
128
128
 
129
- The `.claude/review/` directory is gitignored. Do not stage or commit the file.
129
+ The `.canon/review/` directory is gitignored. Do not stage or commit the file.
130
130
 
131
131
  The report is disposable. It outlives the ship chain that reads it, and `claude-docs` sweeps it once the branch it names is gone, because the durable record of what a review found is the comment `claude-pr-review` posts on the pull request. A review run on a branch that never opens one leaves nothing behind once that branch is gone, so fold anything worth keeping into the pull request body or a task finding while the report is still on disk.
132
132
 
@@ -136,7 +136,7 @@ Output only the summary line and the file path. Do not repeat the full report in
136
136
 
137
137
  ```plaintext
138
138
  X critical, Y should-fix, Z minor across N files.
139
- 📝 Wrote .claude/review/branch/review-<slug>.md
139
+ 📝 Wrote .canon/review/branch/review-<slug>.md
140
140
  ```
141
141
 
142
- If no findings: `✅ No findings. Wrote .claude/review/branch/review-<slug>.md`
142
+ If no findings: `✅ No findings. Wrote .canon/review/branch/review-<slug>.md`
@@ -68,7 +68,7 @@ Before proposing an Update, grep the target section for the seed text's keywords
68
68
 
69
69
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
70
70
 
71
- Write the full proposal to `.claude/review/seed-audit-<slug>.md` at the main worktree root. Do not print the proposal inline.
71
+ Write the full proposal to `.canon/review/seed-audit-<slug>.md` at the main worktree root. Do not print the proposal inline.
72
72
 
73
73
  From a linked worktree the file-editing tools refuse that path, so the proposal goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
74
74
 
@@ -123,7 +123,7 @@ Decision:
123
123
 
124
124
  Update items show both sides in one `diff` block: removed lines from the project version with `-`, added lines from the seed version with `+`, unchanged context lines without a prefix. Add items show only `+` lines. Customized sections appear in the scope table only, never numbered. A file with no drift still appears in the scope table as `in sync`.
125
125
 
126
- After writing, tell the user `✅ Wrote proposal to .claude/review/seed-audit-<slug>.md`. Ask them to fill in `Decision:` per item, then re-ping or use the chat shortcut.
126
+ After writing, tell the user `✅ Wrote proposal to .canon/review/seed-audit-<slug>.md`. Ask them to fill in `Decision:` per item, then re-ping or use the chat shortcut.
127
127
 
128
128
  Rewrite the review file in place whenever the proposal changes mid-review. The file stays the source of truth for the current decisions.
129
129
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: claude-tasks
3
- description: Creates a task file in `.claude/tasks/` with the filename, phase label, and frontmatter the standard requires, and archives a shipped one out of the folder. Use when asked to "add a task", "create a task", "queue this", "put this on the board", "archive that task", or "close out a shipped task". Do NOT use to mark an outcome `[x]` or to archive a plan. That is `claude-docs`.
3
+ description: Creates a task file in `.canon/tasks/` with the filename, phase label, and frontmatter the standard requires, and archives a shipped one out of the folder. Use when asked to "add a task", "create a task", "queue this", "put this on the board", "archive that task", or "close out a shipped task". Do NOT use to mark an outcome `[x]` or to archive a plan. That is `claude-docs`.
4
4
  ---
5
5
 
6
6
  # Claude tasks
@@ -13,9 +13,9 @@ Read `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` before writing any file. It
13
13
 
14
14
  - Resolve the board at the main worktree root, not `pwd`. Run `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo. Every read and write below resolves against that root. The board is gitignored scratch shared across worktrees, so a linked worktree writing to its own `pwd` creates a second board nothing else reads.
15
15
  - From a linked worktree the file-editing tools refuse that root, so a new task file goes out through `Bash` as a plain single command carrying a heredoc. Archiving already runs through `canon tasks archive`, which resolves the root in-process. Marking an outcome shipped is `claude-docs` and runs through `canon tasks outcome`. See Worktrees in `CLAUDE.md`.
16
- - If `.claude/tasks/` does not exist at that root, stop: `❌ No .claude/tasks/ board. Run canon claude init to set it up.`
16
+ - If `.canon/tasks/` does not exist at that root, stop: `❌ No .canon/tasks/ board. Run canon claude init to set it up.`
17
17
  - Route on the request rather than on a flag. Creating names work that does not exist yet, archiving names a task file already on the board. If the request fits neither, stop: `❌ Ambiguous. Say whether to create a task or archive one.`
18
- - Never hand-edit `.claude/tasks/index.md`. A hook regenerates it from sibling frontmatter after a write. 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 regenerates explicitly with `canon indexes regen --no-stage --root <main-root> <main-root>/.claude/tasks/index.md`.
18
+ - Never hand-edit `.canon/tasks/index.md`. A hook regenerates it from sibling frontmatter after a write. 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 regenerates explicitly with `canon indexes regen --no-stage --root <main-root> <main-root>/.canon/tasks/index.md`.
19
19
 
20
20
  ## Create
21
21
 
@@ -29,15 +29,15 @@ Accept work whose origin is the conversation itself only when the user says so e
29
29
 
30
30
  ### Step 2: propose the phase label
31
31
 
32
- List the existing filenames in `.claude/tasks/` and read `index.md` for what each holds. Propose the next label from what is already on the board, and say which neighbors it sits between.
32
+ List the existing filenames in `.canon/tasks/` and read `index.md` for what each holds. Propose the next label from what is already on the board, and say which neighbors it sits between.
33
33
 
34
34
  Do not derive the label from a version file. `${CLAUDE_SKILL_DIR}/../../standards/versioning.md` permits free renumbering, so the board is the only surface that knows what a label currently means. Pad the phase to two digits in the filename, since index entries sort by filename alone and a bare `v9.0` sorts after `v15.0`.
35
35
 
36
36
  ### Step 3: write the file
37
37
 
38
- Write `.claude/tasks/vXX.Y-<slug>.md` following the format in `${CLAUDE_SKILL_DIR}/../../standards/tasks.md`. Include a link line only when the file or folder it names exists. A link to a plan nobody has written yet is the broken pointer the archive rules exist to prevent.
38
+ Write `.canon/tasks/vXX.Y-<slug>.md` following the format in `${CLAUDE_SKILL_DIR}/../../standards/tasks.md`. Include a link line only when the file or folder it names exists. A link to a plan nobody has written yet is the broken pointer the archive rules exist to prevent.
39
39
 
40
- Write `Plan:`, `Groundwork:`, and `Intake:` as markdown links relative to `.claude/tasks/`, as in `Plan: [feature-<slug>](../plans/feature-<slug>.md)`. Leave `Issue:` a bare `#NNN`. A task written in the older bare-path form still parses, so it costs the board a clickable line rather than an archive, but it leaves the board in two shapes for every reader after.
40
+ Write `Plan:`, `Groundwork:`, and `Intake:` as markdown links relative to `.canon/tasks/`, as in `Plan: [feature-<slug>](../plans/feature-<slug>.md)`. Leave `Issue:` a bare `#NNN`. A task written in the older bare-path form still parses, so it costs the board a clickable line rather than an archive, but it leaves the board in two shapes for every reader after.
41
41
 
42
42
  Never write a `Pull request:` line here. `git-pr` adds it when a pull request opens, and a number guessed at create time points at someone else's work.
43
43
 
@@ -45,7 +45,7 @@ Write it immediately. Claude Code's tool permission dialog is the confirmation g
45
45
 
46
46
  ### Step 4: place it on a surface
47
47
 
48
- A task file with no row is a dropped task, so name the surface it lands on in the same pass that creates it. A task that would plausibly be planned within the next few waves takes a row under `## Needs a plan` in `.claude/tasks/priority.md`, positioned by where it sits against the rows already there, with the reason for that position in its `Waiting on` cell. Anything else takes a line in `.claude/tasks/backlog.md`, which is unordered and where in the file it goes means nothing.
48
+ A task file with no row is a dropped task, so name the surface it lands on in the same pass that creates it. A task that would plausibly be planned within the next few waves takes a row under `## Needs a plan` in `.canon/tasks/priority.md`, positioned by where it sits against the rows already there, with the reason for that position in its `Waiting on` cell. Anything else takes a line in `.canon/tasks/backlog.md`, which is unordered and where in the file it goes means nothing.
49
49
 
50
50
  The test and both file shapes are in `${CLAUDE_SKILL_DIR}/../../standards/tasks.md`. From a linked worktree the file-editing tools refuse the main root, so a row lands through the same `Bash` route the file itself took.
51
51
 
@@ -55,9 +55,9 @@ Say which surface it went to and why in the report. The call is a judgment resta
55
55
 
56
56
  Scan for work that has been decided and would otherwise be forgotten. Three origins carry it, and every run reads all three.
57
57
 
58
- List `.claude/groundwork/` and run `gh issue list --state open` when a remote is configured, then grep the board for each track name and issue number. Report any with no task, one line each.
58
+ 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. Report any with no task, one line each.
59
59
 
60
- Read the dumps through `canon intake list --json`, which reports items, open, unread, and malformed per folder and owns the parse of the answer contract `${CLAUDE_SKILL_DIR}/../../standards/intake.md` fixes. Then grep both `.claude/tasks/` and `.claude/tasks/archive/` for each folder slug. A dump with no live task is the ordinary shape of one already promoted and shipped, so a check reading the board by itself reports every finished folder as abandoned.
60
+ Read the dumps through `canon intake list --json`, which reports items, open, unread, and malformed per folder and owns the parse of the answer contract `${CLAUDE_SKILL_DIR}/../../standards/intake.md` fixes. Then grep both `.canon/tasks/` and `.canon/tasks/archive/` for each folder slug. A dump with no live task is the ordinary shape of one already promoted and shipped, so a check reading the board by itself reports every finished folder as abandoned.
61
61
 
62
62
  A dump is the stronger case for this scan rather than the weaker one. A track holds one question and stays visible, while a dump holds dozens of items whose verdicts were reached and then left with nothing carrying them forward.
63
63
 
@@ -122,7 +122,7 @@ Leave `TASK-ARCHIVE.md` alone when it is present in the archive folder. It recor
122
122
 
123
123
  ### Step 4: clear prose naming the task
124
124
 
125
- The command drops the task's row from `.claude/tasks/priority.md` and leaves prose alone. Remove any sentence that still names the archived task or counts the rows that changed, since a stale count reads as board state.
125
+ The command drops the task's row from `.canon/tasks/priority.md` and leaves prose alone. Remove any sentence that still names the archived task or counts the rows that changed, since a stale count reads as board state.
126
126
 
127
127
  ## Output
128
128
 
@@ -131,21 +131,21 @@ Emit the full relative path from the project root for every file written or move
131
131
  Create:
132
132
 
133
133
  ```plaintext
134
- ✅ Created: .claude/tasks/vXX.Y-<slug>.md
134
+ ✅ Created: .canon/tasks/vXX.Y-<slug>.md
135
135
 
136
136
  <label> sits between <neighbor> and <neighbor>.
137
137
  <board or backlog, and why it landed there>.
138
138
 
139
139
  **Origin with no task:**
140
140
 
141
- - `.claude/groundwork/<slug>/`: open, touched <date>
142
- - `.claude/intake/<slug>/`: every item answered, nothing promoted
141
+ - `.canon/groundwork/<slug>/`: open, touched <date>
142
+ - `.canon/intake/<slug>/`: every item answered, nothing promoted
143
143
  - #NNN: <issue title>
144
144
 
145
145
  **Waiting on you:**
146
146
 
147
- - `.claude/intake/<slug>/`: <n> of <n> items unread
148
- - `.claude/intake/<slug>/`: <n> items carry no answer slot, so no verb reaches them
147
+ - `.canon/intake/<slug>/`: <n> of <n> items unread
148
+ - `.canon/intake/<slug>/`: <n> items carry no answer slot, so no verb reaches them
149
149
  ```
150
150
 
151
151
  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: `Read <n> tracks, <n> dumps, and <n> open issues. Nothing unlinked.`
@@ -153,7 +153,7 @@ Drop either block when it carries no rows. When both are empty, which is the ord
153
153
  Archive, reporting the paths the command returned:
154
154
 
155
155
  ```plaintext
156
- 📦 Archived: .claude/tasks/archive/vXX.Y-<slug>.md
156
+ 📦 Archived: .canon/tasks/archive/vXX.Y-<slug>.md
157
157
 
158
158
  <ordering and index disposition in one line>
159
159
  ```
@@ -118,7 +118,7 @@ Follow `${CLAUDE_SKILL_DIR}/references/lesson-craft.md` for what makes a lesson
118
118
  A lesson is a page carrying a stylesheet and a script, and an editor preview opens it with neither, so a path alone delivers unstyled markup that reads as the lesson. Serve the teach root and give the learner a link they can click:
119
119
 
120
120
  ```bash
121
- canon serve .claude/teach --entry <nn>-<topic>/index.html --json
121
+ canon serve .canon/teach --entry <nn>-<topic>/index.html --json
122
122
  ```
123
123
 
124
124
  Start it in the background so the session keeps going, and read `url` off the record rather than composing one. The verb walks past a port already in use, so the port it took is exactly the half a guessed URL gets wrong. Report the refusal and its `reason` when `ok` is false, and report it rather than proceeding silently when the verb does not resolve at all, which is an installed CLI predating it.
@@ -149,12 +149,12 @@ Still owed: <what the destination expects that the page does not carry yet>
149
149
 
150
150
  Then stop and let the operator strike, redirect, or confirm each block.
151
151
 
152
- Write nothing to a destination here. One skill owns the durable writes, and two skills editing one file at one step is the failure that rule exists against. Record each confirmed block in `.claude/.tmp/teach-promotion/<slug>.md` at the main worktree root instead, appending when the file exists, with one H2 per destination naming its path, the source page beneath it, and the page body fenced:
152
+ Write nothing to a destination here. One skill owns the durable writes, and two skills editing one file at one step is the failure that rule exists against. Record each confirmed block in `.canon/tmp/teach-promotion/<slug>.md` at the main worktree root instead, appending when the file exists, with one H2 per destination naming its path, the source page beneath it, and the page body fenced:
153
153
 
154
154
  ````markdown
155
155
  ## <destination path>
156
156
 
157
- Source: .claude/teach/<nn>-<topic>/reference/<slug>.md
157
+ Source: .canon/teach/<nn>-<topic>/reference/<slug>.md
158
158
 
159
159
  ```markdown
160
160
  <the page body as it should land, with the source line the destination expects>
@@ -172,10 +172,10 @@ An append is a whole-file operation, so send it as a plain single `Bash` command
172
172
  ## Output
173
173
 
174
174
  ```plaintext
175
- ✅ <opened|resumed> .claude/teach/<nn>-<topic>/
176
- Lesson: .claude/teach/<nn>-<topic>/lessons/<nnnn>-<slug>.html
177
- Reference: .claude/teach/<nn>-<topic>/reference/<slug>.md
178
- Record: .claude/teach/<nn>-<topic>/learning-records/<nnnn>-<slug>.md
175
+ ✅ <opened|resumed> .canon/teach/<nn>-<topic>/
176
+ Lesson: .canon/teach/<nn>-<topic>/lessons/<nnnn>-<slug>.html
177
+ Reference: .canon/teach/<nn>-<topic>/reference/<slug>.md
178
+ Record: .canon/teach/<nn>-<topic>/learning-records/<nnnn>-<slug>.md
179
179
  Progress: <n> of <m> success lines met
180
180
  Open: [<the url the serve verb reported>](<the same url>)
181
181
  ```
@@ -189,8 +189,8 @@ Emit every path from the project root, in the form the project's instruction fil
189
189
  A promotion pass reports its own shape instead, one line per page the operator confirmed and one naming the handoff:
190
190
 
191
191
  ```plaintext
192
- ➡️ Promoting: .claude/teach/<nn>-<topic>/reference/<slug>.md → <destination path>
193
- → Confirmed pages wait at .claude/.tmp/teach-promotion/<slug>.md. Run /claude-docs from a branch to fold them in.
192
+ ➡️ Promoting: .canon/teach/<nn>-<topic>/reference/<slug>.md → <destination path>
193
+ → Confirmed pages wait at .canon/tmp/teach-promotion/<slug>.md. Run /claude-docs from a branch to fold them in.
194
194
  ```
195
195
 
196
196
  A pass where the operator confirmed nothing writes no handoff file and reports that alone.
@@ -59,19 +59,19 @@ If all changes are automatable, skip the manual checklist:
59
59
 
60
60
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
61
61
 
62
- When a manual checklist is produced, write it directly to `.claude/review/ui-checklist-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
62
+ When a manual checklist is produced, write it directly to `.canon/review/ui-checklist-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
63
63
 
64
64
  From a linked worktree the file-editing tools refuse that path, so the checklist goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
65
65
 
66
66
  Skip the file write when all changes are covered by e2e tests and no checklist was produced.
67
67
 
68
- The `.claude/review/` directory is gitignored. Do not stage or commit the file.
68
+ The `.canon/review/` directory is gitignored. Do not stage or commit the file.
69
69
 
70
70
  ## Output order
71
71
 
72
72
  1. Write and run e2e tests (report pass/fail)
73
73
  2. If a manual checklist was produced, write it to file, then output only the file path in chat:
74
- `📝 Wrote .claude/review/ui-checklist-<slug>.md`
74
+ `📝 Wrote .canon/review/ui-checklist-<slug>.md`
75
75
  3. If no checklist was needed: `✅ All changes covered by e2e tests. No manual verification needed.`
76
76
 
77
77
  Do not repeat the full checklist in chat.
@@ -21,7 +21,7 @@ Read these in parallel from the project root, skipping any that do not exist:
21
21
 
22
22
  ## Step 2: identify surfaces
23
23
 
24
- List the UI surfaces in the project. A surface is a distinct screen, page, panel, or major component (e.g. sidepanel, popup, settings page, empty state). Group files by surface. Do not audit speculative or unfinished code flagged in `.claude/tasks/` as in-progress.
24
+ List the UI surfaces in the project. A surface is a distinct screen, page, panel, or major component (e.g. sidepanel, popup, settings page, empty state). Group files by surface. Do not audit speculative or unfinished code flagged in `.canon/tasks/` as in-progress.
25
25
 
26
26
  ## Step 3: audit each surface
27
27
 
@@ -59,13 +59,13 @@ If nothing is wrong, use: `✅ No observations.`
59
59
 
60
60
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
61
61
 
62
- Write the full report directly to `.claude/review/ux-audit-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
62
+ Write the full report directly to `.canon/review/ux-audit-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
63
63
 
64
64
  From a linked worktree the file-editing tools refuse that path, so the report goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
65
65
 
66
66
  If there are no observations, write `✅ No observations.` to the file with a timestamp.
67
67
 
68
- The `.claude/review/` directory is gitignored. Do not stage or commit the file.
68
+ The `.canon/review/` directory is gitignored. Do not stage or commit the file.
69
69
 
70
70
  ### Chat output
71
71
 
@@ -73,7 +73,7 @@ Output only the summary line and the file path. Do not repeat the full report in
73
73
 
74
74
  ```plaintext
75
75
  X observations across N surfaces.
76
- 📝 Wrote .claude/review/ux-audit-<slug>.md
76
+ 📝 Wrote .canon/review/ux-audit-<slug>.md
77
77
  ```
78
78
 
79
- If no observations: `✅ No observations. Wrote .claude/review/ux-audit-<slug>.md`
79
+ If no observations: `✅ No observations. Wrote .canon/review/ux-audit-<slug>.md`
@@ -106,11 +106,11 @@ Report the reading and stop there. A remedy for a poor verdict is a change with
106
106
 
107
107
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
108
108
 
109
- Write the full reading directly to `.claude/review/ux-measure-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
109
+ Write the full reading directly to `.canon/review/ux-measure-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
110
110
 
111
111
  From a linked worktree the file-editing tools refuse that path, so the reading goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
112
112
 
113
- The `.claude/review/` directory is gitignored. Do not stage or commit the file.
113
+ The `.canon/review/` directory is gitignored. Do not stage or commit the file.
114
114
 
115
115
  ### Chat output
116
116
 
@@ -118,5 +118,5 @@ Output the summary line and the file path. Do not repeat the table in chat.
118
118
 
119
119
  ```plaintext
120
120
  3 metrics measured against <url>. <n> past threshold.
121
- 📝 Wrote .claude/review/ux-measure-<slug>.md
121
+ 📝 Wrote .canon/review/ux-measure-<slug>.md
122
122
  ```
@@ -22,13 +22,13 @@ running and re-invoking it would restart the build.
22
22
 
23
23
  ## Where the session stands
24
24
 
25
- - Resolve `.claude/plans/`, `.claude/tasks/`, `.claude/review/`, and `.claude/memory/` at the main worktree root, never against the linked worktree this session builds in. Those folders are gitignored, so `git worktree add` never creates them and the copy beside the build is absent rather than empty.
25
+ - Resolve `.canon/plans/`, `.canon/tasks/`, `.canon/review/`, and `.canon/memory/` at the main worktree root, never against the linked worktree this session builds in. Those folders are gitignored, so `git worktree add` never creates them and the copy beside the build is absent rather than empty.
26
26
  - Report a plan that fails to resolve as unreadable from here, naming the main-root path. Reporting the task as having no plan is true where this session stands and wrong about the world, and a reader with no second tree to check cannot separate the two.
27
27
  - Build the plan the launch named. Do not write a second one when the path fails to resolve, since a row that cites a plan already has one and drafting another produces two plans for one row.
28
28
 
29
29
  ## The board is read-only
30
30
 
31
- - Never write `.claude/tasks/priority.md` or `.claude/tasks/backlog.md`. The controlling session is their only writer apart from `canon tasks archive`, and both are gitignored, so an overwrite drops a row with no history to recover it from.
31
+ - Never write `.canon/tasks/priority.md` or `.canon/tasks/backlog.md`. The controlling session is their only writer apart from `canon tasks archive`, and both are gitignored, so an overwrite drops a row with no history to recover it from.
32
32
  - Report a row this build turns up rather than adding it. Picking a free label means reading every task file and every archive entry, which this session has not done, so a label it invents collides with one already taken.
33
33
  - Write the task file this build closes and the plan it ran under. The ban covers the shared board rather than the artifacts of the row in hand.
34
34
 
@@ -13,7 +13,7 @@ Wrap the `EnterWorktree` entry path with name derivation so the user does not pi
13
13
  - If neither command resolves, the session is not in a git repo and no `WorktreeCreate` hook is configured. Stop: `❌ Not a git repository. EnterWorktree needs git or a WorktreeCreate hook.`
14
14
  - If the two match and `git rev-parse --show-superproject-working-tree` prints a path, the session is inside a submodule checkout. Stop: `❌ Inside a submodule of <path>. Run this from there instead.`
15
15
 
16
- The submodule guard sits on the matching branch rather than ahead of the first one, and a measurement decided that. Inside a submodule at git 2.43.0 both reads return the same absorbed path under the superproject's `.git/modules/`, so the first guard does not fire and the session proceeds. Every derivation below then reads the submodule as the project: Step 1 resolves the main root to the submodule, the plan lookup reads a `.claude/plans/` the project never wrote, and entry builds `.claude/worktrees/` inside a tree the superproject tracks as a commit. The superproject read is empty in a linked worktree of a submodule and in one of the superproject alike, which is why it separates the two states rather than qualifying the first guard.
16
+ The submodule guard sits on the matching branch rather than ahead of the first one, and a measurement decided that. Inside a submodule at git 2.43.0 both reads return the same absorbed path under the superproject's `.git/modules/`, so the first guard does not fire and the session proceeds. Every derivation below then reads the submodule as the project: Step 1 resolves the main root to the submodule, the plan lookup reads a `.canon/plans/` the project never wrote, and entry builds `.claude/worktrees/` inside a tree the superproject tracks as a commit. The superproject read is empty in a linked worktree of a submodule and in one of the superproject alike, which is why it separates the two states rather than qualifying the first guard.
17
17
 
18
18
  ## Step 1: resolve the main worktree root
19
19
 
@@ -38,8 +38,8 @@ The directory test separates the defect from a genuinely bare repository, which
38
38
  Try each source in order. Stop at the first match.
39
39
 
40
40
  0. **Caller-supplied.** The invocation carried an argument. Take it as the name and infer nothing further. Accept `<name>` or `<type>/<name>`, where a leading segment matching a type in `${CLAUDE_SKILL_DIR}/../../standards/branch.md` sets `<type>` and the rest is `<name>`. A bare `<name>` falls to the default type below.
41
- 1. **Plan matched to current branch.** Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. An empty result falls through to the next source here rather than becoming `latest`, since the slug is one candidate among several. If `<main-root>/.claude/plans/feature-<slug>.md` exists, use `<slug>`.
42
- 2. **Single plan file.** List `<main-root>/.claude/plans/feature-*.md`. If exactly one match, derive `<slug>` from the filename.
41
+ 1. **Plan matched to current branch.** Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. An empty result falls through to the next source here rather than becoming `latest`, since the slug is one candidate among several. If `<main-root>/.canon/plans/feature-<slug>.md` exists, use `<slug>`.
42
+ 2. **Single plan file.** List `<main-root>/.canon/plans/feature-*.md`. If exactly one match, derive `<slug>` from the filename.
43
43
  3. **Multiple plan files, no branch match.** Ask the user which plan. Show the candidate slugs as a numbered list. Do not pick.
44
44
  4. **Current branch.** When no plan exists, use the `<slug>` from step 1 if it is not `main` or `master`.
45
45
  4b. **Session context.** When on `main` or `master` with no matching plan, read the current conversation to infer a kebab slug from the topic being discussed. Propose it: `Infer: <slug>. Confirm or rename?` Do not enter the worktree until the user confirms or provides a corrected name.
@@ -48,12 +48,12 @@ The `pull_request` check the git-pr surface carries reads a pull request's own t
48
48
  Map a bug to `--label bug` and a task to `--label enhancement`.
49
49
 
50
50
  ```bash
51
- mkdir -p .claude/.tmp/issue
52
- cat <<'BODY' > .claude/.tmp/issue/body.md
51
+ mkdir -p .canon/tmp/issue
52
+ cat <<'BODY' > .canon/tmp/issue/body.md
53
53
  <body following the issue.md sections>
54
54
  BODY
55
- gh issue create --title "<type>: <subject>" --label <bug or enhancement> --body-file .claude/.tmp/issue/body.md
56
- rm -rf .claude/.tmp/issue
55
+ gh issue create --title "<type>: <subject>" --label <bug or enhancement> --body-file .canon/tmp/issue/body.md
56
+ rm -rf .canon/tmp/issue
57
57
  ```
58
58
 
59
59
  ## After execution
@@ -111,8 +111,8 @@ Detect an open pull request on the current head and branch: edit it in place whe
111
111
  Labels apply after that branch converges, against a pull request that already exists. `gh pr create --label` refuses a label the remote does not carry and opens no pull request at all, so a mistyped row costs the run rather than the label. One command after the fact also covers the create and the edit path together.
112
112
 
113
113
  ```bash
114
- mkdir -p .claude/.tmp/pr
115
- cat <<'BODY' > .claude/.tmp/pr/body.md
114
+ mkdir -p .canon/tmp/pr
115
+ cat <<'BODY' > .canon/tmp/pr/body.md
116
116
  <body content following pr.md template exactly>
117
117
  BODY
118
118
  pr_labels="<comma-separated labels, empty when the map resolves to nothing>"
@@ -120,16 +120,16 @@ git push -u origin HEAD || exit 1
120
120
  base_branch=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name) || exit 1
121
121
  pr_number=$(gh pr list --head "$(git branch --show-current)" --base "$base_branch" --state open --json number --jq '.[0].number // empty')
122
122
  if [ -n "$pr_number" ]; then
123
- pr_url=$(gh pr edit "$pr_number" --title "<title>" --body-file .claude/.tmp/pr/body.md) || exit 1
123
+ pr_url=$(gh pr edit "$pr_number" --title "<title>" --body-file .canon/tmp/pr/body.md) || exit 1
124
124
  else
125
- pr_url=$(gh pr create --title "<title>" --body-file .claude/.tmp/pr/body.md) || exit 1
125
+ pr_url=$(gh pr create --title "<title>" --body-file .canon/tmp/pr/body.md) || exit 1
126
126
  pr_number=${pr_url##*/}
127
127
  fi
128
128
  if [ -n "$pr_labels" ]; then
129
129
  gh pr edit "$pr_number" --add-label "$pr_labels" >/dev/null ||
130
130
  printf 'Label apply failed. Create a missing label with: gh label create <name>\n' >&2
131
131
  fi
132
- rm -rf .claude/.tmp/pr
132
+ rm -rf .canon/tmp/pr
133
133
  printf 'number=%s\nurl=%s\n' "$pr_number" "$pr_url"
134
134
  ```
135
135
 
@@ -137,7 +137,7 @@ printf 'number=%s\nurl=%s\n' "$pr_number" "$pr_url"
137
137
 
138
138
  Write the `number` the final command printed onto the task the branch is closing. Do not resolve it again. A head branch that carried an earlier pull request now has two, and a second `gh pr view` would pick between them by a precedence rule nothing here states. Reading what created or edited the pull request needs no such rule.
139
139
 
140
- The task is the one whose `Plan:` line names the plan this branch implemented. Name that plan by its file, which is `.claude/plans/feature-<slug>.md` at the main worktree root with `<slug>` derived per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. `claude-feature` writes the plan under the branch slug, so the two correspond on any branch that came through the plan-to-execute path. When the session already knows which plan it implemented, because a caller read it earlier in the chain, use that filename instead of re-deriving.
140
+ The task is the one whose `Plan:` line names the plan this branch implemented. Name that plan by its file, which is `.canon/plans/feature-<slug>.md` at the main worktree root with `<slug>` derived per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. `claude-feature` writes the plan under the branch slug, so the two correspond on any branch that came through the plan-to-execute path. When the session already knows which plan it implemented, because a caller read it earlier in the chain, use that filename instead of re-deriving.
141
141
 
142
142
  ```bash
143
143
  canon tasks pull-request <number> --plan feature-<slug> --json