feat(web): DEPLOY-job — spec/plan, migraties, seed, actions, UI (M17, PBI-124) #98

Merged
janpeter merged 27 commits from claude/gallant-kepler-c118ed into main 2026-07-04 14:55:30 +02:00
Owner

Fases 0-doc + 1 + 2 van M17 (PBI-124, auto-deploy op scrum4me-server na PR-merge):

Docs: spec docs/superpowers/specs/2026-07-03-deploy-job-design.md (rev 5, 4× codex-GO) + plan docs/plans/M17-deploy-job.md (v3 approved: codex r1-NO-GO→r3-GO + multi-model panel).

DB (fase 1): submodule-bump naar shared a84cc3a; migratie 1 (enum-add); migratie 2 (auto_deploy/deploy_flow/resolved_at + partial unique dedup-index + DEPLOY-tak in claude_jobs_kind_id_consistency — zonder die tak falen SYSTEM-inserts op 23514, bestaande takken byte-bewezen identiek); seed-rij DEPLOY.

Actions/UI (fase 2): updateAutoDeploy/updateDeployFlow (invariant beide richtingen), deployNowAction (product-lock → config-read → active-guard → create, mutatie-bewezen volgorde; rate-limit-config), markDeployResolvedAction (lift-pad 2, re-guarded updateMany), DEPLOY uitgesloten van restart (acceptatiecriterium §6), deploy-sectie op product-instellingen + Deploy nu-knop met uitrol-gate, DEPLOY-labels in alle kind-maps (+ provisorische IDEA_CHAT-entries — klein conflict met de idea-chat-web-stroom geaccepteerd), admin markeer-afgehandeld-knop.

Verify volledig groen: 0 lint-fouten, tsc schoon, 192 testbestanden / 1553 tests. Alle taken dubbel gereviewd (spec + kwaliteit) met mutatie-bewijzen in de story-logs (ST-1457/ST-1458).

Migratie-uitrol na merge: server via web-deploy (designated migrator) + eenmalig npm run seed; Neon handmatig via NEON_URL (fase 4, T-1325).

Zuster-PR: scrum4me-mcp #62 (fase 3) — beide nodig vóór de server-rollout.

🤖 Generated with Claude Code

Fases 0-doc + 1 + 2 van M17 (PBI-124, auto-deploy op scrum4me-server na PR-merge): **Docs:** spec `docs/superpowers/specs/2026-07-03-deploy-job-design.md` (rev 5, 4× codex-GO) + plan `docs/plans/M17-deploy-job.md` (v3 approved: codex r1-NO-GO→r3-GO + multi-model panel). **DB (fase 1):** submodule-bump naar shared a84cc3a; migratie 1 (enum-add); migratie 2 (auto_deploy/deploy_flow/resolved_at + partial unique dedup-index + **DEPLOY-tak in `claude_jobs_kind_id_consistency`** — zonder die tak falen SYSTEM-inserts op 23514, bestaande takken byte-bewezen identiek); seed-rij DEPLOY. **Actions/UI (fase 2):** updateAutoDeploy/updateDeployFlow (invariant beide richtingen), deployNowAction (product-lock → config-read → active-guard → create, mutatie-bewezen volgorde; rate-limit-config), markDeployResolvedAction (lift-pad 2, re-guarded updateMany), DEPLOY uitgesloten van restart (acceptatiecriterium §6), deploy-sectie op product-instellingen + Deploy nu-knop met uitrol-gate, DEPLOY-labels in alle kind-maps (+ provisorische IDEA_CHAT-entries — klein conflict met de idea-chat-web-stroom geaccepteerd), admin markeer-afgehandeld-knop. Verify volledig groen: 0 lint-fouten, tsc schoon, 192 testbestanden / 1553 tests. Alle taken dubbel gereviewd (spec + kwaliteit) met mutatie-bewijzen in de story-logs (ST-1457/ST-1458). **Migratie-uitrol na merge:** server via web-deploy (designated migrator) + eenmalig `npm run seed`; Neon handmatig via NEON_URL (fase 4, T-1325). Zuster-PR: scrum4me-mcp #62 (fase 3) — beide nodig vóór de server-rollout. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Brainstorm-uitkomst 2026-07-02/03: nieuw ClaudeJob-kind DEPLOY, enqueue bij
auto-merge-enable, merge-wacht in de job, uitvoering via ops-agent-flows,
per-product opt-in (Product.auto_deploy), fail-loud zonder auto-rollback,
v1 = hele platform-stack + 'Deploy nu'-knop voor handmatige merges.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hoog: eigen update_job_status-lifecycle-branch (done/skipped/failed DB-only,
skipped-redenen), DB-harde dedup via partial unique index op orchestration_key
(kind=DEPLOY), lease runner-owned (job_heartbeat uit allowlist).
Middel: mcp-werk gepreciseerd (claim-filter source+capability, getFullJobContext-
payload, enqueue-hook na geslaagd ENABLE_AUTO_MERGE), per-flow doc-classifier
fail-closed, blokkade-na-falen cancelt ook QUEUED deploys, credential boundary
expliciet (2 narrow tokens).

Alle 3 hoog-bevindingen onafhankelijk geverifieerd tegen scrum4me-mcp/-docker code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Blok-predicaat nu veld-gebaseerd: ClaudeJob.resolved_at + admin-actie 'markeer
afgehandeld' (FAILED kan niet naar CANCELLED); bulk-cancel-semantiek expliciet
(CANCELLED/error/finished_at + pg_notify per job, web-push alleen FAILED);
merge-wacht-timeout v1 in kind-prompt (JobKindConfig heeft geen timeout-veld);
active-job-guard op de 'Deploy nu'-action.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Product-scoped pg_advisory_xact_lock op alle deploy-state-muterende paden
(auto/manual enqueue, failed-branch, manual-DONE-lift, markeer-afgehandeld)
tegen READ COMMITTED-races tussen web en mcp; DEPLOY uitgesloten van generieke
restartClaudeJobAction — herstel-pad is 'Deploy nu'. Beide als acceptatiecriteria.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6 fases over 5 repos: shared (kind+defaults+canoniek schema) -> web
(migraties, seed, actions/UI) -> mcp (lifecycle-branch, enqueue-hook,
claim-filter, payload, dispatch, kind-prompt) -> server-rollout
(ops-agent repo_head_sha, worker-deploy compose) -> E2E. TDD per taak;
beide acceptatiecriteria (product-lock, restart-uitsluiting) gedekt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codex hoog: DEPLOY-tak in kind_id_consistency-constraint (SYSTEM-inserts
faalden anders op 23514); terminale status + bulk-cancel/lift atomair in één
product-locked tx (applyDeployTerminalUpdate); sha-guard via repo_contains_sha
(ancestor-check); spec rev 5: DATABASE_URL hoort bij de standaard worker-env.
Codex middel/laag: config-read binnen de lock (3 enqueue-paden), fake-lock
interleaving-tests beide volgordes, prompt-ownership expliciet (PR_REVIEW-
patroon), triggerPush bij enqueue-falen.
Opus hoog (nieuw): deploy-only worker-scoping — capabilities=['deploy'] claimt
uitsluitend DEPLOY, nooit NULL-capability idea/plan-chat-jobs.
Sonnet/haiku: skipWorktreeCleanup alle terminale statussen, snapshot op beide
enqueue-paden, ACTIVE_JOB_STATUSES DRY, rate-limit-config, cost-analysis-map
niet type-gedwongen, dependency-matrix, knop-gate vóór fase 4.4, rollback-
notities, psql-instructies E2E-5.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Volledige constraint-body inline (geen CHECK-placeholder meer); snapshot-
toevoeging teruggedraaid conform fase-5-beslissing (PR #91: minimale enqueue-
rijen, claim-time DB-leading resolutie) met expliciete rationale; stale
spec-tabelrij scrum4me-docker (DATABASE_URL) gecorrigeerd; rev-verwijzingen
naar spec rev 5 bijgewerkt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bump naar scrum4me-shared a84cc3a (PR #24-merge). Generated schema krijgt
DEPLOY + Product.auto_deploy/deploy_flow + ClaudeJob.resolved_at, plus de
idea-chat-elementen (IDEA_CHAT, IdeaChatMessage, chat_cutoff) die met de
gedeelde main meekomen. Typecheck bewust rood op de 2 KIND_LABELS-maps
(IDEA_CHAT+DEPLOY) tot taak 2.5 — voorspeld in het plan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kwaliteitsreview T-1302: __tests__/db/ is de gevestigde plek voor
migratie-SQL-contracttests (claude-jobs-kind-constraint.test.ts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Handmatige DEPLOY-enqueue ("Deploy nu", spec §5): session/demo/zod-guards,
per-user rate-limit (nieuwe 'deploy-now' CONFIGS-entry), en één transactie
die eerst een pg_advisory_xact_lock op (deploy, productId) neemt vóórdat
deploy_flow gelezen en de active-job-guard (DEPLOY, ACTIVE_JOB_STATUSES)
gecheckt wordt (spec §6, acceptatiecriterium — config-read binnen de lock).
Bewust geen orchestration_key/requested_*-snapshot; de sha-guard dekt
handmatige dubbelen (fase-5-lijn). Na de tx: pg_notify claude_job_enqueued
+ revalidatePath (settings + /jobs).

4 tests (TDD): happy-path met mock-order-assert
['lock','findProduct','findJob','create'], active-job-guard-weigering,
geen-deploy_flow-weigering (lock vóór de weigering), demo-weigering.
De inferred union uit de $transaction-callback discrimineerde niet schoon
op `'error' in outcome` (TS2322 op regel 58). Nu een expliciet
DeployTxOutcome-type als generic op prisma.$transaction; de overbodige
`as const`-annotaties zijn weg. In de test kregen mockFindFirstProduct/
mockFindFirstJob expliciete return-unions zodat de per-test
mockImplementationOnce-varianten (deploy_flow: null / actieve job) op het
type passen (TS2345 op regels 55/62 — zelfde review-gate, zelfde bestand-
scope). Type-only, geen gedragswijziging; tsc-grep op deploy is leeg
(alleen de 2 bekende KIND_LABELS-fouten in components/jobs/* resten, taak 2.5).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lock-enforced idempotentie i.p.v. best-effort: tweede gelijktijdige
admin-klik is een no-op, geen overwrite — zelfde patroon als
applyDeployTerminalUpdate (kwaliteitsreview T-1308).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Task 2.5: bouwt de deploy-UI bovenop de al bestaande actions (T-1305/1306/1308).
- auto-deploy-toggle, deploy-flow-input, deploy-now-button + settings-pagina
  (tab Agent & PR, ná PR-strategie-blok); Deploy nu disabled zonder deploy_flow
  (uitrol-gate, worker landt pas in fase 4).
- KIND_LABELS in job-card.tsx, jobs-column.tsx en cost-analysis.tsx krijgen
  DEPLOY + een provisorische IDEA_CHAT-entry (definitief label volgt uit de
  idea-chat-web-PR); jobs-column KIND_OPTIONS krijgt DEPLOY (niet IDEA_CHAT —
  geen filter-pill voor andermans stroom); cost-analysis hertyped naar
  Record<ClaudeJobKind, string> zodat de map voortaan wél afgedwongen wordt.
- Admin-jobstabel: knop "Markeer afgehandeld" op FAILED DEPLOY-rijen zonder
  resolved_at, via de al bestaande markDeployResolvedAction; resolved_at
  toegevoegd aan de admin-jobs-query en de Job-prop.

npm run verify: groen (0 lint errors / 4 pre-existing warnings, tsc clean,
191 test files / 1550 tests passed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs(spec): §5 REF-matrix-rij gelijkgetrokken met plan v3 (DEPLOY zonder refs, T-1320-review)
Some checks failed
CI / Lint, Typecheck, Test & Build (pull_request) Has been cancelled
CI / Detect deploy-relevant changes (pull_request) Has been cancelled
CI / Deploy Preview (PR) (pull_request) Has been cancelled
CI / Deploy Production (main) (pull_request) Has been cancelled
CI / Deploy Manual (workflow_dispatch) (pull_request) Has been cancelled
e478c48b7b
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
merge: origin/main (idea-chat web + M18) — labels definitief, seed 11 kinds, submodule 8df71d2
All checks were successful
CI / Lint, Typecheck, Test & Build (pull_request) Successful in 3m56s
CI / Deploy Manual (workflow_dispatch) (pull_request) Has been skipped
CI / Detect deploy-relevant changes (pull_request) Has been skipped
CI / Deploy Preview (PR) (pull_request) Has been skipped
CI / Deploy Production (main) (pull_request) Has been skipped
7c681f115f
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/Scrum4Me!98
No description provided.