@@ -15,6 +15,7 @@ import {
1515 createApprovalResume ,
1616 resolveParkedCallIdFromStore ,
1717} from "./approval-resume.js" ;
18+ import { createSessionOperationQueue } from "../tui/delivery-queue.js" ;
1819
1920function assistantTurn (
2021 calls : { id : string ; name : string ; command : string } [ ] ,
@@ -106,6 +107,59 @@ function deliveredCorrelationId(message: InboundMessage): string {
106107 return correlationId ;
107108}
108109
110+ describe ( "approval decision intent headers" , ( ) => {
111+ for ( const allow of [ true , false ] ) {
112+ test ( `preserves ${ allow ? "granted" : "denied" } intent and correlation through the session queue` , async ( ) => {
113+ const delivered : InboundMessage [ ] = [ ] ;
114+ const queue = createSessionOperationQueue ( ) ;
115+ let release ! : ( ) => void ;
116+ const held = new Promise < void > ( ( resolve ) => {
117+ release = resolve ;
118+ } ) ;
119+ queue . enqueue ( ( ) => held ) ;
120+ const agent = {
121+ history : async ( ) => [ ] ,
122+ deliver : ( message : InboundMessage ) => {
123+ delivered . push ( message ) ;
124+ } ,
125+ } ;
126+ const gate = {
127+ resolveSuspended : async ( ) => ( { allow, message : "decision reason" } ) ,
128+ } as unknown as PermissionGate ;
129+ const resume = createApprovalResume ( {
130+ getAgent : ( ) => agent ,
131+ gate,
132+ resolveParkedCallId : ( ) => "typed-call" ,
133+ deliver : ( message ) =>
134+ queue . enqueue ( async ( ) => {
135+ agent . deliver ( message ) ;
136+ } ) ,
137+ } ) ;
138+ const handling = resume . handle (
139+ suspension ( "typed-correlation" , "echo alpha" ) ,
140+ ) ;
141+ expect ( delivered ) . toHaveLength ( 0 ) ;
142+ release ( ) ;
143+ expect ( await handling ) . toBe ( true ) ;
144+ await queue . awaitTail ( ) ;
145+ expect ( delivered ) . toHaveLength ( 1 ) ;
146+ const message = delivered [ 0 ] ;
147+ if ( message === undefined ) throw new Error ( "expected decision" ) ;
148+ expect ( message . headers . interchangeType ) . toBe (
149+ allow ? "approval.granted" : "approval.denied" ,
150+ ) ;
151+ expect ( deliveredCorrelationId ( message ) ) . toBe ( "typed-correlation" ) ;
152+ expect ( decisionBody ( message ) . outcome ) . toBe (
153+ allow ? "approved" : "rejected" ,
154+ ) ;
155+ if ( ! allow )
156+ expect ( JSON . parse ( message . content ?? "" ) . message ) . toBe (
157+ "decision reason" ,
158+ ) ;
159+ } ) ;
160+ }
161+ } ) ;
162+
109163describe ( "approval-resume parallel-parked approvals" , ( ) => {
110164 test ( "delivers A's decision when a different parked call's approval times out" , async ( ) => {
111165 const { resume, delivered } = setup ( {
0 commit comments