@@ -173,4 +173,74 @@ describe("integration — reactor permission + multi-turn", () => {
173173 }
174174 } ,
175175 ) ;
176+
177+ test . serial (
178+ "denied run_shell does not canned-reply a later prose turn and re-asks the same command" ,
179+ async ( ) => {
180+ let asked = 0 ;
181+ const session = await openIntegrationSession ( {
182+ permissionGate : createPermissionGate ( {
183+ approvals : [ ] ,
184+ interactive : true ,
185+ skipPermissions : false ,
186+ reactorGated : false ,
187+ requestApproval : async ( ) => {
188+ asked ++ ;
189+ return { allow : false } ;
190+ } ,
191+ } ) ,
192+ } ) ;
193+
194+ try {
195+ session . harness . scenario . replyOnce ( "anthropic" , {
196+ toolCalls : [
197+ {
198+ name : "run_shell" ,
199+ args : { command : "curl https://example.com/docs" } ,
200+ } ,
201+ ] ,
202+ } ) ;
203+
204+ const denied = await runUntilDone (
205+ session ,
206+ "Fetch https://example.com/docs." ,
207+ ) ;
208+ expect ( asked ) . toBeGreaterThan ( 0 ) ;
209+ const askedAfterDeny = asked ;
210+ expect (
211+ denied . events . some ( ( e ) => e . type === "reactor.error" ) ,
212+ ) . toBe ( false ) ;
213+
214+ session . harness . scenario . replyOnce ( "anthropic" , {
215+ text : "I'll continue without fetching." ,
216+ } ) ;
217+ const prose = await runUntilDone (
218+ session ,
219+ "Do not fetch anything. Confirm in prose." ,
220+ ) ;
221+ expect ( prose . reply ) . toContain ( "I'll continue without fetching." ) ;
222+ expect ( prose . reply ) . not . toContain ( "Tool call rejected by operator." ) ;
223+ expect ( asked ) . toBe ( askedAfterDeny ) ;
224+
225+ session . harness . scenario . replyOnce ( "anthropic" , {
226+ toolCalls : [
227+ {
228+ name : "run_shell" ,
229+ args : { command : "curl https://example.com/docs" } ,
230+ } ,
231+ ] ,
232+ } ) ;
233+ const retried = await runUntilDone (
234+ session ,
235+ "Try fetching https://example.com/docs again." ,
236+ ) ;
237+ expect ( asked ) . toBe ( askedAfterDeny + 1 ) ;
238+ expect (
239+ retried . events . some ( ( e ) => e . type === "reactor.error" ) ,
240+ ) . toBe ( false ) ;
241+ } finally {
242+ await closeIntegrationSession ( session ) ;
243+ }
244+ } ,
245+ ) ;
176246} ) ;
0 commit comments