feat(mosaic): add correlated lease promotion CLI

This commit is contained in:
Jason Woltje
2026-08-11 20:51:03 -05:00
parent 77edb0dea2
commit 4f7f6b3281
7 changed files with 798 additions and 6 deletions
@@ -0,0 +1,53 @@
import { describe, expect, it, vi } from 'vitest';
import type { CommandResult, CommandRunner, FleetRoster } from '../commands/fleet.js';
import { TmuxPromotionTransport } from './promotion-transport.js';
const sessionId = 'a'.repeat(64);
const roster: FleetRoster = {
agents: [{ className: 'worker', name: 'claude-seat', runtime: 'claude' }],
defaults: { workingDirectory: '~/src' },
runtimes: {},
tmux: { holderSession: '_holder', socketName: 'mosaic-fleet' },
transport: 'tmux',
version: 1,
};
function result(stdout = '', exitCode = 0, stderr = ''): CommandResult {
return { exitCode, stderr, stdout };
}
describe('TmuxPromotionTransport', () => {
it('resolves the exact roster seat and sends through the maintained tmux sender', async () => {
const runner = vi
.fn<CommandRunner>()
.mockResolvedValueOnce(result('1234 claude 0 0 0 0\n'))
.mockResolvedValueOnce(result());
const environmentReader = vi.fn(async () => `MOSAIC_LEASE_SESSION_ID=${sessionId}\0`);
const transport = new TmuxPromotionTransport({
environmentReader,
mosaicHome: '/mosaic',
rosterLoader: async () => roster,
runner,
});
const target = await transport.resolve('claude-seat');
await transport.sendPromotion(target);
expect(target).toEqual({
bundle: 'mosaic-fleet',
seat: 'claude-seat',
sessionId,
});
expect(environmentReader).toHaveBeenCalledWith(1234);
expect(runner).toHaveBeenNthCalledWith(2, '/mosaic/tools/tmux/agent-send.sh', [
'-L',
'mosaic-fleet',
'-S',
expect.stringMatching(/:operator$/),
'-s',
'claude-seat',
'-m',
'/mosaic-promote',
]);
});
});
@@ -0,0 +1,116 @@
import { readFile } from 'node:fs/promises';
import {
buildAgentSendCommand,
buildTmuxListPanesCommand,
getDefaultOperatorSourceLabel,
getRosterAgent,
parseTmuxListPanes,
resolveFleetPaths,
type CommandResult,
type CommandRunner,
type FleetRoster,
RUNTIME_ACCEPTABLE_COMMANDS,
} from '../commands/fleet.js';
import { loadFleetRoster } from './fleet-roster-v1.js';
const PROMOTION_COMMAND = '/mosaic-promote';
const SESSION_ID_PATTERN = /^[a-f0-9]{64}$/;
export interface PromotionTarget {
bundle: string;
seat: string;
sessionId: string;
}
export interface PromotionTransport {
resolve(seat: string): Promise<PromotionTarget>;
sendPromotion(target: PromotionTarget): Promise<void>;
}
export interface TmuxPromotionTransportOptions {
environmentReader?: (pid: number) => Promise<string>;
mosaicHome: string;
rosterLoader?: () => Promise<FleetRoster>;
runner: CommandRunner;
}
/** Local, roster-bound transport for the in-seat promotion command. */
export class TmuxPromotionTransport implements PromotionTransport {
private readonly environmentReader: (pid: number) => Promise<string>;
private readonly rosterLoader: () => Promise<FleetRoster>;
constructor(private readonly options: TmuxPromotionTransportOptions) {
this.environmentReader = options.environmentReader ?? readPaneEnvironment;
this.rosterLoader =
options.rosterLoader ??
(() => loadFleetRoster(resolveFleetPaths(options.mosaicHome).rosterPath));
}
async resolve(seat: string): Promise<PromotionTarget> {
const roster = await this.rosterLoader();
const agent = getRosterAgent(roster, seat);
if (agent.runtime !== 'claude') {
throw new Error(`Lease promotion is currently available only for Claude seats: ${seat}.`);
}
const paneResult = await this.run(
buildTmuxListPanesCommand(agent.name, roster.tmux.socketName),
);
if (paneResult.exitCode !== 0) {
throw new Error(`Promotion seat is unavailable: ${seat}.`);
}
const pane = parseTmuxListPanes(paneResult.stdout);
const allowedCommands = RUNTIME_ACCEPTABLE_COMMANDS.claude;
if (
pane.dead ||
pane.pid === null ||
pane.command === null ||
allowedCommands === undefined ||
!allowedCommands.includes(pane.command)
) {
throw new Error(`Promotion seat runtime identity mismatch: ${seat}.`);
}
const sessionId = parseLeaseSessionId(await this.environmentReader(pane.pid));
if (sessionId === null) {
throw new Error(`Promotion seat has no readable lease session: ${seat}.`);
}
return {
bundle: roster.tmux.socketName || 'default',
seat: agent.name,
sessionId,
};
}
async sendPromotion(target: PromotionTarget): Promise<void> {
const command = buildAgentSendCommand(
resolveFleetPaths(this.options.mosaicHome),
target.seat,
PROMOTION_COMMAND,
target.bundle === 'default' ? '' : target.bundle,
getDefaultOperatorSourceLabel(),
);
const result = await this.run(command);
if (result.exitCode !== 0) {
throw new Error(`Promotion command delivery failed: ${target.seat}.`);
}
}
private async run(command: string[]): Promise<CommandResult> {
const [executable, ...args] = command;
if (executable === undefined) {
throw new Error('Promotion transport command is empty.');
}
return this.options.runner(executable, args);
}
}
async function readPaneEnvironment(pid: number): Promise<string> {
return readFile(`/proc/${pid}/environ`, 'utf8');
}
function parseLeaseSessionId(environment: string): string | null {
const value = environment
.split('\0')
.find((entry) => entry.startsWith('MOSAIC_LEASE_SESSION_ID='))
?.slice('MOSAIC_LEASE_SESSION_ID='.length);
return value !== undefined && SESSION_ID_PATTERN.test(value) ? value : null;
}