avibe-bot/avibe

harness: vibe watch list dumps every watch unbounded (5.7 MB / 1149 rows) — no default filter, no pagination

Closed

#1,011 opened on Jul 25, 2026

 (0 comments) (0 reactions) (0 assignees)Python (75 forks)github user discovery
buggood first issue

Repository metrics

Stars
 (489 stars)
PR merge metrics
 (Avg merge 4h 21m) (286 merged PRs in 30d)

Description

Summary

vibe watch list returns every stored watch definition with no default state filter and no pagination. On a long-lived install this is now 5.7 MB of JSON for 1149 watch definitions, of which only 2 are actually live.

This is primarily an agent-facing defect. The Harness system prompt directs agents to vibe watch list to inspect state before creating or changing a watch, and a 5.7 MB tool result does not fit in a context window. --brief does not bound it either — it only drops to 1.3 MB.

Measured on this install (2026-07-25, avibe master @ 7723afbf):

vibe watch list         : 5,666,441 bytes   (1149 rows)
vibe watch list --brief : 1,340,549 bytes   (1149 rows)
vibe task list          :    47,193 bytes   (4 rows)
vibe runs list          :   190,772 bytes   (paginated, 20 rows)

State breakdown of those 1149 watches: completed 1099, failed 47, running 2, paused 1. The oldest completed rows date back to April.

Root cause: three sibling Harness list commands, three levels of maturity

command default state filter pagination other filters
vibe runs list --page / --limit / --all status, type, agent, backend, session, definition, created-after/before, --q
vibe task list hides completed one-shot, --all to include none none
vibe watch list none none none

The infrastructure already exists and simply was not applied to watch list:

  • _add_pagination_args(parser, help_command=...)vibe/cli.py:210 (adds --page/--limit/--all)
  • _page_request_from_args(args, ...)vibe/cli.py:234
  • storage.paginationPageRequest, make_page_request, page_sequence, pagination_payload, DEFAULT_PAGE_LIMIT
  • _is_completed_one_shot(task)vibe/cli.py:1605

cmd_task_list (vibe/cli.py:2604) gets the default filter from a single line:

if not include_all:
    tasks = [task for task in tasks if not _is_completed_one_shot(task)]

cmd_watch_list (vibe/cli.py:7741) has no equivalent — it loads every watch, sorts, and prints:

def cmd_watch_list(*, brief: bool = False):
    store = _watch_store()
    runtime_state = _watch_runtime_store().load().get("watches", {})
    watches = store.list_watches()
    watches.sort(key=lambda item: (item.enabled is False, item.created_at, item.id))
    watch_payloads = [_watch_payload(watch, runtime_state.get(watch.id), brief=brief) for watch in watches]
    _print_cli_payload("run_definitions", definitions=watch_payloads, watches=watch_payloads)
    return 0

The parser at vibe/cli.py:13017 likewise only registers --brief, while the task parser at vibe/cli.py:12727 registers --all.

Proposed fix

  1. watch list: hide finished one-shot watches by default, mirroring the task rule. The watch equivalent of _is_completed_one_shot is mode == "once" and not enabled and last_finished_at. On this install that alone drops 1099 of 1149 rows.
  2. Apply _add_pagination_args + _page_request_from_args to both watch list and task list, so all three Harness list commands share the runs list pagination contract instead of two of them being unbounded.
  3. Consider a --state filter on watch list (running|completed|failed|paused) to match runs list --status.

Open question: --all currently means two different things

  • runs list --all → return all rows without pagination
  • task list --allinclude the completed one-shot tasks that are hidden by default

If pagination lands on task list / watch list, these two meanings collide on the same flag. Suggest reserving --all for pagination (consistent with runs list) and using an explicit --include-completed or --state for the state filter, with whatever back-compat handling you want for existing task list --all callers.

Related: no retention for finished watch definitions

There is no prune / retention path for completed watch definitions — searching for retention|prune|cleanup|purge under vibe/ returns nothing for watches or task/watch definitions, so the table only grows. Pagination fixes the read path, but unbounded growth of finished one-shot definitions is a separate concern and may deserve its own issue.

Environment

  • avibe master @ 7723afbf
  • macOS, Darwin 25.5.0 (arm64)

Contributor guide