Concurrency guards: single-flight, semaphore and timeouts #61

Member

Maestro task: 8f533721-32c9-4f73-af9f-9a9f0e94abf8 (Feature 09 - AI Harness and Skills Framework, final task).

Done-condition

harness.Run accepts a scope key; concurrent runs with the same (skill, scope) share one in-flight execution and result; a global semaphore limits concurrent LLM calls to 2 (configurable) with context-aware waiting; each skill declares a timeout (default 60 s) enforced via context. Blocking-Fake tests prove: two same-scope calls produce one Generate call and identical results; different scopes run independently; a third concurrent call waits for a slot; a cancelled context releases its slot; timeout returns ErrTimeout. Go quality floor passes with -race.

Evidence

  • New internal/ai/harness/guard.go + guard_test.go; harness.go wires scope/semaphore/timeout; llm/fake.go gained blocking support.
  • gofmt/vet/go test -race/build pass; no new dependency (go.mod/go.sum unchanged).

Documented trade-offs: a scope must identify the input (joiners share the first result); shared output is handed to callers as-is; the semaphore limits each Generate call, not each run.

Maestro task: 8f533721-32c9-4f73-af9f-9a9f0e94abf8 (Feature 09 - AI Harness and Skills Framework, final task). ## Done-condition harness.Run accepts a scope key; concurrent runs with the same (skill, scope) share one in-flight execution and result; a global semaphore limits concurrent LLM calls to 2 (configurable) with context-aware waiting; each skill declares a timeout (default 60 s) enforced via context. Blocking-Fake tests prove: two same-scope calls produce one Generate call and identical results; different scopes run independently; a third concurrent call waits for a slot; a cancelled context releases its slot; timeout returns ErrTimeout. Go quality floor passes with -race. ## Evidence - New internal/ai/harness/guard.go + guard_test.go; harness.go wires scope/semaphore/timeout; llm/fake.go gained blocking support. - gofmt/vet/go test -race/build pass; no new dependency (go.mod/go.sum unchanged). Documented trade-offs: a scope must identify the input (joiners share the first result); shared output is handed to callers as-is; the semaphore limits each Generate call, not each run.
dev_agent added 1 commit 2026-10-05 10:01:10 -04:00
Add concurrency guards to harness.Run: single-flight, semaphore and timeouts
CI / ci (push) Successful in 1m34s
CI / ci (pull_request) Successful in 1m37s
d03068ace5
harness.Run now takes a scope key. Concurrent runs of one skill with one
scope share a single in-flight run and its result, errors included, so
only one Generate call is made; different scopes run independently. A
process-wide Guard (NewGuard, DefaultMaxCalls = 2) bounds concurrent LLM
calls with a context-aware semaphore. Each skill declares Timeout()
(DefaultTimeout = 60 s), enforced via context over the whole run; a run
past it fails with an error matching llm.ErrTimeout. A caller whose
context ends gets the context error; the shared run is cancelled, and
its slot freed, once no caller waits for it.

llm.Fake results can now block (Release) and signal entry (Started), so
tests hold calls in flight.

Maestro task: 8f533721-32c9-4f73-af9f-9a9f0e94abf8

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent requested changes 2026-10-05 10:09:41 -04:00
Dismissed
review_agent left a comment
Member

Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.

Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.
overseer added 1 commit 2026-10-05 10:15:08 -04:00
Report work that ends after the skill timeout as llm.ErrTimeout
CI / ci (push) Successful in 1m36s
CI / ci (pull_request) Successful in 1m33s
a6f750ea04
runOnce only mapped an expired context to llm.ErrTimeout when execute
returned an error, so a PostProcess that succeeded after the deadline was
reported as a success. Check the deadline after execution (context cause
or the clock, since the timer may not have fired yet) and fail such a run
with llm.ErrTimeout and a provider_error ai_runs row.

Adds a TestRunTimeout case with a skill whose PostProcess succeeds only
after its timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent requested changes 2026-10-05 10:18:29 -04:00
Dismissed
review_agent left a comment
Member

Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.

Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.
overseer added 1 commit 2026-10-05 10:24:25 -04:00
Fail a run whose ai_runs row is saved after the skill timeout
CI / ci (pull_request) Successful in 1m36s
CI / ci (push) Successful in 1m35s
7b81d48150
runOnce checked the deadline only before saving the row. The save can
wait for the store's single writer, so a run whose work ended in time
could return success after its timeout. Check the deadline again once
the row is saved and return llm.ErrTimeout when it has passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent left a comment
Member

Independent Codex gpt-6-sol review: BLOCKED for this exact commit.

Independent Codex gpt-6-sol review: BLOCKED for this exact commit.
overseer added 1 commit 2026-10-05 10:33:51 -04:00
Assert the late-save row is ok to prove the post-save timeout path
CI / ci (push) Successful in 1m33s
CI / ci (pull_request) Successful in 1m34s
603db32a41
The row-saved-late test only checked that one ai_runs row existed, so it
would also pass if the work itself had timed out before the save. It now
requires the row to be ok with no error, which holds only when the work
ended in time and the save alone ran past the deadline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent left a comment
Member

Independent Codex gpt-6-sol review: APPROVED for this exact commit.

Independent Codex gpt-6-sol review: APPROVED for this exact commit.
approver_agent merged commit a8b0c7894f into feature/d4a8ed83-9cee-459c-aca3-efd1ccf17ecd-ai-harness 2026-10-05 10:42:19 -04:00
Sign in to join this conversation.
No Reviewers
No labels
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Maniacs_Mansion/MealQuest#61