pi-fabric 0.44.13 → 0.44.15
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/dist/actors/global-registry.d.ts.map +1 -1
- package/dist/actors/global-registry.js +2 -7
- package/dist/actors/global-registry.js.map +1 -1
- package/dist/actors/manager.d.ts.map +1 -1
- package/dist/actors/manager.js +2 -7
- package/dist/actors/manager.js.map +1 -1
- package/dist/agents/manager.d.ts.map +1 -1
- package/dist/agents/manager.js +2 -7
- package/dist/agents/manager.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/core/atomic-write.d.ts +14 -0
- package/dist/core/atomic-write.d.ts.map +1 -0
- package/dist/core/atomic-write.js +62 -0
- package/dist/core/atomic-write.js.map +1 -0
- package/dist/core/capability-advisory.d.ts +1 -1
- package/dist/core/capability-advisory.d.ts.map +1 -1
- package/dist/core/capability-advisory.js +55 -19
- package/dist/core/capability-advisory.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -16
- package/dist/index.js.map +1 -1
- package/dist/mesh/store.d.ts.map +1 -1
- package/dist/mesh/store.js +2 -7
- package/dist/mesh/store.js.map +1 -1
- package/dist/residency/client.d.ts.map +1 -1
- package/dist/residency/client.js +2 -7
- package/dist/residency/client.js.map +1 -1
- package/dist/residency/host.d.ts.map +1 -1
- package/dist/residency/host.js +2 -7
- package/dist/residency/host.js.map +1 -1
- package/dist/schema/controller.d.ts.map +1 -1
- package/dist/schema/controller.js +2 -4
- package/dist/schema/controller.js.map +1 -1
- package/dist/storage/retention.d.ts.map +1 -1
- package/dist/storage/retention.js +2 -13
- package/dist/storage/retention.js.map +1 -1
- package/dist/worker/run-record.d.ts.map +1 -1
- package/dist/worker/run-record.js +37 -1
- package/dist/worker/run-record.js.map +1 -1
- package/docs/capability-combustion.md +36 -23
- package/docs/configuration.md +1 -1
- package/package.json +1 -1
- package/dist/core/capability-advisory-store.d.ts +0 -4
- package/dist/core/capability-advisory-store.d.ts.map +0 -1
- package/dist/core/capability-advisory-store.js +0 -46
- package/dist/core/capability-advisory-store.js.map +0 -1
|
@@ -121,29 +121,42 @@ With the default fixture terms, "query the results table please" scores
|
|
|
121
121
|
$s = 1.333$ (weak band): the EWMA crosses $0.9$ only on the second tidy prompt,
|
|
122
122
|
and cool-off while the user edits code delays the fire as intended.
|
|
123
123
|
|
|
124
|
-
## Ash:
|
|
125
|
-
|
|
126
|
-
Fired namespaces are burned
|
|
127
|
-
|
|
124
|
+
## Ash: session-scoped suppression — the transcript is the ledger
|
|
125
|
+
|
|
126
|
+
Fired namespaces are burned, and the burn record lives in the session's own
|
|
127
|
+
transcript — there is no side store:
|
|
128
|
+
|
|
129
|
+
- `fired` — the hint itself is the record: every advisory is emitted as a
|
|
130
|
+
`pi-fabric-capability` custom-message entry whose `details` name the
|
|
131
|
+
namespaces shown. Burning happened *when the paper entered the fire*, and
|
|
132
|
+
the transcript is the fire.
|
|
133
|
+
- `organic` — the model invoked a captured tool from that namespace *without
|
|
134
|
+
a hint*. The tool call is already a transcript entry; the capability's
|
|
135
|
+
information potential was spent by discovery, so we burn it preemptively
|
|
136
|
+
(organic-discovery poisoning: the same one-way door, entered from the other
|
|
137
|
+
side).
|
|
138
|
+
|
|
139
|
+
Ash is *derived*, never stored: on `session_start` and on every branch switch
|
|
140
|
+
(`session_tree`) the advisor replays the current branch's entries
|
|
141
|
+
(`ctx.sessionManager.getBranch()`) and re-marks both burn kinds, with
|
|
142
|
+
provenance (`origin`) and wall time (`at`, taken from the entry's own
|
|
143
|
+
timestamp) rebuilt from the transcript:
|
|
128
144
|
|
|
129
145
|
```json
|
|
130
|
-
{ "
|
|
131
|
-
|
|
132
|
-
{ "namespace": "extension:pi-fovea", "origin": "organic" } ] }
|
|
146
|
+
{ "namespace": "extension:pi-websearch", "origin": "fired", "at": "2026-08-10T16:00:00.000Z" }
|
|
147
|
+
{ "namespace": "extension:pi-fovea", "origin": "organic", "at": "2026-08-10T16:12:11.000Z" }
|
|
133
148
|
```
|
|
134
149
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
smoke streak, per-session cap) but never ash; `hydrate()` loads it on session
|
|
146
|
-
start.
|
|
150
|
+
Thermodynamic consequence: the ash set is exactly "burns that happened up to
|
|
151
|
+
the current point in this branch's history." Fork a session and the fork
|
|
152
|
+
replays ashes up to the fork point; rewind with `/tree` and capabilities whose
|
|
153
|
+
burns live only in the abandoned future burn *back into paper* — you don't
|
|
154
|
+
unburn paper, but undoing time restores what hadn't happened yet. A new
|
|
155
|
+
session is a fresh urn: nothing carries across sessions, because the learner
|
|
156
|
+
the hint was meant for (the model's context) doesn't either. Within a session
|
|
157
|
+
there's still no release path: no expires, no defrost knob — `reset()` clears
|
|
158
|
+
only what is inherently transient (warmth, smoke streak, per-session cap),
|
|
159
|
+
never ash.
|
|
147
160
|
|
|
148
161
|
## Furnace feedback
|
|
149
162
|
|
|
@@ -162,15 +175,15 @@ zero — clean combustion keeps the furnace responsive. Smoke feedback only rais
|
|
|
162
175
|
the *weak-band* ignition bar; strong matches still ignite instantly, because if
|
|
163
176
|
the evidence is that unambiguous the furnace's skepticism isn't invited.
|
|
164
177
|
|
|
165
|
-
Transient feedback lives session-locally too: smoke is lifted by the first
|
|
166
|
-
burn
|
|
167
|
-
|
|
178
|
+
Transient feedback lives session-locally too: smoke is lifted by the first
|
|
179
|
+
clean burn. Like everything else in this model, it does not cross sessions —
|
|
180
|
+
the new session brings a fresh transcript, hence a fresh urn.
|
|
168
181
|
|
|
169
182
|
## Per-session cap
|
|
170
183
|
|
|
171
184
|
$\leq$ `maxPerSession` fires per session regardless of model behavior (default
|
|
172
185
|
3). Unchanged from the pre-combustion design; the cap guards against prompt
|
|
173
|
-
storms in a single session, ash guards against repetition
|
|
186
|
+
storms in a single session, and ash guards against repetition within it.
|
|
174
187
|
|
|
175
188
|
## Summary
|
|
176
189
|
|
package/docs/configuration.md
CHANGED
|
@@ -234,7 +234,7 @@ Fabric risk classes are `read`, `write`, `execute`, `network`, and `agent`; appr
|
|
|
234
234
|
- Captured and directly registered tools default to the conservative `execute` risk because Pi tool definitions do not declare effects. Add exact tool-name overrides under `capture.risks`. Fovea's verified graph-navigation tools (`fovea_sketch`, `fovea_focus`, `fovea_dwell`, and `fovea_impact`) are read-only exceptions and default to `read`.
|
|
235
235
|
- Set `capture.hideFromModel` to `false` to index non-core extension tools without hiding them from the model's active set.
|
|
236
236
|
- `capture.keepVisible` names stay in both Fabric and Pi's model-facing active set, except that Pi core names are always Fabric-owned in full code mode.
|
|
237
|
-
- `capture.advisory` injects a capability hint at `before_agent_start` when the prompt's terms match a captured source's tf-idf fingerprint (names + descriptions grouped by source namespace, no manifest declarations needed). `mode: "enabled"` (default) renders the hint in the transcript, `"hidden"` delivers it to the model only, and `"disabled"` turns it off. Each capability fires at most once — the fired
|
|
237
|
+
- `capture.advisory` injects a capability hint at `before_agent_start` when the prompt's terms match a captured source's tf-idf fingerprint (names + descriptions grouped by source namespace, no manifest declarations needed). `mode: "enabled"` (default) renders the hint in the transcript, `"hidden"` delivers it to the model only, and `"disabled"` turns it off. Each capability fires at most once per session — ash is derived from the session transcript itself (a fired hint is its own custom-message entry; organic use is its own tool call), so reloads and `/tree` branch rewinds replay ashes exactly up to the current point, and a brand-new session starts with a clean urn; `maxPerSession` (default 3) caps hints within a session, `threshold` (default 0.9) tunes sensitivity, `maxPerSession` (default 3) caps hints within a session, `threshold` (default 0.9) tunes sensitivity, and `budget` (default 512, clamped 128–8192 — same range as [pi-fovea](https://github.com/monotykamary/pi-fovea)'s `sync.budget`) caps the advisory text in tokens (estimated as chars/4; rendering walks a degradation ladder — indented tool tree with descriptions → names-only tree → flat per-source lines → `header + steer` — until a rung fits; the ladder keeps leftover tool names in a `+N more:` leaf so they stay addressable). The matcher follows a combustion model: 1/df-weighted term scoring, strong matches fire instantly, weak matches accumulate warmth ($W \leftarrow \frac{1}{2}W + \frac{1}{2}s$; ignites at $W \geq$ threshold), each namespace's fire-set is durable *ash* (`fired` or `organic` — organic covers tools you used without a hint) persisted in `<agent-dir>/fabric/capability-advisories.json` across restarts, and ignored fires push smoke streaks that raise the weak-band ignition point by $\theta/\tau^2$ per streak ($0.25\theta$ at the internal memory scale $\tau = 2$ — every internal constant projects from $\tau$ and the score quantum $q = 1$). See [docs/capability-combustion.md](docs/capability-combustion.md) for the full math. Skill markup pi expands into the prompt (`<available_skills>`/`<skill>` blocks) is stripped before matching so a loaded skill cannot trigger its own hint. The hint follows fovea's structured shape: headline, `Candidates:` refs grouped by source, a `Next:` schema/action line for the top ref, and a `Steer:` directive.
|
|
238
238
|
- An `ask` policy emits a warning notification and opens an explicit **Allow once** / **Allow for this session** / **Deny** permission prompt, matching Claude-style approval scopes. **Allow once** authorizes only the requested action. **Allow for this session** authorizes that risk class until the current Pi session ends. The TUI uses an inline wizard; RPC clients receive the equivalent `select` dialog.
|
|
239
239
|
- Concurrent requests are serialized so a one-time approval never silently widens to sibling calls. Session-wide grants are shared between native calls and `fabric_exec`. Escape, dismissal, unavailable interactive UI, and session restart all fail closed.
|
|
240
240
|
|
package/package.json
CHANGED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { CapabilityBurn } from "./capability-advisory.js";
|
|
2
|
-
export declare const loadCapabilityAdvisoryState: (filePath?: string) => CapabilityBurn[];
|
|
3
|
-
export declare const saveCapabilityAdvisoryState: (burned: Iterable<CapabilityBurn>, filePath?: string) => void;
|
|
4
|
-
//# sourceMappingURL=capability-advisory-store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capability-advisory-store.d.ts","sourceRoot":"","sources":["../../src/core/capability-advisory-store.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAyB/D,eAAO,MAAM,2BAA2B,GAAI,WAAW,MAAM,KAAG,cAAc,EA2B7E,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,QAAQ,QAAQ,CAAC,cAAc,CAAC,EAChC,WAAW,MAAM,KAChB,IAGF,CAAC"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
5
|
-
const ADVISORY_STATE_FILENAME = "capability-advisories.json";
|
|
6
|
-
const defaultStatePath = () =>
|
|
7
|
-
// Sits beside the global actor registry: fired capability hints belong to
|
|
8
|
-
// the user's machine-global agent dir so once-fired advisories stay quiet
|
|
9
|
-
// across session restarts in every project.
|
|
10
|
-
path.join(getAgentDir(), "fabric", ADVISORY_STATE_FILENAME);
|
|
11
|
-
const atomicWriteJson = (filePath, value) => {
|
|
12
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
13
|
-
const temporaryPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
14
|
-
fs.writeFileSync(temporaryPath, JSON.stringify(value, null, 2), {
|
|
15
|
-
encoding: "utf8",
|
|
16
|
-
mode: 0o600,
|
|
17
|
-
});
|
|
18
|
-
fs.renameSync(temporaryPath, filePath);
|
|
19
|
-
};
|
|
20
|
-
export const loadCapabilityAdvisoryState = (filePath) => {
|
|
21
|
-
try {
|
|
22
|
-
const raw = JSON.parse(fs.readFileSync(filePath ?? defaultStatePath(), "utf8"));
|
|
23
|
-
if (raw.format === 2 && Array.isArray(raw.burned)) {
|
|
24
|
-
return raw.burned.filter((entry) => typeof entry === "object" &&
|
|
25
|
-
entry !== null &&
|
|
26
|
-
typeof entry.namespace === "string" &&
|
|
27
|
-
(entry.origin === "fired" ||
|
|
28
|
-
entry.origin === "organic"));
|
|
29
|
-
}
|
|
30
|
-
if (raw.format === 1 && Array.isArray(raw.fired)) {
|
|
31
|
-
return raw.fired
|
|
32
|
-
.filter((entry) => typeof entry === "string")
|
|
33
|
-
.map((namespace) => ({ namespace, origin: "fired" }));
|
|
34
|
-
}
|
|
35
|
-
return [];
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
// Missing or corrupt state means nothing has burned yet.
|
|
39
|
-
return [];
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
export const saveCapabilityAdvisoryState = (burned, filePath) => {
|
|
43
|
-
const document = { format: 2, burned: [...burned] };
|
|
44
|
-
atomicWriteJson(filePath ?? defaultStatePath(), document);
|
|
45
|
-
};
|
|
46
|
-
//# sourceMappingURL=capability-advisory-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capability-advisory-store.js","sourceRoot":"","sources":["../../src/core/capability-advisory-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,MAAM,uBAAuB,GAAG,4BAA4B,CAAC;AAW7D,MAAM,gBAAgB,GAAG,GAAW,EAAE;AACpC,0EAA0E;AAC1E,0EAA0E;AAC1E,4CAA4C;AAC5C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,uBAAuB,CAAC,CAAC;AAE9D,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,KAAc,EAAQ,EAAE;IACjE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,MAAM,aAAa,GAAG,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;IACvE,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAC9D,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;IACH,EAAE,CAAC,UAAU,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,QAAiB,EAAoB,EAAE;IACjF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,IAAI,gBAAgB,EAAE,EAAE,MAAM,CAAC,CAI7E,CAAC;QACF,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CACtB,CAAC,KAAK,EAA2B,EAAE,CACjC,OAAO,KAAK,KAAK,QAAQ;gBACzB,KAAK,KAAK,IAAI;gBACd,OAAQ,KAAwB,CAAC,SAAS,KAAK,QAAQ;gBACvD,CAAE,KAAwB,CAAC,MAAM,KAAK,OAAO;oBAC1C,KAAwB,CAAC,MAAM,KAAK,SAAS,CAAC,CACpD,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,OAAO,GAAG,CAAC,KAAK;iBACb,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;iBAC7D,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAgB,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;QACzD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,MAAgC,EAChC,QAAiB,EACX,EAAE;IACR,MAAM,QAAQ,GAA2B,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5E,eAAe,CAAC,QAAQ,IAAI,gBAAgB,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC5D,CAAC,CAAC"}
|