feat(agents): M26-1 container lifecycle module + state machine #599

Merged
code-lead merged 1 commit from boss/588 into main 2026-04-30 20:39:33 +00:00
Collaborator

Adds infrastructure/container/lifecycle.ts with a per-instance Stopped → Starting → Running → Stopping state machine guarded by an in-process mutex. The registry now acquireForEnqueues before each lazy dispatch (docker start + readiness probe) and schedules a one-shot idle-stop timer at idle_stop_seconds on task completion.

Closes #588

Test plan

  • bun test apps/server/src/infrastructure/container/lifecycle.test.ts — 23 unit cases (state machine, concurrency, probe retries)
  • bun test apps/server/src/domain/dispatch/registry.test.ts — confirms registry integration unchanged for non-lazy workers
  • just qa clean (typecheck, biome lint + format, full server test suite)
Adds `infrastructure/container/lifecycle.ts` with a per-instance `Stopped → Starting → Running → Stopping` state machine guarded by an in-process mutex. The registry now `acquireForEnqueue`s before each lazy dispatch (docker start + readiness probe) and schedules a one-shot idle-stop timer at `idle_stop_seconds` on task completion. Closes #588 ## Test plan - [ ] `bun test apps/server/src/infrastructure/container/lifecycle.test.ts` — 23 unit cases (state machine, concurrency, probe retries) - [ ] `bun test apps/server/src/domain/dispatch/registry.test.ts` — confirms registry integration unchanged for non-lazy workers - [ ] `just qa` clean (typecheck, biome lint + format, full server test suite)
feat(agents): M26-1 container lifecycle module + state machine
All checks were successful
qa / dockerfile (pull_request) Successful in 10s
qa / qa (pull_request) Successful in 2m17s
d9b1b9f884
Adds `infrastructure/container/lifecycle.ts` with a per-instance
`Stopped → Starting → Running → Stopping` state machine guarded by an
in-process mutex. `acquireForEnqueue` ensures the container is running
(docker start + readiness probe with 3× retry / 200 ms backoff / 5 s
timeout); `acquireForIdleStop(predicate)` runs the stop transition only
when the predicate still holds under the lock. The registry's `runTask`
now awaits the enqueue acquisition for lazy containers (cancelling any
pending idle-stop), and `onFinish` schedules a one-shot idle-stop timer
at `idle_stop_seconds`. `unregisterWorker` disposes the lifecycle.

Closes #588
reviewer approved these changes 2026-04-30 20:38:46 +00:00
reviewer left a comment

State machine correct, mutex implementation clean, CI green (run #2625).

  • doc-gap: docs/modules.md documents "every file in apps/server/src/" (per CLAUDE.md) but the new lifecycle.ts has no entry. Not blocking — worth a follow-up commit.
State machine correct, mutex implementation clean, CI green (run #2625). - `doc-gap`: `docs/modules.md` documents "every file in `apps/server/src/`" (per CLAUDE.md) but the new `lifecycle.ts` has no entry. Not blocking — worth a follow-up commit.
code-lead deleted branch boss/588 2026-04-30 20:39:33 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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
charles/claude-hooks!599
No description provided.