@monotykamary/pi-vcc 0.3.16

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.
Files changed (76) hide show
  1. package/README.md +688 -0
  2. package/__tests__/helpers.ts +135 -0
  3. package/__tests__/root-causes.test.ts +858 -0
  4. package/demo.gif +0 -0
  5. package/index.ts +21 -0
  6. package/knip.json +4 -0
  7. package/npm-shrinkwrap.json +3001 -0
  8. package/package.json +36 -0
  9. package/scripts/audit-sessions.ts +88 -0
  10. package/scripts/benchmark-real-sessions.ts +25 -0
  11. package/scripts/compare-before-after.ts +36 -0
  12. package/scripts/dump-branch-output.ts +20 -0
  13. package/src/commands/pi-vcc.ts +36 -0
  14. package/src/commands/vcc-recall.ts +65 -0
  15. package/src/core/brief.ts +497 -0
  16. package/src/core/build-sections.ts +431 -0
  17. package/src/core/content.ts +71 -0
  18. package/src/core/filter-noise.ts +42 -0
  19. package/src/core/format-recall.ts +177 -0
  20. package/src/core/format.ts +98 -0
  21. package/src/core/invisible-continue.ts +172 -0
  22. package/src/core/lineage.ts +26 -0
  23. package/src/core/load-messages.ts +40 -0
  24. package/src/core/normalize.ts +73 -0
  25. package/src/core/recall-scope.ts +49 -0
  26. package/src/core/render-entries.ts +58 -0
  27. package/src/core/report.ts +237 -0
  28. package/src/core/sanitize.ts +5 -0
  29. package/src/core/search-entries.ts +375 -0
  30. package/src/core/settings.ts +190 -0
  31. package/src/core/skill-collapse.ts +35 -0
  32. package/src/core/summarize.ts +179 -0
  33. package/src/core/tool-args.ts +14 -0
  34. package/src/details.ts +19 -0
  35. package/src/extract/commits.ts +69 -0
  36. package/src/extract/goals.ts +79 -0
  37. package/src/extract/preferences.ts +55 -0
  38. package/src/extract/shared-symbols.ts +357 -0
  39. package/src/hooks/before-compact.ts +564 -0
  40. package/src/hooks/proactive-threshold.ts +131 -0
  41. package/src/sections.ts +23 -0
  42. package/src/tools/recall.ts +204 -0
  43. package/src/types.ts +20 -0
  44. package/tests/australian-government.test.ts +479 -0
  45. package/tests/before-compact-hook.test.ts +185 -0
  46. package/tests/before-compact.test.ts +227 -0
  47. package/tests/brief.test.ts +215 -0
  48. package/tests/build-sections.test.ts +59 -0
  49. package/tests/compile.test.ts +89 -0
  50. package/tests/content.test.ts +66 -0
  51. package/tests/deep-extraction.test.ts +313 -0
  52. package/tests/extract-goals.test.ts +86 -0
  53. package/tests/extract-preferences.test.ts +30 -0
  54. package/tests/filter-noise.test.ts +61 -0
  55. package/tests/fixtures.ts +61 -0
  56. package/tests/format-recall.test.ts +87 -0
  57. package/tests/format.test.ts +73 -0
  58. package/tests/government-domain.test.ts +542 -0
  59. package/tests/lineage.test.ts +33 -0
  60. package/tests/load-messages.test.ts +49 -0
  61. package/tests/model-threshold-hook.test.ts +377 -0
  62. package/tests/model-threshold.test.ts +223 -0
  63. package/tests/normalize.test.ts +104 -0
  64. package/tests/proactive-threshold.test.ts +490 -0
  65. package/tests/real-sessions.test.ts +38 -0
  66. package/tests/recall-expand.test.ts +15 -0
  67. package/tests/recall-scope.test.ts +32 -0
  68. package/tests/recall-tool-scope.test.ts +67 -0
  69. package/tests/render-entries.test.ts +92 -0
  70. package/tests/report.test.ts +58 -0
  71. package/tests/sanitize.test.ts +24 -0
  72. package/tests/search-entries.test.ts +233 -0
  73. package/tests/support/load-session.ts +23 -0
  74. package/tests/support/real-sessions.ts +51 -0
  75. package/tests/threshold-integration.test.ts +359 -0
  76. package/tsconfig.json +20 -0
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Integration tests: proactive threshold + session_before_compact interaction.
3
+ *
4
+ * These tests verify the cross-hook contract:
5
+ * - When proactive trigger calls ctx.compact(), session_before_compact
6
+ * must NOT cancel the compaction even if tokensBefore differs from
7
+ * getContextUsage().
8
+ * - When the global threshold triggers compaction but the model can
9
+ * handle more (per-model threshold not crossed), session_before_compact
10
+ * must cancel.
11
+ */
12
+ import { describe, test, expect, afterEach, beforeAll, afterAll } from "bun:test";
13
+ import { existsSync, unlinkSync, writeFileSync, mkdtempSync, rmSync } from "fs";
14
+ import { tmpdir } from "os";
15
+ import { join } from "path";
16
+ import { registerBeforeCompactHook } from "../src/hooks/before-compact";
17
+ import { registerProactiveThresholdHook, resetProactiveState } from "../src/hooks/proactive-threshold";
18
+
19
+ let tmpDir: string;
20
+ let CONFIG_PATH: string;
21
+
22
+ beforeAll(() => {
23
+ tmpDir = mkdtempSync(join(tmpdir(), "pi-vcc-test-"));
24
+ CONFIG_PATH = join(tmpDir, "pi-vcc-config.json");
25
+ process.env.PI_VCC_CONFIG_PATH = CONFIG_PATH;
26
+ });
27
+
28
+ afterAll(() => {
29
+ delete process.env.PI_VCC_CONFIG_PATH;
30
+ rmSync(tmpDir, { recursive: true, force: true });
31
+ });
32
+
33
+ function setConfig(cfg: Record<string, unknown>) {
34
+ writeFileSync(CONFIG_PATH, JSON.stringify(cfg));
35
+ }
36
+
37
+ const msg = (id: string, role: "user" | "assistant" | "toolResult", content = "x") => ({
38
+ id,
39
+ type: "message",
40
+ message: { role, content },
41
+ });
42
+
43
+ function createMockPi(
44
+ model?: { id: string; provider?: string; contextWindow?: number },
45
+ usage?: { tokens: number | null; contextWindow: number; percent: number | null },
46
+ ) {
47
+ const handlers: Record<string, ((e: any, c: any) => any)[]> = {};
48
+ const compactCalls: number[] = [];
49
+ const notifyCalls: { msg: string; level: string }[] = [];
50
+
51
+ const ctx = {
52
+ hasUI: true,
53
+ model: model ?? undefined,
54
+ ui: {
55
+ notify: (msg: string, level: string) => {
56
+ notifyCalls.push({ msg, level });
57
+ },
58
+ },
59
+ getContextUsage: () => usage ?? { tokens: null, contextWindow: 0, percent: null },
60
+ compact: () => {
61
+ compactCalls.push(Date.now());
62
+ },
63
+ } as any;
64
+
65
+ const pi = {
66
+ on: (eventName: string, handler: (e: any, c: any) => any) => {
67
+ if (!handlers[eventName]) handlers[eventName] = [];
68
+ handlers[eventName].push(handler);
69
+ },
70
+ } as any;
71
+
72
+ const emit = (eventName: string, event: any = {}) => {
73
+ const hs = handlers[eventName] ?? [];
74
+ let result: any;
75
+ for (const h of hs) result = h(event, ctx);
76
+ return result;
77
+ };
78
+
79
+ return { pi, ctx, emit, compactCalls, notifyCalls };
80
+ }
81
+
82
+ function makeBeforeCompactEvent(branchEntries: any[], customInstructions?: string, tokensBefore = 100000) {
83
+ return {
84
+ type: "session_before_compact",
85
+ customInstructions,
86
+ branchEntries,
87
+ preparation: {
88
+ previousSummary: undefined,
89
+ fileOps: { read: [], written: [], edited: [] },
90
+ tokensBefore,
91
+ },
92
+ signal: new AbortController().signal,
93
+ };
94
+ }
95
+
96
+ describe("integration: proactive trigger + before-compact", () => {
97
+ afterEach(() => {
98
+ if (existsSync(CONFIG_PATH)) unlinkSync(CONFIG_PATH);
99
+ resetProactiveState();
100
+ });
101
+
102
+ test("proactive trigger then before-compact: does NOT cancel when proactiveTriggerActive", () => {
103
+ // Scenario: agent_end fires, getContextUsage says 110k tokens,
104
+ // per-model threshold is 95232 (128k - 32768). Proactive triggers compact.
105
+ // Then session_before_compact fires with tokensBefore = 94000
106
+ // (slightly different due to estimation).
107
+ // Without the proactiveTriggerActive guard, this would be cancelled.
108
+ setConfig({
109
+ debug: false,
110
+ overrideDefaultCompaction: true,
111
+ modelThresholds: {
112
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
113
+ },
114
+ });
115
+ const { pi, ctx, emit, compactCalls } = createMockPi(
116
+ { id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
117
+ { tokens: 110000, contextWindow: 128000, percent: 86 },
118
+ );
119
+ registerProactiveThresholdHook(pi);
120
+ registerBeforeCompactHook(pi);
121
+
122
+ // Step 1: agent_end fires → proactive trigger calls ctx.compact()
123
+ emit("agent_end", { type: "agent_end", messages: [] });
124
+ expect(compactCalls).toHaveLength(1);
125
+
126
+ // Step 2: session_before_compact fires with tokensBefore = 94000
127
+ // (below the 95232 threshold — but we should NOT cancel because
128
+ // we ourselves triggered this compaction)
129
+ const entries = [
130
+ msg("m1", "user", "hello"),
131
+ msg("m2", "assistant", "hi"),
132
+ msg("m3", "user", "do work"),
133
+ msg("m4", "assistant", "done"),
134
+ ];
135
+ const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 94000));
136
+
137
+ // Should NOT cancel — proactiveTriggerActive is true
138
+ expect(result?.cancel).toBeUndefined();
139
+ // Should proceed with compaction (pi-vcc's own summary)
140
+ expect(result?.compaction).toBeDefined();
141
+ });
142
+
143
+ test("global trigger + before-compact: CANCELS when per-model threshold not crossed and no proactive trigger", () => {
144
+ // Scenario: pi-core's global threshold triggers compaction,
145
+ // but the model's per-model threshold hasn't been crossed.
146
+ // No proactive trigger was set — this is pi-core's own initiative.
147
+ setConfig({
148
+ debug: false,
149
+ overrideDefaultCompaction: true,
150
+ modelThresholds: {
151
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
152
+ },
153
+ });
154
+ const { pi, ctx, emit, compactCalls } = createMockPi(
155
+ { id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
156
+ // getContextUsage says 80k — well below per-model threshold
157
+ { tokens: 80000, contextWindow: 128000, percent: 63 },
158
+ );
159
+ registerProactiveThresholdHook(pi);
160
+ registerBeforeCompactHook(pi);
161
+
162
+ // No agent_end fired (global threshold triggered this)
163
+ const entries = [
164
+ msg("m1", "user", "hello"),
165
+ msg("m2", "assistant", "hi"),
166
+ msg("m3", "user", "do work"),
167
+ msg("m4", "assistant", "done"),
168
+ ];
169
+ // tokensBefore = 90k < 95232 — should cancel
170
+ const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 90000));
171
+ expect(result).toEqual({ cancel: true });
172
+ });
173
+
174
+ test("proactiveTriggerActive is cleared after session_compact", () => {
175
+ setConfig({
176
+ debug: false,
177
+ overrideDefaultCompaction: true,
178
+ modelThresholds: {
179
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
180
+ },
181
+ });
182
+ const { pi, ctx, emit, compactCalls } = createMockPi(
183
+ { id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
184
+ { tokens: 110000, contextWindow: 128000, percent: 86 },
185
+ );
186
+ registerProactiveThresholdHook(pi);
187
+ registerBeforeCompactHook(pi);
188
+
189
+ // Step 1: proactive trigger
190
+ emit("agent_end", { type: "agent_end", messages: [] });
191
+ expect(compactCalls).toHaveLength(1);
192
+
193
+ // Step 2: compaction completes
194
+ emit("session_compact", { type: "session_compact", compactionEntry: {} });
195
+
196
+ // Step 3: now a subsequent session_before_compact (e.g., from pi-core
197
+ // also triggering) with tokensBelow below threshold — should CANCEL
198
+ // because proactiveTriggerActive was cleared by session_compact
199
+ const entries = [
200
+ msg("m1", "user", "hello"),
201
+ msg("m2", "assistant", "hi"),
202
+ msg("m3", "user", "do work"),
203
+ msg("m4", "assistant", "done"),
204
+ ];
205
+ const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 90000));
206
+ expect(result).toEqual({ cancel: true });
207
+ });
208
+
209
+ test("explicit /pi-vcc bypasses both the proactive flag AND threshold guard", () => {
210
+ setConfig({
211
+ debug: false,
212
+ overrideDefaultCompaction: true,
213
+ modelThresholds: {
214
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
215
+ },
216
+ });
217
+ const { pi, ctx, emit } = createMockPi(
218
+ { id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
219
+ { tokens: 50000, contextWindow: 128000, percent: 39 },
220
+ );
221
+ registerProactiveThresholdHook(pi);
222
+ registerBeforeCompactHook(pi);
223
+
224
+ // Direct /pi-vcc with tokens well below threshold — should still proceed
225
+ const entries = [
226
+ msg("m1", "user", "hello"),
227
+ msg("m2", "assistant", "hi"),
228
+ msg("m3", "user", "do work"),
229
+ msg("m4", "assistant", "done"),
230
+ ];
231
+ const result = emit("session_before_compact", makeBeforeCompactEvent(entries, "__pi_vcc__", 50000));
232
+ expect(result?.cancel).toBeUndefined();
233
+ expect(result?.compaction).toBeDefined();
234
+ });
235
+ });
236
+
237
+ describe("integration: proactive trigger + before-compact with overrideDefaultCompaction: false", () => {
238
+ afterEach(() => {
239
+ if (existsSync(CONFIG_PATH)) unlinkSync(CONFIG_PATH);
240
+ resetProactiveState();
241
+ });
242
+
243
+ test("proactive trigger fires, before-compact doesn't cancel, then pi-core handles summary", () => {
244
+ // When overrideDefaultCompaction: false, pi-vcc doesn't handle the summary
245
+ // for non-/pi-vcc compactions. But the threshold guard and proactive trigger
246
+ // should still work — the threshold guard controls WHEN compaction triggers,
247
+ // and pi-core handles the actual summary.
248
+ setConfig({
249
+ debug: false,
250
+ overrideDefaultCompaction: false,
251
+ modelThresholds: {
252
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
253
+ },
254
+ });
255
+ const { pi, ctx, emit, compactCalls } = createMockPi(
256
+ { id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
257
+ { tokens: 110000, contextWindow: 128000, percent: 86 },
258
+ );
259
+ registerProactiveThresholdHook(pi);
260
+ registerBeforeCompactHook(pi);
261
+
262
+ // agent_end fires → proactive trigger
263
+ emit("agent_end", { type: "agent_end", messages: [] });
264
+ expect(compactCalls).toHaveLength(1);
265
+
266
+ // session_before_compact fires: threshold is crossed (tokensBefore = 110k
267
+ // > 95232), and our guard allows it because proactiveTriggerActive.
268
+ // Then overrideDefaultCompaction: false means pi-vcc returns undefined,
269
+ // letting pi-core handle the summary.
270
+ const entries = [
271
+ msg("m1", "user", "hello"),
272
+ msg("m2", "assistant", "hi"),
273
+ msg("m3", "user", "do work"),
274
+ msg("m4", "assistant", "done"),
275
+ ];
276
+ const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 110000));
277
+ // pi-vcc doesn't handle it (overrideDefaultCompaction: false) → returns undefined
278
+ // pi-core will handle the summary
279
+ expect(result).toBeUndefined();
280
+ });
281
+
282
+ test("threshold guard cancels even with overrideDefaultCompaction: false", () => {
283
+ setConfig({
284
+ debug: false,
285
+ overrideDefaultCompaction: false,
286
+ modelThresholds: {
287
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
288
+ },
289
+ });
290
+ const { pi, ctx, emit } = createMockPi(
291
+ { id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
292
+ { tokens: 80000, contextWindow: 128000, percent: 63 },
293
+ );
294
+ registerProactiveThresholdHook(pi);
295
+ registerBeforeCompactHook(pi);
296
+
297
+ // No proactive trigger (context below threshold)
298
+ // Pi-core's global threshold triggers compaction, but per-model threshold
299
+ // says the model can handle more → cancel
300
+ const entries = [
301
+ msg("m1", "user", "hello"),
302
+ msg("m2", "assistant", "hi"),
303
+ ];
304
+ const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 80000));
305
+ expect(result).toEqual({ cancel: true });
306
+ });
307
+ });
308
+
309
+ describe("integration: cooldown prevents double compaction", () => {
310
+ afterEach(() => {
311
+ if (existsSync(CONFIG_PATH)) unlinkSync(CONFIG_PATH);
312
+ resetProactiveState();
313
+ });
314
+
315
+ test("agent_end + model_select on same turn: only one compact()", () => {
316
+ setConfig({
317
+ debug: false,
318
+ overrideDefaultCompaction: true,
319
+ modelThresholds: {
320
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
321
+ },
322
+ });
323
+ const { pi, ctx, emit, compactCalls } = createMockPi(
324
+ { id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
325
+ { tokens: 110000, contextWindow: 128000, percent: 86 },
326
+ );
327
+ registerProactiveThresholdHook(pi);
328
+
329
+ // agent_end triggers compact and sets cooldown
330
+ emit("agent_end", { type: "agent_end", messages: [] });
331
+ expect(compactCalls).toHaveLength(1);
332
+
333
+ // model_select fires on same turn — blocked by cooldown
334
+ emit("model_select", { type: "model_select" });
335
+ expect(compactCalls).toHaveLength(1);
336
+ });
337
+
338
+ test("two consecutive agent_ends without session_compact: second blocked by cooldown", () => {
339
+ setConfig({
340
+ debug: false,
341
+ overrideDefaultCompaction: true,
342
+ modelThresholds: {
343
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
344
+ },
345
+ });
346
+ const { pi, ctx, emit, compactCalls } = createMockPi(
347
+ { id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
348
+ { tokens: 110000, contextWindow: 128000, percent: 86 },
349
+ );
350
+ registerProactiveThresholdHook(pi);
351
+
352
+ emit("agent_end", { type: "agent_end", messages: [] });
353
+ expect(compactCalls).toHaveLength(1);
354
+
355
+ // No session_compact between — cooldown still active
356
+ emit("agent_end", { type: "agent_end", messages: [] });
357
+ expect(compactCalls).toHaveLength(1);
358
+ });
359
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2023"],
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "resolveJsonModule": true,
12
+ "declaration": true,
13
+ "outDir": ".tsbuild",
14
+ "rootDir": "."
15
+ },
16
+ "include": [
17
+ "index.ts",
18
+ "src/**/*.ts"
19
+ ]
20
+ }