fix: let replay recover from dead letter jobs

This commit is contained in:
ImBenji
2026-08-08 23:32:41 +01:00
parent 0344d5ca97
commit 2c023c8962
3 changed files with 104 additions and 32 deletions
+35
View File
@@ -11,6 +11,7 @@ const { validatePaperIntent, createSimulator } = require('../src/autonomy/execut
const { calculateOutcome } = require('../src/autonomy/outcomes');
const { createOrderIntent } = require('../src/autonomy/orderIntents');
const { reconcileArchiveBatch, reconcileLiveBatch } = require('../workers/autonomyWorker');
const { scheduleNext } = require('../workers/replayWorker');
test('autonomy schema and leased jobs are restart-safe', () => {
const db = new Database(':memory:');
@@ -73,6 +74,40 @@ test('replay evidence cannot look beyond its information cutoff and remains non-
assert.equal(executable.length, 0);
});
test('replay scheduler skips terminal replay jobs instead of pinning the cursor', () => {
const archive = new Database(':memory:');
archive.exec(`
CREATE TABLE articles (
id INTEGER PRIMARY KEY,
title TEXT,
description TEXT,
content TEXT,
pub_date_effective TEXT,
is_index_page INTEGER
)
`);
archive.prepare("INSERT INTO articles VALUES (1, 'bad', '', 'content', '2020-01-01T00:00:00Z', 0)").run();
archive.prepare("INSERT INTO articles VALUES (2, 'next', '', 'content', '2020-01-02T00:00:00Z', 0)").run();
const intelligence = new Database(':memory:');
initAutonomySchema(intelligence);
const runId = intelligence.prepare(`
INSERT INTO autonomy_replay_runs (watermark_at, strategy_version, prompt_version, coordinator_model)
VALUES ('2020-01-03T00:00:00Z', 'test', 'test', 'test')
`).run().lastInsertRowid;
enqueueJob(intelligence, {
jobType: 'replay_article', lane: 'historical', priority: 1, entityType: 'article', entityId: 1,
idempotencyKey: `replay:${runId}:article:1`,
});
intelligence.prepare("UPDATE autonomy_jobs SET status='dead_letter', attempts=5, last_error='fetch failed'").run();
const run = intelligence.prepare('SELECT * FROM autonomy_replay_runs WHERE id=?').get(runId);
const next = scheduleNext(intelligence, archive, run);
assert.equal(next.id, 2);
assert.equal(intelligence.prepare('SELECT cursor_article_id FROM autonomy_replay_runs WHERE id=?').get(runId).cursor_article_id, 1);
assert.equal(intelligence.prepare("SELECT COUNT(*) count FROM autonomy_jobs WHERE status='pending' AND entity_id='2'").get().count, 1);
});
test('calibration and policy abstain on insufficient evidence', () => {
const calibration = calibrateOutcomes([
{ excess_return: 0.02, direction_correct: 1 },