main · last commit
13 days ago ·
7g0stsfu
ah-0ge.1 Agent-created tasks via .task/tasks.json file channel
Past Stand
bd reopen ah-0ge.1
| Created by | Eugene Blikh |
| Owner | bigbes@gmail.com |
| Created | 2026-07-17T14:38:02Z |
| Started | 2026-07-17T15:58:45Z |
| Updated | 2026-07-17T16:16:19Z |
| Closed | 2026-07-17T16:16:19Z |
First slice of the delegation loop: agent X declares the child roles it needs, X exits, the reconciler creates those tasks. Deliberately NOT the full ah-0ge tools API — no bearer tokens, no ahub tool CLI, no HTTP endpoints. X writes .task/tasks.json on the way out; the reconciler reads it at run end, the same way .task/question.json is already reserved (SPEC:392) in a directory internal/runner/taskfiles.go already owns. A file channel can only be read at run END, which would cripple an interactive ask-user loop but is EXACTLY the semantics wanted here ('agent X stops'). That constraint is what makes this slice small. Server-side policy from the ah-0ge epic still applies: gen<=2, per-session caps, dedup, project allowlist. A child that spawns children that spawn children fills the board.
Child tasks get a role (must exist in cfg.Roles) + a task body. Open: do children land in Ready directly (agent->agent, per the proposal) or in Triage for a human to release (per SPEC §14.4 as written)? Triage is the safer default and can be relaxed later via config.
A run whose agent writes .task/tasks.json with two child role tasks results in two new board tasks with those roles; a malformed or over-cap file bounces the parent rather than creating anything.
IMPLEMENTED 2026-07-17. Agent writes .task/tasks.json ({tasks:[{role,title,body}]}); a SUCCESSFUL run's finalize reads it and creates one board card per entry under its role (frontmatter 'role: X') in the configured target bucket.
Decisions made during implementation:
- Ready vs Triage: config knob agent_tasks.target_bucket, DEFAULT 'triage' (spec §14.4-aligned, safe: human vets agent-created work). Flip to 'ready' for the full auto agent→agent loop. Documented in config.example.yaml + SPEC §12.
- 'Bounce' semantics: malformed/over-cap/unknown-role/empty-title creates NOTHING (atomic) and posts a rejection comment on the parent; the parent's OWN work still finalizes to In Review. Chose comment-not-card-move because moving the parent to Triage collides with the state model (triage is a parked bucket, not a task State, and the parent has a persisted record). Stronger card-move bounce deferred.
- gen<=2 cap DEFERRED to ah-0ge.2: needs task lineage (parent link) which doesn't exist yet. Only the per-run COUNT cap (max_per_run, default 5) is enforced now.
- Mid-creation transport failure keeps already-created children (can't un-create) and stops; logged. finalize isn't retried post-InReview.
New surface: domain.RequestedTask; ports.Board.CreateTask + ports.NewTask; ports.Runner.RequestedTasks; runner.readTasksFile + PiZellij.RequestedTasks; vikunja.Client.CreateTask (PUT /projects/{id}/tasks then MoveToBucket); reconcile.spawnChildTasks/validateRequestedTasks/childDescription; config.AgentTasks. Tests: reconcile (spawn 2, unknown-role bounce, over-cap bounce, malformed bounce), runner (readTasksFile absent/valid/malformed), vikunja (CreateTask HTTP path), config (defaults + 2 validation failures). Full suite + e2e green under GOFLAGS=-mod=readonly.
ah-0ge.2
— Parent auto-Block/unblock join on child completion
blocks
| id | ah-0ge.1 |
| content_hash | fe7de8b8454eea7571194b1d573a0f6427b0f4c7b704400ef3ea627f37636484 |
| title | Agent-created tasks via .task/tasks.json file channel |
| description | First slice of the delegation loop: agent X declares the child roles it needs, X exits, the reconciler creates those tasks. Deliberately NOT the full ah-0ge tools API — no bearer tokens, no ahub tool CLI, no HTTP endpoints. X writes .task/tasks.json on the way out; the reconciler reads it at run end, the same way .task/question.json is already reserved (SPEC:392) in a directory internal/runner/taskfiles.go already owns. A file channel can only be read at run END, which would cripple an interactive ask-user loop but is EXACTLY the semantics wanted here ('agent X stops'). That constraint is what makes this slice small. Server-side policy from the ah-0ge epic still applies: gen<=2, per-session caps, dedup, project allowlist. A child that spawns children that spawn children fills the board. |
| design | Child tasks get a role (must exist in cfg.Roles) + a task body. Open: do children land in Ready directly (agent->agent, per the proposal) or in Triage for a human to release (per SPEC §14.4 as written)? Triage is the safer default and can be relaxed later via config. |
| acceptance_criteria | A run whose agent writes .task/tasks.json with two child role tasks results in two new board tasks with those roles; a malformed or over-cap file bounces the parent rather than creating anything. |
| notes | IMPLEMENTED 2026-07-17. Agent writes .task/tasks.json ({tasks:[{role,title,body}]}); a SUCCESSFUL run's finalize reads it and creates one board card per entry under its role (frontmatter 'role: X') in the configured target bucket. Decisions made during implementation: - Ready vs Triage: config knob agent_tasks.target_bucket, DEFAULT 'triage' (spec §14.4-aligned, safe: human vets agent-created work). Flip to 'ready' for the full auto agent→agent loop. Documented in config.example.yaml + SPEC §12. - 'Bounce' semantics: malformed/over-cap/unknown-role/empty-title creates NOTHING (atomic) and posts a rejection comment on the parent; the parent's OWN work still finalizes to In Review. Chose comment-not-card-move because moving the parent to Triage collides with the state model (triage is a parked bucket, not a task State, and the parent has a persisted record). Stronger card-move bounce deferred. - gen<=2 cap DEFERRED to ah-0ge.2: needs task lineage (parent link) which doesn't exist yet. Only the per-run COUNT cap (max_per_run, default 5) is enforced now. - Mid-creation transport failure keeps already-created children (can't un-create) and stops; logged. finalize isn't retried post-InReview. New surface: domain.RequestedTask; ports.Board.CreateTask + ports.NewTask; ports.Runner.RequestedTasks; runner.readTasksFile + PiZellij.RequestedTasks; vikunja.Client.CreateTask (PUT /projects/{id}/tasks then MoveToBucket); reconcile.spawnChildTasks/validateRequestedTasks/childDescription; config.AgentTasks. Tests: reconcile (spawn 2, unknown-role bounce, over-cap bounce, malformed bounce), runner (readTasksFile absent/valid/malformed), vikunja (CreateTask HTTP path), config (defaults + 2 validation failures). Full suite + e2e green under GOFLAGS=-mod=readonly. |
| status | closed |
| priority | 3 |
| issue_type | feature |
| assignee | Eugene Blikh |
| estimated_minutes | NULL |
| created_at | 2026-07-17T14:38:02Z |
| created_by | Eugene Blikh |
| owner | bigbes@gmail.com |
| updated_at | 2026-07-17T16:16:19Z |
| closed_at | 2026-07-17T16:16:19Z |
| 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 | Implemented and tested: agent-created child tasks via .task/tasks.json file channel. Acceptance met (two children created; malformed/over-cap bounces atomically). Config knob defaults to Triage; gen-cap deferred to ah-0ge.2. |
| 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-17T15:58:45Z |
| is_blocked | 0 |
| 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 | 6423d3fb-f348-5e36-9df3-0ff9c07ba03f |
| issue_id | ah-0ge.1 |
| 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 | db0446cc-58eb-5fa0-846e-7728bf9bb385 |
| issue_id | ah-0ge.1 |
| type | blocks |
| created_at | 2026-07-17T17:38:41Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | ah-9r4 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 019f7083-5130-7a31-9ba6-6edbe691d9f7 |
| issue_id | ah-0ge.1 |
| event_type | created |
| actor | Eugene Blikh |
| old_value | |
| new_value | |
| comment | NULL |
| created_at | 2026-07-17T17:38:02Z |
| id | 019f70cd-36bd-7e63-9b16-e8df7643b106 |
| issue_id | ah-0ge.1 |
| event_type | claimed |
| actor | Eugene Blikh |
| old_value | {"id":"ah-0ge.1","title":"Agent-created tasks via .task/tasks.json file channel","description":"First slice of the delegation loop: agent X declares the child roles it needs, X exits, the reconciler creates those tasks. Deliberately NOT the full ah-0ge tools API — no bearer tokens, no ahub tool CLI, no HTTP endpoints. X writes .task/tasks.json on the way out; the reconciler reads it at run end, the same way .task/question.json is already reserved (SPEC:392) in a directory internal/runner/taskfiles.go already owns.\nA file channel can only be read at run END, which would cripple an interactive ask-user loop but is EXACTLY the semantics wanted here ('agent X stops'). That constraint is what makes this slice small.\nServer-side policy from the ah-0ge epic still applies: gen\u003c=2, per-session caps, dedup, project allowlist. A child that spawns children that spawn children fills the board.","design":"Child tasks get a role (must exist in cfg.Roles) + a task body. Open: do children land in Ready directly (agent-\u003eagent, per the proposal) or in Triage for a human to release (per SPEC §14.4 as written)? Triage is the safer default and can be relaxed later via config.","acceptance_criteria":"A run whose agent writes .task/tasks.json with two child role tasks results in two new board tasks with those roles; a malformed or over-cap file bounces the parent rather than creating anything.","status":"open","priority":3,"issue_type":"feature","owner":"bigbes@gmail.com","created_at":"2026-07-17T14:38:02Z","created_by":"Eugene Blikh","updated_at":"2026-07-17T14:38:02Z"} |
| new_value | {"assignee":"Eugene Blikh","status":"in_progress"} |
| comment | NULL |
| created_at | 2026-07-17T18:58:44Z |
| id | 019f70dd-4b62-71e8-9068-8281280426bc |
| issue_id | ah-0ge.1 |
| event_type | updated |
| actor | Eugene Blikh |
| old_value | {"id":"ah-0ge.1","title":"Agent-created tasks via .task/tasks.json file channel","description":"First slice of the delegation loop: agent X declares the child roles it needs, X exits, the reconciler creates those tasks. Deliberately NOT the full ah-0ge tools API — no bearer tokens, no ahub tool CLI, no HTTP endpoints. X writes .task/tasks.json on the way out; the reconciler reads it at run end, the same way .task/question.json is already reserved (SPEC:392) in a directory internal/runner/taskfiles.go already owns.\nA file channel can only be read at run END, which would cripple an interactive ask-user loop but is EXACTLY the semantics wanted here ('agent X stops'). That constraint is what makes this slice small.\nServer-side policy from the ah-0ge epic still applies: gen\u003c=2, per-session caps, dedup, project allowlist. A child that spawns children that spawn children fills the board.","design":"Child tasks get a role (must exist in cfg.Roles) + a task body. Open: do children land in Ready directly (agent-\u003eagent, per the proposal) or in Triage for a human to release (per SPEC §14.4 as written)? Triage is the safer default and can be relaxed later via config.","acceptance_criteria":"A run whose agent writes .task/tasks.json with two child role tasks results in two new board tasks with those roles; a malformed or over-cap file bounces the parent rather than creating anything.","status":"in_progress","priority":3,"issue_type":"feature","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-07-17T14:38:02Z","created_by":"Eugene Blikh","updated_at":"2026-07-17T15:58:45Z","started_at":"2026-07-17T15:58:45Z"} |
| new_value | {"notes":"IMPLEMENTED 2026-07-17. Agent writes .task/tasks.json ({tasks:[{role,title,body}]}); a SUCCESSFUL run's finalize reads it and creates one board card per entry under its role (frontmatter 'role: X') in the configured target bucket.\n\nDecisions made during implementation:\n- Ready vs Triage: config knob agent_tasks.target_bucket, DEFAULT 'triage' (spec §14.4-aligned, safe: human vets agent-created work). Flip to 'ready' for the full auto agent→agent loop. Documented in config.example.yaml + SPEC §12.\n- 'Bounce' semantics: malformed/over-cap/unknown-role/empty-title creates NOTHING (atomic) and posts a rejection comment on the parent; the parent's OWN work still finalizes to In Review. Chose comment-not-card-move because moving the parent to Triage collides with the state model (triage is a parked bucket, not a task State, and the parent has a persisted record). Stronger card-move bounce deferred.\n- gen\u003c=2 cap DEFERRED to ah-0ge.2: needs task lineage (parent link) which doesn't exist yet. Only the per-run COUNT cap (max_per_run, default 5) is enforced now.\n- Mid-creation transport failure keeps already-created children (can't un-create) and stops; logged. finalize isn't retried post-InReview.\n\nNew surface: domain.RequestedTask; ports.Board.CreateTask + ports.NewTask; ports.Runner.RequestedTasks; runner.readTasksFile + PiZellij.RequestedTasks; vikunja.Client.CreateTask (PUT /projects/{id}/tasks then MoveToBucket); reconcile.spawnChildTasks/validateRequestedTasks/childDescription; config.AgentTasks. Tests: reconcile (spawn 2, unknown-role bounce, over-cap bounce, malformed bounce), runner (readTasksFile absent/valid/malformed), vikunja (CreateTask HTTP path), config (defaults + 2 validation failures). Full suite + e2e green under GOFLAGS=-mod=readonly."} |
| comment | NULL |
| created_at | 2026-07-17T19:16:18Z |
| id | 019f70dd-4db9-79d7-bbb7-438bcc944910 |
| issue_id | ah-0ge.1 |
| event_type | closed |
| actor | Eugene Blikh |
| old_value | |
| new_value | Implemented and tested: agent-created child tasks via .task/tasks.json file channel. Acceptance met (two children created; malformed/over-cap bounces atomically). Config knob defaults to Triage; gen-cap deferred to ah-0ge.2. |
| comment | NULL |
| created_at | 2026-07-17T19:16:19Z |
| id | 019f7cda-9637-78ca-b14d-4a055099aa62 |
| issue_id | ah-0ge.1 |
| 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-1e27-7d84-91e4-2e63346c82c7 |
| issue_id | ah-0ge.1 |
| 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