@skill-map/cli 0.51.0 → 0.53.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 (53) hide show
  1. package/dist/cli/tutorial/sm-tutorial/SKILL.md +239 -1659
  2. package/dist/cli/tutorial/sm-tutorial/references/_core.md +332 -0
  3. package/dist/cli/tutorial/sm-tutorial/references/_manifest.yml +175 -0
  4. package/dist/cli/tutorial/sm-tutorial/references/fixtures.md +251 -0
  5. package/dist/cli/tutorial/{sm-master/references/tour-authoring.md → sm-tutorial/references/part-authoring.md} +14 -15
  6. package/dist/cli/tutorial/sm-tutorial/references/part-cli.md +267 -0
  7. package/dist/cli/tutorial/sm-tutorial/references/part-connect-harness.md +180 -0
  8. package/dist/cli/tutorial/sm-tutorial/references/part-fundamentals.md +424 -0
  9. package/dist/cli/tutorial/sm-tutorial/references/part-live-site.md +156 -0
  10. package/dist/cli/tutorial/sm-tutorial/references/part-maintain.md +286 -0
  11. package/dist/cli/tutorial/sm-tutorial/references/part-mcp.md +78 -0
  12. package/dist/cli/tutorial/{sm-master/references/tour-plugins.md → sm-tutorial/references/part-plugins.md} +11 -11
  13. package/dist/cli/tutorial/sm-tutorial/references/part-project-kickoff.md +186 -0
  14. package/dist/cli/tutorial/{sm-master/references/tour-settings.md → sm-tutorial/references/part-settings.md} +22 -24
  15. package/dist/cli.js +1253 -564
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +335 -208
  18. package/dist/kernel/index.d.ts +320 -15
  19. package/dist/kernel/index.js +335 -208
  20. package/dist/migrations/001_initial.sql +36 -0
  21. package/dist/ui/chunk-EQ72PEHT.js +1 -0
  22. package/dist/ui/chunk-GBKHMJ4B.js +1110 -0
  23. package/dist/ui/chunk-GEI6INVH.js +515 -0
  24. package/dist/ui/chunk-JXRIGHET.js +552 -0
  25. package/dist/ui/{chunk-WQMZOINB.js → chunk-K2MAVAHG.js} +1 -1
  26. package/dist/ui/{chunk-BV323KTK.js → chunk-KHARMPTZ.js} +1 -1
  27. package/dist/ui/chunk-L4NIF75A.js +2 -0
  28. package/dist/ui/chunk-LCOYSPKE.js +1 -0
  29. package/dist/ui/chunk-OFDQMBSJ.js +1 -0
  30. package/dist/ui/chunk-P2DAPRK7.js +2 -0
  31. package/dist/ui/chunk-Q2A6FWC7.js +4 -0
  32. package/dist/ui/chunk-TXTY24G4.js +2204 -0
  33. package/dist/ui/chunk-UBQUCSQ4.js +1 -0
  34. package/dist/ui/chunk-WFLPMCK4.js +392 -0
  35. package/dist/ui/chunk-WHZVGOS3.js +5 -0
  36. package/dist/ui/chunk-YQFIXHKM.js +123 -0
  37. package/dist/ui/index.html +2 -2
  38. package/dist/ui/main-OYITFJ7B.js +4 -0
  39. package/dist/ui/{styles-RG7Y33BT.css → styles-Q4NCOJQY.css} +1 -1
  40. package/migrations/001_initial.sql +36 -0
  41. package/package.json +10 -8
  42. package/dist/cli/tutorial/sm-master/SKILL.md +0 -688
  43. package/dist/cli/tutorial/sm-master/references/fixture-templates.md +0 -212
  44. package/dist/ui/chunk-2GXE52AJ.js +0 -123
  45. package/dist/ui/chunk-AEA5GIA7.js +0 -1
  46. package/dist/ui/chunk-KHRNVLJW.js +0 -1
  47. package/dist/ui/chunk-OZTRR4M7.js +0 -2312
  48. package/dist/ui/chunk-Q5YJKCTP.js +0 -1066
  49. package/dist/ui/chunk-RCT3JSFL.js +0 -1
  50. package/dist/ui/chunk-VBTLX7GH.js +0 -1110
  51. package/dist/ui/chunk-VJ57LHDR.js +0 -4
  52. package/dist/ui/chunk-WMGW2UAL.js +0 -2
  53. package/dist/ui/main-N7D2YBEX.js +0 -4
@@ -0,0 +1,251 @@
1
+ # Fixture templates
2
+
3
+ Fixtures the orchestrator lays for the auto-fixtured parts. Two sets
4
+ today: the **master fixture** (Part 6, "Extend skill-map",
5
+ `backstage-init`) right below, and the **portfolio fixture** (Part 1,
6
+ "The project from zero", `portfolio-init`) at the end of this file.
7
+ Read the set for the part being entered.
8
+
9
+ ## Master fixture (Part 6): layout (per provider)
10
+
11
+ Per §Provider detection in `SKILL.md`, the `<provider_dir>`
12
+ placeholder resolves to `.claude/` or `.agents/skills/` depending
13
+ on the detected runtime (Google's Antigravity CLI, which replaced
14
+ Gemini CLI on 2026-05-19, adopted the same open standard as
15
+ `agent-skills`, so both share the `.agents/skills/` layout). Drop
16
+ any file whose kind is not in the provider's supported set: on
17
+ `agent-skills` / Antigravity only the skill + note are valid;
18
+ on `claude` (default) all three apply.
19
+
20
+ Canonical layout (substitute `<provider_dir>` per detection):
21
+
22
+ ```
23
+ <cwd>/
24
+ ├── <provider_dir>/
25
+ │ ├── agents/ (claude only)
26
+ │ │ └── master-agent.md
27
+ │ └── skills/ (both providers)
28
+ │ └── master-skill/
29
+ │ └── SKILL.md
30
+ ├── notes/
31
+ │ └── ideas.md
32
+ └── findings.md
33
+ ```
34
+
35
+ On `agent-skills` the `agents/` subtree is omitted (the provider
36
+ does not claim that kind); the skill lives at
37
+ `.agents/skills/master-skill/SKILL.md`.
38
+
39
+ Translate the natural-language prose (descriptions, body text,
40
+ list items) to the tester's language. Keep paths, frontmatter
41
+ keys, identifiers, and link targets in English.
42
+
43
+ ## File: `.claude/agents/master-agent.md` (kind: agent)
44
+
45
+ ```markdown
46
+ ---
47
+ name: master-agent
48
+ description: |
49
+ Example agent used by the advanced tutorial. Has a couple of
50
+ tools so the `core/tools-counter` extractor emits a count.
51
+ tools: [Read, Bash, Edit]
52
+ model: sonnet
53
+ metadata:
54
+ version: "1.0.0"
55
+ ---
56
+
57
+ # master-agent
58
+
59
+ Walks the master-skill outputs and reports findings. Used as the
60
+ target node when we exercise extractors, analyzers, and the
61
+ plugin-authoring flow.
62
+ ```
63
+
64
+ ## File: `.claude/skills/master-skill/SKILL.md` (kind: skill)
65
+
66
+ ```markdown
67
+ ---
68
+ name: master-skill
69
+ description: |
70
+ Example skill paired with the master-agent for the advanced
71
+ tutorial. Links to the agent so extractors and analyzers have
72
+ something to chew on.
73
+ inputs:
74
+ - name: target
75
+ type: path
76
+ description: File to process.
77
+ required: true
78
+ outputs:
79
+ - name: report
80
+ type: string
81
+ description: Markdown summary.
82
+ metadata:
83
+ version: "1.0.0"
84
+ ---
85
+
86
+ # master-skill
87
+
88
+ Hands heavy work over to the
89
+ [master-agent](../../agents/master-agent.md) and emits a Markdown
90
+ report.
91
+
92
+ ## Steps
93
+ 1. Read the `target`.
94
+ 2. Validate the frontmatter.
95
+ 3. Delegate to the agent.
96
+ ```
97
+
98
+ ## File: `notes/ideas.md` (kind: markdown)
99
+
100
+ ```markdown
101
+ ---
102
+ name: Ideas backlog
103
+ description: |
104
+ Free-form notes for the advanced tutorial. Demonstrates the
105
+ catch-all markdown kind alongside the agent and skill.
106
+ tags: [notes, master]
107
+ metadata:
108
+ version: "1.0.0"
109
+ ---
110
+
111
+ # Ideas
112
+
113
+ - [ ] Compare extractor outputs side by side.
114
+ - [ ] Sketch a tiny plugin that surfaces a counter on the agent.
115
+ ```
116
+
117
+ ## File: `findings.md`
118
+
119
+ ```markdown
120
+ # Findings
121
+
122
+ If you spot anything weird during the tutorial, log it here.
123
+
124
+ Per finding:
125
+ - **Chapter**: <id>
126
+ - **Command**: `sm ...`
127
+ - **Expected**: ...
128
+ - **Got**: ...
129
+ - **Notes**: ...
130
+ ```
131
+
132
+ ## Portfolio fixture (Part 1, `portfolio-init`)
133
+
134
+ Laid backstage before the tester's `sm init` in Part 1. The Express
135
+ skeleton (`server.js`, `package.json`, `public/index.html`) is plain
136
+ scaffolding, not `.md`, so the scan ignores it; it makes the project
137
+ real and runnable (Part 5 starts it). The one boot node is the
138
+ handbook `AGENTS.md`. On `agent-skills` / Antigravity (no `agent`
139
+ kind) the harness still works: the agent member is created as a skill
140
+ in a later chapter.
141
+
142
+ Layout:
143
+
144
+ ```
145
+ <cwd>/
146
+ ├── <provider_dir>/ (harness, grown by the chapters)
147
+ ├── docs/ (created in the real-kinds chapter)
148
+ ├── public/
149
+ │ └── index.html
150
+ ├── AGENTS.md (the boot node)
151
+ ├── server.js
152
+ └── package.json
153
+ ```
154
+
155
+ ### File: `AGENTS.md` (kind: markdown, the boot node)
156
+
157
+ ```markdown
158
+ ---
159
+ name: portfolio-handbook
160
+ description: |
161
+ Operating manual for this portfolio site: how its pages get
162
+ written, checked, and published by the .claude/ harness.
163
+ tags: [docs, portfolio]
164
+ ---
165
+
166
+ # Portfolio handbook
167
+
168
+ A small static portfolio site, served by Express (`server.js`). The
169
+ `.claude/` harness maintains it: an agent writes the pages, a skill
170
+ checks the links, a command publishes. The conventions live in
171
+ `docs/STYLE.md`; the deploy steps in `docs/DEPLOY.md`.
172
+ ```
173
+
174
+ ### File: `server.js` (not scanned; runnable scaffolding)
175
+
176
+ ```js
177
+ // Minimal static server for the portfolio. No framework, one dep.
178
+ const express = require('express');
179
+ const path = require('node:path');
180
+
181
+ const app = express();
182
+ app.use(express.static(path.join(__dirname, 'public')));
183
+
184
+ const port = process.env.PORT || 3000;
185
+ app.listen(port, () => console.log(`Portfolio live at http://localhost:${port}`));
186
+ ```
187
+
188
+ ### File: `package.json` (not scanned)
189
+
190
+ ```json
191
+ {
192
+ "name": "my-portfolio",
193
+ "private": true,
194
+ "scripts": { "start": "node server.js" },
195
+ "dependencies": { "express": "4.21.2" }
196
+ }
197
+ ```
198
+
199
+ ### File: `public/index.html` (not scanned; placeholder until Part 5)
200
+
201
+ ```html
202
+ <!doctype html>
203
+ <meta charset="utf-8">
204
+ <title>My portfolio</title>
205
+ <h1>My portfolio</h1>
206
+ <p>Pages land here once the content-editor generates them.</p>
207
+ ```
208
+
209
+ ### `.skillmapignore` additions
210
+
211
+ Append to the portfolio `.skillmapignore` (on top of the tutorial
212
+ internals from `SKILL.md`): `node_modules/` (the Express install) and
213
+ `public/` (generated HTML, not part of the harness graph).
214
+
215
+ ## Seed snapshots (for `preflight: seed`, jumping into a campaign part)
216
+
217
+ When the orchestrator enters a campaign part out of order (its
218
+ predecessors are not `done`), it fast-forwards the project by laying
219
+ the snapshot below, then `sm init` (if `.skill-map/` is missing) +
220
+ `sm scan`. These are **checklists, not content**: each row names a file
221
+ and the chapter that holds its canonical content. Lay each file by
222
+ copying the content from the named chapter (substitute `<provider_dir>`
223
+ and skip provider-unsupported kinds per `_core.md`); an `EDIT` row is
224
+ applied on top of the file an earlier row laid. Keep these lists in
225
+ sync only when a harness FILE is added or removed, the file CONTENT
226
+ lives in the chapters, so editing a chapter needs no change here.
227
+
228
+ ### Seed snapshot: `harness-built` (start of Part 2)
229
+
230
+ The portfolio skeleton plus the harness members Part 1 created, before
231
+ any cross-links:
232
+
233
+ 1. `AGENTS.md`, `server.js`, `package.json`, `public/index.html`, and
234
+ the portfolio `.skillmapignore` additions <- the `## Portfolio
235
+ fixture` section above.
236
+ 2. `CLAUDE.md` (`@AGENTS.md`) <- part-project-kickoff.md, chapter `manual`.
237
+ 3. `<provider_dir>/agents/content-editor.md` <- part-project-kickoff.md, chapter `first-agent`.
238
+ 4. `docs/STYLE.md` and `docs/DEPLOY.md` <- part-project-kickoff.md, chapter `real-kinds`.
239
+
240
+ ### Seed snapshot: `harness-connected` (start of Parts 3, 4, 5)
241
+
242
+ Everything in `harness-built`, PLUS the Part 2 wiring:
243
+
244
+ 5. `<provider_dir>/skills/check-links/SKILL.md` <- part-connect-harness.md, chapter `check-links`.
245
+ 6. `<provider_dir>/commands/publish.md` <- part-connect-harness.md, chapter `publish`.
246
+ 7. EDIT `AGENTS.md`: append the two hub bullets (mention `@content-editor`, invoke `/publish`) <- part-connect-harness.md, chapter `links`.
247
+ 8. EDIT `<provider_dir>/agents/content-editor.md`: add the `[style guide](../../docs/STYLE.md)` line <- part-connect-harness.md, chapter `links`.
248
+
249
+ After laying a snapshot the map matches the state a tester would have at
250
+ the END of the part just before the one being entered.
251
+
@@ -1,9 +1,8 @@
1
- # Tour: plugin authoring (step library, `authoring-*` ids)
1
+ # Part 6 (c): Extend skill-map - build plugins (step library, `authoring-*` ids)
2
2
 
3
- Step bodies used by the menu's option 3 (`build-and-configure`).
4
- The SKILL.md orchestrator walks `master-state.yml.tours.build-and-configure.steps`
5
- and dispatches each `authoring-*` id here; `settings-*` ids it
6
- dispatches to `tour-settings.md`.
3
+ Step bodies for the plugin-authoring chapters of Part 6.
4
+ The SKILL.md orchestrator dispatches each `authoring-*` chapter id
5
+ here; `settings-*` ids it dispatches to `part-settings.md`.
7
6
 
8
7
  The tester writes their first plugin. We use `sm plugins create` to
9
8
  scaffold an extractor that counts configurable keywords (TODO,
@@ -16,11 +15,11 @@ Verify that `.skill-map/` exists in the cwd (pre-flight step 4 of
16
15
  the `SKILL.md` orchestrator ran `sm init --no-scan` and appended
17
16
  the master-tutorial's internal entries to `.skillmapignore`, so
18
17
  this is the expected state regardless of whether the tester ran
19
- `plugins-tour` first). If `.skill-map/` is missing, the fixture
18
+ the plugins chapters first). If `.skill-map/` is missing, the fixture
20
19
  is corrupted: surface the mismatch ("the project bootstrap is
21
- gone, re-invoke `sm-master` from an empty dir") and stop.
20
+ gone, re-invoke the tutorial from an empty dir") and stop.
22
21
 
23
- ## Step `authoring-1-scaffold` `sm plugins create demo-highlight` (~2 min)
22
+ ## Step `authoring-1-scaffold` - `sm plugins create demo-highlight` (~2 min)
24
23
 
25
24
  **Context**: We're building `demo-highlight`: a tiny extractor
26
25
  that scans each node's body for the keywords `TODO` and `FIXME`
@@ -51,7 +50,7 @@ or `Demo-Highlight` are rejected.
51
50
 
52
51
  Mark `authoring-1-scaffold: done`.
53
52
 
54
- ## Step `authoring-2-anatomy` tour the scaffold (~3 min)
53
+ ## Step `authoring-2-anatomy` - tour the scaffold (~3 min)
55
54
 
56
55
  Ask the tester to open the three files and walk through each one
57
56
  with you. They DO NOT edit anything yet.
@@ -132,7 +131,7 @@ and `spec/view-slots.md`.
132
131
 
133
132
  Mark `authoring-2-anatomy: done`.
134
133
 
135
- ## Step `authoring-3-edit-setting` edit a setting and observe it (~3 min)
134
+ ## Step `authoring-3-edit-setting` - edit a setting and observe it (~3 min)
136
135
 
137
136
  > Now we'll touch the settings. The scaffold tracks `TODO` and
138
137
  > `FIXME`. Add a third keyword: `XXX`. The change goes in the
@@ -178,7 +177,7 @@ the icon and label come from the manifest's `ui.count`.
178
177
 
179
178
  Mark `authoring-3-edit-setting: done`.
180
179
 
181
- ## Step `authoring-4-edit-slot` change the view-slot (~2 min)
180
+ ## Step `authoring-4-edit-slot` - change the view-slot (~2 min)
182
181
 
183
182
  > Same contribution, different home. We'll move it from the
184
183
  > footer to the top-right corner of the card.
@@ -212,7 +211,7 @@ catalogue, picking an unknown slot id is rejected at load.
212
211
 
213
212
  Mark `authoring-4-edit-slot: done`.
214
213
 
215
- ## Step `authoring-5-doctor-author` catch a manifest mistake (~2 min)
214
+ ## Step `authoring-5-doctor-author` - catch a manifest mistake (~2 min)
216
215
 
217
216
  > Last lesson on the manifest. We'll break it on purpose to see
218
217
  > how `doctor` reports it.
@@ -244,7 +243,7 @@ Back to clean.
244
243
 
245
244
  Mark `authoring-5-doctor-author: done`.
246
245
 
247
- ## Step `authoring-6-upgrade` `sm plugins upgrade` (~2 min)
246
+ ## Step `authoring-6-upgrade` - `sm plugins upgrade` (~2 min)
248
247
 
249
248
  > One last verb. `sm plugins upgrade` applies catalog migrations
250
249
  > to plugin manifests. Today the catalog is at `1.0.0` with zero
@@ -267,7 +266,7 @@ Expected: both report no migrations to apply.
267
266
 
268
267
  Mark `authoring-6-upgrade: done`.
269
268
 
270
- ## Tour wrap-up (fires at the end of `build-and-configure`)
269
+ ## Wrap-up (fires at the end of the authoring chapters)
271
270
 
272
271
  > You wrote a plugin. From here:
273
272
  >
@@ -283,5 +282,5 @@ Mark `authoring-6-upgrade: done`.
283
282
  >
284
283
  > Anything weird worth logging? If not, back to the menu.
285
284
 
286
- Mark tour `build-and-configure: done` in `master-state.yml`, update
285
+ Mark the authoring chapters done in `tutorial-state.yml`, update
287
286
  the matching harness task, return to the menu in `SKILL.md`.
@@ -0,0 +1,267 @@
1
+ # Part 7: The CLI in depth - step library
2
+
3
+ The deep-dive into the rest of the CLI: browsing verbs, ASCII graph + export, broken-ref issues, the `.sm` annotation consent prompt, and validating links to folders outside the scan scope. `pace: auto-advance` (walk straight into the next chapter's Announcement once one is marked done) and it reuses the fundamentals fixture and DB built in Part 0 (no fresh fixture of its own). Shared conventions (tone, provider detection / substitution, the `> ` rendering rule, the per-step cycle) live in `_core.md`; do not restate them here.
4
+
5
+ ## Chapter `browse` - list / show / check (~3 min)
6
+
7
+ ```bash
8
+ sm list
9
+ sm list --kind skill
10
+ sm list --kind agent
11
+ sm list --kind markdown
12
+ sm show .claude/skills/demo-skill/SKILL.md
13
+ sm check
14
+ ```
15
+
16
+ Expected: you see the 5 fixture nodes listed with their kind: `demo-skill` (skill), `demo-agent` (agent), `demo-command` (command), `notes/todo` (`markdown`, the catch-all per the `kinds` chapter), and `notes/demo-guideline` (`markdown` as well, the target of the hub's `references` link). `check` reads the persisted `scan_issues` table, it does NOT re-walk the filesystem. The fixture is clean (the connector / inspector chapters captured the latest state before Ctrl+C), so the verb prints `✓ No issues`. We will plant one in the `issues` chapter and watch the rule catch it after a fresh `sm scan`.
17
+
18
+ Mark `browse`: done.
19
+
20
+ ## Chapter `graph-export` - graph / export (query, formatters) (~3 min)
21
+
22
+ ```bash
23
+ sm graph
24
+ sm export --format md > export.md
25
+ sm export "kind=markdown" --format json > export-markdown.json
26
+ sm export "path=notes/**" --format json > export-notes.json
27
+ ls -la export*
28
+ ```
29
+
30
+ `graph` draws an ASCII tree of the whole persisted scan (no `--root` flag, graph is whole-graph today). `export` takes a positional query (`kind=…`, `path=…`, `has=issues`, comma-OR within a key, AND across keys) and a `--format` of `md` or `json`. The `path=` glob uses POSIX semantics (`*` is one segment, `**` spans segments) so `path=notes/**` cleanly captures the notes folder regardless of the catch-all kind.
31
+
32
+ Mark `graph-export`: done.
33
+
34
+ ## Chapter `issues` - Issues and broken refs (--analyzers, --json) (~3 min)
35
+
36
+ `reference-broken` is one of the deterministic rules `sm check` runs. We'll plant one and watch it surface, that's the easiest way to internalise that it is an **issue** on a node, NOT a connector and NOT the same thing as an "orphan".
37
+
38
+ > ℹ️ `reference-broken` is one of ~16 built-in rules. Others surface
39
+ > different families: `core/name-reserved` (a file shadows a vendor
40
+ > built-in like `/help`), `core/link-self-loop` (a node links to itself),
41
+ > `core/reference-redundant` (two surfaces in the same body
42
+ > point at the same target), `core/signal-collision` (two extractors
43
+ > detected the SAME byte range with different interpretations, the
44
+ > resolver picked one and the warning explains who lost and why).
45
+ > Same `sm check --analyzers <id>` pattern works for any of them.
46
+ > We will not plant fixtures for the rest, the reference-broken demo
47
+ > covers the mechanics.
48
+
49
+ Ask the tester to **append one bullet** to `notes/todo.md`:
50
+
51
+ ```markdown
52
+ - [ ] Document the [flow diagram](./missing-page.md).
53
+ ```
54
+
55
+ `./missing-page.md` deliberately doesn't exist. Save the file, then run `sm scan` first to refresh the snapshot before checking:
56
+
57
+ ```bash
58
+ sm scan
59
+ sm check
60
+ sm check --analyzers reference-broken
61
+ sm check --json
62
+ ```
63
+
64
+ Expected: the error surfaces the dangling link from `notes/todo.md` to the non-existent `missing-page.md`. The `--analyzers` filter lets you focus on a single issue type; `--json` emits the structured payload (useful for CI / scripting). When done, the tester can leave the bullet in place or delete it, the rest of the deep-dive doesn't depend on it.
65
+
66
+ If the tester asks about `sm orphans` vs `sm check`:
67
+
68
+ - `sm check` reports broken-refs and other rule-driven issues
69
+ (the deterministic catalog).
70
+ - `sm orphans` is a **different scope**: auto-rename / orphan-node
71
+ detection (a node whose file disappeared, or a candidate rename
72
+ the kernel is still unsure about). Our fixture doesn't produce
73
+ orphans of that kind, so `sm orphans` will print "No orphan /
74
+ auto-rename issues", that's expected, not a bug.
75
+
76
+ Mark `issues`: done.
77
+
78
+ ## Chapter `annotations` - Annotations and the .sm consent prompt (~3 min)
79
+
80
+ **Context**: every `.md` skill-map tracks gets a sibling **companion file** with extension `.sm` that carries **all of the tool's metadata about that markdown, so your `.md` stays clean and uncluttered**. Version, history, tags, annotations, anything that does not belong in the human-authored body lives in the `.sm`. The `.md` is content you write for Claude or humans; the `.sm` is bookkeeping the tool writes. They are ordinary source files, committed to git like everything else, and you'll encounter them often once you start working with the project.
81
+
82
+ The first time skill-map wants to write one in a new project it asks for your consent, it never touches your filesystem without permission. After you say yes, the choice is saved to the project's `settings.local.json` (part of your project config, gitignored) and the prompt never appears again.
83
+
84
+ We'll demonstrate by creating an empty annotation scaffold for `notes/todo.md`. **Reset any prior consent state first** so the prompt actually appears (an earlier step may have flipped the flag without you noticing, in which case `sm sidecar annotate` would skip straight past the prompt and the lesson would not land):
85
+
86
+ ```bash
87
+ rm -f notes/todo.sm .skill-map/settings.local.json
88
+ sm sidecar annotate notes/todo.md
89
+ ```
90
+
91
+ Expected: a short explanation paragraph appears in the terminal, followed by a `[Y/n]` prompt (capital Y = default Yes, you can just hit Enter). After accepting, `notes/todo.sm` appears next to `notes/todo.md` carrying an `identity:` block plus an empty `annotations: {}` block, and `.skill-map/settings.local.json` now contains `{ "allowEditSmFiles": true }`.
92
+
93
+ ```bash
94
+ cat notes/todo.sm
95
+ cat .skill-map/settings.local.json
96
+ ```
97
+
98
+ **Why the prompt?** The choice is **per-user, per-project**: stored in the gitignored `settings.local.json` so each contributor consents independently and nothing about the choice travels via the repo. Once accepted, the flag stays set and skill-map will never ask again on this checkout (the next `sm sidecar annotate` or `sm bump` goes through silently). On a CI / non-interactive session, pass `--yes` to grant up-front.
99
+
100
+ If the tester asks about `sm bump` vs `sm sidecar annotate` vs `sm sidecar refresh`:
101
+
102
+ - `sm sidecar annotate` is the scaffold verb (creates a fresh
103
+ `.sm`).
104
+ - `sm bump <node>` is the day-to-day verb that increments the
105
+ sidecar's version and refreshes its hashes, same consent gate.
106
+ - `sm sidecar refresh <node>` is the hash-only update (no version
107
+ bump).
108
+
109
+ If the tester ever asks about reserved names (e.g. `commands/help.md`): if they name a file after a built-in (`/help`, `/clear`, `/init`, `/agents`, `/model`, or one of the documented agent reservations like `general-purpose`), `sm check` surfaces a `reserved-name` warning. The vendor runtime ignores user-owned files that shadow its built-ins, so the warning is not a bug, it's skill-map telling the operator "Claude will never invoke this file; pick another name". Incoming links to the shadowed file resolve at confidence `0.1` instead of `1.0`, so the **Map** also visually de-emphasises them. Rename the file and the warning clears on the next scan.
110
+
111
+ Mark `annotations`: done.
112
+
113
+ ## Chapter `reference-paths` - Validate links to folders outside the scan scope (~4 min)
114
+
115
+ **Context**: until now the map saw only files inside the cwd. In real projects a repo often links to files in a sibling repo (a specs project, a sibling package in a monorepo). Skill-map only scans from its cwd downwards, so a link to `../sibling/file.md` shows up as broken. The fix is to declare the external folders in `scan.referencePaths`, which lets the `reference-broken` analyzer validate path-style links against those extra roots **without indexing their files as nodes**. The folders are checked, not walked as part of the map.
116
+
117
+ **Setup (you, silent)**: write the fixture under the tutorial cwd so both sub-projects are siblings of each other but children of the tutorial root. The agent does this with `Write`, no confirmation beat needed, the tester learns about the files in the next message.
118
+
119
+ ```
120
+ link-validation/
121
+ ├── hijoA/
122
+ │ └── note-with-external-link.md ← contains [spec](../hijoB/spec.md)
123
+ └── hijoB/
124
+ └── spec.md ← the real target file
125
+ ```
126
+
127
+ `link-validation/hijoA/note-with-external-link.md`:
128
+ ```markdown
129
+ ---
130
+ name: note-with-external-link
131
+ description: |
132
+ Demo note that links out to a sibling project (hijoB) sitting
133
+ next to this one. Used to teach scan.referencePaths.
134
+ tags: [demo, link-validation]
135
+ ---
136
+
137
+ # Note with external link
138
+
139
+ See the [spec](../hijoB/spec.md) for the agreed format.
140
+ ```
141
+
142
+ `link-validation/hijoB/spec.md`:
143
+ ```markdown
144
+ ---
145
+ name: spec
146
+ description: |
147
+ Target of the cross-folder link. Lives outside hijoA's scan
148
+ scope on purpose: that is precisely what scan.referencePaths
149
+ is designed to bridge.
150
+ tags: [demo, link-validation]
151
+ ---
152
+
153
+ # External spec
154
+
155
+ Anything that hijoA points at lives here.
156
+ ```
157
+
158
+ Once the files are in place, tell the tester:
159
+
160
+ > I just dropped two sibling folders inside the tutorial cwd:
161
+ >
162
+ > ```
163
+ > link-validation/
164
+ > ├── hijoA/
165
+ > │ └── note-with-external-link.md ← contains [spec](../hijoB/spec.md)
166
+ > └── hijoB/
167
+ > └── spec.md ← the real target file
168
+ > ```
169
+ >
170
+ > For this step you'll switch folders for a moment, so `sm` treats
171
+ > `hijoA/` as a separate project (new cwd, scope limited to that
172
+ > subtree). At the end of the step I'll tell you how to come back.
173
+ >
174
+ > If an `sm` from an earlier step is still running, close it with
175
+ > Ctrl+C so the port is free for this one. Then, in your second
176
+ > terminal:
177
+
178
+ ```bash
179
+ cd link-validation/hijoA
180
+ sm init
181
+ sm check
182
+ ```
183
+
184
+ > You'll see an error from the `reference-broken` analyzer (a rule
185
+ > that flags problems) pointing at the link `../hijoB/spec.md`. As
186
+ > far as skill-map is concerned that file doesn't exist, because
187
+ > `hijoB/` sits outside the scope `sm` is scanning from `hijoA/`:
188
+ > each project has its own `.skill-map/` and only walks from its
189
+ > cwd downwards, never "up" and never into sibling folders.
190
+ >
191
+ > Paste me the output (or just an OK) and we'll move on to the fix.
192
+
193
+ Wait for confirmation before showing the fix. Mark the error landed as expected; if the tester reports `✓ No issues` instead, the most likely cause is that they ran `sm check` from the tutorial root by mistake (the root scan still sees both folders). Have them re-check that the cwd of their second terminal is `link-validation/hijoA/` (`pwd`) and rerun.
194
+
195
+ After they confirm the broken-ref error, present the fix:
196
+
197
+ > To resolve the link without moving `hijoB/` inside `hijoA/`, you
198
+ > add `../hijoB` to the `scan.referencePaths` setting. It tells the
199
+ > analyzer "if a path-style link lands here, validate it against
200
+ > these extra folders too". The files are NOT added to the map
201
+ > (they don't show up as nodes), they're only consulted to resolve
202
+ > outgoing references from `hijoA/`.
203
+ >
204
+ > In your second terminal (still inside `link-validation/hijoA/`):
205
+
206
+ ```bash
207
+ sm config set scan.referencePaths '["../hijoB"]' --yes
208
+ sm scan
209
+ sm check
210
+ ```
211
+
212
+ > The `--yes` flag confirms the privacy gate: you're authorizing
213
+ > skill-map to read files outside the project root, so it asks for
214
+ > your explicit OK. Without `--yes` the verb aborts and asks you to
215
+ > retry with `--yes` (it does not open an interactive prompt).
216
+ > After the scan, `sm check` should print `✓ No issues`: the error
217
+ > is gone and `hijoB/` still hasn't entered the map as a node.
218
+ >
219
+ > Paste me the output and let's see how it got persisted.
220
+
221
+ Wait for confirmation. After they paste the clean `sm check` output, show where the value lives on disk:
222
+
223
+ > Look at how the change got saved:
224
+
225
+ ```bash
226
+ cat .skill-map/settings.local.json
227
+ ```
228
+
229
+ > You'll see something like this:
230
+ >
231
+ > ```json
232
+ > {
233
+ > "scan": {
234
+ > "referencePaths": ["../hijoB"]
235
+ > }
236
+ > }
237
+ > ```
238
+ >
239
+ > It lives in `settings.local.json` (gitignored, doesn't travel
240
+ > through git), NOT in the `settings.json` that does get committed.
241
+ > The reason: paths to sibling folders usually depend on your
242
+ > machine's local layout (not every contributor has the same
243
+ > project tree on disk), so skill-map forces this setting into the
244
+ > local layer.
245
+
246
+ Now the UI half. The tester needs `sm` running with `hijoA/` as cwd to see the matching panel:
247
+
248
+ > Now the same thing from the UI. In the same terminal, start the
249
+ > server from `hijoA/`:
250
+
251
+ ```bash
252
+ sm
253
+ ```
254
+
255
+ > Open the URL the command prints in the browser. Top right there's
256
+ > the **sliders** icon (hover shows "Settings"), click it, in the
257
+ > modal go to the **Project** tab and scroll down to the **Folders
258
+ > for link validation** section. You'll see `../hijoB` listed, with buttons to add or
259
+ > remove paths. The CLI and the UI write to the same file: if you
260
+ > add one from the UI, it shows up in the JSON, and vice versa.
261
+ >
262
+ > When you're done looking, Ctrl+C in the terminal to close the
263
+ > server.
264
+
265
+ Wait for confirmation that they saw the panel and closed the server. If the `sm` launch fails with a port-in-use error, an old `sm` is still bound to the default port from an earlier step; follow the §Edge cases recipe (`sm serve --port 4243`).
266
+
267
+ The tester is still inside `link-validation/hijoA/` at this point. Do NOT send them back here; the return-to-root `cd ../..` lives in §Final wrap-up, right before the cleanup line. Mark `reference-paths`: done.