Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .compozy/tasks/core-tasks/_meta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
created_at: 2026-04-14T03:01:13.414102Z
updated_at: 2026-04-14T13:36:33.887141Z
---

## Summary
- Total: 13
- Completed: 13
- Pending: 0
26 changes: 13 additions & 13 deletions .compozy/tasks/core-tasks/_tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

| # | Title | Status | Complexity | Dependencies |
|---|-------|--------|------------|--------------|
| 01 | Bootstrap the `internal/task` domain | pending | high | — |
| 02 | Persist core task and run records in `globaldb` | pending | high | task_01 |
| 03 | Persist task dependencies, audit trail, and idempotency | pending | high | task_01, task_02 |
| 04 | Implement `TaskManager` creation, mutation, and identity rules | pending | critical | task_01, task_02, task_03 |
| 05 | Implement `TaskRun` lifecycle and propagated cancellation | pending | critical | task_04 |
| 06 | Wire the session bridge, dedicated subtask sessions, and boot recovery | pending | critical | task_01, task_05 |
| 07 | Add task and run API contracts plus core handlers | pending | high | task_04, task_05 |
| 08 | Expose task and run routes through HTTP and UDS | pending | medium | task_07 |
| 09 | Add the `agh task` CLI command group | pending | medium | task_08 |
| 10 | Integrate automation with task-backed work items | pending | high | task_05, task_06 |
| 11 | Integrate extension host APIs with the task domain | pending | high | task_05, task_06 |
| 12 | Integrate network ingress and channel binding for tasks | pending | high | task_05, task_06 |
| 13 | Add observe projections, health queries, and task metrics | pending | high | task_05, task_06, task_12 |
| 01 | Bootstrap the `internal/task` domain | completed | high | — |
| 02 | Persist core task and run records in `globaldb` | completed | high | task_01 |
| 03 | Persist task dependencies, audit trail, and idempotency | completed | high | task_01, task_02 |
| 04 | Implement `TaskManager` creation, mutation, and identity rules | completed | critical | task_01, task_02, task_03 |
| 05 | Implement `TaskRun` lifecycle and propagated cancellation | completed | critical | task_04 |
| 06 | Wire the session bridge, dedicated subtask sessions, and boot recovery | completed | critical | task_01, task_05 |
| 07 | Add task and run API contracts plus core handlers | completed | high | task_04, task_05 |
| 08 | Expose task and run routes through HTTP and UDS | completed | medium | task_07 |
| 09 | Add the `agh task` CLI command group | completed | medium | task_08 |
| 10 | Integrate automation with task-backed work items | completed | high | task_05, task_06 |
| 11 | Integrate extension host APIs with the task domain | completed | high | task_05, task_06 |
| 12 | Integrate network ingress and channel binding for tasks | completed | high | task_05, task_06 |
| 13 | Add observe projections, health queries, and task metrics | completed | high | task_05, task_06, task_12 |
40 changes: 40 additions & 0 deletions .compozy/tasks/core-tasks/memory/MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Workflow Memory

Keep only durable, cross-task context here. Do not duplicate facts that are obvious from the repository, PRD documents, or git history.

## Current State
- `task_02` added durable `tasks` and `task_runs` persistence to `globaldb`; later task-manager/API work can rely on those store surfaces existing behind `internal/store/globaldb`.
- `task_03` added durable `task_dependencies`, `task_events`, and `task_run_idempotency` persistence to `globaldb`; later task-manager/network/observe work can rely on those store surfaces existing behind `internal/store/globaldb`.
- `task_05` added manager-owned `TaskRun` lifecycle methods (`enqueue`, `claim`, `start`, `attach`, `complete`, `fail`, `cancel`) plus tree cancellation and canonical task reconciliation in `internal/task`; later daemon/API/observe work should call these lifecycle methods instead of mutating run or task status directly.
- `task_06` now boots a daemon-owned `TaskManager` into `RuntimeDeps.Tasks` with an injected session bridge; executable task runs allocate dedicated system sessions by default, explicit attach remains validated in `internal/task`, and daemon boot reconciles persisted `claimed`/`starting`/`running` runs against live session state before servers start.
- `task_07` added shared task/run contracts in `internal/api/contract/tasks.go` plus transport-agnostic core handlers in `internal/api/core/tasks.go`; follow-on HTTP/UDS/CLI work should reuse those contracts/handlers instead of reimplementing task parsing, payload conversion, or task-domain error mapping.
- `task_08` exposed the full task/task-run route inventory through both `internal/api/httpapi` and `internal/api/udsapi`; both server constructors now fail fast without an injected `TaskService`, and daemon transport wiring passes `RuntimeDeps.Tasks` into both factories so follow-on CLI/web work should call those transport routes instead of bypassing the shared API surface.
- `task_09` added the daemon-backed `agh task` CLI surface in `internal/cli`, including task create/list/get/update/cancel, child/dependency commands, and run lifecycle commands; follow-on CLI work should extend `internal/cli/task.go` and the shared `DaemonClient` task/run transport methods instead of bypassing UDS routes.
- `task_10` added explicit automation/task integration without making tasks the universal automation wrapper: automation jobs may opt into `job.task`, direct task-backed jobs materialize/enqueue work through `internal/task`, and linked `automation_runs` persist as `delegated` activation records with `task_id` / `task_run_id`.
- `task_11` added extension Host API task surfaces for list/create/get/update/cancel and task-run lifecycle flows; extension task access is now explicitly capability-gated and routes through the daemon-owned `TaskManager` instead of direct store mutation.
- `task_12` added capability-gated network task ingress in `internal/network`: authenticated remote peers now create/update/cancel tasks and enqueue runs only through the daemon-owned `TaskManager`, task ingress writes are audited through the existing network audit sinks, and stale/mismatched channel bindings are rejected before mutation.
- `task_13` added read-side task observability in `internal/observe`: task summary, metrics, and health views now aggregate durable `tasks`, `task_runs`, `task_events`, and `network_audit_log` data plus live session liveness while keeping observe read-side only.

## Shared Decisions
- `globaldb` task writes preflight missing workspace and task references before insert/update paths so callers get `workspace.ErrWorkspaceNotFound` or `task.ErrTaskNotFound` instead of raw SQLite foreign-key failures.
- `task_runs.session_id` is persisted as nullable text without a sessions foreign key, matching the existing automation-run pattern and allowing run/session audit records to survive independently from live session registry state.
- `TaskEvent` persistence includes immutable origin metadata (`origin_kind`, `origin_ref`) alongside actor metadata so later lifecycle and observe work can audit both who acted and which ingress surface produced the write.
- Task-run idempotency lookup/save is scoped by `(idempotency_key, origin_kind, origin_ref)` instead of a bare key so multi-writer replay protection does not collide across ingress surfaces.
- `GlobalDB.CreateDependency` owns the `BEGIN IMMEDIATE` transaction for dependency edge creation, including duplicate detection, per-task edge-limit enforcement, and cycle rejection under the same SQLite write lock.
- Reverse dependency reconciliation is a first-class store surface via `DependencyStore.ListDependents`; manager code uses it to eagerly recalculate downstream task status after dependency, run, and cancellation changes.
- Task cancellation follows a cooperative-then-forced model through `SessionExecutor`: the manager immediately marks queued/open runs cancelled, requests stop for active runs, and escalates to forced stop after the configured grace period while preserving audit events.
- The daemon-owned task/session bridge reuses the existing session manager surface only from `internal/daemon`; workspace-scoped dedicated task sessions bind by workspace ID, global-scoped task sessions bind by the daemon home path, and boot recovery status mutations still flow through task-manager methods rather than direct store writes.
- Automation-linked agent task creation uses `created_by.kind=agent_session` with `origin.kind=automation` and `origin.ref=run:<automation run id>`; future automation, extension, or network ingress work should preserve that separation between actor identity and ingress origin instead of collapsing both to the same session identity.
- Extension-originated task writes derive `created_by` and immutable `origin` server-side from the trusted extension host context via `task.DeriveExtensionActorContext`; follow-on ingress work should preserve this server-owned identity/origin model and ignore payload-supplied actor metadata.
- Network-originated task writes derive `created_by` and immutable `origin` server-side from the authenticated peer/channel context via `task.DeriveNetworkPeerActorContext`; request IDs remain audit metadata and do not change task-run idempotency scope.
- Adding or changing extension Host API method schemas requires regenerating derived API artifacts with `make codegen` so `openapi/agh.json` and generated SDK contracts stay in sync.
- `internal/task.TaskManager` now supports an injected network-channel validator; daemon wiring passes `network.ValidateChannel`, stale task bindings may only be cleared/repaired through network ingress, and stale task/run channel snapshots are rejected before run start or session attach while recording `task.run_rejected`.
- The daemon-backed CLI integration harness in `internal/cli/cli_integration_test.go` now boots a real task manager and its bridge stub must satisfy `observe.BridgeSource`, including `DeliveryMetrics()`, so future end-to-end CLI task coverage should reuse that fixture shape instead of introducing parallel task-only harnesses.

## Shared Learnings
- Task health now exposes stuck claimed/starting/running runs, queue depth, duplicate-ingress totals, channel-mismatch totals, forced-stop totals, and recovery outcomes through `internal/observe`; transport-layer mapping for those fields remains separate follow-on work if external health APIs need them.

## Open Risks
- No known shared verification blocker after `make verify` passed on 2026-04-14 during `task_05`.

## Handoffs
44 changes: 44 additions & 0 deletions .compozy/tasks/core-tasks/memory/task_01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Task Memory: task_01.md

Keep only task-local execution context here. Do not duplicate facts that are obvious from the repository, task file, PRD documents, or git history.

## Objective Snapshot
- Bootstrap `internal/task` with canonical domain types, interfaces, limits, validation helpers, sentinel errors, and required tests.
- Completion gate: task-specific coverage plus `make verify`, then tracking updates and one local commit.
- Implementation, verification, tracking updates, and the local implementation commit are complete.

## Important Decisions
- Pre-change signal is that `internal/task/` does not exist yet.
- Package must keep the session seam task-owned and injected; no `internal/session` import is allowed.
- Ownership is modeled separately from creator identity via `OwnerKind`/`Ownership`, while `created_by` and `origin` stay immutable server-derived structs.
- The package exports a task-owned `Manager`, aggregate `Store`, and `SessionExecutor` seam so downstream `globaldb`, `daemon`, and API tasks can depend on stable contracts.

## Learnings
- ADR-005 locks `created_by` and `origin` as immutable, server-derived identity while ownership remains optional and mutable.
- ADR-006 requires a dedicated session bridge defined in `internal/task` for start/attach/request-stop/force-stop operations.
- Package-local test evidence: `go test ./internal/task`, `go test -cover ./internal/task` (82.2%), and `go test -tags integration ./internal/task` all pass.
- Repository gate evidence: `make verify` passed before tracking updates and again after commit hook formatting, validating commit `c1fb9f6`.

## Files / Surfaces
- `.compozy/tasks/core-tasks/_techspec.md`
- `.compozy/tasks/core-tasks/task_01.md`
- `.compozy/tasks/core-tasks/adrs/adr-001.md`
- `.compozy/tasks/core-tasks/adrs/adr-005.md`
- `.compozy/tasks/core-tasks/adrs/adr-006.md`
- `internal/session/interfaces.go`
- `internal/daemon/boundary.go`
- `internal/task/doc.go`
- `internal/task/errors.go`
- `internal/task/interfaces.go`
- `internal/task/limits.go`
- `internal/task/types.go`
- `internal/task/validate.go`
- `internal/task/validate_test.go`
- `internal/task/interfaces_integration_test.go`

## Errors / Corrections
- Initial package coverage was 53.7%, then 78.0%; additional branch-level validation tests raised it to 82.2% to satisfy the task gate.

## Ready for Next Run
- Task 01 is ready to hand off. Downstream tasks should implement the exported `task.Store` and `task.SessionExecutor` contracts rather than introducing parallel task-domain interfaces.
- Local implementation commit: `c1fb9f6` (`feat: bootstrap task domain`).
28 changes: 28 additions & 0 deletions .compozy/tasks/core-tasks/memory/task_02.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Task Memory: task_02.md

Keep only task-local execution context here. Do not duplicate facts that are obvious from the repository, task file, PRD documents, or git history.

## Objective Snapshot
- Persist `internal/task` `Task` and `TaskRun` records in `internal/store/globaldb` with schema, CRUD/list/query support, and tests that satisfy the task_02 coverage/integration requirements.

## Important Decisions
- Added task/run schema directly to `globaldb` bootstrap statements instead of a standalone migration because these are new tables with no legacy shape to transform.
- Implemented task/run persistence in a dedicated `internal/store/globaldb/global_db_task.go` file and kept task_03 surfaces (`dependencies`, `events`, idempotency store) out of scope.
- Reused `internal/task` validation and immutable-field helpers for canonical shape enforcement, then added store-level reference prechecks for missing workspace, parent task, and run task ids.
- `UpdateTaskRun` enforces single-assignment for `session_id` once a run is already bound.

## Learnings
- Package coverage for `internal/store/globaldb` cleared the 80% target after adding focused tests for not-found/reference-error branches and normalization defaults; broad happy-path tests alone were not enough.
- Stable ordering assertions for task list limits require distinct timestamps because the list query orders by `updated_at`, `created_at`, then `id`.

## Files / Surfaces
- `internal/store/globaldb/global_db.go`
- `internal/store/globaldb/global_db_task.go`
- `internal/store/globaldb/global_db_task_test.go`
- `internal/store/globaldb/global_db_task_integration_test.go`

## Errors / Corrections
- Initial `ListTasks(limit)` test assumed a deterministic order while all fixture timestamps were identical; fixed by assigning distinct timestamps to the filter fixtures before re-running tests.

## Ready for Next Run
- Task tracking still needs to be updated after verification/self-review, and the automatic local commit should stage only code files, not workflow memory or `.compozy` tracking files.
35 changes: 35 additions & 0 deletions .compozy/tasks/core-tasks/memory/task_03.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Task Memory: task_03.md

Keep only task-local execution context here. Do not duplicate facts that are obvious from the repository, task file, PRD documents, or git history.

## Objective Snapshot
- Persist bounded dependency edges, immutable task audit events, and origin-scoped task-run idempotency in `internal/store/globaldb`, with required unit/integration coverage and `make verify` passing.

## Important Decisions
- Widened `task.TaskEvent` to persist immutable origin metadata alongside actor metadata because the task spec requires audit records to preserve both actor and origin.
- Widened the task idempotency contract to use `(idempotency_key, origin)` scoping instead of a bare key and added a `TaskRunIdempotency` record type for storage.
- Implemented dependency insertion with a dedicated SQLite `BEGIN IMMEDIATE` connection transaction so duplicate detection, edge-limit validation, cycle checks, and the insert happen under one write lock.

## Learnings
- `internal/task` already had the graph/payload guardrails needed for this task, so the store layer could reuse those validations rather than introducing storage-only rules.
- Package coverage for `internal/store/globaldb` needed a few negative-path tests to clear the `>=80%` requirement; the final unit coverage is `80.0%`.

## Files / Surfaces
- `internal/task/errors.go`
- `internal/task/interfaces.go`
- `internal/task/interfaces_integration_test.go`
- `internal/task/types.go`
- `internal/task/validate.go`
- `internal/task/validate_test.go`
- `internal/store/globaldb/global_db.go`
- `internal/store/globaldb/global_db_task_aux.go`
- `internal/store/globaldb/global_db_task_graph_audit_test.go`
- `internal/store/globaldb/global_db_task_graph_audit_integration_test.go`
- `internal/store/globaldb/global_db_task_test.go`

## Errors / Corrections
- Initial package coverage landed at `79.5%`; added negative-path tests for dependency/audit/idempotency error branches to reach the required threshold.

## Ready for Next Run
- Verification is clean: `go test ./internal/task ./internal/store/globaldb -count=1`, `go test ./internal/store/globaldb -cover -count=1`, `go test -tags integration ./internal/store/globaldb -count=1`, and a post-commit `make verify` all passed after the final code changes.
- Local code commit created: `d93aa60` (`feat: persist task dependency audit idempotency store`).
Loading