@erclx/canon 5.38.0 → 5.40.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 +5 -5
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +12 -9
- package/claude/skills/auto-ship/SKILL.md +43 -23
- package/claude/skills/backlog-triage/SKILL.md +62 -53
- package/claude/skills/backlog-triage/references/apply.md +69 -0
- package/claude/skills/build-in-slices/SKILL.md +8 -4
- package/claude/skills/canon-cli/SKILL.md +5 -1
- package/claude/skills/canon-feedback/SKILL.md +18 -8
- package/claude/skills/canon-feedback-triage/SKILL.md +10 -3
- package/claude/skills/canvas-board/SKILL.md +37 -18
- package/claude/skills/ci-workflow/SKILL.md +5 -4
- package/claude/skills/code-craft/SKILL.md +10 -6
- package/claude/skills/codebase-layout/SKILL.md +3 -5
- package/claude/skills/context-fold/REQUIREMENT.md +4 -4
- package/claude/skills/context-fold/SKILL.md +42 -23
- package/claude/skills/context-fold/references/context-refresh.md +4 -3
- package/claude/skills/context-fold/references/context.md +79 -64
- package/claude/skills/create-rule/SKILL.md +7 -3
- package/claude/skills/create-skill/SKILL.md +27 -7
- package/claude/skills/create-skill/references/skill-reference.md +41 -17
- package/claude/skills/decision-escalate/SKILL.md +8 -5
- package/claude/skills/deploy-app/SKILL.md +1 -1
- package/claude/skills/deprecation-migration/SKILL.md +12 -4
- package/claude/skills/design-taste/SKILL.md +17 -11
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -0
- package/claude/skills/docs-sync/SKILL.md +17 -6
- package/claude/skills/docs-sync/references/docs.md +54 -21
- package/claude/skills/docs-sync/references/readme.md +32 -8
- package/claude/skills/document-health/SKILL.md +3 -4
- package/claude/skills/draft-and-pick/SKILL.md +73 -47
- package/claude/skills/draft-doc/SKILL.md +9 -4
- package/claude/skills/draft-doc/references/context.md +4 -4
- package/claude/skills/draft-doc/references/docs.md +1 -0
- package/claude/skills/draft-doc/references/wiki.md +3 -2
- package/claude/skills/draft-figure/SKILL.md +9 -7
- package/claude/skills/draft-identity/SKILL.md +24 -52
- package/claude/skills/draft-identity/references/card-route.md +46 -0
- package/claude/skills/draft-ready/SKILL.md +19 -7
- package/claude/skills/draft-screencast/SKILL.md +6 -112
- package/claude/skills/draft-screencast/references/beats-template.md +119 -0
- package/claude/skills/draft-slides/SKILL.md +9 -7
- package/claude/skills/draft-slides/references/deck.md +183 -0
- package/claude/skills/git-branch/SKILL.md +3 -3
- package/claude/skills/git-commit/SKILL.md +5 -3
- package/claude/skills/git-followup/SKILL.md +16 -9
- package/claude/skills/git-issue/SKILL.md +6 -5
- package/claude/skills/git-pr/SKILL.md +56 -44
- 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/git-ship/SKILL.md +43 -34
- package/claude/skills/git-ship/references/ci-watch.md +31 -0
- package/claude/skills/git-split/SKILL.md +28 -100
- package/claude/skills/git-split/references/independent.md +40 -0
- package/claude/skills/git-split/references/stacked.md +73 -0
- package/claude/skills/git-stage/SKILL.md +9 -7
- package/claude/skills/git-worktree/SKILL.md +27 -49
- package/claude/skills/git-worktree/references/cleanup.md +55 -0
- package/claude/skills/markdown-craft/SKILL.md +2 -2
- package/claude/skills/markdown-craft/references/markdown.md +82 -53
- package/claude/skills/plan-feature/SKILL.md +52 -46
- package/claude/skills/plan-feature/references/batches.md +46 -0
- package/claude/skills/plan-groundwork/SKILL.md +60 -74
- package/claude/skills/plan-groundwork/references/output.md +48 -0
- package/claude/skills/plan-intake/SKILL.md +28 -21
- package/claude/skills/plan-intake-answer/SKILL.md +14 -13
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +31 -11
- package/claude/skills/review-address/SKILL.md +76 -158
- package/claude/skills/review-address/references/rebase-only.md +34 -0
- package/claude/skills/review-craft/SKILL.md +27 -11
- package/claude/skills/review-pr/SKILL.md +91 -40
- package/claude/skills/review-ui/SKILL.md +63 -37
- package/claude/skills/review-ui/references/hosted-preview.md +30 -0
- package/claude/skills/role-orchestrator/SKILL.md +105 -74
- package/claude/skills/role-orchestrator/references/orchestrator-filing.md +26 -0
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
- package/claude/skills/role-planner/SKILL.md +66 -64
- package/claude/skills/role-reviewer/SKILL.md +57 -46
- package/claude/skills/role-worker/SKILL.md +68 -63
- package/claude/skills/search-craft/SKILL.md +7 -5
- package/claude/skills/session-compact/SKILL.md +16 -11
- package/claude/skills/session-map/SKILL.md +31 -10
- package/claude/skills/session-relay/SKILL.md +32 -65
- package/claude/skills/session-resume/SKILL.md +18 -13
- package/claude/skills/session-worktree/SKILL.md +70 -42
- package/claude/skills/systematic-debugging/SKILL.md +6 -1
- package/claude/skills/target-check/SKILL.md +13 -6
- package/claude/skills/target-setup/SKILL.md +39 -27
- package/claude/skills/task-board/SKILL.md +68 -60
- package/claude/skills/task-board/references/board.md +1 -1
- package/claude/skills/task-board/references/create-report.md +36 -0
- package/claude/skills/task-board/references/tasks.md +1 -1
- package/claude/skills/task-complete/SKILL.md +20 -18
- package/claude/skills/teach-workspace/SKILL.md +61 -33
- package/claude/skills/test-craft/SKILL.md +2 -1
- package/claude/skills/test-first/SKILL.md +15 -9
- package/claude/skills/ui-checklist/SKILL.md +18 -16
- package/claude/skills/ux-audit/SKILL.md +9 -10
- package/claude/skills/ux-measure/SKILL.md +23 -19
- package/claude/skills/video-craft/SKILL.md +15 -7
- package/claude/skills/write-human/SKILL.md +9 -1
- package/claude/skills/youtube-transcripts/SKILL.md +2 -1
- package/docs/agents/audits.md +61 -60
- package/docs/agents/context-audit.md +40 -58
- package/docs/agents/index.md +11 -61
- package/docs/agents/indexes.md +25 -29
- package/docs/agents/install-and-sync.md +125 -235
- package/docs/agents/markdown-audit.md +54 -96
- package/docs/agents/migrate.md +41 -16
- package/docs/agents/output-shape.md +60 -45
- package/docs/agents/overview.md +36 -12
- package/docs/agents/records.md +37 -79
- package/docs/agents/sessions-transfer.md +26 -70
- package/docs/agents/targets.md +25 -77
- 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 +29 -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/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 +14 -1
- package/src/commands/context.ts +106 -7
- 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/hooks.ts +63 -0
- package/src/commands/intake.ts +17 -0
- package/src/commands/labels.ts +38 -5
- package/src/commands/markdown.ts +169 -32
- package/src/commands/pr.ts +160 -43
- package/src/commands/records.ts +8 -0
- 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 +274 -5
- package/src/context/classify/prompts.ts +1 -1
- package/src/context/folders.ts +1 -1
- package/src/context/gate.ts +23 -7
- package/src/context/shape-gated.ts +30 -0
- 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 +16 -191
- package/src/gate/stages.ts +14 -30
- package/src/git/env.ts +6 -0
- package/src/hooks/reply-links.ts +110 -0
- package/src/markdown/density.ts +258 -0
- package/src/markdown/gate.ts +57 -18
- package/src/markdown/reference-shape.ts +103 -0
- package/src/markdown/scope.ts +162 -0
- package/src/markdown/structure.ts +9 -59
- package/src/pr/lift.ts +153 -19
- package/src/pr/painted.ts +87 -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/shipped/references.ts +1 -1
- package/src/slides/convert/master.ts +3 -0
- package/src/sync/format.ts +46 -0
- package/src/sync/stamp.ts +6 -0
- package/tooling/astro/reference.md +2 -2
- package/tooling/base/reference.md +1 -1
- package/tooling/claude/seeds/.claude/hooks/reply-links.sh +72 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +22 -1
- package/tooling/claude/seeds/.claude/settings.json +4 -0
- package/tooling/go/reference.md +1 -1
- package/tooling/nextjs/reference.md +1 -1
- package/tooling/php/reference.md +1 -1
- package/tooling/python/reference.md +1 -1
- package/tooling/vite-react/reference.md +1 -1
- package/tooling/web/reference.md +1 -1
- package/docs/agents/canvas.md +0 -86
- package/docs/agents/capture.md +0 -65
- package/docs/agents/census.md +0 -23
- package/docs/agents/commands.md +0 -154
- package/docs/agents/comments.md +0 -34
- package/docs/agents/context-audit-checks.md +0 -90
- 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/docs.md +0 -27
- package/docs/agents/drift-surfaces.md +0 -201
- package/docs/agents/driver.md +0 -103
- package/docs/agents/gate.md +0 -90
- package/docs/agents/gov-detect.md +0 -47
- package/docs/agents/hooks.md +0 -58
- 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-weight.md +0 -81
- 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/scripting.md +0 -142
- 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/src/markdown/growth.ts +0 -43
|
@@ -39,15 +39,18 @@ Run these commands in parallel to gather git context:
|
|
|
39
39
|
|
|
40
40
|
### Primary concern
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
The current branch keeps its primary concern, and each secondary concern leaves as a new focused branch via cherry-pick.
|
|
43
|
+
|
|
44
|
+
- Rename the current branch with `git branch -m` when its name does not match the primary concern, and skip the rename when it does
|
|
45
|
+
- If no single concern dominates, as on a dumping-ground branch, split every commit into new branches and add `git branch -d <current>`
|
|
44
46
|
- Propose one new branch per secondary concern following branch.md format.
|
|
45
47
|
|
|
46
48
|
### Independent and stacked
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
Classify the groups before generating commands, since the mode decides each branch's base.
|
|
51
|
+
|
|
49
52
|
- Independent groups: each group's commits apply to `main` without the others. Base every branch on `main`.
|
|
50
|
-
- Stacked groups: groups are ordered and each depends on the commits before it. Base each branch on the previous group's branch
|
|
53
|
+
- Stacked groups: groups are ordered and each depends on the commits before it. Base each branch on the previous group's branch and cherry-pick only that group's commits.
|
|
51
54
|
|
|
52
55
|
## Response format
|
|
53
56
|
|
|
@@ -64,118 +67,43 @@ Run these commands in parallel to gather git context:
|
|
|
64
67
|
|
|
65
68
|
**All <total> commits accounted for.**
|
|
66
69
|
|
|
67
|
-
- For the primary concern
|
|
70
|
+
- For the primary concern, show `<current_branch> → <new_name>` only when renaming, and `<current_branch>` alone otherwise
|
|
68
71
|
- For stacked mode, list rows in merge order: branches based on `main` first, then each layer above. For independent mode, list the primary concern first.
|
|
69
72
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
`🔁 Sequential squash-merge loop. Squash-merge each PR bottom-up with --delete-branch. After each merge, signal me so I can restack the next branch onto main before you merge it.`
|
|
73
|
+
### Merge order line
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
Append the line for the run's mode to the preview.
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
| Mode | Line |
|
|
78
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
79
|
+
| Stacked | `🔁 Sequential squash-merge loop. Squash-merge each PR bottom-up with --delete-branch. After each merge, signal me so I can restack the next branch onto main before you merge it.` |
|
|
80
|
+
| Independent | `🔁 Squash-merge secondaries first, primary last. The primary keeps every cherry-picked commit, so merging it first lands every secondary's content on main and leaves the secondary PRs empty after rebase.` |
|
|
77
81
|
|
|
78
82
|
After outputting the preview, execute the final commands immediately. Claude Code's tool permission dialog is the confirmation gate. Do not wait for user input.
|
|
79
83
|
|
|
80
|
-
|
|
84
|
+
### Pre-publish scan
|
|
81
85
|
|
|
82
|
-
|
|
86
|
+
Before running them, run the scan in `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md` against every title and body. Each body stages under `.canon/tmp/` and leaves through `gh`, so the hook sees neither.
|
|
83
87
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
# Rename current branch to reflect primary concern
|
|
88
|
-
git branch -m <current_branch> <new_name>
|
|
89
|
-
|
|
90
|
-
# Create, cherry-pick, push, and open PR for each secondary branch
|
|
91
|
-
mkdir -p .canon/tmp/pr/split
|
|
92
|
-
git switch -c <branch> main && git cherry-pick <sha> <sha> \
|
|
93
|
-
&& git push -u origin <branch> \
|
|
94
|
-
&& (cat <<'BODY' > .canon/tmp/pr/split/<branch>.md
|
|
95
|
-
<body following pr.md template, written from the cherry-picked commits>
|
|
96
|
-
BODY
|
|
97
|
-
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<branch> -f base=main -F body=@.canon/tmp/pr/split/<branch>.md --jq .html_url \
|
|
98
|
-
&& printf 'opened=true\n' \
|
|
99
|
-
&& rm .canon/tmp/pr/split/<branch>.md
|
|
100
|
-
|
|
101
|
-
# Return to primary branch, push, and open its PR
|
|
102
|
-
git checkout <new_name> && git push -u origin <new_name> \
|
|
103
|
-
&& (cat <<'BODY' > .canon/tmp/pr/split/<new_name>.md
|
|
104
|
-
<body following pr.md template, written from the primary's commits>
|
|
105
|
-
BODY
|
|
106
|
-
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<new_name> -f base=main -F body=@.canon/tmp/pr/split/<new_name>.md --jq .html_url \
|
|
107
|
-
&& printf 'opened=true\n' \
|
|
108
|
-
&& rm .canon/tmp/pr/split/<new_name>.md
|
|
109
|
-
|
|
110
|
-
# Clean up the body-file dir if all PRs succeeded (no-op when non-empty)
|
|
111
|
-
rmdir .canon/tmp/pr/split 2>/dev/null || true
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
Every pull request opens through the REST pulls endpoint rather than the `gh pr` create subcommand, which runs on GraphQL and fails where a cloud session's GitHub proxy refuses it. The endpoint requires `base`, so each call names the branch its layer sits on. `-F` reads the body file, where `-f` would post the path itself.
|
|
115
|
-
|
|
116
|
-
A create the endpoint refuses, such as one for a head that already has an open pull request, exits non-zero and stops the chain before `opened=true` prints and before the body file is removed. The `opened=true` line is what a pull request creation log reads to count the opening, since the REST call prints a URL and never names itself.
|
|
117
|
-
|
|
118
|
-
For stacked mode, base each branch on the previous and cherry-pick only that group's commits:
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
# Rename current branch to reflect primary concern
|
|
122
|
-
git branch -m <current_branch> <new_name>
|
|
123
|
-
|
|
124
|
-
mkdir -p .canon/tmp/pr/split
|
|
125
|
-
|
|
126
|
-
# Group 1: based on main
|
|
127
|
-
git switch -c <branch-1> main && git cherry-pick <g1-sha> <g1-sha> \
|
|
128
|
-
&& git push -u origin <branch-1> \
|
|
129
|
-
&& (cat <<'BODY' > .canon/tmp/pr/split/<branch-1>.md
|
|
130
|
-
<body following pr.md template, written from the cherry-picked commits>
|
|
131
|
-
BODY
|
|
132
|
-
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<branch-1> -f base=main -F body=@.canon/tmp/pr/split/<branch-1>.md --jq .html_url \
|
|
133
|
-
&& printf 'opened=true\n' \
|
|
134
|
-
&& rm .canon/tmp/pr/split/<branch-1>.md
|
|
135
|
-
|
|
136
|
-
# Group 2: based on <branch-1>, this group's commits only
|
|
137
|
-
git checkout -b <branch-2> && git cherry-pick <g2-sha> <g2-sha> \
|
|
138
|
-
&& git push -u origin <branch-2> \
|
|
139
|
-
&& (cat <<'BODY' > .canon/tmp/pr/split/<branch-2>.md
|
|
140
|
-
<body following pr.md template, written from the cherry-picked commits>
|
|
141
|
-
BODY
|
|
142
|
-
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<branch-2> -f base=<branch-1> -F body=@.canon/tmp/pr/split/<branch-2>.md --jq .html_url \
|
|
143
|
-
&& printf 'opened=true\n' \
|
|
144
|
-
&& rm .canon/tmp/pr/split/<branch-2>.md
|
|
145
|
-
|
|
146
|
-
# Return to primary branch, push, and open its PR on the last group's branch
|
|
147
|
-
git checkout <new_name> && git push -u origin <new_name> \
|
|
148
|
-
&& (cat <<'BODY' > .canon/tmp/pr/split/<new_name>.md
|
|
149
|
-
<body following pr.md template, written from the primary's commits>
|
|
150
|
-
BODY
|
|
151
|
-
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<new_name> -f base=<branch-2> -F body=@.canon/tmp/pr/split/<new_name>.md --jq .html_url \
|
|
152
|
-
&& printf 'opened=true\n' \
|
|
153
|
-
&& rm .canon/tmp/pr/split/<new_name>.md
|
|
154
|
-
|
|
155
|
-
# Clean up the body-file dir if all PRs succeeded (no-op when non-empty)
|
|
156
|
-
rmdir .canon/tmp/pr/split 2>/dev/null || true
|
|
157
|
-
```
|
|
88
|
+
Each branch reaches the `pull_request` check only once its own pull request opens, so this scan is what catches a leak ahead of that.
|
|
158
89
|
|
|
159
|
-
|
|
90
|
+
### Final commands
|
|
160
91
|
|
|
161
|
-
|
|
92
|
+
Read the command block for the run's mode on reaching this step, and skip the other.
|
|
162
93
|
|
|
163
|
-
|
|
94
|
+
- Independent mode: `${CLAUDE_SKILL_DIR}/references/independent.md`
|
|
95
|
+
- Stacked mode: `${CLAUDE_SKILL_DIR}/references/stacked.md`
|
|
164
96
|
|
|
165
|
-
|
|
97
|
+
Every pull request opens through the REST pulls endpoint rather than the `gh pr` create subcommand, which runs on GraphQL and fails where a cloud session's GitHub proxy refuses it. The endpoint requires `base`, so each call names its layer's branch, and `-F` reads the body file where `-f` would post the path.
|
|
166
98
|
|
|
167
|
-
|
|
99
|
+
A create the endpoint refuses, such as one for a head with an open pull request, exits non-zero and stops the chain before `opened=true` prints and the body file is removed. A pull request creation log counts openings off `opened=true`, since the REST call prints a URL and never names itself.
|
|
168
100
|
|
|
169
|
-
##
|
|
101
|
+
## After execution
|
|
170
102
|
|
|
171
|
-
|
|
103
|
+
Respond with exactly one line and add no other text, reading each URL off the line its create printed through `--jq .html_url`:
|
|
172
104
|
|
|
173
|
-
|
|
174
|
-
`git fetch origin main && git checkout <branch> && git rebase --onto origin/main HEAD~<own-commit-count> && git push --force-with-lease`
|
|
175
|
-
2. Verify the PR's base auto-retargeted to main with `gh api repos/{owner}/{repo}/pulls/<num> --jq .base.ref`, a REST read a cloud session's GitHub proxy serves where it refuses GraphQL. If not, retarget it with `gh api -X PATCH repos/{owner}/{repo}/pulls/<num> -f base=main --silent`.
|
|
176
|
-
3. Reply: `✅ <branch> rebased onto main. Ready for squash-merge.`
|
|
105
|
+
`✅ Renamed: <old> → <new> | PRs: <primary-url>, <url1>, <url2>`
|
|
177
106
|
|
|
178
|
-
|
|
107
|
+
## Stacked merge loop
|
|
179
108
|
|
|
180
|
-
|
|
181
|
-
- If the PR was orphaned by base-branch deletion, recreate it with the same create the final commands run, passing `-f head=<branch> -f base=main` and a regenerated body, and print `opened=true` after it.
|
|
109
|
+
When the user signals the previous stacked PR has merged, restack the next one. Read `${CLAUDE_SKILL_DIR}/references/stacked.md` from its `## Stacked merge loop` section for the rebase, the retarget, the reply, and the two edge cases. An independent split skips it.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Independent split commands
|
|
3
|
+
description: The final commands git-split runs in independent mode, basing every new branch on main and opening each pull request over REST
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Independent split commands
|
|
7
|
+
|
|
8
|
+
Applies to a `git-split` run whose preview reads `Mode: Independent`. Every branch is based on `main`, since each group's commits apply there without the others.
|
|
9
|
+
|
|
10
|
+
## Final commands
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Rename current branch to reflect primary concern
|
|
14
|
+
git branch -m <current_branch> <new_name>
|
|
15
|
+
|
|
16
|
+
# Create, cherry-pick, push, and open PR for each secondary branch
|
|
17
|
+
mkdir -p .canon/tmp/pr/split
|
|
18
|
+
git switch -c <branch> main && git cherry-pick <sha> <sha> \
|
|
19
|
+
&& git push -u origin <branch> \
|
|
20
|
+
&& (cat <<'BODY' > .canon/tmp/pr/split/<branch>.md
|
|
21
|
+
<body following pr.md template, written from the cherry-picked commits>
|
|
22
|
+
BODY
|
|
23
|
+
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<branch> -f base=main -F body=@.canon/tmp/pr/split/<branch>.md --jq .html_url \
|
|
24
|
+
&& printf 'opened=true\n' \
|
|
25
|
+
&& rm .canon/tmp/pr/split/<branch>.md
|
|
26
|
+
|
|
27
|
+
# Return to primary branch, push, and open its PR
|
|
28
|
+
git checkout <new_name> && git push -u origin <new_name> \
|
|
29
|
+
&& (cat <<'BODY' > .canon/tmp/pr/split/<new_name>.md
|
|
30
|
+
<body following pr.md template, written from the primary's commits>
|
|
31
|
+
BODY
|
|
32
|
+
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<new_name> -f base=main -F body=@.canon/tmp/pr/split/<new_name>.md --jq .html_url \
|
|
33
|
+
&& printf 'opened=true\n' \
|
|
34
|
+
&& rm .canon/tmp/pr/split/<new_name>.md
|
|
35
|
+
|
|
36
|
+
# Clean up the body-file dir if all PRs succeeded (no-op when non-empty)
|
|
37
|
+
rmdir .canon/tmp/pr/split 2>/dev/null || true
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Repeat the secondary block once per secondary branch. The skill body states why each create goes through the REST endpoint and what `opened=true` marks.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Stacked split commands and merge loop
|
|
3
|
+
description: The final commands git-split runs in stacked mode, basing each branch on the one before it, and the restack loop run after each merge
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Stacked split commands and merge loop
|
|
7
|
+
|
|
8
|
+
Applies to a `git-split` run whose preview reads `Mode: Stacked`, where the groups are ordered and each depends on the commits before it.
|
|
9
|
+
|
|
10
|
+
## Final commands
|
|
11
|
+
|
|
12
|
+
Base each branch on the previous one and cherry-pick only that group's commits, since the base branch already carries every prior commit.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Rename current branch to reflect primary concern
|
|
16
|
+
git branch -m <current_branch> <new_name>
|
|
17
|
+
|
|
18
|
+
mkdir -p .canon/tmp/pr/split
|
|
19
|
+
|
|
20
|
+
# Group 1: based on main
|
|
21
|
+
git switch -c <branch-1> main && git cherry-pick <g1-sha> <g1-sha> \
|
|
22
|
+
&& git push -u origin <branch-1> \
|
|
23
|
+
&& (cat <<'BODY' > .canon/tmp/pr/split/<branch-1>.md
|
|
24
|
+
<body following pr.md template, written from the cherry-picked commits>
|
|
25
|
+
BODY
|
|
26
|
+
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<branch-1> -f base=main -F body=@.canon/tmp/pr/split/<branch-1>.md --jq .html_url \
|
|
27
|
+
&& printf 'opened=true\n' \
|
|
28
|
+
&& rm .canon/tmp/pr/split/<branch-1>.md
|
|
29
|
+
|
|
30
|
+
# Group 2: based on <branch-1>, this group's commits only
|
|
31
|
+
git checkout -b <branch-2> && git cherry-pick <g2-sha> <g2-sha> \
|
|
32
|
+
&& git push -u origin <branch-2> \
|
|
33
|
+
&& (cat <<'BODY' > .canon/tmp/pr/split/<branch-2>.md
|
|
34
|
+
<body following pr.md template, written from the cherry-picked commits>
|
|
35
|
+
BODY
|
|
36
|
+
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<branch-2> -f base=<branch-1> -F body=@.canon/tmp/pr/split/<branch-2>.md --jq .html_url \
|
|
37
|
+
&& printf 'opened=true\n' \
|
|
38
|
+
&& rm .canon/tmp/pr/split/<branch-2>.md
|
|
39
|
+
|
|
40
|
+
# Return to primary branch, push, and open its PR on the last group's branch
|
|
41
|
+
git checkout <new_name> && git push -u origin <new_name> \
|
|
42
|
+
&& (cat <<'BODY' > .canon/tmp/pr/split/<new_name>.md
|
|
43
|
+
<body following pr.md template, written from the primary's commits>
|
|
44
|
+
BODY
|
|
45
|
+
) && gh api -X POST 'repos/{owner}/{repo}/pulls' -f title="<title>" -f head=<new_name> -f base=<branch-2> -F body=@.canon/tmp/pr/split/<new_name>.md --jq .html_url \
|
|
46
|
+
&& printf 'opened=true\n' \
|
|
47
|
+
&& rm .canon/tmp/pr/split/<new_name>.md
|
|
48
|
+
|
|
49
|
+
# Clean up the body-file dir if all PRs succeeded (no-op when non-empty)
|
|
50
|
+
rmdir .canon/tmp/pr/split 2>/dev/null || true
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Stacked merge loop
|
|
54
|
+
|
|
55
|
+
When the user signals the previous stacked PR has merged, restack the next one.
|
|
56
|
+
|
|
57
|
+
1. Rebase and push, taking the own-commit-count from the original split table:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
git fetch origin main && git checkout <branch> && git rebase --onto origin/main HEAD~<own-commit-count> && git push --force-with-lease
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
2. Verify the base auto-retargeted to main with `gh api repos/{owner}/{repo}/pulls/<num> --jq .base.ref`. If not, run `gh api -X PATCH repos/{owner}/{repo}/pulls/<num> -f base=main --silent`.
|
|
64
|
+
3. Reply: `✅ <branch> rebased onto main. Ready for squash-merge.`
|
|
65
|
+
|
|
66
|
+
Both reads go through REST, which a cloud session's GitHub proxy serves where it refuses GraphQL.
|
|
67
|
+
|
|
68
|
+
### Edge cases
|
|
69
|
+
|
|
70
|
+
Two states change the loop.
|
|
71
|
+
|
|
72
|
+
- If this branch's commits modify a file added by an unmerged upstream PR, wait for that PR to merge before rebasing
|
|
73
|
+
- If a base-branch deletion orphaned the PR, recreate it with the final commands' create on `-f head=<branch> -f base=main` and a fresh body, then print `opened=true`
|
|
@@ -34,10 +34,14 @@ Run these commands in parallel to gather git context:
|
|
|
34
34
|
|
|
35
35
|
### Order and commands
|
|
36
36
|
|
|
37
|
+
Order and stage the groups so each commit lands whole.
|
|
38
|
+
|
|
37
39
|
- Order commits by dependency: commit dependencies before the files that import them.
|
|
38
40
|
- Prefix the full command sequence with `git restore --staged .` to unstage everything, then stage and commit each group in order.
|
|
39
41
|
- For `D` status files, use `git rm <file>`. For `A` or `M` files, use `git add <file>`.
|
|
40
|
-
- For `R<score>` status rows, `--name-status` emits three tab-separated fields
|
|
42
|
+
- For `R<score>` status rows, `--name-status` emits three tab-separated fields, `R<score>\t<old>\t<new>`
|
|
43
|
+
|
|
44
|
+
Treat a rename pair as one file. Keep both paths in one group and restage them with `git add <old> <new>`, so git detects the rename at commit time rather than recording an add plus a delete.
|
|
41
45
|
|
|
42
46
|
## Response format
|
|
43
47
|
|
|
@@ -53,12 +57,12 @@ Run these commands in parallel to gather git context:
|
|
|
53
57
|
|
|
54
58
|
**All <total> files accounted for.**
|
|
55
59
|
|
|
56
|
-
Count characters in each `<type>(<scope>): <subject>` line
|
|
57
|
-
|
|
58
|
-
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.
|
|
60
|
+
Count characters in each `<type>(<scope>): <subject>` line, shortening any subject past 72 characters and updating the table. Then execute the final command immediately without waiting for user input, since Claude Code's tool permission dialog is the confirmation gate.
|
|
59
61
|
|
|
60
62
|
### Final command
|
|
61
63
|
|
|
64
|
+
Run it as soon as the preview is out.
|
|
65
|
+
|
|
62
66
|
```bash
|
|
63
67
|
git restore --staged .
|
|
64
68
|
# Commit 1: <subject>
|
|
@@ -71,8 +75,6 @@ git add <old> <new> && git commit -m "<type>(<scope>): <subject>"
|
|
|
71
75
|
|
|
72
76
|
## After execution
|
|
73
77
|
|
|
74
|
-
Respond with exactly one line:
|
|
78
|
+
Respond with exactly one line and add no other text:
|
|
75
79
|
|
|
76
80
|
`✅ Committed: <n> commits`
|
|
77
|
-
|
|
78
|
-
Do not add any other text.
|
|
@@ -49,17 +49,32 @@ For each row, determine merge state of its branch:
|
|
|
49
49
|
- `OPEN`: state is `open`, record PR number and URL.
|
|
50
50
|
- `CLOSED`: state is `closed` (not merged), record PR number.
|
|
51
51
|
- Command fails or returns no PR: fall through.
|
|
52
|
-
3. Fallback: `git branch --merged main --format='%(refname:short)' 2>/dev/null | grep -qx "<branch>"
|
|
52
|
+
3. Fallback: `git branch --merged main --format='%(refname:short)' 2>/dev/null | grep -qx "<branch>"`. On match, mark `merged (local)`, otherwise `unmerged`.
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
Match the name alone in the fallback. Without `--format`, git decorates the current branch with `*` and every branch checked out in a linked worktree with `+`, which is the whole set being enumerated.
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
### Dirty, current, and foreign
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
Three more marks come from the row's own path.
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
| Mark | Test |
|
|
61
|
+
| --------- | -------------------------------------------------------------------------------- |
|
|
62
|
+
| `dirty` | `git -C <path> status --porcelain` is non-empty |
|
|
63
|
+
| current | `path` equals `git rev-parse --show-toplevel` |
|
|
64
|
+
| `foreign` | A non-main row whose `path` does not start with `<MAIN_ROOT>/.claude/worktrees/` |
|
|
61
65
|
|
|
62
|
-
|
|
66
|
+
Resolve the root rather than comparing `pwd`, which equals it only at the top of the worktree. A session in a subdirectory would match no row, and `cleanup` would pass its own worktree into the remove set.
|
|
67
|
+
|
|
68
|
+
The `foreign` prefix is the folder `session-worktree` creates under, a convention of that skill rather than a fact this one owns. A tree an operator registered by hand anywhere else reads as `foreign`, and the main row never reaches this test.
|
|
69
|
+
|
|
70
|
+
### Occupancy
|
|
71
|
+
|
|
72
|
+
Run `canon sessions list --json` once for the whole enumeration, never once per row. A row is `occupied` when a live session's `worktree` equals its `path`.
|
|
73
|
+
|
|
74
|
+
- Resolve both sides with `realpath` before comparing, since a session from a second clone reports a path under that clone and a raw compare would hold nothing back
|
|
75
|
+
- A resolved session `worktree` outside `MAIN_ROOT` names a different checkout, so it marks no row occupied
|
|
76
|
+
|
|
77
|
+
The roster is unreadable when the command exits non-zero, when its JSON carries a `reason` instead of a populated `sessions` array, or when `sessions` is non-empty and no entry carries a `worktree` key. An older binary prints that last shape, which cannot be told apart from nothing occupied.
|
|
63
78
|
|
|
64
79
|
## `list` mode
|
|
65
80
|
|
|
@@ -70,7 +85,7 @@ Print the enumeration as a table, then stop. `list` has no final command.
|
|
|
70
85
|
| -- | ---------------------------------- | ----------------- | -------- | ------ | -------- |
|
|
71
86
|
```
|
|
72
87
|
|
|
73
|
-
Notes column shows the first that applies of `current`, `occupied`, `foreign`, `dirty`, or empty. Show paths relative to `MAIN_ROOT` (`.claude/worktrees/<name>`)
|
|
88
|
+
Notes column shows the first that applies of `current`, `occupied`, `foreign`, `dirty`, or empty. Show paths relative to `MAIN_ROOT` (`.claude/worktrees/<name>`), and a `foreign` row's path in full. An unreadable roster leaves the Notes column silent and changes nothing else.
|
|
74
89
|
|
|
75
90
|
After the table, append a one-line hint:
|
|
76
91
|
|
|
@@ -79,54 +94,17 @@ After the table, append a one-line hint:
|
|
|
79
94
|
|
|
80
95
|
## `cleanup` mode
|
|
81
96
|
|
|
82
|
-
If Enumeration marked the roster unreadable, stop: `❌ Session roster unreadable, so occupancy cannot be checked. Resolve the canon sessions list failure, then re-run cleanup.`
|
|
97
|
+
If Enumeration marked the roster unreadable, stop: `❌ Session roster unreadable, so occupancy cannot be checked. Resolve the canon sessions list failure, then re-run cleanup.`
|
|
83
98
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
1. Not the main row.
|
|
87
|
-
2. Not the current session's worktree.
|
|
88
|
-
3. Not occupied by a live session.
|
|
89
|
-
4. Not a `foreign` tree.
|
|
90
|
-
5. State is `merged` or `merged (local)`.
|
|
91
|
-
6. Working tree is clean.
|
|
92
|
-
|
|
93
|
-
Every other non-main row goes to the skip set with a one-word reason, the first that applies in this order: `current`, `occupied`, `foreign`, `dirty`, `open`, `closed`, `unmerged`. A `foreign` tree that is also dirty reports `foreign`, since `dirty` is a state the operator can clear and `foreign` is not. Leading with the transient reason invites a commit or stash that changes nothing, after which the row reports `foreign` and holds back anyway.
|
|
94
|
-
|
|
95
|
-
### Preview
|
|
96
|
-
|
|
97
|
-
```plaintext
|
|
98
|
-
**Removing:** <count>
|
|
99
|
+
Hold every non-main row rather than computing the remove set from the other tests, since removing a tree a live session holds is the failure this skill exists to prevent, and a sweep that removes nothing costs one re-run.
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
| ---- | ------ | -- |
|
|
101
|
+
### Remove set and final command
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
| Path | Branch | Reason |
|
|
106
|
-
| ---- | ------ | ------ |
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
If the remove set is empty, stop with `❌ Nothing to remove. All linked worktrees are current, dirty, unmerged, or foreign.`
|
|
110
|
-
|
|
111
|
-
### Final command
|
|
112
|
-
|
|
113
|
-
After the preview, execute immediately. Claude Code's tool permission dialog is the confirmation gate. Do not wait for user input.
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
git -C <MAIN_ROOT> worktree remove <path1> \
|
|
117
|
-
&& git -C <MAIN_ROOT> branch -D <branch1> \
|
|
118
|
-
&& git -C <MAIN_ROOT> worktree remove <path2> \
|
|
119
|
-
&& git -C <MAIN_ROOT> branch -D <branch2> \
|
|
120
|
-
&& git -C <MAIN_ROOT> worktree prune
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
Chain one `worktree remove` + `branch -D` pair per row in the remove set, then a single `worktree prune` at the end.
|
|
103
|
+
Read `${CLAUDE_SKILL_DIR}/references/cleanup.md` for the remove set, the skip reasons and their order, the preview, and the final command. `list` mode skips it.
|
|
124
104
|
|
|
125
105
|
## After execution
|
|
126
106
|
|
|
127
|
-
Respond with exactly one line:
|
|
107
|
+
Respond with exactly one line and add no other text:
|
|
128
108
|
|
|
129
109
|
- `list`: `✅ <n> worktrees listed`
|
|
130
110
|
- `cleanup`: `✅ Removed: <count> worktrees, <count> branches pruned`
|
|
131
|
-
|
|
132
|
-
Do not add any other text.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Worktree cleanup
|
|
3
|
+
description: Which enumerated worktrees git-worktree cleanup removes, the skip reasons and their order, the preview, and the final command
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Worktree cleanup
|
|
7
|
+
|
|
8
|
+
Applies to `git-worktree` in `cleanup` mode, after the enumeration has run and the roster read cleanly. The roster stop stays in the skill body.
|
|
9
|
+
|
|
10
|
+
## The remove set
|
|
11
|
+
|
|
12
|
+
Include a worktree when every test holds:
|
|
13
|
+
|
|
14
|
+
1. Not the main row.
|
|
15
|
+
2. Not the current session's worktree.
|
|
16
|
+
3. Not occupied by a live session.
|
|
17
|
+
4. Not a `foreign` tree.
|
|
18
|
+
5. State is `merged` or `merged (local)`.
|
|
19
|
+
6. Working tree is clean.
|
|
20
|
+
|
|
21
|
+
### The skip set
|
|
22
|
+
|
|
23
|
+
Every other non-main row goes to the skip set with a one-word reason, the first that applies in this order: `current`, `occupied`, `foreign`, `dirty`, `open`, `closed`, `unmerged`.
|
|
24
|
+
|
|
25
|
+
A `foreign` tree that is also dirty reports `foreign`, since the operator can clear `dirty` and cannot clear `foreign`. Leading with the transient reason invites a commit or stash that changes nothing.
|
|
26
|
+
|
|
27
|
+
## Preview
|
|
28
|
+
|
|
29
|
+
```plaintext
|
|
30
|
+
**Removing:** <count>
|
|
31
|
+
|
|
32
|
+
| Path | Branch | PR |
|
|
33
|
+
| ---- | ------ | -- |
|
|
34
|
+
|
|
35
|
+
**Skipping:** <count>
|
|
36
|
+
|
|
37
|
+
| Path | Branch | Reason |
|
|
38
|
+
| ---- | ------ | ------ |
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
If the remove set is empty, stop with `❌ Nothing to remove. All linked worktrees are current, dirty, unmerged, or foreign.`
|
|
42
|
+
|
|
43
|
+
## Final command
|
|
44
|
+
|
|
45
|
+
After the preview, execute immediately without waiting for user input, since Claude Code's tool permission dialog is the confirmation gate.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git -C <MAIN_ROOT> worktree remove <path1> \
|
|
49
|
+
&& git -C <MAIN_ROOT> branch -D <branch1> \
|
|
50
|
+
&& git -C <MAIN_ROOT> worktree remove <path2> \
|
|
51
|
+
&& git -C <MAIN_ROOT> branch -D <branch2> \
|
|
52
|
+
&& git -C <MAIN_ROOT> worktree prune
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Chain one `worktree remove` + `branch -D` pair per row in the remove set, then a single `worktree prune` at the end.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: markdown-craft
|
|
3
|
-
description: Carries the format and structure rules for markdown, being headings, paragraph and list shape, code spans, the date form, punctuation, emphasis, file references, American spelling, and frontmatter wording, and runs the audit after an edit. Use before a substantial markdown edit, when writing a README, a doc, a skill body, or any `.md` file, or when asked "what are the markdown rules" or "which characters are banned". Do NOT use for voice, rhythm, or word choice, which is `write-human`, or for a Mermaid fence or figure, which is `draft-figure`.
|
|
3
|
+
description: Carries the format and structure rules for markdown, being headings, the density limits, paragraph and list shape, code spans, the date form, punctuation, emphasis, file references, American spelling, and frontmatter wording, and runs the audit after an edit. Use before a substantial markdown edit, when writing a README, a doc, a skill body, or any `.md` file, or when asked "what are the markdown rules" or "which characters are banned". Do NOT use for voice, rhythm, or word choice, which is `write-human`, or for a Mermaid fence or figure, which is `draft-figure`.
|
|
4
4
|
metadata:
|
|
5
5
|
family: answer
|
|
6
6
|
---
|
|
@@ -9,7 +9,7 @@ metadata:
|
|
|
9
9
|
|
|
10
10
|
Read `${CLAUDE_SKILL_DIR}/references/markdown.md` before a substantial markdown edit. Every rule in it is a fact a scan can settle, so do not work the banned characters from memory.
|
|
11
11
|
|
|
12
|
-
Run `canon markdown audit <path>` after the edit. Rewrite the sentence carrying a hit rather than swapping the token for a near-synonym.
|
|
12
|
+
Run `canon markdown audit <path>` after the edit, and fix every ban and density finding it reports before moving on. Rewrite the sentence carrying a ban hit rather than swapping the token for a near-synonym, and fix a density finding by its shape rather than trimming characters.
|
|
13
13
|
|
|
14
14
|
## Routes
|
|
15
15
|
|