@urateam/core 0.1.19 → 0.1.21
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-profiles.test.js +20 -10
- package/dist/__tests__/agent-profiles.test.js.map +1 -1
- package/dist/__tests__/auto-commit-scratchpad.test.d.ts +2 -0
- package/dist/__tests__/auto-commit-scratchpad.test.d.ts.map +1 -0
- package/dist/__tests__/auto-commit-scratchpad.test.js +181 -0
- package/dist/__tests__/auto-commit-scratchpad.test.js.map +1 -0
- package/dist/__tests__/pm-budget.test.js +1 -0
- package/dist/__tests__/pm-budget.test.js.map +1 -1
- package/dist/__tests__/pm-circuit-breaker.test.d.ts +2 -0
- package/dist/__tests__/pm-circuit-breaker.test.d.ts.map +1 -0
- package/dist/__tests__/pm-circuit-breaker.test.js +104 -0
- package/dist/__tests__/pm-circuit-breaker.test.js.map +1 -0
- package/dist/__tests__/pm-promote.test.js +77 -0
- package/dist/__tests__/pm-promote.test.js.map +1 -1
- package/dist/__tests__/pm-scheduler.test.js +1 -0
- package/dist/__tests__/pm-scheduler.test.js.map +1 -1
- package/dist/__tests__/pm-types.test.js +2 -0
- package/dist/__tests__/pm-types.test.js.map +1 -1
- package/dist/__tests__/release-manager-scheduler.test.js +59 -0
- package/dist/__tests__/release-manager-scheduler.test.js.map +1 -1
- package/dist/__tests__/reproduce-bec113-pagination-warning.test.js +1 -0
- package/dist/__tests__/reproduce-bec113-pagination-warning.test.js.map +1 -1
- package/dist/__tests__/reproduce-bec62.test.js +1 -0
- package/dist/__tests__/reproduce-bec62.test.js.map +1 -1
- package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.js +2 -0
- package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.js.map +1 -1
- package/dist/__tests__/start-todo.test.js +71 -0
- package/dist/__tests__/start-todo.test.js.map +1 -1
- package/dist/__tests__/webhook-handler.test.js +1 -0
- package/dist/__tests__/webhook-handler.test.js.map +1 -1
- package/dist/executor/profiles.d.ts.map +1 -1
- package/dist/executor/profiles.js +7 -2
- package/dist/executor/profiles.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 +30 -1
- package/dist/pm/actions/db-queries.js.map +1 -1
- package/dist/pm/actions/promote.d.ts +14 -0
- package/dist/pm/actions/promote.d.ts.map +1 -1
- package/dist/pm/actions/promote.js +16 -0
- package/dist/pm/actions/promote.js.map +1 -1
- package/dist/pm/actions/start-todo.d.ts +12 -0
- package/dist/pm/actions/start-todo.d.ts.map +1 -1
- package/dist/pm/actions/start-todo.js +21 -0
- package/dist/pm/actions/start-todo.js.map +1 -1
- package/dist/pm/scheduler.d.ts.map +1 -1
- package/dist/pm/scheduler.js +9 -0
- package/dist/pm/scheduler.js.map +1 -1
- package/dist/pm/types.d.ts +1 -0
- package/dist/pm/types.d.ts.map +1 -1
- package/dist/pm/types.js +6 -0
- package/dist/pm/types.js.map +1 -1
- package/dist/release-manager/scheduler.d.ts.map +1 -1
- package/dist/release-manager/scheduler.js +11 -0
- package/dist/release-manager/scheduler.js.map +1 -1
- package/dist/repo/git.d.ts +2 -1
- package/dist/repo/git.d.ts.map +1 -1
- package/dist/repo/git.js +121 -1
- package/dist/repo/git.js.map +1 -1
- package/package.json +1 -1
|
@@ -16,25 +16,34 @@ describe("getAgentProfiles defaults", () => {
|
|
|
16
16
|
it("returns the built-in defaults when env var is unset", () => {
|
|
17
17
|
expect(getAgentProfiles()).toEqual(DEFAULT_AGENT_PROFILES);
|
|
18
18
|
});
|
|
19
|
-
it("ships the documented test
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
19
|
+
it("ships the documented test + implement stage budgets", () => {
|
|
20
|
+
// BEC-162 (2026-05-06 BEC-138 dogfood): bumped from implement=50/test=25
|
|
21
|
+
// to implement=100/test=50 after non-trivial sev-2 tickets repeatedly
|
|
22
|
+
// hit the old caps. urateam#38 (bootstrapping) and the override path
|
|
23
|
+
// are unchanged; this is just a more realistic baseline for
|
|
24
|
+
// mature-repo work. Asserting exact shape so any future silent bump
|
|
23
25
|
// shows up in review.
|
|
24
26
|
expect(DEFAULT_AGENT_PROFILES.test).toMatchObject({
|
|
25
|
-
maxTurns:
|
|
27
|
+
maxTurns: 50,
|
|
26
28
|
maxInputTokens: 30_000,
|
|
27
29
|
model: "claude-haiku-4-5",
|
|
28
30
|
});
|
|
31
|
+
expect(DEFAULT_AGENT_PROFILES.implement).toMatchObject({
|
|
32
|
+
maxTurns: 100,
|
|
33
|
+
maxInputTokens: 100_000,
|
|
34
|
+
});
|
|
29
35
|
});
|
|
30
36
|
});
|
|
31
37
|
describe("getAgentProfiles env override", () => {
|
|
32
38
|
it("merges a partial override on top of defaults", () => {
|
|
39
|
+
// BEC-162 review: pick a maxTurns value that does NOT match the default
|
|
40
|
+
// (50 post-bump). Otherwise a regression that drops the merge logic and
|
|
41
|
+
// falls back to the default would silently pass this assertion.
|
|
33
42
|
process.env.URATEAM_AGENT_PROFILES = JSON.stringify({
|
|
34
|
-
test: { maxTurns:
|
|
43
|
+
test: { maxTurns: 75, maxInputTokens: 80_000 },
|
|
35
44
|
});
|
|
36
45
|
const p = getAgentProfiles();
|
|
37
|
-
expect(p.test.maxTurns).toBe(
|
|
46
|
+
expect(p.test.maxTurns).toBe(75);
|
|
38
47
|
expect(p.test.maxInputTokens).toBe(80_000);
|
|
39
48
|
// Untouched fields keep their default
|
|
40
49
|
expect(p.test.model).toBe("claude-haiku-4-5");
|
|
@@ -59,15 +68,16 @@ describe("getAgentProfiles env override", () => {
|
|
|
59
68
|
expect(p.flarble).toBeUndefined();
|
|
60
69
|
});
|
|
61
70
|
it("ignores malformed individual fields without dropping the rest of the stage", () => {
|
|
71
|
+
// BEC-162 review: 75, not 50 — see "merges a partial override" above.
|
|
62
72
|
process.env.URATEAM_AGENT_PROFILES = JSON.stringify({
|
|
63
73
|
test: {
|
|
64
|
-
maxTurns:
|
|
74
|
+
maxTurns: 75, // valid → applied
|
|
65
75
|
maxInputTokens: "lots", // invalid → ignored
|
|
66
76
|
model: "", // invalid (empty) → ignored
|
|
67
77
|
},
|
|
68
78
|
});
|
|
69
79
|
const p = getAgentProfiles();
|
|
70
|
-
expect(p.test.maxTurns).toBe(
|
|
80
|
+
expect(p.test.maxTurns).toBe(75);
|
|
71
81
|
expect(p.test.maxInputTokens).toBe(30_000); // default kept
|
|
72
82
|
expect(p.test.model).toBe("claude-haiku-4-5"); // default kept
|
|
73
83
|
});
|
|
@@ -76,7 +86,7 @@ describe("getAgentProfiles env override", () => {
|
|
|
76
86
|
test: { maxTurns: 0, maxInputTokens: -1 },
|
|
77
87
|
});
|
|
78
88
|
const p = getAgentProfiles();
|
|
79
|
-
expect(p.test.maxTurns).toBe(
|
|
89
|
+
expect(p.test.maxTurns).toBe(50); // BEC-162 default kept
|
|
80
90
|
expect(p.test.maxInputTokens).toBe(30_000); // default kept
|
|
81
91
|
});
|
|
82
92
|
it("falls back to defaults when env var is malformed JSON", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-profiles.test.js","sourceRoot":"","sources":["../../src/__tests__/agent-profiles.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;AAEpD,UAAU,CAAC,GAAG,EAAE;IACd,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAC1C,wBAAwB,EAAE,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;;QACjE,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,QAAQ,CAAC;IACnD,wBAAwB,EAAE,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"agent-profiles.test.js","sourceRoot":"","sources":["../../src/__tests__/agent-profiles.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-commit-scratchpad.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/auto-commit-scratchpad.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { autoCommitChanges, isScratchpadPath } from "../repo/git.js";
|
|
7
|
+
/**
|
|
8
|
+
* BEC-157: pipeline auto-commit must filter agent scratchpad files (e.g.,
|
|
9
|
+
* `.claude/`, root-level `BEC-*-*.md`, `verify-*.{mjs,ts}`) so they don't get
|
|
10
|
+
* pushed to the target repo. The agent has no idea these are local scratchpad;
|
|
11
|
+
* the auto-commit step is the safety gate.
|
|
12
|
+
*/
|
|
13
|
+
const GIT_AUTHOR = {
|
|
14
|
+
GIT_AUTHOR_NAME: "Test Bot",
|
|
15
|
+
GIT_AUTHOR_EMAIL: "test-bot@example.com",
|
|
16
|
+
GIT_COMMITTER_NAME: "Test Bot",
|
|
17
|
+
GIT_COMMITTER_EMAIL: "test-bot@example.com",
|
|
18
|
+
};
|
|
19
|
+
function git(args, cwd) {
|
|
20
|
+
return execFileSync("git", args, { cwd, env: { ...process.env, ...GIT_AUTHOR }, encoding: "utf-8" });
|
|
21
|
+
}
|
|
22
|
+
function listFilesInLastCommit(repo) {
|
|
23
|
+
return git(["show", "--name-only", "--pretty=format:", "HEAD"], repo)
|
|
24
|
+
.trim()
|
|
25
|
+
.split("\n")
|
|
26
|
+
.filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
describe("autoCommitChanges scratchpad filter (BEC-157)", () => {
|
|
29
|
+
let repo;
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
repo = mkdtempSync(join(tmpdir(), "urateam-bec157-"));
|
|
32
|
+
git(["init", "--initial-branch=main"], repo);
|
|
33
|
+
git(["config", "user.email", "test-bot@example.com"], repo);
|
|
34
|
+
git(["config", "user.name", "Test Bot"], repo);
|
|
35
|
+
// Create a base commit so HEAD has a parent (autoCommitChanges expects a
|
|
36
|
+
// valid HEAD it can branch-check against; even without that, commits
|
|
37
|
+
// produce nicer diffs against a parent).
|
|
38
|
+
writeFileSync(join(repo, "README.md"), "# initial\n");
|
|
39
|
+
git(["add", "README.md"], repo);
|
|
40
|
+
git(["commit", "-m", "initial"], repo);
|
|
41
|
+
});
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
rmSync(repo, { recursive: true, force: true });
|
|
44
|
+
});
|
|
45
|
+
it("commits real source files but excludes .claude/* scratchpad", async () => {
|
|
46
|
+
mkdirSync(join(repo, "src"), { recursive: true });
|
|
47
|
+
writeFileSync(join(repo, "src", "foo.ts"), "export const foo = 1;\n");
|
|
48
|
+
mkdirSync(join(repo, ".claude"), { recursive: true });
|
|
49
|
+
writeFileSync(join(repo, ".claude", "settings.json"), '{"hook":"x"}\n');
|
|
50
|
+
const result = await autoCommitChanges(repo, "BEC-999");
|
|
51
|
+
expect(result).toBe(true);
|
|
52
|
+
const files = listFilesInLastCommit(repo);
|
|
53
|
+
expect(files).toContain("src/foo.ts");
|
|
54
|
+
expect(files).not.toContain(".claude/settings.json");
|
|
55
|
+
// Scratchpad file still exists on disk — just not committed
|
|
56
|
+
expect(existsSync(join(repo, ".claude", "settings.json"))).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
it("excludes root-level BEC-NNN-*.md scratchpad", async () => {
|
|
59
|
+
mkdirSync(join(repo, "src"), { recursive: true });
|
|
60
|
+
writeFileSync(join(repo, "src", "real.ts"), "export const real = 1;\n");
|
|
61
|
+
writeFileSync(join(repo, "BEC-149-INDEX.md"), "# scratchpad\n");
|
|
62
|
+
writeFileSync(join(repo, "BEC-149-PR-CHECKLIST.md"), "# checklist\n");
|
|
63
|
+
await autoCommitChanges(repo, "BEC-999");
|
|
64
|
+
const files = listFilesInLastCommit(repo);
|
|
65
|
+
expect(files).toContain("src/real.ts");
|
|
66
|
+
expect(files).not.toContain("BEC-149-INDEX.md");
|
|
67
|
+
expect(files).not.toContain("BEC-149-PR-CHECKLIST.md");
|
|
68
|
+
});
|
|
69
|
+
it("excludes root-level verify-*.{mjs,ts,js} scratchpad scripts", async () => {
|
|
70
|
+
mkdirSync(join(repo, "src"), { recursive: true });
|
|
71
|
+
writeFileSync(join(repo, "src", "real.ts"), "real\n");
|
|
72
|
+
writeFileSync(join(repo, "verify-fix.mjs"), "// scratchpad\n");
|
|
73
|
+
writeFileSync(join(repo, "verify-thing.ts"), "// scratchpad\n");
|
|
74
|
+
await autoCommitChanges(repo, "BEC-999");
|
|
75
|
+
const files = listFilesInLastCommit(repo);
|
|
76
|
+
expect(files).toContain("src/real.ts");
|
|
77
|
+
expect(files).not.toContain("verify-fix.mjs");
|
|
78
|
+
expect(files).not.toContain("verify-thing.ts");
|
|
79
|
+
});
|
|
80
|
+
it("does NOT exclude legitimate root-level files (CHANGELOG.md, CONTRIBUTING.md, README.md)", async () => {
|
|
81
|
+
writeFileSync(join(repo, "CHANGELOG.md"), "# changelog\n");
|
|
82
|
+
writeFileSync(join(repo, "CONTRIBUTING.md"), "# contrib\n");
|
|
83
|
+
await autoCommitChanges(repo, "BEC-999");
|
|
84
|
+
const files = listFilesInLastCommit(repo);
|
|
85
|
+
expect(files).toContain("CHANGELOG.md");
|
|
86
|
+
expect(files).toContain("CONTRIBUTING.md");
|
|
87
|
+
});
|
|
88
|
+
it("does NOT exclude verify-*.ts inside src/ (only root-level matches)", async () => {
|
|
89
|
+
// Real-world: a developer may legitimately have a `verify-*.ts` in
|
|
90
|
+
// src/utils/ as part of an actual feature. Only root-level scratchpad
|
|
91
|
+
// patterns get filtered.
|
|
92
|
+
mkdirSync(join(repo, "src", "utils"), { recursive: true });
|
|
93
|
+
writeFileSync(join(repo, "src", "utils", "verify-input.ts"), "export {};\n");
|
|
94
|
+
await autoCommitChanges(repo, "BEC-999");
|
|
95
|
+
const files = listFilesInLastCommit(repo);
|
|
96
|
+
expect(files).toContain("src/utils/verify-input.ts");
|
|
97
|
+
});
|
|
98
|
+
it("returns false when ALL changes are scratchpad (nothing real to commit)", async () => {
|
|
99
|
+
mkdirSync(join(repo, ".claude"), { recursive: true });
|
|
100
|
+
writeFileSync(join(repo, ".claude", "settings.json"), '{}\n');
|
|
101
|
+
writeFileSync(join(repo, "BEC-200-OUTPUT.md"), "# x\n");
|
|
102
|
+
const result = await autoCommitChanges(repo, "BEC-999");
|
|
103
|
+
// No real files to commit → returns false (just like an empty status)
|
|
104
|
+
expect(result).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
// BEC-157 safety net (Sonnet review Important #1): if a scratchpad file is
|
|
107
|
+
// ALREADY tracked in HEAD (operator committed it pre-filter), unstaging via
|
|
108
|
+
// `git rm --cached` would record a permanent deletion. Skip the unstage for
|
|
109
|
+
// tracked entries — preserve the file as a normal commit.
|
|
110
|
+
it("preserves tracked scratchpad files instead of silently deleting them", async () => {
|
|
111
|
+
// Operator previously (pre-filter) committed .claude/settings.json
|
|
112
|
+
mkdirSync(join(repo, ".claude"), { recursive: true });
|
|
113
|
+
writeFileSync(join(repo, ".claude", "settings.json"), "old\n");
|
|
114
|
+
git(["add", "."], repo);
|
|
115
|
+
git(["commit", "-m", "operator committed scratchpad pre-filter"], repo);
|
|
116
|
+
// Now agent modifies it AND adds a real file
|
|
117
|
+
writeFileSync(join(repo, ".claude", "settings.json"), "new\n");
|
|
118
|
+
mkdirSync(join(repo, "src"), { recursive: true });
|
|
119
|
+
writeFileSync(join(repo, "src", "real.ts"), "real\n");
|
|
120
|
+
const result = await autoCommitChanges(repo, "BEC-999");
|
|
121
|
+
expect(result).toBe(true);
|
|
122
|
+
const files = listFilesInLastCommit(repo);
|
|
123
|
+
expect(files).toContain("src/real.ts");
|
|
124
|
+
// The tracked .claude/settings.json should still appear as committed
|
|
125
|
+
// (with new content) — NOT deleted from the repo.
|
|
126
|
+
expect(files).toContain(".claude/settings.json");
|
|
127
|
+
// Verify the file is not staged for deletion in HEAD~1..HEAD
|
|
128
|
+
const headContent = git(["show", "HEAD:.claude/settings.json"], repo);
|
|
129
|
+
expect(headContent).toBe("new\n");
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe("isScratchpadPath unit tests (BEC-157)", () => {
|
|
133
|
+
// Direct unit tests for the predicate, decoupled from git plumbing.
|
|
134
|
+
// Covers boundary cases that the integration tests don't reach.
|
|
135
|
+
it("matches .claude/ directory and contents", () => {
|
|
136
|
+
expect(isScratchpadPath(".claude")).toBe(true);
|
|
137
|
+
expect(isScratchpadPath(".claude/")).toBe(true);
|
|
138
|
+
expect(isScratchpadPath(".claude/settings.json")).toBe(true);
|
|
139
|
+
expect(isScratchpadPath(".claude/nested/deep.json")).toBe(true);
|
|
140
|
+
});
|
|
141
|
+
it("does NOT match .claude when nested under a directory", () => {
|
|
142
|
+
// Root-anchored: a subproject's .claude dir isn't pipeline scratchpad
|
|
143
|
+
expect(isScratchpadPath("frontend/.claude/x")).toBe(false);
|
|
144
|
+
expect(isScratchpadPath("packages/core/.claude/y")).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
it("matches root-level BEC-NNN-*.md scratchpad", () => {
|
|
147
|
+
expect(isScratchpadPath("BEC-149-INDEX.md")).toBe(true);
|
|
148
|
+
expect(isScratchpadPath("BEC-1-x.md")).toBe(true);
|
|
149
|
+
expect(isScratchpadPath("BEC-9999-foo.md")).toBe(true);
|
|
150
|
+
});
|
|
151
|
+
it("does NOT match BEC-*.md without numeric ID or non-root path", () => {
|
|
152
|
+
expect(isScratchpadPath("BEC-foo.md")).toBe(false); // no numeric prefix
|
|
153
|
+
expect(isScratchpadPath("docs/BEC-149-INDEX.md")).toBe(false); // not at root
|
|
154
|
+
expect(isScratchpadPath("CHANGELOG.md")).toBe(false);
|
|
155
|
+
});
|
|
156
|
+
it("matches root-level verify-*.{mjs,ts,js,cjs} but not without extension", () => {
|
|
157
|
+
expect(isScratchpadPath("verify-fix.mjs")).toBe(true);
|
|
158
|
+
expect(isScratchpadPath("verify-x.ts")).toBe(true);
|
|
159
|
+
expect(isScratchpadPath("verify-y.js")).toBe(true);
|
|
160
|
+
expect(isScratchpadPath("verify-z.cjs")).toBe(true);
|
|
161
|
+
expect(isScratchpadPath("verify.mjs")).toBe(false); // no dash
|
|
162
|
+
expect(isScratchpadPath("verifyutils.mjs")).toBe(false); // no dash
|
|
163
|
+
expect(isScratchpadPath("src/utils/verify-input.ts")).toBe(false); // not at root
|
|
164
|
+
});
|
|
165
|
+
it("matches root-level BEC-NNN-*-VERIFICATION.md but NOT generic *-VERIFICATION.md", () => {
|
|
166
|
+
expect(isScratchpadPath("BEC-149-MIGRATION-VERIFICATION.md")).toBe(true);
|
|
167
|
+
expect(isScratchpadPath("BEC-200-VERIFICATION.md")).toBe(true);
|
|
168
|
+
// Pattern tightened (was overbroad in initial PR; would have filtered these):
|
|
169
|
+
expect(isScratchpadPath("SECURITY-VERIFICATION.md")).toBe(false);
|
|
170
|
+
expect(isScratchpadPath("API-VERIFICATION.md")).toBe(false);
|
|
171
|
+
});
|
|
172
|
+
it("does NOT match legitimate root-level files", () => {
|
|
173
|
+
expect(isScratchpadPath("CHANGELOG.md")).toBe(false);
|
|
174
|
+
expect(isScratchpadPath("CONTRIBUTING.md")).toBe(false);
|
|
175
|
+
expect(isScratchpadPath("README.md")).toBe(false);
|
|
176
|
+
expect(isScratchpadPath("LICENSE")).toBe(false);
|
|
177
|
+
expect(isScratchpadPath("package.json")).toBe(false);
|
|
178
|
+
expect(isScratchpadPath("turbo.json")).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
//# sourceMappingURL=auto-commit-scratchpad.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-commit-scratchpad.test.js","sourceRoot":"","sources":["../../src/__tests__/auto-commit-scratchpad.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pm-budget.test.js","sourceRoot":"","sources":["../../src/__tests__/pm-budget.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAcjD,SAAS,MAAM,CAAC,IAAe;IAC7B,MAAM,KAAK,GAAQ;QACjB,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK;QACnB,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK;QACjB,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK;QAClB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;KACrC,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,YAAoC,EAAE;IACxD,OAAO;QACL,OAAO,EAAE,IAAI;QACb,gBAAgB,EAAE,SAAS;QAC3B,cAAc,EAAE,QAAQ;QACxB,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,WAAW,EAAE,CAAC;QACd,cAAc,EAAE,SAAS;QACzB,eAAe,EAAE,CAAC;QAClB,kBAAkB,EAAE,IAAI;QACxB,qBAAqB,EAAE,SAAS;QAChC,oBAAoB,EAAE,CAAC;QACvB,8BAA8B,EAAE,KAAK;
|
|
1
|
+
{"version":3,"file":"pm-budget.test.js","sourceRoot":"","sources":["../../src/__tests__/pm-budget.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pm-circuit-breaker.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pm-circuit-breaker.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BEC-161 — PM circuit breaker for repeated failures.
|
|
3
|
+
*
|
|
4
|
+
* countConsecutiveFailures(db, issueId) returns the number of failed pipeline
|
|
5
|
+
* runs for the issue since the last successfully-completed run (or since first
|
|
6
|
+
* run if none completed). Promote/start-todo use this to short-circuit
|
|
7
|
+
* candidates that have failed N+ times in a row.
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
10
|
+
import { randomBytes } from "node:crypto";
|
|
11
|
+
import { unlinkSync } from "node:fs";
|
|
12
|
+
import { createDb, pipelineRuns } from "../db/index.js";
|
|
13
|
+
import { countConsecutiveFailures } from "../pm/actions/db-queries.js";
|
|
14
|
+
function tmpDbPath() {
|
|
15
|
+
return `/tmp/laf-cb-test-${randomBytes(8).toString("hex")}.sqlite`;
|
|
16
|
+
}
|
|
17
|
+
describe("countConsecutiveFailures", () => {
|
|
18
|
+
const paths = [];
|
|
19
|
+
async function makeDb() {
|
|
20
|
+
const path = tmpDbPath();
|
|
21
|
+
paths.push(path);
|
|
22
|
+
return createDb({ driver: "sqlite", connectionString: path });
|
|
23
|
+
}
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
for (const p of paths) {
|
|
26
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
27
|
+
try {
|
|
28
|
+
unlinkSync(p + suffix);
|
|
29
|
+
}
|
|
30
|
+
catch { /* ignore */ }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
paths.length = 0;
|
|
34
|
+
});
|
|
35
|
+
function makeRun(id, issueId, status, startedAt, completedAt) {
|
|
36
|
+
return {
|
|
37
|
+
id,
|
|
38
|
+
issueId,
|
|
39
|
+
issueTitle: `Issue ${issueId}`,
|
|
40
|
+
pipelineKey: "default",
|
|
41
|
+
repoUrl: "https://github.com/org/repo",
|
|
42
|
+
status,
|
|
43
|
+
startedAt,
|
|
44
|
+
completedAt,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
it("returns 0 when issue has no runs", async () => {
|
|
48
|
+
const db = await makeDb();
|
|
49
|
+
expect(await countConsecutiveFailures(db, "ISSUE-NEW")).toBe(0);
|
|
50
|
+
});
|
|
51
|
+
it("returns 3 when issue has 3 consecutive failures and no completed run", async () => {
|
|
52
|
+
const db = await makeDb();
|
|
53
|
+
const t0 = new Date(Date.now() - 30 * 60_000);
|
|
54
|
+
await db.insert(pipelineRuns).values([
|
|
55
|
+
makeRun("r1", "ISSUE-A", "failed", new Date(t0.getTime() + 0), new Date(t0.getTime() + 1_000)),
|
|
56
|
+
makeRun("r2", "ISSUE-A", "failed", new Date(t0.getTime() + 5_000), new Date(t0.getTime() + 6_000)),
|
|
57
|
+
makeRun("r3", "ISSUE-A", "failed", new Date(t0.getTime() + 10_000), new Date(t0.getTime() + 11_000)),
|
|
58
|
+
]);
|
|
59
|
+
expect(await countConsecutiveFailures(db, "ISSUE-A")).toBe(3);
|
|
60
|
+
});
|
|
61
|
+
it("resets counter after a completed run (returns failures since last completion)", async () => {
|
|
62
|
+
const db = await makeDb();
|
|
63
|
+
const t0 = new Date(Date.now() - 30 * 60_000);
|
|
64
|
+
await db.insert(pipelineRuns).values([
|
|
65
|
+
makeRun("r1", "ISSUE-B", "failed", new Date(t0.getTime() + 0), new Date(t0.getTime() + 1_000)),
|
|
66
|
+
makeRun("r2", "ISSUE-B", "failed", new Date(t0.getTime() + 5_000), new Date(t0.getTime() + 6_000)),
|
|
67
|
+
makeRun("r3", "ISSUE-B", "failed", new Date(t0.getTime() + 10_000), new Date(t0.getTime() + 11_000)),
|
|
68
|
+
makeRun("r4", "ISSUE-B", "completed", new Date(t0.getTime() + 15_000), new Date(t0.getTime() + 16_000)),
|
|
69
|
+
makeRun("r5", "ISSUE-B", "failed", new Date(t0.getTime() + 20_000), new Date(t0.getTime() + 21_000)),
|
|
70
|
+
]);
|
|
71
|
+
expect(await countConsecutiveFailures(db, "ISSUE-B")).toBe(1);
|
|
72
|
+
});
|
|
73
|
+
it("returns 0 when most recent run is completed (no failures since)", async () => {
|
|
74
|
+
const db = await makeDb();
|
|
75
|
+
const t0 = new Date(Date.now() - 30 * 60_000);
|
|
76
|
+
await db.insert(pipelineRuns).values([
|
|
77
|
+
makeRun("r1", "ISSUE-C", "failed", new Date(t0.getTime() + 0), new Date(t0.getTime() + 1_000)),
|
|
78
|
+
makeRun("r2", "ISSUE-C", "completed", new Date(t0.getTime() + 5_000), new Date(t0.getTime() + 6_000)),
|
|
79
|
+
]);
|
|
80
|
+
expect(await countConsecutiveFailures(db, "ISSUE-C")).toBe(0);
|
|
81
|
+
});
|
|
82
|
+
it("ignores runs for other issues", async () => {
|
|
83
|
+
const db = await makeDb();
|
|
84
|
+
const t0 = new Date(Date.now() - 30 * 60_000);
|
|
85
|
+
await db.insert(pipelineRuns).values([
|
|
86
|
+
makeRun("r1", "ISSUE-D", "failed", new Date(t0.getTime() + 0), new Date(t0.getTime() + 1_000)),
|
|
87
|
+
makeRun("r2", "ISSUE-E", "failed", new Date(t0.getTime() + 5_000), new Date(t0.getTime() + 6_000)),
|
|
88
|
+
makeRun("r3", "ISSUE-E", "failed", new Date(t0.getTime() + 10_000), new Date(t0.getTime() + 11_000)),
|
|
89
|
+
]);
|
|
90
|
+
expect(await countConsecutiveFailures(db, "ISSUE-D")).toBe(1);
|
|
91
|
+
expect(await countConsecutiveFailures(db, "ISSUE-E")).toBe(2);
|
|
92
|
+
});
|
|
93
|
+
it("does not count active (running/queued) runs", async () => {
|
|
94
|
+
const db = await makeDb();
|
|
95
|
+
const t0 = new Date(Date.now() - 30 * 60_000);
|
|
96
|
+
await db.insert(pipelineRuns).values([
|
|
97
|
+
makeRun("r1", "ISSUE-F", "failed", new Date(t0.getTime() + 0), new Date(t0.getTime() + 1_000)),
|
|
98
|
+
makeRun("r2", "ISSUE-F", "failed", new Date(t0.getTime() + 5_000), new Date(t0.getTime() + 6_000)),
|
|
99
|
+
makeRun("r3", "ISSUE-F", "running", new Date(t0.getTime() + 10_000)),
|
|
100
|
+
]);
|
|
101
|
+
expect(await countConsecutiveFailures(db, "ISSUE-F")).toBe(2);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=pm-circuit-breaker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pm-circuit-breaker.test.js","sourceRoot":"","sources":["../../src/__tests__/pm-circuit-breaker.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -267,5 +267,82 @@ describe("promoteReadyIssues", () => {
|
|
|
267
267
|
expect(conflictChecker).toHaveBeenCalledTimes(1);
|
|
268
268
|
});
|
|
269
269
|
});
|
|
270
|
+
describe("circuit breaker (BEC-161)", () => {
|
|
271
|
+
/**
|
|
272
|
+
* The promote action must short-circuit candidates whose pipeline keeps
|
|
273
|
+
* failing. We don't need a real DB here — a stub `db` whose query helper
|
|
274
|
+
* returns the expected failure count per-issue is enough to prove promote
|
|
275
|
+
* consults the count and skips when it exceeds the threshold.
|
|
276
|
+
*
|
|
277
|
+
* Plumbing: promote receives `db` + `maxConsecutiveFailures` and an
|
|
278
|
+
* injectable `getFailureCount` (so tests don't need real db rows).
|
|
279
|
+
*/
|
|
280
|
+
it("skips candidate with N+ consecutive failed runs (default N=3)", async () => {
|
|
281
|
+
const issues = [
|
|
282
|
+
{ id: "i1", identifier: "BEC-161-A", title: "Doom-looping", description: "", priority: 2,
|
|
283
|
+
labels: { nodes: [] }, team: { id: "team-1" }, url: "https://linear.app/BEC-161-A" },
|
|
284
|
+
];
|
|
285
|
+
const client = mockLinearClient(issues);
|
|
286
|
+
const conflictChecker = vi.fn().mockResolvedValue({ overlapRisk: "none", likelyFiles: [], reasoning: "" });
|
|
287
|
+
const getFailureCount = vi.fn().mockResolvedValue(3);
|
|
288
|
+
const results = await promoteReadyIssues({
|
|
289
|
+
linearClient: client,
|
|
290
|
+
teamIds: ["team-1"],
|
|
291
|
+
slotsAvailable: 1,
|
|
292
|
+
checkConflict: conflictChecker,
|
|
293
|
+
stateMap: defaultStateMap,
|
|
294
|
+
maxConsecutiveFailures: 3,
|
|
295
|
+
getFailureCount,
|
|
296
|
+
});
|
|
297
|
+
expect(results).toHaveLength(1);
|
|
298
|
+
expect(results[0].promoted).toBe(false);
|
|
299
|
+
expect(results[0].reason).toMatch(/circuit.breaker/i);
|
|
300
|
+
expect(client.updateIssue).not.toHaveBeenCalled();
|
|
301
|
+
// breaker check happens BEFORE expensive conflict-detection
|
|
302
|
+
expect(conflictChecker).not.toHaveBeenCalled();
|
|
303
|
+
expect(getFailureCount).toHaveBeenCalledWith("BEC-161-A");
|
|
304
|
+
});
|
|
305
|
+
it("promotes candidate with fewer than N consecutive failures", async () => {
|
|
306
|
+
const issues = [
|
|
307
|
+
{ id: "i1", identifier: "BEC-161-B", title: "Recently failed once", description: "", priority: 2,
|
|
308
|
+
labels: { nodes: [] }, team: { id: "team-1" }, url: "https://linear.app/BEC-161-B" },
|
|
309
|
+
];
|
|
310
|
+
const client = mockLinearClient(issues);
|
|
311
|
+
const conflictChecker = vi.fn().mockResolvedValue({ overlapRisk: "none", likelyFiles: [], reasoning: "" });
|
|
312
|
+
const getFailureCount = vi.fn().mockResolvedValue(2);
|
|
313
|
+
const results = await promoteReadyIssues({
|
|
314
|
+
linearClient: client,
|
|
315
|
+
teamIds: ["team-1"],
|
|
316
|
+
slotsAvailable: 1,
|
|
317
|
+
checkConflict: conflictChecker,
|
|
318
|
+
stateMap: defaultStateMap,
|
|
319
|
+
maxConsecutiveFailures: 3,
|
|
320
|
+
getFailureCount,
|
|
321
|
+
});
|
|
322
|
+
expect(results[0].promoted).toBe(true);
|
|
323
|
+
expect(client.updateIssue).toHaveBeenCalled();
|
|
324
|
+
});
|
|
325
|
+
it("breaker disabled when maxConsecutiveFailures is undefined (back-compat)", async () => {
|
|
326
|
+
const issues = [
|
|
327
|
+
{ id: "i1", identifier: "BEC-161-C", title: "Has 99 failures", description: "", priority: 2,
|
|
328
|
+
labels: { nodes: [] }, team: { id: "team-1" }, url: "https://linear.app/BEC-161-C" },
|
|
329
|
+
];
|
|
330
|
+
const client = mockLinearClient(issues);
|
|
331
|
+
const conflictChecker = vi.fn().mockResolvedValue({ overlapRisk: "none", likelyFiles: [], reasoning: "" });
|
|
332
|
+
const getFailureCount = vi.fn().mockResolvedValue(99);
|
|
333
|
+
const results = await promoteReadyIssues({
|
|
334
|
+
linearClient: client,
|
|
335
|
+
teamIds: ["team-1"],
|
|
336
|
+
slotsAvailable: 1,
|
|
337
|
+
checkConflict: conflictChecker,
|
|
338
|
+
stateMap: defaultStateMap,
|
|
339
|
+
// maxConsecutiveFailures intentionally omitted
|
|
340
|
+
getFailureCount,
|
|
341
|
+
});
|
|
342
|
+
expect(results[0].promoted).toBe(true);
|
|
343
|
+
// breaker not invoked → getFailureCount must not be called
|
|
344
|
+
expect(getFailureCount).not.toHaveBeenCalled();
|
|
345
|
+
});
|
|
346
|
+
});
|
|
270
347
|
});
|
|
271
348
|
//# sourceMappingURL=pm-promote.test.js.map
|