Files
STTracker/docs/plans/001-phase1-sdd/task-9-fix1-findings.md
T
Lucas WintherandClaude Opus 5.5 be04fab098 docs: phase 1 handoff, execution ledger and task reports
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>
2026-11-02 04:53:02 +01:00

3.7 KiB
Raw Blame History

Task 9: fix round 1 (binding)

File:line references are to .worktrees/t9 at 166b8ec.

  1. A failed connection is never scheduled again (jobs.ts:528).

    • The scheduler selects connections with status != 'paused' (i.e. active or error), schedule_minutes set, and due.
    • Test: an error connection that is due gets enqueued.
  2. Failures before runSync loop invisibly forever (connections.ts:338-371). Causes: a decrypt failure, a missing plugin, a deleted or paused connection.

    • Ruling: syncHandler catches 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_runs row (mode as requested, status failed, error message) and set the connection status = 'error';
      • advance last_run_at so 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."
    • Signal non-retryable to the worker with a NonRetryableError class, exported from jobs.ts, that the worker marks failed immediately without backoff.
    • Tests for each case.
  3. An unhandled rejection can kill the process (jobs.ts:445-465, 495).

    • Wrap all bookkeeping in runJob in try/catch that logs via console.error("[jobs]", …).
    • Attach .catch(log) before adding to inflight.
    • stop() never rejects.
    • Also add a reaper: at startWorker, and on every tick, reset jobs with status='running' and locked_at older than 1 hour back to queued (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.
  4. 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.

Minors (include):

  • Replace .catch(() => {}) in the worker tick and scheduler with logging (console.error("[jobs]", err)).
  • Run-scoped context. syncHandler passes a makeContext(conn, runId) that builds the context per run, so ctx.log appends to that run's source_runs.log (buffer, flushed by runSync's bookkeeping or appended with a cheap update; your call, but it must be persisted).
  • credentials.save reads the CURRENT DB blob, merges and writes inside one transaction (tx). updateConnection's read-modify-write also runs in one transaction.
  • Abort ctx.signal when stop() is called on the worker (pass an AbortController into job handlers via a second argument, handler(payload, { signal }), and thread it into makePluginContext).
  • 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.md data 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.