@@ -23,6 +23,7 @@ import {
2323 LEGACY_COMPACT_SPACER_TEXT ,
2424 compactorNoOpFloor ,
2525} from "../session/compactor.js" ;
26+ import { buildSummaryPrompt } from "../session/summarizer.js" ;
2627
2728const capabilities = {
2829 infer : ( options ?: unknown ) => ( {
@@ -1433,6 +1434,20 @@ describe("handoff arming (/handoff)", () => {
14331434 ) . toBeNull ( ) ;
14341435 } ) ;
14351436
1437+ test ( "cancelManual restores extraInstructions from a prior successful fold" , ( ) => {
1438+ const governor = createCompactionGovernor ( undefined ) ;
1439+ governor . syncFromTurns ( tenTurns ) ;
1440+ expect ( governor . requestHandoff ( "keep the UI audit" ) ) . toBe ( "armed" ) ;
1441+ governor . interceptIdleContinuation (
1442+ pivot ( "keep the UI audit" ) ,
1443+ capabilities ,
1444+ ) ;
1445+ expect ( governor . extraInstructions ) . toBe ( "keep the UI audit" ) ;
1446+ expect ( governor . requestHandoff ( "failed pivot: drop this" ) ) . toBe ( "armed" ) ;
1447+ governor . cancelManual ( ) ;
1448+ expect ( governor . extraInstructions ) . toBe ( "keep the UI audit" ) ;
1449+ } ) ;
1450+
14361451 test ( "cancelManual clears sticky extraInstructions from a failed pivot" , ( ) => {
14371452 const governor = createCompactionGovernor ( undefined ) ;
14381453 governor . syncFromTurns ( tenTurns ) ;
@@ -1441,6 +1456,55 @@ describe("handoff arming (/handoff)", () => {
14411456 expect ( governor . extraInstructions ) . toBeUndefined ( ) ;
14421457 } ) ;
14431458
1459+ test ( "failed-pivot instructions are not in a later threshold summary prompt" , ( ) => {
1460+ const governor = createCompactionGovernor ( undefined ) ;
1461+ governor . syncFromTurns ( tenTurns ) ;
1462+ expect ( governor . requestHandoff ( "now do the UI audit" ) ) . toBe ( "armed" ) ;
1463+ governor . cancelManual ( ) ;
1464+ governor . noteInferenceDone ( inferenceDone ( overThreshold ) , tenTurns ) ;
1465+ expect (
1466+ governor . interceptActions ( toolDone ( ) , inferAction , capabilities ) ,
1467+ ) . not . toBeNull ( ) ;
1468+ const prompt = buildSummaryPrompt (
1469+ tenTurns ,
1470+ governor . extraInstructions !== undefined
1471+ ? { extraInstructions : governor . extraInstructions }
1472+ : undefined ,
1473+ ) ;
1474+ expect ( prompt ) . not . toContain ( "now do the UI audit" ) ;
1475+ expect ( prompt ) . not . toContain ( "Operator compact instructions" ) ;
1476+ } ) ;
1477+
1478+ test ( "cancelManual does not invent pending" , ( ) => {
1479+ const governor = createCompactionGovernor ( undefined ) ;
1480+ governor . syncFromTurns ( tenTurns ) ;
1481+ expect ( governor . requestHandoff ( "now do the UI audit" ) ) . toBe ( "armed" ) ;
1482+ governor . cancelManual ( ) ;
1483+ expect (
1484+ governor . interceptActions ( toolDone ( ) , inferAction , capabilities ) ,
1485+ ) . toBeNull ( ) ;
1486+ } ) ;
1487+
1488+ test ( "cancelManual restores idlePending so an idle threshold fold still fires" , ( ) => {
1489+ const governor = createCompactionGovernor ( undefined ) ;
1490+ governor . noteInferenceDone ( inferenceDone ( overThreshold ) , tenTurns ) ;
1491+ expect (
1492+ governor . noteIdleTurn ( inferenceDone ( overThreshold ) , [
1493+ { type : "reply" , content : "done" } ,
1494+ ] ) ,
1495+ ) . toBe ( true ) ;
1496+ expect ( governor . requestHandoff ( "now do the UI audit" ) ) . toBe ( "armed" ) ;
1497+ governor . cancelManual ( ) ;
1498+ const actions = governor . interceptIdleContinuation (
1499+ emptyMessage ( ) ,
1500+ capabilities ,
1501+ ) ;
1502+ expect ( actions ) . not . toBeNull ( ) ;
1503+ expect ( actions ?. find ( ( a ) => a . type === "compact" ) ) . toMatchObject ( {
1504+ reason : "context-threshold" ,
1505+ } ) ;
1506+ } ) ;
1507+
14441508 test ( "threshold pending survives cancelManual so a tool pause still folds" , ( ) => {
14451509 const governor = createCompactionGovernor ( undefined ) ;
14461510 governor . noteInferenceDone ( inferenceDone ( overThreshold ) , tenTurns ) ;
0 commit comments