pi-weave 0.2.4 → 0.3.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.
package/README.md CHANGED
@@ -53,14 +53,24 @@ pi-weave keeps track of where knowledge came from, while making the whole worksp
53
53
 
54
54
  **The conversation can end. The knowledge doesn't have to.**
55
55
 
56
- ## Built on Pi
56
+ ## Install
57
57
 
58
- pi-weave is built as an extension for [Pi](https://github.com/earendil-works/pi).
58
+ pi-weave supports [Pi](https://github.com/earendil-works/pi) and OpenCode (V1 **1.18.29+** and V2) from the same package. The adapters share
59
+ the vault, repository index, browser workspace, tools, and skills.
59
60
 
60
- I've grown to love Pi precisely because it is such a lightweight agent harness. It gives the model tools and context without trying to
61
- become the product itself, and its extensibility makes projects like pi-weave possible.
61
+ OpenCode V2:
62
62
 
63
- Install pi-weave:
63
+ ```bash
64
+ opencode plugin add pi-weave
65
+ ```
66
+
67
+ OpenCode V1 1.18.29+: add the package to both `opencode.json` (server) and `tui.json` (browser opening):
68
+
69
+ ```json
70
+ { "plugin": ["pi-weave"] }
71
+ ```
72
+
73
+ Pi:
64
74
 
65
75
  ```bash
66
76
  pi install npm:pi-weave
@@ -75,7 +85,7 @@ pi install /path/to/pi-weave
75
85
 
76
86
  Requires Node **20.13 or newer**.
77
87
 
78
- Then just talk to Pi.
88
+ Then just talk to your agent.
79
89
 
80
90
  ## Start taking notes
81
91
 
@@ -92,21 +102,21 @@ You: Add that the gateway team owns the migration plan.
92
102
  You: What open questions are in this note?
93
103
  ```
94
104
 
95
- For live narration or interview notes, tell Pi that you are dictating:
105
+ For live narration or interview notes, tell your agent that you are dictating:
96
106
 
97
107
  ```text
98
108
  You: Start a note for this interview. I’m going to narrate; keep my words
99
109
  verbatim and organize the note as we go.
100
110
  ```
101
111
 
102
- For each chunk, Pi:
112
+ For each chunk, the agent:
103
113
 
104
114
  1. appends your words unchanged to the note’s `## Raw` tail;
105
115
  2. refreshes the structured summary above it;
106
116
  3. leaves the raw record untouched.
107
117
 
108
118
  This makes the note readable during the conversation without replacing your words with an AI reconstruction. Notes based on your dictation
109
- remain marked `source: human`; notes drafted by Pi are marked `source: agent`.
119
+ remain marked `source: human`; notes drafted by the agent are marked `source: agent`.
110
120
 
111
121
  Useful requests include:
112
122
 
@@ -141,7 +151,7 @@ Renaming or moving a note rewrites its inbound links automatically, so its backl
141
151
  ```bash
142
152
  /weave-view # open the browser workspace
143
153
  /weave-view --no-open # start it and print the URL
144
- /weave-view tui # terminal UI for SSH or browser-free use
154
+ /weave-view tui # Pi only: terminal UI for SSH or browser-free use
145
155
  ```
146
156
 
147
157
  The browser workspace has four connected views:
@@ -163,17 +173,18 @@ last writer wins, and the workspace picks up outside changes within a couple of
163
173
 
164
174
  `/weave-view tui` is the smaller, read-only terminal explorer: tree, focused neighborhood, details, and link health over the same graph.
165
175
 
166
- ## Remember past pi sessions
176
+ ## Remember sessions
167
177
 
168
178
  ```bash
169
- /weave-scan sessions # pi history (default)
179
+ /weave-scan sessions # Pi history, or the current OpenCode session
170
180
  /weave-scan sessions /path/to/history # explicit history root
171
181
  ```
172
182
 
173
183
  This opt-in scan treats a supplied file—or every bounded text file under a supplied directory—as opaque session material for the active
174
- model to interpret, then writes generated notes under `~/.okf/notes/sessions/`. That makes it usable with Claude Code, opencode, Codex, or
175
- exported history trees without requiring their schema or file extension. It skips unchanged files, captures outcomes plus reusable technical
176
- takeaways, works outside Git repositories, and can be stopped with `/weave-scan-cancel`.
184
+ model to interpret, then writes generated notes under `~/.okf/notes/sessions/`. In OpenCode, the pathless form reads the current session
185
+ through the public plugin API; it never inspects OpenCode's internal database. That makes explicit paths usable with Claude Code, OpenCode,
186
+ Codex, or exported history trees without requiring their schema or file extension. It skips unchanged files, captures outcomes plus reusable
187
+ technical takeaways, works outside Git repositories, and can be stopped with `/weave-scan-cancel`.
177
188
 
178
189
  ## Repository knowledge
179
190
 
@@ -196,7 +207,7 @@ Most people only need natural language and `/weave-view`.
196
207
 
197
208
  | Surface | Name | Purpose |
198
209
  |---|---|---|
199
- | Command | `/weave-view` | Open the browser or terminal workspace |
210
+ | Command | `/weave-view` | Open the browser workspace (`tui` is a Pi-only argument) |
200
211
  | Command | `/weave` | Show vault and repository status |
201
212
  | Command | `/weave-scan` | Build or refresh the repository index |
202
213
  | Command | `/weave-scan deep` | Add incremental model-written file summaries |
@@ -205,7 +216,11 @@ Most people only need natural language and `/weave-view`.
205
216
  | Tool | `weave_note` | List, read, add, append, finalize, and search notes |
206
217
  | Tool | `weave_repo` | Check, scan, and summarize the repository index |
207
218
 
208
- The included `weave-notepad` and `weave-explore` skills teach Pi when and how to use these tools.
219
+ The included `weave-notepad` and `weave-explore` skills teach Pi and OpenCode when and how to use these tools. In OpenCode, `/weave` shows
220
+ vault/repository status and scan progress appears in toasts; Pi keeps its persistent status line. V1 slash commands use its standard prompt
221
+ pipeline, so the model reports command results in the conversation. `/weave` does not open a dialog. V1 scans use the model from your last
222
+ chat message: send a message after selecting a model, then scan. Generation runs in temporary child sessions with tools denied;
223
+ those sessions are removed on completion or cancellation. V2 uses its direct command and generation APIs.
209
224
 
210
225
  ## Files, privacy, and portability
211
226
 
@@ -245,14 +260,18 @@ We probably want OIDC next quarter…
245
260
 
246
261
  Set `PI_WEAVE_VAULT` to use a different vault location.
247
262
 
248
- Reading, writing, searching, and viewing notes are local operations. Deep repository scans and session summaries send bounded input to
249
- whichever model you configured in pi. The browser workspace binds only to loopback, uses a per-session token, and shuts down with the pi
250
- session.
263
+ Reading, writing, searching, and viewing notes are local operations. Deep repository scans and session summaries send bounded input to the
264
+ active Pi/V2 model or the last-used V1 chat model. The browser workspace binds only to loopback, uses a per-session token, and shuts down
265
+ with the plugin lifecycle. OpenCode opens it automatically when the terminal can reach the viewer's loopback URL. Otherwise, it shows the
266
+ exact URL for a browser or tunnel.
251
267
 
252
- The vault format, repository index, and skills are intentionally harness-agnostic. `src/core` contains no pi-specific imports.
268
+ The vault format, repository index, and skills are intentionally harness-agnostic. `src/core` contains no Pi- or OpenCode-specific imports.
253
269
 
254
270
  ## Development
255
271
 
272
+ The OpenCode V1/V2 bindings share tool schemas, core actions, and one command/scan workflow. Zod is the only direct runtime dependency,
273
+ required by V1's tool-schema protocol; OpenCode SDKs are development-only.
274
+
256
275
  ```bash
257
276
  npm install
258
277
  npm run check
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-weave",
3
- "version": "0.2.4",
4
- "description": "Local-first Markdown memory and knowledge graph for Pi: preserve decisions, recall across sessions, and explore notes with code.",
3
+ "version": "0.3.0",
4
+ "description": "Local-first Markdown memory and knowledge graph for Pi and OpenCode: preserve decisions, recall sessions, and explore notes with code.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "publishConfig": {
@@ -10,6 +10,7 @@
10
10
  "keywords": [
11
11
  "pi-package",
12
12
  "pi-coding-agent",
13
+ "opencode-plugin",
13
14
  "agent-memory",
14
15
  "persistent-memory",
15
16
  "markdown",
@@ -32,6 +33,10 @@
32
33
  "node": ">=20.13.0"
33
34
  },
34
35
  "exports": {
36
+ "./server": "./src/opencode/index.ts",
37
+ ".": "./src/opencode/index.ts",
38
+ "./tui": "./src/opencode/tui.ts",
39
+ "./rpc": "./src/opencode/rpc.ts",
35
40
  "./core": "./src/core/index.ts"
36
41
  },
37
42
  "files": [
@@ -71,6 +76,8 @@
71
76
  "@earendil-works/pi-ai": "^0.84.2",
72
77
  "@earendil-works/pi-coding-agent": "^0.84.2",
73
78
  "@earendil-works/pi-tui": "^0.84.2",
79
+ "@opencode-ai/plugin": "1.18.29",
80
+ "@opencode/plugin": "^2.0.19",
74
81
  "@types/d3-force": "^3.0.10",
75
82
  "@types/node": "^24.0.0",
76
83
  "@vitest/coverage-v8": "^3.2.4",
@@ -85,5 +92,8 @@
85
92
  "typebox": "1.3.7",
86
93
  "typescript": "^5.8.0",
87
94
  "vitest": "^3.2.4"
95
+ },
96
+ "dependencies": {
97
+ "zod": "4.1.8"
88
98
  }
89
99
  }
@@ -1,54 +1,38 @@
1
1
  ---
2
2
  name: weave-explore
3
- description: Explore a git repository through its pi-weave knowledge index (.okf). Use when starting work in an unfamiliar repo, when asked to "explore this repository", or before broad structural questions about modules, packages, or architecture.
3
+ description: Explore unfamiliar git repositories and answer structural questions about modules, packages, or architecture using the pi-weave index (.okf).
4
4
  ---
5
5
 
6
6
  # Weave Explore
7
7
 
8
- pi-weave keeps a **derived** knowledge index of the repository at `<repo>/.okf/`. Source code is the truth; the index is a rebuildable
9
- cache. Deleting `.okf` loses nothing — rescan to regenerate it.
10
-
11
- ## Tools
12
-
13
- In pi, use the `weave_repo` tool (or the `/weave-scan` command). To see the assembled graph in the terminal, run `/weave-view tui` (Explore
14
- tree, Focus neighborhood, Health surface); `/weave-view` opens the browser viewer. In other harnesses, read the JSON documents under `.okf/`
15
- directly.
8
+ Use `weave_repo`. Without the tool, read `<repo>/.okf/` directly. The index is a generated, rebuildable cache; source code is authoritative.
16
9
 
17
10
  ## Workflow
18
11
 
19
- 1. **Check for an index**: `weave_repo` action=status.
20
- - `missing` → offer to scan (`weave_repo` action=scan), or scan directly when the user asked to explore.
21
- - `stale` → scan again; the repository moved on.
22
- - `fresh` → read it: action=overview.
23
- 2. **Start from the overview**: file counts, languages, packages, module groupings, and likely entry points. This replaces dozens of
24
- `ls`/`find` calls.
25
- 3. **Descend progressively** (design §9): only open files in modules relevant to the user's question. The index gives you the map; the code
26
- gives you the terrain.
27
- 4. **Read summaries before full files**: if the repo has been deep-scanned (`.okf/repository/summaries/` exists), read the relevant sidecars
28
- first — they tell you what a file does and its outward surface in 1–3 sentences, so you can decide whether to open the full file at all.
29
- 5. **Answer with structure**: name modules and packages by their indexed paths so the user can jump straight to them.
12
+ 1. Check `action=status`: if missing, offer a scan or scan when exploration was requested; if stale, rescan; if fresh, read
13
+ `action=overview`.
14
+ 2. Use the overview's languages, packages, modules, and entry points to select relevant paths instead of listing the whole repository.
15
+ 3. Read available `.okf/repository/summaries/` sidecars before opening full files.
16
+ 4. Inspect the relevant code and cite indexed paths in your answer.
30
17
 
31
- ## Deep summaries
18
+ ## Commands
32
19
 
33
- `/weave-scan deep` creates or refreshes `.okf/repository/summaries/` — one sidecar per file, written by the session model. It is **opt-in
34
- and incremental**: it never runs implicitly, and it only re-summarizes files whose content hash changed since their last summary. If
35
- summaries are missing or stale, offer `/weave-scan deep` to create or refresh them before diving into full files.
20
+ - `/weave-scan` refreshes the index (`weave_repo` action=scan).
21
+ - `/weave-scan deep` generates file summaries using the session model. Offer it when summaries are missing or stale; never run it
22
+ implicitly. Only changed content is summarized again.
23
+ - `/weave-view` opens the browser workspace.
24
+ - `/weave-scan sessions [path]` writes session memories to the vault, not the repository index; see `weave-notepad`.
36
25
 
37
- Its sibling `/weave-scan sessions` is a different scope: it summarizes past *session transcripts* into the vault (`notes/sessions/`), not the repository. See the `weave-notepad` skill — nothing it writes lands in `.okf/`.
38
-
39
- ## On-disk layout
26
+ ## Files and trust
40
27
 
41
28
  ```text
42
29
  .okf/
43
30
  ├── okf.json # format version + generator
44
31
  └── repository/
45
32
  ├── identity.json # name, remotes, default branch
46
- ├── git.json # HEAD sha + branch + changed files (staleness anchor)
33
+ ├── git.json # HEAD, branch, changed files
47
34
  ├── structure.json # languages, packages, modules, entry points
48
- └── summaries/ # deep-scan sidecars (one per file, when present)
35
+ └── summaries/ # generated file summaries, when present
49
36
  ```
50
37
 
51
- ## Trust model
52
-
53
- Everything in `.okf` is machine-generated (`source: generated`). If the user corrects an interpretation, that correction belongs in the
54
- vault (see the `weave-notepad` skill) as human knowledge, not in the derived index.
38
+ Index content is `source: generated`. Store user corrections as human knowledge in the vault, never only in the derived index.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: weave-notepad
3
- description: "Take and retrieve durable notes in the pi-weave vault. Use when the user asks to remember something or to start/add to a note (aliases: notes, ai note, note-taking, note-taker), or when answering questions about past decisions, people, or projects. Also handles interview note-taking where raw dictations are appended AND expanded, and deterministic repair of stale [[wiki-links]] between notes."
3
+ description: "Create, update, and retrieve durable notes and past decisions. Use for remember/note requests (notes, ai note, note-taking, note-taker), live dictation, interviews, and repairing or suggesting [[wiki-links]]."
4
4
  ---
5
5
 
6
6
  # Weave Notepad
@@ -8,26 +8,41 @@ description: "Take and retrieve durable notes in the pi-weave vault. Use when th
8
8
  The pi-weave vault is the user's long-term memory: plain Markdown notes with front matter under `~/.okf/notes/`. It is shared with the human
9
9
  — anything you write here, they can read and edit, and vice versa.
10
10
 
11
- ## Tools
11
+ Use `weave_note`. Without the tool, edit the files directly (`PI_WEAVE_VAULT` overrides the vault root). Front matter:
12
+ `title`, `created`, `updated` (ISO-8601), `tags`, and `source: human | agent | generated`.
12
13
 
13
- In pi, use the `weave_note` tool. In other harnesses (or when the tool is not available), operate on the files directly:
14
+ ## Capture
14
15
 
15
- - **Notes** live at `~/.okf/notes/<slug>.md` (vault root overridable via `PI_WEAVE_VAULT`).
16
- - Each note has YAML front matter: `title`, `created`, `updated` (ISO-8601), `tags: [..]`, and `source: human | agent | generated`.
17
- - `weave_note` actions: `list`, `get`, `add`, `append`, `finalize`, `search`, `links`, `suggest`. `finalize` restructures the body *above* the `## Raw` tail and
18
- preserves the tail verbatim — a body with no tail yet is preserved **in full** as a newly created tail, so finalization never destroys
19
- dictation.
20
- - **Dictation appends**: use `append` with `raw: true` — the tool appends the text verbatim into the `## Raw` tail as a dated fenced block,
21
- creating the tail if the note has none. In pi, never hand-format the raw tail; the tool maintains it.
16
+ - Create notes only on explicit requests: “remember this”, “start a note”, “add to this note”. Do not capture conversation unprompted.
17
+ - Given new content, call `add` directly and report the slug. Do not list the vault, inspect the repository, or run git first.
18
+ - When extending existing knowledge, make one targeted `search`, then `append` to the matching note instead of duplicating it.
19
+ - Ask one short question if content is missing; exploration cannot reveal what the user meant.
20
+ - Use a specific title and 1–4 lowercase tags; reuse existing tags when known.
21
+ - User-supplied words are `source: human`; pass that explicitly to `add`. Agent-drafted notes are `source: agent` (the default).
22
+ Finalization changes presentation, not authorship. Preserve human meaning; put agent additions in a dated “Agent addendum”.
23
+ - Do not store repository-derived facts, temporary task state, or secrets the user has not confirmed are safe to persist.
22
24
 
23
- ## Raw Tail Format
25
+ ## Dictation mode (continuous compile)
26
+
27
+ During live dictation or interviews, keep the organized note current after every append; do not wait until the session ends:
24
28
 
25
- In pi you rarely format this by hand: `weave_note` append with `raw: true` appends a dated fenced block into the tail (and creates the whole
26
- tail — separator, heading, notice — when the note has none). The format below is what that produces, and what to write when editing files
27
- directly or working in other harnesses.
29
+ 1. `append` with `raw: true` preserves the user's words verbatim under `## Raw`. Never silently reword dictation.
30
+ 2. Immediately `finalize` the body above the tail: front-loaded summary, sections, decisions, questions, tasks, entities, and links
31
+ reflecting everything said so far.
28
32
 
29
- Every note maintains a verbatim, append-only raw section at the bottom separated by a horizontal rule (`---`):
33
+ Outside dictation, finalize only on request.
34
+
35
+ ### How to capture and append raw input
30
36
 
37
+ - Keep an append-only raw section at the bottom: `---`, then `## Raw`, then the notice shown below.
38
+ - Fence verbatim input in code blocks. Prepend each subsequent block with `<!-- appended YYYY-MM-DD HH:MM -->`.
39
+ - Use `append` with `raw: true` when available; it maintains this format and creates the tail if missing. Do not hand-format it.
40
+ - `finalize` changes only the body above the tail. Never rewrite, remove, or move words out of the raw tail. If no tail exists, preserve the
41
+ entire previous body as a new raw tail before restructuring; the tool does this automatically.
42
+
43
+ When editing files directly, preserve the same format:
44
+
45
+ ````markdown
31
46
  ---
32
47
 
33
48
  ## Raw
@@ -37,120 +52,42 @@ Every note maintains a verbatim, append-only raw section at the bottom separated
37
52
  <Initial verbatim input>
38
53
  ```
39
54
 
40
- <!-- appended 2026-08-23 08:45 -->
55
+ <!-- appended YYYY-MM-DD HH:MM -->
41
56
  ```
42
- <Follow-up verbatim user input>
57
+ <Follow-up verbatim input>
43
58
  ```
59
+ ````
44
60
 
45
- ### How to capture and append raw input
46
-
47
- 1. **Divider and Heading**: The raw section starts with `---` followed by `## Raw` and the notice comment: `<!-- NEVER edit below this line.
48
- Verbatim user input preserved here. -->`.
49
- 2. **Code Blocks for Verbatim Input**: Always wrap verbatim user lines inside code blocks (triple backticks).
50
- 3. **Date and Time on Appends**: When appending subsequent snippets, prepend each snippet with: `<!-- appended YYYY-MM-DD HH:MM -->`.
51
- 4. **Finalization (`finalize`)**:
52
- - `finalize` replaces or structures content only above the `---` and `## Raw` section.
53
- - The `## Raw` block and all verbatim code blocks are never modified or removed.
54
-
55
- ## Dictation mode (continuous compile)
56
-
57
- During live dictation / interview note-taking (see the skill description), Pi does **not** wait until the end to organize the note. Every
58
- interactive append is immediately compiled into the body:
59
-
60
- 1. **Append the raw words verbatim** into the `## Raw` tail (`weave_note` action=append with `raw: true` — the tool adds the dated code block
61
- and creates the tail if missing).
62
- 2. **Then immediately finalize** (`weave_note` action=finalize): rewrite the body *above* the `## Raw` tail — front-loaded summary,
63
- sections, decisions, questions, tasks, entities, links — so the compiled document reflects everything said so far.
64
- 3. **Never rewrite or remove the `## Raw` tail.** It stays append-only and verbatim; only the body above it changes.
65
-
66
- The result is a continuously-updated compiled document that stays current throughout the session — not just a raw tail that gets organized
67
- once at the end.
68
-
69
- ## When to take a note
61
+ ## Retrieve
70
62
 
71
- Create a note **only when the user explicitly asks** for one to exist: "start a note on X", "add to the X note", "remember this", "jot that
72
- down". Never promote conversation into a note on your own initiative — capture is explicit by design.
63
+ - Known slug: `get`. Otherwise, one targeted `search` with the user's terms; never list the vault to find a note.
64
+ - One result or a unique exact-title match returns the full note. Use it; do not fetch it again. A body marked `complete` needs no `get`.
65
+ - For multiple plausible matches, fetch at most the three strongest slugs together. If still ambiguous, ask for another identifier instead
66
+ of repeating searches. Fetch additional content only when marked as an excerpt.
67
+ - Search accepts ordinary multi-term queries, with exact-phrase matching followed by ranked lexical fallback. Read the match evidence and
68
+ bounded content before another call.
69
+ - Connected notes are discovery context, not query matches. Use them only when their stated relationship matters; connections are lexical or
70
+ explicit, not semantic.
71
+ - Trust repository code over conflicting notes about implementation; flag potentially stale intent.
73
72
 
74
- ## When NOT to take a note
73
+ ## Session memory
75
74
 
76
- - Anything derivable from the repository itself (that knowledge belongs to the `.okf` index, not the vault).
77
- - Session-scratch information (in-progress task state).
78
- - Secrets, credentials, or anything the user hasn't confirmed is safe to persist.
75
+ `/weave-scan sessions [path]` creates searchable notes under `notes/sessions/` from available session transcripts.
79
76
 
80
- ## How to write a good note
77
+ - These are `source: generated` recollections; a contradicting human decision record wins.
78
+ - Search their `## Takeaways` for reusable lessons before re-deriving a familiar solution.
79
+ - Rescans update changed transcripts while preserving human edits above the raw tail. Session notes remain re-derivable.
81
80
 
82
- 0. **Go straight to the tool.** A note is one `weave_note` call. Do not `list` the vault, inspect the repository, or run `git` — none of that
83
- informs what to write, and on a large vault `list` alone floods the context. When the user gives you the content ("note that says X"),
84
- `add` it and report the slug.
85
- 1. **Search first when adding to existing knowledge** (`weave_note` action=search, with the note's key terms): if a note on the subject
86
- exists, `append` to it rather than creating a duplicate. Skip this when the user is clearly starting something new — one targeted search,
87
- never a vault listing.
88
- 2. Title: short noun phrase ("Auth boundary decision", not "Notes").
89
- 3. **Ask only when the content is genuinely missing.** A vague request ("write a note weave") needs one short question, not exploration —
90
- searching the vault or the repo will not reveal what the user meant.
91
- 4. **Scribble in, verbatim.** When the user is dictating, append their words to the note as rough, verbatim scribbles — no silent rewording.
92
- Append with `raw: true` so they land under the `## Raw` tail at the end of the note (the tail is created automatically if missing).
93
- 5. **Compile continuously during dictation.** After *every* interactive append in dictation mode, immediately finalize the body *above* the
94
- raw tail so the compiled doc stays current (see [Dictation mode](#dictation-mode-continuous-compile)). Outside dictation mode,
95
- compilation stays on request.
96
- 6. **Finalize on request.** When the user says "finalize this" / "clean this up", restructure the body *above* the raw tail: front-loaded
97
- summary, sections, entities, links. Use `weave_note` action=finalize (or edit the file directly in other harnesses). Move nothing out of
98
- `## Raw` — it is append-only and never rewritten. A note with no `## Raw` tail yet gets its entire pre-finalize body preserved as a new
99
- raw tail: finalization is editorial, never destructive.
100
- 7. Tags: 1–4 lowercase tags; reuse existing tags when possible.
101
- 8. Provenance: notes the user scribbled stay `source: human` (finalization is editorial, not authorship) — pass `source: "human"` to `add`
102
- for user-scribbled notes. Notes you draft from scratch are `source: agent` (the default). Never overwrite a `source: human` note's
103
- meaning; append with a dated "Agent addendum" section instead.
81
+ Scans spend model tokens. Never run them unprompted; suggest one when asked to recover history or improve memory across sessions. An
82
+ explicit path accepts a history file or directory.
104
83
 
105
- ## Session memory (`notes/sessions/`)
84
+ ## Links
106
85
 
107
- `/weave-scan sessions` summarizes past agent session transcripts into generated notes under `notes/sessions/`. These are ordinary vault notes — `search` and `get` reach them like any other — with three differences worth knowing:
108
-
109
- - They are `source: generated`, not human knowledge. Treat one as a recollection of what a past session did, not as a decision record; a human note that contradicts it wins.
110
- - Each carries a `## Takeaways` section: reusable technical lessons (gotchas, root causes, non-obvious rules) from that session. When the user hits a problem that smells familiar, search the vault before re-deriving the answer — a previous session may already have paid for it.
111
- - They are re-derivable. The scan rewrites a note in place when its transcript changes, preserving human edits above the raw tail, so no session note is the only copy of anything.
112
-
113
- The scan is opt-in and never runs on its own. Suggest it when the user asks why the agent keeps forgetting across sessions, or wants history from another tool (`/weave-scan sessions <path>` accepts any history file or directory). Never run it unprompted: it spends model tokens per changed session.
114
-
115
- ## Retrieving knowledge
116
-
117
- When the slug is known, use `weave_note` action=get directly. Otherwise use one targeted `search` with the user's key terms. A search with
118
- one result or one unique exact-title match returns the full note; that result is sufficient, so do not call `get` again. If several
119
- plausible candidates remain, fetch at most the three strongest slugs together in the next tool round. If the answer is still ambiguous,
120
- ask the user for another identifier instead of reformulating and repeating the search. Never list the vault to find a note.
121
-
122
- Search accepts ordinary multi-term queries and automatically falls back from an exact phrase to ranked lexical terms. Results are
123
- strongest-first and include match evidence, metadata, bounded note content, and connected notes found through links, backlinks, shared
124
- tags, and shared distinctive terms. A body marked `complete` is sufficient; call `get` only for content explicitly marked as an excerpt.
125
- Use that context before making another tool call. Connected notes are discovery context, not evidence that they match the query; include
126
- them in an answer only when their stated relationship is relevant. Connections are lexical and explicit, not semantic.
127
-
128
- When a note and the repository index disagree, trust the repository for facts about code and flag the discrepancy — the note may be stale
129
- intent.
130
-
131
- ## Repairing stale links
132
-
133
- A link written as a bare title or basename — `[[Quarterly Roadmap]]` when the note is `planning/roadmap-2026` — resolves to nothing.
134
- **Never reconnect a vault by reading every note and guessing which ones relate.** Run the deterministic pass instead:
135
-
136
- ```jsonc
137
- weave_note { "action": "links" } // report: fixable / ambiguous / unresolvable
138
- weave_note { "action": "links", "fix": true } // apply only the unambiguous repairs
139
- ```
140
-
141
- It resolves by exact slug, then unique basename, then unique title — each requiring exactly one candidate. Ambiguous links are reported
142
- with their candidates and never guessed; unresolvable ones point at notes that were never written. Aliases are preserved, the `## Raw`
143
- tail and code fences are never touched, and `updated` is not bumped. Report first, apply after the user sees it.
144
-
145
- To find connections that were **never written** — two notes that belong together but have never referenced each other — use `suggest`:
146
-
147
- ```jsonc
148
- weave_note { "action": "suggest" } // strongest unlinked pairs
149
- weave_note { "action": "suggest", "slug": "some/note" } // what relates to one note
150
- ```
86
+ Use `links` to report stale targets, then `links` with `fix: true` after the user reviews the report. Resolution requires exactly one
87
+ candidate: exact slug, then basename, then slugified title. Never guess ambiguous targets or invent content for missing notes. Repairs
88
+ preserve aliases, raw tails, code fences, and `updated`; do not reconstruct links by reading the entire vault and guessing.
151
89
 
152
- It ranks pairs by how much *rare* vocabulary they share, and cites the shared terms as evidence. **`suggest` never writes** — there is no `fix`.
153
- A similarity score is a soft signal and a `[[link]]` is a hard claim, so propose the worthwhile pairs to the user and add links only to those they
154
- confirm.
90
+ Use `suggest` (optionally with `slug` or `limit`) for unwritten connections. It reports unlinked pairs with shared-term evidence and never
91
+ writes. Propose relevant pairs and add links only after user confirmation; similarity is not an established relationship.
155
92
 
156
- See [references/link-repair.md](references/link-repair.md) for the full rules, guarantees, and when to run each.
93
+ See [references/link-repair.md](references/link-repair.md) for examples and repair guarantees.
@@ -1,90 +1,42 @@
1
- # Link repair — keeping the vault connected
1
+ # Link repair
2
2
 
3
- A wiki-link resolves to nothing when it is written as a bare title or basename — `[[Quarterly Roadmap]]` while the note lives at
4
- `planning/roadmap-2026` — or when it points at a note that was never written. The graph then shows an isolated note that is in fact well
5
- connected.
6
-
7
- **Never reconnect a vault by reading it.** Do not search the vault note by note, infer which notes "feel related", and hand-write links.
8
- That is slow, costs tokens, and is not reproducible — two runs give two different answers. There is a deterministic pass that does it in
9
- one shot.
10
-
11
- ## The tool
3
+ Use deterministic repair for stale `[[wiki-links]]`; do not read every note and guess connections.
12
4
 
13
5
  ```jsonc
14
- weave_note { "action": "links" } // read-only report
15
- weave_note { "action": "links", "fix": true } // apply the unambiguous repairs
6
+ weave_note { "action": "links" } // report
7
+ weave_note { "action": "links", "fix": true } // apply unambiguous repairs
16
8
  ```
17
9
 
18
- In other harnesses, call `repairVaultLinks(vaultRoot, { apply })` from `pi-weave/core`.
19
-
20
- Always run the report first, read it, then apply. The report is cheap (one pass over the vault, no model calls).
21
-
22
- ## How targets resolve
23
-
24
- Three rules, tried in order. A rule fires only when it yields **exactly one** candidate:
25
-
26
- | # | Rule | Example |
27
- |---|------|---------|
28
- | 1 | exact slug | `[[planning/roadmap-2026]]` — already correct, left alone |
29
- | 2 | unique basename | `[[roadmap-2026]]` → `planning/roadmap-2026` |
30
- | 3 | unique slugified title | `[[Quarterly Roadmap]]` → `planning/roadmap-2026` |
31
-
32
- Anything else is reported, never guessed:
33
-
34
- - **ambiguous** — several notes match (two `plan.md` in different folders). The report lists the candidates; a human picks one, or you
35
- ask. Do not choose on their behalf.
36
- - **unresolvable** — no note matches. The link points at something never written. Offer to create the note or drop the link; **never
37
- invent content to satisfy a link.**
10
+ Without the tool, call `repairVaultLinks(vaultRoot, { apply })` from `pi-weave/core`. Report first, then apply after user review; never run
11
+ `fix: true` unprompted on a vault you did not just change.
38
12
 
39
- ## What a repair does and does not do
13
+ ## Resolution
40
14
 
41
- - Rewrites `[[Quarterly Roadmap]]` → `[[planning/roadmap-2026|Quarterly Roadmap]]`. The **alias preserves the visible text**, so the rendered prose is unchanged —
42
- only the target moves.
43
- - **Does not touch the `## Raw` tail.** A link inside dictation is the user's words, quoted. Off limits, always.
44
- - **Does not touch fenced code blocks.** `[[…]]` in a code sample is a string literal.
45
- - **Does not bump `updated`.** A repair is bookkeeping, not an edit; bumping it would reorder the whole vault by recency.
46
- - **Is idempotent.** A second run finds nothing.
15
+ Try these in order; each requires exactly one candidate:
47
16
 
48
- ## Renames repair themselves
17
+ | Rule | Example |
18
+ |------|---------|
19
+ | Exact slug | `[[planning/roadmap-2026]]` — unchanged |
20
+ | Unique basename | `[[roadmap-2026]]` → `planning/roadmap-2026` |
21
+ | Unique slugified title | `[[Quarterly Roadmap]]` → `planning/roadmap-2026` |
49
22
 
50
- `renameNote`, `moveNote` and `renameFolder` rewrite inbound links automatically, so renaming or moving a note keeps its backlinks intact.
51
- The repair pass is for links that were *written* stale — typed as a bare title, or pointing somewhere that never existed.
23
+ - **Ambiguous:** report candidates and ask; never choose for the user.
24
+ - **Unresolvable:** offer to create the missing note or remove the link; never invent content to satisfy it.
52
25
 
53
- ## Finding connections that were never made
26
+ Repairs preserve visible text through aliases: `[[Quarterly Roadmap]]` becomes `[[planning/roadmap-2026|Quarterly Roadmap]]`. They leave raw
27
+ tails, fenced code, and `updated` untouched. A second run makes no changes. `renameNote`, `moveNote`, and `renameFolder` already repair
28
+ inbound links automatically.
54
29
 
55
- Repair fixes links that point wrong. It cannot find links that were **never written** — two notes that belong together but have never referenced each
56
- other. That is `suggest`:
30
+ ## Unwritten connections
57
31
 
58
32
  ```jsonc
59
- weave_note { "action": "suggest" } // strongest pairs vault-wide
60
- weave_note { "action": "suggest", "slug": "some/note" } // what relates to this note
33
+ weave_note { "action": "suggest" } // strongest unlinked pairs
34
+ weave_note { "action": "suggest", "slug": "some/note" } // one note's candidates
61
35
  weave_note { "action": "suggest", "limit": 40 }
62
36
  ```
63
37
 
64
- It ranks unlinked pairs by IDF-weighted cosine over every term a note carries — title, tags and body in one bag — weighting each term by how rare
65
- it is *in this vault*. Vocabulary shared by most notes (`sprint`, `meeting`, a tag on half the vault) scores near zero and connects nothing;
66
- a ticket id or an unusual name on a handful of notes scores high. Nothing is domain-specific: the vault's own frequencies decide.
67
-
68
- Every suggestion cites the shared terms that earned it. **Read the evidence, not the score** — a list like `shared: acme-1234, release-pipeline`
69
- is checkable, `0.16` is not.
70
-
71
- ### suggest never writes
72
-
73
- This is the rule that matters. `suggest` only reports; there is no `fix`. A similarity score is a soft signal and a `[[link]]` is a hard claim —
74
- once written into a body it is indistinguishable from one the user wrote deliberately. Good scores here are around 0.1–0.3, not 0.9, so treat the
75
- output as a shortlist for a human:
76
-
77
- 1. Run `suggest`, read the shared terms.
78
- 2. Propose the worthwhile pairs **to the user**.
79
- 3. Add `[[wikilinks]]` only to those they confirm.
80
-
81
- Never bulk-apply suggestions, and never present one as an established connection.
82
-
83
- ## When to run it
84
-
85
- - The user asks to "fix the links in" their notes — `links`.
86
- - The health panel or `/weave` reports dangling links — `links`.
87
- - After bulk-importing or reorganising notes outside the tool — `links`.
88
- - The user asks what a note "relates to", or to "connect" / "link up" the vault — `suggest`, then confirm before writing.
38
+ Suggestions rank unlinked pairs by IDF-weighted cosine over title, tags, and body. Rare shared vocabulary matters more than common terms.
39
+ Read the cited terms, not just the score. `suggest` never writes and has no `fix`: propose useful pairs and add links only after
40
+ confirmation. Never bulk-apply suggestions or present them as established connections.
89
41
 
90
- Do not run `fix: true` unprompted on a vault you did not just change — show the report and let the user approve. Reporting is always safe.
42
+ Use `links` for dangling links or after external bulk imports; use `suggest` when asked to discover relationships or connect notes.