Promote task naar IN_PROGRESS bij ClaudeJob CLAIMED/RUNNING (#25)

* feat: add pushed_at field to ClaudeJob schema

Nullable DateTime column to record when the agent's feature branch was
pushed to origin. Enables the UI to show a 'pushed' state independently
of DONE status.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(db): promote task naar IN_PROGRESS bij ClaudeJob CLAIMED/RUNNING

Solo-kaart bleef in 'Te doen'-kolom staan terwijl de agent al bezig
was — alleen DONE was via een trigger gekoppeld (vorige migration).

Nieuwe Postgres-trigger claude_job_claim_to_task: bij INSERT of
UPDATE OF status naar CLAIMED|RUNNING promoot de bijbehorende task
van TO_DO naar IN_PROGRESS. Forceert niet vanuit andere status —
handmatige overrides (REVIEW, DONE) blijven staan.

De bestaande notify_task_change-trigger op tasks zorgt automatisch
voor de pg_notify zodat de Solo-paneel-UI direct synct.

- migration: 20260501130000_promote_task_to_in_progress_on_claim
- doc: architecture.md sectie 'Auto-promote task-status op job-overgangen' uitgebreid

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-01 12:01:27 +02:00 committed by GitHub
parent 3bb87f17ba
commit acb591266f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 45 additions and 2 deletions

View file

@ -1161,9 +1161,14 @@ UI klikt 'Voer uit'
`enqueueClaudeJobAction` weigert een tweede enqueue als er al een job bestaat met `status IN (QUEUED, CLAIMED, RUNNING)`. Teruggestuurde fout bevat het bestaande `jobId` zodat de UI ernaar kan linken. `enqueueClaudeJobAction` weigert een tweede enqueue als er al een job bestaat met `status IN (QUEUED, CLAIMED, RUNNING)`. Teruggestuurde fout bevat het bestaande `jobId` zodat de UI ernaar kan linken.
### Auto-promote task naar DONE ### Auto-promote task-status op job-overgangen
Wanneer een `claude_job` op `DONE` komt, vuurt de Postgres-trigger `claude_job_status_to_task` (zie `prisma/migrations/20260501110000_sync_task_status_from_claude_job`) en zet de bijbehorende task ook op `DONE`. Werkt voor INSERT (direct als DONE aangemaakt) en UPDATE (transitie naar DONE). Idempotent: skip wanneer de task al DONE is. De bestaande `notify_task_change`-trigger op `tasks` vuurt dan automatisch de pg_notify zodat de Solo-paneel-UI synct — geen extra plumbing in de SSE-handler nodig. Twee Postgres-triggers houden `task.status` in sync met `claude_job.status` zodat de Solo-kaart altijd in de juiste kolom staat:
- **`claude_job_claim_to_task`** (`prisma/migrations/20260501130000_promote_task_to_in_progress_on_claim`): bij INSERT met status `CLAIMED|RUNNING` of UPDATE OF status naar `CLAIMED|RUNNING`, promoot de bijbehorende task van `TO_DO` naar `IN_PROGRESS`. Forceert niet vanuit andere status — handmatige overrides (REVIEW, DONE) blijven staan.
- **`claude_job_status_to_task`** (`prisma/migrations/20260501110000_sync_task_status_from_claude_job`): bij DONE zet de task ook op `DONE`. Idempotent: skip wanneer task al DONE is.
De bestaande `notify_task_change`-trigger op `tasks` vuurt automatisch de pg_notify naar `/api/realtime/solo` zodat de UI direct synct — geen extra plumbing in de SSE-handler nodig.
### Hybride-ready ### Hybride-ready

View file

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "claude_jobs" ADD COLUMN "pushed_at" TIMESTAMP(3);

View file

@ -0,0 +1,35 @@
-- Promoot task naar IN_PROGRESS zodra een ClaudeJob CLAIMED of RUNNING wordt.
--
-- Aanvulling op de DONE-trigger uit
-- 20260501110000_sync_task_status_from_claude_job. Daar handelen we de
-- afronding af; hier handelen we de aanvang. Zonder deze trigger blijft
-- een task in de "Te doen"-kolom staan terwijl de agent er al mee bezig
-- is — verwarrend voor de gebruiker.
--
-- Voorwaarde: task moet nog op TO_DO staan. We forceren niet vanuit
-- IN_PROGRESS/REVIEW/DONE terug — die zijn handmatig gezet door de
-- gebruiker en hebben prioriteit.
--
-- De bestaande notify_task_change-trigger op tasks vuurt automatisch de
-- pg_notify naar /api/realtime/solo zodat de UI synct.
CREATE OR REPLACE FUNCTION promote_task_on_claude_job_claim() RETURNS trigger AS $$
BEGIN
IF NEW.status IN ('CLAIMED', 'RUNNING') THEN
IF (TG_OP = 'INSERT')
OR (TG_OP = 'UPDATE' AND OLD.status IS DISTINCT FROM NEW.status)
THEN
UPDATE tasks
SET status = 'IN_PROGRESS', updated_at = now()
WHERE id = NEW.task_id AND status = 'TO_DO';
END IF;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS claude_job_claim_to_task ON claude_jobs;
CREATE TRIGGER claude_job_claim_to_task
AFTER INSERT OR UPDATE OF status ON claude_jobs
FOR EACH ROW
EXECUTE FUNCTION promote_task_on_claude_job_claim();

View file

@ -260,6 +260,7 @@ model ClaudeJob {
claimed_at DateTime? claimed_at DateTime?
started_at DateTime? started_at DateTime?
finished_at DateTime? finished_at DateTime?
pushed_at DateTime?
plan_snapshot String? plan_snapshot String?
branch String? branch String?
summary String? summary String?