Remove what the connector's worker side left behind

Draft
RO
16d ago
+1190-9026

Stacked on #821, which reworded the comments around this code and listed it as dead.

Why

#815 removed the connector's worker side, but left the code that worker side used. No command reaches it:

  • Ledger.Redispatch and its helpers (RedispatchResult, LiveWorker, authorizeBlocked, AuthorizedBlocked).
  • The ledger's whole write side for tasks and attempts: LaunchTask, EndAttempt, CreateTask, SupersedeTask, Dispatch with TaskDispatch (the worker's get_dispatch, ack_dispatch and complete_dispatch), MarkRunning, RecordTaker, ExposeEvent, JoinConversation, StartableRecords, adoption, refusals and still-running.
  • The outbox's readers and resolver (Intents, Intent, ResolveIntent, IsLifecycleReceipt). The outbox table is now written only by its migrations and triggers.
  • The ledger's Hooks. Only the removed dispatcher set them, so every call site ran a nil check and nothing more.
  • OpenExistingLedger and ResolveStateDir (the worker's MCP server), Held (the outbox sender), UnfinishedFromOthers (dangerous mode).
  • setup.TryLock and setup.Duration.
  • Almost all of internal/connector/driver: StartWorker, the preflight probe, the redactor, the environment builder, TerminateRecorded, ConfirmGroupGone and the process-group signals.

make deadcode finds the driver package, TryLock and Duration. It does not find the ledger methods: *Ledger reaches reflect, so deadcode keeps every exported method alive (-whylive says "reachable only through reflection"). I found those with a reference walk that ignores reflection, and confirmed each one with grep.

What

Removed, with the tests that only tested them: about 8,900 lines out, 1,100 in, across 56 files.

internal/connector/driver is now internal/connector/procid. The package kept only the process-identity code: Process, OwnsWorker, LookupProcess, ErrGroupOutlivedLeader and ErrIdentityUnknown, with the per-platform start-time readers. "driver" named an agent boundary that no longer exists, so a small package named for what it does is easier to read. OwnsWorker sends only the zero signal now; the signals that ended process groups went with TerminateRecorded.

Simplified where a removal left a branch with no caller:

  • openLedger loses its non-owner branch, because OpenExistingLedger was the only non-owner caller.
  • operatorEdges keeps only the edges a discard and an import take (into discarded). The edges out of completed and held belonged to redispatch.
  • eventTask, which a discard and an import read, keeps only the outcome and when it settled.
  • setup.Lock inlines its helper, because TryLock was the only other caller.
  • InstructionReply is now HandoffReply, beside HandoffLine, which is the only thing that uses it. The JSON is the same.

Comments. The dispatch lifecycle in ledger_dispatch.go, the tasks header in ledger_tasks.go, the outbox invariants and the hold invariants now say what this build does and what an older build's ledger can hold. They no longer describe functions that are gone.

Also fixed: internal/commands tests did not compile for Windows (a pre-existing problem since #811). Two tests in connect_start_wait_test.go use Unix-only fixtures. They move to connect_start_wait_unix_test.go, so GOOS=windows go vet ./... is clean.

No behavior change.

What stays and why

  • The schema, every migration, table, trigger and index, unchanged. Older ledgers hold tasks, attempts, task events, outbox intents and waiting redispatches, and the triggers still guard every write to those rows.
  • Status and doctor reporting of worker-era state: tasks with their worker and token taker (through procid.OwnsWorker), dispatches, intents, authorized_blocked and redispatch_pending. --json output is unchanged.
  • discard, import, shadow promote and the hold, including how they withdraw a redispatch an older build left waiting, and how they cancel a pending guard acknowledgement or holding reply.
  • move's guard on records a worker was handed (ErrHeldByWorker) and the lifecycle's edges into dispatched, because older ledgers hold dispatched records.
  • The IntentKind, IntentState, MessageKind and Outcome vocabularies, because status reads intents and outcomes through them. AttemptState, StopReason and Delivery had no reader left and are removed.
  • Non-worker test seams that deadcode still reports (Queue.Depth, Intake.CheckpointKey, admission.WithClock and others), and DropContent, which no command calls. These were dead before #815 and are not worker code, so this PR leaves them.

Tests

  • worker_era_test.go is new. It writes the rows the removed dispatcher wrote, with its statements and in its order, so the schema's triggers check them. The tests for status, discard, import, the hold, retention and move now build older-ledger state with it instead of calling the removed methods.
  • The tests that remain check behavior that still exists. For example: a hold, an import and a discard each withdraw a waiting redispatch; retention keeps a waiting redispatch's snapshot; status shows a worker-era task and an unaccounted token holder.
  • The unreadable connect.json test now waits for the record's timed retry instead of a redispatch.
  • procid keeps the identity tests: reused pid, no kernel start time, a group that outlived its leader, and zombie leaders on Linux and macOS.
  • make deadcode, before and after, on all five release platforms. Shipped binary: 157 to 85 unreachable functions (151 to 85 on Windows); internal/connector: 79 to 7 (74 to 8 on Windows). The -tags dev build drops the same set. The 7 that remain are the non-worker test seams above, and InstanceLock.Path. Windows adds the non-Unix procid.OwnsWorker stub: status asks about a recorded worker only on Unix, and the stub keeps the package's API the same on every platform.
  • go vet ./... is clean for linux, darwin, windows, freebsd and openbsd, and with -tags dev.
  • go test -race passes for internal/connector/... and internal/commands.
  • bin/ci is green.

Summary by cubic

Removes the code no command reaches since #815 removed the connector's worker side: the ledger's task and attempt writers, Redispatch and its helpers, the outbox readers and resolver, the never-installed ledger hooks, setup.TryLock and setup.Duration, and most of internal/connector/driver. No behavior change — about 8,900 lines out and 1,100 in, across 56 files.

What stays

  • The schema, migrations and triggers are unchanged; ledgers an older build wrote still hold tasks, attempts, outbox intents and waiting redispatches.
  • Status, doctor, discard, import, shadow promote and the hold still read and clear worker-era rows; the new worker_era_test.go writes those rows the way the removed dispatcher did, so the schema's triggers check them.
  • The process-identity code moves into internal/connector/procid, a package named for what it does.
  • Two Unix-only start-wait tests move behind a build tag, fixing a pre-existing Windows compile break.