@substrate-ai/core 0.20.6 → 0.20.8
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.
|
@@ -23,10 +23,15 @@ export interface RetryableEscalationsResult {
|
|
|
23
23
|
*
|
|
24
24
|
* Key format in the DB: `{storyKey}:{runId}`
|
|
25
25
|
*
|
|
26
|
+
* Scoping:
|
|
26
27
|
* - When `runId` is provided, only decisions whose key contains that runId
|
|
27
|
-
* are considered (AC5
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* are considered (AC5). The caller is explicit; no status filter is applied
|
|
29
|
+
* so a user can still inspect diagnoses from a terminal run by naming it.
|
|
30
|
+
* - When `runId` is omitted, the latest run whose `pipeline_runs.status` is
|
|
31
|
+
* NOT terminal (`failed` / `stopped`) is used. Terminal runs are abandoned
|
|
32
|
+
* or manually stopped — their per-story diagnoses are historical noise and
|
|
33
|
+
* would generate false-positive retry proposals for work that either
|
|
34
|
+
* shipped in a later run or will never be retried in that run's lifetime.
|
|
30
35
|
*
|
|
31
36
|
* @param adapter The database adapter
|
|
32
37
|
* @param runId Optional run ID to scope the query
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry-escalated.d.ts","sourceRoot":"","sources":["../../../src/persistence/queries/retry-escalated.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"retry-escalated.d.ts","sourceRoot":"","sources":["../../../src/persistence/queries/retry-escalated.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AA0BlD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,OAAO,EAAE,YAAY,EAAE,CAAA;CACxB;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,eAAe,EACxB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,0BAA0B,CAAC,CA8ErC"}
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { getDecisionsByCategory } from './decisions.js';
|
|
12
12
|
import { ESCALATION_DIAGNOSIS } from '../schemas/operational.js';
|
|
13
|
+
/**
|
|
14
|
+
* Pipeline-run statuses that make escalation-diagnosis decisions non-actionable.
|
|
15
|
+
* Runs in these states are terminated (abandoned / stopped manually) and their
|
|
16
|
+
* per-story escalations are historical noise — the work either shipped in a
|
|
17
|
+
* later run or was never going to be retried in this run's lifetime.
|
|
18
|
+
*/
|
|
19
|
+
const TERMINAL_RUN_STATUSES = ['failed', 'stopped'];
|
|
13
20
|
// ---------------------------------------------------------------------------
|
|
14
21
|
// Query
|
|
15
22
|
// ---------------------------------------------------------------------------
|
|
@@ -19,10 +26,15 @@ import { ESCALATION_DIAGNOSIS } from '../schemas/operational.js';
|
|
|
19
26
|
*
|
|
20
27
|
* Key format in the DB: `{storyKey}:{runId}`
|
|
21
28
|
*
|
|
29
|
+
* Scoping:
|
|
22
30
|
* - When `runId` is provided, only decisions whose key contains that runId
|
|
23
|
-
* are considered (AC5
|
|
24
|
-
*
|
|
25
|
-
*
|
|
31
|
+
* are considered (AC5). The caller is explicit; no status filter is applied
|
|
32
|
+
* so a user can still inspect diagnoses from a terminal run by naming it.
|
|
33
|
+
* - When `runId` is omitted, the latest run whose `pipeline_runs.status` is
|
|
34
|
+
* NOT terminal (`failed` / `stopped`) is used. Terminal runs are abandoned
|
|
35
|
+
* or manually stopped — their per-story diagnoses are historical noise and
|
|
36
|
+
* would generate false-positive retry proposals for work that either
|
|
37
|
+
* shipped in a later run or will never be retried in that run's lifetime.
|
|
26
38
|
*
|
|
27
39
|
* @param adapter The database adapter
|
|
28
40
|
* @param runId Optional run ID to scope the query
|
|
@@ -53,9 +65,21 @@ export async function getRetryableEscalations(adapter, runId) {
|
|
|
53
65
|
return result;
|
|
54
66
|
}
|
|
55
67
|
// Determine effective runId:
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
|
|
68
|
+
// - caller-supplied runId: honor it verbatim (explicit scoping)
|
|
69
|
+
// - omitted: walk decisions newest-first, pick the first whose referenced
|
|
70
|
+
// pipeline run is NOT in a terminal status
|
|
71
|
+
let effectiveRunId;
|
|
72
|
+
if (runId !== undefined) {
|
|
73
|
+
effectiveRunId = runId;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const candidateRunId = await pickLatestNonTerminalRunId(adapter, parsed);
|
|
77
|
+
if (candidateRunId === undefined) {
|
|
78
|
+
// All referenced runs are terminal (or missing) → no actionable retries.
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
effectiveRunId = candidateRunId;
|
|
82
|
+
}
|
|
59
83
|
// Deduplicate by storyKey: keep the last entry per storyKey (last write wins since the
|
|
60
84
|
// list is ordered by created_at ASC — later entries in the array are more recent).
|
|
61
85
|
const lastEntryByKey = new Map();
|
|
@@ -80,4 +104,47 @@ export async function getRetryableEscalations(adapter, runId) {
|
|
|
80
104
|
}
|
|
81
105
|
return result;
|
|
82
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Walk the parsed decision list newest-last (as supplied), map distinct runIds
|
|
109
|
+
* to their pipeline-run status, and return the runId of the newest decision
|
|
110
|
+
* whose run is NOT in a terminal status.
|
|
111
|
+
*
|
|
112
|
+
* Returns `undefined` when every referenced run is terminal or missing —
|
|
113
|
+
* signalling "nothing retryable" to the caller.
|
|
114
|
+
*
|
|
115
|
+
* The adapter query is a single SELECT against `pipeline_runs` restricted to
|
|
116
|
+
* the distinct runIds we actually care about; keeps the cost O(unique-runs)
|
|
117
|
+
* rather than O(decisions).
|
|
118
|
+
*/
|
|
119
|
+
async function pickLatestNonTerminalRunId(adapter, parsed) {
|
|
120
|
+
const uniqueRunIds = Array.from(new Set(parsed.map((p) => p.decisionRunId)));
|
|
121
|
+
if (uniqueRunIds.length === 0)
|
|
122
|
+
return undefined;
|
|
123
|
+
// Bulk-fetch statuses. Use OR chain rather than IN-clause for
|
|
124
|
+
// InMemoryDatabaseAdapter compatibility (its WHERE parser doesn't support IN).
|
|
125
|
+
const statusByRunId = new Map();
|
|
126
|
+
for (const id of uniqueRunIds) {
|
|
127
|
+
const rows = await adapter.query('SELECT id, status FROM pipeline_runs WHERE id = ?', [id]);
|
|
128
|
+
if (rows.length > 0 && rows[0]) {
|
|
129
|
+
statusByRunId.set(rows[0].id, rows[0].status);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Scan newest-last (parsed is ordered created_at ASC). Return the first
|
|
133
|
+
// (i.e. most-recent) entry whose run is NOT known-terminal.
|
|
134
|
+
//
|
|
135
|
+
// Treatment of missing runs: if a decision references a runId that has
|
|
136
|
+
// no `pipeline_runs` row at all (deleted, or never persisted because the
|
|
137
|
+
// pipeline ran without writing a run record), we *include* it. The filter's
|
|
138
|
+
// purpose is to skip KNOWN-abandoned runs; an unknown status is treated as
|
|
139
|
+
// "status available elsewhere or caller's choice" to preserve backward
|
|
140
|
+
// compatibility with callers that seed decisions without run rows.
|
|
141
|
+
for (let i = parsed.length - 1; i >= 0; i -= 1) {
|
|
142
|
+
const entry = parsed[i];
|
|
143
|
+
const status = statusByRunId.get(entry.decisionRunId);
|
|
144
|
+
if (status !== undefined && TERMINAL_RUN_STATUSES.includes(status))
|
|
145
|
+
continue;
|
|
146
|
+
return entry.decisionRunId;
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
83
150
|
//# sourceMappingURL=retry-escalated.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry-escalated.js","sourceRoot":"","sources":["../../../src/persistence/queries/retry-escalated.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"retry-escalated.js","sourceRoot":"","sources":["../../../src/persistence/queries/retry-escalated.ts"],"names":[],"mappings":"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"}
|