Skip to content

feat(state): C1 — saga_phase v2 migration + resumability CRUD - #1

Merged
gustavobertoi merged 1 commit into
mainfrom
nightly/C1
Jun 29, 2026
Merged

feat(state): C1 — saga_phase v2 migration + resumability CRUD#1
gustavobertoi merged 1 commit into
mainfrom
nightly/C1

Conversation

@gustavobertoi

Copy link
Copy Markdown
Contributor

First chunk of the nightly M2→M7 build (see PROGRESS.md).

Adds the up-saga resumability foundation (gates the orchestrator C5):

  • state schema v2: saga_phase table keyed by (ctx, workspace, scope, phase) — status/fingerprint/timestamps/error; forward-only + backup-before-migrate.
  • CRUD: StartPhase/SatisfyPhase/FailPhase/GetPhase/PhaseSatisfied (fingerprint skip check)/PhasesFor/ClearPhase. Scoped by Docker context, under the flock.

Gate: make ci (fmt+vet+build+test-race) green; migration v1→v2 + phase lifecycle + fingerprint re-arm tested.

Human steps: none.

🤖 Generated with Claude Code

…8/09)

Adds the up-saga resumability foundation that gates the whole orchestrator (C5):
- state schema v2: the `saga_phase` table keyed by (ctx, workspace, scope, phase)
  with status/fingerprint/timestamps/error; forward-only, backup-before-migrate.
- CRUD: StartPhase (upsert, clears prior state), SatisfyPhase, FailPhase, GetPhase,
  PhaseSatisfied (the fingerprint-matched skip check a re-run uses), PhasesFor,
  ClearPhase (compensation). All scoped by Docker context, intended under the flock.

Race-clean; migration v1->v2 + phase lifecycle + fingerprint re-arm tested.
First chunk of the nightly M2->M7 build (see PROGRESS.md).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gustavobertoi
gustavobertoi merged commit 9900b87 into main Jun 29, 2026
9 checks passed
gustavobertoi added a commit that referenced this pull request Jun 29, 2026
…spec 11) (#5)

Run declarative lifecycle hooks at saga phase boundaries:

- internal/state hook_run CRUD: HookSatisfied (lock-free read), RecordHookRun
  (idempotent; success-only, under the flock), DeleteHookRuns (--force-hooks
  re-arm). The cardinal rule — a row reflects only success — makes hooks
  resumable for free.
- internal/hooks: Execer (host via os/exec from the documented base dir; exec
  via `docker compose exec -T -w -e NAME=VALUE`, the only transport that takes
  per-run env values, DECISIONS D10) + OSExecer production impl. Runner applies
  per-hook timeout, retries (fixed backoff), and onFailure (abort/warn/continue).
  RunPhase orders a phase's hooks, skips ledger-satisfied idempotent/once hooks,
  and records success INSIDE the flock — the hook BODY runs OUTSIDE it so a long
  hook never serializes other invocations (spec 08 #1 rule). run:exec without a
  service is rejected (the transport rule config can't express).

Thin runner: ${ref}/${env}/${self}/secret:// interpolation happens upstream in
the saga and arrives via PhaseOpts.ExtraEnv (secrets last); the package never
imports internal/state (Ledger/Locker interfaces) or resolves secrets. Full
workspace-scope ordering is X3.

Unit tests (fake Execer + fake Ledger): host/exec routing, retries→success,
retries exhausted, timeout, abort/warn/continue, idempotent skip, record-on-
success-not-failure under the lock, env ordering. A hermetic OSExecer host test
(real os/exec) + a `//go:build integration` test exec'ing into a real busybox
compose stack with inline -e env injection.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gustavobertoi
gustavobertoi deleted the nightly/C1 branch August 24, 2026 01:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant