Skip to content

ControllerJobHandle::new is pub(crate), so domain drivers cannot unit-test their supervision loop #11858

Description

@chubes4

Surfaced by #11857 (CookJobDriver).

ControllerJobHandle::new is pub(crate) in homeboy-core:

impl ControllerJobHandle {
    pub(crate) fn new(job: JobHandle, driver: Arc<dyn ControllerJobDriver>) -> Self { ... }

A ControllerJobDriver lives in a domain crate (homeboy-agents, homeboy-cli) but its two most important methods — execute and resume — take a ControllerJobHandle. A domain crate therefore cannot construct one, and cannot unit-test the code path that actually runs.

This is not specific to cook. It applies to every driver: AgentTaskPromotionJobDriver, LabStagingDispatchDriver, and CleanupJobDriver all have the same blind spot.

Effect on #11857

CookJobDriver's supervision loop is verified by reading, not by running. Mitigations used there:

  • resume_disposition() was extracted so the idempotency decision is testable without a handle
  • the cancel path is covered by a real child-kill test that does not need one
  • 11 tests pass, but none enters execute/resume/supervise

That is a reasonable workaround and a poor substitute.

Proposal

Add a test-only constructor gated the way the rest of the codebase gates test surface:

#[cfg(any(test, feature = "test-support"))]
pub fn for_tests(job: JobHandle, driver: Arc<dyn ControllerJobDriver>) -> Self

JobHandle will likely need equivalent treatment — check before assuming this is a one-liner.

A fake/recording handle capturing progress/checkpoint/is_cancelled would be even better, since most driver tests want to assert "it checkpointed after the idempotent phase" rather than drive a real job store. ControllerJobHandle is a thin wrapper over JobHandle plus the driver's projections, so a trait or an injectable sink is plausible without disturbing the daemon.

Why it matters beyond testing

The public_* projections exist specifically so private driver state cannot leak into the durable public job log. That is a security-shaped invariant, and right now no driver can test it end to end through a real handle — only by calling the projection functions directly, which does not prove the handle actually routes through them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — plannedtech-debt-sweep2026-08-06 tech debt investigation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions