{"_id":"@agentlair/tbrm","_rev":"2-0e03c484d2d82450e301024b283315ec","name":"@agentlair/tbrm","dist-tags":{"latest":"0.1.0"},"versions":{"0.0.1":{"name":"@agentlair/tbrm","version":"0.0.1","keywords":["agentlair","agent-trust","tbrm","bptr","brier","calibration","reputation","behavioral-attestation"],"author":{"url":"piiiico","name":"AgentLair"},"license":"Apache-2.0","_id":"@agentlair/tbrm@0.0.1","maintainers":[{"name":"piiiico","email":"pico@amdal.dev"}],"homepage":"https://agentlair.dev/specs/tbrm","bugs":{"url":"https://github.com/piiiico/agentlair-primitives/issues"},"dist":{"shasum":"93627f13f41cf55fd47b02c0f6e15794275f82af","tarball":"https://registry.npmjs.org/@agentlair/tbrm/-/tbrm-0.0.1.tgz","fileCount":6,"integrity":"sha512-VysO6LyVavSIRHHHpa4xnT1sftHQQuPouP3h1n5Ej0aGBqWSqGhcApFHa0oQXsO7qVb+iPtz0vlENug6xf6uRg==","signatures":[{"sig":"MEUCICs0o9oPIvAvumQr25W12R+llBTSr0SoDbygGLbxYEv7AiEAtO/bettKUqILScNu70PBYCSQbZXVHuCwI29lBFUgkwI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":4648},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc","check":"tsc --noEmit","prepublishOnly":"tsc"},"_npmUser":{"name":"piiiico","email":"pico@amdal.dev"},"repository":{"url":"git+https://github.com/piiiico/agentlair-primitives.git","type":"git"},"_npmVersion":"10.9.7","description":"AgentLair TBRM (Tracked Brier Reputation Metric) primitive — reserved namespace stub. Predictions as bonded claims. Brier score compounds over resolved calls. See https://agentlair.dev","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/tbrm_0.0.1_1777772023894_0.2104505193184194","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@agentlair/tbrm","version":"0.1.0","description":"Predictions as bonded claims. Brier compounds over resolved calls. Tracked Brier Reputation Metric primitive — verifier SDK for the AgentLair TBRM layer.","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"scripts":{"build":"tsc","check":"tsc --noEmit","test":"bun test","prepublishOnly":"tsc"},"keywords":["agentlair","agent-trust","tbrm","bptr","brier","calibration","reputation","behavioral-attestation"],"author":{"name":"AgentLair","url":"piiiico"},"license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/piiiico/agentlair-primitives.git"},"homepage":"https://agentlair.dev/specs/tbrm","bugs":{"url":"https://github.com/piiiico/agentlair-primitives/issues"},"engines":{"node":">=18.0.0"},"devDependencies":{"typescript":"^5.9.3"},"_id":"@agentlair/tbrm@0.1.0","gitHead":"ae4d1be89419592d10eed7279aee801655dd16fa","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-rZPWloa3LghurVhcBNdNdM+ptuopsFHWfpJddDWlAlrwLOodDV+KSb6PSYPQtLP0X47hj9knYi6VFftsJJHsQA==","shasum":"53a8b5502e4ca5d042b7617278913af395db738c","tarball":"https://registry.npmjs.org/@agentlair/tbrm/-/tbrm-0.1.0.tgz","fileCount":6,"unpackedSize":27889,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDmGlueAW/vdJTn6QNtDgSPg47RR6VHhhmBCCtVF61a0AIgF8IrnpJ6rk7OB41y5wyZKwgwpc5/71UN8djbzDNB59c="}]},"_npmUser":{"name":"piiiico","email":"pico@amdal.dev"},"directories":{},"maintainers":[{"name":"piiiico","email":"pico@amdal.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tbrm_0.1.0_1777966619066_0.6724918262233055"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-03T01:33:43.793Z","modified":"2026-05-05T07:36:59.331Z","0.0.1":"2026-05-03T01:33:44.067Z","0.1.0":"2026-05-05T07:36:59.195Z"},"bugs":{"url":"https://github.com/piiiico/agentlair-primitives/issues"},"author":{"name":"AgentLair","url":"piiiico"},"license":"Apache-2.0","homepage":"https://agentlair.dev/specs/tbrm","keywords":["agentlair","agent-trust","tbrm","bptr","brier","calibration","reputation","behavioral-attestation"],"repository":{"type":"git","url":"git+https://github.com/piiiico/agentlair-primitives.git"},"description":"Predictions as bonded claims. Brier compounds over resolved calls. Tracked Brier Reputation Metric primitive — verifier SDK for the AgentLair TBRM layer.","maintainers":[{"name":"piiiico","email":"pico@amdal.dev"}],"readme":"# @agentlair/tbrm\n\nPredictions as bonded claims. Brier compounds over resolved calls.\n\n## What is TBRM?\n\nTracked Brier Reputation Metric.\n\nEach prediction carries a confidence in [0, 1], a deadline, and a verification method. When the deadline passes, the prediction resolves `correct`, `wrong`, or `unmeasurable`. The Brier delta updates the agent's tracked reputation metric.\n\nThere is no capital lock. The stake is the public, monotonically growing cost of bad calibration. A confident-and-wrong call costs you 81× what the same confidence would have earned if you'd been right (`correct@0.9 → 0.01`, `wrong@0.9 → 0.81`). Brier punishes overconfidence harder than it rewards it — the asymmetry is the whole point.\n\nThis package ships the pure-functional substrate: types for predictions and resolutions, Brier scoring, weighted aggregates, per-vehicle breakdowns, and a selection-bias detector. It is what the AgentLair worker uses internally; v0.1.0 publishes it so any agent-trust integrator can compute the same numbers from the same primitives.\n\n## Install\n\n```bash\nnpm install @agentlair/tbrm\n# or\nbun add @agentlair/tbrm\n```\n\nZero runtime dependencies. Pure functions over plain types — works in Node 18+, Bun, Deno, browsers, and edge runtimes.\n\n## Worked example\n\n10 predictions filed, 5 resolved by deadline.\n\n```typescript\nimport {\n  brierScore,\n  weightedBrierScore,\n  byVehicle,\n  selectionBias,\n  type Prediction,\n  type ResolvedPrediction,\n} from '@agentlair/tbrm';\n\n// Five still-open predictions, awaiting their deadlines.\nconst open: Prediction[] = [\n  { id: 'p06', vehicle: 'cold-email-batch',     claim: 'reply within 7d',\n    confidence: 0.40, deadline: '2026-06-01T00:00:00Z', vm: 'auto',\n    createdAt: '2026-05-25T00:00:00Z' },\n  { id: 'p07', vehicle: 'npm-package-publish',  claim: '≥10 weekly downloads in 30d',\n    confidence: 0.40, deadline: '2026-06-04T00:00:00Z', vm: 'web',\n    createdAt: '2026-05-05T00:00:00Z' },\n  { id: 'p08', vehicle: 'cold-email-batch',     claim: 'paying customer in 30d',\n    confidence: 0.20, deadline: '2026-06-15T00:00:00Z', vm: 'manual',\n    createdAt: '2026-05-15T00:00:00Z' },\n  { id: 'p09', vehicle: 'content-publish',      claim: '≥100 unique visitors in 14d',\n    confidence: 0.35, deadline: '2026-06-12T00:00:00Z', vm: 'web',\n    createdAt: '2026-05-29T00:00:00Z' },\n  { id: 'p10', vehicle: 'content-publish',      claim: 'cited by an AI engine within 60d',\n    confidence: 0.30, deadline: '2026-07-30T00:00:00Z', vm: 'manual',\n    createdAt: '2026-05-30T00:00:00Z' },\n];\n\n// Five resolved predictions across three vehicles.\nconst resolved: ResolvedPrediction[] = [\n  { id: 'p01', vehicle: 'cold-email-batch',    claim: 'reply within 7d',\n    confidence: 0.40, deadline: '2026-04-30T00:00:00Z', vm: 'auto',\n    createdAt: '2026-04-23T00:00:00Z',\n    resolution: 'correct', resolvedAt: '2026-04-29T12:00:00Z' },          // brier 0.36\n\n  { id: 'p02', vehicle: 'cold-email-batch',    claim: 'meeting booked',\n    confidence: 0.30, deadline: '2026-04-30T00:00:00Z', vm: 'auto',\n    createdAt: '2026-04-23T00:00:00Z',\n    resolution: 'wrong', resolvedAt: '2026-04-30T00:00:00Z' },            // brier 0.09\n\n  { id: 'p03', vehicle: 'npm-package-publish', claim: '≥4 weekly downloads in 14d',\n    confidence: 0.50, deadline: '2026-04-15T00:00:00Z', vm: 'web',\n    createdAt: '2026-04-01T00:00:00Z',\n    resolution: 'correct', resolvedAt: '2026-04-15T00:00:00Z' },          // brier 0.25\n\n  { id: 'p04', vehicle: 'content-publish',     claim: 'cited by an AI engine in 14d',\n    confidence: 0.20, deadline: '2026-04-20T00:00:00Z', vm: 'manual',\n    createdAt: '2026-04-06T00:00:00Z',\n    resolution: 'unmeasurable', resolvedAt: '2026-04-20T00:00:00Z' },     // brier null (excluded)\n\n  { id: 'p05', vehicle: 'content-publish',     claim: '≥50 unique visitors in 7d',\n    confidence: 0.45, deadline: '2026-04-15T00:00:00Z', vm: 'web',\n    createdAt: '2026-04-08T00:00:00Z',\n    resolution: 'wrong', resolvedAt: '2026-04-15T00:00:00Z' },            // brier 0.2025\n];\n\n// ── Aggregate Brier across all resolved ──\nconst agg = weightedBrierScore(resolved);\nconsole.log(agg);\n// {\n//   brier: 0.225625,   // mean over 4 measurable: (0.36 + 0.09 + 0.25 + 0.2025) / 4\n//   n: 5,              // includes the unmeasurable\n//   correct: 2,\n//   wrong: 2,\n//   unmeasurable: 1,\n// }\n\n// ── Per-vehicle breakdown — the actual learning signal ──\nconst buckets = byVehicle(resolved);\nconsole.log(buckets);\n// {\n//   'cold-email-batch':    { brier: 0.225,   n: 2 },  // (0.36 + 0.09) / 2\n//   'npm-package-publish': { brier: 0.25,    n: 1 },\n//   'content-publish':     { brier: 0.2025,  n: 2 },  // unmeasurable excluded; n includes it\n// }\n\n// ── Selection bias check ──\nconst bias = selectionBias(open, resolved);\nconsole.log(bias);\n// {\n//   resolveRate: 0.5,                 // 5 resolved / 10 total\n//   avgConfidenceResolved: 0.37,      // (0.4 + 0.3 + 0.5 + 0.2 + 0.45) / 5\n//   // warning omitted — resolveRate >= 0.20\n// }\n```\n\n## API\n\n### `brierScore(p: ResolvedPrediction): number | null`\n\nBrier for a single resolved prediction.\n\n| Resolution     | Formula           | Range  |\n|----------------|-------------------|--------|\n| `correct`      | `(1 - confidence)²` | `[0, 1]` |\n| `wrong`        | `confidence²`     | `[0, 1]` |\n| `unmeasurable` | returns `null` (excluded from the mean) |\n\n### `weightedBrierScore(preds: ResolvedPrediction[]): BrierAggregate`\n\nEqual-weight mean Brier across the input list. Returns:\n\n```typescript\ninterface BrierAggregate {\n  brier: number;          // mean over correct+wrong; 0 if none\n  n: number;              // total preds (includes unmeasurable)\n  correct: number;\n  wrong: number;\n  unmeasurable: number;\n}\n```\n\n`unmeasurable` predictions are excluded from `brier` but counted in `n` — that's intentional. It surfaces the selection-bias failure mode where confident claims pile up in `unmeasurable` and the visible Brier looks healthy because only safe bets ever resolve.\n\nv0.1.0 ships equal weights; recency decay is deferred to v0.2.\n\n### `byVehicle(preds: ResolvedPrediction[]): Record<string, { brier: number; n: number }>`\n\nAggregates Brier per `vehicle` field. Per-vehicle Brier is the actual learning signal — overall Brier blurs unrelated activities. Predictions with a missing or empty `vehicle` land in the `'unknown'` bucket.\n\n### `selectionBias(open: Prediction[], resolved: ResolvedPrediction[]): SelectionBiasReport`\n\nDetects the most common calibration anti-pattern: most confident claims either stay open past their deadline or end up `unmeasurable`. The visible Brier looks fine — but it only reflects the safe-bet subset that actually resolved.\n\n```typescript\ninterface SelectionBiasReport {\n  avgConfidenceResolved: number;  // mean confidence of resolved predictions\n  resolveRate: number;            // resolved / (open + resolved)\n  warning?: string;               // set when resolveRate < 0.20\n}\n```\n\nThe 0.20 threshold is the practical floor for usable signal — below that, the Brier mean is a noisy estimate of a biased subsample. The warning string is human-readable and safe to log directly.\n\n## Calibration anti-pattern: selection bias\n\nMost calibration loops fail not because the math is wrong, but because the resolution path is missing. Predictions get filed at confidence 0.7, 0.8, 0.9 — but never resolve, because there's no shell command, no API, no reachable URL that can verify them. They stay `open` forever, then auto-promote to `unmeasurable` past their deadline.\n\nMeanwhile, the predictions that DO resolve are the easy ones. URL-pingable, count-summable, deterministic. They tend to be filed at lower confidence (0.3–0.5) because they're known-uncertain. So the visible Brier looks fine — 0.10 weighted, well under chance — but it's a snapshot of a biased subsample. The actual track record is unknown.\n\n`selectionBias` makes that visible. Below 20% resolve rate, the warning fires; the Brier you can see is not the Brier you have.\n\nThe fix is upstream: file fewer predictions that lack a resolution path. `--verification-method auto` with an executable command, or `--verification-method web` with a URL the resolver can fetch. The `manual` path is honest, but in practice it stays `open` indefinitely.\n\n## Spec\n\n- TBRM spec: https://agentlair.dev/specs/tbrm\n- AgentLair: https://agentlair.dev\n- Source: https://github.com/piiiico/agentlair-primitives\n\n## License\n\nApache-2.0\n","readmeFilename":"README.md"}