@henryqw/pi-session-recall 4.0.1 → 4.0.3

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
@@ -1,10 +1,6 @@
1
1
  # `@henryqw/pi-session-recall`
2
2
 
3
- Find decisions and context in past Pi sessions through a local FTS5 index.
4
-
5
- Saved transcripts are not injected on every turn. The active tool registration still adds standing prompt cost through its schema, descriptions, and guideline. Returned content enters active model context.
6
-
7
- The bundled `pi-session-pattern-miner` skill prepares one bounded sample. The model then finds repeated work that may deserve automation.
3
+ Search past Pi sessions locally to find prior decisions and context without injecting saved transcripts on every turn. The active tool registration still adds standing prompt cost through its schema, descriptions, and guideline. Returned content enters active model context.
8
4
 
9
5
  ## Install
10
6
 
@@ -12,29 +8,36 @@ The bundled `pi-session-pattern-miner` skill prepares one bounded sample. The mo
12
8
  pi install npm:@henryqw/pi-session-recall
13
9
  ```
14
10
 
11
+ Requires Node.js 22.19.0 or later.
12
+
15
13
  ## Use
16
14
 
17
- Start a progressive search with a distinctive keyword query:
15
+ Ask the agent to search with distinctive keywords, for example:
18
16
 
19
17
  ```json
20
18
  { "query": "database migration rollback" }
21
19
  ```
22
20
 
23
- Discovery returns ranked metadata and snippets. Use a result's `path` and `matchMessageId` to scroll for the relevant messages.
21
+ Discovery returns ranked metadata and snippets. Use a result's `path` and `matchMessageId` to scroll to the relevant messages.
24
22
 
25
- Prepare a repository-scoped pattern-mining sample with one call:
23
+ | Surface | Type | Purpose |
24
+ | --- | --- | --- |
25
+ | `session_search` | tool | Agent tool to browse, search, read, scroll, or prepare a bounded pattern-mining corpus. |
26
+ | `/skill:pi-session-pattern-miner` | skill | Agent workflow, invoked by a user, to find repeated work and choose the smallest useful automation. |
26
27
 
27
- ```json
28
- {
29
- "operation": "prepare-pattern-miner",
30
- "scope": "repository",
31
- "limit": 10
32
- }
33
- ```
28
+ The tool supports these modes. Agents use `session_search`; users can invoke the skill with `/skill:pi-session-pattern-miner`.
34
29
 
35
- Use `scope:"all"` for cross-repository work. It still returns the corpus when repository inventory is unavailable.
30
+ | Mode | Call | Result |
31
+ | --- | --- | --- |
32
+ | Pattern preparation | `operation:"prepare-pattern-miner"` + `scope:"repository"` or `scope:"all"` | Up to ten recent lineage-unique sessions plus repository inventory. `limit` defaults to 10 and is clamped to [1,10]. Repository scope includes exact and descendant `cwd` values, filters before the limit, and excludes the current session file. |
33
+ | Discovery | `query` | BM25-ranked metadata and snippets. Each result includes `path` and `matchMessageId` for a follow-up scroll. Start with keywords, then narrow the query before scrolling. `limit` defaults to 3 and is clamped to [1,10]. |
34
+ | Scroll | `sessionId` + `aroundMessageId` | Raw message roles, including tool results, within ±`window` ([1,20], default 5) of the anchor on the selected branch. Re-anchor on the last or first message ID to scroll. Across forks, pass the previous response's `branchTip`; `aroundMessageId` must lie on that branch. |
35
+ | Read | `sessionId` | Raw message roles, including tool results, from the session. Large sessions return head 20 + tail 10. Oversized content is bounded to 50k characters and marked with `contentTruncated`. |
36
+ | Browse | no args | Recent sessions with path, name, cwd, started date, and preview. `limit` defaults to 3 and is clamped to [1,10]. |
37
+
38
+ BM25 is a text-ranking method. Discovery returns index metadata; READ and SCROLL retrieve messages from saved session files.
36
39
 
37
- Use the discovery result's `path` and `matchMessageId` for a follow-up scroll:
40
+ To scroll directly to a discovery hit, pass its `path` and `matchMessageId`:
38
41
 
39
42
  ```json
40
43
  {
@@ -44,42 +47,37 @@ Use the discovery result's `path` and `matchMessageId` for a follow-up scroll:
44
47
  }
45
48
  ```
46
49
 
47
- The follow-up returns up to ten messages before and after that anchor on the selected branch.
50
+ This returns up to ten messages before and after the anchor on the selected branch.
48
51
 
49
- | Surface | Type | Purpose |
50
- | --- | --- | --- |
51
- | `session_search` | tool | Search, inspect, or prepare a bounded mining corpus from past sessions. |
52
- | `pi-session-pattern-miner` | skill | Find repeated work and choose the smallest useful automation. |
52
+ Start pattern mining with one preparation call:
53
53
 
54
- BM25 is a text-ranking method. Discovery returns index metadata; READ and SCROLL retrieve messages from saved session files.
54
+ ```json
55
+ {
56
+ "operation": "prepare-pattern-miner",
57
+ "scope": "repository",
58
+ "limit": 10
59
+ }
60
+ ```
55
61
 
56
- | Mode | Call | Result |
57
- | --- | --- | --- |
58
- | Pattern preparation | `operation:"prepare-pattern-miner"` + `scope:"repository"` or `scope:"all"` | Up to ten recent lineage-unique sessions plus repository inventory. The default limit is 10. Repository scope includes exact and descendant `cwd` values, filters before the limit, and excludes the current session file. |
59
- | Discovery | `query` | BM25-ranked metadata and snippets. Each result includes `path` and `matchMessageId` for a follow-up SCROLL. Start with keywords, then narrow the query before scrolling. |
60
- | Scroll | `sessionId` + `aroundMessageId` | Raw message roles, including tool results, within ±`window` ([1,20]) of the anchor. Re-anchor on the last or first message ID to scroll. Across forks, pass the previous response's `branchTip`; `aroundMessageId` only centers the window and must lie on that branch. |
61
- | Read | `sessionId` | Raw message roles, including tool results, from the session. Large sessions return head 20 + tail 10. Oversized content is bounded to 50k characters and marked with `contentTruncated`. |
62
- | Browse | no args | Recent sessions with path, name, cwd, started date, and preview. |
62
+ Use `scope:"all"` for cross-repository work. It still returns the corpus when repository inventory is unavailable.
63
63
 
64
64
  In the interactive TUI, the collapsed tool block shows the last five visual lines and the earlier-line count. Press `Ctrl+O` to expand the full bounded response. The model always receives the complete tool result.
65
65
 
66
- ### Skills
66
+ ### Pattern-miner skill
67
67
 
68
- Run `/skill:pi-session-pattern-miner` to find repeated workflows in past sessions. The skill makes one preparation call before interpretation.
68
+ Invoke `/skill:pi-session-pattern-miner` to find repeated workflows in past sessions. The skill makes exactly one preparation call before interpretation.
69
69
 
70
- It treats one lineage as one source. It requires two independent examples before recommending automation. A requested topic gets a focused confirmation search even when the prepared sample does not contain it.
70
+ It treats one lineage as one source and requires two independent examples before recommending automation. A requested topic gets a focused confirmation search even when the prepared sample does not contain it.
71
71
 
72
72
  After clustering, the skill always checks current candidate-relevant package manifests, scripts, skills, and instructions. It abstains if it cannot check them safely.
73
73
 
74
74
  ### Repository inventory
75
75
 
76
- Repository inventory contains discovery hints. It is never proof that a file owns a workflow. It does not verify the current worktree.
76
+ Repository inventory contains discovery hints. It is never proof that a file owns a workflow and does not verify the current worktree.
77
77
 
78
78
  Package scripts, executable paths, and instruction paths come from stage-0 entries in the Git index. Package content comes from indexed blobs. Git reads the objects locally in one check batch and one content batch. Lazy object fetching and replacement refs are disabled. Inventory never opens working-tree package paths.
79
79
 
80
- Executables need index mode `100755`. Instructions need a recognized name and a regular-file index mode.
81
-
82
- Skills come from Pi's effective command registry. Their canonical source paths must stay inside the repository.
80
+ Executables need index mode `100755`. Instructions need a recognized name and a regular-file index mode. Skills come from Pi's effective command registry, and their canonical source paths must stay inside the repository.
83
81
 
84
82
  Available inventory includes this provenance:
85
83
 
@@ -92,9 +90,7 @@ Available inventory includes this provenance:
92
90
  }
93
91
  ```
94
92
 
95
- It also sets `worktreeVerified:false`. Staged adds, changes, and deletes affect the snapshot. Unstaged changes, deletions, mode changes, symlinks, and untracked files do not.
96
-
97
- Inspect the current candidate files before assigning ownership. Abstain if targeted current-file checks cannot be done safely.
93
+ It also sets `worktreeVerified:false`. Staged adds, changes, and deletes affect the Git-index collections. Unstaged changes, deletions, mode changes, symlinks, and untracked files do not affect those collections. Skills come from Pi's effective registry and can include untracked files. Inspect current candidate files before assigning ownership; abstain if targeted current-file checks cannot be done safely.
98
94
 
99
95
  ## Flow
100
96
 
@@ -114,36 +110,22 @@ Search makes no model calls.
114
110
 
115
111
  Discovery excludes the current session file when its path is available. Forked sessions collapse into their parent when both match.
116
112
 
117
- Before browse, discovery, or pattern preparation, the extension lazily syncs the index from the session tree.
118
-
119
- Pattern preparation reports `sync.walkComplete`, `sync.backlogRemaining`, and `sync.complete`. `sync.complete` is true only after a complete walk with no backlog.
113
+ Before browse, discovery, or pattern preparation, the extension lazily syncs the index from the session tree. Pattern preparation reports `sync.walkComplete`, `sync.backlogRemaining`, and `sync.complete`; `sync.complete` is true only after a complete walk with no backlog.
120
114
 
121
115
  ### Retrieval safety
122
116
 
123
117
  Discovery returns short snippets from indexed user and assistant transcript text. Use a result's `path` and `matchMessageId` with SCROLL for targeted context; READ and SCROLL retrieve raw messages, including tool-result messages when present.
124
118
 
125
- Pattern preparation returns only non-empty user and assistant text. It never returns thinking blocks or tool-result content. Preparation keeps citation and lineage metadata when a source cannot be read.
119
+ Pattern preparation returns only non-empty user and assistant text. It never returns thinking blocks or tool-result content, and preserves citation and lineage metadata when a source cannot be read.
126
120
 
127
121
  Historical tool output may contain secrets or other sensitive data. Raw retrieval places that output in active model context.
128
122
 
129
123
  ## State and storage
130
124
 
131
- The extension maintains the derived SQLite search index at `~/.pi/agent/config/pi-session-recall/index.db`.
132
-
133
- This is derived state. Delete it and it rebuilds from your session files.
125
+ The extension maintains its derived SQLite search index at `~/.pi/agent/config/pi-session-recall/index.db`. Delete this derived state to rebuild it from your session files; no migration or recovery machinery is needed.
134
126
 
135
127
  The index and transcript reads stay local. Transcripts are read in place. Returned content follows the data path of your configured model provider.
136
128
 
137
- ## Roll back
138
-
139
- Pin the previous release:
140
-
141
- ```bash
142
- pi install npm:@henryqw/pi-session-recall@2.1.1
143
- ```
144
-
145
- No index migration or cleanup is needed.
146
-
147
129
  ## Limits and recovery
148
130
 
149
131
  Lazy index sync can fail while walking the session tree. Results still come from the current index and can be partly updated or stale. Files found before failure may have new content, while rows for files the walk did not reach stay stale.
@@ -154,15 +136,11 @@ Lazy index sync can fail while walking the session tree. Results still come from
154
136
 
155
137
  Session directories whose encoded path starts with `--tmp-` or `--private-tmp-` are never indexed. These sessions run from `/tmp` or `/private/tmp`.
156
138
 
157
- Session files over 32 MiB are excluded from indexing and hydration. Discovery cannot newly find them.
158
-
159
- READ and SCROLL return an explicit size error. Discovery returns the indexed metadata even when a source file changes afterward.
139
+ Session files over 32 MiB are excluded from indexing and hydration, so discovery cannot newly find them. READ and SCROLL return an explicit size error. Discovery returns indexed metadata even when a source file changes afterward.
160
140
 
161
141
  Pattern preparation runs one sync pass. A positive backlog or incomplete walk limits the sample and sets `sync.complete:false`. A total sync or required repository-inventory failure returns an explicit tool error.
162
142
 
163
- Repository scope fails outside Git or when repository inventory fails. All scope still returns its corpus in both cases.
164
-
165
- Outside Git, all scope sets `inventory.available:false` with `reason:"not-a-git-repository"`. On a repository inventory error, it uses `reason:"inventory-failed"`. Cancellation always aborts the call instead of returning unavailable inventory.
143
+ Repository scope fails outside Git or when repository inventory fails. All scope still returns its corpus when Git-root lookup exits nonzero (`inventory.available:false`, `reason:"not-a-git-repository"`) or inventory fails after the root is resolved (`reason:"inventory-failed"`). If the working directory cannot be resolved, Git cannot start, root lookup overflows or produces invalid output or unexpected stderr, or the call is cancelled, preparation fails even with all scope; these failures do not return unavailable inventory.
166
144
 
167
145
  Preparation rejects `query`, session cursors, or `window` in the same call. It also rejects `scope` without the operation.
168
146
 
@@ -173,3 +151,13 @@ Inventory fails if the Git root output exceeds 4 KiB or the raw index listing ex
173
151
  Inventory accepts at most 512 package manifests. Each indexed manifest can be at most 1 MiB, and their declared sizes can total at most 16 MiB. One bounded batch checks all blob sizes before one bounded batch reads their content. Blob order, type, size, UTF-8, and exact output framing are checked before manifest data is parsed.
174
152
 
175
153
  Session and top-level `contentTruncated` report transcript budget trimming only. Session `truncated` reports omitted middle messages.
154
+
155
+ ### Rollback
156
+
157
+ To return to the older 2.1.1 behavior, pin that release:
158
+
159
+ ```bash
160
+ pi install npm:@henryqw/pi-session-recall@2.1.1
161
+ ```
162
+
163
+ No index migration or cleanup is needed.
@@ -315,10 +315,6 @@ function parseSessionFile(filePath: string, maxBytes: number): ParsedFile {
315
315
  return parsed;
316
316
  }
317
317
 
318
- function isJunkEncodedDir(relSegments: string[]): boolean {
319
- return relSegments.some((seg) => seg.startsWith("--tmp-") || seg.startsWith("--private-tmp-"));
320
- }
321
-
322
318
  /** Walk result. `complete: false` means the tree could not be fully read
323
319
  * (missing root, readdir/stat failure) — callers must not treat unseen
324
320
  * indexed paths as deleted. */
@@ -329,11 +325,10 @@ interface WalkResult {
329
325
 
330
326
  function walkJsonlFiles(sessionsDir: string): WalkResult {
331
327
  const files = new Map<string, fs.Stats>();
332
- if (!fs.existsSync(sessionsDir)) return { files, complete: false };
333
- const stack: { dir: string; rel: string[] }[] = [{ dir: sessionsDir, rel: [] }];
328
+ const stack = [sessionsDir];
334
329
  let complete = true;
335
330
  while (stack.length > 0) {
336
- const { dir, rel } = stack.pop()!;;
331
+ const dir = stack.pop()!;
337
332
  let entries: fs.Dirent[];
338
333
  try {
339
334
  entries = fs.readdirSync(dir, { withFileTypes: true });
@@ -346,8 +341,8 @@ function walkJsonlFiles(sessionsDir: string): WalkResult {
346
341
  if (ent.isDirectory()) {
347
342
  // Junk dirs are pruned before descent so a large ignored tree never
348
343
  // costs a walk + per-file stats on every sync pass.
349
- if (isJunkEncodedDir([...rel, ent.name])) continue;
350
- stack.push({ dir: full, rel: [...rel, ent.name] });
344
+ if (ent.name.startsWith("--tmp-") || ent.name.startsWith("--private-tmp-")) continue;
345
+ stack.push(full);
351
346
  } else if (ent.isFile() && ent.name.endsWith(".jsonl")) {
352
347
  try {
353
348
  files.set(full, fs.statSync(full));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-session-recall",
3
- "version": "4.0.1",
3
+ "version": "4.0.3",
4
4
  "description": "Local FTS5 search over past Pi sessions plus a skill for turning recurring work into deterministic automation.",
5
5
  "keywords": [
6
6
  "pi-package",