@erclx/canon 4.81.0 → 4.82.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/claude/.claude-plugin/plugin.json +1 -1
- package/docs/agents/commands.md +7 -3
- package/docs/agents/context-audit.md +1 -1
- package/docs/agents/context-classify.md +99 -0
- package/docs/agents/index.md +1 -0
- package/docs/target-projects.md +15 -0
- package/docs/workflow/ai-workflow.md +3 -2
- package/governance/rules/claude/545-decisions.md +12 -0
- package/package.json +1 -1
- package/src/claude/seeds.ts +1 -0
- package/src/commands/claude.ts +26 -5
- package/src/commands/context.ts +425 -0
- package/src/context/classify/extract.ts +450 -0
- package/src/context/classify/ollama.ts +172 -0
- package/src/context/classify/patterns.ts +114 -0
- package/src/context/classify/prompts.ts +73 -0
- package/src/context/classify/run.ts +348 -0
- package/src/context/classify/settings.ts +196 -0
- package/src/context/folders.ts +1 -0
- package/src/surface-root.ts +1 -0
- package/standards/decisions.md +100 -0
- package/standards/index.md +1 -0
- package/tooling/claude/reference.md +1 -0
- package/tooling/claude/seeds/CLAUDE.md +1 -0
- package/tooling/claude/seeds/canon/decisions/index.md +8 -0
package/docs/agents/commands.md
CHANGED
|
@@ -58,7 +58,7 @@ Full help: `canon <command> --help`. Behavior notes for the install and sync ver
|
|
|
58
58
|
| `canon migrate rename` | Rewrite every unprotected `aitk` token to `canon` and move the paths that carry the name, reporting the plan without `--write` (`--scope`, `--json`) |
|
|
59
59
|
| `canon migrate skill-names` | Move the prefixed skill folders onto their two-word names and rewrite every citation, reporting the plan without `--write` (`--root`, `--json`) |
|
|
60
60
|
| `canon migrate records` | Move the gitignored session records to `.canon/` and repoint every tracked citation, reporting the plan without `--write` (`--root`, `--json`) |
|
|
61
|
-
| `canon migrate surface-roots` | Move the tracked surfaces (`context/`, `wireframes/`, the three loose documents, and the install stamp folder) from `.claude/` to `canon/` with `git mv` and repoint every tracked citation, reporting the plan without `--write` (`--root`, `--json`)
|
|
61
|
+
| `canon migrate surface-roots` | Move the tracked surfaces (`context/`, `decisions/`, `wireframes/`, the three loose documents, and the install stamp folder) from `.claude/` to `canon/` with `git mv` and repoint every tracked citation, reporting the plan without `--write` (`--root`, `--json`) |
|
|
62
62
|
| `canon migrate record-tree` | Repoint the old-root citations inside the records themselves, scoped to the live folders and reporting every line without `--write` (`--root`, `--json`) |
|
|
63
63
|
| `canon migrate rule-layout` | Move a target's installed rules from the flat `.claude/rules/<subdir>/` layout to `.claude/rules/canon/<subdir>/`, reporting the plan without `--write` (`--root`, `--json`) |
|
|
64
64
|
| `canon migrate scratch-evidence` | Move a folder under `.tmp/` that a durable record cites as evidence to `.canon/review/evidence/`, repointing every citation live or archived, reporting the plan without `--write` (`--root`, `--json`) |
|
|
@@ -67,6 +67,10 @@ Full help: `canon <command> --help`. Behavior notes for the install and sync ver
|
|
|
67
67
|
| `canon worktrees reclaim` | Remove every reclaimable worktree and the branch behind it, reporting without acting under `--dry-run` (`--json`) |
|
|
68
68
|
| `canon comments scan` | Measure comment density by language and comment kind, with a trend recomputed from git |
|
|
69
69
|
| `canon context audit` | Report required sections, length, cited paths, reference form, catalog tables, provenance, superseded-decision narration, and index drift |
|
|
70
|
+
| `canon context classify diff` | Classify the chunks a git range changed, each with its enclosing section, as keep, replace, history, or move (`--base`, `--doc-types`, `--json`) |
|
|
71
|
+
| `canon context classify sweep` | Classify every section of the five canonical doc types, split at H3, as keep, rewrite, or move (`--doc-types`, `--json`) |
|
|
72
|
+
| `canon context classifier show` | Report the resolved classifier backend and model and which source decided them (`--json`) |
|
|
73
|
+
| `canon context classifier set` | Write the project classifier setting to `canon/config/classifier.toml` (`--backend`, `--model`, `--json`) |
|
|
70
74
|
| `canon markdown audit` | Fail any markdown path on a banned character, word, or spelling, or a dead relative link, and report the structural checkpoints |
|
|
71
75
|
| `canon claude skills audit` | Report both skill corpora against the mechanical rules in `standards/skill.md` |
|
|
72
76
|
| `canon standards audit` | Report the corpus against the success-criterion gate `standards/standard.md` states, failing only on a standard new to the branch (`--json`, `--arrivals-only`) |
|
|
@@ -143,7 +147,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
|
|
|
143
147
|
| `intake` | `list`, `answer` |
|
|
144
148
|
| `teach` | `list`, `open`, `resource`, `glossary`, `lesson`, `stylesheet`, `nav`, `render` |
|
|
145
149
|
| `comments` | `scan` |
|
|
146
|
-
| `context` | `audit`
|
|
150
|
+
| `context` | `audit`, `classify diff`, `classify sweep`, `classifier show`, `classifier set` |
|
|
147
151
|
| `markdown` | `audit` |
|
|
148
152
|
| `secrets` | `scan` |
|
|
149
153
|
| `deps` | `audit` |
|
|
@@ -169,7 +173,7 @@ Common patterns:
|
|
|
169
173
|
|
|
170
174
|
A record folder already present at the destination is a refusal rather than a merge, and a line carrying `canon-keep-record-root`, or the nearest non-blank line below it, keeps the old spelling for prose that dates a decision. The records themselves are never swept: everything under `.canon/` and every `.claude/` record folder is passed over and reported as a count on its own line, which is what keeps the run that follows the ignore collapse touching the same files as one before it. Running it twice rewrites nothing, which is the check that the exclusions, the markers, and that skip all fired.
|
|
171
175
|
|
|
172
|
-
`migrate surface-roots` moves the tracked surfaces from `.claude/` to `canon/`: `context/`, `wireframes/`, `ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`, and the install stamp folder, respelled `canon/config/` since a project under `canon/` reserves the bare `canon` name for the CLI's own install. Every path is tracked, so each file moves with `git mv` and its history follows it, and every tracked citation of one is rewritten in the same run. `rules/`, `skills/`, `hooks/`, and `settings.json` stay where Claude Code reads them. It reports until `--write` is passed, and a destination already present under `canon/` refuses the whole plan rather than splitting a surface across both roots.
|
|
176
|
+
`migrate surface-roots` moves the tracked surfaces from `.claude/` to `canon/`: `context/`, `decisions/`, `wireframes/`, `ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`, and the install stamp folder, respelled `canon/config/` since a project under `canon/` reserves the bare `canon` name for the CLI's own install. Every path is tracked, so each file moves with `git mv` and its history follows it, and every tracked citation of one is rewritten in the same run. `rules/`, `skills/`, `hooks/`, and `settings.json` stay where Claude Code reads them. It reports until `--write` is passed, and a destination already present under `canon/` refuses the whole plan rather than splitting a surface across both roots.
|
|
173
177
|
|
|
174
178
|
A line carrying `canon-keep-surface-root`, or the nearest non-blank line above it, keeps the old spelling. A rule's frontmatter `paths:` glob, a citation shaped like a path into another repository, and one inside a dated paragraph are reported by file and line and left alone. Running it twice rewrites nothing, which is the idempotence check. A project that never runs it keeps resolving each surface under `.claude/`, since every reader takes whichever root holds the entry.
|
|
175
179
|
|
|
@@ -29,7 +29,7 @@ canon context audit tooling/base/seeds --gate
|
|
|
29
29
|
|
|
30
30
|
## Folder scope
|
|
31
31
|
|
|
32
|
-
Scope defaults to `context`, `diagrams`, and `wireframes`, and a folder the project does not carry is skipped rather than reported. A domain that outgrew one file and split into `<domain>/` is audited as its own folder, so a split entry measures at the same grain as a flat one.
|
|
32
|
+
Scope defaults to `context`, `decisions`, `diagrams`, and `wireframes`, and a folder the project does not carry is skipped rather than reported. A domain that outgrew one file and split into `<domain>/` is audited as its own folder, so a split entry measures at the same grain as a flat one.
|
|
33
33
|
|
|
34
34
|
A name passed to `--folder` resolves under the record roots first, `.canon/` ahead of `.claude/`, and at the project root last, which is what puts `docs/` and any later corpus in reach of the same engine. The root base is reached only by a name the caller passes, so the default list still resolves under a record root alone and a project holding a root `wireframes/` is not audited against a standard it never adopted. `diagrams` is the one default name that is a session record and moves with them, which is why both record roots are in the list rather than one, and `docs/agents/records.md` states the read order every verb shares. The scope line prints the resolved path, so a project carrying both spellings reads which one was taken. The JSON record carries the base per folder as `folders[].base`.
|
|
35
35
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Doc classifier
|
|
3
|
+
description: Classifying canonical-doc content as keep, replace/rewrite, history, or move in diff and sweep mode, the classifier setting pair, the record shape, and the exit codes
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Doc classifier
|
|
7
|
+
|
|
8
|
+
`canon context classify` reads content from the five canonical doc types (`context/<domain>.md`, `ARCHITECTURE.md`, `wireframes/<surface>.md`, `DESIGN.md`, `REQUIREMENTS.md`) and reports whether each piece states the project as it stands or should be rewritten, narrated elsewhere, or moved to another surface. It reports and never gates: a finding is a judgment for a writer to act on, not a fact a push fails over. Wiring it into `docs-fold`, the merge gate, or `canon context audit` is separate work this verb does not do.
|
|
9
|
+
|
|
10
|
+
Two modes read different units. Diff mode reads the chunks a git range changed, each with the section it landed in, which is what a session checks right after an edit. Sweep mode reads every section of the five doc types, split at H3, which is what a cleanup pass or a periodic re-scan runs over a whole corpus.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
canon context classify diff
|
|
14
|
+
canon context classify diff --base origin/main --json
|
|
15
|
+
canon context classify diff --doc-types context,wireframes
|
|
16
|
+
canon context classify sweep
|
|
17
|
+
canon context classify sweep --doc-types design,requirements --json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
| Option | Behavior |
|
|
21
|
+
| -------------------- | -------------------------------------------------------------- |
|
|
22
|
+
| `--base <ref>` | Diff mode only. Far side of the range, defaulting to the trunk |
|
|
23
|
+
| `--doc-types <list>` | Comma-separated canonical doc types (default: all five) |
|
|
24
|
+
| `--backend <name>` | Override the resolved model backend for this run |
|
|
25
|
+
| `--model <name>` | Override the resolved model name for this run |
|
|
26
|
+
| `--json` | Add a machine-readable record on stdout |
|
|
27
|
+
|
|
28
|
+
## Two layers
|
|
29
|
+
|
|
30
|
+
The regex layer always runs. It is free, needs nothing installed, and catches narration (a branch name, "closed on", "did not survive") and a source file path named inside a wireframe. It never answers REPLACE in diff mode, since telling a restated figure from a genuinely new one needs the section a hunk landed in, which the model layer reads and the regex layer does not.
|
|
31
|
+
|
|
32
|
+
The local Ollama layer runs only when configured, through `canon context classifier`. When it runs, its call is one chunk or section per request, never batched: the groundwork measurement behind this verb found that batching 16 hunks into one call returned KEEP for every one of them. Thinking is always off, since it was measured to catch nothing thinking-off missed while running roughly five times slower and, in sweep mode, losing three real flags by reasoning past them.
|
|
33
|
+
|
|
34
|
+
A finding carries both layers' readings when the model ran. The `verdict` field takes the model's reading when it ran and parsed, and falls back to the regex reading otherwise, since the model catches shapes the regex layer cannot reach structurally. `decidedBy` names which one won.
|
|
35
|
+
|
|
36
|
+
A configured-but-unreachable backend warns on stderr and falls back to the regex layer alone. The run still exits clean: the record's `modelLayer` field names why the model layer did not run (`off`, `skipped-no-model`, `skipped-unreachable`, or `ran`), so a clean regex-only report never reads as a clean model pass.
|
|
37
|
+
|
|
38
|
+
## The classifier setting
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
canon context classifier show
|
|
42
|
+
canon context classifier show --json
|
|
43
|
+
canon context classifier set --backend ollama --model qwen3.8:27b
|
|
44
|
+
canon context classifier set --backend off
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The backend and model resolve independently through the same four-tier precedence: a flag on the verb, then `CANON_CLASSIFIER_BACKEND` / `CANON_CLASSIFIER_MODEL`, then `canon/config/classifier.toml`, then off. `classifier show` reports the resolved backend and model and which tier decided them, without running a classification. There is no default model name: a model that resolves on one machine means nothing on another, so a backend configured with no model reports `no-model` from `show` and runs the regex layer alone from `classify`.
|
|
48
|
+
|
|
49
|
+
`classifier set` writes `canon/config/classifier.toml`, creating `canon/config/` when a project does not carry it yet:
|
|
50
|
+
|
|
51
|
+
```toml
|
|
52
|
+
[classifier]
|
|
53
|
+
backend = "ollama"
|
|
54
|
+
model = "qwen3.8:27b"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`--backend off` writes a file with no `model` line, which reads back as `off` at the same tier a missing file would default to, but with a source line saying the file decided it rather than the default.
|
|
58
|
+
|
|
59
|
+
## The record
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"decision": "ok",
|
|
64
|
+
"mode": "diff",
|
|
65
|
+
"backend": "ollama",
|
|
66
|
+
"model": "qwen3.8:27b",
|
|
67
|
+
"modelLayer": "ran",
|
|
68
|
+
"settingsSource": "file",
|
|
69
|
+
"findings": [
|
|
70
|
+
{
|
|
71
|
+
"file": "canon/context/retrieval.md",
|
|
72
|
+
"docType": "context",
|
|
73
|
+
"regex": {
|
|
74
|
+
"verdict": "KEEP",
|
|
75
|
+
"quote": "",
|
|
76
|
+
"reason": "no narration or wrong-surface pattern"
|
|
77
|
+
},
|
|
78
|
+
"model": {
|
|
79
|
+
"verdict": "REPLACE",
|
|
80
|
+
"quote": "the count moved",
|
|
81
|
+
"reason": "restates a figure the section already carries"
|
|
82
|
+
},
|
|
83
|
+
"verdict": "REPLACE",
|
|
84
|
+
"decidedBy": "model"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Sweep mode's findings carry a `heading` field alongside `file` and use the sweep vocabulary (KEEP, REWRITE, MOVE) rather than diff mode's four (KEEP, REPLACE, HISTORY, MOVE). REWRITE stands in for both REPLACE and HISTORY, matching the sweep prompt's own three-verdict vocabulary: a whole section already shows its own history in view, so there is no diff-mode split left to make.
|
|
91
|
+
|
|
92
|
+
## Exit codes
|
|
93
|
+
|
|
94
|
+
| Code | Meaning |
|
|
95
|
+
| ---- | ------------------------------------------------------------- |
|
|
96
|
+
| `0` | the run completed, whatever the findings say |
|
|
97
|
+
| `1` | refused: a bad range, an unreadable file, or a malformed flag |
|
|
98
|
+
|
|
99
|
+
Findings never set a failing exit code, in either mode. Diff mode refuses on a git range it cannot resolve. Both modes refuse on a file the run could not read.
|
package/docs/agents/index.md
CHANGED
|
@@ -15,6 +15,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
15
15
|
- [Comments](comments.md): Comment density by language and kind, the two structural exclusions, and how the degradation sweep finds its vocabulary
|
|
16
16
|
- [Context audit checks](context-audit-checks.md): What each non-gating check reports, the unit each checkpoint is measured in, the architecture record's length gate and claim coverage, which folders each check reaches, and what moved to the attribute tier
|
|
17
17
|
- [Context audit](context-audit.md): Running the audit, its flags and folder scope, the exit codes, the citation gate, and the widened gate the seed stage runs
|
|
18
|
+
- [Doc classifier](context-classify.md): Classifying canonical-doc content as keep, replace/rewrite, history, or move in diff and sweep mode, the classifier setting pair, the record shape, and the exit codes
|
|
18
19
|
- [Self-stated counts](counts.md): Reading a sentence that asserts a closed catalog's size, how a match is decided, the plausibility filter that keeps a generic word from matching a subset, and why the sweep reports rather than gates
|
|
19
20
|
- [Demo](demo.md): Compiling a screencast draft into a runnable plan, driving a served application to a recording and a still, reading numbered frames back out of a recording, the pointer the recording paints, and what each refusal reports
|
|
20
21
|
- [Design board](design-board.md): Generating a static index over a project's design surfaces, what each panel reads, and which two stay toolkit-checkout-only
|
package/docs/target-projects.md
CHANGED
|
@@ -196,6 +196,21 @@ Run the second line once per stack the project holds, since the two hooks above
|
|
|
196
196
|
|
|
197
197
|
The order carries the reason. A sync replaces each toolkit-owned copy with one already carrying the new names, and the sweep afterwards reaches the prose the project wrote itself. Sweeping first rewrites those installed files in place, which moves them off the hash the install recorded, so the next sync reads them as edited by the project and leaves them alone.
|
|
198
198
|
|
|
199
|
+
### Move the surfaces off `.claude/`, once
|
|
200
|
+
|
|
201
|
+
Tracked surfaces moved out of `.claude/` and into a root of their own. `context/`, `decisions/`, `wireframes/`, the three loose documents (`ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`), and the install stamp folder, respelled `canon/config/`, now live under `canon/`, and `rules/`, `skills/`, `hooks/`, and `settings.json` stay put since Claude Code reads those by path.
|
|
202
|
+
|
|
203
|
+
Run `canon upgrade` first if you have not, then run this from inside the project:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
canon migrate surface-roots --json
|
|
207
|
+
canon migrate surface-roots --write --json
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The first line reports the plan and the second applies it, moving each surface with `git mv` so its history follows and repointing every tracked citation of one in the same run. See `canon docs agents` for the full file list rather than reading it here.
|
|
211
|
+
|
|
212
|
+
Neither `canon sync --check` nor any other command notices a surface still sitting at `.claude/`, so running this is on you rather than on a prompt from the toolkit.
|
|
213
|
+
|
|
199
214
|
### Check first
|
|
200
215
|
|
|
201
216
|
`canon sync --check <path>` reports what has drifted without writing anything. It splits each difference by cause, which is the question that decides what to do next.
|
|
@@ -20,7 +20,8 @@ canon/
|
|
|
20
20
|
├── ARCHITECTURE.md ← technical design decisions
|
|
21
21
|
├── DESIGN.md ← visual intent and token decisions (UI projects)
|
|
22
22
|
├── wireframes/ ← ASCII wireframes: layout, UI copy, and interaction rules (UI projects)
|
|
23
|
-
|
|
23
|
+
├── context/ ← per-domain narrative loaded on demand via index.md
|
|
24
|
+
└── decisions/ ← decision history a canonical doc points at, never loaded eagerly
|
|
24
25
|
|
|
25
26
|
.claude/
|
|
26
27
|
└── rules/ ← path-scoped governance rules, written by canon gov install
|
|
@@ -33,7 +34,7 @@ canon/
|
|
|
33
34
|
└── tmp/ ← deletable scratch, safe to remove without loss
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
A project scaffolded before the move keeps its records under `.claude/`, and every command reads either root. `canon migrate records` moves one project across and repoints what cites it, and `canon migrate record-tree` follows it to reach the citations inside the records themselves, which the first verb passes over because it enumerates through git. A project scaffolded before the surface move keeps its context, wireframes, and loose documents under `.claude/` the same way, and `canon migrate surface-roots` moves those to `canon/` with the history following each file.
|
|
37
|
+
A project scaffolded before the move keeps its records under `.claude/`, and every command reads either root. `canon migrate records` moves one project across and repoints what cites it, and `canon migrate record-tree` follows it to reach the citations inside the records themselves, which the first verb passes over because it enumerates through git. A project scaffolded before the surface move keeps its context, decisions, wireframes, and loose documents under `.claude/` the same way, and `canon migrate surface-roots` moves those to `canon/` with the history following each file.
|
|
37
38
|
|
|
38
39
|
Three tiers of context load with different cost: always-loaded (root `CLAUDE.md`, `canon/REQUIREMENTS.md`, `canon/ARCHITECTURE.md`), path-scoped lazy (`.claude/rules/<scope>.md` with `paths:` glob), and on-demand lookup (`canon/context/<domain>.md`, or `canon/context/<domain>/` once a domain outgrows one file, discovered via `canon/context/index.md`). See [the context model](../../canon/context/context-model.md) for the full picture.
|
|
39
40
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Route canon/decisions/ edits to the decisions standard for record shape and lifecycle
|
|
3
|
+
paths:
|
|
4
|
+
- 'canon/decisions/**'
|
|
5
|
+
- '.claude/decisions/**'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Decisions standards
|
|
9
|
+
|
|
10
|
+
## Authority
|
|
11
|
+
|
|
12
|
+
- Follow the decisions standard for folder layout, the ordinal filename, frontmatter, record sections, and the append-only lifecycle. It is the single source. Read it with `canon standards decisions`.
|
package/package.json
CHANGED
package/src/claude/seeds.ts
CHANGED
package/src/commands/claude.ts
CHANGED
|
@@ -61,6 +61,7 @@ import { copyPreservingMode } from '@/copy'
|
|
|
61
61
|
import { execScript } from '@/exec'
|
|
62
62
|
import { checkoutMismatchWarning, PROJECT_ROOT } from '@/project-root'
|
|
63
63
|
import { recordDir } from '@/record-root'
|
|
64
|
+
import { SURFACE_ENTRIES, surfaceDir } from '@/surface-root'
|
|
64
65
|
import { isDirectory, resolveTarget } from '@/target'
|
|
65
66
|
import { injectGitignore, pruneGitignore } from '@/tooling/inject'
|
|
66
67
|
import {
|
|
@@ -148,7 +149,27 @@ const SEEDED_FILES: readonly string[] = [
|
|
|
148
149
|
'REQUIREMENTS.md',
|
|
149
150
|
'DESIGN.md',
|
|
150
151
|
]
|
|
151
|
-
const SEEDED_DIRS: readonly string[] = [
|
|
152
|
+
const SEEDED_DIRS: readonly string[] = [
|
|
153
|
+
'decisions',
|
|
154
|
+
'memory',
|
|
155
|
+
'tasks',
|
|
156
|
+
'wireframes',
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Where a `SEEDED_DIRS` entry resolves for the sync presence check.
|
|
161
|
+
*
|
|
162
|
+
* `wireframes` and `decisions` are tracked surface entries, resolved under
|
|
163
|
+
* `canon/` ahead of `.claude/`, while `memory` and `tasks` are session records
|
|
164
|
+
* resolved under `.canon/` ahead of `.claude/`. Routing every name through
|
|
165
|
+
* `recordDir` reported a migrated target's `canon/wireframes/` or
|
|
166
|
+
* `canon/decisions/` as missing, since that resolver never checks `canon/`.
|
|
167
|
+
*/
|
|
168
|
+
export function seededDirPath(resolved: string, name: string): string {
|
|
169
|
+
return SURFACE_ENTRIES.includes(name)
|
|
170
|
+
? surfaceDir(resolved, name)
|
|
171
|
+
: recordDir(resolved, name)
|
|
172
|
+
}
|
|
152
173
|
const USER_DIR = join('tooling', 'claude', 'user')
|
|
153
174
|
const STATUSLINE = 'statusline-command.sh'
|
|
154
175
|
const PLUGIN_MANIFEST = join('claude', '.claude-plugin', 'plugin.json')
|
|
@@ -580,16 +601,16 @@ async function runSync(target: string): Promise<number> {
|
|
|
580
601
|
|
|
581
602
|
// A record folder resolves at either root, so a migrated target is reported as
|
|
582
603
|
// seeded rather than sent to `canon claude init` to re-create records it
|
|
583
|
-
// already holds.
|
|
584
|
-
//
|
|
585
|
-
//
|
|
604
|
+
// already holds. `wireframes` and `decisions` are tracked surface entries
|
|
605
|
+
// instead, resolved through `surfaceDir`, since a migrated target holds them
|
|
606
|
+
// at `canon/` rather than under either record root.
|
|
586
607
|
logStep('Seeded')
|
|
587
608
|
for (const name of SEEDED_FILES) {
|
|
588
609
|
if (existsSync(join(resolved, '.claude', name))) logInfo(name)
|
|
589
610
|
else logWarn(`${name} missing. Run \`canon claude init\``)
|
|
590
611
|
}
|
|
591
612
|
for (const name of SEEDED_DIRS) {
|
|
592
|
-
if (isDirectory(
|
|
613
|
+
if (isDirectory(seededDirPath(resolved, name))) logInfo(`${name}/`)
|
|
593
614
|
else logWarn(`${name}/ missing. Run \`canon claude init\``)
|
|
594
615
|
}
|
|
595
616
|
|