@urateam/core 0.1.35 → 0.1.37
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__/auto-deep-review.test.d.ts +2 -0
- package/dist/__tests__/auto-deep-review.test.d.ts.map +1 -0
- package/dist/__tests__/auto-deep-review.test.js +250 -0
- package/dist/__tests__/auto-deep-review.test.js.map +1 -0
- package/dist/__tests__/bec-181-circuit-breaker-audit-gap.test.js +16 -8
- package/dist/__tests__/bec-181-circuit-breaker-audit-gap.test.js.map +1 -1
- package/dist/__tests__/pm-escalation.test.d.ts +2 -0
- package/dist/__tests__/pm-escalation.test.d.ts.map +1 -0
- package/dist/__tests__/pm-escalation.test.js +273 -0
- package/dist/__tests__/pm-escalation.test.js.map +1 -0
- package/dist/__tests__/pm-triage-design-doc.test.d.ts +2 -0
- package/dist/__tests__/pm-triage-design-doc.test.d.ts.map +1 -0
- package/dist/__tests__/pm-triage-design-doc.test.js +226 -0
- package/dist/__tests__/pm-triage-design-doc.test.js.map +1 -0
- package/dist/audit/events.d.ts +34 -0
- package/dist/audit/events.d.ts.map +1 -1
- package/dist/audit/events.js +42 -0
- package/dist/audit/events.js.map +1 -1
- package/dist/pipeline/auto-deep-review.d.ts +70 -0
- package/dist/pipeline/auto-deep-review.d.ts.map +1 -0
- package/dist/pipeline/auto-deep-review.js +86 -0
- package/dist/pipeline/auto-deep-review.js.map +1 -0
- package/dist/pipeline/runner.d.ts.map +1 -1
- package/dist/pipeline/runner.js +71 -8
- 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 +23 -0
- package/dist/pm/actions/db-queries.js.map +1 -1
- package/dist/pm/actions/promote.d.ts +21 -0
- package/dist/pm/actions/promote.d.ts.map +1 -1
- package/dist/pm/actions/promote.js +113 -3
- package/dist/pm/actions/promote.js.map +1 -1
- package/dist/pm/actions/triage.d.ts.map +1 -1
- package/dist/pm/actions/triage.js +78 -7
- package/dist/pm/actions/triage.js.map +1 -1
- package/dist/pm/types.d.ts +10 -0
- package/dist/pm/types.d.ts.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +32 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-deep-review.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/auto-deep-review.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 3 — auto-deep-review thresholds.
|
|
3
|
+
*
|
|
4
|
+
* Promotes the deep-review fanout (`deepReviewPasses`) from opt-in to default
|
|
5
|
+
* for PRs above heuristic thresholds. The decision logic is a pure function
|
|
6
|
+
* so the existing runner integration tests don't need new mocking
|
|
7
|
+
* scaffolding — Tier 3 only changes the value passed to the existing deep-
|
|
8
|
+
* review loop.
|
|
9
|
+
*
|
|
10
|
+
* Three thresholds (any one trips):
|
|
11
|
+
* • newFiles ≥ N — heuristic for "non-trivial" diff
|
|
12
|
+
* • totalLines ≥ N — measures actual diff size
|
|
13
|
+
* • newPublicExports ≥ N — surface-area changes (new functions/types)
|
|
14
|
+
*
|
|
15
|
+
* Defaults: { changedFiles: 5, totalLines: 200, newPublicExports: 2 }.
|
|
16
|
+
*
|
|
17
|
+
* Two escape hatches:
|
|
18
|
+
* 1. `URATEAM_DISABLE_AUTO_DEEP_REVIEW=true` short-circuits the heuristic.
|
|
19
|
+
* 2. Per-pipeline `autoDeepReviewThresholds: { changedFiles: 999999, ... }`
|
|
20
|
+
* effectively raises the bar to disable.
|
|
21
|
+
*
|
|
22
|
+
* Deep-review findings are blocking-by-default (Tier 3 design); the
|
|
23
|
+
* existing review-fix loop already escalates blocking findings, so the
|
|
24
|
+
* runner wires `deepReviewFindingsAreBlocking` into a follow-up flag the
|
|
25
|
+
* deep-review loop already supports.
|
|
26
|
+
*/
|
|
27
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
28
|
+
import { countNewPublicExports, shouldAutoDeepReview, DEFAULT_AUTO_DEEP_REVIEW_THRESHOLDS, } from "../pipeline/auto-deep-review.js";
|
|
29
|
+
describe("countNewPublicExports — parses diff for added `^export ...` lines", () => {
|
|
30
|
+
it("counts a single added function export", () => {
|
|
31
|
+
const diff = `
|
|
32
|
+
diff --git a/packages/core/src/util/x.ts b/packages/core/src/util/x.ts
|
|
33
|
+
index 0000000..1111111 100644
|
|
34
|
+
--- a/packages/core/src/util/x.ts
|
|
35
|
+
+++ b/packages/core/src/util/x.ts
|
|
36
|
+
@@ -0,0 +1,3 @@
|
|
37
|
+
+export function foo() {
|
|
38
|
+
+ return 1;
|
|
39
|
+
+}
|
|
40
|
+
`;
|
|
41
|
+
expect(countNewPublicExports(diff)).toBe(1);
|
|
42
|
+
});
|
|
43
|
+
it("counts class, const, let, interface, type, enum exports — but not import-style", () => {
|
|
44
|
+
const diff = `
|
|
45
|
+
+++ b/packages/core/src/a.ts
|
|
46
|
+
@@ -0,0 +1,8 @@
|
|
47
|
+
+export class A {}
|
|
48
|
+
+export const b = 1;
|
|
49
|
+
+export let c = 2;
|
|
50
|
+
+export interface D {}
|
|
51
|
+
+export type E = string;
|
|
52
|
+
+export enum F { x }
|
|
53
|
+
+export async function g() {}
|
|
54
|
+
+import { something } from './x';
|
|
55
|
+
`;
|
|
56
|
+
expect(countNewPublicExports(diff)).toBe(7);
|
|
57
|
+
});
|
|
58
|
+
it("excludes deletions (lines starting with `-export ...`)", () => {
|
|
59
|
+
const diff = `
|
|
60
|
+
+++ b/packages/core/src/a.ts
|
|
61
|
+
@@ -1,4 +1,2 @@
|
|
62
|
+
-export function gone() {}
|
|
63
|
+
-export const old = 1;
|
|
64
|
+
+export function kept() {}
|
|
65
|
+
`;
|
|
66
|
+
expect(countNewPublicExports(diff)).toBe(1);
|
|
67
|
+
});
|
|
68
|
+
it("ignores context lines that happen to start with `export`", () => {
|
|
69
|
+
// Context lines start with a single space in unified diff; `+export` is
|
|
70
|
+
// added, `export` (no `+`) is context.
|
|
71
|
+
const diff = `
|
|
72
|
+
+++ b/packages/core/src/a.ts
|
|
73
|
+
@@ -1,3 +1,3 @@
|
|
74
|
+
export function unchanged() {
|
|
75
|
+
return 1;
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
expect(countNewPublicExports(diff)).toBe(0);
|
|
79
|
+
});
|
|
80
|
+
it("only counts paths under packages/*/src/ — excludes tests and docs", () => {
|
|
81
|
+
const diff = `
|
|
82
|
+
+++ b/packages/core/src/foo.ts
|
|
83
|
+
@@ -0,0 +1,1 @@
|
|
84
|
+
+export function inSrc() {}
|
|
85
|
+
+++ b/packages/core/src/__tests__/foo.test.ts
|
|
86
|
+
@@ -0,0 +1,1 @@
|
|
87
|
+
+export function inTests() {}
|
|
88
|
+
+++ b/docs/foo.md
|
|
89
|
+
@@ -0,0 +1,1 @@
|
|
90
|
+
+export function inDocs() {}
|
|
91
|
+
+++ b/scripts/x.ts
|
|
92
|
+
@@ -0,0 +1,1 @@
|
|
93
|
+
+export function inScripts() {}
|
|
94
|
+
`;
|
|
95
|
+
expect(countNewPublicExports(diff)).toBe(1);
|
|
96
|
+
});
|
|
97
|
+
it("returns 0 for an empty diff", () => {
|
|
98
|
+
expect(countNewPublicExports("")).toBe(0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe("shouldAutoDeepReview — fires when any threshold trips", () => {
|
|
102
|
+
const ENV_KEY = "URATEAM_DISABLE_AUTO_DEEP_REVIEW";
|
|
103
|
+
beforeEach(() => {
|
|
104
|
+
delete process.env[ENV_KEY];
|
|
105
|
+
});
|
|
106
|
+
afterEach(() => {
|
|
107
|
+
delete process.env[ENV_KEY];
|
|
108
|
+
});
|
|
109
|
+
it("trips on changedFiles >= threshold (5 by default)", () => {
|
|
110
|
+
expect(shouldAutoDeepReview({
|
|
111
|
+
changedFiles: 5,
|
|
112
|
+
totalLines: 0,
|
|
113
|
+
newPublicExports: 0,
|
|
114
|
+
})).toBe(true);
|
|
115
|
+
expect(shouldAutoDeepReview({
|
|
116
|
+
changedFiles: 4,
|
|
117
|
+
totalLines: 0,
|
|
118
|
+
newPublicExports: 0,
|
|
119
|
+
})).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
it("trips on totalLines >= threshold (200 by default)", () => {
|
|
122
|
+
expect(shouldAutoDeepReview({
|
|
123
|
+
changedFiles: 0,
|
|
124
|
+
totalLines: 200,
|
|
125
|
+
newPublicExports: 0,
|
|
126
|
+
})).toBe(true);
|
|
127
|
+
expect(shouldAutoDeepReview({
|
|
128
|
+
changedFiles: 0,
|
|
129
|
+
totalLines: 199,
|
|
130
|
+
newPublicExports: 0,
|
|
131
|
+
})).toBe(false);
|
|
132
|
+
});
|
|
133
|
+
it("trips on newPublicExports >= threshold (2 by default)", () => {
|
|
134
|
+
expect(shouldAutoDeepReview({
|
|
135
|
+
changedFiles: 0,
|
|
136
|
+
totalLines: 0,
|
|
137
|
+
newPublicExports: 2,
|
|
138
|
+
})).toBe(true);
|
|
139
|
+
expect(shouldAutoDeepReview({
|
|
140
|
+
changedFiles: 0,
|
|
141
|
+
totalLines: 0,
|
|
142
|
+
newPublicExports: 1,
|
|
143
|
+
})).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
it("does NOT trip on a clean diff (all below threshold)", () => {
|
|
146
|
+
expect(shouldAutoDeepReview({
|
|
147
|
+
changedFiles: 1,
|
|
148
|
+
totalLines: 10,
|
|
149
|
+
newPublicExports: 0,
|
|
150
|
+
})).toBe(false);
|
|
151
|
+
});
|
|
152
|
+
it("honors per-pipeline threshold overrides (e.g. set to 999999 to disable)", () => {
|
|
153
|
+
expect(shouldAutoDeepReview({ changedFiles: 100, totalLines: 10_000, newPublicExports: 100 }, { changedFiles: 999_999, totalLines: 999_999, newPublicExports: 999_999 })).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
it("URATEAM_DISABLE_AUTO_DEEP_REVIEW=true short-circuits the heuristic", () => {
|
|
156
|
+
process.env[ENV_KEY] = "true";
|
|
157
|
+
expect(shouldAutoDeepReview({
|
|
158
|
+
changedFiles: 1000,
|
|
159
|
+
totalLines: 1_000_000,
|
|
160
|
+
newPublicExports: 1000,
|
|
161
|
+
})).toBe(false);
|
|
162
|
+
});
|
|
163
|
+
it("env-var values other than 'true' do NOT disable", () => {
|
|
164
|
+
for (const v of ["false", "0", "", "yes", "1"]) {
|
|
165
|
+
process.env[ENV_KEY] = v;
|
|
166
|
+
expect(shouldAutoDeepReview({
|
|
167
|
+
changedFiles: 5,
|
|
168
|
+
totalLines: 0,
|
|
169
|
+
newPublicExports: 0,
|
|
170
|
+
}), `env=${v}`).toBe(true);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
describe("DEFAULT_AUTO_DEEP_REVIEW_THRESHOLDS — matches the operator brief", () => {
|
|
175
|
+
it("has the documented defaults", () => {
|
|
176
|
+
expect(DEFAULT_AUTO_DEEP_REVIEW_THRESHOLDS).toEqual({
|
|
177
|
+
changedFiles: 5,
|
|
178
|
+
totalLines: 200,
|
|
179
|
+
newPublicExports: 2,
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
describe("countNewPublicExports — handles export-default, named re-exports, wildcard re-exports", () => {
|
|
184
|
+
it("counts `export default function`", () => {
|
|
185
|
+
const diff = `
|
|
186
|
+
+++ b/packages/core/src/a.ts
|
|
187
|
+
@@ -0,0 +1,2 @@
|
|
188
|
+
+export default function foo() {}
|
|
189
|
+
`;
|
|
190
|
+
expect(countNewPublicExports(diff)).toBe(1);
|
|
191
|
+
});
|
|
192
|
+
it("counts `export default class`", () => {
|
|
193
|
+
const diff = `
|
|
194
|
+
+++ b/packages/core/src/a.ts
|
|
195
|
+
@@ -0,0 +1,2 @@
|
|
196
|
+
+export default class Foo {}
|
|
197
|
+
`;
|
|
198
|
+
expect(countNewPublicExports(diff)).toBe(1);
|
|
199
|
+
});
|
|
200
|
+
it("counts `export { foo, bar }` named re-exports", () => {
|
|
201
|
+
const diff = `
|
|
202
|
+
+++ b/packages/core/src/index.ts
|
|
203
|
+
@@ -0,0 +1,1 @@
|
|
204
|
+
+export { foo, bar } from './x';
|
|
205
|
+
`;
|
|
206
|
+
expect(countNewPublicExports(diff)).toBe(1);
|
|
207
|
+
});
|
|
208
|
+
it("counts `export *` wildcard re-exports", () => {
|
|
209
|
+
const diff = `
|
|
210
|
+
+++ b/packages/core/src/index.ts
|
|
211
|
+
@@ -0,0 +1,1 @@
|
|
212
|
+
+export * from './x';
|
|
213
|
+
`;
|
|
214
|
+
expect(countNewPublicExports(diff)).toBe(1);
|
|
215
|
+
});
|
|
216
|
+
it("counts exports under repo-root `src/` (non-monorepo deployments)", () => {
|
|
217
|
+
const diff = `
|
|
218
|
+
+++ b/src/a.ts
|
|
219
|
+
@@ -0,0 +1,1 @@
|
|
220
|
+
+export function foo() {}
|
|
221
|
+
`;
|
|
222
|
+
expect(countNewPublicExports(diff)).toBe(1);
|
|
223
|
+
});
|
|
224
|
+
it("excludes `src/__tests__/` even at repo root", () => {
|
|
225
|
+
const diff = `
|
|
226
|
+
+++ b/src/__tests__/foo.test.ts
|
|
227
|
+
@@ -0,0 +1,1 @@
|
|
228
|
+
+export function notRealSurface() {}
|
|
229
|
+
`;
|
|
230
|
+
expect(countNewPublicExports(diff)).toBe(0);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
describe("deepReviewFindingsAreBlocking — explicit-false preserves original severity (BC contract)", () => {
|
|
234
|
+
// This contract is the runner-side wiring at runner.ts ~1733. The pure
|
|
235
|
+
// matcher here doesn't touch severity directly, but Tier 3's BC promise is:
|
|
236
|
+
// setting `deepReviewFindingsAreBlocking: false` restores the pre-Tier-3
|
|
237
|
+
// advisory behavior for operators with existing `deepReviewPasses: 1`
|
|
238
|
+
// configs. The runner test for this is covered by the existing deep-review
|
|
239
|
+
// integration suite; this stub documents the contract for future readers.
|
|
240
|
+
it("documents the contract — see runner.ts:1733 for the upgrade logic", () => {
|
|
241
|
+
// The flag default is `config.deepReviewFindingsAreBlocking ?? true`.
|
|
242
|
+
// When false: deepResult.findings flow through with their original
|
|
243
|
+
// severity (.warning / .suggestion / .blocking unchanged).
|
|
244
|
+
// When true (default): all findings are upgraded to "blocking".
|
|
245
|
+
// The schema field is documented in `PipelineConfigSchema` (types.ts)
|
|
246
|
+
// with the breaking-change note in the JSDoc.
|
|
247
|
+
expect(true).toBe(true);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
//# sourceMappingURL=auto-deep-review.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-deep-review.test.js","sourceRoot":"","sources":["../../src/__tests__/auto-deep-review.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -139,18 +139,26 @@ async function assertPromoteBreakerSkip(opts) {
|
|
|
139
139
|
expect(results[0].promoted).toBe(false);
|
|
140
140
|
expect(results[0].reason).toMatch(/circuit.breaker/i);
|
|
141
141
|
expect(results[0].reason).toContain(`${opts.failureCount} consecutive failed runs`);
|
|
142
|
-
|
|
142
|
+
// Tier 5 escalation: when the issue is NOT already labeled `needs-design`,
|
|
143
|
+
// promoteReadyIssues now attempts to label-update the issue and post a
|
|
144
|
+
// Linear comment (the side effects of escalation). The fixture above
|
|
145
|
+
// doesn't include `issueLabels` on the client, so the escalation's label
|
|
146
|
+
// lookup fails — but `createComment` is still called (defensive path).
|
|
147
|
+
// For BEC-181's contract verification we only assert that the circuit
|
|
148
|
+
// breaker still fires before conflict detection.
|
|
143
149
|
// Breaker fires before conflict detection (saves tokens)
|
|
144
150
|
expect(conflictChecker).not.toHaveBeenCalled();
|
|
145
151
|
await flushFireAndForget();
|
|
146
|
-
// Audit
|
|
152
|
+
// Audit events: at minimum `pm.skipped_circuit_breaker` (BEC-181's
|
|
153
|
+
// contract) — Tier 5 may additionally emit `pm.escalated_to_needs_design`
|
|
154
|
+
// when the issue isn't already escalated. Both are expected after Tier 5.
|
|
147
155
|
const auditRows = await db.select().from(auditEvents);
|
|
148
|
-
|
|
149
|
-
expect(
|
|
150
|
-
expect(
|
|
151
|
-
expect(JSON.parse(
|
|
152
|
-
expect(JSON.parse(
|
|
153
|
-
expect(JSON.parse(
|
|
156
|
+
const breakerEvents = auditRows.filter((r) => r.eventType === "pm.skipped_circuit_breaker");
|
|
157
|
+
expect(breakerEvents).toHaveLength(1);
|
|
158
|
+
expect(breakerEvents[0].issueId).toBe(opts.issueId);
|
|
159
|
+
expect(JSON.parse(breakerEvents[0].payload).failureCount).toBe(opts.failureCount);
|
|
160
|
+
expect(JSON.parse(breakerEvents[0].payload).threshold).toBe(opts.threshold);
|
|
161
|
+
expect(JSON.parse(breakerEvents[0].payload).source).toBe("promote");
|
|
154
162
|
}
|
|
155
163
|
describe("BEC-181 Part 2: promoteReadyIssues circuit-breaker skip (working correctly)", () => {
|
|
156
164
|
it("skips promotion for issue with 4 consecutive failures and writes a pm.skipped_circuit_breaker audit event (fix verified)", () => assertPromoteBreakerSkip({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bec-181-circuit-breaker-audit-gap.test.js","sourceRoot":"","sources":["../../src/__tests__/bec-181-circuit-breaker-audit-gap.test.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"bec-181-circuit-breaker-audit-gap.test.js","sourceRoot":"","sources":["../../src/__tests__/bec-181-circuit-breaker-audit-gap.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pm-escalation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pm-escalation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 5 — escalation on consecutive failures.
|
|
3
|
+
*
|
|
4
|
+
* When the circuit breaker fires (≥ maxConsecutiveFailures failed runs in
|
|
5
|
+
* a row), the PM Agent escalates by:
|
|
6
|
+
* 1. Adding the `needs-design` label to the Linear issue (preserving
|
|
7
|
+
* existing labels)
|
|
8
|
+
* 2. Posting a Linear comment with the last failure's error message
|
|
9
|
+
* 3. Invoking the operator-supplied `slackPostAlert` callback
|
|
10
|
+
* 4. Emitting a `pm.escalated_to_needs_design` audit event
|
|
11
|
+
*
|
|
12
|
+
* Subsequent ticks find the `needs-design` label already in place and
|
|
13
|
+
* skip the escalation (the circuit-breaker event still fires for
|
|
14
|
+
* observability).
|
|
15
|
+
*/
|
|
16
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
17
|
+
import { promoteReadyIssues } from "../pm/actions/promote.js";
|
|
18
|
+
function mockLinearClient(issues) {
|
|
19
|
+
const updateIssue = vi.fn().mockResolvedValue({ success: true });
|
|
20
|
+
const createComment = vi.fn().mockResolvedValue({ success: true });
|
|
21
|
+
const issueLabels = vi.fn().mockResolvedValue({
|
|
22
|
+
nodes: [
|
|
23
|
+
{ id: "lbl_auto", name: "auto-implement" },
|
|
24
|
+
{ id: "lbl_bug", name: "bug" },
|
|
25
|
+
{ id: "lbl_nd", name: "needs-design" },
|
|
26
|
+
],
|
|
27
|
+
});
|
|
28
|
+
const wrappedIssues = issues.map((i) => ({
|
|
29
|
+
...i,
|
|
30
|
+
team: Promise.resolve(i.team),
|
|
31
|
+
state: Promise.resolve({ name: "Backlog" }),
|
|
32
|
+
labels: () => Promise.resolve({ nodes: i.labels }),
|
|
33
|
+
}));
|
|
34
|
+
return {
|
|
35
|
+
issues: vi.fn().mockResolvedValue({ nodes: wrappedIssues }),
|
|
36
|
+
issueLabels,
|
|
37
|
+
updateIssue,
|
|
38
|
+
createComment,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const failingIssue = {
|
|
42
|
+
id: "iss_fail",
|
|
43
|
+
identifier: "BEC-700",
|
|
44
|
+
title: "Some broken feature",
|
|
45
|
+
description: "...",
|
|
46
|
+
priority: 2,
|
|
47
|
+
team: { id: "team_1" },
|
|
48
|
+
labels: [{ id: "lbl_auto", name: "auto-implement" }],
|
|
49
|
+
};
|
|
50
|
+
const alreadyEscalatedIssue = {
|
|
51
|
+
id: "iss_already",
|
|
52
|
+
identifier: "BEC-701",
|
|
53
|
+
title: "Previously escalated",
|
|
54
|
+
description: "...",
|
|
55
|
+
priority: 2,
|
|
56
|
+
team: { id: "team_1" },
|
|
57
|
+
labels: [
|
|
58
|
+
{ id: "lbl_auto", name: "auto-implement" },
|
|
59
|
+
{ id: "lbl_nd", name: "needs-design" },
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
describe("Tier 5 — escalation fires when circuit breaker trips on a non-escalated issue", () => {
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
vi.clearAllMocks();
|
|
65
|
+
});
|
|
66
|
+
it("adds the needs-design label, posts a Linear comment, calls slackPostAlert, and updates the result reason", async () => {
|
|
67
|
+
const linearClient = mockLinearClient([failingIssue]);
|
|
68
|
+
const checkConflict = vi.fn().mockResolvedValue({
|
|
69
|
+
overlapRisk: "none",
|
|
70
|
+
likelyFiles: [],
|
|
71
|
+
reasoning: "no conflict",
|
|
72
|
+
});
|
|
73
|
+
const slackPostAlert = vi.fn().mockResolvedValue(undefined);
|
|
74
|
+
const getLastError = vi
|
|
75
|
+
.fn()
|
|
76
|
+
.mockResolvedValue("Stage 'implement' failed: TypeError on line 42");
|
|
77
|
+
const results = await promoteReadyIssues({
|
|
78
|
+
linearClient: linearClient,
|
|
79
|
+
teamIds: ["team_1"],
|
|
80
|
+
slotsAvailable: 3,
|
|
81
|
+
checkConflict,
|
|
82
|
+
stateMap: new Map([["team_1:Todo", "state_todo"]]),
|
|
83
|
+
maxConsecutiveFailures: 3,
|
|
84
|
+
getFailureCount: vi.fn().mockResolvedValue(5),
|
|
85
|
+
getLastError,
|
|
86
|
+
slackPostAlert,
|
|
87
|
+
});
|
|
88
|
+
expect(results).toHaveLength(1);
|
|
89
|
+
expect(results[0].promoted).toBe(false);
|
|
90
|
+
expect(results[0].reason).toContain("escalated to needs-design");
|
|
91
|
+
expect(results[0].reason).not.toContain("already escalated");
|
|
92
|
+
// Label added (preserving existing)
|
|
93
|
+
expect(linearClient.updateIssue).toHaveBeenCalledWith("iss_fail", expect.objectContaining({
|
|
94
|
+
labelIds: expect.arrayContaining(["lbl_auto", "lbl_nd"]),
|
|
95
|
+
}));
|
|
96
|
+
// Comment posted
|
|
97
|
+
expect(linearClient.createComment).toHaveBeenCalledTimes(1);
|
|
98
|
+
const commentBody = linearClient.createComment.mock.calls[0][0].body;
|
|
99
|
+
expect(commentBody).toContain("Escalated to `needs-design`");
|
|
100
|
+
expect(commentBody).toMatch(/\*\*5\*\* consecutive failed pipeline runs/);
|
|
101
|
+
expect(commentBody).toContain("threshold 3");
|
|
102
|
+
expect(commentBody).toContain("TypeError on line 42");
|
|
103
|
+
// Slack alert fired
|
|
104
|
+
expect(slackPostAlert).toHaveBeenCalledTimes(1);
|
|
105
|
+
expect(slackPostAlert).toHaveBeenCalledWith({
|
|
106
|
+
issueId: "BEC-700",
|
|
107
|
+
issueTitle: "Some broken feature",
|
|
108
|
+
failureCount: 5,
|
|
109
|
+
errorMessage: "Stage 'implement' failed: TypeError on line 42",
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
it("renders a fallback message when no last-failure error is available", async () => {
|
|
113
|
+
const linearClient = mockLinearClient([failingIssue]);
|
|
114
|
+
const results = await promoteReadyIssues({
|
|
115
|
+
linearClient: linearClient,
|
|
116
|
+
teamIds: ["team_1"],
|
|
117
|
+
slotsAvailable: 3,
|
|
118
|
+
checkConflict: vi.fn().mockResolvedValue({
|
|
119
|
+
overlapRisk: "none",
|
|
120
|
+
likelyFiles: [],
|
|
121
|
+
reasoning: "no conflict",
|
|
122
|
+
}),
|
|
123
|
+
stateMap: new Map([["team_1:Todo", "state_todo"]]),
|
|
124
|
+
maxConsecutiveFailures: 3,
|
|
125
|
+
getFailureCount: vi.fn().mockResolvedValue(3),
|
|
126
|
+
getLastError: vi.fn().mockResolvedValue(null),
|
|
127
|
+
});
|
|
128
|
+
expect(results[0].reason).toContain("escalated to needs-design");
|
|
129
|
+
const commentBody = linearClient.createComment.mock.calls[0][0].body;
|
|
130
|
+
expect(commentBody).toContain("(no error message captured on the most recent failed run)");
|
|
131
|
+
});
|
|
132
|
+
it("truncates error messages over 500 chars in the Linear comment", async () => {
|
|
133
|
+
const linearClient = mockLinearClient([failingIssue]);
|
|
134
|
+
const longError = "x".repeat(2000);
|
|
135
|
+
await promoteReadyIssues({
|
|
136
|
+
linearClient: linearClient,
|
|
137
|
+
teamIds: ["team_1"],
|
|
138
|
+
slotsAvailable: 3,
|
|
139
|
+
checkConflict: vi.fn().mockResolvedValue({
|
|
140
|
+
overlapRisk: "none",
|
|
141
|
+
likelyFiles: [],
|
|
142
|
+
reasoning: "no conflict",
|
|
143
|
+
}),
|
|
144
|
+
stateMap: new Map([["team_1:Todo", "state_todo"]]),
|
|
145
|
+
maxConsecutiveFailures: 3,
|
|
146
|
+
getFailureCount: vi.fn().mockResolvedValue(3),
|
|
147
|
+
getLastError: vi.fn().mockResolvedValue(longError),
|
|
148
|
+
});
|
|
149
|
+
const commentBody = linearClient.createComment.mock.calls[0][0].body;
|
|
150
|
+
// Body contains the truncated form with a trailing ellipsis.
|
|
151
|
+
expect(commentBody).toMatch(/x{500}…/);
|
|
152
|
+
expect(commentBody).not.toMatch(/x{1000}/);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
describe("Tier 5 — already-escalated issues skip the escalation (idempotency)", () => {
|
|
156
|
+
beforeEach(() => {
|
|
157
|
+
vi.clearAllMocks();
|
|
158
|
+
});
|
|
159
|
+
it("does NOT add the label again, does NOT post a second comment, does NOT call slackPostAlert", async () => {
|
|
160
|
+
const linearClient = mockLinearClient([alreadyEscalatedIssue]);
|
|
161
|
+
const slackPostAlert = vi.fn();
|
|
162
|
+
const results = await promoteReadyIssues({
|
|
163
|
+
linearClient: linearClient,
|
|
164
|
+
teamIds: ["team_1"],
|
|
165
|
+
slotsAvailable: 3,
|
|
166
|
+
checkConflict: vi.fn().mockResolvedValue({
|
|
167
|
+
overlapRisk: "none",
|
|
168
|
+
likelyFiles: [],
|
|
169
|
+
reasoning: "no conflict",
|
|
170
|
+
}),
|
|
171
|
+
stateMap: new Map([["team_1:Todo", "state_todo"]]),
|
|
172
|
+
maxConsecutiveFailures: 3,
|
|
173
|
+
getFailureCount: vi.fn().mockResolvedValue(5),
|
|
174
|
+
slackPostAlert,
|
|
175
|
+
});
|
|
176
|
+
expect(results).toHaveLength(1);
|
|
177
|
+
expect(results[0].reason).toContain("already escalated");
|
|
178
|
+
expect(linearClient.updateIssue).not.toHaveBeenCalled();
|
|
179
|
+
expect(linearClient.createComment).not.toHaveBeenCalled();
|
|
180
|
+
expect(slackPostAlert).not.toHaveBeenCalled();
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
describe("Tier 5 — no escalation when circuit breaker is disabled or threshold not reached", () => {
|
|
184
|
+
beforeEach(() => {
|
|
185
|
+
vi.clearAllMocks();
|
|
186
|
+
});
|
|
187
|
+
it("clean issue (failures below threshold) is promoted normally — no escalation side effects", async () => {
|
|
188
|
+
const linearClient = mockLinearClient([failingIssue]);
|
|
189
|
+
const slackPostAlert = vi.fn();
|
|
190
|
+
const results = await promoteReadyIssues({
|
|
191
|
+
linearClient: linearClient,
|
|
192
|
+
teamIds: ["team_1"],
|
|
193
|
+
slotsAvailable: 3,
|
|
194
|
+
checkConflict: vi.fn().mockResolvedValue({
|
|
195
|
+
overlapRisk: "none",
|
|
196
|
+
likelyFiles: [],
|
|
197
|
+
reasoning: "no conflict",
|
|
198
|
+
}),
|
|
199
|
+
stateMap: new Map([["team_1:Todo", "state_todo"]]),
|
|
200
|
+
maxConsecutiveFailures: 3,
|
|
201
|
+
getFailureCount: vi.fn().mockResolvedValue(1),
|
|
202
|
+
slackPostAlert,
|
|
203
|
+
});
|
|
204
|
+
expect(results).toHaveLength(1);
|
|
205
|
+
expect(results[0].promoted).toBe(true);
|
|
206
|
+
expect(slackPostAlert).not.toHaveBeenCalled();
|
|
207
|
+
// updateIssue was called for the normal promote (Backlog → Todo); confirm
|
|
208
|
+
// that single call did NOT include needs-design.
|
|
209
|
+
expect(linearClient.updateIssue).toHaveBeenCalledTimes(1);
|
|
210
|
+
const callArgs = linearClient.updateIssue.mock.calls[0];
|
|
211
|
+
expect(callArgs[1].labelIds).toBeUndefined();
|
|
212
|
+
});
|
|
213
|
+
it("when slackPostAlert is omitted, escalation still updates Linear + emits audit event", async () => {
|
|
214
|
+
// This proves the alert is best-effort: notifier outages don't suppress
|
|
215
|
+
// the audit / Linear-side signals.
|
|
216
|
+
const linearClient = mockLinearClient([failingIssue]);
|
|
217
|
+
const results = await promoteReadyIssues({
|
|
218
|
+
linearClient: linearClient,
|
|
219
|
+
teamIds: ["team_1"],
|
|
220
|
+
slotsAvailable: 3,
|
|
221
|
+
checkConflict: vi.fn().mockResolvedValue({
|
|
222
|
+
overlapRisk: "none",
|
|
223
|
+
likelyFiles: [],
|
|
224
|
+
reasoning: "no conflict",
|
|
225
|
+
}),
|
|
226
|
+
stateMap: new Map([["team_1:Todo", "state_todo"]]),
|
|
227
|
+
maxConsecutiveFailures: 3,
|
|
228
|
+
getFailureCount: vi.fn().mockResolvedValue(3),
|
|
229
|
+
getLastError: vi.fn().mockResolvedValue("err"),
|
|
230
|
+
// slackPostAlert omitted
|
|
231
|
+
});
|
|
232
|
+
expect(results[0].reason).toContain("escalated to needs-design");
|
|
233
|
+
expect(linearClient.updateIssue).toHaveBeenCalled();
|
|
234
|
+
expect(linearClient.createComment).toHaveBeenCalled();
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
describe("Tier 5 — defensive: label not found in workspace", () => {
|
|
238
|
+
beforeEach(() => {
|
|
239
|
+
vi.clearAllMocks();
|
|
240
|
+
});
|
|
241
|
+
it("logs a warn but does NOT crash when needs-design label is missing from the workspace", async () => {
|
|
242
|
+
const linearClient = mockLinearClient([failingIssue]);
|
|
243
|
+
// Override issueLabels to return no needs-design.
|
|
244
|
+
linearClient.issueLabels.mockResolvedValueOnce({
|
|
245
|
+
nodes: [
|
|
246
|
+
{ id: "lbl_auto", name: "auto-implement" },
|
|
247
|
+
{ id: "lbl_bug", name: "bug" },
|
|
248
|
+
],
|
|
249
|
+
});
|
|
250
|
+
const results = await promoteReadyIssues({
|
|
251
|
+
linearClient: linearClient,
|
|
252
|
+
teamIds: ["team_1"],
|
|
253
|
+
slotsAvailable: 3,
|
|
254
|
+
checkConflict: vi.fn().mockResolvedValue({
|
|
255
|
+
overlapRisk: "none",
|
|
256
|
+
likelyFiles: [],
|
|
257
|
+
reasoning: "no conflict",
|
|
258
|
+
}),
|
|
259
|
+
stateMap: new Map([["team_1:Todo", "state_todo"]]),
|
|
260
|
+
maxConsecutiveFailures: 3,
|
|
261
|
+
getFailureCount: vi.fn().mockResolvedValue(3),
|
|
262
|
+
getLastError: vi.fn().mockResolvedValue("err"),
|
|
263
|
+
});
|
|
264
|
+
expect(results[0].reason).toContain("escalated to needs-design");
|
|
265
|
+
// Comment + label-update would have been attempted; updateIssue NOT called
|
|
266
|
+
// because needsDesignLabelId resolved to undefined.
|
|
267
|
+
expect(linearClient.updateIssue).not.toHaveBeenCalled();
|
|
268
|
+
// Comment still posted (so the operator sees the escalation rationale
|
|
269
|
+
// even when the label couldn't be applied).
|
|
270
|
+
expect(linearClient.createComment).toHaveBeenCalledTimes(1);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
//# sourceMappingURL=pm-escalation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pm-escalation.test.js","sourceRoot":"","sources":["../../src/__tests__/pm-escalation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pm-triage-design-doc.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pm-triage-design-doc.test.ts"],"names":[],"mappings":""}
|