pi-fold 2.0.0 → 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/README.md +49 -28
- package/extensions/active-context.ts +1011 -444
- package/extensions/index.js +16 -3
- package/extensions/lib/curation.ts +56 -60
- package/extensions/lib/editor-ui.ts +739 -0
- package/extensions/lib/folding.ts +26 -42
- package/extensions/lib/instrumentation.ts +10 -3
- package/extensions/lib/measurement.ts +6 -12
- package/extensions/lib/persistence.ts +62 -38
- package/extensions/lib/policy.ts +171 -89
- package/extensions/lib/scheduling.ts +341 -108
- package/extensions/lib/selection.ts +6 -78
- package/extensions/lib/tool-surface.ts +29 -33
- package/extensions/lib/transcript.ts +17 -60
- package/extensions/settings.ts +481 -0
- package/package.json +4 -1
package/extensions/index.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { registerActiveContext } from "./active-context.ts";
|
|
2
2
|
import { registerEvidenceIngestion } from "./evidence.js";
|
|
3
3
|
|
|
4
|
+
export {
|
|
5
|
+
applyFoldSettingsEdit,
|
|
6
|
+
loadFoldSettingsFile,
|
|
7
|
+
readFoldSettingsFile,
|
|
8
|
+
registerFoldSettings,
|
|
9
|
+
saveFoldSettingsFile,
|
|
10
|
+
} from "./settings.ts";
|
|
11
|
+
|
|
4
12
|
const PUBLIC_OPTIONS = Object.freeze([
|
|
5
|
-
"thresholds", "providerInputBudget", "blacklistAutoFoldTools",
|
|
13
|
+
"thresholds", "providerInputBudget", "blacklistAutoFoldTools",
|
|
6
14
|
]);
|
|
7
15
|
|
|
8
16
|
const GENERATOR_DELETED = "the model brief generator is deleted (2026-08-14): across 15 sealed " +
|
|
@@ -16,15 +24,20 @@ const INVERTED_AUTO_FOLD_LIST = "renamed blacklistAutoFoldTools, and the sense i
|
|
|
16
24
|
"it meant to permit";
|
|
17
25
|
|
|
18
26
|
const REFUSED_OPTIONS = Object.freeze({
|
|
27
|
+
guidance: "deleted 2026-08-23: it switched the copy that taught the agent to " +
|
|
28
|
+
"CHOOSE SPANS, and the agent does not choose spans. The runtime cuts at the frontier and " +
|
|
29
|
+
"the agent annotates what it cut, so the guidance it switched is replaced wholesale by " +
|
|
30
|
+
"the post-fold notice, which is not optional: a fold the agent is never told about is one " +
|
|
31
|
+
"it can never brief",
|
|
19
32
|
toolName: "the deployment identity is hardwired to pi-fold: the tool is pi_fold_context",
|
|
20
33
|
toolLabel: "the deployment identity is hardwired to pi-fold",
|
|
21
34
|
brandNoun: "the deployment identity is hardwired to pi-fold",
|
|
22
35
|
entryTypePrefix: "the deployment identity is hardwired to pi-fold: durable state lives " +
|
|
23
36
|
"under pi-fold-active-context, and moving it would strand every fold already written",
|
|
24
37
|
commandPrefix: "the deployment identity is hardwired to pi-fold: the commands are " +
|
|
25
|
-
"/
|
|
38
|
+
"/fold, /fold-editor, /fold-status and /fold-settings",
|
|
26
39
|
commandNames: "the deployment identity is hardwired to pi-fold: the commands are " +
|
|
27
|
-
"/
|
|
40
|
+
"/fold, /fold-editor, /fold-status and /fold-settings",
|
|
28
41
|
isMcpTool: "MCP tools are recognized by the mcp__server__tool naming convention. The " +
|
|
29
42
|
"predicate defaulted to false, so conventionally named MCP tools were never classified " +
|
|
30
43
|
"unless a host supplied one, which is a documented feature that never ran",
|
|
@@ -1,71 +1,68 @@
|
|
|
1
1
|
import { boundReceiptText } from "./measurement.ts";
|
|
2
2
|
import {
|
|
3
3
|
contextBrand,
|
|
4
|
-
CONTEXT_MARK_RESPONSE_BYTES,
|
|
5
4
|
CONTEXT_RECEIPT_BLOCK_BYTES,
|
|
5
|
+
FOLD_NOTICE_BYTES,
|
|
6
6
|
DEFAULT_ACTIVE_CONTEXT_BRAND_NOUN,
|
|
7
7
|
MAX_CONTEXT_RECEIPTS,
|
|
8
8
|
} from "./policy.ts";
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/**
|
|
11
|
+
* THE POST-FOLD NOTICE: THE ONE MOMENT THE AGENT KNOWS SOMETHING THE RUNTIME DOES NOT.
|
|
12
|
+
*
|
|
13
|
+
* The runtime has just cut folds behind the agent, out of material the agent is still
|
|
14
|
+
* looking at. It knows the spans, the sizes and the staleness; it does not know why any
|
|
15
|
+
* of it mattered. So the notice states what was cut and asks for exactly one thing, a
|
|
16
|
+
* brief, and it states the price of answering, which is nothing: the folds it names are
|
|
17
|
+
* PENDING, so a brief written now is stored outside the projection and reaches the window
|
|
18
|
+
* only when the commit writes that placeholder for the first time.
|
|
19
|
+
*
|
|
20
|
+
* It is batched rather than continuous. One notice per cut is noise, and noise is how
|
|
21
|
+
* guidance gets ignored; this one appears when enough folds are standing unbriefed to be
|
|
22
|
+
* worth a turn's attention, and it is ephemeral, so it never accumulates.
|
|
23
|
+
*/
|
|
24
|
+
export function foldNoticeText(input: {
|
|
25
|
+
unbriefed: ReadonlyArray<{ id: string; kind: string; tokens: number }>;
|
|
26
|
+
pending: number;
|
|
13
27
|
toolName: string;
|
|
14
28
|
brandNoun?: string;
|
|
15
29
|
}): string {
|
|
16
30
|
const brand = contextBrand(input.brandNoun ?? DEFAULT_ACTIVE_CONTEXT_BRAND_NOUN);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
`[${brand}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
`
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return boundReceiptText(
|
|
51
|
-
[
|
|
52
|
-
`[${brand} notice] A fold commit just landed; the next one will batch every pending mark ` +
|
|
53
|
-
"into one rewrite, and marks are free until then.",
|
|
54
|
-
"Mark FINISHED units at their clean boundaries; batches beat singles: " +
|
|
55
|
-
`${input.toolName} {"action":"fold","marks":[{"ids":["<start>","<end>"],"brief":"<factual brief>"}]} ` +
|
|
56
|
-
"carries several decisions into that single rewrite, each keeping your brief instead of a " +
|
|
57
|
-
`generated one. ${input.pendingAgentMarks} of your mark(s) pending; ` +
|
|
58
|
-
`${input.eligibleMarks} mark(s) eligible now, freeing about ${input.eligibleFreedTokens} ` +
|
|
59
|
-
`of the ${input.freedTokens} marked token(s).`,
|
|
60
|
-
`Completed units ready to mark, largest first: ${anchors}.`,
|
|
61
|
-
`Pinning: ${input.toolName} {"action":"protect","ids":["<entry-id>"]} holds entries raw through ` +
|
|
62
|
-
`every fold, and {"action":"unprotect"} releases them. Pinned context is ${pinnedPercent}% of ` +
|
|
63
|
-
`the working window against a ${capPercent}% cap; at the cap, protect refuses until ` +
|
|
64
|
-
"something is released.",
|
|
65
|
-
].join("\n"),
|
|
66
|
-
2_048,
|
|
67
|
-
`[${brand} notice] Post-commit curation details are unavailable this pass.`,
|
|
68
|
-
);
|
|
31
|
+
// THE INSTRUCTION IS SEATED BEFORE THE LIST, and the list is what gives when the
|
|
32
|
+
// notice runs out of room. The first cut of this built one string with the ids in the
|
|
33
|
+
// opening line and handed the whole thing to the bound, so a seven-fold batch spent its
|
|
34
|
+
// budget on ids and lost "here is how to answer" off the end: the agent was told which
|
|
35
|
+
// folds were unbriefed and not told that briefing them was free, which is the only fact
|
|
36
|
+
// in here it cannot work out for itself. Fold count grows without limit and the
|
|
37
|
+
// instruction does not, so the instruction is fixed and the ids are the variable part.
|
|
38
|
+
const head = [
|
|
39
|
+
`[${brand} folds] ${input.unbriefed.length} of your ${input.pending} pending fold(s) carry ` +
|
|
40
|
+
"no brief yet. These spans are cut but NOT folded: every byte they cover is still in " +
|
|
41
|
+
"front of you exactly as it was, and they enter your window only when a commit " +
|
|
42
|
+
"applies them.",
|
|
43
|
+
`Give each one a sentence: ${input.toolName} {"action":"brief","id":"<fold-id>","brief":"..."}. ` +
|
|
44
|
+
"You know why the span mattered and what you will want back from it; the automatic " +
|
|
45
|
+
"brief reads the span alone and does not. Writing it now costs your window nothing, " +
|
|
46
|
+
"because the fold is not in your window yet.",
|
|
47
|
+
`Wrong boundary? ${input.toolName} {"action":"reboundary","ids":[...]} re-cuts it. ` +
|
|
48
|
+
`Should not be taken at all? ${input.toolName} {"action":"unmark","ids":["<fold-id>"]}.`,
|
|
49
|
+
].join("\n");
|
|
50
|
+
// WHAT IT COULD NOT NAME, IT COUNTS (gate 136's law, and gate 115's shape one level
|
|
51
|
+
// out): a list that stops early and says nothing reads as a complete list.
|
|
52
|
+
const entries = input.unbriefed
|
|
53
|
+
.map((fold) => `${fold.id} (${fold.kind}, ~${fold.tokens} tokens)`);
|
|
54
|
+
const overflowText = (seated: number) =>
|
|
55
|
+
`${input.toolName} {"action":"status"} lists the other ${input.unbriefed.length - seated}.`;
|
|
56
|
+
let seated = entries.length;
|
|
57
|
+
let list = `Unbriefed: ${entries.join("; ")}.`;
|
|
58
|
+
while (seated > 0 && Buffer.byteLength(`${head}\n${list}`, "utf8") > FOLD_NOTICE_BYTES) {
|
|
59
|
+
seated -= 1;
|
|
60
|
+
list = seated === 0
|
|
61
|
+
? overflowText(0)
|
|
62
|
+
: `Unbriefed: ${entries.slice(0, seated).join("; ")}. ${overflowText(seated)}`;
|
|
63
|
+
}
|
|
64
|
+
return boundReceiptText(`${head}\n${list}`, FOLD_NOTICE_BYTES,
|
|
65
|
+
`[${brand} folds] Pending folds are waiting for briefs; the list is unavailable this pass.`);
|
|
69
66
|
}
|
|
70
67
|
|
|
71
68
|
export interface ContextReceipt {
|
|
@@ -142,7 +139,7 @@ export function receiptLine(receipt: ContextReceipt): string {
|
|
|
142
139
|
? "This ran as overflow recovery: the request would not have been transmissible, and it was rebuilt rather than dropped."
|
|
143
140
|
: "",
|
|
144
141
|
receipt.protectedBytes
|
|
145
|
-
? `${receipt.protectedBytes} byte(s) stay pinned
|
|
142
|
+
? `${receipt.protectedBytes} byte(s) stay pinned; unpin releases them when the work moves on.`
|
|
146
143
|
: "",
|
|
147
144
|
receipt.note ?? "",
|
|
148
145
|
];
|
|
@@ -160,9 +157,8 @@ export function receiptBlockText(input: {
|
|
|
160
157
|
`[${brand} actions] Recent automatic context actions, newest last. Exact source remains expandable.`;
|
|
161
158
|
const verbs = `Correct any of it: ${input.toolName} ` +
|
|
162
159
|
"{\"action\":\"expand\",\"id\":\"<fold-id>\"} restores a span in place; " +
|
|
163
|
-
"{\"action\":\"
|
|
164
|
-
"
|
|
165
|
-
"mis-cut fold to raw so you can fold the span you meant.";
|
|
160
|
+
"{\"action\":\"reboundary\",\"id\":\"<fold-id>\"} returns a mis-cut fold to raw so you can " +
|
|
161
|
+
"fold the span you meant.";
|
|
166
162
|
const fixed = Buffer.byteLength(header, "utf8") + Buffer.byteLength(verbs, "utf8") + 1;
|
|
167
163
|
if (fixed > CONTEXT_RECEIPT_BLOCK_BYTES) {
|
|
168
164
|
return `[${brand} actions] Recent automatic context actions are unavailable this pass.`;
|