@erclx/canon 4.127.0 → 5.2.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.
Files changed (97) hide show
  1. package/README.md +5 -7
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/auto-ship/references/verb-absent.md +0 -1
  4. package/claude/skills/canon-feedback/REQUIREMENT.md +1 -1
  5. package/claude/skills/canon-feedback/SKILL.md +2 -2
  6. package/claude/skills/canon-operator/REQUIREMENT.md +2 -2
  7. package/claude/skills/canon-operator/SKILL.md +3 -3
  8. package/claude/skills/codebase-layout/REQUIREMENT.md +1 -0
  9. package/claude/skills/codebase-layout/SKILL.md +6 -0
  10. package/claude/skills/create-rule/REQUIREMENT.md +1 -1
  11. package/claude/skills/create-standard/REQUIREMENT.md +0 -2
  12. package/claude/skills/decision-escalate/REQUIREMENT.md +1 -2
  13. package/claude/skills/draft-context/REQUIREMENT.md +1 -1
  14. package/claude/skills/draft-docs/REQUIREMENT.md +1 -1
  15. package/claude/skills/draft-wireframes/REQUIREMENT.md +1 -1
  16. package/claude/skills/plan-intake/SKILL.md +1 -1
  17. package/claude/skills/target-setup/REQUIREMENT.md +2 -2
  18. package/claude/skills/target-setup/SKILL.md +1 -1
  19. package/claude/skills/target-setup/references/detect.md +1 -1
  20. package/claude/skills/target-setup/references/indexes.md +1 -5
  21. package/docs/agents/commands.md +7 -3
  22. package/docs/agents/counts.md +1 -2
  23. package/docs/agents/docs.md +1 -1
  24. package/docs/agents/drift-surfaces.md +6 -4
  25. package/docs/agents/index.md +1 -1
  26. package/docs/agents/indexes.md +1 -1
  27. package/docs/agents/install-and-sync.md +1 -8
  28. package/docs/agents/markdown-audit.md +2 -2
  29. package/docs/agents/restated.md +7 -5
  30. package/docs/agents/review-classification.md +1 -2
  31. package/docs/agents/scripting.md +2 -3
  32. package/docs/agents/skills-reach.md +3 -3
  33. package/docs/agents/state-scoped-risk.md +1 -1
  34. package/docs/target/index.md +4 -4
  35. package/docs/target/{target-migrations.md → migrations.md} +17 -1
  36. package/docs/target/{target-projects.md → projects.md} +5 -7
  37. package/docs/target/{target-scenarios.md → scenarios.md} +1 -1
  38. package/docs/target/{target-sync.md → sync.md} +4 -2
  39. package/docs/workflow/ai-workflow.md +3 -7
  40. package/docs/workflow/operating-model.md +4 -4
  41. package/docs/workflow/parallel-features.md +1 -1
  42. package/docs/workflow/skill-map.md +1 -2
  43. package/docs/workflow/visual-design-workflow.md +5 -5
  44. package/docs/workflow/zshrc-aliases.md +1 -1
  45. package/package.json +1 -2
  46. package/scripts/core/check-plugin-boundary.sh +1 -1
  47. package/scripts/core/install-check.sh +3 -4
  48. package/scripts/core/regen-hero.sh +2 -9
  49. package/src/autoship/paths.ts +3 -5
  50. package/src/claude/cases/authoring.ts +1 -5
  51. package/src/claude/plugin-update.ts +2 -2
  52. package/src/claude/skills-reach.ts +1 -2
  53. package/src/cli.ts +0 -2
  54. package/src/commands/feedback-format.ts +0 -1
  55. package/src/commands/gov.ts +8 -7
  56. package/src/commands/markdown.ts +2 -2
  57. package/src/commands/upgrade.ts +62 -6
  58. package/src/counts/catalogs.ts +0 -16
  59. package/src/counts/scan.ts +1 -1
  60. package/src/docs/read.ts +25 -25
  61. package/src/gate/measures.ts +52 -0
  62. package/src/gate/stages.ts +9 -0
  63. package/src/gov/restated.ts +60 -22
  64. package/src/help.ts +0 -2
  65. package/src/init/steps.ts +1 -1
  66. package/src/migrate/skill-names.ts +4 -5
  67. package/src/secrets/shipped.ts +2 -2
  68. package/src/serve/static.ts +1 -2
  69. package/src/shipped/references.ts +7 -8
  70. package/src/sync/engine.ts +2 -2
  71. package/standards/context.md +2 -0
  72. package/standards/docs.md +1 -0
  73. package/standards/index.md +0 -1
  74. package/standards/skill.md +1 -2
  75. package/standards/wiki.md +2 -1
  76. package/tooling/base/reference.md +2 -2
  77. package/tooling/claude/reference.md +1 -1
  78. package/claude/skills/create-snippet/REQUIREMENT.md +0 -39
  79. package/claude/skills/create-snippet/SKILL.md +0 -30
  80. package/scripts/snippets/create.sh +0 -156
  81. package/snippets/align.md +0 -12
  82. package/snippets/claude/decision-memo.md +0 -39
  83. package/snippets/claude/feature-recap.md +0 -19
  84. package/snippets/claude/figma-steps.md +0 -24
  85. package/snippets/compact-summary.md +0 -5
  86. package/snippets/decision-help.md +0 -6
  87. package/snippets/meta-prompt.md +0 -14
  88. package/snippets/research-prompt.md +0 -7
  89. package/snippets/session-notes.md +0 -11
  90. package/snippets/snippets.toml +0 -5
  91. package/snippets/step-by-step.md +0 -10
  92. package/snippets/web-research.md +0 -21
  93. package/src/commands/snippets.ts +0 -90
  94. package/src/snippets/categories.ts +0 -66
  95. package/src/snippets/list.ts +0 -32
  96. package/src/snippets/presets.ts +0 -50
  97. package/standards/snippets.md +0 -76
@@ -17,7 +17,6 @@ Does not govern:
17
17
 
18
18
  - What a `REQUIREMENT.md` must answer, its sections, and its template: `skill-requirement.md`
19
19
  - Path-scoped coding rules, which load on a file match rather than on a request match: `rule.md`
20
- - Single-purpose chat prompts carrying no frontmatter, references, or scripts: `snippets.md`
21
20
  - Voice, rhythm, and sentence construction in a skill body: the `write-human` skill
22
21
  - Punctuation, formatting, and word choice in a skill body: `markdown.md`
23
22
  - The transform from a branch name to a slug a skill carries in a filename: `slug.md`
@@ -128,7 +127,7 @@ allowed-tools: <tools required>
128
127
 
129
128
  - Avoid flags that dispatch between alternate flows. The model misreads them and runs the vanilla path. Dry-run-style toggles are fine. For alternate flows, prefer a separate skill or manual invocation of two skills in sequence.
130
129
  - When a skill should fire from multiple callers, rely on description matching with strong trigger phrases. Do not hardcode `Skill` calls in sibling skills that could trigger it naturally.
131
- - Before collapsing a manual multi-step flow into a skill, ask what the manual pauses do. Where a pause carries external timing, error-surfacing, or judgment weight, prefer a snippet or explicit per-step confirmation.
130
+ - Before collapsing a manual multi-step flow into a skill, ask what the manual pauses do. Where a pause carries external timing, error-surfacing, or judgment weight, prefer explicit per-step confirmation.
132
131
 
133
132
  ### Output and tuning
134
133
 
package/standards/wiki.md CHANGED
@@ -37,7 +37,8 @@ A page failing either is non-conforming even when it satisfies every shape rule
37
37
 
38
38
  ## Naming
39
39
 
40
- - Name a page with a `claude-` prefix before the kebab subject.
40
+ - Name a page by its kebab subject alone. The vendor folder it sits in already names the vendor, so a prefix repeats the folder.
41
+ - The `codebase-layout` skill carries the same rule for every folder in a project, beyond the wiki.
41
42
 
42
43
  ## Sourcing
43
44
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  The base layer covers every project the toolkit scaffolds, whatever language sits on top. It ships formatting, spelling, shell linting, conventional commits, git hooks, CI, and one maintenance script. Every other stack extends it, so a decision made here is one every stack inherits.
6
6
 
7
- A repository with several language roots layers this stack once at the root and skips it per subtree, since git honors only one `core.hooksPath` and a re-dropped husky silently breaks. `canon docs target-scenarios` carries the recipe.
7
+ A repository with several language roots layers this stack once at the root and skips it per subtree, since git honors only one `core.hooksPath` and a re-dropped husky silently breaks. `canon docs scenarios` carries the recipe.
8
8
 
9
9
  ## What ships as golden configs
10
10
 
@@ -97,4 +97,4 @@ Sticky negative knowledge. Do not relearn.
97
97
 
98
98
  `bun run check` repairs a checkout rather than gating one. It runs `format` first to auto-fix drifted code, then asserts only what the formatters could not fix. The pull request workflow calls `check:format`, `check:spell`, and `check:shell` directly, and those three are the gate.
99
99
 
100
- `scripts/verify.sh`'s `Markdown bans` stage is the exception: it gates rather than repairs. It runs `canon markdown audit` over every tracked markdown file except `CHANGELOG.md`, since a generated changelog carries commit subjects nobody wrote against the ban set, and exits `2` on a finding or `3` on a shipped-empty ban set, failing `bun run check` and the `pre-push` hook that calls it. A refusal to measure exits `1` and is logged as a skip rather than a failure, as does a corpus with no file left to check once `CHANGELOG.md` is set aside. The stage needs `canon` on PATH. `canon docs target-projects` names the install command. Without it, the stage is skipped and logged, and coverage falls back to the three checks above.
100
+ `scripts/verify.sh`'s `Markdown bans` stage is the exception: it gates rather than repairs. It runs `canon markdown audit` over every tracked markdown file except `CHANGELOG.md`, since a generated changelog carries commit subjects nobody wrote against the ban set, and exits `2` on a finding or `3` on a shipped-empty ban set, failing `bun run check` and the `pre-push` hook that calls it. A refusal to measure exits `1` and is logged as a skip rather than a failure, as does a corpus with no file left to check once `CHANGELOG.md` is set aside. The stage needs `canon` on PATH. `canon docs projects` names the install command. Without it, the stage is skipped and logged, and coverage falls back to the three checks above.
@@ -82,7 +82,7 @@ The first entry covers the whole record root, so a record folder added later nee
82
82
  ## CLAUDE.md
83
83
 
84
84
  - Ships as a seed with placeholder project name, description, and key paths. Fill these in after init.
85
- - Section layout: `Context`, `Indexes`, `Markdown`, `Key paths`, `Spelling`, `Snippets`, `Tasks`, `Memory`. Each section groups rules that share a surface so skills can detect, extend, or skip by heading.
85
+ - Section layout: `Context`, `Indexes`, `Markdown`, `Key paths`, `Spelling`, `Tasks`, `Memory`. Each section groups rules that share a surface so skills can detect, extend, or skip by heading.
86
86
  - The memory rules favor signal over volume. Saving only after a second occurrence or an explicit user correction keeps entries focused on patterns worth preventing, not first-occurrence slips. The 3-line cap stops the built-in auto-memory from drifting into narrative writeups that bury the rule underneath the recovery story.
87
87
  - The `Context` section points at `.claude/` state docs one line. `plan-feature` does the parallel read when invoked. The seed intentionally does not re-list every file.
88
88
 
@@ -1,39 +0,0 @@
1
- ---
2
- name: create-snippet
3
- description: Why a snippet needs its shape read from the reference and its write surface resolved before anything is drafted
4
- ---
5
-
6
- # Create snippet requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a snippet is drafted the way any other markdown file is drafted, so it arrives carrying frontmatter, headings, and a fill-in placeholder. None of the invocation channels strip those. Typing `>slug` in a chat inserts the scaffolding verbatim, and the file that was meant to be one instruction reads as a document.
11
-
12
- The write surface is the second failure. The toolkit authors at `snippets/` and a target project may still hold a stale `.claude/snippets/` copy from before that domain's install channel retired, so a session picks whichever folder it noticed first. A toolkit snippet written into the consumed copy fails the drift assertion that regenerates that folder. A snippet written there in a target project is correct and looks identical, which is why the surface has to be resolved from what the project has rather than guessed.
13
-
14
- Inside the project surface, a third failure sits one level deeper. A project-authored snippet sharing a name with a toolkit one used to be indistinguishable from it, back when `canon snippets sync` walked that folder and could not tell which side owned the file. That verb retired with the domain's install channel, so nothing reads ownership by location there any more, but the `project/` subfolder still separates the two by eye, which is worth keeping even with no sync left to protect from.
15
-
16
- ## Must
17
-
18
- - Read the bundled snippet reference before drafting, since the shape rules are what the invocation channels depend on
19
- - Resolve the write surface from which snippet folder the project has, rather than from whichever one the session noticed first
20
- - On the project surface, write under its `project/` subfolder, keeping a project-authored file visually apart from a toolkit-installed one
21
- - Confirm the slug and the full body with the user before writing
22
- - Emit the written path in full, so the terminal can resolve it
23
- - State what the resolved surface implies after writing, since a root file needs the consumed copy regenerated and a project-local one needs copying to the toolkit to ship
24
-
25
- ## Must not
26
-
27
- - Restate the snippet authoring conventions in the body, which the bundled reference owns and which would drift from it
28
- - Write a standard, which answers to a different authoring contract
29
-
30
- ## Guards
31
-
32
- - Neither snippet folder exists: stop, since there is nowhere for the snippet to live
33
-
34
- ## Out of scope
35
-
36
- - Editing a snippet that already exists
37
- - A standard, which `create-standard` owns
38
- - Installing and syncing the snippets the toolkit ships, which the `canon snippets` commands own
39
- - What a snippet is and how it is invoked, which the bundled snippet reference states
@@ -1,30 +0,0 @@
1
- ---
2
- name: create-snippet
3
- description: Creates a new snippet file in `snippets/` or `.claude/snippets/`. Use when asked to "create a snippet", add a snippet, write a reusable prompt, or make a new snippet. Do NOT use to edit an existing snippet.
4
- ---
5
-
6
- # Create snippet
7
-
8
- Creates one snippet file. Read these files in parallel:
9
-
10
- - `${CLAUDE_SKILL_DIR}/../../standards/markdown.md`: punctuation and formatting for all generated text
11
- - The `write-human` skill: voice, rhythm, and sentence construction for all generated text
12
- - `${CLAUDE_SKILL_DIR}/../../standards/snippets.md`: authoring conventions, invocation channels, use patterns
13
-
14
- ## Guards
15
-
16
- - If neither `snippets/` nor `.claude/snippets/` exists, stop: `❌ No snippets/ or .claude/snippets/ directory found.`
17
-
18
- ## Steps
19
-
20
- 1. Resolve the write surface: `snippets/` at the root if present, which is the toolkit's own authoring source. Otherwise `.claude/snippets/`, a stale copy a target project holds from before its install channel retired.
21
- 2. Draft the content from the user's description. The snippet reference governs structure, invocation, and authoring conventions.
22
- 3. Confirm the slug and full content with the user before writing
23
- 4. Write the file. On the root surface: `<surface>/<category>/<slug>.md`, or `<surface>/<slug>.md` when the snippet takes no category. On the `.claude/` surface: the same shape nested one level deeper under `project/`, a convention kept for its own sake now that nothing syncs that folder.
24
-
25
- ## After writing
26
-
27
- Emit the full path on its own line.
28
-
29
- - Root surface: this is the toolkit's authoring source. Remind the user to run `bun run check` to regenerate the consumed copy under `.claude/`.
30
- - `.claude/` surface: the file is project-local, under `.claude/snippets/project/`. Remind the user to copy it to the toolkit repo, under `snippets/<category>/<name>.md`, if it should ship to every project.
@@ -1,156 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -e
3
- set -o pipefail
4
-
5
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
- PROJECT_ROOT="${PROJECT_ROOT:-$(dirname "$(dirname "$SCRIPT_DIR")")}"
7
-
8
- source "$PROJECT_ROOT/scripts/lib/ui.sh"
9
- trap close_timeline EXIT
10
-
11
- SNIPPETS_SOURCE="$PROJECT_ROOT/snippets"
12
-
13
- show_help() {
14
- echo -e "${GREY}┌${NC}"
15
- echo -e "${GREY}├${NC} ${WHITE}Usage:${NC} canon snippets create"
16
- echo -e "${GREY}│${NC}"
17
- echo -e "${GREY}│${NC} Creates a new snippet: prompts for category and name, writes the file."
18
- echo -e "${GREY}│${NC}"
19
- echo -e "${GREY}│${NC} ${WHITE}Options:${NC}"
20
- echo -e "${GREY}│${NC} -h, --help ${GREY}# Show this help message${NC}"
21
- echo -e "${GREY}└${NC}"
22
- exit 0
23
- }
24
-
25
- list_categories() {
26
- echo "base (root, no prefix)"
27
- find "$SNIPPETS_SOURCE" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort
28
- echo "new category"
29
- }
30
-
31
- slug_error() {
32
- local slug="$1"
33
- local path="$2"
34
- if [ -z "$slug" ]; then
35
- echo "name cannot be empty"
36
- return
37
- fi
38
- if [[ ! "$slug" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
39
- echo "kebab-case only (e.g. my-snippet)"
40
- return
41
- fi
42
- if [ -f "$path" ]; then
43
- echo "file already exists: $path"
44
- return
45
- fi
46
- echo ""
47
- }
48
-
49
- ask_new_category() {
50
- while true; do
51
- ask "Category name?" "CATEGORY_INPUT"
52
- if [ -z "$CATEGORY_INPUT" ]; then
53
- log_warn "Category name cannot be empty"
54
- continue
55
- fi
56
- if [[ ! "$CATEGORY_INPUT" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
57
- log_warn "Invalid category: kebab-case only (e.g. my-category)"
58
- continue
59
- fi
60
- if [ -d "$SNIPPETS_SOURCE/$CATEGORY_INPUT" ]; then
61
- log_warn "Category '$CATEGORY_INPUT' already exists"
62
- continue
63
- fi
64
- CATEGORY_NAME="$CATEGORY_INPUT"
65
- break
66
- done
67
- }
68
-
69
- ask_name() {
70
- local category="$1"
71
- local is_base="$2"
72
- local label
73
- local error
74
-
75
- label="Snippet name?"
76
-
77
- while true; do
78
- ask "$label" "NAME_INPUT"
79
- local dest_path
80
- if [ "$is_base" = "true" ]; then
81
- dest_path="$SNIPPETS_SOURCE/$NAME_INPUT.md"
82
- else
83
- dest_path="$SNIPPETS_SOURCE/$category/$NAME_INPUT.md"
84
- fi
85
- error=$(slug_error "$NAME_INPUT" "$dest_path")
86
- if [ -z "$error" ]; then
87
- NAME="$NAME_INPUT"
88
- break
89
- fi
90
- log_warn "Invalid name: $error"
91
- done
92
- }
93
-
94
- cmd_create() {
95
- local categories=()
96
- mapfile -t categories < <(list_categories)
97
-
98
- select_option "Category?" "${categories[@]}"
99
- local selected="$SELECTED_OPTION"
100
-
101
- local category
102
- local is_base="false"
103
-
104
- if [ "$selected" = "base (root, no prefix)" ]; then
105
- is_base="true"
106
- category="base"
107
- elif [ "$selected" = "new category" ]; then
108
- ask_new_category
109
- category="$CATEGORY_NAME"
110
- else
111
- category="$selected"
112
- fi
113
-
114
- ask_name "$category" "$is_base"
115
- local name="$NAME"
116
-
117
- local dest_path
118
- local install_path
119
- if [ "$is_base" = "true" ]; then
120
- dest_path="$SNIPPETS_SOURCE/$name.md"
121
- install_path="snippets/$name"
122
- else
123
- dest_path="$SNIPPETS_SOURCE/$category/$name.md"
124
- install_path="snippets/$category/$name"
125
- fi
126
-
127
- log_info "Installs as: @${install_path}"
128
-
129
- log_step "Creating file"
130
-
131
- if [ "$is_base" = "false" ]; then
132
- mkdir -p "$SNIPPETS_SOURCE/$category"
133
- fi
134
-
135
- printf '<!-- TODO: write %s prompt -->\n' "$slug" >"$dest_path"
136
-
137
- if [ "$is_base" = "true" ]; then
138
- log_add "snippets/$name.md"
139
- else
140
- log_add "snippets/$category/$name.md"
141
- fi
142
- }
143
-
144
- main() {
145
- if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
146
- show_help
147
- fi
148
-
149
- cmd_create
150
-
151
- trap - EXIT
152
- echo -e "${GREY}└${NC}\n"
153
- echo -e "${GREEN}✓ Snippet created${NC}"
154
- }
155
-
156
- main "$@"
package/snippets/align.md DELETED
@@ -1,12 +0,0 @@
1
- Check alignment before acting, not after. State three lines, then proceed.
2
-
3
- - Outcome: what will be true when this is done
4
- - Scope: what this deliberately does not touch
5
- - Assumption: the one inference that would change the work if it is wrong
6
-
7
- Act without waiting, unless being wrong about the assumption wastes the work rather than costing an edit.
8
-
9
- - Three lines, not three paragraphs
10
- - Name the inference you are least sure of, not the safest one
11
- - Do not ask what the request already answers
12
- - Silence is agreement
@@ -1,39 +0,0 @@
1
- Produce a decision memo for a research or should-we question. This is the decision-heavy counterpart to `plan-feature`, which plans a build. Write one file per independent concern under `.canon/plans/feature-<slug>.md`, or answer inline when the plan is small. Use the same plans folder as `plan-feature`.
2
-
3
- Read the current state from the code and docs before recommending. Do not assume it.
4
-
5
- Output this shape per memo:
6
-
7
- ```markdown
8
- # <slug title>
9
-
10
- <the question in one or two lines>
11
-
12
- ## Summary
13
-
14
- - <goal in one line>
15
- - <deliverables in one line>
16
- - <key tradeoff in one line>
17
-
18
- ## Finding
19
-
20
- <what the current state actually is, from reading the code and docs>
21
-
22
- ## Item A: <decision>
23
-
24
- **Current state.** <what exists today>
25
-
26
- **Recommendation.** <the pick, with the tradeoff in one sentence>
27
-
28
- **Options.** <the real alternatives, only when the choice is the user's to make>
29
-
30
- **Feasibility.** <what is not buildable as asked and why, omit when all options are buildable>
31
-
32
- **Questions.**
33
-
34
- 1. <question>
35
- - Suggested: <best-practice default derived from context>
36
- - Answer:
37
- ```
38
-
39
- Repeat the `## Item` block per decision. Keep chat to the file pointer plus the questions. Recommend, do not enumerate, unless the user's preference is the deciding factor.
@@ -1,19 +0,0 @@
1
- Recap the implementation this session completed. Read the plan file referenced in the session (usually `.canon/plans/feature-<slug>.md`) and produce a verification block.
2
-
3
- Output this shape, nothing else:
4
-
5
- ```markdown
6
- **Deliverable 1**: <name from the plan>
7
-
8
- - `path/to/file`: one-line reason
9
-
10
- **Deliverable 2**: <name from the plan>
11
-
12
- - `path/to/file`: one-line reason
13
-
14
- **Verified**: <what was smoke-tested or `Nothing tested in session.`>
15
-
16
- **Open**: <unresolved questions, deferred items, or `None.`>
17
- ```
18
-
19
- Group files by deliverable, not by directory. Keep each line scannable. Do not restate the plan body.
@@ -1,24 +0,0 @@
1
- Read the relevant spec from `canon/DESIGN.md` and any other design files needed. Write step-by-step Figma instructions to produce the component exactly.
2
-
3
- For each step, specify:
4
-
5
- - The exact tool or keyboard shortcut to activate
6
- - Which panel or field to click
7
- - The exact value to enter
8
-
9
- When a step has multiple sub-actions or lists several items, use nested bullets instead of stacking them in one sentence.
10
-
11
- Cover in order:
12
-
13
- - Frame or group setup (dimensions, corner radius, fill)
14
- - Each layer or shape (type, size, position, fill, stroke)
15
- - Alignment and spacing rules
16
- - Export settings
17
-
18
- Throughout:
19
-
20
- - Use exact values from the spec
21
- - Do not restate design rationale
22
- - Use Title Case for all layer and frame names
23
- - Use Figma terminology throughout, not code or CSS equivalents
24
- - Reuse existing frames or components from the same Figma document by name instead of rebuilding from scratch
@@ -1,5 +0,0 @@
1
- Summarize the research or findings above into a compact, scannable block.
2
-
3
- - State the main takeaways directly
4
- - Skip background context the reader already has
5
- - Use short headings and tight bullets where multiple items exist
@@ -1,6 +0,0 @@
1
- Apply senior-level judgment. Pick the best option from the discussion so far. State the pick in one sentence, then the reason and the main tradeoff in one or two sentences.
2
-
3
- - Minimal and necessary only
4
- - No nice-to-haves
5
- - No padding
6
- - No alternatives unless they change the recommendation
@@ -1,14 +0,0 @@
1
- Turn the idea below into a production-grade system prompt.
2
-
3
- Give it a role of one to three lines, a constraints section, and an output format carrying a template plus one worked example. Add a validation checklist when the prompt involves multi-step logic, edge cases, or error handling. Omit that checklist for a single-purpose prompt.
4
-
5
- Group constraints under domain headings when they span two or more domains and total five or more. Use flat must-do and must-not-do lists otherwise. Keep dos and don'ts together under the topic they belong to.
6
-
7
- Use `{{DOUBLE_BRACES}}` for values the end user fills in at runtime.
8
-
9
- Constraints:
10
-
11
- - Use imperative voice. Write `Do X`, never `You should` or `Try to`.
12
- - Make every constraint verifiable from the output. Reject subjective qualifiers like `appropriate`, `concise`, or `well-structured`.
13
- - Match prompt length to task complexity. A single-purpose task gets a minimal prompt.
14
- - Never write `maybe`, `consider`, or `depending on`. Be definitive.
@@ -1,7 +0,0 @@
1
- Generate a self-contained research prompt for another AI chat. Include:
2
-
3
- - State what I am trying to do and why
4
- - List what I have already tried and the results
5
- - Specify questions that need answers
6
-
7
- Write it in first person. Assume the reader has no context from this session.
@@ -1,11 +0,0 @@
1
- Write session notes for this conversation using this format:
2
-
3
- ```markdown
4
- # Session notes: <topic>
5
-
6
- ## <title>
7
-
8
- <what was decided and why>
9
- ```
10
-
11
- Only include decisions made in this session. Output only the markdown block, nothing else.
@@ -1,5 +0,0 @@
1
- [essentials]
2
- names = [
3
- "align",
4
- "decision-help",
5
- ]
@@ -1,10 +0,0 @@
1
- Give me step-by-step instructions.
2
-
3
- For each step:
4
-
5
- - State what to do in one sentence.
6
- - Include the exact value, command, or input where precision matters.
7
- - Note any output to save or verify before moving on.
8
- - When the step has multiple sub-actions or lists several items, use nested bullets instead of stacking them in one sentence.
9
-
10
- Group related steps under a heading if the process has distinct phases. Flag any step that is irreversible or that blocks later steps.
@@ -1,21 +0,0 @@
1
- Search the web for the topic or question added after this snippet. Fetch the most relevant pages. Synthesize findings into a decision-ready block using this format:
2
-
3
- ```markdown
4
- Topic: [what was researched]
5
- Recommendation: [one clear answer or choice]
6
-
7
- Options considered:
8
-
9
- - [Option A]: why considered, why chosen or rejected
10
- - [Option B]: why considered, why chosen or rejected
11
-
12
- Key constraints:
13
-
14
- - [constraint that shaped the decision]
15
-
16
- Sources:
17
-
18
- - [URL]: what it confirmed
19
- ```
20
-
21
- Output only the block. Do not add commentary before or after it.
@@ -1,90 +0,0 @@
1
- import type { Command } from 'commander'
2
- import { registerPassThroughVerbs } from '@/commands/pass-through'
3
- import { checkoutMismatchWarning, PROJECT_ROOT } from '@/project-root'
4
- import { BASE_CATEGORY } from '@/snippets/categories'
5
- import { buildSnippetsCatalog } from '@/snippets/list'
6
- import { intro, logInfo, logStep, logWarn, outro } from '@/ui'
7
-
8
- const PASS_THROUGH_VERBS = ['create'] as const
9
-
10
- interface ListOptions {
11
- readonly categories?: boolean
12
- readonly entries?: boolean
13
- readonly json?: boolean
14
- }
15
-
16
- export function register(program: Command): void {
17
- const snippets = program
18
- .command('snippets')
19
- .description('Snippets commands (create, list)')
20
- .helpOption('-h, --help', 'Show this help message')
21
-
22
- snippets
23
- .command('list')
24
- .description('List snippet presets, categories, and entries')
25
- .helpOption('-h, --help', 'Show this help message')
26
- .option('--categories', 'Only list presets and category names')
27
- .option('--entries', 'Only list entry slugs grouped by category')
28
- .option('--json', 'Emit machine-readable JSON')
29
- .action((opts: ListOptions) => {
30
- process.exitCode = runList(opts)
31
- })
32
-
33
- registerPassThroughVerbs(snippets, 'snippets', PASS_THROUGH_VERBS)
34
- }
35
-
36
- /**
37
- * `JSON.stringify` replaces a `printf` template that interpolated names into a
38
- * JSON string literal unescaped, so a slug or category carrying a quote emitted
39
- * output no consuming skill could parse.
40
- *
41
- * The frame opens after the `--json` return, since the bash verb only ever
42
- * emitted section headers and the pass-through above it owned the `┌`.
43
- */
44
- function runList(opts: ListOptions): number {
45
- // The warning is a frame-interior line, so it goes out after `intro` on the
46
- // path that opens one and bare on the `--json` path, which returns first and
47
- // opens none. One position cannot serve both.
48
- const mismatch = checkoutMismatchWarning(process.cwd())
49
- const catalog = buildSnippetsCatalog(PROJECT_ROOT)
50
-
51
- if (opts.json) {
52
- if (mismatch !== undefined) logWarn(mismatch)
53
- process.stdout.write(`${JSON.stringify(catalog)}\n`)
54
- return 0
55
- }
56
-
57
- intro('canon snippets list')
58
- if (mismatch !== undefined) logWarn(mismatch)
59
-
60
- const showCategories = opts.entries !== true
61
- const showEntries = opts.categories !== true
62
-
63
- if (showCategories) {
64
- if (catalog.presets.length > 0) {
65
- logStep('Presets')
66
- for (const preset of catalog.presets) {
67
- logInfo(`${preset.name} (${preset.slugs.length} entries)`)
68
- }
69
- }
70
-
71
- logStep('Categories')
72
- for (const category of catalog.categories) {
73
- logInfo(`${category.name} (${category.entries.length} entries)`)
74
- }
75
- }
76
-
77
- if (showEntries) {
78
- logStep('Entries')
79
- for (const category of catalog.categories) {
80
- for (const entry of category.entries) {
81
- logInfo(
82
- category.name === BASE_CATEGORY ? entry : `${category.name}/${entry}`,
83
- )
84
- }
85
- }
86
- }
87
-
88
- outro()
89
- return 0
90
- }
@@ -1,66 +0,0 @@
1
- import { readdirSync } from 'node:fs'
2
- import { join } from 'node:path'
3
- import { isDirectory } from '@/target'
4
-
5
- export const BASE_CATEGORY = 'base'
6
- /** A real category resolving to zero entries, for a caller declining on purpose. */
7
- export const NONE_CATEGORY = 'none'
8
-
9
- export function snippetsSourceDir(root: string): string {
10
- return join(root, 'snippets')
11
- }
12
-
13
- /**
14
- * Lists the folder categories. `base` is the synthetic name for snippets
15
- * sitting directly under `snippets/`, so it is not a directory and callers
16
- * prepend it themselves.
17
- *
18
- * Nothing is filtered: toolkit-internal snippets are authored under `internal/`,
19
- * which this never reads, so every category found here is publishable.
20
- */
21
- export function listFolderCategories(root: string): string[] {
22
- const dir = snippetsSourceDir(root)
23
- if (!isDirectory(dir)) return []
24
-
25
- return readdirSync(dir, { withFileTypes: true })
26
- .filter((entry) => entry.isDirectory())
27
- .map((entry) => entry.name)
28
- .sort()
29
- }
30
-
31
- export function listCategories(root: string): string[] {
32
- return [BASE_CATEGORY, ...listFolderCategories(root)]
33
- }
34
-
35
- export function categoryDir(root: string, category: string): string {
36
- const source = snippetsSourceDir(root)
37
- return category === BASE_CATEGORY ? source : join(source, category)
38
- }
39
-
40
- /**
41
- * Tests for a directory rather than mere existence. `snippets/` holds files
42
- * alongside its category folders, so an argument naming one of them resolves
43
- * to a real path that cannot be scanned as a category.
44
- *
45
- * An empty category refuses rather than resolving, since `join(source, '')`
46
- * is `source` and would otherwise report the base directory as the category,
47
- * widening an unset value to every base entry instead of naming none.
48
- */
49
- export function categoryExists(root: string, category: string): boolean {
50
- if (category === '') return false
51
- return isDirectory(categoryDir(root, category))
52
- }
53
-
54
- /**
55
- * Lists one category's entry slugs. Only the immediate level is read, matching
56
- * the `find -maxdepth 1` the bash used, so a nested folder is its own category
57
- * rather than part of its parent.
58
- */
59
- export function listEntries(root: string, category: string): string[] {
60
- const dir = categoryDir(root, category)
61
- if (!isDirectory(dir)) return []
62
-
63
- return [...new Bun.Glob('*.md').scanSync({ cwd: dir, onlyFiles: true })]
64
- .map((name) => name.slice(0, -'.md'.length))
65
- .sort()
66
- }
@@ -1,32 +0,0 @@
1
- import { listCategories, listEntries } from '@/snippets/categories'
2
- import { loadPresets } from '@/snippets/presets'
3
-
4
- export interface CategoryCatalogEntry {
5
- readonly name: string
6
- readonly entries: readonly string[]
7
- }
8
-
9
- export interface SnippetsCatalog {
10
- readonly presets: readonly {
11
- readonly name: string
12
- readonly slugs: readonly string[]
13
- }[]
14
- readonly categories: readonly CategoryCatalogEntry[]
15
- }
16
-
17
- /**
18
- * Builds the catalog both output modes read, so the human list and the `--json`
19
- * one cannot describe different corpora.
20
- */
21
- export function buildSnippetsCatalog(root: string): SnippetsCatalog {
22
- return {
23
- presets: loadPresets(root).map((preset) => ({
24
- name: preset.name,
25
- slugs: preset.slugs,
26
- })),
27
- categories: listCategories(root).map((name) => ({
28
- name,
29
- entries: listEntries(root, name),
30
- })),
31
- }
32
- }