pi-canon 0.2.2 → 0.2.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 +11 -11
- package/extensions/canon.ts +22 -18
- package/extensions/lib/retrieval.ts +23 -27
- package/extensions/lib/surfacing.ts +19 -17
- package/extensions/lib/tool.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Or clone this repo into `~/.pi/agent/extensions/`. Node 22.18 or later, Pi 0.83
|
|
|
16
16
|
|
|
17
17
|
## The first article
|
|
18
18
|
|
|
19
|
-
A session is not greeted: through 0.2.0 every session opened with an orientation line
|
|
19
|
+
A session is not greeted: through 0.2.0 every session opened with an orientation line. A 2x2 experiment with an inert implementation found significant negative main effects for both that line and the tool schema, but their 19/32 versus 21/32 comparison did not resolve which component cost more. Study 3 detected no benefit loss when the line was removed, so 0.2.1 deleted it. The tool description carries the doctrine instead. The first article takes one tool call:
|
|
20
20
|
|
|
21
21
|
```json
|
|
22
22
|
{ "action": "write",
|
|
@@ -82,7 +82,7 @@ pi-canon is an increment on the pattern rather than a replacement for it, and it
|
|
|
82
82
|
|
|
83
83
|
**A spine**, the addressing convention. An article's address is computed from the asset instead of searched for, and nothing has to be configured for that mapping to hold, which makes the spine a convention rather than a mode. It is also why nothing in the RECALL path searches: when a touch already decided the address, there is nothing to find. The `search` action exists for the opposite direction, the agent that wants to ask, and it never runs unasked.
|
|
84
84
|
|
|
85
|
-
**Surfacing**, push rather than pull. When a tool call is detected touching a governed asset, that article's capsule is staged for the session, at most once per article, so nobody has to think to ask. Detection of a path inside a tool call is best effort. Resolution, once a path is in hand, is not.
|
|
85
|
+
**Surfacing**, push rather than pull. When a tool call is detected touching a governed asset, that article's capsule is staged for the session, at most once per article while it stays in context (see Surfacing), so nobody has to think to ask. Detection of a path inside a tool call is best effort. Resolution, once a path is in hand, is not.
|
|
86
86
|
|
|
87
87
|
The evaluation below does not test that lineage argument: no evaluated arm is a search-driven LLM wiki, so nothing here shows pi-canon beats a disciplined one.
|
|
88
88
|
|
|
@@ -96,7 +96,7 @@ A rename is a file move you make yourself. pi-canon does not watch the filesyste
|
|
|
96
96
|
|
|
97
97
|
An article matching no asset is ordinary free knowledge. The spine guarantees an address for the assets a project already has; it does not confine the store to them. The tradeoff is worth stating in the same breath: surfacing is asset-scoped, so an off-spine article is reached by a link or an explicit read rather than pushed on a touch, or by relevance when a retriever is configured.
|
|
98
98
|
|
|
99
|
-
Such an article may say so, with `scope: rule` on the write.
|
|
99
|
+
Such an article may say so, with `scope: rule` on the write. Forgetting the declaration never excludes an off-spine article from retrieval. Declaring it separates a rule filed on purpose from an article whose asset disappeared, and keeps that rule in the retrieval corpus if an asset later appears at the same address. `scope: asset` takes the declaration back.
|
|
100
100
|
|
|
101
101
|
## The tool
|
|
102
102
|
|
|
@@ -120,7 +120,7 @@ One lint line is different in kind. When a write supplies a body and an article
|
|
|
120
120
|
|
|
121
121
|
## Surfacing
|
|
122
122
|
|
|
123
|
-
A tool call stages the governing article for whatever it touched and sends nothing. Each turn end flushes everything staged as a single message, because pi's steering queue drains one message per provider round trip and a message per tool call would buy every nudge its own model call. An article surfaces at most once
|
|
123
|
+
A tool call stages the governing article for whatever it touched and sends nothing. Each turn end flushes everything staged as a single message, because pi's steering queue drains one message per provider round trip and a message per tool call would buy every nudge its own model call. An article with a presence mark surfaces at most once while that mark remains in the context the provider receives; one folded or compacted away returns to surfacing and rides again on its asset's next touch (the `resurface` option below). Delivered text shorter than 24 normalized characters cannot be tested safely and conservatively stays seen for the session. Nothing persists across sessions: a new session re-surfaces everything.
|
|
124
124
|
|
|
125
125
|
No character count decides any of this. A capsule is written to fit 1,000 characters, and that is a target handed to the agent at write time, not a gate at read time: an article whose governing asset a turn touched surfaces whole or does not surface. Earlier versions charged capsule text against a session allowance and degraded the overflow to bare pointers. That allowance was removed in 2.0. It was a constant guessing at a policy nobody had measured, and what it decided was how much an agent got to see. What stands in its place is measurement: every surfaced line records what it cost the window, so context taken can be read against relevance afterwards instead of a constant ruling on it in advance. The one remaining reason a line is not capsule text is an article that has no capsule, which surfaces as a pointer naming the address and telling the agent to read it.
|
|
126
126
|
|
|
@@ -147,10 +147,10 @@ Six keys, and any other throws at registration by name, because everything else
|
|
|
147
147
|
|
|
148
148
|
- **`root`** places the store. Absolute is used as given, relative joins the project cwd. Default `<project>/.canon`.
|
|
149
149
|
- **`surface: false`** silences the per-turn flush and the settle reminder. The `pi_canon` tool and `/pi-canon` stay registered and working.
|
|
150
|
-
- **`resurface: false`** returns an article to surfacing at most once per session however long ago it left the window. The default is `true`: an article counts as seen only while
|
|
151
|
-
- **`retrieval`** ranks the
|
|
150
|
+
- **`resurface: false`** returns an article to surfacing at most once per session however long ago it left the window. The default is `true`: an article with a presence mark counts as seen only while that mark remains in the context the provider receives, so one folded or compacted away surfaces again the next time its asset is touched. Text shorter than 24 normalized characters has no safe mark and conservatively retains the once-per-session behavior. A fresh touch is what brings a marked article back, so nothing re-surfaces on its own.
|
|
151
|
+
- **`retrieval`** ranks the retrieval corpus against what the agent is doing: every off-spine article, plus any article declared `scope: rule` so a rule stays reachable if an asset later appears at its address. Ordinary asset-scoped articles stay out because the address spine already reaches them. The default is `"none"`, which ranks and surfaces nothing by relevance: the spine alone, exactly as 1.0. `"lexical"` is BM25 over the standard library, no dependency and no model. Anything that needs a model is supplied here as `{ name, score, index? }`, so this package never carries one and never decides which you run. With a retriever configured the tool's filing rule changes with it, because the advice costs knowledge in either direction. On the default it says knowledge filed off the asset path never surfaces, which is true and is why you should not file it there. With a retriever it says the opposite: a constraint governing many assets and owning none belongs at its own address naming the rule, because the only parent unrelated packages share is the root and a root article surfaces on every touch of anything.
|
|
152
152
|
|
|
153
|
-
- **`standout`** is how far the best-ranked article must beat the best one that will not ride anyway, meaning the fourth, the one the three-per-message cap was already going to leave behind. A multiple, not a score: `standout: 1.5` asks for the best to score half again what the first held-back rival scored. Default `1.4`, an operating point priced by a 120-cell benchmark rather than picked:
|
|
153
|
+
- **`standout`** is how far the best-ranked article must beat the best one that will not ride anyway, meaning the fourth, the one the three-per-message cap was already going to leave behind. A multiple, not a score: `standout: 1.5` asks for the best to score half again what the first held-back rival scored. Default `1.4`, an operating point priced by a 120-cell benchmark rather than picked: its n=15 comparison with the uncut channel differed by -0.07 rule facts at p=1.0 while cutting suggestions from 26 a session to 3, raised the rate at which the agent acted on one from 0.17 to 0.82, and never fired at all on a store with nothing relevant to say, 0 rankings of 139. That small observed contrast is not a general detection bound. Precision is the side to protect, though the measured argument is tokens rather than attention: a companion 124-cell study found good suggestions opened at similar rates buried among twenty-seven as one of four, so what the cutoff saves is the context it declines to spend on lines that were never going to be read. The other side has a price too, and the same benchmark paid it: a cutoff set past what a decisive ranking reaches silences the channel, and at 2.0 it delivered nothing and gave back everything the channel had won. `standout: 1` is no cutoff, the measurement setting for reading your own store's trace. Below `1` throws at registration, because it asks for the best article to be worse than its rival and is what a caller writes who is still thinking in scores.
|
|
154
154
|
|
|
155
155
|
**It is a ratio because a score is not the same quantity twice.** `lexical` normalizes against a saturation ceiling computed from the query, so a score is a fraction of the best match POSSIBLE for that query rather than of the best match available in your store, and it falls as the agent says more. On a 380-article store the same article at the same relevance scored 0.68 against a short question and 0.16 with a hundred words of tool output around it. Across two benchmark runs it was worse than unstable, it inverted: keeping the answers on one corpus needed a cutoff below 0.11, and silencing the other needed one above 0.73. Dividing by another score from the same query cancels both.
|
|
156
156
|
|
|
@@ -170,14 +170,14 @@ Held by the runtime:
|
|
|
170
170
|
- A journal entry is created with the exclusive-create flag, so pi_canon never rewrites or deletes one, and a name collision increments a suffix rather than losing an entry. The files stay ordinary Markdown, so any other tool can still rewrite or delete one: append-only is a property of the tool, not of the filesystem.
|
|
171
171
|
- Once a path is in hand it resolves to exactly one article, walking to the nearest ancestor that has one, or to nothing at all.
|
|
172
172
|
- An article surfaces whole, with no character count able to truncate it or hold it back.
|
|
173
|
-
- An article surfaces at most once while
|
|
173
|
+
- An article with a presence mark surfaces at most once while that mark remains in the context the provider receives. Presence is read from that projection rather than remembered, so folding or compaction returns a marked article to surfacing; an untestably short delivery or a harness that reports no projection degrades to at most once per session.
|
|
174
174
|
- Reading an article through the tool withdraws its staged capsule before the message goes out.
|
|
175
175
|
|
|
176
176
|
Asked of the agent, and checked by nothing:
|
|
177
177
|
|
|
178
178
|
- Read the governing article before working on an asset, and update it after real changes. No write is gated on a prior read, and the settle reminder is a message rather than a gate.
|
|
179
179
|
- Record the source as it arrived, names and exact numbers included, because articles distill and only the journal keeps the original.
|
|
180
|
-
- File the entry under the right subject, and file a constraint at the asset it governs rather than the asset you happened to edit.
|
|
180
|
+
- File the entry under the right subject, and file a constraint at the asset it governs rather than the asset you happened to edit. On the default `retrieval: "none"`, knowledge filed off the asset path never surfaces; with a retriever configured, a cross-cutting rule can instead live at its own declared address and surface by relevance.
|
|
181
181
|
- Open the article when a capsule or a pointer says there is one. A line in the context is not a read.
|
|
182
182
|
- Decide whether a dropped constraint still holds. Then follow the rule, against a live prompt asking for something else.
|
|
183
183
|
|
|
@@ -186,14 +186,14 @@ Nothing in the package can compel an agent to keep a line it has decided to cut.
|
|
|
186
186
|
What the package does not do, stated so nothing above reads as more than it is:
|
|
187
187
|
|
|
188
188
|
- No search that runs unasked. `search` is an action the agent calls; touches resolve to articles by exact address or the ancestor walk, never by ranking, and no query ever fires on the agent's behalf.
|
|
189
|
-
- No embeddings and no model. `retrieval: "lexical"` builds a BM25 index over
|
|
189
|
+
- No embeddings and no model. `retrieval: "lexical"` builds a BM25 index over off-spine articles plus declared rules, and ordinary asset-scoped articles are never ranked; any other ranker is a function the caller supplies.
|
|
190
190
|
- No filesystem watching, and no staleness detection: `updated` is the date of the last write and is never compared against the asset.
|
|
191
191
|
- No delete and no rename. Removing or moving an article is a file operation you perform.
|
|
192
192
|
- Articles are last write wins, with no lock, no merge, and no warning that someone else changed the file. Only journal entries get the collision retry.
|
|
193
193
|
- No duplicate detection. One canonical address per asset is structural, not checked.
|
|
194
194
|
- Nothing writes, summarizes, or compacts on its own, and nothing filters what goes in: no secrets scanning and no redaction. Every line pi-canon wrote came from an explicit tool call.
|
|
195
195
|
- Nothing about surfacing persists between sessions. A new session re-surfaces everything.
|
|
196
|
-
- Presence is tested
|
|
196
|
+
- Presence is tested against both the article address and the tail of what it actually placed in the provider projection. Any delivery shorter than 24 normalized characters has no safe mark and is conservatively kept present; that can be a tiny read, write, or exceptionally short surfaced line. For marked deliveries, a digest without the delivered tail counts as absent.
|
|
197
197
|
|
|
198
198
|
## Evidence
|
|
199
199
|
|
package/extensions/canon.ts
CHANGED
|
@@ -12,8 +12,9 @@ export interface CanonOptions {
|
|
|
12
12
|
root?: string;
|
|
13
13
|
/* Surface governing articles as tool calls touch assets. Default: true. */
|
|
14
14
|
surface?: boolean;
|
|
15
|
-
/* Treat an article as seen only while
|
|
16
|
-
folded or compacted away surfaces again the next
|
|
15
|
+
/* Treat an article with a presence mark as seen only while that mark remains in the
|
|
16
|
+
live context window, so one folded or compacted away surfaces again on the next
|
|
17
|
+
touch. Untestably short delivered text has no mark and conservatively stays seen.
|
|
17
18
|
Default: true. Set false for 1.0 behavior, where a surfaced article is never
|
|
18
19
|
surfaced again however long ago it left the window. */
|
|
19
20
|
resurface?: boolean;
|
|
@@ -21,18 +22,21 @@ export interface CanonOptions {
|
|
|
21
22
|
assets, addressed by basename: mounts: ["/data/lake"] serves lake:prices.
|
|
22
23
|
Workspaces that mount the same directory share its knowledge. */
|
|
23
24
|
mounts?: string[];
|
|
24
|
-
/* How
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
25
|
+
/* How the retrieval corpus is ranked against what the agent is doing: every
|
|
26
|
+
off-spine article plus any declared rule, so a rule remains reachable if an asset
|
|
27
|
+
later appears at its address. Ordinary addressed articles stay out because the
|
|
28
|
+
spine already reaches them. "none" is the default and is the 1.0 behavior exactly:
|
|
29
|
+
nothing is ranked or surfaced by relevance. "lexical" is BM25 over the standard
|
|
30
|
+
library. Anything needing a model is supplied here as { name, score, index? }, so
|
|
31
|
+
this package never depends on one. */
|
|
29
32
|
retrieval?: RetrievalOption;
|
|
30
33
|
/* How far the best-ranked article must stand out from the rest of what this same
|
|
31
34
|
query touched before it may ride a message. A multiple, not a score: 2 means the
|
|
32
35
|
best must score twice the best article that will not ride, the one just past the
|
|
33
|
-
per-turn cap. Default 1.4, the operating point a 120-cell study priced:
|
|
34
|
-
|
|
35
|
-
ninth of the suggestion volume.
|
|
36
|
+
per-turn cap. Default 1.4, the operating point a 120-cell study priced: its n=15
|
|
37
|
+
comparison with the uncut channel differed by -0.07 rule facts at p=1.0 while
|
|
38
|
+
using a ninth of the suggestion volume. That small observed contrast is not a
|
|
39
|
+
general detection bound. 1 is no cutoff and is the 1.0 behavior exactly.
|
|
36
40
|
|
|
37
41
|
Relative rather than absolute because an absolute cutoff is not the same quantity
|
|
38
42
|
twice. A lexical score is a fraction of the query's whole idf mass, so it falls as
|
|
@@ -44,10 +48,10 @@ export interface CanonOptions {
|
|
|
44
48
|
and a number never did.
|
|
45
49
|
|
|
46
50
|
Raising it trades recall for precision, and precision is the side to protect,
|
|
47
|
-
though the measured argument is tokens rather than attention:
|
|
48
|
-
found good suggestions opened at
|
|
49
|
-
of four, so what the cutoff declines to spend is context on
|
|
50
|
-
never going to be read. Ignored when retrieval is "none". */
|
|
51
|
+
though the measured argument is tokens rather than attention: a companion
|
|
52
|
+
124-cell study found good suggestions opened at similar rates buried among
|
|
53
|
+
twenty-seven as one of four, so what the cutoff declines to spend is context on
|
|
54
|
+
lines that were never going to be read. Ignored when retrieval is "none". */
|
|
51
55
|
standout?: number;
|
|
52
56
|
}
|
|
53
57
|
|
|
@@ -114,10 +118,10 @@ export function registerPiCanon(pi: any, options: CanonOptions = {}): void {
|
|
|
114
118
|
pi.registerTool(buildCanonTool(ready, retriever.name));
|
|
115
119
|
|
|
116
120
|
/* session_start only resets per-session state. Through 0.2.0 it also delivered an
|
|
117
|
-
orientation line
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
description, which every session carries anyway. */
|
|
121
|
+
orientation line. A 2x2 with an inert implementation found significant negative
|
|
122
|
+
main effects for both that line and the tool schema, but did not resolve which
|
|
123
|
+
component cost more. Study 3 detected no benefit loss from removing the line. The
|
|
124
|
+
doctrine rides the tool description, which every session carries anyway. */
|
|
121
125
|
pi.on("session_start", (_event: unknown, ctx: any) => {
|
|
122
126
|
runtime = undefined;
|
|
123
127
|
ready(ctx);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/* Retrieval: the seam for knowledge the spine cannot address.
|
|
1
|
+
/* Retrieval: the seam for knowledge the ordinary spine cannot address.
|
|
2
2
|
|
|
3
|
-
The spine answers
|
|
4
|
-
nothing here changes that. Retrieval runs over the RESIDUE
|
|
5
|
-
address matches no asset,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
The spine answers ordinary asset-scoped questions deterministically and for free,
|
|
4
|
+
and nothing here changes that. Retrieval runs over the RESIDUE: every article whose
|
|
5
|
+
address matches no asset, plus an article declared `scope: rule` even if an asset
|
|
6
|
+
later appears at its address. That scoping completes the spine without competing
|
|
7
|
+
with it: ordinary addressed articles are answered without ranking, while a declared
|
|
8
|
+
cross-cutting rule cannot disappear because of a filesystem name collision.
|
|
9
9
|
|
|
10
10
|
Two built-ins ship. `none` is 1.0 exactly and is the experiment's control. `lexical`
|
|
11
11
|
is BM25 with nothing but the standard library. Anything that needs a model is
|
|
@@ -25,8 +25,9 @@ export interface Candidate {
|
|
|
25
25
|
capsule: string;
|
|
26
26
|
body: string;
|
|
27
27
|
updated: string;
|
|
28
|
-
/* Whether this article SAID it is a cross-cutting rule
|
|
29
|
-
|
|
28
|
+
/* Whether this article SAID it is a cross-cutting rule. A declared rule qualifies
|
|
29
|
+
independently of the filesystem; an undeclared article qualifies only off-spine.
|
|
30
|
+
See residue below. */
|
|
30
31
|
declared: boolean;
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -290,24 +291,19 @@ export function buildRetriever(option: RetrievalOption | undefined): Retriever {
|
|
|
290
291
|
);
|
|
291
292
|
}
|
|
292
293
|
|
|
293
|
-
/* The residue
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
So an article may DECLARE itself with `scope: rule`, and every candidate carries
|
|
307
|
-
whether it did. Nothing here filters on it, because a declaration the agent forgot
|
|
308
|
-
must not cost it the only mechanism that can reach it. What the flag buys is honesty:
|
|
309
|
-
a declared article is a rule on purpose, an undeclared one is a question, and the two
|
|
310
|
-
stop being counted as one number. */
|
|
294
|
+
/* The residue completes the spine. Every off-spine article qualifies because an asset
|
|
295
|
+
touch cannot surface it, and dropping it from retrieval would lose its only automatic
|
|
296
|
+
path. A declared `scope: rule` also qualifies if an asset later appears at the same
|
|
297
|
+
address, because the declaration says the article is cross-cutting rather than
|
|
298
|
+
governed by that coincident asset. Ordinary addressed articles stay out, or retrieval
|
|
299
|
+
would compete with deterministic address resolution.
|
|
300
|
+
|
|
301
|
+
The off-spine set itself holds two populations. One is the deliberate cross-cutting
|
|
302
|
+
rule the doctrine asks for, filed at an address naming the rule. The other is an
|
|
303
|
+
accident: a typo in an address, or an article whose asset was deleted under it. Every
|
|
304
|
+
candidate therefore carries whether it declared itself. Forgetting the declaration
|
|
305
|
+
never excludes an off-spine article; the flag makes the distinction visible and keeps
|
|
306
|
+
a declared rule eligible across a later filesystem collision. */
|
|
311
307
|
export function residue(store: CanonStore, dir: string): Candidate[] {
|
|
312
308
|
const out: Candidate[] = [];
|
|
313
309
|
for (const path of store.list()) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Surfacing: tool calls stage the articles governing what they touch; the staged
|
|
2
|
-
lines flush as ONE message per turn, once
|
|
3
|
-
turn matters: pi's steering queue drains one message per provider round trip, so
|
|
2
|
+
lines flush as ONE message per turn, once while a testable presence mark remains.
|
|
3
|
+
One message per turn matters: pi's steering queue drains one message per provider round trip, so
|
|
4
4
|
a message per tool call would buy each nudge its own extra LLM call.
|
|
5
5
|
|
|
6
6
|
Nothing here is bounded by a character count. A session budget used to cap the
|
|
@@ -44,17 +44,16 @@ const PATHLIKE = /(?:^|[\s"'`=:,([{])(\/?[\w.@-]+(?:\/[\w.@-]+)+)/g;
|
|
|
44
44
|
JSON escaping, whitespace rewrapping, and quoting differences between however the
|
|
45
45
|
projection is rendered and however we wrote it. A short mark is not distinctive enough
|
|
46
46
|
to test, so it is never expired; failing to expire only costs a re-surface that does
|
|
47
|
-
not happen, while a false expiry would spam the window.
|
|
48
|
-
|
|
49
|
-
not.
|
|
47
|
+
not happen, while a false expiry would spam the window. The same floor applies to
|
|
48
|
+
surfaced lines, reads, and writes; an exceptionally terse value in any path stays seen.
|
|
50
49
|
|
|
51
50
|
A mark has two parts and BOTH must be in the projection.
|
|
52
51
|
|
|
53
52
|
IDENTITY is the article's own address, which is in the window whichever way the
|
|
54
53
|
article got there: the surfaced line reads "path: capsule" and a read prints the
|
|
55
54
|
address as its title. LIVENESS is the tail of whatever actually entered, the caller
|
|
56
|
-
passing the whole of it. A surfaced line is
|
|
57
|
-
|
|
55
|
+
passing the whole of it. A surfaced line is held to the tail of that exact line; a
|
|
56
|
+
read is capsule plus body and is held to the body.
|
|
58
57
|
|
|
59
58
|
Both parts are needed because either alone is wrong in a way that matters. Identity
|
|
60
59
|
alone cannot tell a one-line nudge from the full article, which is the defect that
|
|
@@ -143,9 +142,10 @@ export class Surfacer {
|
|
|
143
142
|
|
|
144
143
|
/* How far the best must beat the rest of the same query before anything rides. See
|
|
145
144
|
retrieve(). The default is an operating point priced by a 120-cell study rather than
|
|
146
|
-
picked: at 1.4
|
|
147
|
-
of the suggestion volume, and a store with nothing
|
|
148
|
-
|
|
145
|
+
picked: at 1.4 the n=15 comparison with the uncut channel differed by -0.07 rule
|
|
146
|
+
facts at p=1.0 while using a ninth of the suggestion volume, and a store with nothing
|
|
147
|
+
relevant never reached it. That small observed contrast is not a general detection
|
|
148
|
+
bound. 1 turns the cutoff off. */
|
|
149
149
|
private standout: number;
|
|
150
150
|
|
|
151
151
|
constructor(mounts: Mount[], retriever: Retriever = NONE, resurface = true, standout = 1.4) {
|
|
@@ -282,7 +282,7 @@ export class Surfacer {
|
|
|
282
282
|
/* This turn's intent, one entry per tool call. Kept separate from `collect` because
|
|
283
283
|
they answer different questions: collect asks what asset was touched, which the
|
|
284
284
|
spine answers by address, and this asks what the agent is trying to do, which is
|
|
285
|
-
|
|
285
|
+
what every article in the retrieval corpus is ranked against. */
|
|
286
286
|
noteIntent(toolName: unknown, input: unknown): void {
|
|
287
287
|
if (typeof toolName === "string" && toolName) this.intent.push({ toolName, input });
|
|
288
288
|
}
|
|
@@ -321,8 +321,10 @@ export class Surfacer {
|
|
|
321
321
|
ceiling it means "at least one query term appears in this article at all", which is
|
|
322
322
|
a property of the query rather than a constant someone picked. `standout` is the
|
|
323
323
|
tuned one. A 120-cell study priced it on a corpus with something worth finding in
|
|
324
|
-
its residue
|
|
325
|
-
volume; that is the default, and the
|
|
324
|
+
its residue. At 1.4 the n=15 comparison with the uncut channel differed by -0.07
|
|
325
|
+
rule facts at p=1.0 while using a ninth of the volume; that is the default, and the
|
|
326
|
+
caller moves it against their own trace. The small contrast is an observation from
|
|
327
|
+
this study, not a general detection bound.
|
|
326
328
|
|
|
327
329
|
There used to be an absolute threshold here, on the grounds that a study session was
|
|
328
330
|
handed 28 ranked lines and opened 5, and the scores of the opened and the ignored
|
|
@@ -571,10 +573,10 @@ export class Surfacer {
|
|
|
571
573
|
Both are the same mistake, which is testing presence against something other than
|
|
572
574
|
what was delivered.
|
|
573
575
|
|
|
574
|
-
This also retires the workaround the short-capsule case needed.
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
576
|
+
This also retires the workaround the short-capsule case needed. The address and
|
|
577
|
+
date make ordinary lines testable: `Cache.` fingerprints to 5 characters and the
|
|
578
|
+
`src/core/terse` line to 39. The valid shortest case, address `a` and capsule `x`,
|
|
579
|
+
reaches only 22 and therefore keeps the conservative short-text behavior. */
|
|
578
580
|
this.remember(path, line);
|
|
579
581
|
this.lastFlush.set(path, entry);
|
|
580
582
|
this.staged.delete(path);
|
package/extensions/lib/tool.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/* The pi_canon tool: one tool,
|
|
2
|
-
for events; map to orient. */
|
|
1
|
+
/* The pi_canon tool: one tool, five verbs. Read and update over create; the journal
|
|
2
|
+
for events; map to orient; search when the agent asks. */
|
|
3
3
|
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { basename, join } from "node:path";
|
package/package.json
CHANGED