@erclx/canon 5.39.0 → 5.41.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 +39 -22
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
- package/claude/skills/auto-ship/SKILL.md +6 -0
- package/claude/skills/auto-ship/references/fan-in.md +59 -0
- package/claude/skills/canvas-board/SKILL.md +1 -1
- package/claude/skills/create-skill/references/skill.md +1 -1
- package/claude/skills/decision-escalate/REQUIREMENT.md +1 -1
- package/claude/skills/decision-escalate/SKILL.md +1 -2
- package/claude/skills/draft-slides/SKILL.md +2 -3
- package/claude/skills/draft-slides/references/deck.md +183 -0
- package/claude/skills/git-branch/REQUIREMENT.md +17 -6
- package/claude/skills/git-branch/SKILL.md +63 -7
- package/claude/skills/git-pr/references/evidence.md +2 -2
- package/claude/skills/git-pr/references/final-command.md +1 -1
- package/claude/skills/git-pr/references/labels.md +1 -1
- package/claude/skills/git-pr/references/publish.md +1 -1
- package/claude/skills/plan-feature/references/batches.md +48 -1
- package/claude/skills/plan-feature/references/plan.md +2 -0
- package/claude/skills/plan-intake-answer/REQUIREMENT.md +1 -1
- package/claude/skills/plan-intake-answer/SKILL.md +1 -2
- package/claude/skills/review-address/references/rebase-conflicts.md +7 -0
- package/claude/skills/review-ui/SKILL.md +3 -0
- package/claude/skills/review-ui/references/close-out.md +47 -0
- package/claude/skills/review-ui/references/post.md +3 -1
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +1 -0
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
- package/claude/skills/role-worker/REQUIREMENT.md +1 -0
- package/claude/skills/role-worker/SKILL.md +9 -0
- package/claude/skills/task-board/references/board.md +1 -1
- package/claude/skills/task-board/references/tasks.md +1 -1
- package/claude/skills/teach-workspace/REQUIREMENT.md +1 -1
- package/claude/skills/teach-workspace/SKILL.md +1 -2
- package/claude/skills/ux-measure/SKILL.md +1 -1
- package/docs/agents/audits.md +61 -60
- package/docs/agents/context-audit.md +40 -58
- package/docs/agents/index.md +5 -51
- package/docs/agents/install-and-sync.md +1 -0
- package/docs/agents/markdown-audit.md +53 -99
- package/docs/agents/records.md +37 -79
- package/docs/agents/sessions-transfer.md +26 -70
- package/docs/target/index.md +0 -1
- package/docs/target/migrations.md +57 -66
- package/docs/target/projects.md +36 -78
- package/docs/target/scenarios.md +9 -19
- package/docs/target/sync.md +27 -68
- package/docs/workflow/ai-workflow.md +22 -68
- package/docs/workflow/operating-model.md +32 -186
- package/docs/workflow/parallel-features.md +30 -66
- package/docs/workflow/skill-map-on-request.md +22 -24
- package/docs/workflow/skill-map.md +72 -76
- package/docs/workflow/visual-design-workflow.md +25 -118
- package/docs/workflow/zshrc-aliases.md +18 -37
- package/package.json +1 -1
- package/src/canvas/client/inspector/fields.css +4 -0
- package/src/canvas/index.html +6 -0
- package/src/claude/cases/git.ts +4 -0
- package/src/claude/skills-reach.ts +2 -2
- package/src/cli/ui.ts +3 -1
- package/src/commands/canvas.ts +23 -0
- package/src/commands/capture.ts +14 -0
- package/src/commands/claude.ts +13 -0
- package/src/commands/demo.ts +22 -0
- package/src/commands/deps.ts +6 -0
- package/src/commands/driver.ts +28 -2
- package/src/commands/gov.ts +52 -18
- package/src/commands/intake.ts +17 -0
- package/src/commands/labels.ts +38 -5
- package/src/commands/pr.ts +192 -52
- package/src/commands/records.ts +19 -3
- package/src/commands/secrets.ts +6 -0
- package/src/commands/sessions.ts +8 -0
- package/src/commands/tasks.ts +52 -0
- package/src/commands/teach.ts +13 -0
- package/src/commands/upstream.ts +25 -1
- package/src/commands/worktrees.ts +5 -0
- package/src/context/audit.ts +22 -4
- package/src/context/folders.ts +1 -1
- package/src/context/shape-gated.ts +5 -2
- package/src/counts/scan.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/design/document.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/gate/boundaries.ts +4 -1
- package/src/gate/measures.ts +1 -1
- package/src/gate/stages.ts +7 -7
- package/src/git/env.ts +6 -0
- package/src/markdown/scope.ts +11 -19
- package/src/pr/frames.ts +53 -9
- package/src/pr/lift.ts +153 -19
- package/src/pr/painted.ts +87 -0
- package/src/records/validate.ts +1 -0
- package/src/roots/record.ts +18 -1
- package/src/sandbox/census.ts +1 -1
- package/src/sandbox/headless/run.ts +3 -2
- package/src/sandbox/headless/watch.ts +3 -4
- package/src/slides/convert/master.ts +3 -0
- package/src/sync/format.ts +46 -0
- package/src/sync/stamp.ts +6 -0
- package/src/tasks/answers.ts +79 -2
- package/src/tasks/fan-in.ts +176 -0
- package/src/tasks/stack.ts +1 -1
- package/tooling/astro/reference.md +80 -39
- package/tooling/base/reference.md +63 -32
- package/tooling/base/seeds/canon/context/ci.md +7 -15
- package/tooling/base/seeds/canon/context/development.md +14 -14
- package/tooling/claude/reference.md +40 -22
- package/tooling/cloudflare/reference.md +31 -12
- package/tooling/go/reference.md +47 -23
- package/tooling/nextjs/reference.md +52 -19
- package/tooling/php/reference.md +35 -16
- package/tooling/python/reference.md +47 -30
- package/tooling/shell/reference.md +6 -5
- package/tooling/vite-react/reference.md +49 -21
- package/tooling/web/reference.md +131 -71
- package/docs/agents/canvas.md +0 -86
- package/docs/agents/capture.md +0 -65
- package/docs/agents/census.md +0 -23
- package/docs/agents/comments.md +0 -34
- package/docs/agents/context-audit-checks.md +0 -108
- package/docs/agents/context-classify.md +0 -101
- package/docs/agents/counts.md +0 -74
- package/docs/agents/demo.md +0 -140
- package/docs/agents/driver.md +0 -103
- package/docs/agents/gate.md +0 -90
- package/docs/agents/hooks.md +0 -78
- package/docs/agents/intake.md +0 -81
- package/docs/agents/key-changes.md +0 -116
- package/docs/agents/label-coverage.md +0 -86
- package/docs/agents/markdown-audit-density.md +0 -39
- package/docs/agents/markdown-audit-weight.md +0 -83
- package/docs/agents/pr-evidence-layout.md +0 -70
- package/docs/agents/pr-evidence.md +0 -273
- package/docs/agents/pr-frames.md +0 -131
- package/docs/agents/pr-lift.md +0 -132
- package/docs/agents/pr-local.md +0 -111
- package/docs/agents/pr-preview.md +0 -155
- package/docs/agents/pr-reads.md +0 -111
- package/docs/agents/pr-tick.md +0 -72
- package/docs/agents/records-push.md +0 -61
- package/docs/agents/records-stale.md +0 -40
- package/docs/agents/records-validate.md +0 -57
- package/docs/agents/restated.md +0 -83
- package/docs/agents/routing.md +0 -61
- package/docs/agents/rule-citations.md +0 -90
- package/docs/agents/sandbox.md +0 -126
- package/docs/agents/sessions.md +0 -128
- package/docs/agents/skills-audit.md +0 -120
- package/docs/agents/skills-reach.md +0 -64
- package/docs/agents/slides.md +0 -176
- package/docs/agents/state-scoped-risk.md +0 -105
- package/docs/agents/superseded.md +0 -85
- package/docs/agents/tasks-archive.md +0 -83
- package/docs/agents/tasks-plans.md +0 -152
- package/docs/agents/tasks-validate.md +0 -133
- package/docs/agents/tasks.md +0 -123
- package/docs/agents/teach-authoring.md +0 -118
- package/docs/agents/teach.md +0 -157
- package/docs/agents/test-order.md +0 -58
- package/docs/agents/upstream.md +0 -94
- package/docs/agents/worktrees.md +0 -118
- package/docs/target/standards-moved.md +0 -34
package/README.md
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
|
|
14
14
|
canon is a CLI and Claude Code plugin that runs your agent's work from plan to merge, holds it to the practices that make code worth keeping, and installs the same setup in every repository.
|
|
15
|
-
|
|
16
15
|
**[See it run at canon.erclx.dev](https://canon.erclx.dev)**
|
|
17
16
|
|
|
18
17
|
</div>
|
|
@@ -21,9 +20,13 @@ That page is one real session the toolkit ran on itself, and every count on it i
|
|
|
21
20
|
|
|
22
21
|
## Why
|
|
23
22
|
|
|
24
|
-
If an agent writes code for you in more than one repository, this is for you. canon runs that work from plan to merge. A planner writes the plan, a worker builds it on its own branch, and a separate session reviews the pull request.
|
|
23
|
+
If an agent writes code for you in more than one repository, this is for you. canon runs that work from plan to merge. A planner writes the plan, a worker builds it on its own branch, and a separate session reviews the pull request.
|
|
24
|
+
|
|
25
|
+
It holds the work to a practice, with rules that load when a matching path is edited and checks that fail when a rule is ignored. Both run on one setup, installed the same way in every repository you keep.
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
### The shared setup
|
|
28
|
+
|
|
29
|
+
That shared setup is what the rest of this page describes, and it drifts without a source. Every AI coding setup accumulates the same assets. Prompts to reuse, rules agents should follow, slash commands, skills, seed docs, sync scripts. Once you have enough projects, your copies drift and your agents stop getting consistent signals.
|
|
27
30
|
|
|
28
31
|
Three design choices shape the toolkit.
|
|
29
32
|
|
|
@@ -61,17 +64,21 @@ bun install --global @erclx/canon
|
|
|
61
64
|
|
|
62
65
|
Each domain has a canonical source in this repo and a thin install or sync CLI on your side. The domains split on one line: some are copied into your project and become yours to edit, and some are never copied at all.
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
67
|
+
### Domain catalog
|
|
68
|
+
|
|
69
|
+
| Domain | What it is | How it reaches you |
|
|
70
|
+
| -------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
|
|
71
|
+
| Plugin skills | Skills that plan a feature, review a diff, sync the planning docs, and run the ship chain | Loaded live from the plugin, never copied |
|
|
72
|
+
| Governance | Coding and authoring rules that load into a Claude session when a matching path is edited | Installed per project by `canon gov install`, refreshed by sync |
|
|
73
|
+
| Tooling stacks | Golden configs, seeds, and a reference per framework | Laid down by `canon init`, reconciled by `canon tooling sync` |
|
|
74
|
+
| Design system | Ships a `DESIGN.md` intent format pointing at your stylesheet for values, a skill that drafts one, and a render command | `canon design render` |
|
|
75
|
+
| Slides | A folder of HTML slides per deck, drawn in the project's tokens and rebuilt as editable shapes | `canon slides render` writes PowerPoint |
|
|
76
|
+
| Teach | Lessons, sources, and a glossary in one workspace, rendered to a small site | `canon teach` |
|
|
77
|
+
| Canvas | Pages of HTML frames on a local pan and zoom surface, each frame drawn with the project's tokens | `canon canvas serve` |
|
|
78
|
+
| Transcripts | A YouTube transcript with metadata frontmatter | `canon transcripts <url>` writes it into any repo |
|
|
79
|
+
| Sandbox | Scenario scaffolds that provision an isolated project state for verifying each domain flow | `canon sandbox` |
|
|
80
|
+
|
|
81
|
+
### How domains reach you
|
|
75
82
|
|
|
76
83
|
Those domains reach you in three shapes. A tooling stack lands as real files under version control, because a config is something your build reads and your project owns. A plugin skill and the references it carries are never copied, so there is no copy in your repo to drift from this one.
|
|
77
84
|
|
|
@@ -117,6 +124,8 @@ The first two update the skills, the third updates the CLI, and they move indepe
|
|
|
117
124
|
|
|
118
125
|
`canon upgrade` reads the package manager off its own install path and reinstalls with that one, so you don't have to remember which put it there. It names what it detected before it runs anything, and it refuses a source checkout rather than reinstalling over your clone.
|
|
119
126
|
|
|
127
|
+
### Checking for drift
|
|
128
|
+
|
|
120
129
|
You don't have to wait until something breaks to find out you're behind. `canon sync --check` and `canon claude skills drift` both report the installed version against the newest published one, and neither changes its exit code over it, so an offline machine reads unknown rather than red.
|
|
121
130
|
|
|
122
131
|
To stop doing this by hand, turn auto-update on once under `/plugin` in the Marketplaces tab. Confirm what you are running with `canon --version` and `claude plugin list`.
|
|
@@ -127,6 +136,8 @@ Working on the toolkit starts from a clone. Running the CLI doesn't, since it in
|
|
|
127
136
|
|
|
128
137
|
### Prerequisites
|
|
129
138
|
|
|
139
|
+
Bun, Git, and a shell are required, and the GitHub CLI is optional.
|
|
140
|
+
|
|
130
141
|
- [Bun](https://bun.sh) for the CLI runtime and scripts
|
|
131
142
|
- [Git](https://git-scm.com) with worktree support
|
|
132
143
|
- [GitHub CLI](https://cli.github.com) (optional) for ship flows
|
|
@@ -141,7 +152,10 @@ bun install
|
|
|
141
152
|
bun run bootstrap
|
|
142
153
|
```
|
|
143
154
|
|
|
144
|
-
The script is idempotent, so re-run it after pulling upstream changes without duplicating anything.
|
|
155
|
+
The script is idempotent, so re-run it after pulling upstream changes without duplicating anything. It confirms the install by resolving `canon --help` on the last step.
|
|
156
|
+
|
|
157
|
+
- 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.
|
|
158
|
+
- [Zshrc aliases](docs/workflow/zshrc-aliases.md) covers what each alias does, how to pick up a new one, and how to opt out of the block.
|
|
145
159
|
|
|
146
160
|
With the CLI linked, scaffold a fresh project.
|
|
147
161
|
|
|
@@ -151,9 +165,12 @@ git init
|
|
|
151
165
|
canon init
|
|
152
166
|
```
|
|
153
167
|
|
|
154
|
-
`canon init` installs base tooling configs, Claude seeds, and governance rules in one pass, and scaffolds a `.claude/wiki/` stub for your project's own reference pages.
|
|
168
|
+
`canon init` installs base tooling configs, Claude seeds, and governance rules in one pass, and scaffolds a `.claude/wiki/` stub for your project's own reference pages.
|
|
155
169
|
|
|
156
|
-
|
|
170
|
+
- Governance defaults to the `base` stack, so a bare init lands the workflow and doc-authoring rules in `.claude/rules/`.
|
|
171
|
+
- Each rule names the skill it loads, so no corpus is copied into your project.
|
|
172
|
+
- Pass `--stack <name>` for a language stack such as `node` or `python`, or `--skip governance` to leave rules out.
|
|
173
|
+
- Run `canon tooling list --json` to see the catalog.
|
|
157
174
|
|
|
158
175
|
For the full journey from scaffold through adding a domain later to syncing upstream drift, see [target projects](docs/target/projects.md).
|
|
159
176
|
|
|
@@ -161,13 +178,13 @@ For the full journey from scaffold through adding a domain later to syncing upst
|
|
|
161
178
|
|
|
162
179
|
Each domain carries an entry written for someone maintaining the toolkit rather than installing it. These paths resolve in a clone only. The published package ships `docs` and not `.claude`, so an installed copy does not carry them.
|
|
163
180
|
|
|
164
|
-
- [Claude Code plugin](canon/context/
|
|
165
|
-
- [Governance rules](canon/context/governance
|
|
166
|
-
- [Tooling stacks](canon/context/tooling
|
|
167
|
-
- [Design system](canon/context/design.md)
|
|
181
|
+
- [Claude Code plugin](canon/context/surfaces/plugin.md)
|
|
182
|
+
- [Governance rules](canon/context/surfaces/governance.md)
|
|
183
|
+
- [Tooling stacks](canon/context/surfaces/tooling.md)
|
|
184
|
+
- [Design system](canon/context/features/design.md)
|
|
168
185
|
- [Slides](canon/context/features/slides.md)
|
|
169
186
|
- [Transcripts](canon/context/features/transcripts.md)
|
|
170
|
-
- [Sandbox](canon/context/sandbox
|
|
187
|
+
- [Sandbox](canon/context/development/sandbox.md)
|
|
171
188
|
|
|
172
189
|
## Contributing
|
|
173
190
|
|
|
@@ -19,6 +19,7 @@ Without this skill, the run from an approved plan to an open pull request is a c
|
|
|
19
19
|
- Open the pull request as a draft before the continuous integration watch begins, since a pull request marked after it is mergeable for the length of the run
|
|
20
20
|
- Continue past a produced UI checklist rather than stopping on it, and report its unchecked boxes in the closing block, since the draft mark already holds the merge
|
|
21
21
|
- Prove the draft target's head is the current branch and its state is open before marking it, and stop with nothing marked on a mismatch, since the number is retyped between steps and a draft mark on a release pull request holds that release
|
|
22
|
+
- Stop a fan-in member after its verify and test order with a push and a done message rather than a pull request, and open an integrator's build by merging the member branches, since parallel batches sharing edge files put every open sibling into conflict on each merge
|
|
22
23
|
- Name the recovery for the stop it took, since the value of stopping is that the user knows where to resume
|
|
23
24
|
|
|
24
25
|
## Must not
|
|
@@ -73,6 +73,8 @@ When this run decides against a suggestion, rewrite its line as `overridden at e
|
|
|
73
73
|
|
|
74
74
|
Load `canon:build-in-slices`, reporting it when it does not resolve, and implement only what the plan describes. Do not expand scope, refactor neighbors, or touch files outside the plan's "Files to touch" list without reason.
|
|
75
75
|
|
|
76
|
+
When the plan's `**Constraints:**` carry a `Fans in` bullet, this run is a fan-in integrator, so open this step by merging the member branches, per `${CLAUDE_SKILL_DIR}/references/fan-in.md`.
|
|
77
|
+
|
|
76
78
|
## Step 3: verify
|
|
77
79
|
|
|
78
80
|
Run the verify commands defined in `CLAUDE.md` (lint, typecheck, tests). On failure:
|
|
@@ -97,6 +99,10 @@ The verb reads git history rather than the working tree, so it catches a violati
|
|
|
97
99
|
|
|
98
100
|
Never read a missing subcommand as clean. Read `${CLAUDE_SKILL_DIR}/references/verb-absent.md` on meeting one.
|
|
99
101
|
|
|
102
|
+
### A fan-in member stops here
|
|
103
|
+
|
|
104
|
+
When the plan's `**Constraints:**` carry a `Fan-in member of` bullet, push the branch, announce it done, and stop before Step 5. A member opens no pull request, since its integrator ships the whole set. Read `${CLAUDE_SKILL_DIR}/references/fan-in.md` for the push and the message.
|
|
105
|
+
|
|
100
106
|
## Step 5: UI checklist (conditional)
|
|
101
107
|
|
|
102
108
|
If the diff touches UI files (JSX, TSX, Vue, Svelte, HTML, or CSS under `src/`), invoke `canon:ui-checklist`, then continue to Step 6 whatever it returns, in every run. The Step 6 draft mark holds the merge, so a stop here protects nothing.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Fan-in member exit and integrator merge
|
|
3
|
+
description: How auto-ship stops a fan-in member after its push and how an integrator merges the member branches before its own build, so a set of parallel batches ships as one pull request
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fan-in
|
|
7
|
+
|
|
8
|
+
The session reads this file at one of two points in `auto-ship`. A member reads `## Member exit` after Step 4, and an integrator reads `## Integrator merge` at the opening of Step 2. When to fan in and how a plan declares its side are in `${CLAUDE_SKILL_DIR}/../plan-feature/references/batches.md`.
|
|
9
|
+
|
|
10
|
+
## Member exit
|
|
11
|
+
|
|
12
|
+
Step 3's verify and Step 4's test order have already run, so the branch is green and committed. The member ends here rather than at a pull request.
|
|
13
|
+
|
|
14
|
+
1. Push the branch with `git push -u origin <branch>`. The pre-push hook runs the project check, and a member that fails it stops the way Step 3 does.
|
|
15
|
+
2. Read the head with `git rev-parse HEAD` once the push returns.
|
|
16
|
+
3. Announce the batch done to the controlling session through `canon:session-relay`, carrying the branch, the head commit, the integrator the plan names, and any row this build turned up.
|
|
17
|
+
4. Stop. Run no UI checklist, no `git-ship`, and no draft mark.
|
|
18
|
+
|
|
19
|
+
The pushed branch is the done signal the integrator's gate reads, so push once, at the end, and never mid-build. The announcement carries no reach, since members of one set share files by design and the integrator's announcement carries the reach for the whole set.
|
|
20
|
+
|
|
21
|
+
A fix the integrator needs after this point lands on the integrator's branch, since a member has no pull request to fix it on.
|
|
22
|
+
|
|
23
|
+
## Integrator merge
|
|
24
|
+
|
|
25
|
+
The members are pushed before this run starts, since `canon tasks plan-answers` holds an integrator until every member branch is on origin. Confirm that before merging anything:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git fetch origin --quiet
|
|
29
|
+
canon tasks plan-answers <plan> --json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Stop on `launchable: false`, reporting each `open` entry, since a `Fan-in pending` entry names a member that has not pushed and a `Fan-in set` entry names a set whose sides disagree. Then merge each member in the order the `Fans in` bullet lists:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git merge --no-ff --no-edit origin/<member branch>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Conflicts and the order
|
|
39
|
+
|
|
40
|
+
`--no-ff` keeps one merge commit per member, so `git log --first-parent` shows the reviewer one member at a time. Never squash or fast-forward a member in.
|
|
41
|
+
|
|
42
|
+
- Resolve each conflict by `## Resolving a conflict` in `${CLAUDE_SKILL_DIR}/../review-address/references/rebase-conflicts.md`
|
|
43
|
+
- Stop on a hunk needing a decision with `git merge --abort` in place of the rebase abort that file names
|
|
44
|
+
- Regenerate the indexes once, after the last merge, rather than resolving a generated file by hand at each one
|
|
45
|
+
- Run `git config rerere.enabled true` before the first merge, since a stale integrator rebases with `--rebase-merges` per the same file and that replays each merge without its recorded resolution
|
|
46
|
+
|
|
47
|
+
Continue Step 2 with the integrator plan's own `**Files to touch:**`, then the rest of the chain as an ordinary worker.
|
|
48
|
+
|
|
49
|
+
### What the pull request carries
|
|
50
|
+
|
|
51
|
+
Say in the pull request body that each member is one merge commit and name the members in merge order. Once the pull request merges, delete each member's branch on origin, its worktree, and its local branch:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git push origin --delete <member branch>
|
|
55
|
+
git worktree remove <member worktree>
|
|
56
|
+
git branch -D <member branch>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Read each member's worktree path off `git worktree list --porcelain` by its branch. The integrator holds the member list, so the deletion is its step rather than a sweep's. No member opens a pull request, so `canon worktrees reclaim` never reads a member's branch as merged and reports a leftover worktree as unmerged work on every run.
|
|
@@ -9,7 +9,7 @@ metadata:
|
|
|
9
9
|
|
|
10
10
|
Drive the canvas the operator is looking at. A page is a folder of HTML frames and a frame is one file, so a session draws by writing files and the operator sees each write land in the browser. The content format is fixed by `${CLAUDE_SKILL_DIR}/references/canvas.md`. Read it before writing a frame.
|
|
11
11
|
|
|
12
|
-
Every verb below is `canon canvas`. Run `canon
|
|
12
|
+
Every verb below is `canon canvas`. Run `canon canvas --help` for the verbs and their refusals, and read `${CLAUDE_SKILL_DIR}/references/canvas.md` for the content format.
|
|
13
13
|
|
|
14
14
|
## Guards
|
|
15
15
|
|
|
@@ -104,7 +104,7 @@ allowed-tools: <tools required>
|
|
|
104
104
|
|
|
105
105
|
- **`name`** (required): kebab-case, matches folder name, no spaces or capitals
|
|
106
106
|
- **`description`** (required): what it does + when to use it, under 1024 chars, no XML tags
|
|
107
|
-
- **`disable-model-invocation: true`**:
|
|
107
|
+
- **`disable-model-invocation: true`**: Claude will not auto-trigger, and the `Skill` tool also refuses the operator's own request made in words. Set it only on a skill run by slash command alone. A skill wanting just the first effect writes `Do NOT auto-trigger` in its description.
|
|
108
108
|
- **`allowed-tools`**: restrict tool access when the skill is active
|
|
109
109
|
- **`metadata`**: optional key-value pairs (`author`, `version`, `mcp-server`)
|
|
110
110
|
- **`metadata.family`** (required on a skill under `claude/skills/`): the skill map group the skill's row sits under, as one key from `families` in `canon claude skills list --json`. A skill under `.claude/skills/` takes none.
|
|
@@ -41,4 +41,4 @@ The opposite failure is the one that ships silently. A session that takes a pref
|
|
|
41
41
|
|
|
42
42
|
- Making the ordinary judgment call, which is a pick plus a one-sentence tradeoff and needs no surface
|
|
43
43
|
- Writing the decision into a plan, task, or context entry, which each owning standard governs and this skill only routes to
|
|
44
|
-
- Deciding when to fire. The
|
|
44
|
+
- Deciding when to fire. The description states `Do NOT auto-trigger`, so escalating is the operator's call rather than a description match.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: decision-escalate
|
|
3
|
-
description: Collects every open decision whose answer turns on the operator's preference, since only they know what they need, puts them as one batch of questions each carrying options and a recommended default, then waits. Use when asked to "escalate this", "ask me the open questions", "batch the open decisions", "what do you need from me", or "stop and ask before you pick". Do NOT use for a judgment call the session can settle, which is a pick with the tradeoff stated in one sentence.
|
|
4
|
-
disable-model-invocation: true
|
|
3
|
+
description: Collects every open decision whose answer turns on the operator's preference, since only they know what they need, puts them as one batch of questions each carrying options and a recommended default, then waits. Use when asked to "escalate this", "ask me the open questions", "batch the open decisions", "what do you need from me", or "stop and ask before you pick". Do NOT use for a judgment call the session can settle, which is a pick with the tradeoff stated in one sentence. Do NOT auto-trigger.
|
|
5
4
|
metadata:
|
|
6
5
|
family: decide
|
|
7
6
|
---
|
|
@@ -11,16 +11,15 @@ Draw each slide as an HTML file in a deck folder, then shell out to `canon slide
|
|
|
11
11
|
|
|
12
12
|
## Read the decks and the format
|
|
13
13
|
|
|
14
|
-
Run
|
|
14
|
+
Run the list first, then read the format. Never hardcode a deck name, an attribute, or a chart type.
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
17
|
canon slides list --json 2>/dev/null
|
|
18
|
-
canon docs slides
|
|
19
18
|
```
|
|
20
19
|
|
|
21
20
|
The list returns one row per deck, carrying its `name`, `title`, slide count, and `path`. When the request names a deck the list holds, edit that folder. Otherwise pick a new kebab-case name no row carries.
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
Read `${CLAUDE_SKILL_DIR}/references/deck.md`. It states what `deck.json` holds, what each slide declares on its `<body>`, the motion attributes, speaker notes, and charts. Each refusal prints as a `✗` line from the render.
|
|
24
23
|
|
|
25
24
|
## Draw the deck
|
|
26
25
|
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Deck reference
|
|
3
|
+
description: The deck folder, the deck.json fields, the attributes a slide sets on its body, motion, the master's token roles, speaker notes, and charts
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deck reference
|
|
7
|
+
|
|
8
|
+
Applies to the slides under `.canon/slides/<deck>/`, which `canon slides render <deck>` turns into an editable PowerPoint file. Each slide describes its own shapes. What belongs to the whole deck sits in `deck.json`.
|
|
9
|
+
|
|
10
|
+
## Contents
|
|
11
|
+
|
|
12
|
+
- [The deck folder](#the-deck-folder)
|
|
13
|
+
- [The deck file](#the-deck-file)
|
|
14
|
+
- [What each slide declares](#what-each-slide-declares)
|
|
15
|
+
- [Motion](#motion)
|
|
16
|
+
- [The master](#the-master)
|
|
17
|
+
- [Speaker notes](#speaker-notes)
|
|
18
|
+
- [Charts](#charts)
|
|
19
|
+
|
|
20
|
+
## The deck folder
|
|
21
|
+
|
|
22
|
+
| Path | Holds |
|
|
23
|
+
| -------------------------------- | ---------------------------------------------------- |
|
|
24
|
+
| `.canon/slides/<deck>/*.html` | the slides, rendered in filename order |
|
|
25
|
+
| `.canon/slides/<deck>/deck.json` | what belongs to the whole deck |
|
|
26
|
+
| `.canon/slides/<deck>/assets/` | images the slides reference by a relative path |
|
|
27
|
+
| `.canon/slides/layouts/` | the project's shared layouts, never listed as a deck |
|
|
28
|
+
|
|
29
|
+
A folder holding no `.html` file is not a deck. `render` with no name takes the only deck, and refuses with the list when there are several. It also takes a folder path outside `.canon/slides/`.
|
|
30
|
+
|
|
31
|
+
## The deck file
|
|
32
|
+
|
|
33
|
+
`deck.json` is optional. Without it the deck takes the defaults below.
|
|
34
|
+
|
|
35
|
+
| Field | Default | What it sets |
|
|
36
|
+
| -------------- | ------------------------------ | ------------------------------------------------- |
|
|
37
|
+
| `title` | the folder name | the file's title and the default footer text |
|
|
38
|
+
| `header` | off | a band at the top, with `left`, `center`, `right` |
|
|
39
|
+
| `footer` | on, with the title on the left | a band at the bottom, with the same three slots |
|
|
40
|
+
| `slideNumbers` | `true` | the number at the right of the footer |
|
|
41
|
+
| `mark` | none | an image path, relative to the folder, top right |
|
|
42
|
+
| `fonts` | none | faces to embed in the file |
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"title": "Q3 review",
|
|
47
|
+
"header": { "left": "Acme" },
|
|
48
|
+
"footer": { "center": "Internal" },
|
|
49
|
+
"mark": "assets/mark.png",
|
|
50
|
+
"fonts": [
|
|
51
|
+
{ "family": "Inter", "path": "fonts/Inter-Regular.ttf" },
|
|
52
|
+
{ "family": "Inter", "weight": 700, "path": "fonts/Inter-Bold.ttf" }
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Bands and the mark
|
|
58
|
+
|
|
59
|
+
A band takes `show` and the three slots. A declared band merges over its default, so `"footer": { "center": "Internal" }` keeps the title on the left. Declaring any slot turns a band on unless it also says `"show": false`. Set a slot to `""` to empty it.
|
|
60
|
+
|
|
61
|
+
- Slide numbers hold the footer's right slot and show only where the footer does. Set `slideNumbers` to `false` to use `footer.right`.
|
|
62
|
+
- Prefer a raster mark, since an SVG mark lands as a vector with a broken fallback.
|
|
63
|
+
|
|
64
|
+
### Embedded faces
|
|
65
|
+
|
|
66
|
+
Each `fonts` entry names one TrueType or OpenType file inside the deck folder:
|
|
67
|
+
|
|
68
|
+
| Key | Default | Rule |
|
|
69
|
+
| -------- | -------- | ------------------------------------------------------------------- |
|
|
70
|
+
| `family` | required | match the family the slides set |
|
|
71
|
+
| `weight` | `400` | `600` and above fills the bold slot, anything lighter fills regular |
|
|
72
|
+
| `style` | `normal` | `normal` or `italic` |
|
|
73
|
+
| `path` | required | relative to the folder, and has to stay inside it |
|
|
74
|
+
|
|
75
|
+
A face is left out, and the deck still written, when its license forbids embedding, when it is a variable font or a `woff` or `woff2` file, or when a second face lands in a filled slot. Supply static instances, one per weight, and the TrueType or OpenType file a `woff2` was compressed from.
|
|
76
|
+
|
|
77
|
+
## What each slide declares
|
|
78
|
+
|
|
79
|
+
A slide sets its place in the deck through attributes on `<body>`.
|
|
80
|
+
|
|
81
|
+
| Attribute | Effect |
|
|
82
|
+
| --------------------------------------- | --------------------------------------------- |
|
|
83
|
+
| `data-section="Results"` | opens a section the slides after it stay in |
|
|
84
|
+
| `data-hidden` | hides the slide in the show |
|
|
85
|
+
| `data-header="off"` | drops the header on this slide |
|
|
86
|
+
| `data-footer="off"` | drops the footer and its number on this slide |
|
|
87
|
+
| `data-footer-left`, `-center`, `-right` | replaces that footer slot on this slide alone |
|
|
88
|
+
| `data-header-left`, `-center`, `-right` | replaces that header slot on this slide alone |
|
|
89
|
+
|
|
90
|
+
Once any slide opens a section, slides ahead of the first sit in a section named after the deck. A title the deck returns to after another section opens a new section numbered `Intro (2)`.
|
|
91
|
+
|
|
92
|
+
A slide dropping one band keeps the other from the master. A slide replacing a slot draws its band as its own text, so a later edit in the master view skips it.
|
|
93
|
+
|
|
94
|
+
## Motion
|
|
95
|
+
|
|
96
|
+
| Attribute | Takes | Effect |
|
|
97
|
+
| -------------------------- | ------------------------------- | -------------------------------------- |
|
|
98
|
+
| `data-transition` | `fade`, `push`, `wipe`, `cover` | the transition into this slide |
|
|
99
|
+
| `data-transition-duration` | `500`, `500ms`, or `0.5s` | rounded to 0.5, 0.75, or 1 second |
|
|
100
|
+
| `data-enter` | `fade`, `fly`, `wipe`, `zoom` | an entrance played on a click |
|
|
101
|
+
| `data-enter-order` | a number | the click it plays on, lowest first |
|
|
102
|
+
| `data-enter-duration` | `500`, `500ms`, or `0.5s` | the entrance length, 500 ms by default |
|
|
103
|
+
|
|
104
|
+
`data-transition` and `data-transition-duration` go on `<body>`. The `data-enter` family goes on the element.
|
|
105
|
+
|
|
106
|
+
```html
|
|
107
|
+
<body data-transition="fade">
|
|
108
|
+
<h1>Results</h1>
|
|
109
|
+
<div class="card" data-enter="fly" data-enter-order="1">…</div>
|
|
110
|
+
<div class="card" data-enter="fly" data-enter-order="2">…</div>
|
|
111
|
+
</body>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
- Each entrance is its own click, and entrances without an order play after the ordered ones, in page order.
|
|
115
|
+
- An entrance brings in every shape drawn from its element and the elements inside it, so a card's box and text arrive together.
|
|
116
|
+
- An inner element with its own `data-enter` waits for its own click.
|
|
117
|
+
- Fly comes in from the bottom and wipe from the left.
|
|
118
|
+
|
|
119
|
+
## The master
|
|
120
|
+
|
|
121
|
+
The master takes its colors from the `<html>` element of the first slide, laid out with the project's token stylesheet injected:
|
|
122
|
+
|
|
123
|
+
| Source | Used for |
|
|
124
|
+
| -------------------------------------------- | ---------------- |
|
|
125
|
+
| `--color-background` | the slide ground |
|
|
126
|
+
| `--color-text` | the header text |
|
|
127
|
+
| `--color-muted` | the footer text |
|
|
128
|
+
| `--color-accent` | the slide number |
|
|
129
|
+
| `<body>` font family, ` Variable` suffix cut | the theme face |
|
|
130
|
+
|
|
131
|
+
A role the project declares no token for falls back to the slide body's own color and prints one `✗` line naming it. It never falls back to the toolkit's palette.
|
|
132
|
+
|
|
133
|
+
A slide whose `<body>` background differs from the master's keeps its own. A slide whose `<body>` computes a `--color-text` apart from the master's prints a `✗` line, since its bands keep the master's colors and may not read against its ground.
|
|
134
|
+
|
|
135
|
+
## Speaker notes
|
|
136
|
+
|
|
137
|
+
`<aside class="notes">` becomes the slide's notes and is never drawn. Each paragraph or list item becomes its own line, and markup is dropped.
|
|
138
|
+
|
|
139
|
+
## Charts
|
|
140
|
+
|
|
141
|
+
A `<figure data-chart="...">` holding a `<table>` becomes a native, editable chart where the figure was laid out. The table is not drawn as well.
|
|
142
|
+
|
|
143
|
+
```html
|
|
144
|
+
<figure data-chart="bar" data-labels>
|
|
145
|
+
<figcaption>Revenue by region</figcaption>
|
|
146
|
+
<table>
|
|
147
|
+
<tr>
|
|
148
|
+
<th>Region</th>
|
|
149
|
+
<th>Q1</th>
|
|
150
|
+
<th>Q2</th>
|
|
151
|
+
</tr>
|
|
152
|
+
<tr>
|
|
153
|
+
<td>North</td>
|
|
154
|
+
<td>12</td>
|
|
155
|
+
<td>16</td>
|
|
156
|
+
</tr>
|
|
157
|
+
<tr>
|
|
158
|
+
<td>South</td>
|
|
159
|
+
<td></td>
|
|
160
|
+
<td>11</td>
|
|
161
|
+
</tr>
|
|
162
|
+
</table>
|
|
163
|
+
</figure>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
- `data-chart` takes `bar`, `line`, `area`, `pie`, or `doughnut`.
|
|
167
|
+
- The header row names the series and the first column names the categories.
|
|
168
|
+
- An empty cell is a gap, not a zero. A comma is a thousands separator only where it groups in threes, as in `12,345.5`, so a comma-decimal `3,5` refuses.
|
|
169
|
+
- `data-labels` shows each value, and a `<figcaption>` becomes the chart title.
|
|
170
|
+
- Series take the accent first, then every other declared `--color-*` role in sheet order except the background and surface, repeating past the last.
|
|
171
|
+
|
|
172
|
+
A refused chart, effect, or face is left out and the rest of the deck is written. Each prints a `✗` line, and the exit depends on the case:
|
|
173
|
+
|
|
174
|
+
| Case | Exit |
|
|
175
|
+
| ----------------------------------------------------------------------- | ---- |
|
|
176
|
+
| malformed or unknown `deck.json` field | 1 |
|
|
177
|
+
| `mark` path missing | 1 |
|
|
178
|
+
| `fonts` path missing or outside the folder | 1 |
|
|
179
|
+
| face that cannot embed | 0 |
|
|
180
|
+
| unknown transition or entrance name | 0 |
|
|
181
|
+
| entrance on an element that draws nothing | 0 |
|
|
182
|
+
| chart cell that is not a number, or `data-chart` off-list | 0 |
|
|
183
|
+
| token role not declared, or a slide body setting its own `--color-text` | 0 |
|
|
@@ -9,12 +9,17 @@ description: What branch naming is for, the gaps it closes, and where the family
|
|
|
9
9
|
|
|
10
10
|
Without this skill, a branch name is invented once per session. The type prefix drifts from what the history already carries, the name runs past the width a pull request list renders, and a rename lands on a branch that already exists on the remote, which detaches every open pull request pointing at it.
|
|
11
11
|
|
|
12
|
+
A session standing on `main` has no route either. The `git.md` rule sends every git operation through a `git-*` skill, and the only one for branches stopped on `Cannot rename a protected branch`, so the first act of any feature, creating its branch, had no skill to go through.
|
|
13
|
+
|
|
12
14
|
## Must
|
|
13
15
|
|
|
14
16
|
- Read the branch format reference before generating, so the type vocabulary and the length limit come from one source
|
|
15
|
-
-
|
|
17
|
+
- Create the branch on `main` or `master` and rename it anywhere else, so one skill covers both ends of a branch's start
|
|
18
|
+
- Derive the name from the commits ahead of main when a rename carries no description
|
|
19
|
+
- Take a created name from `canon tasks plan-branch` when the invocation names a plan, so the skill and the dispatch gate hold one derivation
|
|
16
20
|
- Resolve whether the branch exists on the remote before proposing a rename, since the hazard is invisible from local state
|
|
17
|
-
-
|
|
21
|
+
- Read the remote itself with `git ls-remote` before creating, since `origin/<name>` sees only the last fetch
|
|
22
|
+
- Show the name and its length against the limit before renaming or creating
|
|
18
23
|
- Execute immediately after the preview. The tool permission dialog is the confirmation gate.
|
|
19
24
|
|
|
20
25
|
## Must not
|
|
@@ -22,17 +27,23 @@ Without this skill, a branch name is invented once per session. The type prefix
|
|
|
22
27
|
- Rename `main` or `master`
|
|
23
28
|
- Rename when the current name already conforms. The skill is chained, so a conforming name has to pass through rather than churn the branch.
|
|
24
29
|
- Rename a branch that exists on the remote. Local rename plus force push is not the same operation and it breaks the pull request.
|
|
30
|
+
- Create a branch from anywhere but `main` or `master`, or create one whose name exists locally or on the remote
|
|
31
|
+
- Invent a name when the plan verb refuses, since a name the skill calls non-conforming strands the rename at ship
|
|
32
|
+
- Fetch or stash while creating
|
|
25
33
|
- Emit anything after the result line
|
|
26
34
|
|
|
27
35
|
## Guards
|
|
28
36
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
37
|
+
- Create with no plan and no name: stop and name both missing inputs
|
|
38
|
+
- Create with a name breaking the branch standard: stop and name the cap
|
|
39
|
+
- Create with a name existing locally or on the remote: stop and say which
|
|
40
|
+
- Rename name already conforms: stop with a success marker, not a failure, since a chained caller continues past it
|
|
41
|
+
- Rename with no commits and no description: stop and name both missing inputs
|
|
42
|
+
- Rename of a branch existing on the remote: stop and route to the surface that preserves the pull request link
|
|
33
43
|
|
|
34
44
|
## Out of scope
|
|
35
45
|
|
|
36
46
|
- The commit message, which `git-commit` owns
|
|
37
47
|
- Pushing and opening the pull request, which `git-pr` owns. That skill reads a conforming name as a precondition and refuses without one, so this skill runs first.
|
|
38
48
|
- Splitting a branch whose commits span concerns, which `git-split` owns
|
|
49
|
+
- Entering a worktree, which `session-worktree` owns and which names its own branch
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: git-branch
|
|
3
|
-
description: Generates and validates conventional branch names. Use for any branch naming or renaming, such as when asked to "name this branch".
|
|
3
|
+
description: Generates and validates conventional branch names, creating the branch from main or master and renaming it anywhere else. Use for any branch naming, creating, or renaming, such as when asked to "name this branch" or "create the branch for this feature".
|
|
4
4
|
metadata:
|
|
5
5
|
family: ship
|
|
6
6
|
---
|
|
@@ -13,7 +13,64 @@ Before generating a branch name, read:
|
|
|
13
13
|
|
|
14
14
|
Follow it exactly.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Run `git branch --show-current` to pick the mode. On `main` or `master` the skill creates a branch, and anywhere else it renames the current one.
|
|
17
|
+
|
|
18
|
+
## Create mode
|
|
19
|
+
|
|
20
|
+
### Name
|
|
21
|
+
|
|
22
|
+
Take the name from the invocation. An argument ending in `.md` or resolving under `.canon/plans/` is a plan, and anything else is a branch name, since a name always carries a `<type>/` segment.
|
|
23
|
+
|
|
24
|
+
- For a plan, run `canon tasks plan-branch <plan> --json` and take the record's `branch`. The verb fixes the type at `feat`, so a plan never yields another type.
|
|
25
|
+
- When the verb refuses or the record carries `conforms: false`, stop and relay its reason. Never invent a name in its place.
|
|
26
|
+
- For a name, check it against the whole Format section of `branch.md`, including the description word bound and the no-repeated-type rule, as the rename guard does.
|
|
27
|
+
|
|
28
|
+
### Context
|
|
29
|
+
|
|
30
|
+
Run these in parallel once the name is known:
|
|
31
|
+
|
|
32
|
+
- `git show-ref --verify --quiet "refs/heads/<name>" && echo "LOCAL_EXISTS" || echo "LOCAL_FREE"`
|
|
33
|
+
- `git ls-remote --exit-code --heads origin "<name>" 2>/dev/null; echo "REMOTE_EXIT=$?"`
|
|
34
|
+
|
|
35
|
+
Exit 0 on the remote read is a collision. Exit 2, or a repository with no `origin`, is no collision. The check reads the remote itself, never `origin/<name>`, which sees only the last fetch. The skill does not fetch.
|
|
36
|
+
|
|
37
|
+
### Guards
|
|
38
|
+
|
|
39
|
+
Each guard stops before any ref moves.
|
|
40
|
+
|
|
41
|
+
- If the invocation carries no plan and no name, stop: `❌ No plan or branch name to create from.`
|
|
42
|
+
- If the name breaks `branch.md`, stop and name the cap it broke: `❌ <name> breaks the branch standard: <cap>.`
|
|
43
|
+
- If the name exists locally, stop: `❌ Branch <name> already exists locally.`
|
|
44
|
+
- If the name exists on the remote, stop: `❌ Branch <name> already exists on origin.`
|
|
45
|
+
|
|
46
|
+
### Preview
|
|
47
|
+
|
|
48
|
+
Output the preview first.
|
|
49
|
+
|
|
50
|
+
- **Current:** <main_or_master>
|
|
51
|
+
- **Creating:** <name>
|
|
52
|
+
- **Length:** <count>/50
|
|
53
|
+
- **Source:** <plan | name>
|
|
54
|
+
|
|
55
|
+
After outputting the preview, execute the final command immediately. Claude Code's tool permission dialog is the confirmation gate. Do not wait for user input.
|
|
56
|
+
|
|
57
|
+
### Final command
|
|
58
|
+
|
|
59
|
+
The branch starts at the current tip, and uncommitted changes carry onto it. The skill stashes nothing.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git switch -c <name>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### After execution
|
|
66
|
+
|
|
67
|
+
Respond with exactly one line and add no other text:
|
|
68
|
+
|
|
69
|
+
`✅ Created: <name>`
|
|
70
|
+
|
|
71
|
+
## Rename mode
|
|
72
|
+
|
|
73
|
+
### Context
|
|
17
74
|
|
|
18
75
|
Run these commands in parallel to gather git context:
|
|
19
76
|
|
|
@@ -21,14 +78,13 @@ Run these commands in parallel to gather git context:
|
|
|
21
78
|
- `git rev-parse --verify "origin/$(git branch --show-current)" 2>/dev/null && echo "EXISTS" || echo "LOCAL_ONLY"`
|
|
22
79
|
- `git log main..HEAD --oneline 2>/dev/null || echo "NO_COMMITS"`
|
|
23
80
|
|
|
24
|
-
|
|
81
|
+
### Guards
|
|
82
|
+
|
|
83
|
+
A conforming name passes through, so a chained caller continues past it.
|
|
25
84
|
|
|
26
|
-
- If already on main or master, stop: `❌ Cannot rename a protected branch.`
|
|
27
85
|
- If branch name already follows conventions, stop: `✅ Branch name already follows conventions.`
|
|
28
86
|
- If no commits and no args provided, stop: `❌ No commits or description to derive a branch name from.`
|
|
29
87
|
|
|
30
|
-
## Response format
|
|
31
|
-
|
|
32
88
|
### Preview
|
|
33
89
|
|
|
34
90
|
Output the preview first.
|
|
@@ -55,7 +111,7 @@ Only output if LOCAL_ONLY:
|
|
|
55
111
|
git branch -m <current> <suggested>
|
|
56
112
|
```
|
|
57
113
|
|
|
58
|
-
|
|
114
|
+
### After execution
|
|
59
115
|
|
|
60
116
|
Respond with exactly one line and add no other text:
|
|
61
117
|
|