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
package/dist/replay.js ADDED
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Replay engine — pure functions. PRD §M5c.
3
+ *
4
+ * Given an `EvalExample` and a candidate continuation produced by a
5
+ * provider variant under test, compute per-example quality metrics. The
6
+ * caller drives the actual provider invocation (this module stays I/O-free
7
+ * so it's trivially unit-testable and deterministic for fixture providers).
8
+ */
9
+ import { quantile } from "./bench.js";
10
+ /**
11
+ * Score one replay. `exactMatch` is the strict equality test;
12
+ * `prefixMatchLen` is the longest common leading-character run between
13
+ * the actual and the expected continuation; `editDistance` is plain
14
+ * Levenshtein. `savedAt{1,3,5}` is the PRD's `chars-saved / max(1, L)`
15
+ * over the top-k candidates.
16
+ */
17
+ export function evaluateExample(result) {
18
+ const expected = result.example.expected;
19
+ const actual = result.actual ?? "";
20
+ const exactMatch = actual === expected;
21
+ const prefixMatchLen = leadingMatch(actual, expected);
22
+ const editDistance = levenshtein(actual, expected);
23
+ const candidates = result.candidates ?? [actual];
24
+ return {
25
+ exactMatch,
26
+ prefixMatchLen,
27
+ editDistance,
28
+ savedAt1: savedAtK(candidates, expected, 1),
29
+ savedAt3: savedAtK(candidates, expected, 3),
30
+ savedAt5: savedAtK(candidates, expected, 5),
31
+ prefixRecallAt1: prefixRecallAtN(candidates, expected, 1),
32
+ prefixRecallAt3: prefixRecallAtN(candidates, expected, 3),
33
+ prefixRecallAt5: prefixRecallAtN(candidates, expected, 5),
34
+ };
35
+ }
36
+ /**
37
+ * First "identifier-or-punctuation" chunk of `s`. Mirrors the editor's
38
+ * `nextWordChunk` behavior without importing from ghost-editor (replay
39
+ * stays I/O-free). Skips leading whitespace, then either consumes an
40
+ * identifier run (`[A-Za-z0-9_]+`) or one punctuation char.
41
+ *
42
+ * Returns "" only when `s` has no non-whitespace content. The result
43
+ * INCLUDES the leading whitespace so that callers can `startsWith` the
44
+ * raw candidate against it without re-trimming.
45
+ */
46
+ export function firstTokenPrefix(s) {
47
+ if (!s)
48
+ return "";
49
+ let i = 0;
50
+ while (i < s.length && /\s/.test(s[i] ?? ""))
51
+ i++;
52
+ if (i >= s.length)
53
+ return "";
54
+ const start = i;
55
+ const isIdent = /[A-Za-z0-9_]/.test(s[i] ?? "");
56
+ if (isIdent) {
57
+ while (i < s.length && /[A-Za-z0-9_]/.test(s[i] ?? ""))
58
+ i++;
59
+ return s.slice(0, i);
60
+ }
61
+ // Single punctuation char + leading ws.
62
+ return s.slice(0, start + 1);
63
+ }
64
+ /**
65
+ * 1 if any of `candidates[0..n)` starts with `firstTokenPrefix(expected)`,
66
+ * else 0. PRD §M5b extension — ChaI-TeA's per-token recall metric. The
67
+ * binary 0/1 shape (vs. fractional `saved@k`) makes the rate interpretable
68
+ * directly as "fraction of expected first-tokens recovered."
69
+ */
70
+ export function prefixRecallAtN(candidates, expected, n) {
71
+ if (n <= 0 || candidates.length === 0 || !expected)
72
+ return 0;
73
+ const token = firstTokenPrefix(expected);
74
+ if (!token)
75
+ return 0;
76
+ const max = Math.min(n, candidates.length);
77
+ for (let i = 0; i < max; i++) {
78
+ const c = candidates[i] ?? "";
79
+ if (c.startsWith(token))
80
+ return 1;
81
+ }
82
+ return 0;
83
+ }
84
+ /**
85
+ * Number of leading characters where `a` and `b` agree. Used as the
86
+ * `prefixMatchLen` quality metric (PRD §M5b).
87
+ */
88
+ export function leadingMatch(a, b) {
89
+ const n = Math.min(a.length, b.length);
90
+ let i = 0;
91
+ while (i < n && a[i] === b[i])
92
+ i++;
93
+ return i;
94
+ }
95
+ /**
96
+ * `saved@k = max(0, charsSaved - acceptCost) / max(1, L)` per PRD §M5b,
97
+ * where `charsSaved` is the longest leading-match among ranks 1..k and
98
+ * `acceptCost = 1 + cycles` (one Right + cycle keystrokes). `k <= 0`
99
+ * returns 0; ranks beyond the array are skipped.
100
+ */
101
+ export function savedAtK(candidates, expected, k) {
102
+ if (k <= 0)
103
+ return 0;
104
+ const L = Math.max(1, expected.length);
105
+ let bestSaved = 0;
106
+ let bestRank = 0;
107
+ const max = Math.min(k, candidates.length);
108
+ for (let i = 0; i < max; i++) {
109
+ const c = candidates[i] ?? "";
110
+ const saved = leadingMatch(c, expected);
111
+ if (saved > bestSaved) {
112
+ bestSaved = saved;
113
+ bestRank = i + 1;
114
+ }
115
+ }
116
+ const acceptCost = bestRank === 0 ? 0 : bestRank; // 1 Right + (rank-1) cycles
117
+ return Math.max(0, bestSaved - acceptCost) / L;
118
+ }
119
+ /**
120
+ * Classic Levenshtein distance with single-row DP. O(n*m) time, O(min)
121
+ * space. Used by replay to flag near-matches in the bench.
122
+ */
123
+ export function levenshtein(a, b) {
124
+ if (a === b)
125
+ return 0;
126
+ if (a.length === 0)
127
+ return b.length;
128
+ if (b.length === 0)
129
+ return a.length;
130
+ // Swap so `b` is shorter — smaller inner row.
131
+ if (a.length < b.length)
132
+ [a, b] = [b, a];
133
+ let prev = new Array(b.length + 1);
134
+ let curr = new Array(b.length + 1);
135
+ for (let j = 0; j <= b.length; j++)
136
+ prev[j] = j;
137
+ for (let i = 1; i <= a.length; i++) {
138
+ curr[0] = i;
139
+ for (let j = 1; j <= b.length; j++) {
140
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
141
+ curr[j] = Math.min(prev[j] + 1, // deletion
142
+ curr[j - 1] + 1, // insertion
143
+ prev[j - 1] + cost);
144
+ }
145
+ const tmp = prev;
146
+ prev = curr;
147
+ curr = tmp;
148
+ }
149
+ return prev[b.length];
150
+ }
151
+ /**
152
+ * Aggregate per-example metrics + latencies into a single report. Skips
153
+ * error results from quality metrics but includes them in `count`/`errors`
154
+ * for transparency.
155
+ */
156
+ export function summarizeReplay(results) {
157
+ if (results.length === 0) {
158
+ return zeroSummary();
159
+ }
160
+ const ok = results.filter((r) => !r.error);
161
+ const errors = results.length - ok.length;
162
+ if (ok.length === 0) {
163
+ return { ...zeroSummary(), count: results.length, errors };
164
+ }
165
+ let exact = 0;
166
+ let sumPrefix = 0;
167
+ let sumEdit = 0;
168
+ let sumS1 = 0;
169
+ let sumS3 = 0;
170
+ let sumS5 = 0;
171
+ let sumPR1 = 0;
172
+ let sumPR3 = 0;
173
+ let sumPR5 = 0;
174
+ for (const r of ok) {
175
+ const m = evaluateExample(r);
176
+ if (m.exactMatch)
177
+ exact++;
178
+ sumPrefix += m.prefixMatchLen;
179
+ sumEdit += m.editDistance;
180
+ sumS1 += m.savedAt1;
181
+ sumS3 += m.savedAt3;
182
+ sumS5 += m.savedAt5;
183
+ sumPR1 += m.prefixRecallAt1;
184
+ sumPR3 += m.prefixRecallAt3;
185
+ sumPR5 += m.prefixRecallAt5;
186
+ }
187
+ const latencies = ok.map((r) => r.latencyMs).sort((a, b) => a - b);
188
+ return {
189
+ count: results.length,
190
+ errors,
191
+ exactMatchRate: exact / ok.length,
192
+ meanPrefixMatchLen: sumPrefix / ok.length,
193
+ meanEditDistance: sumEdit / ok.length,
194
+ meanSavedAt1: sumS1 / ok.length,
195
+ meanSavedAt3: sumS3 / ok.length,
196
+ meanSavedAt5: sumS5 / ok.length,
197
+ prefixRecallAt1: sumPR1 / ok.length,
198
+ prefixRecallAt3: sumPR3 / ok.length,
199
+ prefixRecallAt5: sumPR5 / ok.length,
200
+ p50LatencyMs: quantile(latencies, 0.5),
201
+ p95LatencyMs: quantile(latencies, 0.95),
202
+ };
203
+ }
204
+ function zeroSummary() {
205
+ return {
206
+ count: 0,
207
+ errors: 0,
208
+ exactMatchRate: 0,
209
+ meanPrefixMatchLen: 0,
210
+ meanEditDistance: 0,
211
+ meanSavedAt1: 0,
212
+ meanSavedAt3: 0,
213
+ meanSavedAt5: 0,
214
+ prefixRecallAt1: 0,
215
+ prefixRecallAt3: 0,
216
+ prefixRecallAt5: 0,
217
+ p50LatencyMs: 0,
218
+ p95LatencyMs: 0,
219
+ };
220
+ }
221
+ // `quantile` re-exported from `bench.ts` so replay + bench reports use
222
+ // the same percentile semantics (nearest-rank). Diverging implementations
223
+ // would mean the same dataset reports different p95s in the two tools.
224
+ export { quantile } from "./bench.js";
225
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Multi-source candidate reranker. See PRD §M3c.
3
+ *
4
+ * Pure function (`candidates, opts → ranked[]`). No I/O, no provider calls,
5
+ * no editor state — easy to unit-test without mocks.
6
+ *
7
+ * Pipeline:
8
+ * 1. Merge candidates by exact text (collapsing race-member duplicates,
9
+ * taking the max logprob across sources and accumulating the source set).
10
+ * 2. Score each merged candidate as a weighted sum of normalized features:
11
+ * logprob, profile-bias (M4 hook), length-prior, agreement bonus.
12
+ * 3. Tie-break (within 1e-6) on length-around-median, local-over-cloud,
13
+ * lexicographic.
14
+ *
15
+ * Missing logprobs (Mercury FIM today) map to the neutral mid-value 0.5
16
+ * after normalization so a single-provider Mercury candidate isn't
17
+ * penalized against a multi-provider race that returns logprobs.
18
+ */
19
+ import type { GhostCandidate } from "./providers/types.js";
20
+ export declare const TIE_EPSILON = 0.000001;
21
+ export declare const LENGTH_PRIOR_LOW = 5;
22
+ export declare const LENGTH_PRIOR_HIGH = 30;
23
+ export declare const LENGTH_PRIOR_ZERO_AT = 80;
24
+ /**
25
+ * Prefix-length threshold above which the lengthPrior plateau and decay
26
+ * tail scale up. Empirically (ChaI-TeA + Copilot data): the longer the
27
+ * typed prefix, the longer the completion the user actually wants. Below
28
+ * this threshold the curve matches the original (prefix-blind) behavior.
29
+ */
30
+ export declare const PREFIX_LENGTH_SCALE_THRESHOLD = 30;
31
+ export declare const FALLBACK_MEDIAN_LENGTH = 15;
32
+ export declare const MISSING_LOGPROB_NEUTRAL = 0.5;
33
+ export interface RerankWeights {
34
+ logprob: number;
35
+ profileBias: number;
36
+ lengthPrior: number;
37
+ agreement: number;
38
+ /**
39
+ * Enhancement #1: weight on the edit-history proximity feature. Default
40
+ * 0.10. Set to 0 to disable. Trimmed from `logprob` (0.05) and
41
+ * `agreement` (0.05) so the weight sum remains 1.0.
42
+ */
43
+ editProximity: number;
44
+ }
45
+ export declare const DEFAULT_WEIGHTS: RerankWeights;
46
+ export interface RerankerInput extends GhostCandidate {
47
+ /** Producing provider name. Multiple sources collapse on merge. */
48
+ provider: string;
49
+ /** True when `provider` is a `local` kind (Ollama / vLLM). */
50
+ local?: boolean;
51
+ }
52
+ export interface RerankerOpts {
53
+ weights?: RerankWeights;
54
+ /**
55
+ * Number of race members that participated. Used to normalize the
56
+ * agreement bonus: `(sources - 1) / (raceMembers - 1)`. Default 1.
57
+ */
58
+ raceMembers?: number;
59
+ /**
60
+ * Optional profile-bias scorer (M4 hook). Receives raw candidate text,
61
+ * returns a non-negative score. Missing → all candidates score 0.
62
+ */
63
+ profileBias?: (text: string) => number;
64
+ /**
65
+ * Enhancement #1: edit-history proximity scorer. Receives raw candidate
66
+ * text; returns a real number (negative permitted — candidates that
67
+ * resurrect recently-deleted tokens score below neutral). Missing →
68
+ * all candidates score 0.
69
+ */
70
+ editProximityScorer?: (text: string) => number;
71
+ /** Median length of historically-accepted ghosts. Default 15. */
72
+ medianAcceptedLength?: number;
73
+ /**
74
+ * Length of the typed prefix at the cursor (active line). When supplied
75
+ * the lengthPrior curve scales above `PREFIX_LENGTH_SCALE_THRESHOLD` so
76
+ * long-prefix queries are not penalized for long completions
77
+ * (empirical finding from ChaI-TeA / Copilot data).
78
+ */
79
+ prefixLen?: number;
80
+ }
81
+ export interface RerankedCandidate {
82
+ text: string;
83
+ score: number;
84
+ avgLogprob?: number;
85
+ sources: string[];
86
+ /** Internal — exposed for diagnostics + tie-break tests. */
87
+ scoreBreakdown: {
88
+ logprob: number;
89
+ profileBias: number;
90
+ lengthPrior: number;
91
+ agreement: number;
92
+ editProximity: number;
93
+ };
94
+ }
95
+ export interface MergedCandidate {
96
+ text: string;
97
+ avgLogprob?: number;
98
+ sources: Set<string>;
99
+ anyLocal: boolean;
100
+ }
101
+ /**
102
+ * Merge candidates by exact text, accumulating sources and taking the max
103
+ * logprob across providers (agreement = positive evidence).
104
+ */
105
+ export declare function mergeCandidates(cands: RerankerInput[]): MergedCandidate[];
106
+ /**
107
+ * Length prior for a candidate of `len` characters. `prefixLen` adjusts the
108
+ * plateau and decay bounds: completions get scored against a curve scaled to
109
+ * the typed prefix length, so long prefixes don't penalize long completions.
110
+ *
111
+ * When `prefixLen <= PREFIX_LENGTH_SCALE_THRESHOLD` (or omitted), the curve
112
+ * matches the original prefix-blind behavior: plateau over
113
+ * `[LENGTH_PRIOR_LOW, LENGTH_PRIOR_HIGH]`, linear ramp below LOW, linear
114
+ * decay between HIGH and `LENGTH_PRIOR_ZERO_AT`, and zero above ZERO_AT.
115
+ *
116
+ * When `prefixLen > PREFIX_LENGTH_SCALE_THRESHOLD`, the upper plateau (HIGH)
117
+ * and the zero-crossing (ZERO_AT) both scale by `prefixLen / THRESHOLD`:
118
+ * - prefixLen = 30: scale = 1.0 → HIGH=30, ZERO_AT=80 (unchanged)
119
+ * - prefixLen = 60: scale = 2.0 → HIGH=60, ZERO_AT=160
120
+ * - prefixLen = 120: scale = 4.0 → HIGH=120, ZERO_AT=320
121
+ * LOW stays fixed — even very long prefixes still penalize trivially-short
122
+ * (1–4 char) completions, matching empirical user behavior.
123
+ */
124
+ export declare function lengthPrior(len: number, prefixLen?: number): number;
125
+ /**
126
+ * Compute the prefix-length-aware HIGH and ZERO_AT bounds. Exposed for
127
+ * diagnostics + tests so the scaling logic can be verified directly.
128
+ */
129
+ export declare function lengthPriorBounds(prefixLen: number): {
130
+ high: number;
131
+ zeroAt: number;
132
+ };
133
+ export declare function rerank(cands: RerankerInput[], opts?: RerankerOpts): RerankedCandidate[];
134
+ /** Default confidence gate threshold (PRD §M3c.1). Set to 0 to disable. */
135
+ export declare const DEFAULT_MIN_CONFIDENCE = 0.55;
136
+ /** Default top-vs-second margin gate (PRD §M3c.1). */
137
+ export declare const DEFAULT_DISAGREEMENT_MARGIN = 0.05;
138
+ export interface ConfidenceGateOpts {
139
+ /** Suppress the ghost when the top score is below this. Range [0, 1]. */
140
+ minConfidence?: number;
141
+ /** Suppress when top - 2nd margin is below this. */
142
+ minMargin?: number;
143
+ }
144
+ /**
145
+ * After rerank, decide whether to show the top candidate at all. Returns the
146
+ * top candidate when both gates pass, else `null` (caller should fall back to
147
+ * cache miss / no ghost). PRD §M3c.1.
148
+ *
149
+ * Both gates apply only to the top vs. second-best. With a single candidate,
150
+ * the margin gate trivially passes (no rival to disagree with) and only
151
+ * `minConfidence` matters.
152
+ *
153
+ * Score range: with default weights summing to 1.0 (PRD §M3c) and each
154
+ * feature normalized to [0, 1], the weighted sum lands in [0, 1] too —
155
+ * `minConfidence=0.55` and `minMargin=0.05` are calibrated against that
156
+ * range. User-supplied weights via `PI_GHOST_RERANK_WEIGHTS` that don't
157
+ * sum to 1.0 shift the effective score range; adjust gates accordingly
158
+ * or set them to 0 to disable.
159
+ *
160
+ * PRD §M3c.1 lists a third gate ("`avgLogprob` exists and falls below a
161
+ * calibrated provider-specific threshold"). It depends on accept-rate
162
+ * buckets from M5/M5c replay — deferred until that data is in hand.
163
+ * Setting `minConfidence=0` disables both implemented gates.
164
+ */
165
+ export declare function applyConfidenceGate(ranked: RerankedCandidate[], opts?: ConfidenceGateOpts): RerankedCandidate | null;
166
+ /**
167
+ * Parse `PI_GHOST_MIN_CONFIDENCE`. Returns fallback when unset, non-finite,
168
+ * or outside [0, 1].
169
+ */
170
+ export declare function parseMinConfidenceEnv(raw: string | undefined): number;
171
+ /**
172
+ * Parse `PI_GHOST_RERANK_WEIGHTS=a,b,c,d[,e]` into a `RerankWeights`.
173
+ * Accepts 4 or 5 comma-separated weights:
174
+ * - 4 values: `logprob,profileBias,lengthPrior,agreement` (legacy form;
175
+ * `editProximity` defaults to 0 to preserve pre-#1 behavior).
176
+ * - 5 values: same plus `editProximity` (Enhancement #1).
177
+ * Falls back to defaults on parse error or invalid count. Negative weights
178
+ * are clamped to 0 ("ignore this signal").
179
+ */
180
+ export declare function parseWeightsEnv(raw: string | undefined): RerankWeights;
181
+ //# sourceMappingURL=reranker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reranker.d.ts","sourceRoot":"","sources":["../src/reranker.ts"],"names":[],"mappings":"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"}