@skill-map/cli 0.53.0 → 0.53.1

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.
@@ -148,25 +148,28 @@ Apply §Provider detection from `_core.md`. Persist the result into
148
148
  > Got the second terminal open and anchored to the folder? Confirm
149
149
  > before we move on.
150
150
 
151
- ### 5. Lay the Part 0 fixture and route
151
+ ### 5. Write the universal files and show the menu
152
152
 
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:
153
+ Pre-flight does NOT pre-lay any part's fixture and does NOT auto-enter
154
+ a part. It writes only the two files every part needs, then routes to
155
+ the menu:
157
156
 
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
157
  - `findings.md` (block below).
163
- - `tutorial-state.yml` (template below).
158
+ - `tutorial-state.yml` (template below; it starts with `parts: {}`,
159
+ empty, a part's entry is added the first time the tester picks it).
164
160
 
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.
161
+ Then **route** per §Routing + menu in `_core.md`: render the **start
162
+ menu** (numbered, Part 0 the prologue as option 1, the recommended
163
+ first pick). The tester picks a part by number; that part's own
164
+ `preflight` (see §Entering a part) lays its fixture when it begins.
165
+ Part 0's demo fixture (the `demo-agent` + the demo `.skillmapignore`,
166
+ blocks below) is laid by its `taught-init` entry, not here.
168
167
 
169
- ## Fixture blocks (Part 0 / `taught-init`)
168
+ ## Fixture and state templates
169
+
170
+ The `findings.md` and `tutorial-state.yml` here are universal (written
171
+ in pre-flight); the `demo-agent.md` + the demo `.skillmapignore` are
172
+ Part 0's fixture (laid by its `taught-init` entry).
170
173
 
171
174
  `<provider_dir>/agents/demo-agent.md`:
172
175
  ```markdown
@@ -245,33 +248,39 @@ tutorial:
245
248
  provider: "<claude | agent-skills | antigravity>"
246
249
  tester:
247
250
  level: 2
251
+ parts: {} # filled in as the tester picks parts from the menu
252
+ findings_file: "./findings.md"
253
+ ```
254
+
255
+ When the tester picks a part from the menu, add its `parts.<id>`
256
+ entry the first time it starts, seeded from the manifest, e.g.:
257
+
258
+ ```yaml
248
259
  parts:
249
260
  fundamentals:
250
- status: "in_progress" # not_started | in_progress | done | declined
261
+ status: "in_progress" # not_started | in_progress | done | declined | skipped
251
262
  chapters:
252
263
  init: { status: "pending" } # pending | done | failed | skipped
253
264
  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" }
260
- findings_file: "./findings.md"
265
+ # one row per chapter in the part's manifest entry
261
266
  ```
262
267
 
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.
268
+ Planned parts are not tracked until they have content. Parts the
269
+ `seed` mechanism fast-forwards past are recorded with `status:
270
+ "skipped"`.
267
271
 
268
272
  ## Entering a part
269
273
 
270
274
  When a part begins, honour its `preflight` from the manifest:
271
275
 
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.
276
+ - **`taught-init`** (Part 0): silently, before the tester's `sm init`
277
+ in the `init` chapter, `Write` the demo fixture (the
278
+ `<provider_dir>/agents/demo-agent.md` boot node + the demo
279
+ `.skillmapignore`, both in the §Fixture blocks above), substituting
280
+ `<provider_dir>` per detection. Write `.skillmapignore` BEFORE the
281
+ tester runs `sm init` so the first scan never sees the tutorial's
282
+ own files (`sm init` only writes that file when absent). The tester
283
+ runs `sm init` themselves in the first chapter.
275
284
  - **`portfolio-init`** (Part 1 `project-kickoff`): the campaign's
276
285
  real project begins. Backstage, before the tester's `sm init` in
277
286
  the `kickoff` chapter: (1) if the prologue ran first in this dir,
@@ -337,11 +346,13 @@ and the part's `pace`.
337
346
 
338
347
  All three are specified in `_core.md`:
339
348
 
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.
349
+ - **Routing + menu**: §Routing + menu. The session always starts at
350
+ the **numbered start menu** (Part 0 is option 1, the recommended
351
+ first pick); the menu (the ToC from `_manifest.yml`, numbered,
352
+ completed parts ticked, `planned` parts hidden, `prereq` gating only
353
+ the parts that have no `seed`) is the entry point on the first
354
+ invocation and after every part closes / on resume. Render it with
355
+ the format in `_core.md` §Menu format.
345
356
  - **Resume / restart**: §Resume / restart. On start-over, the exact
346
357
  wipe list is whatever the tester's parts actually created:
347
358
  `tutorial-state.yml`, `findings.md`, `.skillmapignore`,
@@ -38,8 +38,11 @@ loanwords embedded in Spanish prose:
38
38
  - `connector` / `edge` → `conector` (**NEVER** `arista`, even
39
39
  though it is the common graph translation; skill-map's house
40
40
  word is `conector` everywhere).
41
- - `watcher` `observador` (or rephrase: "skill-map sigue tus
42
- cambios").
41
+ - `watcher` and `browser` stay **English**, do NOT translate them to
42
+ `observador` / `navegador`. They are words the tester reads in
43
+ skill-map's own UI and docs, keep them recognisable. If a bare
44
+ English noun reads oddly mid-sentence, rephrase ("skill-map sigue
45
+ tus cambios" instead of forcing "el watcher detecta...").
43
46
  - `scan` (verb) → `escanear`; `scan` (noun) → `escaneo`.
44
47
  - `node` → `nodo`; `link` → `enlace` or `vínculo`; `fixture` →
45
48
  `set de prueba`; `pre-flight` → `preparación inicial`;
@@ -49,10 +52,9 @@ loanwords embedded in Spanish prose:
49
52
  …), CLI verbs (`sm init`, `sm watch`), and code identifiers stay
50
53
  English, that's the public surface, not jargon.
51
54
 
52
- Anti-pattern (do NOT emit): "aparecen los otros tres kinds", "el
53
- watcher detectó el cambio", "vamos a hacer un scan ahora". Correct:
54
- "aparecen los otros tres tipos", "skill-map detectó el cambio",
55
- "vamos a escanear ahora". These translations apply to **chapter
55
+ Anti-pattern (do NOT emit): "aparecen los otros tres kinds", "vamos a
56
+ hacer un scan ahora". Correct: "aparecen los otros tres tipos", "vamos
57
+ a escanear ahora" (and `watcher` / `browser` stay as-is in English). These translations apply to **chapter
56
58
  titles** too: a `title` like `"First scan of the fixture"` is
57
59
  announced as `"Primer escaneo del set de prueba"`. Never emit a
58
60
  chapter title (or any tester-facing prose) in English while the
@@ -175,9 +177,10 @@ first kind quoted, the second kind never.
175
177
  the output or replies "OK" / "done". Only then advance.
176
178
  4. **Persist progress after every chapter.** Update the state file
177
179
  (`parts.<id>.chapters.<id>.status` = `done` / `failed` /
178
- `skipped` + a timestamp). Mirror the same status on the harness
179
- task via `TaskUpdate`; the harness list is the in-session view,
180
- the state file is the cross-session source of truth.
180
+ `skipped` + a timestamp). The state file is the ONLY progress
181
+ tracker. Do NOT create harness tasks (`TaskCreate` / `TaskUpdate`)
182
+ for tutorial progress, they clutter the tester's task list and add
183
+ nothing the state file does not already hold.
181
184
  5. **If the tester reports anything weird**, offer to record it in
182
185
  `findings.md` (in the cwd). Reactive, not proactive: only offer
183
186
  the findings log when the tester flags something, asks "is that
@@ -242,46 +245,85 @@ today. The detection wiring is here so mirrored skills at
242
245
 
243
246
  ## Per-step cycle (inside a chapter)
244
247
 
245
- When you enter a part, call `TaskCreate` once with one task per
246
- chapter in that part's `chapters` list. Update each to
247
- `in_progress` when its block begins and `completed` when it ends.
248
+ A **chapter is the unit of confirmation**. Walk it as ONE beat:
249
+ announce it, do the preparation, hand the tester everything they need
250
+ to do, and ask for confirmation **exactly once, at the end**. Do NOT
251
+ pepper a chapter with several "tell me when…" / "¿viste X?" prompts,
252
+ bundle the actions into a single instruction ("hacé A, después B, y
253
+ avisame cuando el mapa muestre …"). Split a chapter's confirmation
254
+ ONLY when a later action genuinely cannot start until the tester
255
+ finished an earlier one (e.g. they must have the browser open before
256
+ they can watch a node change), and even then keep it to the minimum.
257
+ Never call `TaskCreate` / `TaskUpdate` (Inviolable rule #4).
248
258
 
249
- For every step in a chapter:
259
+ For every chapter:
250
260
 
251
261
  1. **Announcement**: "Capítulo N: `<title>`. ~M min." then a blank
252
262
  line, then (optionally) one sentence of context on its own
253
263
  paragraph. `N` is the 1-based index of the chapter inside its
254
- part; it resets per part. The context paragraph renders ONLY
255
- when the source has a `**Context**:` field; if omitted, announce
256
- the title alone. The title comes from the chapter's `title` in
264
+ part; it resets per part. The context paragraph renders ONLY when
265
+ the source has a `**Context**:` field; if omitted, announce the
266
+ title alone. The title comes from the chapter's `title` in
257
267
  `_manifest.yml` (translated per §Tone), not the internal id.
258
- 2. **Preparation** (if applicable): create or modify files, show
259
- the path and a short preview.
260
- 3. **Commands to run**: a ` ```bash ` block.
261
- 4. **Pause**: "Run that and paste me the output (or say OK)."
262
- 5. **Verification**: read their reply. If something errored,
263
- suggest a fix before advancing. If fine, mark `done`. Honour the
264
- part's `pace`: `auto-advance` moves straight into the next
265
- chapter's Announcement; `per-step` asks "¿seguimos?" first.
268
+ 2. **Preparation** (if applicable): create or modify the fixture
269
+ files the chapter calls for (silently, per §Silence).
270
+ 3. **The tester's part**: the command block(s) and instructions,
271
+ bundled into one flow, closed by the single confirmation.
272
+ 4. **Verification**: read their reply. If something errored, suggest
273
+ a fix before advancing. If fine, mark `done`. Honour the part's
274
+ `pace`: `auto-advance` moves straight into the next chapter's
275
+ Announcement; `per-step` asks "¿seguimos?" first.
266
276
 
267
277
  ## Routing + menu (orchestrator)
268
278
 
269
- - **No state (first-timer)**: enter the first `spine` part of
270
- lowest `order` (Part 0) at its chapter 1, **with no ToC** (the
271
- onboarding flow is a single continuous path; never expose the
272
- part split).
273
- - **After a part closes, or state exists**: render the **ToC menu**
274
- from `_manifest.yml`, parts in `order` with their chapters,
275
- completed chapters prefixed `✓ `. A part with a `seed` (the campaign
276
- parts) is **always shown**, even out of order: its `preflight: seed`
277
- fast-forwards the project into it (SKILL.md §Entering a part). A part
278
- with a `prereq` but NO `seed` (Part 7 `cli`) is shown only once its
279
- `prereq` is `done`. Parts with `status: planned` (no `step_file`) are
280
- NOT shown. Let the tester pick; walk that part; return to the menu
281
- when it ends.
282
- - **Adding content** is data-only: a new chapter in a part (or a
283
- new `part-<id>.md` + a manifest row). Keep chapter-id prefixes
284
- matching the file name so dispatch stays mechanical.
279
+ - **Always start at the menu.** On the first invocation (no state)
280
+ AND after any part closes / on resume, render the **start menu**:
281
+ the book ToC, numbered, and let the tester pick a part by number.
282
+ Part 0 (the prologue) is option 1, the recommended starting point,
283
+ so a brand-new tester just types `1`. Do NOT auto-enter a part; the
284
+ menu is the entry point every time. On later renders, prefix any
285
+ completed part's title with `✓ `.
286
+ - **Which parts to list**: parts in `order`, `status: active` only
287
+ (`planned` parts are hidden). A part with a `seed` (the campaign
288
+ parts) is always shown, even out of order, its `preflight: seed`
289
+ fast-forwards the project into it (SKILL.md §Entering a part). A
290
+ part with a `prereq` but NO `seed` (Part 7 `cli`) is shown only once
291
+ its `prereq` is `done`.
292
+ - **After the tester picks**: walk that part; when it ends, return to
293
+ this menu.
294
+ - **Adding content** is data-only: a new chapter in a part (or a new
295
+ `part-<id>.md` + a manifest row). Keep chapter-id prefixes matching
296
+ the file name so dispatch stays mechanical.
297
+
298
+ ### Menu format
299
+
300
+ Render the menu numbered and formatted (NOT a bare list), translated
301
+ to the tester's language. A one-line intro, then per part a **bold
302
+ numbered title line** (number + title + `(~M min)`) as plain prose,
303
+ immediately followed by a single-level `> ` blockquote one-line
304
+ description (what the part covers, derived from its title + chapters).
305
+ NO blank line between a title and its description; ONE blank line
306
+ between parts; NO outer blockquote around the whole menu. Close with a
307
+ short "¿Cuál?" / "Which one?" on its own line. Sample (Claude variant,
308
+ fill the parts and durations from `_manifest.yml`):
309
+
310
+ ```
311
+ ¿Por dónde querés arrancar? Podés volver al menú cuando termines cada parte.
312
+
313
+ **1. El mapa en vivo** (~12 min)
314
+ > El prólogo: corrés `sm`, abrís el browser y ves el mapa actualizarse en vivo mientras editás `.md`. Si es tu primera vez, empezá por acá.
315
+
316
+ **2. El proyecto desde cero** (~8 min)
317
+ > Arrancás un proyecto real (un portfolio) y su harness `.claude/`.
318
+
319
+ ¿Cuál?
320
+ ```
321
+
322
+ This menu is the ONE exception to the "wrap tester-facing prose in a
323
+ single blockquote" rule: the intro, the bold titles and the trailing
324
+ "¿Cuál?" are plain prose; only the description lines carry `> `. On
325
+ non-Claude hosts the `> ` collapses to plain prose, indent each
326
+ description two spaces so it stays subordinate to its title.
285
327
 
286
328
  ## Resume / restart
287
329
 
@@ -13,42 +13,20 @@ ls -la .skill-map/
13
13
 
14
14
  Expected: `.skill-map/skill-map.db` appears (plus config files). The initial scan reports a small node / link / issue count from the demo-agent fixture, NOT 14+ phantom issues from the tutorial's own prose: pre-flight already wrote `.skillmapignore` with the right exclusions in place, so `sm init` leaves that file alone (it only writes when absent) and the scan never sees `sm-tutorial.md` / `findings.md` / `tutorial-state.yml`.
15
15
 
16
- Before launching the server, ask the tester to set up a **side-by-side view** so they can watch the magic happen without alt-tabbing every step. Tell the tester:
16
+ Before launching the server, ask the tester to set up a **side-by-side view** so they can watch the magic happen without alt-tabbing every step, then launch the server and open the link it prints. Don't hardcode the URL here, the verb itself is the source of truth (it logs the bound `http://host:port` after listen). Tell the tester:
17
17
 
18
- > Now arrange your screen so the **browser** (where the **Map**
19
- > updates in real time) and **this chat** are both visible at once
20
- >, typical layout is browser on the left half, chat on the right
18
+ > First, arrange your screen so the **browser** (where the **Map**
19
+ > updates in real time) and **this chat** are both visible at once,
20
+ > typical layout is browser on the left half, chat on the right
21
21
  > (or any split that lets you see both). The terminal running
22
22
  > `sm` can stay off to the side; it just prints scan progress
23
23
  > lines and you don't need to read them.
24
24
  >
25
- > Tell me when you're set up and we start.
26
-
27
- Wait for confirmation before moving on. Once they're ready, prompt them to launch the server and open the link it prints, without hardcoding the URL here, since the verb itself is the source of truth (it logs the bound `http://host:port` after listen):
28
-
29
- > Run `sm`. After a couple of seconds it will print a line with the
30
- > URL where the UI is listening, copy that link and open it in the
31
- > browser you just arranged. Tell me when you see the page load.
32
-
33
- Wait for confirmation that the page loaded. Then tell the tester:
34
-
35
- > You'll see exactly **one node** in the **Map**: `demo-agent`
36
- > (kind `agent`). That's our starting point.
37
- >
38
- > The workspace opens **map-first**: the canvas fills the screen and
39
- > the **Files** panel sits collapsed against the left edge. Click the
40
- > expand handle on the far left (the `>` arrow, its tooltip reads
41
- > "Expand files panel") to open it.
42
- >
43
- > Now walk the two views before we go on:
44
- > 1. **Map**: the single agent node on the canvas.
45
- > 2. **Files**: one row, with path / kind / metadata.
25
+ > Then run `sm`. After a couple of seconds it will print a line
26
+ > with the URL where the UI is listening, copy that link and open
27
+ > it in the browser you just arranged.
46
28
  >
47
- > Then, back in **Map**, click the node: the **Inspector** panel
48
- > slides out with its frontmatter (the YAML block at the top of
49
- > every `.md`, between the two `---` lines) and its links.
50
- >
51
- > Did the node show up?
29
+ > Tell me when the page is open showing one node, `demo-agent`.
52
30
 
53
31
  Wait for confirmation. Mark `init`: done.
54
32
 
@@ -182,11 +160,6 @@ Tell the tester:
182
160
  > the field you'll edit next, so leave the card open and the
183
161
  > change will be obvious.
184
162
  >
185
- > ⚠ Heads-up: the inspector header shows a couple of action
186
- > buttons (**Bump version**, **Refresh body**). **Don't click
187
- > them yet**, they write files to your project and we cover that
188
- > flow deliberately in the annotations chapter. For now, just look.
189
- >
190
163
  > Now open `.claude/agents/demo-agent.md` in your editor of
191
164
  > choice. In the **frontmatter** at the top of the file, change
192
165
  > the `description:` field to any text you want, the actual
@@ -236,18 +209,17 @@ Tell the tester:
236
209
  > - `notes/todo → demo-guideline` (kind: `references`)
237
210
  >
238
211
  > The kind comes from the syntax in the bullet: an `@handle` is
239
- > always a mention, a `/command` is always an invoke, a markdown
240
- > link is always a reference. Four arrows, three kinds, three
241
- > colours on the canvas (the two `invokes` share a colour, as you
242
- > would expect).
212
+ > always a mention, a `/skill` or `/command` is always an invoke, a
213
+ > markdown link is always a reference. Four arrows, three kinds,
214
+ > three colours on the canvas (the two `invokes` share a colour, as
215
+ > you would expect).
243
216
  >
244
217
  > Notice too that the connectors have different transparency.
245
218
  > Skill-map estimates how sure it is of each connection: a
246
219
  > `[text](file.md)` that points at a real file (confidence 1.00,
247
- > now that the target exists) looks solid, while an `@handle` that
248
- > resolves to no node sits at 0.5 (ambiguous) and looks
249
- > translucent. The opacity tells that story at a glance: the more
250
- > solid the arrow, the more reliable the inference.
220
+ > now that the target exists) looks solid. The opacity tells that
221
+ > story at a glance: the more solid the arrow, the more reliable
222
+ > the inference.
251
223
  >
252
224
  > Confirm when you see it. If a connector is missing, refresh the
253
225
  > browser and let me know.
@@ -258,25 +230,25 @@ If a connector is missing, do not advance, the next chapter inspects the same hu
258
230
 
259
231
  The connector opacity tells the confidence story at a glance; the exact per-link breakdown lives in the Inspector. Open it on the hub so the tester registers the surface before the `edit-link` chapter changes topology.
260
232
 
261
- > 🆕 Open the Inspector for `notes/todo` (click the node on the
262
- > map). Scroll down to the **Linked nodes** panel: it has two
263
- > sections, **Outgoing** and **Incoming**. `notes/todo` lists 4
264
- > links under Outgoing (it's the hub pointing at four nodes) and 0
265
- > under Incoming; if you open the Inspector for any of the four
266
- > targeted nodes, you'll see 1 under Incoming. Each row shows the
267
- > link kind (`mentions`, `invokes`, `references`) and a badge with
268
- > its confidence: the numeric value (`1.00`, `0.50`, …).
233
+ > 🆕 Open the Inspector for **Demo TODO list** (click the node on
234
+ > the map). **Expand** the **Connections** section (it's collapsed
235
+ > by default): it has two sections, **Outgoing** and **Incoming**.
236
+ > Demo TODO list lists 4 links under Outgoing (it's the hub pointing
237
+ > at four nodes) and 0 under Incoming; if you open the Inspector for
238
+ > any of the four targeted nodes, you'll see 1 under Incoming. Each
239
+ > row shows the link kind (`mentions`, `invokes`, `references`) and
240
+ > a badge with its confidence: the numeric value (`1.00`, `0.50`,
241
+ > …).
242
+ >
243
+ > 💡 Tip: if all these changes left the nodes crowded together, the
244
+ > map toolbar has a **Re-arrange layout** button (tooltip "Re-arrange
245
+ > the visible nodes (re-run auto layout)"): it re-runs the
246
+ > auto-layout so everything reads better. If you've moved nodes by
247
+ > hand it asks for confirmation first, otherwise it just re-arranges.
269
248
  >
270
249
  > Let me know when you see it.
271
250
 
272
- After the tester confirms, drop this tip:
273
-
274
- > 💡 Tip: if all these changes left the nodes crowded together,
275
- > the map toolbar has a **Reset layout** button: it re-runs the
276
- > auto-layout so everything reads better. It asks for confirmation
277
- > because it discards any positions you moved by hand.
278
-
279
- Wait for confirmation. Mark `inspector`: done.
251
+ Mark `inspector`: done.
280
252
 
281
253
  ## Chapter `edit-link` - Edit a link, the topology changes (~3 min)
282
254
 
@@ -296,7 +268,7 @@ You verify by reading `notes/todo.md` to confirm the change was applied. (On `ag
296
268
 
297
269
  ## Chapter `workspace` - Navigate the workspace (files, search, isolate) (~2 min)
298
270
 
299
- **Context**: you've built the graph and understood it; this beat is about *moving around* it. The workspace has two halves: the **Map** you've been working in, and a **Files** panel, a folder tree of every node. You'll open that tree, filter it with the search box, and use **isolate** to collapse the map down to a single node and the things it touches. No file edits here, pure navigation, and the same `sm` session you booted back in the `init` chapter is still running.
271
+ **Context**: you've built the graph and understood it; this beat is about *moving around* it. The workspace has two halves: the **Map** you've been working in, and a **Files** panel, a folder tree of every node. You'll open that tree and filter it with the search box. No file edits here, pure navigation, and the same `sm` session you booted back in the `init` chapter is still running.
300
272
 
301
273
  Per §Provider detection, on `agent-skills` / Antigravity the fixture has fewer nodes (`demo-skill` plus the two `notes/` files), so swap the node names below for ones that exist in that set; the gestures are identical.
302
274
 
@@ -318,8 +290,7 @@ Per §Provider detection, on `agent-skills` / Antigravity the fixture has fewer
318
290
  > `Search…`). Type `guideline`. Watch both halves at once: the tree
319
291
  > narrows down to `demo-guideline` and the **Map** drops every node
320
292
  > except `demo-guideline`. The search matches a node's name, path,
321
- > tags or description, and filters live as you type, no Enter
322
- > needed.
293
+ > or description, and filters live as you type, no Enter needed.
323
294
  >
324
295
  > Now clear the box. All five nodes come back, in both the tree and
325
296
  > the Map. Confirm you saw it filter and then restore.
@@ -369,7 +340,7 @@ description: |
369
340
  API_TOKEN: example-not-real
370
341
  ```
371
342
 
372
- Confirm the file appears in the map as a sixth node (`notes/private-credentials`). The watcher sees it like any other `.md`, that's the point of the demo.
343
+ Confirm the file appears in the map as a sixth node (`notes/private-credentials`). The watcher sees it like any other `.md`, that's the point of the demo. (If the tester doesn't see it, they may need to click **Show all** in the map toolbar to clear any leftover selection.)
373
344
 
374
345
  **Beat 2, you show the project structure (the agent does this).**
375
346
 
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // cli/entry.ts
2
2
 
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="82aaa5c6-6dae-53a6-8d4a-1a673357051c")}catch(e){}}();
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="dd2e1877-e17a-5d0b-86e5-6416814d7a78")}catch(e){}}();
4
4
  import { existsSync as existsSync33 } from "fs";
5
5
  import { Builtins, Cli as Cli2 } from "clipanion";
6
6
 
@@ -246,7 +246,7 @@ function bucketByKind(kind, instance, bag) {
246
246
  // package.json
247
247
  var package_default = {
248
248
  name: "@skill-map/cli",
249
- version: "0.53.0",
249
+ version: "0.53.1",
250
250
  description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
251
251
  license: "MIT",
252
252
  type: "module",
@@ -18113,12 +18113,12 @@ var DB_DRIFT_TEXTS = {
18113
18113
  // `{{reason}}` is one of the `driftReason*` strings below so the
18114
18114
  // operator sees WHY the cache is being rebuilt (version skew vs an
18115
18115
  // inline schema change the version did not bump).
18116
- driftPrompt: "{{glyph}} The local cache was built by skill-map {{dbVersion}} and you are on {{currentVersion}} ({{reason}}).\n {{hint}}\n",
18117
- driftPromptHint: "Pre-1.0 the DB is a derived cache (your .sm sidecars hold the real data); it cannot be carried across a schema change and has to be rebuilt.",
18118
- driftPromptQuestion: "Delete the local cache and rebuild it on this scan? [y/N] ",
18116
+ driftPrompt: "{{glyph}} Local cache is from skill-map {{dbVersion}}, you are on {{currentVersion}} ({{reason}}).\n {{hint}}\n",
18117
+ driftPromptHint: "It will be rebuilt from your .sm files on this scan; nothing of yours is touched.",
18118
+ driftPromptQuestion: "Rebuild the local cache now? [y/N] ",
18119
18119
  // Receipt after the rebuild (printed by the scan / refresh path).
18120
- driftReset: "{{glyph}} Local cache rebuilt ({{reason}}): it was written by skill-map {{dbVersion}}, you are on {{currentVersion}}.\n {{hint}}\n",
18121
- driftResetHint: "The DB was deleted and is being regenerated by this scan; .sm sidecars were not touched.",
18120
+ driftReset: "{{glyph}} Local cache rebuilt: was from skill-map {{dbVersion}}, you are on {{currentVersion}}.\n {{hint}}\n",
18121
+ driftResetHint: "Rebuilt from your .sm files; nothing of yours was touched.",
18122
18122
  // Abort headline when the operator declines (wrapped by the caller's
18123
18123
  // `sm scan: {message}` shell, so it carries no glyph / verb prefix).
18124
18124
  driftAborted: "cache rebuild declined: the {{dbVersion}} cache cannot be reused on {{currentVersion}} ({{reason}}). {{hint}}",
@@ -18136,12 +18136,13 @@ async function maybeResetOnDrift(dbPath, policy) {
18136
18136
  const reason = detectDriftReason(dbPath, policy.currentVersion);
18137
18137
  if (reason === null) return { kind: "no-drift" };
18138
18138
  const dbVersion = readScannedByVersion(dbPath) ?? "unknown";
18139
- const confirmed = await confirmDriftReset(dbVersion, reason, policy);
18139
+ const prompted = shouldPromptForReset(policy);
18140
+ const confirmed = prompted ? await askDriftReset(dbVersion, reason, policy) : true;
18140
18141
  if (!confirmed) {
18141
18142
  return { kind: "aborted", dbVersion, currentVersion: policy.currentVersion, reason };
18142
18143
  }
18143
18144
  await removeDbFiles(dbPath);
18144
- renderResetReceipt(dbVersion, reason, policy);
18145
+ if (!prompted) renderResetReceipt(dbVersion, policy);
18145
18146
  return { kind: "reset", dbVersion, currentVersion: policy.currentVersion, reason };
18146
18147
  }
18147
18148
  function detectDriftReason(dbPath, currentVersion) {
@@ -18166,10 +18167,6 @@ function readScannedByVersion(dbPath) {
18166
18167
  raw?.close();
18167
18168
  }
18168
18169
  }
18169
- async function confirmDriftReset(dbVersion, reason, policy) {
18170
- if (!shouldPromptForReset(policy)) return true;
18171
- return askDriftReset(dbVersion, reason, policy);
18172
- }
18173
18170
  function reasonText(reason) {
18174
18171
  return reason === "version" ? DB_DRIFT_TEXTS.driftReasonVersion : DB_DRIFT_TEXTS.driftReasonSchema;
18175
18172
  }
@@ -18200,7 +18197,7 @@ async function askDriftReset(dbVersion, reason, policy) {
18200
18197
  rl.close();
18201
18198
  }
18202
18199
  }
18203
- function renderResetReceipt(dbVersion, reason, policy) {
18200
+ function renderResetReceipt(dbVersion, policy) {
18204
18201
  if (!policy.printer) return;
18205
18202
  const warnGlyph = policy.style?.warnGlyph ?? "\u26A0";
18206
18203
  const dim = policy.style?.dim ?? ((s) => s);
@@ -18209,7 +18206,6 @@ function renderResetReceipt(dbVersion, reason, policy) {
18209
18206
  glyph: warnGlyph,
18210
18207
  dbVersion,
18211
18208
  currentVersion: policy.currentVersion,
18212
- reason: reasonText(reason),
18213
18209
  hint: dim(DB_DRIFT_TEXTS.driftResetHint)
18214
18210
  })
18215
18211
  );
@@ -30255,4 +30251,4 @@ function resolveBareDefault() {
30255
30251
  process.exit(ExitCode.Error);
30256
30252
  }
30257
30253
  //# sourceMappingURL=cli.js.map
30258
- //# debugId=82aaa5c6-6dae-53a6-8d4a-1a673357051c
30254
+ //# debugId=dd2e1877-e17a-5d0b-86e5-6416814d7a78
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // kernel/i18n/registry.texts.ts
2
2
 
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e7950f5b-8f6d-5eab-bd05-e9a3e4de4731")}catch(e){}}();
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5755b8d3-0320-507b-8287-e7141109764a")}catch(e){}}();
4
4
  var REGISTRY_TEXTS = {
5
5
  duplicateExtension: "Extension already registered: {{kind}}:{{qualifiedId}}",
6
6
  unknownKind: "Unknown extension kind: {{kind}}",
@@ -102,7 +102,7 @@ import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
102
102
  // package.json
103
103
  var package_default = {
104
104
  name: "@skill-map/cli",
105
- version: "0.53.0",
105
+ version: "0.53.1",
106
106
  description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
107
107
  license: "MIT",
108
108
  type: "module",
@@ -3632,4 +3632,4 @@ export {
3632
3632
  runScanWithRenames
3633
3633
  };
3634
3634
  //# sourceMappingURL=index.js.map
3635
- //# debugId=e7950f5b-8f6d-5eab-bd05-e9a3e4de4731
3635
+ //# debugId=5755b8d3-0320-507b-8287-e7141109764a
@@ -1,6 +1,6 @@
1
1
  // kernel/i18n/registry.texts.ts
2
2
 
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5a40a4c9-3996-540c-b687-874d383944d0")}catch(e){}}();
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c1e3d822-fab9-519a-9e3e-3ad2f7070d52")}catch(e){}}();
4
4
  var REGISTRY_TEXTS = {
5
5
  duplicateExtension: "Extension already registered: {{kind}}:{{qualifiedId}}",
6
6
  unknownKind: "Unknown extension kind: {{kind}}",
@@ -102,7 +102,7 @@ import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
102
102
  // package.json
103
103
  var package_default = {
104
104
  name: "@skill-map/cli",
105
- version: "0.53.0",
105
+ version: "0.53.1",
106
106
  description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
107
107
  license: "MIT",
108
108
  type: "module",
@@ -3632,4 +3632,4 @@ export {
3632
3632
  runScanWithRenames
3633
3633
  };
3634
3634
  //# sourceMappingURL=index.js.map
3635
- //# debugId=5a40a4c9-3996-540c-b687-874d383944d0
3635
+ //# debugId=c1e3d822-fab9-519a-9e3e-3ad2f7070d52