@erclx/canon 5.32.0 → 5.33.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/auto-ship/SKILL.md +1 -1
- package/claude/skills/auto-ship/references/worktree-name.md +1 -1
- package/claude/skills/backlog-triage/REQUIREMENT.md +2 -2
- package/claude/skills/backlog-triage/SKILL.md +1 -1
- package/claude/skills/canon-cli/REQUIREMENT.md +16 -13
- package/claude/skills/canon-cli/SKILL.md +75 -32
- package/claude/skills/canon-feedback/SKILL.md +1 -1
- package/claude/skills/{canvas → canvas-board}/REQUIREMENT.md +2 -2
- package/claude/skills/{canvas → canvas-board}/SKILL.md +2 -2
- package/{standards → claude/skills/canvas-board/references}/design.md +11 -2
- package/claude/skills/context-fold/REQUIREMENT.md +25 -33
- package/claude/skills/context-fold/SKILL.md +25 -70
- package/claude/skills/context-fold/references/classify.md +3 -3
- package/claude/skills/context-fold/references/completion-report.md +4 -4
- package/claude/skills/context-fold/references/context-refresh.md +5 -5
- package/{standards → claude/skills/context-fold/references}/context.md +16 -5
- package/claude/skills/context-fold/references/unusable-baseline.md +3 -5
- package/claude/skills/create-rule/SKILL.md +2 -2
- package/{standards → claude/skills/create-rule/references}/rule.md +12 -5
- package/claude/skills/create-skill/SKILL.md +2 -2
- package/{standards → claude/skills/create-skill/references}/skill.md +17 -14
- package/claude/skills/design-taste/REQUIREMENT.md +3 -3
- package/claude/skills/design-taste/SKILL.md +1 -1
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -1
- package/claude/skills/docs-sync/SKILL.md +3 -3
- package/{standards → claude/skills/docs-sync/references}/docs.md +11 -0
- package/{standards → claude/skills/docs-sync/references}/readme.md +9 -2
- package/claude/skills/draft-and-pick/SKILL.md +5 -5
- package/claude/skills/draft-doc/SKILL.md +6 -6
- package/claude/skills/draft-figure/REQUIREMENT.md +2 -2
- package/claude/skills/draft-figure/SKILL.md +2 -2
- package/claude/skills/draft-figure/references/hand-drawn.md +1 -1
- package/claude/skills/draft-figure/references/mermaid-path.md +1 -1
- package/claude/skills/draft-identity/REQUIREMENT.md +2 -2
- package/claude/skills/draft-identity/SKILL.md +2 -2
- package/claude/skills/draft-ready/SKILL.md +1 -1
- package/claude/skills/git-branch/SKILL.md +1 -1
- package/{standards → claude/skills/git-branch/references}/branch.md +1 -1
- package/claude/skills/git-commit/SKILL.md +2 -2
- package/claude/skills/git-followup/REQUIREMENT.md +1 -1
- package/claude/skills/git-followup/SKILL.md +1 -1
- package/claude/skills/git-issue/SKILL.md +1 -1
- package/claude/skills/git-pr/SKILL.md +13 -13
- package/claude/skills/git-pr/references/evidence.md +2 -2
- package/claude/skills/git-pr/references/final-command.md +38 -14
- package/claude/skills/git-pr/references/labels.md +5 -1
- package/{standards → claude/skills/git-pr/references}/pr.md +19 -9
- package/{standards → claude/skills/git-pr/references}/publish.md +4 -2
- package/claude/skills/git-pr/references/task-number.md +1 -1
- package/claude/skills/git-ship/SKILL.md +15 -14
- package/claude/skills/git-split/SKILL.md +3 -3
- package/claude/skills/git-stage/SKILL.md +1 -1
- package/claude/skills/plan-feature/REQUIREMENT.md +1 -1
- package/claude/skills/review-address/SKILL.md +1 -1
- package/claude/skills/review-address/references/post-review-findings.md +1 -1
- package/claude/skills/review-pr/REQUIREMENT.md +1 -1
- package/claude/skills/review-pr/SKILL.md +3 -3
- package/claude/skills/review-pr/references/body-variants.md +2 -2
- package/claude/skills/review-pr/references/key-changes.md +3 -3
- package/claude/skills/review-pr/references/post.md +4 -2
- package/claude/skills/review-ui/REQUIREMENT.md +1 -1
- package/claude/skills/review-ui/SKILL.md +1 -1
- package/claude/skills/review-ui/references/post.md +1 -1
- package/claude/skills/role-orchestrator/REQUIREMENT.md +3 -0
- package/claude/skills/role-orchestrator/SKILL.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +8 -5
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +23 -1
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-resume.md +3 -0
- package/claude/skills/role-planner/REQUIREMENT.md +2 -1
- package/claude/skills/role-planner/SKILL.md +13 -2
- package/claude/skills/role-reviewer/SKILL.md +1 -1
- package/claude/skills/role-worker/REQUIREMENT.md +1 -0
- package/claude/skills/role-worker/SKILL.md +9 -1
- package/claude/skills/session-map/SKILL.md +1 -1
- package/claude/skills/session-resume/REQUIREMENT.md +2 -2
- package/claude/skills/session-worktree/SKILL.md +5 -5
- package/claude/skills/target-setup/references/detect.md +1 -1
- package/claude/skills/task-board/REQUIREMENT.md +7 -12
- package/claude/skills/task-board/SKILL.md +5 -17
- package/claude/skills/task-board/references/tasks.md +2 -2
- package/claude/skills/task-complete/REQUIREMENT.md +47 -0
- package/claude/skills/task-complete/SKILL.md +86 -0
- package/claude/skills/{task-board → task-complete}/references/archive.md +4 -4
- package/claude/skills/{context-fold → task-complete}/references/receipt-sweep.md +5 -5
- package/claude/skills/task-complete/references/unusable-baseline.md +19 -0
- package/claude/skills/teach-workspace/REQUIREMENT.md +6 -2
- package/claude/skills/teach-workspace/SKILL.md +8 -4
- package/claude/skills/teach-workspace/references/lesson-craft.md +1 -1
- package/claude/skills/{context-fold/references/promoted-pages.md → teach-workspace/references/promotion-fold.md} +3 -3
- package/claude/skills/teach-workspace/references/promotion.md +3 -3
- package/claude/skills/ui-checklist/SKILL.md +1 -1
- package/claude/skills/ux-audit/SKILL.md +1 -1
- package/claude/skills/ux-measure/SKILL.md +1 -1
- package/docs/agents/canvas.md +1 -1
- package/docs/agents/commands.md +3 -2
- package/docs/agents/context-audit-checks.md +4 -4
- package/docs/agents/index.md +3 -3
- package/docs/agents/indexes.md +1 -1
- package/docs/agents/install-and-sync.md +6 -11
- package/docs/agents/key-changes.md +5 -5
- package/docs/agents/label-coverage.md +11 -0
- package/docs/agents/migrate.md +1 -1
- package/docs/agents/records-push.md +2 -2
- package/docs/agents/records-stale.md +12 -47
- package/docs/agents/records-validate.md +3 -7
- package/docs/agents/records.md +5 -27
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/sandbox.md +4 -4
- package/docs/agents/skills-audit.md +1 -1
- package/docs/agents/tasks-plans.md +2 -2
- package/docs/agents/tasks.md +2 -2
- package/docs/target/migrations.md +10 -2
- package/docs/target/projects.md +1 -1
- package/docs/target/sync.md +1 -1
- package/docs/workflow/operating-model.md +2 -2
- package/docs/workflow/parallel-features.md +7 -7
- package/docs/workflow/skill-map-on-request.md +9 -9
- package/docs/workflow/skill-map.md +12 -11
- package/docs/workflow/visual-design-workflow.md +2 -2
- package/governance/renames.toml +0 -11
- package/governance/rules/canon/context.md +13 -0
- package/governance/rules/claude/skill.md +17 -0
- package/governance/stacks/base.toml +2 -4
- package/package.json +4 -4
- package/scripts/core/install-check.sh +3 -3
- package/scripts/lib/ui.sh +0 -159
- package/src/audits/catalog.ts +0 -1
- package/src/claude/cases/misc.ts +1 -1
- package/src/claude/cases/setup.ts +4 -0
- package/src/claude/cases/workflow.ts +6 -1
- package/src/claude/seeds.ts +1 -1
- package/src/claude/skills-audit.ts +2 -2
- package/src/cli/help.ts +3 -1
- package/src/cli/ui.ts +2 -3
- package/src/commands/claude.ts +1 -1
- package/src/commands/gov.ts +2 -15
- package/src/commands/labels.ts +326 -7
- package/src/commands/migrate.ts +6 -1
- package/src/commands/pr.ts +1 -1
- package/src/commands/records.ts +13 -399
- package/src/commands/sandbox.ts +3 -6
- package/src/commands/tasks.ts +3 -3
- package/src/context/audit.ts +5 -5
- package/src/context/folders.ts +1 -1
- package/src/design/budget.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/design/document.ts +1 -1
- package/src/design/regen.ts +1 -1
- package/src/design/render.ts +1 -1
- package/src/gate/measures.ts +1 -1
- package/src/gate/sequencer.ts +56 -1
- package/src/gate/stages.ts +1 -7
- package/src/gov/install.ts +2 -3
- package/src/gov/stacks.ts +1 -1
- package/src/hooks/post-merge.ts +1 -1
- package/src/labels/apply.ts +39 -0
- package/src/labels/format.ts +3 -3
- package/src/labels/phase.ts +3 -3
- package/src/labels/sections.ts +43 -0
- package/src/migrate/skill-names.ts +20 -1
- package/src/pr/paths.ts +4 -4
- package/src/records/backup.ts +16 -6
- package/src/records/stale-canonical.ts +31 -1
- package/src/records/validate.ts +2 -188
- package/src/sandbox/census.ts +1 -1
- package/src/sandbox/coverage.ts +2 -6
- package/src/sandbox/equivalence.ts +5 -44
- package/src/sandbox/expect.ts +4 -4
- package/src/sandbox/provision.ts +13 -36
- package/src/sandbox/scenario.ts +26 -48
- package/src/sandbox/tree.ts +2 -6
- package/src/standards/read.ts +14 -1
- package/src/sync/git.ts +1 -1
- package/src/tasks/archive.ts +5 -5
- package/src/tasks/branch.ts +3 -3
- package/src/tasks/label.ts +1 -1
- package/src/tasks/record.ts +2 -2
- package/src/tasks/validate.ts +1 -1
- package/standards/index.md +0 -13
- package/standards/standard.md +1 -7
- package/tooling/base/reference.md +1 -1
- package/tooling/base/seeds/.github/pull_request_template.md +2 -2
- package/tooling/claude/reference.md +1 -1
- package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +9 -1
- package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +171 -0
- package/tooling/claude/seeds/.claude/settings.json +9 -0
- package/governance/rules/standards/context.md +0 -14
- package/governance/rules/standards/design.md +0 -12
- package/governance/rules/standards/readme.md +0 -12
- package/governance/rules/standards/rule.md +0 -13
- package/governance/rules/standards/skill.md +0 -21
- package/governance/rules/standards/standard.md +0 -13
- package/scripts/config.sh +0 -11
- package/scripts/lib/gov.sh +0 -14
- package/scripts/lib/sandbox-fixtures.sh +0 -191
- package/scripts/lib/sandbox-git.sh +0 -125
- package/scripts/lib/sandbox-path.sh +0 -50
- package/scripts/sandbox-hook.sh +0 -99
- package/src/gov/standard-rules.ts +0 -179
- package/src/records/migrate.ts +0 -78
- package/src/records/stale.ts +0 -243
- package/src/sandbox/hooks.ts +0 -128
- /package/claude/skills/{canvas → canvas-board}/references/canvas.md +0 -0
- /package/{standards → claude/skills/draft-figure/references}/figures.md +0 -0
- /package/{standards → claude/skills/git-branch/references}/slug.md +0 -0
- /package/{standards → claude/skills/git-commit/references}/commit.md +0 -0
- /package/{standards → claude/skills/git-commit/references}/versioning.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-board
|
|
3
|
-
description: Why creating and
|
|
3
|
+
description: Why creating and declining a task file is one skill, the origin invariant enforceable only at creation, and why settling a shipped task belongs elsewhere
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Task board requirement
|
|
@@ -9,8 +9,6 @@ description: Why creating and archiving a task file is one skill, the origin inv
|
|
|
9
9
|
|
|
10
10
|
Without this skill, a task file gets a filename and frontmatter invented on the spot, so the board sorts wrong and the regenerated index reads fields that are not there. A task arrives with no origin, which is either lost context or work nobody decided to do, and by the time anyone notices there is no way to recover which it was. The phase label gets derived from a version file rather than from what the board already means, and a single-digit phase sorts after a double-digit one because nobody padded it. A label picked off the live board alone repeats one the archive already spent, since the archive holds most of what has ever been allocated and a board-only scan cannot see it.
|
|
11
11
|
|
|
12
|
-
Archiving fails in two ways that both lose work. Moving the file, editing the ordering file, and regenerating the index as three separate acts drifts from the one command the merge hook calls, so the attended and unattended paths stop agreeing. And an all-`[x]` task gets archived while its pull request is still open, because marking outcomes happens on the branch as the first step of shipping. The board is gitignored, so nothing restores a task archived early.
|
|
13
|
-
|
|
14
12
|
Placing a row without checking for another writer collides the same way. Two sessions filing work at once can claim one phase label twice or land two rows beside each other unread, since neither reads the board before writing it.
|
|
15
13
|
|
|
16
14
|
## Must
|
|
@@ -20,29 +18,26 @@ Placing a row without checking for another writer collides the same way. Two ses
|
|
|
20
18
|
- Require an origin at creation, because that is the only moment the invariant is enforceable
|
|
21
19
|
- Claim the phase label with `canon tasks next-label --claim` rather than reading or proposing one by hand
|
|
22
20
|
- Check the roster for a live orchestrator before writing a row, and hand off rather than write when one is found
|
|
23
|
-
-
|
|
24
|
-
- Run the archive command and route on the reason it refuses, since each reason has one resolution
|
|
21
|
+
- Run the decline command and route on the reason it refuses, since each reason has one resolution
|
|
25
22
|
- Report an origin that carries no task, as a list rather than a prompt
|
|
26
23
|
|
|
27
24
|
## Must not
|
|
28
25
|
|
|
29
|
-
- Mark an outcome complete or
|
|
26
|
+
- Mark an outcome complete, archive a task, or move a plan
|
|
30
27
|
- Hand-edit the index or the ordering file, or move the task file directly
|
|
31
28
|
- Write a pull request line at creation, when any number is a guess at someone else's work
|
|
32
|
-
-
|
|
33
|
-
- Split the legacy single-file archive into per-task files nobody wrote
|
|
29
|
+
- Decline around a refusal
|
|
34
30
|
- Claim a label or write a task file for a session holding the worker role, since that role reports a row upward and the controlling session places it
|
|
35
31
|
- Fall through to a direct write when no orchestrator is found and this session's own name starts with `worker-` or `planner-`, since those role bodies ban the write with no exception
|
|
36
32
|
|
|
37
33
|
## Guards
|
|
38
34
|
|
|
39
35
|
- No task board at the main root: stop
|
|
40
|
-
- The request fits neither creating nor
|
|
41
|
-
- Work not yet on the default branch: stop, because the board has no history to restore from
|
|
36
|
+
- The request fits neither creating nor declining: stop rather than picking one
|
|
42
37
|
- No origin given and none offered: stop
|
|
43
38
|
|
|
44
39
|
## Out of scope
|
|
45
40
|
|
|
46
|
-
-
|
|
41
|
+
- Marking a shipped task's outcomes and archiving it, which `task-complete` owns, with the `post-merge` hook running the unattended archive
|
|
47
42
|
- Deciding what the task should argue. This owns the file's existence and its shape, not its content.
|
|
48
|
-
- Relocating a plan, which
|
|
43
|
+
- Relocating a plan, which `canon tasks archive` owns so two movers do not relocate it differently
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-board
|
|
3
|
-
description: Creates a task file in `.canon/tasks/` with the filename, phase label, and frontmatter the standard requires, and
|
|
3
|
+
description: Creates a task file in `.canon/tasks/` with the filename, phase label, and frontmatter the standard requires, and declines one decided against. Use when asked to "add a task", "create a task", "queue this", "put this on the board", or "decline that task". Do NOT use to mark an outcome `[x]` or to archive a shipped task. That is `task-complete`.
|
|
4
4
|
metadata:
|
|
5
5
|
family: decide
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Task board
|
|
9
9
|
|
|
10
|
-
Owns the two operations that
|
|
10
|
+
Owns the two operations that decide a task: bringing its file into existence, and declining one decided against. `task-complete` settles a task once its work exists, marking outcomes `[x]` and archiving a shipped one. Do not mark outcomes or archive here, and do not move a plan by hand.
|
|
11
11
|
|
|
12
12
|
Read `${CLAUDE_SKILL_DIR}/references/tasks.md` before writing any file. It holds the filename convention, the frontmatter contract, and the file format. Do not work them from memory.
|
|
13
13
|
|
|
14
14
|
## Guards
|
|
15
15
|
|
|
16
16
|
- Resolve the board at the main worktree root, not `pwd`. Run `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo. Every read and write below resolves against that root. The board is gitignored scratch shared across worktrees, so a linked worktree writing to its own `pwd` creates a second board nothing else reads.
|
|
17
|
-
- A new task file is a main-root write, so it goes out as a heredoc.
|
|
17
|
+
- A new task file is a main-root write, so it goes out as a heredoc. Declining already runs through `canon tasks decline`, which resolves the root in-process. Resolve that root and route the write the way `session-worktree` states.
|
|
18
18
|
- If `.canon/tasks/` does not exist at that root, stop: `❌ No .canon/tasks/ board. Run canon claude init to set it up.`
|
|
19
|
-
- Route on the request rather than on a flag. Creating names work that does not exist yet,
|
|
19
|
+
- Route on the request rather than on a flag. Creating names work that does not exist yet, and declining names a task file decided against. A request to archive a shipped task or mark its outcomes belongs to `task-complete`, so name it and stop. If the request fits neither, stop: `❌ Ambiguous. Say whether to create a task or decline one.`
|
|
20
20
|
- Never hand-edit `.canon/tasks/index.md`. A hook regenerates it from sibling frontmatter after a write. Do not run the regen command directly, except after a shell write from a linked worktree: the hook matches `Write|Edit|MultiEdit` and nothing fires on `Bash`, so that one case regenerates explicitly with `canon indexes regen --no-stage --root <main-root> <main-root>/.canon/tasks/index.md`.
|
|
21
21
|
|
|
22
22
|
## Create
|
|
@@ -39,7 +39,7 @@ The guard sits ahead of Step 2 because `--claim` reserves a label on disk, so a
|
|
|
39
39
|
|
|
40
40
|
Run `canon tasks next-label --claim --json` and take its `label` field. The verb reads the live board and its `archive/` sibling together, so the label it returns accounts for what the board alone no longer shows, and `--claim` reserves it under `.canon/ordinal-locks/` so a second session filing at the same moment gets the next one. Branch on the record's `reason` rather than the exit: `label-contended` means re-run the claim, and a usage error from an unknown `--claim` means the installed binary predates the flag, so report the verb as unavailable rather than falling back to a bare read, which reopens the race.
|
|
41
41
|
|
|
42
|
-
Do not derive the label from a version file. `${CLAUDE_SKILL_DIR}
|
|
42
|
+
Do not derive the label from a version file. `${CLAUDE_SKILL_DIR}/../git-commit/references/versioning.md` permits free renumbering, so the verb's two folders are the only surface that knows what a label currently means.
|
|
43
43
|
|
|
44
44
|
### Step 3: write the file
|
|
45
45
|
|
|
@@ -90,10 +90,6 @@ Report rather than prompt. A track can be opened long after its task would have
|
|
|
90
90
|
|
|
91
91
|
Say the origins were read even when nothing comes back, which is the ordinary result. A step going silent on a clean pass is indistinguishable from one that never ran.
|
|
92
92
|
|
|
93
|
-
## Archive
|
|
94
|
-
|
|
95
|
-
Read `${CLAUDE_SKILL_DIR}/references/archive.md` when the request names a shipped task to archive. It carries the check that the work reached `main`, the `canon tasks archive` call, the route for each refusal, and the prose to clear afterwards. Never move the file, edit `priority.md`, or regenerate the index by hand, since the command owns all three.
|
|
96
|
-
|
|
97
93
|
## Decline
|
|
98
94
|
|
|
99
95
|
Read `${CLAUDE_SKILL_DIR}/references/decline.md` when the request names a task decided against. It carries gathering the reason, the `canon tasks decline` call, the route for each refusal, and the prose to clear afterwards. Never move the file, edit `priority.md` or `backlog.md`, or regenerate the index by hand, since the command owns all three.
|
|
@@ -124,12 +120,4 @@ Create:
|
|
|
124
120
|
|
|
125
121
|
Drop either block when it carries no rows. When both are empty, which is the ordinary result, replace them with one line naming what was read: `Read <n> tracks, <n> dumps, and <n> open issues. Nothing unlinked.`
|
|
126
122
|
|
|
127
|
-
Archive, reporting the paths the command returned:
|
|
128
|
-
|
|
129
|
-
```plaintext
|
|
130
|
-
📦 Archived: .canon/tasks/archive/vXX.Y-<slug>.md
|
|
131
|
-
|
|
132
|
-
<ordering and index disposition in one line>
|
|
133
|
-
```
|
|
134
|
-
|
|
135
123
|
A refusal reports the reason and the resolution the mode's reference routes it to under its Step 3, on one line each.
|
|
@@ -54,13 +54,13 @@ One file per task is what keeps the board safe under parallel sessions. Two sess
|
|
|
54
54
|
|
|
55
55
|
Siblings sit in the folder without being tasks, and each earns its place by being governed somewhere. `index.md`, `priority.md`, and `backlog.md` are governed by `board.md`. Every `session-` file is a pre-compaction handoff governed by `session.md`, and each is optional: a project whose sessions never approach a compaction carries none. Anything filtering the folder to tasks skips all of them, so a name outside the set is a task whatever it holds.
|
|
56
56
|
|
|
57
|
-
The `task-board` skill creates and
|
|
57
|
+
The `task-board` skill creates and declines task files. The `task-complete` skill marks outcomes `[x]` in an existing file and archives a shipped one, and the archive carries the task's plan with it. Neither does the other's job.
|
|
58
58
|
|
|
59
59
|
## Filenames
|
|
60
60
|
|
|
61
61
|
`vXX.Y-<slug>.md`, where the version is the phase label zero-padded to two digits and the slug is kebab-case.
|
|
62
62
|
|
|
63
|
-
Padding is load-bearing. Index entries sort by filename and nothing else, so a bare `v9.0` sorts after `v15.0` and the catalog reads out of board order.
|
|
63
|
+
Padding is load-bearing. Index entries sort by filename and nothing else, so a bare `v9.0` sorts after `v15.0` and the catalog reads out of board order. `${CLAUDE_SKILL_DIR}/../git-commit/references/versioning.md` governs the label itself and permits free renumbering, so expect the occasional rename. Nothing points at a task filename, since a `Plan:` line runs from task to plan rather than the reverse. <!-- canon-allow-reference: illustrates the padding rule's own sort collision, not a citation of a real task -->
|
|
64
64
|
|
|
65
65
|
## Frontmatter
|
|
66
66
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: task-complete
|
|
3
|
+
description: Why marking shipped outcomes and archiving a shipped task sit in one skill, why the diff decides completion alone, and why the ship chain marks but never archives
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task complete requirement
|
|
7
|
+
|
|
8
|
+
## Gap
|
|
9
|
+
|
|
10
|
+
Without this skill, the board describes the scope a branch opened with. An outcome the diff shipped stays unchecked, so the board reports finished work as open and the next session re-plans it. When marking rode inside the context fold, it kept a ten-step skill running on every ship for a write that had nothing to do with the context entries, and a session reading the fold's name never learned that it also wrote the board.
|
|
11
|
+
|
|
12
|
+
Archiving fails in two ways that both lose work. Moving the file, editing the ordering file, and regenerating the index as three separate acts drifts from the one command the merge hook calls, so the attended and unattended paths stop agreeing. And an all-`[x]` task gets archived while its pull request is still open, because marking happens on the branch as a ship-chain step. The board is gitignored, so nothing restores a task archived early.
|
|
13
|
+
|
|
14
|
+
Review receipts pile up the same way. A branch report is read once by the session addressing it, and nothing but an operator asking ever collected one whose branch was gone, so the folder grew per shipped branch and never shrank.
|
|
15
|
+
|
|
16
|
+
## Must
|
|
17
|
+
|
|
18
|
+
- Take completion from the diff, since completion is a fact about the repository rather than about the conversation
|
|
19
|
+
- Match an outcome on the behavior it names, never on a filename or a commit subject
|
|
20
|
+
- Leave an outcome unchecked when the diff is ambiguous. An unmarked shipped outcome costs one manual edit and a wrongly marked one hides work that never happened.
|
|
21
|
+
- Close outcomes through `canon tasks outcome` and branch on the record's `ok` and `reason` rather than the exit
|
|
22
|
+
- Resolve the board at the main worktree root, since a linked worktree reading `pwd` finds no board
|
|
23
|
+
- Sweep a branch review report whose branch no longer exists, and leave the current branch's receipt alone, since its branch is still live
|
|
24
|
+
- Confirm the work reached the default branch before archiving
|
|
25
|
+
- Run the archive command and route on the reason it refuses, since each reason has one resolution
|
|
26
|
+
|
|
27
|
+
## Must not
|
|
28
|
+
|
|
29
|
+
- Infer a new task from the diff. Only outcomes already on the board get marked.
|
|
30
|
+
- Touch a task file the diff does not relate to
|
|
31
|
+
- Archive from the ship chain. The pull request has not merged there, and the `post-merge` hook archives through the same command once it does.
|
|
32
|
+
- Hand-edit the index or the ordering file, or move a task file or a plan directly
|
|
33
|
+
- Archive around a refusal
|
|
34
|
+
- Split the legacy single-file archive into per-task files nobody wrote
|
|
35
|
+
- Widen what the marking step reads into a write when the baseline is unusable
|
|
36
|
+
|
|
37
|
+
## Guards
|
|
38
|
+
|
|
39
|
+
- No task board at the main root: Mark reports one skip line and returns, since the ship chain runs it on every project, and Archive stops naming the command that sets one up
|
|
40
|
+
- Work not yet on the default branch when archiving: stop, because the board has no history to restore from
|
|
41
|
+
|
|
42
|
+
## Out of scope
|
|
43
|
+
|
|
44
|
+
- Creating or declining a task, which `task-board` owns
|
|
45
|
+
- The context entries, which `context-fold` owns
|
|
46
|
+
- The unattended archive at merge, which the `post-merge` hook runs through `canon tasks archive`
|
|
47
|
+
- Regenerating the task index, owned by a hook
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: task-complete
|
|
3
|
+
description: Marks the outcomes a branch's diff shipped `[x]` on the task board, sweeps the review receipts whose branch is gone, and archives a shipped task by hand where the `post-merge` hook could not. Use when asked to "mark what shipped", "tick the outcomes", "close out a shipped task", or "archive that task", or as the ship-chain step after `context-fold`. Do NOT use to create or decline a task, which is `task-board`, or to update the context entries, which is `context-fold`.
|
|
4
|
+
metadata:
|
|
5
|
+
family: ship
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Task complete
|
|
9
|
+
|
|
10
|
+
Owns the two operations that settle a task once its work exists: marking the outcomes the diff shipped, and archiving a task whose work reached `main`. `task-board` brings a task into existence and declines one, and `context-fold` writes the context entries. Do not create a task here, and do not move a plan by hand: the archive carries it.
|
|
11
|
+
|
|
12
|
+
## Guards
|
|
13
|
+
|
|
14
|
+
- Resolve the board at the main worktree root, not `pwd`. Run `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo. The board is gitignored scratch shared across worktrees, so a linked worktree reading its own `pwd` finds no board at all.
|
|
15
|
+
- If `.canon/tasks/` does not exist at that root, Mark has nothing to mark: report `⏭️ No .canon/tasks/ board, so no outcomes to mark.` and return, still running Step 4's receipt sweep, since `git-ship` invokes Mark on every ship and a project with no board is not a failed one. Archive stops instead: `❌ No .canon/tasks/ board. Run canon claude init to set it up.`
|
|
16
|
+
- Route on the request rather than on a flag. A request naming a shipped task to archive, or a task file the `post-merge` hook left in place, takes Archive. Every other request takes Mark, which is what the ship chain invokes.
|
|
17
|
+
- Never hand-edit `.canon/tasks/index.md`. A hook regenerates it.
|
|
18
|
+
|
|
19
|
+
## Mark
|
|
20
|
+
|
|
21
|
+
### Step 1: resolve the diff baseline
|
|
22
|
+
|
|
23
|
+
Resolve the base ref once:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main 2>/dev/null
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Take the union of `git diff --name-only <base> HEAD`, `git diff --name-only HEAD`, and `git ls-files --others --exclude-standard`. Read content with `git diff <base> HEAD` and `git diff HEAD`.
|
|
30
|
+
|
|
31
|
+
Prefer `origin/main` over local `main`. On `main` itself the local ref resolves to HEAD, so every committed change drops out of the set and this step goes blind to the work it is meant to read.
|
|
32
|
+
|
|
33
|
+
The baseline is unusable when no merge base resolves against either ref, or when the base came from local `main` and equals HEAD. On an unusable baseline, read `${CLAUDE_SKILL_DIR}/references/unusable-baseline.md` before Step 2 for what to read instead.
|
|
34
|
+
|
|
35
|
+
### Step 2: match the diff against the board
|
|
36
|
+
|
|
37
|
+
Read `.canon/tasks/index.md` at the main worktree root, pick the task files whose title or description relates to the changed paths, and read them.
|
|
38
|
+
|
|
39
|
+
Path matching only chooses which files to open. Behavior decides each outcome. For each unchecked outcome, decide whether the diff shipped the behavior that outcome names.
|
|
40
|
+
|
|
41
|
+
Completion is a fact about the repository rather than a fact about the conversation, so the diff decides it and the session does not.
|
|
42
|
+
|
|
43
|
+
Keep the match conservative:
|
|
44
|
+
|
|
45
|
+
- Mark only outcomes already written on the board. Never infer a new task from the diff.
|
|
46
|
+
- Match on the behavior an outcome describes, not on filenames or commit subjects. The path match above only narrowed which task files to open.
|
|
47
|
+
- Leave an outcome `[ ]` when the diff is ambiguous. An unmarked shipped outcome costs one manual edit, while a wrongly marked one hides work that never happened.
|
|
48
|
+
- Do not touch task files the diff does not relate to.
|
|
49
|
+
|
|
50
|
+
### Step 3: close the matched outcomes
|
|
51
|
+
|
|
52
|
+
Mark each completed outcome `[x]` in the task's own file through `canon tasks outcome <stem> --close <n> --json`, repeating `--close` for each. Positions count every outcome checkbox in file order from 1, which the read above already gives. Do not move or archive the file, even when every outcome now reads `[x]`, since the pull request has not merged and the `post-merge` hook archives the task once it does.
|
|
53
|
+
|
|
54
|
+
The verb resolves the board at the main worktree root in-process, which is the route `session-worktree` states for an edit inside an existing main-root file.
|
|
55
|
+
|
|
56
|
+
Read `ok` and `reason` out of that record rather than the exit. An operator's shell profile may wrap `canon` in a function that runs the binary and then a second command and takes the second status, which flattens every non-zero exit to zero. A refusal arriving as success leaves the outcome unmarked while the chain moves on, so the board reports shipped work as open and the next session re-plans it.
|
|
57
|
+
|
|
58
|
+
### Step 4: sweep consumed receipts
|
|
59
|
+
|
|
60
|
+
Read `${CLAUDE_SKILL_DIR}/references/receipt-sweep.md` for which review receipts this run sweeps, which it keeps, and the output lines. Skip this step silently when nothing qualifies.
|
|
61
|
+
|
|
62
|
+
## Archive
|
|
63
|
+
|
|
64
|
+
Read `${CLAUDE_SKILL_DIR}/references/archive.md` when the request names a shipped task to archive. It carries the check that the work reached `main`, the `canon tasks archive` call, the route for each refusal, and the prose to clear afterwards. Never move the file, edit `priority.md`, or regenerate the index by hand, since the command owns all three.
|
|
65
|
+
|
|
66
|
+
## Output
|
|
67
|
+
|
|
68
|
+
Emit the full relative path from the project root for every file written or moved. A bare filename names a file the reader cannot open.
|
|
69
|
+
|
|
70
|
+
Mark, one line per outcome closed, then the sweep lines Step 4 names:
|
|
71
|
+
|
|
72
|
+
```plaintext
|
|
73
|
+
✅ Marked: .canon/tasks/vXX.Y-<slug>.md, outcome <n>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
When the diff closed nothing, output `✅ No outcomes shipped on this diff.` and nothing for Step 3. A refusal reports the record's `reason` on one line, naming the task.
|
|
77
|
+
|
|
78
|
+
Archive, reporting the paths the command returned:
|
|
79
|
+
|
|
80
|
+
```plaintext
|
|
81
|
+
📦 Archived: .canon/tasks/archive/vXX.Y-<slug>.md
|
|
82
|
+
|
|
83
|
+
<ordering and index disposition in one line>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
A refusal reports the reason and the resolution `references/archive.md` routes it to under its Step 3, on one line each.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Archive a shipped task
|
|
3
|
-
description: How task-
|
|
3
|
+
description: How task-complete confirms a task's work reached main, runs canon tasks archive, routes each refusal, and clears prose naming the archived task
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Archive a shipped task
|
|
7
7
|
|
|
8
|
-
The Archive mode of `task-
|
|
8
|
+
The Archive mode of `task-complete`. The session reads this file when the request names a task file already shipped.
|
|
9
9
|
|
|
10
10
|
The `post-merge` git hook archives the task a merge closed, so a request arriving here is usually one the hook could not resolve on its own. Run the steps below against whatever the hook left in place.
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@ Do not move the file, edit `priority.md`, or regenerate the index by hand. `cano
|
|
|
13
13
|
|
|
14
14
|
## Step 1: confirm the work reached main
|
|
15
15
|
|
|
16
|
-
`
|
|
16
|
+
`task-complete` marks outcomes on the branch as step 2 of the ship chain, so an all-`[x]` task routinely describes a pull request that is still open. The command gates on the outcomes and cannot tell those two apart, which is what puts this check here:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
git fetch origin main --quiet && git log origin/main --oneline -20
|
|
@@ -39,7 +39,7 @@ On success the record carries `from`, `to`, `priorityRowRemoved`, and `indexRege
|
|
|
39
39
|
|
|
40
40
|
Each reason has one resolution and none of them is to archive around it:
|
|
41
41
|
|
|
42
|
-
- `open-outcomes`: the named outcomes are unmarked or genuinely open. Run `
|
|
42
|
+
- `open-outcomes`: the named outcomes are unmarked or genuinely open. Run `task-complete` when the work shipped and nothing marked it. Leave the task on the board when the outcome is real. When the work is being abandoned, cut it by striking the body, `- ~~<outcome>~~ <why>`, whatever the checkbox holds, so the board records what was dropped rather than meeting this refusal a second time.
|
|
43
43
|
- `ambiguous`: two tasks name one pull request, which is the misfile `${CLAUDE_SKILL_DIR}/references/tasks.md` rules out. Resolve the citation by hand, since no sweep repairs it.
|
|
44
44
|
- `earlier-slice`: the number is listed on the task but is not the last, so a later slice is still to merge. Leave the task on the board. Its last slice's merge archives it.
|
|
45
45
|
- `pending-branch`: a branch named in `detail` ticked an outcome before its own pull request number was recorded. Leave the task live, since that branch's merge archives it once `git-pr` records the number. When the operator decides a named branch was abandoned, archive by stem, which is the one case for it.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Sweep consumed receipts
|
|
3
|
-
description: How
|
|
3
|
+
description: How task-complete's marking step sweeps branch review reports whose branch is gone, and what it keeps and reports
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Sweep consumed receipts
|
|
7
7
|
|
|
8
|
-
Step
|
|
8
|
+
Step 4 of `task-complete`'s Mark mode, reached in order on every marking run.
|
|
9
9
|
|
|
10
|
-
Sweep the review receipts
|
|
10
|
+
Sweep the review receipts a shipped branch left behind. Resolve all paths at the main worktree root, not the current worktree, the way `session-worktree` does.
|
|
11
11
|
|
|
12
12
|
Every delete below is a plain `rm`, one per call, routed the way `session-worktree` states.
|
|
13
13
|
|
|
14
|
-
Plans are not swept here. A plan is settled by the merge rather than by an outcome this run marked, and `canon tasks archive` moves it with the task the `post-merge` hook archives. Sweeping it from this step read a closure Step 3
|
|
14
|
+
Plans are not swept here. A plan is settled by the merge rather than by an outcome this run marked, and `canon tasks archive` moves it with the task the `post-merge` hook archives. Sweeping it from this step would read a closure Step 3 wrote moments earlier and move a plan the branch is still building from.
|
|
15
15
|
|
|
16
16
|
## Reviews
|
|
17
17
|
|
|
@@ -19,7 +19,7 @@ Leave the current branch's review receipt where it is. No skill writes one now,
|
|
|
19
19
|
|
|
20
20
|
The body that writes a receipt owns its lifetime. This skill sweeps on behalf of whatever called it and has no way to read whether a file is still in use, where the chain that wrote this one cites it in its own output and knows. What reaps it is the branch sweep below, one branch later, once the branch it names is gone.
|
|
21
21
|
|
|
22
|
-
Sweep the branch reports this session never opened. List `.canon/review/branch-*.md`, run the slug transform in `${CLAUDE_SKILL_DIR}
|
|
22
|
+
Sweep the branch reports this session never opened. List `.canon/review/branch-*.md`, run the slug transform in `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md` over every name `git branch --format='%(refname:short)'` prints, and delete a report whose slug matches none of them. Take the names from that format rather than from `git branch --list`, which marks the current branch with `* ` and a branch checked out in another worktree with `+ `, so a transform reading the marked lines as written turns a live branch into a slug nothing matches and sweeps a report a sibling worktree is still working from. A branch report is read once, by the session addressing it, and the durable record of what a review found is the comment `review-pr` posts on the pull request, so a report outliving its branch is holding nothing. Skipping this leaves them accumulating for the life of the checkout, since a slug is unique per feature and no later branch ever looks for one.
|
|
23
23
|
|
|
24
24
|
What that removes is a local-only review on a branch deleted before it opened a pull request. The sweep runs anyway rather than keeping every report against the one case, since nothing else ever clears them.
|
|
25
25
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: An unusable diff baseline
|
|
3
|
+
description: When task-complete's diff baseline is unusable, what the marking step reads to recover the committed half, and why that widened read is safe here
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# An unusable diff baseline
|
|
7
|
+
|
|
8
|
+
Step 1 of `task-complete`'s Mark mode. The session reads this file when no merge base resolves or the base came from local `main` and equals HEAD.
|
|
9
|
+
|
|
10
|
+
The baseline is unusable in two cases:
|
|
11
|
+
|
|
12
|
+
- No merge base resolves against either ref.
|
|
13
|
+
- The base came from local `main` and equals HEAD. Nothing is pushed to compare against, so a narrow read reports no changes rather than admitting it cannot see them.
|
|
14
|
+
|
|
15
|
+
An unusable baseline costs only the committed half. `git diff <base> HEAD` is empty by definition once the base equals HEAD, while `git diff HEAD` and `git ls-files --others --exclude-standard` still report uncommitted and untracked work at correct scope.
|
|
16
|
+
|
|
17
|
+
Recover the committed half. Read `git log -p -1`, widening to `git log -p -<n>` when the session spans several commits, and read the candidate task files against the working tree. That yields names and content both, which is what lets Step 2 decide on behavior rather than on filenames. A fresh `git init` on `main` with no remote is the ordinary shape of a scaffolded project, so this path carries the evidence rather than covering an edge case.
|
|
18
|
+
|
|
19
|
+
On a fresh `git init` project the last commit is the scaffold commit, so `git log -p -1` is the whole tree by another route. The marking step tolerates that because it only reads the diff, and it matches conservatively against outcomes already on the board. Widening what a step reads is safe. Never carry the widened set into a step that writes per file.
|
|
@@ -21,6 +21,8 @@ The lesson then reaches nobody. It is a page carrying a stylesheet and a script,
|
|
|
21
21
|
|
|
22
22
|
The durable half then has nowhere to go. A reference page and a glossary carry no learner and are ordinary reference prose, so they belong wherever the project already keeps prose on that subject, and a workspace holding them is a gitignored folder one person reads. A session moving them by hand picks a destination from the reader's activity rather than from who owns the subject, drops a page into a corpus without the source line that corpus requires, and has nothing stopping it from carrying a lesson across.
|
|
23
23
|
|
|
24
|
+
A confirmed page then waits in gitignored scratch until something lands it, and the session that produced it is gone by the time a branch exists to carry the write. Left unfolded it reads as promoted while the destination holds nothing.
|
|
25
|
+
|
|
24
26
|
Two failures land specifically on where the folder sits. A workspace resolved against the current directory forks into a copy per linked worktree, so the learning records split and no session sees the whole history. A body naming only the destination path reports success and loses the write, because the file-editing tools refuse a main-root path from a linked worktree and offer a worktree copy instead.
|
|
25
27
|
|
|
26
28
|
## Must
|
|
@@ -38,12 +40,14 @@ Two failures land specifically on where the folder sits. A workspace resolved ag
|
|
|
38
40
|
- Hand the learner a link that opens the workspace in a real browser on every run, reading it back from the verb that served it rather than composing one, since the port a preview lands on is not the port it asked for
|
|
39
41
|
- Propose a destination for each durable page by who owns its subject, and wait for the operator rather than routing on the session's own reading
|
|
40
42
|
- Hand each confirmed page off through a named file of its own, so one skill owns the durable writes and no other producer's unread work is discarded with it
|
|
43
|
+
- Land each block of that handoff from a branch, at the destination its heading names, taking the destination as already decided, then delete the file so a later run does not fold it twice
|
|
41
44
|
- Name what the destination expects that the page does not carry yet, since the workspace runs none of the gates the destination does
|
|
42
45
|
|
|
43
46
|
## Must not
|
|
44
47
|
|
|
45
48
|
- Teach from recall without saying which claims rest on it
|
|
46
|
-
- Write to a destination surface
|
|
49
|
+
- Write to a destination surface outside the fold mode, since the proposal and the landing are two steps a branch boundary separates and two writers at one step is what the handoff exists against
|
|
50
|
+
- Overwrite a file a promotion block routes to. A destination that already holds a page is a merge for a person, and folding over it discards work this skill never read.
|
|
47
51
|
- Open a second workspace on a subject an existing one already covers
|
|
48
52
|
- Renumber a workspace folder, a lesson, or a learning record, since the number is cited by files already written
|
|
49
53
|
- Promote a lesson, at any age and on any request, since it is generated markup carrying a quiz and a learner into a corpus every other page passed a gate to enter
|
|
@@ -55,7 +59,7 @@ Two failures land specifically on where the folder sits. A workspace resolved ag
|
|
|
55
59
|
|
|
56
60
|
## Out of scope
|
|
57
61
|
|
|
58
|
-
-
|
|
62
|
+
- Creating a wiki folder a project never chose
|
|
59
63
|
- What the verbs do internally, which is the CLI domain's own contract rather than this skill's, and the records backup that carries the folder off one disk
|
|
60
64
|
- What a lesson renders as and how a quiz behaves once rendered, which the lesson-craft reference shapes and a rendering layer executes
|
|
61
65
|
- Deciding when to fire. The skill is user-invoked through `disable-model-invocation`, so opening a workspace is the learner's call rather than a description match.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: teach-workspace
|
|
3
|
-
description: Opens and runs a learning workspace on one subject, holding a mission, resources, numbered lessons, reference pages, a glossary, and learning records that survive across sessions,
|
|
3
|
+
description: Opens and runs a learning workspace on one subject, holding a mission, resources, numbered lessons, reference pages, a glossary, and learning records that survive across sessions, proposes where a durable page from one belongs once it outgrows the workspace, and lands the confirmed pages from a branch. Use when asked to "teach me X", "open a learning workspace", "I want to learn X", "quiz me on this", "continue the lesson", "resume my workspace on X", "promote this reference page", or "fold the promoted pages in". Do NOT use to write project documentation, which belongs to the surface owning that document, and do NOT use to answer one question, which is an ordinary reply.
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
argument-hint: <subject to learn,
|
|
5
|
+
argument-hint: <subject to learn, the topic of a workspace to resume or promote, or fold>
|
|
6
6
|
metadata:
|
|
7
7
|
family: answer
|
|
8
8
|
---
|
|
@@ -17,7 +17,7 @@ The shape of the workspace is fixed by `${CLAUDE_SKILL_DIR}/references/teach.md`
|
|
|
17
17
|
|
|
18
18
|
- If the invocation names no subject and no existing workspace matches, stop: `❌ No subject. Invoke with the subject to learn, or the topic of a workspace to resume.`
|
|
19
19
|
- Never trust recall for what the subject says. Research first, cite what was read, and say what was not.
|
|
20
|
-
- Write nothing outside the workspace folder, apart from the one handoff file Step 6 names. A durable page stays in `reference/`
|
|
20
|
+
- Write nothing outside the workspace folder, apart from the one handoff file Step 6 names and the destinations the fold mode lands from that file. A durable page stays in `reference/` until the operator confirms a destination, and only the fold mode copies it out, from a branch.
|
|
21
21
|
- Do not open a second workspace on a subject one already covers. Resume that one.
|
|
22
22
|
- Never promote a lesson. It is generated markup carrying a quiz and a learner, and no request makes it promotable.
|
|
23
23
|
- Never write a favicon link by hand. `canon teach nav` puts the toolkit's icon on every page it generates and inside a lesson's `style` region, so a hand-written one in a lesson's `<head>` gives the page two.
|
|
@@ -41,7 +41,7 @@ Every path under the main root is a main-root write, routed the way `session-wor
|
|
|
41
41
|
|
|
42
42
|
## Step 1: open or resume
|
|
43
43
|
|
|
44
|
-
A topic the listing already carries is a resume, and anything else is a new workspace. An invocation asking to promote is neither: read the named workspace through the listing and go to Step 6, which teaches nothing and writes no lesson.
|
|
44
|
+
A topic the listing already carries is a resume, and anything else is a new workspace. An invocation asking to promote is neither: read the named workspace through the listing and go to Step 6, which teaches nothing and writes no lesson. An invocation asking to fold confirmed promotions in is neither as well: go to `## Fold mode`.
|
|
45
45
|
|
|
46
46
|
On a resume, run `canon teach list <topic> --json` for the files behind each count, then read the highest-numbered learning record and `GLOSSARY.md`. Those carry where the learner stopped and what they got wrong. The listing record carries `success`, the mission's success lines, which are the exit criteria this workspace is finished against. Report them with what is already met before teaching anything.
|
|
47
47
|
|
|
@@ -141,6 +141,10 @@ Run this when the invocation asks for it, or offer it in one line when a mission
|
|
|
141
141
|
|
|
142
142
|
Read `${CLAUDE_SKILL_DIR}/references/promotion.md` first. It carries what may be promoted, the routing test, both spellings of the wiki folder, the refusal when a project has none, what each destination expects a page to carry, and under `## Proposing and handing off` the proposal block, the handoff file this step writes in place of any destination, and how the operator is told to fold it. Propose and wait, and write nothing to a destination here.
|
|
143
143
|
|
|
144
|
+
## Fold mode
|
|
145
|
+
|
|
146
|
+
Run this only when the invocation asks to fold, and only from a branch in a linked worktree, since every destination is a tracked file that commits with the branch while the handoff sits in gitignored scratch at the main root. Read `${CLAUDE_SKILL_DIR}/references/promotion-fold.md` for how each block lands, the overwrite refusal, the handoff delete, and the output lines, which replace the Output block below.
|
|
147
|
+
|
|
144
148
|
## Output
|
|
145
149
|
|
|
146
150
|
```plaintext
|
|
@@ -50,7 +50,7 @@ Every element competes with the material for attention.
|
|
|
50
50
|
Decide the figure once per lesson, before writing the body.
|
|
51
51
|
|
|
52
52
|
1. Name the one relationship, boundary, path, or before-and-after the lesson is about. A lesson about none ends here, with `Figure: none, <why it names no structure>` on the reply.
|
|
53
|
-
2. Hold it against the bar in `${CLAUDE_SKILL_DIR}
|
|
53
|
+
2. Hold it against the bar in `${CLAUDE_SKILL_DIR}/../draft-figure/references/figures.md`, which also carries the drawing rules.
|
|
54
54
|
3. Draw it hand-written through `canon:draft-figure` into a `raw` block before the quiz, never inside it or after its feedback, which breaks the stepper's gating. Report it, never draw it yourself, if the skill does not resolve.
|
|
55
55
|
4. Or write one line on why prose carries it better, such as a structure an earlier lesson gave.
|
|
56
56
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Fold promoted pages
|
|
3
|
-
description: How
|
|
3
|
+
description: How teach-workspace's fold mode lands each page a teach promotion handoff carries from a branch, deletes the handoff, and reports what it landed or left unfolded
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Fold promoted pages
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
The fold mode of `teach-workspace`, run from a branch in a worktree. The session reads this file when the invocation asks to fold confirmed promotions in.
|
|
9
9
|
|
|
10
|
-
Derive `<slug>` per `${CLAUDE_SKILL_DIR}
|
|
10
|
+
Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`, falling back to `latest` on an empty result, and read `.canon/tmp/handoff/teach-promotion/<slug>.md` at the main worktree root. `teach-workspace` writes it, one H2 per destination naming the path, with a source line under the heading and the page body in a fenced block below that. Read the body out of the fence rather than off the heading level, since a reference page carries headings of its own and only the fence separates them from the next destination. Stop when the file is absent, reporting `❌ No promotion handoff at .canon/tmp/handoff/teach-promotion/<slug>.md. Run the promotion step from the workspace first.`
|
|
11
11
|
|
|
12
12
|
Each block is a page an operator already confirmed a destination for, so this step lands it rather than judging it again. Write to the destination the heading names, at `pwd` rather than at the main root, since every destination here is a tracked file that commits with the branch:
|
|
13
13
|
|
|
@@ -77,17 +77,17 @@ Source: .canon/teach/<nn>-<topic>/reference/<slug>.md
|
|
|
77
77
|
|
|
78
78
|
The body is fenced rather than written bare because a reference page carries headings of its own, and the reader splits this file on its H2 lines. An unfenced body turns every section heading in the page into a destination naming no path. Open the body fence with four backticks so a page carrying a fenced code block of its own still closes where it should, and widen both fences together if it carries a four-backtick fence.
|
|
79
79
|
|
|
80
|
-
Derive `<slug>` per `${CLAUDE_SKILL_DIR}
|
|
80
|
+
Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. Fall back to `latest` on an empty result.
|
|
81
81
|
|
|
82
82
|
The handoff is its own file rather than a shared one. The routed-facts file another skill writes is deleted by whichever pass folds it, so a second producer's unread work goes with it, and a sibling path costs the folding skill one more read and removes the interaction.
|
|
83
83
|
|
|
84
|
-
An append is a whole-file operation, so send it as a heredoc, per the skill's Step 0. Then tell the operator that `/
|
|
84
|
+
An append is a whole-file operation, so send it as a heredoc, per the skill's Step 0. Then tell the operator that `/teach-workspace fold` folds the file in from a branch. The proposal costs nothing tracked and runs anywhere, while the page it describes is a tracked file, so the fold is a worktree operation and the workspace it came from is not.
|
|
85
85
|
|
|
86
86
|
A promotion pass reports this shape in place of the skill's Output block, one line per page the operator confirmed and one naming the handoff:
|
|
87
87
|
|
|
88
88
|
```plaintext
|
|
89
89
|
➡️ Promoting: .canon/teach/<nn>-<topic>/reference/<slug>.md → <destination path>
|
|
90
|
-
→ Confirmed pages wait at .canon/tmp/handoff/teach-promotion/<slug>.md. Run /
|
|
90
|
+
→ Confirmed pages wait at .canon/tmp/handoff/teach-promotion/<slug>.md. Run /teach-workspace fold from a branch to fold them in.
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
A pass where the operator confirmed nothing writes no handoff file and reports that alone.
|
|
@@ -61,7 +61,7 @@ Omit the heading when every automatable change is covered.
|
|
|
61
61
|
|
|
62
62
|
## Persist the checklist
|
|
63
63
|
|
|
64
|
-
Derive `<slug>` per `${CLAUDE_SKILL_DIR}
|
|
64
|
+
Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. Fall back to `latest` on an empty result.
|
|
65
65
|
|
|
66
66
|
When a checklist is produced, write it directly to `.canon/tmp/handoff/ui-checklist/<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite. This is a handoff file rather than a deliverable: `git-pr` renders it into the evidence comment once a pull request opens, then removes it, and nothing here talks to `gh` directly.
|
|
67
67
|
|
|
@@ -61,7 +61,7 @@ If nothing is wrong, use: `✅ No observations.`
|
|
|
61
61
|
|
|
62
62
|
### Persist
|
|
63
63
|
|
|
64
|
-
Derive `<slug>` per `${CLAUDE_SKILL_DIR}
|
|
64
|
+
Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. Fall back to `latest` on an empty result.
|
|
65
65
|
|
|
66
66
|
Write the full report directly to `.canon/review/ux-audit-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite.
|
|
67
67
|
|
|
@@ -108,7 +108,7 @@ Report the reading and stop there. A remedy for a poor verdict is a change with
|
|
|
108
108
|
|
|
109
109
|
### Persist
|
|
110
110
|
|
|
111
|
-
Derive `<slug>` per `${CLAUDE_SKILL_DIR}
|
|
111
|
+
Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. Fall back to `latest` on an empty result.
|
|
112
112
|
|
|
113
113
|
Write the full reading directly to `.canon/review/ux-measure-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite.
|
|
114
114
|
|
package/docs/agents/canvas.md
CHANGED
|
@@ -5,7 +5,7 @@ description: The canvas server, its content format, and the verbs that list, arr
|
|
|
5
5
|
|
|
6
6
|
# Canvas
|
|
7
7
|
|
|
8
|
-
`canon canvas` serves a local canvas of pages and HTML frames and gives an agent the verbs the operator's mouse has. A page is a folder under `.canon/canvas/`, a frame is one HTML file in it, and `layout.json` beside them holds each frame's box. `claude/skills/canvas/references/canvas.md` fixes that content format, and the `canvas` skill carries the procedure a session follows to drive the canvas.
|
|
8
|
+
`canon canvas` serves a local canvas of pages and HTML frames and gives an agent the verbs the operator's mouse has. A page is a folder under `.canon/canvas/`, a frame is one HTML file in it, and `layout.json` beside them holds each frame's box. `claude/skills/canvas-board/references/canvas.md` fixes that content format, and the `canvas-board` skill carries the procedure a session follows to drive the canvas.
|
|
9
9
|
|
|
10
10
|
## Serve
|
|
11
11
|
|
package/docs/agents/commands.md
CHANGED
|
@@ -108,7 +108,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
|
|
|
108
108
|
- `gate`, in `gate.md`: `run`
|
|
109
109
|
- `secrets`, in `state-scoped-risk.md`: `scan`
|
|
110
110
|
- `deps`, in `state-scoped-risk.md`: `audit`
|
|
111
|
-
- `labels`, in `label-coverage.md`: `audit`, `scan`
|
|
111
|
+
- `labels`, in `label-coverage.md`: `audit`, `apply`, `scan`
|
|
112
112
|
- `comments`, in `comments.md`: `scan`
|
|
113
113
|
- `context`, in `context-audit.md`: `audit`, `classify diff`, `classify sweep`, `classifier show`, `classifier set`
|
|
114
114
|
- `markdown`, in `markdown-audit.md`: `audit`
|
|
@@ -129,7 +129,8 @@ Subcommands no other page describes:
|
|
|
129
129
|
- `slides render [deck]` takes a deck name or a folder, defaulting to the only deck, and lays out each `.html` file in filename order in Chromium at 1280 by 720 and rebuilds it as editable shapes. Each element drawn as a picture prints one `✗` line on stderr naming the slide, the selector, and the properties that forced it. A link left out, being a `#slide-N` past the deck's end or any target that is neither that nor an absolute URL, prints one too, and the exit stays 0.
|
|
130
130
|
- A deck folder's `deck.json` and the faces it embeds, its per-slide `<body>` attributes, transitions and entrances, speaker notes, and charts are described in `slides.md`.
|
|
131
131
|
- `canvas`, with its verbs, content format, and write routes, is described in `canvas.md`.
|
|
132
|
-
- `labels
|
|
132
|
+
- `labels apply <number>` adds the labels this branch earns to its open pull request, refusing a pull request whose head is not the current branch or that is not open, and never creating a label the remote lacks or removing one a person added (`--check` writes nothing and exits 2 when labels are owed, `--base`, `--json`).
|
|
133
|
+
- `labels scan` fails a pull request or a posted review whose title, body, or review comment carries a phase label, a label a code span quotes, a gitignored record path, a session link, a banned character, a body heading outside the closed section list or a missing `## Summary` or `## Key changes`, a title word no dictionary holds, or a title breaking `claude/skills/git-pr/references/pr.md`'s format, casing, or length rule (`--event`, `--body-file`, `--json`).
|
|
133
134
|
|
|
134
135
|
## Version skew
|
|
135
136
|
|