@openparachute/vault 0.6.5-rc.15 → 0.6.5-rc.16

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.
@@ -23,6 +23,9 @@ import {
23
23
  applySeedPack,
24
24
  CAPTURE_ANYTHING_PATH,
25
25
  CONNECT_AI_PATH,
26
+ DEFAULT_VAULT_DESCRIPTION,
27
+ IMPORTED_VAULT_DESCRIPTION,
28
+ YOURS_TO_KEEP_PATH,
26
29
  GETTING_STARTED_CONTENT,
27
30
  GETTING_STARTED_PACK,
28
31
  GETTING_STARTED_PATH,
@@ -282,11 +285,38 @@ describe("getting-started pack", () => {
282
285
  // exist. It names the pack + the way to add it.
283
286
  expect(GETTING_STARTED_CONTENT).not.toContain("[[Surface Starter]]");
284
287
  expect(GETTING_STARTED_CONTENT).toContain("Surface Starter");
285
- expect(GETTING_STARTED_CONTENT).toContain("add-pack surface-starter");
288
+ // Points at the add-pack flow (console affordance / CLI) without spelling
289
+ // out a terminal command — de-emphasise the CLI (Aaron 2026-07-06).
290
+ expect(GETTING_STARTED_CONTENT).toContain("add-pack");
286
291
  // The surface packages are still named for discoverability.
287
292
  expect(GETTING_STARTED_CONTENT).toContain("@openparachute/surface-client");
288
293
  expect(GETTING_STARTED_CONTENT).toContain("@openparachute/surface-render");
289
294
  });
295
+
296
+ test("Getting Started is onboarding-first + carries no dead CLI guidance (2026-07-06 rewrite)", () => {
297
+ // Two-part structure: onboarding conversation leads, mechanics reference follows.
298
+ expect(GETTING_STARTED_CONTENT).toContain("## Part 1 — Onboarding the person");
299
+ expect(GETTING_STARTED_CONTENT).toContain("## Part 2 — Vault mechanics");
300
+ // Points the person at the five human guides by name (all resolve to seeds).
301
+ for (const g of [WELCOME_PATH, CAPTURE_ANYTHING_PATH, TAGS_GRAPH_PATH, CONNECT_AI_PATH, YOURS_TO_KEEP_PATH]) {
302
+ expect(GETTING_STARTED_CONTENT).toContain("[[" + g + "]]");
303
+ }
304
+ // The old live bug: it told cloud AIs to run a CLI that doesn't exist there.
305
+ expect(GETTING_STARTED_CONTENT).not.toContain("parachute-vault import");
306
+ // Data-in leads with the import UI + MCP bridge, not the terminal.
307
+ expect(GETTING_STARTED_CONTENT).toContain("Import button");
308
+ expect(GETTING_STARTED_CONTENT).toContain("over MCP");
309
+ });
310
+
311
+ test("default vault-description constants orient + tell the AI to self-replace them", () => {
312
+ for (const d of [DEFAULT_VAULT_DESCRIPTION, IMPORTED_VAULT_DESCRIPTION]) {
313
+ expect(d.length).toBeGreaterThan(100);
314
+ expect(d).toContain("Getting Started");
315
+ expect(d).toContain("vault-info { description:"); // the self-replace instruction
316
+ }
317
+ expect(DEFAULT_VAULT_DESCRIPTION).toContain("brand-new");
318
+ expect(IMPORTED_VAULT_DESCRIPTION).toContain("imported");
319
+ });
290
320
  });
291
321
 
292
322
  describe("surface-starter pack", () => {
@@ -34,6 +34,32 @@
34
34
 
35
35
  import type { Store, TagFieldSchema } from "./types.ts";
36
36
 
37
+ // ---------------------------------------------------------------------------
38
+ // Default vault descriptions — the single source of truth
39
+ // ---------------------------------------------------------------------------
40
+
41
+ /**
42
+ * The `vault-info` description a **brand-new** vault ships with. It's the first
43
+ * thing a connected AI reads about the vault, so it doubles as a nudge: orient
44
+ * the person, read the Getting Started brief, do one small real thing, and — once
45
+ * real structure lands — REPLACE this text with a current picture of the vault.
46
+ *
47
+ * Exported as the single source of truth; the runtimes (bun vault default seed +
48
+ * cloud vault DO) consume it in a follow-up PR. Not wired into `applySeedPack`
49
+ * here — a description is vault metadata, not a pack note.
50
+ */
51
+ export const DEFAULT_VAULT_DESCRIPTION =
52
+ 'This is a brand-new personal vault — just its starter guides so far; the person it belongs to is probably new to Parachute. Before helping them set it up, read the "Getting Started" note — it\'s your onboarding brief. Short version: start with a conversation, not a filing system; learn how they want to use this and where their notes live today; do one small real thing first. When the vault has real structure, replace this description (vault-info { description: "..." }) with a current picture of what lives here and how to work it — so every future session, yours or another AI\'s, starts oriented.';
53
+
54
+ /**
55
+ * The `vault-info` description a vault gets when it was **imported/restored** —
56
+ * it arrived with content. Flips the AI's first job from seed-it to learn-it:
57
+ * orient over the existing shape, reflect it back, and only then replace this
58
+ * text with a current picture.
59
+ */
60
+ export const IMPORTED_VAULT_DESCRIPTION =
61
+ 'This vault was imported — it arrived with its own notes, tags, and history. Orient before you write: vault-info { include_stats: true }, list-tags, read a sample, and read "Getting Started" if present. Your first job is to learn the shape that\'s already here and reflect it back to the person — not to propose new structure cold. When you understand it, replace this description (vault-info { description: "..." }) with a current picture.';
62
+
37
63
  // ---------------------------------------------------------------------------
38
64
  // Pack shape
39
65
  // ---------------------------------------------------------------------------
@@ -306,24 +332,98 @@ export const SURFACE_STARTER_PATH = "Surface Starter";
306
332
  /**
307
333
  * Body of the seeded `Getting Started` note.
308
334
  *
309
- * Voice: addressed to the connected AI ("you"), practical, SKILL.md-style.
310
- * Covers (a) what a Parachute vault is, (b) tags-vs-paths-vs-schemas design,
311
- * (c) importing existing notes, (d) that it's an adaptable starting point.
312
- * Mentions the Surface Starter PACK by name (no wikilink the note isn't
313
- * seeded by default, and a dangling `[[Surface Starter]]` would sit unresolved
314
- * on every fresh vault).
335
+ * Voice: addressed to the connected AI ("you"), warm and practical, SKILL.md-style.
336
+ * ONE note, two labeled parts:
337
+ * - Part 1 Onboarding the person: lead with a real conversation, leverage
338
+ * prior context, offer to survey their content, do one small real thing
339
+ * first, the data-in menu (import UI / MCP bridge / paste-and-file — NOT the
340
+ * CLI, NOT Obsidian-first), the arrived-with-content branch, and closing the
341
+ * loop by updating the vault description (see DEFAULT_VAULT_DESCRIPTION).
342
+ * - Part 2 — Vault mechanics: the preserved reference — what a vault is + the
343
+ * tool list, tags-vs-paths-vs-schemas, write gotchas, the custom-surface
344
+ * pointer, and "Adapt this note."
345
+ *
346
+ * Deliberately points AIs at the import UI + MCP bridge, never at a
347
+ * `parachute-vault import` CLI (that verb doesn't exist on cloud — the old copy
348
+ * shipped that live bug to every hosted user). Mentions the Surface Starter PACK
349
+ * by name (no wikilink — the note isn't seeded by default, and a dangling
350
+ * `[[Surface Starter]]` would sit unresolved on every fresh vault).
315
351
  */
316
352
  export const GETTING_STARTED_CONTENT = `# Getting Started
317
353
 
318
- This is the **start-here guide** for this Parachute vault — think of it like a
319
- \`SKILL.md\`: practical instructions for setting up and growing the vault. Read it
320
- when you're **getting the vault started** or orienting yourself to it you don't
321
- need to re-read it every session. It's a **starting point, not a script**, and
322
- it's adaptable: edit it (see "Adapt this note") as the vault takes shape.
323
-
324
- When the operator says something like *"help me set up my parachute,"* this is
325
- your brief: design their structure with them, import what they already have, and
326
- shape the vault around how they actually think and work.
354
+ This is the **start-here guide** for this Parachute vault — instructions for a
355
+ connected AI (you), like a \`SKILL.md\`. Read it when the vault is new, when
356
+ you're orienting yourself, or when the person says *"help me set up my
357
+ parachute."* You don't need to re-read it every session. It has two parts:
358
+ **how to onboard the person** (start there if they're new) and **vault
359
+ mechanics** (reference for operating the vault). It's a starting point, not a
360
+ script and it's editable (see "Adapt this note" at the end).
361
+
362
+ ---
363
+
364
+ ## Part 1 — Onboarding the person
365
+
366
+ ### Start with a conversation, not a filing system
367
+
368
+ If this vault is fresh, this is probably the person's first real session with
369
+ it. Don't start building — orient them, briefly, in your own words: this vault
370
+ is **their** memory, one place every AI they choose to connect can read and
371
+ write, and they can export all of it anytime as plain markdown. Then have a
372
+ real conversation:
373
+
374
+ - **How do they imagine using this?** A journal, a project brain, a people
375
+ directory, meeting notes, a commonplace book — or they don't know yet
376
+ (that's fine; capture-first works).
377
+ - **Where do their notes and data live now?** Another app, a pile of markdown,
378
+ another Parachute — or nowhere yet.
379
+ - **What's alive for them right now?** A project, a decision, a trip, a draft.
380
+ The first note should be about something real.
381
+
382
+ **Use what you already know.** If you have memory or context about this person
383
+ from working with them, bring it — propose the two or three kinds of
384
+ information *they specifically* would want here ("you mention a lot of book
385
+ ideas — want a place for those?"). Propose, confirm, then write; never
386
+ bulk-create structure they didn't agree to. You can also **offer to survey**
387
+ what they already have — "want me to look through what you've brought in and
388
+ suggest a few ways to organize it?" — then read a sample and propose, don't
389
+ impose.
390
+
391
+ ### Do one small real thing first
392
+
393
+ The failure mode of every notes tool is over-organizing an empty vault. So:
394
+ **one small real thing this session.** Capture a thought they actually have,
395
+ file one document, or bring in one small batch — then stop and show them what
396
+ happened. Structure grows from real notes (that's Part 2's design vocabulary).
397
+ Setup is a relationship over many sessions, not an install step.
398
+
399
+ Five short guides ship in this vault for the person to read (tagged \`#guide\`):
400
+ [[Welcome to your vault 🪂]], [[Capture anything]], [[Tags and the graph]],
401
+ [[Connect your AI]], and [[Yours to keep]]. Point them there for anything you'd
402
+ otherwise lecture about — they're the return-point between sessions. If a
403
+ session ends mid-setup, leave a breadcrumb (update this note or the vault
404
+ description) so the next one picks up where you left off.
405
+
406
+ ### If this vault already has content
407
+
408
+ Some vaults arrive full — an import, a restore, months of use. Then your first
409
+ job is to **learn it, not seed it**: \`vault-info { include_stats: true }\`,
410
+ \`list-tags\`, read a sample (\`query-notes { search: "..." }\`), then reflect the
411
+ shape back to the person and ask what's missing or wrong. Propose structure
412
+ only once you can describe what's already there.
413
+
414
+ ### Close the loop: describe the vault
415
+
416
+ When the first real structure lands, update the vault description —
417
+ \`vault-info { description: "..." }\` — so every future session (yours or another
418
+ AI's) starts oriented: what this vault is for, its main tags, its conventions.
419
+ The default description says "brand-new vault"; once that stops being true,
420
+ replace it. Keep it a few sentences (the projection carries the schema detail,
421
+ and this note carries the richer conventions — see "Adapt this note"). Bringing
422
+ their existing data in is covered under "Bringing existing notes in" below.
423
+
424
+ ---
425
+
426
+ ## Part 2 — Vault mechanics
327
427
 
328
428
  ## What a Parachute vault is
329
429
 
@@ -417,33 +517,40 @@ A few behaviors worth knowing before you write at scale:
417
517
 
418
518
  (Full design guide, with copy-paste examples: https://parachute.computer/scripting/)
419
519
 
420
- ## Importing existing notes
520
+ ## Bringing existing notes in
521
+
522
+ If the person already keeps notes somewhere, help them bring what matters —
523
+ start with what's alive for them, not the whole archive. What works today:
421
524
 
422
- If the operator already keeps notes (Obsidian, Markdown, etc.), bring them in
423
- rather than starting cold:
525
+ - **Connect the source over MCP (the flexible path).** If their AI client can
526
+ add other MCP servers — a Google Drive server, a Notion server, a filesystem
527
+ server — connect it alongside this vault in the same session. Then read from
528
+ there and \`create-note\` here: a selective, conversational migration, no
529
+ export file needed.
530
+ - **Paste and file.** They paste anything — a doc, a list, an export — and you
531
+ \`create-note\` it (batch mode for many at once).
532
+ - **Import a Parachute export.** Moving between Parachute vaults (cloud ⇄
533
+ self-host) is lossless — on Parachute Cloud, the console's Import button —
534
+ ids, tags, links, schemas, and attachments round-trip.
424
535
 
425
- - **Obsidian / a Markdown folder:** \`parachute-vault import <path>\` preserves
426
- frontmatter, tags, \`[[wikilinks]]\`, and file paths.
427
- - **A portable Parachute export** (a dir with \`.parachute/vault.yaml\`): the same
428
- \`import\` command auto-detects it and does a lossless round-trip (ids, typed
429
- links, tag schemas, attachments).
430
- - **Ad hoc / pasted content:** just \`create-note\` it. Then help the operator tag
431
- and schematize: read a sample of imported notes, propose a small tag
432
- vocabulary, and apply it.
536
+ Bringing a whole Obsidian or Markdown library in is getting easier, and a
537
+ flexible import is on the way; for now the connect-over-MCP and paste paths
538
+ handle it without anyone touching a terminal. Whatever they bring, offer to
539
+ survey it and suggest a first structure — read a sample, propose a small tag
540
+ vocabulary, confirm, then apply. Don't impose structure silently.
433
541
 
434
- After an import, orient yourself: \`vault-info\` for the new schema picture,
435
- \`list-tags\` to see what vocabulary arrived, \`query-notes { search: "..." }\` to
436
- spot-check. Then propose structure — don't impose it silently.
542
+ After bringing content in, orient: \`vault-info\` for the schema picture,
543
+ \`list-tags\` for the vocabulary that arrived, \`query-notes { search: "..." }\`
544
+ to spot-check.
437
545
 
438
546
  ## Later: a custom surface
439
547
 
440
548
  Building a custom UI over the vault (a dashboard, a notes app) is usually **not**
441
- the starting point — get the notes and structure right first. If and when the
442
- operator wants one, add the **Surface Starter** guide to this vault — it's a
443
- seed pack that isn't installed by default. Run
444
- \`parachute-vault add-pack surface-starter\` (or use the console's add-pack
445
- affordance) to seed it; it covers building a surface with
446
- \`@openparachute/surface-client\` + \`@openparachute/surface-render\`.
549
+ the starting point — get the notes and structure right first. When the person
550
+ wants one, add the **Surface Starter** guide to this vault — an optional pack
551
+ (not installed by default) that covers building a surface with
552
+ \`@openparachute/surface-client\` + \`@openparachute/surface-render\`. On Parachute
553
+ Cloud it's the console's add-pack affordance.
447
554
 
448
555
  ## Adapt this note
449
556
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openparachute/vault",
3
- "version": "0.6.5-rc.15",
3
+ "version": "0.6.5-rc.16",
4
4
  "description": "Agent-native knowledge graph. Notes, tags, links over MCP.",
5
5
  "module": "src/cli.ts",
6
6
  "type": "module",
@@ -82,7 +82,10 @@ describe("seedOnboardingNotes — default packs (welcome + getting-started)", ()
82
82
  expect(gs!.content).toContain("Tags = types");
83
83
  expect(gs!.content).toContain("Paths = organization");
84
84
  expect(gs!.content).toContain("Schemas = typed metadata fields");
85
- expect(gs!.content).toContain("parachute-vault import");
85
+ // Data-in leads with the import UI + MCP bridge; the old `parachute-vault
86
+ // import` CLI line (a live bug on cloud) is gone (2026-07-06 rewrite).
87
+ expect(gs!.content).not.toContain("parachute-vault import");
88
+ expect(gs!.content).toContain("Bringing existing notes in");
86
89
  expect(gs!.content).toContain("Adapt this note");
87
90
 
88
91
  // The welcome ring: five person-voiced guide notes.
@@ -200,7 +203,7 @@ describe("seedOnboardingNotes — default packs (welcome + getting-started)", ()
200
203
  // Getting Started mentions the surface-starter PACK — not a wikilink to a
201
204
  // note that the default seed no longer creates.
202
205
  expect(gs!.content).not.toContain("[[Surface Starter]]");
203
- expect(gs!.content).toContain("add-pack surface-starter");
206
+ expect(gs!.content).toContain("add-pack");
204
207
  });
205
208
 
206
209
  test("idempotent: a second seed run skips all notes (does not duplicate)", async () => {
@@ -414,7 +414,7 @@ describe("vault create — default pack seeding (welcome + getting-started)", ()
414
414
  // Surface Starter is out of the default seed — no note, no dangling link.
415
415
  expect(notes.find((n) => n.path === "Surface Starter")).toBeUndefined();
416
416
  expect(gs!.content).not.toContain("[[Surface Starter]]");
417
- expect(gs!.content).toContain("add-pack surface-starter");
417
+ expect(gs!.content).toContain("add-pack");
418
418
 
419
419
  // The capture tag Notes requires arrives with the welcome pack, alongside
420
420
  // the guide (skill-file) + pinned tags — and nothing else (fresh-vault