feat(coding-agent): session_before_refine extension hook - #1558
Open
snimu wants to merge 5 commits into
Open
Conversation
Let extensions customize continual-harness refinement the same way
session_before_compact customizes compaction. The hook fires before the
planning LLM call for /refine and auto-refine with the planning inputs
(trigger, instructions, scope, planning harness state, refinement
history, serialized conversation). An extension can return a
RefinementProposal to replace the built-in planner (edits still pass
apply-time validation and baseline conflict rejection), return
{ skip: true } to suppress the round, or return nothing to fall back to
the default planner. Rollback refinements bypass the hook.
Includes examples/extensions/custom-refinement.ts (planning with a
cheaper model, covering discussion #1464) and documents the existing
refine_complete event.
…ne paths Serialized auto-refine now reaches session_before_refine with trigger "auto", an extension skip there stamps the cooldown without emitting refine_failed, and a skipped explicit refine.run surfaces the RefineSkippedError instead of passing as a silent reviewer decline. The example planner now labels entry ids with their scope and tells the model other-scope entries are read-only.
…efine-hook # Conflicts: # packages/coding-agent/CHANGELOG.md
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ba2a500. Configure here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What this does
Adds a
session_before_refineextension hook so extensions can customize continual-harness refinement the same waysession_before_compactcustomizes compaction. Generalizes discussion #1464 (cheaper model for /refine) into an extensibility point for refinement-policy experimentation.How it works
The hook fires before the planning LLM call for both
/refineand auto-refine, with the planning inputs:validateEditplus baseline conflict rejection — so a bad proposal degrades to per-edit errors, never harness corruption./refinesurfaces aRefineSkippedError; auto-refine treats it like a reviewer decline (serialized path maps it to the existingskipstatus).triggerdistinguishes"manual"(/refine,refine.run) from"auto"(auto-refine), threaded through all three planning entry points (direct refine, queued/serialized refine, background auto-plan).HarnessState/RefinementProposal/RefinementEdittypes (now exported from the package index alongside the new event types).Also included
examples/extensions/custom-refinement.ts— working example that plans with a cheaper model (the literal Allow using a different model for /refine #1464 ask, ~a screenful of code)extensions.md, which also documents the previously undocumentedrefine_completeeventagent-session-refine-extension.test.ts): proposal replaces planner (no LLM call), invalid extension edits rejected at apply time, skip propagation, fallback-on-undefinedValidation
Linear: ENG-5323
Covers: #1464
Note
Medium Risk
Touches continual-harness planning and skip/failure semantics for both manual and auto-refine. Invalid extension proposals still fail at apply time rather than corrupting harness state.
Overview
Extensions can now intercept continual-harness refinement (
/refineand auto-refine) viasession_before_refine, matching the compaction hook pattern.Handlers receive planning inputs (
trigger, scope, harness state, history, truncated conversation) and may skip the round, replace the built-in planner with aRefinementProposal, or fall through. Rollbacks bypass the hook. Extension edits still go through the existing apply-time validation.Skip is treated as a non-failure for auto-refine (like a reviewer decline) and as
RefineSkippedError/refine_failedfor explicit/refine. Docs, public types (RefinementProposal, event types), a cheaper-model example (custom-refinement.ts), and tests cover replace, skip, fallback, and invalid edits.Reviewed by Cursor Bugbot for commit 1b1bb37. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add
session_before_refineextension hook to agent session refinementsession_before_refineextension event inagent-session.tsthat fires before each refinement round, giving extensions the ability to skip refinement or supply a customRefinementProposalwithout invoking the built-in planner.'auto'or'manual'), planning inputs, and a serialized conversation (truncated to ~80k chars); returning{ skip: true }throws the newRefineSkippedError, and returning aproposalbypasses planning entirely./refineskips surface asrefine_failed, while auto-refine skips are treated as non-failures.RefinePreparation,SessionBeforeRefineEvent,SessionBeforeRefineResult,RefinementProposal, etc.) from the public index and adds acustom-refinement.tsexample.Macroscope summarized 1b1bb37.