import { afterEach, describe, expect, it, vi } from 'vitest';

interface FakeEntry {
  type: string;
  customType?: string;
  data?: unknown;
}

interface SentMessage {
  message: {
    customType: string;
    content: string;
    display: boolean;
  };
  options?: {
    triggerTurn?: boolean;
    deliverAs?: 'steer' | 'followUp' | 'nextTurn';
  };
}

interface FakeContext {
  cwd: string;
  ui: {
    notifications: Array<{ message: string; level?: string }>;
    statuses: Map<string, string | undefined>;
    notify(message: string, level?: string): void;
    setStatus(key: string, value: string | undefined): void;
  };
  sessionManager: {
    getBranch(): FakeEntry[];
  };
  isIdle(): boolean;
  hasPendingMessages(): boolean;
  abort(): void;
}

type EventHandler = (
  event: Record<string, unknown>,
  context: FakeContext,
) => unknown | Promise<unknown>;

type CommandHandler = (args: string, context: FakeContext) => unknown | Promise<unknown>;

interface FakeToolResult {
  content: Array<{ type: string; text: string }>;
  details?: unknown;
  terminate?: boolean;
}

interface FakeTool {
  name: string;
  execute(
    toolCallId: string,
    params: Record<string, unknown>,
    signal: AbortSignal | undefined,
    onUpdate: undefined,
    context: FakeContext,
  ): Promise<FakeToolResult>;
}

interface GoalExtensionFactory {
  (api: FakePiApi): void;
}

interface GoalExtensionModule {
  default: GoalExtensionFactory;
}

interface FakePiApi {
  on(event: string, handler: EventHandler): void;
  registerCommand(name: string, options: { description: string; handler: CommandHandler }): void;
  registerTool(tool: FakeTool): void;
  appendEntry(customType: string, data?: unknown): void;
  sendMessage(message: SentMessage['message'], options?: SentMessage['options']): void;
}

function isGoalExtensionModule(value: unknown): value is GoalExtensionModule {
  if (typeof value !== 'object' || value === null) return false;
  return typeof Reflect.get(value, 'default') === 'function';
}

const goalExtensionUrl = new URL('../../framework/runtime/pi/goal-extension.ts', import.meta.url)
  .href;
const importedGoalExtension: unknown = await import(goalExtensionUrl);
if (!isGoalExtensionModule(importedGoalExtension)) {
  throw new Error('Pi goal extension must export a default registration function');
}
const registerGoalExtension = importedGoalExtension.default;

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

class FakePi {
  readonly handlers = new Map<string, EventHandler[]>();
  readonly commands = new Map<string, CommandHandler>();
  readonly tools = new Map<string, FakeTool>();
  readonly entries: FakeEntry[] = [];
  readonly sentMessages: SentMessage[] = [];
  readonly notifications: Array<{ message: string; level?: string }> = [];
  readonly statuses = new Map<string, string | undefined>();
  branch: FakeEntry[] = [];
  idle = true;
  pending = false;
  abortCount = 0;

  readonly context: FakeContext = {
    cwd: '/tmp/project',
    ui: {
      notifications: this.notifications,
      statuses: this.statuses,
      notify: (message: string, level?: string): void => {
        this.notifications.push({ message, level });
      },
      setStatus: (key: string, value: string | undefined): void => {
        this.statuses.set(key, value);
      },
    },
    sessionManager: {
      getBranch: (): FakeEntry[] => [...this.branch],
    },
    isIdle: (): boolean => this.idle,
    hasPendingMessages: (): boolean => this.pending,
    abort: (): void => {
      this.abortCount += 1;
    },
  };

  readonly api: FakePiApi = {
    on: (event: string, handler: EventHandler): void => {
      this.handlers.set(event, [...(this.handlers.get(event) ?? []), handler]);
    },
    registerCommand: (
      name: string,
      options: { description: string; handler: CommandHandler },
    ): void => {
      this.commands.set(name, options.handler);
    },
    registerTool: (tool: FakeTool): void => {
      this.tools.set(tool.name, tool);
    },
    appendEntry: (customType: string, data?: unknown): void => {
      const entry: FakeEntry = { type: 'custom', customType, data };
      this.entries.push(entry);
      this.branch.push(entry);
    },
    sendMessage: (message: SentMessage['message'], options?: SentMessage['options']): void => {
      this.sentMessages.push({ message, options });
    },
  };

  constructor(initialBranch: FakeEntry[] = []) {
    this.branch = [...initialBranch];
    registerGoalExtension(this.api);
  }

  async emit(event: string, value: Record<string, unknown> = {}): Promise<unknown[]> {
    const results: unknown[] = [];
    for (const handler of this.handlers.get(event) ?? []) {
      results.push(await handler(value, this.context));
    }
    return results;
  }

  async goal(args: string): Promise<void> {
    const handler = this.commands.get('goal');
    if (handler === undefined) throw new Error('/goal was not registered');
    await handler(args, this.context);
  }

  async report(params: Record<string, unknown>): Promise<FakeToolResult> {
    const tool = this.tools.get('mosaic_goal_report');
    if (tool === undefined) throw new Error('mosaic_goal_report was not registered');
    return await tool.execute('goal-report-1', params, undefined, undefined, this.context);
  }
}

function latestGoalStateData(pi: FakePi): Record<string, unknown> {
  for (let index = pi.entries.length - 1; index >= 0; index -= 1) {
    const entry = pi.entries[index];
    if (entry?.customType === 'mosaic-goal-state' && isRecord(entry.data)) return entry.data;
  }
  throw new Error('No persisted Mosaic goal state found');
}

function stateField(pi: FakePi, field: string): unknown {
  return latestGoalStateData(pi)[field];
}

function activeGoalStatementFromContext(result: unknown): string {
  if (!isRecord(result)) throw new Error('Context handler did not return an object');
  const messages = result['messages'];
  if (!Array.isArray(messages)) throw new Error('Context result did not include messages');
  const goalMessage = messages.find(
    (message: unknown): boolean =>
      isRecord(message) && message['customType'] === 'mosaic-goal-context',
  );
  if (!isRecord(goalMessage) || typeof goalMessage['content'] !== 'string') {
    throw new Error('Goal context message was not injected');
  }
  return goalMessage['content'];
}

afterEach(() => {
  vi.useRealTimers();
  vi.unstubAllEnvs();
});

describe('Mosaic Pi goal extension commands', () => {
  it('shows help and handles controls safely when no goal exists', async () => {
    const pi = new FakePi();

    await pi.goal('');
    expect(pi.notifications.at(-1)?.message).toContain('/goal set');
    await pi.goal('status');
    expect(pi.notifications.at(-1)?.message).toContain('No Mosaic goal is set');

    for (const command of ['pause', 'resume', 'cancel']) {
      await pi.goal(command);
      expect(pi.notifications.at(-1)?.level).toBe('warning');
    }
    expect(pi.entries).toHaveLength(0);
    expect(pi.sentMessages).toHaveLength(0);
  });

  it('sets, reports, pauses, resumes, and cancels a bounded goal', async () => {
    const pi = new FakePi();

    await pi.goal('set Deliver the local goal extension with tests');
    expect(stateField(pi, 'phase')).toBe('active');
    expect(stateField(pi, 'statement')).toBe('Deliver the local goal extension with tests');
    expect(pi.sentMessages).toHaveLength(1);
    expect(pi.sentMessages[0]?.options?.triggerTurn).toBe(true);

    await pi.goal('status');
    expect(pi.notifications.at(-1)?.message).toContain('Deliver the local goal extension');
    expect(pi.notifications.at(-1)?.message).toContain('active');

    await pi.goal('pause');
    expect(stateField(pi, 'phase')).toBe('paused');
    pi.sentMessages.length = 0;
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(0);

    await pi.goal('resume');
    expect(stateField(pi, 'phase')).toBe('active');
    expect(pi.sentMessages).toHaveLength(1);

    await pi.goal('cancel');
    expect(stateField(pi, 'phase')).toBe('cancelled');
    pi.sentMessages.length = 0;
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(0);
  });

  it('accepts /goal <statement> shorthand but refuses to replace an active goal', async () => {
    const pi = new FakePi();

    await pi.goal('First goal');
    const firstGoalId = stateField(pi, 'goalId');
    await pi.goal('set Second goal');

    expect(stateField(pi, 'goalId')).toBe(firstGoalId);
    expect(stateField(pi, 'statement')).toBe('First goal');
    expect(pi.notifications.at(-1)?.level).toBe('warning');
    expect(pi.notifications.at(-1)?.message).toContain('/goal cancel');
  });

  it('rejects invalid phase transitions, aborts busy work, and supports clear as cancel', async () => {
    const pi = new FakePi();
    await pi.goal('set Preserve transition safety');

    await pi.goal('resume');
    expect(pi.notifications.at(-1)?.message).toContain('cannot be resumed');
    pi.idle = false;
    await pi.goal('pause maintenance window');
    expect(stateField(pi, 'stopReason')).toBe('maintenance window');
    expect(pi.abortCount).toBe(1);
    await pi.goal('pause');
    expect(pi.notifications.at(-1)?.message).toContain('cannot be paused');
    await pi.goal('clear');
    expect(stateField(pi, 'phase')).toBe('cancelled');
    expect(pi.abortCount).toBe(2);
  });

  it('rejects empty and oversized goal statements without starting a run', async () => {
    const pi = new FakePi();

    await pi.goal('set');
    await pi.goal(`set ${'x'.repeat(8_001)}`);

    expect(pi.entries).toHaveLength(0);
    expect(pi.sentMessages).toHaveLength(0);
    expect(pi.notifications.at(-1)?.level).toBe('warning');
  });
});

describe('Mosaic Pi goal lifecycle', () => {
  it('injects one fresh active contract before every model context', async () => {
    const pi = new FakePi();
    await pi.goal('set Keep the agent oriented');

    const existingGoalContext = {
      role: 'custom',
      customType: 'mosaic-goal-context',
      content: 'stale',
    };
    const existingContinuation = {
      role: 'custom',
      customType: 'mosaic-goal-continuation',
      content: 'stale continuation',
    };
    const first = await pi.emit('context', {
      messages: [existingGoalContext, existingContinuation],
    });
    const second = await pi.emit('context', { messages: [] });

    expect(activeGoalStatementFromContext(first[0])).toContain('Keep the agent oriented');
    expect(activeGoalStatementFromContext(first[0])).toContain('mosaic_goal_report');
    expect(activeGoalStatementFromContext(first[0])).not.toContain('stale');
    if (!isRecord(first[0]) || !Array.isArray(first[0]['messages'])) {
      throw new Error('Expected filtered context messages');
    }
    expect(first[0]['messages']).toHaveLength(1);
    expect(activeGoalStatementFromContext(second[0])).toContain('Keep the agent oriented');

    await pi.goal('cancel');
    expect(
      await pi.emit('context', {
        messages: [existingGoalContext, existingContinuation],
      }),
    ).toEqual([{ messages: [] }]);
  });

  it('lets an existing busy run adopt the goal and waits behind a pending message', async () => {
    const busy = new FakePi();
    busy.idle = false;
    await busy.goal('set Join the current run safely');
    expect(busy.sentMessages).toHaveLength(0);

    busy.pending = true;
    await busy.emit('agent_settled');
    expect(busy.sentMessages).toHaveLength(0);
    busy.pending = false;
    busy.idle = true;
    await busy.emit('agent_settled');
    expect(busy.sentMessages).toHaveLength(1);
  });

  it('records every turn and continues once when an active run settles', async () => {
    const pi = new FakePi();
    await pi.goal('set Finish all acceptance criteria');
    pi.sentMessages.length = 0;

    await pi.emit('turn_end', { turnIndex: 0, message: {}, toolResults: [] });
    expect(stateField(pi, 'turnCount')).toBe(1);
    expect(stateField(pi, 'lastCheckSource')).toBe('turn');

    await pi.emit('agent_settled');
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(1);
    expect(pi.sentMessages[0]?.message.content).toContain('Goal remains active');

    await pi.emit('agent_start');
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(2);
  });

  it('requires two consecutive evidence-bearing achievement reports', async () => {
    const pi = new FakePi();
    await pi.goal('set Prove the feature works');
    pi.sentMessages.length = 0;

    const first = await pi.report({
      status: 'achieved',
      summary: 'Focused tests pass',
      evidence: ['pnpm test: 12 passed'],
    });
    expect(first.terminate).toBe(true);
    expect(stateField(pi, 'phase')).toBe('verifying');
    expect(stateField(pi, 'verificationPasses')).toBe(1);

    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(1);
    expect(pi.sentMessages[0]?.message.content).toContain('verification pass');

    await pi.emit('agent_start');
    const second = await pi.report({
      status: 'achieved',
      summary: 'Independent recheck confirms completion',
      evidence: ['rerun: 12 passed', 'framework path verified'],
    });
    expect(second.terminate).toBe(true);
    expect(stateField(pi, 'phase')).toBe('achieved');
    expect(stateField(pi, 'verificationPasses')).toBe(2);

    pi.sentMessages.length = 0;
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(0);
  });

  it('rejects malformed progress reports and reports submitted without an active goal', async () => {
    const noGoal = new FakePi();
    await expect(
      noGoal.report({ status: 'continue', summary: 'work', evidence: [] }),
    ).rejects.toThrow(/No active Mosaic goal/);

    const pi = new FakePi();
    await pi.goal('set Validate report boundaries');
    const invalidReports: Record<string, unknown>[] = [
      {},
      { status: 'invalid', summary: 'work', evidence: [] },
      { status: 'continue', evidence: [] },
      { status: 'continue', summary: '   ', evidence: [] },
      { status: 'continue', summary: 'x'.repeat(2_001), evidence: [] },
      { status: 'continue', summary: 'work', evidence: 'not-an-array' },
      { status: 'continue', summary: 'work', evidence: Array.from({ length: 21 }, () => 'x') },
      { status: 'continue', summary: 'work', evidence: [4] },
      { status: 'continue', summary: 'work', evidence: [''] },
      { status: 'continue', summary: 'work', evidence: ['x'.repeat(1_001)] },
      { status: 'continue', summary: 'work', evidence: [], nextStep: 4 },
      { status: 'continue', summary: 'work', evidence: [], nextStep: '   ' },
      { status: 'continue', summary: 'work', evidence: [], nextStep: 'x'.repeat(2_001) },
    ];
    for (const report of invalidReports) {
      await expect(pi.report(report)).rejects.toThrow();
    }
    expect(stateField(pi, 'phase')).toBe('active');
  });

  it('rejects an achievement claim without evidence', async () => {
    const pi = new FakePi();
    await pi.goal('set Require evidence');

    await expect(
      pi.report({ status: 'achieved', summary: 'Trust me', evidence: [] }),
    ).rejects.toThrow(/evidence/i);
    expect(stateField(pi, 'phase')).toBe('active');
  });

  it('redacts credential-shaped goal and report text before persistence or display', async () => {
    const githubToken = `ghp_${'a'.repeat(32)}`;
    const anthropicKey = `sk-ant-api03-${'b'.repeat(40)}`;
    const bearerToken = 'header.payload.signature-canary';
    const databaseUrl = 'postgresql://mosaic:password-canary@db.example.invalid/mosaic';
    const password = 'password-canary';
    const pi = new FakePi();

    await pi.goal(`set Rotate ${githubToken} without retaining it`);
    const context = await pi.emit('context', { messages: [] });
    expect(activeGoalStatementFromContext(context[0])).not.toContain(githubToken);

    const result = await pi.report({
      status: 'achieved',
      summary: `Validated ${anthropicKey}`,
      evidence: [`Authorization: Bearer ${bearerToken}`, `DATABASE_URL=${databaseUrl}`],
      nextStep: `password=${password}`,
    });
    await pi.goal('status');

    const persisted = JSON.stringify(latestGoalStateData(pi));
    const displayed = pi.notifications.at(-1)?.message ?? '';
    const toolOutput = JSON.stringify(result);
    for (const secret of [githubToken, anthropicKey, bearerToken, databaseUrl, password]) {
      expect(persisted).not.toContain(secret);
      expect(displayed).not.toContain(secret);
      expect(toolOutput).not.toContain(secret);
    }
    expect(persisted).toContain('[REDACTED-SECRET]');
  });

  it('preserves ordinary typed fields that resemble sensitive assignment names', async () => {
    const typedFields = 'token: string, password: boolean, secret: false';
    const pi = new FakePi();

    await pi.goal(`set Preserve TypeScript fields: ${typedFields}`);
    await pi.report({
      status: 'continue',
      summary: `Schema still contains ${typedFields}`,
      evidence: [`interface Config { ${typedFields} }`],
      nextStep: `Keep ${typedFields} unchanged`,
    });

    expect(stateField(pi, 'statement')).toContain(typedFields);
    expect(JSON.stringify(stateField(pi, 'lastReport'))).toContain(typedFields);
    expect(JSON.stringify(latestGoalStateData(pi))).not.toContain('[REDACTED-SECRET]');
  });

  it('stops autonomous continuation when the max-turn limit is reached', async () => {
    vi.stubEnv('MOSAIC_GOAL_MAX_TURNS', '2');
    const pi = new FakePi();
    await pi.goal('set Bound this run');
    pi.sentMessages.length = 0;

    await pi.emit('turn_end', { turnIndex: 0, message: {}, toolResults: [] });
    await pi.emit('turn_end', { turnIndex: 1, message: {}, toolResults: [] });

    expect(stateField(pi, 'phase')).toBe('exhausted');
    expect(pi.abortCount).toBe(1);
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(0);
  });

  it('resets the no-progress sequence when a continuation report changes', async () => {
    const pi = new FakePi();
    await pi.goal('set Track changing progress');

    await pi.report({
      status: 'continue',
      summary: 'First checkpoint',
      evidence: ['file A changed'],
      nextStep: 'Run focused tests',
    });
    await pi.report({
      status: 'continue',
      summary: 'Second checkpoint',
      evidence: ['focused tests passed'],
      nextStep: 'Review the diff',
    });

    expect(stateField(pi, 'phase')).toBe('active');
    expect(stateField(pi, 'noProgressReports')).toBe(1);
    await pi.goal('status');
    expect(pi.notifications.at(-1)?.message).toContain('Next step: Review the diff');
    expect(pi.notifications.at(-1)?.message).toContain('focused tests passed');
  });

  it('stops after a bounded number of identical no-progress reports', async () => {
    vi.stubEnv('MOSAIC_GOAL_MAX_NO_PROGRESS', '2');
    const pi = new FakePi();
    await pi.goal('set Detect stalled work');

    const report = {
      status: 'continue',
      summary: 'No change yet',
      evidence: ['same observation'],
      nextStep: 'Try again',
    };
    await pi.report(report);
    await pi.report(report);

    expect(stateField(pi, 'phase')).toBe('exhausted');
    expect(stateField(pi, 'noProgressReports')).toBe(2);
    pi.sentMessages.length = 0;
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(0);
  });

  it('rejects a goal report mixed with another tool result in the same turn', async () => {
    const pi = new FakePi();
    await pi.goal('set Require a sole final report');
    await pi.report({
      status: 'achieved',
      summary: 'Premature mixed claim',
      evidence: ['one observation'],
    });

    await pi.emit('turn_end', {
      turnIndex: 0,
      message: {},
      toolResults: [{ toolName: 'mosaic_goal_report' }, { toolName: 'read' }],
    });

    expect(stateField(pi, 'phase')).toBe('active');
    expect(stateField(pi, 'verificationPasses')).toBe(0);
    expect(stateField(pi, 'lastCheckOutcome')).toBe('mixed-goal-report-rejected');
    expect(pi.notifications.at(-1)?.level).toBe('warning');
  });

  it('marks blocked reports terminal until the operator resumes', async () => {
    const pi = new FakePi();
    await pi.goal('set Stop on a real blocker');

    await pi.report({
      status: 'blocked',
      summary: 'Missing required access',
      evidence: ['provider returned 403'],
    });
    expect(stateField(pi, 'phase')).toBe('blocked');

    pi.sentMessages.length = 0;
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(0);

    await pi.goal('resume');
    expect(stateField(pi, 'phase')).toBe('active');
    expect(stateField(pi, 'turnCount')).toBe(0);
    expect(pi.sentMessages).toHaveLength(1);
  });
});

describe('Mosaic Pi goal compaction and restoration', () => {
  it('resets provisional verification and defers manual-compaction continuation until idle', async () => {
    vi.useFakeTimers();
    const pi = new FakePi();
    await pi.goal('set Survive compaction');
    await pi.report({
      status: 'achieved',
      summary: 'Initial claim',
      evidence: ['focused test passed'],
    });
    expect(stateField(pi, 'phase')).toBe('verifying');
    pi.sentMessages.length = 0;

    await pi.emit('session_compact', { reason: 'manual', willRetry: false });
    expect(stateField(pi, 'phase')).toBe('active');
    expect(stateField(pi, 'verificationPasses')).toBe(0);
    expect(stateField(pi, 'compactionCount')).toBe(1);
    expect(stateField(pi, 'lastCheckSource')).toBe('compact');
    expect(pi.sentMessages).toHaveLength(0);

    await vi.runAllTimersAsync();
    expect(pi.sentMessages).toHaveLength(1);
    expect(pi.sentMessages[0]?.message.content).toContain('compaction');
  });

  it('does not re-enter an active automatic compaction and relies on the settled backstop', async () => {
    vi.useFakeTimers();
    const pi = new FakePi();
    await pi.goal('set Avoid compaction races');
    pi.sentMessages.length = 0;
    pi.idle = false;

    await pi.emit('session_compact', { reason: 'threshold', willRetry: false });
    await vi.runAllTimersAsync();
    expect(pi.sentMessages).toHaveLength(0);

    pi.idle = true;
    await pi.emit('agent_settled');
    expect(pi.sentMessages).toHaveLength(1);
  });

  it('restores branch-specific state on session start and tree navigation', async () => {
    vi.useFakeTimers();
    const source = new FakePi();
    await source.goal('set Restore this exact branch goal');
    const activeState = latestGoalStateData(source);

    const restored = new FakePi([
      { type: 'custom', customType: 'mosaic-goal-state', data: activeState },
    ]);
    await restored.emit('session_start', { reason: 'resume' });
    expect(restored.statuses.get('mosaic-goal')).toContain('active');
    const context = await restored.emit('context', { messages: [] });
    expect(activeGoalStatementFromContext(context[0])).toContain('Restore this exact branch goal');

    await restored.goal('pause');
    const pausedState = latestGoalStateData(restored);
    restored.branch = [{ type: 'custom', customType: 'mosaic-goal-state', data: pausedState }];
    await restored.emit('session_tree', {});
    await vi.runAllTimersAsync();
    expect(stateField(restored, 'phase')).toBe('paused');
    expect(restored.sentMessages).toHaveLength(0);
  });

  it('restores only fully valid persisted states and ignores malformed entries', async () => {
    vi.useFakeTimers();
    const source = new FakePi();
    await source.goal('set Validate persisted branch state');
    await source.report({
      status: 'continue',
      summary: 'Valid report',
      evidence: ['valid evidence'],
      nextStep: 'Continue validation',
    });
    const valid = latestGoalStateData(source);

    const validRestore = new FakePi([
      { type: 'custom', customType: 'mosaic-goal-state', data: valid },
    ]);
    await validRestore.emit('session_start', { reason: 'resume' });
    expect(stateField(validRestore, 'statement')).toBe('Validate persisted branch state');
    await validRestore.emit('session_shutdown', { reason: 'reload' });

    const validReport = latestGoalStateData(source)['lastReport'];
    if (!isRecord(validReport)) throw new Error('Expected a valid persisted report fixture');
    const integerFields = [
      'turnCount',
      'reportCount',
      'verificationPasses',
      'requiredVerificationPasses',
      'noProgressReports',
      'maxTurns',
      'maxNoProgressReports',
      'compactionCount',
    ];
    const corruptions: Array<(state: Record<string, unknown>) => unknown> = [
      (): unknown => null,
      (state): unknown => ({ ...state, version: 99 }),
      (state): unknown => ({ ...state, goalId: '' }),
      (state): unknown => ({ ...state, statement: '' }),
      (state): unknown => ({ ...state, statement: 'x'.repeat(8_001) }),
      (state): unknown => ({ ...state, phase: 'unknown' }),
      (state): unknown => ({ ...state, lastCheckSource: 'unknown' }),
      (state): unknown => ({ ...state, startedAt: 4 }),
      (state): unknown => ({ ...state, lastCheckAt: 4 }),
      (state): unknown => ({ ...state, lastReport: null }),
      (state): unknown => ({ ...state, lastProgressFingerprint: 4 }),
      (state): unknown => ({ ...state, stopReason: 4 }),
      ...integerFields.map((field: string) => (state: Record<string, unknown>): unknown => ({
        ...state,
        [field]: -1,
      })),
    ];

    corruptions.push(
      (state: Record<string, unknown>): unknown => ({ ...state, maxTurns: 501 }),
      (state: Record<string, unknown>): unknown => ({ ...state, maxNoProgressReports: 101 }),
      (state: Record<string, unknown>): unknown => ({ ...state, requiredVerificationPasses: 3 }),
    );
    const reportCorruptions: Array<Record<string, unknown>> = [
      { ...validReport, status: 'bad' },
      { ...validReport, summary: '' },
      { ...validReport, evidence: 'bad' },
      { ...validReport, evidence: [4] },
      { ...validReport, fingerprint: '' },
      { ...validReport, reportedAt: '' },
      { ...validReport, nextStep: 4 },
    ];
    for (const corruptReport of reportCorruptions) {
      corruptions.push((state: Record<string, unknown>): unknown => ({
        ...state,
        lastReport: corruptReport,
      }));
    }

    for (const corrupt of corruptions) {
      const candidate = corrupt(structuredClone(valid));
      const restored = new FakePi([
        { type: 'custom', customType: 'mosaic-goal-state', data: candidate },
      ]);
      await restored.emit('session_start', { reason: 'resume' });
      expect(restored.statuses.get('mosaic-goal')).toBeUndefined();
      expect(await restored.emit('context', { messages: [] })).toEqual([undefined]);
    }

    const failClosed = new FakePi([
      { type: 'custom', customType: 'mosaic-goal-state', data: valid },
      { type: 'custom', customType: 'mosaic-goal-state', data: { ...valid, version: 99 } },
    ]);
    await failClosed.emit('session_start', { reason: 'resume' });
    expect(failClosed.statuses.get('mosaic-goal')).toBeUndefined();
  });

  it('fails closed instead of reusing credential-bearing legacy branch state', async () => {
    const source = new FakePi();
    await source.goal('set Build a valid restore fixture');
    const cleanState = latestGoalStateData(source);
    const legacyState = structuredClone(cleanState);
    legacyState['statement'] = `Legacy secret ghp_${'z'.repeat(32)}`;

    const restored = new FakePi([
      { type: 'custom', customType: 'mosaic-goal-state', data: legacyState },
      { type: 'custom', customType: 'mosaic-goal-state', data: cleanState },
    ]);
    await restored.emit('session_start', { reason: 'resume' });

    expect(restored.statuses.get('mosaic-goal')).toBeUndefined();
    expect(await restored.emit('context', { messages: [] })).toEqual([undefined]);
    expect(restored.notifications.at(-1)?.level).toBe('warning');
    expect(restored.notifications.at(-1)?.message).toContain('was not restored');
    expect(restored.entries).toHaveLength(0);
  });

  it('schedules an active tree-restored goal and preserves terminal state through compaction', async () => {
    vi.useFakeTimers();
    const source = new FakePi();
    await source.goal('set Restore active tree work');
    const active = latestGoalStateData(source);

    const restored = new FakePi();
    restored.branch = [{ type: 'custom', customType: 'mosaic-goal-state', data: active }];
    await restored.emit('session_tree', {});
    await vi.runAllTimersAsync();
    expect(restored.sentMessages).toHaveLength(1);
    expect(restored.sentMessages[0]?.message.content).toContain('tree navigation');

    await restored.goal('cancel');
    await restored.emit('session_compact', { reason: 'manual', willRetry: false });
    expect(stateField(restored, 'phase')).toBe('cancelled');
    expect(stateField(restored, 'compactionCount')).toBe(1);
  });

  it('cancels deferred continuation when the session shuts down', async () => {
    vi.useFakeTimers();
    const pi = new FakePi();
    await pi.goal('set Do not leak a stale timer');
    pi.sentMessages.length = 0;

    await pi.emit('session_compact', { reason: 'manual', willRetry: false });
    await pi.emit('session_shutdown', { reason: 'reload' });
    await vi.runAllTimersAsync();

    expect(pi.sentMessages).toHaveLength(0);
  });
});
