instar 1.3.784 → 1.3.786

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 (41) hide show
  1. package/dashboard/index.html +15 -2
  2. package/dist/core/routingSpendView.d.ts +36 -0
  3. package/dist/core/routingSpendView.d.ts.map +1 -1
  4. package/dist/core/routingSpendView.js +70 -0
  5. package/dist/core/routingSpendView.js.map +1 -1
  6. package/dist/core/types.d.ts +12 -0
  7. package/dist/core/types.d.ts.map +1 -1
  8. package/dist/core/types.js.map +1 -1
  9. package/dist/monitoring/FeatureMetricsLedger.d.ts +6 -0
  10. package/dist/monitoring/FeatureMetricsLedger.d.ts.map +1 -1
  11. package/dist/monitoring/FeatureMetricsLedger.js +7 -2
  12. package/dist/monitoring/FeatureMetricsLedger.js.map +1 -1
  13. package/dist/monitoring/ProviderCostReportStore.d.ts +138 -0
  14. package/dist/monitoring/ProviderCostReportStore.d.ts.map +1 -0
  15. package/dist/monitoring/ProviderCostReportStore.js +0 -0
  16. package/dist/monitoring/ProviderCostReportStore.js.map +1 -0
  17. package/dist/monitoring/ProviderReconciliationSweep.d.ts +72 -0
  18. package/dist/monitoring/ProviderReconciliationSweep.d.ts.map +1 -0
  19. package/dist/monitoring/ProviderReconciliationSweep.js +97 -0
  20. package/dist/monitoring/ProviderReconciliationSweep.js.map +1 -0
  21. package/dist/server/AgentServer.d.ts +3 -0
  22. package/dist/server/AgentServer.d.ts.map +1 -1
  23. package/dist/server/AgentServer.js +78 -0
  24. package/dist/server/AgentServer.js.map +1 -1
  25. package/dist/server/routes.d.ts +2 -0
  26. package/dist/server/routes.d.ts.map +1 -1
  27. package/dist/server/routes.js +42 -0
  28. package/dist/server/routes.js.map +1 -1
  29. package/dist/testing/selfActionRegistry.d.ts.map +1 -1
  30. package/dist/testing/selfActionRegistry.js +38 -0
  31. package/dist/testing/selfActionRegistry.js.map +1 -1
  32. package/package.json +1 -1
  33. package/scripts/lint-scrape-fixture-realness.js +17 -0
  34. package/scripts/routing-price-refresh.mjs +146 -4
  35. package/src/data/builtin-manifest.json +47 -47
  36. package/src/data/state-coherence-registry.json +1241 -1223
  37. package/src/scaffold/templates/jobs/instar/routing-price-web-verify.md +32 -0
  38. package/upgrades/1.3.785.md +56 -0
  39. package/upgrades/1.3.786.md +42 -0
  40. package/upgrades/side-effects/routing-spend-increment-1c.md +44 -0
  41. package/upgrades/side-effects/routing-spend-pr4-operator-additions.md +50 -0
@@ -96,6 +96,9 @@ import { TelegramSpendTopicChannel, spendAlertDeliveryId } from '../core/Telegra
96
96
  import { SpendAlertEmitters } from '../core/SpendAlertEmitters.js';
97
97
  import { MachineIdentityManager } from '../core/MachineIdentity.js';
98
98
  import { PendingRelayStore as SpendAlertRelayStore } from '../messaging/pending-relay-store.js';
99
+ import { ProviderCostReportStore } from '../monitoring/ProviderCostReportStore.js';
100
+ import { ProviderReconciliationSweep } from '../monitoring/ProviderReconciliationSweep.js';
101
+ import { meteredKeysFromChains } from '../core/routingSpendView.js';
99
102
  import { DEFAULT_FRESHNESS_SLA_DAYS } from '../core/routingPriceAuthority.js';
100
103
  import { METERED_ROUTING_DOORS } from '../data/llmBenchCoverage.js';
101
104
  import { DEFAULT_METERED_CAPS } from '../core/routingSpendView.js';
@@ -198,6 +201,9 @@ export class AgentServer {
198
201
  spendAlertEmitters = null;
199
202
  /** Lazily-opened durable relay handle for money-critical alert delivery. */
200
203
  spendAlertRelayStore = null;
204
+ /** Layer 1c provider-report store + reconciliation sweep (reporting-only; FD-21). */
205
+ providerCostReportStore = null;
206
+ reconSweepTimer = null;
201
207
  featureMetricsPruneTimer = null;
202
208
  a2aDeliveryTracker = null;
203
209
  tokenLedgerPoller = null;
@@ -664,6 +670,72 @@ export class AgentServer {
664
670
  console.warn('[instar] pin-attempt store init failed (non-fatal — in-memory lockout only):', err);
665
671
  this.pinAttemptStore = null;
666
672
  }
673
+ // ── Layer 1c provider-report store + reconciliation sweep (FD-21 —
674
+ // REPORTING-only; rides the same dev-gated view flag as the summary;
675
+ // structurally excluded from the money gate, which imports nothing here).
676
+ if (routingSpendOn) {
677
+ try {
678
+ const rsCfg = options.config.routingSpend;
679
+ this.providerCostReportStore = new ProviderCostReportStore({
680
+ dbPath: path.join(options.config.stateDir, 'server-data', 'provider-cost-reports.db'),
681
+ retentionDays: rsCfg?.providerReportRetentionDays ?? 400,
682
+ });
683
+ this.providerCostReportStore.prune(); // boot prune (batched — scal-F4)
684
+ const doorToKey = new Map(meteredKeysFromChains().map((m) => [m.door, m.keyRef]));
685
+ const sweep = new ProviderReconciliationSweep({
686
+ store: this.providerCostReportStore,
687
+ // Internal-derived per (keyRef, door): the metered doors' daily token
688
+ // buckets × the as-of reviewed price (the same reporting math the
689
+ // summary uses) — reporting-side reads only, never the money mutex.
690
+ internalDerivedUsd: (sinceMs, untilMs) => {
691
+ const ledger = this.featureMetricsLedger;
692
+ const prices = this.routingPriceAuthority;
693
+ if (!ledger || !prices)
694
+ return [];
695
+ prices.reloadIfChanged();
696
+ const sinceDays = Math.max(1, Math.ceil((untilMs - sinceMs) / 86_400_000) + 1);
697
+ const buckets = ledger.spendTokenRollupDaily({ sinceDays });
698
+ const agg = new Map();
699
+ for (const b of buckets) {
700
+ const keyRef = doorToKey.get(b.door);
701
+ if (!keyRef)
702
+ continue; // metered doors only
703
+ if (b.bucketStartMs < sinceMs - 86_400_000 || b.bucketStartMs > untilMs)
704
+ continue;
705
+ const res = prices.resolve(b.door, b.modelId, b.bucketStartMs);
706
+ const cost = prices.reportingCost(res, b.tokensIn, b.tokensOut, b.tokensCached);
707
+ const e = agg.get(`${keyRef} ${b.door}`) ?? { keyRef, door: b.door, internalUsd: 0 };
708
+ e.internalUsd += cost.grossUsd;
709
+ agg.set(`${keyRef} ${b.door}`, e);
710
+ }
711
+ return [...agg.values()];
712
+ },
713
+ committedUsd: (keyRef) => {
714
+ try {
715
+ return this.meteredSpendLedger?.committed(keyRef).committedLifetimeUsd ?? null;
716
+ }
717
+ catch {
718
+ // @silent-fallback-ok: committed is holder-known enrichment; a
719
+ // read failure records the comparison provider-vs-internal only.
720
+ return null;
721
+ }
722
+ },
723
+ // The Increment-C emit surface (late-bound; dispatcher dryRun-soaked).
724
+ onDrift: (keyRef, door, driftPct) => this.spendAlertEmitters?.onReconciliationDrift(keyRef, door, driftPct),
725
+ driftAlertPct: rsCfg?.reconciliation?.driftAlertPct ?? 10,
726
+ });
727
+ const sweepMs = Math.max(1, rsCfg?.reconciliation?.sweepIntervalHours ?? 6) * 60 * 60 * 1000;
728
+ this.reconSweepTimer = setInterval(() => void sweep.run(), sweepMs);
729
+ this.reconSweepTimer.unref?.();
730
+ }
731
+ catch (err) {
732
+ // @silent-fallback-ok: loud warn — a broken provider-report layer
733
+ // degrades every row to internal-derived (labeled); it never touches
734
+ // money admission or the router path.
735
+ console.warn('[instar] provider-cost report layer init failed (non-fatal — internal-derived reporting remains):', err);
736
+ this.providerCostReportStore = null;
737
+ }
738
+ }
667
739
  // ── Increment B MONEY layer (routing-control-room-spend §Layer 3 / Surface 2).
668
740
  // EXPLICIT enable only (`routingSpend.money.enabled === true`) — a documented
669
741
  // DARK_GATE_EXCLUSIONS action-bearing case (FD-16): NEVER resolveDevAgentGate.
@@ -2181,6 +2253,7 @@ export class AgentServer {
2181
2253
  meteredSpendGate: this.meteredSpendGate,
2182
2254
  spendPlanStore: this.spendPlanStore,
2183
2255
  pinAttemptStore: this.pinAttemptStore,
2256
+ providerCostReportStore: this.providerCostReportStore,
2184
2257
  resourceLedger: this.resourceLedger,
2185
2258
  processFootprintMonitor: this.processFootprintMonitor,
2186
2259
  approvalLedger: this.approvalLedger,
@@ -3976,6 +4049,11 @@ export class AgentServer {
3976
4049
  await this.spendAlertDispatcher?.flushDigest();
3977
4050
  }
3978
4051
  catch { /* @silent-fallback-ok: a failed final digest flush loses only a coalesced NOTICE at shutdown */ }
4052
+ try {
4053
+ if (this.reconSweepTimer)
4054
+ clearInterval(this.reconSweepTimer);
4055
+ }
4056
+ catch { /* @silent-fallback-ok: timer teardown is best-effort cleanup at shutdown */ }
3979
4057
  this.featureMetricsPruneTimer = null;
3980
4058
  }
3981
4059
  if (this.tokenLedger) {