agentfootprint 6.22.0 → 6.24.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.
Files changed (92) hide show
  1. package/AGENTS.md +17 -0
  2. package/CLAUDE.md +17 -0
  3. package/README.md +58 -0
  4. package/dist/core/Agent.js +109 -18
  5. package/dist/core/Agent.js.map +1 -1
  6. package/dist/core/agent/stages/toolCalls.js +19 -4
  7. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  8. package/dist/esm/core/Agent.js +109 -18
  9. package/dist/esm/core/Agent.js.map +1 -1
  10. package/dist/esm/core/agent/stages/toolCalls.js +19 -4
  11. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  12. package/dist/esm/index.js.map +1 -1
  13. package/dist/esm/lib/influence-core/cache.js +149 -0
  14. package/dist/esm/lib/influence-core/cache.js.map +1 -0
  15. package/dist/esm/lib/influence-core/index.js +32 -0
  16. package/dist/esm/lib/influence-core/index.js.map +1 -0
  17. package/dist/esm/lib/influence-core/margin.js +110 -0
  18. package/dist/esm/lib/influence-core/margin.js.map +1 -0
  19. package/dist/esm/lib/influence-core/signals.js +232 -0
  20. package/dist/esm/lib/influence-core/signals.js.map +1 -0
  21. package/dist/esm/lib/influence-core/similarity.js +79 -0
  22. package/dist/esm/lib/influence-core/similarity.js.map +1 -0
  23. package/dist/esm/lib/influence-core/types.js +35 -0
  24. package/dist/esm/lib/influence-core/types.js.map +1 -0
  25. package/dist/esm/lib/trace-toolpack/bounded.js +76 -0
  26. package/dist/esm/lib/trace-toolpack/bounded.js.map +1 -0
  27. package/dist/esm/lib/trace-toolpack/index.js +10 -0
  28. package/dist/esm/lib/trace-toolpack/index.js.map +1 -0
  29. package/dist/esm/lib/trace-toolpack/traceToolpack.js +699 -0
  30. package/dist/esm/lib/trace-toolpack/traceToolpack.js.map +1 -0
  31. package/dist/esm/lib/trace-toolpack/types.js +24 -0
  32. package/dist/esm/lib/trace-toolpack/types.js.map +1 -0
  33. package/dist/esm/observe.js +12 -0
  34. package/dist/esm/observe.js.map +1 -1
  35. package/dist/esm/recorders/core/typedEmit.js +26 -0
  36. package/dist/esm/recorders/core/typedEmit.js.map +1 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/lib/influence-core/cache.js +155 -0
  39. package/dist/lib/influence-core/cache.js.map +1 -0
  40. package/dist/lib/influence-core/index.js +50 -0
  41. package/dist/lib/influence-core/index.js.map +1 -0
  42. package/dist/lib/influence-core/margin.js +114 -0
  43. package/dist/lib/influence-core/margin.js.map +1 -0
  44. package/dist/lib/influence-core/signals.js +242 -0
  45. package/dist/lib/influence-core/signals.js.map +1 -0
  46. package/dist/lib/influence-core/similarity.js +83 -0
  47. package/dist/lib/influence-core/similarity.js.map +1 -0
  48. package/dist/lib/influence-core/types.js +38 -0
  49. package/dist/lib/influence-core/types.js.map +1 -0
  50. package/dist/lib/trace-toolpack/bounded.js +86 -0
  51. package/dist/lib/trace-toolpack/bounded.js.map +1 -0
  52. package/dist/lib/trace-toolpack/index.js +16 -0
  53. package/dist/lib/trace-toolpack/index.js.map +1 -0
  54. package/dist/lib/trace-toolpack/traceToolpack.js +704 -0
  55. package/dist/lib/trace-toolpack/traceToolpack.js.map +1 -0
  56. package/dist/lib/trace-toolpack/types.js +28 -0
  57. package/dist/lib/trace-toolpack/types.js.map +1 -0
  58. package/dist/observe.js +31 -1
  59. package/dist/observe.js.map +1 -1
  60. package/dist/recorders/core/typedEmit.js +26 -0
  61. package/dist/recorders/core/typedEmit.js.map +1 -1
  62. package/dist/types/core/Agent.d.ts +40 -3
  63. package/dist/types/core/Agent.d.ts.map +1 -1
  64. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  65. package/dist/types/core/agent/types.d.ts +61 -1
  66. package/dist/types/core/agent/types.d.ts.map +1 -1
  67. package/dist/types/index.d.ts +2 -1
  68. package/dist/types/index.d.ts.map +1 -1
  69. package/dist/types/lib/influence-core/cache.d.ts +95 -0
  70. package/dist/types/lib/influence-core/cache.d.ts.map +1 -0
  71. package/dist/types/lib/influence-core/index.d.ts +33 -0
  72. package/dist/types/lib/influence-core/index.d.ts.map +1 -0
  73. package/dist/types/lib/influence-core/margin.d.ts +34 -0
  74. package/dist/types/lib/influence-core/margin.d.ts.map +1 -0
  75. package/dist/types/lib/influence-core/signals.d.ts +104 -0
  76. package/dist/types/lib/influence-core/signals.d.ts.map +1 -0
  77. package/dist/types/lib/influence-core/similarity.d.ts +26 -0
  78. package/dist/types/lib/influence-core/similarity.d.ts.map +1 -0
  79. package/dist/types/lib/influence-core/types.d.ts +158 -0
  80. package/dist/types/lib/influence-core/types.d.ts.map +1 -0
  81. package/dist/types/lib/trace-toolpack/bounded.d.ts +48 -0
  82. package/dist/types/lib/trace-toolpack/bounded.d.ts.map +1 -0
  83. package/dist/types/lib/trace-toolpack/index.d.ts +10 -0
  84. package/dist/types/lib/trace-toolpack/index.d.ts.map +1 -0
  85. package/dist/types/lib/trace-toolpack/traceToolpack.d.ts +70 -0
  86. package/dist/types/lib/trace-toolpack/traceToolpack.d.ts.map +1 -0
  87. package/dist/types/lib/trace-toolpack/types.d.ts +60 -0
  88. package/dist/types/lib/trace-toolpack/types.d.ts.map +1 -0
  89. package/dist/types/observe.d.ts +2 -0
  90. package/dist/types/observe.d.ts.map +1 -1
  91. package/dist/types/recorders/core/typedEmit.d.ts.map +1 -1
  92. package/package.json +3 -3
@@ -0,0 +1,110 @@
1
+ /**
2
+ * scoreMargin — choice-margin scoring over a candidate set
3
+ * (RFC-002 C4's core: (candidates, contextText, chosen) → scores +
4
+ * margin + flags).
5
+ *
6
+ * Pattern: pure async function, embedder-injected. NO recorder wiring
7
+ * — `toolChoiceRecorder` (C5) owns event ingestion and a
8
+ * KeyedStore, and calls this for the math.
9
+ * Role: `src/lib/influence-core/` leaf. No agent/runtime imports.
10
+ *
11
+ * The competition model (RFC-002 §4): embed the choice context (what
12
+ * the model saw — user message + latest reasoning), embed each offered
13
+ * candidate's text, rank candidates by similarity to the context.
14
+ * margin = score(best chosen) − score(best non-chosen)
15
+ * Small margin = fragile choice (`narrow`); top-scored candidate not
16
+ * among the chosen = `proxyDisagreement` (always worth surfacing:
17
+ * either a proxy miss or a genuinely surprising model choice).
18
+ *
19
+ * Honest claim: the scores are embedding geometry between context and
20
+ * descriptions — a proxy for the model's selection function, never
21
+ * "the model chose because". Margin is EVIDENCE of decisiveness, not
22
+ * proof; tier 3 (choice-entropy sampling) validates the proxy.
23
+ */
24
+ import { cosineSimilarity } from '../../memory/embedding/cosine.js';
25
+ import { DEFAULT_MARGIN_THRESHOLD } from './types.js';
26
+ /**
27
+ * Rank candidates by cosine similarity to the choice context and
28
+ * measure how decisively the chosen one(s) won.
29
+ *
30
+ * Returns ranked `scores` (descending; ties keep candidate input
31
+ * order), the `topScored` name, the `margin` (undefined when every
32
+ * candidate was chosen — no competition to measure; `narrow` is false
33
+ * in that case), and the two flags.
34
+ *
35
+ * Fail-loud validation: empty candidates/chosen, duplicate candidate
36
+ * names, or a chosen name missing from the candidates throw — those
37
+ * are wiring bugs in the caller, not runtime conditions.
38
+ */
39
+ export async function scoreMargin(args) {
40
+ const { candidates, chosen, embedder } = args;
41
+ const marginThreshold = args.marginThreshold ?? DEFAULT_MARGIN_THRESHOLD;
42
+ validate(candidates, chosen);
43
+ // One deduplicated embedding pass: context + distinct candidate texts.
44
+ const distinct = [...new Set([args.contextText, ...candidates.map((c) => c.text)])];
45
+ const vectors = embedder.embedBatch
46
+ ? await embedder.embedBatch({
47
+ texts: distinct,
48
+ ...(args.signal ? { signal: args.signal } : {}),
49
+ })
50
+ : await sequentialEmbed(embedder, distinct, args.signal);
51
+ const vectorByText = new Map();
52
+ for (let i = 0; i < distinct.length; i++)
53
+ vectorByText.set(distinct[i], vectors[i]);
54
+ const contextVec = vectorByText.get(args.contextText);
55
+ const scores = candidates.map((candidate) => ({
56
+ name: candidate.name,
57
+ score: cosineSimilarity(contextVec, vectorByText.get(candidate.text)),
58
+ }));
59
+ // Stable sort — ties keep candidate input order.
60
+ scores.sort((a, b) => b.score - a.score);
61
+ const chosenSet = new Set(chosen);
62
+ let bestChosen = -Infinity;
63
+ let bestOther = -Infinity;
64
+ for (const { name, score } of scores) {
65
+ if (chosenSet.has(name))
66
+ bestChosen = Math.max(bestChosen, score);
67
+ else
68
+ bestOther = Math.max(bestOther, score);
69
+ }
70
+ const margin = bestOther === -Infinity ? undefined : bestChosen - bestOther;
71
+ const topScored = scores[0].name;
72
+ return {
73
+ scores,
74
+ chosen: [...chosen],
75
+ topScored,
76
+ margin,
77
+ flags: {
78
+ narrow: margin !== undefined && margin < marginThreshold,
79
+ proxyDisagreement: !chosenSet.has(topScored),
80
+ },
81
+ };
82
+ }
83
+ async function sequentialEmbed(embedder, texts, signal) {
84
+ const out = [];
85
+ for (const text of texts) {
86
+ out.push(await embedder.embed({ text, ...(signal ? { signal } : {}) }));
87
+ }
88
+ return out;
89
+ }
90
+ function validate(candidates, chosen) {
91
+ if (candidates.length === 0) {
92
+ throw new Error('scoreMargin: candidates must be non-empty');
93
+ }
94
+ const names = new Set();
95
+ for (const candidate of candidates) {
96
+ if (names.has(candidate.name)) {
97
+ throw new Error(`scoreMargin: duplicate candidate name '${candidate.name}' — names must be unique`);
98
+ }
99
+ names.add(candidate.name);
100
+ }
101
+ if (chosen.length === 0) {
102
+ throw new Error('scoreMargin: chosen must be non-empty — calls that chose nothing have no margin to score');
103
+ }
104
+ for (const name of chosen) {
105
+ if (!names.has(name)) {
106
+ throw new Error(`scoreMargin: chosen '${name}' is not among the candidates`);
107
+ }
108
+ }
109
+ }
110
+ //# sourceMappingURL=margin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"margin.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/margin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * FDL influence signals — the four-signal composite from the Visible
3
+ * Reasoning paper (Eq. 1–6), extracted verbatim as RFC-003 block D6.
4
+ *
5
+ * Pattern: pure scorer functions + one async orchestrator. Vector-level
6
+ * functions are deterministic and embedder-free; only
7
+ * `scoreInfluence` touches the injected `Embedder`.
8
+ * Role: `src/lib/influence-core/` leaf. Consumers: the FDL paper
9
+ * pipeline (stage 5, computeInfluenceScores), RFC-003 D7's
10
+ * LLM-edge weigher, and — one level up — RFC-002's margin
11
+ * scoring shares the same geometry via `margin.ts`.
12
+ *
13
+ * ## Honest claim per signal (RFC-002 §2 discipline)
14
+ *
15
+ * Every signal is embedding GEOMETRY — a deterministic proxy, not a
16
+ * window into the model:
17
+ *
18
+ * - FA "the tool's output is semantically close to the final
19
+ * answer" — NOT "the answer was derived from it".
20
+ * - AVG "the tool's output stayed semantically close to the
21
+ * reasoning steps" — NOT "the model kept consulting it".
22
+ * - PERSIST "many reasoning steps are similar to it above T" — breadth
23
+ * of apparent reference, NOT counted citations.
24
+ * - DEPTH pure structure (1/(1+ancestors)) — directness of position
25
+ * in the trace, knows nothing about content at all.
26
+ *
27
+ * The composite S(d) means "high semantic alignment with the answer",
28
+ * never "this source contributed X% of the answer" (paper §5.2: scores
29
+ * are per-item, not additive, not causal attribution). Same inputs →
30
+ * same scores, unlike LLM-as-judge.
31
+ */
32
+ import { cosineSimilarity } from '../../memory/embedding/cosine.js';
33
+ import { DEFAULT_INFLUENCE_WEIGHTS, DEFAULT_PERSISTENCE_THRESHOLD } from './types.js';
34
+ /**
35
+ * FA — Final Answer Similarity (paper Eq. 1).
36
+ *
37
+ * `FA(d) = sim(e_d, e_f)` — cosine between the evidence embedding and
38
+ * the final-answer embedding. The strongest prior: verbatim or
39
+ * paraphrased reuse of a tool result scores high. Proxy: semantic
40
+ * overlap, not provenance.
41
+ */
42
+ export function finalAnswerSimilarity(evidenceVec, finalAnswerVec) {
43
+ return cosineSimilarity(evidenceVec, finalAnswerVec);
44
+ }
45
+ /**
46
+ * AVG — Average Relevancy (paper Eq. 2).
47
+ *
48
+ * Mean cosine between the evidence and each LLM reasoning ancestor;
49
+ * 0 when there are no ancestors (structurally zero — see
50
+ * `adaptWeights`). Proxy: consistent semantic closeness across the
51
+ * chain, not actual consultation.
52
+ */
53
+ export function averageRelevancy(evidenceVec, ancestorVecs) {
54
+ const n = ancestorVecs.length;
55
+ if (n === 0)
56
+ return 0;
57
+ let sum = 0;
58
+ for (const ancestorVec of ancestorVecs) {
59
+ sum += cosineSimilarity(evidenceVec, ancestorVec);
60
+ }
61
+ return sum / n;
62
+ }
63
+ /**
64
+ * PERSIST — Persistence (paper Eq. 3).
65
+ *
66
+ * Fraction of ancestors whose similarity to the evidence EXCEEDS the
67
+ * threshold T (strict `>`, default 0.30); 0 when there are no
68
+ * ancestors. Unlike AVG it measures BREADTH: referenced in 4 of 5
69
+ * steps (0.8) beats referenced intensely in 1. Proxy: similarity
70
+ * above a tunable bar, not counted citations.
71
+ */
72
+ export function persistence(evidenceVec, ancestorVecs, threshold = DEFAULT_PERSISTENCE_THRESHOLD) {
73
+ const n = ancestorVecs.length;
74
+ if (n === 0)
75
+ return 0;
76
+ let above = 0;
77
+ for (const ancestorVec of ancestorVecs) {
78
+ if (cosineSimilarity(evidenceVec, ancestorVec) > threshold)
79
+ above += 1;
80
+ }
81
+ return above / n;
82
+ }
83
+ /**
84
+ * DEPTH — Structural Proximity (paper Eq. 4).
85
+ *
86
+ * `DEPTH(d) = 1 / (1 + n)` where n counts LLM reasoning ancestors
87
+ * ONLY (not pipeline plumbing — callers decide what counts as an
88
+ * ancestor when building `EvidenceInput.ancestorTexts`). Direct
89
+ * evidence with no intermediaries gets exactly 1.0. The only
90
+ * content-blind signal: pure trace structure.
91
+ */
92
+ export function structuralProximity(ancestorCount) {
93
+ if (!Number.isInteger(ancestorCount) || ancestorCount < 0) {
94
+ throw new Error(`structuralProximity: ancestorCount must be a non-negative integer (got ${ancestorCount})`);
95
+ }
96
+ return 1 / (1 + ancestorCount);
97
+ }
98
+ /**
99
+ * Adaptive weight redistribution (paper Eq. 6, §5.3).
100
+ *
101
+ * When an item has NO LLM ancestors, AVG and PERSIST are structurally
102
+ * zero — not because the evidence was uninfluential, but because there
103
+ * is nothing to measure against. Without adaptation its score is
104
+ * capped at α+δ (≈0.50 under defaults). Eq. 6 moves the β+γ mass onto
105
+ * FA and DEPTH preserving their ratio:
106
+ *
107
+ * α′ = α + (β+γ)·α/(α+δ), δ′ = δ + (β+γ)·δ/(α+δ), β′ = γ′ = 0
108
+ *
109
+ * Defaults → α′=0.80, δ′=0.20 (the 4:1 FA:DEPTH ratio kept).
110
+ * Per-evidence-item: in a multi-tool pipeline some items adapt while
111
+ * others keep standard weights; `adapted` says which (surface it — the
112
+ * paper's UI marks adapted items).
113
+ *
114
+ * Degenerate guard: if α+δ = 0 there is no defined ratio to preserve —
115
+ * weights return unchanged with `adapted: false`, and the composite is
116
+ * honestly 0 for a no-ancestor item.
117
+ */
118
+ export function adaptWeights(weights, ancestorCount) {
119
+ if (ancestorCount > 0)
120
+ return { weights, adapted: false };
121
+ const base = weights.fa + weights.depth;
122
+ if (base === 0)
123
+ return { weights, adapted: false };
124
+ const mass = weights.avg + weights.persist;
125
+ return {
126
+ weights: {
127
+ fa: weights.fa + (mass * weights.fa) / base,
128
+ avg: 0,
129
+ persist: 0,
130
+ depth: weights.depth + (mass * weights.depth) / base,
131
+ },
132
+ adapted: mass > 0,
133
+ };
134
+ }
135
+ /**
136
+ * Composite score S(d) (paper Eq. 5).
137
+ *
138
+ * `S = α·FA + β·AVG + γ·PERSIST + δ·DEPTH` under the given weights —
139
+ * pass the EFFECTIVE weights from `adaptWeights` for no-ancestor
140
+ * items. With weights summing to 1, S ∈ [−(α+β), 1] (FA/AVG are
141
+ * cosines and may go negative; PERSIST/DEPTH are non-negative).
142
+ */
143
+ export function compositeScore(signals, weights) {
144
+ return (weights.fa * signals.fa +
145
+ weights.avg * signals.avg +
146
+ weights.persist * signals.persist +
147
+ weights.depth * signals.depth);
148
+ }
149
+ /**
150
+ * Score every evidence item on the four FDL signals and rank by
151
+ * composite, descending (paper pipeline stages 4–6 in one call:
152
+ * embed → score → rank). Ties keep input order (stable sort).
153
+ *
154
+ * Deterministic for a deterministic embedder: same inputs → same
155
+ * scores. All texts are embedded in ONE deduplicated batch — with an
156
+ * `EmbeddingCache` injected, repeat calls embed nothing.
157
+ *
158
+ * Honest claim: ranked semantic-alignment proxies. NOT causal
159
+ * attribution — see module docs.
160
+ */
161
+ export async function scoreInfluence(args) {
162
+ const weights = args.weights ?? DEFAULT_INFLUENCE_WEIGHTS;
163
+ assertValidWeights(weights);
164
+ const threshold = args.persistenceThreshold ?? DEFAULT_PERSISTENCE_THRESHOLD;
165
+ assertUniqueIds(args.evidence);
166
+ // ONE deduplicated embedding pass over every distinct text.
167
+ const texts = new Set([args.finalAnswerText]);
168
+ for (const item of args.evidence) {
169
+ texts.add(item.text);
170
+ for (const ancestor of item.ancestorTexts)
171
+ texts.add(ancestor);
172
+ }
173
+ const vectorByText = await embedAll(args.embedder, [...texts], args.signal);
174
+ const finalVec = vectorByText.get(args.finalAnswerText);
175
+ const scored = args.evidence.map((item) => {
176
+ const evidenceVec = vectorByText.get(item.text);
177
+ const ancestorVecs = item.ancestorTexts.map((t) => vectorByText.get(t));
178
+ const signals = {
179
+ fa: finalAnswerSimilarity(evidenceVec, finalVec),
180
+ avg: averageRelevancy(evidenceVec, ancestorVecs),
181
+ persist: persistence(evidenceVec, ancestorVecs, threshold),
182
+ depth: structuralProximity(ancestorVecs.length),
183
+ };
184
+ const effective = adaptWeights(weights, ancestorVecs.length);
185
+ return {
186
+ id: item.id,
187
+ signals,
188
+ weights: effective.weights,
189
+ adapted: effective.adapted,
190
+ score: compositeScore(signals, effective.weights),
191
+ };
192
+ });
193
+ // Stable sort — equal scores keep evidence input order.
194
+ return scored.sort((a, b) => b.score - a.score);
195
+ }
196
+ /** Embed distinct texts via batch API when available, else sequentially. */
197
+ async function embedAll(embedder, texts, signal) {
198
+ const vectors = embedder.embedBatch
199
+ ? await embedder.embedBatch({ texts, ...(signal ? { signal } : {}) })
200
+ : await sequentialEmbed(embedder, texts, signal);
201
+ const byText = new Map();
202
+ for (let i = 0; i < texts.length; i++)
203
+ byText.set(texts[i], vectors[i]);
204
+ return byText;
205
+ }
206
+ async function sequentialEmbed(embedder, texts, signal) {
207
+ const out = [];
208
+ for (const text of texts) {
209
+ out.push(await embedder.embed({ text, ...(signal ? { signal } : {}) }));
210
+ }
211
+ return out;
212
+ }
213
+ function assertValidWeights(weights) {
214
+ for (const [name, value] of Object.entries(weights)) {
215
+ if (!Number.isFinite(value) || value < 0) {
216
+ throw new Error(`scoreInfluence: weight '${name}' must be a finite non-negative number (got ${value})`);
217
+ }
218
+ }
219
+ if (weights.fa + weights.avg + weights.persist + weights.depth === 0) {
220
+ throw new Error('scoreInfluence: all weights are zero — the composite would always be 0');
221
+ }
222
+ }
223
+ function assertUniqueIds(evidence) {
224
+ const seen = new Set();
225
+ for (const item of evidence) {
226
+ if (seen.has(item.id)) {
227
+ throw new Error(`scoreInfluence: duplicate evidence id '${item.id}' — ids must be unique`);
228
+ }
229
+ seen.add(item.id);
230
+ }
231
+ }
232
+ //# sourceMappingURL=signals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAQpE,OAAO,EAAE,yBAAyB,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAEtF;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,WAA8B,EAC9B,cAAiC;IAEjC,OAAO,gBAAgB,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAA8B,EAC9B,YAA8C;IAE9C,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC;IAC9B,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,GAAG,IAAI,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CACzB,WAA8B,EAC9B,YAA8C,EAC9C,YAAoB,6BAA6B;IAEjD,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC;IAC9B,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,IAAI,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,GAAG,SAAS;YAAE,KAAK,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,KAAK,GAAG,CAAC,CAAC;AACnB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,aAAqB;IACvD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CACb,0EAA0E,aAAa,GAAG,CAC3F,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAyB,EACzB,aAAqB;IAErB,IAAI,aAAa,GAAG,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC;IACxC,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC;IAC3C,OAAO;QACL,OAAO,EAAE;YACP,EAAE,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI;YAC3C,GAAG,EAAE,CAAC;YACN,OAAO,EAAE,CAAC;YACV,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI;SACrD;QACD,OAAO,EAAE,IAAI,GAAG,CAAC;KAClB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,OAAqB,EAAE,OAAyB;IAC7E,OAAO,CACL,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE;QACvB,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG;QACzB,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO;QACjC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAC9B,CAAC;AACJ,CAAC;AAqBD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAwB;IAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,yBAAyB,CAAC;IAC1D,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,IAAI,6BAA6B,CAAC;IAC7E,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE/B,4DAA4D;IAC5D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,aAAa;YAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAE5E,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAsB,CAAC;IAE7E,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAkB,EAAE;QACxD,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAsB,CAAC;QACrE,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAsB,CAAC,CAAC;QAE7F,MAAM,OAAO,GAAiB;YAC5B,EAAE,EAAE,qBAAqB,CAAC,WAAW,EAAE,QAAQ,CAAC;YAChD,GAAG,EAAE,gBAAgB,CAAC,WAAW,EAAE,YAAY,CAAC;YAChD,OAAO,EAAE,WAAW,CAAC,WAAW,EAAE,YAAY,EAAE,SAAS,CAAC;YAC1D,KAAK,EAAE,mBAAmB,CAAC,YAAY,CAAC,MAAM,CAAC;SAChD,CAAC;QACF,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QAE7D,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,OAAO;YACP,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,KAAK,EAAE,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC;SAClD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC;AAED,4EAA4E;AAC5E,KAAK,UAAU,QAAQ,CACrB,QAAkB,EAClB,KAAwB,EACxB,MAAoB;IAEpB,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU;QACjC,CAAC,CAAC,MAAM,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QACrE,CAAC,CAAC,MAAM,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,QAAkB,EAClB,KAAwB,EACxB,MAAoB;IAEpB,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAyB;IACnD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,2BAA2B,IAAI,+CAA+C,KAAK,GAAG,CACvF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,QAAkC;IACzD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,0CAA0C,IAAI,CAAC,EAAE,wBAAwB,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;AACH,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * pairwiseSimilarity — pairwise cosine over a set of texts
3
+ * (RFC-002 C1's core: tool descriptions → matrix + ranked pairs).
4
+ *
5
+ * Pattern: pure async function, embedder-injected. No thresholds, no
6
+ * verdicts, no lint rules — those are C1's `analyzeToolCatalog`
7
+ * policy layer ON TOP of this geometry. The core stays
8
+ * reusable for any "how confusable are these texts" question.
9
+ * Role: `src/lib/influence-core/` leaf. No agent/runtime imports.
10
+ *
11
+ * Honest claim: similarity is embedding geometry over the DESCRIPTIONS
12
+ * — a confusability HEURISTIC, not a measurement of the model's actual
13
+ * selection function (RFC-002 §2; tier 3 validates the proxy via
14
+ * choice-entropy sampling).
15
+ */
16
+ import { cosineSimilarity } from '../../memory/embedding/cosine.js';
17
+ /**
18
+ * Embed every item once (deduplicated batch) and compute the full
19
+ * cosine matrix plus ranked upper-triangle pairs (descending; ties
20
+ * keep input pair order).
21
+ *
22
+ * Invariants (pinned by property tests):
23
+ * - `matrix[i][j] === matrix[j][i]` — computed once, mirrored.
24
+ * - `matrix[i][i] === 1` EXACTLY — set by definition, so
25
+ * self-similarity is an invariant rather than a float artifact
26
+ * (and duplicate texts at different ids still compare via cosine).
27
+ * - N items → N·(N−1)/2 pairs.
28
+ */
29
+ export async function pairwiseSimilarity(args) {
30
+ const { items, embedder } = args;
31
+ assertUniqueIds(items);
32
+ const ids = items.map((item) => item.id);
33
+ if (items.length === 0)
34
+ return { ids, matrix: [], pairs: [] };
35
+ // Deduplicated embedding pass (identical descriptions embed once).
36
+ const distinct = [...new Set(items.map((item) => item.text))];
37
+ const vectors = embedder.embedBatch
38
+ ? await embedder.embedBatch({
39
+ texts: distinct,
40
+ ...(args.signal ? { signal: args.signal } : {}),
41
+ })
42
+ : await sequentialEmbed(embedder, distinct, args.signal);
43
+ const vectorByText = new Map();
44
+ for (let i = 0; i < distinct.length; i++)
45
+ vectorByText.set(distinct[i], vectors[i]);
46
+ const itemVecs = items.map((item) => vectorByText.get(item.text));
47
+ // Upper triangle once, mirrored; diagonal exactly 1 by definition.
48
+ const matrix = items.map(() => new Array(items.length).fill(0));
49
+ const pairs = [];
50
+ for (let i = 0; i < items.length; i++) {
51
+ matrix[i][i] = 1;
52
+ for (let j = i + 1; j < items.length; j++) {
53
+ const similarity = cosineSimilarity(itemVecs[i], itemVecs[j]);
54
+ matrix[i][j] = similarity;
55
+ matrix[j][i] = similarity;
56
+ pairs.push({ a: ids[i], b: ids[j], similarity });
57
+ }
58
+ }
59
+ // Stable sort — ties keep (i, j) input order.
60
+ pairs.sort((p, q) => q.similarity - p.similarity);
61
+ return { ids, matrix, pairs };
62
+ }
63
+ async function sequentialEmbed(embedder, texts, signal) {
64
+ const out = [];
65
+ for (const text of texts) {
66
+ out.push(await embedder.embed({ text, ...(signal ? { signal } : {}) }));
67
+ }
68
+ return out;
69
+ }
70
+ function assertUniqueIds(items) {
71
+ const seen = new Set();
72
+ for (const item of items) {
73
+ if (seen.has(item.id)) {
74
+ throw new Error(`pairwiseSimilarity: duplicate item id '${item.id}' — ids must be unique`);
75
+ }
76
+ seen.add(item.id);
77
+ }
78
+ }
79
+ //# sourceMappingURL=similarity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/similarity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * influence-core types — the ONE embedding-based scoring contract.
3
+ *
4
+ * Pattern: Strategy seam (plug-and-play meta-pattern) — the frame and
5
+ * rule engine are the library's; the `Embedder` is consumer-
6
+ * injected, exactly like NarrativeFormatter / reliability /
7
+ * permission / commentary strategies.
8
+ * Role: `src/lib/` leaf module. Shared by the FDL paper pipeline
9
+ * (Visible Reasoning, Eq. 1–6), RFC-002's tool-catalog lint +
10
+ * margin recorder (C1/C4/C5), and RFC-003 Part B's LLM-edge
11
+ * weigher (D7). Extracted as RFC-003 block D6 so all three
12
+ * consumers share one scoring engine and one embedding cache.
13
+ *
14
+ * ## Honest claim (RFC-002 §2, the FDL discipline)
15
+ *
16
+ * Every score produced under these types is a PROXY computed from
17
+ * embedding geometry — cosine similarity over consumer-injected
18
+ * embeddings. None of it reads model internals. Scores mean "high
19
+ * semantic alignment", never "the model chose/answered BECAUSE".
20
+ * Scores are not additive across items and are not causal attribution
21
+ * — counterfactual ablation (RFC-003 stage 4) is where causal claims
22
+ * live.
23
+ */
24
+ /** Paper defaults: α=0.40, β=0.30, γ=0.20, δ=0.10 (sum to 1.0). */
25
+ export const DEFAULT_INFLUENCE_WEIGHTS = Object.freeze({
26
+ fa: 0.4,
27
+ avg: 0.3,
28
+ persist: 0.2,
29
+ depth: 0.1,
30
+ });
31
+ /** Paper default for the PERSIST threshold T (Eq. 3). */
32
+ export const DEFAULT_PERSISTENCE_THRESHOLD = 0.3;
33
+ /** RFC-002 §4 default: margins below this flag the choice as `narrow`. */
34
+ export const DEFAULT_MARGIN_THRESHOLD = 0.05;
35
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AA0BH,mEAAmE;AACnE,MAAM,CAAC,MAAM,yBAAyB,GAAqB,MAAM,CAAC,MAAM,CAAC;IACvE,EAAE,EAAE,GAAG;IACP,GAAG,EAAE,GAAG;IACR,OAAO,EAAE,GAAG;IACZ,KAAK,EAAE,GAAG;CACX,CAAC,CAAC;AAEH,yDAAyD;AACzD,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAEjD,0EAA0E;AAC1E,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Bounded serialization helpers for the trace toolpack.
3
+ *
4
+ * Pattern: pure functions — no state, no events.
5
+ * Role: The token-economics layer. EVERY value the toolpack serves goes
6
+ * through these: previews are capped, truncation is EXPLICIT
7
+ * (never silent), and nested-path keys round-trip between the
8
+ * engine's DELIM encoding and LLM-friendly dot notation.
9
+ */
10
+ /**
11
+ * footprintjs's canonical nested-path delimiter (ASCII unit separator,
12
+ * `src/lib/memory/utils.ts`). Internal to the engine — the toolpack
13
+ * translates it to/from dot notation so the LLM never sees a control char.
14
+ */
15
+ export const FP_PATH_DELIM = '\u001F';
16
+ /** Engine path → LLM-friendly dotted display form. */
17
+ export function displayKey(path) {
18
+ return path.includes(FP_PATH_DELIM) ? path.split(FP_PATH_DELIM).join('.') : path;
19
+ }
20
+ /**
21
+ * LLM-supplied key → engine path. Exact keys pass through; a dotted key
22
+ * that doesn't exist verbatim but matches a known DELIM-joined path is
23
+ * translated back. `knownPaths` is the set of every path seen in the
24
+ * commit log's trace entries.
25
+ */
26
+ export function normalizeKey(key, knownPaths) {
27
+ if (knownPaths.has(key))
28
+ return key;
29
+ if (key.includes('.')) {
30
+ const delimForm = key.split('.').join(FP_PATH_DELIM);
31
+ if (knownPaths.has(delimForm))
32
+ return delimForm;
33
+ }
34
+ return key;
35
+ }
36
+ /** Replace every DELIM in an already-formatted text block with '.' for display. */
37
+ export function displayText(text) {
38
+ return text.split(FP_PATH_DELIM).join('.');
39
+ }
40
+ /**
41
+ * Serialize a value to compact JSON, total-function style: cycles, BigInt
42
+ * and other non-JSON values degrade to a tagged placeholder instead of
43
+ * throwing — a debugger tool must never crash on the evidence it serves.
44
+ */
45
+ export function safeStringify(value) {
46
+ if (value === undefined)
47
+ return 'undefined';
48
+ try {
49
+ const json = JSON.stringify(value);
50
+ return json === undefined ? String(value) : json;
51
+ }
52
+ catch {
53
+ return '[unserializable value]';
54
+ }
55
+ }
56
+ /** Serialize + cap at `maxChars`. Truncation is reported, never silent. */
57
+ export function boundedPreview(value, maxChars) {
58
+ const full = safeStringify(value);
59
+ if (full.length <= maxChars) {
60
+ return { text: full, totalChars: full.length, truncated: false };
61
+ }
62
+ return { text: `${full.slice(0, maxChars)}…`, totalChars: full.length, truncated: true };
63
+ }
64
+ /** Render a preview with its honesty suffix when truncated. */
65
+ export function renderPreview(preview, fetchHint) {
66
+ if (!preview.truncated)
67
+ return preview.text;
68
+ const hint = fetchHint ? ` — ${fetchHint}` : '';
69
+ return `${preview.text} (${preview.totalChars} chars total${hint})`;
70
+ }
71
+ /** Clamp an LLM-supplied numeric param into [min, hardCap], with a default. */
72
+ export function clampParam(requested, fallback, min, hardCap) {
73
+ const value = typeof requested === 'number' && Number.isFinite(requested) ? requested : fallback;
74
+ return Math.max(min, Math.min(Math.floor(value), hardCap));
75
+ }
76
+ //# sourceMappingURL=bounded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded.js","sourceRoot":"","sources":["../../../../src/lib/trace-toolpack/bounded.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * trace-toolpack — RFC-003 Part C: the introspection toolpack.
3
+ *
4
+ * footprintjs trace evidence exposed as TOOLS an LLM calls: a debugging
5
+ * model navigates a COMPLETED run's evidence by runtimeStageIds instead of
6
+ * reading dumps. Bounded, honest (⚠ markers), redaction-respecting.
7
+ */
8
+ export { callTraceTool, traceToolpack } from './traceToolpack.js';
9
+ export { TOOLPACK_HARD_CAPS, } from './types.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/trace-toolpack/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EACL,kBAAkB,GAGnB,MAAM,YAAY,CAAC"}