@erclx/canon 4.9.1 → 4.10.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/claude/skills/claude-autoship/SKILL.md +12 -5
- package/claude/skills/claude-orchestrate/SKILL.md +1 -1
- package/claude/skills/claude-worker/SKILL.md +1 -0
- package/docs/ai-workflow.md +1 -1
- package/package.json +1 -1
- package/scripts/core/install-check.sh +29 -17
|
@@ -158,13 +158,18 @@ This chain owns the receipt's lifetime, which is what makes the Output block's c
|
|
|
158
158
|
|
|
159
159
|
Invoke `canon:git-ship`. That body owns the sequence, being the verify gate, memory capture, both doc syncs, staging, the commit grouping, the branch rename, the pull request, the CI watch, and the scoped memory review, along with the reason each step sits where it does. This step used to restate that list and the two drifted apart with nothing comparing them, so read the order there and never here.
|
|
160
160
|
|
|
161
|
-
One thing this chain adds. Mark the pull request as a draft as soon as `git-ship`'s pull request step returns, ahead of its CI watch:
|
|
161
|
+
One thing this chain adds. Mark the pull request as a draft as soon as `git-ship`'s pull request step returns, ahead of its CI watch, then read the flag back:
|
|
162
162
|
|
|
163
163
|
```bash
|
|
164
|
-
gh pr ready --undo
|
|
164
|
+
gh pr ready --undo <number>
|
|
165
|
+
gh pr view <number> --json isDraft
|
|
165
166
|
```
|
|
166
167
|
|
|
167
|
-
|
|
168
|
+
Name the number `git-ship`'s pull request step returned on both calls rather than leaving either to resolve by branch, since each matches a head ref and ignores state, so a reused branch name reaches a merged namesake. The read is where that costs the most, answering with the wrong record's flag, and the write above it errors rather than mutating one.
|
|
169
|
+
|
|
170
|
+
Report what the read returned rather than what the command printed, since the exit says the call ran and says nothing about the state. A `true` reports a draft. A `false` reports the pull request as opened ready and unsupervised, and the chain stops there. Never re-issue the undo on a disagreeing read, which fights whoever readied it instead of guarding anything.
|
|
171
|
+
|
|
172
|
+
Placement is why the call sits ahead of the watch rather than after it. Marking afterwards leaves the pull request unmarked for the whole CI run, which is the stretch an unattended worker's branch is least supervised. What the mark buys is a reader learning the pull request has had no review yet. It buys no bound on that stretch: readying a pull request to merge lifts the mark, GitHub requires it before a merge, and it is the operator's act to take.
|
|
168
173
|
|
|
169
174
|
`git-ship` verifies again at its own gate, which repeats this chain's Step 3 on the run where nothing stopped. That cost is deliberate: four of the stop points in the table below hand the run straight back to that body, and a gate the chain skips for being redundant is a gate no resumed run ever meets.
|
|
170
175
|
|
|
@@ -173,16 +178,18 @@ Placement is the whole point of naming it. Marking after the watch leaves the pu
|
|
|
173
178
|
Respond with up to five lines:
|
|
174
179
|
|
|
175
180
|
```plaintext
|
|
176
|
-
✅ Autoshipped (
|
|
181
|
+
✅ Autoshipped (<state>): <PR url>
|
|
177
182
|
<N minor findings kept in .canon/review/branch/review-<slug>.md>
|
|
178
183
|
<N facts routed to context entries>
|
|
179
184
|
<N memories captured in .canon/memory/>
|
|
180
185
|
<Memory proposal at .canon/review/memory/memory-review-<slug>.md>
|
|
181
186
|
```
|
|
182
187
|
|
|
188
|
+
`<state>` is whatever the Step 7 read returned, being `draft` or `ready, unsupervised`, rather than the state the undo asked for. Writing the word `draft` there unconditionally is what this line used to do, and it named a state no step had read.
|
|
189
|
+
|
|
183
190
|
Omit the second line if there were no minor findings, and the third if nothing routed. Omit the fourth and fifth if `claude-memory-capture` wrote no memory file this session, since an empty pen means no scoped review and no proposal. A run that routes every fact and writes none is the shape to expect, and it reports three lines.
|
|
184
191
|
|
|
185
|
-
This block replaces the one `git-ship` closes on rather than following it. The two carry the same three trailing lines and differ on the two above them, since the first names the
|
|
192
|
+
This block replaces the one `git-ship` closes on rather than following it. The two carry the same three trailing lines and differ on the two above them, since the first names the state the read returned and the second reports the minor findings Step 6 kept, neither of which that body has a counterpart for. Emitting both reports one run twice and buries the state under a `✅ Shipped` that does not name it.
|
|
186
193
|
|
|
187
194
|
## Failure recovery
|
|
188
195
|
|
|
@@ -119,7 +119,7 @@ Write no shape for a correction. A correction is a sentence, and a format for ad
|
|
|
119
119
|
- Resolve the target at the moment of sending with `canon sessions list --branch`, never from a mapping written down earlier, since names rotate as sessions end and one recorded earlier in a session has failed inside the hour. The runbook read at step 5 routes on the count and the confidence it answers with
|
|
120
120
|
- Open the message with the worktree and branch the sender believes the reader holds, asking to be corrected, whenever that mapping is inferred rather than confirmed
|
|
121
121
|
- Name the skill for the reader to run rather than writing an invocation, which arrives as text
|
|
122
|
-
- Read the pull request's own draft flag rather than the state a worker reports, since two reported a draft that read ready inside ninety seconds
|
|
122
|
+
- Read the pull request's own draft flag rather than the state a worker reports, since two reported a draft that read ready inside ninety seconds, and report what the read returned and when rather than the state alone. The flag settles the question only once the worker's chain has run its undo, and nothing marks that moment, so a read taken between the pull request opening and that call sees a genuinely ready pull request about to become a draft. That is how a poll on `#1307` told an operator the opposite of what the worker had said.
|
|
123
123
|
|
|
124
124
|
A session is reachable when it appears in a live listing, which reads what each session registered on disk rather than probing it, and a message carries plain text and no authority. When no live session holds the branch, report the invocation for the human, naming the branch, the pull request, and the skill to run, then stop. Retrying or waiting leaves the loop believing it is open while nothing acts on it. Every dispatch in the trial behind this step found a live session, so this branch stands on reasoning rather than on observation.
|
|
125
125
|
|
|
@@ -25,6 +25,7 @@ running and re-invoking it would restart the build.
|
|
|
25
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
|
+
- Report a draft flag reading ready once, and leave it cleared. The ship chain marks the pull request a draft and no step anywhere un-marks, so a flag reading ready afterwards was lifted by a person readying it to merge, which GitHub requires and is theirs to take. Re-drafting fights them, which four sessions did on 2026-08-31 on a belief no surface in the tree states.
|
|
28
29
|
|
|
29
30
|
## The board is read-only
|
|
30
31
|
|
package/docs/ai-workflow.md
CHANGED
|
@@ -80,7 +80,7 @@ When features are independent, run them in parallel instead of sequentially. Use
|
|
|
80
80
|
- Invoke `canon:claude-feature` in each session. Plans land at the main worktree root as `.canon/plans/feature-<slug>.md`, one per feature, no collisions. Small features stay in chat and skip the file.
|
|
81
81
|
- Implement, verify, and review each feature independently. `claude-review` and `claude-ui-test` write per-branch files at the main worktree root (`review/branch/review-<slug>.md`, `review/ui-checklist-<slug>.md`), so parallel sessions do not overwrite each other. The slug is the branch name with any leading type segment dropped, so `feat/jwt-expiration` and the plan at `feature-jwt-expiration.md` meet on one name
|
|
82
82
|
- Ship each worktree separately with `canon:git-ship`
|
|
83
|
-
- For full autonomy per worktree, invoke `canon:claude-autoship` instead of the manual chain. Approve the plan, walk away, come back to draft
|
|
83
|
+
- For full autonomy per worktree, invoke `canon:claude-autoship` instead of the manual chain. Approve the plan, walk away, come back to a pull request the chain marked as a draft and then read the flag back on. The mark says the work has had no review yet, and it holds no window, since readying a pull request to merge lifts it and is the operator's act.
|
|
84
84
|
|
|
85
85
|
To run several worktrees as a coordinated flow rather than ad hoc, assert the orchestrator role in one warm session with `canon:claude-orchestrate`. It holds the cross-feature call, plans each feature itself or dispatches a cold planner under `canon:claude-planner` to write the plan, refills the ready queue so a free worker never waits, and reviews each worker's PR with `canon:claude-pr-review`, then tells the session holding that branch to run `canon:claude-address-review` whenever the pass posted a finding at any severity, which is the same threshold `canon:claude-pr-review` states and posts its open heading under. The human launches workers and merges. See [operating model](operating-model.md) for the full loop.
|
|
86
86
|
|
package/package.json
CHANGED
|
@@ -8,7 +8,8 @@ PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
|
8
8
|
source "$PROJECT_ROOT/scripts/lib/ui.sh"
|
|
9
9
|
|
|
10
10
|
TMP_ROOT="$PROJECT_ROOT/.canon/tmp/install-check"
|
|
11
|
-
|
|
11
|
+
PACK_DIR="$TMP_ROOT/pack"
|
|
12
|
+
EXTRACT_DIR="$TMP_ROOT/extract"
|
|
12
13
|
TARGET_DIR="$TMP_ROOT/target"
|
|
13
14
|
KEEP=0
|
|
14
15
|
|
|
@@ -19,12 +20,13 @@ for arg in "$@"; do
|
|
|
19
20
|
cat <<HELP
|
|
20
21
|
Usage: scripts/core/install-check.sh [--keep]
|
|
21
22
|
|
|
22
|
-
Verifies the
|
|
23
|
-
1.
|
|
24
|
-
2.
|
|
25
|
-
3. Runs
|
|
26
|
-
4.
|
|
27
|
-
5.
|
|
23
|
+
Verifies the published install path end to end:
|
|
24
|
+
1. Packs this repo into a tarball at .canon/tmp/install-check/pack
|
|
25
|
+
2. Extracts it and asserts scripts/sandbox is absent from the tree
|
|
26
|
+
3. Runs bun install --production in the extracted tree
|
|
27
|
+
4. Runs the CLI with --help from the extracted tree to confirm it resolves
|
|
28
|
+
5. Scaffolds a fresh project in .canon/tmp/install-check/target
|
|
29
|
+
6. Runs canon init from the extracted package and asserts a scaffold landed
|
|
28
30
|
|
|
29
31
|
Flags:
|
|
30
32
|
--keep Keep the tmp tree on exit for inspection
|
|
@@ -45,21 +47,31 @@ cleanup() {
|
|
|
45
47
|
trap cleanup EXIT
|
|
46
48
|
|
|
47
49
|
rm -rf "$TMP_ROOT"
|
|
48
|
-
mkdir -p "$
|
|
50
|
+
mkdir -p "$PACK_DIR" "$EXTRACT_DIR"
|
|
49
51
|
|
|
50
52
|
open_timeline "Install verification"
|
|
51
53
|
|
|
52
|
-
log_step "
|
|
53
|
-
|
|
54
|
-
log_info "
|
|
54
|
+
log_step "Pack"
|
|
55
|
+
TARBALL_PATH="$(cd "$PROJECT_ROOT" && bun pm pack --quiet --ignore-scripts --destination "$PACK_DIR" | tail -n 1)"
|
|
56
|
+
log_info "Packed to $TARBALL_PATH"
|
|
55
57
|
|
|
56
|
-
log_step "
|
|
57
|
-
|
|
58
|
-
log_info "
|
|
58
|
+
log_step "Extract"
|
|
59
|
+
tar -xzf "$TARBALL_PATH" -C "$EXTRACT_DIR" --strip-components=1
|
|
60
|
+
log_info "Extracted to $EXTRACT_DIR"
|
|
61
|
+
|
|
62
|
+
log_step "Assert excluded path is absent"
|
|
63
|
+
if [ -e "$EXTRACT_DIR/scripts/sandbox" ]; then
|
|
64
|
+
log_error "scripts/sandbox shipped in the tarball, and the files field in package.json excludes it"
|
|
65
|
+
fi
|
|
66
|
+
log_info "Absent: scripts/sandbox"
|
|
67
|
+
|
|
68
|
+
log_step "Install dependencies (production)"
|
|
69
|
+
(cd "$EXTRACT_DIR" && bun install --production --ignore-scripts --silent 2>&1 | pipe_output) || log_error "bun install --production failed"
|
|
70
|
+
log_info "Dependencies installed without devDependencies"
|
|
59
71
|
|
|
60
72
|
log_step "Confirm CLI runs"
|
|
61
|
-
(cd "$
|
|
62
|
-
log_info "canon --help ran clean"
|
|
73
|
+
(cd "$EXTRACT_DIR" && bun run src/cli.ts --help >/dev/null) || log_error "canon --help failed"
|
|
74
|
+
log_info "canon --help ran clean from the extracted package"
|
|
63
75
|
|
|
64
76
|
log_step "Scaffold fresh project"
|
|
65
77
|
mkdir -p "$TARGET_DIR"
|
|
@@ -67,7 +79,7 @@ mkdir -p "$TARGET_DIR"
|
|
|
67
79
|
log_info "Initialized git in $TARGET_DIR"
|
|
68
80
|
|
|
69
81
|
log_step "Run canon init"
|
|
70
|
-
(cd "$TARGET_DIR" && CANON_NON_INTERACTIVE=1 bun run "$
|
|
82
|
+
(cd "$TARGET_DIR" && CANON_NON_INTERACTIVE=1 bun run "$EXTRACT_DIR/src/cli.ts" init --stack base 2>&1 | pipe_output) || log_error "canon init failed"
|
|
71
83
|
log_info "canon init completed"
|
|
72
84
|
|
|
73
85
|
log_step "Assert scaffold"
|