pi-vault-mind 0.16.6 → 0.16.7

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.16.7 / 0.6.10 — 2026-07-18
4
+
5
+ ### Fixed
6
+
7
+ - **Obsidian Markdown lifecycle.** Assistant Markdown renders through Obsidian's native renderer, renderer components unload on panel close or remount, stale asynchronous opens cannot remount a closed panel, and deferred message fills cannot hijack a replacement message placeholder.
8
+ - **Generated sandbox constants.** Root builds now format the sandbox extension-package catalog they regenerate, so the release build cannot invalidate the sandbox verification suite.
9
+ - **Repository-only documentation.** Removed the obsolete MkDocs configuration, GitHub Pages deployment workflow, publication badges, and generated-site instructions while retaining maintained Markdown documentation in the repository.
10
+
11
+ ### Tests
12
+
13
+ - Added focused regressions for Markdown cleanup ownership, direct remount disposal, close-during-refresh cancellation, and deferred placeholder isolation.
14
+
15
+ ## 0.6.9 — 2026-07-18
16
+
17
+ ### Fixed
18
+
19
+ - **First-run personalization recovery.** The configured-vault onboarding card now retains its active personalization state until durable runtime status confirms completion, including when the prompt acknowledgement fails or a permission request is pending. The chat feed and composer remain correctly gated until then.
20
+ - **Portable model selection.** The shared panel contract now passes opaque model IDs end-to-end; the Obsidian adapter resolves each ID to Pi's provider/model RPC payload internally, preserving IDs that contain `/` or `:`.
21
+
22
+ ### Tests
23
+
24
+ - Added focused regressions for acknowledgement failure, pending permission delivery, re-entry protection, and exact model-ID selection ordering.
25
+
3
26
  ## 0.16.6 / 0.6.8 — 2026-07-18
4
27
 
5
28
  ### Fixed
package/README.md CHANGED
@@ -3,8 +3,6 @@
3
3
  [![npm version](https://img.shields.io/npm/v/pi-vault-mind)](https://www.npmjs.com/package/pi-vault-mind)
4
4
  [![license](https://img.shields.io/npm/l/pi-vault-mind)](LICENSE)
5
5
  [![pi-extension](https://img.shields.io/badge/pi-extension-blue)](https://github.com/mariozechner/pi)
6
- [![docs](https://img.shields.io/badge/docs-pi--vault--mind-blue)](https://kylebrodeur.github.io/pi-vault-mind/)
7
- [![docs build](https://github.com/kylebrodeur/pi-vault-mind/actions/workflows/docs.yml/badge.svg)](https://github.com/kylebrodeur/pi-vault-mind/actions/workflows/docs.yml)
8
6
 
9
7
  Passive Obsidian vault extension for the [pi](https://github.com/mariozechner/pi) agent ecosystem. Watches `@agent` markers in your vault, dispatches forked subagents, and stores results in LanceDB with vector + FTS + graph. Multi-agent "Drop & Forget" workflow.
10
8
 
@@ -363,19 +361,16 @@ Edit `pi-vault-mind.config.json` to match your domain:
363
361
 
364
362
  ## Documentation
365
363
 
366
- > **Full docs site:** [kylebrodeur.github.io/pi-vault-mind](https://kylebrodeur.github.io/pi-vault-mind/) (GH Pages, built from [`docs/`](docs/)).
367
- > The links below point to the source files in this repository.
364
+ Documentation is maintained directly in this repository.
368
365
 
369
366
  ### Getting started
370
367
 
371
368
  | Doc | Description |
372
369
  |---|---|
373
- | [docs/getting-started/QUICKSTART.md](docs/getting-started/QUICKSTART.md) | **Fastest path** 60-second install, setup, first append |
374
- | [docs/getting-started/NEW_VAULT_WALKTHROUGH.md](docs/getting-started/NEW_VAULT_WALKTHROUGH.md) | **Fresh Mac new vault Modal sync → verified**, one linear path (incl. multi-vault storage isolation) |
375
- | [docs/getting-started/INSTALL.md](docs/getting-started/INSTALL.md) | **Canonical install playbook** all 5 layers (pi ext, skills, Obsidian, config, external CLIs) |
376
- | [docs/getting-started/GETTING_STARTED.md](docs/getting-started/GETTING_STARTED.md) | End-to-end workflow + daily "drop & forget" usage |
377
- | [docs/getting-started/CLI_ONLY_WALKTHROUGH.md](docs/getting-started/CLI_ONLY_WALKTHROUGH.md) | Same setup + daily commands, entirely CLI — no Obsidian plugin required |
378
- | [docs/getting-started/WALKTHROUGH_PROMPT.md](docs/getting-started/WALKTHROUGH_PROMPT.md) | Paste-into-pi guided setup with checkpoints between phases |
370
+ | [Install playbook](docs/_reference/reference_archive/getting-started/INSTALL.md) | Canonical install procedure for the extension, skills, Obsidian plugin, configuration, and external CLIs |
371
+ | [Getting started](docs/_reference/reference_archive/getting-started/GETTING_STARTED.md) | End-to-end setup and daily “drop and forget” workflow |
372
+ | [CLI-only walkthrough](docs/_reference/reference_archive/getting-started/CLI_ONLY_WALKTHROUGH.md) | Setup and daily commands without the Obsidian plugin |
373
+ | [ReturnVape walkthrough](docs/getting-started/WALKTHROUGH.md) | Current guided Obsidian test-vault procedure |
379
374
 
380
375
  ### Architecture & design
381
376
 
@@ -384,8 +379,6 @@ Edit `pi-vault-mind.config.json` to match your domain:
384
379
  | [docs/architecture/AGENTS.md](docs/architecture/AGENTS.md) | Agent Roster and Multi-Agent Architecture ("Fork & Review" model) |
385
380
  | [docs/architecture/EXTENSION_WIRING.md](docs/architecture/EXTENSION_WIRING.md) | Extension dependencies, runtime wiring, auto-install patterns |
386
381
  | [docs/architecture/DISPATCHER_SPEC.md](docs/architecture/DISPATCHER_SPEC.md) | Technical spec for the passive file-watcher and subagent routing — incl. the "Fork & Dispatch" rationale and thread resume |
387
- | [docs/architecture/AGENTS.md](docs/architecture/AGENTS.md) | Agent roster + the Miner's "Drop & Forget" ingestion pipeline |
388
- | [docs/integrations/OBSIDIAN_SETUP.md](docs/integrations/OBSIDIAN_SETUP.md) | Recommended Obsidian vault structure, plugins, and CLI |
389
382
 
390
383
  ### Modal embedding service (local integration done)
391
384
 
@@ -401,8 +394,6 @@ full design.
401
394
  | Doc | Description |
402
395
  |---|---|
403
396
  | [docs/integrations/MODAL_EMBEDDING.md](docs/integrations/MODAL_EMBEDDING.md) | Design of record: ADRs, HTTP contract, sync protocol, roadmap for the cloud embedding service |
404
- | [docs/plans/modal-embedding-plan.md](docs/plans/modal-embedding-plan.md) | **Consolidated plan & next steps** — phases, owners, status, decision gate (in repo, not on the docs site) |
405
- | [docs/plans/embedding-open-questions.md](docs/plans/embedding-open-questions.md) | Embedding-strategy decision log (decided + open questions) |
406
397
  | [modal/](modal/) | The deployable Modal app: embedding service + bulk worker + sync + dataset generator |
407
398
  | [eval/](eval/) | Retrieval eval harness + labeled benchmark datasets for picking the canonical model |
408
399
 
@@ -412,17 +403,10 @@ full design.
412
403
  |---|---|
413
404
  | [skills/vault-mind/SKILL.md](skills/vault-mind/SKILL.md) | The Manager skill — what pi auto-loads about this extension |
414
405
  | [docs/CHANGELOG.md](docs/CHANGELOG.md) | Version history (rename from `pi-knowledge-store` to `pi-vault-mind` was v0.7.0) |
415
- | [docs/reference/tools.md](docs/reference/tools.md) | The 11 `vm_*` and `vm_query`/`vm_append`/etc. tools parameters, return shapes |
416
- | [docs/reference/commands.md](docs/reference/commands.md) | Full `/vm` slash command tree |
417
- | [docs/reference/configuration.md](docs/reference/configuration.md) | The complete `pi-vault-mind.config.json` schema |
418
- | [docs/reference/skill.md](docs/reference/skill.md) | Manifest of all bundled skills and their trigger phrases |
419
-
420
- ### Testing
421
-
422
- | Doc | Description |
423
- |---|---|
424
- | [docs/testing/TESTING.md](docs/testing/TESTING.md) | Test plan for agent / human / HITL personas, regression suite |
425
- | [docs/testing/E2E_MANUAL_TEST.md](docs/testing/E2E_MANUAL_TEST.md) | Manual end-to-end verification procedure (watcher → dispatch → vault) |
406
+ | [Tools reference](docs/_reference/reference_archive/tools.md) | Registered Vault Mind tools, parameters, and return shapes |
407
+ | [Commands reference](docs/_reference/reference_archive/commands.md) | Full `/vm` slash command tree |
408
+ | [Configuration reference](docs/_reference/reference_archive/configuration.md) | Complete `pi-vault-mind.config.json` schema |
409
+ | [Skill manifest](docs/_reference/reference_archive/skill.md) | Bundled skills and their trigger phrases |
426
410
 
427
411
  ### Development
428
412
 
@@ -430,22 +414,13 @@ full design.
430
414
  |---|---|
431
415
  | [docs/development/CONTRIBUTING.md](docs/development/CONTRIBUTING.md) | Dev setup, testing, and commit conventions |
432
416
  | [docs/development/PUBLISHING.md](docs/development/PUBLISHING.md) | How to publish this extension to npm |
433
- | [docs/development/FUTURE_WORK.md](docs/development/FUTURE_WORK.md) | Roadmap — codegraph integration, pagination, TUI rendering, etc. |
434
-
435
- ### Research
436
-
437
- | Doc | Description |
438
- |---|---|
439
- | [docs/research/COMPETITOR_COMPARISON.md](docs/research/COMPETITOR_COMPARISON.md) | Tier 1/2/3 comparison vs. other Obsidian-LLM tools (22 competitors) |
440
- | [docs/research/naming-decisions.md](docs/research/naming-decisions.md) | Historical record of the 2026-06-06 decision to name the project `pi-vault-mind` |
441
- | [docs/research/obsidian-links-reviewed.csv](docs/research/obsidian-links-reviewed.csv) | Curated subset of starred Obsidian repos with adoption verdicts |
442
417
 
443
418
  ### Archive
444
419
 
445
420
  | Doc | Description |
446
421
  |---|---|
447
422
  | [docs/_archive/](docs/_archive/) | Historical docs kept for context (e.g. the `pi-knowledge-store` → `pi-vault-mind` rename audit) |
448
- | [docs/_archive/legacy-audit.md](docs/_archive/legacy-audit.md) | The 2026-06-08 legacy-terminology audit (139 findings, 13 blockers) and its resolution log. Resolved 2026-06-09; archived 2026-06-16 (in the repo, not on the docs site) |
423
+ | [docs/_archive/legacy-audit.md](docs/_archive/legacy-audit.md) | The 2026-06-08 legacy-terminology audit (139 findings, 13 blockers) and its resolution log. Resolved 2026-06-09 and archived 2026-06-16. |
449
424
 
450
425
  ## Contributing
451
426
 
@@ -1637,30 +1637,32 @@ async function handleVmSearch(req, res, serverState, overrideBody) {
1637
1637
  res.end(JSON.stringify({ error: `Unknown mode: ${mode}` }));
1638
1638
  return;
1639
1639
  }
1640
+ const sources = Array.isArray(body.sources) ? body.sources : ["vault"];
1641
+ const includeVault = sources.includes("vault");
1640
1642
  try {
1641
- let results;
1643
+ let results = [];
1642
1644
  let relations;
1643
1645
  let message;
1644
- if (resolvedMode === "hybrid") {
1646
+ if (includeVault && resolvedMode === "hybrid") {
1645
1647
  results = await searchHybridRanked(cfg.vaultMind.dataDir, collection, query, limit, cfg.vaultMind, identity);
1646
1648
  }
1647
- else if (resolvedMode === "semantic") {
1649
+ else if (includeVault && resolvedMode === "semantic") {
1648
1650
  results = await searchHybrid(cfg.vaultMind.dataDir, collection, query, limit, cfg.vaultMind, identity);
1649
1651
  }
1650
- else if (resolvedMode === "fts") {
1652
+ else if (includeVault && resolvedMode === "fts") {
1651
1653
  results = await searchFts(cfg.vaultMind.dataDir, collection, query, limit, cfg.vaultMind, identity);
1652
1654
  }
1653
- else if (resolvedMode === "graph") {
1655
+ else if (includeVault && resolvedMode === "graph") {
1654
1656
  const depth = body.depth ?? 1;
1655
1657
  const norm = normalizeGraphResult(await queryGraph(cfg.vaultMind.dataDir, cfg.vaultMind, entity, depth, identity));
1656
1658
  results = norm.hits;
1657
1659
  relations = norm.relations;
1658
1660
  message = norm.message;
1659
1661
  }
1660
- else if (resolvedMode === "vault") {
1662
+ else if (includeVault && resolvedMode === "vault") {
1661
1663
  results = await searchVaultNative(vaultPath, query, limit, body.tags);
1662
1664
  }
1663
- else {
1665
+ else if (includeVault) {
1664
1666
  // mode === "full"
1665
1667
  const depth = body.depth ?? 1;
1666
1668
  const [hybrid, semantic, fts, graph, vault] = await Promise.all([
@@ -1709,7 +1711,6 @@ async function handleVmSearch(req, res, serverState, overrideBody) {
1709
1711
  addResults(vault, "vault");
1710
1712
  results = merged.slice(0, limit);
1711
1713
  }
1712
- const sources = Array.isArray(body.sources) ? body.sources : ["vault"];
1713
1714
  if (sources.includes("sessions")) {
1714
1715
  results = [...results, ...searchSessions(resolveSessionsDir(), query, limit)];
1715
1716
  }
@@ -192,19 +192,19 @@ describe("personalize", () => {
192
192
  // AGENTS.md was never created, so rejection means it still does not exist.
193
193
  assert.equal(fs.existsSync(path.join(testDir, "AGENTS.md")), false);
194
194
  });
195
- it("persists a completion marker even when all suggestions are rejected or skipped", async () => {
195
+ it("persists a completion marker even when all suggestions are rejected", async () => {
196
196
  const { runPersonalize } = await import("../src/personalize.js");
197
197
  const pi = makePi(JSON.stringify({
198
198
  commentary: "No changes needed.",
199
199
  files: [
200
- { path: ".pi/agent/system.md", action: "skip" },
201
- { path: "AGENTS.md", action: "skip" },
200
+ { path: ".pi/agent/system.md", action: "create", content: "# System" },
201
+ { path: "AGENTS.md", action: "create", content: "# Agents" },
202
202
  ],
203
203
  }));
204
- const ctx = makeCtx(testDir, []);
204
+ const ctx = makeCtx(testDir, [false, false]);
205
205
  await runPersonalize(ctx, pi);
206
206
  const markerPath = path.join(testDir, ".vault-mind", "personalized.json");
207
- assert.ok(fs.existsSync(markerPath), "runPersonalize must write a durable completion marker after the flow finishes, even when every diff is rejected");
207
+ assert.ok(fs.existsSync(markerPath), "runPersonalize must write a durable completion marker after the flow finishes, even when the user rejects every actionable suggestion");
208
208
  const marker = JSON.parse(fs.readFileSync(markerPath, "utf-8"));
209
209
  assert.strictEqual(marker.completed, true);
210
210
  assert.ok(typeof marker.completedAt === "string");
@@ -229,11 +229,11 @@ describe("personalize", () => {
229
229
  const pi = makePi(JSON.stringify({
230
230
  commentary: "No changes needed.",
231
231
  files: [
232
- { path: ".pi/agent/system.md", action: "skip" },
233
- { path: "AGENTS.md", action: "skip" },
232
+ { path: ".pi/agent/system.md", action: "create", content: "# System" },
233
+ { path: "AGENTS.md", action: "create", content: "# Agents" },
234
234
  ],
235
235
  }));
236
- const ctx = makeCtx(testDir, []);
236
+ const ctx = makeCtx(testDir, [false, false]);
237
237
  const result = await runPersonalize(ctx, pi);
238
238
  assert.ok(result, "runPersonalize must return a result, not void");
239
239
  assert.strictEqual(result.completed, true, "all-rejected personalization must resolve as a successful completion");
@@ -4,6 +4,7 @@ import * as os from "node:os";
4
4
  import * as path from "node:path";
5
5
  import { after, before, describe, it } from "node:test";
6
6
  import { _resetAuthCache } from "../src/auth.js";
7
+ import { resetConnection } from "../src/lance.js";
7
8
  import { fakePi, fetchJson, makeVault, startTestServer, TEST_TOKEN, } from "./helpers/server.js";
8
9
  const envVar = "PVM_API_TOKEN";
9
10
  describe("REST vm routes", () => {
@@ -265,8 +266,8 @@ describe("REST vm routes", () => {
265
266
  assert.ok(Array.isArray(d.sources), "sources should be echoed");
266
267
  }
267
268
  });
268
- it("POST /vm/search with sources sessions merges session hits", async () => {
269
- // Seed a temp sessions dir
269
+ it("POST /vm/search with only sessions succeeds without an available vault index", async () => {
270
+ // Seed a temp sessions dir while the configured LanceDB index remains unavailable.
270
271
  const tmpSessions = fs.mkdtempSync(path.join(os.tmpdir(), "pvm-rest-sessions-"));
271
272
  const slugDir = path.join(tmpSessions, "--test--");
272
273
  fs.mkdirSync(slugDir, { recursive: true });
@@ -284,18 +285,24 @@ describe("REST vm routes", () => {
284
285
  const savedDir = process.env.PI_SESSIONS_DIR;
285
286
  try {
286
287
  process.env.PI_SESSIONS_DIR = tmpSessions;
288
+ resetConnection();
289
+ const vaultIndexPath = path.join(vaultPath, ".lancedb");
290
+ fs.rmSync(vaultIndexPath, { recursive: true, force: true });
291
+ assert.equal(fs.existsSync(vaultIndexPath), false, "the vault index fixture must be absent");
287
292
  const { status, body } = await fetchJson(port, "POST", "/vm/search", {
288
- body: { query: "searchtestquery", mode: "vault", sources: ["sessions"] },
293
+ body: { query: "searchtestquery", mode: "hybrid", sources: ["sessions"] },
289
294
  token: TEST_TOKEN,
290
295
  });
291
- assert.ok(status === 200 || status === 500, `expected 200 or 500, got ${status}`);
292
- if (status === 200) {
293
- const d = body;
294
- const hits = d.hits;
295
- assert.ok(hits.some((h) => h._source === "session"), "should contain at least one session hit");
296
- }
296
+ assert.equal(status, 200, "sessions-only search must not initialize or query the vault index");
297
+ assert.equal(fs.existsSync(vaultIndexPath), false, "sessions-only search must leave the unavailable vault index untouched");
298
+ const d = body;
299
+ assert.deepEqual(d.sources, ["sessions"], "the response must preserve the isolated source");
300
+ const hits = d.hits;
301
+ assert.ok(hits.length > 0, "sessions-only search should return the seeded session hit");
302
+ assert.ok(hits.every((hit) => hit._source === "session"), "sessions-only search must not merge vault hits");
297
303
  }
298
304
  finally {
305
+ resetConnection();
299
306
  if (savedDir === undefined)
300
307
  delete process.env.PI_SESSIONS_DIR;
301
308
  else
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-vault-mind",
3
- "version": "0.16.6",
3
+ "version": "0.16.7",
4
4
  "description": "Passive Obsidian vault extension for pi. Watches @agent markers, dispatches forked subagents (Miner, Broadcaster, Heavy-Lifter), stores in LanceDB with vector + FTS + graph. Multi-agent 'Drop & Forget' workflow for the pi agent ecosystem.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -64,7 +64,7 @@
64
64
  "scripts": {
65
65
  "prepare": "husky",
66
66
  "check": "biome check --write . && tsc --noEmit",
67
- "generate-constants": "node scripts/generate-extension-packages-json.mjs && node scripts/generate-config-keys-json.mjs && biome check --write extension-packages.json config-keys.json packages/obsidian/src/extension-packages.json packages/obsidian/src/config-keys.json",
67
+ "generate-constants": "node scripts/generate-extension-packages-json.mjs && node scripts/generate-config-keys-json.mjs && biome check --write extension-packages.json config-keys.json packages/obsidian/src/extension-packages.json packages/obsidian/src/config-keys.json packages/obsidian-ui/src/extension-packages.json",
68
68
  "build": "npm run generate-constants && tsc && tsc -p tsconfig.test.json",
69
69
  "dev": "tsc --watch",
70
70
  "test": "node --test \"dist/test/**/*.test.js\"",