Skip to content
Closed
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ Subdirectories contain specialized files that extend these rules.
- **MUST** run `bun run typecheck && bun run lint && bun run test && bun run build` before opening a PR
- **MUST NOT** commit secrets, API keys, or tokens

### Planning and Durable Knowledge (MUST)

- **MUST** inspect applicable active plans, accepted decisions/ADRs, relevant research, current architecture documentation, linked Issues, and package-local instructions before substantial implementation work.
- **MUST NOT** silently contradict an accepted durable decision. If implementation requires a material change, update the governing plan/decision record and obtain any required approval before proceeding.
- **MUST** keep non-trivial implementation planning in repository artifacts rather than only in chat history.
- **MUST** honor plan approval gates. Do not begin implementation while a governing plan is `Draft`, `Awaiting implementation approval`, or `Blocked`.
- **MUST** distinguish a required blocked prerequisite from consciously deferred scope; do not bypass blockers by relabeling them deferred.
- **MUST** update `docs/DECISIONS.md` and any applicable ADR when a durable decision is accepted or superseded. ADRs normally stay in place and use status/links to preserve decision history.
- **MUST** reconcile durable project knowledge before considering implementation complete: resulting architecture, decisions, research, documentation, acceptance criteria, blockers, and remaining Issues must match reality.
- **MUST** update current architecture documentation when implementation materially changes system/module boundaries, persistent state, interfaces, runtime topology, or major integration relationships.
- **MUST** treat artifacts under archive paths as historical context, not authoritative current state, unless verified against current code, decisions, architecture, and active plans.
- **SHOULD** use `docs/plans/` for non-trivial active plans, `docs/research/` for reusable research, and `docs/decisions/` for standalone ADRs when no more specific established convention applies.

### Plugin Development (MUST)

Scope: V1 packages. The two V2 ports use the Promise API instead; see the V2 boundary below.
Expand Down
103 changes: 103 additions & 0 deletions docs/DECISIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Decisions

This ledger records durable repository and product decisions. Small decisions live here directly; larger architectural decisions link to standalone ADRs under [`docs/decisions/`](./decisions/).

## D-001 — Auto Advisor uses a dual-path architecture

**Status:** Accepted
**Scope:** `@capybearista/opencode-auto-advisor`
**ADR:** [ADR-0001](./decisions/0001-dual-path-auto-advisor.md)

Explicit Executor-triggered consultation and experimental automatic routing converge on one fresh, stateless Advisor service that receives the actual relevant Executor context.

---

## D-002 — Automatic routing is experimental in v1

**Status:** Accepted
**Scope:** Auto Advisor automatic routing
**ADR:** [ADR-0002](./decisions/0002-experimental-automatic-routing.md)

Automatic routing ships behind `off | observe | active` modes. `off` is the default; `observe` requires telemetry; `active` remains experimental.

---

## D-003 — Automatic advice uses system-role context in v1

**Status:** Accepted
**Scope:** Auto Advisor advice delivery
**ADR:** [ADR-0003](./decisions/0003-automatic-advice-delivery.md)

Explicit consultation returns a genuine tool result. Automatic consultation uses system-role context through `session.context`, with plugin-managed same-turn lifetime, until OpenCode exposes a suitable native durable instruction API to plugins.

---

## D-004 — The explicit Advisor tool accepts no arguments

**Status:** Accepted
**Scope:** Auto Advisor public tool API

The Executor invokes `advisor()` with an empty object input. The plugin owns context collection; the Executor does not pass a question or context summary.

---

## D-005 — An Advisor model must be configured

**Status:** Accepted
**Scope:** Auto Advisor configuration

The plugin requires an Advisor model configuration and does not silently fall back to the Executor model. The configured model need not be described as objectively stronger.

---

## D-006 — Use native V2 plugin options

**Status:** Accepted
**Scope:** Auto Advisor configuration

Configuration uses OpenCode V2 `plugins[].options`. No plugin-specific sidecar configuration file is introduced.

---

## D-007 — v1 Advisor consultations are fresh and tool-free

**Status:** Accepted
**Scope:** Advisor behavior

Every consultation is stateless, returns plain-text advice, and has no independent repository or network tools.

---

## D-008 — v1 Jev providers are TypeSafe AI and OpenCode Zen

**Status:** Accepted
**Scope:** Experimental automatic routing

v1 supports direct TypeSafe AI and OpenCode Zen only. Provider-specific Evaluation details remain isolated behind the Jev adapter.

---

## D-009 — Automatic consultation budget is configurable

**Status:** Accepted
**Scope:** Automatic routing policy

The initial default is one automatic consultation per user turn. Explicit `advisor()` calls do not consume the automatic budget.

---

## D-010 — Telemetry is opt-in except in observe mode

**Status:** Accepted
**Scope:** Routing telemetry

Telemetry is disabled by default. `observe` requires durable telemetry because its purpose is to collect routing evidence without changing Executor behavior.

---

## D-011 — Auto Advisor is V2-only and publishes on npm latest

**Status:** Accepted
**Scope:** Package compatibility and release policy

`@capybearista/opencode-auto-advisor` is an OpenCode V2-only package with no V1 line. Its npm distribution channel is `latest`, not `opencode` or `opencode2`. Release tooling must preserve host-version separation independently of dist-tag choice.
17 changes: 17 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ The root [README](../README.md) and package READMEs describe current installatio
| [output-styles/claude-output-styles.md](./output-styles/claude-output-styles.md) | Upstream reference | Snapshot of Claude Code output-style docs. Background for the output-styles plugin, not a statement of this repo's behavior. |
| [ram-monitor/post-mortem-v1.0.0.md](./ram-monitor/post-mortem-v1.0.0.md) | Package note | What broke and what fixed it during ram-monitor 1.0.0 stabilization. |
| [ram-monitor/codex-comparison.md](./ram-monitor/codex-comparison.md) | Package note | Prompt-structure comparison between the official Codex plugin and this repo's review plugin. |
| [DECISIONS.md](./DECISIONS.md) | Active | Durable project decisions. Small accepted decisions live in the ledger; larger architectural choices link to standalone ADRs under `decisions/`. |
| [plans/opencode-auto-advisor.md](./plans/opencode-auto-advisor.md) | Draft plan | Governing product/technical plan for the proposed OpenCode Auto Advisor plugin. |
| [research/claude-code-advisor.md](./research/claude-code-advisor.md) | Current research | Claude Advisor behavior, tool surface, persistence, and prompt evidence. |
| [research/opencode-v2-advisor-runtime.md](./research/opencode-v2-advisor-runtime.md) | Current research | OpenCode V2 context, generation, tool timing, and automatic-advice delivery capabilities. |
| [research/opencode-v2-jev-evaluation.md](./research/opencode-v2-jev-evaluation.md) | Revalidate before implementation | Experimental Evaluation/Jev routing capability and provider constraints. |

## Generated prompt sources

Expand All @@ -27,6 +32,18 @@ The V1 prompt-sync workflow stays on. There is no V2 prompt-inheritance port.

Provenance notes ship with the skill where they exist. The Biome skill carries its own `LICENSE.txt` and changelog. Do not invent ownership or license claims for the rest.

## Planning and durable project knowledge

Non-trivial work may use:

- `DECISIONS.md` plus `decisions/` for durable choices and ADR history;
- `research/` for findings likely to matter during implementation or maintenance;
- `plans/` for active non-trivial project plans.

Plans describe intent and constraints rather than current implemented architecture. GitHub Issues remain the execution/status system. Research is not archived merely because a current task stops using it; mark it for revalidation or supersession when its facts or applicability change. ADRs normally remain in place and use status to record lifecycle.

Completed or cancelled plans may later move to `archive/plans/` after current architecture, durable decisions, research, and unresolved execution work have been reconciled.

## Conventions

Dated documents retain their scope banners and existing paths. Prefer links to current installation instructions rather than copying them; the V1 guide is the explicit compatibility reference for frozen releases. Update navigation and inbound links together if documents move.
83 changes: 83 additions & 0 deletions docs/decisions/0001-dual-path-auto-advisor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# ADR-0001: Use a dual-path Auto Advisor architecture

## Status

Accepted

## Context

A Claude Code-style Advisor is useful when an Executor recognizes that it needs independent judgment. That explicit pattern has a self-routing weakness: the same Executor that is uncertain or mistaken must recognize that consultation is warranted.

A continuous parallel watchdog could independently intervene, but it adds persistent reviewer state, asynchronous races, duplicated investigation, stale advice, interruption semantics, and substantial orchestration complexity.

The project needs independent routing without turning the Advisor into a continuously running second agent.

## Decision

Auto Advisor uses two consultation paths that converge on one shared Advisor service:

```text
┌──────────────┐
explicit advisor() ─────►│ │
│ Advisor │
automatic route ────────►│ Service │
│ │
└──────┬───────┘
│
fresh configured inference
│
▼
Executor
```

The explicit path is triggered by the Executor calling zero-argument `advisor()`.

The automatic path evaluates the Executor state at safe primary model-dispatch boundaries and may consult the same Advisor before the next Executor inference proceeds.

The Advisor service:

- receives plugin-collected actual Executor context rather than an Executor-authored summary;
- uses a configured model;
- creates a fresh stateless inference for every consultation;
- has no persistent private Advisor conversation;
- has no independent tools in v1;
- returns concise plain-text judgment.

Automatic routing logic is kept outside the Advisor service.

## Alternatives considered

### Explicit-only Advisor

This reproduces the useful Claude Advisor mechanism but leaves consultation entirely dependent on Executor self-awareness.

Rejected as the complete product architecture because independent routing is a core project goal.

### Persistent autonomous watchdog

A background reviewer could observe the Executor continuously and push unsolicited guidance.

Rejected because it creates substantially more lifecycle, synchronization, stale-context, cost, and interruption complexity than required. The project intentionally routes between Executor inferences instead of supervising token streams continuously.

### Separate explicit and automatic Advisor implementations

Separate services could tailor behavior to each trigger.

Rejected because both paths are meant to request the same kind of independent judgment over the same evidence. Duplicating Advisor personalities or context logic would create drift.

## Consequences

- Explicit and automatic consultation share context capture and Advisor behavior.
- Automatic routing can evolve or be replaced without changing the Advisor.
- The design avoids mid-generation interruption.
- The Executor can still override Advisor guidance when evidence warrants it.
- Fresh consultations reduce anchoring from a persistent reviewer history.
- Context fidelity becomes a critical validation requirement.

## Supersedes

None.

## Superseded by

None.
71 changes: 71 additions & 0 deletions docs/decisions/0002-experimental-automatic-routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# ADR-0002: Treat automatic routing as experimental in v1

## Status

Accepted

## Context

OpenCode V2 provides a synchronous `session.context` hook immediately before provider dispatch, which is a suitable safe boundary for automatic routing.

The initial routing implementation uses OpenCode's Evaluation/Jev capability. That API is published under an experimental surface whose contract is explicitly expected to evolve. Independently of API stability, the project does not yet have empirical evidence that Jev's routing precision justifies the latency and cost of evaluating materially new Executor dispatches.

The plugin needs the automatic-routing architecture in v1 without presenting an unvalidated router as stable/default behavior.

## Decision

v1 includes automatic routing behind three modes:

- `off` — no automatic routing; explicit `advisor()` remains available.
- `observe` — Jev evaluates routing opportunities and records the assessment and hypothetical deterministic policy result, but does not invoke the Advisor or alter Executor context.
- `active` — Jev evaluates routing opportunities and deterministic policy may trigger an automatic Advisor consultation.

`off` is the default.

Telemetry is required in `observe`.

Automatic routing remains documented as experimental in v1.

The stable domain depends on an `AdvisorRouter` abstraction and a normalized router assessment. OpenCode Evaluation types, System One types, confidence metadata, and provider-specific structures remain inside the Jev adapter.

v1 Jev provider scope is limited to:

- direct TypeSafe AI;
- OpenCode Zen.

Automatic consultation budgeting is configurable, initially defaulting to one automatic consultation per user turn.

## Alternatives considered

### Enable automatic routing by default

Rejected because both the Evaluation API contract and routing quality are insufficiently validated.

### Ship explicit Advisor first and add routing in a later product version

Rejected because independent routing is a core product requirement and the surrounding architecture can be established safely now. The implementation may sequence explicit foundations before routing, but v1's product architecture contains both paths.

### Build deterministic pre-routing heuristics instead of Jev

Rejected as the primary approach because it would duplicate the judgment the routing model is intended to provide and introduce premature policy complexity. Deterministic policy still governs whether a model estimate causes a consultation.

### Couple stable interfaces directly to OpenCode Evaluation types

Rejected because the Evaluation contract is experimental and likely to change.

## Consequences

- v1 can collect routing evidence without changing Executor behavior.
- Jev can be replaced later without rewriting the Advisor service.
- Provider/API churn is concentrated in one adapter boundary.
- `observe` introduces a clear calibration path before stronger stability claims.
- Automatic routing still incurs extra inference latency/cost in `observe` and `active`.
- The supported OpenCode/Evaluation range must be explicitly tested and revalidated.

## Supersedes

None.

## Superseded by

None.
77 changes: 77 additions & 0 deletions docs/decisions/0003-automatic-advice-delivery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# ADR-0003: Deliver automatic advice as plugin-managed system context in v1

## Status

Accepted

## Context

Explicit `advisor()` consultation naturally produces a genuine tool call and tool result that persist in normal conversation history.

Automatic routing is different: the Executor did not call `advisor()`. Fabricating a tool invocation would make the transcript claim an action the Executor never took.

OpenCode V2 exposes `session.synthetic` to plugins, but synthetic messages are lowered to user-role model messages. Advisor guidance should not impersonate the user.

OpenCode V2 also has durable session instruction-entry machinery that is semantically appropriate for privileged chronological updates, but the current Promise and Effect plugin contexts do not expose that API. Directly bypassing the supported plugin surface would couple v1 to an intentionally unexposed API.

The public `session.context` hook can mutate the outgoing request with system-role context, but those mutations are request-local rather than native durable transcript entries.

## Decision

Explicit consultation uses the real tool-call/tool-result path.

Automatic consultation in v1:

1. generates advice before the waiting primary Executor request proceeds;
2. stores the applicable automatic review in plugin-owned session/turn state;
3. injects that advice as system-role context through `session.context`;
4. reinjects it on relevant continuations during the same user turn;
5. lets a newer automatic review supersede the prior active review;
6. expires the active review on normal new user input.

The plugin must not:

- fabricate an `advisor()` call;
- deliver Advisor advice with `session.synthetic`;
- depend on the currently unexposed instruction-entry API.

The design should keep advice delivery replaceable so that a future OpenCode version can use native durable instruction entries if they become part of the supported plugin API.

## Alternatives considered

### Fabricate an Advisor tool call/result pair

Rejected because it falsely attributes the consultation decision to the Executor.

### Use session.synthetic

Rejected because OpenCode lowers synthetic messages to user-role context, which gives Advisor guidance the wrong semantic authority.

### Call the hidden/experimental instruction-entry endpoint directly

Rejected for v1 because normal plugins do not receive that capability through the supported Promise or Effect plugin context.

### Inject advice only once

Rejected because tool continuations cause later model requests in the same user turn; the Executor must continue to see the applicable review.

### Reinject all historical automatic advice forever

Rejected because it creates unbounded context growth and increases the risk of stale guidance.

## Consequences

- Automatic advice has appropriate system authority without falsifying transcript history.
- The plugin owns the lifetime of active automatic advice.
- Automatic advice is not natively persisted as an ordinary conversation message in v1.
- Same-turn state/expiry behavior requires explicit tests.
- Compaction does not require replaying all historical reviews; only the currently applicable review is reinjected.
- A future native delivery mechanism can replace the v1 delivery implementation without changing Jev or AdvisorService.

## Supersedes

None.

## Superseded by

None.
Loading