Problem Statement
When the current integration discovers a file path from a tool call, the matching rule is learned after the model has already selected that tool. In the current delivery flow, the rule may not reach the agent until a later user message. For example, an agent can read a file covered by a path-scoped rule, continue without that guidance, and only receive it on the next turn.
OpenCode v2 exposes a session-context hook immediately before each provider dispatch. The v2 migration should use that boundary so rules discovered during a tool cycle are available before the agent makes its next decision in the same turn.
Solution
During the OpenCode v2 migration, record tool-derived context in the existing per-session state and make the v2 session context hook the single delivery seam for model-visible rules.
- Tool execution hooks capture paths and evaluate tool-event hooks, but do not attempt to mutate a provider request they cannot see.
- The session context hook reevaluates matched rules immediately before each provider dispatch and adds newly matched content to the mutable system or message context.
- Durable delivery is persisted as a synthetic session message without creating an unrelated extra user turn; transient delivery is limited to the current dispatch and is not persisted.
- The earliest possible boundary is the next provider dispatch. A tool call already emitted by the model cannot be retroactively influenced; pre-execution enforcement remains a tool-hook block followed by model retry.
User Stories
- As an agent, I want a rule matched by a path discovered during a tool call to be available before my next model decision, so that I follow the guidance without requiring another user message.
- As a developer, I want tool-derived context to participate in rule delivery during the same turn, so that multi-step agent work follows scoped guidance continuously.
- As a session owner, I want the v2 session context hook to be the earliest model-facing delivery seam, so that rules are delivered immediately before provider dispatch.
- As an agent, I want rules matched by read, edit, write, glob, grep, and shell-related tool context to be delivered consistently, so that the rule system does not depend on which supported tool exposed the path.
- As a developer, I want paths normalized before matching, so that relative, absolute, and equivalent path spellings select the same rule.
- As an agent, I want rules mentioned in the initial user request to retain their current delivery behavior, so that the v2 migration does not regress ordinary first-dispatch guidance.
- As an agent, I want a rule discovered by one tool call to be present in the immediate continuation request, so that I can use it when choosing the next tool or response.
- As a session owner, I want durable rules discovered mid-turn to remain in conversation history, so that the guidance survives later turns, resume, and compaction.
- As a session owner, I want transient rules discovered mid-turn to apply only to the relevant provider dispatch, so that context-specific guidance does not pollute history.
- As a developer, I want durable and transient rule lifetimes to remain distinct during v2 delivery, so that persistence and recomputation semantics stay predictable.
- As an agent, I want content activated by a matching tool hook to be delivered at the same next-dispatch boundary, so that hook-owned guidance is not delayed behind ordinary user input.
- As a safety owner, I want pre-execution blocking hooks to remain enforceable, so that a rule can reject a tool call when guidance must apply before the call runs.
- As an agent, I want a blocked tool call to produce a model-visible failure that permits retry, so that an early rule or policy can affect the next decision without pretending to change the already-issued call.
- As a developer, I want multiple tool calls in one provider response to be merged before the next dispatch, so that all newly matched rules are considered together.
- As a session owner, I want concurrent tool calls that match the same rule to produce one delivery, so that duplicate guidance does not consume context or confuse the agent.
- As a session owner, I want path-derived rule identities and delivery ledger behavior preserved, so that already delivered durable rules are not re-added after every tool cycle.
- As a session owner, I want removed, reverted, or compacted messages to invalidate delivery state correctly, so that a durable rule can be delivered again when it is no longer present in history.
- As an agent, I want rules filtered by agent, model, branch, available tools, project, operating system, command, keyword, and path to be evaluated against the current dispatch context, so that changing session conditions do not leave stale guidance active.
- As a developer, I want a rule-evaluation or persistence failure to preserve pending delivery for a later retry, so that a transient infrastructure error does not silently lose guidance.
- As a session owner, I want rule delivery to happen without an unrelated extra assistant response or user interaction, so that early guidance does not disrupt the normal turn lifecycle.
- As a maintainer, I want the v2 runtime to use one authoritative delivery coordinator, so that matching, lifetime routing, framing, deduplication, and persistence cannot drift between hook paths.
- As a maintainer, I want the migration to preserve existing rule framing and ordering, so that agents receive stable, recognizable guidance regardless of whether it was matched before or during a tool cycle.
- As a maintainer, I want v2 behavior covered by a deterministic session-runner test, so that the specific late-delivery regression remains locked down.
- As a maintainer, I want the migration boundary and earliest-delivery limitation documented in the implementation, so that future changes do not attempt impossible retroactive tool-call delivery.
Implementation Decisions
- The migration targets the OpenCode v2 Promise plugin API, matching the runtime's existing asynchronous design. The runtime will register tool and session hooks through the v2 plugin context rather than retaining a parallel implementation of matching semantics.
- Tool execution hooks are responsible for extracting and normalizing context, recording it in per-session state, evaluating tool-event hooks, and preserving blocking behavior. They are not a direct provider-context mutation seam.
- The v2 session context hook is the single highest delivery seam. It runs before every provider dispatch, consumes the current session state, evaluates the rule snapshot, and routes newly matched content by lifetime.
- The session context hook may mutate the current dispatch's system or message context. Durable content must also be admitted through the v2 synthetic-session operation with no independent reply/resume, so the current dispatch and future history see consistent content.
- Transient content is added only to the current provider context and is never persisted as a conversation message. It is recomputed for each applicable dispatch.
- Durable content is persisted once per path-derived rule identity and remains subject to the existing ledger, history-change, resume, compaction, and message-removal semantics.
- Rule and hook content continues to use the existing framed delivery format, with one preamble and identifiable rule blocks, regardless of whether the match was discovered from the user request or a tool event.
- Tool-derived state updates and pending deliveries are serialized or otherwise coordinated per session. A continuation dispatch must observe the merged state after all tool executions from the preceding provider response have settled.
- Existing condition lifetimes and matching rules are unchanged. This issue changes when matched content is delivered during the v2 migration, not the rule metadata language.
- A tool call already emitted by the model cannot receive newly discovered guidance retroactively. If a pre-execution policy must affect that call, the existing block/failure path rejects it and lets the model retry after the next context delivery.
- Delivery failures must leave pending content retryable and must not mark a rule as durably delivered until persistence and current-dispatch delivery have been accepted.
- No new user-facing command, configuration option, or separate background model turn is introduced.
- The migration should keep the current v1 behavior stable until the v2 integration boundary is adopted; v1 and v2 code must not develop separate rule-matching or delivery policies.
Testing Decisions
- The primary test seam is one end-to-end v2 session-runner integration test using a deterministic provider and tool. The provider first emits a tool call for a path covered by a rule; the tool hook records the path; the tool completes; and the test asserts that the next provider request already contains the rule before the provider makes its next decision. This is the highest seam and directly reproduces the late-delivery symptom.
- Tests assert externally observable provider context, conversation history, tool outcomes, and dispatch ordering. They do not assert private queues, maps, hook registration order, or other implementation details.
- The integration coverage must prove that no additional user message is required and that delivery happens within the same logical turn.
- The integration coverage must distinguish durable delivery from transient delivery: durable content appears once in persisted history and survives the next turn, while transient content appears only in the applicable dispatch.
- The integration coverage must include multiple matching tool calls, concurrent tool calls, and duplicate matches to verify coalescing and identity-based deduplication.
- The integration coverage must include a matching tool hook and a blocked pre-execution hook, verifying that hook content is delivered at the next dispatch and blocking still rejects the original call.
- The integration coverage must exercise path normalization and representative supported tools so that the regression cannot be fixed only for one argument shape.
- The integration coverage must cover history removal, resume, compaction, and revert behavior where those operations affect whether durable content is present.
- Failure-path tests must verify that evaluation or synthetic persistence errors do not permanently mark pending rules as delivered.
- Existing rule-filter, rule-delivery, runtime, and OpenCode v2 session-context test patterns should be extended rather than replaced. Unit tests remain appropriate for framing, matching, and ledger invariants, but the late-delivery requirement is accepted only when the session-runner seam passes.
Out of Scope
- Changing rule syntax, frontmatter, condition semantics, or lifetime classification.
- Making newly discovered rules affect a tool call that the model has already emitted.
- Reworking the current v1 delivery flow before the v2 migration boundary.
- Adding a new OpenCode hook or modifying OpenCode itself.
- Creating an extra user-visible turn or unrelated model response solely to deliver rules.
- Persisting transient rules or making all rules globally durable.
- Replacing the existing delivery framing, identity, or history-reconciliation model.
- Automatically undoing side effects from a tool call that was made before a rule became available.
- Broad prompt-token optimization unrelated to early rule delivery.
Further Notes
OpenCode v2's public documentation at https://opencode.ai/v2/docs is intentionally sparse. The v2 plugin and SDK package contracts are the relevant migration reference, especially the session context hook, tool execution hooks, and synthetic session operation.
The acceptance condition for this issue is temporal: when a tool-derived path first causes a rule to match, the rule must be available in the immediately following provider dispatch of that same turn, subject only to the platform limitation that the original tool call has already been selected.
Problem Statement
When the current integration discovers a file path from a tool call, the matching rule is learned after the model has already selected that tool. In the current delivery flow, the rule may not reach the agent until a later user message. For example, an agent can read a file covered by a path-scoped rule, continue without that guidance, and only receive it on the next turn.
OpenCode v2 exposes a session-context hook immediately before each provider dispatch. The v2 migration should use that boundary so rules discovered during a tool cycle are available before the agent makes its next decision in the same turn.
Solution
During the OpenCode v2 migration, record tool-derived context in the existing per-session state and make the v2 session context hook the single delivery seam for model-visible rules.
User Stories
Implementation Decisions
Testing Decisions
Out of Scope
Further Notes
OpenCode v2's public documentation at https://opencode.ai/v2/docs is intentionally sparse. The v2 plugin and SDK package contracts are the relevant migration reference, especially the session context hook, tool execution hooks, and synthetic session operation.
The acceptance condition for this issue is temporal: when a tool-derived path first causes a rule to match, the rule must be available in the immediately following provider dispatch of that same turn, subject only to the platform limitation that the original tool call has already been selected.