~bigbes/agents-dev · issues

jg4jc2dsohj4vpev0gnbpdoiqsgfslf3 · 63 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-xuc.1214d3638d45c9064a76941832983973f494233fccabe6a738101abdf7f06e6d89docs: sync SPEC with Stage 2 behaviorSPEC.md gains normative Stage 2 sections mirroring what landed, in the established style (invariants and failure modes, not narrative): domain deltas (stalled outcome, canonical buckets as a superset of states, Run.Timeout), ports deltas (Labels, Skills, Publish), store v2 migration, vikunja labels, runner skills plus publish (never force-push), reconciler claim spec resolution + Triage bounce + parked buckets + per-run timeout + watchdog + notification ordering, httpapi webhook endpoint (HMAC, disabled when unset), config reference with the full new example, security notes (webhook secret, TG token redaction, srht push scope), roadmap section 14 marks Stage 2 delivered. Cross-check config.example.yaml for drift. AGENTS.md and CLAUDE.md only if conventions changed (mirror both if so — independent files).Each new SPEC section spot-checked against the shipped code; no contradiction with Stage 1 sections; the research-v3 supersede note stays accurateclosed2taskEugene BlikhNULL2026-07-13T05:16:35ZEugene Blikhbigbes@gmail.com2026-07-13T08:38:17Z2026-07-13T08:38:17ZNULL0NULLNULLNULL000�{}e13b65c + b48849f (two wording nits); accuracy reviewer merge-ready — every behavioral claim verified against code; SPEC section-12 example validates through ahub validate-config; pre-existing RunStatus.MetaAttempt drift filed as ah-6u00NULLNULLNULL02026-07-13T07:53:57Z0
ah-xuc.2fa1ad68d45c1cb503c73e2f25b2c07769c319f1d2adc6eefbb30f03d70297a4ainternal/spec: Task Spec frontmatter parse, type-label defaults, validationNew pure package internal/spec (imports domain, config, yaml only — no board/store/runner I/O). Custom fields do not exist in Vikunja, so the machine-readable part of a task lives as YAML frontmatter at the head of the description; labels give per-type defaults. Parse: frontmatter delimited by --- lines at the very start of the description (tolerate CRLF; no frontmatter = empty spec). Known fields: role, model, skills (list of names), timeout (duration string). Unknown fields are collected as warnings, never errors. Returns spec + body (description with frontmatter stripped) + warnings. Resolve(cfg, labels, description): merge precedence config defaults < type:<name> label preset (cfg.TaskTypes) < frontmatter. More than one type:* label is a validation error; a type:* label naming an unknown task type is a validation error. Validation (bounce-class) errors: broken YAML, unknown role, skill name not a safe slug, skills requested while skills_dir unset, missing <skills_dir>/<name>/SKILL.md, SKILL.md frontmatter with an empty description, timeout unparseable or nonpositive. Output: Resolved{RoleName, Model, SkillPaths (absolute), Timeout, Body, Warnings}. Filesystem checks go through a small injected func so most tests need no real skills tree; add one real-FS test with t.TempDir() fixtures. Validation errors must be a typed, human-readable list — the reconciler posts them verbatim in the Triage bounce comment — distinct from internal errors.go test ./internal/spec/... green, go vet clean; table tests cover merge precedence for every field and each bounce class; frontmatter stripping keeps the body exact after the closing delimiterclosed2featureEugene BlikhNULL2026-07-13T05:15:08ZEugene Blikhbigbes@gmail.com2026-07-13T06:22:47Z2026-07-13T06:22:47ZNULL0NULLNULLNULL000�{}d714741 + eb5a4be (review-gap pinning); hostile adversarial review merge-ready (yaml alias bombs bounded, path traversal blocked, error taxonomy sound)0NULLNULLNULL02026-07-13T05:44:24Z0
ah-xuc.3130d6553f11713918d8f32dca70661607918c8ae7bed880ea98a1b417dca5b30vikunja: fetch task labels into BoardTask.LabelsStage 2 type defaults key off Vikunja labels and the adapter currently drops them. wireTask gains the labels array (verify the exact field shape against the live docs.json or the go-vikunja v2.3.0 source, as was done for result-count semantics in commit 7802095). Snapshot copies label titles into ports.BoardTask.Labels ([]string, empty-safe, order as returned). Extend the httptest fixtures with tasks carrying zero, one, and several labels, including one with a type: prefix. No behavior change for existing methods.go test ./internal/vikunja/... green, go vet clean; fixtures cover labeled and label-less tasksclosed2taskEugene BlikhNULL2026-07-13T05:15:10ZEugene Blikhbigbes@gmail.com2026-07-13T06:22:48Z2026-07-13T06:22:48ZNULL0NULLNULLNULL000�{}1e9fc7e; wire shape pinned against upstream go-vikunja v2.3.0; review clean0NULLNULLNULL02026-07-13T05:44:24Z0
ah-xuc.433d26ffac04170d2d8e34c39c29e316a661775ceecd8aa8f20c5d11929a7589dstore: migration v2 — per-run timeout columnThe effective timeout can differ per run once Task Spec overrides land, and a daemon restart must keep enforcing the right deadline, so it is persisted on the run row. Schema user_version 2: runs gains timeout_seconds INTEGER NOT NULL DEFAULT 0 (0 = config default at enforcement time). Fresh databases create straight at v2; existing v1 files get ALTER TABLE on open. Follow the existing hand-rolled migrator (PRAGMA user_version gate, BEGIN IMMEDIATE serialization, first-boot busy retry — keep every one of those properties). CreateRun/UpdateRun/LatestRun round-trip domain.Run.Timeout, stored as integer seconds.go test ./internal/store/... green, go vet clean; tests: fresh create lands at user_version 2; a v1 database upgrades in place preserving rows; timeout round-trips; existing first-boot race tests keep passingclosed2taskEugene BlikhNULL2026-07-13T05:15:22ZEugene Blikhbigbes@gmail.com2026-07-13T06:22:49Z2026-07-13T06:22:49ZNULL0NULLNULLNULL000�{}c04f7d7; step-list migrator preserves all race properties (verified under -race); review clean0NULLNULLNULL02026-07-13T05:44:25Z0
ah-xuc.5b5fbb872b97c09d1baaee1d165892ef0ed8473656472b639900c43d5dbb8e0afrunner: explicit --skill arguments and Publish to the review remoteTwo runner extensions, both behind existing seams. All argv construction stays in commands.go per SPEC section 9. Skills: piArgv gains the resolved skill dirs — one --skill <absolute-path> per entry, appended while keeping --no-skills and --no-extensions (pi 0.70.2 loads explicit --skill paths even under --no-skills, giving a deterministic per-run set). Start threads StartSpec.Skills through. Publish(ctx, taskID): resolve the task worktree, branch, and repo the same way Summary does today. When the repo has no review_remote, return a zero PublishInfo and nil error (publish not configured). Otherwise git -C <worktree> push <review_remote> <branch> with the branch pushed to the same name — plain push, never force (SPEC: agent branches are never force-pushed). On success fill PublishInfo{RemoteURL, Branch, WebURL} where WebURL is the repo review_url with {branch} substituted (empty when review_url unset). Push failures return a wrapped error carrying a stderr prefix.go test ./internal/runner/... green, go vet clean; argv table tests for skills present/absent and push; PATH-shim git stub verifies push argv, success, and failure propagation; a Start test asserts --skill flags reach the pi argvCoordinator refinement: implement ports.Publisher (separate port defined in ah-xuc.1) as a method on the existing runner type — the ports.Runner interface itself does not change.closed2featureEugene BlikhNULL2026-07-13T05:15:26ZEugene Blikhbigbes@gmail.com2026-07-13T06:22:49Z2026-07-13T06:22:49ZNULL0NULLNULLNULL000�{}28f75aa + eae0845; refspec refs/heads/X:refs/heads/X pinned, no-force verified, findWorktree semantics shared with Summary; review clean0NULLNULLNULL02026-07-13T05:44:25Z0
ah-xuc.6e8c8ca06f34dfebba7004095b3bec4be6a1dd7a6c04bce0af09d4edc831fed76telegram: ports.Notifier implementation (Bot API through HTTPS_PROXY)New package internal/telegram implementing ports.Notifier. POST {api_base}/bot{token}/sendMessage with JSON {chat_id, text, disable_web_page_preview: true}. http.Client with a 10s timeout whose transport keeps ProxyFromEnvironment semantics so HTTPS_PROXY is honored (Telegram is blocked from the lab network; egress goes through the proxy) — do not build a bare Transport without the Proxy field. Non-2xx responses and ok:false bodies become errors carrying a short body prefix; the bot token must never appear in logs or error strings — redact the URL when wrapping errors. No retries: the reconciler treats Notify as best-effort. api_base comes from config telegram.api_base so tests and e2e can point it at httptest.go test ./internal/telegram/... green, go vet clean; httptest covers success, HTTP error, ok:false, and token redaction in returned errors; a test asserts proxy resolution from the environment is activeclosed2featureEugene BlikhNULL2026-07-13T05:15:38ZEugene Blikhbigbes@gmail.com2026-07-13T06:22:50Z2026-07-13T06:22:50ZNULL0NULLNULLNULL000�{}e15fe4c; token-leak vectors traced to stdlib source and closed; proxy semantics verified empirically; review clean0NULLNULLNULL02026-07-13T05:44:25Z0
ah-xuc.762a6806491ee4096a8206ec5b958064c69d772d7f8376188ca61bbfc8a354510httpapi: Vikunja webhook receiver with HMAC verificationPOST /webhooks/vikunja as a reconciler poke. Design principle 1: a webhook only triggers an immediate iteration; polling stays the source of truth because Vikunja delivers webhooks once, without retries. Deps gain WebhookSecret string and a Webhook hook (non-blocking; cmd wires it to Reconciler.Poke). Empty secret = feature disabled: the route is not registered at all. Verification: X-Vikunja-Signature carries hex HMAC-SHA256 over the raw request body; compute over the exact bytes read and compare with hmac.Equal; missing or wrong signature = 401 with a terse body that echoes nothing back; cap the body at 256 KiB. After verification decode {event_name} best-effort for the log line only — the payload is otherwise untrusted and unused. Respond 200 fast, call the hook once per verified delivery. Exposing the loopback listener to Vikunja is infra (ah-k23), not this bead.go test ./internal/httpapi/... green, go vet clean; tests: a valid computed signature pokes the hook and returns 200; tampered body, wrong secret, and missing header return 401 without invoking the hook; oversized body rejected; unset secret leaves the route absent and existing routes unaffectedclosed2featureEugene BlikhNULL2026-07-13T05:15:43ZEugene Blikhbigbes@gmail.com2026-07-13T06:22:50Z2026-07-13T06:22:50ZNULL0NULLNULLNULL000�{}61400ae; HMAC discipline verified (full-read-before-verify, uniform 401, constant-time compare); review clean0NULLNULLNULL02026-07-13T05:44:26Z0
ah-xuc.8d48513a80bea7b4ebcfc74514ea6d2a7079500b44f1b1eebca7b445db6e316b7reconcile: spec-driven claim, Triage bounce, parked buckets, per-run timeoutClaim-path integration of Stage 2. Same-package constraint: this bead owns the internal/reconcile edits for the claim path; the finalize-path bead must not start until this one is committed. iterate(): canonical buckets triage/blocked/question become parked buckets — superviseRuntime only (detached supervision persists runtime truth; no claim, no kill, no card moves, no comments). They are never claim sources and never terminal targets. Blocked and Question get real semantics in Stage 4; Stage 2 only reserves and parks them. claim(): resolve the Task Spec via internal/spec from BoardTask.Labels plus Description. A validation failure bounces: MoveToBucket(triage) first, then one diagnostic comment listing the problems verbatim plus a hint to fix the spec and drag back to Ready, then event spec_rejected — move-then-comment discipline so a persistent move failure cannot spam comments; appendEvent dedup applies. No record is persisted and the card never goes to Failed for spec problems. Warnings (unknown fields) never block: append them to the claim comment. Success path: the spec role name resolves through cfg.Roles; model override applies; the prompt renders over the frontmatter-stripped Body; resolved SkillPaths go into StartSpec.Skills; the effective timeout (spec override or config default) goes into StartSpec.Timeout and is persisted as Run.Timeout. check(): deadline enforcement uses run.Timeout when positive, else cfg.Timeout — in both the running arm and the degraded neither-state arm. Extend fakes_test.go (fake runner captures Skills and Timeout; board tasks carry Labels) and cover: each bounce class end to end, merge precedence reaching StartSpec, parked buckets neither claim nor kill while detached supervision still finalizes a finished runtime, per-run timeout enforced at the right boundary with the fake clock — both shorter and longer than the config default.go test ./internal/reconcile/... green, go vet clean; bounce tests assert move-before-comment ordering and zero Failed transitions; parked-bucket tests assert no board writes; timeout tests cover run.Timeout smaller and larger than the config default Additional: pre-existing gofmt drift in internal/reconcile/reconcile_test.go (comment alignment around lines 983-984 and 1345, present since before Stage 2) — run gofmt -w on the files you touch and fold the fix into this bead's commit.closed2featureEugene BlikhNULL2026-07-13T05:16:00ZEugene Blikhbigbes@gmail.com2026-07-13T06:57:17Z2026-07-13T06:57:17ZNULL0NULLNULLNULL000�{}9823250 + 06_pin commit; review merge-ready (all SPEC section-10 invariants traced clean); validator 10/10 incl. e2e byte-identical for spec-less tasks; adopt-over-bounce coverage gap closed0NULLNULLNULL02026-07-13T06:23:38Z0
ah-xuc.95c6568a5b55170ea70ba05fb8c0af96dcfaf33b977424934bdb124f8c46e5c10reconcile: publish review branch, watchdog on stale events, Telegram notificationsFinalize-path integration of Stage 2. Starts only after the claim-path bead is committed (same package). Publish: in finalize, on the success path with moveCard set, call runner.Publish before posting the In Review comment. Zero PublishInfo = not configured, plain comment. Success adds a review link line (WebURL, falling back to RemoteURL plus branch) and appends event published. Failure degrades: the comment still posts with a push-failed line carrying the error, event publish_failed (deduped). A refinalize repeats the push — pushing an up-to-date branch is idempotent and fine. Watchdog: in the check() running arm, when cfg.StallTimeout > 0 and now minus max(st.LastEvent, run.StartedAt) exceeds StallTimeout, the run is stalled: kill and finalize with OutcomeStalled, exit -1 (share the timeoutKill shape). The neither-state arm stays deadline-only — no events are observable there. failureComment renders the stalled outcome distinctly (agent went silent, not merely slow). Notifications: Notify best-effort — log on error, never gate the flow, guard the nil notifier — after a successful move plus comment: finalize with moveCard (success and failure including timeout and stalled) and the spec bounce. Text: outcome emoji, task id and title, outcome word, cost when known, and the human task link built from vikunja web_url. Tests with fakes: the In Review comment contains the review link; publish failure still posts the comment; the stall kill fires just past the boundary and not before; a run with events flowing but past run.Timeout still dies by deadline; notify recorded after move and comment in that order; nil notifier safe; a notify failure does not fail finalize.go test ./internal/reconcile/... green, go vet clean; ordering asserted move then comment then notify; stalled and timeout outcomes distinguishable in comments, events, and notificationsCoordinator refinement: publishing arrives via a new optional reconcile Deps field of type ports.Publisher (nil-guarded like Notifier); finalize publishes only when the field is non-nil. cmd wires the runner into it in ah-xuc.10.closed2featureEugene BlikhNULL2026-07-13T05:16:07ZEugene Blikhbigbes@gmail.com2026-07-13T07:35:20Z2026-07-13T07:35:20ZNULL0NULLNULLNULL000�{}d5d1efc + 64a7216 (review fix: bounded publish ctx via publish_timeout knob, zero-delta recorder covers publish/notify); reviewer merge-ready after fix, validator 10/10 with all 24 subtests by name0NULLNULLNULL02026-07-13T06:57:43Z0
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
ah-ydx.1942024e29b162a28d01e0bddbd3bf862f1ff8bf498c45bd03199c5a0dc916489internal/mem0: REST client for live mem0.bigb.esTyped Go client for the self-hosted Mem0 server (LIVE at mem0.bigb.es, phoebe-lab/mem0 stack): X-API-Key auth, add/search/get-all/delete memories. Encode scoping conventions as helpers: user_id='proj:<slug>' | 'global', run_id='task:<id>'; do NOT rely on agent_id filtering (buggy upstream per SPEC §14.3). Stdlib-only, httptest unit tests; live verification (incl. API-key provisioning via dashboard/register) is a follow-up ops step.closed2featureEugene BlikhNULL2026-07-18T13:23:56ZEugene Blikhbigbes@gmail.com2026-07-18T13:41:11Z2026-07-18T13:41:11ZNULL0NULLNULLNULL000�{}internal/mem0 client merged to master (55b9b43); routes confirmed against mem0 v2.0.11 source; live verification against mem0.bigb.es tracked in ah-ydx.30NULLNULLNULL02026-07-18T13:25:07Z0
ah-ydx.2f548f321fdf44dbfaaa3c420a175ff8b3bea76ab1cf76d097509d87eeb461072internal/ctxpack: Context Pack builderDeterministic prompt-context assembler per SPEC §14.3: ordered sections (task, comment thread, parent chain, memory, git log/diffstat) under a ~40k char budget, per-section truncate-from-tail with stable ordering so identical inputs render identical packs. Pure package + table tests first; wiring into runner PROMPT.md rendering is a separate integration step after wave 1 merges.closed2featureEugene BlikhNULL2026-07-18T13:23:56ZEugene Blikhbigbes@gmail.com2026-07-18T13:41:11Z2026-07-18T13:41:11ZNULL0NULLNULLNULL000�{}internal/ctxpack merged to master (342410e); format contract pinned by golden tests; runner integration tracked in ah-ydx.30NULLNULLNULL02026-07-18T13:25:08Z0
ah-ydx.316681b27f4960105b6ca27beabc1e8219b7b6edab3c59c243830102a1c17bd7aMemory lifecycle: load-on-claim CONTEXT section, save-on-DoneWire mem0 into the task loop per SPEC §14.3: on claim, search mem0 (proj scope + global) and render a memory section into the prompt context via ctxpack; on Done/Cancelled terminal scan (shares the ah-07g hook), save run summary/verdict facts back to mem0 (run_id='task:<id>'). Depends on the mem0 client, ctxpack, and the ah-07g terminal-state scan.MEM0 SERVER HEALTHY (2026-07-18, after user-authorized override delete + restart): /configure now reflects env-of-truth (deepseek/deepseek-v4-flash + nvidia/nemotron-embed-1b-v2). FULL live smoke green: ADD infer=false 200/event=ADD; SEARCH 200 with score (embeddings ok); ADD infer=true 200 (LLM extraction ok); LIST/PURGE/EMPTY clean; bogus key 401. Server-side contract fully verified — lifecycle implementation unblocked once ah-07g lands the terminal-state hook. OPERATIONAL RULE: mem0 config is ENV-ONLY; never POST /configure (GET redacts secrets, round-trip corrupts stored creds — happened + fixed today, backup at phoebe:/root/mem0-settings-backup.sql); if a stored override reappears (dashboard onboarding creates one), delete settings row key=config_overrides + restart.open2featureNULLNULL2026-07-18T13:23:57ZEugene Blikhbigbes@gmail.com2026-07-18T13:57:49ZNULLNULL0NULLNULLNULL000�{}0NULLNULLNULL0NULL0