instar 0.28.109 → 0.28.111

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 (39) hide show
  1. package/dashboard/proposals.html +418 -0
  2. package/dist/monitoring/BurnVerifier.d.ts +68 -0
  3. package/dist/monitoring/BurnVerifier.d.ts.map +1 -0
  4. package/dist/monitoring/BurnVerifier.js +151 -0
  5. package/dist/monitoring/BurnVerifier.js.map +1 -0
  6. package/dist/remediation/NovelFailureReviewer.d.ts +212 -0
  7. package/dist/remediation/NovelFailureReviewer.d.ts.map +1 -0
  8. package/dist/remediation/NovelFailureReviewer.js +605 -0
  9. package/dist/remediation/NovelFailureReviewer.js.map +1 -0
  10. package/dist/remediation/Remediator.d.ts.map +1 -1
  11. package/dist/remediation/Remediator.js +1 -0
  12. package/dist/remediation/Remediator.js.map +1 -1
  13. package/dist/remediation/TrustElevationSource.d.ts +8 -1
  14. package/dist/remediation/TrustElevationSource.d.ts.map +1 -1
  15. package/dist/remediation/TrustElevationSource.js +8 -1
  16. package/dist/remediation/TrustElevationSource.js.map +1 -1
  17. package/dist/remediation/audit/AuditProjection.d.ts +7 -0
  18. package/dist/remediation/audit/AuditProjection.d.ts.map +1 -1
  19. package/dist/remediation/audit/AuditProjection.js +16 -0
  20. package/dist/remediation/audit/AuditProjection.js.map +1 -1
  21. package/dist/remediation/audit/AuditWriter.d.ts +8 -0
  22. package/dist/remediation/audit/AuditWriter.d.ts.map +1 -1
  23. package/dist/remediation/audit/AuditWriter.js +5 -1
  24. package/dist/remediation/audit/AuditWriter.js.map +1 -1
  25. package/dist/server/AgentServer.d.ts +4 -0
  26. package/dist/server/AgentServer.d.ts.map +1 -1
  27. package/dist/server/AgentServer.js +90 -0
  28. package/dist/server/AgentServer.js.map +1 -1
  29. package/dist/server/routes/remediation-proposals.d.ts +114 -0
  30. package/dist/server/routes/remediation-proposals.d.ts.map +1 -0
  31. package/dist/server/routes/remediation-proposals.js +350 -0
  32. package/dist/server/routes/remediation-proposals.js.map +1 -0
  33. package/package.json +1 -1
  34. package/src/data/builtin-manifest.json +3 -3
  35. package/upgrades/0.28.110.md +41 -0
  36. package/upgrades/0.28.111.md +43 -0
  37. package/upgrades/side-effects/s1-novel-failure-reviewer.md +79 -0
  38. package/upgrades/side-effects/s2-dashboard-proposals.md +76 -0
  39. package/upgrades/side-effects/token-burn-detection-phase-6.md +63 -0
@@ -0,0 +1,212 @@
1
+ /**
2
+ * NovelFailureReviewer — bottom-up signature discovery for `no-matching-runbook`
3
+ * degradation events.
4
+ *
5
+ * Tier-3 S-1 of the Self-Healing Remediator v2 rollout.
6
+ *
7
+ * NOT a `CoherenceReviewer` subclass and NOT under `src/core/reviewers/`
8
+ * (§A50). NOT the same as `src/monitoring/SystemReviewer.ts` (the probe
9
+ * runner — see §A18 for the rename history). This module lives at
10
+ * `src/remediation/NovelFailureReviewer.ts` and is structurally distinct
11
+ * from both.
12
+ *
13
+ * Spec anchor: docs/specs/SELF-HEALING-REMEDIATOR-V2-SPEC.md
14
+ * §A10 caps / batching / structured rendering / schema constraints
15
+ * §A18 module rename (SystemReviewer → NovelFailureReviewer)
16
+ * §A26 additional guardrails (dismiss-trust, no-slot-for-collisions,
17
+ * model allowlist, raw-response redaction)
18
+ * §A32 signed `producingAgentId` on every proposal
19
+ * §A47 per-signature counter persistence at
20
+ * `.instar/remediation/cluster-counters-<machineId>.json`
21
+ * §A50 naming clarity (this comment)
22
+ * §A57 Tier-3 placement
23
+ * §A60 deterministic proposalId = sha256(clusterSignature || windowStartMs || fleetScope)
24
+ * §A65 LLM monthly budget circuit-breaker + per-call cost cap
25
+ *
26
+ * Pipeline per `runTick()`:
27
+ * 1. Read `auditProjection.unmatched()` — `no-matching-runbook` entries.
28
+ * 2. Cluster by signature: `(subsystem, errorCode-token-classed,
29
+ * reason-prefix-hashed)` (§A10).
30
+ * 3. Persist per-signature counters with HMAC (§A47).
31
+ * 4. For clusters crossing thresholds (≥3 occurrences × ≥2 process
32
+ * lifetimes within `windowDays`):
33
+ * - If outstanding-proposal cap reached → silently queue (no LLM
34
+ * call, no slot consumed).
35
+ * - Else: call `llmCaller()` with a fixed safety frame; validate
36
+ * schema (§A10), strip injection artifacts, check collision
37
+ * against active runbook errorCodes (§A26 — collision rejection
38
+ * does NOT consume an outstanding slot), persist the signed
39
+ * proposal, and emit observability events.
40
+ *
41
+ * Out of scope for S-1 (handled by S-2 Dashboard / S-3 promotion-gate):
42
+ * - Batched Telegram notification rendering — S-1 emits structured
43
+ * events; S-2 owns UI.
44
+ * - Primary-aggregator lease + fencing tokens — A47 / A60 cross-machine
45
+ * coordination ships alongside S-2 / S-3.
46
+ */
47
+ import { AuditProjection } from './audit/AuditProjection.js';
48
+ import type { AuditEntry } from './audit/AuditWriter.js';
49
+ import type { RemediationKeyVault } from './RemediationKeyVault.js';
50
+ import type { TrustElevationSource } from './TrustElevationSource.js';
51
+ export interface NovelFailureReviewerConfig {
52
+ /** Minimum occurrences to qualify a cluster for proposal (§A10/§A17). */
53
+ clusterThresholdOccurrences: number;
54
+ /** Minimum distinct process lifetimes spanned (§A10/§A17). */
55
+ clusterThresholdLifetimes: number;
56
+ /** Sliding window in days for occurrence / lifetime counting. */
57
+ windowDays: number;
58
+ /** Max outstanding proposals per agent at any time (§A10). */
59
+ outstandingProposalCap: number;
60
+ /** Cluster LRU bound (§A10). */
61
+ clusterLruCap: number;
62
+ /** LLM model id (allowlisted in production via §A26). */
63
+ llmModel: string;
64
+ /** Monthly cumulative LLM spend ceiling in USD (§A65). */
65
+ llmMonthlyBudgetUsd: number;
66
+ /** Per-call estimated cost ceiling in USD (§A65). */
67
+ llmPerCallCostCapUsd?: number;
68
+ /** Estimated USD cost per LLM call. Default fits Haiku-class pricing. */
69
+ llmEstimatedCostPerCallUsd?: number;
70
+ }
71
+ export declare const DEFAULT_NOVEL_FAILURE_REVIEWER_CONFIG: NovelFailureReviewerConfig;
72
+ /** §A10 — small, fixed allowlist enforced at config-load (per §A26). */
73
+ export declare const LLM_MODEL_ALLOWLIST: ReadonlySet<string>;
74
+ export interface SampleEvent {
75
+ subsystem: string;
76
+ errorCode: string;
77
+ reason: {
78
+ redacted: string;
79
+ };
80
+ timestamp: number;
81
+ }
82
+ export interface NovelFailureProposal {
83
+ /** §A60: sha256(clusterSignature || windowStartMs || fleetScope). */
84
+ proposalId: string;
85
+ clusterSignature: string;
86
+ occurrencesObserved: number;
87
+ processLifetimes: number;
88
+ /** ≤ 3 redacted entries — §A26 raw-response redaction handled by writer. */
89
+ sampleEvents: SampleEvent[];
90
+ llmSummary: string;
91
+ suggestedErrorCode: string;
92
+ hypothesis: string;
93
+ /** §A32 — signed agent identity stamped on every proposal. */
94
+ producingAgentId: string;
95
+ producingAgentSignature: string;
96
+ generatedAt: number;
97
+ status: 'outstanding' | 'dismissed' | 'promoted';
98
+ /** §A10 forensic fields (prompt-hash, raw-response, model, generated-at). */
99
+ forensic: {
100
+ promptHash: string;
101
+ llmModel: string;
102
+ /** Redacted raw response. Pre-redaction copy lives in `llm-raw-*.jsonl`. */
103
+ rawResponse: string;
104
+ };
105
+ }
106
+ export type LlmCaller = (prompt: string) => Promise<string>;
107
+ export interface ObservabilityEvent {
108
+ event: string;
109
+ payload?: Record<string, unknown>;
110
+ }
111
+ export interface NovelFailureReviewerOpts {
112
+ stateDir: string;
113
+ auditProjection: AuditProjection;
114
+ llmCaller: LlmCaller;
115
+ keyVault: RemediationKeyVault;
116
+ /** Agent identity stamped on every proposal (§A32). */
117
+ agentId: string;
118
+ /** Machine id — disambiguates persistence files (§A47). */
119
+ machineId: string;
120
+ /** Fleet scope identifier for §A60 proposalId derivation. */
121
+ fleetScope?: string;
122
+ /** §A26 dismiss gate — when present, dismiss requires `collaborative`. */
123
+ trustSource?: TrustElevationSource;
124
+ /** Active runbook errorCodes for §A10 / §A26 collision rejection. */
125
+ getActiveRunbookErrorCodes?: () => ReadonlySet<string>;
126
+ /**
127
+ * Receives observability events synchronously. Production wires to the
128
+ * server's metrics sink; tests collect events for assertion.
129
+ */
130
+ onEvent?: (e: ObservabilityEvent) => void;
131
+ /** Optional `Date.now`-equivalent for deterministic tests. */
132
+ now?: () => number;
133
+ /** Process lifetime token — distinct restarts must use distinct values. */
134
+ processLifetimeToken?: string;
135
+ config?: Partial<NovelFailureReviewerConfig>;
136
+ }
137
+ export declare class NovelFailureReviewer {
138
+ private readonly opts;
139
+ private readonly cfg;
140
+ private readonly proposalDir;
141
+ private readonly countersPath;
142
+ private readonly spendPath;
143
+ private readonly rawLlmPath;
144
+ private readonly hmacKey;
145
+ private readonly proposalSigningKey;
146
+ /** In-memory mirror of the counters file. */
147
+ private counters;
148
+ /** LRU touch order — oldest first; mirrors `counters` membership. */
149
+ private lru;
150
+ constructor(opts: NovelFailureReviewerOpts);
151
+ /**
152
+ * Run one hourly tick. Reads unmatched audit entries, updates per-signature
153
+ * counters, and emits proposals for clusters crossing thresholds.
154
+ */
155
+ runTick(): Promise<{
156
+ clusters: number;
157
+ proposals: number;
158
+ }>;
159
+ /** Returns currently persisted proposals, sorted oldest-first. */
160
+ listProposals(): Promise<NovelFailureProposal[]>;
161
+ /**
162
+ * Mark a proposal dismissed. Requires `collaborative` trust via the
163
+ * injected TrustElevationSource (§A26).
164
+ */
165
+ dismissProposal(proposalId: string, principal: {
166
+ userId: string;
167
+ }): Promise<void>;
168
+ private emit;
169
+ /** Update an in-memory cluster counter; touches LRU. */
170
+ private touch;
171
+ private evictExpired;
172
+ private loadCounters;
173
+ private persistCounters;
174
+ private signCounters;
175
+ private computeProposalId;
176
+ private buildPrompt;
177
+ private buildProposal;
178
+ private persistProposal;
179
+ private canSpendLlm;
180
+ private recordLlmSpend;
181
+ private readMonthlySpend;
182
+ private appendRawLlmLog;
183
+ private gcRawLlmLog;
184
+ }
185
+ /**
186
+ * §A10 token-classed signature: paths → `<path>`, hex → `<hex>`,
187
+ * numbers → `<num>`. Collapses cardinality.
188
+ */
189
+ export declare function tokenClassify(s: string): string;
190
+ export declare function computeClusterSignature(e: AuditEntry): string;
191
+ interface ParsedLlmOutput {
192
+ summary: string;
193
+ suggestedErrorCode: string;
194
+ hypothesis: string;
195
+ }
196
+ /**
197
+ * Parse + sanitize LLM JSON output. Returns null when:
198
+ * - JSON parse fails
199
+ * - fields missing / wrong types
200
+ * - schema constraints violated AFTER sanitization
201
+ *
202
+ * Per §A10: URLs, code fences, and imperative-verb markers are stripped
203
+ * BEFORE schema enforcement. Length / regex constraints then enforced.
204
+ */
205
+ export declare function parseAndSanitizeLlmOutput(raw: string): ParsedLlmOutput | null;
206
+ /**
207
+ * §A10 — strip URLs, code fences, and imperative-verb markers from
208
+ * LLM-emitted free-text before persistence.
209
+ */
210
+ export declare function redactInjectionArtifacts(s: string): string;
211
+ export {};
212
+ //# sourceMappingURL=NovelFailureReviewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NovelFailureReviewer.d.ts","sourceRoot":"","sources":["../../src/remediation/NovelFailureReviewer.ts"],"names":[],"mappings":"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"}