Files
openchamber/packages/ui/src/lib/sessionBtwMetadata.test.ts
T
dibanez 7a95efc4ac fix(btw): stop the boundary from outliving the session it applies to
Review catch: `promoteBtwSession` removes the btw metadata, but the
boundary instruction is persisted on every message the session sent while
it was a side conversation, and there is no API to delete a message part
after the fact. A promoted session therefore keeps reading "no sub-agents,
do not touch the workspace" out of its own history, in a session that is
no longer a side conversation.

Promotion cannot delete those lines, so it answers them instead:
`withoutBtwSessionMarker` now leaves `openchamber.btwPromoted`, and the
composer sends `BTW_PROMOTION_NOTICE` with every message in a session
carrying it — stating that the session is now the main thread and the
usual tool, sub-agent and workspace permissions are in force.

It rides with every send for the same reason the boundary does: the
instructions it revokes are re-read on every turn, so a one-shot notice
would lose its position relative to them as the conversation grows.

`btwPromoted` is additive and optional. A session that never went through
`/btw` never has it, and one promoted before this change simply keeps the
old behavior.
2026-08-27 13:54:29 +02:00

85 lines
4.1 KiB
TypeScript

import { describe, expect, test } from 'bun:test';
import type { Session } from '@opencode-ai/sdk/v2';
import {
getBtwBoundaryMessageID,
getBtwOriginalSessionID,
getBtwSessionID,
isBtwSession,
withBtwSessionLink,
withBtwSessionMarker,
withoutBtwSessionLink,
wasPromotedBtwSession,
withoutBtwSessionMarker,
} from './sessionBtwMetadata';
const sessionWith = (metadata: unknown): Session => ({ id: 's', metadata }) as unknown as Session;
describe('parent link', () => {
test('withBtwSessionLink preserves unrelated openchamber metadata', () => {
const next = withBtwSessionLink({ openchamber: { reviewSessionID: 'r-1' }, other: 1 }, 'fork-1');
expect(next).toEqual({ openchamber: { reviewSessionID: 'r-1', btwSessionID: 'fork-1' }, other: 1 });
});
test('getBtwSessionID reads the link and rejects blank values', () => {
expect(getBtwSessionID(sessionWith({ openchamber: { btwSessionID: 'fork-1' } }))).toBe('fork-1');
expect(getBtwSessionID(sessionWith({ openchamber: { btwSessionID: ' ' } }))).toBeNull();
expect(getBtwSessionID(sessionWith(undefined))).toBeNull();
expect(getBtwSessionID(null)).toBeNull();
});
test('withoutBtwSessionLink removes only a matching link', () => {
const linked = { openchamber: { btwSessionID: 'fork-1', reviewSessionID: 'r-1' } };
expect(withoutBtwSessionLink(linked, 'fork-2')).toBe(linked);
expect(withoutBtwSessionLink(linked, 'fork-1')).toEqual({ openchamber: { reviewSessionID: 'r-1' } });
});
test('withoutBtwSessionLink drops an emptied openchamber object', () => {
expect(withoutBtwSessionLink({ openchamber: { btwSessionID: 'fork-1' } }, 'fork-1')).toEqual({});
});
});
describe('fork marker', () => {
test('withBtwSessionMarker replaces inherited openchamber metadata', () => {
const inherited = { openchamber: { btwSessionID: 'stale', reviewSessionID: 'r-1' }, other: 1 };
expect(withBtwSessionMarker(inherited, 'parent-1', 'msg-9')).toEqual({
openchamber: { kind: 'btw', originalSessionID: 'parent-1', btwBoundaryMessageID: 'msg-9' },
other: 1,
});
});
test('withBtwSessionMarker omits a null boundary (empty parent)', () => {
expect(withBtwSessionMarker({}, 'parent-1', null)).toEqual({
openchamber: { kind: 'btw', originalSessionID: 'parent-1' },
});
});
test('marker readers only apply to btw-kind sessions', () => {
const fork = sessionWith({ openchamber: { kind: 'btw', originalSessionID: 'parent-1', btwBoundaryMessageID: 'msg-9' } });
expect(isBtwSession(fork)).toBe(true);
expect(getBtwOriginalSessionID(fork)).toBe('parent-1');
expect(getBtwBoundaryMessageID(fork)).toBe('msg-9');
const review = sessionWith({ openchamber: { kind: 'review', originalSessionID: 'parent-1', btwBoundaryMessageID: 'msg-9' } });
expect(isBtwSession(review)).toBe(false);
expect(getBtwOriginalSessionID(review)).toBeNull();
expect(getBtwBoundaryMessageID(review)).toBeNull();
});
test('withoutBtwSessionMarker strips the marker, keeps other keys, and records the promotion', () => {
const marked = { openchamber: { kind: 'btw', originalSessionID: 'parent-1', btwBoundaryMessageID: 'msg-9', btwSessionID: 'nested' } };
expect(withoutBtwSessionMarker(marked)).toEqual({ openchamber: { btwSessionID: 'nested', btwPromoted: true } });
expect(withoutBtwSessionMarker({ openchamber: { kind: 'btw', originalSessionID: 'parent-1' } })).toEqual({ openchamber: { btwPromoted: true } });
const plain = { openchamber: { kind: 'review' } };
expect(withoutBtwSessionMarker(plain)).toBe(plain);
});
test('wasPromotedBtwSession only reports a session that went through promotion', () => {
expect(wasPromotedBtwSession(sessionWith({ openchamber: { btwPromoted: true } }))).toBe(true);
// Still a live btw fork: the boundary applies, the notice must not.
expect(wasPromotedBtwSession(sessionWith({ openchamber: { kind: 'btw', originalSessionID: 'p-1' } }))).toBe(false);
expect(wasPromotedBtwSession(sessionWith({ openchamber: {} }))).toBe(false);
expect(wasPromotedBtwSession(sessionWith(undefined))).toBe(false);
expect(wasPromotedBtwSession(null)).toBe(false);
});
});