diff --git a/TODO.md b/TODO.md index 4b009f827f..8d5773f108 100644 --- a/TODO.md +++ b/TODO.md @@ -102,9 +102,9 @@ Tasks with no open blockers - ready to work on. Use `/ready` to refresh this lis - Notes: CANCELLED: Reconciled: queued in DB but TODO.md has no #auto-dispatch tag or Dispatch Queue entry (t1180) - [x] t1303 Soft TTSR rule engine — define rules in `.agents/rules/` with `ttsr_trigger` regex in frontmatter (following oh-my-pi's pattern). Implement rule loader that discovers and parses rule files. Rules specify: trigger regex, rule content (correction instructions), repeat policy (once/after-gap). This is the foundation for both soft TTSR (Phase 1) and future real TTSR when OpenCode adds stream hooks. ~1h #feature #harness #auto-dispatch model:sonnet ref:GH#2127 status:deployed pr:#2136 completed:2026-02-22 - [x] t1304 Soft TTSR: wire rules into OpenCode plugin hooks — use three currently-unused plugin hooks: (1) `experimental.chat.system.transform` to inject active rules into system prompt preventatively, (2) `experimental.chat.messages.transform` to scan previous assistant outputs for rule violations and inject correction context into message history, (3) `experimental.text.complete` to detect violations post-hoc and flag them. This gives us preventative enforcement without stream-level interception. ~2h #feature #harness #opencode #auto-dispatch model:sonnet ref:GH#2128 assignee:marcusquinn started:2026-02-22T05:02:07Z status:deployed pr:#2139 completed:2026-02-22 - - [ ] t1305 OpenCode upstream: open issue proposing stream.delta + stream.aborted plugin hooks — research existing OpenCode issues for overlap. Draft issue citing oh-my-pi benchmark data (hashline improved 15 models, 5-68% success rate gains, 20-61% token reduction). Propose two new hooks: `stream.delta` (observe individual streaming tokens, return `{abort?: boolean}`) and `stream.aborted` (handle abort with `{retry?: boolean, injectMessage?: string}`). Reference the streaming loop where hooks would be inserted. Include code sketch showing the modest change needed. NOTE: v1.2.7 did massive Bun→Filesystem migration and v1.2.1 added PartDelta SDK events — re-check processor.ts location and streaming architecture before starting. ~2h #feature #auto-dispatch #harness #opencode #upstream model:opus ref:GH#2129 status:deployed - - [ ] t1306 OpenCode upstream: proof-of-concept PR for stream hooks — fork anomalyco/opencode, implement `stream.delta` and `stream.aborted` hooks in streaming loop. Add plugin trigger calls at `text-delta`, `reasoning-delta`, and `tool-input-delta` cases. Implement abort mechanism via AbortController exposure. Add tests. Reference the issue from t1305. NOTE: v1.2.7 migrated from Bun.file() to Filesystem module across entire codebase — fork from latest main, not our stale clone. ~4h #feature #auto-dispatch #harness #opencode #upstream model:opus ref:GH#2130 [proposed:auto-dispatch model:opus] status:deployed - - Notes: CANCELLED: cancelled by supervisor + - [x] t1305 OpenCode upstream: open issue proposing stream.delta + stream.aborted plugin hooks — research existing OpenCode issues for overlap. Draft issue citing oh-my-pi benchmark data (hashline improved 15 models, 5-68% success rate gains, 20-61% token reduction). Propose two new hooks: `stream.delta` (observe individual streaming tokens, return `{abort?: boolean}`) and `stream.aborted` (handle abort with `{retry?: boolean, injectMessage?: string}`). Reference the streaming loop where hooks would be inserted. Include code sketch showing the modest change needed. ~2h #feature #auto-dispatch #harness #opencode #upstream model:opus ref:GH#2129 pr:#2152 completed:2026-02-22 upstream-issue:anomalyco/opencode#14740 + - [x] t1306 OpenCode upstream: proof-of-concept PR for stream hooks — fork anomalyco/opencode, implement `stream.delta` and `stream.aborted` hooks in streaming loop. Add plugin trigger calls at `text-delta`, `reasoning-delta`, and `tool-input-delta` cases. Implement abort mechanism via AbortController exposure. Add tests. Reference the issue from t1305. ~4h #feature #auto-dispatch #harness #opencode #upstream model:opus ref:GH#2130 completed:2026-02-25 upstream-pr:anomalyco/opencode#14741 + - Notes: Upstream PR anomalyco/opencode#14741 — all 9/9 CI checks pass, MERGEABLE, 267 additions (processor.ts stream hooks + plugin type definitions + 11 tests). Awaiting upstream maintainer review. - [x] t1307 LLM observability: SQLite-based request tracking — create `observability-helper.sh` with SQLite WAL-mode database tracking all LLM requests: model, provider, tokens (input/output/cache read/write), costs (per-category), duration, TTFT (time to first token), stop reason, error messages. Inspired by oh-my-pi's `packages/stats/` system. Incremental parsing with offset tracking. CLI: `aidevops stats [summary|models|projects|costs|trend]`. Wire into existing budget enforcement (t1100). ~3h #feature #observability #auto-dispatch model:sonnet ref:GH#2176 pr:#2137 completed:2026-02-22 - [x] t1308 LLM observability: data collection from OpenCode plugin — extend OpenCode plugin to capture LLM request metadata via `event` hook and `tool.execute.after`. Record: model used, token counts, cost, duration, tool call counts, success/failure. Write to the SQLite DB from t1307. Incremental — each session appends, no full reparse needed. ~1h #feature #observability #opencode #auto-dispatch model:sonnet ref:GH#2177 assignee:marcusquinn started:2026-02-22T05:02:44Z status:deployed pr:#2138 completed:2026-02-22 - [x] t1309 Intent tracing in OpenCode plugin — add intent field to tool call logging. Inspired by oh-my-pi's `agent__intent` pattern where a hidden field is injected into every tool's JSON Schema requiring the LLM to describe its intent in present participle form. In our case, log the intent alongside tool calls in the observability DB (t1307) for debugging and audit trails. v1.2.7 now passes sessionID and callID to shell.env hook — more context available. Evaluate whether `tool.execute.before` hook provides enough context. ~1h #feature #auto-dispatch #observability #opencode model:sonnet ref:GH#2190 assignee:marcusquinn started:2026-02-22T16:37:42Z status:deployed pr:#2153 completed:2026-02-22 diff --git a/todo/tasks/t1306-brief.md b/todo/tasks/t1306-brief.md new file mode 100644 index 0000000000..66554a3d7b --- /dev/null +++ b/todo/tasks/t1306-brief.md @@ -0,0 +1,120 @@ +--- +mode: subagent +--- +# t1306: OpenCode upstream — proof-of-concept PR for stream hooks + +## Origin + +- **Created:** 2026-02-22 +- **Session:** claude-code (interactive) +- **Created by:** ai-supervisor (auto-dispatch from p030 harness plan) +- **Parent task:** t1302 (Harness engineering: oh-my-pi learnings) +- **Conversation context:** Analysis of oh-my-pi's TTSR (Time-To-Stream Rules) pattern revealed OpenCode lacks plugin hooks for real-time stream observation. t1305 opened the upstream issue; this task implements the proof-of-concept PR. + +## What + +Fork anomalyco/opencode and submit a PR implementing two new plugin hooks: + +1. **`stream.delta`** — fires on `text-delta`, `reasoning-delta`, and `tool-input-delta` events during streaming. Plugins can set `output.abort = true` to cancel the stream. +2. **`stream.aborted`** — fires after abort. Plugins can set `output.retry = true` with optional `injectMessage` to retry with corrective context. + +The PR must include type definitions in the plugin package, implementation in `processor.ts`, and tests. + +## Why + +Full TTSR (real-time stream policy enforcement) is blocked without stream-level plugin hooks. The existing `experimental.text.complete` hook only fires after generation completes — too late for real-time content filtering, pattern detection, or cost control. This is the highest-leverage upstream contribution from the p030 harness plan. + +## How (Approach) + +1. Fork from latest `anomalyco/opencode` dev branch (not stale clone — v1.2.7+ migrated from Bun.file() to Filesystem module) +2. Add `Plugin.trigger("stream.delta", ...)` calls in the three delta cases in `packages/opencode/src/session/processor.ts` +3. Add `StreamAbortedError` class for clean abort signaling +4. Add catch-block handling with retry logic (max 3 attempts) and optional message injection +5. Add type definitions to `packages/plugin/src/index.ts` (Hooks interface) +6. Add tests in `packages/opencode/test/session/stream-hooks.test.ts` + +Key files: +- `packages/opencode/src/session/processor.ts` — streaming loop (two locations: reasoning and text delta handlers) +- `packages/plugin/src/index.ts:231` — Hooks interface extension +- `packages/opencode/test/session/stream-hooks.test.ts` — new test file + +## Acceptance Criteria + +- [x] `stream.delta` hook fires on text-delta, reasoning-delta, and tool-input-delta + + ```yaml + verify: + method: manual + prompt: "Check upstream PR anomalyco/opencode#14741 diff for Plugin.trigger calls in all three delta cases" + ``` + +- [x] `stream.aborted` hook fires after abort with retry capability + + ```yaml + verify: + method: manual + prompt: "Check upstream PR anomalyco/opencode#14741 diff for StreamAbortedError catch block with retry logic" + ``` + +- [x] Plugin type definitions added to Hooks interface + + ```yaml + verify: + method: manual + prompt: "Check packages/plugin/src/index.ts diff for stream.delta and stream.aborted type definitions" + ``` + +- [x] Tests pass (11 tests covering StreamAbortedError, hook shapes, retry loop) + + ```yaml + verify: + method: manual + prompt: "Check upstream CI — all 9/9 checks pass including unit (linux) with stream-hooks tests" + ``` + +- [x] All upstream CI checks pass + + ```yaml + verify: + method: manual + prompt: "gh pr checks 14741 --repo anomalyco/opencode — all 9 checks SUCCESS" + ``` + +- [x] PR references upstream issue from t1305 + +## Context & Decisions + +- **v2 branch**: First attempt (`feature/stream-hooks`, PR #14701/#14727) was closed due to stale base. Rebased onto latest dev as `feature/stream-hooks-v2` (PR #14741). +- **AbortController vs custom error**: Chose `StreamAbortedError` custom error class over AbortController exposure — simpler, doesn't require plumbing AbortController through the plugin API. +- **Max retries = 3**: Hardcoded constant `STREAM_ABORT_MAX_RETRIES = 3` to prevent infinite retry loops. +- **Type assertions for tool-input-delta**: Used `(value as any).id` and `(value as any).delta` because the upstream SDK types don't expose these fields on tool-input-delta events yet. +- **Accumulated text tracking**: Added `toolInputAccumulated` record to track accumulated tool input per tool call ID, matching the pattern used for text and reasoning deltas. + +## Relevant Files + +- `packages/opencode/src/session/processor.ts` — main implementation (stream hooks + abort handling) +- `packages/plugin/src/index.ts` — type definitions for new hooks +- `packages/opencode/test/session/stream-hooks.test.ts` — 11 tests (new file) + +## Dependencies + +- **Blocked by:** t1305 (upstream issue — completed, anomalyco/opencode#14740) +- **Blocks:** Full TTSR implementation (real-time stream policy enforcement in aidevops OpenCode plugin) +- **External:** Upstream maintainer review and merge of anomalyco/opencode#14741 + +## Estimate Breakdown + +| Phase | Time | Notes | +|-------|------|-------| +| Research/read | 1h | Study processor.ts streaming architecture, v1.2.7 migration | +| Implementation | 2h | Hook calls, error class, retry logic, type definitions | +| Testing | 30m | 11 unit tests + CI verification | +| PR iteration | 30m | Rebase onto latest dev, address CI flakiness | +| **Total** | **4h** | | + +## Completion Evidence + +- **Upstream PR:** [anomalyco/opencode#14741](https://github.com/anomalyco/opencode/pull/14741) — OPEN, MERGEABLE, 9/9 CI checks pass +- **Upstream issue:** [anomalyco/opencode#14740](https://github.com/anomalyco/opencode/issues/14740) — OPEN +- **Changes:** 267 additions, 2 deletions across 3 files +- **Tests:** 11 new tests in `stream-hooks.test.ts` + all 120 existing session tests pass