pi-ghost-autocomplete 0.3.1 → 0.3.2

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 (155) hide show
  1. package/README.md +101 -6
  2. package/dist/bench-cli.js +81 -5
  3. package/dist/bench-cli.js.map +1 -1
  4. package/dist/bench.d.ts +130 -2
  5. package/dist/bench.d.ts.map +1 -1
  6. package/dist/bench.js +285 -4
  7. package/dist/bench.js.map +1 -1
  8. package/dist/cache.d.ts +124 -0
  9. package/dist/cache.d.ts.map +1 -0
  10. package/dist/cache.js +173 -0
  11. package/dist/cache.js.map +1 -0
  12. package/dist/candidate-rerank.d.ts +57 -0
  13. package/dist/candidate-rerank.d.ts.map +1 -0
  14. package/dist/candidate-rerank.js +78 -0
  15. package/dist/candidate-rerank.js.map +1 -0
  16. package/dist/config.d.ts +43 -0
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +148 -18
  19. package/dist/config.js.map +1 -1
  20. package/dist/context-aggregator.d.ts +14 -5
  21. package/dist/context-aggregator.d.ts.map +1 -1
  22. package/dist/context-aggregator.js +38 -9
  23. package/dist/context-aggregator.js.map +1 -1
  24. package/dist/context-selector.d.ts +128 -0
  25. package/dist/context-selector.d.ts.map +1 -0
  26. package/dist/context-selector.js +300 -0
  27. package/dist/context-selector.js.map +1 -0
  28. package/dist/cycle-manager.d.ts +102 -0
  29. package/dist/cycle-manager.d.ts.map +1 -0
  30. package/dist/cycle-manager.js +168 -0
  31. package/dist/cycle-manager.js.map +1 -0
  32. package/dist/edit-history-ring.d.ts +148 -0
  33. package/dist/edit-history-ring.d.ts.map +1 -0
  34. package/dist/edit-history-ring.js +262 -0
  35. package/dist/edit-history-ring.js.map +1 -0
  36. package/dist/entropy-stop.d.ts +102 -0
  37. package/dist/entropy-stop.d.ts.map +1 -0
  38. package/dist/entropy-stop.js +141 -0
  39. package/dist/entropy-stop.js.map +1 -0
  40. package/dist/eval-dataset.d.ts +66 -0
  41. package/dist/eval-dataset.d.ts.map +1 -0
  42. package/dist/eval-dataset.js +127 -0
  43. package/dist/eval-dataset.js.map +1 -0
  44. package/dist/fast-path-engine.d.ts +286 -0
  45. package/dist/fast-path-engine.d.ts.map +1 -0
  46. package/dist/fast-path-engine.js +341 -0
  47. package/dist/fast-path-engine.js.map +1 -0
  48. package/dist/fuzzy-matcher.d.ts +8 -0
  49. package/dist/fuzzy-matcher.d.ts.map +1 -1
  50. package/dist/fuzzy-matcher.js +5 -3
  51. package/dist/fuzzy-matcher.js.map +1 -1
  52. package/dist/ghost-editor.d.ts +321 -4
  53. package/dist/ghost-editor.d.ts.map +1 -1
  54. package/dist/ghost-editor.js +1190 -144
  55. package/dist/ghost-editor.js.map +1 -1
  56. package/dist/index.d.ts +17 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +81 -2
  59. package/dist/index.js.map +1 -1
  60. package/dist/keystroke-timer.d.ts +59 -0
  61. package/dist/keystroke-timer.d.ts.map +1 -0
  62. package/dist/keystroke-timer.js +94 -0
  63. package/dist/keystroke-timer.js.map +1 -0
  64. package/dist/metrics-builder.d.ts +71 -0
  65. package/dist/metrics-builder.d.ts.map +1 -0
  66. package/dist/metrics-builder.js +71 -0
  67. package/dist/metrics-builder.js.map +1 -0
  68. package/dist/metrics.d.ts +99 -2
  69. package/dist/metrics.d.ts.map +1 -1
  70. package/dist/metrics.js +131 -17
  71. package/dist/metrics.js.map +1 -1
  72. package/dist/path-matcher.d.ts +9 -0
  73. package/dist/path-matcher.d.ts.map +1 -1
  74. package/dist/path-matcher.js +5 -2
  75. package/dist/path-matcher.js.map +1 -1
  76. package/dist/profile-store.d.ts +82 -0
  77. package/dist/profile-store.d.ts.map +1 -0
  78. package/dist/profile-store.js +199 -0
  79. package/dist/profile-store.js.map +1 -0
  80. package/dist/profile.d.ts +185 -0
  81. package/dist/profile.d.ts.map +1 -0
  82. package/dist/profile.js +434 -0
  83. package/dist/profile.js.map +1 -0
  84. package/dist/providers/cloud-provider.d.ts +10 -1
  85. package/dist/providers/cloud-provider.d.ts.map +1 -1
  86. package/dist/providers/cloud-provider.js +71 -14
  87. package/dist/providers/cloud-provider.js.map +1 -1
  88. package/dist/providers/local-provider.d.ts +8 -1
  89. package/dist/providers/local-provider.d.ts.map +1 -1
  90. package/dist/providers/local-provider.js +15 -3
  91. package/dist/providers/local-provider.js.map +1 -1
  92. package/dist/providers/openai-compat-provider.d.ts +11 -1
  93. package/dist/providers/openai-compat-provider.d.ts.map +1 -1
  94. package/dist/providers/openai-compat-provider.js +93 -6
  95. package/dist/providers/openai-compat-provider.js.map +1 -1
  96. package/dist/providers/openai-completions-runner.d.ts +25 -1
  97. package/dist/providers/openai-completions-runner.d.ts.map +1 -1
  98. package/dist/providers/openai-completions-runner.js +109 -14
  99. package/dist/providers/openai-completions-runner.js.map +1 -1
  100. package/dist/providers/race.d.ts +58 -1
  101. package/dist/providers/race.d.ts.map +1 -1
  102. package/dist/providers/race.js +317 -4
  103. package/dist/providers/race.js.map +1 -1
  104. package/dist/providers/truncate.d.ts.map +1 -1
  105. package/dist/providers/truncate.js +20 -2
  106. package/dist/providers/truncate.js.map +1 -1
  107. package/dist/providers/types.d.ts +96 -1
  108. package/dist/providers/types.d.ts.map +1 -1
  109. package/dist/providers/types.js +59 -1
  110. package/dist/providers/types.js.map +1 -1
  111. package/dist/provisional-manager.d.ts +93 -0
  112. package/dist/provisional-manager.d.ts.map +1 -0
  113. package/dist/provisional-manager.js +98 -0
  114. package/dist/provisional-manager.js.map +1 -0
  115. package/dist/provisional.d.ts +150 -0
  116. package/dist/provisional.d.ts.map +1 -0
  117. package/dist/provisional.js +238 -0
  118. package/dist/provisional.js.map +1 -0
  119. package/dist/regret-tracker.d.ts +84 -0
  120. package/dist/regret-tracker.d.ts.map +1 -0
  121. package/dist/regret-tracker.js +145 -0
  122. package/dist/regret-tracker.js.map +1 -0
  123. package/dist/replay-cli.d.ts +13 -0
  124. package/dist/replay-cli.d.ts.map +1 -0
  125. package/dist/replay-cli.js +167 -0
  126. package/dist/replay-cli.js.map +1 -0
  127. package/dist/replay.d.ts +107 -0
  128. package/dist/replay.d.ts.map +1 -0
  129. package/dist/replay.js +225 -0
  130. package/dist/replay.js.map +1 -0
  131. package/dist/reranker.d.ts +181 -0
  132. package/dist/reranker.d.ts.map +1 -0
  133. package/dist/reranker.js +324 -0
  134. package/dist/reranker.js.map +1 -0
  135. package/dist/session-trie.d.ts +103 -0
  136. package/dist/session-trie.d.ts.map +1 -0
  137. package/dist/session-trie.js +280 -0
  138. package/dist/session-trie.js.map +1 -0
  139. package/dist/speculative.d.ts +74 -0
  140. package/dist/speculative.d.ts.map +1 -0
  141. package/dist/speculative.js +107 -0
  142. package/dist/speculative.js.map +1 -0
  143. package/dist/tool-summarize.d.ts +40 -0
  144. package/dist/tool-summarize.d.ts.map +1 -0
  145. package/dist/tool-summarize.js +245 -0
  146. package/dist/tool-summarize.js.map +1 -0
  147. package/dist/trie-sanitize.d.ts +22 -0
  148. package/dist/trie-sanitize.d.ts.map +1 -0
  149. package/dist/trie-sanitize.js +142 -0
  150. package/dist/trie-sanitize.js.map +1 -0
  151. package/dist/versions.d.ts +23 -0
  152. package/dist/versions.d.ts.map +1 -0
  153. package/dist/versions.js +31 -0
  154. package/dist/versions.js.map +1 -0
  155. package/package.json +3 -2
@@ -0,0 +1,71 @@
1
+ import { estimateTimeSavedMs } from "./keystroke-timer.js";
2
+ import { SWAP_FLICKER_WINDOW_MS } from "./provisional.js";
3
+ /**
4
+ * Build the metrics record for a ghost that was shown and is now being
5
+ * finalized. Pure — no I/O, no `Date.now()`, no env reads (caller resolves
6
+ * `now` and `shortHoverThresholdMs`).
7
+ */
8
+ export function buildShownMetricsRecord(input) {
9
+ const { pending: m, outcome, now } = input;
10
+ const isAccept = outcome === "accepted" || outcome === "accepted-partial";
11
+ const shouldEvictCache = !!(m.cacheKey && !isAccept);
12
+ const providers = m.trace
13
+ ? m.trace.providers
14
+ : [
15
+ {
16
+ provider: m.providerName,
17
+ latencyMs: m.latencyMs ?? 0,
18
+ result: "produced",
19
+ },
20
+ ];
21
+ const multi = input.candidateCount > 1;
22
+ const isNonAcceptOutcome = outcome === "dismissed" || outcome === "stale" || outcome === "expired";
23
+ const flicker = m.swapRenderedAt !== undefined &&
24
+ isNonAcceptOutcome &&
25
+ now - m.swapRenderedAt < SWAP_FLICKER_WINDOW_MS;
26
+ const hoverMs = m.shownAt !== undefined ? Math.max(0, now - m.shownAt) : undefined;
27
+ const shortHoverDismiss = outcome === "dismissed" &&
28
+ hoverMs !== undefined &&
29
+ hoverMs < input.shortHoverThresholdMs;
30
+ let shortHoverPenalty = null;
31
+ if (shortHoverDismiss && m.prefixAtShown && m.completion && m.completion.length > 0) {
32
+ const lastLine = m.prefixAtShown.split("\n").pop() ?? "";
33
+ if (lastLine)
34
+ shortHoverPenalty = { lastLine, completion: m.completion };
35
+ }
36
+ const acceptedChars = isAccept && m.completion ? m.completion.length : undefined;
37
+ const perceivedLatencyMs = m.ttftMs ?? m.latencyMs ?? 0;
38
+ const estimatedTimeSavedMs = acceptedChars !== undefined
39
+ ? estimateTimeSavedMs(acceptedChars, input.msPerChar, perceivedLatencyMs)
40
+ : undefined;
41
+ const record = {
42
+ ts: now,
43
+ requestId: m.requestId,
44
+ mode: m.mode,
45
+ providers,
46
+ winner: m.trace?.winner ?? m.providerName,
47
+ result: "produced",
48
+ completionLength: m.completion?.length,
49
+ shown: true,
50
+ acceptance: outcome,
51
+ matchedPath: m.matchedPath,
52
+ ...(acceptedChars !== undefined ? { acceptedChars } : {}),
53
+ ...(estimatedTimeSavedMs !== undefined ? { estimatedTimeSavedMs } : {}),
54
+ ...(multi
55
+ ? { candidateCount: input.candidateCount, candidateRank: input.candidateIdx + 1 }
56
+ : {}),
57
+ ...(input.cycledCount > 0 ? { cycledCount: input.cycledCount } : {}),
58
+ ...(input.partialAccepts > 0 ? { partialAccepts: input.partialAccepts } : {}),
59
+ ...(m.provisionalSwapMs !== undefined ? { provisionalSwapMs: m.provisionalSwapMs } : {}),
60
+ ...(m.provisionalWasCorrect !== undefined ? { provisionalWasCorrect: m.provisionalWasCorrect } : {}),
61
+ ...(flicker ? { provisionalSwapFlicker: true } : {}),
62
+ ...(shortHoverDismiss ? { shortHoverDismiss: true } : {}),
63
+ ...(m.typedPastDivergent ? { typedPastDivergent: true } : {}),
64
+ ...(hoverMs !== undefined ? { displayDurationMs: hoverMs } : {}),
65
+ ...(m.ttftMs !== undefined ? { ttftMs: m.ttftMs } : {}),
66
+ ...(m.editProximityScore !== undefined ? { editProximityScore: m.editProximityScore } : {}),
67
+ ...(m.editHistorySize !== undefined ? { editHistorySize: m.editHistorySize } : {}),
68
+ };
69
+ return { record, isAccept, shouldEvictCache, shortHoverPenalty };
70
+ }
71
+ //# sourceMappingURL=metrics-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-builder.js","sourceRoot":"","sources":["../src/metrics-builder.ts"],"names":[],"mappings":"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"}
package/dist/metrics.d.ts CHANGED
@@ -1,6 +1,13 @@
1
- export type CompletionMode = "deterministic" | "llm";
1
+ /**
2
+ * Source of truth for all completion modes. Both the type union (compile-time)
3
+ * and the parser whitelist (runtime, in `bench.ts`) derive from this array so
4
+ * adding a mode means updating one place.
5
+ */
6
+ export declare const COMPLETION_MODES: readonly ["deterministic", "llm", "cache", "trie", "speculative-warm", "provisional", "profile-slash"];
7
+ export type CompletionMode = (typeof COMPLETION_MODES)[number];
2
8
  export type RequestResult = "produced" | "empty" | "rejected" | "aborted" | "error";
3
- export type AcceptanceOutcome = "accepted" | "dismissed" | "stale" | "expired";
9
+ export type AcceptanceOutcome = "accepted" | "accepted-partial" | "dismissed" | "stale" | "expired";
10
+ export type QualityAttribution = "accepted" | "dismissed-attributed" | "unknown";
4
11
  export type RejectionReason = "stale-text" | "newline" | "too-long" | "assistant-phrasing" | "duplicate-suffix" | "markdown" | "empty" | "echo-token";
5
12
  export interface ProviderLatency {
6
13
  provider: string;
@@ -25,7 +32,91 @@ export interface MetricsRecord {
25
32
  * Never set for LLM mode (would risk leaking output text).
26
33
  */
27
34
  matchedPath?: string;
35
+ /** Characters of the ghost the user accepted (full or partial). */
36
+ acceptedChars?: number;
37
+ /** Chars from suggestion that matched the user's eventual committed text. */
38
+ prefixMatchLen?: number;
39
+ /** Levenshtein distance between top-1 candidate and committed line. */
40
+ editDistance?: number;
41
+ /** Count of Ctrl+Right partial accepts on this candidate. */
42
+ partialAccepts?: number;
43
+ /** 1-based rank accepted at time of accept (M3 candidate sets). */
44
+ candidateRank?: number;
45
+ /** Number of candidates considered. */
46
+ candidateCount?: number;
47
+ /** Number of Alt+]/Alt+[ cycles before acceptance. */
48
+ cycledCount?: number;
49
+ /** Prefix-match length per rank — numeric only. */
50
+ prefixMatchLenByRank?: number[];
51
+ /** saved@k by k. */
52
+ savedAt?: {
53
+ "1"?: number;
54
+ "3"?: number;
55
+ "5"?: number;
56
+ };
57
+ /** Time the ghost was visible to the user, in ms. */
58
+ displayDurationMs?: number;
59
+ /** Whether quality fields above are reliable for this record. */
60
+ qualityAttribution?: QualityAttribution;
61
+ /** Provider time-to-first-token in ms (streaming providers only). */
62
+ ttftMs?: number;
63
+ /** Time from provisional ghost render to LLM swap, in ms. */
64
+ provisionalSwapMs?: number;
65
+ /** True iff provisional matched LLM within prefix-match >= 0.8. */
66
+ provisionalWasCorrect?: boolean;
67
+ /**
68
+ * True iff a provisional→LLM swap was rendered and the user dismissed or
69
+ * aborted within `SWAP_FLICKER_WINDOW_MS`. Tracks the perceived flicker
70
+ * cost of swaps — the `PI_GHOST_PROVISIONAL_PREFER=1` knob trades raw
71
+ * recall for a lower value of this rate.
72
+ */
73
+ provisionalSwapFlicker?: boolean;
74
+ /**
75
+ * True iff the ghost was visible for less than `SHORT_HOVER_DISMISS_MS`
76
+ * before the user dismissed it. Mild negative signal — emitted on the
77
+ * non-accept record so M8 / future weighting can read it without joining
78
+ * separate streams. The actual hover duration is in `displayDurationMs`.
79
+ */
80
+ shortHoverDismiss?: boolean;
81
+ /**
82
+ * True iff the user typed at least `TYPED_PAST_DIVERGENT_THRESHOLD`
83
+ * consecutive characters that diverged from the served ghost without
84
+ * accepting it (#5). The detection runs across consecutive stale
85
+ * finalizations on the same line, so a single keystroke doesn't trip
86
+ * it — the run resets on any accept. When set, the editor also applies
87
+ * a session-trie penalty against the (prefix, ghost) pair so future
88
+ * suggestions on the same prefix are de-prioritised.
89
+ */
90
+ typedPastDivergent?: boolean;
91
+ /** Heuristic: acceptedChars * userAvgMsPerChar - perceivedLatencyMs. */
92
+ estimatedTimeSavedMs?: number;
93
+ /**
94
+ * True when the user deleted >50% of inserted text within the regret
95
+ * window after acceptance. See PRD §6 M5a.
96
+ */
97
+ acceptRegret?: boolean;
98
+ /** Inserted characters subsequently deleted within the regret window. */
99
+ regretDeletedChars?: number;
100
+ /** Combined behavior fingerprint at the time this record was logged. */
101
+ versionFingerprint?: string;
102
+ /**
103
+ * Top candidate's raw `editProximityScore` (un-normalized output of the
104
+ * scorer the reranker received). Pure observability — bench/replay
105
+ * correlate it with `acceptance` to validate the feature weight. Set
106
+ * only when reranker actually ran and edit-history was enabled.
107
+ */
108
+ editProximityScore?: number;
109
+ /**
110
+ * Size of the `EditHistoryRing` snapshot at predict time. Useful for
111
+ * filtering out records where the ring was still warming up.
112
+ */
113
+ editHistorySize?: number;
28
114
  }
115
+ /**
116
+ * Debug records have a loose payload by necessity (different kinds carry
117
+ * different shapes). The redactor below scrubs any field that looks like
118
+ * raw prompt/completion content before serialization — see `redactDebug`.
119
+ */
29
120
  export interface DebugRecord {
30
121
  ts: number;
31
122
  requestId: string;
@@ -53,4 +144,10 @@ export declare class MetricsLogger {
53
144
  flush(): Promise<void>;
54
145
  private enqueue;
55
146
  }
147
+ /**
148
+ * Strip any debug-record field not on the pass-through whitelist. Replaces
149
+ * the value with a `[redacted: type=T len=N]` placeholder so debugging still
150
+ * sees that *something* was there, without leaking content. SEC-27.
151
+ */
152
+ export declare function redactDebug(rec: DebugRecord): DebugRecord;
56
153
  //# sourceMappingURL=metrics.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,KAAK,CAAC;AAErD,MAAM,MAAM,aAAa,GACtB,UAAU,GACV,OAAO,GACP,UAAU,GACV,SAAS,GACT,OAAO,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,CAAC;AAE/E,MAAM,MAAM,eAAe,GACxB,YAAY,GACZ,SAAS,GACT,UAAU,GACV,oBAAoB,GACpB,kBAAkB,GAClB,UAAU,GACV,OAAO,GACP,YAAY,CAAC;AAEhB,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,eAAe,CAAC,EAAE,eAAe,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC7B,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,wBAAwB,IAAI,aAAa,CAKxD;AAED,qBAAa,aAAa;IAOxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPrB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAK;gBAGD,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,aAAa;IAMpC,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,YAAY,IAAI,MAAM;IAItB,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAKtC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAK7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO,CAAC,OAAO;CAGf"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
package/dist/metrics.js CHANGED
@@ -3,6 +3,46 @@ import { dirname, join } from "node:path";
3
3
  const MAX_BYTES = 10 * 1024 * 1024;
4
4
  const METRICS_REL = ".pi/ghost-autocomplete/metrics.jsonl";
5
5
  const DEBUG_REL = ".pi/ghost-autocomplete/debug.jsonl";
6
+ /**
7
+ * Source of truth for all completion modes. Both the type union (compile-time)
8
+ * and the parser whitelist (runtime, in `bench.ts`) derive from this array so
9
+ * adding a mode means updating one place.
10
+ */
11
+ export const COMPLETION_MODES = [
12
+ "deterministic",
13
+ "llm",
14
+ "cache",
15
+ "trie",
16
+ "speculative-warm",
17
+ "provisional",
18
+ "profile-slash",
19
+ ];
20
+ /**
21
+ * Fields callers may safely pass through to debug records. Anything outside
22
+ * this set is JSON-quoted but with its value replaced by a `[redacted-N]`
23
+ * placeholder showing only its length and type. SEC-27.
24
+ *
25
+ * To allow a new field type-safely, add it here and add a test in
26
+ * `metrics.test.ts`.
27
+ */
28
+ const DEBUG_PASS_THROUGH_KEYS = new Set([
29
+ "ts",
30
+ "requestId",
31
+ "kind",
32
+ "provider",
33
+ "providerName",
34
+ "mode",
35
+ "latencyMs",
36
+ "durationMs",
37
+ "length",
38
+ "count",
39
+ "status",
40
+ "errorName",
41
+ "reason",
42
+ "phase",
43
+ "branch",
44
+ "matchedPath",
45
+ ]);
6
46
  export function readMetricsConfigFromEnv() {
7
47
  return {
8
48
  metricsEnabled: process.env.PI_GHOST_METRICS === "1",
@@ -39,7 +79,7 @@ export class MetricsLogger {
39
79
  logDebug(record) {
40
80
  if (!this.cfg.debugEnabled)
41
81
  return;
42
- this.enqueue(() => writeLine(this.debugPath, record));
82
+ this.enqueue(() => writeLine(this.debugPath, redactDebug(record)));
43
83
  }
44
84
  async flush() {
45
85
  await this.writeQueue;
@@ -49,22 +89,96 @@ export class MetricsLogger {
49
89
  }
50
90
  }
51
91
  function redactMetric(rec) {
52
- const { ts, requestId, mode, providers, winner, result, rejectionReason, completionLength, shown, acceptance, matchedPath } = rec;
53
- const out = { ts, requestId, mode, result };
54
- if (providers && providers.length > 0)
55
- out.providers = providers;
56
- if (winner !== undefined)
57
- out.winner = winner;
58
- if (rejectionReason !== undefined)
59
- out.rejectionReason = rejectionReason;
60
- if (completionLength !== undefined)
61
- out.completionLength = completionLength;
62
- if (shown !== undefined)
63
- out.shown = shown;
64
- if (acceptance !== undefined)
65
- out.acceptance = acceptance;
66
- if (mode === "deterministic" && matchedPath !== undefined)
67
- out.matchedPath = matchedPath;
92
+ const out = { ts: rec.ts, requestId: rec.requestId, mode: rec.mode, result: rec.result };
93
+ if (rec.providers && rec.providers.length > 0)
94
+ out.providers = rec.providers;
95
+ if (rec.winner !== undefined)
96
+ out.winner = rec.winner;
97
+ if (rec.rejectionReason !== undefined)
98
+ out.rejectionReason = rec.rejectionReason;
99
+ if (rec.completionLength !== undefined)
100
+ out.completionLength = rec.completionLength;
101
+ if (rec.shown !== undefined)
102
+ out.shown = rec.shown;
103
+ if (rec.acceptance !== undefined)
104
+ out.acceptance = rec.acceptance;
105
+ if (rec.mode === "deterministic" && rec.matchedPath !== undefined)
106
+ out.matchedPath = rec.matchedPath;
107
+ // M5a — numeric/boolean fields only; no raw completion text.
108
+ if (rec.acceptedChars !== undefined)
109
+ out.acceptedChars = rec.acceptedChars;
110
+ if (rec.prefixMatchLen !== undefined)
111
+ out.prefixMatchLen = rec.prefixMatchLen;
112
+ if (rec.editDistance !== undefined)
113
+ out.editDistance = rec.editDistance;
114
+ if (rec.partialAccepts !== undefined)
115
+ out.partialAccepts = rec.partialAccepts;
116
+ if (rec.candidateRank !== undefined)
117
+ out.candidateRank = rec.candidateRank;
118
+ if (rec.candidateCount !== undefined)
119
+ out.candidateCount = rec.candidateCount;
120
+ if (rec.cycledCount !== undefined)
121
+ out.cycledCount = rec.cycledCount;
122
+ if (rec.prefixMatchLenByRank !== undefined)
123
+ out.prefixMatchLenByRank = rec.prefixMatchLenByRank;
124
+ if (rec.savedAt !== undefined)
125
+ out.savedAt = rec.savedAt;
126
+ if (rec.displayDurationMs !== undefined)
127
+ out.displayDurationMs = rec.displayDurationMs;
128
+ if (rec.qualityAttribution !== undefined)
129
+ out.qualityAttribution = rec.qualityAttribution;
130
+ if (rec.ttftMs !== undefined)
131
+ out.ttftMs = rec.ttftMs;
132
+ if (rec.provisionalSwapMs !== undefined)
133
+ out.provisionalSwapMs = rec.provisionalSwapMs;
134
+ if (rec.provisionalWasCorrect !== undefined)
135
+ out.provisionalWasCorrect = rec.provisionalWasCorrect;
136
+ if (rec.provisionalSwapFlicker !== undefined)
137
+ out.provisionalSwapFlicker = rec.provisionalSwapFlicker;
138
+ if (rec.shortHoverDismiss !== undefined)
139
+ out.shortHoverDismiss = rec.shortHoverDismiss;
140
+ if (rec.typedPastDivergent !== undefined)
141
+ out.typedPastDivergent = rec.typedPastDivergent;
142
+ if (rec.estimatedTimeSavedMs !== undefined)
143
+ out.estimatedTimeSavedMs = rec.estimatedTimeSavedMs;
144
+ if (rec.acceptRegret !== undefined)
145
+ out.acceptRegret = rec.acceptRegret;
146
+ if (rec.regretDeletedChars !== undefined)
147
+ out.regretDeletedChars = rec.regretDeletedChars;
148
+ if (rec.versionFingerprint !== undefined)
149
+ out.versionFingerprint = rec.versionFingerprint;
150
+ return out;
151
+ }
152
+ /**
153
+ * Strip any debug-record field not on the pass-through whitelist. Replaces
154
+ * the value with a `[redacted: type=T len=N]` placeholder so debugging still
155
+ * sees that *something* was there, without leaking content. SEC-27.
156
+ */
157
+ export function redactDebug(rec) {
158
+ const out = { ts: rec.ts, requestId: rec.requestId, kind: rec.kind };
159
+ for (const [k, v] of Object.entries(rec)) {
160
+ if (k === "ts" || k === "requestId" || k === "kind")
161
+ continue;
162
+ if (DEBUG_PASS_THROUGH_KEYS.has(k)) {
163
+ // Permit primitives and shallow arrays of primitives only.
164
+ if (v === null ||
165
+ typeof v === "boolean" ||
166
+ typeof v === "number" ||
167
+ typeof v === "string") {
168
+ out[k] = v;
169
+ }
170
+ else if (Array.isArray(v) && v.every((e) => typeof e === "number" || typeof e === "string")) {
171
+ out[k] = v;
172
+ }
173
+ else {
174
+ out[k] = `[redacted: type=${typeof v}]`;
175
+ }
176
+ continue;
177
+ }
178
+ const type = typeof v;
179
+ const len = typeof v === "string" ? v.length : Array.isArray(v) ? v.length : undefined;
180
+ out[k] = len !== undefined ? `[redacted: type=${type} len=${len}]` : `[redacted: type=${type}]`;
181
+ }
68
182
  return out;
69
183
  }
70
184
  async function writeLine(path, payload) {
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,15 @@ export interface PathPrefixMatch {
11
11
  export interface FindPathPrefixOptions {
12
12
  limit?: number;
13
13
  recentPaths?: Set<string> | null;
14
+ /**
15
+ * PRD §M4 — bounded boost from persistent path frequency. Caller passes
16
+ * `(path) => profileStore.profilePathBoost(path)` which returns a value
17
+ * in `[0, MAX_PATH_BOOST]` (0.2). Multiplied by 1e3 in the score formula
18
+ * so it ranks below recent-mention (1e6) but above path length, breaking
19
+ * ties between equally-fresh matches in favor of historically-frequent
20
+ * paths. Cannot beat subtree (1e9) — exact session matches still win.
21
+ */
22
+ profileBoost?: ((path: string) => number) | null;
14
23
  }
15
24
  /**
16
25
  * Extract a path-like token from the end of `before` (text before the cursor).
@@ -1 +1 @@
1
- {"version":3,"file":"path-matcher.d.ts","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;CACjC;AAKD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAevE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,qBAAqB,GAAG,MAAW,GACvC,eAAe,GAAG,IAAI,CA+BxB"}
1
+ {"version":3,"file":"path-matcher.d.ts","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACjC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC;CACjD;AAKD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAevE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,qBAAqB,GAAG,MAAW,GACvC,eAAe,GAAG,IAAI,CAmCxB"}
@@ -41,6 +41,7 @@ export function findPathPrefix(index, token, opts = {}) {
41
41
  const o = typeof opts === "number" ? { limit: opts } : opts;
42
42
  const limit = o.limit ?? 64;
43
43
  const recent = o.recentPaths ?? null;
44
+ const profileBoost = o.profileBoost ?? null;
44
45
  // Normalize a leading `./` — extractPathPrefixToken preserves it from the
45
46
  // user's text (e.g. "./src/con") but git ls-files entries never start with
46
47
  // `./`, so the prefix lookup would otherwise miss every cwd-relative entry.
@@ -57,8 +58,10 @@ export function findPathPrefix(index, token, opts = {}) {
57
58
  for (const m of matches) {
58
59
  const inSub = cwdRel === "" || m.startsWith(cwdRel);
59
60
  const rb = recentBoost(m, recent);
60
- // Lex-rank: subtree dominates, then recent-mention boost, then short.
61
- const score = (inSub ? 1_000_000_000 : 0) + rb * 1_000_000 - m.length;
61
+ const pb = profileBoost ? profileBoost(m) : 0;
62
+ // Lex-rank: subtree dominates, then recent-mention, then profile
63
+ // frequency (tie-breaker), then short.
64
+ const score = (inSub ? 1_000_000_000 : 0) + rb * 1_000_000 + pb * 1_000 - m.length;
62
65
  if (score > bestScore) {
63
66
  bestScore = score;
64
67
  best = m;
@@ -1 +1 @@
1
- {"version":3,"file":"path-matcher.js","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"path-matcher.js","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Stateful wrapper around `profile.ts` for the editor. Holds the in-memory
3
+ * `ProfileIndex`, serializes writes, triggers periodic compaction, and
4
+ * exposes a synchronous lookup surface for the editor's hot path.
5
+ *
6
+ * Lifecycle:
7
+ * 1. `create(cwd)` — loads + indexes the JSONL once. Returns a disabled
8
+ * store if `PI_GHOST_PROFILE=off`. Errors during load yield an empty
9
+ * index (best-effort).
10
+ * 2. `captureCommit(text)` / `captureAccept(prefix, completion, weight)`
11
+ * — append to disk (async, fire-and-forget) and merge into the
12
+ * in-memory index so the next lookup sees them immediately.
13
+ * 3. Every `COMPACT_CHECK_EVERY` writes the store runs `compactIfNeeded`
14
+ * in the background. Compaction reloads the index after rewrite.
15
+ *
16
+ * `disabled` is a public boolean so callers can short-circuit lookups
17
+ * without an extra function call on the keystroke path.
18
+ */
19
+ import { DEFAULT_DECAY_DAYS, type ProfileIndex } from "./profile.js";
20
+ export declare class ProfileStore {
21
+ private readonly cwd;
22
+ readonly disabled: boolean;
23
+ private index;
24
+ private writeQueue;
25
+ private writesSinceCompact;
26
+ private decayDays;
27
+ private constructor();
28
+ /**
29
+ * Build a store and load the JSONL into memory. Caller awaits before
30
+ * exposing the store to the editor so the index is hot on first
31
+ * keystroke. Disabled stores short-circuit load entirely.
32
+ */
33
+ static create(cwd: string, env?: NodeJS.ProcessEnv): Promise<ProfileStore>;
34
+ getIndex(): ProfileIndex;
35
+ get decayDaysSetting(): number;
36
+ /**
37
+ * Capture user-committed text. Extracts paths + slash + trigrams, drops
38
+ * sensitive messages entirely. Returns the count of records emitted —
39
+ * useful for tests/diagnostics.
40
+ */
41
+ captureCommit(text: string, ts?: number): number;
42
+ /**
43
+ * Capture an accept (full or partial). `weight` defaults to 3 to match
44
+ * PRD §M2 trie weights. Returns true when a record was emitted.
45
+ */
46
+ captureAccept(prefix: string, completion: string, weight?: number, ts?: number): boolean;
47
+ /** Public lookup surfaces — thin wrappers around `profile.ts`. */
48
+ bestSlashMatch(prefix: string): {
49
+ cmd: string;
50
+ weight: number;
51
+ } | null;
52
+ profileBias(text: string): number;
53
+ profilePathBoost(path: string): number;
54
+ /**
55
+ * Provisional fallback (PRD §M3.5b) — look up an exact-prefix accept
56
+ * record. Returns the completion tokens + summed weight, or null when
57
+ * the prefix has never been the exact key of a captured accept.
58
+ * `prefix` is hashed in-process; the raw string never leaves memory.
59
+ */
60
+ lookupAcceptByPrefix(prefix: string): {
61
+ completionTokens: string[];
62
+ weight: number;
63
+ } | null;
64
+ /** Flush any pending writes — call before process exit. */
65
+ flush(): Promise<void>;
66
+ /**
67
+ * Append records both in-memory and to disk. In-memory merge happens
68
+ * synchronously so the very next lookup sees the new weight; the disk
69
+ * write is queued through `writeQueue` to serialize concurrent commits.
70
+ */
71
+ private mergeAndPersist;
72
+ /**
73
+ * Inline equivalent of `buildIndex` for a small record batch. The
74
+ * fresh-record path skips decay since we just wrote `ts`. Keeping this
75
+ * separate from `profile.buildIndex` avoids reindexing the whole store
76
+ * on every keystroke.
77
+ */
78
+ private applyToIndex;
79
+ }
80
+ /** Exported for tests — surface compactor knob without re-exporting `profile.ts`. */
81
+ export { DEFAULT_DECAY_DAYS };
82
+ //# sourceMappingURL=profile-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-store.d.ts","sourceRoot":"","sources":["../src/profile-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAKN,kBAAkB,EASlB,KAAK,YAAY,EAEjB,MAAM,cAAc,CAAC;AAQtB,qBAAa,YAAY;IAQvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPrB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO;IAQP;;;;OAIG;WACU,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,YAAY,CAAC;IAe7F,QAAQ,IAAI,YAAY;IAIxB,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED;;;;OAIG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAE,MAAmB,GAAG,MAAM;IAQ5D;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAI,EAAE,EAAE,GAAE,MAAmB,GAAG,OAAO;IAQ/F,kEAAkE;IAClE,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKtE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKjC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKtC;;;;;OAKG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAM3F,2DAA2D;IACrD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;;OAIG;IACH,OAAO,CAAC,eAAe;IA0BvB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;CAmCpB;AAED,qFAAqF;AACrF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}