@erclx/canon 4.20.1 → 4.22.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 +4 -4
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/claude-address-review/SKILL.md +6 -6
- package/claude/skills/claude-orchestrate/references/orchestrator-poll.md +2 -0
- package/claude/skills/claude-orchestrate/scripts/poll.sh +19 -1
- package/claude/skills/claude-pr-review/SKILL.md +1 -1
- package/claude/skills/git-ship/SKILL.md +1 -1
- package/docs/agents/commands.md +3 -0
- package/docs/agents/docs.md +11 -1
- package/docs/agents/index.md +1 -0
- package/docs/agents/pr-reads.md +73 -0
- package/docs/index.md +1 -7
- package/docs/target-projects.md +2 -2
- package/docs/{ai-workflow.md → workflow/ai-workflow.md} +6 -6
- package/docs/workflow/index.md +18 -0
- package/docs/{operating-model.md → workflow/operating-model.md} +12 -5
- package/docs/{visual-design-workflow.md → workflow/visual-design-workflow.md} +17 -17
- package/docs/{zshrc-aliases.md → workflow/zshrc-aliases.md} +3 -1
- package/package.json +1 -1
- package/scripts/docs/list.sh +21 -2
- package/src/cli.ts +1 -1
- package/src/commands/pr.ts +368 -4
- package/src/docs/read.ts +88 -25
- package/src/pr/checks.ts +83 -0
- package/src/pr/head.ts +108 -0
- package/src/targets/pulls.ts +7 -1
package/README.md
CHANGED
|
@@ -61,9 +61,9 @@ Each domain has a canonical source in this repo and a thin install or sync CLI o
|
|
|
61
61
|
|
|
62
62
|
Scaffolding your first project? Start with target projects, then the AI workflow loop. Everything else answers questions that arrive later.
|
|
63
63
|
|
|
64
|
-
- [AI workflow](docs/ai-workflow.md): feature-development loop inside a toolkit-managed project
|
|
65
|
-
- [Operating model](docs/operating-model.md): orchestrator, planner, and worker roles for building across parallel sessions
|
|
66
|
-
- [Visual design workflow](docs/visual-design-workflow.md): tiered guide for design and wireframe authoring
|
|
64
|
+
- [AI workflow](docs/workflow/ai-workflow.md): feature-development loop inside a toolkit-managed project
|
|
65
|
+
- [Operating model](docs/workflow/operating-model.md): orchestrator, planner, and worker roles for building across parallel sessions
|
|
66
|
+
- [Visual design workflow](docs/workflow/visual-design-workflow.md): tiered guide for design and wireframe authoring
|
|
67
67
|
- [Target projects](docs/target-projects.md): scaffold, add a domain later, sync upstream drift
|
|
68
68
|
- [Agents](docs/agents/index.md): CLI flags, exit codes, and JSON output shapes
|
|
69
69
|
- [Docs index](docs/index.md): every reference doc in this repo
|
|
@@ -106,7 +106,7 @@ bun install
|
|
|
106
106
|
bun run bootstrap
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
The script is idempotent, so re-run it after pulling upstream changes without duplicating anything. That also means it leaves an alias block you already have alone rather than refreshing it, so an alias added upstream needs the block deleted and the script re-run. It confirms the install by resolving `canon --help` on the last step. See [zshrc aliases](docs/zshrc-aliases.md) for what each alias does, how to pick up a new one, and how to opt out of the block.
|
|
109
|
+
The script is idempotent, so re-run it after pulling upstream changes without duplicating anything. That also means it leaves an alias block you already have alone rather than refreshing it, so an alias added upstream needs the block deleted and the script re-run. It confirms the install by resolving `canon --help` on the last step. See [zshrc aliases](docs/workflow/zshrc-aliases.md) for what each alias does, how to pick up a new one, and how to opt out of the block.
|
|
110
110
|
|
|
111
111
|
With the CLI linked, scaffold a fresh project.
|
|
112
112
|
|
|
@@ -27,10 +27,10 @@ For inline review comments, read them via `gh api` on the PR's review comments.
|
|
|
27
27
|
Also read the CI check status so the fixes cover failing checks, not only review comments:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
|
|
30
|
+
canon pr checks <number> --json
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Treat
|
|
33
|
+
Read the verdict off the record's `state` rather than off the exit. Treat `failing` as a finding to resolve alongside the review comments. A `pending` covers a tip whose runs have yet to conclude and a tip carrying no run at all, which the record separates on `matched`, and neither is a green to continue on. Fall back to `gh pr checks <number>` when no record comes back at all, which is a target whose CLI predates the verb.
|
|
34
34
|
|
|
35
35
|
## Step 2: address each finding
|
|
36
36
|
|
|
@@ -161,10 +161,10 @@ gh pr comment <number> --body-file .canon/tmp/address-review/reply-<number>.md
|
|
|
161
161
|
|
|
162
162
|
## Step 7: confirm resolution
|
|
163
163
|
|
|
164
|
-
After the follow-up push, watch CI on the PR. Poll
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
clear terminal state:
|
|
164
|
+
After the follow-up push, watch CI on the PR. Poll
|
|
165
|
+
`canon pr checks <number> --json` until the record's `state` leaves `pending`,
|
|
166
|
+
then read it. When every finding is addressed and the state is `passing`, post
|
|
167
|
+
one closing comment so the thread has a clear terminal state:
|
|
168
168
|
|
|
169
169
|
```bash
|
|
170
170
|
gh pr comment <number> --body "✅ All review findings addressed, CI green."
|
|
@@ -72,6 +72,8 @@ The report is also where the count in `## Parallelism` is legible. That threshol
|
|
|
72
72
|
|
|
73
73
|
The count reads low, and it errs in the direction that breaks the trigger. A review's `commit.oid` is stamped with the head at submission rather than with the commit the reviewer read, so an author pushing between the diff read and the post leaves the pass recorded against a commit it never saw, and `SEEN` then fires on a head still awaiting its first look at that delta. Measured on `#1299` on 2026-08-31, where a pass written against `5653721` landed stamped `a5ceb40` and the delta it skipped was a real fix. So a `SEEN` on a head you do not recognize is worth one `gh pr view --json reviews` before it is believed, and a wave past three is likelier to trip the fallback late than early.
|
|
74
74
|
|
|
75
|
+
The other side of that comparison used to lag as well, which made the two errors compound rather than cancel. `gh pr view --json headRefOid` answers from the pull request object and that object trails the branch ref by up to a minute after a push, reporting nothing about the trail, so a pass stamped ahead of the commit it read was compared against a head stamped behind the commit that exists. Two sessions were wrong off that field on 2026-09-01: a reviewing session posted a finding calling a pushed commit unpushed, and a worker fired a green claim it retracted on its own thread minutes later. The head now comes from `canon pr head`, which resolves the tip through `git ls-remote` and reports which commit each source names, and the object's head stays behind it as the fallback for a target whose CLI predates the verb. The review stamp is unchanged, so the paragraph above still holds on its own half.
|
|
76
|
+
|
|
75
77
|
## The watch beside it
|
|
76
78
|
|
|
77
79
|
`${CLAUDE_SKILL_DIR}/scripts/watch.sh` is a long-running loop rather than a scheduled prompt. It reads the open pull request list and the session roster together every sixty seconds and prints one line per new pull request, per worker whose status changed, and per worker that dropped out of the roster. Start it in the background and read what it emits. It writes nothing.
|
|
@@ -187,7 +187,25 @@ snapshot() {
|
|
|
187
187
|
continue
|
|
188
188
|
fi
|
|
189
189
|
|
|
190
|
-
head
|
|
190
|
+
# The tip is the authority for the head, not the pull request object. That
|
|
191
|
+
# object lags the ref by up to a minute after a push, so MOVED fired late
|
|
192
|
+
# and the merge-tree read below judged a commit the branch had already left
|
|
193
|
+
# behind. Read on the record's own field rather than on the exit, since an
|
|
194
|
+
# operator shell profile can wrap canon in a function that flattens it.
|
|
195
|
+
# The trailing assignment is load-bearing under `set -e` and `set -o
|
|
196
|
+
# pipefail` at the top of this file. Every refusal exits 1, and a refusal
|
|
197
|
+
# here is ordinary rather than exceptional, so an unguarded pipeline would
|
|
198
|
+
# end the whole poll on the first pull request whose branch was deleted.
|
|
199
|
+
head=$(canon pr head "$n" --json 2>/dev/null | jq -r '.tip // empty') || head=""
|
|
200
|
+
|
|
201
|
+
# The object's head is the fallback rather than the source. This script
|
|
202
|
+
# ships with the plugin and the verb ships with the CLI, so a target on an
|
|
203
|
+
# older binary reaches no `pr head` at all, and answering there with the
|
|
204
|
+
# lagging head is the behavior this poll already had.
|
|
205
|
+
if [ -z "$head" ]; then
|
|
206
|
+
head=$(jq -r '.headRefOid // empty' <<<"$payload")
|
|
207
|
+
fi
|
|
208
|
+
|
|
191
209
|
if [ -z "$head" ]; then
|
|
192
210
|
carry_forward "$n" "returned no head"
|
|
193
211
|
continue
|
|
@@ -29,7 +29,7 @@ reader scanning the thread finds the current verdict where the last one sat.
|
|
|
29
29
|
|
|
30
30
|
## Step 1: resolve the PR and read context
|
|
31
31
|
|
|
32
|
-
Resolve the PR: `gh pr view --json number,headRefName,headRefOid,title,body` for the current branch, or use a PR number the user names.
|
|
32
|
+
Resolve the PR: `gh pr view --json number,headRefName,headRefOid,title,body` for the current branch, or use a PR number the user names. Take `<headRefOid>` from `canon pr head <number> --json`, off that record's `tip`, and fall back to the `headRefOid` field above when no record comes back, which is a target whose CLI predates the verb. The first seven characters are `<short-sha>`, which names the body file in Step 4.
|
|
33
33
|
|
|
34
34
|
Read these in parallel from the project root, skipping any that do not exist:
|
|
35
35
|
|
|
@@ -30,7 +30,7 @@ Run `git diff --cached --name-only 2>/dev/null` to check for staged files. If ou
|
|
|
30
30
|
5. Invoke `canon:git-stage` to group staged changes and commit by concern
|
|
31
31
|
6. Invoke `canon:git-branch` to rename branch to match conventional format
|
|
32
32
|
7. Invoke `canon:git-pr` to push branch and open pull request
|
|
33
|
-
8. After the PR opens, watch CI. Poll `gh pr checks <number>`
|
|
33
|
+
8. After the PR opens, watch CI. Poll `canon pr checks <number> --json` until the record's `state` leaves `pending`, branching on that field rather than on the exit, and fall back to `gh pr checks <number>` when no record comes back at all, which is a target whose CLI predates the verb. On `passing`, continue. On `failing`, stop the sequence and report the failing check with its URL. Do not auto-fix. This step may output on failure, the one exception to the no-text-between-steps rule.
|
|
34
34
|
9. If step 1 wrote or updated at least one memory file, invoke `canon:claude-memory-review` scoped to those entries to propose fixes while session context is fresh. If the pen got nothing, skip this step.
|
|
35
35
|
|
|
36
36
|
A caller wrapping this sequence may act between step 7 and step 8, which is the one gap the order leaves open, since the pull request exists there and nothing has read its checks yet. `claude-autoship` marks the pull request draft in it. Nothing else may go there, and a caller that needs a step anywhere else in the sequence is asking for a change to this body rather than for a place to stand.
|
package/docs/agents/commands.md
CHANGED
|
@@ -71,6 +71,8 @@ Full help: `canon <command> --help`. Behavior notes for the install and sync ver
|
|
|
71
71
|
| `canon labels scan` | Fail a pull request whose title or body carries a phase label, a label a code span quotes, a gitignored record path, or a session link (`--event`, `--json`) |
|
|
72
72
|
| `canon autoship classify` | Decide whether a changed set needs the review pass, naming the file and the test that decided it (`--json`) |
|
|
73
73
|
| `canon pr key-changes` | Compare the files a pull request body's Key Changes names against its own diff, in both directions (`--body`, `--base`, `--json`) |
|
|
74
|
+
| `canon pr head` | Compare the head a pull request object reports against the branch tip the remote carries, naming both shas (`--root`, `--json`) |
|
|
75
|
+
| `canon pr checks` | Report the check runs belonging to the branch tip, reading pending for a tip carrying none rather than clean (`--root`, `--json`) |
|
|
74
76
|
| `canon repo metadata propose` | Compare a description, homepage, and topic set computed from the README and `package.json` against what the remote carries, writing nothing (`--root`, `--json`) |
|
|
75
77
|
| `canon repo metadata apply` | Write an explicitly supplied description, homepage, or topic set to the remote through `gh repo edit` (`--description`, `--homepage`, `--topics`, `--root`, `--json`) |
|
|
76
78
|
| `canon census [path]` | Report tracked file count, a breakdown by extension, and a line total that skips whatever reads as binary (`--json`) |
|
|
@@ -132,6 +134,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
|
|
|
132
134
|
| `labels` | `audit` |
|
|
133
135
|
| `migrate` | `rename`, `records` |
|
|
134
136
|
| `autoship` | `classify` |
|
|
137
|
+
| `pr` | `key-changes`, `head`, `checks` |
|
|
135
138
|
| `audits` | `run`, `list` |
|
|
136
139
|
| `gate` | `run` |
|
|
137
140
|
|
package/docs/agents/docs.md
CHANGED
|
@@ -10,7 +10,17 @@ description: How canon docs resolves the toolkit's own reference surface from an
|
|
|
10
10
|
- `canon docs list [--json]` lists the downstream catalog: the consumer-facing `docs/` surface plus per-domain narrative from `.claude/context/` when that root is present. Toolkit-internal context entries (`ci`, `development`, `sandbox`) are dropped. From a registry install the context section is absent rather than empty.
|
|
11
11
|
- `canon docs <topic>` prints one doc to stdout, resolved by exact name from `docs/` first, then `.claude/context/`. Any doc the install carries is reachable by name, including the toolkit-internal topics the list omits.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## How a name resolves
|
|
14
|
+
|
|
15
|
+
A domain too large for one file splits into `<domain>/` with a generated `index.md`, and both verbs name it by the folder. `canon docs <domain>` prints that index, which is the catalog routing to the sub-area files, and the listing describes it from the index's `subtitle` where a sibling file supplies `description`. A folder carrying no `index.md` is absent from both, since a catalog is what makes the sub-areas reachable, and so are the files inside it.
|
|
16
|
+
|
|
17
|
+
A sub-area file resolves by its bare name too, so `canon docs operating-model` reaches `docs/workflow/operating-model.md`. Three spellings are tried in order, being a sibling file, a folder of that name, then a sub-area file one level down, and each spelling is tried across both roots before the next one runs. A sibling file therefore wins over a folder of the same name, and both win over a sub-area file. Reading the folder last is what keeps the sub-area spelling from changing any name that resolved before it existed.
|
|
18
|
+
|
|
19
|
+
A bare name carried by two folders resolves to neither. Eight context folders hold an `overview.md`, so `canon docs overview` names the available topics and exits 1 rather than answering with whichever folder sorts first.
|
|
20
|
+
|
|
21
|
+
`canon docs list` stops at the folder where `canon docs <topic>` goes on to name each file inside it. The listing is the downstream catalog rather than the index of what a name reaches, so a sub-area file appears there only where it declares a target-facing `category` of its own, and no sub-area file of the context root appears at all. A name that resolves and does not list is the divergence the toolkit-internal topics already carry.
|
|
22
|
+
|
|
23
|
+
## Output
|
|
14
24
|
|
|
15
25
|
Data prints to stdout and the frame to stderr, so `canon docs <topic> > out.md` captures clean markdown. With no topic and no verb, `canon docs` runs `list`. An unknown topic names the available topics on stderr and exits 1.
|
|
16
26
|
|
package/docs/agents/index.md
CHANGED
|
@@ -28,6 +28,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
28
28
|
- [Markdown audit](markdown-audit.md): Running the audit over any markdown path, where its bans and checkpoints are read from, what each check reports, and why the ban half gates while the structural half reports
|
|
29
29
|
- [Output shape](output-shape.md): Two framed shapes every command renders into, how JSON and --names modes keep stdout clean, and the exit discipline that lets piped output drain
|
|
30
30
|
- [Overview](overview.md): What this folder covers, the invocation rules every command inherits, and where domain behavior is documented instead
|
|
31
|
+
- [Head-sensitive pull request reads](pr-reads.md): Resolving a branch tip from the remote rather than from the pull request object, reading check runs keyed on that tip, why an empty run list is not a pass, the refusal reasons each verb names, and what the remote read costs
|
|
31
32
|
- [Records](records.md): The two roots a record folder resolves at, validating the session records and the standards corpus, the per-kind checks, the refusal reasons, migrating a record a frontmatter change orphaned, reading each folder's size and growth, backing the folders to a private remote, and which root each kind defaults to
|
|
32
33
|
- [Restated instructions](restated.md): Counting the instructions the always-loaded file and every path-scoped rule share with the seed, the shipped skill bodies, and each other, how a match is decided, the three classes, which surface a later edit starts from, and why the sweep reports rather than gates
|
|
33
34
|
- [Review classification](review-classification.md): Deciding whether a changed set needs the review pass, the two tests it runs, why an empty set refuses rather than skipping, and the written fallback a target on an older binary falls back to
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Head-sensitive pull request reads
|
|
3
|
+
description: Resolving a branch tip from the remote rather than from the pull request object, reading check runs keyed on that tip, why an empty run list is not a pass, the refusal reasons each verb names, and what the remote read costs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Head-sensitive pull request reads
|
|
7
|
+
|
|
8
|
+
`canon pr head` and `canon pr checks` answer about a commit. Both resolve the branch tip from the remote with `git ls-remote` and report what they found for that sha, rather than taking the pull request object's word for which commit the branch is on.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
canon pr head
|
|
12
|
+
canon pr head 1341 --json
|
|
13
|
+
canon pr checks
|
|
14
|
+
canon pr checks 1341 --json
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## The pull request object is not the authority for a head
|
|
18
|
+
|
|
19
|
+
`gh pr view --json headRefOid` reads a field on the pull request object. That object trails the branch ref by up to a minute after a push and carries nothing saying how far behind it is, so a session that keys a read on it is describing whichever commit GitHub last folded into the object.
|
|
20
|
+
|
|
21
|
+
Two failures on 2026-09-01 came off that one field. A reviewing session posted a finding calling a pushed commit unpushed. A worker fired a green claim and retracted it on its own thread minutes later. Neither session did anything wrong with the value it was handed. The value was stale and said so nowhere.
|
|
22
|
+
|
|
23
|
+
The remote ref carries no such lag. `git ls-remote --heads origin <branch>` asks the remote itself rather than a tracking ref, which is only as current as the last fetch, and the push worth catching is the one this process never saw.
|
|
24
|
+
|
|
25
|
+
The argument is stated here once. The shipped skill bodies call the verb rather than repeating it, because a sentence telling a session to compare two shas is a sentence a session can decide it already followed.
|
|
26
|
+
|
|
27
|
+
## What each verb answers
|
|
28
|
+
|
|
29
|
+
`canon pr head` reports `fresh` when the object and the remote name the same commit and `stale` when they disagree, with both shas on the record. The tip is the authority and the object's head is the claim being checked against it.
|
|
30
|
+
|
|
31
|
+
`canon pr checks` reads `repos/{owner}/{repo}/commits/<tip>/check-runs` and collapses it to `passing`, `failing`, or `pending`. A failure outranks a run still going, since a run in flight cannot clear a job that already failed.
|
|
32
|
+
|
|
33
|
+
`gh pr checks` cannot be made to answer this question at all, which is the argument for the move rather than a preference between two working commands. Its `--json` field set is `bucket, completedAt, description, event, link, name, startedAt, state, workflow`, with no sha among them, so a caller cannot even learn which commit its answer describes.
|
|
34
|
+
|
|
35
|
+
## An empty run list is not a pass
|
|
36
|
+
|
|
37
|
+
Keying the query on a sha is necessary and not sufficient. The endpoint answered with `total_count` 2 and an empty row list during a measured window on 2026-09-02, so a reader that finds no run for the tip and reports `passing` reproduces the false green behind a better query.
|
|
38
|
+
|
|
39
|
+
Both empty cases report `pending` instead: a tip carrying no run yet, and a listing whose rows all belong to some other commit. The record separates them, since `matched` counts the runs belonging to the tip and `foreign` counts the rest, and a caller that wants to tell "not started" from "still going" reads those two numbers rather than the state alone.
|
|
40
|
+
|
|
41
|
+
`matched` counts runs and not distinct checks, which is where it parts company with the list `gh pr checks` prints. A workflow that fires twice on one commit lands two runs under one name, so a pull request whose body was edited after the push reads 3 against that command's 2. Measured on 2026-09-02 against a commit whose phase-label workflow ran on the push and again on a later body edit. Read a `matched` above the check count as that, rather than as the verb disagreeing with the command.
|
|
42
|
+
|
|
43
|
+
A listing carrying even one foreign run reports `pending` whatever the matching half says. A set that describes another commit says nothing about this one, so answering off the rows that happen to match would put a verdict on a set already known to be incomplete.
|
|
44
|
+
|
|
45
|
+
A count above the rows returned reports `pending` for the same reason. The query asks for 100 rows against the endpoint's default of 30, and a commit carrying more than that comes back short, so the verb reports the tip as unread rather than collapsing the page it happens to hold. `reported` against `matched` and `foreign` is where a reader sees which of the three shapes produced the answer.
|
|
46
|
+
|
|
47
|
+
## Reading the answer
|
|
48
|
+
|
|
49
|
+
Branch on the record rather than on the exit. Both verbs exit 0 whenever they resolved a tip, whatever the verdict, and 1 only when they refused. An operator shell profile can wrap `canon` in a function whose status comes from a trailing command, which flattens every non-zero exit to 0, so the exit is not a channel either verb puts a verdict on. `gh pr checks` reserving exit 8 for pending is the pattern being replaced rather than one to copy.
|
|
50
|
+
|
|
51
|
+
Each refusal names a different repair:
|
|
52
|
+
|
|
53
|
+
| Reason | What it means |
|
|
54
|
+
| ------------------ | ------------------------------------------------------------------------------------------ |
|
|
55
|
+
| `gh-missing` | `gh` is not on the path, so no pull request resolved |
|
|
56
|
+
| `gh-failed` | `gh` could not answer for this branch, so name a number instead |
|
|
57
|
+
| `no-branch` | The pull request carries no head branch name, so no ref could be read |
|
|
58
|
+
| `unresolvable-ref` | The remote read failed, which is not the same answer as an absent branch |
|
|
59
|
+
| `no-remote-branch` | The remote carries no branch by that name, so there is no tip to compare against |
|
|
60
|
+
| `no-object-head` | The pull request object reported no head, so `head` has nothing to compare the tip against |
|
|
61
|
+
| `runs-unreadable` | The check runs for the tip could not be read, which is unread rather than none |
|
|
62
|
+
|
|
63
|
+
A failed remote read and a branch the remote does not carry stay apart rather than collapsing into one reason. Reading the first as the second would report a network refusal as a deleted branch, and the repairs have nothing in common.
|
|
64
|
+
|
|
65
|
+
## What it costs
|
|
66
|
+
|
|
67
|
+
One remote round trip per call, sampled here at 0.41s, 0.55s, and 0.67s on 2026-09-01 and 2026-09-02, against 0.001s for the local ref read. The spread is the network rather than the command, so read it as roughly half a second and not as a figure to compare a later reading against. Every caller pointed at these verbs already spends a `gh` round trip on the same line, so the added cost lands on a path that was never local to begin with.
|
|
68
|
+
|
|
69
|
+
One head-sensitive read is left on the object deliberately. `canon targets pulls` reads `statusCheckRollup` for every open pull request across every target, where resolving a tip per row would cost one remote read per pull request across a dozen projects, against a surface that reports a listing rather than gating a push.
|
|
70
|
+
|
|
71
|
+
The orchestrator poll spends that same read per open pull request and repeats it on a three-minute timer, which makes it the heaviest caller here rather than an exception to the paragraph above. Six open pull requests is around 120 remote reads an hour. What separates the two cases is what each reading decides rather than what it costs. The poll's head fires the review trigger, so a stale one sends a pass at a commit nobody read or withholds one that is owed. The listing decides nothing, so the same spend buys a fresher column in a report and no correctness at all.
|
|
72
|
+
|
|
73
|
+
`canon pr key-changes` also stays on the object, for a different reason. It reads the body, the file list, and `headRefOid` in one call on purpose, so the three describe one commit. That is a consistency requirement rather than a freshness one, and keying its head elsewhere would break it.
|
package/docs/index.md
CHANGED
|
@@ -9,15 +9,9 @@ One-line reference for each doc in this folder.
|
|
|
9
9
|
|
|
10
10
|
## Agent surface
|
|
11
11
|
|
|
12
|
-
- [AI workflow](ai-workflow.md): Overarching AI workflow across domains
|
|
13
12
|
- [Target projects](target-projects.md): Scaffold, add domains later, and sync upstream drift in a toolkit-managed project
|
|
14
13
|
|
|
15
|
-
## Workflow
|
|
16
|
-
|
|
17
|
-
- [Operating model](operating-model.md): Orchestrator, planner, and worker roles for building across parallel sessions
|
|
18
|
-
- [Visual design workflow](visual-design-workflow.md): Tiered guide for design and wireframe authoring with Claude Code
|
|
19
|
-
- [Zshrc aliases for Claude Code](zshrc-aliases.md): Shell aliases that shorten common Claude Code invocations
|
|
20
|
-
|
|
21
14
|
## Sub-catalogs
|
|
22
15
|
|
|
23
16
|
- [Agents](agents/index.md): CLI catalog and invocation rules for agents, split by command domain. Start with overview.
|
|
17
|
+
- [Workflow](workflow/index.md): How a person and their agents run a feature, from the design tier through the parallel-session loop to the shell that launches them.
|
package/docs/target-projects.md
CHANGED
|
@@ -71,7 +71,7 @@ Scaffold installs tooling and seeds. It does not fill the planning docs or the d
|
|
|
71
71
|
1. Fill `.claude/REQUIREMENTS.md` and `.claude/ARCHITECTURE.md`. The seed provides the files, the scope and decisions are yours to write.
|
|
72
72
|
2. For a UI project, invoke `canon:claude-design-extract` to draft `.claude/DESIGN.md`. With no UI code yet it takes the greenfield path and proposes tokens from the requirements and a `## Personality` section. Skip for non-UI projects.
|
|
73
73
|
3. Optionally invoke `canon:claude-diagram` to draft entries under `.canon/diagrams/` from the architecture and the requirements. One file per diagram kind, so a later refresh of one kind leaves the others untouched. It renders each diagram it writes to verify the layout, which downloads the Mermaid CLI on first use and takes about 15 seconds.
|
|
74
|
-
4. Start the feature loop. See [AI workflow](ai-workflow.md) for the per-feature sequence.
|
|
74
|
+
4. Start the feature loop. See [AI workflow](workflow/ai-workflow.md) for the per-feature sequence.
|
|
75
75
|
|
|
76
76
|
A machine without a renderer still gets the diagrams and is told which check was skipped.
|
|
77
77
|
|
|
@@ -286,6 +286,6 @@ Sync also refuses a target whose working tree is dirty, so commit or stash befor
|
|
|
286
286
|
## Related
|
|
287
287
|
|
|
288
288
|
- [agents](agents/index.md): CLI flags, exit codes, and JSON output shapes
|
|
289
|
-
- [AI workflow](ai-workflow.md): feature-development loop inside a toolkit-managed project
|
|
289
|
+
- [AI workflow](workflow/ai-workflow.md): feature-development loop inside a toolkit-managed project
|
|
290
290
|
- [tooling](../.claude/context/tooling.md), [governance](../.claude/context/governance/index.md), [claude plugin](../.claude/context/claude-plugin/index.md), [indexes](../.claude/context/indexes.md), [snippets](../.claude/context/snippets.md), [standards](../.claude/context/standards/index.md): per-domain mechanics
|
|
291
291
|
- [sandbox](../.claude/context/sandbox/index.md): scenario catalog for verifying domain flows
|
|
@@ -33,7 +33,7 @@ Project docs split across two roots at the project root, on one mechanical line:
|
|
|
33
33
|
|
|
34
34
|
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.
|
|
35
35
|
|
|
36
|
-
Three tiers of context load with different cost: always-loaded (root `CLAUDE.md`, `.claude/REQUIREMENTS.md`, `.claude/ARCHITECTURE.md`), path-scoped lazy (`.claude/rules/<scope>.md` with `paths:` glob), and on-demand lookup (`.claude/context/<domain>.md`, or `.claude/context/<domain>/` once a domain outgrows one file, discovered via `.claude/context/index.md`). See [the context model](
|
|
36
|
+
Three tiers of context load with different cost: always-loaded (root `CLAUDE.md`, `.claude/REQUIREMENTS.md`, `.claude/ARCHITECTURE.md`), path-scoped lazy (`.claude/rules/<scope>.md` with `paths:` glob), and on-demand lookup (`.claude/context/<domain>.md`, or `.claude/context/<domain>/` once a domain outgrows one file, discovered via `.claude/context/index.md`). See [the context model](../../.claude/context/context-model.md) for the full picture.
|
|
37
37
|
|
|
38
38
|
Run `canon init` to seed the `.claude/` directory, a root `CLAUDE.md` file, and `.claude/rules/` in one pass. `canon init` chains claude init and governance install. Claude Code auto-loads every file in `.claude/rules/` at session start, applying always-on rules unconditionally and path-scoped rules to files matching their `paths:` glob.
|
|
39
39
|
|
|
@@ -41,7 +41,7 @@ Run `canon init` to seed the `.claude/` directory, a root `CLAUDE.md` file, and
|
|
|
41
41
|
|
|
42
42
|
### Bootstrap a new project
|
|
43
43
|
|
|
44
|
-
See [target projects](target-projects.md) for the scaffold decision, core domains and skips, and the full lifecycle across scaffold, add-a-domain-later, and upstream sync.
|
|
44
|
+
See [target projects](../target-projects.md) for the scaffold decision, core domains and skips, and the full lifecycle across scaffold, add-a-domain-later, and upstream sync.
|
|
45
45
|
|
|
46
46
|
### New feature
|
|
47
47
|
|
|
@@ -94,7 +94,7 @@ Before a handoff, the orchestrator checks the plan against the tree rather than
|
|
|
94
94
|
|
|
95
95
|
A constraint naming a track in flight carries the same problem past the handoff, so the block opens with the commit it was measured against. A worker re-tests before honoring one, fetching and then logging that commit against `origin/main` over the paths the constraint names, and any merge there means the track landed and the constraint is dead. An unstamped block reads as unverified rather than as live, which covers every plan written before the rule.
|
|
96
96
|
|
|
97
|
-
`.canon/plans/`, `.canon/review/`, and `.canon/memory/` all resolve at the main worktree root, so artifacts created in any session are visible from any sibling worktree. A session inside a worktree reads them directly, since the file-editing tools refuse a main-root path but `Read` resolves normally. It writes a whole file through the shell and makes a change inside an existing file through a `canon` verb, which resolves the main root in-process. See [Claude Code and git worktrees](
|
|
97
|
+
`.canon/plans/`, `.canon/review/`, and `.canon/memory/` all resolve at the main worktree root, so artifacts created in any session are visible from any sibling worktree. A session inside a worktree reads them directly, since the file-editing tools refuse a main-root path but `Read` resolves normally. It writes a whole file through the shell and makes a change inside an existing file through a `canon` verb, which resolves the main root in-process. See [Claude Code and git worktrees](../../wiki/claude/claude-worktrees.md) for the full rule and the domain-level fan-out guidance.
|
|
98
98
|
|
|
99
99
|
The plan's shape is fixed by `standards/plan.md`: the section list, the filename, the lifecycle, and the contract its questions keep. Every question carries a `- Suggested:` line and an empty `- Answer:` slot, and a blank answer accepts the suggestion at execution time. That default is what makes a plan decision-ready in one pass, and it is the opposite of the contract an intake folder keeps, where an empty slot means nobody reached the item.
|
|
100
100
|
|
|
@@ -104,7 +104,7 @@ An execution that picks other than the suggestion rewrites the `- Suggested:` li
|
|
|
104
104
|
|
|
105
105
|
`canon records push` carries these folders off the disk they live on, and `canon records pull` brings them back. Nine of them are backed: `diagrams`, `groundwork`, `intake`, `memory`, `plans`, `proposals`, `review`, `tasks`, and `teach`, each carrying whatever it has archived inside it. The history lives in a second git directory at `.canon/.records.git` with `.canon/` as its work tree, so every path a task file cites stays where it is.
|
|
106
106
|
|
|
107
|
-
A person points it at a private repository once and both verbs refuse until they have, and `push` refuses when that origin is also a remote of the project, since the payload is the memory pen and the groundwork trails. `.husky/post-merge` runs the push after its archive loop, on every merge rather than only on one that closed a task. See [records](agents/records.md) for the refusal table.
|
|
107
|
+
A person points it at a private repository once and both verbs refuse until they have, and `push` refuses when that origin is also a remote of the project, since the payload is the memory pen and the groundwork trails. `.husky/post-merge` runs the push after its archive loop, on every merge rather than only on one that closed a task. See [records](../agents/records.md) for the refusal table.
|
|
108
108
|
|
|
109
109
|
`canon records size` reports what each of these folders holds, heaviest first, along with `.canon/tmp`. Each row carries the file count, the bytes, how many files were written in the last 7 and 30 days, and the dates of the least and most recently written one. Nothing fails on a number, because a record folder has no correct size. What the verb replaces is a reading somebody had to remember to take: the memory pen went from 44 entries to 236 between two counts made by hand a fortnight apart, and nothing reported the rate in between.
|
|
110
110
|
|
|
@@ -151,7 +151,7 @@ Markdown under one states what an agent does, so a branch touching it reaches re
|
|
|
151
151
|
|
|
152
152
|
An empty changed-file list stops the chain rather than counting as prose-only. The filename test passes vacuously on an empty set, which routed a branch past review instead of through it.
|
|
153
153
|
|
|
154
|
-
`canon autoship classify` answers that decision now, and the chain branches on the record it returns rather than on a session applying the list above. Three runs read past the list while it was prose, the last of them a driven arm that staged a file the list names and shipped a draft pull request with no review. The verb takes the names the chain already computed, so no second diff baseline resolves, and it names the file and the test that decided. [Review classification](agents/review-classification.md) carries the record shape and the exit codes.
|
|
154
|
+
`canon autoship classify` answers that decision now, and the chain branches on the record it returns rather than on a session applying the list above. Three runs read past the list while it was prose, the last of them a driven arm that staged a file the list names and shipped a draft pull request with no review. The verb takes the names the chain already computed, so no second diff baseline resolves, and it names the file and the test that decided. [Review classification](../agents/review-classification.md) carries the record shape and the exit codes.
|
|
155
155
|
|
|
156
156
|
The list stays written in the skill body as the fallback for a target whose installed CLI predates the verb, since the two ship at different speeds. That fallback is never a skip: failing open is the defect the verb closes, so an absent subcommand routes to review rather than past it.
|
|
157
157
|
|
|
@@ -187,7 +187,7 @@ Before the first feature session on a UI-heavy project, pick a design tier. The
|
|
|
187
187
|
|
|
188
188
|
## Skills
|
|
189
189
|
|
|
190
|
-
Groups run in the order a project meets them, so a reader at a known point scans to that group and reads across. The set reconciles the scenarios above with the lifecycle [target projects](target-projects.md) describes, rather than inventing a third vocabulary beside those two, so a group name matches neither source exactly and every moment either one names has a group. Each row says when to reach for the skill. What it does is the skill's own description.
|
|
190
|
+
Groups run in the order a project meets them, so a reader at a known point scans to that group and reads across. The set reconciles the scenarios above with the lifecycle [target projects](../target-projects.md) describes, rather than inventing a third vocabulary beside those two, so a group name matches neither source exactly and every moment either one names has a group. Each row says when to reach for the skill. What it does is the skill's own description.
|
|
191
191
|
|
|
192
192
|
This section is the corpus the coverage claim is measured against: every name `canon claude skills list --names` reports takes exactly one row here. A skill serving two moments sits at the earlier one, and mentions elsewhere in this file are prose rather than routing.
|
|
193
193
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Workflow
|
|
3
|
+
subtitle: How a person and their agents run a feature, from the design tier through the parallel-session loop to the shell that launches them.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow
|
|
7
|
+
|
|
8
|
+
How a person and their agents run a feature, from the design tier through the parallel-session loop to the shell that launches them.
|
|
9
|
+
|
|
10
|
+
## Agent surface
|
|
11
|
+
|
|
12
|
+
- [AI workflow](ai-workflow.md): Overarching AI workflow across domains
|
|
13
|
+
|
|
14
|
+
## Workflow
|
|
15
|
+
|
|
16
|
+
- [Operating model](operating-model.md): Orchestrator, planner, and worker roles for building across parallel sessions
|
|
17
|
+
- [Visual design workflow](visual-design-workflow.md): Tiered guide for design and wireframe authoring with Claude Code
|
|
18
|
+
- [Zshrc aliases for Claude Code](zshrc-aliases.md): Shell aliases that shorten common Claude Code invocations
|
|
@@ -12,7 +12,7 @@ cross-feature call and reviews. Planning runs there or in a session of its own.
|
|
|
12
12
|
Cold worker sessions build. The human launches workers and merges.
|
|
13
13
|
|
|
14
14
|
This page covers the roles and the loop. For the worktree mechanism (isolation, merge
|
|
15
|
-
order, port collisions), see [Claude Code and git worktrees](
|
|
15
|
+
order, port collisions), see [Claude Code and git worktrees](../../wiki/claude/claude-worktrees.md).
|
|
16
16
|
|
|
17
17
|
## Three roles
|
|
18
18
|
|
|
@@ -99,7 +99,7 @@ becomes the commit message and the record on the trunk once the branch is gone.
|
|
|
99
99
|
`canon pr key-changes` compares the paths the body's Key Changes claims against
|
|
100
100
|
its own changed-file list, and a claim the diff does not carry is a finding on
|
|
101
101
|
the body rather than on a file. See
|
|
102
|
-
[Key Changes bijection](agents/key-changes.md).
|
|
102
|
+
[Key Changes bijection](../agents/key-changes.md).
|
|
103
103
|
|
|
104
104
|
## The review channel
|
|
105
105
|
|
|
@@ -108,6 +108,13 @@ Findings travel on the PR. `claude-pr-review` posts them there.
|
|
|
108
108
|
threads, and pushes a follow-up. `claude-pr-review` then runs again, reading only
|
|
109
109
|
what the follow-up added.
|
|
110
110
|
|
|
111
|
+
Both halves of that loop key on a commit rather than on the pull request object,
|
|
112
|
+
which trails the branch ref by up to a minute after a push and says nothing
|
|
113
|
+
about the trail. `canon pr head` resolves the tip the review pass scopes its
|
|
114
|
+
delta against, and `canon pr checks` reports the runs belonging to that tip, so a
|
|
115
|
+
follow-up push cannot be read as green off the predecessor's completed run. See
|
|
116
|
+
[Head-sensitive pull request reads](../agents/pr-reads.md).
|
|
117
|
+
|
|
111
118
|
What the session channel carries is the handback instruction and the worker's
|
|
112
119
|
reply to it, which is a notification layer over a record that stays on the PR. A
|
|
113
120
|
reply that changes an outcome, such as a worker naming the plan question that
|
|
@@ -241,11 +248,11 @@ A dev server, an end-to-end run, and a screenshot run alongside each other on a
|
|
|
241
248
|
web stack, since every worktree derives its own port. Singleton resources (one
|
|
242
249
|
local model server, one GPU) still serialize, as does any port a stack fixes by
|
|
243
250
|
hand. See
|
|
244
|
-
[Claude Code and git worktrees](
|
|
251
|
+
[Claude Code and git worktrees](../../wiki/claude/claude-worktrees.md) for merge order and the
|
|
245
252
|
port-collision detail.
|
|
246
253
|
|
|
247
254
|
## Related
|
|
248
255
|
|
|
249
|
-
- [Claude Code and git worktrees](
|
|
250
|
-
- [Claude Code subagents](
|
|
256
|
+
- [Claude Code and git worktrees](../../wiki/claude/claude-worktrees.md) for the isolation and fan-out mechanics
|
|
257
|
+
- [Claude Code subagents](../../wiki/claude/claude-subagents.md) for in-session parallelism without worktrees
|
|
251
258
|
- `.claude/context/claude-plugin/skill-strategy.md` for how the skills in the loop are categorized
|
|
@@ -8,9 +8,9 @@ category: Workflow
|
|
|
8
8
|
|
|
9
9
|
Three tiers cover the range from prose-only design docs to a fully graphical design source of truth. Pick one per project based on how UI-heavy the work is, whether stakeholders review visuals, and whether a designer is involved. Tiers stack, so moving up does not invalidate work done at a lower tier.
|
|
10
10
|
|
|
11
|
-
The tier framework sits alongside [Claude Design](
|
|
11
|
+
The tier framework sits alongside [Claude Design](../../wiki/claude/claude-design.md), [visual wireframes](../../wiki/tools/visual-wireframes.md), [community skills and plugins](../../wiki/tools/community-skills.md), and [community MCP servers](../../wiki/tools/community-mcp-servers.md). Those pages catalog the tooling. This page decides when to reach for what.
|
|
12
12
|
|
|
13
|
-
Two tools anchor tier 1 and tier 2. [Stitch](
|
|
13
|
+
Two tools anchor tier 1 and tier 2. [Stitch](../../wiki/tools/stitch.md) is the agent-addressable default through its MCP server at `stitch.googleapis.com/mcp`, with a free tier of 400 daily credits that covers daily iteration. [Claude Design](../../wiki/claude/claude-design.md), released 2026-04-17 and priced inside Claude subscriptions, is the ceiling tool reserved for codebase extraction and the richly annotated handoff bundle. Each covers a different job, they are not swappable.
|
|
14
14
|
|
|
15
15
|
## Tier 0: prose only
|
|
16
16
|
|
|
@@ -31,7 +31,7 @@ A cell no source anchors ends in `? verify`, and the preview shows that marker b
|
|
|
31
31
|
### Tools
|
|
32
32
|
|
|
33
33
|
- None beyond Claude Code itself
|
|
34
|
-
- Playwright CLI optional for verifying form submissions and interactive surfaces. See [`claude-ui-test`](
|
|
34
|
+
- Playwright CLI optional for verifying form submissions and interactive surfaces. See [`claude-ui-test`](../../claude/skills/claude-ui-test/SKILL.md).
|
|
35
35
|
|
|
36
36
|
### Skills
|
|
37
37
|
|
|
@@ -66,16 +66,16 @@ Impeccable, if installed, keeps its own root `DESIGN.md` and `PRODUCT.md` in the
|
|
|
66
66
|
|
|
67
67
|
### Tools
|
|
68
68
|
|
|
69
|
-
- Stitch via MCP at `stitch.googleapis.com/mcp`. Default pick for agent-driven visual generation. Free tier of 400 daily credits. See [Stitch](
|
|
70
|
-
- Excalidraw canvas server on localhost plus the `yctimlin/mcp_excalidraw` MCP shim, for projects that need an agent to draw, read back, and revise a canvas. See [visual wireframes](
|
|
71
|
-
- Playwright MCP for browser-side verification. See [Playwright](
|
|
72
|
-
- Chrome DevTools MCP for live frontend debugging. See [Chrome DevTools](
|
|
73
|
-
- Claude Design as the ceiling option for codebase extraction or polished handoff bundles. See [Claude Design](
|
|
69
|
+
- Stitch via MCP at `stitch.googleapis.com/mcp`. Default pick for agent-driven visual generation. Free tier of 400 daily credits. See [Stitch](../../wiki/tools/stitch.md).
|
|
70
|
+
- Excalidraw canvas server on localhost plus the `yctimlin/mcp_excalidraw` MCP shim, for projects that need an agent to draw, read back, and revise a canvas. See [visual wireframes](../../wiki/tools/visual-wireframes.md) for setup and footguns.
|
|
71
|
+
- Playwright MCP for browser-side verification. See [Playwright](../../wiki/tools/community-mcp-servers.md#playwright-microsoft).
|
|
72
|
+
- Chrome DevTools MCP for live frontend debugging. See [Chrome DevTools](../../wiki/tools/community-mcp-servers.md#chrome-devtools-google).
|
|
73
|
+
- Claude Design as the ceiling option for codebase extraction or polished handoff bundles. See [Claude Design](../../wiki/claude/claude-design.md).
|
|
74
74
|
|
|
75
75
|
### Skills
|
|
76
76
|
|
|
77
77
|
- Everything from tier 0
|
|
78
|
-
- A frontend design skill to steer visual quality. Pick one of [Impeccable](
|
|
78
|
+
- A frontend design skill to steer visual quality. Pick one of [Impeccable](../../wiki/tools/community-skills.md#pbakausimpeccable), [UI/UX Pro Max](../../wiki/tools/community-skills.md#nextlevelbuilderui-ux-pro-max-skill), or Anthropic's `frontend-design` plugin. Impeccable is the strongest default because of its curated anti-patterns.
|
|
79
79
|
|
|
80
80
|
### When to pick
|
|
81
81
|
|
|
@@ -106,9 +106,9 @@ Design happens in a graphical tool. `.claude/DESIGN.md` either regenerates from
|
|
|
106
106
|
|
|
107
107
|
### Tools
|
|
108
108
|
|
|
109
|
-
- Figma desktop app with the [Figma Dev Mode MCP](
|
|
110
|
-
- Claude Design with its Claude Code handoff bundle for teams without an existing Figma investment and for solo founders or PMs driving design themselves. One-way handoff, no bidirectional sync. See [Claude Design](
|
|
111
|
-
- Stitch via MCP as a low-cost complement to either, used for bulk screen generation driven by Claude Code. See [Stitch](
|
|
109
|
+
- Figma desktop app with the [Figma Dev Mode MCP](../../wiki/tools/community-skills.md#figma-mcp-and-code-to-canvas) for teams with a dedicated designer already on Figma. Bidirectional sync and Code to Canvas capture.
|
|
110
|
+
- Claude Design with its Claude Code handoff bundle for teams without an existing Figma investment and for solo founders or PMs driving design themselves. One-way handoff, no bidirectional sync. See [Claude Design](../../wiki/claude/claude-design.md).
|
|
111
|
+
- Stitch via MCP as a low-cost complement to either, used for bulk screen generation driven by Claude Code. See [Stitch](../../wiki/tools/stitch.md).
|
|
112
112
|
- Playwright and Chrome DevTools MCPs as in tier 1
|
|
113
113
|
|
|
114
114
|
### Skills
|
|
@@ -145,9 +145,9 @@ Resist over-tiering early. Moving up is cheap because tiers stack. Moving down m
|
|
|
145
145
|
|
|
146
146
|
## References
|
|
147
147
|
|
|
148
|
-
- [Stitch](
|
|
149
|
-
- [Claude Design](
|
|
148
|
+
- [Stitch](../../wiki/tools/stitch.md): Gemini-powered design product with the MCP server that anchors tier 1
|
|
149
|
+
- [Claude Design](../../wiki/claude/claude-design.md): first-party hosted design product and handoff bundle
|
|
150
150
|
- `.claude/context/claude-plugin/skill-strategy.md`: how to decide between workflow and domain-knowledge skills
|
|
151
|
-
- [Visual wireframes](
|
|
152
|
-
- [Community skills and plugins](
|
|
153
|
-
- [Community MCP servers](
|
|
151
|
+
- [Visual wireframes](../../wiki/tools/visual-wireframes.md): Excalidraw research and setup for the tier 1 wireframe companion
|
|
152
|
+
- [Community skills and plugins](../../wiki/tools/community-skills.md): catalog of frontend design skills and integrations
|
|
153
|
+
- [Community MCP servers](../../wiki/tools/community-mcp-servers.md): catalog of MCPs referenced across all tiers
|
|
@@ -38,6 +38,8 @@ The block sits after any `PATH` mutations and the `claude` CLI install. Zsh expa
|
|
|
38
38
|
|
|
39
39
|
To opt out, delete the block between the two markers. Bootstrap re-adds it on the next run, so skip that step by running `bun install` and `bun link` yourself instead.
|
|
40
40
|
|
|
41
|
+
The block itself works unchanged in bash, and what differs is the file it goes in and who writes it. Paste it into `~/.bashrc` by hand, since `bun run bootstrap` appends to `~/.zshrc` alone and a run from a bash shell installs nothing that shell reads. Bash re-checks the first word of an alias expansion the way zsh does, so the `cl` and `clp` chains below still inherit their base, and the `bun install` and `bun link` step above is the opt-out either shell takes.
|
|
42
|
+
|
|
41
43
|
## What each one does
|
|
42
44
|
|
|
43
45
|
`cl`, `clw`, and `cls` carry no explicit plugin dir and start a fresh session. Use them inside the toolkit repository, where Claude Code auto-discovers the plugin from `claude/.claude-plugin/plugin.json`. Loading `--plugin-dir` on top of auto-discovery registers every skill twice and produces duplicate entries in the slash command list.
|
|
@@ -66,7 +68,7 @@ Use `clp` in any other repository where you want the toolkit skills available. W
|
|
|
66
68
|
|
|
67
69
|
Use `cls` or `clps` to save Opus usage on routine sessions. Switch mid-session with `/model` to avoid restarting.
|
|
68
70
|
|
|
69
|
-
Use `clw <name>` for features that will take more than one session. A worktree isolates the branch, the transcripts, and the `/resume` history. See [Claude Code and git worktrees](
|
|
71
|
+
Use `clw <name>` for features that will take more than one session. A worktree isolates the branch, the transcripts, and the `/resume` history. See [Claude Code and git worktrees](../../wiki/claude/claude-worktrees.md) for fan-out rules.
|
|
70
72
|
|
|
71
73
|
Use `clc` to resume the last session without a picker. Use `clr` when you have several sessions and need to pick by name or recency. Reach for `clpc` over `clc` wherever the resumed session needs the plugin, inside the toolkit repository as well as outside it, since neither resume re-runs discovery.
|
|
72
74
|
|
package/package.json
CHANGED
package/scripts/docs/list.sh
CHANGED
|
@@ -42,7 +42,8 @@ is_internal_topic() {
|
|
|
42
42
|
# sorted so a domain split into a folder lands in its alphabetical place rather
|
|
43
43
|
# than after every file. A folder declares its category on its own index, since
|
|
44
44
|
# the allowlist is what separates a target-facing doc from a workflow one and a
|
|
45
|
-
# split domain is not exempt from it.
|
|
45
|
+
# split domain is not exempt from it. A sub-area file declares its own, which is
|
|
46
|
+
# what keeps a page's listing membership unchanged by the folder it moves into.
|
|
46
47
|
collect_docs() {
|
|
47
48
|
local file name description category
|
|
48
49
|
{
|
|
@@ -64,12 +65,30 @@ collect_docs() {
|
|
|
64
65
|
description=$(read_frontmatter_field "$file" "subtitle")
|
|
65
66
|
printf '%s\t%s\t%s\t%s\n' "$name" "$description" "$category" "docs/$name/index.md"
|
|
66
67
|
done < <(find "$DOCS_DIR" -mindepth 2 -maxdepth 2 -type f -name "index.md")
|
|
68
|
+
|
|
69
|
+
# A sub-area file is named and described like a sibling file, and reaches a
|
|
70
|
+
# caller by that bare name, so the depth it sits at is not the listing's
|
|
71
|
+
# business. Only a folder carrying an index is walked, matching resolveTopic
|
|
72
|
+
while IFS= read -r file; do
|
|
73
|
+
name=$(basename "$file" .md)
|
|
74
|
+
[ "$name" = "index" ] && continue
|
|
75
|
+
[ -f "$(dirname "$file")/index.md" ] || continue
|
|
76
|
+
category=$(read_frontmatter_field "$file" "category")
|
|
77
|
+
is_target_facing "$category" || continue
|
|
78
|
+
description=$(read_frontmatter_field "$file" "description")
|
|
79
|
+
printf '%s\t%s\t%s\t%s\n' "$name" "$description" "$category" "docs/$(basename "$(dirname "$file")")/$name.md"
|
|
80
|
+
done < <(find "$DOCS_DIR" -mindepth 2 -maxdepth 2 -type f -name "*.md")
|
|
67
81
|
} | sort
|
|
68
82
|
}
|
|
69
83
|
|
|
70
84
|
# Emits `name<TAB>description<TAB>target` per context entry, sorted so a domain
|
|
71
85
|
# split into a folder lands in its alphabetical place rather than after every
|
|
72
|
-
# file
|
|
86
|
+
# file, the way listTopics in src/docs/read.ts sorts both together.
|
|
87
|
+
#
|
|
88
|
+
# It stops at the folder where listTopics goes on to name each sub-area file.
|
|
89
|
+
# This is the downstream catalog and that one answers what a caller could have
|
|
90
|
+
# typed, so a reachable name absent here is the same divergence the internal
|
|
91
|
+
# topics already carry, and docs/agents/docs.md states it.
|
|
73
92
|
collect_context() {
|
|
74
93
|
local file name description
|
|
75
94
|
{
|
package/src/cli.ts
CHANGED
|
@@ -88,7 +88,7 @@ function showHelp(): void {
|
|
|
88
88
|
`${GREY}│${NC} deps [cmd] ${GREY}# Read the resolved dependency set for advisories (audit)${NC}`,
|
|
89
89
|
`${GREY}│${NC} labels [cmd] ${GREY}# Read a changed set against the pull request label map (audit)${NC}`,
|
|
90
90
|
`${GREY}│${NC} autoship [cmd] ${GREY}# Decide whether a changed set needs the review pass (classify)${NC}`,
|
|
91
|
-
`${GREY}│${NC} pr [cmd] ${GREY}# Read a pull request
|
|
91
|
+
`${GREY}│${NC} pr [cmd] ${GREY}# Read a pull request against its own diff and its branch tip (key-changes, head, checks)${NC}`,
|
|
92
92
|
`${GREY}│${NC} repo [cmd] ${GREY}# This repository's own remote metadata (metadata propose, apply)${NC}`,
|
|
93
93
|
`${GREY}│${NC} census [path] ${GREY}# Report tracked file count, extension breakdown, and line totals${NC}`,
|
|
94
94
|
`${GREY}│${NC} audits [cmd] ${GREY}# Run every health check as one set (run, list)${NC}`,
|