Files
cleveragents-core/tools
drew dc96848174 feat(auto-agents): archive entire task-tool subagent tree before DELETE root
Before this change the dispatcher archived only the top-level
wrapper session. The entire ``task``-tool subagent chain
(tier-dispatcher → estimator-implementation / tier-qwen-med →
task-implementor → git-isolator-util) was opaque the moment
the dispatcher's DELETE /session/{id} fired, so post-mortem
analysis of an implementer run was limited to whatever
live-API polling we'd done DURING the run. That's how the
recent optimization round had to work from two cherry-picked
live snapshots of task-implementor and git-isolator-util —
unreliable, only what happened to be active when polled.

Three changes:

1. tools/_opencode_worker.py
   - New helpers: _walk_subagent_descendants (BFS over
     GET /session keyed on parentID), _extract_subagent_agent_name
     (parses OpenCode's "(@<agent> subagent)" title convention),
     _ms_to_iso (epoch-ms to ISO-8601), and _archive_subagent_tree
     (best-effort walk + fetch + write driver; never raises).
   - _archive_session / _build_archive_payload gain optional
     parent_session_id / subagent_title / subagent_depth kwargs.
     When set, the filename includes a ``sub<depth>`` infix
     (e.g. 2026-...__sub01__AUTO-IMP-PR-30__tier-dispatcher__ses_*.json)
     so a directory listing groups every session from one
     dispatcher cycle and reads top-down in BFS order.
   - Archive schema bumped from v1 → v2. New fields are nullable;
     v1 readers (the existing telemetry-console endpoints) treat
     them as missing and remain forward-compatible.
   - run_session_blocking's finally block calls
     _archive_subagent_tree after the root archive write and
     before the root DELETE. Both calls are wrapped in
     try/except so a subagent-walk failure can never mask the
     worker outcome or stop the dispatcher from cleaning up.
   - The dispatcher's existing redact_values list (the Forgejo
     PAT) propagates into every subagent archive too, so a
     ``git clone https://${PAT}@...`` in git-isolator-util's
     bash history is masked the same way the wrapper's prompt is.

2. .opencode/telemetry/server.py
   - _api_archived_sessions listing endpoint now surfaces the
     three v2 fields (schema_version, parent_session_id,
     subagent_title, subagent_depth) in each row payload so a
     future UI render can nest subagents under their wrapper.
     Additive — existing row keys are preserved.

3. tests/auto_agents/test_opencode_worker_observability.py
   - 17 new tests across four classes:
     - TestSubagentTitleExtraction (5): title parser edge cases
     - TestWalkSubagentDescendants (6): BFS order, depth
       annotation, transport-error / malformed-payload paths,
       cycle safety
     - TestArchiveSubagentTree (5): end-to-end orchestration
       including a redaction-propagation test that asserts a
       PAT inside a subagent's bash tool input is replaced
       with <REDACTED>
     - TestEndToEndSubagentArchive (1): drives the full
       run_session_blocking lifecycle with a wired subagent
       descendant and asserts BOTH archives land on disk
   - Existing schema-version assertion updated to v2 + three
     new ``None``-on-top-level field assertions.
   - Two manually-wired archive tests (transport-error,
     timeout) now wire GET /session so the walker doesn't emit
     a spurious warning.

Total auto_agents suite: 1061 passed, 3 skipped (up from 1044).

This is the prerequisite for trustworthy quantification of the
upcoming default-flip of IMPLEMENTER_DISPATCHER_PREFETCH=1 and
IMPLEMENTER_DISPATCHER_PRECLONE=1. With the walker in place,
every cycle now leaves a complete trace on disk that a human
can read bottom-up months later.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 21:21:01 -04:00
..