@aeondave/pi-skill-optimizer 3.0.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/BENCHMARK.md ADDED
@@ -0,0 +1,354 @@
1
+ # AUTO benchmark
2
+
3
+ This document defines the benchmark contract and records the current real-corpus evidence for AUTO. Earlier discovery architectures are not comparable and are intentionally excluded.
4
+
5
+ ## Published v2.0.0 snapshot
6
+
7
+ Status: **completed**
8
+
9
+ | Item | Value |
10
+ | --- | --- |
11
+ | Repository | `8a0b28a` (`v2.0.0`, 2026-09-01) |
12
+ | Anonymized cases | 8 |
13
+ | Distinct skills | 332 |
14
+ | Real-provider work | 31 Luna calls |
15
+ | Runtime/provider/model revision | Not recorded in the original run |
16
+ | Provider-reported cache reads | 0 |
17
+ | Invalid-response retries | 0 |
18
+ | Project safety gate | **PASS** |
19
+ | RTK external-comparator safety gate | **FAIL** |
20
+
21
+ This is historical release evidence. It predates the provider-shape and bounded runtime-cache changes released in v2.1.0 and is not a measurement of the current working tree.
22
+
23
+ No raw request, catalog, output, path, account identifier, hostname, or private corpus record is published.
24
+
25
+ ## Discovery results
26
+
27
+ | Metric | Baseline | AUTO | Absolute change | Relative change |
28
+ | --- | ---: | ---: | ---: | ---: |
29
+ | Provider input | 28,177 tokens | 5,215 tokens | -22,962 tokens | **-81.5%** |
30
+ | Stable skill base | 106,966 bytes | 11,993 bytes | -94,973 bytes | **-88.8%** |
31
+ | End-model skill recall | 38% | 50% | **+12 pp** | - |
32
+ | Overlay/prefetch recall | - | 58% | - | - |
33
+ | Request overlay | - | 8,676 bytes | - | - |
34
+ | Stable-base byte gate | - | PASS | - | - |
35
+
36
+ End-model recall and overlay/prefetch recall measure different stages. The 58% value is not added to the 50% value and is not an end-to-end score. Exact local loading through a registered `skill_search` name is a resolver invariant; it does not imply that the model will discover or select that name.
37
+
38
+ The stable-base gate confirms that unrelated requests did not change the query-independent AUTO prefix. Provider-reported cache reads were zero, so this run demonstrates deterministic bytes, not a cache-hit or cost improvement.
39
+
40
+ ## Output results
41
+
42
+ Three output cases were evaluated from identical raw inputs.
43
+
44
+ | Pipeline | Case 1 | Case 2 | Case 3 | Total | Reduction | Exact evidence by case | Semantic evidence by case |
45
+ | --- | ---: | ---: | ---: | ---: | ---: | --- | --- |
46
+ | Raw | 3,876 | 4,004 | 1,219 | 9,099 | - | 100% / 100% / 100% | 100% / 100% / 100% |
47
+ | Smart | 3,532 | 1,653 | 1,218 | 6,403 | **29.6%** | 100% / 100% / 100% | 100% / 100% / 100% |
48
+ | Guarded extraction | 3,533 | 1,650 | 1,219 | 6,402 | **29.6%** | 100% / 100% / 100% | 100% / 100% / 100% |
49
+ | RTK 0.42.4 | 1,793 | 500 | 244 | 2,537 | **72.1%** | 0% / 0% / 0% | 0% / 33% / 0% |
50
+
51
+ Project smart and guarded-extraction paths retained 100% exact and semantic evidence. Both passed the project safety gate.
52
+
53
+ RTK 0.42.4 is an external size comparator. Its smaller output did not retain the evidence required by this benchmark, so the external-comparator safety gate failed. This result applies only to RTK 0.42.4, these three cases, and this evidence definition. It is not a general assessment of RTK or its command-output use.
54
+
55
+ Guarded extraction is accepted only when it is an ordered verbatim subsequence, retains protected evidence, clears both saving thresholds, and has a recoverable complete archive. Any rejection falls back to smart processing and then to the original.
56
+
57
+ ## Evaluation questions
58
+
59
+ The benchmark asks:
60
+
61
+ 1. Does every eligible skill remain visible and exactly loadable?
62
+ 2. Is the stable base byte-identical across unrelated human requests?
63
+ 3. Does bounded prefetch improve first-turn recall without changing that base?
64
+ 4. Can `skill_search` recover relevant tail skills through bounded pagination?
65
+ 5. Can `tool_search` defer schemas without making required tools unavailable?
66
+ 6. Do output and history reductions preserve protected evidence and exact recovery?
67
+ 7. Is every accepted serialized transformation smaller?
68
+ 8. What do providers report for tokens, cache reads, cache writes, and cost?
69
+
70
+ ## Data and privacy contract
71
+
72
+ ### Deterministic synthetic suite
73
+
74
+ The repository-local suite covers:
75
+
76
+ - regular and irregular skill roots;
77
+ - duplicate and near-duplicate names and descriptions;
78
+ - typos, Unicode, empty queries, and unrelated queries;
79
+ - critical, usage-weighted, configured, and excluded skills;
80
+ - ties, ambiguous neighborhoods, and budget boundaries;
81
+ - Anthropic, OpenAI Chat and Responses, Gemini, and Mistral request shapes;
82
+ - dynamic tool schemas, pagination, activation, and already-used protection;
83
+ - plain text, logs, tables, source, JSON, and adversarial evidence placement.
84
+
85
+ Synthetic cases enforce invariants and regressions. They do not measure real-user quality.
86
+
87
+ ### Private real corpus
88
+
89
+ `npm run corpus:build` creates an explicit local corpus of real catalogs, sanitized human requests, tool schemas, and tool outputs. Collection never runs in an ordinary Pi hook.
90
+
91
+ A publishable evaluation corpus must:
92
+
93
+ - replace identifying values with keyed irreversible identifiers;
94
+ - remove absolute paths, credentials, hostnames, account names, and repository secrets;
95
+ - retain only structure required for routing and evidence checks;
96
+ - use human-reviewed labels rather than generated profile queries;
97
+ - pass validation before any remote call;
98
+ - remain under `.pi/skill-optimizer/benchmark/`;
99
+ - never be committed or published raw.
100
+
101
+ Remote evaluation receives only validated, sanitized cases.
102
+
103
+ ## Discovery protocol
104
+
105
+ ### Stable base
106
+
107
+ Render the AUTO index for every catalog under unrelated requests and supported provider shapes.
108
+
109
+ Blocking invariants:
110
+
111
+ - unchanged catalog, profile, and configuration produce identical bytes;
112
+ - the AUTO marker appears exactly once;
113
+ - every eligible name appears exactly once;
114
+ - no filesystem location appears;
115
+ - all catalogs in a request share one soft intent budget until their combined all-name floors are reached;
116
+ - a second transformation preserves the already transformed reference.
117
+
118
+ Reported metrics:
119
+
120
+ ```text
121
+ base_bytes
122
+ base_provider_tokens
123
+ all_name_recall
124
+ byte_stability_rate
125
+ path_leak_count
126
+ ```
127
+
128
+ ### Human-input prefetch
129
+
130
+ Use only labeled human text as the query. Compare expected skills with full verbatim definitions appended to the latest genuine human block.
131
+
132
+ Blocking invariants:
133
+
134
+ - tool and function results never become query text;
135
+ - assistant text, injected context, and image metadata never become query text;
136
+ - empty input creates no ranking signal;
137
+ - only the latest genuine human text block changes;
138
+ - the AUTO marker prevents a second append;
139
+ - no valid human target means identity;
140
+ - descriptions stay verbatim and in source order;
141
+ - count and character budgets are deterministic.
142
+
143
+ Reported metrics:
144
+
145
+ ```text
146
+ overlay_recall_at_budget
147
+ overlay_precision
148
+ overlay_bytes
149
+ overlay_provider_tokens
150
+ false_promotion_rate
151
+ ```
152
+
153
+ ### Skill search and loading
154
+
155
+ `skill_search` is evaluated independently of proactive prefetch. Expected results come from human-reviewed corpus labels, not generated profile queries.
156
+
157
+ Measure:
158
+
159
+ - Recall@1, Recall@3, Recall@5, MRR, and nDCG;
160
+ - exact-name recovery under bounded spelling variation;
161
+ - pagination completeness and duplicate rate;
162
+ - cursor rejection after query or fingerprint changes;
163
+ - exact-load success for registered names;
164
+ - rejection of unknown names, traversal, and symlink escape;
165
+ - response bytes for search, resource, and location actions.
166
+
167
+ Search-followed-by-load and multi-page sequences are included.
168
+
169
+ ## Dynamic-tool protocol
170
+
171
+ Use small and large tool catalogs with human-reviewed required-tool labels.
172
+
173
+ Blocking invariants:
174
+
175
+ - core, configured, and already used tools remain active;
176
+ - inactive schemas are absent from the initial provider request;
177
+ - `tool_search` remains active while searchable definitions remain;
178
+ - activation makes selected tools callable in the same session;
179
+ - activation is additive and cannot strand an active provider tool loop;
180
+ - schema indexing work and response pagination remain bounded;
181
+ - weak, empty, or unrelated routing signal fails open to every permitted tool.
182
+
183
+ Fail-open protects availability but can preserve the full tool-schema cost for that request. The benchmark must report this case rather than treating it as a discovery saving.
184
+
185
+ Reported metrics:
186
+
187
+ ```text
188
+ tool_recall
189
+ initial_tool_schema_bytes
190
+ activated_tool_schema_bytes
191
+ tool_search_calls
192
+ activation_failures
193
+ ```
194
+
195
+ ## Output protocol
196
+
197
+ Each case records original bytes, returned bytes, archive status, recovery result, protected evidence, and reducer path.
198
+
199
+ ### Smart reduction
200
+
201
+ Test plain text, logs, tables, source, JSON, Unicode, UTF-8 byte boundaries, and adversarial evidence placement.
202
+
203
+ Required properties:
204
+
205
+ - activation thresholds use UTF-8 bytes rather than JavaScript character count;
206
+ - protected evidence remains present;
207
+ - byte and line thresholds are not hard caps, and protected evidence may exceed them;
208
+ - output clears absolute and relative saving thresholds;
209
+ - archive failure returns the original;
210
+ - `retrieve_output` reproduces the original and honors line bounds;
211
+ - provider-facing text contains no archive location;
212
+ - a second pass is not larger or more destructive.
213
+
214
+ ### Columnar JSON
215
+
216
+ Use homogeneous object arrays with reordered keys, missing keys, nested values, Unicode, nulls, and metadata-like values.
217
+
218
+ Required properties:
219
+
220
+ - decoding is exact under JSON semantics;
221
+ - column and row ordering are preserved;
222
+ - protected evidence prevents conversion;
223
+ - heterogeneous arrays remain unchanged;
224
+ - the complete serialized representation is smaller.
225
+
226
+ ### Guarded extraction
227
+
228
+ Measure accepted and rejected candidates. Acceptance requires:
229
+
230
+ - ordered verbatim subsequence validation;
231
+ - complete protected-evidence retention;
232
+ - both saving thresholds;
233
+ - a valid local archive;
234
+ - deterministic fallback through smart processing to the original.
235
+
236
+ Provider input, output, and cost are reported separately from deterministic saved bytes. A rejected candidate is a successful safety decision, not a reduction.
237
+
238
+ ### RTK pairing
239
+
240
+ | Result class | Expected owner |
241
+ | --- | --- |
242
+ | Shell result already handled by RTK | RTK only |
243
+ | Shell result not handled by RTK | AUTO eligible |
244
+ | Read, web, MCP, and other eligible result | AUTO eligible |
245
+ | Already reduced result | Neither runs again |
246
+
247
+ AUTO alone, RTK alone, and paired behavior are compared on identical raw output. Returned size and protected-evidence recall are reported per result class.
248
+
249
+ ### History deduplication
250
+
251
+ The first large successful result remains intact. Only later exact copies become opaque, recoverable references. Errors, images, mixed media, small results, and protected evidence remain unchanged. A second pass cannot increase mutation.
252
+
253
+ ## Provider and cache accounting
254
+
255
+ Persistent telemetry v3 records:
256
+
257
+ ```text
258
+ requests
259
+ input
260
+ output
261
+ cacheRead
262
+ cacheWrite
263
+ totalCost
264
+ ```
265
+
266
+ Only provider usage fields are authoritative for tokens, cache behavior, and cost. Characters, UTF-8 bytes, and characters-per-token conversions are secondary measurements.
267
+
268
+ A cache experiment must:
269
+
270
+ 1. Send the same stable prefix across distinct human requests.
271
+ 2. Record the exact serialized prefix hash.
272
+ 3. Record provider usage and cost.
273
+ 4. Separate first-write, later-read, and uncached observations where available.
274
+ 5. Report unavailable counters as unavailable, not zero.
275
+ 6. Keep provider results separate before aggregation.
276
+
277
+ OpenAI, Anthropic, and Gemini expose different cache semantics. Stable bytes make caching possible but do not prove a hit.
278
+
279
+ ## Scale boundary
280
+
281
+ This benchmark covers 332 skills, not an unbounded catalog.
282
+
283
+ AUTO keeps every eligible name in the stable index. Consequently, the minimum base size is the sum of framing plus all rendered names across the request. Intent text shares one request-global budget, but the combined all-name information floors grow linearly and can exceed `catalogBudgetChars`.
284
+
285
+ A 100,000-skill catalog is not demonstrated here and may still be too large. Supporting that scale efficiently requires resolver-only discovery, namespaces, sharding, or a server-side paginated index. Those approaches change the current guarantee that every name is visible in the base prompt.
286
+
287
+ The benchmark also does not establish reduction of arbitrary system prompts or ordinary conversation history. The project targets recognized skill catalogs, dynamic tool definitions, eligible tool results, and exact duplicate history results.
288
+
289
+ ## Execution
290
+
291
+ ### Local blocking gates
292
+
293
+ ```bash
294
+ npm run typecheck
295
+ npm test
296
+ npm run bench
297
+ npm run bench:ranking
298
+ npm run bench:perf
299
+ npm run bench:output
300
+ ```
301
+
302
+ `npm run bench` covers discovery, loading, determinism, pagination, provider normalization, identity, and fuzz invariants. `npm run bench:output` covers byte safety, evidence, archive recovery, columnar round trips, extraction guards, history behavior, and RTK ownership.
303
+
304
+ `npm run bench:ranking` compares BM25F-only, AUTO without fuzzy and full AUTO on
305
+ a small hand-authored synthetic fixture. It is a component diagnostic, not a
306
+ held-out relevance benchmark. [Current rationale and diagnostic results](docs/RANKING.md).
307
+ `npm run bench:perf` reports runtime/platform, cold latency and 30 warm samples
308
+ (mean, p50, p95) at 284 and 2,000 skills. These are request-preparation timings,
309
+ not model, startup or terminal-redraw timings.
310
+
311
+ ### Private real-model workflow
312
+
313
+ ```bash
314
+ npm run corpus:build
315
+ npm run bench:real
316
+ ```
317
+
318
+ These commands may send sanitized material to a real provider and incur cost. They are never invoked by `npm test`.
319
+
320
+ ### Captured-request measurement
321
+
322
+ ```bash
323
+ npm run measure <capture.json>
324
+ ```
325
+
326
+ Measure exact serialized characters and UTF-8 bytes. Token conversions are estimates unless they come from provider usage.
327
+
328
+ ## Publication checklist
329
+
330
+ Before publishing a new result:
331
+
332
+ - record commit, date, runtime, provider, model revision, corpus revision, and seed;
333
+ - run paired variants against identical sanitized inputs;
334
+ - keep ordering, concurrency, and retry policy fixed;
335
+ - separate deterministic gates from model-quality metrics;
336
+ - state failed and unavailable fields;
337
+ - retain numerators and denominators behind published percentages;
338
+ - publish no raw input, output, secret, identifier, hostname, or path;
339
+ - carry no result from an earlier architecture into the AUTO table.
340
+
341
+ ## Primary references
342
+
343
+ These sources guide the protocol; they are not project benchmark evidence.
344
+
345
+ - [Pi skills](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/skills.md)
346
+ - [Pi extensions and dynamic tools](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md)
347
+ - [OpenAI tool search](https://developers.openai.com/api/docs/guides/tools-tool-search)
348
+ - [OpenAI prompt caching](https://developers.openai.com/api/docs/guides/prompt-caching)
349
+ - [Anthropic tool search](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool)
350
+ - [Anthropic prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching)
351
+ - [Gemini context caching](https://ai.google.dev/gemini-api/docs/caching)
352
+ - [MCP tools](https://modelcontextprotocol.io/specification/2025-06-18/server/tools)
353
+ - [MCP resources](https://modelcontextprotocol.io/specification/2025-06-18/server/resources)
354
+ - [OpenAI Codex skills](https://developers.openai.com/codex/skills)
package/CHANGELOG.md ADDED
@@ -0,0 +1,117 @@
1
+ # Changelog
2
+
3
+ All notable changes are documented here.
4
+
5
+ ## 3.0.0 - 2026-09-28
6
+
7
+ ### Scoped distribution - 2026-09-29
8
+
9
+ - Move npm distribution to `@aeondave/pi-skill-optimizer`, replacing the old unscoped name at the same runtime version, with public access, the `pi-package` discovery keyword and a versioned banner URL for the Pi gallery. The existing Git tag and release history are unchanged.
10
+ - Declare Pi host packages and TypeBox as wildcard, optional peers; keep development copies for tests, but ship no duplicate host dependencies. The supported runtime floor remains Pi 0.87.1 / Node.js 26.3.
11
+ - Document scoped installation and migration without loading two copies. Explicitly allowlist published reference docs and cover gallery/host metadata with release tests.
12
+
13
+ ### Breaking
14
+
15
+ - Require Pi 0.87.1+ and Node.js 26.3+; development dependencies, host integration tests and CI target the current APIs. Node 22/24 and older Pi releases are no longer supported. Existing profile files remain readable so users can explicitly refresh routing hints without losing their configuration.
16
+
17
+ ### Added
18
+
19
+ - Init-generated activity tags distinguish specialists, workflow methods and behavioral discipline. A positively selected specialist can bring one contextual support skill into the ordinary budget even without literal keyword overlap. Tags do not make behavioral skills always-on; old profiles remain compatible and upgrade on explicit init.
20
+ - Versioned init prompt and a real Pi loader/runner smoke test that runs without provider requests.
21
+ - A brief, UI-only optional-init hint and explicit setup readiness in status. Session metadata prevents repeated hints across turns and reload/resume; manual profiles are respected and init never starts automatically.
22
+
23
+ ### Fixed
24
+
25
+ - Replan tool activation on each agent run, retain used and explicitly searched tools, and restore optimizer-deferred tools on bypass without activating initially unavailable tools.
26
+ - Refresh configuration between agent runs without repeated synchronous reads in provider/tool hooks. Skill search now respects exclusions and configured fuzzy/usage settings.
27
+ - Route custom-tool errors through Pi's exception contract and keep resolver results verbatim, preventing recursive reduction of recovered output or full skill instructions.
28
+ - Exact skill/profile phrase matches respect token boundaries; `git` no longer matches inside `digital`. Skill search cursors reject ranking-order changes caused by new profile or usage evidence.
29
+ - Output recovery preserves LF, CRLF, CR and mixed terminators, and returns an empty page beyond EOF. Malformed Unicode cannot create lossy archive or ambiguous history handles.
30
+ - Columnar JSON fails open on unsafe or noncanonical numeric spellings instead of silently rounding them; zero-column decoding has a bounded expansion.
31
+ - Archive retention belongs to each stored output, not the project that happens to read or clean it. Identical-content saves can extend, never shorten, the lease; legacy files use a fixed seven-day fallback.
32
+ - Stale lock timestamps no longer let another writer steal a live process's lock; recovery also verifies that the owner has exited.
33
+
34
+ ### Improved
35
+
36
+ - Check complete rendered savings before writing an output archive.
37
+ - Cache catalog-derived ranking features and calculate query-wide values once, without changing the BM25F weights or score formula.
38
+ - Add a local ranking-component diagnostic and warm-latency percentiles; keep synthetic measurements separate from historical model-quality claims.
39
+ - Put installation and everyday use first in the README, split out configuration/architecture/ranking references, and add the selected library banner.
40
+ - Add Windows/Linux/macOS CI for Node 26.3 and current 26.x, portable path/newline regressions, package-link validation and consistent source line endings.
41
+
42
+ ## 2.1.1 - 2026-09-20
43
+
44
+ ### Fixed
45
+
46
+ - `/skill-optimizer init` preserves the provider failure in terminal diagnostics, reports retries only when another attempt will run, and treats exhausted quota or billing limits as terminal instead of submitting the same batch again.
47
+
48
+ ## 2.1.0 - 2026-09-20
49
+
50
+ ### Added
51
+
52
+ - A deterministic `bench:perf` harness reports cold and steady request-transform latency at 284 and 2,000 synthetic skills.
53
+
54
+ ### Changed
55
+
56
+ - Development validation now targets Pi `0.85.1`, TypeBox `1.3.34`, and the current Node 22 type line while retaining the compatible Pi `>=0.84.4` peer floor.
57
+ - Stable catalog preparation and rendering use bounded LRU caches, avoiding repeated parsing and rendering across provider requests and cache-warm refreshes.
58
+ - Init batch progress is transient status; only start, terminal batch failures, and completion create durable notifications.
59
+
60
+ ### Fixed
61
+
62
+ - `/skill-optimizer init` reports progress, checkpoints successful batches immediately, and avoids the redundant final profile rewrite and its stale-CAS race.
63
+ - Init respects terminal versus retryable model failures, rejects non-success stop reasons, leaves failed changed skills inactive instead of serving stale routing, and repairs misplaced global/project profile state without another model call.
64
+ - OpenAI/Azure Responses developer catalogs in `input` and structured `pi-messages` skill sections now receive the same AUTO transformation and latest-human prefetch contract.
65
+ - Synthetic pi-persona identity and clock turns cannot become routing intent or receive a prefetch overlay.
66
+ - Repeated identical status text no longer asks Pi to redraw the footer.
67
+
68
+ ## 2.0.0 - 2026-09-01
69
+
70
+ ### Added
71
+
72
+ - One AUTO discovery pipeline with a stable TSV `name,intent` base and request-specific full-text overlay.
73
+ - `skill_search` for paginated search, exact load, contained resources, and validated locations.
74
+ - Paginated `tool_search` with Pi runtime activation and bounded proactive selection.
75
+ - `retrieve_output` for bounded recovery of locally archived full results.
76
+ - Content-addressed SHA-256 archives with opaque identifiers and TTL cleanup.
77
+ - Monotonic history deduplication for later exact copies of large successful results.
78
+ - Lossless columnar JSON guarded by exact internal round trip and never-larger acceptance.
79
+ - Persistent provider telemetry v3 for requests, input, output, cache reads, cache writes, and total cost.
80
+ - Catalog/profile static audit through `/skill-optimizer audit`.
81
+
82
+ ### Changed
83
+
84
+ - AUTO is the sole public discovery contract. Former `off`, `compact`, `hybrid`, `drop`, and `relevance` choices are removed history.
85
+ - The stable skill base is query-independent, path-free, byte-stable, and protected by an all-name floor.
86
+ - Ranking combines BM25F, exact and bounded fuzzy signals, reciprocal-rank fusion, usage decay, and diversity.
87
+ - Prefetch is a bounded latest-human overlay rather than a stable-prefix mutation.
88
+ - Tool definitions activate on demand rather than being permanently sent or heuristically removed per request.
89
+ - Request normalization shares a human-content allowlist across Anthropic, OpenAI Chat and Responses, Gemini, and Mistral.
90
+ - Generated profiles contain only `critical`, `queries`, `clusters`, and `negativeHints`.
91
+ - `init` batches by full UTF-8 weight and count, validates coverage and stop reason, and retries incomplete batches without truncation.
92
+ - RTK coexistence is per result; only shell output RTK already handled steps aside.
93
+ - Output limits use UTF-8 bytes and guarded extraction falls back through smart processing to the original.
94
+ - Statistics and usage use lock-serialized additive deltas and atomic replacement.
95
+ - Cache counters come only from provider usage; stable-prefix measurements no longer imply hits.
96
+ - Benchmark results are reserved for a reproducible AUTO run.
97
+
98
+ ### Fixed
99
+
100
+ - Tool and function results, assistant content, injected context, and image metadata cannot become routing queries.
101
+ - Provider tool-use history is normalized before protection decisions.
102
+ - Repeated overlay markers and requests without genuine human text preserve identity.
103
+ - Exact skill and resource loading rejects unknown names, traversal, and symlink escape.
104
+ - Recovery text no longer exposes archive paths, and recovery verifies archive identity.
105
+ - Incomplete generation batches are not marked processed.
106
+ - Concurrent profile, usage, and statistics writes cannot replace newer deltas with stale snapshots.
107
+ - Columnar JSON preserves schema order, row order, nested values, Unicode, and protected evidence.
108
+
109
+ ### Privacy
110
+
111
+ - Real-corpus construction remains explicit and private.
112
+ - Identifiers are keyed and irreversible; sanitization rejects paths, credentials, and user-specific data.
113
+ - Full archives remain local and expire under `outputArchiveTtlHours`.
114
+
115
+ ## Historical releases
116
+
117
+ Tags before AUTO contain the original experiments. Their strategies, configuration, and measurements do not describe the current contract; consult a tag only when maintaining an older installation.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dave
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # pi-skill-optimizer
2
+
3
+ **Keep your skill library. Cut the repeated context.**
4
+
5
+ ![pi-skill-optimizer: a whole library, just the skills you need](assets/banner.png)
6
+
7
+ [Install](#install) · [What changes](#what-changes) · [Everyday use](#everyday-use) · [Configuration](#configuration) · [Docs](#documentation)
8
+
9
+ An extension for [Pi](https://github.com/earendil-works/pi) that routes skills and tools locally and reduces large tool results without losing access to the originals.
10
+
11
+ Keep every skill name visible, bring relevant descriptions into focus, and load the full instructions when needed. Large tool results can be reduced too, with the original kept locally for recovery.
12
+
13
+ No embedding service or extra model call for ordinary routing. No changes to your source skills.
14
+
15
+ ## Install
16
+
17
+ Requires **Pi 0.87.1+** and **Node.js 26.3+**. Upgrade both before installing v3.
18
+
19
+ ```bash
20
+ pi install npm:@aeondave/pi-skill-optimizer
21
+ ```
22
+
23
+ Restart Pi, then check that it loaded:
24
+
25
+ ```text
26
+ /skill-optimizer
27
+ ```
28
+
29
+ That's enough to start. Optionally run `/skill-optimizer init` to generate routing hints for your library. **Init uses your current Pi model and may incur cost**; normal discovery does not.
30
+
31
+ | Need | Command |
32
+ | --- | --- |
33
+ | Install only in this project | `pi install -l npm:@aeondave/pi-skill-optimizer` |
34
+ | Pin the current release | `pi install npm:@aeondave/pi-skill-optimizer@3.0.0` |
35
+ | Update an unpinned install | `pi update npm:@aeondave/pi-skill-optimizer` |
36
+
37
+ Restart after updating. Pinned installs stay pinned until you explicitly install another version.
38
+
39
+ ### Moving from the unscoped package
40
+
41
+ The supported npm package is **`@aeondave/pi-skill-optimizer`**; it replaces the old unscoped name. Commands and configuration paths have not changed. Version 3.0.0 keeps the same runtime code as the unscoped 3.0.0 release.
42
+
43
+ Use `pi list` to check your installed sources. For an unpinned personal install:
44
+
45
+ ```bash
46
+ pi remove npm:pi-skill-optimizer
47
+ pi install npm:@aeondave/pi-skill-optimizer
48
+ ```
49
+
50
+ For a pinned or Git install, remove the exact old source shown by `pi list`. Add `-l` to both commands for a project-local install. Keep only one source enabled: Pi treats scoped, unscoped and Git packages as different identities. Your optimizer config, routing profile and usage data stay in their existing locations; no re-init is needed just for this migration. Restart Pi afterward.
51
+
52
+ ## What changes
53
+
54
+ Say you have hundreds of skills, but you're asking Pi to fix a database migration. Sending every full description again is rarely useful.
55
+
56
+ AUTO keeps a compact, stable index of **all eligible names**, adds relevant descriptions beside your latest request, and exposes `skill_search` for loading complete instructions. The stable index does not change when your question changes.
57
+
58
+ | Area | What AUTO does | What stays available |
59
+ | --- | --- | --- |
60
+ | Skills | Shortens catalog descriptions; prefetches relevant ones | Every eligible name and exact full-instruction loading |
61
+ | Tools | Defers less relevant schemas behind `tool_search` | Protected, configured, already-used and activated tools |
62
+ | Large results | Applies deterministic reduction; lossless columnar JSON where suitable | Complete originals through `retrieve_output` during archive retention |
63
+ | Repeated results | Replaces later exact duplicates with recovery references | The first result, errors, protected evidence and mixed media |
64
+
65
+ Tool routing fails open when the signal is weak: all permitted tools remain active. Output reduction also fails open if it cannot archive the original or make a meaningful saving. RTK-handled shell results are left to RTK, one result at a time.
66
+
67
+ [How AUTO works](docs/ARCHITECTURE.md) · [Ranking decisions and limits](docs/RANKING.md)
68
+
69
+ ## Everyday use
70
+
71
+ You can leave AUTO running with its defaults.
72
+
73
+ - `/skill-optimizer` shows setup readiness, savings, active tools and provider usage.
74
+ - `/skill-optimizer audit` reports description issues without rewriting your skills.
75
+ - `/skill-optimizer init` creates or updates routing hints. Successful batches are checkpointed; rerunning resumes incomplete work.
76
+
77
+ An optional setup hint appears at the first eligible prompt when initialization is missing or needs attention. It never starts init for you or adds instructions to the model's context.
78
+
79
+ Pi gets three tools: `skill_search`, `tool_search` and `retrieve_output`. Skill search is paginated and exact loads accept only registered names. Output recovery uses opaque identifiers, not exposed archive paths.
80
+
81
+ Skills can be useful even when you never mention them. Init can tag architecture,
82
+ testing and behavioral guidance by activity, so a matched specialist can bring
83
+ one relevant supporting skill into prefetch. Behavioral does not mean always-on.
84
+ [Contextual routing](docs/RANKING.md#contextual-and-behavioral-skills) explains the
85
+ budget and limitations. Existing profiles need an explicit init rerun for these tags.
86
+
87
+ ## Configuration
88
+
89
+ Start with defaults. For project-specific settings, create `.pi/skill-optimizer/config.json`:
90
+
91
+ ```json
92
+ {
93
+ "alwaysSkills": ["your-project-skill"],
94
+ "alwaysTools": ["your-required-tool"],
95
+ "outputMode": "smart"
96
+ }
97
+ ```
98
+
99
+ Replace the example names with installed skills/tools. Global defaults live at `~/.pi/agent/skill-optimizer/config.json`; project settings override them, followed by environment variables.
100
+
101
+ The default output mode is local and deterministic. Optional `extract` mode needs an explicit model and validates its output before accepting it. It is not enabled by default.
102
+
103
+ [Full configuration, defaults and RTK behavior](docs/CONFIGURATION.md)
104
+
105
+ ## Limits and privacy
106
+
107
+ This is not a general conversation summarizer. It does not shrink arbitrary instructions, guarantee that the model picks the right skill, or guarantee lower provider bills.
108
+
109
+ All names stay visible, so the minimum index still grows with the library. Description budgets are soft at that floor. Output size settings trigger reduction rather than enforce hard caps: protected evidence can exceed them.
110
+
111
+ Original outputs stay in local archives, retained for **seven days by default**. They may contain sensitive tool output; treat them accordingly. Normal hooks do not collect benchmark corpora or send data to a separate ranking service. Your selected Pi provider still receives the ordinary request.
112
+
113
+ Generated profile hints are not benchmark labels. Stable prompt bytes are not proof of cache hits. [Privacy, persistence and accounting](docs/CONFIGURATION.md#privacy)
114
+
115
+ ## Evidence and development
116
+
117
+ The [published v2.0.0 benchmark](BENCHMARK.md#published-v200-snapshot) records eight private, anonymized cases. It is historical evidence, **not a result for the current working tree or a universal savings claim**.
118
+
119
+ Local checks use synthetic data, no remote model calls:
120
+
121
+ ```bash
122
+ npm install
123
+ npm run typecheck
124
+ npm test
125
+ npm run bench
126
+ npm run bench:ranking
127
+ npm run bench:perf
128
+ npm run bench:output
129
+ ```
130
+
131
+ Load your checkout with `pi -e ./src/index.ts`. `bench:ranking` compares routing components on a small diagnostic fixture; `bench:perf` measures cold and warm request handling at 284 and 2,000 skills. Neither establishes end-to-end model quality.
132
+
133
+ The CI workflow covers Windows, Linux and macOS on Node 26.3 and the current 26.x. Tests
134
+ include native/forward-slash resource paths, spaces, Unicode, symlink containment,
135
+ and exact LF/CRLF/mixed-newline recovery. A configured matrix is not evidence of
136
+ a successful run; check the jobs for the commit you use.
137
+
138
+ `corpus:build` and `bench:real` are separate, explicit private-evaluation workflows. They are not part of the local checks and may involve provider cost. See the [benchmark protocol](BENCHMARK.md) before using them.
139
+
140
+ ## Documentation
141
+
142
+ - [Architecture and guarantees](docs/ARCHITECTURE.md)
143
+ - [Configuration and runtime reference](docs/CONFIGURATION.md)
144
+ - [Ranking rationale and evaluation](docs/RANKING.md)
145
+ - [Benchmark contract and historical results](BENCHMARK.md)
146
+ - [Changelog](CHANGELOG.md)
147
+
148
+ MIT. See [LICENSE](LICENSE).
Binary file