main · last commit
13 days ago ·
7g0stsfu
ah-0ge.2 Parent auto-Block/unblock join on child completion
Past Stand
bd reopen ah-0ge.2
| Created by | Eugene Blikh |
| Owner | bigbes@gmail.com |
| Created | 2026-07-17T14:38:03Z |
| Started | 2026-07-17T17:45:37Z |
| Updated | 2026-07-17T19:05:05Z |
| Closed | 2026-07-17T19:05:05Z |
The join half of the delegation loop, per SPEC §14.4 'parent auto-Block/unblock'. When X spawns children it parks in the Blocked bucket — which already exists as a parked bucket that never claims and never kills (SPEC:174) — and returns to Ready when all children reach a terminal state. Needs a parent link (tasks.parent_id in internal/store/schema.sql, or Vikunja task relations) plus somewhere to hold each child's result for the resume payload. UNSPECIFIED IN THE SPEC AND NEEDS A DECISION: partial failure. Y done, Z failed — does X resume with the failure reported, bounce to Failed, or go to Triage? §14 says auto-unblock but not what unblock means when a child died.
X with children Y,Z sits in Blocked while either runs and returns to Ready only once both are terminal; the partial-failure path is decided and covered by a transitions test.
COMPLETED 2026-07-17 together with ah-0ge.3 (they were inseparable — see prior note). The full block→wait→resume join is implemented and tested. STATE MODEL: 'blocked' promoted to a real domain.State (7 states now). domain.States/Valid/CanClaim/CanonicalBuckets updated; BucketBlocked const removed (blocked is a state, not a parked bucket); triage/question remain parked. reconcile iterate() routes the blocked bucket to a new handleBlocked. BEHAVIOR: a successful run that validly delegates now PARKS the parent in Blocked (delegateAndBlock) instead of In Review; children are created in target_bucket (triage=human-gated, ready=full-auto). handleBlocked resumes the parent (new attempt, resumeParent) once EVERY child reaches a terminal bucket (in_review/failed/done/cancelled; a vanished child counts terminal to avoid deadlock). Resume re-runs the role prompt + an appended 'Delegated work completed' section reporting each child's outcome and instructing 'do not re-delegate'. Child-done threshold = In Review (decision). Partial failure = resume-and-report; agent may retry (decision), bounded by MaxPerRun as a per-parent LIFETIME cap (existing ChildIDsOf count + requested) so retries can't loop forever. Depth bounded by MaxGeneration. Tests: domain (7 states); reconcile (spawn→blocks, resume-when-children-finish incl. failed child in prompt, waits-while-pending, + updated ah-0ge.1 spawn/reject tests); store migration/lineage. Full unit suite + e2e green under -mod=readonly. SPEC §9-pseudocode, state model, and §12 updated. NOTE/deviation: resume is a fresh attempt in the parent's existing worktree (which holds its committed work) + resume prompt, NOT a literal 'pi --session' continuation — pi session-file mechanics weren't verifiable here, and the worktree+prompt path is robust and correctness-equivalent for avoiding re-delegation. True --session continuation is a possible future optimization (see ah-0ge.3).
ah-0ge.3
— Resume parent via pi --session with child results as a new attempt
blocks
| id | ah-0ge.2 |
| content_hash | cc37ff5a5860feb86cb3556e7841450c187af1c9a8c3899f32e4f991134e9e1b |
| title | Parent auto-Block/unblock join on child completion |
| description | The join half of the delegation loop, per SPEC §14.4 'parent auto-Block/unblock'. When X spawns children it parks in the Blocked bucket — which already exists as a parked bucket that never claims and never kills (SPEC:174) — and returns to Ready when all children reach a terminal state. Needs a parent link (tasks.parent_id in internal/store/schema.sql, or Vikunja task relations) plus somewhere to hold each child's result for the resume payload. UNSPECIFIED IN THE SPEC AND NEEDS A DECISION: partial failure. Y done, Z failed — does X resume with the failure reported, bounce to Failed, or go to Triage? §14 says auto-unblock but not what unblock means when a child died. |
| design | |
| acceptance_criteria | X with children Y,Z sits in Blocked while either runs and returns to Ready only once both are terminal; the partial-failure path is decided and covered by a transitions test. |
| notes | COMPLETED 2026-07-17 together with ah-0ge.3 (they were inseparable — see prior note). The full block→wait→resume join is implemented and tested. STATE MODEL: 'blocked' promoted to a real domain.State (7 states now). domain.States/Valid/CanClaim/CanonicalBuckets updated; BucketBlocked const removed (blocked is a state, not a parked bucket); triage/question remain parked. reconcile iterate() routes the blocked bucket to a new handleBlocked. BEHAVIOR: a successful run that validly delegates now PARKS the parent in Blocked (delegateAndBlock) instead of In Review; children are created in target_bucket (triage=human-gated, ready=full-auto). handleBlocked resumes the parent (new attempt, resumeParent) once EVERY child reaches a terminal bucket (in_review/failed/done/cancelled; a vanished child counts terminal to avoid deadlock). Resume re-runs the role prompt + an appended 'Delegated work completed' section reporting each child's outcome and instructing 'do not re-delegate'. Child-done threshold = In Review (decision). Partial failure = resume-and-report; agent may retry (decision), bounded by MaxPerRun as a per-parent LIFETIME cap (existing ChildIDsOf count + requested) so retries can't loop forever. Depth bounded by MaxGeneration. Tests: domain (7 states); reconcile (spawn→blocks, resume-when-children-finish incl. failed child in prompt, waits-while-pending, + updated ah-0ge.1 spawn/reject tests); store migration/lineage. Full unit suite + e2e green under -mod=readonly. SPEC §9-pseudocode, state model, and §12 updated. NOTE/deviation: resume is a fresh attempt in the parent's existing worktree (which holds its committed work) + resume prompt, NOT a literal 'pi --session' continuation — pi session-file mechanics weren't verifiable here, and the worktree+prompt path is robust and correctness-equivalent for avoiding re-delegation. True --session continuation is a possible future optimization (see ah-0ge.3). |
| status | closed |
| priority | 3 |
| issue_type | feature |
| assignee | Eugene Blikh |
| estimated_minutes | NULL |
| created_at | 2026-07-17T14:38:03Z |
| created_by | Eugene Blikh |
| owner | bigbes@gmail.com |
| updated_at | 2026-07-17T19:05:05Z |
| closed_at | 2026-07-17T19:05:05Z |
| closed_by_session | |
| external_ref | NULL |
| spec_id | |
| compaction_level | 0 |
| compacted_at | NULL |
| compacted_at_commit | NULL |
| original_size | NULL |
| sender | |
| ephemeral | 0 |
| wisp_type | |
| pinned | 0 |
| is_template | 0 |
| mol_type | |
| work_type | |
| source_system | |
| metadata | �{} |
| source_repo | |
| close_reason | Block→wait→resume join implemented and tested together: blocked promoted to a real state; delegating parents park in Blocked and resume as a new attempt (in-worktree + resume prompt) once all children reach a terminal bucket. Decisions honored (child-done=In Review; partial-failure=resume-and-report with lifetime-capped retry). Full suite + e2e green. |
| event_kind | |
| actor | |
| target | |
| payload | |
| await_type | |
| await_id | |
| timeout_ns | 0 |
| waiters | |
| hook_bead | |
| role_bead | |
| agent_state | |
| last_activity | NULL |
| role_type | |
| rig | |
| due_at | NULL |
| defer_until | NULL |
| no_history | 0 |
| started_at | 2026-07-17T17:45:37Z |
| is_blocked | 0 |
| id | 37350a43-d1cf-589c-ad21-f1a995e71e61 |
| issue_id | ah-0ge.3 |
| type | blocks |
| created_at | 2026-07-17T17:38:40Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | ah-0ge.2 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 5e2253b1-6d56-5425-9481-7de7669b5d9f |
| issue_id | ah-0ge.2 |
| type | blocks |
| created_at | 2026-07-17T17:38:39Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | ah-0ge.1 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 89451810-b9c9-5774-8dfa-d2150d295f85 |
| issue_id | ah-0ge.2 |
| type | parent-child |
| created_at | 2026-07-17T17:38:02Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | ah-0ge |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 019f7083-5495-7c7b-970f-1c7fe985f283 |
| issue_id | ah-0ge.2 |
| event_type | created |
| actor | Eugene Blikh |
| old_value | |
| new_value | |
| comment | NULL |
| created_at | 2026-07-17T17:38:02Z |
| id | 019f712f-0ce2-79eb-b2de-26915f09aef8 |
| issue_id | ah-0ge.2 |
| event_type | claimed |
| actor | Eugene Blikh |
| old_value | {"id":"ah-0ge.2","title":"Parent auto-Block/unblock join on child completion","description":"The join half of the delegation loop, per SPEC §14.4 'parent auto-Block/unblock'. When X spawns children it parks in the Blocked bucket — which already exists as a parked bucket that never claims and never kills (SPEC:174) — and returns to Ready when all children reach a terminal state. Needs a parent link (tasks.parent_id in internal/store/schema.sql, or Vikunja task relations) plus somewhere to hold each child's result for the resume payload.\nUNSPECIFIED IN THE SPEC AND NEEDS A DECISION: partial failure. Y done, Z failed — does X resume with the failure reported, bounce to Failed, or go to Triage? §14 says auto-unblock but not what unblock means when a child died.","acceptance_criteria":"X with children Y,Z sits in Blocked while either runs and returns to Ready only once both are terminal; the partial-failure path is decided and covered by a transitions test.","status":"open","priority":3,"issue_type":"feature","owner":"bigbes@gmail.com","created_at":"2026-07-17T14:38:03Z","created_by":"Eugene Blikh","updated_at":"2026-07-17T14:38:03Z"} |
| new_value | {"assignee":"Eugene Blikh","status":"in_progress"} |
| comment | NULL |
| created_at | 2026-07-17T20:45:36Z |
| id | 019f7138-1076-7d84-9b11-fdb4d8a0cf24 |
| issue_id | ah-0ge.2 |
| event_type | updated |
| actor | Eugene Blikh |
| old_value | {"id":"ah-0ge.2","title":"Parent auto-Block/unblock join on child completion","description":"The join half of the delegation loop, per SPEC §14.4 'parent auto-Block/unblock'. When X spawns children it parks in the Blocked bucket — which already exists as a parked bucket that never claims and never kills (SPEC:174) — and returns to Ready when all children reach a terminal state. Needs a parent link (tasks.parent_id in internal/store/schema.sql, or Vikunja task relations) plus somewhere to hold each child's result for the resume payload.\nUNSPECIFIED IN THE SPEC AND NEEDS A DECISION: partial failure. Y done, Z failed — does X resume with the failure reported, bounce to Failed, or go to Triage? §14 says auto-unblock but not what unblock means when a child died.","acceptance_criteria":"X with children Y,Z sits in Blocked while either runs and returns to Ready only once both are terminal; the partial-failure path is decided and covered by a transitions test.","status":"in_progress","priority":3,"issue_type":"feature","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-07-17T14:38:03Z","created_by":"Eugene Blikh","updated_at":"2026-07-17T17:45:37Z","started_at":"2026-07-17T17:45:37Z"} |
| new_value | {"notes":"PARTIAL 2026-07-17. Split delivered: the parent↔child LINEAGE + DEPTH CAP is done and tested; the behavioral block/wait/resume JOIN is deferred and coupled to ah-0ge.3 (see finding below).\n\nDELIVERED (green, GOFLAGS=-mod=readonly):\n- store schema v3: task_parents(child_id PK, parent_id, generation, created_at) + migration [2]-\u003e[3].\n- ports.Store + store: RecordChild, GenerationOf, ChildIDsOf (idempotent on child_id).\n- config.AgentTasks.MaxGeneration (default 2, must be positive).\n- reconcile.spawnChildTasks now enforces the depth cap (a task at generation \u003e= MaxGeneration cannot delegate; childGen = parentGen+1) and records each child's lineage on creation; 'spawned_tasks' event carries generation.\n- Tests: store lineage round-trip + idempotency; reconcile lineage-recorded + over-depth rejection; config default + negative-generation validation; migration tests updated to schemaVersion + task_parents presence.\n\nARCHITECTURAL FINDING (blocks the join; needs a decision):\nah-0ge.2 and ah-0ge.3 are INSEPARABLE. If a blocked parent 'unblocks' into a plain re-claim without its pi session context, it re-runs from scratch, re-spawns the same children, and blocks again — infinite re-delegation (bounded only by caps). So 'unblock' is only correct AS 'resume-with-context', which is ah-0ge.3. Also, a delegating parent must WAIT in a real state: 'blocked' is currently a parked BUCKET, not a task State, so the join requires promoting blocked to a normative State (domain.States/Valid/CanClaim/transitions + the reconcile bucket switch) — SPEC §14.4 explicitly sanctions this ('blocked earns real semantics in Stage 4').\n\nDECISIONS captured for the join (from the user): child counts as done at IN REVIEW (not Done); partial failure -\u003e resume the parent reporting each child's outcome, parent may retry a couple of times (bounded by MaxGeneration + a future per-parent round cap).\n\nRECOMMENDATION: implement the join + resume as ONE unit (merge ah-0ge.2 remaining scope with ah-0ge.3), starting by promoting 'blocked' to a real State."} |
| comment | NULL |
| created_at | 2026-07-17T20:55:27Z |
| id | 019f7177-caa8-7d75-bf84-df653d118195 |
| issue_id | ah-0ge.2 |
| event_type | updated |
| actor | Eugene Blikh |
| old_value | {"id":"ah-0ge.2","title":"Parent auto-Block/unblock join on child completion","description":"The join half of the delegation loop, per SPEC §14.4 'parent auto-Block/unblock'. When X spawns children it parks in the Blocked bucket — which already exists as a parked bucket that never claims and never kills (SPEC:174) — and returns to Ready when all children reach a terminal state. Needs a parent link (tasks.parent_id in internal/store/schema.sql, or Vikunja task relations) plus somewhere to hold each child's result for the resume payload.\nUNSPECIFIED IN THE SPEC AND NEEDS A DECISION: partial failure. Y done, Z failed — does X resume with the failure reported, bounce to Failed, or go to Triage? §14 says auto-unblock but not what unblock means when a child died.","acceptance_criteria":"X with children Y,Z sits in Blocked while either runs and returns to Ready only once both are terminal; the partial-failure path is decided and covered by a transitions test.","notes":"PARTIAL 2026-07-17. Split delivered: the parent↔child LINEAGE + DEPTH CAP is done and tested; the behavioral block/wait/resume JOIN is deferred and coupled to ah-0ge.3 (see finding below).\n\nDELIVERED (green, GOFLAGS=-mod=readonly):\n- store schema v3: task_parents(child_id PK, parent_id, generation, created_at) + migration [2]-\u003e[3].\n- ports.Store + store: RecordChild, GenerationOf, ChildIDsOf (idempotent on child_id).\n- config.AgentTasks.MaxGeneration (default 2, must be positive).\n- reconcile.spawnChildTasks now enforces the depth cap (a task at generation \u003e= MaxGeneration cannot delegate; childGen = parentGen+1) and records each child's lineage on creation; 'spawned_tasks' event carries generation.\n- Tests: store lineage round-trip + idempotency; reconcile lineage-recorded + over-depth rejection; config default + negative-generation validation; migration tests updated to schemaVersion + task_parents presence.\n\nARCHITECTURAL FINDING (blocks the join; needs a decision):\nah-0ge.2 and ah-0ge.3 are INSEPARABLE. If a blocked parent 'unblocks' into a plain re-claim without its pi session context, it re-runs from scratch, re-spawns the same children, and blocks again — infinite re-delegation (bounded only by caps). So 'unblock' is only correct AS 'resume-with-context', which is ah-0ge.3. Also, a delegating parent must WAIT in a real state: 'blocked' is currently a parked BUCKET, not a task State, so the join requires promoting blocked to a normative State (domain.States/Valid/CanClaim/transitions + the reconcile bucket switch) — SPEC §14.4 explicitly sanctions this ('blocked earns real semantics in Stage 4').\n\nDECISIONS captured for the join (from the user): child counts as done at IN REVIEW (not Done); partial failure -\u003e resume the parent reporting each child's outcome, parent may retry a couple of times (bounded by MaxGeneration + a future per-parent round cap).\n\nRECOMMENDATION: implement the join + resume as ONE unit (merge ah-0ge.2 remaining scope with ah-0ge.3), starting by promoting 'blocked' to a real State.","status":"in_progress","priority":3,"issue_type":"feature","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-07-17T14:38:03Z","created_by":"Eugene Blikh","updated_at":"2026-07-17T17:55:27Z","started_at":"2026-07-17T17:45:37Z"} |
| new_value | {"notes":"COMPLETED 2026-07-17 together with ah-0ge.3 (they were inseparable — see prior note). The full block→wait→resume join is implemented and tested.\n\nSTATE MODEL: 'blocked' promoted to a real domain.State (7 states now). domain.States/Valid/CanClaim/CanonicalBuckets updated; BucketBlocked const removed (blocked is a state, not a parked bucket); triage/question remain parked. reconcile iterate() routes the blocked bucket to a new handleBlocked.\n\nBEHAVIOR: a successful run that validly delegates now PARKS the parent in Blocked (delegateAndBlock) instead of In Review; children are created in target_bucket (triage=human-gated, ready=full-auto). handleBlocked resumes the parent (new attempt, resumeParent) once EVERY child reaches a terminal bucket (in_review/failed/done/cancelled; a vanished child counts terminal to avoid deadlock). Resume re-runs the role prompt + an appended 'Delegated work completed' section reporting each child's outcome and instructing 'do not re-delegate'. Child-done threshold = In Review (decision). Partial failure = resume-and-report; agent may retry (decision), bounded by MaxPerRun as a per-parent LIFETIME cap (existing ChildIDsOf count + requested) so retries can't loop forever. Depth bounded by MaxGeneration.\n\nTests: domain (7 states); reconcile (spawn→blocks, resume-when-children-finish incl. failed child in prompt, waits-while-pending, + updated ah-0ge.1 spawn/reject tests); store migration/lineage. Full unit suite + e2e green under -mod=readonly. SPEC §9-pseudocode, state model, and §12 updated.\n\nNOTE/deviation: resume is a fresh attempt in the parent's existing worktree (which holds its committed work) + resume prompt, NOT a literal 'pi --session' continuation — pi session-file mechanics weren't verifiable here, and the worktree+prompt path is robust and correctness-equivalent for avoiding re-delegation. True --session continuation is a possible future optimization (see ah-0ge.3)."} |
| comment | NULL |
| created_at | 2026-07-17T22:05:03Z |
| id | 019f7177-ce38-7e4c-9efc-a9431043c0ae |
| issue_id | ah-0ge.2 |
| event_type | closed |
| actor | Eugene Blikh |
| old_value | |
| new_value | Block→wait→resume join implemented and tested together: blocked promoted to a real state; delegating parents park in Blocked and resume as a new attempt (in-worktree + resume prompt) once all children reach a terminal bucket. Decisions honored (child-done=In Review; partial-failure=resume-and-report with lifetime-capped retry). Full suite + e2e green. |
| comment | NULL |
| created_at | 2026-07-17T22:05:04Z |
| id | 019f7cda-9636-7e53-b88f-1e232d84293e |
| issue_id | ah-0ge.2 |
| event_type | label_added |
| actor | Eugene Blikh |
| old_value | NULL |
| new_value | NULL |
| comment | Added label: milestone:stage-4 |
| created_at | 2026-07-20T03:08:47Z |
| id | 019f7cdc-1f2a-7105-b15d-6b003d3566d9 |
| issue_id | ah-0ge.2 |
| event_type | label_removed |
| actor | Eugene Blikh |
| old_value | NULL |
| new_value | NULL |
| comment | Removed label: milestone:stage-4 |
| created_at | 2026-07-20T03:10:28Z |
No comments.
Close reason