@urateam/core 0.1.25 → 0.1.26
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/dist/__tests__/agent-stream-cache-tokens.test.d.ts +2 -0
- package/dist/__tests__/agent-stream-cache-tokens.test.d.ts.map +1 -0
- package/dist/__tests__/agent-stream-cache-tokens.test.js +25 -0
- package/dist/__tests__/agent-stream-cache-tokens.test.js.map +1 -0
- package/dist/__tests__/audit/pm-skipped-circuit-breaker-event.test.d.ts +2 -0
- package/dist/__tests__/audit/pm-skipped-circuit-breaker-event.test.d.ts.map +1 -0
- package/dist/__tests__/audit/pm-skipped-circuit-breaker-event.test.js +32 -0
- package/dist/__tests__/audit/pm-skipped-circuit-breaker-event.test.js.map +1 -0
- package/dist/__tests__/audit/review-model-low-output-ratio-event.test.d.ts +2 -0
- package/dist/__tests__/audit/review-model-low-output-ratio-event.test.d.ts.map +1 -0
- package/dist/__tests__/audit/review-model-low-output-ratio-event.test.js +23 -0
- package/dist/__tests__/audit/review-model-low-output-ratio-event.test.js.map +1 -0
- package/dist/__tests__/audit-immutability.test.js +2 -0
- package/dist/__tests__/audit-immutability.test.js.map +1 -1
- package/dist/__tests__/bec-181-circuit-breaker-audit-gap.test.d.ts +24 -0
- package/dist/__tests__/bec-181-circuit-breaker-audit-gap.test.d.ts.map +1 -0
- package/dist/__tests__/bec-181-circuit-breaker-audit-gap.test.js +253 -0
- package/dist/__tests__/bec-181-circuit-breaker-audit-gap.test.js.map +1 -0
- package/dist/__tests__/executor/review-feedback-profile-override.test.d.ts +2 -0
- package/dist/__tests__/executor/review-feedback-profile-override.test.d.ts.map +1 -0
- package/dist/__tests__/executor/review-feedback-profile-override.test.js +32 -0
- package/dist/__tests__/executor/review-feedback-profile-override.test.js.map +1 -0
- package/dist/__tests__/executor/review-feedback-prompt.test.d.ts +2 -0
- package/dist/__tests__/executor/review-feedback-prompt.test.d.ts.map +1 -0
- package/dist/__tests__/executor/review-feedback-prompt.test.js +29 -0
- package/dist/__tests__/executor/review-feedback-prompt.test.js.map +1 -0
- package/dist/__tests__/pipeline/pr-cost-summary.test.js +23 -0
- package/dist/__tests__/pipeline/pr-cost-summary.test.js.map +1 -1
- package/dist/__tests__/pm-circuit-breaker.test.js +86 -15
- package/dist/__tests__/pm-circuit-breaker.test.js.map +1 -1
- package/dist/__tests__/prune-worktrees-in-repo-dirs.test.d.ts +2 -0
- package/dist/__tests__/prune-worktrees-in-repo-dirs.test.d.ts.map +1 -0
- package/dist/__tests__/prune-worktrees-in-repo-dirs.test.js +64 -0
- package/dist/__tests__/prune-worktrees-in-repo-dirs.test.js.map +1 -0
- package/dist/__tests__/review/model-health.test.d.ts +2 -0
- package/dist/__tests__/review/model-health.test.d.ts.map +1 -0
- package/dist/__tests__/review/model-health.test.js +122 -0
- package/dist/__tests__/review/model-health.test.js.map +1 -0
- package/dist/__tests__/review-feedback.test.js +3 -2
- package/dist/__tests__/review-feedback.test.js.map +1 -1
- package/dist/__tests__/runner-ralph-feedback-skip.test.d.ts +2 -0
- package/dist/__tests__/runner-ralph-feedback-skip.test.d.ts.map +1 -0
- package/dist/__tests__/runner-ralph-feedback-skip.test.js +23 -0
- package/dist/__tests__/runner-ralph-feedback-skip.test.js.map +1 -0
- package/dist/__tests__/templates.test.js +4 -2
- package/dist/__tests__/templates.test.js.map +1 -1
- package/dist/__tests__/worktree-stale-recovery.test.js +11 -1
- package/dist/__tests__/worktree-stale-recovery.test.js.map +1 -1
- package/dist/audit/events.d.ts +12 -0
- package/dist/audit/events.d.ts.map +1 -1
- package/dist/audit/events.js +26 -0
- package/dist/audit/events.js.map +1 -1
- package/dist/db/migrations/postgres/013_stage_runs_cache_tokens.sql +6 -0
- package/dist/db/migrations/sqlite/012_stage_runs_cache_tokens.sql +6 -0
- package/dist/db/schema.d.ts +34 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +2 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/executor/agent-stream.d.ts +4 -0
- package/dist/executor/agent-stream.d.ts.map +1 -1
- package/dist/executor/agent-stream.js +5 -1
- package/dist/executor/agent-stream.js.map +1 -1
- package/dist/executor/executor.d.ts +9 -1
- package/dist/executor/executor.d.ts.map +1 -1
- package/dist/executor/executor.js +26 -4
- package/dist/executor/executor.js.map +1 -1
- package/dist/executor/prompt/templates.js +8 -8
- package/dist/executor/prompt/templates.js.map +1 -1
- package/dist/executor/review/model-health.d.ts +28 -0
- package/dist/executor/review/model-health.d.ts.map +1 -0
- package/dist/executor/review/model-health.js +64 -0
- package/dist/executor/review/model-health.js.map +1 -0
- package/dist/pipeline/cost-summary.d.ts +2 -0
- package/dist/pipeline/cost-summary.d.ts.map +1 -1
- package/dist/pipeline/cost-summary.js +18 -7
- package/dist/pipeline/cost-summary.js.map +1 -1
- package/dist/pipeline/review-providers-runner.d.ts.map +1 -1
- package/dist/pipeline/review-providers-runner.js +49 -0
- package/dist/pipeline/review-providers-runner.js.map +1 -1
- package/dist/pipeline/runner-ralph-helpers.d.ts +8 -0
- package/dist/pipeline/runner-ralph-helpers.d.ts.map +1 -0
- package/dist/pipeline/runner-ralph-helpers.js +15 -0
- package/dist/pipeline/runner-ralph-helpers.js.map +1 -0
- package/dist/pipeline/runner.d.ts +2 -2
- package/dist/pipeline/runner.d.ts.map +1 -1
- package/dist/pipeline/runner.js +10 -18
- package/dist/pipeline/runner.js.map +1 -1
- package/dist/pm/actions/db-queries.d.ts +11 -0
- package/dist/pm/actions/db-queries.d.ts.map +1 -1
- package/dist/pm/actions/db-queries.js +46 -0
- package/dist/pm/actions/db-queries.js.map +1 -1
- package/dist/pm/actions/promote.d.ts +5 -4
- package/dist/pm/actions/promote.d.ts.map +1 -1
- package/dist/pm/actions/promote.js +24 -4
- package/dist/pm/actions/promote.js.map +1 -1
- package/dist/pm/actions/start-todo.d.ts +4 -3
- package/dist/pm/actions/start-todo.d.ts.map +1 -1
- package/dist/pm/actions/start-todo.js +29 -8
- package/dist/pm/actions/start-todo.js.map +1 -1
- package/dist/pm/scheduler.d.ts.map +1 -1
- package/dist/pm/scheduler.js +6 -3
- package/dist/pm/scheduler.js.map +1 -1
- package/dist/repo/git.d.ts +27 -2
- package/dist/repo/git.d.ts.map +1 -1
- package/dist/repo/git.js +67 -8
- package/dist/repo/git.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AnyDb } from "../../db/client.js";
|
|
2
|
+
export interface ModelHealthScore {
|
|
3
|
+
runs: number;
|
|
4
|
+
outputRatio: number;
|
|
5
|
+
lastSeen: Date;
|
|
6
|
+
}
|
|
7
|
+
export interface HealthOptions {
|
|
8
|
+
lookbackHours: number;
|
|
9
|
+
minRuns: number;
|
|
10
|
+
}
|
|
11
|
+
export interface FlagOptions {
|
|
12
|
+
threshold: number;
|
|
13
|
+
minRuns: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Aggregate per-model health stats from review_model_runs over a rolling
|
|
17
|
+
* window. Only `status = 'completed'` runs contribute to the output-ratio
|
|
18
|
+
* computation — failed runs typically have zero in/out tokens and would
|
|
19
|
+
* dilute the signal.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getModelHealthScores(db: AnyDb, opts: HealthOptions): Promise<Map<string, ModelHealthScore>>;
|
|
22
|
+
/**
|
|
23
|
+
* Filter a list of model IDs down to those that look low-yield given the
|
|
24
|
+
* health scores. Models with insufficient data (`runs < minRuns`) are NOT
|
|
25
|
+
* flagged — we don't want a single bad-luck call to suspend a model.
|
|
26
|
+
*/
|
|
27
|
+
export declare function flagLowYieldModels(scores: Map<string, ModelHealthScore>, models: string[], opts: FlagOptions): string[];
|
|
28
|
+
//# sourceMappingURL=model-health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-health.d.ts","sourceRoot":"","sources":["../../../src/executor/review/model-health.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAGhD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,KAAK,EACT,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAuCxC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACrC,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,WAAW,GAChB,MAAM,EAAE,CASV"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { gte } from "drizzle-orm";
|
|
2
|
+
import { reviewModelRuns } from "../../db/schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Aggregate per-model health stats from review_model_runs over a rolling
|
|
5
|
+
* window. Only `status = 'completed'` runs contribute to the output-ratio
|
|
6
|
+
* computation — failed runs typically have zero in/out tokens and would
|
|
7
|
+
* dilute the signal.
|
|
8
|
+
*/
|
|
9
|
+
export async function getModelHealthScores(db, opts) {
|
|
10
|
+
const cutoff = new Date(Date.now() - opts.lookbackHours * 3600_000);
|
|
11
|
+
const rows = await db
|
|
12
|
+
.select({
|
|
13
|
+
modelId: reviewModelRuns.modelId,
|
|
14
|
+
inputTokens: reviewModelRuns.inputTokens,
|
|
15
|
+
outputTokens: reviewModelRuns.outputTokens,
|
|
16
|
+
startedAt: reviewModelRuns.startedAt,
|
|
17
|
+
status: reviewModelRuns.status,
|
|
18
|
+
})
|
|
19
|
+
.from(reviewModelRuns)
|
|
20
|
+
.where(gte(reviewModelRuns.startedAt, cutoff));
|
|
21
|
+
const acc = new Map();
|
|
22
|
+
for (const r of rows) {
|
|
23
|
+
if (r.status !== "completed")
|
|
24
|
+
continue;
|
|
25
|
+
const cur = acc.get(r.modelId) ?? {
|
|
26
|
+
runs: 0,
|
|
27
|
+
sumIn: 0,
|
|
28
|
+
sumOut: 0,
|
|
29
|
+
lastSeen: new Date(0),
|
|
30
|
+
};
|
|
31
|
+
cur.runs += 1;
|
|
32
|
+
cur.sumIn += r.inputTokens;
|
|
33
|
+
cur.sumOut += r.outputTokens;
|
|
34
|
+
if (r.startedAt && r.startedAt > cur.lastSeen)
|
|
35
|
+
cur.lastSeen = r.startedAt;
|
|
36
|
+
acc.set(r.modelId, cur);
|
|
37
|
+
}
|
|
38
|
+
const result = new Map();
|
|
39
|
+
for (const [modelId, v] of acc) {
|
|
40
|
+
const denom = v.sumIn + v.sumOut;
|
|
41
|
+
const outputRatio = denom > 0 ? v.sumOut / denom : 0;
|
|
42
|
+
result.set(modelId, { runs: v.runs, outputRatio, lastSeen: v.lastSeen });
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Filter a list of model IDs down to those that look low-yield given the
|
|
48
|
+
* health scores. Models with insufficient data (`runs < minRuns`) are NOT
|
|
49
|
+
* flagged — we don't want a single bad-luck call to suspend a model.
|
|
50
|
+
*/
|
|
51
|
+
export function flagLowYieldModels(scores, models, opts) {
|
|
52
|
+
const flagged = [];
|
|
53
|
+
for (const modelId of models) {
|
|
54
|
+
const s = scores.get(modelId);
|
|
55
|
+
if (!s)
|
|
56
|
+
continue;
|
|
57
|
+
if (s.runs < opts.minRuns)
|
|
58
|
+
continue;
|
|
59
|
+
if (s.outputRatio < opts.threshold)
|
|
60
|
+
flagged.push(modelId);
|
|
61
|
+
}
|
|
62
|
+
return flagged;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=model-health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-health.js","sourceRoot":"","sources":["../../../src/executor/review/model-health.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ export interface StageCostBreakdown {
|
|
|
3
3
|
stage: string;
|
|
4
4
|
inputTokens: number;
|
|
5
5
|
outputTokens: number;
|
|
6
|
+
cacheCreationInputTokens?: number;
|
|
7
|
+
cacheReadInputTokens?: number;
|
|
6
8
|
/** When present, per-model rows from the fanout review stage. */
|
|
7
9
|
modelRuns?: ModelRunRow[];
|
|
8
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost-summary.d.ts","sourceRoot":"","sources":["../../src/pipeline/cost-summary.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE;QACN,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,eAAe,EAAE,MAAM,CAAC;YAAC,gBAAgB,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACtF,CAAC;IACF,eAAe,CAAC,EAAE,MAAM,CACtB,MAAM,EACN;QACE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,OAAO,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC9B,CACF,CAAC;CACH;AA4DD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,EAAE,EAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,GACxB,MAAM,
|
|
1
|
+
{"version":3,"file":"cost-summary.d.ts","sourceRoot":"","sources":["../../src/pipeline/cost-summary.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iEAAiE;IACjE,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE;QACN,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,eAAe,EAAE,MAAM,CAAC;YAAC,gBAAgB,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACtF,CAAC;IACF,eAAe,CAAC,EAAE,MAAM,CACtB,MAAM,EACN;QACE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,OAAO,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC9B,CACF,CAAC;CACH;AA4DD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,EAAE,EAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,GACxB,MAAM,CAkCR"}
|
|
@@ -42,20 +42,31 @@ function renderStage(stage, pipelineKey, config) {
|
|
|
42
42
|
* report (caller should suppress the comment).
|
|
43
43
|
*/
|
|
44
44
|
export function formatPRCostSummary(stages, pipelineKey, config) {
|
|
45
|
-
const
|
|
46
|
-
.map((s) => renderStage(s, pipelineKey, config))
|
|
47
|
-
.filter((r) => r.inputTokens > 0 || r.outputTokens > 0);
|
|
48
|
-
if (
|
|
45
|
+
const pairs = stages
|
|
46
|
+
.map((s) => ({ stage: s, rendered: renderStage(s, pipelineKey, config) }))
|
|
47
|
+
.filter(({ rendered: r }) => r.inputTokens > 0 || r.outputTokens > 0);
|
|
48
|
+
if (pairs.length === 0)
|
|
49
49
|
return "";
|
|
50
|
+
const rendered = pairs.map(({ rendered: r }) => r);
|
|
50
51
|
const labelWidth = Math.max(...rendered.map((r) => r.label.length));
|
|
51
52
|
const inWidth = Math.max(...rendered.map((r) => fmt(r.inputTokens).length));
|
|
52
53
|
const outWidth = Math.max(...rendered.map((r) => fmt(r.outputTokens).length));
|
|
53
|
-
const lines =
|
|
54
|
+
const lines = [];
|
|
55
|
+
for (const { stage: s, rendered: r } of pairs) {
|
|
54
56
|
const labelPad = `${r.label}:`.padEnd(labelWidth + 1);
|
|
55
57
|
const inPad = fmt(r.inputTokens).padStart(inWidth);
|
|
56
58
|
const outPad = fmt(r.outputTokens).padStart(outWidth);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
lines.push(`- ${labelPad} ${inPad} in / ${outPad} out tokens — $${r.dollars.toFixed(4)}`);
|
|
60
|
+
const cacheRead = s.cacheReadInputTokens ?? 0;
|
|
61
|
+
const cacheCreation = s.cacheCreationInputTokens ?? 0;
|
|
62
|
+
if (cacheRead > 0 || cacheCreation > 0) {
|
|
63
|
+
const divisor = cacheRead + cacheCreation + s.inputTokens;
|
|
64
|
+
const pct = divisor > 0 ? Math.round((cacheRead / divisor) * 100) : 0;
|
|
65
|
+
const readK = (cacheRead / 1000).toFixed(1);
|
|
66
|
+
const createdK = (cacheCreation / 1000).toFixed(1);
|
|
67
|
+
lines.push(` cache hit: ${pct}% — read ${readK}K / created ${createdK}K`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
59
70
|
const totalDollars = rendered.reduce((a, r) => a + r.dollars, 0);
|
|
60
71
|
return [
|
|
61
72
|
"🤖 **Pipeline cost summary**",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost-summary.js","sourceRoot":"","sources":["../../src/pipeline/cost-summary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"cost-summary.js","sourceRoot":"","sources":["../../src/pipeline/cost-summary.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-providers-runner.d.ts","sourceRoot":"","sources":["../../src/pipeline/review-providers-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,uCAAuC,CAAC;AAE/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"review-providers-runner.d.ts","sourceRoot":"","sources":["../../src/pipeline/review-providers-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,uCAAuC,CAAC;AAE/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAmBjD,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,EAAE,EAAE,KAAK,CAAC;CACX;AAED,MAAM,WAAW,wBAAwB;IACvC,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,wBAAwB,CAAC,CA4FnC"}
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import { getEnabledProviders, } from "../executor/review/review-provider.js";
|
|
2
2
|
import { insertReviewModelRuns } from "../db/review-model-runs.js";
|
|
3
3
|
import { createLogger } from "../logger.js";
|
|
4
|
+
import { logAuditEventUnchecked } from "../audit/writer.js";
|
|
5
|
+
import { reviewModelLowOutputRatioEvent } from "../audit/events.js";
|
|
6
|
+
import { getModelHealthScores, flagLowYieldModels } from "../executor/review/model-health.js";
|
|
4
7
|
const log = createLogger({ component: "ReviewProvidersRunner" });
|
|
8
|
+
function parseFloatOr(envValue, fallback) {
|
|
9
|
+
if (!envValue)
|
|
10
|
+
return fallback;
|
|
11
|
+
const n = parseFloat(envValue);
|
|
12
|
+
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
13
|
+
}
|
|
14
|
+
function parseIntOr(envValue, fallback) {
|
|
15
|
+
if (!envValue)
|
|
16
|
+
return fallback;
|
|
17
|
+
const n = parseInt(envValue, 10);
|
|
18
|
+
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
19
|
+
}
|
|
5
20
|
/**
|
|
6
21
|
* Runs all enabled review providers in sequence and persists their per-model
|
|
7
22
|
* results to `review_model_runs` when a stage_run row id is provided.
|
|
@@ -21,6 +36,40 @@ const log = createLogger({ component: "ReviewProvidersRunner" });
|
|
|
21
36
|
export async function runReviewProviders(ctx, opts) {
|
|
22
37
|
const providers = getEnabledProviders(opts.env);
|
|
23
38
|
const allRuns = [];
|
|
39
|
+
// BEC-178 follow-up: low-yield review-model health check. Advisory only —
|
|
40
|
+
// emit a warn + audit event for models below threshold; operator removes
|
|
41
|
+
// from REVIEW_MODELS manually. Auto-suspend deliberately scoped out
|
|
42
|
+
// (transient outage feedback-loop risk).
|
|
43
|
+
const modelIds = (opts.env.REVIEW_MODELS ?? "")
|
|
44
|
+
.split(",")
|
|
45
|
+
.map((s) => s.trim())
|
|
46
|
+
.filter(Boolean);
|
|
47
|
+
const healthThreshold = parseFloatOr(process.env.REVIEW_MODELS_MIN_OUTPUT_RATIO, 0.05);
|
|
48
|
+
const healthLookbackHours = parseIntOr(process.env.REVIEW_MODELS_HEALTH_LOOKBACK_HOURS, 168);
|
|
49
|
+
const healthMinRuns = parseIntOr(process.env.REVIEW_MODELS_MIN_RUNS, 5);
|
|
50
|
+
try {
|
|
51
|
+
const scores = await getModelHealthScores(opts.db, {
|
|
52
|
+
lookbackHours: healthLookbackHours,
|
|
53
|
+
minRuns: healthMinRuns,
|
|
54
|
+
});
|
|
55
|
+
const flagged = flagLowYieldModels(scores, modelIds, {
|
|
56
|
+
threshold: healthThreshold,
|
|
57
|
+
minRuns: healthMinRuns,
|
|
58
|
+
});
|
|
59
|
+
for (const modelId of flagged) {
|
|
60
|
+
const s = scores.get(modelId);
|
|
61
|
+
log.warn({ modelId, outputRatio: s.outputRatio, runs: s.runs, threshold: healthThreshold }, `review model below output-ratio threshold — consider removing from REVIEW_MODELS`);
|
|
62
|
+
void logAuditEventUnchecked(opts.db, reviewModelLowOutputRatioEvent({
|
|
63
|
+
modelId,
|
|
64
|
+
outputRatio: s.outputRatio,
|
|
65
|
+
runs: s.runs,
|
|
66
|
+
threshold: healthThreshold,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
log.warn({ err }, "model-health probe failed — skipping flagging this tick");
|
|
72
|
+
}
|
|
24
73
|
for (const p of providers) {
|
|
25
74
|
try {
|
|
26
75
|
const runs = await p.runReview(ctx);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-providers-runner.js","sourceRoot":"","sources":["../../src/pipeline/review-providers-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAGpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"review-providers-runner.js","sourceRoot":"","sources":["../../src/pipeline/review-providers-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helper for RALPH iteration computation — extracted to enable unit testing
|
|
3
|
+
* without pulling in the full runner module. (BEC-182)
|
|
4
|
+
*/
|
|
5
|
+
export declare function computeEffectiveRalphIterations(run: {
|
|
6
|
+
runType?: string | null;
|
|
7
|
+
}, configIterations: number | undefined, hasDeepReviewLicense: boolean): number;
|
|
8
|
+
//# sourceMappingURL=runner-ralph-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner-ralph-helpers.d.ts","sourceRoot":"","sources":["../../src/pipeline/runner-ralph-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAChC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,oBAAoB,EAAE,OAAO,GAC5B,MAAM,CAOR"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helper for RALPH iteration computation — extracted to enable unit testing
|
|
3
|
+
* without pulling in the full runner module. (BEC-182)
|
|
4
|
+
*/
|
|
5
|
+
export function computeEffectiveRalphIterations(run, configIterations, hasDeepReviewLicense) {
|
|
6
|
+
// BEC-182: skip RALPH for review-feedback runs — RALPH re-evaluates against
|
|
7
|
+
// the original issue ACs but feedback work is bounded to the comments, not
|
|
8
|
+
// the full ACs. RALPH adds turn cost without value here.
|
|
9
|
+
if (run.runType === "review-feedback")
|
|
10
|
+
return 0;
|
|
11
|
+
if (hasDeepReviewLicense)
|
|
12
|
+
return configIterations ?? 2;
|
|
13
|
+
return Math.min(configIterations ?? 1, 1);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=runner-ralph-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner-ralph-helpers.js","sourceRoot":"","sources":["../../src/pipeline/runner-ralph-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,+BAA+B,CAC7C,GAAgC,EAChC,gBAAoC,EACpC,oBAA6B;IAE7B,4EAA4E;IAC5E,2EAA2E;IAC3E,yDAAyD;IACzD,IAAI,GAAG,CAAC,OAAO,KAAK,iBAAiB;QAAE,OAAO,CAAC,CAAC;IAChD,IAAI,oBAAoB;QAAE,OAAO,gBAAgB,IAAI,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -126,8 +126,8 @@ export declare class PipelineRunner {
|
|
|
126
126
|
recoverStuckRuns(): Promise<void>;
|
|
127
127
|
/**
|
|
128
128
|
* Run `git worktree prune` on every repository directory found under
|
|
129
|
-
* repoCloneDir.
|
|
130
|
-
*
|
|
129
|
+
* repoCloneDir. BEC-180: skips entries with no `.git/` (e.g. the BEC-174
|
|
130
|
+
* `.agent-sweep/` parent dir) so they don't produce noisy ERROR logs.
|
|
131
131
|
*/
|
|
132
132
|
private pruneAllWorktreeRefs;
|
|
133
133
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/pipeline/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EAEV,QAAQ,EAGR,cAAc,EAId,qBAAqB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,EAAE,EAAS,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/pipeline/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/pipeline/runner.js
CHANGED
|
@@ -4,6 +4,7 @@ import { executeStage } from "../executor/executor.js";
|
|
|
4
4
|
import { validateHandoff } from "../executor/validate.js";
|
|
5
5
|
import { isFeatureLicensed } from "../license.js";
|
|
6
6
|
import { checkRequirements, buildRalphContext } from "../executor/ralph.js";
|
|
7
|
+
import { computeEffectiveRalphIterations } from "./runner-ralph-helpers.js";
|
|
7
8
|
import { checkTestQuality } from "../executor/test-quality.js";
|
|
8
9
|
import { buildDeepReviewContext } from "../executor/deep-review.js";
|
|
9
10
|
import { runReviewProviders } from "./review-providers-runner.js";
|
|
@@ -11,13 +12,13 @@ import { postFanoutCommentsToPR } from "../executor/review/post-fanout-comments.
|
|
|
11
12
|
import { extractHandoff } from "../executor/extract-handoff.js";
|
|
12
13
|
import { DEFAULT_AGENT_CLAUDE_MD } from "../executor/agent-config.js";
|
|
13
14
|
import { generatePRDescription } from "./pr-description.js";
|
|
14
|
-
import { access,
|
|
15
|
+
import { access, writeFile, appendFile } from "node:fs/promises";
|
|
15
16
|
import { join, resolve } from "node:path";
|
|
16
17
|
import { homedir } from "node:os";
|
|
17
18
|
import { execFile as execFileCb } from "node:child_process";
|
|
18
19
|
import { promisify } from "node:util";
|
|
19
20
|
const execFileAsync = promisify(execFileCb);
|
|
20
|
-
import { cloneRepo, createWorktree, deleteWorktree, pushBranch, pushBranchForce, choosePushStrategy, rebaseBranch, abortRebase, autoCommitChanges, getAgentCommits, createPRViaCli, mergePRViaCli, getDiffLineCount, getChangedFiles, checkDuplicateBranch, branchName,
|
|
21
|
+
import { cloneRepo, createWorktree, deleteWorktree, pushBranch, pushBranchForce, choosePushStrategy, rebaseBranch, abortRebase, autoCommitChanges, getAgentCommits, createPRViaCli, mergePRViaCli, getDiffLineCount, getChangedFiles, checkDuplicateBranch, branchName, createWorktreeFromRemote, pruneWorktreesInRepoDirs, } from "../repo/git.js";
|
|
21
22
|
import { addPRComment, createGitHubClient, createPR, prHasCommentStartingWith, rerequestPRReview, } from "../repo/github.js";
|
|
22
23
|
import { createMR, buildAuthenticatedUrl, } from "../repo/gitlab.js";
|
|
23
24
|
import { parseRepoUrl, parseGitLabUrl } from "../repo/config.js";
|
|
@@ -386,6 +387,7 @@ export class PipelineRunner {
|
|
|
386
387
|
});
|
|
387
388
|
const run = this.buildPipelineRun(runId, issue, pipelineKey, repoConfig, branch);
|
|
388
389
|
run.prUrl = prUrl;
|
|
390
|
+
run.runType = "review-feedback";
|
|
389
391
|
// Register in activeFeedbackRuns BEFORE enqueue so rate-limit check works
|
|
390
392
|
this.activeFeedbackRuns.set(prUrl, runId);
|
|
391
393
|
this.queue
|
|
@@ -552,9 +554,7 @@ export class PipelineRunner {
|
|
|
552
554
|
// don't waste time hunting for a non-existent failed requirement.
|
|
553
555
|
let ralphEvaluationFailed = false;
|
|
554
556
|
let ralphEvaluationError;
|
|
555
|
-
const effectiveRalphIterations = isFeatureLicensed("deep-review")
|
|
556
|
-
? config.ralphIterations ?? 2
|
|
557
|
-
: Math.min(config.ralphIterations ?? 1, 1);
|
|
557
|
+
const effectiveRalphIterations = computeEffectiveRalphIterations(run, config.ralphIterations, isFeatureLicensed("deep-review"));
|
|
558
558
|
const ralphIterations = effectiveRalphIterations;
|
|
559
559
|
// Execute each stage
|
|
560
560
|
runLog.info({ stages: stagesToRun }, "starting pipeline stages");
|
|
@@ -1707,6 +1707,8 @@ export class PipelineRunner {
|
|
|
1707
1707
|
stage: s.stage,
|
|
1708
1708
|
inputTokens: s.inputTokens,
|
|
1709
1709
|
outputTokens: s.outputTokens,
|
|
1710
|
+
cacheCreationInputTokens: s.cacheCreationInputTokens ?? 0,
|
|
1711
|
+
cacheReadInputTokens: s.cacheReadInputTokens ?? 0,
|
|
1710
1712
|
modelRuns: modelsByStage.get(s.id),
|
|
1711
1713
|
}));
|
|
1712
1714
|
const body = formatPRCostSummary(breakdown, run.pipelineKey, {
|
|
@@ -1927,21 +1929,11 @@ export class PipelineRunner {
|
|
|
1927
1929
|
}
|
|
1928
1930
|
/**
|
|
1929
1931
|
* Run `git worktree prune` on every repository directory found under
|
|
1930
|
-
* repoCloneDir.
|
|
1931
|
-
*
|
|
1932
|
+
* repoCloneDir. BEC-180: skips entries with no `.git/` (e.g. the BEC-174
|
|
1933
|
+
* `.agent-sweep/` parent dir) so they don't produce noisy ERROR logs.
|
|
1932
1934
|
*/
|
|
1933
1935
|
async pruneAllWorktreeRefs() {
|
|
1934
|
-
|
|
1935
|
-
try {
|
|
1936
|
-
entries = await readdir(this.repoCloneDir);
|
|
1937
|
-
}
|
|
1938
|
-
catch {
|
|
1939
|
-
// repoCloneDir does not exist yet — nothing to prune.
|
|
1940
|
-
return;
|
|
1941
|
-
}
|
|
1942
|
-
await Promise.all(entries.map((entry) =>
|
|
1943
|
-
// gitExecSafe returns "" on error, so non-git directories are harmless.
|
|
1944
|
-
gitExecSafe(["worktree", "prune"], join(this.repoCloneDir, entry))));
|
|
1936
|
+
await pruneWorktreesInRepoDirs(this.repoCloneDir);
|
|
1945
1937
|
}
|
|
1946
1938
|
/**
|
|
1947
1939
|
* Query the DB for all runs on a given date and emit a DailyTokenSummary
|