Argus Task System — Design (epic / feature / task, evidence-derived status)¶
Date: 2026-06-15. Status: DESIGN / pre-implementation. Captures the design
discussion of 2026-06-14/15. Grounded in
docs/research/2026-06-14-task-system-research.md (two deep-research runs).
NOT to be confused with docs/plans/2026-06-12-tasks-module-m3.md — that is the
Python cron task-runner (heartbeat/distill/ofelia run-reporting + watchdog).
THIS is the work-tracking system: epic/feature/task items whose "done" is derived
from CI/merge evidence. Different concern, different tables.
All decisions from the 2026-06-14/15 design walk are folded in below and RESOLVED — Decision 3 (the multi-evidence AND rule) was confirmed 2026-06-17. Design is locked; ready for the TDD implementation plan.
Goal¶
A personal, agent-maintained work tracker (epic/feature/task hierarchy) where the
hardest problem — keeping status trustworthy when a coding agent, not a human, is
the maintainer — is solved by making terminal "done" a DERIVED consequence of
tamper-resistant evidence (a merged PR + a green CI test the agent cannot edit),
never an agent-asserted flag. It also records the planning discipline now codified
in ~/.claude/PLANNING.md (vertical slice + acceptance criterion + one PR).
Core thesis (from the research)¶
Agents falsely claim completion at first-class rates (~21% of MAST multi-agent failures are verification failures) and actively game the signal they're trusted on (delete/monkey-patch tests to force green). Therefore: a test-gated status is only trustworthy if the agent CANNOT edit the oracle. The fix is a deterministic checker, outside the agent's write reach, that sets terminal status from external evidence — exactly what GitHub's merge-closes-issue and spec-kit's test-first gate operationalize.
v1 scope (minimal, in Argus)¶
One table, one checker, one rollup view, one read-only UI. Deliberately small.
itemstable — epic/feature/task viatype+parent_id.item_events— append-only audit log (every lifecycle change + verify/un-verify).- An evidence-checker task (deterministic; same shape as existing Argus tasks)
that reads CI truth from
gitea.db action_runand setsverified. - A rollup SQL view (parent done iff all non-optional children verified).
- A read-only
/ui/taskspage (mirrors/ui/parked).
Deferred (do NOT design now): dependency/blocks edges + ready-queue (v2),
bug-as-distinct-type with regression-test gate (v3), the "discovered-scope"
intake, decomposition automation, anything LLM.
The load-bearing details (RESOLVED 2026-06-15)¶
Expensive to retrofit; decided in the design walk.
- Stable human-readable ID — RESOLVED: per-project prefix.
ARGUS-<n>,TURFTRACK-<n>, etc. — prefix + per-project monotonic number, embedded in branches/PR titles/commits. Schema carries aprojectfield + a per-project counter (counters table or per-project sequence), not one global sequence. - Evidence is structured AND bound — RESOLVED.
{kind, repo, pr_number, commit_sha, test_or_job}, machine-checkable (not a freetext URL). Anti-gaming rule: the checker counts evidence ONLY if the PR references the item ID (else any green PR could be attached). lifecyclehas no "done" — RESOLVED. Agent-writable lifecycle =backlog | ready | in_progress | blocked | cancelled. Terminal truth lives only inverified(checker-set). Keystone: if lifecycle could say "done," we're back to asserted status.- Append-only
item_eventsfrom day 1 — RESOLVED. Every lifecycle change + verify/un-verify, with the evidence snapshot. Trust-first; retrofitting is lossy. - Required
whyon every item — RESOLVED (added 2026-06-15). A first-classwhyfield (rationale/context: why this needs doing), required on epic, feature, AND task — distinct frombody(the how). Withacceptance(tasks) this is a two-pronged admission gate: state why it matters, and (for tasks) how it's verified — structurally blocking vague/ad-hoc items.
Evidence tiers — how non-code tasks verify (RESOLVED 2026-06-15)¶
verified always requires at least one piece of evidence the building agent
cannot unilaterally produce. The bound kind depends on task nature; the system
records WHICH tier verified it, so the trust level is always visible:
- Tier 1 — external system (strongest):
ci_run(named test green on the Forgejo runner — the real gate in the autonomous loop, since the agent merges its own PRs),pr(merged to default branch),deploy_log/healthcheck (gatus 200, Komodo deploy success) for ops tasks. Agent-independent. - Tier 2 — artifact exists (medium):
artifact— a file/doc committed at a path; the checker verifies existence deterministically (git/fs), not quality. Artifact-only tasks must pair with a Tier-1 or Tier-3 gate. - Tier 3 — human approval (escape hatch):
approval— a human marks it done via the UI; the agent can NEVER self-approve. For decisions, physical tasks, anything with no digital signal. Recorded initem_events(who + when). The UI needs an Approve action (reuses the parked-UI Retry pattern: HX-Request request, CSRF fence, event row).
Verification rule — RESOLVED 2026-06-17 (Decision 3):
verified iff ALL bound evidence passes (AND across the evidence the task
declares). No weighting — binary "all required evidence present and passing, or
not done," to avoid the soft/gameable partial status the design exists to remove. A code task binds CI-green (+ PR-merged); a doc task may
bind only approval; an ops task binds a healthcheck. If a PR is merged but its
bound test is absent/red, the task is NOT verified. This moves authority from the
agent flipping feature_list.json to the checker reading gitea.db.
Per-type contract¶
One record type, shared columns, but required/meaningful fields differ by type.
Only tasks carry their own acceptance + evidence; epic/feature done-ness is
DERIVED from children.
| field | epic | feature | task |
|---|---|---|---|
| id / type / parent_id / project | yes | yes (->epic) | yes (->feature) |
| title | the outcome | the visible behavior | the vertical slice |
| why (REQUIRED) | why this milestone | why this behavior | why this slice |
| body | scope (in/out) | what behavior / detail | approach / notes |
| acceptance | derived | optional integration check | REQUIRED (testable criterion) |
| evidence | derived | rolls up | REQUIRED at done (tiered — see above) |
| steps[] | — | — | optional checklist (agent-maintained, NOT evidence-gated) |
| lifecycle | derived | derived | agent-writable |
| verified | rollup | rollup | checker-set |
| priority | yes | yes | yes |
Subtasks — RESOLVED 2026-06-15: NOT a durable row type. Within-task
decomposition lives as an optional steps[] checklist field ON a task (the
agent's plan/progress for one PR), explicitly NOT evidence-gated and NOT rolled
up. Only the task's verified is load-bearing. The sharp test: would this step
be its own PR with its own green test? If yes → it's a sibling task (the
hierarchy handles it); if no → it's a steps[] checklist item. This keeps the
trust model at the task level and avoids reintroducing agent-asserted status
below it.
What each level's detail holds:
- Epic = milestone contract: why (rationale) + capability + explicit scope
in/out. No own acceptance; done when its features are.
- Feature = one visible behavior, a vertical slice; why + the behavior.
Done when its tasks verify. If small enough to be one PR, it IS a single task —
don't force a split.
- Task = the leaf, the only strict one: title + why + acceptance
(required) + evidence + optional steps[] + verified. One task = one PR =
one green check. This is feature_list.json grown up.
Worked example (dogfooding this very system)¶
EPIC ARGUS-M6 "Trustworthy task system"
body: Outcome — track epic/feature/task work where "done" is DERIVED from
CI/merge evidence, not asserted.
In scope: items table, evidence checker, rollup view, read UI.
Out of scope: dependencies, bug-type, decomposition automation.
status: 0/4 verified (rolls up)
FEATURE ARGUS-M6-F1 "Evidence-derived task status"
body: A task reaches verified only when its PR is merged to main AND its
named test is green, set by a checker outside the agent's write reach.
TASK ARGUS-101 "items + item_events schema"
why: every other field hangs off this table; ship it first so
the checker and rollup have something to write to.
acceptance: migration creates items + item_events; TestItemsSchema green in CI
evidence: { kind: ci_run, repo: runonyourown/argus, commit: <sha>, test: TestItemsSchema }
steps: [ ] write failing TestItemsSchema
[ ] write migration [ ] run suite green
lifecycle: in_progress verified: false (checker-set)
TASK ARGUS-102 "verifier reads gitea.db action_run"
acceptance: flips verified=true ONLY when PR merged-to-main AND named
run=success AND the PR references the item id; TestVerifierGitea green
lifecycle: ready verified: false
TASK ARGUS-103 "rollup SQL view (parent done iff all non-optional children verified)"
acceptance: TestRollupView green — reverting a child PR un-dones the parent
lifecycle: backlog verified: false
The tree IS the plan and the tracker: read top-down to plan; leaves are the
PR-sized units; status rolls up so an epic shows 0/4 verified at a glance.
Authoring vs reading (no dual source of truth)¶
The DB is canonical (the checker writes verified there; queries are
deterministic). What you read/plan against is a generated tree view — short by
default (ARGUS-M6 0/4 · F1 0/3 · ARGUS-101 in_progress), expand a node for
body/acceptance/evidence. Authoring goes through one thin interface (CLI/MCP/UI)
that writes the DB; the readable TASKS.md-style tree is generated, never
hand-edited — avoiding the "same status in two places" failure the research flags.
This is the existing Argus pattern (DB canonical, markdown is an export).
Presentation layer — visual plan / visual recap (roadmap, fed from the DB)¶
The DB is the state/verification engine; the visual layer is how a human reads
and approves it. Aaron wants this to be visual and approvable, not a plain
text tree. Prior art studied 2026-06-15: BuilderIO/skills (MIT,
npx @agent-native/skills@latest add) — two skills that are a near-match for the
presentation layer we want:
/visual-plan— turns a plan into an interactive MDX artifact with diagrams, file maps, annotated code, open questions, UI/prototype review, "scannable, commentable, intuitive enough for a human to approve before code changes start." This is a richer form of our "generated tree view," and its approve-before-coding gate maps directly onto our Tier-3approvalevidence./visual-recap— turns a branch/PR diff into MDX with annotated diffs, diagrams, API/schema summaries, file maps, UI state, review notes; a GitHub Action auto-generates one per PR. For Argus this is the rendered form of a task's PR/CI evidence — the "what actually changed" companion toverified. (We'd wire it via a Forgejo Action.)- Viewer: the "Agent-Native plans app" (BuilderIO/agent-native, MIT, TS, Drizzle/Nitro — self-hostable, "any DB, any host"). But it's a full agent-native app framework (needs ANTHROPIC_API_KEY for its app features), far heavier than a plan viewer.
STEAL: the MDX section structure (diagrams / file-maps / annotated / open
questions), approve-before-coding, and auto-recap-per-PR. AVOID: adopting the
agent-native viewer wholesale (heavyweight, AI-key deps) — Argus's hub already
serves its own HTML/UI, so render our own MDX/HTML from the DB; and their
informal approval (human just reads) — we keep the structured approval
evidence (recorded, who+when, agent-can't-self-approve).
Sequencing: v1 ships the engine + a simple read-only /ui/tasks. The rich
visual-plan/visual-recap render is v2 presentation, generated FROM the DB
(the data model already supports it). /visual-plan can also be used standalone
today as a planning aid while Argus handles tracking. Distinct concern from the
verification engine; does not affect Decision 3.
Tamper boundary (the most important hardening)¶
Terminal status is derived from CI evidence (gitea.db action_run on the Forgejo
runner), NOT the agent's local go test. The checker and the verified column
are writable only by the checker process, not the building agent. This is what
turns the existing feature_list.json pattern from a soft prompt rule into a real
gate. The agent may set lifecycle and attach evidence; it may never set verified.
Where it lives / relationships¶
- Argus, not
track: the CI evidence, run-store, no-show watchdog, and the agent loop already live here; bolting evidence-derived status onto Argus is less work than merging two products. - Complementary to the M3 cron tasks-module and to the memory hub — different concern; no shared tables.
Decisions — all RESOLVED¶
per-project IDs (#1), structured+bound evidence (#2), lifecycle-has-no-done (#3),
append-only item_events (#4), required why, evidence tiers + approval for
non-code tasks, subtasks-as-steps[]-checklist (not a row type), and the
multi-evidence rule (Decision 3, confirmed 2026-06-17): verified = AND across
all bound evidence. Design is locked.
Next step¶
Write the TDD implementation plan (migration + failing test per task) under
docs/plans/, starting with ARGUS-101 (items + item_events schema), and
reconcile/retire references so the M3 cron-tasks plan and this work-tracking
system are clearly distinct. The visual plan/recap presentation layer is tracked
as v2 (see Presentation layer).