instar 1.3.793 → 1.3.795
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.
- package/dashboard/index.html +99 -0
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +17 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/ModelTierEscalation.d.ts +1 -1
- package/dist/core/ModelTierEscalation.d.ts.map +1 -1
- package/dist/core/ModelTierEscalation.js +7 -0
- package/dist/core/ModelTierEscalation.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +14 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +52 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/componentCategories.d.ts.map +1 -1
- package/dist/core/componentCategories.js +6 -0
- package/dist/core/componentCategories.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +6 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +23 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/data/llmBenchCoverage.d.ts.map +1 -1
- package/dist/data/llmBenchCoverage.js +12 -0
- package/dist/data/llmBenchCoverage.js.map +1 -1
- package/dist/monitoring/DashboardInsightEngine.d.ts +209 -0
- package/dist/monitoring/DashboardInsightEngine.d.ts.map +1 -0
- package/dist/monitoring/DashboardInsightEngine.js +369 -0
- package/dist/monitoring/DashboardInsightEngine.js.map +1 -0
- package/dist/monitoring/dashboardInsightCollectors.d.ts +34 -0
- package/dist/monitoring/dashboardInsightCollectors.d.ts.map +1 -0
- package/dist/monitoring/dashboardInsightCollectors.js +88 -0
- package/dist/monitoring/dashboardInsightCollectors.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +7 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +4 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +35 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +16 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +5 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +45 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/scripts/model-registry-freshness.manifest.json +6 -3
- package/src/data/builtin-manifest.json +64 -64
- package/src/data/llmBenchCoverage.ts +14 -0
- package/src/scaffold/templates.ts +7 -0
- package/upgrades/1.3.794.md +19 -0
- package/upgrades/1.3.795.md +36 -0
- package/upgrades/side-effects/codex-gpt56-allowlist.md +60 -0
- package/upgrades/side-effects/dashboard-live-insights.md +137 -0
|
@@ -824,6 +824,13 @@ I declare owner/blockedOn at commitment creation; a later state change goes thro
|
|
|
824
824
|
- **Proactive trigger**: when the user asks "is the loop noticing anything? / how's the rollout going? / what's it found?" → point them to the Process Health tab (give the dashboard URL + PIN). Do NOT paraphrase \`/failures*\` curl output at them — the tab IS the answer surface. Only read \`/failures/analysis\` yourself when you need the raw numbers for your own reasoning.
|
|
825
825
|
- **Disabled note**: when \`monitoring.failureLearning.enabled\` is false the tab shows a friendly "not turned on yet" message, not an error.
|
|
826
826
|
|
|
827
|
+
**Live Insights (Dashboard Tab)** — The at-a-glance layer on top of your raw dashboard data (docs/specs/dashboard-live-insights.md): a per-page **Insight Strip** — one plain-English (ELI16) headline + up to 3 supporting observations about THAT page's own data, each ending with a button to open the page it came from. It turns 25 tabs of raw numbers into "here's what stands out, and where to look." AWARENESS-ONLY: the strip observes and phrases; it never acts, never mutates, never links to a mutating action.
|
|
828
|
+
- **Where**: the "Insights" tab in the dashboard (first in the Runtime group). Nothing to run — it renders on open. Point the user there rather than pasting curl output.
|
|
829
|
+
- **How the insight is made**: a DETERMINISTIC per-page one-liner floor (always available) PLUS, when live, an LLM insight routed through the SHARED nature-router funnel (the FAST lane — model selection comes from the benchmark-derived routing chains, never a hardcoded model). It generates ON VIEW and is CACHED per page (\`ttlSeconds\`, default 300) so unchanged data never re-spends. A slow/failed LLM call DEGRADES to the deterministic floor — the strip never blocks the page and never fabricates.
|
|
830
|
+
- **API** (read-only): \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/insights\` (all pages) · \`GET /insights/:page\` (one page) · \`GET /insights/status\` (posture). The LLM call is auditable in the LLM Activity tab under component \`DashboardInsightEngine\` (Token-Audit Completeness — every insight call is metered).
|
|
831
|
+
- **Rollout**: dev-gated dark — \`dashboard.liveInsights.enabled\` is OMITTED so it resolves LIVE on a development agent, DARK on the fleet (routes 503 when dark). \`dryRun:true\` (dev default) is the spend canary — the deterministic floor renders and the LLM layer only logs "would generate"; a deliberate \`dryRun:false\` activates real LLM insights.
|
|
832
|
+
- **Proactive trigger**: when the user asks "what stands out on my dashboard? / anything I should look at? / summarize this page" → point them at the Insights tab (dashboard URL + PIN). When the routes 503, say honestly that live insights aren't turned on for this agent yet.
|
|
833
|
+
|
|
827
834
|
**Backup System** — Snapshot and restore agent state. Use before risky changes, after major progress, or to recover from corruption.
|
|
828
835
|
- List snapshots: \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/backups\`
|
|
829
836
|
- Create snapshot: \`curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:${port}/backups\`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
The GPT-5.6 model family (`gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`) went GA on the Codex subscription and is now on instar's accepted-model allowlists for the `codex-cli` framework. Two mirrored lists gained the three ids: `KNOWN_CODEX_MODEL_IDS` (the model-tier-escalation resolver's closed enum, `src/core/ModelTierEscalation.ts`) and `CODEX_MODELS_SUBSCRIPTION` (the `POST /sessions/spawn` model validator, `src/server/routes.ts`). The topic-profile validator reads the same enum, so it accepts the new ids automatically. The fail-closed design is unchanged — an id outside the closed enum is still rejected; we only widened the set of recognized ids.
|
|
9
|
+
|
|
10
|
+
The Doorway/Model Knowledge Registry (`scripts/model-registry-freshness.manifest.json`) also learned the three models as recognized, reachable entries with pricing, so `GET /doorways` knows they exist. They are deliberately NOT promoted to the frontier pin — the capable tier still resolves to `gpt-5.5`; a benchmark-driven promotion is a tracked follow-up.
|
|
11
|
+
|
|
12
|
+
## What to Tell Your User
|
|
13
|
+
|
|
14
|
+
If you run Codex sessions, you can now pin a topic or spawn a session on the new GPT-5.6 models — sol (the flagship), terra (mid-size), or luna (small and cheap) — and instar accepts them instead of rejecting them as unknown. This needs the Codex CLI at version 0.144.0 or newer; older CLIs reject GPT-5.6 with a "requires a newer version" error, so update the Codex CLI if you hit that. If your setup already escalates heavy work onto the GPT-5.6 flagship, it becomes live with this update. The Pro variants are intentionally not accepted yet (they're likely plan-gated and pricier — a future follow-up), and for now instar still picks GPT-5.5 for its heavy tier until the new models earn that spot through benchmarks.
|
|
15
|
+
|
|
16
|
+
## Summary of New Capabilities
|
|
17
|
+
|
|
18
|
+
- `codex-cli` sessions and topic profiles accept `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna` (model-tier escalation, `/sessions/spawn`, and topic-profile pins).
|
|
19
|
+
- `GET /doorways` reports the three GPT-5.6 models (with pricing) as recognized, reachable Codex models.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: minor -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
The dashboard gained a new **Insights** tab (first in the Runtime group) — the "at-a-glance meaning" layer on top of the raw data the other 25 tabs show. For each page it renders one calm **Insight Strip**: a single plain-English (ELI16) headline naming the most important thing about that page's data, up to three short supporting lines, and a button to open the page the insight came from. It turns "here are 40 numbers" into "here's the one thing worth a look, and where to look" (operator directive, topic 29723: *"extremely digestible • clearly actionable • simple (think eli16) but clear paths to drill into details • use of LLM intelligence to provide active/live insights into page data"*).
|
|
9
|
+
|
|
10
|
+
Two layers produce each strip. A **deterministic one-liner** computed straight from the page's numbers is always available — so the tab is useful and honest even with the AI turned off. When the feature is live, an **LLM insight** is generated instead, routed through the agent's existing nature-router down its **FAST lane**: the model is chosen by the benchmark-derived routing chains (never hardcoded), the call is metered under component `DashboardInsightEngine` in the LLM Activity tab, it is generated only on view and **cached per page for 5 minutes** (unchanged data never re-spends), and it degrades back to the deterministic one-liner on any failure or timeout. The insight is strictly **awareness-only**: it observes and phrases, it never acts, never mutates state, and never links to a mutating action.
|
|
11
|
+
|
|
12
|
+
New read-only routes back the tab: `GET /insights`, `GET /insights/:page`, `GET /insights/status`. The feature ships **dark on the fleet and live on a development agent** (the standard maturation ladder), and even on a dev agent the actual LLM spend stays behind a `dryRun` switch (the deterministic floor renders; the LLM only logs "would generate") until an operator deliberately flips `dryRun:false` after a soak. This ship wires the **LLM Activity** page collector end-to-end (the motivating example — it separates real routing errors from mesh-probe noise); additional page collectors and the cross-page "what needs you" digest are tracked follow-ups (the engine, route, and UI are page-generic).
|
|
13
|
+
|
|
14
|
+
## What to Tell Your User
|
|
15
|
+
|
|
16
|
+
- "There's a new **Insights** tab in your dashboard. It reads each page's data and tells you, in one plain sentence, what stands out — plus a button to open the page it came from. It only explains; it never changes anything."
|
|
17
|
+
- "The insights can be written by an AI model, chosen automatically by our benchmark-tuned routing (the cheap, fast lane) and cached for 5 minutes so it doesn't waste money. If the AI is unavailable, you still get a plain summary computed from the numbers — the tab never breaks."
|
|
18
|
+
- "It's on for development agents and off for everyone else for now; even on a dev agent the AI spend is held behind one more switch until it's been watched working. No action needed — open the Insights tab (first tab in the dashboard)."
|
|
19
|
+
|
|
20
|
+
## Summary of New Capabilities
|
|
21
|
+
|
|
22
|
+
| Capability | How to Use |
|
|
23
|
+
|-----------|-----------|
|
|
24
|
+
| Per-page Insight Strip (Insights tab) | Open the **Insights** tab in the dashboard (dashboard URL + PIN) |
|
|
25
|
+
| Cross-page insight digest (API) | `GET /insights` — every page's strip; `GET /insights/:page` — one page |
|
|
26
|
+
| Insight posture (API) | `GET /insights/status` — enabled / dryRun / ttl / pageCount |
|
|
27
|
+
| AI insight routing | Automatic — the FAST lane of the nature-router (model from the benchmark chains); metered under `DashboardInsightEngine` in LLM Activity |
|
|
28
|
+
| Enable real AI insights (dev agent) | Set `dashboard.liveInsights.dryRun: false` after a soak (default `true`) |
|
|
29
|
+
| Fleet enable | Set `dashboard.liveInsights.enabled: true` (dev-gated dark by default) |
|
|
30
|
+
|
|
31
|
+
## Evidence
|
|
32
|
+
|
|
33
|
+
- **Unit** (`tests/unit/dashboard-insight-engine.test.ts`, 21 tests): the deterministic floor (anomaly headline / affirmative-healthy / empty / paused / throwing-collector), the LLM path + exact FAST-lane attribution (`model:'fast'`, `component:'DashboardInsightEngine'`, `nature:'A'`, `gating:false`, `injectionExposed:true`), snapshot-fingerprint caching (unchanged → no re-spend; changed / TTL-expired → regen), degrade-to-floor on throw + on unparseable output, the `dryRun` spend canary (LLM never called), untrusted enveloping, and the parser's severity clamp.
|
|
34
|
+
- **Integration** (`tests/integration/insights-routes.test.ts`, 5 tests): the dark→live gate — 503 on every route when the engine is null, 200 with the strip payload when wired, 404 on an unknown page, and the LLM source rendered under `dryRun:false`.
|
|
35
|
+
- **E2E "feature is alive"** (`tests/e2e/insights-alive.test.ts`, 3 tests): the developmentAgent gate resolves LIVE on a dev agent / DARK on the fleet over the REAL ConfigDefaults; `GET /insights` returns a real insight payload built by the REAL LLM-Activity collector over a REAL `FeatureMetricsLedger` (a genuinely failing check surfaces); the dark contract 503s.
|
|
36
|
+
- **Ratchets** re-green after the map additions: `llm-bench-coverage-ratchet`, `llm-routing-nature-ratchet`, `nature-routing-injection-exposure-ratchet`, `untrusted-input-classification-ratchet`, `llm-attribution-ratchet` (componentCategories wiring), `devGatedFeatures-wiring`, `capabilities-discoverability`, `lint-dev-agent-dark-gate`, and the three dashboard UX floors (F1/F2/F3). Typecheck clean.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Side-Effects Review — Add the GPT-5.6 family to the codex model allowlists
|
|
2
|
+
|
|
3
|
+
**Change:** additive model-id allowlist extension for the `codex-cli` framework. **Tier 1** (small, low-risk, fail-closed design unchanged). **Parent principle:** Structure > Willpower (the closed model-id enumeration is a code-enforced gate; this widens the allowed set, it does not weaken the gate).
|
|
4
|
+
|
|
5
|
+
**Files changed:**
|
|
6
|
+
- `src/core/ModelTierEscalation.ts` — `KNOWN_CODEX_MODEL_IDS` gains `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`.
|
|
7
|
+
- `src/server/routes.ts` — `CODEX_MODELS_SUBSCRIPTION` (the `POST /sessions/spawn` codex model validator) gains the same three ids, keeping the two lists identical (the comment pins them as mirrors).
|
|
8
|
+
- `scripts/model-registry-freshness.manifest.json` — the Doorway/Model Knowledge Registry's `codex-cli.topModels` gains the three ids as recognized entries (`frontier: false`, pricing populated) + the door note / `$flaggedStaleNote` prose corrected to reflect the 2026-07-09 GA (the earlier "gpt-5.6-sol is preview-only/unreachable" line was now false).
|
|
9
|
+
- `tests/unit/modelTierEscalation-resolver.test.ts`, `tests/unit/route-validation-edge.test.ts`, `tests/unit/topicProfileValidation.test.ts` — allowlist + resolver + spawn + validation coverage.
|
|
10
|
+
- `docs/specs/codex-gpt56-allowlist.eli16.md`, `upgrades/next/codex-gpt56-allowlist.md` — the ELI16 + release fragment.
|
|
11
|
+
|
|
12
|
+
## What changed
|
|
13
|
+
|
|
14
|
+
The GPT-5.6 family (sol/terra/luna) went GA on the codex subscription on 2026-07-09 and was live-verified working (codex CLI >= 0.144.0 required; older CLIs 400 with "requires a newer version"). instar fails closed on model ids outside its closed per-framework enums, so these ids were rejected everywhere. This change adds the three ids to the two mirrored acceptance lists (`KNOWN_CODEX_MODEL_IDS` + `CODEX_MODELS_SUBSCRIPTION`). The `-pro` variants are deliberately excluded (plan-gated + pricier — tracked follow-up).
|
|
15
|
+
|
|
16
|
+
## Lists touched vs deliberately left
|
|
17
|
+
|
|
18
|
+
**Touched (acceptance / validation lists):**
|
|
19
|
+
- `KNOWN_CODEX_MODEL_IDS` (`src/core/ModelTierEscalation.ts`) — the escalation resolver's closed enum, and (via `KNOWN_MODEL_IDS`) the source for `topicProfileValidation.validateModelId`. One edit flows to both surfaces.
|
|
20
|
+
- `CODEX_MODELS_SUBSCRIPTION` (`src/server/routes.ts`) — the `/sessions/spawn` codex-cli model validator. Kept byte-identical in membership to the enum above (they are documented mirrors).
|
|
21
|
+
- `scripts/model-registry-freshness.manifest.json` → `doors.codex-cli.topModels` — the Doorway/Model Knowledge registry, added the three ids with `frontier: false` + pricing so `GET /doorways` knows they exist and their cost.
|
|
22
|
+
|
|
23
|
+
**Deliberately LEFT (routing/selection — a model earns a lane via benchmarks, not by GA date):**
|
|
24
|
+
- `src/providers/adapters/openai-codex/models.ts` `TIER_MODEL` (capable → gpt-5.5, fast/balanced → gpt-5.4-mini) — model CHOICES per tier, not an acceptance list.
|
|
25
|
+
- `src/core/frameworkSessionLaunch.ts` tier→model resolution — same reason.
|
|
26
|
+
- `src/data/llmBenchCoverage.ts` (`ROUTING_LABEL_TO_MODEL_ID`, bench coverage, nature-routing chains) — the routing chains that pick models for lanes; models earn these via benchmarks.
|
|
27
|
+
- The doorway manifest's `codex-capable-tier` PIN and the `frontier: true` flag — left at `gpt-5.5`. Promoting `gpt-5.6-sol` to the capable pin / frontier is a benchmark-driven follow-up, not this acceptance PR.
|
|
28
|
+
|
|
29
|
+
## Blast radius
|
|
30
|
+
|
|
31
|
+
- **Purely additive.** No id removed, no existing id's behavior changed. A caller not asking for a GPT-5.6 id is entirely unaffected.
|
|
32
|
+
- **Fail-closed preserved.** A well-shaped id outside the enum is still rejected (`id-not-in-closed-enum`); a made-up `gpt-9.9-fake` still 400s at spawn and resolves to null in escalation — both covered by new tests.
|
|
33
|
+
- **No new route, no new config default, no schema change.** No dark-gate line shift (no `enabled:` line added to `ConfigDefaults.ts`).
|
|
34
|
+
|
|
35
|
+
## Risk + mitigation
|
|
36
|
+
|
|
37
|
+
- **Risk:** the two mirror lists drift apart. **Mitigation:** both edited in the same commit with a cross-referencing comment on each; new tests assert acceptance through both the resolver and the spawn route.
|
|
38
|
+
- **Risk:** the doorway manifest edit trips the CI-gating model-registry-freshness lint. **Mitigation:** the new entries are `frontier: false`, so the codex-cli derived frontier set stays `['gpt-5.5']` and the `codex-capable-tier` pin (still `gpt-5.5`) remains a member — the drift tooth is unaffected. Staleness is unchanged (`lastReviewedAt` untouched, well within the 45-day window). Verified: `node scripts/lint-model-registry-freshness.mjs` → PASS.
|
|
39
|
+
- **Risk:** a user on an old codex CLI selects a GPT-5.6 id and gets an opaque failure. **Mitigation:** the ELI16 + release fragment both call out the codex CLI >= 0.144.0 requirement explicitly.
|
|
40
|
+
|
|
41
|
+
## Framework generality
|
|
42
|
+
|
|
43
|
+
The change is scoped to the `codex-cli` framework's own acceptance surfaces and routes through the existing per-framework `KNOWN_MODEL_IDS` / spawn-validator abstraction — it does not touch the session-launch/inject abstraction and makes no Claude-specific assumption. Other frameworks (claude-code, gemini-cli, pi-cli) are untouched.
|
|
44
|
+
|
|
45
|
+
## Migration parity
|
|
46
|
+
|
|
47
|
+
- No agent-installed file changes (no `.claude/settings.json`, no `.instar/config.json` default, no CLAUDE.md template section, no hook/skill). The allowlists are shipped code read at runtime, so existing agents pick up the new ids on the normal server/dist update — no `PostUpdateMigrator` entry needed. The operator's already-set `models.tierEscalation.frameworks.codex-cli.escalated = "gpt-5.6-sol"` becomes live purely by deploying this code.
|
|
48
|
+
|
|
49
|
+
## Tests
|
|
50
|
+
|
|
51
|
+
- `tests/unit/modelTierEscalation-resolver.test.ts` — codex-cli escalated tier accepts each of gpt-5.6-sol/terra/luna; a made-up id fails closed (`id-not-in-closed-enum`); the `-pro` variants are asserted absent.
|
|
52
|
+
- `tests/unit/route-validation-edge.test.ts` — `POST /sessions/spawn` with framework `codex-cli` accepts the three GPT-5.6 ids (not 400) and rejects `gpt-9.9-fake` (400, error names "model").
|
|
53
|
+
- `tests/unit/topicProfileValidation.test.ts` — `validateModelId(..., 'codex-cli')` returns null for the three ids (the KNOWN_MODEL_IDS mirror path).
|
|
54
|
+
- Adjacent suites re-run green: `model-registry-freshness`, `codex-model-tier-resolution`, `frameworkSessionLaunch`, `model-tier-swap-route`, `model-tier-escalation-lifecycle`. `npx tsc --noEmit` clean.
|
|
55
|
+
|
|
56
|
+
## Follow-ups
|
|
57
|
+
|
|
58
|
+
- Add the `-pro` GPT-5.6 variants once their plan-gating + pricing are confirmed.
|
|
59
|
+
- Benchmark GPT-5.6-sol and, if it wins the lane, promote it to the codex capable tier pin (`TIER_MODEL.capable` + the manifest `frontier: true` + `lastReviewedAt` bump) and into the routing chains — a routing decision, not an acceptance change.
|
|
60
|
+
- Populate real per-token pricing across the doorway registry if/when the metered doorway-scan scopes consume it.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Side-Effects Review — Dashboard Live-LLM-Insights
|
|
2
|
+
|
|
3
|
+
Spec: `docs/specs/dashboard-live-insights.md` (operator-approved 2026-07-09, topic 29723: *"i approve the live-insights design spec with your recommendations."*). This is an approved DESIGN doc, not a converged spec; the /instar-dev tier reflects that.
|
|
4
|
+
Build branch: `echo/dashboard-live-insights` off `upstream/main` @ v1.3.792.
|
|
5
|
+
Tier: **1** (a new, dev-gated-dark, awareness-only READ surface; no irreversible action, no external egress, no money authority).
|
|
6
|
+
|
|
7
|
+
## Phase 1 — Principle check (signal vs authority)
|
|
8
|
+
|
|
9
|
+
**Does this change involve a decision point / authority?** NO. The feature is
|
|
10
|
+
strictly **awareness-only**. Its entire output is display text (a headline + lines +
|
|
11
|
+
legible metrics). It carries **zero action authority**:
|
|
12
|
+
- It NEVER gates, blocks, delays, or rewrites any message or operation.
|
|
13
|
+
- It NEVER mutates state — every route is a GET; the engine only reads.
|
|
14
|
+
- The one "action" it offers is a plain deep-link to a normal dashboard tab; that tab's
|
|
15
|
+
own already-guarded controls (PIN / coherence / external-op gates) are unchanged and
|
|
16
|
+
remain the only authority for anything mutating. The insight can never arm a door,
|
|
17
|
+
send a message, or approve anything.
|
|
18
|
+
|
|
19
|
+
**Signal-vs-authority shape:** the LLM insight is a pure SIGNAL. The deterministic
|
|
20
|
+
one-liner floor is the always-available honest fallback. Neither is an authority. This
|
|
21
|
+
is the correct shape for a digestibility surface — it informs; it never decides.
|
|
22
|
+
|
|
23
|
+
## Phase 2 — Plan (build location + interactions)
|
|
24
|
+
|
|
25
|
+
- **Build location:** FRESH worktree `echo-dashboard-live-insights` off `upstream/main`
|
|
26
|
+
@ v1.3.792 (per the AGENT-WORKTREE-CONVENTION-SPEC; the agent-home checkout on
|
|
27
|
+
`echo/serve-main` is ~127 commits behind canonical). git remote = JKHeadley; per-worktree
|
|
28
|
+
identity set by `instar worktree create`.
|
|
29
|
+
- **Re-grounding against main (all confirmed present):** `resolveDevAgentGate`
|
|
30
|
+
(`src/core/devAgentGate.ts`) + the `DEV_GATED_FEATURES` registry + its both-sides wiring
|
|
31
|
+
test (`devGatedFeatures-wiring.test.ts`); the shared `IntelligenceProvider`/`IntelligenceRouter`
|
|
32
|
+
funnel with `attribution.component` auto-recording into `FeatureMetricsLedger` via the
|
|
33
|
+
CircuitBreakingIntelligenceProvider tap; the nature-router maps
|
|
34
|
+
(`LLM_ROUTING_NATURE` non-exhaustive, `LLM_ROUTING_INJECTION_EXPOSURE`, `LLM_UNTRUSTED_INPUT`,
|
|
35
|
+
`LLM_BENCH_COVERAGE`, `COMPONENT_CATEGORY`) + their ratchets; the Process Health tab as the
|
|
36
|
+
calm read-surface precedent; the Dashboard UX Standard F1–F8 floors + their static tests;
|
|
37
|
+
`migrateConfigRoutingSpendDark` as the dev-gate config-seed migration precedent.
|
|
38
|
+
|
|
39
|
+
## Phase 3 — Side-effects enumeration
|
|
40
|
+
|
|
41
|
+
**New files (additive):**
|
|
42
|
+
- `src/monitoring/DashboardInsightEngine.ts` — the engine (deterministic floor + LLM layer + TTL cache).
|
|
43
|
+
- `src/monitoring/dashboardInsightCollectors.ts` — the built-in page collectors (LLM Activity wired).
|
|
44
|
+
- `tests/unit/dashboard-insight-engine.test.ts`, `tests/integration/insights-routes.test.ts`, `tests/e2e/insights-alive.test.ts`, `tests/unit/PostUpdateMigrator-dashboardLiveInsights.test.ts`.
|
|
45
|
+
- Docs: `docs/specs/dashboard-live-insights.md` (design authority, copied in), `.eli16.md`, `upgrades/next/…`, this file.
|
|
46
|
+
|
|
47
|
+
**Edited files (surgical, additive):**
|
|
48
|
+
- `src/server/routes.ts` — new `RouteContext.dashboardInsightEngine?` field + 3 GET routes (503 when null). No existing route touched.
|
|
49
|
+
- `src/server/AgentServer.ts` — new private field + dev-gate construction (own try/catch, cannot cascade) + one ctx-assembly line. Mirrors the `growthMilestoneAnalyst` precedent.
|
|
50
|
+
- `src/core/types.ts` — `DashboardConfig.liveInsights?` + `LiveInsightsConfig` (new optional shape).
|
|
51
|
+
- `src/config/ConfigDefaults.ts` — new `dashboard.liveInsights` default block (OMITS `enabled`; `dryRun:true`). Add-missing deep-merge; never clobbers `dashboard.fileViewer`/`poolStream`.
|
|
52
|
+
- `src/core/componentCategories.ts` — `DashboardInsightEngine: 'reflector'`.
|
|
53
|
+
- `src/data/llmBenchCoverage.ts` — bench `{exempt}`, injection `exposed(ALL)`, untrusted `true`. NOT added to `LLM_ROUTING_NATURE` (cite-the-bench forbids a nature row for an exempt component — the call rides the shared router's fast tier + declares `nature:'A'`, ready to graduate to a FAST-chain row when a bench task is authored).
|
|
54
|
+
- `src/core/devGatedFeatures.ts` — `dashboardLiveInsights` registry entry.
|
|
55
|
+
- `src/core/PostUpdateMigrator.ts` — `migrateConfigDashboardLiveInsightsDevGate` + runner registration.
|
|
56
|
+
- `src/server/CapabilityIndex.ts` — `/insights` prefix classified (surfaces in `/capabilities`).
|
|
57
|
+
- `src/scaffold/templates.ts` — CLAUDE.md "Live Insights (Dashboard Tab)" capability section (Agent Awareness).
|
|
58
|
+
- `dashboard/index.html` — nav button + panel + TAB_REGISTRY entry + `loadInsights()` (F1–F8 compliant).
|
|
59
|
+
- `tests/unit/llm-bench-coverage-ratchet.test.ts` — `DashboardInsightEngine` added to the pinned `EXEMPT_BASELINE` (a visible, reviewed act, per the ratchet's contract).
|
|
60
|
+
- `tests/unit/lint-dev-agent-dark-gate.test.ts` — line-number remap (+17) of the `EXPECTED` config-defaults snapshot. My block OMITS `enabled`, so the path SET is unchanged (still 25 entries) — pure line shift, re-verified.
|
|
61
|
+
|
|
62
|
+
**Migration parity:** existing agents get the config block + normalization via
|
|
63
|
+
`migrateConfigDashboardLiveInsightsDevGate` (idempotent, existence-checked, never writes
|
|
64
|
+
`enabled`, preserves an operator fleet-flip + sibling dashboard blocks); the CLAUDE.md
|
|
65
|
+
capability via the template; the routes via the shipped code.
|
|
66
|
+
|
|
67
|
+
**Cost / spend:** the ONLY cost path is the LLM insight call, and it is quadruple-bounded:
|
|
68
|
+
(1) it never fires while `dryRun` holds (dev default); (2) it fires only on `GET /insights*`,
|
|
69
|
+
never on a background sweep; (3) it is snapshot-fingerprint-cached (default 5 min) so a
|
|
70
|
+
polling dashboard re-spends at most once per page per TTL; (4) it rides the shared funnel's
|
|
71
|
+
host spawn-cap + circuit breaker, and is metered in `feature_metrics` (Token-Audit
|
|
72
|
+
Completeness — an unmetered LLM call is an unaccountable one).
|
|
73
|
+
|
|
74
|
+
**Untrusted-input safety:** page data (which can embed user/peer-authored rows) is
|
|
75
|
+
sanitized, length-clamped, and wrapped in a `<untrusted-page-data>` envelope that tells
|
|
76
|
+
the model it is data, never instructions; the component is `injectionExposed:true` so the
|
|
77
|
+
walk never routes it onto a non-injection door; the parsed output is treated as text only
|
|
78
|
+
(severity enum-clamped, unknown fields dropped, HTML-escaped at render).
|
|
79
|
+
|
|
80
|
+
## Phase 4 — Failure modes + rollback
|
|
81
|
+
|
|
82
|
+
- **LLM slow/failed/unparseable** → degrade to the deterministic floor (recorded, never
|
|
83
|
+
silent; never throws to the route; never fabricates).
|
|
84
|
+
- **Collector throws / returns null / stale** → honest empty/paused state (F6), never a blank.
|
|
85
|
+
- **Engine construction throws** → own try/catch sets the engine null → routes 503 (dark
|
|
86
|
+
contract), server boot unaffected.
|
|
87
|
+
- **Rollback lever:** unset/false `dashboard.liveInsights.enabled` (fleet) or set
|
|
88
|
+
`dryRun:true` (dev) — read live at construction; a server restart reverts to byte-identical
|
|
89
|
+
prior behavior (the tab 503s; no other surface changes). No data written that needs undoing.
|
|
90
|
+
|
|
91
|
+
## 6b. Operator-surface quality (Operator-Surface Quality standard)
|
|
92
|
+
|
|
93
|
+
This change touches an operator surface (`dashboard/index.html` — the new Insights tab).
|
|
94
|
+
|
|
95
|
+
1. **Leads with the primary action?** YES. The tab's purpose is *reading the insights*,
|
|
96
|
+
and the Insight Strips ARE the primary content — they render immediately on tab open
|
|
97
|
+
(below the one-line purpose sentence), each with its "Open <page>" drill-in button
|
|
98
|
+
visible on the card. Nothing the operator came for is behind a toggle or below the fold;
|
|
99
|
+
the raw metrics are the ONLY thing collapsed (behind a "Show the data" disclosure), which
|
|
100
|
+
is correct progressive disclosure — the plain-English takeaway leads, the numbers are opt-in.
|
|
101
|
+
2. **Zero raw internals as primary content?** YES. The headline and lines are plain English
|
|
102
|
+
(an LLM/deterministic sentence). No JSON, fingerprints, UUIDs, hashes, or slugs appear as
|
|
103
|
+
headline content. The only identifiers are the small muted source badge ("AI" / "summary" /
|
|
104
|
+
"cached" / "paused") and the "as of <time>" stamp — support metadata, de-emphasized.
|
|
105
|
+
3. **Destructive actions de-emphasized?** N/A — the surface has NO destructive (or any
|
|
106
|
+
mutating) action by construction. Its only interactive control is the "Open <page>"
|
|
107
|
+
drill-in button (navigation) and a "Show the data" disclosure. There is nothing to
|
|
108
|
+
revoke/delete/stop here.
|
|
109
|
+
4. **Plain language + phone width?** YES. Labels read the way a non-engineer would ("Live
|
|
110
|
+
insights aren't turned on for this agent yet", "Couldn't load insights just now"). The
|
|
111
|
+
strip uses the same `ph-root` responsive layout as the Process Health tab; metrics use a
|
|
112
|
+
`repeat(auto-fit,minmax(120px,1fr))` grid that stacks at phone width; there is no fixed-
|
|
113
|
+
width table and no horizontal scroll (F4). The dark state and error state render as calm
|
|
114
|
+
sentences, never a raw error or a blank.
|
|
115
|
+
|
|
116
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
117
|
+
|
|
118
|
+
**Machine-local BY DESIGN — pure per-machine observability.** The Insight Strip summarizes
|
|
119
|
+
THIS machine's own dashboard-page data (its `FeatureMetricsLedger`, its live state). Each
|
|
120
|
+
machine's dashboard shows its own machine's insights — there is nothing to replicate and it
|
|
121
|
+
should differ per machine (a machine's routing health is that machine's). It emits NO
|
|
122
|
+
user-facing notices (no one-voice gating needed — it never sends; it only renders when the
|
|
123
|
+
operator opens the tab), holds NO durable state (the TTL cache is in-memory, per-process; it
|
|
124
|
+
strands nothing on a topic transfer), and generates NO URLs that cross machine boundaries
|
|
125
|
+
(the only link is an intra-dashboard `switchTab`). A pool-scope (`?scope=pool`) merged view
|
|
126
|
+
across machines is a natural future enhancement, not required for correctness — a
|
|
127
|
+
single-machine or per-machine read is the honest, correct default here.
|
|
128
|
+
|
|
129
|
+
## Phase 5 — Deferred (tracked follow-ups, honest)
|
|
130
|
+
|
|
131
|
+
- Increment C (cross-page Attention digest, JUDGE lane, optional default landing view).
|
|
132
|
+
- Increment D (gate-guarded action deep-links).
|
|
133
|
+
- Additional page collectors (Spend / Machines / Sessions / Attention) — the engine/route/UI
|
|
134
|
+
are page-generic; each is a small additive collector. This ship wires LLM Activity as the
|
|
135
|
+
proven end-to-end example.
|
|
136
|
+
- A `LLM_ROUTING_NATURE` row for `DashboardInsightEngine` once a real INSTAR-Bench task for
|
|
137
|
+
the insight summarizer is authored (graduating it from `{exempt}` to `{task}` — cite-the-bench).
|