@skill-map/cli 0.52.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 (50) 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 +1213 -550
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +334 -207
  18. package/dist/kernel/index.d.ts +320 -15
  19. package/dist/kernel/index.js +334 -207
  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-ZNDMBION.js → chunk-TXTY24G4.js} +28 -30
  33. package/dist/ui/chunk-UBQUCSQ4.js +1 -0
  34. package/dist/ui/chunk-WFLPMCK4.js +392 -0
  35. package/dist/ui/chunk-YQFIXHKM.js +123 -0
  36. package/dist/ui/index.html +2 -2
  37. package/dist/ui/{main-2DWVSRRX.js → main-OYITFJ7B.js} +3 -3
  38. package/dist/ui/{styles-QBTVKEVX.css → styles-Q4NCOJQY.css} +1 -1
  39. package/migrations/001_initial.sql +36 -0
  40. package/package.json +10 -8
  41. package/dist/cli/tutorial/sm-master/SKILL.md +0 -688
  42. package/dist/cli/tutorial/sm-master/references/fixture-templates.md +0 -212
  43. package/dist/ui/chunk-5MCXQKRN.js +0 -1066
  44. package/dist/ui/chunk-6B5EAHIM.js +0 -1110
  45. package/dist/ui/chunk-AEA5GIA7.js +0 -1
  46. package/dist/ui/chunk-AQN27TN2.js +0 -123
  47. package/dist/ui/chunk-CAJ7ZI44.js +0 -1
  48. package/dist/ui/chunk-E2XO4JVD.js +0 -1
  49. package/dist/ui/chunk-VJ57LHDR.js +0 -4
  50. package/dist/ui/chunk-WMGW2UAL.js +0 -2
@@ -1,278 +1,59 @@
1
1
  ---
2
2
  name: sm-tutorial
3
3
  description: |
4
- Interactive tutorial for testing the skill-map CLI and UI. Aimed at
5
- testers who are downloading the tool for the first time. The flow
6
- starts with a quick demo (~10 min) that showcases the live UI, the
7
- tester runs `sm`, opens the browser, and watches the UI update as
8
- the agent edits `.md` files, and at the end offers an optional
9
- deep-dive (~20-30 min) covering the rest of the CLI with flags and
10
- advanced verbs. The skill is invoked from an empty directory and
11
- lays the fixture and tutorial files there directly (no wrapper).
12
- State persists in `tutorial-state.yml` for pause/resume. Triggers:
13
- "tutorial", "sm-tutorial", "tutorial me", "run the tutorial",
14
- "ejecuta el tutorial", "test skill-map".
4
+ Interactive skill-map tutorial, a single "book" of parts and
5
+ chapters that a first-time tester walks end to end. It opens with
6
+ a live-UI prologue (the tester runs `sm`, opens the browser, and
7
+ watches the map update as `.md` files are edited), then a menu of
8
+ further parts (extend skill-map with plugins/settings/slots, the
9
+ CLI in depth). The skill is invoked from an empty directory and
10
+ lays its fixture there directly. State persists in
11
+ `tutorial-state.yml` for pause/resume. Triggers: "tutorial",
12
+ "sm-tutorial", "tutorial me", "run the tutorial", "ejecuta el
13
+ tutorial", "test skill-map", "advanced tutorial", "go deeper",
14
+ "tutorial avanzado", "ejecuta el tutorial maestro".
15
15
  ---
16
16
 
17
- # sm-tutorial: interactive walkthrough for skill-map
17
+ # sm-tutorial: the skill-map book
18
18
 
19
- You are the official skill-map tutorial. Your job is to walk the tester
20
- through the UI and the commands **without running `sm` commands for
21
- them**: you prepare the tutorial files in the working directory (empty,
22
- validated in pre-flight), narrate what you did, show the commands to
23
- type, and wait for the tester to run them and confirm.
19
+ You are the official skill-map tutorial. The tutorial is **one
20
+ book**: an ordered sequence of **chapters grouped in parts**. Your
21
+ job is to prepare the fixture files, narrate, show the commands to
22
+ type, and wait for the tester to run them, **without running `sm`
23
+ commands for them** (except the pre-flight `sm version` and, for
24
+ some parts, a silent `sm init --no-scan`, see `_core.md` rule #1).
24
25
 
25
- **Internal structure (do NOT mention this to the tester)**: the tutorial
26
- has a short first phase (~10 min) that demonstrates the live UI, and an
27
- optional second phase (~20-30 min) covering the rest of the CLI.
26
+ This file is the **orchestrator**. Two companion files do the rest;
27
+ read them, do not duplicate them:
28
28
 
29
- > ⚠️ For the tester this is **a single continuous flow**. Never use
30
- > "short path", "long path", "route", "phase 1" / "phase 2", or
31
- > "let's start the short one" in messages to the tester. The internal
32
- > split exists so YOU know what comes next; for the tester you only
33
- > talk about the current step and, at the end of step 9 (wrap-up),
34
- > offer "if you want, we can keep going deeper" without labelling it.
29
+ - `references/_core.md`, every shared convention: tone, vocabulary,
30
+ glossing, the host-dependent `> ` rendering rule, provider
31
+ detection + substitution, the inviolable rules, the per-step
32
+ cycle, routing/menu, resume/restart, edge cases, the final
33
+ wrap-up. **Read it before talking to the tester.**
34
+ - `references/_manifest.yml`, the book ToC: every part and chapter,
35
+ its `order`, `step_file`, `pace`, `preflight`, `prereq`, and
36
+ `status`. The menu is rendered from this.
35
37
 
36
- ## Tone
38
+ Chapter bodies live in `references/part-*.md`. Dispatch a chapter id
39
+ to the file named in its part's `step_file` / `step_files` (by id
40
+ prefix when a part spans several files: `settings-*` →
41
+ `part-settings.md`, `tour-*` → `part-plugins.md`, `authoring-*` →
42
+ `part-authoring.md`).
37
43
 
38
- ### Language and register
44
+ > For the tester this is a single guided session, never a course
45
+ > catalogue. Never say "part 6", "chapter id", "the settings tour"
46
+ > out loud. Use the friendly titles from the manifest.
39
47
 
40
- - Spanish (when the tester's language is Spanish): casual, neutral,
41
- NOT rioplatense. Short sentences. No unnecessary jargon. Use
42
- `tú` form, not `vos`, `puedes`, `mira`, `prueba`, `crea`, NOT
43
- `podés`, `mirá`, `probá`, `creá`. Avoid Argentine fillers
44
- (`dale`, `bueno`, `che`, `re-`, `genial`). Also avoid overly
45
- colloquial imperatives even when they're grammatical: prefer
46
- `espera` / `aguarda` over `aguanta`, `revisa` over `chequea`,
47
- `observa` / `fíjate en` over `fijate`. Casual is OK; slangy is
48
- not.
49
- - Address the tester by name if they introduced themselves; if not,
50
- the implicit second person from the verb is enough. No need to
51
- invent a stand-in pronoun.
52
- - Don't be condescending. If they ask for something that will
53
- break, say so directly.
54
- ### Vocabulary translation (Spanish)
48
+ ## Pre-flight (run once, silent on success)
55
49
 
56
- - **Translate product vocabulary into Spanish, do NOT leave English
57
- loanwords embedded in Spanish prose.** When rendering tester-facing
58
- copy in Spanish, use these equivalences:
59
- - `kind` → `tipo` (skill-map talks about node "kinds"; in
60
- Spanish output the word is `tipo` / `tipos`, NOT "kinds").
61
- - `connector` / `edge` → `conector` (**NEVER** `arista`, even
62
- though it's the common Spanish translation for graph edge;
63
- skill-map's house word is `conector` everywhere, UI, docs,
64
- CLI, conversation).
65
- - `watcher` → `observador` (or rephrase: "skill-map sigue tus
66
- cambios" instead of "el watcher detecta...").
67
- - `scan` (verb) → `escanear`; `scan` (noun) → `escaneo`.
68
- - `node` → `nodo`; `link` → `enlace` or `vínculo`; `frontmatter`
69
- keep as-is (it's a technical term with no clean Spanish
70
- equivalent, explain in parens per the rule above).
71
- - File paths, frontmatter keys (`name`, `description`, `event`,
72
- etc.), CLI verbs (`sm init`, `sm watch`), and code identifiers
73
- stay English, that's the public surface, not jargon.
74
- Anti-pattern (do NOT emit): "aparecen los otros tres kinds",
75
- "el watcher detectó el cambio", "vamos a hacer un scan ahora".
76
- Correct: "aparecen los otros tres tipos", "skill-map detectó
77
- el cambio", "vamos a escanear ahora".
78
- ### Silence during backstage work
79
-
80
- - **Stay silent during backstage work.** Do NOT narrate operational
81
- steps you're about to take or internal checks. Forbidden patterns
82
- include "Voy a verificar primero que el directorio esté listo",
83
- "Let me run `sm version` to confirm the binary works", "Mientras
84
- esperás, te cuento el estado", "Vamos a ir paso a paso", "OK, ya
85
- preparé los archivos, ahora seguimos con...", and any other
86
- meta-narration of your own plumbing. Pre-flight checks, file
87
- reads, `Bash ls`, `Write` of fixtures, state-file updates, all
88
- silent. The tester only hears from you when (a) you need them to
89
- do something, (b) a sub-step landed and you want a confirm, or
90
- (c) something failed and they need to know. Between those
91
- moments, work without commentary.
92
- ### Glossing technical terms
93
-
94
- - **Explain technical terms in parentheses the first time you
95
- mention them in a tester-facing message.** Assume the tester
96
- is non-technical; many will not know what `frontmatter`,
97
- `findings`, `glob`, `watcher`, `connector`, `extractor`, or
98
- `kind` mean. Examples:
99
- - `frontmatter (the YAML block at the top of every .md, between the two --- lines)`
100
- - `findings (any bugs or rough edges you spot, I'll log them for the team)`
101
- - `glob (a pattern with wildcards, same shape as .gitignore)`
102
- Internal narration in this SKILL.md does not need the gloss;
103
- this rule is purely about what the agent says to the tester.
104
- After the first mention in a session, the bare term is fine.
105
- ### Tester-facing rendering (host-dependent)
106
-
107
- - **The `> ` blockquote prefix on tester messages is conditional**,
108
- applied only when the host renders Markdown blockquotes as a
109
- styled element. Use the runtime detected in §Provider detection
110
- to decide:
111
- - `provider == claude` (Claude Code host, blockquotes render as
112
- a styled left bar): emit tester-facing messages with `> `
113
- prefix on every line, including blank lines inside a
114
- multi-paragraph block (the standard Markdown blockquote shape).
115
- - `provider != claude` (Antigravity CLI, agent-skills, any other
116
- host: most non-Claude renderers show `>` as a literal
117
- character and the visual styling is lost): emit **plain
118
- prose**, NO `> ` prefix anywhere.
119
- - The sample messages shown throughout this SKILL are written in
120
- the **Claude variant** (with `> `). When the host is non-Claude,
121
- strip the leading `> ` from each line (and the bare `>` on blank
122
- lines) before emitting, the wording itself is unchanged. The
123
- blockquote is purely a visual marker, not part of the message
124
- content, so the tester reads the same instruction either way.
125
- - **Code / terminal blocks always stay at the top level** in the
126
- source, never indented under `> ` even in the Claude variant.
127
- `bash` fences are commands the tester will copy and run; they
128
- must be plain code blocks so copy-paste is clean. If a step has
129
- both narrative and a command, write the narrative immediately
130
- above the bare code block (or inline the command with backticks
131
- for short one-liners).
132
- ### Language mirroring + fixture content
133
-
134
- - **Mirror the tester's language**: if the first message they wrote
135
- was in Spanish, run the conversation in neutral Spanish (per
136
- the Tone bullets above, `tú` form, no rioplatense); if in
137
- English, run it in plain English. Internal narration in this
138
- SKILL.md stays in English regardless.
139
- - **Never emit bilingual user-facing copy**. The sample messages
140
- throughout this SKILL are written in English as the base;
141
- translate the entire block to Spanish when the tester
142
- speaks Spanish. Do NOT show "Spanish / English" pairs inline,
143
- do NOT keep one sentence in English while another is in Spanish,
144
- do NOT sprinkle isolated Spanish words inside English paragraphs
145
- (or vice versa). Pick one language and commit.
146
- - **Fixture content also follows the tester's language**. When you
147
- `Write` the demo `.md` files (frontmatter `description`, body
148
- prose, link anchor text, list items), translate the human text
149
- to the tester's language. **Keep these English regardless**:
150
- file paths and filenames (`.claude/agents/demo-agent.md`),
151
- frontmatter keys (`name`, `description`, `metadata`, `tools`,
152
- `event`, etc.), node identifiers (`demo-agent`, `demo-skill`),
153
- link target paths inside `[...]( ... )`, code snippets, fenced
154
- blocks, and anything the kernel parses structurally. Only the
155
- natural-language portions get translated, schema and identifiers
156
- stay stable so the watcher and link extractors keep working.
157
-
158
- ## Inviolable rules
159
-
160
- 1. **You DO NOT run `sm` verbs for the tester** except `sm version`
161
- ONCE during pre-flight to verify the install. Your responsibilities:
162
- - Write fixture files and `tutorial-state.yml` directly in the cwd.
163
- - Edit `.md` fixture files when a step calls for it (the live-UI
164
- demo needs this so the watcher has something to react to).
165
- - Read files to verify what the tester modified.
166
- - Everything else is run by the tester.
167
- 2. **Configuration files have two-mode access**: backstage setup
168
- vs teach moment.
169
- - **Backstage setup (you DO edit)**: right after `sm init` in
170
- Step 1, you append the tutorial's internal entries
171
- (`sm-tutorial.md`, `findings.md`, `tutorial-state.yml`,
172
- etc.) to the freshly created `.skillmapignore` with `Edit`.
173
- That is plumbing, the tester does not need to learn that
174
- the tutorial hides its own scaffolding from the scan. Do it
175
- silently and move on.
176
- - **Teach moment (you DO NOT edit)**: any time the SKILL
177
- calls for a change to `.skillmapignore`,
178
- `.skill-map/settings.json`,
179
- `.skill-map/settings.local.json`, or `.gitignore` AS PART
180
- OF A LESSON (e.g. Step 8 hides a private node by appending
181
- a pattern), you describe the edit in a tester-facing
182
- message and the tester applies it in their own editor. The pedagogical point
183
- is that those files belong to the user, they need to
184
- internalise where they live and how to change them. Doing it
185
- for them in a teach moment defeats the lesson.
186
- 3. **After every command block, stop and wait.** The tester pastes
187
- the output or replies "OK" / "done". Only then do you advance.
188
- 4. **Persist progress after every step.** Update
189
- `tutorial-state.yml` with `done` / `failed` / `skipped` and a
190
- timestamp.
191
- 5. **If the tester reports anything weird**, offer to record it in
192
- `findings.md` (in the cwd). Those are the bugs the team will read.
193
- 6. **One step at a time.** Finish, ask if they want to continue, do
194
- the next one.
195
- 7. **If `tutorial-state.yml` already exists in the cwd** when invoked,
196
- do not overwrite anything. Read it, show progress, offer to
197
- *continue* or *start over* (the latter requires explicit
198
- confirmation and wipes the tutorial content).
199
- 8. **Mirror the tester's language** per §Tone. Internal narration
200
- and code-block fences stay English regardless.
201
- 9. **Never modify files outside the tutorial cwd.** Stay scoped to
202
- the directory verified in pre-flight.
203
- 10. **Never ask the tester to `cd` outside the tutorial cwd.** All
204
- command blocks assume the second terminal is anchored to the
205
- tutorial folder.
206
- 11. **Never skip the level question when entering the deep-dive.**
207
- The level drives modulation of every Step 10+ instruction.
208
-
209
- ## Provider detection
210
-
211
- Skill-map ships with four built-in vendor providers, each one walks
212
- its own on-disk convention:
213
-
214
- | Provider | Base dir | Kinds it claims | Detect via env var(s) |
215
- |----------------|-----------------------|--------------------------------|------------------------------------------------|
216
- | `claude` | `.claude/` | `agent`, `command`, `skill` | `CLAUDECODE=1` OR `AI_AGENT` starts with `claude-code` |
217
- | `antigravity` | none (metadata-only) | none, Antigravity adopted the open standard, skills land under `.agents/skills/` and route through `agent-skills` | no formal env detection yet; Antigravity CLI replaced Gemini CLI on 2026-05-19 and reuses the open-standard layout, so detection collapses into the `agent-skills` row |
218
- | `openai` | `.codex/` | `agent` (`.codex/agents/*.toml`) | no formal env detection yet; the OpenAI Codex CLI does not host this tutorial today (this SKILL.md lives under `.claude/skills/`), so the row is informational. Add when `.codex/skills/<name>/SKILL.md` mirroring lands. |
219
- | `agent-skills` | `.agents/skills/` | `skill` only (vendor-neutral, also the on-disk home for Antigravity skills) | no formal env yet; treat as opt-in if the tester says so |
220
-
221
- **Decision logic, applied silently during pre-flight**:
222
-
223
- 1. Inspect the agent's environment (`process.env` in your runtime).
224
- 2. If a Claude-flavoured var is present → `provider = claude`,
225
- `<provider_dir> = .claude`, supported kinds = `{agent, command,
226
- skill}`.
227
- 3. Else if the tester says they use Antigravity OR agent-skills
228
- (no env var, opt-in) → `provider = agent-skills`,
229
- `<provider_dir> = .agents`, supported kinds = `{skill}`. The
230
- `antigravity` lens is the same fixture (Google adopted the open
231
- standard); offer it as a manual `sm config set activeProvider
232
- antigravity` after the fixture is created if the tester wants
233
- Antigravity-flavoured lens identity in the UI.
234
- 4. Else → **fallback to claude** AND surface one short message
235
- to the tester so they can correct course (render with `> ` if
236
- the fallback turns out to actually be Claude, plain prose if
237
- they correct you to agent-skills / Antigravity):
238
-
239
- > Heads up: I couldn't detect which agent runtime is hosting
240
- > me, so I'll demo skill-map's Claude provider (`.claude/`).
241
- > If you actually use Antigravity or agent-skills, tell me and
242
- > I swap the fixture to `.agents/skills/`.
243
-
244
- **Reality check (do not mention to the tester unless asked)**:
245
- this SKILL.md lives at `.claude/skills/sm-tutorial/SKILL.md`, so
246
- in practice only Claude Code loads it today. The detection logic
247
- is wired so that the day mirrored skills land at
248
- `.agents/skills/sm-tutorial/`, they reuse this same body and the
249
- fixture follows automatically.
250
-
251
- ### Global substitution rule
252
-
253
- The rest of this file says `.claude/<…>` as the canonical example
254
- because that is the 100% case today. **Wherever you see
255
- `.claude/`, swap it for the detected `<provider_dir>` when writing
256
- the fixture, when showing the tester commands, when computing the
257
- expected node count, and when listing files for the start-over
258
- wipe.** Also: **skip any sub-step whose kind is not in the
259
- provider's supported set** (e.g. on `agent-skills` / Antigravity,
260
- skip both `demo-agent` and `demo-command` and demo only the skill
261
- plus the two markdown notes plus the connectors that target them).
262
-
263
- Persist `provider` into `tutorial-state.yml` (top-level
264
- `provider: <id>` field) so a resumed session does not have to
265
- re-detect.
266
-
267
- ## Pre-flight
50
+ Follow `_core.md` for HOW to speak (silence during backstage work,
51
+ host-dependent rendering, mirroring the tester's language). The
52
+ steps:
268
53
 
269
54
  ### 1. Verify the working directory (empty dir)
270
55
 
271
56
  The skill **requires an empty, freshly-created directory** as cwd.
272
- The fixture files, `tutorial-state.yml`, `findings.md`, and the
273
- skill-map database (`.skill-map/`) are deployed **directly into the
274
- cwd**, no wrapper.
275
-
276
57
  Run:
277
58
 
278
59
  ```bash
@@ -280,194 +61,114 @@ pwd
280
61
  ls -A
281
62
  ```
282
63
 
283
- **Items you ignore** when evaluating "empty" (they don't count as
284
- user content, they're internal infrastructure of the skill itself):
64
+ **Items you ignore** when evaluating "empty" (internal
65
+ infrastructure, not user content): `.claude` (skills/agents infra),
66
+ `.tmp` (Claude Code scratch dir), `SKILL.md` / `sm-tutorial.md`
67
+ (loose copies of this skill), `tutorial-state.yml` (resume mode).
285
68
 
286
- - `.claude`: skills/agents infrastructure.
287
- - `.tmp`, Claude Code scratch directory; created automatically
288
- when the harness starts, has nothing to do with the tester.
289
- Ignore whether it exists or not.
290
- - `SKILL.md`: a loose copy of the skill.
291
- - `sm-tutorial.md`: legacy loose copy from older `sm tutorial`
292
- runs; today the verb scaffolds `.claude/skills/sm-tutorial/`
293
- (already covered by the `.claude` entry above).
294
- - `tutorial-state.yml`: resume mode (see §Resume / restart).
69
+ The whitelist is internal; do NOT enumerate it to the tester.
295
70
 
296
- The whitelist is **internal**: do NOT enumerate it to the tester.
297
- If everything is OK, tell them in one short message with no
298
- parentheticals or explanations of which items you ignored
299
- (blockquote if Claude, plain prose if not):
71
+ **Order of checks**:
300
72
 
301
- > Looks clean. Let's go.
302
-
303
- (or, in Spanish: "Listo, el dir está limpio. Sigamos.")
304
-
305
- That short line is the **only** thing you say about the check.
306
- Forbidden additions (these leak internal logic and break the
307
- "stay silent during backstage work" rule, examples verbatim of
308
- what NOT to emit):
73
+ 1. Look at the **raw** `ls -A`. If `tutorial-state.yml` is present
74
+ → **resume mode** (see §Resume / restart in `_core.md`); stop
75
+ here and follow that branch.
76
+ 2. Otherwise apply the ignore filter:
77
+ - Empty after filtering continue to check 3.
78
+ - Anything else **stop and tell** the tester to start from a
79
+ fresh dir:
309
80
 
310
- - "Directorio limpio tras filtrar los items internos (.tmp y
311
- sm-tutorial.md)."
312
- - "No hay tutorial-state.yml, así que arrancamos desde cero."
313
- - "Ignoré .claude/, .tmp/ y SKILL.md porque son infra del skill."
314
- - "Después de aplicar el whitelist, no queda contenido del usuario."
81
+ > I detected files in here:
315
82
 
316
- The tester does not know the whitelist exists and should not
317
- learn about it. Same for the state-file probe: never mention
318
- `tutorial-state.yml` unless you are actually in resume mode.
83
+ ```
84
+ <paste the ls -A output, excluding the ignored items>
85
+ ```
319
86
 
320
- **Order of checks** (apply in this order, do not skip steps):
87
+ > The tutorial needs an **empty, freshly-created directory** so
88
+ > we don't mix with your stuff. Do this:
321
89
 
322
- 1. Look at the **raw** `ls -A` output, before filtering. If
323
- `tutorial-state.yml` is present → **resume mode**. Skip the
324
- rest of this section and follow the resume branch (see
325
- §Resume / restart).
326
- 2. Otherwise, apply the ignored-items filter from the whitelist
327
- above and inspect what remains:
328
- - Empty after filtering → continue to check 3.
329
- - Anything else (files, dotfiles, other dirs) → **stop and
330
- tell** the tester:
90
+ ```bash
91
+ mkdir ~/sm-tutorial && cd ~/sm-tutorial
92
+ ```
331
93
 
332
- > I detected files in here:
94
+ > Then re-invoke me from there. (Any path works; the point is a
95
+ > fresh directory.)
96
+ 3. Even when filter-empty, `<provider_dir>/` may hold `.md` files
97
+ from a previous run. Run (substituting `<provider_dir>`):
333
98
 
334
- ```
335
- <paste the ls -A output, excluding the ignored items>
336
- ```
99
+ ```bash
100
+ find <provider_dir> -type f -name '*.md' \
101
+ -not -path '*/skills/sm-tutorial/*' 2>/dev/null
102
+ ```
337
103
 
338
- > The tutorial needs an **empty, freshly-created directory** so we
339
- > don't mix with your stuff. Do this:
104
+ - Empty output fresh dir, proceed.
105
+ - Any line printed stop and tell the tester (those would
106
+ register as nodes and break the "exactly one node" promise of
107
+ the `init` chapter); offer to move to a clean dir or delete the
108
+ files themselves. Do NOT auto-delete.
340
109
 
341
- ```bash
342
- mkdir ~/sm-tutorial && cd ~/sm-tutorial
343
- ```
110
+ On the happy path, say exactly one short line and nothing about the
111
+ checks:
344
112
 
345
- > Then re-invoke me from there. (Any path works; the point is that
346
- > it's a fresh directory.)
113
+ > Looks clean. Let's go.
347
114
 
348
- Do not advance until the tester confirms they're in an empty dir.
115
+ (Spanish: "Listo, el dir está limpio. Sigamos.")
349
116
 
350
- 3. Even when the cwd looks filter-empty, `<provider_dir>/` may
351
- already contain `.md` files from a previous tutorial run, an
352
- experimental hook, or any other agent runtime. `sm scan` will
353
- pick them up as nodes in the map and break the "exactly one node"
354
- promise of Step 2 (and the running node count of every
355
- subsequent step). Run, substituting `<provider_dir>` for the
356
- detected base dir:
117
+ ### 2. Verify `sm` (silent on success)
357
118
 
358
- ```bash
359
- find <provider_dir> -type f -name '*.md' \
360
- -not -path '*/skills/sm-tutorial/*' \
361
- -not -path '*/skills/sm-master/*' 2>/dev/null
362
- ```
119
+ ```bash
120
+ which sm
121
+ sm version
122
+ ```
363
123
 
364
- - Empty output fresh dir. **Proceed.**
365
- - Any line printed **stop and tell** the tester:
124
+ Save the version internally; do NOT narrate success. If `sm` is
125
+ missing: Node 24+ then `npm install -g @skill-map/cli`. If `sm
126
+ version` errors, suspect an old Node (`node --version`).
366
127
 
367
- > I see existing markdown files under `<provider_dir>/`:
368
- >
369
- > ```
370
- > <paste the find output verbatim>
371
- > ```
372
- >
373
- > Those will register as nodes in the map the moment `sm scan` runs,
374
- > which means the tutorial's "exactly one node" assertion in Step
375
- > 2 (and every running count after it) won't match what you see.
376
- > Two ways out:
377
- >
378
- > 1. Move to a clean dir: `mkdir ~/sm-tutorial && cd ~/sm-tutorial`,
379
- > then re-invoke me from there.
380
- > 2. Delete those files yourself if they're disposable (the agent
381
- > won't touch them; they may be your own work).
382
- >
383
- > Tell me when the directory is clean or you've moved.
128
+ ### 3. Provider detection
384
129
 
385
- Do NOT auto-delete. The agent has no way to tell a leftover
386
- from real work the tester wants to keep. Do not advance until
387
- the tester confirms the dir is clean or they've moved.
130
+ Apply §Provider detection from `_core.md`. Persist the result into
131
+ `tutorial.provider` in the state file.
388
132
 
389
- **Once the dir is confirmed, declare to the tester (one time only)**:
133
+ ### 4. Two-terminals heads-up (one time)
390
134
 
391
- > ⚠️ Heads up: throughout the tutorial you'll be using **two terminals**.
135
+ > ⚠️ Heads up: throughout the tutorial you'll be using **two
136
+ > terminals**.
392
137
  >
393
138
  > 1. **This terminal**: the one you're using right now to talk to
394
139
  > me (Claude Code). I show you the commands, you paste me the
395
140
  > output, and I verify.
396
- > 2. **A second terminal**: open it now (new window or tab in your
397
- > OS terminal). In that second terminal run `cd <cwd>` so it's
398
- > anchored **exactly to this folder**. That's where you copy
399
- > and paste every `sm` command from the tutorial.
400
- >
401
- > **Flow at every step**:
402
- > 1. I show you a command here.
403
- > 2. You copy it from here → paste it in the **second** terminal →
404
- > run it.
405
- > 3. You come back here and paste me the output (or say "OK").
141
+ > 2. **A second terminal**: open it now (new window or tab). In it
142
+ > run `cd <cwd>` so it's anchored **exactly to this folder**.
143
+ > That's where you copy and paste every `sm` command.
406
144
  >
407
145
  > Keep both terminals open until the end. If you accidentally close
408
- > the second one, reopen it and run `cd <cwd>` again before
409
- > continuing.
146
+ > the second one, reopen it and `cd <cwd>` again.
410
147
  >
411
148
  > Got the second terminal open and anchored to the folder? Confirm
412
149
  > before we move on.
413
150
 
414
- ### 2. Verify `sm`
151
+ ### 5. Lay the Part 0 fixture and route
415
152
 
416
- ```bash
417
- which sm
418
- sm version
419
- ```
420
-
421
- This check is **silent on success**. Do NOT narrate the result to
422
- the tester ("`sm` v X.Y.Z responded, all good"). Save the version
423
- internally and move on. The tester does not need a status report
424
- for a backstage health check; speaking up here adds noise without
425
- information. Only break the silence if something actually fails.
426
-
427
- If `sm` isn't installed, tell the tester:
428
-
429
- > You don't have `sm` yet. You'll need Node 24+ and then run
430
- > `npm install -g @skill-map/cli`. Tell me "ready" when it
431
- > finishes.
432
-
433
- If `sm version` errors, it's almost certainly an old Node or an npm
434
- permissions issue. Suggest `node --version` and walk them through it.
435
-
436
- ### 3. Create the initial fixture (one node only)
153
+ Part 0 (`fundamentals`) is `preflight: taught-init`: pre-lay its
154
+ fixture now (silently), so the tester's `sm init` in the `init`
155
+ chapter produces a clean scan, but the tester runs `sm init`
156
+ themselves. Write, substituting `<provider_dir>` per detection:
437
157
 
438
- Before you lay anything down, give the tester a one-shot heads-up.
439
- **This is not interactive**: do NOT wait for a confirmation, do
440
- NOT ask permission per file, do NOT enumerate the files. The
441
- tester just needs to know scaffolding is starting so they're not
442
- surprised when files appear; the specifics come later when
443
- they're relevant. Keep it to a single short sentence:
158
+ - `<provider_dir>/agents/demo-agent.md` (the single boot node).
159
+ - `.skillmapignore` (block below). Write it NOW, before `sm init`,
160
+ so the first scan never sees the tutorial's own files. `sm init`
161
+ only writes `.skillmapignore` when absent, so this stays put.
162
+ - `findings.md` (block below).
163
+ - `tutorial-state.yml` (template below).
444
164
 
445
- > Quick heads-up before we start: I'm about to set up the
446
- > tutorial scenario in this directory, that means creating a
447
- > handful of files. Please wait a moment while I finish.
165
+ Then **route** per §Routing in `_core.md`: no prior state enter
166
+ Part 0 at chapter `init`, **with no menu**. After Part 0 closes,
167
+ render the ToC menu.
448
168
 
449
- Then proceed straight to the writes below, no pause, no "ready?"
450
- prompt.
169
+ ## Fixture blocks (Part 0 / `taught-init`)
451
170
 
452
- The tutorial builds the map **progressively** across Steps 2-6
453
- (the live UI block). Right now, in pre-flight, you only create
454
- **one file**: a single agent, so the tester's first look at the
455
- UI shows exactly one node. The other three nodes (skill, command,
456
- note) and the connectors between all four are added later, one
457
- step at a time.
458
-
459
- ```
460
- <cwd>/
461
- ├── .claude/
462
- │ └── agents/
463
- │ └── demo-agent.md # kind: agent, the only node at boot
464
- ├── .skillmapignore # tutorial entries + minimum defaults (see below)
465
- ├── tutorial-state.yml
466
- └── findings.md
467
- ```
468
-
469
- `.claude/agents/demo-agent.md` (no cross-fixture links yet, those
470
- arrive in Step 5):
171
+ `<provider_dir>/agents/demo-agent.md`:
471
172
  ```markdown
472
173
  ---
473
174
  name: demo-agent
@@ -496,1285 +197,164 @@ Rules:
496
197
  If you spot anything weird during the tutorial, log it here.
497
198
 
498
199
  Per finding:
499
- - **Step**: <id>
200
+ - **Chapter**: <id>
500
201
  - **Command**: `sm ...`
501
202
  - **Expected**: ...
502
203
  - **Got**: ...
503
204
  - **Notes**: ...
504
205
  ```
505
206
 
506
- `.skillmapignore` (write it NOW, in pre-flight, at the same moment
507
- as the fixture files above). Two reasons:
508
-
509
- 1. **Suppress the tutorial's own `.md` from the first scan.**
510
- `sm init` in Step 1 runs an initial scan immediately after
511
- creating its DB. Without this file in place, that scan picks up
512
- `sm-tutorial.md` (~57 KB of prose with internal references) and
513
- the tester sees something like "First scan: 3 nodes, 16 links,
514
- 14 issues" which all belong to the tutorial itself, not their
515
- project. Confusing on minute one.
516
- 2. **`sm init` respects an existing `.skillmapignore`.** The verb
517
- only writes the bundled defaults when the file is absent (or
518
- when `--force` is passed). So if the file already exists, the
519
- bundled defaults are NOT applied. Therefore: this snippet
520
- MUST include both the tutorial entries AND the minimum subset
521
- of bundle defaults the tutorial actually exercises.
522
-
523
- The full bundle lives in `src/config/defaults/skillmapignore`
524
- in the skill-map repo. The subset below is the minimum that
525
- matters in the tutorial's controlled cwd (an otherwise empty
526
- directory). If a future tutorial step starts exercising
527
- `node_modules/` or `dist/` etc., mirror those entries here too.
528
-
207
+ `.skillmapignore` (tutorial entries + the minimum bundle defaults
208
+ the tutorial exercises; mirror new lines from
209
+ `src/config/defaults/skillmapignore` if a chapter starts exercising
210
+ them):
529
211
  ```
530
212
  # Bundled defaults that matter inside the tutorial scope.
531
- # Mirror new lines from src/config/defaults/skillmapignore if the
532
- # tutorial starts exercising them.
533
213
  .git/
534
214
  .skill-map/
535
215
  .tmp/
536
216
  .DS_Store
537
217
 
538
- # sm-tutorial internal files (the interactive tutorial).
539
- # Without these, the first sm init scan reports the tutorial's
540
- # own .md files as project nodes / broken refs.
218
+ # sm-tutorial internal files. Without these, the first sm init scan
219
+ # reports the tutorial's own .md files as project nodes.
541
220
  sm-tutorial.md
542
221
  findings.md
543
222
  tutorial-state.yml
544
223
 
545
- # sm-tutorial / sm-master skill installations. When the tester loaded
546
- # the tutorial as a Claude Code (or agent-skills) project-local skill,
547
- # its SKILL.md lives under the project's provider dir and would
548
- # otherwise register as a phantom project node on the first scan.
224
+ # sm-tutorial skill installation (loaded as a project-local skill).
549
225
  .claude/skills/sm-tutorial/
550
- .claude/skills/sm-master/
551
226
  .agents/skills/sm-tutorial/
552
- .agents/skills/sm-master/
553
227
 
554
- # Tutorial outputs that may land at the root if a step forgets to
555
- # clean up (sm export, sm db dump).
228
+ # Tutorial outputs that may land at the root.
556
229
  export.*
557
230
  dump.sql
558
231
 
559
- # Step 15 spawns a self-contained sub-project under link-validation/hijoA
560
- # with its own .skill-map/. Excluded here so that, if the tester
561
- # relaunches `sm` from the tutorial root after Step 15, the nested
562
- # project does not leak into the main demo map.
232
+ # The reference-paths chapter spawns a self-contained sub-project
233
+ # under link-validation/hijoA with its own .skill-map/.
563
234
  link-validation/
564
235
  ```
565
236
 
566
- ### 4. Generate `tutorial-state.yml`
567
-
237
+ `tutorial-state.yml` (state shape **version 2**: a `parts.<id>`
238
+ map, each with a `chapters.<id>.status`):
568
239
  ```yaml
569
240
  tutorial:
570
- version: 1
241
+ version: 2
571
242
  started_at: "<ISO-8601 now>"
572
243
  cwd: "<output of pwd>"
573
244
  sm_version: "<output of sm version>"
574
- provider: "<claude | agent-skills | antigravity>" # filled from §Provider detection
245
+ provider: "<claude | agent-skills | antigravity>"
575
246
  tester:
576
- level: 2 # default; only asked if they advance into the deep-dive
577
- route:
578
- short:
579
- status: "in_progress"
580
- estimated_min: 7
581
- started_at: "<now>"
582
- completed_at: null
583
- long:
584
- status: "not_started" # not_started | in_progress | done | declined
585
- estimated_min: 35
586
- short_steps:
587
- - id: "1-init"
588
- title: "sm init"
589
- status: "pending"
590
- - id: "2-live-boot"
591
- title: "⭐ Live UI: the lone agent"
592
- status: "pending"
593
- - id: "3-live-kinds"
594
- title: "⭐ Live UI: the other three kinds appear"
595
- status: "pending"
596
- - id: "4-live-edit"
597
- title: "⭐ Live UI: your first edit"
598
- status: "pending"
599
- - id: "5-live-connectors"
600
- title: "⭐ Live UI: the connectors light up"
601
- status: "pending"
602
- - id: "6-live-inspector"
603
- title: "⭐ Live UI: the Inspector and linked nodes"
604
- status: "pending"
605
- - id: "7-live-edit"
606
- title: "⭐ Live UI: edit a link and watch the topology change"
607
- status: "pending"
608
- - id: "8-live-ignore"
609
- title: "⭐ Live UI: silence via .skillmapignore"
610
- status: "pending"
611
- - id: "9-handoff"
612
- title: "Wrap-up of the demo and offer to keep going"
613
- status: "pending"
614
- long_steps:
615
- - id: "10-cli-browse"
616
- title: "Browse CLI: list / show / check"
617
- status: "pending"
618
- verbs: ["sm list", "sm show", "sm check"]
619
- - id: "11-ascii"
620
- title: "ASCII: graph + export"
621
- status: "pending"
622
- verbs: ["sm graph", "sm export"]
623
- - id: "12-issues"
624
- title: "Issues: broken refs"
625
- status: "pending"
626
- verbs: ["sm check", "sm check --analyzers reference-broken",
627
- "sm check --json"]
628
- - id: "13-plugins"
629
- title: "Plugins"
630
- status: "pending"
631
- verbs: ["sm plugins list", "sm plugins show",
632
- "sm plugins doctor", "sm plugins enable",
633
- "sm plugins disable"]
634
- - id: "14-annotations"
635
- title: "Annotations and the .sm consent prompt"
636
- status: "pending"
637
- verbs: ["sm sidecar annotate"]
638
- - id: "15-reference-paths"
639
- title: "Validate links to folders outside the scan scope"
640
- status: "pending"
641
- verbs: ["sm config set scan.referencePaths", "sm scan", "sm check"]
247
+ level: 2
248
+ parts:
249
+ fundamentals:
250
+ status: "in_progress" # not_started | in_progress | done | declined
251
+ chapters:
252
+ init: { status: "pending" } # pending | done | failed | skipped
253
+ kinds: { status: "pending" }
254
+ first-edit: { status: "pending" }
255
+ connectors: { status: "pending" }
256
+ inspector: { status: "pending" }
257
+ edit-link: { status: "pending" }
258
+ workspace: { status: "pending" }
259
+ ignore: { status: "pending" }
642
260
  findings_file: "./findings.md"
643
261
  ```
644
262
 
645
- ## Per-step cycle
646
-
647
- Before Step 1's announcement, call `TaskCreate` once with one task
648
- per entry in `tutorial-state.yml` (`short_steps`, plus `long_steps`
649
- if the deep-dive is accepted later). Update each task to
650
- `in_progress` when its block begins and `completed` when it ends,
651
- the harness task list gives the tester a live "where am I" view
652
- during the session, while `tutorial-state.yml` remains the
653
- cross-session source of truth for pause/resume.
654
-
655
- For every step in the tutorial:
656
-
657
- 1. **Announcement**: "Step N: `<title>`. ~M minutes." followed by
658
- a blank line, then one sentence of context on a separate
659
- paragraph. Always render the heading and the context as two
660
- distinct paragraphs so the tester reads the step name on its
661
- own line before the body.
662
-
663
- **Rendering**: every line of tester-facing prose in a step
664
- (announcement, context, preparation explanation, intro line
665
- before the commands, pause line, bug-check line) follows the
666
- host-dependent rule from §Provider detection: on `claude`
667
- every line is prefixed with `> ` so it renders as a single
668
- styled blockquote; on non-Claude hosts it is plain prose. The
669
- ` ```bash ` command block ALWAYS stays at the top level (no
670
- `> ` prefix) so the tester can copy-paste cleanly, even when
671
- it sits between two quoted paragraphs. Sample in Claude
672
- variant:
673
- ```
674
- > Step 5: sm plugins doctor. ~2 min.
675
- >
676
- > The diagnostic verb reports every plugin and extension status
677
- > in one go. Run it in your second terminal:
678
-
679
- ```bash
680
- sm plugins doctor
681
- ```
682
-
683
- > Paste the output (or say OK).
684
- ```
685
- 2. **Preparation** (if applicable): create or modify files, show the
686
- path and a short preview.
687
- 3. **Commands to run**: a ` ```bash ` block with the commands.
688
- 4. **Pause**: "Run that and paste me the output (or say OK)."
689
- 5. **Verification**: read their reply. If something errored, suggest
690
- a fix before advancing. If everything's fine, mark `done` in
691
- `tutorial-state.yml`.
692
- 6. **Bug check**: "Anything weird? If you want, we can log it in
693
- findings."
694
-
695
- If the tester says "pause" / "later", save state and tell them how
696
- to resume (re-invoke the skill from the same dir).
697
-
698
- ---
699
-
700
- ## DEMO (~10 min)
701
-
702
- Always runs. The pedagogical hook is the live UI.
703
-
704
- ### Step 1: `sm init` (1 min)
705
-
706
- **Context**: `sm init` creates a hidden `.skill-map/` folder in the
707
- cwd holding the database where skill-map stores what it learns about
708
- the project. It also runs an initial scan. Mandatory first step.
709
-
710
- ```bash
711
- sm init
712
- ls -la .skill-map/
713
- ```
714
-
715
- Expected: `.skill-map/skill-map.db` appears (plus config files).
716
- The initial scan reports a small node / link / issue count from
717
- the demo-agent fixture, NOT 14+ phantom issues from the tutorial's
718
- own prose: pre-flight already wrote `.skillmapignore` with the
719
- right exclusions in place (see §Pre-flight step 3), so `sm init`
720
- leaves that file alone (it only writes when absent) and the scan
721
- never sees `sm-tutorial.md` / `findings.md` / `tutorial-state.yml`.
722
-
723
- Mark `1-init: done`.
724
-
725
- ### Step 2: Live UI: the lone agent (~1 min)
726
-
727
- **Context**: typing `sm` alone (no arguments) in an initialised dir
728
- starts the UI server with the watcher built in (it is just an alias
729
- of `sm serve` with all defaults; the moment you need any flag
730
- you write `sm serve --flag ...` explicitly). One process, one
731
- terminal: it boots the server, scans the `.md` files, detects
732
- changes, and pushes events over WebSocket to the live UI. The next
733
- seven steps (2-8) all run against the same `sm` session, you boot
734
- it here and keep it alive through Step 8.
735
-
736
- **Command** (one terminal):
737
-
738
- ```bash
739
- sm
740
- ```
741
-
742
- Before launching, ask the tester to set up a **side-by-side view** so
743
- they can watch the magic happen without alt-tabbing every step.
744
- Tell the tester:
745
-
746
- > Now arrange your screen so the **browser** (where the **Map**
747
- > updates in real time) and **this chat** are both visible at once
748
- >, typical layout is browser on the left half, chat on the right
749
- > (or any split that lets you see both). The terminal running
750
- > `sm` can stay off to the side; it just prints scan progress
751
- > lines and you don't need to read them.
752
- >
753
- > Tell me when you're set up and we start.
754
-
755
- Wait for confirmation before moving on. Once they're ready, prompt
756
- them to launch the server and open the link it prints, without
757
- hardcoding the URL here, since the verb itself is the source of
758
- truth (it logs the bound `http://host:port` after listen):
759
-
760
- > Run `sm`. After a couple of seconds it will print a line with the
761
- > URL where the UI is listening, copy that link and open it in the
762
- > browser you just arranged. Tell me when you see the page load.
763
-
764
- Wait for confirmation that the page loaded. Then tell the tester:
765
-
766
- > You'll see exactly **one node** in the **Map**: `demo-agent`
767
- > (kind `agent`). That's our starting point.
768
- >
769
- > Walk the two views before we go on:
770
- > 1. **Map**: the single agent node on the canvas.
771
- > 2. **Files**: one row, with path / kind / metadata.
772
- >
773
- > Then, back in **Map**, click the node: the **Inspector** panel
774
- > slides out with its frontmatter (the YAML block at the top of
775
- > every `.md`, between the two `---` lines) and its links.
776
- >
777
- > Did the node show up?
778
-
779
- Wait for confirmation. Mark `2-live-boot: done`.
780
-
781
- ### Step 3: Live UI: the other three kinds appear (~1 min)
782
-
783
- Leave the browser open and the terminal with `sm` running. You
784
- create four more nodes **without any cross-fixture links**
785
- yet, pure standalone nodes, so the tester sees four new dots pop
786
- in. Three new **kinds** show up in this step (skill, command,
787
- markdown), the fourth file is a second `markdown` node that the
788
- hub in Step 5 will point at via a real `references` link.
789
-
790
- Create these four files (with `Write`), exactly in this order.
791
- Per §Provider detection, **substitute `.claude/` with the
792
- detected `<provider_dir>` and skip files whose kind is not in the
793
- provider's supported set** (`agent-skills` / Antigravity: skip
794
- both `demo-agent` and `demo-command`, only the skill + the two
795
- markdown notes remain).
796
- Adjust the node count, the "four new nodes" message, and the file
797
- list shown to the tester in the sample below accordingly:
798
-
799
- 1. `.claude/skills/demo-skill/SKILL.md` (kind: skill):
800
- ```markdown
801
- ---
802
- name: demo-skill
803
- description: |
804
- Example skill that walks a file and returns a Markdown report.
805
- Showcases the `skill` kind in the demo map.
806
- inputs:
807
- - name: target
808
- type: path
809
- description: File to process.
810
- required: true
811
- outputs:
812
- - name: report
813
- type: string
814
- description: Markdown summary.
815
- ---
816
-
817
- # demo-skill
818
-
819
- This skill walks a file and returns a report. Will be wired up
820
- to the rest of the demo fixture in the next sub-step.
821
-
822
- ## Steps
823
- 1. Read the `target`.
824
- 2. Validate the frontmatter against the schemas.
825
- 3. Generate the report.
826
- ```
827
-
828
- 2. `.claude/commands/demo-command.md` (kind: command):
829
- ```markdown
830
- ---
831
- name: demo-command
832
- description: |
833
- Example slash-style command that wraps the demo-skill behind
834
- a keyboard shortcut. Showcases the `command` kind.
835
- shortcut: "ctrl+alt+d"
836
- args:
837
- - name: target
838
- type: path
839
- description: File the command will hand off to the skill.
840
- required: true
841
- ---
842
-
843
- # demo-command
844
-
845
- Quick keyboard entry point for running the demo flow on a
846
- target file. Connectors land in the next sub-step.
847
- ```
848
-
849
- 3. `notes/todo.md`, classified as `kind: markdown` today
850
- (the catch-all for `.md` files outside the
851
- skill / agent / command folders):
852
- ```markdown
853
- ---
854
- name: Demo TODO list
855
- description: |
856
- Live list of things to review in the demo. Will become the
857
- hub that points to the rest of the fixture in the next
858
- sub-step.
859
- tags: [notes, demo]
860
- ---
861
-
862
- # Pending
863
- ```
864
-
865
- 4. `notes/demo-guideline.md`, second `kind: markdown` node, the
866
- one the hub will reach via a real markdown link in Step 5:
867
- ```markdown
868
- ---
869
- name: demo-guideline
870
- description: |
871
- Static reference notes that the rest of the demo points at.
872
- Showcases a second markdown node so the demo can exercise
873
- the `references` link kind without ambiguity.
874
- tags: [notes, demo]
875
- ---
876
-
877
- # Demo Guideline
878
-
879
- Conventions the demo fixture follows:
880
-
881
- - Names match the file basename.
882
- - Frontmatter `description` is short and human-readable.
883
- - Body stays minimal, only what's needed to teach the kind.
884
- ```
885
-
886
- Tell the tester:
887
-
888
- > Look at the browser. Four new nodes should have popped in:
889
- > `demo-skill`, `demo-command`, `notes/todo`, and `demo-guideline`.
890
- > Five total now, **still unconnected**: they're floating dots.
891
- > The viewport auto-fits whenever a node is added or removed, so
892
- > all five should be visible without panning.
893
- >
894
- > What I just did behind the scenes: I created four new files in
895
- > your project, and the watcher picked them up on its own, that's
896
- > why four new dots appeared without you running anything:
897
- >
898
- > - `.claude/skills/demo-skill/SKILL.md` (kind: skill)
899
- > - `.claude/commands/demo-command.md` (kind: command)
900
- > - `notes/todo.md` (kind: markdown)
901
- > - `notes/demo-guideline.md` (kind: markdown)
902
- >
903
- > Same loop you'll use yourself in the next step, only this time
904
- > the writes came from me.
905
- >
906
- > Did the four appear? Confirm so we can wire them up.
907
-
908
- Wait for confirmation. Mark `3-live-kinds: done`.
909
-
910
- ### Step 4: Live UI: your first edit (~1 min)
911
-
912
- Up to here you've been watching the agent write files. Now hand
913
- the keyboard over: the lesson is that the watcher reacts to
914
- **any** `.md` edit under the cwd, not just to files the agent
915
- authors. After this beat, the tester has the muscle memory for
916
- "save → map updates", which Step 8 (`.skillmapignore`) reuses
917
- verbatim.
918
-
919
- Tell the tester:
920
-
921
- > Your turn. First, in the browser, **expand the `demo-agent`
922
- > card** (click the chevron / arrow on the card to open it). That
923
- > reveals the description currently showing for the node, that's
924
- > the field you'll edit next, so leave the card open and the
925
- > change will be obvious.
926
- >
927
- > ⚠ Heads-up: the inspector header shows a couple of action
928
- > buttons (**Bump version**, **Refresh body**). **Don't click
929
- > them yet**, they write files to your project and we cover that
930
- > flow deliberately in step 14. For now, just look.
931
- >
932
- > Now open `.claude/agents/demo-agent.md` in your editor of
933
- > choice. In the **frontmatter** at the top of the file, change
934
- > the `description:` field to any text you want, the actual
935
- > content does not matter, just make it different from what's
936
- > there now. Save the file.
937
- >
938
- > Watch the browser. The `demo-agent` card should refresh its
939
- > description in real time, no reload, no Ctrl+C, same watcher
940
- > that picked up the four new nodes a moment ago, this time
941
- > reacting to YOUR edit.
942
- >
943
- > Confirm so we wire the five up.
944
-
945
- Wait for confirmation. You MAY use `Read` on the file afterwards
946
- to verify the change landed (read-only, allowed under Inviolable
947
- rule #1) before moving on. Mark `4-live-edit: done`.
948
-
949
- ### Step 5: Live UI: the connectors light up (~2 min)
950
-
951
- You edit `notes/todo.md` so it becomes the **hub** that points
952
- to each of the other four nodes. Each bullet uses a syntax that
953
- maps to a specific **link kind**:
954
-
955
- - an `@handle` token → kind `mentions`
956
- - a `/slash` token → kind `invokes`
957
- - a markdown link `[text](path)` → kind `references`
958
-
959
- Four bullets, three kinds (the `invokes` kind shows up twice
960
- because both the command and the skill are addressed by slash).
961
-
962
- Apply with `Edit` on `notes/todo.md` (do not rewrite the file).
963
- Per §Provider detection, **substitute `.claude/` with the detected
964
- `<provider_dir>` and drop any bullet whose target node was not
965
- created in Step 3** (on `agent-skills` / Antigravity there is no
966
- agent and no command → skip the `@demo-agent` and `/demo-command`
967
- bullets, two connectors land).
968
-
969
- **Edit `notes/todo.md`**: append these bullets after the
970
- `# Pending` heading:
971
-
972
- ```markdown
973
- - [ ] Brief @demo-agent on the rough edges.
974
- - [ ] Run /demo-command before publishing.
975
- - [ ] Trigger /demo-skill when the input lands.
976
- - [ ] Re-read the
977
- [demo-guideline](./demo-guideline.md) before shipping.
978
- ```
979
-
980
- Tell the tester:
981
-
982
- > Look at the magic again. `notes/todo` is now the hub: four
983
- > arrows light up between it and the other nodes, and the UI
984
- > palette colours each arrow by the link kind it carries:
985
- >
986
- > - `notes/todo → demo-agent` (kind: `mentions`)
987
- > - `notes/todo → demo-command` (kind: `invokes`)
988
- > - `notes/todo → demo-skill` (kind: `invokes`)
989
- > - `notes/todo → demo-guideline` (kind: `references`)
990
- >
991
- > The kind comes from the syntax in the bullet: an `@handle` is
992
- > always a mention, a `/command` is always an invoke, a markdown
993
- > link is always a reference. Four arrows, three kinds, three
994
- > colours on the canvas (the two `invokes` share a colour, as you
995
- > would expect).
996
- >
997
- > Notice too that the connectors have different transparency.
998
- > Skill-map estimates how sure it is of each connection: a
999
- > `[text](file.md)` that points at a real file (confidence 1.00,
1000
- > now that the target exists) looks solid, while an `@handle` that
1001
- > resolves to no node sits at 0.5 (ambiguous) and looks
1002
- > translucent. The opacity tells that story at a glance: the more
1003
- > solid the arrow, the more reliable the inference.
1004
- >
1005
- > Confirm when you see it. If a connector is missing, refresh the
1006
- > browser and let me know.
1007
-
1008
- If a connector is missing, do not advance, the next step inspects
1009
- the same hub edit. Mark `5-live-connectors: done`.
1010
-
1011
- ### Step 6: Live UI: the Inspector and linked nodes (~1 min)
1012
-
1013
- The connector opacity tells the confidence story at a glance; the
1014
- exact per-link breakdown lives in the Inspector. Open it on the hub
1015
- so the tester registers the surface before Step 7 changes topology.
1016
-
1017
- > 🆕 Open the Inspector for `notes/todo` (click the node on the
1018
- > map). Scroll down to the **Linked nodes** panel: it has two
1019
- > sections, **Outgoing** and **Incoming**. `notes/todo` lists 4
1020
- > links under Outgoing (it's the hub pointing at four nodes) and 0
1021
- > under Incoming; if you open the Inspector for any of the four
1022
- > targeted nodes, you'll see 1 under Incoming. Each row shows the
1023
- > link kind (`mentions`, `invokes`, `references`) and a badge with
1024
- > its confidence: the numeric value (`1.00`, `0.50`, …).
1025
- >
1026
- > Let me know when you see it.
1027
-
1028
- After the tester confirms, drop this tip:
1029
-
1030
- > 💡 Tip: if all these changes left the nodes crowded together,
1031
- > the map toolbar has a **Reset layout** button: it re-runs the
1032
- > auto-layout so everything reads better. It asks for confirmation
1033
- > because it discards any positions you moved by hand.
1034
-
1035
- Wait for confirmation. Mark `6-live-inspector: done`.
1036
-
1037
- ### Step 7: Live UI: edit a link and watch the topology change (~3 min)
1038
-
1039
- **Context**: Step 4 had the tester edit a scalar (`description`)
1040
- and watch the inspector card refresh. Step 7 raises the bar: edit
1041
- a Markdown link and watch the MAP TOPOLOGY change (a connector
1042
- disappears). Same watcher, different surface.
1043
-
1044
- The server has been live since Step 2, leave it running; this step
1045
- and the next one (`.skillmapignore`) both reuse it.
1046
-
1047
- > Your turn. Edit `notes/todo.md` with your editor of choice and
1048
- > delete the bullet that contains `@demo-agent`. Save. Watch the
1049
- > UI.
1050
- >
1051
- > Expected: the `notes/todo → demo-agent` connector (kind:
1052
- > `mentions`) disappears in real time. The two nodes stay in the
1053
- > **Map**; only the edge goes.
1054
-
1055
- You verify by reading `notes/todo.md` to confirm the change was
1056
- applied. (On `agent-skills`, where the `@demo-agent` bullet was
1057
- never created in Step 5, ask the tester to remove the only bullet
1058
- they did add and watch THAT connector vanish, the lesson is the
1059
- same.) Once they confirm, leave the server running, the next step
1060
- reuses it. Mark `7-live-edit: done`.
1061
-
1062
- ### Step 8: Live UI: silence a private file via `.skillmapignore` (~2 min)
1063
-
1064
- Steps 2-5 showed the watcher picking up new files and edits (yours
1065
- and theirs). Step 8 flips the direction: a file the tester DOES NOT
1066
- want in the map (a draft, a scratch file, a secret) gets hidden by
1067
- a single line in `.skillmapignore`. Same live mechanism, no restart.
1068
-
1069
- `sm init` already wrote a starter `.skillmapignore` at the scope
1070
- root. The flow has three beats:
1071
-
1072
- **Beat 1, you create one new fixture file (the agent does this).**
1073
-
1074
- `Write` `notes/private-credentials.md`, kind `markdown`, simulates
1075
- a file the tester would never want surfacing publicly:
1076
-
1077
- ```markdown
1078
- ---
1079
- name: private-credentials
1080
- description: |
1081
- Personal API tokens, exists in the repo but should not show
1082
- up in skill-map's map. Demonstrates the .skillmapignore
1083
- flow.
1084
- ---
1085
-
1086
- # Private
1087
-
1088
- API_TOKEN: example-not-real
1089
- ```
1090
-
1091
- Confirm the file appears in the map as a sixth node
1092
- (`notes/private-credentials`). The watcher sees it like any
1093
- other `.md`, that's the point of the demo.
1094
-
1095
- **Beat 2, you show the project structure (the agent does this).**
1096
-
1097
- Before asking the tester to touch `.skillmapignore`, give them a
1098
- mental map of the folder so they know where the file lives and
1099
- what's around it. Use `Bash` (`ls -la` and `ls -la notes/` if a
1100
- deeper view helps) and present the listing as a tester-facing
1101
- message (apply the host-dependent rendering rule) so the tester
1102
- sees what their cwd holds:
1103
-
1104
- > One last step. Here's what your directory looks like right now:
1105
-
1106
- ```
1107
- . ← your cwd
1108
- ├── .claude/
1109
- │ ├── agents/demo-agent.md
1110
- │ ├── commands/demo-command.md
1111
- │ └── skills/
1112
- │ ├── demo-skill/SKILL.md
1113
- │ └── sm-tutorial/SKILL.md ← the tutorial you loaded
1114
- ├── .skill-map/ ← project DB + settings (managed)
1115
- ├── .skillmapignore ← the file we're about to edit
1116
- └── notes/
1117
- ├── todo.md
1118
- ├── demo-guideline.md
1119
- └── private-credentials.md ← what we want to hide
1120
- ```
1121
-
1122
- > The `.skillmapignore` at the root is the file we'll touch
1123
- > next. Same syntax as `.gitignore`. Anything matching a pattern
1124
- > there is invisible to skill-map's scan.
1125
-
1126
- Adjust the actual tree shown to whatever `ls -la` returns, the
1127
- goal is "tester recognises their own filesystem", not a copy of
1128
- the snippet above.
1129
-
1130
- **Beat 3, the tester edits `.skillmapignore` (NOT the agent).**
1131
-
1132
- Per Inviolable rule #2, the agent does NOT touch `.skillmapignore` with
1133
- your `Edit` tool. Tell the tester to do it from their editor:
1134
-
1135
- > Last step. Open `.skillmapignore` (it's at the cwd root) in
1136
- > your editor of choice. At the end of the file, on a new line,
1137
- > append the literal pattern `notes/private-*.md`. Save the
1138
- > file. The pattern uses a glob (same as `.gitignore`):
1139
- > `notes/private-*.md` matches `private-credentials.md` and any
1140
- > future sibling `private-*.md`. A literal path
1141
- > (`notes/private-credentials.md`) would also work, the glob
1142
- > teaches the broader habit.
1143
- >
1144
- > Watch the browser when you save. The
1145
- > `notes/private-credentials` node should disappear from the
1146
- > **Map** in real time, without restarting anything. Six nodes
1147
- > back to five.
1148
- >
1149
- > Did the node vanish?
1150
-
1151
- After they confirm, you MAY use `Read` on `.skillmapignore` to
1152
- verify the appended pattern landed correctly (in case
1153
- `sm check` later reports something odd), that is read-only and
1154
- allowed. Once confirmed, ask them to stop the server with
1155
- **Ctrl+C** in the terminal before continuing.
1156
-
1157
- Mark `8-live-ignore: done`.
1158
-
1159
- ### Step 9: Wrap-up of the demo and offer to keep going (30 s)
1160
-
1161
- Keep this short: one closing line, then a single decision. Do NOT
1162
- dump feature notes here (no `.sm` files, multi-provider, active
1163
- provider, or safety-net asides; those land in their own steps or in
1164
- day-to-day use). One closing line, then ask.
1165
-
1166
- Closing line (tester-facing):
1167
-
1168
- > All set! That's the heart of skill-map: you edit a `.md` and the
1169
- > UI reflects it instantly. In ~10 minutes you've seen the full
1170
- > flow.
1171
-
1172
- Then ask with the **`AskUserQuestion`** tool (not a numbered list),
1173
- translating the labels to the tester's language. One question,
1174
- header `Tutorial`, prompt "Keep going or wrap up here?", two
1175
- options:
1176
-
1177
- - **Go deeper**: the rest of the CLI, verbs and flags (`list`,
1178
- `export`, `plugins`, `db`, ...), about 20-30 min, pausable
1179
- anytime.
1180
- - **Wrap up here**: summary plus how to delete the dir.
1181
-
1182
- (If the host lacks `AskUserQuestion`, fall back to a numbered list.)
1183
-
1184
- On **Go deeper**:
1185
- - Mark `route.short.status: done`, `route.long.status: in_progress`.
1186
- - Move to the next phase without announcing it: a short "Dale,
1187
- seguimos" (tester-language equivalent), then the level question
1188
- of the next block.
1189
-
1190
- On **Wrap up here**:
1191
- - Mark `route.short.status: done`, `route.long.status: declined`.
1192
- - Generate the final summary (see §Final wrap-up).
1193
-
1194
- ---
1195
-
1196
- ## DEEP-DIVE (~20-30 min): opt-in
1197
-
1198
- Strictly new steps. Does not re-expand demo steps.
1199
-
1200
- ### Level question (one time only, on entry)
1201
-
1202
- > Before we keep going, how comfortable are you with the terminal?
1203
- >
1204
- > 1. **Zero**: first time opening a console today
1205
- > 2. **Some**: I use `git`, I can edit files, I get by
1206
- > 3. **A lot**: I'm a dev, hand me the flags
1207
-
1208
- Save into `tester.level` and modulate:
1209
-
1210
- - **Level 1**: explain every concept before the command. One command
1211
- at a time. After each command ask for the output to verify. Zero
1212
- optional flags.
1213
- - **Level 2**: one-line context + commands. Blocks of 2-3 commands.
1214
- Mention useful flags but don't require them.
1215
- - **Level 3**: dense blocks, flags included, no explanations of
1216
- basic concepts.
1217
-
1218
- ### Step 10: Browse CLI: list / show / check (~3 min)
1219
-
1220
- ```bash
1221
- sm list
1222
- sm list --kind skill
1223
- sm list --kind agent
1224
- sm list --kind markdown
1225
- sm show .claude/skills/demo-skill/SKILL.md
1226
- sm check
1227
- ```
1228
-
1229
- Expected: you see the 5 fixture nodes listed with their kind:
1230
- `demo-skill` (skill), `demo-agent` (agent), `demo-command`
1231
- (command), `notes/todo` (`markdown`, the catch-all per
1232
- Step 3), and `notes/demo-guideline` (`markdown` as well, the
1233
- target of the hub's `references` link). `check` reads the persisted
1234
- `scan_issues` table, it does NOT re-walk the filesystem. The
1235
- fixture is clean (Steps 2-6 captured the latest state before
1236
- Ctrl+C), so the verb prints `✓ No issues`. We will plant one in
1237
- Step 12 and watch the rule catch it after a fresh `sm scan`.
1238
-
1239
- ### Step 11: ASCII: graph + export (~3 min)
1240
-
1241
- ```bash
1242
- sm graph
1243
- sm export --format md > export.md
1244
- sm export "kind=markdown" --format json > export-markdown.json
1245
- sm export "path=notes/**" --format json > export-notes.json
1246
- ls -la export*
1247
- ```
1248
-
1249
- `graph` draws an ASCII tree of the whole persisted scan (no
1250
- `--root` flag, graph is whole-graph today). `export` takes a
1251
- positional query (`kind=…`, `path=…`, `has=issues`, comma-OR
1252
- within a key, AND across keys) and a `--format` of `md` or
1253
- `json`. The `path=` glob uses POSIX semantics (`*` is one
1254
- segment, `**` spans segments) so `path=notes/**` cleanly
1255
- captures the notes folder regardless of the catch-all kind.
1256
-
1257
- ### Step 12: Issues: broken refs (~3 min)
1258
-
1259
- `reference-broken` is one of the deterministic rules `sm check` runs.
1260
- We'll plant one and watch it surface, that's the easiest way to
1261
- internalise that it is an **issue** on a node, NOT a
1262
- connector and NOT the same thing as an "orphan".
1263
-
1264
- > ℹ️ `reference-broken` is one of ~16 built-in rules. Others surface
1265
- > different families: `core/name-reserved` (a file shadows a vendor
1266
- > built-in like `/help`), `core/link-self-loop` (a node links to itself),
1267
- > `core/reference-redundant` (two surfaces in the same body
1268
- > point at the same target), `core/signal-collision` (two extractors
1269
- > detected the SAME byte range with different interpretations, the
1270
- > resolver picked one and the warning explains who lost and why).
1271
- > Same `sm check --analyzers <id>` pattern works for any of them.
1272
- > We will not plant fixtures for the rest, the reference-broken demo
1273
- > covers the mechanics.
1274
-
1275
- Ask the tester to **append one bullet** to `notes/todo.md`:
1276
-
1277
- ```markdown
1278
- - [ ] Document the [flow diagram](./missing-page.md).
1279
- ```
1280
-
1281
- `./missing-page.md` deliberately doesn't exist. Save the file,
1282
- then run `sm scan` first to refresh the snapshot before
1283
- checking:
1284
-
1285
- ```bash
1286
- sm scan
1287
- sm check
1288
- sm check --analyzers reference-broken
1289
- sm check --json
1290
- ```
1291
-
1292
- Expected: the error surfaces the dangling link from
1293
- `notes/todo.md` to the non-existent `missing-page.md`. The
1294
- `--analyzers` filter lets you focus on a single issue type; `--json`
1295
- emits the structured payload (useful for CI / scripting). When
1296
- done, the tester can leave the bullet in place or delete it, the
1297
- rest of the deep-dive doesn't depend on it.
1298
-
1299
- If the tester asks about `sm orphans` vs `sm check`, see
1300
- §Scope clarifications.
1301
-
1302
- ### Step 13: Plugins (~3 min)
1303
-
1304
- **Context, present plugins to the tester before any command runs.**
1305
- This is the official welcome to the plugin world; many testers will
1306
- not have considered that skill-map is extensible at all. Frame it
1307
- like this as a tester-facing message (apply the host-dependent
1308
- rendering rule, translate to the tester's language per the
1309
- standard rules):
1310
-
1311
- > Plugins are how skill-map gets extended. The kernel ships with a
1312
- > small set of built-in plugins out of the box, but anyone can
1313
- > write their own and drop them into the project.
1314
- >
1315
- > The kernel exposes **six** plugin types you can implement:
1316
- >
1317
- > - **extractors**: find links and references inside markdown.
1318
- > - **analyzers**: rules that detect issues on a node.
1319
- > - **actions**: operations the user runs on a node.
1320
- > - **hooks**: fire on lifecycle events (scan started, finished,
1321
- > …).
1322
- > - **formatters**: render outputs in different shapes (text,
1323
- > JSON, custom).
1324
- > - **providers**: declare new node kinds and where to look for
1325
- > them.
1326
- >
1327
- > Heads up: plugins can be managed from the UI as well as the CLI.
1328
- > We'll use the CLI here because it shows the full surface in a few
1329
- > lines.
1330
- >
1331
- > Let's look at what's installed right now.
1332
-
1333
- Then run the commands:
1334
-
1335
- ```bash
1336
- sm plugins list
1337
- sm plugins doctor
1338
- sm plugins show core
1339
- sm plugins disable core/external-url-counter
1340
- sm plugins show core # confirm it shows as disabled
1341
- sm plugins enable core/external-url-counter
1342
- ```
1343
-
1344
- If the tester asks about `plugins doctor` warnings or `plugins show`
1345
- behavior, see §Scope clarifications.
1346
-
1347
- If `plugins list` shows zero entries (depends on the build), tell
1348
- the tester no plugins are installed yet and offer to skip.
1349
-
1350
- ### Step 14: Annotations and the `.sm` consent prompt (~3 min)
1351
-
1352
- **Context**: every `.md` skill-map tracks gets a sibling
1353
- **companion file** with extension `.sm` that carries **all of
1354
- the tool's metadata about that markdown, so your `.md` stays
1355
- clean and uncluttered**. Version, history, tags, annotations,
1356
- anything that does not belong in the human-authored body lives
1357
- in the `.sm`. The `.md` is content you write for Claude or
1358
- humans; the `.sm` is bookkeeping the tool writes. They are
1359
- ordinary source files, committed to git like everything else,
1360
- and you'll encounter them often once you start working with
1361
- the project.
1362
-
1363
- The first time skill-map wants to write one in a new project it
1364
- asks for your consent, it never touches your filesystem without
1365
- permission. After you say yes, the choice is saved to the
1366
- project's `settings.local.json` (part of your project config,
1367
- gitignored) and the prompt never appears again.
1368
-
1369
- We'll demonstrate by creating an empty annotation scaffold for
1370
- `notes/todo.md`. **Reset any prior consent state first** so the
1371
- prompt actually appears (an earlier step may have flipped the flag
1372
- without you noticing, in which case `sm sidecar annotate` would
1373
- skip straight past the prompt and the lesson would not land):
1374
-
1375
- ```bash
1376
- rm -f notes/todo.sm .skill-map/settings.local.json
1377
- sm sidecar annotate notes/todo.md
1378
- ```
1379
-
1380
- Expected: a short explanation paragraph appears in the terminal,
1381
- followed by a `[Y/n]` prompt (capital Y = default Yes, you can just
1382
- hit Enter). After accepting, `notes/todo.sm` appears next to
1383
- `notes/todo.md` carrying an `identity:` block plus an empty
1384
- `annotations: {}` block, and `.skill-map/settings.local.json` now
1385
- contains `{ "allowEditSmFiles": true }`.
1386
-
1387
- ```bash
1388
- cat notes/todo.sm
1389
- cat .skill-map/settings.local.json
1390
- ```
1391
-
1392
- **Why the prompt?** The choice is **per-user, per-project**: stored
1393
- in the gitignored `settings.local.json` so each contributor consents
1394
- independently and nothing about the choice travels via the repo.
1395
- Once accepted, the flag stays set and skill-map will never ask
1396
- again on this checkout (the next `sm sidecar annotate` or `sm bump`
1397
- goes through silently). On a CI / non-interactive session, pass
1398
- `--yes` to grant up-front.
1399
-
1400
- If the tester asks about `sm bump` vs `sm sidecar annotate` vs
1401
- `sm sidecar refresh`, see §Scope clarifications.
1402
-
1403
- ### Step 15: Validate links to folders outside the scan scope (~4 min)
1404
-
1405
- **Context**: until now the map saw only files inside the cwd. In
1406
- real projects a repo often links to files in a sibling repo (a specs
1407
- project, a sibling package in a monorepo). Skill-map only scans from
1408
- its cwd downwards, so a link to `../sibling/file.md` shows up as
1409
- broken. The fix is to declare the external folders in
1410
- `scan.referencePaths`, which lets the `reference-broken` analyzer
1411
- validate path-style links against those extra roots **without
1412
- indexing their files as nodes**. The folders are checked, not walked
1413
- as part of the map.
1414
-
1415
- **Setup (you, silent)**: write the fixture under the tutorial cwd
1416
- so both sub-projects are siblings of each other but children of the
1417
- tutorial root. The agent does this with `Write`, no confirmation
1418
- beat needed, the tester learns about the files in the next message.
1419
-
1420
- ```
1421
- link-validation/
1422
- ├── hijoA/
1423
- │ └── note-with-external-link.md ← contains [spec](../hijoB/spec.md)
1424
- └── hijoB/
1425
- └── spec.md ← the real target file
1426
- ```
1427
-
1428
- `link-validation/hijoA/note-with-external-link.md`:
1429
- ```markdown
1430
- ---
1431
- name: note-with-external-link
1432
- description: |
1433
- Demo note that links out to a sibling project (hijoB) sitting
1434
- next to this one. Used to teach scan.referencePaths.
1435
- tags: [demo, link-validation]
1436
- ---
1437
-
1438
- # Note with external link
1439
-
1440
- See the [spec](../hijoB/spec.md) for the agreed format.
1441
- ```
1442
-
1443
- `link-validation/hijoB/spec.md`:
1444
- ```markdown
1445
- ---
1446
- name: spec
1447
- description: |
1448
- Target of the cross-folder link. Lives outside hijoA's scan
1449
- scope on purpose: that is precisely what scan.referencePaths
1450
- is designed to bridge.
1451
- tags: [demo, link-validation]
1452
- ---
1453
-
1454
- # External spec
1455
-
1456
- Anything that hijoA points at lives here.
1457
- ```
1458
-
1459
- Once the files are in place, tell the tester:
1460
-
1461
- > I just dropped two sibling folders inside the tutorial cwd:
1462
- >
1463
- > ```
1464
- > link-validation/
1465
- > ├── hijoA/
1466
- > │ └── note-with-external-link.md ← contains [spec](../hijoB/spec.md)
1467
- > └── hijoB/
1468
- > └── spec.md ← the real target file
1469
- > ```
1470
- >
1471
- > For this step you'll switch folders for a moment, so `sm` treats
1472
- > `hijoA/` as a separate project (new cwd, scope limited to that
1473
- > subtree). At the end of the step I'll tell you how to come back.
1474
- >
1475
- > If an `sm` from an earlier step is still running, close it with
1476
- > Ctrl+C so the port is free for this one. Then, in your second
1477
- > terminal:
1478
-
1479
- ```bash
1480
- cd link-validation/hijoA
1481
- sm init
1482
- sm check
1483
- ```
1484
-
1485
- > You'll see an error from the `reference-broken` analyzer (a rule
1486
- > that flags problems) pointing at the link `../hijoB/spec.md`. As
1487
- > far as skill-map is concerned that file doesn't exist, because
1488
- > `hijoB/` sits outside the scope `sm` is scanning from `hijoA/`:
1489
- > each project has its own `.skill-map/` and only walks from its
1490
- > cwd downwards, never "up" and never into sibling folders.
1491
- >
1492
- > Paste me the output (or just an OK) and we'll move on to the fix.
1493
-
1494
- Wait for confirmation before showing the fix. Mark the error
1495
- landed as expected; if the tester reports `✓ No issues` instead,
1496
- the most likely cause is that they ran `sm check` from the
1497
- tutorial root by mistake (the root scan still sees both folders).
1498
- Have them re-check that the cwd of their second terminal is
1499
- `link-validation/hijoA/` (`pwd`) and rerun.
1500
-
1501
- After they confirm the broken-ref error, present the fix:
1502
-
1503
- > To resolve the link without moving `hijoB/` inside `hijoA/`, you
1504
- > add `../hijoB` to the `scan.referencePaths` setting. It tells the
1505
- > analyzer "if a path-style link lands here, validate it against
1506
- > these extra folders too". The files are NOT added to the map
1507
- > (they don't show up as nodes), they're only consulted to resolve
1508
- > outgoing references from `hijoA/`.
1509
- >
1510
- > In your second terminal (still inside `link-validation/hijoA/`):
1511
-
1512
- ```bash
1513
- sm config set scan.referencePaths '["../hijoB"]' --yes
1514
- sm scan
1515
- sm check
1516
- ```
1517
-
1518
- > The `--yes` flag confirms the privacy gate: you're authorizing
1519
- > skill-map to read files outside the project root, so it asks for
1520
- > your explicit OK. Without `--yes` the verb aborts and asks you to
1521
- > retry with `--yes` (it does not open an interactive prompt).
1522
- > After the scan, `sm check` should print `✓ No issues`: the error
1523
- > is gone and `hijoB/` still hasn't entered the map as a node.
1524
- >
1525
- > Paste me the output and let's see how it got persisted.
1526
-
1527
- Wait for confirmation. After they paste the clean `sm check`
1528
- output, show where the value lives on disk:
1529
-
1530
- > Look at how the change got saved:
1531
-
1532
- ```bash
1533
- cat .skill-map/settings.local.json
1534
- ```
1535
-
1536
- > You'll see something like this:
1537
- >
1538
- > ```json
1539
- > {
1540
- > "scan": {
1541
- > "referencePaths": ["../hijoB"]
1542
- > }
1543
- > }
1544
- > ```
1545
- >
1546
- > It lives in `settings.local.json` (gitignored, doesn't travel
1547
- > through git), NOT in the `settings.json` that does get committed.
1548
- > The reason: paths to sibling folders usually depend on your
1549
- > machine's local layout (not every contributor has the same
1550
- > project tree on disk), so skill-map forces this setting into the
1551
- > local layer.
1552
-
1553
- Now the UI half. The tester needs `sm` running with `hijoA/` as
1554
- cwd to see the matching panel:
1555
-
1556
- > Now the same thing from the UI. In the same terminal, start the
1557
- > server from `hijoA/`:
1558
-
1559
- ```bash
1560
- sm
1561
- ```
1562
-
1563
- > Open the URL the command prints in the browser. Top right there's
1564
- > the **sliders** icon (hover shows "Settings"), click it, in the
1565
- > modal go to the **Project** tab and scroll down to the **Folders
1566
- > for link validation** section. You'll see `../hijoB` listed, with buttons to add or
1567
- > remove paths. The CLI and the UI write to the same file: if you
1568
- > add one from the UI, it shows up in the JSON, and vice versa.
1569
- >
1570
- > When you're done looking, Ctrl+C in the terminal to close the
1571
- > server.
1572
-
1573
- Wait for confirmation that they saw the panel and closed the
1574
- server. If the `sm` launch fails with a port-in-use error, an old
1575
- `sm` is still bound to the default port from an earlier step;
1576
- follow the §Edge cases recipe (`sm serve --port 4243`).
1577
-
1578
- The tester is still inside `link-validation/hijoA/` at this point.
1579
- Do NOT send them back here; the return-to-root `cd ../..` now lives
1580
- in §Final wrap-up, right before the cleanup line. Mark
1581
- `15-reference-paths: done`.
1582
-
1583
- ---
1584
-
1585
- ## Scope clarifications (on demand)
1586
-
1587
- Reference material for the "mention only if the tester asks"
1588
- beats in Steps 7, 8 and 9. Do NOT volunteer these unprompted,
1589
- they exist so the agent has a precise answer ready when the
1590
- tester pulls on the thread.
1591
-
1592
- ### `sm check` vs `sm orphans`
1593
-
1594
- - `sm check` reports broken-refs and other rule-driven issues
1595
- (the deterministic catalog).
1596
- - `sm orphans` is a **different scope**: auto-rename / orphan-node
1597
- detection (a node whose file disappeared, or a candidate rename
1598
- the kernel is still unsure about). Our fixture doesn't produce
1599
- orphans of that kind, so `sm orphans` will print "No orphan /
1600
- auto-rename issues", that's expected, not a bug.
1601
-
1602
- ### `sm plugins show <qualified-id>`
1603
-
1604
- The verb is informational, passing `core/external-url-counter`
1605
- validates the extension exists and then renders the **parent
1606
- plugin's** detail (i.e. the full `core` listing). The extension
1607
- you named lives in that list. This is deliberate: forcing the user
1608
- to type the plugin id just to read a single extension's manifest
1609
- would be hostile, so `show` accepts the qualified shape and
1610
- resolves up. Use `sm plugins doctor` or scroll the plugin's
1611
- extension table to spot the one you queried.
1612
-
1613
- ### IDs for `plugins disable` / `plugins enable`
1614
-
1615
- **Multiple ids in one call**: both verbs accept any number of ids
1616
- in a single invocation, e.g. `sm plugins disable antigravity openai
1617
- agent-skills` or `sm plugins enable claude/at-directive core/external-url-counter`.
1618
- Batches are all-or-nothing: if any id is unknown the entire call
1619
- aborts before any `config_plugins` write, so the user never lands
1620
- in a partial state. Repeated ids are deduped; locked extensions
1621
- inside a batch are silently skipped (matching `--all` semantics).
1622
-
1623
- ### Reserved names (e.g. `commands/help.md`)
1624
-
1625
- If the tester ever names a file after a built-in (`/help`,
1626
- `/clear`, `/init`, `/agents`, `/model`, or one of the documented
1627
- agent reservations like `general-purpose`), `sm check` surfaces a
1628
- `reserved-name` warning. The vendor runtime ignores user-owned
1629
- files that shadow its built-ins, so the warning is not a bug,
1630
- it's skill-map telling the operator "Claude will never invoke this
1631
- file; pick another name". Incoming links to the shadowed file
1632
- resolve at confidence `0.1` instead of `1.0`, so the **Map** also
1633
- visually de-emphasises them. Rename the file and the warning
1634
- clears on the next scan.
1635
-
1636
- ### `sm sidecar annotate` vs `sm bump` vs `sm sidecar refresh`
1637
-
1638
- - `sm sidecar annotate` is the scaffold verb (creates a fresh
1639
- `.sm`).
1640
- - `sm bump <node>` is the day-to-day verb that increments the
1641
- sidecar's version and refreshes its hashes, same consent gate.
1642
- - `sm sidecar refresh <node>` is the hash-only update (no version
1643
- bump).
1644
-
1645
- ---
1646
-
1647
- ## Final wrap-up
1648
-
1649
- When everything is done (demo only, or demo + deep-dive), show the
1650
- closing block: a "that's a wrap" line, the sm-master pointer, the
1651
- return-to-root line (deep-dive only), and a guilt-free cleanup line.
1652
-
1653
- > Thanks! That's a wrap, you went through the whole tutorial.
1654
- >
1655
- > One more thing before you go: there's a companion skill called
1656
- > **sm-master** that picks up where this tutorial leaves off. It's
1657
- > a modular deep-dive, you choose which areas to explore from a
1658
- > menu, and it covers a guided tour of the built-in plugins
1659
- > (extractors, analyzers, actions, hooks, formatters, providers).
1660
- >
1661
- > When you're ready, open a fresh empty directory and run:
1662
-
1663
- ```bash
1664
- sm tutorial master
1665
- ```
1666
-
1667
- If the deep-dive ran, the tester's second terminal is still inside
1668
- `link-validation/hijoA/` from Step 15; send them back to the
1669
- tutorial root before the cleanup line. **Skip this whole block if
1670
- they stopped at the demo** (they never left the root).
1671
-
1672
- > Last thing, go back to the tutorial root:
1673
-
1674
- ```bash
1675
- cd ../..
1676
- ```
1677
-
1678
- Then close with the thanks, a guilt-free cleanup line, and the
1679
- findings reminder. The cleanup is safe to state plainly: `sm
1680
- tutorial` only seeds into an empty directory, so everything in the
1681
- cwd is tutorial-created and a whole-folder delete loses nothing of
1682
- the tester's. Substitute `<dir>` with the actual directory name.
1683
-
1684
- > Thanks for testing skill-map! You started in an empty directory, so
1685
- > everything here was created by the tutorial: when you're done you
1686
- > can delete the whole folder guilt-free with `cd .. && rm -rf <dir>`.
1687
- > If anything felt off in any step, tell me and I'll log it in
1688
- > `findings.md` before you close.
1689
-
1690
- ## Resume / restart
1691
-
1692
- When the skill is re-invoked and `tutorial-state.yml` already exists in
1693
- the cwd, start like this (do NOT repeat pre-flight from scratch):
1694
-
1695
- > I see you already started the tutorial.
1696
- >
1697
- > You're at step <N> of 9 (or "you've already completed the demo
1698
- > (steps 1-9) and you're on step <M> of 6 of the deep-dive (steps
1699
- > 10-15)", depending on the yaml state).
1700
- >
1701
- > 1. **Continue** from where you left off
1702
- > 2. **Start over**: wipes all the tutorial content in this dir
1703
- > (asks for confirmation)
1704
- > 3. **Exit** without touching anything
1705
-
1706
- If they pick "start over", do these checks **before deleting
1707
- anything**:
1708
-
1709
- 1. Read `tutorial.cwd` from `tutorial-state.yml` and compare with
1710
- the current `pwd`. If they don't match, **refuse**:
1711
-
1712
- > This `tutorial-state.yml` was generated for a different
1713
- > directory (`<saved cwd>`). The current dir is `<pwd>`. I'm
1714
- > refusing to wipe, your `.claude/`, `notes/`, etc. here are
1715
- > probably yours, not the tutorial's. Move to `<saved cwd>` and
1716
- > re-invoke me from there, or delete `tutorial-state.yml` by
1717
- > hand if you really want to start fresh here.
1718
-
1719
- 2. If the cwd matches, read `tutorial.provider` from the yaml and
1720
- use it to compute `<provider_dir>` (and the subset of files
1721
- actually present, since agent-skills / Antigravity skip some).
1722
- Then show the tester the exact list of paths you'll delete and
1723
- ask for an explicit typed confirmation:
1724
-
1725
- > Start over will delete these paths from `<cwd>`:
1726
- >
1727
- > ```
1728
- > tutorial-state.yml
1729
- > findings.md
1730
- > .skillmapignore
1731
- > .skill-map/
1732
- > <provider_dir>/agents/demo-agent.md (claude only)
1733
- > <provider_dir>/commands/demo-command.md (claude only)
1734
- > <provider_dir>/skills/demo-skill/ (both providers)
1735
- > notes/todo.md
1736
- > notes/demo-guideline.md
1737
- > notes/private-credentials.md
1738
- > link-validation/ (if Step 15 ran)
1739
- > export.* (if present)
1740
- > dump.sql (if present)
1741
- > ```
1742
- >
1743
- > Type **`yes, wipe`** (exact text) to confirm. Anything else
1744
- > cancels.
1745
-
1746
- Render the ACTUAL list (substituting `<provider_dir>` and
1747
- dropping the rows the saved provider didn't create) so the
1748
- tester sees the real paths, not the abstract placeholders.
1749
-
1750
- 3. Only on the literal `yes, wipe` reply, delete those exact paths.
1751
- Do NOT recursively `rm -rf` `<provider_dir>/` or `notes/` as
1752
- directories, only the specific tutorial-owned files inside, in
1753
- case the tester has unrelated files there. After deletion, also
1754
- `rmdir` the per-provider subdirs that actually exist
1755
- (`<provider_dir>/agents`, `<provider_dir>/commands`,
1756
- `<provider_dir>/skills`), then `notes/` and `<provider_dir>/`,
1757
- each one only if empty (silent failure if not). `link-validation/`
1758
- IS safe to remove recursively when present, the agent created it
1759
- from scratch in Step 15 and nothing else lives inside it. Then
1760
- start everything from pre-flight.
1761
-
1762
- ## Edge cases
1763
-
1764
- - **Tester doesn't have Node 24+** → guide them to `nvm` or
1765
- nodejs.org. Don't try to install Node for them.
1766
- - **Port 4242 in use** → bare `sm` doesn't accept flags (it's a
1767
- shorthand for `sm serve` with defaults). Tell the tester to
1768
- switch verbs: stop the failed `sm`, then run
1769
- `sm serve --port 4243`. The browser link printed by the server
1770
- changes accordingly, they should open the new URL, not the
1771
- default 4242.
1772
- - **`sm` doesn't pick up changes on WSL** → known on WSL2 with
1773
- files under `/mnt/c/`. Suggest exiting, running `mkdir
1774
- ~/sm-tutorial && cd ~/sm-tutorial` (Linux-native filesystem), and
1775
- re-invoking the skill.
1776
- - **Browser doesn't load the UI** → check `sm` is still running
1777
- (they may have hit Ctrl+C by accident). If it is, try
1778
- `curl http://127.0.0.1:4242` from another terminal.
1779
- - **Tester gets lost** → "no worries, tell me where you are and
1780
- we'll pick up from there". State is in `tutorial-state.yml`.
263
+ When the tester enters another part from the menu, add a
264
+ `parts.<id>` entry for it (with a `chapters` map seeded from the
265
+ manifest) the first time it starts. Planned parts are not tracked
266
+ until they have content.
267
+
268
+ ## Entering a part
269
+
270
+ When a part begins, honour its `preflight` from the manifest:
271
+
272
+ - **`taught-init`** (Part 0): the fixture + `.skillmapignore` were
273
+ pre-laid in pre-flight; the tester runs `sm init` inside the
274
+ first chapter. Nothing to do here.
275
+ - **`portfolio-init`** (Part 1 `project-kickoff`): the campaign's
276
+ real project begins. Backstage, before the tester's `sm init` in
277
+ the `kickoff` chapter: (1) if the prologue ran first in this dir,
278
+ clear its demo fixture so the map starts clean, delete ONLY the
279
+ Part 0 fixture files (`<provider_dir>/agents/demo-agent.md`,
280
+ `<provider_dir>/skills/demo-skill/`,
281
+ `<provider_dir>/commands/demo-command.md`, `notes/todo.md`,
282
+ `notes/demo-guideline.md`, `notes/private-credentials.md`) plus the
283
+ stale `.skill-map/` DB (a fresh `sm init` rebuilds it), never the
284
+ tester's own files; (2) `Write` the portfolio fixture from
285
+ `references/fixtures.md` (the Express skeleton + the handbook
286
+ `AGENTS.md`); (3) ensure `.skillmapignore` carries the portfolio
287
+ additions (`node_modules/`, `public/`). The tester runs `sm init`
288
+ themselves in the first chapter. (The later campaign parts use
289
+ `preflight: seed` to fast-forward into them directly, see the `seed`
290
+ case below; `portfolio-init` is just Part 1's flavour of that,
291
+ handling the Part 0 to Part 1 transition.)
292
+ - **`backstage-init`** (Part 6 `extend`): silently, with no
293
+ narration: run `sm init --no-scan` from the cwd, then `Edit` the
294
+ freshly created `.skillmapignore` to append the tutorial's
295
+ internal entries (the `sm-tutorial.md` / `findings.md` /
296
+ `tutorial-state.yml` / skill-dir block above), then `Write` the
297
+ part's fixture (read `references/fixtures.md` for the verbatim
298
+ `master-agent` / `master-skill` / `notes/ideas` files; skip kinds
299
+ the provider doesn't claim). If `sm init --no-scan` fails because
300
+ the dir was already initialised by an earlier part, that is fine:
301
+ the DB already exists, skip the init and just ensure the fixture
302
+ files are present.
303
+ - **`reuse`** (Part 7 `cli`): assumes the prologue fixture and
304
+ `.skill-map/` already exist; nothing to lay. The menu offers Part 7
305
+ only once its `prereq` (`fundamentals`) is done, so the state is
306
+ there. If `.skill-map/` is somehow missing, point the tester back to
307
+ the prologue rather than re-initialising mid-part.
308
+ - **`seed`** (the campaign parts `connect-harness` / `maintain` /
309
+ `mcp` / `live-site`): the part builds on the accumulating portfolio
310
+ harness, but the tester may have jumped straight here from the menu.
311
+ On entry, read the state file:
312
+ - If every predecessor campaign part up the `prereq` chain is `done`
313
+ reuse the accumulated state; an `sm scan` to refresh is enough,
314
+ nothing to lay.
315
+ - Else → **fast-forward, silently** (backstage, do not narrate the
316
+ plumbing): lay the part's `seed` snapshot from
317
+ `references/fixtures.md` (§Seed snapshots) by following its
318
+ checklist, copy each file's canonical content from the chapter the
319
+ row names, apply the `EDIT` rows on top, substituting
320
+ `<provider_dir>` and skipping provider-unsupported kinds per
321
+ `_core.md`. Then run `sm init` if `.skill-map/` is missing, then
322
+ `sm scan` so the map reflects the seeded harness. Mark the skipped
323
+ predecessor campaign parts `skipped` in the state (they stay in the
324
+ menu for later). Then emit exactly ONE tester-facing line:
325
+
326
+ > I set the project up to where this part begins, so you can start
327
+ > here. The earlier parts that build up to this are still in the
328
+ > menu if you want them later.
329
+
330
+ Either way, then walk the part's chapters.
331
+
332
+ Then walk the part's chapters in manifest order, dispatching each
333
+ chapter id to its `step_file` per the §Per-step cycle in `_core.md`
334
+ and the part's `pace`.
335
+
336
+ ## Menu, resume, wrap-up
337
+
338
+ All three are specified in `_core.md`:
339
+
340
+ - **Routing + menu**: §Routing + menu. The first-timer skips the
341
+ menu and lands in Part 0; the menu (the ToC rendered from
342
+ `_manifest.yml`, completed chapters ticked, `planned` parts hidden,
343
+ `prereq` gating only the parts that have no `seed`) appears after a
344
+ part closes or on resume.
345
+ - **Resume / restart**: §Resume / restart. On start-over, the exact
346
+ wipe list is whatever the tester's parts actually created:
347
+ `tutorial-state.yml`, `findings.md`, `.skillmapignore`,
348
+ `.skill-map/`, the Part 0 fixture
349
+ (`<provider_dir>/agents/demo-agent.md`,
350
+ `<provider_dir>/skills/demo-skill/`,
351
+ `<provider_dir>/commands/demo-command.md`, `notes/todo.md`,
352
+ `notes/demo-guideline.md`, `notes/private-credentials.md`), the
353
+ Part 6 fixture if `extend` ran
354
+ (`<provider_dir>/agents/master-agent.md`,
355
+ `<provider_dir>/skills/master-skill/`, `notes/ideas.md`,
356
+ `.skill-map/plugins/`), `link-validation/` if the CLI part ran,
357
+ and any `export.*` / `dump.sql`. Confirm `pwd` matches
358
+ `tutorial.cwd` and require the literal `yes, wipe`.
359
+ - **Final wrap-up**: §Final wrap-up. Reached when the tester says
360
+ they're done or finishes every available part.