A code-driven walker that prints exactly one open task at a time and waits. You complete it, update it, reassign it, or skip it — then the next one appears. Batching is structurally impossible. Delete is not a key the walker accepts. Every action is logged. Run it once a day; never see a task graveyard again.
At the prompt:
aaicase> process my tasks
The terminal switches to a focused walker UI. One task per screen. The card shows the task description, the case (with name, not just an ID), who it’s assigned to, the due date, the priority. Below that, the eight options. You press one letter. The walker writes to Merus, verifies, logs, and shows the next task.
You repeat that until tasks are done or you press Q.
bin/aai-task-walk.mjs) that owns the terminal until you quit. The Claude agent loop is not running during the walk. Routing, formatting, option selection, and write decisions are all in deterministic JavaScript.
This is intentional. The whole problem with most AI-driven task tools is they batch: they read your task list, write a summary, propose seven actions, and ask you to approve. By the time you’ve approved or denied each one, you have no idea whether anything is actually correct, and the model has already moved on to summarizing the next batch.
This walker is the opposite. The loop variable is literally for (let i = 0; i < tasks.length; i++) — one iteration, one task. Batching is not a configuration option the walker happens not to use. It is structurally impossible.
The model is involved in exactly three places: detecting the trigger phrase (in REPL code, not a model decision), explaining things if you ask a question instead of choosing an option (via a no-tools sub-call — it cannot write anything), and nowhere else.
The walker prints these and only these:
| Key | Action | What happens |
|---|---|---|
| C | Complete | Writes completed=1, re-fetches the task, verifies complete:true. If not verified, the walker stops — it will not silently move on after a failed write. |
| K | Keep | No write. The task stays as-is and the walker advances. Used when a stale task is intentionally being preserved (e.g. an open Lit task waiting on a defense response). |
| S | Skip | Same effect as Keep, different intent (“don’t want to deal with right now”). Logged separately in the audit so you can find what you ducked. |
| R | Reassign | Shows the firm directory pulled live from /users/index. You pick by number or name. The walker shows a preview, waits for yes, writes user_id=NEW_ID, verifies, logs. |
| U | Update | Plain-English edit: due date, priority, or description. Type “due 2026-06-15, priority high” and the walker parses, previews, confirms, writes, verifies. |
| D | Review docs | Fetches activities for the case, shows uploads with dates and descriptions. No write. You go back to the options. |
| A | Review activities | Same fetch, shows the last 15 activities with tags. No write. You go back. |
| F | Switch user | Re-runs the user-filter picker, re-fetches the task list under the new filter, restarts the walk. |
| Q | Quit | Exits the walker, returns to the aaicase REPL. |
d or delete, the walker responds: “Delete is not an option. Use C (complete) — the record stays in the audit trail.”
A completed task is auditable. You can run a report, see when it was closed, see who closed it, see what it said. A deleted task is gone. There is no investigation possible. If a task was created in error, complete it with a note — the audit trail remains intact.
This is the rule across AAI: integrity is restored by moving records to their correct state, not by erasing them. The Merus task table is a contemporaneous record — treating it like a scratchpad you can clear is exactly the kind of habit that hurts at a State Bar inquiry.
The walker is multi-user-aware. At startup it asks:
~/.aaicase/config.json./users/index. Useful for covering someone’s tasks during PTO.The card header always shows the active filter:
Filter: SampleParalegal (14 tasks)
Press F mid-walk to switch. If you ever have to ask “whose tasks am I looking at?” the card header has failed at its job — that’s the rule.
Before rendering each card, the walker re-reads from disk and re-fetches from Merus:
skills/_approval-flow.md).~/.aaicase/queue/bindings.json, message-bindings.json)./tasks/view/TASK_ID.This is shown as a thin gray status line under the card:
[fresh-load] skill ✓ bindings 42 audit 50
If any of those load steps fail (skill file deleted, queue dir gone, audit log unreadable), the walker still proceeds — the load is best-effort, not a hard requirement. The re-fetch of the task itself is hard. If the task came back complete in the meantime, the walker prints “already complete — skipping” and moves on. That catches concurrent edits.
The walker never shows you a bare case_file_id or user_id. The card always reads:
Case: Sample, Alex v. Sample County Agency (#74)
Assigned: Sample Associate
Due: 2026-06-15
Not:
case_file_id: 74
user_id: [internal-id]
The walker re-fetches /caseFiles/index per task to build a case-name map, falling back to /caseFiles/view/{id} for any case_id not in the index (typically closed or archived cases). Same pattern for /users/index → user-name map. If a name lookup fails, the card surfaces the ID along with the failure reason — you should never have to mentally translate an integer to a person mid-walk.
Suppose you type why is this assigned to her. That’s not one of the options. The walker does not silently skip, error, or guess. It dispatches your input as a question to a no-tools Claude sub-call with the task context, gets a 1–4 sentence answer, prints the answer, then re-shows the card and re-issues the prompt.
The sub-call has no write tools. It can read the task, read the activity history, explain what it sees. It cannot modify the task, the case, the audit log, or anything else. You always come back to the same card, the same eight options, and a clearer head about what to do.
This is the model’s contribution to the skill: explanation on demand, never silent action.
Every action writes one line to ~/.aaicase/audit.log:
{"ts":"2026-05-18T18:00:00Z","action":"task-complete","task_id":"[ID]","case_id":"74"}
{"ts":"2026-05-18T18:01:30Z","action":"task-update","task_id":"[ID]","case_id":"719","changes":{"Priority":"HIGH","Due":"2026-06-01"}}
{"ts":"2026-05-18T18:02:00Z","action":"task-skip","task_id":"[ID]","case_id":"654"}
One line per write. JSON Lines so it’s greppable. The walker can also undo recent writes — aai-undo reads the audit log, finds the entry by label and timestamp, and reverses it.
Some tasks Merus generates automatically are nearly always noise: REVIEW (auto…), VERIFY (auto…), Review filed orphan. The walker shows them anyway — sometimes they’re real — but the morning brief and status counts filter them out so your “14 open tasks” number reflects the work that actually requires attention, not the auto-generated chatter.
The narrowed noise filter is documented in skills/status.md and is intentionally conservative. False positives (filtering a real task) are worse than false negatives (showing an auto-noise task), so the regex matches only the prefixes that have never produced a real task in practice.
If you’re walking the task list and someone else completes the same task — through the Merus UI, another aaicase session, or another flow — the walker’s per-iteration re-fetch of the task picks that up. The card never appears for an already-complete task; the walker just prints “already complete — skipping” and moves on.
The same protection covers reassignments and edits made between iterations. The walker always shows the current task state, not the state it inventoried at startup. This is a deliberate trade-off: more network calls per iteration, but no possibility of acting on stale data.
The REPL surfaces the error and stops. The agent does not try to emulate the walker by walking tasks itself — that defeats the entire architecture. Most common cause: an aaicase upgrade that didn’t finish; re-run /update or reinstall.
Name lookup failed — usually a transient API issue on /caseFiles/index or /users/index. Press F to restart the walk; the lookups re-fetch fresh.
You can’t. Complete it. The record stays in the audit trail and you can later see exactly what it said and when it was closed. If the task is genuinely garbage — created by accident, duplicates of a real task, autogen noise — complete it. The completion is the cleanup.
Check the filter line at the top of the card. If it says “Everyone’s” or another user’s name, you’re seeing their queue. Press F to switch.
The walker is stateless — there’s no “saved progress.” Just re-run process my tasks; it picks up the current open task list. Anything you completed during the prior walk is still completed.
Run aai-undo. It reads the audit log and lets you reverse recent writes by label and timestamp. Completes can be re-opened, reassignments can be reverted, updates can be rolled back.
Part of AAI for MerusCase — code-guarded AI case intelligence for California Workers’ Comp attorneys.