@urateam/core 0.1.50 → 0.1.52
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__/agentic-deep-review-provider.test.js +6 -1
- package/dist/__tests__/agentic-deep-review-provider.test.js.map +1 -1
- package/dist/__tests__/audit-session-events.test.d.ts +2 -0
- package/dist/__tests__/audit-session-events.test.d.ts.map +1 -0
- package/dist/__tests__/audit-session-events.test.js +39 -0
- package/dist/__tests__/audit-session-events.test.js.map +1 -0
- package/dist/__tests__/db-migration-agent-session-id.test.d.ts +2 -0
- package/dist/__tests__/db-migration-agent-session-id.test.d.ts.map +1 -0
- package/dist/__tests__/db-migration-agent-session-id.test.js +35 -0
- package/dist/__tests__/db-migration-agent-session-id.test.js.map +1 -0
- package/dist/__tests__/deep-review-resume.test.d.ts +18 -0
- package/dist/__tests__/deep-review-resume.test.d.ts.map +1 -0
- package/dist/__tests__/deep-review-resume.test.js +90 -0
- package/dist/__tests__/deep-review-resume.test.js.map +1 -0
- package/dist/__tests__/execute-stage-session-opts.test.d.ts +17 -0
- package/dist/__tests__/execute-stage-session-opts.test.d.ts.map +1 -0
- package/dist/__tests__/execute-stage-session-opts.test.js +188 -0
- package/dist/__tests__/execute-stage-session-opts.test.js.map +1 -0
- package/dist/__tests__/ralph-handoff-suppression.test.d.ts +2 -0
- package/dist/__tests__/ralph-handoff-suppression.test.d.ts.map +1 -0
- package/dist/__tests__/ralph-handoff-suppression.test.js +37 -0
- package/dist/__tests__/ralph-handoff-suppression.test.js.map +1 -0
- package/dist/__tests__/session-lazy-creation.test.d.ts +17 -0
- package/dist/__tests__/session-lazy-creation.test.d.ts.map +1 -0
- package/dist/__tests__/session-lazy-creation.test.js +146 -0
- package/dist/__tests__/session-lazy-creation.test.js.map +1 -0
- package/dist/__tests__/session-policy.test.d.ts +2 -0
- package/dist/__tests__/session-policy.test.d.ts.map +1 -0
- package/dist/__tests__/session-policy.test.js +44 -0
- package/dist/__tests__/session-policy.test.js.map +1 -0
- package/dist/__tests__/session-resume-fallback.test.d.ts +22 -0
- package/dist/__tests__/session-resume-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/session-resume-fallback.test.js +145 -0
- package/dist/__tests__/session-resume-fallback.test.js.map +1 -0
- package/dist/__tests__/session-resume-flag.test.d.ts +2 -0
- package/dist/__tests__/session-resume-flag.test.d.ts.map +1 -0
- package/dist/__tests__/session-resume-flag.test.js +87 -0
- package/dist/__tests__/session-resume-flag.test.js.map +1 -0
- package/dist/__tests__/session-store.test.d.ts +2 -0
- package/dist/__tests__/session-store.test.d.ts.map +1 -0
- package/dist/__tests__/session-store.test.js +44 -0
- package/dist/__tests__/session-store.test.js.map +1 -0
- package/dist/__tests__/session-volume-check.test.d.ts +2 -0
- package/dist/__tests__/session-volume-check.test.d.ts.map +1 -0
- package/dist/__tests__/session-volume-check.test.js +28 -0
- package/dist/__tests__/session-volume-check.test.js.map +1 -0
- package/dist/__tests__/validate-run-mode.test.d.ts +2 -0
- package/dist/__tests__/validate-run-mode.test.d.ts.map +1 -0
- package/dist/__tests__/validate-run-mode.test.js +102 -0
- package/dist/__tests__/validate-run-mode.test.js.map +1 -0
- package/dist/__tests__/zombie-age-default.test.d.ts +2 -0
- package/dist/__tests__/zombie-age-default.test.d.ts.map +1 -0
- package/dist/__tests__/zombie-age-default.test.js +24 -0
- package/dist/__tests__/zombie-age-default.test.js.map +1 -0
- package/dist/audit/events.d.ts +45 -0
- package/dist/audit/events.d.ts.map +1 -1
- package/dist/audit/events.js +79 -0
- package/dist/audit/events.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +4 -1
- package/dist/db/client.js.map +1 -1
- package/dist/db/schema.d.ts +19 -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/deep-review.d.ts +28 -1
- package/dist/executor/deep-review.d.ts.map +1 -1
- package/dist/executor/deep-review.js +113 -9
- package/dist/executor/deep-review.js.map +1 -1
- package/dist/executor/executor.d.ts +33 -0
- package/dist/executor/executor.d.ts.map +1 -1
- package/dist/executor/executor.js +104 -4
- package/dist/executor/executor.js.map +1 -1
- package/dist/executor/index.d.ts +7 -0
- package/dist/executor/index.d.ts.map +1 -1
- package/dist/executor/index.js +7 -0
- package/dist/executor/index.js.map +1 -1
- package/dist/executor/prompt/assembler.d.ts +7 -1
- package/dist/executor/prompt/assembler.d.ts.map +1 -1
- package/dist/executor/prompt/assembler.js +9 -3
- package/dist/executor/prompt/assembler.js.map +1 -1
- package/dist/executor/prompt/templates.d.ts +25 -6
- package/dist/executor/prompt/templates.d.ts.map +1 -1
- package/dist/executor/prompt/templates.js +21 -12
- package/dist/executor/prompt/templates.js.map +1 -1
- package/dist/executor/review/agentic-deep-review.d.ts.map +1 -1
- package/dist/executor/review/agentic-deep-review.js +15 -1
- package/dist/executor/review/agentic-deep-review.js.map +1 -1
- package/dist/executor/review/review-provider.d.ts +21 -0
- package/dist/executor/review/review-provider.d.ts.map +1 -1
- package/dist/executor/review/review-provider.js.map +1 -1
- package/dist/executor/session-policy.d.ts +38 -0
- package/dist/executor/session-policy.d.ts.map +1 -0
- package/dist/executor/session-policy.js +66 -0
- package/dist/executor/session-policy.js.map +1 -0
- package/dist/executor/session-store.d.ts +32 -0
- package/dist/executor/session-store.d.ts.map +1 -0
- package/dist/executor/session-store.js +38 -0
- package/dist/executor/session-store.js.map +1 -0
- package/dist/executor/validate.d.ts +20 -1
- package/dist/executor/validate.d.ts.map +1 -1
- package/dist/executor/validate.js +16 -1
- package/dist/executor/validate.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/runner.d.ts.map +1 -1
- package/dist/pipeline/runner.js +139 -6
- package/dist/pipeline/runner.js.map +1 -1
- package/dist/pipeline/session-volume-check.d.ts +38 -0
- package/dist/pipeline/session-volume-check.d.ts.map +1 -0
- package/dist/pipeline/session-volume-check.js +45 -0
- package/dist/pipeline/session-volume-check.js.map +1 -0
- package/dist/pm/scheduler.d.ts +14 -0
- package/dist/pm/scheduler.d.ts.map +1 -1
- package/dist/pm/scheduler.js +9 -5
- package/dist/pm/scheduler.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +16 -0
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BEC-231 — Lazy / retry SDK session creation.
|
|
3
|
+
*
|
|
4
|
+
* Reproduces the production bug surfaced during the BEC-227 Phase 2 dogfood
|
|
5
|
+
* soak: when the first resumable stage's SDK call fails before any JSONL
|
|
6
|
+
* message is written (auth 401, pre-stream stall, etc.), subsequent stages
|
|
7
|
+
* MUST retry the create path (`sessionId:`) rather than blindly using
|
|
8
|
+
* `resume:` against a transcript that never materialized.
|
|
9
|
+
*
|
|
10
|
+
* The pre-BEC-231 implementation used an in-memory `hasInitiatedSession` flag
|
|
11
|
+
* (flipped after the first resumable stage's CALL, not after the SDK actually
|
|
12
|
+
* wrote a message). The new implementation derives the shape from
|
|
13
|
+
* `transcriptExists()` on every stage entry, so a stage 2 invocation against
|
|
14
|
+
* a non-existent JSONL re-attempts creation.
|
|
15
|
+
*/
|
|
16
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
17
|
+
// ── Module mocks (declared before imports) ────────────────────────────────────
|
|
18
|
+
vi.mock("@anthropic-ai/claude-agent-sdk", () => ({
|
|
19
|
+
query: vi.fn(),
|
|
20
|
+
}));
|
|
21
|
+
vi.mock("../executor/auth-check.js", () => ({
|
|
22
|
+
isClaudeAuthValid: vi.fn().mockResolvedValue(true),
|
|
23
|
+
resolveClaudeAuth: vi.fn().mockReturnValue({ method: "session" }),
|
|
24
|
+
}));
|
|
25
|
+
vi.mock("../executor/extract-handoff.js", () => ({
|
|
26
|
+
extractHandoff: vi.fn().mockResolvedValue({
|
|
27
|
+
artifact: {
|
|
28
|
+
runId: "run-bec231",
|
|
29
|
+
issueId: "BEC-231",
|
|
30
|
+
stage: "implement",
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
summary: "Stub handoff",
|
|
33
|
+
filesChanged: [],
|
|
34
|
+
approach: "Stub",
|
|
35
|
+
context: { issueIntent: "x", constraints: [], assumptions: [] },
|
|
36
|
+
tokenBudget: { contextTokensUsed: 0, recommendedMaxTurns: 1 },
|
|
37
|
+
},
|
|
38
|
+
structured: true,
|
|
39
|
+
}),
|
|
40
|
+
}));
|
|
41
|
+
const { transcriptExistsMock } = vi.hoisted(() => ({
|
|
42
|
+
transcriptExistsMock: vi.fn(),
|
|
43
|
+
}));
|
|
44
|
+
vi.mock("../executor/session-store.js", async () => {
|
|
45
|
+
const real = await vi.importActual("../executor/session-store.js");
|
|
46
|
+
return {
|
|
47
|
+
...real,
|
|
48
|
+
transcriptExists: transcriptExistsMock,
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
// ── Imports ───────────────────────────────────────────────────────────────────
|
|
52
|
+
import { executeStage } from "../executor/executor.js";
|
|
53
|
+
import { createDb } from "../db/client.js";
|
|
54
|
+
import { pipelineRuns } from "../db/schema.js";
|
|
55
|
+
// ── Fixtures ──────────────────────────────────────────────────────────────────
|
|
56
|
+
const testIssue = {
|
|
57
|
+
id: "BEC-231",
|
|
58
|
+
slug: "lazy-session-creation",
|
|
59
|
+
title: "BEC-231 lazy session creation",
|
|
60
|
+
description: "Verify session shape is derived from on-disk state",
|
|
61
|
+
acceptanceCriteria: ["transcriptExists drives sessionId vs resume choice"],
|
|
62
|
+
labels: ["bug"],
|
|
63
|
+
priority: 2,
|
|
64
|
+
};
|
|
65
|
+
const testRepoConfig = {
|
|
66
|
+
url: "https://github.com/test-org/test-repo",
|
|
67
|
+
defaultBranch: "main",
|
|
68
|
+
testCommand: "echo ok",
|
|
69
|
+
buildCommand: "echo ok",
|
|
70
|
+
};
|
|
71
|
+
async function seedPipelineRun(db, runId) {
|
|
72
|
+
await db.insert(pipelineRuns).values({
|
|
73
|
+
id: runId,
|
|
74
|
+
issueId: testIssue.id,
|
|
75
|
+
issueTitle: testIssue.title,
|
|
76
|
+
pipelineKey: "auto-implement",
|
|
77
|
+
repoUrl: testRepoConfig.url,
|
|
78
|
+
branch: `agent/${runId}`,
|
|
79
|
+
status: "running",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function makeMinimalStream() {
|
|
83
|
+
return (async function* () {
|
|
84
|
+
yield { type: "assistant", content: [{ type: "text", text: "done" }] };
|
|
85
|
+
})();
|
|
86
|
+
}
|
|
87
|
+
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
88
|
+
describe("BEC-231 — lazy session creation derives shape from transcriptExists()", () => {
|
|
89
|
+
let db;
|
|
90
|
+
beforeEach(async () => {
|
|
91
|
+
db = await createDb({ connectionString: ":memory:" });
|
|
92
|
+
vi.clearAllMocks();
|
|
93
|
+
});
|
|
94
|
+
it("isFirstResumableStage=false BUT transcript absent → retries create (sessionId:), not resume:", async () => {
|
|
95
|
+
// This is the exact bug pattern: a "second" stage gets called with
|
|
96
|
+
// isFirstResumableStage=false (because the runner's in-memory flag
|
|
97
|
+
// believed the first stage initiated the session) but the JSONL was
|
|
98
|
+
// never written (first stage failed at auth before any SDK message).
|
|
99
|
+
// Pre-BEC-231: routed to resume:, found JSONL missing, dropped to
|
|
100
|
+
// legacy fresh-session-no-opts, lost the session permanently.
|
|
101
|
+
// Post-BEC-231: routes to sessionId: → SDK creates the session now.
|
|
102
|
+
const { query } = await import("@anthropic-ai/claude-agent-sdk");
|
|
103
|
+
query.mockReturnValue(makeMinimalStream());
|
|
104
|
+
transcriptExistsMock.mockReturnValue(false);
|
|
105
|
+
await seedPipelineRun(db, "run-bec231-stage2-recreate");
|
|
106
|
+
await executeStage({
|
|
107
|
+
runId: "run-bec231-stage2-recreate",
|
|
108
|
+
issueId: testIssue.id,
|
|
109
|
+
stage: "implement",
|
|
110
|
+
sanitizedIssue: testIssue,
|
|
111
|
+
repoConfig: testRepoConfig,
|
|
112
|
+
workdir: "/tmp/bec231-workdir",
|
|
113
|
+
db,
|
|
114
|
+
agentSessionId: "uuid-bec231",
|
|
115
|
+
isFirstResumableStage: false,
|
|
116
|
+
});
|
|
117
|
+
const opts = query.mock.calls[0][0].options;
|
|
118
|
+
expect(opts.sessionId).toBe("uuid-bec231");
|
|
119
|
+
expect(opts.resume).toBeUndefined();
|
|
120
|
+
});
|
|
121
|
+
it("isFirstResumableStage=true AND transcript present → resumes (transcriptExists wins over the flag)", async () => {
|
|
122
|
+
// Symmetric case: the runner says "this is the first resumable stage"
|
|
123
|
+
// but the JSONL actually already exists (e.g. retriable resume after a
|
|
124
|
+
// restart that lost the in-memory flag). BEC-231 still routes to
|
|
125
|
+
// resume: because the transcript is on disk.
|
|
126
|
+
const { query } = await import("@anthropic-ai/claude-agent-sdk");
|
|
127
|
+
query.mockReturnValue(makeMinimalStream());
|
|
128
|
+
transcriptExistsMock.mockReturnValue(true);
|
|
129
|
+
await seedPipelineRun(db, "run-bec231-restarted");
|
|
130
|
+
await executeStage({
|
|
131
|
+
runId: "run-bec231-restarted",
|
|
132
|
+
issueId: testIssue.id,
|
|
133
|
+
stage: "implement",
|
|
134
|
+
sanitizedIssue: testIssue,
|
|
135
|
+
repoConfig: testRepoConfig,
|
|
136
|
+
workdir: "/tmp/bec231-workdir",
|
|
137
|
+
db,
|
|
138
|
+
agentSessionId: "uuid-bec231-existing",
|
|
139
|
+
isFirstResumableStage: true,
|
|
140
|
+
});
|
|
141
|
+
const opts = query.mock.calls[0][0].options;
|
|
142
|
+
expect(opts.resume).toBe("uuid-bec231-existing");
|
|
143
|
+
expect(opts.sessionId).toBeUndefined();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=session-lazy-creation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-lazy-creation.test.js","sourceRoot":"","sources":["../../src/__tests__/session-lazy-creation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-policy.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/session-policy.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { isResumable, isAlwaysFreshStage, ALWAYS_FRESH_STAGES } from "../executor/session-policy.js";
|
|
3
|
+
describe("session-policy (BEC-227)", () => {
|
|
4
|
+
describe("isAlwaysFreshStage", () => {
|
|
5
|
+
it("validate stage is always fresh", () => {
|
|
6
|
+
expect(isAlwaysFreshStage("validate")).toBe(true);
|
|
7
|
+
});
|
|
8
|
+
it("ralph-check stage is always fresh", () => {
|
|
9
|
+
expect(isAlwaysFreshStage("ralph-check")).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
it("implement stage is NOT always fresh", () => {
|
|
12
|
+
expect(isAlwaysFreshStage("implement")).toBe(false);
|
|
13
|
+
});
|
|
14
|
+
it("ALWAYS_FRESH_STAGES set is exposed and immutable from caller's perspective", () => {
|
|
15
|
+
expect(ALWAYS_FRESH_STAGES.has("validate")).toBe(true);
|
|
16
|
+
expect(ALWAYS_FRESH_STAGES.has("implement")).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe("isResumable", () => {
|
|
20
|
+
it("Sonnet on implement → resumable", () => {
|
|
21
|
+
expect(isResumable("implement", "claude-sonnet-4-6")).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
it("Opus on implement → resumable (same family)", () => {
|
|
24
|
+
expect(isResumable("implement", "claude-opus-4-7")).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
it("Haiku on implement → not resumable (different family)", () => {
|
|
27
|
+
expect(isResumable("implement", "claude-haiku-4-5")).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
it("any model on validate → not resumable", () => {
|
|
30
|
+
expect(isResumable("validate", "claude-sonnet-4-6")).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
it("Sonnet on review → resumable", () => {
|
|
33
|
+
expect(isResumable("review", "claude-sonnet-4-6")).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it("Sonnet on deep-review → resumable", () => {
|
|
36
|
+
expect(isResumable("deep-review", "claude-sonnet-4-6")).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
it("non-Claude model → not resumable", () => {
|
|
39
|
+
expect(isResumable("review", "qwen/qwen-3-plus")).toBe(false);
|
|
40
|
+
expect(isResumable("review", "openai/gpt-oss-120b")).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=session-policy.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-policy.test.js","sourceRoot":"","sources":["../../src/__tests__/session-policy.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAErG,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;YACpF,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,CAAC,WAAW,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9D,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for BEC-227 Task 7, AS UPDATED BY BEC-231 (lazy session creation).
|
|
3
|
+
*
|
|
4
|
+
* Original BEC-227 design (T7): when `isFirstResumableStage=false` AND the
|
|
5
|
+
* JSONL is missing, drop to fresh-session shape (no opts) + emit
|
|
6
|
+
* `missing_fallback` audit event. The bug: the in-memory `hasInitiatedSession`
|
|
7
|
+
* flag flipped after the first stage's CALL, not after the SDK actually wrote
|
|
8
|
+
* the JSONL. If the first stage failed (auth 401, etc.) before writing, every
|
|
9
|
+
* later stage thought "session initiated; use resume:" but the JSONL didn't
|
|
10
|
+
* exist, so they all dropped to fresh-session-with-no-opts — losing the
|
|
11
|
+
* session permanently for the run's lifetime.
|
|
12
|
+
*
|
|
13
|
+
* BEC-231 fix: derive the shape from on-disk state, not from the in-memory
|
|
14
|
+
* flag. JSONL present → `resume:`. JSONL absent → `sessionId:` (retries
|
|
15
|
+
* creation). The `missing_fallback` audit event is no longer emitted from
|
|
16
|
+
* the executor — the new logic always picks the right shape.
|
|
17
|
+
*
|
|
18
|
+
* This test now verifies the new behavior: missing JSONL → SDK call shape
|
|
19
|
+
* is `{ sessionId: <uuid> }` (the create/retry path), NOT empty opts.
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=session-resume-fallback.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-resume-fallback.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/session-resume-fallback.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for BEC-227 Task 7, AS UPDATED BY BEC-231 (lazy session creation).
|
|
3
|
+
*
|
|
4
|
+
* Original BEC-227 design (T7): when `isFirstResumableStage=false` AND the
|
|
5
|
+
* JSONL is missing, drop to fresh-session shape (no opts) + emit
|
|
6
|
+
* `missing_fallback` audit event. The bug: the in-memory `hasInitiatedSession`
|
|
7
|
+
* flag flipped after the first stage's CALL, not after the SDK actually wrote
|
|
8
|
+
* the JSONL. If the first stage failed (auth 401, etc.) before writing, every
|
|
9
|
+
* later stage thought "session initiated; use resume:" but the JSONL didn't
|
|
10
|
+
* exist, so they all dropped to fresh-session-with-no-opts — losing the
|
|
11
|
+
* session permanently for the run's lifetime.
|
|
12
|
+
*
|
|
13
|
+
* BEC-231 fix: derive the shape from on-disk state, not from the in-memory
|
|
14
|
+
* flag. JSONL present → `resume:`. JSONL absent → `sessionId:` (retries
|
|
15
|
+
* creation). The `missing_fallback` audit event is no longer emitted from
|
|
16
|
+
* the executor — the new logic always picks the right shape.
|
|
17
|
+
*
|
|
18
|
+
* This test now verifies the new behavior: missing JSONL → SDK call shape
|
|
19
|
+
* is `{ sessionId: <uuid> }` (the create/retry path), NOT empty opts.
|
|
20
|
+
*/
|
|
21
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
22
|
+
// ── Module mocks (declared before imports) ────────────────────────────────────
|
|
23
|
+
vi.mock("@anthropic-ai/claude-agent-sdk", () => ({
|
|
24
|
+
query: vi.fn(),
|
|
25
|
+
}));
|
|
26
|
+
vi.mock("../executor/auth-check.js", () => ({
|
|
27
|
+
isClaudeAuthValid: vi.fn().mockResolvedValue(true),
|
|
28
|
+
resolveClaudeAuth: vi.fn().mockReturnValue({ method: "session" }),
|
|
29
|
+
}));
|
|
30
|
+
vi.mock("../executor/extract-handoff.js", () => ({
|
|
31
|
+
extractHandoff: vi.fn().mockResolvedValue({
|
|
32
|
+
artifact: {
|
|
33
|
+
runId: "run-bec227-t7",
|
|
34
|
+
issueId: "BEC-227",
|
|
35
|
+
stage: "implement",
|
|
36
|
+
timestamp: new Date().toISOString(),
|
|
37
|
+
summary: "Stub handoff",
|
|
38
|
+
filesChanged: [],
|
|
39
|
+
approach: "Stub",
|
|
40
|
+
context: { issueIntent: "x", constraints: [], assumptions: [] },
|
|
41
|
+
tokenBudget: { contextTokensUsed: 0, recommendedMaxTurns: 1 },
|
|
42
|
+
},
|
|
43
|
+
structured: true,
|
|
44
|
+
}),
|
|
45
|
+
}));
|
|
46
|
+
vi.mock("../executor/session-store.js", async () => {
|
|
47
|
+
const real = await vi.importActual("../executor/session-store.js");
|
|
48
|
+
return {
|
|
49
|
+
...real,
|
|
50
|
+
// Force the transcript-not-found path so the fallback branch fires.
|
|
51
|
+
transcriptExists: vi.fn().mockReturnValue(false),
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
const { logAuditEventMock } = vi.hoisted(() => ({
|
|
55
|
+
logAuditEventMock: vi.fn().mockResolvedValue(undefined),
|
|
56
|
+
}));
|
|
57
|
+
vi.mock("../audit/writer.js", async () => {
|
|
58
|
+
const real = await vi.importActual("../audit/writer.js");
|
|
59
|
+
return {
|
|
60
|
+
...real,
|
|
61
|
+
logAuditEvent: logAuditEventMock,
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
// ── Imports ───────────────────────────────────────────────────────────────────
|
|
65
|
+
import { executeStage } from "../executor/executor.js";
|
|
66
|
+
import { createDb } from "../db/client.js";
|
|
67
|
+
import { pipelineRuns } from "../db/schema.js";
|
|
68
|
+
// ── Fixtures ──────────────────────────────────────────────────────────────────
|
|
69
|
+
const testIssue = {
|
|
70
|
+
id: "BEC-227",
|
|
71
|
+
slug: "agent-session-continuity",
|
|
72
|
+
title: "Agent session continuity Phase 1",
|
|
73
|
+
description: "Resume fallback when JSONL is missing",
|
|
74
|
+
acceptanceCriteria: ["fallback to fresh session on missing JSONL"],
|
|
75
|
+
labels: ["auto-implement"],
|
|
76
|
+
priority: 4,
|
|
77
|
+
};
|
|
78
|
+
const testRepoConfig = {
|
|
79
|
+
url: "https://github.com/test-org/test-repo",
|
|
80
|
+
defaultBranch: "main",
|
|
81
|
+
testCommand: "echo ok",
|
|
82
|
+
buildCommand: "echo ok",
|
|
83
|
+
};
|
|
84
|
+
async function seedPipelineRun(db, runId) {
|
|
85
|
+
await db.insert(pipelineRuns).values({
|
|
86
|
+
id: runId,
|
|
87
|
+
issueId: testIssue.id,
|
|
88
|
+
issueTitle: testIssue.title,
|
|
89
|
+
pipelineKey: "auto-implement",
|
|
90
|
+
repoUrl: testRepoConfig.url,
|
|
91
|
+
branch: `agent/${runId}`,
|
|
92
|
+
status: "running",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function makeMinimalStream() {
|
|
96
|
+
return (async function* () {
|
|
97
|
+
yield {
|
|
98
|
+
type: "assistant",
|
|
99
|
+
content: [{ type: "text", text: "done" }],
|
|
100
|
+
};
|
|
101
|
+
})();
|
|
102
|
+
}
|
|
103
|
+
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
104
|
+
describe("executeStage — lazy session creation when JSONL absent (BEC-231 update of BEC-227 T7)", () => {
|
|
105
|
+
let db;
|
|
106
|
+
beforeEach(async () => {
|
|
107
|
+
db = await createDb({ connectionString: ":memory:" });
|
|
108
|
+
vi.clearAllMocks();
|
|
109
|
+
logAuditEventMock.mockClear();
|
|
110
|
+
logAuditEventMock.mockResolvedValue(undefined);
|
|
111
|
+
});
|
|
112
|
+
it("transcript missing → retries session creation (sessionId set), does NOT emit missing_fallback (BEC-231)", async () => {
|
|
113
|
+
const { query } = await import("@anthropic-ai/claude-agent-sdk");
|
|
114
|
+
query.mockReturnValue(makeMinimalStream());
|
|
115
|
+
await seedPipelineRun(db, "run-bec231-retry-create");
|
|
116
|
+
// Even though the caller passes isFirstResumableStage=false (the old
|
|
117
|
+
// pre-BEC-231 callers do this for non-first stages), the new logic checks
|
|
118
|
+
// transcriptExists() and routes to sessionId: when it returns false.
|
|
119
|
+
await executeStage({
|
|
120
|
+
runId: "run-bec231-retry-create",
|
|
121
|
+
issueId: testIssue.id,
|
|
122
|
+
stage: "implement",
|
|
123
|
+
sanitizedIssue: testIssue,
|
|
124
|
+
repoConfig: testRepoConfig,
|
|
125
|
+
workdir: "/nonexistent/path/bec231",
|
|
126
|
+
db,
|
|
127
|
+
agentSessionId: "uuid-bec231-recreate",
|
|
128
|
+
isFirstResumableStage: false, // ← ignored under BEC-231
|
|
129
|
+
});
|
|
130
|
+
expect(query).toHaveBeenCalledOnce();
|
|
131
|
+
const opts = query.mock.calls[0][0].options;
|
|
132
|
+
// BEC-231: when JSONL is absent, we (re-)create with sessionId: rather
|
|
133
|
+
// than dropping to legacy fresh-session shape.
|
|
134
|
+
expect(opts.sessionId).toBe("uuid-bec231-recreate");
|
|
135
|
+
expect(opts.resume).toBeUndefined();
|
|
136
|
+
// BEC-231: missing_fallback audit event is no longer emitted from the
|
|
137
|
+
// executor — the new logic always picks the right shape.
|
|
138
|
+
const fallbackCall = logAuditEventMock.mock.calls.find((call) => call[1]?.eventType === "pipeline.agent_session_missing_fallback");
|
|
139
|
+
expect(fallbackCall).toBeUndefined();
|
|
140
|
+
// resumed event is also not emitted (we're creating, not resuming).
|
|
141
|
+
const resumedCall = logAuditEventMock.mock.calls.find((call) => call[1]?.eventType === "pipeline.agent_session_resumed");
|
|
142
|
+
expect(resumedCall).toBeUndefined();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
//# sourceMappingURL=session-resume-fallback.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-resume-fallback.test.js","sourceRoot":"","sources":["../../src/__tests__/session-resume-fallback.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-resume-flag.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/session-resume-flag.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { eq } from "drizzle-orm";
|
|
3
|
+
import { createDb } from "../db/client.js";
|
|
4
|
+
import { pipelineRuns } from "../db/schema.js";
|
|
5
|
+
/**
|
|
6
|
+
* BEC-227 — Task 5 verification.
|
|
7
|
+
*
|
|
8
|
+
* `runner.start()` mints an `agent_session_id` UUID and persists it on the
|
|
9
|
+
* `pipeline_runs` row when `URATEAM_ENABLE_AGENT_SESSION_RESUME=true`. This
|
|
10
|
+
* test simulates the row state directly (rather than invoking `start()`
|
|
11
|
+
* which requires reconstructing 6 positional params + a queue + executor)
|
|
12
|
+
* and asserts the column behaviour — the runner-level integration is
|
|
13
|
+
* verified by typecheck + existing pipeline tests.
|
|
14
|
+
*/
|
|
15
|
+
describe("agent_session_id minting (BEC-227)", () => {
|
|
16
|
+
let originalEnv;
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
originalEnv = process.env.URATEAM_ENABLE_AGENT_SESSION_RESUME;
|
|
19
|
+
});
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
if (originalEnv === undefined) {
|
|
22
|
+
delete process.env.URATEAM_ENABLE_AGENT_SESSION_RESUME;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
process.env.URATEAM_ENABLE_AGENT_SESSION_RESUME = originalEnv;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
it("flag on → mints UUID and persists on pipeline_runs row", async () => {
|
|
29
|
+
process.env.URATEAM_ENABLE_AGENT_SESSION_RESUME = "true";
|
|
30
|
+
const db = await createDb({ driver: "sqlite", connectionString: ":memory:" });
|
|
31
|
+
const runId = "test-run-with-session";
|
|
32
|
+
await db.insert(pipelineRuns).values({
|
|
33
|
+
id: runId,
|
|
34
|
+
issueId: "BEC-227",
|
|
35
|
+
issueTitle: "test",
|
|
36
|
+
repoUrl: "https://example.com/repo",
|
|
37
|
+
pipelineKey: "auto-implement",
|
|
38
|
+
status: "queued",
|
|
39
|
+
startedAt: new Date(),
|
|
40
|
+
agentSessionId: "expected-uuid", // simulate what start() writes
|
|
41
|
+
});
|
|
42
|
+
const [row] = await db
|
|
43
|
+
.select()
|
|
44
|
+
.from(pipelineRuns)
|
|
45
|
+
.where(eq(pipelineRuns.id, runId));
|
|
46
|
+
expect(row.agentSessionId).toBe("expected-uuid");
|
|
47
|
+
});
|
|
48
|
+
it("flag off → agentSessionId stays null", async () => {
|
|
49
|
+
delete process.env.URATEAM_ENABLE_AGENT_SESSION_RESUME;
|
|
50
|
+
const db = await createDb({ driver: "sqlite", connectionString: ":memory:" });
|
|
51
|
+
const runId = "test-run-legacy";
|
|
52
|
+
await db.insert(pipelineRuns).values({
|
|
53
|
+
id: runId,
|
|
54
|
+
issueId: "BEC-227",
|
|
55
|
+
issueTitle: "test",
|
|
56
|
+
repoUrl: "https://example.com/repo",
|
|
57
|
+
pipelineKey: "auto-implement",
|
|
58
|
+
status: "queued",
|
|
59
|
+
startedAt: new Date(),
|
|
60
|
+
});
|
|
61
|
+
const [row] = await db
|
|
62
|
+
.select()
|
|
63
|
+
.from(pipelineRuns)
|
|
64
|
+
.where(eq(pipelineRuns.id, runId));
|
|
65
|
+
expect(row.agentSessionId).toBeNull();
|
|
66
|
+
});
|
|
67
|
+
it("isAgentSessionResumeEnabled reads env at call time (strict equality 'true')", async () => {
|
|
68
|
+
const { isAgentSessionResumeEnabled } = await import("../executor/session-policy.js");
|
|
69
|
+
expect(isAgentSessionResumeEnabled({
|
|
70
|
+
URATEAM_ENABLE_AGENT_SESSION_RESUME: "true",
|
|
71
|
+
})).toBe(true);
|
|
72
|
+
expect(isAgentSessionResumeEnabled({
|
|
73
|
+
URATEAM_ENABLE_AGENT_SESSION_RESUME: "1",
|
|
74
|
+
})).toBe(false);
|
|
75
|
+
expect(isAgentSessionResumeEnabled({
|
|
76
|
+
URATEAM_ENABLE_AGENT_SESSION_RESUME: "yes",
|
|
77
|
+
})).toBe(false);
|
|
78
|
+
expect(isAgentSessionResumeEnabled({
|
|
79
|
+
URATEAM_ENABLE_AGENT_SESSION_RESUME: "TRUE",
|
|
80
|
+
})).toBe(false);
|
|
81
|
+
expect(isAgentSessionResumeEnabled({
|
|
82
|
+
URATEAM_ENABLE_AGENT_SESSION_RESUME: "",
|
|
83
|
+
})).toBe(false);
|
|
84
|
+
expect(isAgentSessionResumeEnabled({})).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=session-resume-flag.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-resume-flag.test.js","sourceRoot":"","sources":["../../src/__tests__/session-resume-flag.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAc,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;;;;GASG;AACH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,IAAI,WAA+B,CAAC;IACpC,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;IAChE,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,mCAAmC,GAAG,WAAW,CAAC;QAChE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,OAAO,CAAC,GAAG,CAAC,mCAAmC,GAAG,MAAM,CAAC;QACzD,MAAM,EAAE,GAAU,MAAM,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,CAAC;QACrF,MAAM,KAAK,GAAG,uBAAuB,CAAC;QACtC,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC;YACnC,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,SAAS;YAClB,UAAU,EAAE,MAAM;YAClB,OAAO,EAAE,0BAA0B;YACnC,WAAW,EAAE,gBAAgB;YAC7B,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,cAAc,EAAE,eAAe,EAAE,+BAA+B;SACjE,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;aACnB,MAAM,EAAE;aACR,IAAI,CAAC,YAAY,CAAC;aAClB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,GAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,OAAO,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;QACvD,MAAM,EAAE,GAAU,MAAM,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,CAAC;QACrF,MAAM,KAAK,GAAG,iBAAiB,CAAC;QAChC,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC;YACnC,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,SAAS;YAClB,UAAU,EAAE,MAAM;YAClB,OAAO,EAAE,0BAA0B;YACnC,WAAW,EAAE,gBAAgB;YAC7B,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;aACnB,MAAM,EAAE;aACR,IAAI,CAAC,YAAY,CAAC;aAClB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,GAAI,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,EAAE,2BAA2B,EAAE,GAAG,MAAM,MAAM,CAClD,+BAA+B,CAChC,CAAC;QACF,MAAM,CACJ,2BAA2B,CAAC;YAC1B,mCAAmC,EAAE,MAAM;SAC5C,CAAC,CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,MAAM,CACJ,2BAA2B,CAAC;YAC1B,mCAAmC,EAAE,GAAG;SACzC,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,MAAM,CACJ,2BAA2B,CAAC;YAC1B,mCAAmC,EAAE,KAAK;SAC3C,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,MAAM,CACJ,2BAA2B,CAAC;YAC1B,mCAAmC,EAAE,MAAM;SAC5C,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,MAAM,CACJ,2BAA2B,CAAC;YAC1B,mCAAmC,EAAE,EAAE;SACxC,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,MAAM,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/session-store.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { transcriptPath, transcriptExists } from "../executor/session-store.js";
|
|
6
|
+
let tmpRoot;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
tmpRoot = mkdtempSync(join(tmpdir(), "urateam-session-store-test-"));
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
12
|
+
});
|
|
13
|
+
describe("session-store (BEC-227)", () => {
|
|
14
|
+
it("transcriptPath builds the expected per-cwd / per-session path", () => {
|
|
15
|
+
const p = transcriptPath({
|
|
16
|
+
projectsRoot: tmpRoot,
|
|
17
|
+
cwd: "/home/ura/data/runs/abc/worktree",
|
|
18
|
+
sessionId: "uuid-1",
|
|
19
|
+
});
|
|
20
|
+
// Per SDK convention: projectsRoot / <encoded-cwd> / <sessionId>.jsonl
|
|
21
|
+
expect(p).toMatch(/uuid-1\.jsonl$/);
|
|
22
|
+
expect(p).toContain(tmpRoot);
|
|
23
|
+
});
|
|
24
|
+
it("transcriptExists returns true when the JSONL file is present", () => {
|
|
25
|
+
const dir = join(tmpRoot, "encoded-cwd");
|
|
26
|
+
mkdirSync(dir, { recursive: true });
|
|
27
|
+
writeFileSync(join(dir, "uuid-1.jsonl"), '{"message":"hi"}\n');
|
|
28
|
+
const exists = transcriptExists({
|
|
29
|
+
projectsRoot: tmpRoot,
|
|
30
|
+
cwd: "/encoded-cwd",
|
|
31
|
+
sessionId: "uuid-1",
|
|
32
|
+
});
|
|
33
|
+
expect(exists).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it("transcriptExists returns false when missing", () => {
|
|
36
|
+
const exists = transcriptExists({
|
|
37
|
+
projectsRoot: tmpRoot,
|
|
38
|
+
cwd: "/nonexistent",
|
|
39
|
+
sessionId: "uuid-missing",
|
|
40
|
+
});
|
|
41
|
+
expect(exists).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=session-store.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.test.js","sourceRoot":"","sources":["../../src/__tests__/session-store.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAM,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAc,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhF,IAAI,OAAe,CAAC;AAEpB,UAAU,CAAC,GAAG,EAAE;IACd,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,6BAA6B,CAAC,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AACH,SAAS,CAAC,GAAG,EAAE;IACb,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,GAAG,cAAc,CAAC;YACvB,YAAY,EAAE,OAAO;YACrB,GAAG,EAAE,kCAAkC;YACvC,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QACH,uEAAuE;QACvE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACpC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACzC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,gBAAgB,CAAC;YAC9B,YAAY,EAAE,OAAO;YACrB,GAAG,EAAE,cAAc;YACnB,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,gBAAgB,CAAC;YAC9B,YAAY,EAAE,OAAO;YACrB,GAAG,EAAE,cAAc;YACnB,SAAS,EAAE,cAAc;SAC1B,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-volume-check.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/session-volume-check.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { checkSessionVolume } from "../pipeline/session-volume-check.js";
|
|
6
|
+
let dir;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
dir = mkdtempSync(join(tmpdir(), "vol-check-"));
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
rmSync(dir, { recursive: true, force: true });
|
|
12
|
+
});
|
|
13
|
+
describe("checkSessionVolume (BEC-227)", () => {
|
|
14
|
+
it("writeable persistent dir → returns ok", () => {
|
|
15
|
+
const result = checkSessionVolume({ projectsDir: dir });
|
|
16
|
+
expect(result.ok).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
it("nonexistent dir → returns not-found", () => {
|
|
19
|
+
const result = checkSessionVolume({
|
|
20
|
+
projectsDir: "/totally/not/a/real/path/asdf",
|
|
21
|
+
});
|
|
22
|
+
expect(result.ok).toBe(false);
|
|
23
|
+
if (!result.ok) {
|
|
24
|
+
expect(result.reason).toBe("not-found");
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=session-volume-check.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-volume-check.test.js","sourceRoot":"","sources":["../../src/__tests__/session-volume-check.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE,IAAI,GAAW,CAAC;AAChB,UAAU,CAAC,GAAG,EAAE;IACd,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;AAClD,CAAC,CAAC,CAAC;AACH,SAAS,CAAC,GAAG,EAAE;IACb,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,MAAM,GAAG,kBAAkB,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,kBAAkB,CAAC;YAChC,WAAW,EAAE,+BAA+B;SAC7C,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-run-mode.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validate-run-mode.test.ts"],"names":[],"mappings":""}
|