@erclx/canon 5.41.0 → 5.43.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/api-design/references/adopted.md +34 -14
- package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
- package/claude/skills/auto-ship/SKILL.md +24 -4
- package/claude/skills/auto-ship/references/draft-mark.md +32 -6
- package/claude/skills/auto-ship/references/failure-recovery.md +15 -13
- package/claude/skills/auto-ship/references/tier-failures.md +31 -10
- package/claude/skills/auto-ship/references/ui-checklist.md +9 -4
- package/claude/skills/auto-ship/references/worktree-name.md +9 -3
- package/claude/skills/build-in-slices/references/adopted.md +35 -21
- package/claude/skills/canvas-board/references/canvas.md +17 -6
- package/claude/skills/canvas-board/references/design.md +26 -7
- package/claude/skills/ci-workflow/REQUIREMENT.md +2 -1
- package/claude/skills/ci-workflow/SKILL.md +12 -2
- package/claude/skills/ci-workflow/references/workflows.md +12 -9
- package/claude/skills/code-craft/references/adopted.md +58 -20
- package/claude/skills/codebase-layout/references/adopted.md +49 -16
- package/claude/skills/codebase-layout/references/frontend.md +11 -4
- package/claude/skills/codebase-layout/references/tests.md +4 -2
- package/claude/skills/context-fold/references/classify.md +10 -15
- package/claude/skills/context-fold/references/completion-report.md +11 -9
- package/claude/skills/context-fold/references/context-refresh.md +26 -9
- package/claude/skills/context-fold/references/unusable-baseline.md +5 -3
- package/claude/skills/create-rule/REQUIREMENT.md +5 -0
- package/claude/skills/create-rule/SKILL.md +10 -1
- package/claude/skills/create-rule/references/checklist.md +26 -0
- package/claude/skills/create-rule/references/rule.md +98 -20
- package/claude/skills/create-skill/SKILL.md +1 -0
- package/claude/skills/create-skill/references/skill-disclosure.md +10 -2
- package/claude/skills/create-skill/references/skill-frontmatter.md +43 -0
- package/claude/skills/create-skill/references/skill-paths.md +7 -4
- package/claude/skills/create-skill/references/skill-practice.md +6 -3
- package/claude/skills/create-skill/references/skill-requirement.md +4 -2
- package/claude/skills/create-skill/references/skill.md +67 -44
- package/claude/skills/decision-escalate/SKILL.md +1 -2
- package/claude/skills/deploy-app/references/vercel.md +2 -1
- package/claude/skills/deprecation-migration/references/adopted.md +44 -25
- package/claude/skills/design-taste/references/adopted.md +9 -1
- package/claude/skills/design-taste/references/craft.md +3 -1
- package/claude/skills/design-taste/references/kinds.md +8 -7
- package/claude/skills/design-taste/references/preflight.md +12 -0
- package/claude/skills/design-taste/references/systems.md +7 -6
- package/claude/skills/design-taste/references/tells.md +24 -25
- package/claude/skills/design-taste/references/vocabulary.md +7 -5
- package/claude/skills/document-health/references/axes.md +55 -30
- package/claude/skills/draft-and-pick/references/live-arms.md +2 -2
- package/claude/skills/draft-doc/references/context.md +4 -3
- package/claude/skills/draft-doc/references/docs.md +6 -3
- package/claude/skills/draft-doc/references/readme/agent-facing.md +6 -0
- package/claude/skills/draft-doc/references/readme/application.md +8 -2
- package/claude/skills/draft-doc/references/readme/cli.md +5 -1
- package/claude/skills/draft-doc/references/readme/library.md +4 -0
- package/claude/skills/draft-doc/references/readme/plugin.md +9 -1
- package/claude/skills/draft-doc/references/readme.md +30 -13
- package/claude/skills/draft-doc/references/requirements.md +17 -4
- package/claude/skills/draft-doc/references/wiki-kind.md +20 -10
- package/claude/skills/draft-doc/references/wiki.md +1 -1
- package/claude/skills/draft-figure/references/architecture-set.md +7 -3
- package/claude/skills/draft-figure/references/figures.md +8 -6
- package/claude/skills/draft-figure/references/hand-drawn.md +3 -1
- package/claude/skills/draft-figure/references/mermaid-path.md +19 -9
- package/claude/skills/draft-figure/references/mermaid.md +10 -5
- package/claude/skills/draft-ready/references/ready.md +22 -15
- package/claude/skills/git-branch/references/branch.md +11 -1
- package/claude/skills/git-branch/references/slug.md +17 -5
- package/claude/skills/git-commit/references/commit.md +9 -5
- package/claude/skills/git-commit/references/versioning.md +23 -17
- package/claude/skills/git-followup/REQUIREMENT.md +1 -1
- package/claude/skills/git-followup/SKILL.md +5 -6
- package/claude/skills/git-issue/references/issue.md +29 -16
- package/claude/skills/git-pr/REQUIREMENT.md +1 -5
- package/claude/skills/git-pr/SKILL.md +11 -22
- package/claude/skills/git-pr/references/final-command.md +21 -8
- package/claude/skills/git-pr/references/labels.md +45 -28
- package/claude/skills/git-pr/references/pr.md +29 -9
- package/claude/skills/git-pr/references/publish.md +42 -28
- package/claude/skills/git-pr/references/task-number.md +20 -8
- package/claude/skills/git-ship/SKILL.md +1 -1
- package/claude/skills/plan-feature/SKILL.md +1 -1
- package/claude/skills/plan-feature/references/plan-lifecycle.md +10 -3
- package/claude/skills/plan-feature/references/plan.md +58 -21
- package/claude/skills/plan-groundwork/references/groundwork-spikes.md +4 -1
- package/claude/skills/plan-groundwork/references/groundwork.md +14 -16
- package/claude/skills/plan-intake/references/intake.md +29 -24
- package/claude/skills/pr-evidence/REQUIREMENT.md +40 -0
- package/claude/skills/pr-evidence/SKILL.md +53 -0
- package/claude/skills/pr-evidence/references/evidence.md +150 -0
- package/claude/skills/review-address/references/post-review-findings.md +10 -3
- package/claude/skills/review-address/references/rebase-conflicts.md +15 -7
- package/claude/skills/review-address/references/rest-reads.md +3 -1
- package/claude/skills/review-craft/references/adopted.md +35 -18
- package/claude/skills/review-craft/references/security.md +42 -7
- package/claude/skills/review-craft/references/ui.md +23 -8
- package/claude/skills/review-pr/SKILL.md +6 -6
- package/claude/skills/review-pr/references/body-variants.md +29 -9
- package/claude/skills/review-pr/references/close-out.md +20 -5
- package/claude/skills/review-pr/references/key-changes.md +27 -3
- package/claude/skills/review-pr/references/post.md +83 -31
- package/claude/skills/review-pr/references/scope.md +54 -19
- package/claude/skills/review-ui/references/close-out.md +7 -5
- package/claude/skills/review-ui/references/driving.md +24 -4
- package/claude/skills/review-ui/references/post.md +43 -15
- package/claude/skills/role-orchestrator/SKILL.md +2 -0
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +67 -17
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +80 -40
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +52 -15
- package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +48 -26
- package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +12 -13
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +72 -36
- package/claude/skills/role-orchestrator/references/orchestrator-output.md +16 -4
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +64 -24
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +80 -26
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +41 -18
- package/claude/skills/role-orchestrator/references/orchestrator-resume.md +19 -7
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +22 -12
- package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +15 -6
- package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +25 -7
- package/claude/skills/role-orchestrator/references/orchestrator-watch.md +34 -8
- package/claude/skills/role-orchestrator/scripts/poll.ts +16 -24
- package/claude/skills/role-planner/REQUIREMENT.md +1 -1
- package/claude/skills/role-planner/SKILL.md +3 -3
- package/claude/skills/role-worker/REQUIREMENT.md +3 -0
- package/claude/skills/role-worker/SKILL.md +34 -2
- package/claude/skills/search-craft/REQUIREMENT.md +1 -1
- package/claude/skills/search-craft/SKILL.md +2 -2
- package/claude/skills/search-craft/references/adopted.md +18 -6
- package/claude/skills/session-map/references/session.md +26 -7
- package/claude/skills/session-worktree/references/main-root-writes.md +25 -8
- package/claude/skills/systematic-debugging/references/adopted.md +30 -16
- package/claude/skills/target-check/references/domains.md +39 -11
- package/claude/skills/target-setup/references/detect.md +80 -65
- package/claude/skills/target-setup/references/indexes.md +8 -6
- package/claude/skills/task-board/references/board.md +86 -30
- package/claude/skills/task-board/references/decline.md +29 -13
- package/claude/skills/task-board/references/tasks-decline.md +12 -5
- package/claude/skills/task-board/references/tasks.md +65 -33
- package/claude/skills/task-complete/references/archive.md +41 -17
- package/claude/skills/task-complete/references/receipt-sweep.md +23 -9
- package/claude/skills/task-complete/references/unusable-baseline.md +10 -3
- package/claude/skills/teach-workspace/references/glossary.md +6 -2
- package/claude/skills/teach-workspace/references/lesson-build.md +44 -16
- package/claude/skills/teach-workspace/references/lesson-craft.md +12 -7
- package/claude/skills/teach-workspace/references/pedagogy.md +6 -3
- package/claude/skills/teach-workspace/references/promotion-fold.md +17 -11
- package/claude/skills/teach-workspace/references/promotion.md +31 -8
- package/claude/skills/teach-workspace/references/revisit.md +8 -2
- package/claude/skills/teach-workspace/references/teach.md +17 -9
- package/claude/skills/test-craft/references/adopted.md +48 -14
- package/claude/skills/test-craft/references/component.md +7 -4
- package/claude/skills/test-craft/references/e2e.md +25 -7
- package/claude/skills/test-craft/references/unit.md +3 -1
- package/claude/skills/test-first/references/adopted.md +12 -4
- package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
- package/claude/skills/ui-checklist/SKILL.md +1 -1
- package/claude/skills/video-craft/references/adopted.md +62 -18
- package/claude/skills/write-human/references/adopted.md +21 -8
- package/docs/agents/audits.md +1 -0
- package/docs/agents/migrate.md +11 -8
- package/docs/target/migrations.md +11 -0
- package/docs/workflow/parallel-features.md +1 -1
- package/docs/workflow/skill-map.md +1 -0
- package/governance/detect.toml +4 -0
- package/governance/rules/canon/context.md +2 -1
- package/governance/rules/canon/plan.md +3 -5
- package/governance/rules/canon/scratch.md +3 -1
- package/governance/rules/canon/task-scope.md +2 -1
- package/governance/rules/canon/tasks.md +2 -1
- package/governance/rules/canon/worktrees.md +5 -2
- package/governance/rules/claude/output.md +7 -4
- package/governance/rules/claude/skill.md +6 -4
- package/governance/rules/tooling/ci-workflow.md +6 -39
- package/governance/rules/ui/design-reference.md +37 -0
- package/governance/rules/writing/markdown.md +2 -1
- package/package.json +6 -6
- package/src/audits/catalog.ts +42 -0
- package/src/claude/cases/workflow.ts +5 -0
- package/src/claude/settings.ts +8 -4
- package/src/commands/claude.ts +11 -1
- package/src/commands/gov.ts +198 -0
- package/src/commands/migrate.ts +121 -2
- package/src/commands/pr.ts +146 -105
- package/src/commands/tooling.ts +3 -3
- package/src/commands/worktrees.ts +49 -0
- package/src/gate/stages.ts +15 -0
- package/src/gov/audit.ts +440 -0
- package/src/listeners/belongs.ts +21 -0
- package/src/listeners/machine.ts +93 -0
- package/src/listeners/parse.ts +41 -0
- package/src/markdown/scope.ts +144 -0
- package/src/migrate/session-defaults.ts +138 -0
- package/src/pr/lift.ts +6 -3
- package/src/pr/local.ts +4 -69
- package/src/pr/review-state.ts +182 -0
- package/src/sync/check.ts +15 -0
- package/src/tooling/stamp.ts +56 -12
- package/src/worktrees/stop.ts +92 -0
- package/tooling/base/configs/.github/workflows/phase-label-gate.yml +6 -2
- package/tooling/base/configs/commitlint.config.js +0 -20
- package/tooling/base/reference.md +1 -1
- package/tooling/base/seeds/.github/workflows/verify.yml +4 -1
- package/tooling/claude/reference.md +13 -7
- package/tooling/claude/seeds/.claude/settings.json +4 -0
- package/tooling/claude/user/settings.template.json +0 -4
- package/tooling/cloudflare/configs/.github/workflows/deploy.yml +5 -5
- package/tooling/public/configs/.github/dependabot.yml +12 -0
- package/tooling/public/configs/.github/workflows/release-please.yml +30 -0
- package/tooling/public/manifest.toml +8 -0
- package/tooling/public/reference.md +53 -0
- package/tooling/public/seeds/.github/ISSUE_TEMPLATE/bug.yml +48 -0
- package/tooling/public/seeds/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/tooling/public/seeds/.github/ISSUE_TEMPLATE/feature.yml +16 -0
- package/tooling/public/seeds/.release-please-manifest.json +3 -0
- package/tooling/public/seeds/CONTRIBUTING.md +50 -0
- package/tooling/public/seeds/LICENSE +21 -0
- package/tooling/public/seeds/SECURITY.md +13 -0
- package/tooling/public/seeds/release-please-config.json +12 -0
- package/tooling/shell/configs/.github/workflows/shell.yml +4 -1
- package/tooling/web/configs/.github/workflows/readme-screenshot.yml +6 -3
- package/tooling/web/configs/.github/workflows/verify.yml +15 -12
- package/claude/skills/git-pr/references/evidence.md +0 -124
|
@@ -5,9 +5,7 @@ description: The catalog reads, evidence list, argument resolution, gap handling
|
|
|
5
5
|
|
|
6
6
|
# Detect and resolve
|
|
7
7
|
|
|
8
|
-
What the `install` and `gov` phases both do before they write anything. Stated
|
|
9
|
-
once here rather than twice in the body, since the two phases differ in what
|
|
10
|
-
they install rather than in how they read the project.
|
|
8
|
+
What the `install` and `gov` phases both do before they write anything. Stated once here rather than twice in the body, since the two phases differ in what they install rather than in how they read the project.
|
|
11
9
|
|
|
12
10
|
## Contents
|
|
13
11
|
|
|
@@ -19,25 +17,20 @@ they install rather than in how they read the project.
|
|
|
19
17
|
|
|
20
18
|
## Read the catalogs
|
|
21
19
|
|
|
22
|
-
Run in parallel. Never hardcode stack, rule, or standards names. The
|
|
23
|
-
catalog is the source of truth.
|
|
20
|
+
Run in parallel. Never hardcode stack, rule, or standards names. The catalog is the source of truth.
|
|
24
21
|
|
|
25
|
-
Run from the target project's current directory. Do not cd into the toolkit
|
|
26
|
-
source tree. The `canon` CLI is global.
|
|
22
|
+
Run from the target project's current directory. Do not cd into the toolkit source tree. The `canon` CLI is global.
|
|
27
23
|
|
|
28
24
|
```bash
|
|
29
25
|
canon gov list --json 2>/dev/null
|
|
30
26
|
canon tooling list --json 2>/dev/null
|
|
31
27
|
```
|
|
32
28
|
|
|
33
|
-
The `gov` phase needs only the first. Run both anyway on a bare invocation,
|
|
34
|
-
since the chain reaches the tooling resolution a moment later.
|
|
29
|
+
The `gov` phase needs only the first. Run both anyway on a bare invocation, since the chain reaches the tooling resolution a moment later.
|
|
35
30
|
|
|
36
31
|
## Detect
|
|
37
32
|
|
|
38
|
-
A monorepo keeps its languages in subfolders, so read the markers from every
|
|
39
|
-
folder to depth two rather than from the root alone. Collect the language roots
|
|
40
|
-
first:
|
|
33
|
+
A monorepo keeps its languages in subfolders, so read the markers from every folder to depth two rather than from the root alone. Collect the language roots first:
|
|
41
34
|
|
|
42
35
|
```bash
|
|
43
36
|
git ls-files --cached --others --exclude-standard \
|
|
@@ -45,25 +38,21 @@ git ls-files --cached --others --exclude-standard \
|
|
|
45
38
|
| awk -F/ 'NF <= 3'
|
|
46
39
|
```
|
|
47
40
|
|
|
48
|
-
Every folder holding a marker is a language root,
|
|
49
|
-
one when it holds a marker itself. Going through git keeps ignored trees such as
|
|
50
|
-
`node_modules/`, `vendor/`, and `.venv/` off the list, since each carries
|
|
51
|
-
markers of its own. Outside a git repository, fall back to
|
|
52
|
-
`find . -maxdepth 3 \( -path '*/.*' -o -name node_modules -o -name vendor \) -prune -o -type f -print`
|
|
53
|
-
filtered to the same five names.
|
|
41
|
+
Every folder holding a marker is a language root, the repository root included when it holds one itself. Going through git keeps ignored trees such as `node_modules/`, `vendor/`, and `.venv/` off the list, since each carries markers of its own.
|
|
54
42
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
examples as false roots.
|
|
43
|
+
- Outside a git repository, fall back to `find . -maxdepth 3 \( -path '*/.*' -o -name node_modules -o -name vendor \) -prune -o -type f -print` filtered to the same five names
|
|
44
|
+
- Depth two reaches a service folder at depth one and a workspace package under `packages/<name>/`. Deeper, the walk finds fixtures and examples as false roots.
|
|
58
45
|
|
|
59
|
-
|
|
46
|
+
### Per root
|
|
47
|
+
|
|
48
|
+
Read these per language root in parallel, skipping any that do not exist:
|
|
60
49
|
|
|
61
50
|
- `package.json`: `dependencies` and `devDependencies`
|
|
62
51
|
- The root's own configs: `astro.config.*`, `next.config.*`, `vite.config.*`, `tailwind.config.*`, `tsconfig.json`, `pyproject.toml`, `go.mod`, `composer.json`, `Cargo.toml`
|
|
63
52
|
|
|
64
|
-
A non-JavaScript marker outranks a `package.json` in the same folder. A Go or
|
|
65
|
-
|
|
66
|
-
|
|
53
|
+
A non-JavaScript marker outranks a `package.json` in the same folder. A Go or Composer service often carries a `package.json` only to host scripts, so that folder is a Go or PHP root.
|
|
54
|
+
|
|
55
|
+
### Once, at the root
|
|
67
56
|
|
|
68
57
|
Read these once, from the repository root:
|
|
69
58
|
|
|
@@ -72,39 +61,56 @@ Read these once, from the repository root:
|
|
|
72
61
|
|
|
73
62
|
## Resolve arguments
|
|
74
63
|
|
|
75
|
-
Governance installs once, at the repository root, and a rule's `paths:` globs
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
Governance installs once, at the repository root, and a rule's `paths:` globs already reach every subfolder. Tooling installs per folder, so resolve one governance stack for the whole repository and one tooling stack per language root.
|
|
65
|
+
|
|
66
|
+
### Governance stack
|
|
67
|
+
|
|
68
|
+
Match the repository root's detected language against stack names in the catalog. Governance stacks are per language, so a framework never names one, and its rules arrive as extras.
|
|
69
|
+
|
|
70
|
+
- If the root matched nothing, `base` is the stack, even when subfolders matched. No subfolder owns the repository, and picking one by order states a preference nobody gave.
|
|
71
|
+
- Mark it `fallback` in the preview only when no root matched anywhere
|
|
72
|
+
|
|
73
|
+
### Tooling stack
|
|
74
|
+
|
|
75
|
+
For each language root, pick the closest tooling stack from `canon tooling list --json`, such as `vite-react`, `astro`, or `nextjs`. It is distinct from the governance stack.
|
|
76
|
+
|
|
77
|
+
- Fall back to `base` for a root with no framework or language match, and carry that fallback into its preview row
|
|
78
|
+
- Map `next` in a root's dependencies, or a `next.config.ts`, `.js`, or `.mjs` there, to the `node` governance stack and the `nextjs` tooling stack
|
|
79
|
+
- The `next` dependency name alone matches no stack, and the Next.js rule arrives as an extra
|
|
80
|
+
|
|
81
|
+
### Extras
|
|
82
|
+
|
|
83
|
+
Run `canon gov detect <target> --stack <stack> --json` from the target and take its `proposals` array as the candidate extras. Each proposal names a `rule` and the `evidence` that matched it across every language root to depth two.
|
|
84
|
+
|
|
85
|
+
- The verb already leaves out every rule the picked stack resolves, so do not dedupe again
|
|
86
|
+
- Do not match a rule's `description` or `paths` by hand
|
|
87
|
+
- The verb proposes no language rule, since a stack reaches each one
|
|
88
|
+
|
|
89
|
+
A language root below the repository root whose language the stack does not carry contributes its language rule by name, read from `canon gov list --json`.
|
|
90
|
+
|
|
91
|
+
### Subfolder tooling and skips
|
|
79
92
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
- **Subfolder language rules:** a language root below the repository root whose language the picked stack does not carry contributes its language rule by name, read from `canon gov list --json`. The verb proposes no language rule, since a stack reaches each one.
|
|
85
|
-
- **Subfolder tooling:** a language root below the repository root takes its own `canon tooling sync <stack> <path> --skip base`, since `canon init` already lands `base` once at the root. Leave a root whose stack resolves to `base` out of the commands, since that sync would land nothing. A repository-root `package.json` hosting only formatters and hooks is that case, and it adds no row.
|
|
86
|
-
- **Skip (`--skip`):** `wiki` installs by default. Add `--skip wiki` only when the user explicitly wants it left out.
|
|
93
|
+
A language root below the repository root takes its own `canon tooling sync <stack> <path> --skip base`, since `canon init` already lands `base` once at the root.
|
|
94
|
+
|
|
95
|
+
- Leave a root whose stack resolves to `base` out of the commands, since that sync lands nothing. A root `package.json` hosting only formatters and hooks is that case and adds no row.
|
|
96
|
+
- `wiki` installs by default. Add `--skip wiki` only when the user explicitly wants it left out.
|
|
87
97
|
|
|
88
98
|
## Gap handling
|
|
89
99
|
|
|
90
|
-
If a detected technology has no matching rule or stack, do not guess. Surface
|
|
91
|
-
|
|
100
|
+
If a detected technology has no matching rule or stack, do not guess. Surface the gap.
|
|
101
|
+
|
|
102
|
+
On the full chain, either defer and author a rule in the toolkit before re-running, or proceed with the matched layer and list the gap in the final report. Rules and stacks are authored in the toolkit repository, never in the target project on the fly.
|
|
92
103
|
|
|
93
|
-
|
|
94
|
-
re-running, or proceed with the matched layer and list the gap in the final
|
|
95
|
-
report. Rules and stacks are authored in the toolkit repository, never in the
|
|
96
|
-
target project on the fly.
|
|
104
|
+
### The gov phase
|
|
97
105
|
|
|
98
106
|
On the `gov` phase, stop and present four options rather than picking:
|
|
99
107
|
|
|
100
|
-
1. Author a
|
|
101
|
-
2. Invoke `create-rule`, which scaffolds the file into the target project at a non-colliding number. Take this
|
|
108
|
+
1. Author a rule in the toolkit at `governance/rules/<domain>/<num>-<name>.md` per `${CLAUDE_SKILL_DIR}/../create-rule/references/rule.md`, commit, and re-run install, when every project should get it.
|
|
109
|
+
2. Invoke `create-rule`, which scaffolds the file into the target project at a non-colliding number. Take this when the rule is project-specific and no sync should overwrite it.
|
|
102
110
|
3. Install the matching non-`<tech>` rules and skip the tech-specific layer.
|
|
103
111
|
4. Abort.
|
|
104
112
|
|
|
105
|
-
`--skip-gaps` takes option 3 ahead of the prompt, which
|
|
106
|
-
non-interactive. This skill authors no rule itself. Option 1 writes in the
|
|
107
|
-
toolkit repository, and option 2 hands the project-local file to `create-rule`.
|
|
113
|
+
`--skip-gaps` takes option 3 ahead of the prompt, which keeps the phase non-interactive. This skill authors no rule itself, since option 1 writes in the toolkit and option 2 hands the file to `create-rule`.
|
|
108
114
|
|
|
109
115
|
## Preview
|
|
110
116
|
|
|
@@ -112,28 +118,37 @@ Before executing, output:
|
|
|
112
118
|
|
|
113
119
|
- **Detected:** each technology with its evidence file, path included, so a subfolder marker reads as one
|
|
114
120
|
- **Stack:** picked governance stack and resolved rule count. Mark it `fallback` when no detected language matched a catalog name.
|
|
115
|
-
- **Tooling stack:** one row per language root, each
|
|
116
|
-
- **Extras:** each proposal with the evidence the verb returned, plus each subfolder language rule, listed in full as the list the operator confirms
|
|
121
|
+
- **Tooling stack:** one row per language root, each with its path, picked stack, a `fallback` mark on the same test, and its own command. Omit these rows on the `gov` phase.
|
|
122
|
+
- **Extras:** each proposal with the evidence the verb returned, plus each subfolder language rule, listed in full as the list the operator confirms
|
|
117
123
|
- **Skip:** any `--skip` entries with reason
|
|
118
124
|
- **Target:** resolved target path
|
|
119
125
|
- **Commands:** the full chain that will run
|
|
120
126
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
127
|
+
### The root tooling row
|
|
128
|
+
|
|
129
|
+
On the repository root's row, name what `base` lands. Configs, seeds, and gitignore entries land in every case.
|
|
130
|
+
|
|
131
|
+
- The JavaScript development dependencies, scripts, and hook activation land wherever a `package.json` exists to carry them
|
|
132
|
+
- A project outside that ecosystem runs none of that second group and keeps the first
|
|
133
|
+
|
|
134
|
+
### Why mark it here
|
|
135
|
+
|
|
136
|
+
A resolved name and a fallback read alike once written, so mark the fallback in the preview rather than the report. The preview is the last point before the first write.
|
|
137
|
+
|
|
138
|
+
The extras list stays whole for a similar reason. `canon init --stack` takes one stack, so a second matched stack reaches the install only through this list, and a shortened list reads as that stack dropped.
|
|
124
139
|
|
|
125
140
|
### Confirm the extras
|
|
126
141
|
|
|
127
|
-
The extras are the one part of the preview the operator confirms before the
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
they kept nothing.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
headless setup.
|
|
142
|
+
The extras are the one part of the preview the operator confirms before the install runs, since a proposal is evidence that a project might want a rule rather than proof that it does. Put the list through the structured question surface with three options.
|
|
143
|
+
|
|
144
|
+
- Take every proposal, the recommended first option
|
|
145
|
+
- Take none
|
|
146
|
+
- Name a subset, which the operator types as a comma-separated list
|
|
147
|
+
|
|
148
|
+
Pass what they kept to `--add`, and drop the flag when they kept nothing.
|
|
149
|
+
|
|
150
|
+
### Answering ahead
|
|
151
|
+
|
|
152
|
+
An `--extras` argument answers ahead of time and skips the question. `--extras <a>,<b>` takes the named rules, and `--extras none` takes none.
|
|
153
|
+
|
|
154
|
+
With neither and no one to answer, take every proposal and list each in the report. A proposed rule costs one file to delete, and stopping would break every headless setup.
|
|
@@ -29,7 +29,8 @@ before scanning.
|
|
|
29
29
|
|
|
30
30
|
- Bootstrap un-indexed folders only. Skip folders that already contain an `index.md`.
|
|
31
31
|
- All-or-nothing per chosen folder. Every `*.md` sibling in a chosen folder gets `title` and `description` injected, or none does. Partial migration creates folders that hard-error on regen.
|
|
32
|
-
-
|
|
32
|
+
- An install wanting the Claude layer without the tooling chain arrives here once `canon claude init` has seeded the docs
|
|
33
|
+
- The work is the same either way, since the scan prunes `.claude` and reads the project's own documentation folders whichever route reached it
|
|
33
34
|
|
|
34
35
|
## Scan
|
|
35
36
|
|
|
@@ -75,7 +76,8 @@ candidate list and stop rather than choosing on the operator's behalf.
|
|
|
75
76
|
For each chosen folder, read every `*.md` sibling and draft frontmatter:
|
|
76
77
|
|
|
77
78
|
- `title`: derived from the first H1. If absent, derive from the filename in sentence case.
|
|
78
|
-
- `description`: one line summarizing the file's purpose, drawn from the first paragraph after the H1
|
|
79
|
+
- `description`: one line summarizing the file's purpose, drawn from the first paragraph after the H1
|
|
80
|
+
- Follow `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md` § Frontmatter descriptions for the description's length and style
|
|
79
81
|
|
|
80
82
|
Surface every drafted entry to the user grouped by file:
|
|
81
83
|
|
|
@@ -131,10 +133,10 @@ canon indexes regen --json
|
|
|
131
133
|
```
|
|
132
134
|
|
|
133
135
|
Count the `written` actions in that record and report the number. Read the real
|
|
134
|
-
run the
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
regen that errored on a sibling missing `title` arrives here as a clean pass
|
|
136
|
+
run the way the dry run is read, since the exit carries nothing reliable back.
|
|
137
|
+
|
|
138
|
+
- An operator's shell profile may wrap `canon` in a function that takes a second command's status
|
|
139
|
+
- A regen that errored on a sibling missing `title` then arrives here as a clean pass
|
|
138
140
|
|
|
139
141
|
## Offer the convention seed
|
|
140
142
|
|
|
@@ -40,51 +40,104 @@ A board failing these is non-conforming even when it satisfies every shape rule
|
|
|
40
40
|
|
|
41
41
|
`canon tasks list` reports each task's readiness from `priority.md` and `backlog.md`, so a reader never infers it from the folder.
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
| File | Rule |
|
|
44
|
+
| ------------- | ----------------------------------------------------------------------------------------- |
|
|
45
|
+
| `priority.md` | Required. Carries execution order and what each task waits on |
|
|
46
|
+
| `backlog.md` | Optional. A project whose every task would be planned soon carries none |
|
|
47
|
+
| `index.md` | Generated from sibling frontmatter by a hook passing the changed path. Never hand-edit it |
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
The catalog is the one reader that filters nothing, so it carries a row per sibling alongside the tasks, handoffs included. Anything reading the catalog as the backlog therefore does its own filtering, and a reader that takes every row as a task reports the handoffs as queued work.
|
|
49
|
+
The folder is gitignored, so the whole-repo index walk skips it. The catalog filters nothing and carries a row per sibling, handoffs included, so a reader taking every row as a task reports the handoffs as queued work.
|
|
48
50
|
|
|
49
51
|
## Ordering
|
|
50
52
|
|
|
51
|
-
`priority.md` carries execution order and what each task
|
|
53
|
+
`priority.md` carries execution order and what each task waits on. The generated index sorts by filename and says nothing about order, so without this file board state gets rebuilt by hand every session.
|
|
54
|
+
|
|
55
|
+
### Where the rationale lives
|
|
56
|
+
|
|
57
|
+
Why a row sits where it does is stated on the row, in the cell that already says what the task waits on, one line per row.
|
|
52
58
|
|
|
53
|
-
|
|
59
|
+
- Rationale spanning several rows has no home, and the gap is deliberate. A second document holding it would be the version-sequencing surface this board replaced.
|
|
60
|
+
- The row already states what it waits on, which is the part of the reasoning a reader acts on.
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
### The shape
|
|
63
|
+
|
|
64
|
+
Group tasks by readiness rather than by status, one row per task, under the columns each group fixes. Keep it to links and blockers, being tables plus at most one sentence per section.
|
|
65
|
+
|
|
66
|
+
- A paragraph in `priority.md` is a defect whatever it says
|
|
67
|
+
- Stating the shape lets a single diff fail. A size cap trips only after the fact, and every addition looks defensible on its own.
|
|
56
68
|
|
|
57
69
|
### Readiness groups
|
|
58
70
|
|
|
59
|
-
Readiness is three groups under fixed headings, `## Run now`, `## Up next`, and `## Needs a plan`, in that order.
|
|
71
|
+
Readiness is three groups under fixed headings, `## Run now`, `## Up next`, and `## Needs a plan`, in that order. A task belongs to exactly one, and the tests are read in order.
|
|
72
|
+
|
|
73
|
+
| Group | Test |
|
|
74
|
+
| ----------------- | -------------------------------------------------------------------------------------- |
|
|
75
|
+
| `## Run now` | A written plan covers every open outcome, and nothing stated keeps the task from start |
|
|
76
|
+
| `## Up next` | A written plan exists, and the `Waiting on` column names why the task cannot start |
|
|
77
|
+
| `## Needs a plan` | Everything else. No plan, or a plan that no longer describes the work |
|
|
78
|
+
|
|
79
|
+
The names are the contract. A board grouped by readiness under names of its own reads as empty to anything counting rows under a heading, so add no fourth group.
|
|
80
|
+
|
|
81
|
+
### What blocks a run
|
|
82
|
+
|
|
83
|
+
A collision with running work blocks a task only where no merge settles it, being a contract, a relocation, or a sweep. A shared file alone is none, since the branch merging second rebases.
|
|
84
|
+
|
|
85
|
+
- A worker is handed a task from `## Run now` alone, and its `Touches` column states the set to read
|
|
86
|
+
- Each group's columns follow from its test. Neither half of the `## Run now` test is checkable without the file set and the plan beside the task.
|
|
87
|
+
|
|
88
|
+
### The `Touches` cell
|
|
60
89
|
|
|
61
|
-
|
|
62
|
-
- `## Up next`: a written plan exists, and the task carries a stated reason it cannot start. The `Waiting on` column names that reason.
|
|
63
|
-
- `## Needs a plan`: everything else. The task has no plan, or the plan it carries no longer describes the work.
|
|
90
|
+
A `Touches` cell is copied from its plan's list, so it states what the branch sets out to write rather than a bound on it. A branch outgrows it while the row still reads as it did at dispatch.
|
|
64
91
|
|
|
65
|
-
|
|
92
|
+
- Once a branch runs, correct the cell from the diff rather than the plan, which is the prediction that already went stale
|
|
93
|
+
- `canon tasks plan-reach <plan>` reads that diff against every live plan and every cell in the group
|
|
94
|
+
- The row's owner writes the correction. A worker never edits this board.
|
|
66
95
|
|
|
67
|
-
|
|
96
|
+
### Cell width
|
|
68
97
|
|
|
69
|
-
A cell holds no code span whose longest unbroken run passes 60 characters
|
|
98
|
+
A cell holds no code span whose longest unbroken run passes 60 characters. A span has no break point, and a wider one makes its table scroll sideways in the preview.
|
|
99
|
+
|
|
100
|
+
- Write a brace-glob out as separate paths for the same reason
|
|
101
|
+
- `canon tasks validate` reports both in its `wide` array and moves no exit code
|
|
70
102
|
|
|
71
103
|
### Row order
|
|
72
104
|
|
|
73
|
-
Row position inside `## Needs a plan` is the order those tasks get planned in, top first. The three tests answer whether a task can start,
|
|
105
|
+
Row position inside `## Needs a plan` is the order those tasks get planned in, top first. The three tests answer whether a task can start, and none answers which task is worth starting, a judgment no column holds.
|
|
74
106
|
|
|
75
|
-
Position
|
|
107
|
+
- Position records that judgment, so the top row answers what to plan next. The other two groups read position the same way, and they are short by construction.
|
|
108
|
+
- No rank column exists. A number beside each row duplicates the order, and one session edits the file at a time, so the written order is unambiguous.
|
|
109
|
+
- A position with no stated reason gets re-derived from memory by the next session, the failure the ordering replaces
|
|
76
110
|
|
|
77
111
|
### The waiting-on cell
|
|
78
112
|
|
|
79
|
-
The `Waiting on` column under `## Up next` carries
|
|
113
|
+
The `Waiting on` column under `## Up next` carries the reason in one of three forms. `## Needs a plan` states no file set, because a task with no plan has no bounded one. A group with no rows keeps its heading and header row.
|
|
114
|
+
|
|
115
|
+
| Form | The cell names |
|
|
116
|
+
| ------------------ | ----------------------------------------------------------------------------- |
|
|
117
|
+
| Collision | The file the running task holds, and whether a contract, relocation, or sweep |
|
|
118
|
+
| Sibling task | That task |
|
|
119
|
+
| External condition | The condition and what would satisfy it |
|
|
120
|
+
|
|
121
|
+
Naming what would satisfy a condition separates a blocked row from one nobody examined, so a condition with no way out fails the test. The header text is the contract, since a reader resolves the column by header rather than position.
|
|
122
|
+
|
|
123
|
+
### The needs-a-plan cell
|
|
124
|
+
|
|
125
|
+
Under `## Needs a plan` the cell takes two clauses, being what the task needs before it can be planned and then why it sits at this position. The second clause names what the row ranks against, a sibling row or the class of rows it sits in.
|
|
80
126
|
|
|
81
|
-
|
|
127
|
+
- The row `leads`, `heads`, `opens`, `closes`, `trails`, `precedes`, `follows`, or `outranks` what it names, or `sits under`, `above`, or `below` it
|
|
128
|
+
- Either form puts something other than this row in the clause, which makes the position readable by anyone but its author
|
|
129
|
+
- `canon tasks validate` reads that clause back and recognizes this vocabulary alone. A phrasing outside it reports as unranked, and widening it is a change to the check.
|
|
82
130
|
|
|
83
|
-
|
|
131
|
+
### What the cell drifts into
|
|
84
132
|
|
|
85
|
-
Why the task matters is not
|
|
133
|
+
Why the task matters is not the comparative claim, and it is what the cell drifts into. A reason naming no other row ranks against nothing, so every row reads defensible and the order records only when each was filed.
|
|
86
134
|
|
|
87
|
-
|
|
135
|
+
- The comparison replaces that reason rather than joining it, and no third clause is licensed by naming a rival in the second
|
|
136
|
+
- A longer cell is the deleted paragraph arriving one row at a time. It costs most in this group, which holds the rows nobody read recently.
|
|
137
|
+
|
|
138
|
+
### Template
|
|
139
|
+
|
|
140
|
+
The tests live here so the board does not carry them. A sentence under each heading produces the deleted paragraph, and a criterion with no home gets restated from memory each time.
|
|
88
141
|
|
|
89
142
|
```markdown
|
|
90
143
|
---
|
|
@@ -112,19 +165,22 @@ description: One line on what the board covers
|
|
|
112
165
|
| [vXX.Y <slug>](vXX.Y-<slug>.md) | <what it needs before it can be planned, and which row or class it ranks against> |
|
|
113
166
|
```
|
|
114
167
|
|
|
115
|
-
The tests live here so the board does not carry them. Writing them as a sentence under each heading produces the paragraph the rule above deletes, and a criterion with no home gets restated from memory every time the board is touched.
|
|
116
|
-
|
|
117
168
|
## The backlog
|
|
118
169
|
|
|
119
|
-
A task sits on the board when it would plausibly be planned within the next few waves, and on `backlog.md` otherwise.
|
|
170
|
+
A task sits on the board when it would plausibly be planned within the next few waves, and on `backlog.md` otherwise. Restate that judgment whenever the board is swept, since a backlogged task rises when the work in front of it lands and a board row falls when it stops being near-term.
|
|
171
|
+
|
|
172
|
+
### Why a split
|
|
173
|
+
|
|
174
|
+
A test over age or origin was the alternative, and neither predicts what gets picked next. Leaving everything on the board produces a group too long to rank.
|
|
120
175
|
|
|
121
|
-
|
|
176
|
+
- The split keeps the board short enough for its order to be read, at the cost of a second surface
|
|
177
|
+
- The trade pays only while the backlog carries no order, no groups, and no readiness claim
|
|
122
178
|
|
|
123
|
-
|
|
179
|
+
### Shape
|
|
124
180
|
|
|
125
|
-
Nothing is deleted. A backlogged task keeps its file,
|
|
181
|
+
Nothing is deleted. A backlogged task keeps its file, findings, and frontmatter, and the row points at that file. The folder has no history, so a row dropped without landing somewhere readable is gone.
|
|
126
182
|
|
|
127
|
-
The backlog is a flat list of links under one heading, sorted by filename.
|
|
183
|
+
The backlog is a flat list of links under one heading, sorted by filename. The order matches the index, so no position on it reads as a queue.
|
|
128
184
|
|
|
129
185
|
```markdown
|
|
130
186
|
---
|
|
@@ -140,8 +196,8 @@ Unordered. Nothing here is scheduled, and a task rises to `priority.md` when it
|
|
|
140
196
|
- [vXX.Y <slug>](vXX.Y-<slug>.md)
|
|
141
197
|
```
|
|
142
198
|
|
|
143
|
-
Add no fourth readiness group in place of this file.
|
|
199
|
+
Add no fourth readiness group in place of this file. A backlog makes no readiness claim, only that nobody has scheduled the task, a fact about attention rather than whether the work can start.
|
|
144
200
|
|
|
145
201
|
## Validation
|
|
146
202
|
|
|
147
|
-
`canon tasks validate` reads the board against the tree, and what it checks,
|
|
203
|
+
`canon tasks validate` reads the board against the tree, and `canon tasks validate --help` states what it checks, refuses on, and reports. Run it when the readiness claim is made rather than on a schedule, since the board is per-machine scratch and no shared moment exists to hang it on.
|
|
@@ -7,15 +7,13 @@ description: How task-board gathers the reason a task is decided against, runs c
|
|
|
7
7
|
|
|
8
8
|
The Decline mode of `task-board`. The session reads this file when the request names a task decided against.
|
|
9
9
|
|
|
10
|
-
Read `${CLAUDE_SKILL_DIR}/references/tasks-decline.md` first
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Do not move the file, edit `priority.md` or `backlog.md`, or regenerate the index by hand. `canon tasks decline` owns all three as one unit.
|
|
10
|
+
- Read `${CLAUDE_SKILL_DIR}/references/tasks-decline.md` first, for the declined folder, the `Declined:` line, and what the move does to a plan and a board row
|
|
11
|
+
- A declined task carries no `post-merge` hook of its own, so every decline request arrives here directly
|
|
12
|
+
- `canon tasks decline` moves the file, edits `priority.md` or `backlog.md`, and regenerates the index as one unit. Do none of the three by hand.
|
|
15
13
|
|
|
16
14
|
## Step 1: gather the reason
|
|
17
15
|
|
|
18
|
-
Ask for the reason when the request
|
|
16
|
+
Ask for the reason when the request carries none, and stop rather than guessing with `❌ No reason. Say why the task is being declined.` The command refuses without `--reason <text>`, so asking first saves the round trip.
|
|
19
17
|
|
|
20
18
|
## Step 2: run the decline
|
|
21
19
|
|
|
@@ -25,18 +23,36 @@ Pass the task's filename stem:
|
|
|
25
23
|
canon tasks decline <stem> --reason "<text>" [--by <name>] --json
|
|
26
24
|
```
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
Branch on the record's `ok`, then on `reason`, never on the exit. A shell wrapper can flatten the exit, the same hazard `canon tasks archive` carries.
|
|
27
|
+
|
|
28
|
+
### Success record
|
|
29
|
+
|
|
30
|
+
A successful decline returns one record whose fields match `canon tasks archive` where the two overlap.
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
| Field | Holds |
|
|
33
|
+
| -------------------- | ------------------------------------------------------------------------ |
|
|
34
|
+
| `from`, `to` | The task's old and new path |
|
|
35
|
+
| `priorityRowRemoved` | Whether a `priority.md` row was dropped |
|
|
36
|
+
| `backlogRowRemoved` | Whether a `backlog.md` row was dropped, a field archive lacks |
|
|
37
|
+
| `indexRegenerated` | Whether the index was rewritten |
|
|
38
|
+
| `plans` | A `from` and `to` per live plan the task last cited, empty if none moved |
|
|
39
|
+
|
|
40
|
+
`backlogRowRemoved` is decline's own, since a task can be declined straight off `backlog.md` and archive never checks that file.
|
|
31
41
|
|
|
32
42
|
## Step 3: route on a refusal
|
|
33
43
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
Each refusal names its cause and the fix.
|
|
45
|
+
|
|
46
|
+
| `reason` | Cause | Fix |
|
|
47
|
+
| ----------- | -------------------------------------------------------------------- | ------------------------------------------ |
|
|
48
|
+
| `no-match` | No task matches, or one starts with the stem and needs its full name | Check against the listed stems |
|
|
49
|
+
| `ambiguous` | The stem is a prefix of more than one task | Pass the full stem |
|
|
50
|
+
| `bad-input` | The command line was wrong rather than the board | Read the message, fix the arguments, rerun |
|
|
51
|
+
|
|
52
|
+
Archive's own `ambiguous` fires on a shared pull request instead, and decline takes no pull-request selector. A `bad-input` leaves nothing on the board to repair, which separates it from the other two.
|
|
37
53
|
|
|
38
|
-
|
|
54
|
+
Never move a plan by hand from this skill. The command carries the plan along when no other live task cites it and retargets the `Plan:` line, and a second mover relocates the same file differently.
|
|
39
55
|
|
|
40
56
|
## Step 4: clear prose naming the task
|
|
41
57
|
|
|
42
|
-
The command drops the
|
|
58
|
+
The command drops the row from `.canon/tasks/priority.md` or `.canon/tasks/backlog.md` and leaves prose alone. Remove any sentence that still names the declined task or counts the changed rows, since a stale count reads as board state.
|
|
@@ -27,12 +27,19 @@ A declined task works when a later reader can tell, from the folder and the file
|
|
|
27
27
|
|
|
28
28
|
## Declining
|
|
29
29
|
|
|
30
|
-
A task decided against moves to `.canon/tasks/declined/` rather than `.canon/tasks/archive/`.
|
|
30
|
+
A task decided against moves to `.canon/tasks/declined/` rather than `.canon/tasks/archive/`. Archive means the work shipped, and declined means somebody decided against doing it.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
- A merely unscheduled task fits neither. It stays on `backlog.md`, since nobody decided against it and it may still rise.
|
|
33
|
+
- `canon tasks decline` carries no outcome-state gate, so a task can be declined at any outcome state, open outcomes included
|
|
34
|
+
- The move clears whichever of `priority.md` or `backlog.md` holds the task's row
|
|
33
35
|
|
|
34
|
-
The
|
|
36
|
+
### The `Declined:` line
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
The decision is recorded on the task with a `Declined:` line in the `Plan:` and `Pull request:` family, as `Declined: <reason>, <who> on <YYYY-MM-DD>`. It anchors after the last origin line the task carries, as `Pull request:` does, and stays free prose since it names no file to link.
|
|
37
39
|
|
|
38
|
-
The
|
|
40
|
+
### The plan
|
|
41
|
+
|
|
42
|
+
Declining moves the plan alongside the task when the task is that plan's last live citation, as archiving does. A plan several tasks share stays where it is.
|
|
43
|
+
|
|
44
|
+
- A declined task's plan lands in `.canon/plans/archive/`, indistinguishable from a shipped one by folder alone
|
|
45
|
+
- The task file under `.canon/tasks/declined/` records which it was
|