Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import type { SessionHeader, StoredMessage } from '@maka/core/session';
import { agentGraphIdForRootSession } from '@maka/runtime/stream-graph-coordinator';
import { collectConversationCopyLinkedChildReferences } from '@maka/runtime/conversation-copy';
import {
agentGraphRevisionAdmissionSessionIds,
prepareAgentGraphRevisionReferences,
linkedChildCopyAdmissionSessionIds,
prepareLinkedChildCopyReferences,
} from '../server/session-revision-graph-references.js';

const ROOT_SESSION_ID = 'root-session';
Expand Down Expand Up @@ -60,35 +60,25 @@ test('Agent Graph revision references preserve only exact terminal provenance',
const accepted = await prepare();
assert.equal(accepted.ok, true);
if (!accepted.ok) assert.fail('Expected accepted Graph references');
assert.deepEqual([...accepted.references.get(CHILD_SESSION_ID)!.runIds], [CHILD_RUN_ID]);
assert.deepEqual(
[...accepted.references.get(CHILD_SESSION_ID)!.artifactIds],
[CHILD_ARTIFACT_ID],
);

const archived = await prepare({
messages: [],
archivedResults: [JSON.stringify(linkedResult().content)],
});
assert.equal(archived.ok, true);
});

test('Side Conversation references accept terminal linked children as snapshots', async () => {
const accepted = await prepare({ kind: 'side_conversation' });
assert.equal(accepted.ok, true);
if (!accepted.ok) assert.fail('Expected accepted Side Conversation references');
assert.deepEqual([...accepted.references.keys()], [CHILD_SESSION_ID]);
assert.deepEqual([...accepted.shared.get(CHILD_SESSION_ID)!.runIds], [CHILD_RUN_ID]);
assert.deepEqual([...accepted.shared.get(CHILD_SESSION_ID)!.artifactIds], [CHILD_ARTIFACT_ID]);
assert.equal(accepted.snapshots.size, 0);
});

test('Side Conversation references accept terminal non-Graph child Sessions as snapshots', async () => {
const accepted = await prepare({
kind: 'side_conversation',
messages: [linkedSubagentResult('completed')],
sessionHeaders: [sessionHeader(ROOT_SESSION_ID), childHeader({ graph: false })],
});
assert.equal(accepted.ok, true);
if (!accepted.ok) assert.fail('Expected accepted linked-child snapshot');
assert.deepEqual([...accepted.references.keys()], [CHILD_SESSION_ID]);
test('only a revision shares Graph children; every other retained child is a snapshot', async () => {
for (const kind of ['branch', 'side_conversation', 'revision'] as const) {
for (const graph of [true, false]) {
const accepted = await prepare({
kind,
messages: [linkedSubagentResult('completed')],
sessionHeaders: [sessionHeader(ROOT_SESSION_ID), childHeader({ graph })],
});
if (!accepted.ok) assert.fail(`Expected accepted ${kind} references`);
const shares = kind === 'revision' && graph;
assert.deepEqual([...accepted.shared.keys()], shares ? [CHILD_SESSION_ID] : []);
assert.deepEqual([...accepted.snapshots.keys()], shares ? [] : [CHILD_SESSION_ID]);
}
}
});

test('Side Conversation references wait for live Graph and child state', async () => {
Expand Down Expand Up @@ -131,7 +121,7 @@ test('Side Conversation rejects a retained child without a terminal result snaps
assert.deepEqual(outcome, {
ok: false,
code: 'operation_unavailable',
message: 'Side Conversation requires a terminal result for every retained linked child',
message: 'Conversation copy requires a terminal result for every retained linked child',
});
});

Expand Down Expand Up @@ -234,11 +224,6 @@ test('Agent Graph revision references outlive the Artifacts they name', async ()
});

test('Agent Graph revision references reject invalid ownership boundaries', async () => {
const genericChild = childHeader({ graph: false });
const generic = await prepare({ sessionHeaders: [sessionHeader(ROOT_SESSION_ID), genericChild] });
assert.equal(generic.ok, false);
if (!generic.ok) assert.equal(generic.code, 'operation_unavailable');

const otherParent = childHeader({ parentSessionId: 'other-root' });
const crossFamily = await prepare({
sessionHeaders: [sessionHeader(ROOT_SESSION_ID), sessionHeader('other-root'), otherParent],
Expand All @@ -251,10 +236,6 @@ test('Agent Graph revision references reject invalid ownership boundaries', asyn
});
assert.equal(wrongGraph.ok, false);
if (!wrongGraph.ok) assert.equal(wrongGraph.code, 'operation_unavailable');

const branch = await prepare({ kind: 'branch' });
assert.equal(branch.ok, false);
if (!branch.ok) assert.equal(branch.code, 'operation_unavailable');
});

test('Agent Graph revision references verify resumed Run lineage', async () => {
Expand Down Expand Up @@ -305,14 +286,13 @@ test('Agent Graph revision admission includes only retained direct and reference
const laterChild = childHeader({ id: 'later-child', parentTurnId: 'later-turn' });
const siblingChild = childHeader({ id: 'sibling-child', parentSessionId: 'sibling-session' });
assert.deepEqual(
agentGraphRevisionAdmissionSessionIds({
linkedChildCopyAdmissionSessionIds({
sourceSessionId: ROOT_SESSION_ID,
sessionHeaders: [sessionHeader(ROOT_SESSION_ID), childHeader(), laterChild, siblingChild],
copyTurnIds: [ROOT_TURN_ID],
requests: collectConversationCopyLinkedChildReferences({
messages: [linkedResult()],
runtimeEvents: [],
archivedResults: [],
}),
}),
[CHILD_SESSION_ID],
Expand All @@ -322,7 +302,6 @@ test('Agent Graph revision admission includes only retained direct and reference
interface PrepareOverrides {
readonly kind?: 'branch' | 'revision' | 'side_conversation';
readonly messages?: readonly StoredMessage[];
readonly archivedResults?: readonly string[];
readonly sessionHeaders?: readonly SessionHeader[];
readonly runs?: readonly RuntimeInvocationRecord[];
readonly sessionGraphState?: 'absent' | 'live' | 'terminal';
Expand All @@ -335,7 +314,7 @@ interface PrepareOverrides {
async function prepare(overrides: PrepareOverrides = {}) {
const sourceHeader = sessionHeader(ROOT_SESSION_ID);
const messages = overrides.messages ?? [linkedResult()];
return prepareAgentGraphRevisionReferences(
return prepareLinkedChildCopyReferences(
{
kind: overrides.kind ?? 'revision',
sourceSessionId: ROOT_SESSION_ID,
Expand All @@ -345,7 +324,6 @@ async function prepare(overrides: PrepareOverrides = {}) {
requests: collectConversationCopyLinkedChildReferences({
messages,
runtimeEvents: [],
archivedResults: overrides.archivedResults ?? [],
}),
},
{
Expand Down
Loading