~bigbes/agents-dev · parade

main · last commit 13 days ago · 7g0stsfu

← Back to the parade

ah-nyl.5 reconcile: the control loop Past Stand

status: closed P1 task
bd reopen ah-nyl.5
Created byEugene Blikh
Ownerbigbes@gmail.com
Created2026-07-12T23:35:17Z
Started2026-07-12T23:55:05Z
Updated2026-07-13T00:15:01Z
Closed2026-07-13T00:15:01Z
Description
Implement internal/reconcile per docs/SPEC.md SS10 (read SPEC fully; SS5, SS6, SS10, SS12 normative). The reconciler imports ONLY internal/domain, internal/ports, internal/config (+ stdlib). Sibling packages (store/vikunja/runner) may not compile yet — you must not import or build them.

Deliverables:
- New(deps Deps) *Reconciler where Deps{Store ports.Store; Board ports.Board; Runner ports.Runner; Notifier ports.Notifier; Cfg *config.Config; Log *slog.Logger; Now func() time.Time}.
- Run(ctx): loop — iterate every cfg.PollInterval, plus immediately when poked; Poke() (non-blocking, coalescing via 1-buffered channel); clean shutdown on ctx cancel.
- iterate(ctx) implementing SPEC SS10 verbatim: the bucket switch (ready claim/heal; in_progress adopt-or-fail/check; terminal buckets kill+align), vanish handling for store tasks missing from snapshot, claim ordering (persist BEFORE moving the card), check() with finalize on Completed, timeout kill (Now() - StartedAt > cfg.Timeout -> Kill + OutcomeTimeout), comments per the SS10 templates (claim comment with attach hint; success comment with DiffStat+Commits; failure comment with outcome + fenced tail of events — obtain the tail via Runner.Summary? No: events tail is runner-internal; include what RunStatus/Summary give you: outcome, exit code, diff stat if any, and reference to the worktree path + zellij attach hint. Keep comment builders as small pure funcs with tests).
- Prompt rendering per SPEC SS12: text/template over the role prompt file with {ID, Title, Description, Branch, RepoSlug}; render errors -> comment + move to failed (per SS12).
- Per-task action errors: log, append event where sensible, continue with other tasks; Snapshot error aborts the iteration (SS10).
- Every state-changing action appends a domain.Event via Store.AppendEvent.

Tests (the heart of this task — table-driven, in-memory fakes for all four ports, fake clock): claim happy path (verify order: CreateRun+UpsertTask precede MoveToBucket; comment posted), exit-0 finalize -> in_review + summary comment, exit!=0 -> failed + diagnostic comment, timeout -> Kill + failed(timeout), human drag to cancelled mid-run -> Kill + killed + aligned, crash-between-persist-and-move heal (rec in_progress + bucket ready -> just MoveToBucket), adopt (bucket in_progress, no rec, runner reports running), adopt-fail (no runtime -> failed + comment), vanish (in store, not on board -> kill + cancelled), poke triggers immediate iteration, ctx cancel stops Run. Fakes record calls for assertion; no real time.Sleep beyond trivial.

Constraints: work ONLY under internal/reconcile/. No go.mod changes, no .beads/. Build/test ONLY: go build ./internal/reconcile/... && go vet ./internal/reconcile/... && go test ./internal/reconcile/... . Commit 'reconcile: ...' staging only internal/reconcile. Do NOT push.

Depends on

  • ah-nyl.1 — foundation: go module, domain, ports, config blocks closed
  • ah-nyl — Stage 1 MVP: poll-driven happy path parent-child closed

Depended on by

  • ah-nyl.6 — wiring: httpapi + agenthubd + ahub CLIs blocks

Prerequisite chain — everything this waits on, transitively

  • ah-nyl.1 — foundation: go module, domain, ports, config blocks closed
  • ah-nyl — Stage 1 MVP: poll-driven happy path parent-child closed

Unblocks — everything waiting on this, transitively

  • ah-nyl.6 — wiring: httpapi + agenthubd + ahub CLIs blocks closed
  • ah-nyl.7 — e2e: harness with fake vikunja + stub pi blocks closed
  • ah-nyl.8 — refactor: adopt go.bigb.es/auxilia (scribe/culpa/steward) where it pays blocks closed

No comments.

Close reason

landed 2acf7c4, 11/11 scenarios + extras, race-clean, testify+culpa applied; ambiguity rulings recorded in agent report (vanish idempotency, adopt-or-fail refinement, crash-window adopt)
  • Eugene Blikh added under epic ah-nyl · 2026-07-13T02:35:16Z
  • Eugene Blikh created the issue · 2026-07-13T02:35:16Z
  • Eugene Blikh added dependency on ah-nyl.1 · 2026-07-13T02:35:17Z
  • Eugene Blikh ah-nyl.6 now depends on this · 2026-07-13T02:35:55Z
  • Eugene Blikh changed status to in_progress · 2026-07-13T02:55:04Z
  • Eugene Blikh closed the issue · 2026-07-13T03:15:01Z
    landed 2acf7c4, 11/11 scenarios + extras, race-clean, testify+culpa applied; ambiguity rulings recorded in agent report (vanish idempotency, adopt-or-fail refinement, crash-window adopt)
  • Eugene Blikh added label milestone:stage-1 · 2026-07-20T03:08:46Z
  • Eugene Blikh removed label milestone:stage-1 · 2026-07-20T03:10:22Z
Stored rows — what this pane was built from, as read
issues 1 row
id ah-nyl.5
content_hash a229e6751c3b6c7e11fca843ebea6db9830e910a9d3b730b6df4481690de2551
title reconcile: the control loop
description Implement internal/reconcile per docs/SPEC.md SS10 (read SPEC fully; SS5, SS6, SS10, SS12 normative). The reconciler imports ONLY internal/domain, internal/ports, internal/config (+ stdlib). Sibling packages (store/vikunja/runner) may not compile yet — you must not import or build them. Deliverables: - New(deps Deps) *Reconciler where Deps{Store ports.Store; Board ports.Board; Runner ports.Runner; Notifier ports.Notifier; Cfg *config.Config; Log *slog.Logger; Now func() time.Time}. - Run(ctx): loop — iterate every cfg.PollInterval, plus immediately when poked; Poke() (non-blocking, coalescing via 1-buffered channel); clean shutdown on ctx cancel. - iterate(ctx) implementing SPEC SS10 verbatim: the bucket switch (ready claim/heal; in_progress adopt-or-fail/check; terminal buckets kill+align), vanish handling for store tasks missing from snapshot, claim ordering (persist BEFORE moving the card), check() with finalize on Completed, timeout kill (Now() - StartedAt > cfg.Timeout -> Kill + OutcomeTimeout), comments per the SS10 templates (claim comment with attach hint; success comment with DiffStat+Commits; failure comment with outcome + fenced tail of events — obtain the tail via Runner.Summary? No: events tail is runner-internal; include what RunStatus/Summary give you: outcome, exit code, diff stat if any, and reference to the worktree path + zellij attach hint. Keep comment builders as small pure funcs with tests). - Prompt rendering per SPEC SS12: text/template over the role prompt file with {ID, Title, Description, Branch, RepoSlug}; render errors -> comment + move to failed (per SS12). - Per-task action errors: log, append event where sensible, continue with other tasks; Snapshot error aborts the iteration (SS10). - Every state-changing action appends a domain.Event via Store.AppendEvent. Tests (the heart of this task — table-driven, in-memory fakes for all four ports, fake clock): claim happy path (verify order: CreateRun+UpsertTask precede MoveToBucket; comment posted), exit-0 finalize -> in_review + summary comment, exit!=0 -> failed + diagnostic comment, timeout -> Kill + failed(timeout), human drag to cancelled mid-run -> Kill + killed + aligned, crash-between-persist-and-move heal (rec in_progress + bucket ready -> just MoveToBucket), adopt (bucket in_progress, no rec, runner reports running), adopt-fail (no runtime -> failed + comment), vanish (in store, not on board -> kill + cancelled), poke triggers immediate iteration, ctx cancel stops Run. Fakes record calls for assertion; no real time.Sleep beyond trivial. Constraints: work ONLY under internal/reconcile/. No go.mod changes, no .beads/. Build/test ONLY: go build ./internal/reconcile/... && go vet ./internal/reconcile/... && go test ./internal/reconcile/... . Commit 'reconcile: ...' staging only internal/reconcile. Do NOT push.
design
acceptance_criteria
notes
status closed
priority 1
issue_type task
assignee NULL
estimated_minutes NULL
created_at 2026-07-12T23:35:17Z
created_by Eugene Blikh
owner bigbes@gmail.com
updated_at 2026-07-13T00:15:01Z
closed_at 2026-07-13T00:15:01Z
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 landed 2acf7c4, 11/11 scenarios + extras, race-clean, testify+culpa applied; ambiguity rulings recorded in agent report (vanish idempotency, adopt-or-fail refinement, crash-window adopt)
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-12T23:55:05Z
is_blocked 0
dependencies 3 rows
id 888276da-d042-55a9-a0ff-1942e36d9674
issue_id ah-nyl.6
type blocks
created_at 2026-07-13T02:35:55Z
created_by Eugene Blikh
metadata �{}
thread_id
depends_on_issue_id ah-nyl.5
depends_on_wisp_id NULL
depends_on_external NULL
id 9d961c7a-5369-5b87-ab39-3aa80050e04e
issue_id ah-nyl.5
type blocks
created_at 2026-07-13T02:35:17Z
created_by Eugene Blikh
metadata �{}
thread_id
depends_on_issue_id ah-nyl.1
depends_on_wisp_id NULL
depends_on_external NULL
id eda881a0-619a-5f2c-9b24-0ee18bc0c053
issue_id ah-nyl.5
type parent-child
created_at 2026-07-13T02:35:16Z
created_by Eugene Blikh
metadata �{}
thread_id
depends_on_issue_id ah-nyl
depends_on_wisp_id NULL
depends_on_external NULL
events 5 rows
id 019f58af-62ab-7a9e-b2a4-6d11ed68d18b
issue_id ah-nyl.5
event_type created
actor Eugene Blikh
old_value
new_value
comment NULL
created_at 2026-07-13T02:35:16Z
id 019f58c1-82f6-7835-84f8-e7bdd4c477a5
issue_id ah-nyl.5
event_type status_changed
actor Eugene Blikh
old_value {"id":"ah-nyl.5","title":"reconcile: the control loop","description":"Implement internal/reconcile per docs/SPEC.md SS10 (read SPEC fully; SS5, SS6, SS10, SS12 normative). The reconciler imports ONLY internal/domain, internal/ports, internal/config (+ stdlib). Sibling packages (store/vikunja/runner) may not compile yet — you must not import or build them.\n\nDeliverables:\n- New(deps Deps) *Reconciler where Deps{Store ports.Store; Board ports.Board; Runner ports.Runner; Notifier ports.Notifier; Cfg *config.Config; Log *slog.Logger; Now func() time.Time}.\n- Run(ctx): loop — iterate every cfg.PollInterval, plus immediately when poked; Poke() (non-blocking, coalescing via 1-buffered channel); clean shutdown on ctx cancel.\n- iterate(ctx) implementing SPEC SS10 verbatim: the bucket switch (ready claim/heal; in_progress adopt-or-fail/check; terminal buckets kill+align), vanish handling for store tasks missing from snapshot, claim ordering (persist BEFORE moving the card), check() with finalize on Completed, timeout kill (Now() - StartedAt \u003e cfg.Timeout -\u003e Kill + OutcomeTimeout), comments per the SS10 templates (claim comment with attach hint; success comment with DiffStat+Commits; failure comment with outcome + fenced tail of events — obtain the tail via Runner.Summary? No: events tail is runner-internal; include what RunStatus/Summary give you: outcome, exit code, diff stat if any, and reference to the worktree path + zellij attach hint. Keep comment builders as small pure funcs with tests).\n- Prompt rendering per SPEC SS12: text/template over the role prompt file with {ID, Title, Description, Branch, RepoSlug}; render errors -\u003e comment + move to failed (per SS12).\n- Per-task action errors: log, append event where sensible, continue with other tasks; Snapshot error aborts the iteration (SS10).\n- Every state-changing action appends a domain.Event via Store.AppendEvent.\n\nTests (the heart of this task — table-driven, in-memory fakes for all four ports, fake clock): claim happy path (verify order: CreateRun+UpsertTask precede MoveToBucket; comment posted), exit-0 finalize -\u003e in_review + summary comment, exit!=0 -\u003e failed + diagnostic comment, timeout -\u003e Kill + failed(timeout), human drag to cancelled mid-run -\u003e Kill + killed + aligned, crash-between-persist-and-move heal (rec in_progress + bucket ready -\u003e just MoveToBucket), adopt (bucket in_progress, no rec, runner reports running), adopt-fail (no runtime -\u003e failed + comment), vanish (in store, not on board -\u003e kill + cancelled), poke triggers immediate iteration, ctx cancel stops Run. Fakes record calls for assertion; no real time.Sleep beyond trivial.\n\nConstraints: work ONLY under internal/reconcile/. No go.mod changes, no .beads/. Build/test ONLY: go build ./internal/reconcile/... \u0026\u0026 go vet ./internal/reconcile/... \u0026\u0026 go test ./internal/reconcile/... . Commit 'reconcile: ...' staging only internal/reconcile. Do NOT push.\n","status":"open","priority":1,"issue_type":"task","owner":"bigbes@gmail.com","created_at":"2026-07-12T23:35:17Z","created_by":"Eugene Blikh","updated_at":"2026-07-12T23:35:17Z"}
new_value {"status":"in_progress"}
comment NULL
created_at 2026-07-13T02:55:04Z
id 019f58d3-c470-7207-bbce-66b172244fa5
issue_id ah-nyl.5
event_type closed
actor Eugene Blikh
old_value
new_value landed 2acf7c4, 11/11 scenarios + extras, race-clean, testify+culpa applied; ambiguity rulings recorded in agent report (vanish idempotency, adopt-or-fail refinement, crash-window adopt)
comment NULL
created_at 2026-07-13T03:15:01Z
id 019f7cda-9087-7455-8ca8-e094110ab91d
issue_id ah-nyl.5
event_type label_added
actor Eugene Blikh
old_value NULL
new_value NULL
comment Added label: milestone:stage-1
created_at 2026-07-20T03:08:46Z
id 019f7cdc-05ca-7733-8cf3-5d9f1ae105f5
issue_id ah-nyl.5
event_type label_removed
actor Eugene Blikh
old_value NULL
new_value NULL
comment Removed label: milestone:stage-1
created_at 2026-07-20T03:10:22Z