Captures the owner's requirements and decisions from the planning conversation, current branch/worktree state, open tasks 17-19, pending owner decisions and the controller's rulings so a new agent can resume. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.7 KiB
3.7 KiB
Task 9: fix round 1 (binding)
File:line references are to .worktrees/t9 at 166b8ec.
-
A failed connection is never scheduled again (jobs.ts:528).
- The scheduler selects connections with
status != 'paused'(i.e.activeorerror),schedule_minutesset, and due. - Test: an
errorconnection that is due gets enqueued.
- The scheduler selects connections with
-
Failures before runSync loop invisibly forever (connections.ts:338-371). Causes: a decrypt failure, a missing plugin, a deleted or paused connection.
- Ruling:
syncHandlercatches these, and the job does NOT retry:- a missing or deleted connection: drop silently (the job is marked done with last_error);
- a missing plugin, or a CryptoError: insert a
source_runsrow (mode as requested, statusfailed, error message) and set the connectionstatus = 'error'; - advance
last_run_atso the scheduler waits a full interval.
- Messages:
- CryptoError →
"Cannot decrypt this source's credentials. Was STTRACKER_SECRET changed? Reconnect the source to fix it." - missing plugin →
"Plugin '<id>' is not installed or failed to load."
- CryptoError →
- Signal non-retryable to the worker with a
NonRetryableErrorclass, exported from jobs.ts, that the worker marksfailedimmediately without backoff. - Tests for each case.
- Ruling:
-
An unhandled rejection can kill the process (jobs.ts:445-465, 495).
- Wrap all bookkeeping in
runJobin try/catch that logs viaconsole.error("[jobs]", …). - Attach
.catch(log)before adding toinflight. stop()never rejects.- Also add a reaper: at
startWorker, and on every tick, reset jobs withstatus='running'andlocked_atolder than 1 hour back toqueued(attempts unchanged), so a crash never holds a lockKey forever. - Tests: a handler whose bookkeeping update fails (inject one) doesn't reject
stop(); a stale running job is re-queued.
- Wrap all bookkeeping in
-
Reload misses a plugin's non-index files (plan-mandated limitation, verified on Bun 1.3.14).
- Ruling: keep
?v=reload, but document it. Add a DECISIONS entry ("reload re-imports entry files only; changes in a plugin's other modules need a server restart") and a TODO line. - Make the reload test assert that a change to the entry file IS picked up: write a temp plugin dir, reload, edit index.ts, reload, and see the new manifest version.
- Ruling: keep
Minors (include):
- Replace
.catch(() => {})in the worker tick and scheduler with logging (console.error("[jobs]", err)). - Run-scoped context.
syncHandlerpasses amakeContext(conn, runId)that builds the context per run, soctx.logappends to that run'ssource_runs.log(buffer, flushed by runSync's bookkeeping or appended with a cheap update; your call, but it must be persisted). credentials.savereads the CURRENT DB blob, merges and writes inside one transaction (tx).updateConnection's read-modify-write also runs in one transaction.- Abort
ctx.signalwhenstop()is called on the worker (pass an AbortController into job handlers via a second argument,handler(payload, { signal }), and thread it intomakePluginContext). - Add a test that asserts the rate-limit wiring: makePluginContext with manifest
rateLimit {perMinute: 60, burst: 1}and a fake clock or sleep spacing two calls. - Remove the orphaned comment in plugins/mangabaka/src/api.ts:4.
docs/ARCHITECTURE.mddata flow: mark steps 1–2 as real. TODO: rate limiting is per run, not per plugin (spec §11 says per plugin; Phase 2).
Run both dialects:
bun test packages/core plugins;- the same with
TEST_POSTGRES_URL=postgres://postgres:postgres@127.0.0.1:55432/postgres; bun run typecheck.
Commit fix(core): …, append "Fix round 1" to task-9-report.md, and reply with the short contract.