instar 1.3.706 → 1.3.707

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 +1 @@
1
- {"version":3,"file":"componentCategories.d.ts","sourceRoot":"","sources":["../../src/core/componentCategories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,OAAO,CAAC;AAEpF,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,iBAAiB,CAEjE,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,iBAAiB,CAEtE;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAkE1E,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,CAIrF;AAED,gGAAgG;AAChG,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C"}
1
+ {"version":3,"file":"componentCategories.d.ts","sourceRoot":"","sources":["../../src/core/componentCategories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,OAAO,CAAC;AAEpF,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,iBAAiB,CAEjE,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,iBAAiB,CAEtE;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAyF1E,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,CAIrF;AAED,gGAAgG;AAChG,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C"}
@@ -91,6 +91,28 @@ export const COMPONENT_CATEGORY = {
91
91
  // enrichment then never spends Anthropic quota. Only used by the dark
92
92
  // llmEnrichment path; the shipped deterministic auditor makes no LLM calls.
93
93
  StandardsCoverageEnrichment: 'job',
94
+ // ── Previously-uncategorized LLM callsites (LLM Routing Registry audit,
95
+ // 2026-07-01). Each calls an intelligence provider's .evaluate() but was
96
+ // absent from this map AND passes no explicit attribution.category, so it
97
+ // resolved to 'other' → the agent default framework (Claude) — silently
98
+ // spending Anthropic quota instead of routing off-Claude like its peers.
99
+ // Categorized by function (sentinel = background judgment call, gate =
100
+ // pre-action allow/deny, reflector = extraction/summarization/analysis).
101
+ // The drift-guard test (componentCategories-evaluate-coverage.test.ts)
102
+ // keeps this map exhaustive over .evaluate() callsites going forward. ──
103
+ InputClassifier: 'sentinel', // input auto-approve vs relay classification
104
+ SessionSummarySentinel: 'sentinel', // summarize tmux output → task/phase/files
105
+ TelegramAdapter: 'sentinel', // stall/idle alert-suppression judge (parity with SlackAdapter)
106
+ ResumeValidator: 'gate', // does a resume UUID match the topic? (pre-resume gate)
107
+ Usher: 'reflector', // route a turn to candidate topics
108
+ TopicIntentExtractor: 'reflector', // extract topic intent from a turn
109
+ PreCompactionFlush: 'reflector', // extract durable facts before compaction
110
+ TreeSynthesis: 'reflector', // synthesize knowledge fragments → answer
111
+ LLMConflictResolver: 'reflector', // resolve divergent multi-machine state
112
+ openConversationBrief: 'reflector', // generate an A2A conversation brief
113
+ 'a2a-checkin': 'reflector', // summarize A2A check-in threads (server:a2a-checkin)
114
+ 'correction-learning': 'reflector', // distill recurring corrections → preference (server:correction-learning)
115
+ 'mentor-stage-b': 'reflector', // classify mentor signals → forensic findings
94
116
  };
95
117
  /**
96
118
  * Resolve a component's category. Strips a trailing "/segment" call-site suffix
@@ -1 +1 @@
1
- {"version":3,"file":"componentCategories.js","sourceRoot":"","sources":["../../src/core/componentCategories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAqC;IACpE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO;CAChD,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,CAAU;IAC5C,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAK,oBAA0C,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgD;IAC7E,uEAAuE;IACvE,aAAa,EAAE,UAAU;IACzB,UAAU,EAAE,UAAU;IACtB,uBAAuB,EAAE,UAAU;IACnC,gBAAgB,EAAE,UAAU;IAC5B,kBAAkB,EAAE,UAAU;IAC9B,aAAa,EAAE,UAAU;IACzB,aAAa,EAAE,UAAU;IACzB,eAAe,EAAE,UAAU;IAC3B,mBAAmB,EAAE,UAAU;IAC/B,wBAAwB,EAAE,UAAU;IACpC,mBAAmB,EAAE,UAAU;IAC/B,eAAe,EAAE,UAAU;IAC3B,0EAA0E;IAC1E,uEAAuE;IACvE,kBAAkB,EAAE,UAAU;IAC9B,mBAAmB,EAAE,UAAU;IAC/B,wEAAwE;IACxE,iDAAiD;IACjD,0BAA0B,EAAE,UAAU;IACtC,iEAAiE;IACjE,YAAY,EAAE,UAAU;IAExB,iDAAiD;IACjD,UAAU,EAAE,MAAM;IAClB,YAAY,EAAE,MAAM;IACpB,eAAe,EAAE,MAAM;IACvB,qBAAqB,EAAE,MAAM;IAC7B,iBAAiB,EAAE,MAAM;IACzB,mBAAmB,EAAE,MAAM;IAC3B,aAAa,EAAE,MAAM;IACrB,iBAAiB,EAAE,MAAM;IACzB,iBAAiB,EAAE,MAAM;IACzB,2EAA2E;IAC3E,YAAY,EAAE,MAAM;IACpB,oDAAoD;IACpD,gBAAgB,EAAE,MAAM;IACxB,cAAc,EAAE,MAAM;IAEtB,gEAAgE;IAChE,YAAY,EAAE,WAAW;IACzB,kBAAkB,EAAE,WAAW;IAC/B,iBAAiB,EAAE,WAAW;IAC9B,UAAU,EAAE,WAAW;IACvB,eAAe,EAAE,WAAW;IAC5B,mBAAmB,EAAE,WAAW;IAChC,mBAAmB,EAAE,WAAW;IAChC,4BAA4B,EAAE,WAAW;IACzC,kBAAkB,EAAE,WAAW;IAE/B,8BAA8B;IAC9B,kBAAkB,EAAE,KAAK;IACzB,8EAA8E;IAC9E,4EAA4E;IAC5E,8EAA8E;IAC9E,4EAA4E;IAC5E,4EAA4E;IAC5E,+EAA+E;IAC/E,iBAAiB,EAAE,KAAK;IACxB,8EAA8E;IAC9E,gFAAgF;IAChF,gFAAgF;IAChF,sEAAsE;IACtE,4EAA4E;IAC5E,2BAA2B,EAAE,KAAK;CACnC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAA6B;IAChE,IAAI,CAAC,SAAS;QAAE,OAAO,OAAO,CAAC;IAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpE,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC;AAC7C,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,eAAe;IAC7B,OAAO,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"componentCategories.js","sourceRoot":"","sources":["../../src/core/componentCategories.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.706",
3
+ "version": "1.3.707",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-07-02T04:52:58.637Z",
5
- "instarVersion": "1.3.706",
4
+ "generatedAt": "2026-07-02T05:36:09.449Z",
5
+ "instarVersion": "1.3.707",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,65 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Thirteen background LLM call sites that were quietly running on the default
9
+ framework (Claude) now route off-Claude with their peers. The framework router
10
+ picks a provider by a component's category; these thirteen were absent from the
11
+ category map, so they resolved to `other` and fell back to Claude — burning
12
+ Anthropic quota while near-identical siblings routed to the cheaper, less
13
+ rate-limited off-Claude providers.
14
+
15
+ They were the pinned `WIRING_EXCLUSIONS` backlog explicitly deferred from the
16
+ token-audit PR ("each needs its own deliberate routing decision"). This is that
17
+ decision: each is registered by function — `InputClassifier`,
18
+ `SessionSummarySentinel`, `TelegramAdapter` (sentinel; `TelegramAdapter` also fixes
19
+ an asymmetry versus the already-registered `SlackAdapter` alert-suppression judge);
20
+ `ResumeValidator` (gate); and `Usher`, `TopicIntentExtractor`, `PreCompactionFlush`,
21
+ `TreeSynthesis`, `LLMConflictResolver`, `openConversationBrief`, `a2a-checkin`,
22
+ `correction-learning`, `mentor-stage-b` (reflector).
23
+
24
+ `WIRING_EXCLUSIONS` now holds only the five components that route via an explicit
25
+ `attribution.category` and are correctly map-unregistered. The existing wiring
26
+ ratchet remains the drift guard against future recurrence. Additive and fully
27
+ reversible; no new logic, no new decision authority.
28
+
29
+ ## What to Tell Your User
30
+
31
+ Thirteen of my small background AI helpers — the ones that classify messages,
32
+ summarize sessions, extract facts before compaction, and similar housekeeping —
33
+ were quietly running on Claude instead of the cheaper providers the rest of my
34
+ background checks use. That was burning Claude subscription quota (the scarce,
35
+ rate-limited resource) on work that never needed it. They now route off Claude
36
+ like their peers, so more of your Claude quota stays available for the
37
+ conversations and heavy work where it matters. Nothing changes in what these
38
+ helpers do — only which provider quietly runs them.
39
+
40
+ ## Summary of New Capabilities
41
+
42
+ None — no new API routes, config keys, or user-facing behavior. This is a
43
+ routing-map completion: 13 existing internal LLM call sites now resolve to their
44
+ proper category (`sentinel`/`gate`/`reflector`) so the existing
45
+ Provider-Fallback Default Policy routes them off Claude. Operators can still
46
+ override any of them per-agent via `sessions.componentFrameworks.overrides`.
47
+
48
+ ## Evidence
49
+
50
+ Before: `GET /intelligence/routing` on a live agent showed these 13 components
51
+ absent from the known-components registry, and `categoryForComponent()` in the
52
+ deployed dist resolved each to `'other'` → the agent default framework (Claude).
53
+ Verified against the deployed code during the 2026-07-01 LLM Routing Registry
54
+ audit (docs/LLM-ROUTING-REGISTRY.md), not just the source branch — each of the
55
+ 13 calls `.evaluate()` with an `attribution.component` that had no map entry and
56
+ no explicit `attribution.category`, while siblings like `SlackAdapter` (mapped)
57
+ routed off-Claude.
58
+
59
+ After: `categoryForComponent('InputClassifier')` → `'sentinel'` (and likewise
60
+ for all 13; `'TelegramAdapter'` now matches the already-mapped `SlackAdapter`).
61
+ The wiring ratchet (`tests/unit/llm-attribution-ratchet.test.ts`) proves both
62
+ directions over the real source tree: every literal `attribution.component` in
63
+ `src/` resolves to a registered category or a pinned explicit-category
64
+ exception, and every remaining exception genuinely resolves to `'other'`. The
65
+ router, integration, and e2e routing suites are green unchanged.
@@ -0,0 +1,100 @@
1
+ # Side-Effects Review — Register 13 uncategorized LLM components
2
+
3
+ **Version / slug:** `llm-routing-register-uncategorized-components`
4
+ **Date:** `2026-07-01`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required`
7
+
8
+ ## Summary of the change
9
+
10
+ Adds 13 previously-unregistered LLM call-site component names to `COMPONENT_CATEGORY`
11
+ in `src/core/componentCategories.ts`, each tagged `sentinel` / `gate` / `reflector`
12
+ by function, so the framework router resolves them to a real category instead of
13
+ `other` (which falls back to the agent default framework, Claude). Correspondingly
14
+ removes those 13 names from the `WIRING_EXCLUSIONS` pinned backlog in
15
+ `tests/unit/llm-attribution-ratchet.test.ts`, leaving only the 5 components that
16
+ route via an explicit `attribution.category` (so they correctly stay map-unregistered).
17
+ Files touched: `src/core/componentCategories.ts`, `tests/unit/llm-attribution-ratchet.test.ts`.
18
+ The change interacts with one decision point — the router's category resolution
19
+ (`categoryForComponent`) — but only feeds it more data; it adds no branching logic.
20
+
21
+ ## Decision-point inventory
22
+
23
+ - `categoryForComponent` (src/core/componentCategories.ts) — **pass-through** — unchanged
24
+ function; this change only adds rows to the map it reads. No control-flow edit.
25
+ - `IntelligenceRouter.resolveFramework` (per-component framework routing) — **pass-through** —
26
+ consumes the category; unchanged. The 13 components now resolve to their category's
27
+ configured framework instead of the default, which is the intended effect.
28
+
29
+ ---
30
+
31
+ ## 1. Over-block
32
+
33
+ **What legitimate inputs does this change reject that it shouldn't?**
34
+
35
+ No block/allow surface — over-block not applicable. This is a routing-map data change,
36
+ not a gate. It changes WHICH provider runs a call, never WHETHER the call is allowed.
37
+
38
+ ---
39
+
40
+ ## 2. Under-block
41
+
42
+ **What failure modes does this still miss?**
43
+
44
+ No block/allow surface — under-block not applicable. The change cannot make any gate
45
+ more permissive; gate *authority* is untouched. (The one `gate`-category addition,
46
+ ResumeValidator, keeps its existing behavior; only its provider changes.)
47
+
48
+ ---
49
+
50
+ ## 3. Wrong-provider / routing correctness
51
+
52
+ **Could a component now route to a provider that can't serve it correctly?**
53
+
54
+ Low risk. All 13 join categories (`sentinel`/`gate`/`reflector`) that the
55
+ Provider-Fallback Default Policy already routes off-Claude for dozens of live
56
+ components — the target providers (codex-cli → pi-cli → gemini-cli, Claude last)
57
+ are production-exercised. A rate-limited or missing framework degrades via the
58
+ existing per-framework circuit breaker + fallback chain (unchanged). No component
59
+ routes to a provider class not already in use for its category.
60
+
61
+ The one behavioral nuance: components that make *nuanced/critical* judgments
62
+ (e.g. LLMConflictResolver resolving divergent multi-machine state) now run on a
63
+ non-Claude reasoning-capable model (gpt-5.5 via codex) rather than Claude. This is
64
+ aligned with the operator directive to prefer subsidized non-Claude subscriptions,
65
+ and gpt-5.5 is reasoning-capable. A later nature-based routing pass (operator-reviewed)
66
+ will refine per-task model tiers; this change does not lock that in.
67
+
68
+ ---
69
+
70
+ ## 4. Reversibility / rollback
71
+
72
+ Fully reversible: remove the 13 rows from `COMPONENT_CATEGORY` (and restore them to
73
+ `WIRING_EXCLUSIONS`) and routing returns to the prior state. No migration, no state
74
+ schema change, no persisted data. An operator can also override any single component
75
+ per-agent via `sessions.componentFrameworks.overrides` without touching this map.
76
+
77
+ ---
78
+
79
+ ## 5. Blast radius
80
+
81
+ Fleet-wide once shipped (it's a core map), but strictly additive and category-consistent.
82
+ No new code paths execute; the router simply finds a category where it previously found
83
+ none. Existing tests cover it: the wiring ratchet (`llm-attribution-ratchet.test.ts`)
84
+ proves every live `.evaluate()` component now resolves, `intelligence-router.test.ts` and
85
+ the integration/e2e routing suites remain green. Signal-vs-authority: N/A — no detector
86
+ and no authority is added or modified; this is a data-map completion.
87
+
88
+ ---
89
+
90
+ ## 6. Test coverage
91
+
92
+ - `tests/unit/llm-attribution-ratchet.test.ts` — the drift guard; asserts every literal
93
+ `attribution.component` in `src/` resolves to a registered category or a pinned
94
+ (explicit-category) exception, AND that every pinned exception still resolves to `other`.
95
+ Both sides green after the change.
96
+ - `tests/unit/intelligence-router.test.ts`, `tests/unit/standards-coverage-component-category.test.ts`,
97
+ `tests/integration/intelligence-routing-routes.test.ts`,
98
+ `tests/integration/provider-fallback-default-routing.test.ts` — all green.
99
+ - No NEW test added: the existing ratchet already IS the structural guard for this
100
+ invariant (adding a duplicate would be noise).