feat(jobs): assistant answers in the Jobs tray (core JobTracking, QQQ RC.8) #54

Merged
KofTwentyTwo merged 4 commits from feature/jobs-tray into develop 2026-10-15 02:25:23 +00:00
KofTwentyTwo commented 2026-10-15 02:21:06 +00:00 (Migrated from github.com)

Why

The owner asked for assistant runs to show in the Jobs tray. #49 added the AssistantRunTracker hook as a stand-in until core job tracking shipped (STAND-IN(core=QRun-IO/qqq#1210)). QQQ 4.1.0-RC.8, now on Maven Central, ships JobTracking, so this PR replaces the stand-in with the real tracker.

What

  • JobTrackingRunTracker is the new default AssistantRunTracker. Each answer becomes a core tracking job:
    • processName assistant.turn, source INLINE, label "Assistant answer", owned by the user, linked to its assistant_conversation.
    • Phases are thinking, tool and writing. During the tool phase, the tool's label is the message.
    • Stop in the tray (POST /jobs/{id}/cancel) stops the turn. The turn's own finaliser then finishes the job as COMPLETED, CANCELLED or FAILED, with fixed messages. Prompt and answer text never reach the job row or its log.
    • If the pod dies, core's reaper fails the job, and the turn's own lease ends the turn.
    • If no durable jobs runtime is running on the pod, answers are not tracked and nothing else changes.
  • withRunTracker(AssistantRunTracker.NOOP) opts out; hosts can still plug in their own tracker.
  • The build now uses QQQ 4.1.0-RC.8.

Tests

./mvnw verify -pl qbit-assistant -am passes: 325 tests, with the JaCoCo gate met. The new JobTrackingRunTrackerTest runs a real DurableJobsRuntime and covers:

  • phases, then completion
  • Stop from the tray cancelling the answer
  • a failed answer that leaves no transcript text in the job or its log
  • no runtime running
  • separate phase state for each job
  • the status mapping.

Codex wrote the tests and adjusted the tracker; Claude reviewed both.

🤖 Generated with Claude Code

## Why The owner asked for assistant runs to show in the Jobs tray. #49 added the `AssistantRunTracker` hook as a stand-in until core job tracking shipped (`STAND-IN(core=QRun-IO/qqq#1210)`). QQQ 4.1.0-RC.8, now on Maven Central, ships `JobTracking`, so this PR replaces the stand-in with the real tracker. ## What - `JobTrackingRunTracker` is the new default `AssistantRunTracker`. Each answer becomes a core tracking job: - processName `assistant.turn`, source INLINE, label "Assistant answer", owned by the user, linked to its `assistant_conversation`. - Phases are thinking, tool and writing. During the tool phase, the tool's label is the message. - Stop in the tray (`POST /jobs/{id}/cancel`) stops the turn. The turn's own finaliser then finishes the job as COMPLETED, CANCELLED or FAILED, with fixed messages. Prompt and answer text never reach the job row or its log. - If the pod dies, core's reaper fails the job, and the turn's own lease ends the turn. - If no durable jobs runtime is running on the pod, answers are not tracked and nothing else changes. - `withRunTracker(AssistantRunTracker.NOOP)` opts out; hosts can still plug in their own tracker. - The build now uses QQQ 4.1.0-RC.8. ## Tests `./mvnw verify -pl qbit-assistant -am` passes: 325 tests, with the JaCoCo gate met. The new `JobTrackingRunTrackerTest` runs a real `DurableJobsRuntime` and covers: - phases, then completion - Stop from the tray cancelling the answer - a failed answer that leaves no transcript text in the job or its log - no runtime running - separate phase state for each job - the status mapping. Codex wrote the tests and adjusted the tracker; Claude reviewed both. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.