@@ -1595,7 +1595,7 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
15951595 }
15961596 } ) ;
15971597
1598- it ( "does not persist exact-command allow-always approvals for planner-rejected shell" , async ( ) => {
1598+ it ( "persists exact-command allow-always approvals for planner-rejected shell" , async ( ) => {
15991599 if ( process . platform === "win32" ) {
16001600 return ;
16011601 }
@@ -1617,7 +1617,41 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
16171617
16181618 expect ( runCommand ) . toHaveBeenCalledTimes ( 1 ) ;
16191619 expectInvokeOk ( sendInvokeResult , { payloadContains : "allow-always-ok" } ) ;
1620- expect ( loadExecApprovals ( ) . agents ?. main ?. allowlist ?? [ ] ) . toStrictEqual ( [ ] ) ;
1620+ const allowlist = loadExecApprovals ( ) . agents ?. main ?. allowlist ?? [ ] ;
1621+ expect ( allowlist ) . toHaveLength ( 1 ) ;
1622+ expect ( allowlist [ 0 ] ) . toEqual (
1623+ expect . objectContaining ( {
1624+ pattern : expect . stringMatching ( / ^ = c o m m a n d : [ 0 - 9 a - f ] { 16 } $ / ) ,
1625+ source : "allow-always" ,
1626+ } ) ,
1627+ ) ;
1628+
1629+ const rerun = await runSystemInvoke ( {
1630+ preferMacAppExecHost : false ,
1631+ command : [ "/bin/sh" , "-lc" , "printf x > out.txt" ] ,
1632+ rawCommand : "printf x > out.txt" ,
1633+ cwd : createFixtureDir ( "openclaw-exact-fallback-rerun-" ) ,
1634+ security : "allowlist" ,
1635+ ask : "on-miss" ,
1636+ runCommand : vi . fn ( async ( ) => createLocalRunResult ( "exact-rerun-ok" ) ) ,
1637+ } ) ;
1638+ expect ( rerun . runCommand ) . toHaveBeenCalledTimes ( 1 ) ;
1639+ expectInvokeOk ( rerun . sendInvokeResult , { payloadContains : "exact-rerun-ok" } ) ;
1640+
1641+ const changed = await runSystemInvoke ( {
1642+ preferMacAppExecHost : false ,
1643+ command : [ "/bin/sh" , "-lc" , "printf y > out.txt" ] ,
1644+ rawCommand : "printf y > out.txt" ,
1645+ cwd : createFixtureDir ( "openclaw-exact-fallback-changed-" ) ,
1646+ security : "allowlist" ,
1647+ ask : "on-miss" ,
1648+ runCommand : vi . fn ( async ( ) => createLocalRunResult ( "changed-ok" ) ) ,
1649+ } ) ;
1650+ expect ( changed . runCommand ) . not . toHaveBeenCalled ( ) ;
1651+ expectApprovalRequiredDenied ( {
1652+ sendNodeEvent : changed . sendNodeEvent ,
1653+ sendInvokeResult : changed . sendInvokeResult ,
1654+ } ) ;
16211655 } ,
16221656 } ) ;
16231657 } ) ;
@@ -2434,7 +2468,7 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
24342468 }
24352469 } ) ;
24362470
2437- it ( "keeps prompt-only shell-wrapper reruns approval-gated despite exact-command durable trust" , async ( ) => {
2471+ it ( "allows prompt-only shell-wrapper reruns with exact-command durable trust" , async ( ) => {
24382472 if ( process . platform === "win32" ) {
24392473 return ;
24402474 }
@@ -2480,11 +2514,8 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
24802514 runCommand : vi . fn ( async ( ) => createLocalRunResult ( "shell-wrapper-reused" ) ) ,
24812515 } ) ;
24822516
2483- expect ( rerun . runCommand ) . not . toHaveBeenCalled ( ) ;
2484- expectApprovalRequiredDenied ( {
2485- sendNodeEvent : rerun . sendNodeEvent ,
2486- sendInvokeResult : rerun . sendInvokeResult ,
2487- } ) ;
2517+ expect ( rerun . runCommand ) . toHaveBeenCalledTimes ( 1 ) ;
2518+ expectInvokeOk ( rerun . sendInvokeResult , { payloadContains : "shell-wrapper-reused" } ) ;
24882519 } ,
24892520 } ) ;
24902521 } ) ;
0 commit comments