@tangle-network/agent-app 0.44.27 → 0.44.28

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.
@@ -1,4 +1,4 @@
1
- import { a as AppToolContext } from './types-BCxK0wyS.js';
1
+ import { A as AppToolContext } from './types-DbU-oO5h.js';
2
2
 
3
3
  /**
4
4
  * Header names carrying the server-set per-turn context + the capability token.
@@ -14,8 +14,8 @@ import '../contract-CEewO6DI.js';
14
14
  import '../types-DB82fktc.js';
15
15
  import '../plans/index.js';
16
16
  import '@tangle-network/sandbox';
17
- import '../auth-anc7mv2W.js';
18
- import '../types-BCxK0wyS.js';
17
+ import '../auth-DJs6lfAs.js';
18
+ import '../types-DbU-oO5h.js';
19
19
  import '../harness/index.js';
20
20
  import '../model-CdCDfBA9.js';
21
21
  import '../budget-BOucfcb_.js';
@@ -6,9 +6,9 @@ import { a as SceneStore, N as NewSceneDecision, b as SceneDocumentRecord } from
6
6
  export { c as SceneDecision, d as SceneExportFormat, e as SceneExportRecord, S as SceneStoreScope } from '../store-CqfDtnPQ.js';
7
7
  export { C as CHANNEL_PRESETS, a as ChannelPreset, b as ChannelPresetId, c as ChannelScaleResult, E as EXPORT_PRESETS, d as ExportCropRect, e as ExportFormat, f as ExportPreset, S as SIZE_PRESETS, g as SizePreset, h as bleedAwareExportBounds, i as bleedAwareExportRect, j as findPreset, m as matchPreset, r as requireChannelPreset, s as scaleForPreset, k as scalePageForChannelPreset } from '../export-presets-mgVulRaV.js';
8
8
  import { a as McpToolDefinition } from '../mcp-rpc-CzU5LWWT.js';
9
- import { S as ScopedMcpServerEntryOptions, A as AppToolMcpServer } from '../mcp-D3qVzbE1.js';
10
- import '../types-BCxK0wyS.js';
11
- import '../auth-anc7mv2W.js';
9
+ import { S as ScopedMcpServerEntryOptions, A as AppToolMcpServer } from '../mcp-Dt4V4ZLT.js';
10
+ import '../types-DbU-oO5h.js';
11
+ import '../auth-DJs6lfAs.js';
12
12
 
13
13
  /**
14
14
  * Pre-write validation for scene operations. Every rule runs against a
@@ -1,6 +1,113 @@
1
1
  import { CompletionRequirement, RuntimeEventLike } from '@tangle-network/agent-eval';
2
2
  export { CompletionRequirement, CompletionVerdict, CorrectnessChecker, ProducedState, RuntimeEventLike, SatisfiedBy, TaskGold, createLlmCorrectnessChecker, extractProducedState, verifyCompletion, weightedComposite } from '@tangle-network/agent-eval';
3
- import { A as AppToolProducedEvent } from '../types-BCxK0wyS.js';
3
+ import { c as AppToolProducedEvent } from '../types-DbU-oO5h.js';
4
+
5
+ /**
6
+ * Calibration — prove a gate can FAIL before believing that it PASSED, and
7
+ * prove a probe can SEE before believing the zero it reported.
8
+ *
9
+ * Every expensive failure this package has shipped was a check that verified
10
+ * its own input instead of the world, and reported green:
11
+ *
12
+ * - `quote_verification 16/16` passed a work product whose nine citations
13
+ * claimed a figure the cited document never mentions.
14
+ * - `audit_form passed=3 failed=0` passed a form fill whose values landed in
15
+ * "Combat zone" — the audit re-read the field paths the writer had just
16
+ * invented, so a wrong path could not be wrong.
17
+ * - `evidence_coverage 0/0` passed vacuously because the artifact it was
18
+ * counting targets from was null.
19
+ * - A benchmark reported 6/8 for the product while a bare
20
+ * "You are a helpful assistant." scored 8/8 on the same cases.
21
+ *
22
+ * A gate is only evidence if it REJECTS something. A metric is only evidence
23
+ * if a worse system scores worse on it. Neither property is implied by a
24
+ * green run, and neither is visible in the output — which is why both have to
25
+ * be asserted separately, in code, next to the gate.
26
+ *
27
+ * This module is deliberately domain-free: a "gate" is any predicate over any
28
+ * input. Products supply the known-good and known-bad cases, because only the
29
+ * product knows what bad looks like in its domain.
30
+ */
31
+ /** A case whose verdict is known in advance, used to calibrate a gate. */
32
+ interface CalibrationCase<TInput> {
33
+ /** What this case represents, e.g. `'quote that does not occur in the source'`. */
34
+ readonly label: string;
35
+ readonly input: TInput;
36
+ /** `'reject'` — the gate MUST refuse this. `'accept'` — it MUST allow it. */
37
+ readonly expect: 'accept' | 'reject';
38
+ }
39
+ interface CalibrationOutcome {
40
+ readonly label: string;
41
+ readonly expected: 'accept' | 'reject';
42
+ readonly actual: 'accept' | 'reject';
43
+ readonly ok: boolean;
44
+ /** Set when the gate threw; a throw counts as `'reject'`. */
45
+ readonly threw?: string;
46
+ }
47
+ interface CalibrationReport {
48
+ /** True only when every case matched AND both controls were present. */
49
+ readonly discriminates: boolean;
50
+ readonly outcomes: readonly CalibrationOutcome[];
51
+ readonly failures: readonly CalibrationOutcome[];
52
+ /** Why the gate is not trustworthy. Absent when `discriminates` is true. */
53
+ readonly reason?: string;
54
+ }
55
+ /**
56
+ * A gate under calibration. Returning `false` OR throwing both count as a
57
+ * rejection — a fail-loud gate (`ToolInputError`) and a boolean gate calibrate
58
+ * through the same path.
59
+ */
60
+ type GateFn<TInput> = (input: TInput) => boolean | Promise<boolean>;
61
+ /**
62
+ * Run a gate against cases whose verdicts are known, and report whether it
63
+ * actually discriminates.
64
+ *
65
+ * Requires BOTH controls:
66
+ * - at least one `'reject'` case — without it a gate that returns `true`
67
+ * unconditionally is indistinguishable from a working one. This is the
68
+ * control that all four failures above were missing.
69
+ * - at least one `'accept'` case — without it a gate that refuses everything
70
+ * scores perfectly, and an unsatisfiable gate does not stop bad work, it
71
+ * selects for invented work (measured: 38 fabricated citations written to
72
+ * clear a coverage gate no honest answer could satisfy).
73
+ */
74
+ declare function calibrateGate<TInput>(gate: GateFn<TInput>, cases: readonly CalibrationCase<TInput>[]): Promise<CalibrationReport>;
75
+ /**
76
+ * `calibrateGate`, but throws instead of reporting. Use in a test or at wiring
77
+ * time so an uncalibrated gate cannot ship silently.
78
+ */
79
+ declare function assertGateDiscriminates<TInput>(name: string, gate: GateFn<TInput>, cases: readonly CalibrationCase<TInput>[]): Promise<CalibrationReport>;
80
+ interface ProbeReport<TValue> {
81
+ /** True when the positive control registered something, so a zero is real. */
82
+ readonly canSee: boolean;
83
+ readonly measured: number;
84
+ readonly control: number;
85
+ readonly value: TValue;
86
+ readonly reason?: string;
87
+ }
88
+ /**
89
+ * Measure something, but only after proving the instrument can register a
90
+ * non-zero — because an absence is a claim about the measurement first.
91
+ *
92
+ * Six blind probes were mistaken for real zeros in a single day: a SQL `LIKE`
93
+ * over a column the product encrypts (which equally returned 0 for `"text"`
94
+ * across every row — the tell), a `grep` run against worktrees on stale
95
+ * branches, a status-code comparison that never read the response bodies, a
96
+ * live event count taken from a run that was never dispatched, `rg --hidden`
97
+ * silently exiting 2 because `rg` was aliased to `grep`, and an intercepted
98
+ * `git show` returning an empty diff. Each nearly caused a wrong fix.
99
+ *
100
+ * `control` must count something that MUST exist. If it counts zero, the
101
+ * measurement is unusable regardless of what `measure` returned.
102
+ */
103
+ declare function measureWithControl<TValue>(opts: {
104
+ readonly measure: () => TValue | Promise<TValue>;
105
+ /** Must return a value whose count is non-zero, or the probe is blind. */
106
+ readonly control: () => TValue | Promise<TValue>;
107
+ readonly count: (value: TValue) => number;
108
+ /** Describes what the control counts, for the failure message. */
109
+ readonly controlLabel: string;
110
+ }): Promise<ProbeReport<TValue>>;
4
111
 
5
112
  /**
6
113
  * Eval — the app-shell BRIDGE to `@tangle-network/agent-eval`, not a reimpl.
@@ -47,4 +154,4 @@ declare function createTokenRecallChecker(opts?: {
47
154
  reason: string;
48
155
  }>;
49
156
 
50
- export { createTokenRecallChecker, producedFromToolEvents };
157
+ export { type CalibrationCase, type CalibrationOutcome, type CalibrationReport, type GateFn, type ProbeReport, assertGateDiscriminates, calibrateGate, createTokenRecallChecker, measureWithControl, producedFromToolEvents };
@@ -1,5 +1,46 @@
1
1
  // src/eval/index.ts
2
2
  import { verifyCompletion, extractProducedState, weightedComposite, createLlmCorrectnessChecker } from "@tangle-network/agent-eval";
3
+
4
+ // src/eval/calibration.ts
5
+ async function calibrateGate(gate, cases) {
6
+ const outcomes = [];
7
+ for (const c of cases) {
8
+ let actual;
9
+ let threw;
10
+ try {
11
+ actual = await gate(c.input) ? "accept" : "reject";
12
+ } catch (err) {
13
+ actual = "reject";
14
+ threw = err instanceof Error ? err.message : String(err);
15
+ }
16
+ outcomes.push({ label: c.label, expected: c.expect, actual, ok: actual === c.expect, ...threw ? { threw } : {} });
17
+ }
18
+ const failures = outcomes.filter((o) => !o.ok);
19
+ const hasNegative = cases.some((c) => c.expect === "reject");
20
+ const hasPositive = cases.some((c) => c.expect === "accept");
21
+ const reason = !hasNegative ? "no negative control: every case expects acceptance, so a gate that never refuses would score perfectly" : !hasPositive ? "no positive control: every case expects rejection, so a gate that refuses everything would score perfectly" : failures.length > 0 ? `${failures.length}/${outcomes.length} cases disagreed: ${failures.map((f) => `${f.label} expected ${f.expected}, got ${f.actual}`).join("; ")}` : void 0;
22
+ return { discriminates: reason === void 0, outcomes, failures, ...reason ? { reason } : {} };
23
+ }
24
+ async function assertGateDiscriminates(name, gate, cases) {
25
+ const report = await calibrateGate(gate, cases);
26
+ if (!report.discriminates) throw new Error(`gate "${name}" is not evidence \u2014 ${report.reason}`);
27
+ return report;
28
+ }
29
+ async function measureWithControl(opts) {
30
+ const value = await opts.measure();
31
+ const controlValue = await opts.control();
32
+ const measured = opts.count(value);
33
+ const control = opts.count(controlValue);
34
+ return control > 0 ? { canSee: true, measured, control, value } : {
35
+ canSee: false,
36
+ measured,
37
+ control,
38
+ value,
39
+ reason: `probe is blind: the positive control (${opts.controlLabel}) counted 0, so the measured ${measured} carries no information`
40
+ };
41
+ }
42
+
43
+ // src/eval/index.ts
3
44
  function producedFromToolEvents(events) {
4
45
  return events.map(
5
46
  (e) => e.type === "proposal_created" ? { type: "proposal_created", proposalId: e.proposalId, title: e.title, status: e.status, content: e.content } : { type: "artifact", artifactId: `vault:${e.path}`, name: e.path, uri: `vault://${e.path}`, mimeType: "text/markdown", content: e.content }
@@ -21,9 +62,12 @@ function createTokenRecallChecker(opts = {}) {
21
62
  };
22
63
  }
23
64
  export {
65
+ assertGateDiscriminates,
66
+ calibrateGate,
24
67
  createLlmCorrectnessChecker,
25
68
  createTokenRecallChecker,
26
69
  extractProducedState,
70
+ measureWithControl,
27
71
  producedFromToolEvents,
28
72
  verifyCompletion,
29
73
  weightedComposite
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/eval/index.ts"],"sourcesContent":["/**\n * Eval — the app-shell BRIDGE to `@tangle-network/agent-eval`, not a reimpl.\n *\n * The completion/scoring ENGINE lives in agent-eval (a peer dependency):\n * `verifyCompletion`, `extractProducedState`, `weightedComposite`,\n * `createLlmCorrectnessChecker`, and the `CompletionRequirement` / `TaskGold` /\n * `ProducedState` types — all re-exported here so a consumer has one import\n * root. This module adds only what agent-eval doesn't have and what is\n * app-shell-specific:\n *\n * 1. {@link producedFromToolEvents} — the bridge: turn the structured app-tool\n * side channel's `AppToolProducedEvent`s (from a tool runtime executor's\n * `onProduced`) into the `RuntimeEventLike`s agent-eval's\n * `extractProducedState` consumes. This is the one piece that knows about\n * the app-tool channel, so it belongs here, not in the engine.\n * 2. {@link createTokenRecallChecker} — a deterministic, no-LLM\n * `CorrectnessChecker` (agent-eval ships only the LLM one). For apps/tests\n * that gate completion without a judge call.\n *\n * Full campaigns (persona simulation, traces, scorecards, held-out gates) are\n * agent-eval's `runEvalCampaign` / `AgentDriver` / `BenchmarkRunner` — use them\n * directly; this module composes with them.\n */\nimport type { RuntimeEventLike, CompletionRequirement } from '@tangle-network/agent-eval'\nimport type { AppToolProducedEvent } from '../tools/types'\n\n// Re-export the engine so consumers import completion + scoring from one place.\nexport { verifyCompletion, extractProducedState, weightedComposite, createLlmCorrectnessChecker } from '@tangle-network/agent-eval'\nexport type {\n CompletionRequirement,\n TaskGold,\n ProducedState,\n SatisfiedBy,\n CompletionVerdict,\n CorrectnessChecker,\n RuntimeEventLike,\n} from '@tangle-network/agent-eval'\n\n/**\n * Bridge the app-tool side channel's produced events into the runtime-event\n * shape agent-eval's `extractProducedState` reads. Pipe it:\n * `verifyCompletion(taskGold, extractProducedState(producedFromToolEvents(events)), checker)`\n */\nexport function producedFromToolEvents(events: readonly AppToolProducedEvent[]): RuntimeEventLike[] {\n return events.map((e) =>\n e.type === 'proposal_created'\n ? { type: 'proposal_created', proposalId: e.proposalId, title: e.title, status: e.status, content: e.content }\n : { type: 'artifact', artifactId: `vault:${e.path}`, name: e.path, uri: `vault://${e.path}`, mimeType: 'text/markdown', content: e.content },\n )\n}\n\nconst STOPWORDS = new Set(['the', 'a', 'an', 'and', 'or', 'for', 'to', 'of', 'in', 'on', 'with', 'review', 'update', 'new', 'proposed'])\n\n/**\n * A deterministic `CorrectnessChecker` (agent-eval exports only\n * `createLlmCorrectnessChecker`). A produced item fulfils a requirement when\n * its content is substantive and recalls ≥ `minRecall` of the requirement\n * title's significant tokens. No network — the default gate for apps/tests\n * without an LLM judge. Pass to `verifyCompletion` as the checker.\n */\nexport function createTokenRecallChecker(opts: { minRecall?: number; minContentLength?: number } = {}): (\n requirement: CompletionRequirement,\n content: string,\n) => Promise<{ correct: boolean; reason: string }> {\n const minRecall = opts.minRecall ?? 0.5\n const minLen = opts.minContentLength ?? 120\n return async (requirement, content) => {\n const body = content.trim()\n if (body.length < minLen) return { correct: false, reason: `content too thin (${body.length} chars) to be the deliverable` }\n const tokens = requirement.title.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 2 && !STOPWORDS.has(t))\n if (tokens.length === 0) return { correct: true, reason: 'requirement title has no significant tokens — structural match accepted' }\n const lower = body.toLowerCase()\n const hits = tokens.filter((t) => lower.includes(t)).length\n const recall = hits / tokens.length\n return recall >= minRecall\n ? { correct: true, reason: `content recalls ${hits}/${tokens.length} requirement tokens` }\n : { correct: false, reason: `content recalls only ${hits}/${tokens.length} requirement tokens` }\n }\n}\n"],"mappings":";AA2BA,SAAS,kBAAkB,sBAAsB,mBAAmB,mCAAmC;AAgBhG,SAAS,uBAAuB,QAA6D;AAClG,SAAO,OAAO;AAAA,IAAI,CAAC,MACjB,EAAE,SAAS,qBACP,EAAE,MAAM,oBAAoB,YAAY,EAAE,YAAY,OAAO,EAAE,OAAO,QAAQ,EAAE,QAAQ,SAAS,EAAE,QAAQ,IAC3G,EAAE,MAAM,YAAY,YAAY,SAAS,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,KAAK,WAAW,EAAE,IAAI,IAAI,UAAU,iBAAiB,SAAS,EAAE,QAAQ;AAAA,EAC/I;AACF;AAEA,IAAM,YAAY,oBAAI,IAAI,CAAC,OAAO,KAAK,MAAM,OAAO,MAAM,OAAO,MAAM,MAAM,MAAM,MAAM,QAAQ,UAAU,UAAU,OAAO,UAAU,CAAC;AAShI,SAAS,yBAAyB,OAA0D,CAAC,GAGjD;AACjD,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,SAAS,KAAK,oBAAoB;AACxC,SAAO,OAAO,aAAa,YAAY;AACrC,UAAM,OAAO,QAAQ,KAAK;AAC1B,QAAI,KAAK,SAAS,OAAQ,QAAO,EAAE,SAAS,OAAO,QAAQ,qBAAqB,KAAK,MAAM,gCAAgC;AAC3H,UAAM,SAAS,YAAY,MAAM,YAAY,EAAE,MAAM,YAAY,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;AAClH,QAAI,OAAO,WAAW,EAAG,QAAO,EAAE,SAAS,MAAM,QAAQ,+EAA0E;AACnI,UAAM,QAAQ,KAAK,YAAY;AAC/B,UAAM,OAAO,OAAO,OAAO,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE;AACrD,UAAM,SAAS,OAAO,OAAO;AAC7B,WAAO,UAAU,YACb,EAAE,SAAS,MAAM,QAAQ,mBAAmB,IAAI,IAAI,OAAO,MAAM,sBAAsB,IACvF,EAAE,SAAS,OAAO,QAAQ,wBAAwB,IAAI,IAAI,OAAO,MAAM,sBAAsB;AAAA,EACnG;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/eval/index.ts","../../src/eval/calibration.ts"],"sourcesContent":["/**\n * Eval — the app-shell BRIDGE to `@tangle-network/agent-eval`, not a reimpl.\n *\n * The completion/scoring ENGINE lives in agent-eval (a peer dependency):\n * `verifyCompletion`, `extractProducedState`, `weightedComposite`,\n * `createLlmCorrectnessChecker`, and the `CompletionRequirement` / `TaskGold` /\n * `ProducedState` types — all re-exported here so a consumer has one import\n * root. This module adds only what agent-eval doesn't have and what is\n * app-shell-specific:\n *\n * 1. {@link producedFromToolEvents} — the bridge: turn the structured app-tool\n * side channel's `AppToolProducedEvent`s (from a tool runtime executor's\n * `onProduced`) into the `RuntimeEventLike`s agent-eval's\n * `extractProducedState` consumes. This is the one piece that knows about\n * the app-tool channel, so it belongs here, not in the engine.\n * 2. {@link createTokenRecallChecker} — a deterministic, no-LLM\n * `CorrectnessChecker` (agent-eval ships only the LLM one). For apps/tests\n * that gate completion without a judge call.\n *\n * Full campaigns (persona simulation, traces, scorecards, held-out gates) are\n * agent-eval's `runEvalCampaign` / `AgentDriver` / `BenchmarkRunner` — use them\n * directly; this module composes with them.\n */\nimport type { RuntimeEventLike, CompletionRequirement } from '@tangle-network/agent-eval'\nimport type { AppToolProducedEvent } from '../tools/types'\n\n// Re-export the engine so consumers import completion + scoring from one place.\nexport { verifyCompletion, extractProducedState, weightedComposite, createLlmCorrectnessChecker } from '@tangle-network/agent-eval'\n\n// Calibration: prove a gate can FAIL before believing it PASSED, and prove a\n// probe can SEE before believing the zero it reported. Domain-free, so it\n// calibrates a citation gate, a form audit, or a benchmark equally.\nexport { calibrateGate, assertGateDiscriminates, measureWithControl } from './calibration'\nexport type { CalibrationCase, CalibrationOutcome, CalibrationReport, GateFn, ProbeReport } from './calibration'\nexport type {\n CompletionRequirement,\n TaskGold,\n ProducedState,\n SatisfiedBy,\n CompletionVerdict,\n CorrectnessChecker,\n RuntimeEventLike,\n} from '@tangle-network/agent-eval'\n\n/**\n * Bridge the app-tool side channel's produced events into the runtime-event\n * shape agent-eval's `extractProducedState` reads. Pipe it:\n * `verifyCompletion(taskGold, extractProducedState(producedFromToolEvents(events)), checker)`\n */\nexport function producedFromToolEvents(events: readonly AppToolProducedEvent[]): RuntimeEventLike[] {\n return events.map((e) =>\n e.type === 'proposal_created'\n ? { type: 'proposal_created', proposalId: e.proposalId, title: e.title, status: e.status, content: e.content }\n : { type: 'artifact', artifactId: `vault:${e.path}`, name: e.path, uri: `vault://${e.path}`, mimeType: 'text/markdown', content: e.content },\n )\n}\n\nconst STOPWORDS = new Set(['the', 'a', 'an', 'and', 'or', 'for', 'to', 'of', 'in', 'on', 'with', 'review', 'update', 'new', 'proposed'])\n\n/**\n * A deterministic `CorrectnessChecker` (agent-eval exports only\n * `createLlmCorrectnessChecker`). A produced item fulfils a requirement when\n * its content is substantive and recalls ≥ `minRecall` of the requirement\n * title's significant tokens. No network — the default gate for apps/tests\n * without an LLM judge. Pass to `verifyCompletion` as the checker.\n */\nexport function createTokenRecallChecker(opts: { minRecall?: number; minContentLength?: number } = {}): (\n requirement: CompletionRequirement,\n content: string,\n) => Promise<{ correct: boolean; reason: string }> {\n const minRecall = opts.minRecall ?? 0.5\n const minLen = opts.minContentLength ?? 120\n return async (requirement, content) => {\n const body = content.trim()\n if (body.length < minLen) return { correct: false, reason: `content too thin (${body.length} chars) to be the deliverable` }\n const tokens = requirement.title.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 2 && !STOPWORDS.has(t))\n if (tokens.length === 0) return { correct: true, reason: 'requirement title has no significant tokens — structural match accepted' }\n const lower = body.toLowerCase()\n const hits = tokens.filter((t) => lower.includes(t)).length\n const recall = hits / tokens.length\n return recall >= minRecall\n ? { correct: true, reason: `content recalls ${hits}/${tokens.length} requirement tokens` }\n : { correct: false, reason: `content recalls only ${hits}/${tokens.length} requirement tokens` }\n }\n}\n","/**\n * Calibration — prove a gate can FAIL before believing that it PASSED, and\n * prove a probe can SEE before believing the zero it reported.\n *\n * Every expensive failure this package has shipped was a check that verified\n * its own input instead of the world, and reported green:\n *\n * - `quote_verification 16/16` passed a work product whose nine citations\n * claimed a figure the cited document never mentions.\n * - `audit_form passed=3 failed=0` passed a form fill whose values landed in\n * \"Combat zone\" — the audit re-read the field paths the writer had just\n * invented, so a wrong path could not be wrong.\n * - `evidence_coverage 0/0` passed vacuously because the artifact it was\n * counting targets from was null.\n * - A benchmark reported 6/8 for the product while a bare\n * \"You are a helpful assistant.\" scored 8/8 on the same cases.\n *\n * A gate is only evidence if it REJECTS something. A metric is only evidence\n * if a worse system scores worse on it. Neither property is implied by a\n * green run, and neither is visible in the output — which is why both have to\n * be asserted separately, in code, next to the gate.\n *\n * This module is deliberately domain-free: a \"gate\" is any predicate over any\n * input. Products supply the known-good and known-bad cases, because only the\n * product knows what bad looks like in its domain.\n */\n\n/** A case whose verdict is known in advance, used to calibrate a gate. */\nexport interface CalibrationCase<TInput> {\n /** What this case represents, e.g. `'quote that does not occur in the source'`. */\n readonly label: string\n readonly input: TInput\n /** `'reject'` — the gate MUST refuse this. `'accept'` — it MUST allow it. */\n readonly expect: 'accept' | 'reject'\n}\n\nexport interface CalibrationOutcome {\n readonly label: string\n readonly expected: 'accept' | 'reject'\n readonly actual: 'accept' | 'reject'\n readonly ok: boolean\n /** Set when the gate threw; a throw counts as `'reject'`. */\n readonly threw?: string\n}\n\nexport interface CalibrationReport {\n /** True only when every case matched AND both controls were present. */\n readonly discriminates: boolean\n readonly outcomes: readonly CalibrationOutcome[]\n readonly failures: readonly CalibrationOutcome[]\n /** Why the gate is not trustworthy. Absent when `discriminates` is true. */\n readonly reason?: string\n}\n\n/**\n * A gate under calibration. Returning `false` OR throwing both count as a\n * rejection — a fail-loud gate (`ToolInputError`) and a boolean gate calibrate\n * through the same path.\n */\nexport type GateFn<TInput> = (input: TInput) => boolean | Promise<boolean>\n\n/**\n * Run a gate against cases whose verdicts are known, and report whether it\n * actually discriminates.\n *\n * Requires BOTH controls:\n * - at least one `'reject'` case — without it a gate that returns `true`\n * unconditionally is indistinguishable from a working one. This is the\n * control that all four failures above were missing.\n * - at least one `'accept'` case — without it a gate that refuses everything\n * scores perfectly, and an unsatisfiable gate does not stop bad work, it\n * selects for invented work (measured: 38 fabricated citations written to\n * clear a coverage gate no honest answer could satisfy).\n */\nexport async function calibrateGate<TInput>(\n gate: GateFn<TInput>,\n cases: readonly CalibrationCase<TInput>[],\n): Promise<CalibrationReport> {\n const outcomes: CalibrationOutcome[] = []\n for (const c of cases) {\n let actual: 'accept' | 'reject'\n let threw: string | undefined\n try {\n actual = (await gate(c.input)) ? 'accept' : 'reject'\n } catch (err) {\n actual = 'reject'\n threw = err instanceof Error ? err.message : String(err)\n }\n outcomes.push({ label: c.label, expected: c.expect, actual, ok: actual === c.expect, ...(threw ? { threw } : {}) })\n }\n\n const failures = outcomes.filter((o) => !o.ok)\n const hasNegative = cases.some((c) => c.expect === 'reject')\n const hasPositive = cases.some((c) => c.expect === 'accept')\n\n const reason = !hasNegative\n ? 'no negative control: every case expects acceptance, so a gate that never refuses would score perfectly'\n : !hasPositive\n ? 'no positive control: every case expects rejection, so a gate that refuses everything would score perfectly'\n : failures.length > 0\n ? `${failures.length}/${outcomes.length} cases disagreed: ${failures.map((f) => `${f.label} expected ${f.expected}, got ${f.actual}`).join('; ')}`\n : undefined\n\n return { discriminates: reason === undefined, outcomes, failures, ...(reason ? { reason } : {}) }\n}\n\n/**\n * `calibrateGate`, but throws instead of reporting. Use in a test or at wiring\n * time so an uncalibrated gate cannot ship silently.\n */\nexport async function assertGateDiscriminates<TInput>(\n name: string,\n gate: GateFn<TInput>,\n cases: readonly CalibrationCase<TInput>[],\n): Promise<CalibrationReport> {\n const report = await calibrateGate(gate, cases)\n if (!report.discriminates) throw new Error(`gate \"${name}\" is not evidence — ${report.reason}`)\n return report\n}\n\nexport interface ProbeReport<TValue> {\n /** True when the positive control registered something, so a zero is real. */\n readonly canSee: boolean\n readonly measured: number\n readonly control: number\n readonly value: TValue\n readonly reason?: string\n}\n\n/**\n * Measure something, but only after proving the instrument can register a\n * non-zero — because an absence is a claim about the measurement first.\n *\n * Six blind probes were mistaken for real zeros in a single day: a SQL `LIKE`\n * over a column the product encrypts (which equally returned 0 for `\"text\"`\n * across every row — the tell), a `grep` run against worktrees on stale\n * branches, a status-code comparison that never read the response bodies, a\n * live event count taken from a run that was never dispatched, `rg --hidden`\n * silently exiting 2 because `rg` was aliased to `grep`, and an intercepted\n * `git show` returning an empty diff. Each nearly caused a wrong fix.\n *\n * `control` must count something that MUST exist. If it counts zero, the\n * measurement is unusable regardless of what `measure` returned.\n */\nexport async function measureWithControl<TValue>(opts: {\n readonly measure: () => TValue | Promise<TValue>\n /** Must return a value whose count is non-zero, or the probe is blind. */\n readonly control: () => TValue | Promise<TValue>\n readonly count: (value: TValue) => number\n /** Describes what the control counts, for the failure message. */\n readonly controlLabel: string\n}): Promise<ProbeReport<TValue>> {\n const value = await opts.measure()\n const controlValue = await opts.control()\n const measured = opts.count(value)\n const control = opts.count(controlValue)\n return control > 0\n ? { canSee: true, measured, control, value }\n : {\n canSee: false,\n measured,\n control,\n value,\n reason: `probe is blind: the positive control (${opts.controlLabel}) counted 0, so the measured ${measured} carries no information`,\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,5 @@
1
- import { a as AppToolContext, b as AppToolName, c as AppToolDefinition } from './types-BCxK0wyS.js';
2
- import { T as ToolHeaderNames } from './auth-anc7mv2W.js';
1
+ import { A as AppToolContext, a as AppToolName, b as AppToolDefinition } from './types-DbU-oO5h.js';
2
+ import { T as ToolHeaderNames } from './auth-DJs6lfAs.js';
3
3
 
4
4
  /** Default route path each app tool is served at. A product mounts its routes
5
5
  * at these paths (or supplies its own via {@link BuildMcpServerOptions.paths}). */
@@ -1,6 +1,6 @@
1
1
  import { KeyProvisioner, KeyCrypto, WorkspaceKeyManager, WorkspaceKeyStore } from '../billing/index.js';
2
2
  import { KnowledgeStateAccessor } from '../knowledge/index.js';
3
- import { d as AppToolHandlers } from '../types-BCxK0wyS.js';
3
+ import { d as AppToolHandlers } from '../types-DbU-oO5h.js';
4
4
  import { KvLike } from '../web/index.js';
5
5
  import '@tangle-network/agent-eval';
6
6
 
@@ -4,9 +4,9 @@ import * as _tangle_network_agent_runtime from '@tangle-network/agent-runtime';
4
4
  import { ToolLoopMessage } from '@tangle-network/agent-runtime';
5
5
  export { RunToolLoopOptions as AppToolLoopOptions, ToolLoopAssistantToolCall as LoopAssistantToolCall, ToolLoopMessage as LoopMessage, ToolLoopCall as LoopToolCall, StreamToolLoopOptions as StreamAppToolLoopOptions, StreamToolLoopYield as StreamLoopYield, ToolLoopEvent, ToolLoopResult, ToolLoopStopReason, runToolLoop as runAppToolLoop, streamToolLoop as streamAppToolLoop } from '@tangle-network/agent-runtime';
6
6
  import { CertifiedProfile } from '@tangle-network/agent-runtime/intelligence';
7
- import { A as AppToolMcpServer } from '../mcp-D3qVzbE1.js';
8
- import '../types-BCxK0wyS.js';
9
- import '../auth-anc7mv2W.js';
7
+ import { A as AppToolMcpServer } from '../mcp-Dt4V4ZLT.js';
8
+ import '../types-DbU-oO5h.js';
9
+ import '../auth-DJs6lfAs.js';
10
10
 
11
11
  /**
12
12
  * Events the app's OpenAI-compat stream adapter ({@link toLoopEvents}) yields.
@@ -1,8 +1,8 @@
1
1
  import { SandboxInstance, ProvisionEvent, StorageConfig, ScopedTokenScope, TurnDriveResult, Sandbox, MintScopedTokenOptions } from '@tangle-network/sandbox';
2
2
  export { StorageConfig } from '@tangle-network/sandbox';
3
3
  import { AgentProfileMcpServer, AgentProfileFileMount, AgentProfile } from '@tangle-network/agent-interface';
4
- import { T as ToolHeaderNames } from '../auth-anc7mv2W.js';
5
- import { b as AppToolName, a as AppToolContext } from '../types-BCxK0wyS.js';
4
+ import { T as ToolHeaderNames } from '../auth-DJs6lfAs.js';
5
+ import { a as AppToolName, A as AppToolContext } from '../types-DbU-oO5h.js';
6
6
  import { Harness } from '../harness/index.js';
7
7
  import { a as TangleExecutionEnvironment } from '../model-CdCDfBA9.js';
8
8
  import { b as ProfileFingerprint, C as ComposeProfileBudget } from '../budget-BOucfcb_.js';
@@ -1,10 +1,10 @@
1
1
  import { j as SequenceMediaKind, f as SequenceTimeline, k as TimelineInterval, b as SequenceStore } from '../store-B7LLlk9p.js';
2
2
  export { M as MIN_SEQUENCE_CLIP_FRAMES, N as NewSequenceClip, l as NewSequenceDecision, m as NewSequenceTrack, g as SequenceClip, a as SequenceClipMedia, n as SequenceClipPatch, o as SequenceDecision, d as SequenceExportFormat, h as SequenceExportRecord, p as SequenceExportStatus, q as SequenceFrameSnapshot, i as SequenceMeta, r as SequenceStatus, S as SequenceStoreScope, e as SequenceTrack, c as SequenceTrackKind, T as TimelineClipBounds, s as assertClipFitsSequence, t as chooseCaptionPlacement, u as clampClipDuration, v as clampClipStart, w as formatSeconds, x as formatTimecode, y as framesToSeconds, z as secondsToFrames, A as snapshotFrame, B as trackIntervals } from '../store-B7LLlk9p.js';
3
3
  export { A as AddCaptionOperation, C as CaptionTargetResolution, a as CreateTrackOperation, D as DeleteClipOperation, E as ExtendSequenceOperation, M as MoveClipOperation, P as PlaceClipOperation, Q as QueueExportOperation, S as SEQUENCE_OPERATION_TYPES, b as SequenceApplyResult, c as SequenceOperation, d as SequenceOperationContext, e as SequenceOperationType, f as SequencePlan, g as SetClipDisabledOperation, h as SetClipTextOperation, i as SplitClipOperation, T as TrimClipOperation, j as applySequenceOperation, k as applySequenceOperations, l as assertSequenceMediaUrl, m as captionTrackNameForLanguage, n as lastClipEndFrame, p as parseSequenceOperations, r as resolveCaptionPlacement, o as resolveCaptionTarget, q as resolvePlaceClipTrack, v as validateAddCaption, s as validateCreateTrack, t as validateDeleteClip, u as validateExtendSequence, w as validateMoveClip, x as validatePlaceClip, y as validateQueueExport, z as validateSequenceOperation, B as validateSequenceOperations, F as validateSetClipDisabled, G as validateSetClipText, H as validateSplitClip, I as validateTrimClip } from '../apply-6wlMOLf8.js';
4
- import { S as ScopedMcpServerEntryOptions, A as AppToolMcpServer } from '../mcp-D3qVzbE1.js';
4
+ import { S as ScopedMcpServerEntryOptions, A as AppToolMcpServer } from '../mcp-Dt4V4ZLT.js';
5
5
  export { M as SEQUENCES_MCP_PROTOCOL_VERSIONS } from '../mcp-rpc-CzU5LWWT.js';
6
- import '../types-BCxK0wyS.js';
7
- import '../auth-anc7mv2W.js';
6
+ import '../types-DbU-oO5h.js';
7
+ import '../auth-DJs6lfAs.js';
8
8
 
9
9
  /**
10
10
  * Pure interchange-format builders over `SequenceTimeline` — SRT, WebVTT,
@@ -1,8 +1,8 @@
1
- import { T as ToolHeaderNames } from '../auth-anc7mv2W.js';
2
- export { A as AuthenticateOptions, D as DEFAULT_HEADER_NAMES, a as ToolAuthResult, b as authenticateToolRequest, r as readToolArgs } from '../auth-anc7mv2W.js';
3
- import { e as AppToolTaxonomy, d as AppToolHandlers, c as AppToolDefinition, a as AppToolContext, A as AppToolProducedEvent, f as AppToolOutcome, b as AppToolName } from '../types-BCxK0wyS.js';
4
- export { g as APP_TOOL_NAMES, h as AddCitationArgs, i as AddCitationResult, B as BuildAppToolsOptions, O as OpenAIFunctionTool, R as RenderUiArgs, j as RenderUiResult, S as ScheduleFollowupArgs, k as ScheduleFollowupResult, l as SubmitProposalArgs, m as SubmitProposalResult, n as buildAppToolOpenAITools, o as customToolToOpenAI, p as defineAppTool, q as findCustomTool, r as isAppToolName } from '../types-BCxK0wyS.js';
5
- export { A as AppToolMcpServer, B as BuildHttpMcpServerOptions, a as BuildMcpServerOptions, D as DEFAULT_APP_TOOL_PATHS, S as ScopedMcpServerEntryOptions, b as buildAppToolMcpServer, c as buildHttpMcpServer, d as buildScopedMcpServerEntry } from '../mcp-D3qVzbE1.js';
1
+ import { T as ToolHeaderNames } from '../auth-DJs6lfAs.js';
2
+ export { A as AuthenticateOptions, D as DEFAULT_HEADER_NAMES, a as ToolAuthResult, b as authenticateToolRequest, r as readToolArgs } from '../auth-DJs6lfAs.js';
3
+ import { e as AppToolTaxonomy, d as AppToolHandlers, b as AppToolDefinition, A as AppToolContext, c as AppToolProducedEvent, f as AppToolOutcome, a as AppToolName } from '../types-DbU-oO5h.js';
4
+ export { g as APP_TOOL_NAMES, h as AddCitationArgs, i as AddCitationResult, B as BuildAppToolsOptions, O as OpenAIFunctionTool, R as RenderUiArgs, j as RenderUiResult, S as ScheduleFollowupArgs, k as ScheduleFollowupResult, l as SubmitProposalArgs, m as SubmitProposalResult, n as buildAppToolOpenAITools, o as customToolToOpenAI, p as defineAppTool, q as findCustomTool, r as isAppToolName } from '../types-DbU-oO5h.js';
5
+ export { A as AppToolMcpServer, B as BuildHttpMcpServerOptions, a as BuildMcpServerOptions, D as DEFAULT_APP_TOOL_PATHS, S as ScopedMcpServerEntryOptions, b as buildAppToolMcpServer, c as buildHttpMcpServer, d as buildScopedMcpServerEntry } from '../mcp-Dt4V4ZLT.js';
6
6
  export { C as CreateMcpToolHandlerOptions, M as MCP_PROTOCOL_VERSIONS, b as McpProtocolVersion, c as McpServerInfo, a as McpToolDefinition, d as createMcpToolHandler } from '../mcp-rpc-CzU5LWWT.js';
7
7
 
8
8
  /** A correctable bad-input error a tool handler throws; the HTTP layer maps it
@@ -219,4 +219,4 @@ type AppToolOutcome = {
219
219
  status?: number;
220
220
  };
221
221
 
222
- export { type AppToolProducedEvent as A, type BuildAppToolsOptions as B, type OpenAIFunctionTool as O, type RenderUiArgs as R, type ScheduleFollowupArgs as S, type AppToolContext as a, type AppToolName as b, type AppToolDefinition as c, type AppToolHandlers as d, type AppToolTaxonomy as e, type AppToolOutcome as f, APP_TOOL_NAMES as g, type AddCitationArgs as h, type AddCitationResult as i, type RenderUiResult as j, type ScheduleFollowupResult as k, type SubmitProposalArgs as l, type SubmitProposalResult as m, buildAppToolOpenAITools as n, customToolToOpenAI as o, defineAppTool as p, findCustomTool as q, isAppToolName as r };
222
+ export { type AppToolContext as A, type BuildAppToolsOptions as B, type OpenAIFunctionTool as O, type RenderUiArgs as R, type ScheduleFollowupArgs as S, type AppToolName as a, type AppToolDefinition as b, type AppToolProducedEvent as c, type AppToolHandlers as d, type AppToolTaxonomy as e, type AppToolOutcome as f, APP_TOOL_NAMES as g, type AddCitationArgs as h, type AddCitationResult as i, type RenderUiResult as j, type ScheduleFollowupResult as k, type SubmitProposalArgs as l, type SubmitProposalResult as m, buildAppToolOpenAITools as n, customToolToOpenAI as o, defineAppTool as p, findCustomTool as q, isAppToolName as r };
@@ -1,6 +1,6 @@
1
1
  import { a as WorkProductProvenance, d as WorkProductStorePort, e as WorkProductAuditEvent, b as WorkProductRecord, f as WorkProductArtifact, Q as QualityCheck, E as EvidenceEntry, g as ExceptionEntry, h as WorkProductStatus, c as WorkProductPersistedPart } from '../types-DB82fktc.js';
2
2
  export { A as AgentCheckInput, i as EvidenceLocator, j as EvidenceSpan, k as ExceptionSeverity, P as ProfileBacktestSummary, l as QuoteBasis, m as WorkProductParseResult, n as WorkProductPatch, W as WorkProductRef, o as WorkProductUpdateGuard, p as WorkProductVersionEntry, q as isWorkProductStatus, r as parseAgentCheckInput, s as parseArtifactInput, t as parseEvidenceInput, u as parseExceptionInput, v as persistedPartToWorkProduct, w as unresolvedBlockingExceptions, x as workProductToPersistedPart } from '../types-DB82fktc.js';
3
- import { a as AppToolContext, c as AppToolDefinition } from '../types-BCxK0wyS.js';
3
+ import { A as AppToolContext, b as AppToolDefinition } from '../types-DbU-oO5h.js';
4
4
  import { JudgeVerdict } from '@tangle-network/agent-eval';
5
5
  import { T as TrustItem } from '../trust-gate-Dcm5xSva.js';
6
6
  export { R as ReviewQueueInputs, a as ReviewQueueItem, b as ReviewQueuePendingAsk, c as ReviewQueueState, d as ReviewQueueThread, p as parseReviewQueueItem, e as projectReviewQueue } from '../queue-vRI0Qx3X.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-app",
3
- "version": "0.44.27",
3
+ "version": "0.44.28",
4
4
  "packageManager": "pnpm@10.33.4",
5
5
  "description": "Application-shell framework for Tangle agent products: a bounded tool loop, the structured agent→app tool side channel, integration-hub client, per-workspace billing, and crypto — composed over the Tangle agent substrate through typed seams.",
6
6
  "keywords": [