@@ -22,7 +22,7 @@ import {
2222 * tool. Consumers follow the agent execution's event stream and filter for this event to
2323 * receive live, schema-typed updates while the investigation is still running. Every emission
2424 * carries the FULL current investigation state (never a delta) — see
25- * {@link investigationAgentOutputSchema }.
25+ * {@link investigationStateSchema }.
2626 */
2727export const INVESTIGATION_PROGRESS_UI_EVENT = 'investigation_progress' as const ;
2828
@@ -144,21 +144,10 @@ export type InvestigationHypothesis = z.infer<typeof investigationHypothesisSche
144144/** Max recommendation entries a current investigation can emit. Keep in sync with YAML maxItems. */
145145export const MAX_RECOMMENDATIONS = 3 ;
146146
147- /** Historical recommendation limit retained by the read schema for persisted investigations. */
148- const MAX_LEGACY_RECOMMENDATIONS = 5 ;
149-
150147const investigationItemConfidenceSchema = z . number ( ) . min ( 0 ) . max ( 1 ) ;
151148
152- const sortByConfidence = < T extends { confidence ?: number } > ( items : T [ ] ) : T [ ] =>
153- [ ...items ] . sort ( ( first , second ) => {
154- if ( first . confidence === undefined ) {
155- return second . confidence === undefined ? 0 : 1 ;
156- }
157- if ( second . confidence === undefined ) {
158- return - 1 ;
159- }
160- return second . confidence - first . confidence ;
161- } ) ;
149+ const sortByConfidence = < T extends { confidence : number } > ( items : T [ ] ) : T [ ] =>
150+ [ ...items ] . sort ( ( first , second ) => second . confidence - first . confidence ) ;
162151
163152/**
164153 * One concrete, actionable step to resolve or mitigate the issue — a command, config change, or
@@ -169,7 +158,7 @@ export const investigationRecommendationSchema = z.object({
169158 /** The action itself, stated concretely (e.g. "Revert the pool-size config change"). */
170159 title : z . string ( ) . max ( MAX_MEDIUM_STRING_LENGTH ) ,
171160 /** How strongly the findings support that this action will resolve or mitigate the confirmed problem. */
172- confidence : investigationItemConfidenceSchema . optional ( ) ,
161+ confidence : investigationItemConfidenceSchema ,
173162 /** Why this step helps, or detail needed to carry it out, when the title alone isn't enough. */
174163 description : z . string ( ) . max ( MAX_TEXT_LENGTH ) . optional ( ) ,
175164 /** A command, config snippet, or code change backing this step, when one applies. Raw source,
@@ -178,24 +167,9 @@ export const investigationRecommendationSchema = z.object({
178167} ) ;
179168export type InvestigationRecommendation = z . infer < typeof investigationRecommendationSchema > ;
180169
181- const investigationRecommendationOutputSchema = investigationRecommendationSchema . required ( {
182- confidence : true ,
183- } ) ;
184- export type InvestigationRecommendationOutput = z . infer <
185- typeof investigationRecommendationOutputSchema
186- > ;
187-
188- export const investigationRecommendationsOutputSchema = z
189- . array ( investigationRecommendationOutputSchema )
190- . max ( MAX_RECOMMENDATIONS )
191- . overwrite ( sortByConfidence ) ;
192-
193170/** Max blind spot entries a current investigation can emit. Keep in sync with YAML maxItems. */
194171export const MAX_BLIND_SPOTS = 3 ;
195172
196- /** Historical blind spot limit retained by the read schema for persisted investigations. */
197- const MAX_LEGACY_BLIND_SPOTS = 10 ;
198-
199173/**
200174 * A signal the agent wanted but could not access (e.g. missing instrumentation) — an actionable
201175 * knowledge gap, not an incident-specific fact. Structured so consumers don't have to split a
@@ -205,22 +179,12 @@ export const investigationBlindSpotSchema = z.object({
205179 /** The missing data source or access, named concisely (e.g. "No traces for the cart service"). */
206180 title : z . string ( ) . max ( MAX_MEDIUM_STRING_LENGTH ) ,
207181 /** How strongly the findings support that closing this gap would materially improve the investigation. */
208- confidence : investigationItemConfidenceSchema . optional ( ) ,
182+ confidence : investigationItemConfidenceSchema ,
209183 /** Why this gap mattered to the investigation. */
210184 description : z . string ( ) . max ( MAX_TEXT_LENGTH ) ,
211185} ) ;
212186export type InvestigationBlindSpot = z . infer < typeof investigationBlindSpotSchema > ;
213187
214- const investigationBlindSpotOutputSchema = investigationBlindSpotSchema . required ( {
215- confidence : true ,
216- } ) ;
217- export type InvestigationBlindSpotOutput = z . infer < typeof investigationBlindSpotOutputSchema > ;
218-
219- export const investigationBlindSpotsOutputSchema = z
220- . array ( investigationBlindSpotOutputSchema )
221- . max ( MAX_BLIND_SPOTS )
222- . overwrite ( sortByConfidence ) ;
223-
224188/** Max evidence entries per trigger-feedback proposal. Keep in sync with the YAML maxItems. */
225189export const MAX_TRIGGER_FEEDBACK_EVIDENCE = 10 ;
226190
@@ -276,9 +240,7 @@ export type TriggerFeedback = z.infer<typeof triggerFeedbackSchema>;
276240export const MAX_HYPOTHESES = 50 ;
277241
278242/**
279- * Read-facing investigation state. It accepts historical unscored recommendations and blind spots
280- * at their original limits while ranking any scored items. Current agent output uses the stricter
281- * {@link investigationAgentOutputSchema}; both shapes render through this compatible state type.
243+ * Full investigation state shared by agent output, persistence, and consumers.
282244 */
283245export const investigationStateSchema = z . object ( {
284246 /** Current ("what's happening now") or final narrative summary of the investigation. */
@@ -312,21 +274,16 @@ export const investigationStateSchema = z.object({
312274 /** Concrete, actionable steps to resolve or mitigate the issue. */
313275 recommendations : z
314276 . array ( investigationRecommendationSchema )
315- . max ( MAX_LEGACY_RECOMMENDATIONS )
277+ . max ( MAX_RECOMMENDATIONS )
316278 . overwrite ( sortByConfidence )
317279 . optional ( ) ,
318280 /**
319- * Actionable knowledge gaps discovered during the investigation. Replaces the free-text
320- * `gaps_found` string array. Investigations persisted before this field existed still carry
321- * `gaps_found`, which this schema strips as a key it no longer declares — so recovering them
322- * means rewriting the raw payload before it reaches this schema, as
323- * `normalizeLegacyInvestigationState` in `@kbn/investigation-output` does. Those gaps are also
324- * folded into the memory `_gaps/overview` page by the workflow's `merge_investigation_gaps`
325- * step, so they survive outside this payload either way.
281+ * Actionable knowledge gaps discovered during the investigation. Replaces the legacy free-text
282+ * `gaps_found` string array, which this schema ignores.
326283 */
327284 blind_spots : z
328285 . array ( investigationBlindSpotSchema )
329- . max ( MAX_LEGACY_BLIND_SPOTS )
286+ . max ( MAX_BLIND_SPOTS )
330287 . overwrite ( sortByConfidence )
331288 . optional ( ) ,
332289 /**
@@ -345,10 +302,3 @@ export const investigationStateSchema = z.object({
345302 impact : investigationImpactSchema . optional ( ) ,
346303} ) ;
347304export type InvestigationState = z . infer < typeof investigationStateSchema > ;
348-
349- /** Strict state emitted by current agents; reads remain tolerant of historical unscored items. */
350- export const investigationAgentOutputSchema = investigationStateSchema . extend ( {
351- recommendations : investigationRecommendationsOutputSchema . optional ( ) ,
352- blind_spots : investigationBlindSpotsOutputSchema . optional ( ) ,
353- } ) ;
354- export type InvestigationAgentOutput = z . infer < typeof investigationAgentOutputSchema > ;
0 commit comments