~bigbes/agents-dev · issues

dnu038ahj3vo0ovfittn1ocnjc7alqhp · 14 rows

idcontent_hashtitledescriptiondesignacceptance_criterianotesstatuspriorityissue_typeassigneeestimated_minutescreated_atcreated_byownerupdated_atclosed_atclosed_by_sessionexternal_refspec_idcompaction_levelcompacted_atcompacted_at_commitoriginal_sizesenderephemeralwisp_typepinnedis_templatemol_typework_typesource_systemmetadatasource_repoclose_reasonevent_kindactortargetpayloadawait_typeawait_idtimeout_nswaitershook_beadrole_beadagent_statelast_activityrole_typerigdue_atdefer_untilno_historystarted_atis_blocked
ah-0ge2c909b097105e578055b7ee05ca088aa4e70e7f293e15e7aae83f28ef1a5aedaStage 4: agent tools API, question loop, AgentsView linksPer SPEC SS14.4: per-task bearer tokens; ahub tool task-create/ask-user/memory-search/memory-add over loopback HTTP; server-side policies (Triage-only, gen<=2, per-session caps, dedup, project allowlist); question.json -> Question bucket -> comment-answer -> pi --session resume as new attempt; parent auto-Block/unblock on subtask completion; AgentsView: pg push from runner host + /sessions/<id> deep links in comments.open3epicNULLNULL2026-07-12T23:36:29ZEugene Blikhbigbes@gmail.com2026-07-12T23:36:29ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0
ah-k23da0056f7dd6aa3670d94ec5f884c39b8591e1894a3ad250858f26540912ac504Infra: phoebe-lab wiring for agents-devTracked in ~/data/home/phoebe-lab (deploy via labng). Runtime setup: Vikunja project+buckets+API token+webhook target; LiteLLM virtual key for agents (budget-capped); mem0 m0sk key; srht agent-hub user + repo ACLs; later: Proxmox VM (lab.yml remote entry, basic-vmagent host, VM-local singbox for TG egress — decided: VM-local, not LAN-published), agentsview pg-push firewall allowlist for the VM.open3epicNULLNULL2026-07-12T23:36:30ZEugene Blikhbigbes@gmail.com2026-07-12T23:36:30ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0
ah-nyl343ac6a94d3bd1074e58a6f7897af90cfc1a84f2e764dc2f17d9f96ba094b31fStage 1 MVP: poll-driven happy pathVikunja task dragged to Ready -> claim -> worktree+branch -> pi in zellij -> In Review with diff summary (or Failed with diagnostics). Everything per docs/SPEC.md (authoritative). Done when: e2e harness green + a real task passes the loop against live Vikunja.open1epicNULLNULL2026-07-12T23:34:03ZEugene Blikhbigbes@gmail.com2026-07-12T23:34:03ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0
ah-nyl.1faee2c254f4120dc1b198544543cd6073a586bf48f0606929988685660049281foundation: go module, domain, ports, configCreate the Go foundation of agents-dev exactly per docs/SPEC.md (read it fully first; SS4-6, SS12-13 are normative for this task). Deliverables: 1. go.mod: module go.bigb.es/agents-dev, go 1.26. Add ALL stage-1 external deps now so siblings never touch go.mod: modernc.org/sqlite, gopkg.in/yaml.v3. Populate go.sum by building a throwaway smoke import (e.g. internal/smoke_test.go importing both, then delete the file but keep go.sum entries; or keep a tiny blank-import file under internal/deps/deps.go with build tag 'deps' — your choice, document it). 2. internal/domain: types + constants from SPEC SS5 (State, Outcome, Task, Repo, TaskRecord, Run, Event, RunSummary) and pure transition helpers, at minimum CanClaim(*TaskRecord) bool per SS5 semantics. Table tests for every helper. 3. internal/ports: interfaces exactly as SPEC SS6 (Board, Runner, Store, Notifier + BoardTask, StartSpec, RunInfo, RunStatus). Doc comments on every method stating error/nil semantics ((nil, nil) for absent, etc.). 4. internal/config: Load(path string) (*Config, error) implementing SPEC SS12: yaml.v3 with KnownFields(true), ${VAR} env expansion in string values (only for vars that exist; unknown var = validation error), "~" expansion in paths, duration parsing, validation that collects ALL problems into one error (repos non-empty, default_repo/default_role resolve, buckets map has all six canonical keys, listen is loopback host:port). Config struct mirrors config.example.yaml at repo root (keep the two in sync; fix the example if you find an inconsistency and note it in the commit message). Tests: golden-load of config.example.yaml with env set, plus failure cases. Rules: stdlib + the two deps only; log/slog if logging is needed (probably not here); no package-level state. Run: go build ./... && go vet ./... && go test ./... (allowed for THIS task only, since you own the whole tree). Commit everything as one or two commits, message style 'domain: ...', 'config: ...'. Do NOT push. Do NOT touch .beads/. Acceptance: go build/vet/test green on a clean checkout; interfaces compile exactly against the names/signatures in SPEC SS6 (parallel siblings will implement them verbatim); config.example.yaml loads. closed0taskNULLNULL2026-07-12T23:34:03ZEugene Blikhbigbes@gmail.com2026-07-12T23:55:03Z2026-07-12T23:55:03ZNULL0NULLNULLNULL000�{}Closed0NULLNULLNULL02026-07-12T23:38:10Z0
ah-nyl.2160899e1969f48c186279e62ca24ed7aa7f362fd1b56dc90ed2247c4cf660322store: SQLite implementation of ports.StoreImplement internal/store per docs/SPEC.md SS7 (read SPEC fully; SS5-7 normative). ports.Store on modernc.org/sqlite. Deliverables: - internal/store/store.go: New(path string) (*Store, error) — opens DB, applies PRAGMAs (WAL, busy_timeout=5000, foreign_keys=on), runs migrations; Close(). - Migrations: embedded schema.sql (embed package), applied under a PRAGMA user_version gate (hand-rolled, target version 1). DDL exactly per SPEC SS7. - All ports.Store methods with the documented semantics: GetTask/LatestRun return (nil, nil) when absent; CreateRun surfaces UNIQUE(task_id, attempt) violation as a distinguishable error (exported sentinel ErrDuplicateRun); UpsertTask insert-or-update by id; timestamps RFC3339 UTC; contexts honored (database/sql *Context variants everywhere). - Compile-time check: var _ ports.Store = (*Store)(nil). Tests (stdlib testing only, t.TempDir() databases): round-trip every method; absent-row nil,nil; duplicate run -> ErrDuplicateRun; upsert updates fields + updated_at; ListTasks ordering deterministic (by id); events append + monotonically increasing seq; migration idempotence (New twice on same file). Constraints: work ONLY under internal/store/. Do not modify go.mod/go.sum (deps are already there), other packages, or .beads/. Build/test ONLY your package: go build ./internal/store/... && go vet ./internal/store/... && go test ./internal/store/... . Commit with 'store: ...' staging only internal/store. Do NOT push. in_progress1taskNULLNULL2026-07-12T23:34:33ZEugene Blikhbigbes@gmail.com2026-07-12T23:55:04ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL02026-07-12T23:55:04Z0
ah-nyl.3c5a4d9c93b65bce4f1b5dea36aa896d1dec99ba8a4a1c9579ace421cbb9f8d21vikunja: Board adapter over the REST APIImplement internal/vikunja per docs/SPEC.md SS8 (read SPEC fully; SS6, SS8 normative). ports.Board over the Vikunja 2.3.0 REST API. Deliverables: - New(cfg config.Vikunja, logger *slog.Logger) (*Client, error) storing an http.Client with a sane timeout (~15s). - Bucket resolution per SPEC SS8: locate the kanban view of the configured project, build title->bucketID and bucketID->canonical-name maps from the config buckets mapping; missing configured title = error listing found titles. Resolve lazily on first use and cache; provide a Refresh path when a lookup misses (board edited). - Snapshot(ctx): tasks of the project with canonical bucket names ("" for unmapped buckets), honoring pagination. - MoveToBucket(ctx, taskID, canonical), Comment(ctx, taskID, markdown), each per SPEC SS8 endpoints. - Error style: non-2xx -> error with method, path, status, and <=200 bytes of body. - Compile-time check: var _ ports.Board = (*Client)(nil). IMPORTANT — verify the real API contract before coding: the live OpenAPI JSON is at https://tasks.bigb.es/api/v1/docs.json (Swagger UI at /api/v1/docs) — fetch it (no auth needed for the spec itself) and confirm exact paths, request/response shapes, and pagination headers for: project views list, kanban view tasks, buckets list, bucket task move, comment create (Vikunja uses PUT-for-create), single task get. If the live spec is unreachable, use the upstream docs at https://vikunja.io/docs/ and pin your best understanding in code comments + fixtures. SPEC SS8's endpoint list is the expected shape, not gospel — trust the OpenAPI. Tests: httptest.Server fixtures (JSON canned from the OpenAPI shapes) covering snapshot incl. pagination + unmapped buckets, bucket resolution failure (helpful error), move, comment, non-2xx error rendering. No live-network tests. Constraints: work ONLY under internal/vikunja/. No go.mod changes, no other packages, no .beads/. Build/test ONLY your package (go build/vet/test ./internal/vikunja/...). Commit 'vikunja: ...' staging only internal/vikunja. Do NOT push. in_progress1taskNULLNULL2026-07-12T23:34:34ZEugene Blikhbigbes@gmail.com2026-07-12T23:55:04ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL02026-07-12T23:55:04Z0
ah-nyl.4ff6bd742ed8006517b016443e69e35e99531123b2198633480125843c1ee2f40runner: pi+zellij implementation + ahub-run supervisorImplement internal/runner + cmd/ahub-run per docs/SPEC.md SS9 (read SPEC fully; SS6, SS9 normative). This is the trickiest package — the SS9 contract (worktree layout, .task/ files, status precedence) is normative; follow it to the letter. Deliverables: - internal/runner: New(cfg *config.Config, logger *slog.Logger) *PiZellij implementing ports.Runner (compile-time check var _ ports.Runner = ...). - Start: create/reuse worktree + branch per SS9 (git -C <repo> worktree add ...; handle existing worktree dir and existing branch for retries), write .task/PROMPT.md and .task/meta.json, worktree-local ignore via the resolved git-dir info/exclude per SS9, ensure zellij session (zellij attach --create-background task-<id>), spawn the pane (zellij --session task-<id> run --cwd <worktree> -- ahub-run --task-id N --attempt K --report-url <url> -- pi --mode json -p @.task/PROMPT.md --model <model> --no-skills --no-extensions [pi_args...]). Return RunInfo. - Status: precedence per SS9 — exit.json => Completed (outcome success/error by code); else session alive in `zellij list-sessions --short` => Running with LastEvent=mtime(events.jsonl); else Completed with OutcomeCrashed, exit -1. Parse PiSession + CostUSD from events.jsonl leniently: scan lines as loose JSON maps; session id from the first object that has a plausible session identifier; cost accumulated from usage/cost fields when present. IMPORTANT: pi 0.70.2 is installed locally — empirically capture a real `pi --mode json -p 'say hi'` JSONL sample (any cheap/configured model, or ask for the shape via `pi --help` + a dry attempt; if no model is invocable offline, mark the parser 'best-effort, fixture-based' and derive fixtures from pi's documented event shape), commit the sample as a testdata fixture, and pin the parser to it. - Kill: zellij kill-session + best-effort delete-session. Summary: git log/diff per SS9. - ALL zellij/pi/git argv construction centralized in commands.go with unit tests asserting exact argv (SS9 requirement). - cmd/ahub-run: supervisor per SS9 contract — tee child stdout to .task/events.jsonl (stderr passthrough), atomic exit.json (tmp+rename), best-effort POST to --report-url (2s timeout, 1 retry), signal-death -> 128+sig, --keep-pane default true iff $ZELLIJ set (then print resume hint + exec $SHELL), false => exit with child code. Tests: stub `zellij`/`pi`/(where sensible `git` is real — use real git with a t.TempDir() repo for worktree tests) as executable scripts prepended to PATH; cover: worktree create+reuse, argv construction, status precedence matrix (exit.json / alive / gone), events parsing from fixture, ahub-run end-to-end via os/exec (tee, atomic exit.json, report POST to httptest, exit-code mapping). No sleeps >100ms; no real zellij sessions in tests. Constraints: work ONLY under internal/runner/ and cmd/ahub-run/. No go.mod changes, no other packages, no .beads/. Build/test ONLY yours: go build ./internal/runner/... ./cmd/ahub-run/... && go vet <same> && go test <same>. Commit 'runner: ...' staging only your paths. Do NOT push. open1taskNULLNULL2026-07-12T23:35:16ZEugene Blikhbigbes@gmail.com2026-07-12T23:35:16ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0
ah-nyl.5a229e6751c3b6c7e11fca843ebea6db9830e910a9d3b730b6df4481690de2551reconcile: the control loopImplement 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. open1taskNULLNULL2026-07-12T23:35:17ZEugene Blikhbigbes@gmail.com2026-07-12T23:35:17ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0
ah-nyl.60f3627c5d82d75a475ee9648fba27c211ab6ca3b93bbb47bbb18b50ec3c92db4wiring: httpapi + agenthubd + ahub CLIsWire the daemon together per docs/SPEC.md SS3, SS11 (read SPEC fully). All sibling packages now exist — full-tree builds are allowed and expected in THIS task. Deliverables: - internal/httpapi: loopback server per SS11 — GET /healthz; POST /internal/v1/run-exit {task_id,attempt,exit_code} validated -> calls a RunExitHook (func injected by main; it pokes the reconciler); GET /api/v1/status -> JSON {tasks:[TaskRecord+latest Run], generated_at}. stdlib net/http + 1.22 mux patterns; graceful shutdown; tests via httptest. - cmd/agenthubd: flags --config (default ./agenthub.yaml) --log-level; load config, open store, construct vikunja client, runner, no-op notifier (slog), reconciler; start httpapi + reconciler.Run; SIGINT/SIGTERM -> graceful stop (context cancel, http shutdown, store close). slog JSON to stderr. - cmd/ahub: subcommands (stdlib flag, no cobra): `status` (GET /api/v1/status from --addr default 127.0.0.1:9100, human-readable table + --json raw), `validate-config` (load config, print OK or the collected errors, exit code accordingly), `version` (var set via -ldflags, default "dev"). - justfile: verify `just build` produces bin/agenthubd bin/ahub bin/ahub-run (adjust if needed). - Smoke check you must run and make pass: `go build ./... && go vet ./... && go test ./...` (whole tree), then `bin/agenthubd --config config.example.yaml` with a fake VIKUNJA_TOKEN env — it must start, log the bucket-resolution failure gracefully (retry next tick, not crash-loop-exit), and /healthz must answer. Note in the bead comment if SPEC/behavior forced any deviation. Constraints: you own cmd/agenthubd, cmd/ahub, internal/httpapi, plus minimal glue edits elsewhere ONLY if a sibling package has an integration bug you must fix to link (document any such fix in its own commit '<pkg>: fix ...'). No .beads/ changes. Commits: 'httpapi: ...', 'cmd: ...'. Do NOT push. open1taskNULLNULL2026-07-12T23:35:55ZEugene Blikhbigbes@gmail.com2026-07-12T23:35:55ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL1
ah-nyl.77c266e5f2bb15c0bb076a169f5f91846b9e15c8d4397026b55d441ea8638463de2e: harness with fake vikunja + stub piBuild the end-to-end harness per docs/SPEC.md SS1/SS14 stage-1 acceptance: prove the full loop without live services. Build tag e2e, directory e2e/, run via `just e2e`. Scenario (single test, subtests per phase): temp dir with (a) a real git repo as the target repo (one commit on master), (b) fake Vikunja: httptest server implementing the subset internal/vikunja uses (views, kanban tasks, buckets, move, comment) over in-memory state you can mutate from the test; (c) stub `pi` script on PATH that reads .task/PROMPT.md, makes a commit in the cwd repo ('stub: change'), emits 2-3 plausible JSONL lines to stdout, exits 0; (d) real zellij is NOT used: stub `zellij` script that for `run` executes the wrapped command directly (background), for attach --create-background no-ops, for list-sessions prints active names from a state file — i.e. simulate sessions with files. (e) real ahub-run and agenthubd binaries built by the test (go build into t.TempDir()). Flow: start agenthubd with a generated config (short poll_interval ~200ms) -> put a task in fake-Vikunja Ready bucket -> wait (poll with deadline, no fixed sleeps) for: card moved to In Progress with claim comment; then card in In Review with a comment containing the diff stat; store db has task in_review + run finished/success (inspect via ahub status --json against the daemon). Negative subtest: stub pi exits 1 -> card lands in Failed with diagnostic comment. Timeout subtest optional (only if cheap with the fake clock — the daemon uses real time; skip if it needs sleeps >2s and note why). Constraints: everything under e2e/ (+ justfile tweak if needed). Full-tree build allowed. If you find integration bugs in other packages, fix them in separate commits '<pkg>: fix ...' with a test where feasible. No .beads/ changes. Commit 'e2e: ...'. Do NOT push. open2taskNULLNULL2026-07-12T23:35:56ZEugene Blikhbigbes@gmail.com2026-07-12T23:35:56ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL1
ah-nyl.856c1d153e12c3a78d437729c157cf9955e07e9f7fdb9f846e61d0984e74e1941refactor: adopt go.bigb.es/auxilia (scribe/culpa/steward) where it paysPost-MVP, per SPEC SS13: evaluate replacing slog wiring with scribe, error plumbing with culpa, cmd wiring with steward. Load the auxilia skill for API reference. Only adopt where it reduces code; keep diffs reviewable per package. Blocked until stage-1 e2e is green and stable.open3choreNULLNULL2026-07-12T23:35:57ZEugene Blikhbigbes@gmail.com2026-07-12T23:35:57ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL1
ah-oeq4c7fd7ca7b85255c43283cb38978e25fe359f7f32e03dd3033ee0860fe52a5bfStage 5: VM deploy, web terminal, virtual keys, spec editor, MCP facadePer SPEC SS14.5: dedicated Proxmox VM (deploy via systemd, precedent remote/basic-vmagent in phoebe-lab); zellij web / ttyd behind Traefik (needs file provider for non-Docker backend); per-task LiteLLM virtual keys with max_budget + /spend attribution; spec-editor page; MCP facade over the agent API; multi-repo + pipeline roles.open4epicNULLNULL2026-07-12T23:36:30ZEugene Blikhbigbes@gmail.com2026-07-12T23:36:30ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0
ah-xuc19aa9e472e32b714a672302d4a5b9431d5154fa20c3d0f98ef188f68d40ea1b7Stage 2: webhooks, Task Spec, full buckets, Telegram, srht push, watchdogPer SPEC SS14.2: Vikunja webhook receiver (HMAC) as reconciler poke; Task Spec YAML frontmatter (role/model/skills/limits) + label type defaults + validation -> Triage bounce; buckets Triage/Blocked/Question; Telegram notifier (honor HTTPS_PROXY; TG blocked from lab network); push agent/task-N branch to git.srht.bigb.es for review + link in In Review comment; watchdog on stale events.jsonl; pi --skill materialization from /srv/skills.open3epicNULLNULL2026-07-12T23:36:28ZEugene Blikhbigbes@gmail.com2026-07-12T23:36:28ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0
ah-ydx8735805091c14831debfbdb26c8f324f6832e8b80ebcc313e05201a7bd3c85f8Stage 3: mem0 memory lifecycle + Context PackPer SPEC SS14.3: mem0 REST client (X-API-Key, scoping user_id=proj:<slug>/global, run_id=task:<id> — agent_id filter is buggy upstream); load cascade on claim -> .task/CONTEXT.md section; save on Done; post-run summarizer role; Context Pack builder (task+thread+parent-chain+memory+git, ~40k char budget, deterministic order, truncate-from-tail).open3epicNULLNULL2026-07-12T23:36:28ZEugene Blikhbigbes@gmail.com2026-07-12T23:36:28ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0