Repository navigation
feat: dependency-driven auto-enqueue (opt-in) - #232
Conversation
When a task's blocking dependencies complete and it becomes ready, optionally enqueue its run automatically so a multi-step task DAG advances without a manual StartTask per node. Opt-in via a new per-task auto_enqueue_on_ready flag (default false), preserving the explicit-execution-boundary contract. - types: AutoEnqueueOnReady on Task/CreateTask (+ Reference/Summary round-trip) - store: persist the column; migration v41 add_task_auto_enqueue - CompleteRunLease: after the dependent reconcile, enqueue ready+opted-in dependents (skips paused; idempotency key keyed on the completed run id; store guards reject duplicate/blocked enqueues); best-effort, never rolls back the completion. Failed/expired blockers do not satisfy a blocks edge, so only completion triggers it. - tests: updated shipped-migration count + tasks column list Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Real-store test: an opted-in dependent gets exactly one auto-enqueued queued run when its blocker completes via the lease path (the autonomy worker flow); an opted-out dependent gets none.
|
@richardfogaca is attempting to deploy a commit to the Compozy Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughAdds AutoEnqueueOnReady across domain types, API contracts, CLI, storage schema/migrations, and task completion logic so dependents that opt in are automatically enqueued when their blockers complete. ChangesAuto-Enqueue on Ready Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Expose the per-task auto_enqueue_on_ready flag through the public surfaces so clients can set it at creation and read it back. Previously the flag existed in the domain/store but could only be set with a direct DB write, which made the dependency-driven auto-enqueue feature unusable from any client. - contract: AutoEnqueueOnReady on CreateTaskRequest + CreateTaskChildRequest (set), and on TaskPayload + TaskSummaryPayload (read back). - api handler: map the flag into the CreateTask spec for both task and child create; surface it in TaskPayloadFromTask and both summary builders. - extension host API: same read mapping (request type is an alias, so the set surface is inherited). - cli: --auto-enqueue-on-ready flag on `task create` and `task child create`. - test: the create integration test asserts the flag reaches the CreateTask spec. Most of the diff is gofmt re-aligning struct fields after the new column. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR introduces an opt-in AutoEnqueueOnReady task property that causes the runtime to automatically enqueue a dependent task's run once its blocking dependencies complete. The default (false) preserves the existing explicit-execution-boundary contract.
Changes:
- Adds
AutoEnqueueOnReadyfield across the task domain (Task/Summary/CreateTask), API contracts/payloads, CLI flags, and host extension API. - Adds storage support: a new
auto_enqueue_on_readycolumn ontaskswith a schema migration (v41) and updated SQL select/insert/update statements and scan fields. - Wires the auto-enqueue behavior into
CompleteRunLeasevia a best-effortautoEnqueueReadyDependentshelper, with an integration test exercising opted-in vs opted-out dependents.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/task/types.go | Adds AutoEnqueueOnReady to Task, Summary, and CreateTask. |
| internal/task/manager.go | Propagates AutoEnqueueOnReady through create/summary/record conversions. |
| internal/task/lease_manager.go | Implements autoEnqueueReadyDependents triggered after CompleteRunLease. |
| internal/task/manager_integration_test.go | Integration test covering opt-in/out behavior after blocker completion. |
| internal/store/globaldb/migrate_task_auto_enqueue.go | New migration adding the auto_enqueue_on_ready column. |
| internal/store/globaldb/global_db.go | Registers the new migration as version 41. |
| internal/store/globaldb/global_db_task.go | Updates SQL insert/update/select and scan fields for the new column. |
| internal/store/globaldb/global_db_task_aux.go | Adds new column to auxiliary select query. |
| internal/store/globaldb/global_db_task_test.go | Asserts new column on tasks table. |
| internal/store/globaldb/global_db_test.go | Adds migration identity entry. |
| internal/extension/host_api_tasks.go | Maps new field in extension host API payloads. |
| internal/api/contract/tasks.go | Adds field to API payloads/requests. |
| internal/api/core/tasks.go | Forwards field from request and into payloads. |
| internal/api/core/tasks_integration_test.go | Verifies field is forwarded by handler. |
| internal/api/core/scheduler.go | Adds field to scheduler payload conversion. |
| internal/cli/task.go | Adds --auto-enqueue-on-ready flags to create/child-create. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
internal/store/globaldb/global_db_task_test.go (1)
38-78:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winCover
AutoEnqueueOnReadyin a round-trip assertion too.This only proves the column exists. The current task helpers in this file still ignore
AutoEnqueueOnReady, so a broken insert/select/update/summary mapping would pass unnoticed. Please set the flag in an existing round-trip case and compare it inassertTaskEqualandassertTaskSummaryMatchesTask.As per coding guidelines "MUST test meaningful business logic, not trivial operations."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/store/globaldb/global_db_task_test.go` around lines 38 - 78, The tests currently only assert the presence of the tasks.column AutoEnqueueOnReady; add a round-trip check by setting AutoEnqueueOnReady on one of the existing test tasks created by the helpers, and verify it survives insert/select/update/summary cycles: update the test case that builds a Task to set AutoEnqueueOnReady=true (and toggle a case for false if desired), then include assertions for that field in assertTaskEqual and assertTaskSummaryMatchesTask so the selected Task and its TaskSummary are compared against the original AutoEnqueueOnReady value; make sure any helper functions that populate tasks (in this test file) include and return the flag so the round-trip covers persistence and mapping.internal/extension/host_api_tasks.go (1)
680-694:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPropagate
AutoEnqueueOnReadyin the extension create path.
createTaskSpecFromRequeststill dropsreq.AutoEnqueueOnReady, so extensions can read the flag back but cannot actually set it when creating a task.Suggested fix
spec := taskpkg.CreateTask{ ID: strings.TrimSpace(req.ID), Identifier: strings.TrimSpace(req.Identifier), Scope: scope, WorkspaceID: workspaceID, NetworkChannel: strings.TrimSpace(req.NetworkChannel), Title: strings.TrimSpace(req.Title), Description: strings.TrimSpace(req.Description), Priority: req.Priority.Normalize(), MaxAttempts: req.MaxAttempts, + AutoEnqueueOnReady: req.AutoEnqueueOnReady, Draft: req.Draft, ApprovalPolicy: req.ApprovalPolicy.Normalize(), Owner: cloneOwnership(req.Owner), Metadata: cloneRawMessage(req.Metadata), }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/extension/host_api_tasks.go` around lines 680 - 694, The create path is dropping the AutoEnqueueOnReady flag when building the task spec; update the struct literal in createTaskSpecFromRequest (the taskpkg.CreateTask assignment) to include AutoEnqueueOnReady: req.AutoEnqueueOnReady so the extension-provided flag is propagated into the created task (use the same field name as in the request, no extra transformation needed).
🧹 Nitpick comments (2)
internal/api/core/tasks_integration_test.go (1)
83-105: ⚡ Quick winAssert the create response body for
auto_enqueue_on_ready.This only proves the request reached the manager. If the handler or payload mapper drops
auto_enqueue_on_readyon the response, this test still passes.As per coding guidelines, "Assert both HTTP status code AND response body in HTTP tests — status-code-only assertions are insufficient."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/tasks_integration_test.go` around lines 83 - 105, The test currently only asserts HTTP status and the manager-captured create payload; additionally assert the HTTP response body includes auto_enqueue_on_ready=true to ensure the handler returns it. After performRequest (createResp), unmarshal createResp.Body (or parse JSON) and assert the returned object’s auto_enqueue_on_ready field is true (alongside existing checks on capturedCreate); reference the variables createResp and capturedCreate and the performRequest call to locate where to add the response-body assertion and fail the test if the value is missing or false.internal/task/manager_integration_test.go (1)
760-852: 🏗️ Heavy liftConsider adding test cases for idempotency and paused-task exclusion.
The PR summary mentions "idempotency keyed on the completed run id" and "ready + opted-in (and not-paused) dependents". The current test verifies the happy path but doesn't cover:
- Idempotency: Completing the same blocker run multiple times should only trigger one auto-enqueue per dependent
- Paused task exclusion: An opted-in dependent that is paused should NOT be auto-enqueued
These edge cases are important for verifying the complete behavior described in the PR objectives.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/task/manager_integration_test.go` around lines 760 - 852, Add two assertions to cover idempotency and paused-task exclusion: after completing the blocker run once (using manager.EnqueueRun -> ClaimNextRun -> CompleteRunLease) complete the same blocker run a second time and assert ListTaskRuns(optedIn.ID) still returns exactly one queued run (idempotency keyed on the completed run id); and create a third dependent with AutoEnqueueOnReady true then pause it (via the existing API—e.g., manager.PauseTask or updating the task's paused flag) before completing the blocker and assert ListTaskRuns(pausedDependent.ID) returns 0 (paused dependents are not auto-enqueued). Use the same functions from the test (manager.CreateTask, manager.AddDependency, manager.EnqueueRun, manager.ClaimNextRun, manager.CompleteRunLease, db.ListTaskRuns) to implement these checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/task/lease_manager.go`:
- Around line 244-253: The branch that auto-enqueues dependents (checking
dependent.AutoEnqueueOnReady and dependent.Status.Normalize() ==
TaskStatusReady) must first check whether the dependent already has an existing
non-terminal/open run and skip enqueuing if so; before calling m.EnqueueRun(…,
EnqueueRun{TaskID: dependentID, IdempotencyKey: key}, actor) query the run store
for dependentID for any run with a non-terminal status (or use an existing
helper like GetOpenRun/HasOpenRun), and continue instead of enqueueing when one
exists; preserve the pauseReader.IsTaskEffectivelyPaused check and keep the
idempotency key when enqueuing.
In `@internal/task/manager_integration_test.go`:
- Around line 760-770: Wrap the body of
TestTaskManagerAutoEnqueueOnReadyEnqueuesDependentOnCompletionIntegration in a
t.Run("Should ...") subtest: create a t.Run with a descriptive "Should ..."
name, move the existing test setup and assertions into its closure, and call
t.Parallel() inside that subtest (keep any outer setup before the t.Run only if
shared across multiple subtests). Update references to the test-local variables
(ctx, db, manager, actor) so they are declared inside the t.Run closure or
captured appropriately, ensuring the test function
TestTaskManagerAutoEnqueueOnReadyEnqueuesDependentOnCompletionIntegration simply
calls t.Run with the new subtest closure that contains the existing logic.
---
Outside diff comments:
In `@internal/extension/host_api_tasks.go`:
- Around line 680-694: The create path is dropping the AutoEnqueueOnReady flag
when building the task spec; update the struct literal in
createTaskSpecFromRequest (the taskpkg.CreateTask assignment) to include
AutoEnqueueOnReady: req.AutoEnqueueOnReady so the extension-provided flag is
propagated into the created task (use the same field name as in the request, no
extra transformation needed).
In `@internal/store/globaldb/global_db_task_test.go`:
- Around line 38-78: The tests currently only assert the presence of the
tasks.column AutoEnqueueOnReady; add a round-trip check by setting
AutoEnqueueOnReady on one of the existing test tasks created by the helpers, and
verify it survives insert/select/update/summary cycles: update the test case
that builds a Task to set AutoEnqueueOnReady=true (and toggle a case for false
if desired), then include assertions for that field in assertTaskEqual and
assertTaskSummaryMatchesTask so the selected Task and its TaskSummary are
compared against the original AutoEnqueueOnReady value; make sure any helper
functions that populate tasks (in this test file) include and return the flag so
the round-trip covers persistence and mapping.
---
Nitpick comments:
In `@internal/api/core/tasks_integration_test.go`:
- Around line 83-105: The test currently only asserts HTTP status and the
manager-captured create payload; additionally assert the HTTP response body
includes auto_enqueue_on_ready=true to ensure the handler returns it. After
performRequest (createResp), unmarshal createResp.Body (or parse JSON) and
assert the returned object’s auto_enqueue_on_ready field is true (alongside
existing checks on capturedCreate); reference the variables createResp and
capturedCreate and the performRequest call to locate where to add the
response-body assertion and fail the test if the value is missing or false.
In `@internal/task/manager_integration_test.go`:
- Around line 760-852: Add two assertions to cover idempotency and paused-task
exclusion: after completing the blocker run once (using manager.EnqueueRun ->
ClaimNextRun -> CompleteRunLease) complete the same blocker run a second time
and assert ListTaskRuns(optedIn.ID) still returns exactly one queued run
(idempotency keyed on the completed run id); and create a third dependent with
AutoEnqueueOnReady true then pause it (via the existing API—e.g.,
manager.PauseTask or updating the task's paused flag) before completing the
blocker and assert ListTaskRuns(pausedDependent.ID) returns 0 (paused dependents
are not auto-enqueued). Use the same functions from the test
(manager.CreateTask, manager.AddDependency, manager.EnqueueRun,
manager.ClaimNextRun, manager.CompleteRunLease, db.ListTaskRuns) to implement
these checks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 3c4bedf2-0235-49d4-8b39-e4f501163453
📒 Files selected for processing (16)
internal/api/contract/tasks.gointernal/api/core/scheduler.gointernal/api/core/tasks.gointernal/api/core/tasks_integration_test.gointernal/cli/task.gointernal/extension/host_api_tasks.gointernal/store/globaldb/global_db.gointernal/store/globaldb/global_db_task.gointernal/store/globaldb/global_db_task_aux.gointernal/store/globaldb/global_db_task_test.gointernal/store/globaldb/global_db_test.gointernal/store/globaldb/migrate_task_auto_enqueue.gointernal/task/lease_manager.gointernal/task/manager.gointernal/task/manager_integration_test.gointernal/task/types.go
- extension host API: propagate AutoEnqueueOnReady in the create path
(createTaskSpecFromRequest dropped it, so extensions could read but not set it)
- auto-enqueue hook: classify EnqueueRun rejections — the store's expected dedup
(open run -> ErrInvalidStatusTransition, replayed key -> ErrConflict) is a quiet
skip; Warn is reserved for real failures. The store stays the single owner of the
one-open-run invariant, so no redundant pre-check is added.
- tests: round-trip AutoEnqueueOnReady through the globaldb insert/select/summary
assertions; wrap the auto-enqueue integration test in a t.Run("Should ...") subtest.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
Addressed the review in b0af586:
Declined with reasoning in-thread: the |
pedronauck
left a comment
There was a problem hiding this comment.
Automated review — self + Codex (gpt-5.5, xhigh)
Self verdict: FIX_BEFORE_SHIP
Codex verdict: FIX_BEFORE_SHIP (3 blockers, 1 risk)
This PR is well-shaped: auto-enqueue reuses the canonical EnqueueRun/task_runs path (no parallel queue, no peer claimer), the dispatch is at the completion call site (CompleteRunLease → autoEnqueueReadyDependents) consistent with the autonomy "hooks dispatch at the call site that owns the state transition" rule, migration v41 is appended at the registry tail with a CHECK-constrained column defaulting to 0, and the opt-in defaults to no behavior change. Both reviewers nonetheless land on FIX_BEFORE_SHIP. The blockers below should be resolved before merge.
Blockers
-
[self+codex] Contract codegen co-ship missing.
internal/api/contract/tasks.goaddsauto_enqueue_on_readytoCreateTaskRequest(:639),CreateTaskChildRequest(:657),TaskPayload(:75) andTaskSummaryPayload(:37), but the changed-file set does NOT includeopenapi/agh.jsonorweb/src/generated/agh-openapi.d.ts, and a repo search finds the field in neither. This violates the contract co-ship rule andmake codegen-checkwill likely fail. Fix: runmake codegen, commit the regeneratedopenapi/agh.json+web/src/generated/agh-openapi.d.ts, update any affected MSW fixtures/stories, and verify withmake codegen-check+ the Bun typecheck/test gate. -
[codex] Docs + official AGH skill co-ship missing.
internal/cli/task.go:379and:1843add the user-visible--auto-enqueue-on-readyflag (create + child create), a new runtime behavior and agent-operable surface, but there is nopackages/sitedoc update and noskills/aghupdate. Agents/operators cannot discover the opt-in policy, the paused-dependent behavior, or the read-back field from the official surfaces. Fix: document the flag/field and the readiness/paused/open-run-dedup semantics in the relevantpackages/sitetask/CLI page and the bundledskills/aghguidance (regenerate the CLI reference from Cobra if it is generated), and include theAGH Impact Auditfour-row block in the PR body. -
[self+codex] Post-commit auto-enqueue is tied to the request context.
internal/task/lease_manager.go:210callsm.autoEnqueueReadyDependents(ctx, ...)with the inbound callerctxafterCompleteRunLeasehas already committed the completion, reconciled the cascade, and recorded the event; the helper then uses that samectxforListDependents(:225) andEnqueueRun(:253). Per the detached-execution invariant ("any work that outlives a request MUST detach viacontext.WithoutCancel"), if the UDS/request context is canceled or hits its deadline in this post-commit window, the completion stays committed but an opted-in dependent can remainreadywith no queued run and no durable retry — wedging hands-off DAG advancement until a manual start. Fix: deriveautoCtx := context.WithoutCancel(ctx)(with an explicit short timeout if needed) for the helper, or make the side effect retriable so an already-ready opted-in dependent is eventually queued after a transient cancel. Keep completion non-rollbacking.
Risks
-
[self+codex] No UPDATE path to toggle the flag.
UpdateTaskRequest(internal/api/contract/tasks.go, ~:665) carries noauto_enqueue_on_ready, and neither the domain patch type (internal/task/types.go~:478) nor the CLI update input (internal/cli/task.go~:113) can set it. The feature is create-only even though DAG policy often becomes clear after a tree is assembled — an agent-manageability gap against the "manageable by agents via CLI + REST/UDS" premise. Fix: thread an optional*bool AutoEnqueueOnReadythroughUpdateTaskRequest→task.Patch→taskPatchFromRequest/applyTaskPatch→ changed-field/event reporting → extension host mapping →agh task update, with tests proving true/false round-trip while omitted preserves the existing value. -
[self] Concurrency: dedup hinges on the open-run reservation, not the idempotency key. The idempotency key is
task.auto_enqueue.<dependentID>.<triggerRunID>(internal/task/lease_manager.go:252), keyed on the blocker run id — so two different blockers of the same dependent completing concurrently generate different keys, and duplicate-enqueue prevention relies entirely on the store's queued/open-run reservation rejecting a second open run. Codex confirms the reservation does reject the second run, but the integration test (internal/task/manager_integration_test.go:762) only exercises single-blocker completion. Suggested: add a concurrency test that completes two distinct blockers of one opted-in dependent in parallel and asserts exactly one queued run, to lock this invariant against regressions.
Codex peer review: dispatched once via compozy exec --ide codex --model gpt-5.5 --reasoning-effort xhigh (exit 0); findings validated against the round-1 implementation schema (frontmatter reviewer_runtime: codex, reviewer_model: gpt-5.5, verdict FIX_BEFORE_SHIP, 3 blockers / 1 risk / 0 nits). This comment merges the Codex findings with an independent self-review of all 16 changed files.
Round-2 review on compozy#232: - Co-ship contract codegen: regenerate openapi/agh.json + web/sdk generated types for auto_enqueue_on_ready (Create/CreateChild/Update requests, Task + TaskSummary payloads). - Detach post-commit auto-enqueue from the request context (context.WithoutCancel + bounded timeout) so a canceled UDS/HTTP request cannot leave a ready dependent unqueued. - Add the update path: AutoEnqueueOnReady *bool through UpdateTaskRequest -> task.Patch -> applyTaskPatch/changed-fields -> core+extension mappers -> agh task update --auto-enqueue-on-ready[=false]. - Document the flag/field and readiness/paused/open-run-dedup semantics in the task-runs docs, generated CLI reference, and the official agh skill. - Tests: concurrency (two distinct blockers -> exactly one queued run) and an update true/false/omitted round-trip. - Cluster Task/Summary bool fields under the 512-byte gocritic copy threshold; fix a pre-existing integration build break (fakeStore missing MarkTaskRunNeedsAttention/RecoverTaskRun).
|
Addressed in Blockers
Risks
Two pre-existing branch issues I had to fix to get |
TL;DR
Opt-in dependency-driven auto-enqueue: when a task's blocking dependencies complete and it becomes
ready, the runtime enqueues its run automatically — so a multi-step task DAG advances hands-off, without an operator issuingStartTaskper node. Includes the create/read surface to set and inspect the flag.Motivation
AGH already has the dependency graph (
blocksedges →TaskStatusReadyon completion viareconcileTaskCascade) and worker auto-dispatch (OwnerKindPool+taskRoleRuntimestarts a worker on run-enqueue). The missing link for a self-advancing DAG: reachingreadynever enqueues a run —EnqueueRunis only reached viaexecuteTaskBoundary(StartTask/PublishTask/ApproveTask). So a dependent that becomesreadyjust sits there until something explicitly enqueues it.This adds exactly that missing link, opt-in.
What this adds
auto_enqueue_on_readyflag (default false — preserves the "task creation records intent only; enqueue is an explicit boundary" invariant).v41 add_task_auto_enqueue.CompleteRunLease: after the dependent reconcile, enqueue ready + opted-in dependents.--auto-enqueue-on-readyontask create/task child create; the field onCreateTaskRequest/CreateTaskChildRequest(set) andTaskPayload/TaskSummaryPayload(read back); handler + payload builders + extension host API mapped.Design choices
CompleteRunLease(the autonomy worker completion path:task next→ … →task_run_complete). A failed/expired blocker does not satisfy ablocksedge, so only completion triggers it. (Open question: should the operatorCompleteRunpath also trigger it? See follow-ups.)readyalready excludes draft/approval-blocked/unresolved-deps/attempts-exhausted; the only added guard is skipping an effectively-paused dependent.Tests / validation
internal/task,internal/store/globaldb,internal/config,internal/coordinator,internal/daemon,internal/api/contract,internal/api/core,internal/extension,internal/cli. Updated the shipped-migration count and thetaskscolumn-list assertions for the new column/migration.internal/task, real globaldb store): completing a blocker via the lease path auto-enqueues exactly one queued run for an opted-in dependent and none for an opted-out dependent.internal/api/core): the create request's flag reaches theCreateTaskspec.A → B(Bblocks-depends on A,auto_enqueue_on_ready=true). A singletask start A, then no further action:taskRoleRuntimedispatched A's worker → it completed via the lease path → B auto-enqueued →taskRoleRuntimedispatched B's worker → both completed. B's run carried originagent_sessionand idempotency keytask.auto_enqueue.<B>.<A-run>, confirming the enqueue came from this path (vs A's operatortask.start.<A>).Follow-ups (not in this PR)
CompleteRunpath (not just the lease path).taskRoleRuntimedoes not currently bound worker fan-out bymax_active_sessions_per_workspace; auto-enqueuing many simultaneously-ready dependents could fan out unbounded worker sessions (bounded for sequential DAGs). Worth a follow-up.Note
The package's
-tags integrationbuild is pre-broken onmain(thefakeStoreininternal/task/interfaces_integration_test.gois missingMarkTaskRunNeedsAttentionandRecoverTaskRun, added to theStoreinterface in #230). That's unrelated to this change and left untouched here; the newinternal/taskintegration test passes once those two no-op stubs are added. Theinternal/api/coreintegration test in this PR builds and passes under the tag as-is.Summary by CodeRabbit
New Features
CLI / API
Database
Tests
AGH Impact Audit
agh__task_*catalog (internal/tools/builtin/testdata/native-tool-catalog.json) unchanged — the task create/update native tools do not surfaceauto_enqueue_on_ready; codegen produced no catalog diff. No tool IDs, toolsets, schema digests, or capability gates changed.internal/extension/host_api_tasks.go) propagateAutoEnqueueOnReady(parity with CLI/REST); post-commit auto-enqueue dispatch detached viacontext.WithoutCancel. No hook taxonomy, bundle, registry, MCP, orconfig.tomlchange.auto_enqueue_on_readyis a task-scoped field persisted in the existingtaskscolumn (migration v41); update flows through the existing workspace-scopedUpdateTask. No new global/workspace/session datum and no new cross-workspace list/read/cache/SSE path.skills/agh/references/tasks-and-orchestration.mddocuments the create/update flag, the readiness/paused/open-run-dedup semantics, and theagh task inspect -o jsonread-back field.