~bigbes/agents-dev · events

b60u6k6ij4rmaimj7s41pm3oidqs37pl · 406 rows

idissue_idevent_typeactorold_valuenew_valuecommentcreated_at
019f7cdf-2e5c-74fd-bf26-105aacf83db2ah-efelabel_removedEugene BlikhNULLNULLRemoved label: milestone:v0.1.02026-07-20T03:13:49Z
019f7cdf-2f63-79f6-8bb2-265a57ced2eeah-efelabel_addedEugene BlikhNULLNULLAdded label: milestone:v0.2.02026-07-20T03:13:49Z
019f7cdf-6fba-75e7-965f-79478aa1b878ah-1cxlabel_removedEugene BlikhNULLNULLRemoved label: milestone:v0.1.02026-07-20T03:14:05Z
019f7cdf-70c3-7ecd-8e47-c24bfda0df97ah-efelabel_removedEugene BlikhNULLNULLRemoved label: milestone:v0.2.02026-07-20T03:14:06Z
019f7cea-e517-7557-9476-bacfa9af34c6ah-wd4createdEugene BlikhNULL2026-07-20T03:26:36Z
019f7cf1-3477-79bc-be78-cf15a6ec2977ah-wd4updatedEugene Blikh{"id":"ah-wd4","title":"DECISION: move the task board from Vikunja to beads+Dolt (full swap vs hybrid mirror)","description":"Three independent Opus researchers audited this on 2026-07-20 (board contract / beads capabilities / human workflow). Consensus: writing the adapter is the EASY part; the cost is infrastructure and the human write path.\n\nFEASIBILITY (good news): ports.Board is only 6 methods (Snapshot, MoveToBucket, Comment, Comments, CreateTask, SwapLabel), 22 call sites all in internal/reconcile, and everything else (attempts, runs, lineage, Q\u0026A links) lives in the SQLite store. domain/ is Vikunja-free; bucket names are domain constants. Adapter est. a few hundred lines, minus the 238-line markdown-\u003eHTML converter which a plain-text board does not need. All 9 canonical buckets ARE expressible via beads custom statuses with active/wip/done/frozen categories, wired into the ready_issues view at SQL level. bd ready --claim is a real compare-and-swap (ErrAlreadyClaimed) — stronger than what we have today. Comments live in their own table, NOT mixed with the events audit log, so the ask-user answer detector is safe from machine-generated lines.\n\nBLOCKERS (the real cost):\n1. NO Go library (all packages are internal/), no MCP, no HTTP daemon. The only interfaces are fork/exec of bd --json (~250ms warm) or raw MySQL to a dolt sql-server.\n2. Embedded mode is single-process and BLOCKS UNBOUNDEDLY — measured bd count waiting 43s behind a 40s external DB hold, no timeout knob. Upstream design doc calls multi-process embedded 'unsupported'. Migrating to dolt sql-server mode is MANDATORY (backup + bd init --server + restore; different data dir; a new server process to supervise).\n3. Human write path. Vikunja is the human INPUT surface, not just storage; the viewer is read-only. The killer interaction is ask-user: a card parked in Question (or a live agent polling /api/tool/answer against a 30m timeout) waits on a human comment. Today that is typed from any device in \u003c=20s; under beads it is laptop-only bd comment behind a ~5min auto-push debounce (~17% of a run timeout per exchange). Lowering the interval does not fix the failure CLASS: a local write that reports success and is invisible to the daemon.\n4. Every write is a Dolt commit — a comment per state change plus per-heartbeat progress = write amplification into a version-controlled DAG that auto-pushes. bd batch help names this; bd compact/gc/flatten are the cleanup treadmill.\n5. int64 task IDs are load-bearing (branch task-\u003cid\u003e, zellij session, archive filename, tool-token binding, HTTP API, notification URL). Beads ids are strings (ah-1cx.1). Recommended fix: repo-wide int64-\u003estring (mechanical, compiler-verified, ~10 files) over a synthetic mapping table that can drift.\n6. Snapshot must NEVER be partial: a card missing from a snapshot is treated as vanished and the daemon KILLS the live run and cancels the record. Any adapter must enumerate transactionally or prove completeness (the Vikunja adapter refuses a truncated bucket rather than dropping tasks). Watch bd list default limits.\n7. Same-field concurrent updates are last-writer-wins with no optimistic locking (upstream open question #3); only --claim has CAS. Contradicts the SPEC principle that human intent wins and the daemon aligns.\n8. No change notification, by product charter ('Beads does not need sub-second sync'). Poll the events table by created_at. NOTE: this is NOT a real blocker for us — the Vikunja webhook is explicitly only an acceleration of the 20s poll, and agent-completion latency rides the separate run-exit poke.\n\nWHAT IMPROVES: Task Spec escapes the rich-text editor (plainTextFromHTML exists ONLY to undo Vikunja HTML mangling of YAML frontmatter — becomes deletable); first-class deferred/--defer beats an unmapped Someday column; dependency-aware bd ready for free; agent and human share one tracker beside the code; full history/diff/branching. Attachments are a non-issue (zero code references).\n\nOPTIONS:\nA) HYBRID MIRROR (low risk): keep Vikunja as the board, add a one-way exporter into beads for reporting/milestones. No reconcile changes at all. Note the milestone viewer at dolt.srht.bigb.es/~bigbes/agents-dev/view/milestones already delivers most of this value today.\nB) FULL SWAP, gated on prerequisites: migrate beads to dolt sql-server mode; daemon speaks MySQL directly (or bd --json --sandbox with pushes on its own timer); map ready-\u003estatus open (REQUIRED: the CAS claim hardcodes status='open'); use metadata JSON for daemon-private state; events.created_at as poll cursor; batch comment writes + scheduled compaction; int64-\u003estring ids; AND build a human write path — 3 POST endpoints on the existing httpapi (comment / status / label) reusing the proven bearer-token pattern, plus a small form in the viewer. Because the daemon runs on agent-1 next to the authoritative working set, writes through it have ZERO sync latency and take the laptop out of the write path entirely.\n\nRECOMMENDATION: do not swap while the viewer is read-only. Either stay on Vikunja, or commit to option B including the write path — the write path is what makes it viable, not the adapter. Implementation beads to be filed once this decision is made.","notes":"Researcher evidence is summarized here rather than linked; the three reports were transcript-only. Key measured facts to re-verify before acting: bd 1.1.0 embedded blocking (43s observed), bd has no non-internal Go packages, claim.go hardcodes status='open' in the CAS UPDATE, auto-push debounce default 5m / timeout 30s.","status":"open","priority":3,"issue_type":"decision","owner":"bigbes@gmail.com","created_at":"2026-07-20T00:26:37Z","created_by":"Eugene Blikh","updated_at":"2026-07-20T00:26:37Z"}{"notes":"CORRECTION 2026-07-20 (verified against the v1.1.0 source zip from proxy.golang.org): blocker #1 'NO Go library' is WRONG. github.com/steveyegge/beads has a root package beads.go documented as 'a minimal public API for extending bd with custom orchestration', MIT licensed. It re-exports the internal layer via type aliases (Storage, Transaction, RemoteStore, SyncStore, Issue, Comment, Event, IssueFilter, WorkFilter, status/type constants) and exposes Open(ctx, dbPath), OpenFromConfig(ctx, beadsDir), FindBeadsDir, FindDatabasePath.\n\nThe Storage interface covers the Board port almost 1:1: SearchIssues/GetReadyWork -\u003e Snapshot; UpdateIssue(id, {status}) -\u003e MoveToBucket; AddIssueComment/GetIssueComments (typed, ordered) -\u003e Comment/Comments; CreateIssue -\u003e CreateTask; AddLabel+RemoveLabel -\u003e SwapLabel.\n\nThree risks in the description are downgraded by this API:\n- Write amplification: RunInTransaction(ctx, commitMsg, fn) batches many writes into ONE Dolt commit, rolls back on error or panic. Also makes SwapLabel ATOMIC — better than the current Vikunja adapter, which documents a deliberate non-atomic add-then-remove.\n- Change notification: GetAllEventsSince(ctx, since time.Time) is a typed poll cursor; no hand-rolled SQL over the events table needed.\n- Embedded-vs-server: OpenFromConfig respects dolt_mode in metadata.json, so switching is configuration, not code, and the daemon holds the connection instead of fork/exec-ing a ~250ms CLI. RemoteStore (via type assertion) exposes Push/Pull so the daemon controls push timing itself rather than inheriting the 5-min auto-push debounce.\n\nSTILL TO VERIFY before relying on it: which call enumerates ALL issues for Snapshot (there is no plain ListIssues — likely SearchIssues with an empty query + IssueFilter) and whether IssueFilter applies a default limit. A silently truncated snapshot makes the daemon treat missing cards as vanished and KILL live runs, so this needs an explicit completeness guarantee.\n\nUNCHANGED: the human write path is still the real blocker, and the recommendation stands — do not swap while the viewer is read-only."}NULL2026-07-20T03:33:30Z