Ctrl K
ComunidadGuías…

test/codex-recovery-admission.test.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
var test = require('node:test');
var assert = require('node:assert/strict');
var helpers = require('./helpers/codex-recovery-fixture.cjs');
var fixture = helpers.fixture, tick = helpers.tick, until = helpers.until;

test('recovery starts beside an active different thread without stopping its runtime', async function(t) {
  var kit = fixture(t);
  var sibling = await kit.fresh();
  sibling.pushMessage('Worker needs Driver assistance');
  await tick();
  var recovery = await kit.recover();
  assert.equal(kit.servers[0].stopped, 0);
  assert.equal(kit.servers[0].handlers.length, 1);
  recovery.pushMessage('Review the Worker result');
  await tick();
  assert.equal(kit.servers[1].calls.filter(function(call) { return call.method === 'turn/start'; }).length, 1);
  assert.equal(kit.servers[0].calls.some(function(call) { return call.method === 'turn/interrupt'; }), false);
});

test('same-thread concurrent recoveries wait cancellably and resume once the first becomes idle', async function(t) {
  var kit = fixture(t), waiting = [];
  var first = await kit.recover();
  first.pushMessage('First turn');
  await tick();
  var admitted = false;
  var second = kit.recover({ onRecoveryWaiting: function(reason) { waiting.push(reason); } }).then(function(handle) { admitted = true; return handle; });
  await until(function() { return waiting.length > 0; });
  assert.equal(admitted, false);
  kit.servers[0].complete('saved-thread');
  var handle = await second;
  handle.pushMessage('Second turn');
  await tick();
  assert.equal(first.pushMessage('Retired'), false);
  assert.equal(kit.servers[0].stopped, 1);
  assert.equal(kit.servers[1].calls.filter(function(call) { return call.method === 'turn/start'; }).length, 1);
});

test('an idle target unloads beside a running sibling without interrupting the sibling', async function(t) {
  var kit = fixture(t);
  var target = await kit.fresh({ resumeSessionId: 'saved-thread' });
  target.pushMessage('Previous Driver turn');
  await tick();
  kit.servers[0].complete('saved-thread');
  await tick();
  var sibling = await kit.fresh();
  sibling.pushMessage('Worker awaits assistance');
  await tick();
  var recovery = await kit.recover();
  assert.equal(target.pushMessage('Closed'), false);
  assert.equal(kit.servers[0].stopped, 0);
  assert.ok(kit.servers[0].calls.some(function(call) { return call.method === 'thread/unsubscribe' && call.params.threadId === 'saved-thread'; }));
  assert.equal(kit.servers[0].handlers.length, 1);
  recovery.pushMessage('Driver can assist now');
  await tick();
});

test('stale loaded bookkeeping requires explicit idle status and terminal proof before unloading', async function(t) {
  var kit = fixture(t, function(server, method) {
    if (method === 'thread/read') return Promise.resolve({ thread: { id: 'saved-thread', status: { type: 'idle' } } });
  });
  var sibling = await kit.fresh();
  sibling.pushMessage('Active sibling');
  await tick();
  kit.servers[0].loaded.push('saved-thread');
  await kit.recover();
  assert.equal(kit.servers[0].stopped, 0);
  assert.ok(kit.servers[0].calls.some(function(call) { return call.method === 'thread/backgroundTerminals/list' && call.params.threadId === 'saved-thread'; }));
});

test('background terminals, unknown loaded state, and active target remain protected until Stop', async function(t) {
  var cases = ['background', 'unknown', 'active', 'pagination', 'wrong-thread'];
  for (var kind of cases) {
    await t.test(kind, async function(st) {
      var kit = fixture(st, function(server, method) {
        if (method === 'thread/read') return Promise.resolve({ thread: { id: kind === 'wrong-thread' ? 'other-thread' : 'saved-thread', status: { type: kind === 'active' ? 'active' : 'idle' } } });
        if (kind === 'unknown' && method === 'thread/loaded/list') return Promise.reject(new Error('Unsupported probe'));
        if (kind === 'pagination' && method === 'thread/loaded/list') return Promise.resolve({ data: [], nextCursor: 'same-cursor' });
        if (kind === 'background' && method === 'thread/backgroundTerminals/list') return Promise.resolve({ data: [{ status: 'running' }] });
      });
      var sibling = await kit.fresh();
      sibling.pushMessage('Active sibling');
      await tick();
      kit.servers[0].loaded.push('saved-thread');
      var controller = new AbortController(), waiting = false;
      var cancelled = assert.rejects(kit.recover({ abortController: controller, onRecoveryWaiting: function() { waiting = true; } }), { name: 'AbortError' });
      await until(function() { return waiting; });
      controller.abort();
      await cancelled;
      assert.equal(kit.servers.length, 1);
      assert.equal(kit.servers[0].stopped, 0);
      if (kind === 'background' || kind === 'active' || kind === 'wrong-thread') assert.equal(kit.servers[0].calls.some(function(call) { return call.method === 'thread/unsubscribe'; }), false);
    });
  }
});

test('Worker completion stays correlated through safe waiting and preserves queued human input', async function(t) {
  var kit = require('./helpers/codex-recovery-delivery.cjs').fixture(t);
  var previous = await kit.recover();
  previous.pushMessage('Previous Driver execution');
  await tick();
  kit.complete();
  await until(function() { return !!kit.driver._providerRecoveryWaiting; });
  assert.equal(kit.sdk.pushMessage(kit.driver, 'Human follow-up retained during startup'), true);
  await new Promise(function(resolve) { setTimeout(resolve, 90); });
  assert.equal(kit.record().deliveryState, 'attempting');
  assert.equal(kit.record().deliveryAttemptCount, 1);
  assert.equal(kit.worker._pairDelegation, kit.token);
  kit.servers[0].complete('saved-thread');
  await until(function() { return kit.record().deliveryState === 'accepted'; });
  await tick();
  assert.equal(kit.record().taskId, 'task-13');
  assert.equal(kit.record().generation, 13);
  assert.equal(kit.driver.history.filter(function(entry) { return entry.partnerResult; }).length, 1);
  var resumedServer = kit.servers[kit.servers.length - 1];
  var starts = resumedServer.calls.filter(function(call) { return call.method === 'turn/start'; });
  assert.equal(starts.length, 1);
  assert.match(starts[0].params.input[0].text, /Verify the replacement Worker result/);
  assert.match(starts[0].params.input[0].text, /Verified Worker evidence/);
  resumedServer.complete('saved-thread');
  await until(function() { return resumedServer.calls.filter(function(call) { return call.method === 'turn/start'; }).length === 2; });
  starts = resumedServer.calls.filter(function(call) { return call.method === 'turn/start'; });
  assert.match(starts[1].params.input[0].text, /Human follow-up retained/);
  assert.equal(kit.worker._pairDelegation, undefined);
  assert.ok(kit.driver.history.some(function(entry) { return /Your message is retained/.test(entry.content || ''); }));
});

test('production completion delivery resumes once beside an active Worker runtime', async function(t) {
  var kit = require('./helpers/codex-recovery-delivery.cjs').fixture(t);
  var sibling = await kit.fresh();
  sibling.pushMessage('Worker remains active after replacement');
  await tick();
  kit.complete();
  await until(function() { return kit.record().deliveryState === 'accepted'; }).catch(function() {
    var record = kit.record();
    assert.fail('Completion was not admitted: ' + JSON.stringify({ state: record.deliveryState,
      attempts: record.deliveryAttemptCount, error: record.deliveryError, retained: record.outcome.response }));
  });
  assert.equal(kit.record().deliveryAttemptCount, 1);
  assert.equal(kit.servers[0].stopped, 0);
  assert.equal(kit.driver.history.filter(function(entry) { return entry.partnerResult; }).length, 1);
  assert.equal(kit.worker._pairDelegation, undefined);
});

test('human Stop during completion admission prevents late input and retains the completed result', async function(t) {
  var kit = require('./helpers/codex-recovery-delivery.cjs').fixture(t);
  var previous = await kit.recover();
  previous.pushMessage('Still executing');
  await tick();
  kit.complete();
  await until(function() { return !!kit.driver._providerRecoveryWaiting; });
  kit.stop();
  kit.driver.abortController.abort();
  kit.pipeline.delivery.wake(kit.driver, kit.worker, kit.token);
  await until(function() { return !kit.driver._queryStarting; });
  kit.driver.taskStopRequested = false;
  kit.pipeline.delivery.wake(kit.driver, kit.worker, kit.token);
  kit.servers[0].complete('saved-thread');
  await tick();
  assert.equal(kit.servers.reduce(function(count, server) { return count + server.calls.filter(function(call) { return call.method === 'turn/start'; }).length; }, 0), 1);
  assert.equal(kit.record().state, 'blocked');
  assert.equal(kit.record().blockedCode, 'human_stop');
  assert.equal(kit.record().outcome.response, 'Verified Worker evidence');
});

test('runtime startup failure retries the retained completion without duplicate transcript or sibling cancellation', async function(t) {
  var failed = false;
  var kit = require('./helpers/codex-recovery-delivery.cjs').fixture(t, function(server, method) {
    if (method === 'initialize' && server.options.config.mcp_servers['clay-session-tools'] && !failed) {
      failed = true;
      return Promise.reject(new Error('Transport initialization failed'));
    }
  });
  var sibling = await kit.fresh();
  sibling.pushMessage('Active Worker');
  await tick();
  kit.complete();
  await until(function() { return kit.record().deliveryState === 'accepted'; });
  assert.equal(failed, true);
  assert.equal(kit.record().deliveryAttemptCount, 2);
  assert.equal(kit.driver.history.filter(function(entry) { return entry.partnerResult; }).length, 1);
  assert.equal(kit.servers[0].stopped, 0);
  assert.equal(kit.servers[1].stopped, 1);
  assert.equal(kit.servers[2].calls.filter(function(call) { return call.method === 'turn/start'; }).length, 1);
});

test('replaced Worker generation cannot deliver a retained older completion', async function(t) {
  var kit = require('./helpers/codex-recovery-delivery.cjs').fixture(t);
  kit.worker._pairGeneration++;
  kit.complete();
  await tick();
  assert.equal(kit.servers.length, 0);
  assert.equal(kit.driver.history.filter(function(entry) { return entry.partnerResult; }).length, 0);
});

test('a stale production SDK input resumes completion in the same outbox attempt', async function(t) {
  var kit = require('./helpers/codex-recovery-delivery.cjs').fixture(t);
  var stale = await kit.fresh();
  stale.close();
  kit.driver.queryInstance = stale;
  kit.complete();
  await until(function() { return kit.record().deliveryState === 'accepted'; });
  assert.equal(kit.record().deliveryAttemptCount, 1);
  assert.equal(kit.driver.history.filter(function(entry) { return entry.partnerResult; }).length, 1);
});

test('slow initial safety probes retain completion eligibility before the first waiting notice', async function(t) {
  var release, probing = false;
  var probe = new Promise(function(resolve) { release = resolve; });
  var kit = require('./helpers/codex-recovery-delivery.cjs').fixture(t, function(server, method) {
    if (probing && method === 'thread/loaded/list') return probe;
  });
  var sibling = await kit.fresh();
  sibling.pushMessage('Active sibling');
  await tick();
  probing = true;
  kit.complete();
  await until(function() { return !!kit.driver._providerRecoveryWaiting; });
  await new Promise(function(resolve) { setTimeout(resolve, 90); });
  assert.equal(kit.record().deliveryState, 'attempting');
  assert.equal(kit.record().deliveryAttemptCount, 1);
  release({ data: ['thread-1'] });
  await until(function() { return kit.record().deliveryState === 'accepted'; });
  assert.equal(kit.servers[0].stopped, 0);
});

test('distinct recovery threads run simultaneously and ordinary resumes respect the target lease', async function(t) {
  var kit = fixture(t);
  var first = await kit.recover();
  first.pushMessage('First target');
  await tick();
  var different = await kit.recover({ resumeSessionId: 'different-thread' });
  different.pushMessage('Independent target');
  await tick();
  var waiting = false;
  var ordinary = kit.fresh({ resumeSessionId: 'saved-thread', onRecoveryWaiting: function() { waiting = true; } });
  await until(function() { return waiting; });
  kit.servers[0].complete('saved-thread');
  var resumed = await ordinary;
  resumed.pushMessage('Ordinary resumed target');
  await tick();
  assert.equal(kit.servers[0].stopped, 1);
  assert.equal(kit.servers[1].stopped, 0);
  assert.equal(kit.servers[1].handlers.length, 1);
});

test('cancelling a queued recovery cannot release an earlier admission probe', async function(t) {
  var release, probing = false;
  var probe = new Promise(function(resolve) { release = resolve; });
  var kit = fixture(t, function(server, method) {
    if (probing && method === 'thread/backgroundTerminals/list') return probe;
  });
  var idle = await kit.fresh();
  idle.pushMessage('Idle');
  await tick();
  kit.servers[0].complete('thread-1');
  await tick();
  probing = true;
  var first = kit.recover({ resumeSessionId: 'thread-1' });
  await tick();
  var controller = new AbortController();
  var cancelled = assert.rejects(kit.recover({ resumeSessionId: 'cancelled-thread', abortController: controller }), { name: 'AbortError' });
  controller.abort();
  await cancelled;
  var admitted = false;
  var ordinary = kit.fresh().then(function(handle) { admitted = true; return handle; });
  await tick();
  assert.equal(admitted, false);
  release({ data: [] });
  await first;
  await ordinary;
  assert.equal(kit.servers.length, 3);
});

test('initialization races keep recovery cancellable without resurrecting a cancelled ordinary handle', async function(t) {
  var release;
  var initialization = new Promise(function(resolve) { release = resolve; });
  var first = true;
  var kit = fixture(t, function(server, method) {
    if (method === 'initialize' && first) { first = false; return initialization; }
  });
  var controller = new AbortController();
  var cancelled = assert.rejects(kit.fresh({ abortController: controller }), { name: 'AbortError' });
  await tick();
  var waiting = false;
  var recovery = kit.recover({ onRecoveryWaiting: function() { waiting = true; } });
  await until(function() { return waiting; });
  controller.abort();
  await cancelled;
  release({});
  await recovery;
  assert.equal(kit.servers[0].handlers.length, 0);
  assert.equal(kit.servers[0].stopped, 1);
});

test('Stop during unsubscribe keeps admission closed until that lifecycle RPC settles', async function(t) {
  var release;
  var unsubscribe = new Promise(function(resolve) { release = resolve; });
  var kit = fixture(t, function(server, method) {
    if (method === 'thread/unsubscribe') return unsubscribe;
  });
  var previous = await kit.fresh({ resumeSessionId: 'saved-thread' });
  previous.pushMessage('Previous turn');
  await tick();
  kit.servers[0].complete('saved-thread');
  await tick();
  var sibling = await kit.fresh();
  sibling.pushMessage('Sibling turn');
  await tick();
  var controller = new AbortController();
  var cancelled = assert.rejects(kit.recover({ abortController: controller }), { name: 'AbortError' });
  await until(function() { return kit.servers[0].calls.some(function(call) { return call.method === 'thread/unsubscribe'; }); });
  controller.abort();
  await cancelled;
  var admitted = false;
  var ordinary = kit.fresh({ resumeSessionId: 'saved-thread' }).then(function(handle) { admitted = true; return handle; });
  await tick();
  assert.equal(admitted, false);
  kit.servers[0].loaded = kit.servers[0].loaded.filter(function(id) { return id !== 'saved-thread'; });
  release({ status: 'unsubscribed' });
  var handle = await ordinary;
  handle.pushMessage('Resume after unsubscribe finished');
  await tick();
  assert.equal(kit.servers[0].stopped, 0);
  assert.equal(kit.servers[0].calls.filter(function(call) { return call.method === 'thread/resume' && call.params.threadId === 'saved-thread'; }).length, 2);
});

test('closed inputs do not authorize reclaiming unrelated loaded background work', async function(t) {
  var kit = fixture(t);
  var handle = await kit.fresh();
  handle.pushMessage('Leave a background terminal');
  await tick();
  kit.servers[0].complete('thread-1');
  await tick();
  handle.endInput();
  await tick();
  await kit.recover();
  assert.equal(kit.servers[0].stopped, 0);
  assert.equal(kit.servers[0].loaded.indexOf('thread-1') !== -1, true);
});

test('a disconnected shared provider fails admission explicitly without starting another writer', async function(t) {
  var kit = fixture(t, function(server, method) {
    if (method === 'thread/loaded/list') { server.started = false; return Promise.reject(new Error('Provider disconnected')); }
  });
  var active = await kit.fresh();
  active.pushMessage('Active turn');
  await tick();
  await assert.rejects(kit.recover(), /Provider disconnected/);
  assert.equal(kit.servers.length, 1);
});

test('unconfirmed recovery process exit retains its target reservation after bounded cleanup', async function() {
  var EventEmitter = require('node:events').EventEmitter;
  var proc = new EventEmitter();
  proc.exitCode = null; proc.signalCode = null; proc.kill = function() {};
  // The process is synthetic and deliberately cannot exit. No real child or
  // external runtime is created; shutdown failure is asserted explicitly.
  var kit = fixture({ after: function() {} }, function(server, method) {
    if (method === 'initialize') server.proc = proc;
  });
  var first = await kit.recover();
  first.pushMessage('Running');
  await tick();
  await first.abort();
  await assert.rejects(kit.recover(), /exit could not be confirmed/);
  assert.equal(kit.servers.length, 1);
  await assert.rejects(kit.adapter.shutdown(), /cleanup could not be confirmed/);
});

test('unconfirmed shared process exit also blocks ordinary resumes and warmup', async function() {
  var EventEmitter = require('node:events').EventEmitter;
  var proc = new EventEmitter();
  proc.exitCode = null; proc.signalCode = null; proc.kill = function() {};
  var kit = fixture({ after: function() {} });
  var handle = await kit.fresh();
  handle.pushMessage('Previous shared turn');
  await tick();
  kit.servers[0].complete('thread-1');
  await tick();
  kit.servers[0].proc = proc;
  await assert.rejects(kit.recover({ resumeSessionId: 'thread-1' }), /shared runtime exit could not be confirmed/);
  await assert.rejects(kit.fresh({ resumeSessionId: 'thread-1' }), /shared runtime exit could not be confirmed/);
  await assert.rejects(kit.adapter.init({}), /shared runtime exit could not be confirmed/);
  assert.equal(kit.servers.length, 1);
  await assert.rejects(kit.adapter.shutdown(), /shared runtime exit could not be confirmed/);
});

test('ordinary input waits through recovery-owned idle shutdown and attaches after confirmed exit', async function(t) {
  var EventEmitter = require('node:events').EventEmitter;
  var proc = new EventEmitter();
  proc.exitCode = null; proc.signalCode = null; proc.kill = function() {};
  var kit = fixture(t);
  var handle = await kit.fresh();
  handle.pushMessage('Previous shared turn');
  await tick();
  kit.servers[0].complete('thread-1');
  await tick();
  kit.servers[0].proc = proc;
  var stop = kit.servers[0].stop;
  kit.servers[0].stop = function() {
    stop();
    setTimeout(function() { proc.exitCode = 0; proc.emit('exit'); }, 60);
  };
  var recovery = kit.recover({ resumeSessionId: 'thread-1' });
  await until(function() { return kit.servers[0].stopped === 1; });
  var ordinary = kit.fresh();
  await recovery;
  var fresh = await ordinary;
  assert.equal(fresh.pushMessage('New ordinary input'), true);
  await tick();
  assert.equal(kit.servers.length, 3);
  assert.equal(proc.exitCode, 0);
  assert.equal(kit.servers[2].calls.filter(function(call) { return call.method === 'turn/start'; }).length, 1);
});