Merge remote-tracking branch 'origin/main' into feat/247-foreign-workflows-pr2
This commit is contained in:
@@ -263,15 +263,18 @@ test.describe('public chronological history with the actual acknowledged host br
|
||||
});
|
||||
});
|
||||
|
||||
test('a cached dynamic unknown positive stays readable by run UUID and outside the known raw Library scope', async ({ execution }) => {
|
||||
const text = `unknown positive ${randomUUID()}`, graph = recipeGraph({ text, dynamic: true });
|
||||
// #403: the graph cannot show a dynamic positive's raw text; a cached job takes it from the execution it reuses.
|
||||
test('a cached dynamic positive takes its raw text from the execution it reuses and joins the Library scope', async ({ execution }) => {
|
||||
const text = `dynamic positive ${randomUUID()}`, graph = recipeGraph({ text, dynamic: true });
|
||||
const first = await submit(execution.request, graph);await history(execution.request, first);const known = (await capture(execution, first)).contexts[0];
|
||||
const second = await submit(execution.request, graph);await history(execution.request, second);const unknown = (await capture(execution, second)).contexts[0];
|
||||
expect(unknown.positive.raw).toBeNull();expect(unknown.positive.effective).toBe(known.positive.effective);
|
||||
const second = await submit(execution.request, graph);await history(execution.request, second);const reused = await capture(execution, second);const cached = reused.contexts[0];
|
||||
expect(cached.evidence.positive.effective.source).toBe('host_cache_output');expect(cached.positive.effective).toBe(known.positive.effective);
|
||||
expect(cached.positive.raw).toBe(known.positive.raw);expect(cached.evidence.positive.raw).toMatchObject({ provenance: 'inferred', source: 'graph_semantics' });
|
||||
expect(cached.positive_prompt_id).toBe(known.positive_prompt_id);
|
||||
const result = await readExecutionRuns(execution.databasePath, second), runId = result.rows[0].run_id;
|
||||
const detail = await execution.request.get(`/prompt_manager/history/runs/${runId}`);expect(detail.ok()).toBe(true);expect((await detail.json()).contexts[0].positive.raw).toBeNull();
|
||||
const detail = await execution.request.get(`/prompt_manager/history/runs/${runId}`);expect(detail.ok()).toBe(true);expect((await detail.json()).contexts[0].positive.raw).toBe(known.positive.raw);
|
||||
const response = await execution.request.get(`/prompt_manager/library/${known.positive_prompt_id}/history`);expect(response.ok()).toBe(true);const window = await response.json();
|
||||
expect(window.recorded_run_count).toBe(1);expect(window.items.map(item => item.run_id)).not.toContain(runId);
|
||||
expect(window.recorded_run_count).toBe(2);expect(window.items.map(item => item.run_id)).toContain(runId);
|
||||
});
|
||||
|
||||
test('actual PM A,A,B jobs persist two combinations and one identical positive snapshot', async ({ execution }) => {
|
||||
@@ -369,7 +372,7 @@ test('successful source capture survives downstream failure and real interruptio
|
||||
}
|
||||
});
|
||||
|
||||
test('cached dynamic raw stays unknown while literal affixes and effective cache text survive', async ({ execution }) => {
|
||||
test('cached dynamic raw comes from the reused execution while literal affixes and effective cache text survive (#403)', async ({ execution }) => {
|
||||
const graph = recipeGraph({ dynamic: true, text: 'runtime dynamic recipe', prepend: ' pre ', append: ' post ' });
|
||||
const first = await submit(execution.request, graph);
|
||||
await history(execution.request, first);
|
||||
@@ -377,8 +380,9 @@ test('cached dynamic raw stays unknown while literal affixes and effective cache
|
||||
const second = await submit(execution.request, graph);
|
||||
await history(execution.request, second);
|
||||
const value = (await capture(execution, second)).contexts[0];
|
||||
expect(value.positive).toEqual({ raw: null, prepend: ' pre ', append: ' post ', effective: 'pre runtime dynamic recipe post' });
|
||||
expect(value.evidence.positive.raw.provenance).toBe('unknown');
|
||||
expect(value.positive).toEqual({ raw: 'runtime dynamic recipe', prepend: ' pre ', append: ' post ', effective: 'pre runtime dynamic recipe post' });
|
||||
expect(value.evidence.positive.raw).toMatchObject({ provenance: 'inferred', source: 'graph_semantics' });
|
||||
expect(value.evidence.positive.prepend.source).toBe('graph_literal');
|
||||
expect(value.evidence.positive.effective.source).toBe('host_cache_output');
|
||||
});
|
||||
|
||||
|
||||
@@ -287,6 +287,14 @@ async function capturedContext(execution, id) {
|
||||
return result.captures[result.rows[0].run_id].contexts[0];
|
||||
}
|
||||
|
||||
// #403: the prompt's history "tracked runs", once every job's capture reached SQLite.
|
||||
async function expectTrackedRuns(execution, promptId, expected) {
|
||||
await expect.poll(async () => {
|
||||
const response = await execution.request.get(`/prompt_manager/library/${promptId}/history`);
|
||||
return response.ok() ? (await response.json()).recorded_run_count : null;
|
||||
}, { timeout: 10000, message: 'history tracked runs equal the Library run count' }).toBe(expected);
|
||||
}
|
||||
|
||||
async function firstRun(execution, page, testCase) {
|
||||
const prefix = `textlink/${randomUUID()}`;
|
||||
const built = await build(page, { ...testCase, prefix });
|
||||
@@ -309,6 +317,8 @@ for (const kind of ['PromptManager', 'PromptManagerFocused', 'PromptManagerSplit
|
||||
const counts = await runCounts(execution, first.context);
|
||||
expect(counts.positive).toBe(3);
|
||||
if (pair) expect(counts).toMatchObject({ negative: 0, pair: 3 });
|
||||
// #403: the cached jobs are tracked runs of the prompt too
|
||||
await expectTrackedRuns(execution, first.context.positive_prompt_id, 3);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -329,6 +339,7 @@ test.describe('cached runs in one renderer (#347)', () => {
|
||||
else expect(again.cached).toContain(first.promptNode);
|
||||
}
|
||||
expect((await runCounts(execution, first.context)).positive).toBe(3);
|
||||
await expectTrackedRuns(execution, first.context.positive_prompt_id, 3);
|
||||
} finally { await setCache(execution, 'RAM_PRESSURE'); }
|
||||
});
|
||||
}
|
||||
@@ -352,6 +363,9 @@ test.describe('cached runs in one renderer (#347)', () => {
|
||||
const bContext = await capturedContext(execution, second.id);
|
||||
expect(bContext.positive.raw).toBe(b);
|
||||
expect((await runCounts(execution, bContext)).positive).toBe(1);
|
||||
// #403: the third job reuses A's execution, not the newest (B's)
|
||||
await expectTrackedRuns(execution, first.context.positive_prompt_id, 2);
|
||||
await expectTrackedRuns(execution, bContext.positive_prompt_id, 1);
|
||||
} finally { await setCache(execution, 'RAM_PRESSURE'); }
|
||||
});
|
||||
|
||||
@@ -390,10 +404,14 @@ test.describe('cached runs in one renderer (#347)', () => {
|
||||
} });
|
||||
expect(rewired.cached).toContain(first.promptNode);
|
||||
expect((await runCounts(execution, first.context)).positive).toBe(1);
|
||||
// The history capture of a cached job is unchanged: effective text from the cache, no stored-prompt hint
|
||||
// #403: a cached job's history takes the raw text of the execution it reuses and names the prompt
|
||||
const cachedContext = await capturedContext(execution, (await queueAgain(execution, first, { seed: 3 })).id);
|
||||
expect(cachedContext.positive.effective).toBe(first.context.positive.effective);
|
||||
expect(cachedContext.positive_prompt_id).toBeNull();
|
||||
expect(cachedContext.positive.raw).toBe(first.context.positive.raw);
|
||||
expect(cachedContext.evidence.positive.raw).toMatchObject({ provenance: 'inferred', source: 'graph_semantics' });
|
||||
expect(cachedContext.positive_prompt_id).toBe(first.context.positive_prompt_id);
|
||||
expect((await runCounts(execution, first.context)).positive).toBe(2);
|
||||
// The rewired job used the prompt as its negative: neither number counts it
|
||||
await expectTrackedRuns(execution, first.context.positive_prompt_id, 2);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user