@wrongstack/tools 0.277.1 → 0.280.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/exec.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/_output-spool.ts","../src/_util.ts","../src/circuit-breaker.ts","../src/process-registry.ts","../src/_win32-resolve.ts","../src/exec.ts"],"names":["path","fsp2","isWin","path3","blocked","resolve","spawn"],"mappings":";;;;;;;;;;;AA6BA,IAAM,kBAAA,GAAqB,CAAA,GAAI,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAE9C,IAAM,qBAAA,GAAwB,IAAI,IAAA,GAAO,IAAA;AAEzC,IAAI,YAAA,GAAe,KAAA;AAGZ,SAAS,aAAA,GAAwB;AACtC,EAAA,OAAYA,KAAA,CAAA,IAAA,CAAK,gBAAA,EAAiB,EAAG,aAAa,CAAA;AACpD;AAOA,SAAS,mBAAmB,GAAA,EAAmB;AAC7C,EAAA,IAAI,YAAA,EAAc;AAClB,EAAA,YAAA,GAAe,IAAA;AACf,EAAA,KAAA,CAAM,YAAY;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAU,GAAA,CAAA,OAAA,CAAQ,GAAG,CAAA,EAAG;AACzC,QAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC5B,QAAA,MAAM,CAAA,GAASA,KAAA,CAAA,IAAA,CAAK,GAAA,EAAK,IAAI,CAAA;AAC7B,QAAA,IAAI;AACF,UAAA,MAAM,EAAA,GAAK,MAAU,GAAA,CAAA,IAAA,CAAK,CAAC,CAAA;AAC3B,UAAA,IAAI,MAAM,EAAA,CAAG,OAAA,GAAU,kBAAA,EAAoB,MAAU,WAAO,CAAC,CAAA;AAAA,QAC/D,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA,GAAG;AACL;AAoCO,SAAS,UAAU,IAAA,EAAyB;AACjD,EAAA,MAAM,UACJ,IAAA,CAAK,YAAA,GAAe,IAAI,CAAA,GAAA,EAAM,IAAA,CAAK,YAAY,CAAA,iCAAA,CAAA,GAAsC,EAAA;AACvF,EAAA,OAAO;AAAA,8BAAA,EAA8B,KAAK,KAAK,CAAA,UAAA,EAAa,IAAA,CAAK,IAAI,GAAG,OAAO,CAAA,yEAAA,CAAA;AACjF;AAEO,SAAS,kBAAkB,IAAA,EAA6C;AAC7E,EAAA,MAAM,SAAA,GAAY,KAAK,cAAkB;AACzC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,mBAAA,EAAqB,GAAG,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,IAAK,MAAA;AAE7E,EAAA,IAAI,IAAA,GAAO,EAAA;AACX,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,YAAA,GAAe,CAAA;AACnB,EAAA,IAAI,MAAA,GAA6B,IAAA;AACjC,EAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,EAAA,MAAM,OAAO,MAAY;AACvB,IAAA,IAAI,UAAU,MAAA,EAAQ;AACtB,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,aAAA,EAAc;AAI1B,MAAA,SAAA,CAAU,GAAA,EAAK,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAClC,MAAA,kBAAA,CAAmB,GAAG,CAAA;AACtB,MAAA,MAAM,KAAA,GAAA,qBAAY,IAAA,EAAK,EAAE,aAAY,CAAE,OAAA,CAAQ,SAAS,GAAG,CAAA;AAC3D,MAAA,MAAM,IAAA,GAAO,KAAK,MAAA,EAAO,CAAE,SAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAClD,MAAA,QAAA,GAAgBA,KAAA,CAAA,IAAA,CAAK,KAAK,CAAA,EAAG,KAAK,IAAI,QAAQ,CAAA,CAAA,EAAI,IAAI,CAAA,IAAA,CAAM,CAAA;AAC5D,MAAA,MAAA,GAAS,kBAAkB,QAAA,EAAU,EAAE,OAAO,GAAA,EAAK,QAAA,EAAU,QAAQ,CAAA;AACrE,MAAA,MAAA,CAAO,EAAA,CAAG,SAAS,MAAM;AAEvB,QAAA,MAAA,GAAS,IAAA;AACT,QAAA,MAAA,GAAS,IAAA;AACT,QAAA,QAAA,GAAW,IAAA;AAAA,MACb,CAAC,CAAA;AAED,MAAA,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,IACnB,CAAA,CAAA,MAAQ;AACN,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,QAAA,GAAW,IAAA;AAAA,IACb;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,EAAoB;AACxB,MAAA,IAAI,SAAA,IAAa,CAAC,IAAA,EAAM;AACxB,MAAA,UAAA,IAAc,MAAA,CAAO,UAAA,CAAW,IAAA,EAAM,MAAM,CAAA;AAC5C,MAAA,IAAI,CAAC,MAAA,IAAU,CAAC,MAAA,EAAQ;AACtB,QAAA,IAAI,SAAA,GAAY,IAAA,CAAK,MAAA,IAAU,SAAA,EAAW;AACxC,UAAA,IAAA,IAAQ,IAAA;AACR,UAAA,SAAA,IAAa,IAAA,CAAK,MAAA;AAClB,UAAA;AAAA,QACF;AACA,QAAA,IAAA,IAAQ,IAAA;AACR,QAAA,IAAA,EAAK;AACL,QAAA,IAAA,GAAO,EAAA;AACP,QAAA;AAAA,MACF;AACA,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,IAAI,MAAA,CAAO,iBAAiB,qBAAA,EAAuB;AACjD,UAAA,YAAA,IAAgB,MAAA,CAAO,UAAA,CAAW,IAAA,EAAM,MAAM,CAAA;AAC9C,UAAA;AAAA,QACF;AACA,QAAA,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,MACnB;AAAA,IACF,CAAA;AAAA,IACA,QAAA,GAA6B;AAC3B,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,OAAO,WAAW,EAAE,IAAA,EAAM,UAAU,KAAA,EAAO,UAAA,EAAY,cAAa,GAAI,IAAA;AAAA,MAC1E;AACA,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,IAAA,GAAO,EAAA;AACP,MAAA,IAAI,CAAC,MAAA,IAAU,CAAC,QAAA,EAAU,OAAO,IAAA;AACjC,MAAA,IAAI;AACF,QAAA,MAAA,CAAO,GAAA,EAAI;AAAA,MACb,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,YAAY,YAAA,EAAa;AAAA,IAC3D;AAAA,GACF;AACF;AC5JO,SAAS,WAAA,CAAY,OAAe,GAAA,EAAsB;AAC/D,EAAA,OAAY,KAAA,CAAA,UAAA,CAAW,KAAK,CAAA,GAAS,KAAA,CAAA,SAAA,CAAU,KAAK,CAAA,GAAS,KAAA,CAAA,OAAA,CAAQ,GAAA,CAAI,UAAA,IAAc,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AACvG;AAOA,SAAS,aAAa,GAAA,EAAwB;AAC5C,EAAA,OAAO,CAAM,cAAQ,GAAA,CAAI,WAAW,GAAQ,KAAA,CAAA,OAAA,CAAa,IAAA,CAAA,gBAAA,EAAkB,CAAC,CAAA;AAC9E;AAGA,SAAS,WAAA,CAAY,QAAgB,KAAA,EAA0B;AAC7D,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,IAAA,KAAS;AAC1B,IAAA,MAAM,GAAA,GAAW,KAAA,CAAA,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AACtC,IAAA,OAAO,GAAA,KAAQ,MAAO,CAAC,GAAA,CAAI,WAAW,IAAI,CAAA,IAAK,CAAM,KAAA,CAAA,UAAA,CAAW,GAAG,CAAA;AAAA,EACrE,CAAC,CAAA;AACH;AAEO,SAAS,gBAAA,CAAiB,SAAiB,GAAA,EAAsB;AACtE,EAAA,MAAM,MAAA,GAAc,cAAQ,OAAO,CAAA;AAEnC,EAAA,IAAI,GAAA,CAAI,yBAAyB,OAAO,MAAA;AACxC,EAAA,IAAI,YAAY,MAAA,EAAQ,YAAA,CAAa,GAAG,CAAC,GAAG,OAAO,MAAA;AACnD,EAAA,MAAM,IAAI,MAAM,CAAA,MAAA,EAAS,OAAO,8BAAmC,KAAA,CAAA,OAAA,CAAQ,GAAA,CAAI,WAAW,CAAC,CAAA,CAAA,CAAG,CAAA;AAChG;AAEO,SAAS,WAAA,CAAY,OAAe,GAAA,EAAsB;AAC/D,EAAA,OAAO,gBAAA,CAAiB,WAAA,CAAY,KAAA,EAAO,GAAG,GAAG,GAAG,CAAA;AACtD;AAgBA,eAAsB,oBAAA,CAAqB,SAAiB,GAAA,EAA6B;AAEvF,EAAA,IAAI,IAAI,uBAAA,EAAyB;AAGjC,EAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,GAAA;AAAA,IAC9B,YAAA,CAAa,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAUC,GAAA,CAAA,QAAA,CAAS,CAAC,CAAA,CAAE,KAAA,CAAM,MAAW,KAAA,CAAA,OAAA,CAAQ,CAAC,CAAC,CAAC;AAAA,GAC3E;AACA,EAAA,IAAI,KAAA,GAAQ,OAAA;AACZ,EAAA,WAAS;AACP,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI;AACF,MAAA,IAAA,GAAO,MAAUA,aAAS,KAAK,CAAA;AAAA,IACjC,SAAS,GAAA,EAAK;AACZ,MAAA,IAAK,GAAA,CAA8B,SAAS,QAAA,EAAU;AACpD,QAAA,MAAM,MAAA,GAAc,cAAQ,KAAK,CAAA;AACjC,QAAA,IAAI,WAAW,KAAA,EAAO;AACtB,QAAA,KAAA,GAAQ,MAAA;AACR,QAAA;AAAA,MACF;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AACA,IAAA,IAAI,WAAA,CAAY,IAAA,EAAM,SAAS,CAAA,EAAG;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,MAAA,EAAS,OAAO,CAAA,mDAAA,EAAsD,SAAA,CAAU,CAAC,CAAC,CAAA,CAAA;AAAA,KACpF;AAAA,EACF;AACF;AAGA,eAAsB,eAAA,CAAgB,OAAe,GAAA,EAA+B;AAClF,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,KAAA,EAAO,GAAG,CAAA;AAClC,EAAA,MAAM,oBAAA,CAAqB,KAAK,GAAG,CAAA;AACnC,EAAA,OAAO,GAAA;AACT;AA6BO,IAAM,wBAAA,GAA2B,KAAA;AAGxC,IAAM,oBAAA,GAAuB,CAAA;AAQtB,SAAS,wBAAwB,IAAA,EAAsB;AAC5D,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAS,IAAI,CAAA;AACrC,EAAA,IAAI,CAAC,EAAA,CAAG,QAAA,CAAS,IAAI,GAAG,OAAO,EAAA;AAC/B,EAAA,OAAO,EAAA,CACJ,MAAM,IAAI,CAAA,CACV,IAAI,CAAC,IAAA,KAAU,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,GAAI,KAAK,KAAA,CAAM,IAAA,CAAK,YAAY,IAAI,CAAA,GAAI,CAAC,CAAA,GAAI,IAAK,CAAA,CACnF,IAAA,CAAK,IAAI,CAAA;AACd;AAOO,SAAS,6BAAA,CAA8B,IAAA,EAAc,MAAA,GAAS,oBAAA,EAA8B;AACjG,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC7B,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,OAAO,CAAA,GAAI,MAAM,MAAA,EAAQ;AACvB,IAAA,IAAI,IAAI,CAAA,GAAI,CAAA;AACZ,IAAA,OAAO,CAAA,GAAI,MAAM,MAAA,IAAU,KAAA,CAAM,CAAC,CAAA,KAAM,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,EAAA;AAClD,IAAA,MAAM,MAAM,CAAA,GAAI,CAAA;AAChB,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,GAAA,CAAI,KAAK,KAAA,CAAM,CAAC,CAAA,EAAI,CAAA,sBAAA,EAAe,GAAG,CAAA,UAAA,CAAI,CAAA;AAAA,IAC5C,CAAA,MAAO;AACL,MAAA,KAAA,IAAS,CAAA,GAAI,GAAG,CAAA,GAAI,CAAA,EAAG,KAAK,GAAA,CAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAE,CAAA;AAAA,IAChD;AACA,IAAA,CAAA,GAAI,CAAA;AAAA,EACN;AACA,EAAA,OAAO,GAAA,CAAI,KAAK,IAAI,CAAA;AACtB;AAGA,SAAS,aAAA,CAAc,GAAW,QAAA,EAA0B;AAC1D,EAAA,IAAI,QAAA,IAAY,GAAG,OAAO,EAAA;AAE1B,EAAA,IAAI,OAAO,UAAA,CAAW,CAAA,EAAG,MAAM,CAAA,IAAK,UAAU,OAAO,CAAA;AACrD,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,KAAK,CAAA,CAAE,MAAA;AACX,EAAA,OAAO,KAAK,EAAA,EAAI;AACd,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAA,CAAM,EAAA,GAAK,MAAM,CAAC,CAAA;AACnC,IAAA,IAAI,MAAA,CAAO,UAAA,CAAW,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,EAAG,MAAM,CAAA,IAAK,QAAA,EAAU,EAAA,GAAK,GAAA;AAAA,cACvD,GAAA,GAAM,CAAA;AAAA,EAClB;AACA,EAAA,OAAO,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACtB;AAGA,SAAS,aAAA,CAAc,GAAW,QAAA,EAA0B;AAC1D,EAAA,IAAI,QAAA,IAAY,GAAG,OAAO,EAAA;AAE1B,EAAA,IAAI,OAAO,UAAA,CAAW,CAAA,EAAG,MAAM,CAAA,IAAK,UAAU,OAAO,CAAA;AACrD,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,KAAK,CAAA,CAAE,MAAA;AACX,EAAA,OAAO,KAAK,EAAA,EAAI;AACd,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAA,CAAM,EAAA,GAAK,MAAM,CAAC,CAAA;AACnC,IAAA,IAAI,MAAA,CAAO,UAAA,CAAW,CAAA,CAAE,KAAA,CAAM,CAAA,CAAE,MAAA,GAAS,GAAG,CAAA,EAAG,MAAM,CAAA,IAAK,QAAA,EAAU,EAAA,GAAK,GAAA;AAAA,cAC/D,GAAA,GAAM,CAAA;AAAA,EAClB;AACA,EAAA,OAAO,CAAA,CAAE,KAAA,CAAM,CAAA,CAAE,MAAA,GAAS,EAAE,CAAA;AAC9B;AAOO,SAAS,gBAAA,CAAiB,GAAW,QAAA,EAA0B;AACpE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,UAAA,CAAW,CAAA,EAAG,MAAM,CAAA;AACzC,EAAA,IAAI,KAAA,IAAS,UAAU,OAAO,CAAA;AAG9B,EAAA,MAAM,cAAA,GAAiB,EAAA;AACvB,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,WAAW,cAAc,CAAA;AACnD,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,IAAI,CAAA;AAC1C,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,CAAA,EAAG,UAAU,CAAA;AACxC,EAAA,MAAM,IAAA,GAAO,cAAc,CAAA,EAAG,KAAA,GAAQ,OAAO,UAAA,CAAW,IAAA,EAAM,MAAM,CAAC,CAAA;AACrE,EAAA,MAAM,IAAA,GAAO,OAAO,UAAA,CAAW,IAAA,EAAM,MAAM,CAAA,GAAI,MAAA,CAAO,UAAA,CAAW,IAAA,EAAM,MAAM,CAAA;AAC7E,EAAA,OAAO,GAAG,IAAI;AAAA,iBAAA,EAAiB,QAAQ,IAAI,CAAA;AAAA,EAAa,IAAI,CAAA,CAAA;AAC9D;AAOO,SAAS,sBAAA,CACd,GAAA,EACA,IAAA,GAA0C,EAAC,EACnC;AACR,EAAA,IAAI,CAAC,KAAK,OAAO,GAAA;AACjB,EAAA,IAAI,IAAA,GAAY,eAAU,GAAG,CAAA;AAC7B,EAAA,IAAA,GAAO,wBAAwB,IAAI,CAAA;AACnC,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,WAAA,EAAa,EAAE,CAAA;AACnC,EAAA,IAAA,GAAO,8BAA8B,IAAI,CAAA;AACzC,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,MAAM,CAAA;AACrC,EAAA,OAAO,gBAAA,CAAiB,IAAA,EAAM,IAAA,CAAK,QAAA,IAAY,wBAAwB,CAAA;AACzE;;;AC3LA,IAAM,gCAAA,GAAmC,CAAA;AACzC,IAAM,8BAAA,GAAiC,IAAA;AAIvC,IAAM,sBAAA,GAAyB,CAAA;AAC/B,IAAM,iBAAA,GAAoB,GAAA;AAC1B,IAAM,4BAAA,GAA+B,EAAA;AACrC,IAAM,mBAAA,GAAsB,GAAA;AAarB,IAAM,iBAAN,MAAqB;AAAA,EACT,sBAAA;AAAA,EACA,mBAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,iBAAA;AAAA,EACA,UAAA;AAAA,EAET,KAAA,GAAsB,QAAA;AAAA,EACtB,mBAAA,GAAsB,CAAA;AAAA,EACtB,SAAuB,EAAC;AAAA,EACxB,aAAA,GAA+B,IAAA;AAAA,EAC/B,UAAA,GAA4B,IAAA;AAAA;AAAA,EAE5B,QAAA,GAA0B,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1B,OAAA,GAAU,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA;AAAA,EAEA,WAAA,CAAY,MAAA,GAA+B,EAAC,EAAG;AAC7C,IAAA,IAAA,CAAK,sBAAA,GAAyB,OAAO,sBAAA,IAA0B,gCAAA;AAC/D,IAAA,IAAA,CAAK,mBAAA,GAAsB,OAAO,mBAAA,IAAuB,8BAAA;AACzD,IAAA,IAAA,CAAK,YAAA,GAAe,OAAO,YAAA,IAAgB,sBAAA;AAC3C,IAAA,IAAA,CAAK,QAAA,GAAW,OAAO,QAAA,IAAY,iBAAA;AACnC,IAAA,IAAA,CAAK,iBAAA,GAAoB,OAAO,iBAAA,IAAqB,4BAAA;AACrD,IAAA,IAAA,CAAK,UAAA,GAAa,OAAO,UAAA,IAAc,mBAAA;AAAA,EACzC;AAAA;AAAA,EAGA,WAAW,OAAA,EAAwB;AACjC,IAAA,IAAI,IAAA,CAAK,YAAY,OAAA,EAAS;AAC9B,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAI,CAAC,OAAA,EAAS,IAAA,CAAK,MAAA,EAAO;AAAA,EAC5B;AAAA,EAEA,IAAI,SAAA,GAAqB;AACvB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,UAAA,GAAsB;AACxB,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,OAAO,IAAA;AAC1B,IAAA,IAAA,CAAK,qBAAA,EAAsB;AAC3B,IAAA,OAAO,KAAK,KAAA,KAAU,MAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,GAAmC;AACjC,IAAA,IAAA,CAAK,qBAAA,EAAsB;AAC3B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,IAAI,iBAAA,GAAmC,IAAA;AACvC,IAAA,IAAI,IAAA,CAAK,QAAA,KAAa,IAAA,IAAQ,IAAA,CAAK,UAAU,MAAA,EAAQ;AACnD,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,QAAA;AAC3B,MAAA,iBAAA,GAAoB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,aAAa,OAAO,CAAA;AAAA,IAC3D;AACA,IAAA,OAAO;AAAA,MACL,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,qBAAqB,IAAA,CAAK,mBAAA;AAAA,MAC1B,iBAAA,EAAmB,KAAK,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CAAE,MAAA;AAAA,MACrD,aAAA,EAAe,KAAK,MAAA,CAAO,MAAA;AAAA,MAC3B,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,mBAAA,EAAqB,iBAAA;AAAA,MACrB,eAAe,IAAA,CAAK,aAAA;AAAA,MACpB,YAAY,IAAA,CAAK;AAAA,KACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,UAAA,CAAW,SAAS,KAAA,EAAgB;AAClC,IAAA,IAAI,MAAA,IAAU,CAAC,IAAA,CAAK,OAAA,EAAS,OAAO,IAAA;AACpC,IAAA,IAAA,CAAK,qBAAA,EAAsB;AAC3B,IAAA,IAAI,IAAA,CAAK,KAAA,KAAU,MAAA,EAAQ,OAAO,KAAA;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,SAAA,CAAU,UAAA,EAAoB,MAAA,EAAiB,MAAA,GAAS,KAAA,EAAa;AACnE,IAAA,IAAI,MAAA,IAAU,CAAC,IAAA,CAAK,OAAA,EAAS;AAE7B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,IAAI,IAAA,CAAK,UAAU,WAAA,EAAa;AAE9B,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,IAAA,CAAK,KAAA,EAAM;AACX,QAAA;AAAA,MACF;AAEA,MAAA,IAAA,CAAK,MAAA,EAAO;AACZ,MAAA;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,aAAa,GAAG,CAAA;AAErB,IAAA,MAAM,IAAA,GAAO,cAAc,IAAA,CAAK,mBAAA;AAChC,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,EAAE,IAAI,GAAA,EAAK,MAAA,EAAQ,MAAM,CAAA;AAE1C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,mBAAA,EAAA;AACL,MAAA,IAAA,CAAK,aAAA,GAAgB,GAAA;AACrB,MAAA,IAAI,IAAA,CAAK,mBAAA,IAAuB,IAAA,CAAK,sBAAA,EAAwB;AAC3D,QAAA,IAAA,CAAK,KAAA,EAAM;AAAA,MACb;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,mBAAA,GAAsB,CAAA;AAE3B,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAA,CAAK,UAAA,GAAa,GAAA;AAClB,MAAA,MAAM,SAAA,GAAY,KAAK,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CAAE,MAAA;AACpD,MAAA,IAAI,SAAA,IAAa,KAAK,YAAA,EAAc;AAClC,QAAA,IAAA,CAAK,KAAA,EAAM;AAAA,MACb;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAY,KAAK,MAAA,CAAO,MAAA;AAC9B,IAAA,IAAI,SAAA,IAAa,KAAK,iBAAA,EAAmB;AAIvC,MAAA,IAAA,CAAK,KAAA,EAAM;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,SAAA,GAAkB;AAChB,IAAA,IAAA,CAAK,KAAA,EAAM;AAAA,EACb;AAAA;AAAA,EAGA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEQ,KAAA,GAAc;AACpB,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AAC3B,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AACb,IAAA,IAAA,CAAK,QAAA,GAAW,KAAK,GAAA,EAAI;AAOzB,IAAA,IAAA,CAAK,SAAS,EAAC;AAEf,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,IAAS;AAAA,IAChB,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,MAAA,GAAe;AACrB,IAAA,MAAM,aAAA,GAAgB,KAAK,KAAA,KAAU,QAAA;AACrC,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAA;AACb,IAAA,IAAA,CAAK,mBAAA,GAAsB,CAAA;AAC3B,IAAA,IAAA,CAAK,SAAS,EAAC;AACf,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAGhB,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,OAAA,IAAU;AAAA,MACjB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGQ,qBAAA,GAA8B;AACpC,IAAA,IAAI,IAAA,CAAK,KAAA,KAAU,MAAA,IAAU,IAAA,CAAK,aAAa,IAAA,EAAM;AACrD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,QAAA;AAClC,IAAA,IAAI,OAAA,IAAW,KAAK,UAAA,EAAY;AAC9B,MAAA,IAAA,CAAK,KAAA,GAAQ,WAAA;AACb,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,aAAa,GAAA,EAAmB;AACtC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,QAAA;AAC1B,IAAA,IAAA,CAAK,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,MAAM,CAAA;AAAA,EACxD;AACF,CAAA;;;ACnQA,IAAM,uBAAA,GAAoC;AAAA;AAAA,EAExC,4NAAA;AAAA;AAAA,EAEA,iCAAA;AAAA,EACA,gDAAA;AAAA;AAAA,EAEA,iJAAA;AAAA;AAAA;AAAA,EAGA;AACF,CAAA;AAMO,SAAS,cAAc,GAAA,EAAqB;AACjD,EAAA,IAAI,MAAA,GAAS,GAAA;AACb,EAAA,KAAA,MAAW,WAAW,uBAAA,EAAyB;AAC7C,IAAA,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,OAAA,EAAS,CAAC,KAAA,KAAU;AAG1C,MAAA,MAAM,EAAA,GAAK,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC5B,MAAA,MAAM,EAAA,GAAK,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA;AAC5B,MAAA,MAAM,KAAA,GAAQ,OAAO,EAAA,GAAK,GAAA,GAAM,OAAO,EAAA,GAAK,KAAA,CAAM,EAAE,CAAA,GAAI,IAAA;AACxD,MAAA,IAAI,UAAU,IAAA,EAAM;AAClB,QAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,QAAQ,aAAA,CAAc,KAAK,CAAC,CAAA,GAAI,CAAC,CAAA;AACnE,QAAA,OAAO,GAAG,IAAI,CAAA,UAAA,CAAA;AAAA,MAChB;AAGA,MAAA,MAAM,UAAU,KAAA,CAAM,KAAA,CAAM,4BAA4B,CAAA,GAAI,CAAC,CAAA,IAAK,KAAA;AAClE,MAAA,OAAO,GAAG,OAAO,CAAA,aAAA,CAAA;AAAA,IACnB,CAAC,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT;AA0BA,IAAM,gBAAA,GAAmB,GAAA;AAelB,SAAS,cAAc,GAAA,EAAsB;AAClD,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,UAAA,EAAY,CAAC,MAAA,EAAQ,OAAO,GAAG,CAAA,EAAG,IAAA,EAAM,IAAI,CAAA,EAAG;AAAA,MACjE,KAAA,EAAO,QAAA;AAAA,MACP,WAAA,EAAa;AAAA,KACd,CAAA;AAMD,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AAAA,IAAC,CAAC,CAAA;AAC1B,IAAA,KAAA,CAAM,KAAA,EAAM;AACZ,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,IAAM,sBAAN,MAA0B;AAAA,EACd,SAAA,uBAAgB,GAAA,EAA4B;AAAA,EAC5C,OAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,eAAA,GAAkB,CAAA;AAAA,EAClB,aAAA,GAAsD,IAAA;AAAA,EACtD,eAAA,GAAiC,IAAA;AAAA,EACjC,4BAAwD,EAAC;AAAA,EAEjE,YAAY,aAAA,EAAsC;AAChD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,cAAA,CAAe,aAAa,CAAA;AAE/C,IAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,GAAS,MAAM,IAAA,CAAK,iBAAA,EAAkB;AACnD,IAAA,IAAA,CAAK,OAAA,CAAQ,OAAA,GAAU,MAAM,IAAA,CAAK,oBAAA,EAAqB;AAEvD,IAAA,IAAA,CAAK,OAAA,CAAQ,WAAW,KAAK,CAAA;AAAA,EAC/B;AAAA,EAEA,SAAS,IAAA,EAAgG;AACvG,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,IAAA,CAAK,GAAA,EAAK,EAAE,GAAG,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,IAAA,CAAK,SAAA,IAAa,OAAO,CAAA;AAAA,EAC7F;AAAA,EAEQ,iBAAiB,GAAA,EAAsB;AAC7C,IAAA,OAAO,MAAA,CAAO,SAAA,CAAU,GAAG,CAAA,IAAK,GAAA,GAAM,KAAK,GAAA,KAAQ,OAAA,CAAQ,GAAA,IAAO,GAAA,KAAQ,OAAA,CAAQ,IAAA;AAAA,EACpF;AAAA,EAEQ,uBAAuB,CAAA,EAA4B;AACzD,IAAA,OACK,aAAS,KAAM,OAAA,IAClB,EAAE,kBAAA,KAAuB,IAAA,IACzB,KAAK,gBAAA,CAAiB,CAAA,CAAE,GAAG,CAAA,IAC3B,OAAO,EAAE,KAAA,CAAM,GAAA,KAAQ,YACvB,CAAA,CAAE,KAAA,CAAM,QAAQ,CAAA,CAAE,GAAA;AAAA,EAEtB;AAAA,EAEQ,gBAAA,CAAiB,GAAmB,MAAA,EAA8B;AACxE,IAAA,IAAI;AACF,MAAA,CAAA,CAAE,KAAA,CAAM,KAAK,MAAM,CAAA;AAAA,IACrB,CAAA,CAAA,MAAQ;AAAA,IAGR;AAAA,EACF;AAAA,EAEQ,UAAA,CAAW,GAAmB,MAAA,EAA8B;AAClE,IAAA,IAAI,IAAA,CAAK,sBAAA,CAAuB,CAAC,CAAA,EAAG;AAClC,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,CAAE,GAAA,EAAK,MAAM,CAAA;AAC3B,QAAA;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,IAAA,CAAK,gBAAA,CAAiB,GAAG,MAAM,CAAA;AAAA,EACjC;AAAA;AAAA,EAGA,WAAW,GAAA,EAAmB;AAC5B,IAAA,IAAA,CAAK,SAAA,CAAU,OAAO,GAAG,CAAA;AAAA,EAC3B;AAAA;AAAA,EAGA,IAAI,GAAA,EAAyC;AAC3C,IAAA,IAAA,CAAK,YAAY,GAAG,CAAA;AACpB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA;AAAA,EAC/B;AAAA;AAAA,EAGA,IAAA,GAAyB;AACvB,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AAAA,EAC3C;AAAA;AAAA,EAGA,OAAO,IAAA,EAAgC;AACrC,IAAA,OAAO,IAAA,CAAK,MAAK,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,IAAI,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,UAAU,SAAA,EAAqC;AAC7C,IAAA,OAAO,IAAA,CAAK,MAAK,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,SAAS,CAAA;AAAA,EAC5D;AAAA;AAAA,EAGA,IAAI,WAAA,GAAsB;AACxB,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,SAAA,CAAU,MAAA,EAAO,EAAG;AACvC,MAAA,IAAI,CAAC,EAAE,MAAA,EAAQ,CAAA,EAAA;AAAA,IACjB;AACA,IAAA,OAAO,CAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAuB;AACrB,IAAA,OAAO;AAAA,MACL,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,UAAA,EAAY,KAAK,SAAA,CAAU,IAAA;AAAA,MAC3B,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,QAAA;AAAS,KACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,UAAA,GAAsB;AACxB,IAAA,OAAO,KAAK,OAAA,CAAQ,UAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAA,CAAW,SAAS,KAAA,EAAgB;AAClC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAA,CAAU,UAAA,EAAoB,MAAA,EAAiB,MAAA,GAAS,KAAA,EAAa;AACnE,IAAA,IAAA,CAAK,OAAA,CAAQ,SAAA,CAAU,UAAA,EAAY,MAAA,EAAQ,MAAM,CAAA;AAAA,EACnD;AAAA;AAAA,EAGA,gBAAA,GAAyB;AACvB,IAAA,IAAA,CAAK,QAAQ,SAAA,EAAU;AAAA,EACzB;AAAA;AAAA,EAGA,iBAAA,GAA0B;AACxB,IAAA,IAAA,CAAK,QAAQ,UAAA,EAAW;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,iBAAiB,GAAA,EAAoF;AACnG,IAAA,IAAI,IAAI,OAAA,KAAY,MAAA,OAAgB,OAAA,CAAQ,UAAA,CAAW,IAAI,OAAO,CAAA;AAClE,IAAA,IAAI,GAAA,CAAI,oBAAoB,MAAA,EAAW,IAAA,CAAK,kBAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,GAAA,CAAI,eAAe,CAAA;AAE7F,IAAA,IAAI,IAAA,CAAK,mBAAmB,CAAA,EAAG;AAC7B,MAAA,IAAA,CAAK,oBAAA,EAAqB;AAC1B,MAAA;AAAA,IACF;AAIA,IAAA,IAAI,IAAA,CAAK,QAAQ,SAAA,IAAa,IAAA,CAAK,QAAQ,QAAA,EAAS,CAAE,UAAU,MAAA,EAAQ;AACtE,MAAA,IAAA,CAAK,iBAAA,EAAkB;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAA,GAA+C;AAC7C,IAAA,IAAI,KAAK,eAAA,KAAoB,IAAA,IAAQ,IAAA,CAAK,eAAA,IAAmB,GAAG,OAAO,IAAA;AACvE,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,eAAA;AAClC,IAAA,OAAO,EAAE,WAAA,EAAa,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,eAAA,GAAkB,OAAO,CAAA,EAAG,OAAA,EAAS,IAAA,CAAK,eAAA,EAAgB;AAAA,EACnG;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAAyB,QAAA,EAAgD;AACvE,IAAA,IAAA,CAAK,yBAAA,CAA0B,KAAK,QAAQ,CAAA;AAC5C,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,4BAA4B,IAAA,CAAK,yBAAA,CAA0B,OAAO,CAAC,CAAA,KAAM,MAAM,QAAQ,CAAA;AAAA,IAC9F,CAAA;AAAA,EACF;AAAA,EAEQ,qBAAA,GAA8B;AACpC,IAAA,MAAM,IAAA,GAAO,KAAK,mBAAA,EAAoB;AACtC,IAAA,KAAA,MAAW,CAAA,IAAK,KAAK,yBAAA,EAA2B;AAC9C,MAAA,IAAI;AACF,QAAA,CAAA,CAAE,IAAI,CAAA;AAAA,MACR,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iBAAA,GAA0B;AAChC,IAAA,IAAI,KAAK,eAAA,IAAmB,CAAA,IAAK,CAAC,IAAA,CAAK,QAAQ,SAAA,EAAW;AAC1D,IAAA,IAAA,CAAK,mBAAA,EAAoB;AACzB,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,GAAA,EAAI;AAChC,IAAA,IAAA,CAAK,aAAA,GAAgB,WAAW,MAAM;AACpC,MAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAEvB,MAAA,IAAA,CAAK,OAAA,CAAQ,EAAE,KAAA,EAAO,KAAA,EAAO,CAAA;AAC7B,MAAA,IAAA,CAAK,QAAQ,UAAA,EAAW;AACxB,MAAA,IAAA,CAAK,qBAAA,EAAsB;AAAA,IAC7B,CAAA,EAAG,KAAK,eAAe,CAAA;AAEvB,IAAA,IAAA,CAAK,cAAc,KAAA,IAAQ;AAC3B,IAAA,IAAA,CAAK,qBAAA,EAAsB;AAAA,EAC7B;AAAA,EAEQ,oBAAA,GAA6B;AACnC,IAAA,MAAM,QAAA,GAAW,KAAK,eAAA,KAAoB,IAAA;AAC1C,IAAA,IAAA,CAAK,mBAAA,EAAoB;AACzB,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AACvB,MAAA,IAAA,CAAK,qBAAA,EAAsB;AAAA,IAC7B;AAAA,EACF;AAAA,EAEQ,mBAAA,GAA4B;AAClC,IAAA,IAAI,IAAA,CAAK,kBAAkB,IAAA,EAAM;AAC/B,MAAA,YAAA,CAAa,KAAK,aAAa,CAAA;AAC/B,MAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,IAAA,CAAK,GAAA,EAAa,IAAA,GAAiB,EAAC,EAAY;AAC9C,IAAA,IAAA,CAAK,YAAY,GAAG,CAAA;AACpB,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA;AAChC,IAAA,IAAI,CAAC,GAAG,OAAO,KAAA;AACf,IAAA,IAAI,CAAA,CAAE,QAAQ,OAAO,IAAA;AACrB,IAAA,IAAI,CAAA,CAAE,WAAW,OAAO,KAAA;AAExB,IAAA,MAAM,EAAE,KAAA,GAAQ,KAAA,EAAO,OAAA,GAAU,kBAAiB,GAAI,IAAA;AACtD,IAAA,MAAMC,MAAAA,GAAW,aAAS,KAAM,OAAA;AAEhC,IAAA,IAAIA,MAAAA,EAAO;AAWT,MAAA,MAAM,aAAA,GAAgB,EAAE,KAAA,CAAM,QAAA,KAAa,QAAQ,OAAO,CAAA,CAAE,MAAM,GAAA,KAAQ,QAAA;AAC1E,MAAA,IAAI,aAAA,IAAiB,aAAA,CAAc,GAAG,CAAA,EAAG;AACvC,QAAA,MAAM,QAAA,GAAW,WAAW,MAAM;AAChC,UAAA,IAAI,CAAA,CAAE,KAAA,CAAM,QAAA,KAAa,IAAA,EAAM;AAC7B,YAAA,IAAI;AACF,cAAA,CAAA,CAAE,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,YACxB,CAAA,CAAA,MAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF,GAAG,OAAO,CAAA;AACV,QAAA,QAAA,CAAS,KAAA,IAAQ;AAAA,MACnB,CAAA,MAAO;AACL,QAAA,IAAI;AACF,UAAA,CAAA,CAAE,KAAA,CAAM,IAAA,CAAK,KAAA,GAAQ,SAAA,GAAY,SAAS,CAAA;AAAA,QAC5C,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,CAAA,CAAE,MAAA,GAAS,IAAA;AACX,MAAA,OAAO,IAAA;AAAA,IACT;AAKA,IAAA,IAAI;AACF,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,IAAA,CAAK,UAAA,CAAW,GAAG,SAAS,CAAA;AAAA,MAC9B,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,UAAA,CAAW,GAAG,SAAS,CAAA;AAE5B,QAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAE7B,UAAA,IAAI,IAAA,CAAK,UAAU,GAAA,CAAI,GAAG,KAAK,CAAC,CAAA,CAAE,MAAM,MAAA,EAAQ;AAC9C,YAAA,IAAA,CAAK,UAAA,CAAW,GAAG,SAAS,CAAA;AAAA,UAC9B;AAAA,QACF,GAAG,OAAO,CAAA;AACV,QAAA,KAAA,CAAM,KAAA,IAAQ;AAAA,MAChB;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,CAAA,CAAE,MAAA,GAAS,IAAA;AACX,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAA,CAAQ,IAAA,GAAiB,EAAC,EAAa;AACrC,IAAA,MAAM,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAC7C,IAAA,MAAM,SAAmB,EAAC;AAC1B,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA;AAChC,MAAA,IAAI,CAAA,IAAK,CAAC,CAAA,CAAE,SAAA,IAAa,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,IAAI,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAAA,IAChE;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAA,CAAY,SAAA,EAAmB,IAAA,GAAiB,EAAC,EAAa;AAC5D,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU,SAAS,EAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,GAAG,CAAA;AACvD,IAAA,MAAM,SAAmB,EAAC;AAC1B,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,IAAI,KAAK,IAAA,CAAK,GAAA,EAAK,IAAI,CAAA,EAAG,MAAA,CAAO,KAAK,GAAG,CAAA;AAAA,IAC3C;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBQ,cAAc,KAAA,EAAgC;AACpD,IAAA,OAAO,KAAA,CAAM,MAAM,QAAA,KAAa,IAAA,IAAQ,KAAK,GAAA,EAAI,GAAI,MAAM,SAAA,GAAY,GAAA;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAY,GAAA,EAAmB;AACrC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA;AACpC,IAAA,IAAI,KAAA,IAAS,IAAA,CAAK,aAAA,CAAc,KAAK,CAAA,EAAG;AACtC,MAAA,IAAA,CAAK,SAAA,CAAU,OAAO,GAAG,CAAA;AAAA,IAC3B;AAAA,EACF;AACF,CAAA;AAGA,IAAI,SAAA;AAEG,SAAS,kBAAA,GAA0C;AACxD,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,SAAA,GAAY,IAAI,mBAAA,EAAoB;AAAA,EACtC;AACA,EAAA,OAAO,SAAA;AACT;AC7gBO,SAAS,oBAAoB,GAAA,EAAqB;AACvD,EAAA,IAAI,OAAA,CAAQ,QAAA,KAAa,OAAA,EAAS,OAAO,GAAA;AAKzC,EAAA,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,IAAK,IAAI,QAAA,CAAS,IAAI,CAAA,IAAUC,KAAA,CAAA,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAC,CAAA,EAAG;AACrF,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAA,CAAW,QAAQ,GAAA,CAAI,SAAS,KAAK,uCAAA,EACxC,WAAA,EAAY,CACZ,KAAA,CAAM,GAAG,CAAA;AAEZ,EAAA,MAAM,YAAY,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,IAAK,EAAA,EAAI,MAAWA,KAAA,CAAA,SAAS,CAAA;AAEjE,EAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,IAAA,MAAM,IAAA,GAAYA,KAAA,CAAA,IAAA,CAAK,GAAA,EAAK,GAAG,CAAA;AAG/B,IAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,MAAA,MAAM,IAAA,GAAO,CAAA,EAAG,IAAI,CAAA,EAAG,GAAG,CAAA,CAAA;AAC1B,MAAA,IAAI;AACF,QAAG,EAAA,CAAA,UAAA,CAAW,IAAA,EAAS,EAAA,CAAA,SAAA,CAAU,IAAI,CAAA;AACrC,QAAA,OAAO,IAAA;AAAA,MACT,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAIA,EAAA,OAAO,GAAA;AACT;AAqDA,IAAM,gBAAA,GAAmB,eAAA;AAYlB,SAAS,yBAAyB,IAAA,EAAgC;AACvE,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,gBAAA,CAAiB,IAAA,CAAK,GAAG,CAAA,EAAG;AACzD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,0MAAA,GAGE,IAAA,CAAK,SAAA,CAAU,GAAG;AAAA,OACtB;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,2BAAA,CACd,OAAA,EACA,IAAA,GAA0B,EAAC,EACH;AACxB,EAAA,wBAAA,CAAyB,CAAC,OAAA,EAAS,GAAG,IAAI,CAAC,CAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,CAAC,MAAA,EAAQ,gBAAA,CAAiB,OAAO,CAAA,EAAG,GAAG,IAAA,CAAK,GAAA,CAAI,gBAAgB,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AACxF,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,IAAK,SAAA;AAAA,IACnC,IAAA,EAAM,CAAC,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA;AAAA,IACvB,wBAAA,EAA0B;AAAA,GAC5B;AACF;AAEA,SAAS,iBAAiB,GAAA,EAAqB;AAC7C,EAAA,OAAO,IAAI,GAAG,CAAA,CAAA,CAAA;AAChB;;;AC/HA,IAAM,KAAA,GAAQ,QAAQ,QAAA,KAAa,OAAA;AAWnC,IAAM,wBAAA,uBAAoD,GAAA,CAAI;AAAA;AAAA,EAE5D,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,MAAA;AAAA,EAC7C,UAAA;AAAA,EAAY,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,MAAA;AAAA,EACvD,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,UAAA;AAAA,EAAY,OAAA;AAAA,EAAS,IAAA;AAAA,EAAM,SAAA;AAAA,EAAW,QAAA;AAAA,EACzD,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,YAAA;AAAA,EAAc,SAAA;AAAA;AAAA,EAEzC,KAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EAAS,OAAA;AAAA;AAAA,EAET,IAAA;AAAA;AAAA,EAEA,QAAA;AAAA,EAAU,SAAA;AAAA,EAAW,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,MAAA;AAAA,EACtD,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,KAAA;AAAA;AAAA,EAEhC,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,QAAA;AAAA;AAAA,EAEf,KAAA;AAAA,EAAO,UAAA;AAAA,EAAY,SAAA;AAAA;AAAA,EAEnB,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,QAAA;AAAA,EAAU,SAAA;AAAA;AAAA,EAElC,QAAA;AAAA;AAAA,EAEA,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,UAAA;AAAA,EAAY,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,SAAA;AAAA;AAAA,EAErE,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,SAAA;AAAA;AAAA,EAEpB,MAAA;AAAA,EAAQ,MAAA;AAAA;AAAA,EAER,KAAA;AAAA,EAAO,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,MAAA;AAAA,EACxD,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,OAAA;AAAA,EAAS,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,IAAA;AAAA,EAC3D,OAAA;AAAA,EAAS,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,IAAA;AAAA,EACA,OAAA;AAAA,EAAS,UAAA;AAAA,EAAY,YAAA;AAAA,EAAc,MAAA;AAAA,EAAQ,IAAA;AAAA,EAC3C,SAAA;AAAA,EAAW,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAW,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ9C,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,YAAA;AAAA,EAAc,gBAAA;AAAA,EAAkB,MAAA;AAAA,EAAQ,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1D,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,MAAA;AAAA;AAAA,EAErF,KAAA;AAAA,EAAO,UAAA;AAAA,EAAY,YAAA;AAAA;AAAA,EAEnB,SAAA;AAAA,EAAW,kBAAA;AAAA,EAAoB,eAAA;AAAA,EAAiB,cAAA;AAAA,EAAgB,gBAAA;AAAA,EAAkB,UAAA;AAAA;AAAA,EAElF,KAAA;AAAA,EAAO,WAAA;AAAA,EAAa,UAAA;AAAA,EAAY,IAAA;AAAA,EAAM,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,YAAA;AAAA;AAAA,EAE7E,SAAA;AAAA,EAAW,cAAA;AAAA,EAAgB,YAAA;AAAA,EAAc,QAAA;AAAA,EAAU,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,SAAA;AAAA,EAAW,eAAA;AAAA;AAAA,EAE5I,SAAA;AAAA,EAAW,QAAA;AAAA,EAAU,SAAA;AAAA,EAAW,QAAA;AAAA,EAAU,IAAA;AAAA,EAAM,UAAA;AAAA;AAAA,EAEhD,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,KAAA;AAAA,EAAO,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,MAAA;AAAA;AAAA,EAEzD,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,SAAA;AAAA;AAAA,EAE5C,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,IAAA;AAAA,EAAM,QAAA;AAAA;AAAA,EAEzE,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,YAAA;AAAA,EAAc,aAAA;AAAA,EAAe,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,WAAA;AAAA,EAAa,SAAA;AAAA,EAAW,MAAA;AAAA,EAAQ,SAAA;AAAA;AAAA,EAEtH,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,IAAA;AAAA,EAAM,QAAA;AAAA,EAAU,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,MAAA;AAAA;AAAA,EAExF,aAAA;AAAA,EAAe,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,WAAA;AAAA,EAAa,UAAA;AAAA,EAAY,MAAA;AAAA,EAAQ,UAAA;AAAA,EAAY,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,KAAA;AAAA,EAChH,gBAAA;AAAA,EAAkB,SAAA;AAAA,EAAW,QAAA;AAAA,EAAU,SAAA;AAAA,EAAW,KAAA;AAAA,EAAO,SAAA;AAAA;AAAA,EAEzD,SAAA;AAAA,EAAW,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,SAAA;AAAA,EAAW,YAAA;AAAA,EAAc,OAAA;AAAA,EAAS,YAAA;AAAA,EAAc,WAAA;AAAA,EAAa,SAAA;AAAA,EAAW,cAAA;AAAA,EACrG,WAAA;AAAA,EAAa,cAAA;AAAA,EAAgB,WAAA;AAAA,EAAa,SAAA;AAAA,EAAW,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,OAAA;AAAA,EACxE,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,WAAA;AAAA,EAAa,cAAA;AAAA;AAAA,EAE/D,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EAAU,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,MAAA;AAAA;AAAA,EAExE,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,KAAA;AAAA,EAAO,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxC,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,UAAA;AAAA,EAAY,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,QAAA;AAAA,EAAU,OAAA;AAAA,EACzG,KAAA;AAAA,EAAO,IAAA;AAAA,EAAM,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,GAAA;AAAA,EAAK,QAAA;AAAA,EAC5F,KAAA;AAAA,EACA,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,SAAA;AAAA,EAAW,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,SAAA;AAAA,EAAW,IAAA;AAAA,EAAM,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,MAAA;AAAA,EACpH,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,SAAA;AAAA,EAAW,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,GAAA;AAAA,EAAK,OAAA;AAAA,EAAS,SAAA;AAAA,EACzG,KAAA;AAAA,EAAO,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,UAAA;AAAA,EAAY,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,MAAA;AAAA;AAAA,EAE7E,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,SAAA;AAAA,EAAW,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,KAAA;AAAA,EACpI,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,OAAA;AAAA,EAChD,MAAA;AAAA,EAAQ,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,IAAA;AAAA,EAAM,QAAA;AAAA;AAAA,EAEpD,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,KAAA;AAAA,EAAO,WAAA;AAAA,EAAa,SAAA;AAAA,EAAW,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,IAAA;AAAA,EAAM,MAAA;AAAA,EAAQ,OAAA;AAAA;AAAA,EAEhI,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,WAAA;AAAA,EAAa,WAAA;AAAA,EAAa,WAAA;AAAA,EAAa,eAAA;AAAA;AAAA,EAEnE,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,QAAA;AAAA,EAAU,QAAA;AAAA;AAAA,EAEhI,SAAA;AAAA,EAAW,QAAA;AAAA,EAAU,WAAA;AAAA;AAAA,EAErB,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,eAAA;AAAA,EAAiB,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,IAAA;AAAA,EAAM,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,IAAA;AAAA;AAAA,EAEpI,WAAA;AAAA,EAAa,QAAA;AAAA,EAAU,cAAA;AAAA,EAAgB,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,QAAA;AAAA;AAAA,EAErF,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,GAAA;AAAA,EAAK,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,KAAA;AAAA;AAAA,EAEjH,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,SAAA;AAAA,EAAW,OAAA;AAAA,EACvD,KAAA;AAAA,EAAO,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,UAAA;AAAA,EAC/C,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,SAAA;AAAA,EACzB,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,UAAA;AAAA,EAAY,cAAA;AAAA;AAAA,EAEvC,UAAA;AAAA,EAAY,kBAAA;AAAA,EAAoB,gBAAA;AAAA,EAAkB,cAAA;AAAA,EAAgB,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,SAAA;AAAA,EACpF,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,SAAA;AAAA,EAAW,WAAA;AAAA,EAAa,YAAA;AAAA;AAAA,EAEzC,QAAA;AAAA,EAAU,WAAA;AAAA,EAAa,UAAA;AAAA,EAAY,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,MAAA;AAAA;AAAA,EAEvD,QAAA;AAAA,EAAU,YAAA;AAAA,EAAc,aAAA;AAAA,EAAe,eAAA;AAAA,EAAiB,QAAA;AAAA,EAAU,KAAA;AAAA,EAAO,UAAA;AAAA,EAAY,eAAA;AAAA,EAAiB,OAAA;AAAA,EAAS,WAAA;AAAA;AAAA,EAE/G,SAAA;AAAA,EAAW,aAAA;AAAA,EAAe,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,UAAA;AAAA;AAAA,EAEhD,QAAA;AAAA,EAAU,UAAA;AAAA,EAAY,SAAA;AAAA,EAAW,cAAA;AAAA;AAAA,EAEjC,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,WAAA;AAAA,EAAa,kBAAA;AAAA,EAAoB,YAAA;AAAA;AAAA,EAE/D,OAAA;AAAA,EAAS,cAAA;AAAA,EAAgB,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,aAAA;AAAA,EAAe,aAAA;AAAA;AAAA,EAEzF,SAAA;AAAA,EAAW,aAAA;AAAA,EAAe,OAAA;AAAA,EAAS,UAAA;AAAA,EAAY,OAAA;AAAA,EAAS,SAAA;AAAA,EAAW,SAAA;AAAA;AAAA,EAEnE,SAAA;AAAA,EAAW,MAAA;AAAA,EAAQ,UAAA;AAAA,EAAY,OAAA;AAAA,EAAS,WAAA;AAAA,EAAa,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,aAAA;AAAA,EAAe,WAAA;AAAA,EAAa,KAAA;AAAA,EAAO,aAAA;AAAA,EAAe,UAAA;AAAA,EAAY,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW;AAChM,CAAC,CAAA;AAID,IAAI,eAAA,GAA+B,IAAI,GAAA,CAAI,wBAAwB,CAAA;AAEnE,IAAM,YAAA,GAAe,CAAC,CAAA,KAAsB,CAAA,CAAE,IAAA,EAAK;AAW5C,SAAS,mBAAA,CAAoB,IAAA,GAAwF,EAAC,EAAS;AACpI,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,wBAAwB,CAAA;AAC7C,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,KAAA,IAAS,EAAC,EAAG;AAChC,IAAA,MAAM,CAAA,GAAI,aAAa,CAAC,CAAA;AACxB,IAAA,IAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AAAA,EACnB;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,KAAK,IAAA,IAAQ,IAAI,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,CAAC,CAAC,CAAA;AAC5D,EAAA,eAAA,GAAkB,IAAA;AACpB;AAGO,SAAS,eAAA,GAAwB;AACtC,EAAA,eAAA,GAAkB,IAAI,IAAI,wBAAwB,CAAA;AACpD;AAGO,SAAS,qBAAqB,GAAA,EAAsB;AACzD,EAAA,OAAO,eAAA,CAAgB,GAAA,CAAI,YAAA,CAAa,GAAG,CAAC,CAAA;AAC9C;AAGO,SAAS,gBAAA,GAA6B;AAC3C,EAAA,OAAO,CAAC,GAAG,eAAe,CAAA,CAAE,IAAA,EAAK;AACnC;AAEA,IAAM,QAAA,GAAW,EAAA;AAKjB,IAAM,UAAA,GAAa,GAAA;AACnB,IAAM,kBAAA,GAAqB,GAAA;AAM3B,IAAM,oBAAA,GAAiD;AAAA,EACrD,QAAQ,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT,GAAA,EAAK;AAAA,IACH,UAAA;AAAA,IACA,iBAAA;AAAA,IACA,kBAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,IACA,YAAA;AAAA,IACA,MAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,MAAM,EAAC;AAAA,EACP,IAAI,EAAC;AAAA,EACL,KAAK,EAAC;AAAA,EACN,QAAQ,EAAC;AAAA;AAAA,EAET,IAAA,EAAM,CAAC,SAAA,EAAW,UAAA,EAAY,OAAA,EAAS,UAAU,YAAA,EAAc,aAAA,EAAe,SAAA,EAAW,OAAA,EAAS,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9G,EAAA,EAAI,CAAC,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,QAAQ,QAAA,EAAU,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,MAAM,CAAA;AAAA;AAAA;AAAA,EAG1E,KAAK,EAAC;AAAA,EACN,MAAM,EAAC;AAAA,EACP,KAAK;AACP,CAAA;AAKA,IAAM,mBAAA,GAA2D;AAAA,EAC/D,MAAA,kBAAQ,IAAI,GAAA,CAAI,CAAC,MAAM,CAAC,CAAA;AAAA,EACxB,MAAA,kBAAQ,IAAI,GAAA,CAAI,CAAC,MAAM,CAAC,CAAA;AAAA,EACxB,qBAAK,IAAI,GAAA,CAAI,CAAC,SAAA,EAAW,QAAQ,CAAC,CAAA;AAAA,EAClC,sBAAM,IAAI,GAAA,CAAI,CAAC,SAAA,EAAW,QAAQ,CAAC,CAAA;AAAA,EACnC,IAAA,kBAAM,IAAI,GAAA,CAAI,CAAC,SAAS,CAAC;AAC3B,CAAA;AAEA,IAAM,4BAAA,GAA+E;AAAA,EACnF,IAAA,EAAM,CAAC,CAAC,KAAA,EAAO,SAAS,CAAC;AAC3B,CAAA;AAEA,SAAS,gBAAgB,IAAA,EAA+B;AACtD,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,GAAA,KAAQ,MAAM,OAAO,IAAA;AACzB,IAAA,IAAI,CAAC,GAAA,CAAI,UAAA,CAAW,GAAG,GAAG,OAAO,GAAA;AAAA,EACnC;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,eAAe,IAAA,EAA0B;AAChD,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,QAAQ,IAAA,EAAM;AAClB,IAAA,IAAI,CAAC,GAAA,CAAI,UAAA,CAAW,GAAG,CAAA,EAAG,GAAA,CAAI,KAAK,GAAG,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,YAAA,CAAa,KAAa,IAAA,EAA+B;AAChE,EAAA,MAAM,kBAAA,GAAqB,oBAAoB,GAAG,CAAA;AAClD,EAAA,MAAM,UAAA,GAAa,gBAAgB,IAAI,CAAA;AACvC,EAAA,IAAI,kBAAA,IAAsB,UAAA,IAAc,kBAAA,CAAmB,GAAA,CAAI,UAAU,CAAA,EAAG;AAC1E,IAAA,OAAO,CAAA,oBAAA,EAAuB,UAAU,CAAA,eAAA,EAAkB,GAAG,CAAA,CAAA,CAAA;AAAA,EAC/D;AAEA,EAAA,MAAM,gBAAA,GAAmB,6BAA6B,GAAG,CAAA;AACzD,EAAA,IAAI,gBAAA,EAAkB;AACpB,IAAA,MAAM,MAAA,GAAS,eAAe,IAAI,CAAA;AAClC,IAAA,MAAMC,QAAAA,GAAU,gBAAA,CAAiB,IAAA,CAAK,CAAC,QAAQ,GAAA,CAAI,KAAA,CAAM,CAAC,IAAA,EAAM,GAAA,KAAQ,MAAA,CAAO,GAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AAC7F,IAAA,IAAIA,QAAAA,SAAgB,CAAA,oBAAA,EAAuBA,QAAAA,CAAQ,KAAK,GAAG,CAAC,kBAAkB,GAAG,CAAA,CAAA,CAAA;AAAA,EACnF;AAEA,EAAA,MAAM,OAAA,GAAU,qBAAqB,GAAG,CAAA;AACxC,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAErB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,KAAA,MAAW,WAAW,OAAA,EAAS;AAC7B,MAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,EAAG;AACrB,QAAA,OAAO,CAAA,kBAAA,EAAqB,GAAG,CAAA,eAAA,EAAkB,GAAG,+BAA+B,OAAO,CAAA,CAAA,CAAA;AAAA,MAC5F;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAmBO,IAAM,QAAA,GAAwC;AAAA,EACnD,IAAA,EAAM,MAAA;AAAA,EACN,QAAA,EAAU,OAAA;AAAA,EACV,WAAA,EACE,sTAAA;AAAA,EAGF,SAAA,EACE,wuBAAA;AAAA,EAOF,UAAA,EAAY,SAAA;AAAA,EACZ,QAAA,EAAU,IAAA;AAAA,EACV,QAAA,EAAU,UAAA;AAAA,EACV,SAAA,EAAW,kBAAA;AAAA,EACX,YAAA,EAAc,CAAC,kBAAkB,CAAA;AAAA,EACjC,IAAA,EAAM,UAAA;AAAA,EACN,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,QAAA;AAAA,IACN,UAAA,EAAY;AAAA,MACV,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,IAAA,EAAM,OAAA;AAAA,QACN,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,QACxB,WAAA,EAAa;AAAA,OACf;AAAA,MACA,GAAA,EAAK;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,SAAA;AAAA,QACN,WAAA,EAAa;AAAA;AACf,KACF;AAAA,IACA,QAAA,EAAU,CAAC,SAAS;AAAA,GACtB;AAAA,EACA,MAAM,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM;AAC9B,IAAA,MAAM,WAAW,kBAAA,EAAmB;AACpC,IAAA,IAAI,CAAC,SAAS,UAAA,EAAY;AACxB,MAAA,OAAO;AAAA,QACL,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,IAAA,EAAM,KAAA,CAAM,IAAA,IAAQ,EAAC;AAAA,QACrB,MAAA,EAAQ,EAAA;AAAA,QACR,MAAA,EAAQ,2FAAA;AAAA,QACR,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW,KAAA;AAAA,QACX,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAK;AAC/B,IAAA,IAAI,CAAC,GAAA;AACH,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,GAAA;AAAA,QACT,MAAM,EAAC;AAAA,QACP,MAAA,EAAQ,EAAA;AAAA,QACR,MAAA,EAAQ,eAAA;AAAA,QACR,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW,KAAA;AAAA,QACX,OAAA,EAAS;AAAA,OACX;AAEF,IAAA,IAAI,CAAC,oBAAA,CAAqB,GAAG,CAAA,EAAG;AAC9B,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,GAAA;AAAA,QACT,IAAA,EAAM,KAAA,CAAM,IAAA,IAAQ,EAAC;AAAA,QACrB,MAAA,EAAQ,EAAA;AAAA,QACR,MAAA,EACE,CAAA,SAAA,EAAY,GAAG,CAAA,mGAAA,EACmE,GAAG,CAAA,4DAAA,CAAA;AAAA,QAEvF,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW,KAAA;AAAA,QACX,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AAEA,IAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,IAAQ,EAAC,EAAG,KAAA,CAAM,GAAG,QAAQ,CAAA;AACjD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAI,KAAA,CAAM,OAAA,IAAW,kBAAA,EAAoB,kBAAkB,CAAC,CAAA;AAG7F,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,GAAA,EAAK,IAAI,CAAA;AACvC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,GAAA;AAAA,QACT,IAAA;AAAA,QACA,MAAA,EAAQ,EAAA;AAAA,QACR,MAAA,EAAQ,QAAA;AAAA,QACR,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW,KAAA;AAAA,QACX,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AAEA,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AAGF,MAAA,GAAA,GAAM,KAAA,CAAM,GAAA,GAAM,MAAM,eAAA,CAAgB,KAAA,CAAM,GAAA,EAAK,GAAG,CAAA,GAAI,MAAM,eAAA,CAAgB,GAAA,CAAI,GAAA,EAAK,GAAG,CAAA;AAAA,IAC9F,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,GAAA;AAAA,QACT,IAAA;AAAA,QACA,MAAA,EAAQ,EAAA;AAAA,QACR,MAAA,EAAQ,CAAA,KAAA,EAAQ,KAAA,CAAM,GAAA,IAAO,IAAI,GAAG,CAAA,+BAAA,CAAA;AAAA,QACpC,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW,KAAA;AAAA,QACX,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AACA,IAAA,MAAM,SAAS,IAAA,CAAK,MAAA;AAEpB,IAAA,OAAO,UAAA,CAAW,KAAK,IAAA,EAAM,GAAA,EAAK,SAAS,MAAA,EAAQ,GAAA,CAAI,SAAS,EAAE,CAAA;AAAA,EACpE;AACF;AAEA,SAAS,WACP,GAAA,EACA,IAAA,EACA,GAAA,EACA,OAAA,EACA,QACA,SAAA,EACqB;AACrB,EAAA,OAAO,IAAI,OAAA,CAAQ,CAACC,QAAAA,KAAY;AAC9B,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,KAAA;AACb,IAAA,MAAM,YAAA,GAAe,EAAE,KAAA,EAAO,KAAA,EAAM;AACpC,IAAA,MAAM,MAAA,GAAS,CAAC,MAAA,KAA6B;AAK3C,MAAA,IAAI,aAAa,KAAA,EAAO;AACxB,MAAA,YAAA,CAAa,KAAA,GAAQ,IAAA;AACrB,MAAAA,SAAQ,MAAM,CAAA;AAAA,IAChB,CAAA;AACA,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAI3B,IAAA,MAAM,KAAA,GAAQ,kBAAkB,EAAE,IAAA,EAAM,QAAQ,GAAG,CAAA,CAAA,EAAI,cAAA,EAAgB,UAAA,EAAY,CAAA;AAKnF,IAAA,MAAM,QAAA,GAAW,oBAAoB,GAAG,CAAA;AACxC,IAAA,MAAM,UAAA,GAAa,UAAU,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,IAAK,QAAA,CAAS,SAAS,MAAM,CAAA,CAAA;AAClF,IAAA,MAAM,IAAA,GAAO,UAAA,GAAa,2BAAA,CAA4B,QAAA,EAAU,IAAI,CAAA,GAAI,IAAA;AACxE,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,IAAW,QAAA;AAClC,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,IAAQ,IAAA;AAQhC,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AAKF,MAAA,KAAA,GAAQC,KAAAA,CAAM,UAAU,SAAA,EAAW;AAAA,QACjC,GAAA;AAAA,QACA,GAAA,EAAK,cAAc,SAAS,CAAA;AAAA,QAC5B,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM,CAAA;AAAA,QAChC,WAAA,EAAa,IAAA;AAAA,QACb,GAAI,KAAA,GAAQ,EAAC,GAAI,EAAE,MAAA,EAAO;AAAA,QAC1B,GAAI,IAAA,GAAO,EAAE,0BAA0B,IAAA,CAAK,wBAAA,KAA6B;AAAC,OAC3E,CAAA;AAAA,IACH,SAAS,GAAA,EAAK;AAMZ,MAAA,KAAA,CAAM,QAAA,EAAS;AACf,MAAA,MAAA,CAAO;AAAA,QACL,OAAA,EAAS,GAAA;AAAA,QACT,IAAA;AAAA,QACA,MAAA,EAAQ,EAAA;AAAA,QACR,MAAA,EAAQ,CAAA,cAAA,EAAiB,cAAA,CAAe,GAAG,CAAC,CAAA,CAAA;AAAA,QAC5C,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW,KAAA;AAAA,QACX,OAAA,EAAS;AAAA,OACV,CAAA;AACD,MAAA;AAAA,IACF;AASA,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAKzB,MAAA,MAAM,OAAA,GAAU,GAAA,IAAQ,GAAA,CAA8B,IAAA,KAAS,WAAA;AAC/D,MAAA,MAAM,aAAa,OAAA,GAAU,CAAA,SAAA,EAAY,GAAA,CAAI,OAAO,KAAK,GAAA,CAAI,OAAA;AAC7D,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,IAAI,KAAA,EAAO,MAAA,CAAO,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AACtD,MAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,QAAA,CAAS,WAAW,GAAG,CAAA;AACpD,MAAA,QAAA,CAAS,SAAA,CAAU,IAAA,CAAK,GAAA,EAAI,GAAI,WAAW,IAAI,CAAA;AAC/C,MAAA,KAAA,CAAM,QAAA,EAAS;AACf,MAAA,MAAA,CAAO;AAAA,QACL,OAAA,EAAS,GAAA;AAAA,QACT,IAAA;AAAA,QACA,MAAA,EAAQ,uBAAuB,MAAM,CAAA;AAAA,QACrC,MAAA,EAAQ,UAAA;AAAA,QACR,QAAA,EAAU,UAAU,GAAA,GAAM,CAAA;AAAA,QAC1B,SAAA,EAAW,MAAA,CAAO,UAAA,CAAW,MAAA,EAAQ,MAAM,CAAA,GAAI,wBAAA;AAAA,QAC/C,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,MAAM,WAAW,kBAAA,EAAmB;AACpC,IAAA,MAAM,MAAM,KAAA,CAAM,GAAA;AAClB,IAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,MAAA,MAAM,cAAc,CAAA,EAAG,GAAG,IAAI,IAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAC5C,MAAA,QAAA,CAAS,QAAA,CAAS,EAAE,GAAA,EAAK,IAAA,EAAM,QAAQ,OAAA,EAAS,aAAA,CAAc,WAAW,CAAA,EAAG,WAAW,IAAA,CAAK,GAAA,EAAI,EAAG,SAAA,EAAW,OAAO,CAAA;AAAA,IACvH;AAEA,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,QAAA,CAAS,KAAK,GAAG,CAAA;AAAA,WACzC,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,IAC3B,GAAG,OAAO,CAAA;AAEV,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,IAAI,OAAO,QAAQ,QAAA,EAAU,QAAA,CAAS,KAAK,GAAA,EAAK,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA;AAAA,WAC1D,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,IAC3B,CAAA;AACA,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,IAAI,MAAA,CAAO,SAAS,OAAA,EAAQ;AAAA,kBAChB,gBAAA,CAAiB,OAAA,EAAS,SAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IAC/D;AAEA,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AAC1C,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,EAAS;AAC5B,MAAA,IAAI,MAAA,CAAO,MAAA,GAAS,UAAA,EAAY,MAAA,IAAU,IAAA;AAC1C,MAAA,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,IAClB,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AAC1C,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,EAAS;AAC5B,MAAA,IAAI,MAAA,CAAO,MAAA,GAAS,UAAA,EAAY,MAAA,IAAU,IAAA;AAC1C,MAAA,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,IAClB,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,IAAI,KAAA,EAAO,MAAA,CAAO,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AACtD,MAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,QAAA,CAAS,WAAW,GAAG,CAAA;AACpD,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAChC,MAAA,MAAM,QAAA,GAAW,MAAA,GAAS,GAAA,GAAO,IAAA,IAAQ,CAAA;AACzC,MAAA,QAAA,CAAS,SAAA,CAAU,UAAA,EAAY,QAAA,KAAa,CAAC,CAAA;AAC7C,MAAA,MAAM,OAAA,GAAU,MAAM,QAAA,EAAS;AAC/B,MAAA,MAAA,CAAO;AAAA,QACL,OAAA,EAAS,GAAA;AAAA,QACT,IAAA;AAAA,QACA,QAAQ,sBAAA,CAAuB,MAAM,KAAK,OAAA,GAAU,SAAA,CAAU,OAAO,CAAA,GAAI,EAAA,CAAA;AAAA,QACzE,MAAA,EAAQ,uBAAuB,MAAM,CAAA;AAAA,QACrC,QAAA;AAAA,QACA,SAAA,EACE,MAAA,CAAO,UAAA,CAAW,MAAA,EAAQ,MAAM,CAAA,GAAI,wBAAA,IACpC,MAAA,CAAO,UAAA,CAAW,MAAA,EAAQ,MAAM,CAAA,GAAI,wBAAA;AAAA,QACtC,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH","file":"exec.js","sourcesContent":["/**\n * _output-spool — file-based capture of FULL command output.\n *\n * Command tools (bash/exec and the _spawn-stream consumers) cap what they\n * keep in memory and what reaches the model (COMMAND_OUTPUT_MAX_BYTES head+\n * tail). Everything past the cap used to be silently dropped, which pushed\n * agents to re-run commands with bigger buffers or stuff huge outputs into\n * chat history. The spool keeps the host's memory and the context window\n * small while losing nothing: once a command's output exceeds the in-memory\n * threshold, the FULL stream is written to a log file under\n * `~/.wrongstack/tool-output/` and the capped tool result carries a\n * `[full output: <path>]` marker so the model can read/grep the file\n * selectively instead of dumping it into context.\n *\n * Properties:\n * - zero disk I/O for small outputs (file is created lazily on first byte\n * past the threshold; the buffered head is flushed at that moment)\n * - bounded memory: the head buffer never exceeds the threshold, and disk\n * backpressure drops chunks past a 4 MB writable-buffer high-water mark\n * (counted and reported in the marker) instead of queueing them on the heap\n * - best-effort: any fs error disables the spool silently — command tools\n * must never fail because diagnostics couldn't be written\n * - retention: spool files older than 7 days are swept once per process\n */\nimport { createWriteStream, mkdirSync, type WriteStream } from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { wstackGlobalRoot } from '@wrongstack/core';\n\nconst SPOOL_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;\n/** Stop queueing chunks on the heap when the fs stream falls this far behind. */\nconst SPOOL_WRITE_HWM_BYTES = 4 * 1024 * 1024;\n\nlet sweepStarted = false;\n\n/** Directory for spooled command output (under the wstack global root). */\nexport function toolOutputDir(): string {\n return path.join(wstackGlobalRoot(), 'tool-output');\n}\n\n/** Reset module state — test hook (per-process sweep memo + nothing else). */\nexport function _resetOutputSpoolForTests(): void {\n sweepStarted = false;\n}\n\nfunction sweepOldSpoolFiles(dir: string): void {\n if (sweepStarted) return;\n sweepStarted = true;\n void (async () => {\n try {\n const now = Date.now();\n for (const name of await fsp.readdir(dir)) {\n if (!name.endsWith('.log')) continue;\n const p = path.join(dir, name);\n try {\n const st = await fsp.stat(p);\n if (now - st.mtimeMs > SPOOL_RETENTION_MS) await fsp.unlink(p);\n } catch {\n /* concurrently removed — ignore */\n }\n }\n } catch {\n /* directory doesn't exist yet — nothing to sweep */\n }\n })();\n}\n\nexport interface SpoolInfo {\n /** Absolute path of the spool file. */\n path: string;\n /** Total bytes of output produced (including what reached the file). */\n bytes: number;\n /** Bytes dropped due to disk backpressure (0 in the normal case). */\n droppedBytes: number;\n}\n\nexport interface OutputSpool {\n /** Feed every raw output chunk. Never throws. */\n write(text: string): void;\n /**\n * Close the file (if one was opened) and return its info, or null when the\n * output never exceeded the threshold. Idempotent.\n */\n finalize(): SpoolInfo | null;\n}\n\nexport interface CreateOutputSpoolOptions {\n /** Tool name used in the spool filename (sanitized). */\n tool: string;\n /**\n * Output size at which the spool activates. Should match the tool's\n * in-memory cap so files are only created for output the model can't\n * already see in full. Default 32 KB.\n */\n thresholdBytes?: number | undefined;\n}\n\n/**\n * Render the marker line appended to a capped tool result. Kept in one place\n * so every command tool phrases it identically (and tests can match it).\n */\nexport function spoolNote(info: SpoolInfo): string {\n const dropped =\n info.droppedBytes > 0 ? `, ~${info.droppedBytes} bytes dropped under backpressure` : '';\n return `\\n[output truncated — full ${info.bytes} bytes at ${info.path}${dropped}; read/grep that file selectively instead of re-running with more output]`;\n}\n\nexport function createOutputSpool(opts: CreateOutputSpoolOptions): OutputSpool {\n const threshold = opts.thresholdBytes ?? 32_768;\n const safeTool = opts.tool.replace(/[^a-zA-Z0-9._-]+/g, '_').slice(0, 40) || 'tool';\n\n let head = '';\n let headBytes = 0;\n let totalBytes = 0;\n let droppedBytes = 0;\n let stream: WriteStream | null = null;\n let filePath: string | null = null;\n let failed = false;\n let finalized = false;\n\n const open = (): void => {\n if (stream || failed) return;\n try {\n const dir = toolOutputDir();\n // Synchronous on purpose: createWriteStream would race an async mkdir\n // and error with ENOENT. This runs at most once per oversized command,\n // and after the first call the dir exists (mkdirSync is a no-op stat).\n mkdirSync(dir, { recursive: true });\n sweepOldSpoolFiles(dir);\n const stamp = new Date().toISOString().replace(/[:.]/g, '-');\n const rand = Math.random().toString(36).slice(2, 6);\n filePath = path.join(dir, `${stamp}-${safeTool}-${rand}.log`);\n stream = createWriteStream(filePath, { flags: 'w', encoding: 'utf8' });\n stream.on('error', () => {\n // Disk full / permission — disable the spool, keep the tool alive.\n failed = true;\n stream = null;\n filePath = null;\n });\n // Flush the buffered head first so the file is the complete output.\n stream.write(head);\n } catch {\n failed = true;\n stream = null;\n filePath = null;\n }\n };\n\n return {\n write(text: string): void {\n if (finalized || !text) return;\n totalBytes += Buffer.byteLength(text, 'utf8');\n if (!stream && !failed) {\n if (headBytes + text.length <= threshold) {\n head += text;\n headBytes += text.length;\n return;\n }\n head += text; // include the crossing chunk so the file misses nothing\n open();\n head = ''; // flushed into the stream by open(); release the heap copy\n return;\n }\n if (stream) {\n if (stream.writableLength > SPOOL_WRITE_HWM_BYTES) {\n droppedBytes += Buffer.byteLength(text, 'utf8');\n return;\n }\n stream.write(text);\n }\n },\n finalize(): SpoolInfo | null {\n if (finalized) {\n return filePath ? { path: filePath, bytes: totalBytes, droppedBytes } : null;\n }\n finalized = true;\n head = '';\n if (!stream || !filePath) return null;\n try {\n stream.end();\n } catch {\n /* already closed */\n }\n return { path: filePath, bytes: totalBytes, droppedBytes };\n },\n };\n}\n","import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport * as Core from '@wrongstack/core';\nimport type { Context } from '@wrongstack/core';\n/** Detected package manager for a project directory. */\nexport type PackageManager = 'pnpm' | 'yarn' | 'npm';\n\n/**\n * Detect the project's package manager by inspecting lockfiles in `cwd`.\n * Order: pnpm → yarn → npm (default). Missing or unreadable directories fall\n * back to `npm` rather than throwing, so a `safeResolve`-checked cwd that\n * happens to be empty never aborts the tool.\n */\nexport async function detectPackageManager(cwd: string): Promise<PackageManager> {\n const { stat } = await import('node:fs/promises');\n try {\n await stat(`${cwd}/pnpm-lock.yaml`);\n return 'pnpm';\n } catch {\n /* not pnpm */\n }\n try {\n await stat(`${cwd}/yarn.lock`);\n return 'yarn';\n } catch {\n /* not yarn */\n }\n return 'npm';\n}\n\nexport function resolvePath(input: string, ctx: Context): string {\n return path.isAbsolute(input) ? path.normalize(input) : path.resolve(ctx.workingDir ?? ctx.cwd, input);\n}\n\n/**\n * Roots every file tool may always reach, even in restricted mode: the\n * project root and the user-global `~/.wrongstack` directory (config, memory,\n * sessions, skills). `~/.wrongstack` honors the `WRONGSTACK_HOME` override.\n */\nfunction allowedRoots(ctx: Context): string[] {\n return [path.resolve(ctx.projectRoot), path.resolve(Core.wstackGlobalRoot())];\n}\n\n/** True if `target` is `root` itself or nested inside any of `roots`. */\nfunction isInsideAny(target: string, roots: string[]): boolean {\n return roots.some((root) => {\n const rel = path.relative(root, target);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n });\n}\n\nexport function ensureInsideRoot(absPath: string, ctx: Context): string {\n const target = path.resolve(absPath);\n // Unrestricted filesystem access: skip the project-root containment check.\n if (ctx.allowOutsideProjectRoot) return target;\n if (isInsideAny(target, allowedRoots(ctx))) return target;\n throw new Error(`Path \"${absPath}\" is outside project root \"${path.resolve(ctx.projectRoot)}\"`);\n}\n\nexport function safeResolve(input: string, ctx: Context): string {\n return ensureInsideRoot(resolvePath(input, ctx), ctx);\n}\n\n/**\n * Defense against in-root→out-of-root symlink escape (CWE-59). `safeResolve`\n * only does a syntactic `../` check, so a symlink that lives *inside* the\n * project root but points outside still passes it. This resolves the path\n * through `fs.realpath` and re-verifies containment against the realpath of\n * the project root (comparing like-for-like, since the root itself may be a\n * symlink — macOS `/var`→`/private/var`, Windows 8.3 short names). For a path\n * that does not exist yet (e.g. a `write` to a new file) the nearest existing\n * ancestor directory is checked instead. Throws if the real target escapes.\n *\n * Mirrors the per-file guard already used in `replace.ts`/`grep.ts`; applied\n * to single-file `read`/`edit`/`write` it throws (rather than skips) because\n * the caller named exactly one file.\n */\nexport async function assertRealInsideRoot(absPath: string, ctx: Context): Promise<void> {\n // Unrestricted filesystem access: no symlink-escape check to perform.\n if (ctx.allowOutsideProjectRoot) return;\n // Compare like-for-like against the realpath of each always-allowed root\n // (project root + ~/.wrongstack), since a root may itself be a symlink.\n const realRoots = await Promise.all(\n allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path.resolve(r))),\n );\n let probe = absPath;\n for (;;) {\n let real: string;\n try {\n real = await fsp.realpath(probe);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n const parent = path.dirname(probe);\n if (parent === probe) return; // reached fs root without escaping\n probe = parent;\n continue;\n }\n throw err;\n }\n if (isInsideAny(real, realRoots)) return;\n throw new Error(\n `Path \"${absPath}\" resolves through a symlink outside project root \"${realRoots[0]}\"`,\n );\n }\n}\n\n/** `safeResolve` + symlink realpath containment check. Async. */\nexport async function safeResolveReal(input: string, ctx: Context): Promise<string> {\n const abs = safeResolve(input, ctx);\n await assertRealInsideRoot(abs, ctx);\n return abs;\n}\n\nexport function truncateMiddle(s: string, max: number): string {\n if (Buffer.byteLength(s, 'utf8') <= max) return s;\n const half = Math.floor(max / 2);\n return (\n s.slice(0, half) +\n `\\n…[truncated ${Buffer.byteLength(s, 'utf8') - max} bytes from middle]…\\n` +\n s.slice(-half)\n );\n}\n\nexport function isBinaryBuffer(buf: Buffer): boolean {\n const len = Math.min(buf.length, 8192);\n for (let i = 0; i < len; i++) {\n if (buf[i] === 0) return true;\n }\n return false;\n}\n\n// ─── Command-output normalization (token-saving) ────────────────────────────\n//\n// Raw process output is full of tokens the model gains nothing from: ANSI\n// escapes, carriage-return progress spam, runs of identical warning lines, and\n// huge tails of build noise. These helpers strip that noise before the output\n// reaches the LLM. They are scoped to COMMAND tools (bash/git/exec and the\n// _spawn-stream consumers) — never applied to structured/code outputs.\n\n/** Unified byte cap for all command tool output fed to the model. */\nexport const COMMAND_OUTPUT_MAX_BYTES = 32_768;\n\n/** Runs of >= this many identical consecutive lines are collapsed. */\nconst REPEAT_RUN_THRESHOLD = 3;\n\n/**\n * Collapse carriage-return overwrites the way a terminal would: `\\r\\n` becomes\n * `\\n`, and a bare `\\r` (progress redraw) keeps only the text after the LAST\n * `\\r` on its physical line. Without this, a single progress bar that redraws\n * 200 times explodes into 200 lines.\n */\nexport function collapseCarriageReturns(text: string): string {\n const lf = text.replace(/\\r\\n/g, '\\n');\n if (!lf.includes('\\r')) return lf;\n return lf\n .split('\\n')\n .map((line) => (line.includes('\\r') ? line.slice(line.lastIndexOf('\\r') + 1) : line))\n .join('\\n');\n}\n\n/**\n * Collapse a run of `minRun`+ identical consecutive lines into the line once\n * plus a marker. Consecutive-only — it never reorders or dedups non-adjacent\n * lines, so diffs/source stay intact.\n */\nexport function collapseConsecutiveDuplicates(text: string, minRun = REPEAT_RUN_THRESHOLD): string {\n const lines = text.split('\\n');\n const out: string[] = [];\n let i = 0;\n while (i < lines.length) {\n let j = i + 1;\n while (j < lines.length && lines[j] === lines[i]) j++;\n const run = j - i;\n if (run >= minRun) {\n out.push(lines[i]!, `… ⟨repeated ${run}×⟩`);\n } else {\n for (let k = i; k < j; k++) out.push(lines[k]!);\n }\n i = j;\n }\n return out.join('\\n');\n}\n\n/** Largest prefix of `s` whose UTF-8 byte length is <= `maxBytes`. */\nfunction takeHeadBytes(s: string, maxBytes: number): string {\n if (maxBytes <= 0) return '';\n /* v8 ignore next -- only caller (truncateHeadTail) passes a budget smaller than s; defensive. */\n if (Buffer.byteLength(s, 'utf8') <= maxBytes) return s;\n let lo = 0;\n let hi = s.length;\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (Buffer.byteLength(s.slice(0, mid), 'utf8') <= maxBytes) lo = mid;\n else hi = mid - 1;\n }\n return s.slice(0, lo);\n}\n\n/** Largest suffix of `s` whose UTF-8 byte length is <= `maxBytes`. */\nfunction takeTailBytes(s: string, maxBytes: number): string {\n if (maxBytes <= 0) return '';\n /* v8 ignore next -- only caller (truncateHeadTail) passes a budget smaller than s; defensive. */\n if (Buffer.byteLength(s, 'utf8') <= maxBytes) return s;\n let lo = 0;\n let hi = s.length;\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (Buffer.byteLength(s.slice(s.length - mid), 'utf8') <= maxBytes) lo = mid;\n else hi = mid - 1;\n }\n return s.slice(s.length - lo);\n}\n\n/**\n * Truncate to `maxBytes` keeping BOTH ends — the head (what ran / early context)\n * and the tail (errors and summaries usually land last), biased ~45/55 toward\n * the tail. The result never exceeds `maxBytes`.\n */\nexport function truncateHeadTail(s: string, maxBytes: number): string {\n const total = Buffer.byteLength(s, 'utf8');\n if (total <= maxBytes) return s;\n // Reserve a fixed allowance for the marker so the final string can't exceed\n // the cap even though the dropped-byte count's digit width varies.\n const MARKER_RESERVE = 64;\n const avail = Math.max(0, maxBytes - MARKER_RESERVE);\n const headBudget = Math.floor(avail * 0.45);\n const head = takeHeadBytes(s, headBudget);\n const tail = takeTailBytes(s, avail - Buffer.byteLength(head, 'utf8'));\n const kept = Buffer.byteLength(head, 'utf8') + Buffer.byteLength(tail, 'utf8');\n return `${head}\\n…[truncated ${total - kept} bytes]…\\n${tail}`;\n}\n\n/**\n * Full token-saving pipeline for command tool output: strip ANSI → collapse\n * carriage-return progress → trim trailing whitespace → collapse identical\n * consecutive lines → squeeze blank-line runs → head+tail truncate to the cap.\n */\nexport function normalizeCommandOutput(\n raw: string,\n opts: { maxBytes?: number | undefined } = {},\n): string {\n if (!raw) return raw;\n let text = Core.stripAnsi(raw);\n text = collapseCarriageReturns(text);\n text = text.replace(/[ \\t]+$/gm, ''); // trailing whitespace per line\n text = collapseConsecutiveDuplicates(text);\n text = text.replace(/\\n{3,}/g, '\\n\\n'); // >=2 blank lines → 1\n return truncateHeadTail(text, opts.maxBytes ?? COMMAND_OUTPUT_MAX_BYTES);\n}\n","/**\n * CircuitBreaker — prevents runaway bash/exec tool chains by:\n *\n * - Tripping on consecutive failures (models that keep repeating the\n * same failing command, e.g. `npm install` with wrong args in a loop)\n * - Tripping on slow call ratio (too many long-running commands suggest\n * a hung subprocess that the model doesn't know how to kill)\n * - Rate-limiting bursts (rapid succession of commands without reading\n * output suggests the model isn't processing results)\n * - Auto-recovering after a cooldown period so a fixed model can resume\n *\n * The breaker is owned by the ProcessRegistry so any tool that registers\n * a process participates in the same circuit. \"Per-tool\" isolation is\n * intentionally NOT implemented — the model treats bash/exec as one\n * resource pool; isolating them would let the model route around the\n * breaker by alternating which tool it uses.\n */\n\nexport interface CircuitBreakerConfig {\n /**\n * Consecutive failures before trip. Default: 5.\n * A single success resets this counter to 0.\n */\n maxConsecutiveFailures?: number | undefined;\n /**\n * Slow-call threshold in ms. A call that runs longer than this is\n * counted as \"slow\". Default: 60_000 (1 minute).\n */\n slowCallThresholdMs?: number | undefined;\n /**\n * Max slow calls before trip (within the sliding window). Default: 3.\n */\n maxSlowCalls?: number | undefined;\n /**\n * Sliding window for rate-limit and slow-call counting, in ms.\n * Default: 60_000 (1 minute).\n */\n windowMs?: number | undefined;\n /**\n * Max calls within the sliding window. Default: 30.\n * Burst exceeding this trips the breaker immediately.\n */\n maxCallsPerWindow?: number | undefined;\n /**\n * Cooldown before auto-recovery attempt, in ms. Default: 30_000 (30s).\n * After this the breaker enters \"half-open\" state and allows one call\n * through to test whether the problem is resolved.\n */\n cooldownMs?: number | undefined;\n}\n\ninterface CallRecord {\n at: number;\n /** True if the call threw or returned an is_error result. */\n failed: boolean;\n /** True if elapsed time exceeded slowCallThresholdMs. */\n slow: boolean;\n}\n\ntype BreakerState = 'closed' | 'open' | 'half-open';\n\nconst DEFAULT_MAX_CONSECUTIVE_FAILURES = 5;\nconst DEFAULT_SLOW_CALL_THRESHOLD_MS = 180_000;\n// 3 minutes — balanced against the 5-minute bash timeout. Commands\n// running <3min are normal; 3-5min are \"slow\" and count toward the\n// breaker. 3 consecutive slow calls trip the circuit.\nconst DEFAULT_MAX_SLOW_CALLS = 3;\nconst DEFAULT_WINDOW_MS = 60_000;\nconst DEFAULT_MAX_CALLS_PER_WINDOW = 30;\nconst DEFAULT_COOLDOWN_MS = 30_000;\n\nexport interface CircuitBreakerSnapshot {\n state: 'closed' | 'open' | 'half-open';\n consecutiveFailures: number;\n slowCallsInWindow: number;\n callsInWindow: number;\n windowMs: number;\n cooldownRemainingMs: number | null;\n lastFailureAt: number | null;\n lastSlowAt: number | null;\n}\n\nexport class CircuitBreaker {\n private readonly maxConsecutiveFailures: number;\n private readonly slowCallThresholdMs: number;\n private readonly maxSlowCalls: number;\n private readonly windowMs: number;\n private readonly maxCallsPerWindow: number;\n private readonly cooldownMs: number;\n\n private state: BreakerState = 'closed';\n private consecutiveFailures = 0;\n private window: CallRecord[] = [];\n private lastFailureAt: number | null = null;\n private lastSlowAt: number | null = null;\n /** Timestamp when the breaker was opened (for cooldown calculation). */\n private openedAt: number | null = null;\n\n /**\n * Master enable flag. When false the breaker is bypassed: `beforeCall`\n * always returns true and `afterCall` records nothing. The class itself\n * defaults to enabled (so the standalone unit tests exercise tripping); the\n * ProcessRegistry flips this off until the user opts in via `/settings`.\n */\n private enabled = true;\n\n /**\n * Fired (best-effort) when the breaker transitions into the `open` state.\n * The registry uses this to arm its auto kill/reset countdown.\n */\n onTrip?: (() => void) | undefined;\n /**\n * Fired (best-effort) when the breaker returns to `closed` after having been\n * open/half-open. The registry uses this to cancel a pending kill/reset.\n */\n onReset?: (() => void) | undefined;\n\n constructor(config: CircuitBreakerConfig = {}) {\n this.maxConsecutiveFailures = config.maxConsecutiveFailures ?? DEFAULT_MAX_CONSECUTIVE_FAILURES;\n this.slowCallThresholdMs = config.slowCallThresholdMs ?? DEFAULT_SLOW_CALL_THRESHOLD_MS;\n this.maxSlowCalls = config.maxSlowCalls ?? DEFAULT_MAX_SLOW_CALLS;\n this.windowMs = config.windowMs ?? DEFAULT_WINDOW_MS;\n this.maxCallsPerWindow = config.maxCallsPerWindow ?? DEFAULT_MAX_CALLS_PER_WINDOW;\n this.cooldownMs = config.cooldownMs ?? DEFAULT_COOLDOWN_MS;\n }\n\n /** Toggle the master enable. Disabling resets to a clean `closed` state. */\n setEnabled(enabled: boolean): void {\n if (this.enabled === enabled) return;\n this.enabled = enabled;\n if (!enabled) this._reset();\n }\n\n get isEnabled(): boolean {\n return this.enabled;\n }\n\n /**\n * Returns true if the circuit allows a new call to proceed.\n * When false, callers should abort the tool call and return a\n * circuit-breaker error instead of spawning a process.\n */\n get canProceed(): boolean {\n if (!this.enabled) return true;\n this._checkStateTransition();\n return this.state !== 'open';\n }\n\n /**\n * Snapshot of the current breaker state for observability (`/kill`).\n */\n snapshot(): CircuitBreakerSnapshot {\n this._checkStateTransition();\n const now = Date.now();\n let cooldownRemaining: number | null = null;\n if (this.openedAt !== null && this.state === 'open') {\n const elapsed = now - this.openedAt;\n cooldownRemaining = Math.max(0, this.cooldownMs - elapsed);\n }\n return {\n state: this.state,\n consecutiveFailures: this.consecutiveFailures,\n slowCallsInWindow: this.window.filter((c) => c.slow).length,\n callsInWindow: this.window.length,\n windowMs: this.windowMs,\n cooldownRemainingMs: cooldownRemaining,\n lastFailureAt: this.lastFailureAt,\n lastSlowAt: this.lastSlowAt,\n };\n }\n\n /**\n * Call this BEFORE spawning a bash/exec process.\n * Returns true if the call is allowed; false if the breaker is open.\n * When false, callers MUST NOT spawn a process.\n *\n * @param bypass - If true, skip the circuit breaker check entirely.\n * Use for background/fire-and-forget processes that should\n * not affect breaker state.\n */\n beforeCall(bypass = false): boolean {\n if (bypass || !this.enabled) return true;\n this._checkStateTransition();\n if (this.state === 'open') return false;\n return true;\n }\n\n /**\n * Call this AFTER a bash/exec process finishes (success or failure).\n * `durationMs` is the wall-clock time the process ran.\n * `failed` is true when the process returned a non-zero exit code or\n * threw an exception before spawning.\n *\n * @param bypass - If true, do not update breaker state.\n * Use for background/fire-and-forget processes.\n */\n afterCall(durationMs: number, failed: boolean, bypass = false): void {\n if (bypass || !this.enabled) return;\n\n const now = Date.now();\n\n if (this.state === 'half-open') {\n // First call through after cooldown — if it failed, go back to open.\n if (failed) {\n this._trip();\n return;\n }\n // Success in half-open → reset to closed.\n this._reset();\n return;\n }\n\n // Prune old records outside the sliding window.\n this._pruneWindow(now);\n\n const slow = durationMs >= this.slowCallThresholdMs;\n this.window.push({ at: now, failed, slow });\n\n if (failed) {\n this.consecutiveFailures++;\n this.lastFailureAt = now;\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n this._trip();\n }\n return;\n }\n\n // Success: reset consecutive failure counter.\n this.consecutiveFailures = 0;\n\n if (slow) {\n this.lastSlowAt = now;\n const slowCount = this.window.filter((c) => c.slow).length;\n if (slowCount >= this.maxSlowCalls) {\n this._trip();\n }\n }\n\n const callCount = this.window.length;\n if (callCount >= this.maxCallsPerWindow) {\n // Rate limit exceeded. This is a soft trip — we reset the window\n // and let the next call try immediately (the caller will still see\n // canProceed=false until the window drains naturally).\n this._trip();\n }\n }\n\n /** Force the breaker open. Used by /kill force and Ctrl+C. */\n forceOpen(): void {\n this._trip();\n }\n\n /** Force a reset to closed. Used by tests and /kill reset. */\n forceReset(): void {\n this._reset();\n }\n\n private _trip(): void {\n if (this.state === 'open') return; // already open\n this.state = 'open';\n this.openedAt = Date.now();\n // P3 #23 (before-release.md): clear the window on trip. Old records are\n // irrelevant once tripped — the breaker starts fresh after cooldown\n // (half-open → closed resets the counters). Without this the window array\n // holds onto CallRecord entries for its lifetime if no new afterCall()\n // arrives (which is the case when the breaker stays open and no new calls\n // are attempted).\n this.window = [];\n // Best-effort: never let a listener failure corrupt breaker state.\n try {\n this.onTrip?.();\n } catch {\n /* ignored — observability hook only */\n }\n }\n\n private _reset(): void {\n const wasRecovering = this.state !== 'closed';\n this.state = 'closed';\n this.consecutiveFailures = 0;\n this.window = [];\n this.openedAt = null;\n // Only notify on a real recovery (open/half-open → closed), not on the\n // initial closed state or an idempotent re-reset.\n if (wasRecovering) {\n try {\n this.onReset?.();\n } catch {\n /* ignored — observability hook only */\n }\n }\n }\n\n /** Transition from open → half-open when cooldown elapses. */\n private _checkStateTransition(): void {\n if (this.state !== 'open' || this.openedAt === null) return;\n const elapsed = Date.now() - this.openedAt;\n if (elapsed >= this.cooldownMs) {\n this.state = 'half-open';\n this.openedAt = null;\n }\n }\n\n private _pruneWindow(now: number): void {\n const cutoff = now - this.windowMs;\n this.window = this.window.filter((c) => c.at >= cutoff);\n }\n}","import { expectDefined } from '@wrongstack/core';\n/**\n * ProcessRegistry — global singleton that tracks all spawned child processes\n * from `bash` and `exec` tools. Enables:\n *\n * - Listing active processes (for TUI status bar)\n * - Killing individual processes or all processes (for Ctrl+C and /kill)\n * - Detecting runaway processes (hung, looping)\n * - Circuit breaker integration to prevent recursive/repeated failures\n *\n * Thread-safety: Node.js is single-threaded, but async callbacks can fire\n * in any order. All mutations go through synchronized Map methods.\n */\nimport { spawn } from 'node:child_process';\nimport type { ChildProcess } from 'node:child_process';\nimport * as os from 'node:os';\nimport { CircuitBreaker, type CircuitBreakerSnapshot, type CircuitBreakerConfig } from './circuit-breaker.js';\nexport type { CircuitBreakerSnapshot, CircuitBreakerConfig } from './circuit-breaker.js';\n\nexport interface TrackedProcess {\n pid: number;\n name: string;\n /** Display-safe redacted command string — safe for logs, /ps, crash dumps.\n * Contains [REDACTED] in place of sensitive flag values. */\n command: string;\n startedAt: number;\n sessionId?: string | undefined;\n /** The raw ChildProcess handle. Never call .kill() directly on this —\n * use `kill()` below which handles process groups correctly on POSIX\n * and degrades gracefully on Windows. */\n child: ChildProcess;\n /** True only when this child was spawned as a POSIX process-group/session\n * leader (for example `spawn(..., { detached: true })`) and `pid` is the\n * actual `child.pid`. Negative-PID signaling is host-wide dangerous for\n * values like -1, so tests and manually registered entries must not opt in. */\n processGroupLeader?: boolean | undefined;\n /** True once the process has been kill()ed but not yet exited.\n * We keep it in the registry until 'close' fires so callers can\n * distinguish \"still running\" from \"just exited\". */\n killed: boolean;\n /** If true, kill() and killAll() will refuse to kill this process.\n * Used for infrastructure processes (browser, dev servers, …) that\n * must outlive the agent session. */\n protected: boolean;\n}\n\n// Sensitive CLI flag patterns that may appear in process command lines.\n// Redacted to [REDACTED] so crash dumps /ps output cannot leak secrets.\nconst SENSITIVE_FLAG_PATTERNS: RegExp[] = [\n // --flag=value or --flag \"value\" (value captured up to next space or comma)\n /--(?:token|password|passwd|pwd|secret|api[-_]?key|api[-_]?secret|auth|credential|private[-_]?key|access[-_]?key|github[-_]?token|gh[-_]?token|bearer|jwt|oauth|pin|pincode|passphrase|access[-_]?token)(?:[=\\s,][^\\s]*)?/gi,\n // -f \"value\" style short flags\n /(?<!\\w)-t(?:\\s+|\\s*=\\s*)[^\\s,]+/,\n /(?<!\\w)-(?:p|password)(?:\\s+|\\s*=\\s*)[^\\s,]+/gi,\n // env var–style secrets: TOKEN=x, API_KEY=y, etc.\n /(?:TOKEN|API_KEY|API_SECRET|AUTH_TOKEN|GITHUB_TOKEN|GH_TOKEN|BEARER|JWT|OAUTH|CREDENTIAL|SECRET|PRIVATE_KEY|PASSWORD|PASSWD)\\s*[=:]\\s*[^\\s,]+/gi,\n // Generic high-entropy look: base64 strings >32 chars or hex strings >32 digits — but only\n // when preceded by a flag name (e.g. --github-token=EyJ...).\n /--\\w*(?:token|key|secret|password|passwd|auth|credential)\\w*[=\\s,][A-Za-z0-9+/=]{32,}/,\n];\n\n/**\n * Returns a display-safe copy of `cmd` with sensitive flag values replaced by [REDACTED].\n * The original string is unchanged; this is pure and has no side effects.\n */\nexport function redactCommand(cmd: string): string {\n let result = cmd;\n for (const pattern of SENSITIVE_FLAG_PATTERNS) {\n result = result.replace(pattern, (match) => {\n // Preserve the flag name portion; redact only the value part.\n // e.g. \"--token=sekrit_abc\" → \"--token=[REDACTED]\"\n const eq = match.indexOf('=');\n const sp = match.search(/\\s/);\n const delim = eq !== -1 ? '=' : sp !== -1 ? match[sp] : null;\n if (delim !== null) {\n const flag = match.slice(0, match.indexOf(expectDefined(delim)) + 1);\n return `${flag}[REDACTED]`;\n }\n // Nothing delimitable found; replace the whole token silently.\n // Short flags like -tVALUE are replaced entirely to avoid edge cases.\n const flagEnd = match.match(/^--?[a-zA-Z][a-zA-Z0-9_-]*/)?.[0] ?? match;\n return `${flagEnd}=**redacted**`;\n });\n }\n return result;\n}\n\ninterface KillOpts {\n /** SIGKILL instead of SIGTERM. Default: false (SIGTERM first). */\n force?: boolean | undefined;\n /** MS to wait between SIGTERM and SIGKILL on POSIX. Default: 2000. */\n graceMs?: number | undefined;\n}\n\n/**\n * Snapshot of the armed auto kill/reset countdown, or null when nothing is\n * armed. `remainingMs` ticks down in real time; the TUI statusline renders it.\n */\nexport interface BreakerCountdown {\n remainingMs: number;\n totalMs: number;\n}\n\ntype BreakerCountdownListener = (snapshot: BreakerCountdown | null) => void;\n\nexport interface RegistryStats {\n activeCount: number;\n totalCount: number;\n breaker: CircuitBreakerSnapshot;\n}\n\nconst DEFAULT_GRACE_MS = 2000;\n\n/**\n * Kill an entire process tree on Windows via `taskkill /T /F`.\n *\n * TerminateProcess (what `child.kill()` maps to) has no process-group\n * semantics, so killing a shell wrapper (`cmd.exe /c …`) orphans its\n * grandchildren (node, vitest forks, dev servers). The orphans inherit the\n * parent's stdio pipe handles and can keep streaming into this process for\n * the rest of the session — which both prevents the child's 'close' event\n * from ever firing and grows in-memory output buffers without bound.\n *\n * Fire-and-forget: returns true if taskkill was spawned, false if spawning\n * it failed (caller should fall back to a direct `child.kill()`).\n */\nexport function killWin32Tree(pid: number): boolean {\n try {\n const child = spawn('taskkill', ['/pid', String(pid), '/T', '/F'], {\n stdio: 'ignore',\n windowsHide: true,\n });\n // spawn() reports a failure to launch (e.g. taskkill not on PATH, blocked by\n // security software) via an ASYNC 'error' event — the surrounding try/catch\n // only traps synchronous throws. Without a listener that event is unhandled\n // and crashes the whole process. Swallow it: this is best-effort tree-kill\n // and the registry still has the direct child.kill() fallback.\n child.on('error', () => {});\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n\nexport class ProcessRegistryImpl {\n private readonly processes = new Map<number, TrackedProcess>();\n private readonly breaker: CircuitBreaker;\n\n /**\n * Auto kill/reset config. When the breaker trips and `autoKillResetMs > 0`,\n * a countdown is armed; on expiry all tracked processes are killed and the\n * breaker is reset to closed (forced recovery). Zero means manual recovery\n * only (`/kill reset`).\n */\n private autoKillResetMs = 0;\n private autoKillTimer: ReturnType<typeof setTimeout> | null = null;\n private autoKillArmedAt: number | null = null;\n private breakerCountdownListeners: BreakerCountdownListener[] = [];\n\n constructor(breakerConfig?: CircuitBreakerConfig) {\n this.breaker = new CircuitBreaker(breakerConfig);\n // Arm on trip, cancel on recovery. Listeners are best-effort.\n this.breaker.onTrip = () => this._armAutoKillReset();\n this.breaker.onReset = () => this._cancelAutoKillReset();\n // Protection is OFF by default — the user opts in via `/settings breaker on`.\n this.breaker.setEnabled(false);\n }\n\n register(info: Omit<TrackedProcess, 'killed' | 'protected'> & { protected?: boolean | undefined }): void {\n this.processes.set(info.pid, { ...info, killed: false, protected: info.protected ?? false });\n }\n\n private _isSafeSignalPid(pid: number): boolean {\n return Number.isInteger(pid) && pid > 1 && pid !== process.pid && pid !== process.ppid;\n }\n\n private _canSignalProcessGroup(p: TrackedProcess): boolean {\n return (\n os.platform() !== 'win32' &&\n p.processGroupLeader === true &&\n this._isSafeSignalPid(p.pid) &&\n typeof p.child.pid === 'number' &&\n p.child.pid === p.pid\n );\n }\n\n private _killChildDirect(p: TrackedProcess, signal: NodeJS.Signals): void {\n try {\n p.child.kill(signal);\n } catch {\n // Process may have already exited, or this may be a persistent entry\n // without a live ChildProcess handle in the current process.\n }\n }\n\n private _killPosix(p: TrackedProcess, signal: NodeJS.Signals): void {\n if (this._canSignalProcessGroup(p)) {\n try {\n process.kill(-p.pid, signal);\n return;\n } catch {\n // Process group may already be gone; fall back to the direct child.\n }\n }\n this._killChildDirect(p, signal);\n }\n\n /** Unregister a process by PID. Called on 'close' / 'exit' events. */\n unregister(pid: number): void {\n this.processes.delete(pid);\n }\n\n /** Get a single process by PID. */\n get(pid: number): TrackedProcess | undefined {\n this._pruneStale(pid);\n return this.processes.get(pid);\n }\n\n /** Get all tracked processes. */\n list(): TrackedProcess[] {\n return Array.from(this.processes.values());\n }\n\n /** Get processes filtered by name (e.g. 'bash', 'exec'). */\n byName(name: string): TrackedProcess[] {\n return this.list().filter((p) => p.name === name);\n }\n\n /** Get processes filtered by session. */\n bySession(sessionId: string): TrackedProcess[] {\n return this.list().filter((p) => p.sessionId === sessionId);\n }\n\n /** Count of active (non-killed) processes. */\n get activeCount(): number {\n let n = 0;\n for (const p of this.processes.values()) {\n if (!p.killed) n++;\n }\n return n;\n }\n\n /**\n * Combined stats for observability — used by /ps and the TUI status bar.\n */\n stats(): RegistryStats {\n return {\n activeCount: this.activeCount,\n totalCount: this.processes.size,\n breaker: this.breaker.snapshot(),\n };\n }\n\n /**\n * Returns true if the circuit allows a new bash/exec call to proceed.\n * When false, callers MUST NOT spawn a process.\n */\n get canProceed(): boolean {\n return this.breaker.canProceed;\n }\n\n /**\n * Called before spawning a process. Returns true if allowed; false if\n * the circuit breaker is open.\n *\n * @param bypass - If true, skip circuit breaker check (for background processes).\n */\n beforeCall(bypass = false): boolean {\n return this.breaker.beforeCall(bypass);\n }\n\n /**\n * Called after a process finishes. `durationMs` is wall-clock time;\n * `failed` is true for non-zero exit codes.\n *\n * @param bypass - If true, do not update circuit breaker state (for background processes).\n */\n afterCall(durationMs: number, failed: boolean, bypass = false): void {\n this.breaker.afterCall(durationMs, failed, bypass);\n }\n\n /** Force-open the circuit breaker (Ctrl+C, /kill force). */\n forceBreakerOpen(): void {\n this.breaker.forceOpen();\n }\n\n /** Force-reset the circuit breaker to closed (/kill reset). */\n forceBreakerReset(): void {\n this.breaker.forceReset();\n }\n\n /**\n * Configure circuit-breaker protection at runtime. Called from `/settings`\n * (instant, all modes) and on TUI mount (applies persisted config).\n *\n * - `enabled` toggles whether the breaker gates `bash`/`exec`.\n * - `autoKillResetMs` arms the auto kill/reset countdown when the breaker\n * trips (0 = manual recovery only).\n *\n * Re-applies cleanly on every call: cancels a pending countdown when the\n * timeout is cleared or protection disabled, and re-arms if the breaker is\n * currently open under the new settings.\n */\n setBreakerConfig(cfg: { enabled?: boolean | undefined; autoKillResetMs?: number | undefined }): void {\n if (cfg.enabled !== undefined) this.breaker.setEnabled(cfg.enabled);\n if (cfg.autoKillResetMs !== undefined) this.autoKillResetMs = Math.max(0, cfg.autoKillResetMs);\n\n if (this.autoKillResetMs <= 0) {\n this._cancelAutoKillReset();\n return;\n }\n // If protection is active and the breaker is currently tripped, ensure a\n // countdown is armed for the new window (covers a live config change while\n // the breaker is already open).\n if (this.breaker.isEnabled && this.breaker.snapshot().state === 'open') {\n this._armAutoKillReset();\n }\n }\n\n /**\n * Live countdown to the next auto kill/reset, or null when nothing is armed.\n * The TUI polls this on a 1s tick while armed so the statusline decrements.\n */\n getBreakerCountdown(): BreakerCountdown | null {\n if (this.autoKillArmedAt === null || this.autoKillResetMs <= 0) return null;\n const elapsed = Date.now() - this.autoKillArmedAt;\n return { remainingMs: Math.max(0, this.autoKillResetMs - elapsed), totalMs: this.autoKillResetMs };\n }\n\n /**\n * Subscribe to countdown arm/cancel events. Returns an unsubscribe function.\n * Use {@link getBreakerCountdown} for the live ticking value between events.\n */\n onBreakerCountdownChange(listener: BreakerCountdownListener): () => void {\n this.breakerCountdownListeners.push(listener);\n return () => {\n this.breakerCountdownListeners = this.breakerCountdownListeners.filter((l) => l !== listener);\n };\n }\n\n private _emitBreakerCountdown(): void {\n const snap = this.getBreakerCountdown();\n for (const l of this.breakerCountdownListeners) {\n try {\n l(snap);\n } catch {\n /* listener failure must never affect breaker behavior */\n }\n }\n }\n\n /**\n * Arm the auto kill/reset countdown. Idempotent: re-arming resets the window\n * (a fresh trip after a failed half-open probe restarts the clock). No-op\n * when protection is off or no timeout is configured.\n */\n private _armAutoKillReset(): void {\n if (this.autoKillResetMs <= 0 || !this.breaker.isEnabled) return;\n this._clearAutoKillTimer();\n this.autoKillArmedAt = Date.now();\n this.autoKillTimer = setTimeout(() => {\n this.autoKillTimer = null;\n this.autoKillArmedAt = null;\n // Forced recovery: nuke runaway processes and reopen the circuit.\n this.killAll({ force: false });\n this.breaker.forceReset();\n this._emitBreakerCountdown();\n }, this.autoKillResetMs);\n // Don't keep the event loop alive purely for auto-recovery.\n this.autoKillTimer.unref?.();\n this._emitBreakerCountdown();\n }\n\n private _cancelAutoKillReset(): void {\n const wasArmed = this.autoKillArmedAt !== null;\n this._clearAutoKillTimer();\n if (wasArmed) {\n this.autoKillArmedAt = null;\n this._emitBreakerCountdown();\n }\n }\n\n private _clearAutoKillTimer(): void {\n if (this.autoKillTimer !== null) {\n clearTimeout(this.autoKillTimer);\n this.autoKillTimer = null;\n }\n }\n\n /** Kill a single process by PID.\n *\n * On POSIX: sends SIGTERM to the *process group* (-pid) so that\n * runaway grandchild processes (`sleep 9999 & disown`) are also killed.\n * After `graceMs` a SIGKILL is sent if the process hasn't exited.\n *\n * On Windows: `child.kill()` maps to TerminateProcess — process groups\n * are not meaningfully supported. A second `force=true` call sends\n * SIGKILL (which maps to TerminateProcess again — the distinction is\n * in the exit code, not the signal).\n *\n * Returns true if the process was found and kill was attempted.\n */\n kill(pid: number, opts: KillOpts = {}): boolean {\n this._pruneStale(pid);\n const p = this.processes.get(pid);\n if (!p) return false;\n if (p.killed) return true; // already kill()ed, don't double-send\n if (p.protected) return false; // protected processes are never kill()ed\n\n const { force = false, graceMs = DEFAULT_GRACE_MS } = opts;\n const isWin = os.platform() === 'win32';\n\n if (isWin) {\n // Windows: no process group semantics. A direct kill terminates only\n // the immediate child — shell-wrapped commands (cmd.exe /c …) leave\n // grandchildren running that hold the inherited stdio pipes open and\n // keep feeding output into this process indefinitely. Kill the whole\n // tree via taskkill instead, but only for a real, still-running child\n // (exitCode === null); test fakes and already-exited processes take\n // the plain-kill path. The direct kill is deliberately NOT sent\n // immediately alongside taskkill: killing the root first would break\n // taskkill's parent-pid tree enumeration and orphan the grandchildren\n // again — it runs as a delayed fallback instead.\n const liveRealChild = p.child.exitCode === null && typeof p.child.pid === 'number';\n if (liveRealChild && killWin32Tree(pid)) {\n const fallback = setTimeout(() => {\n if (p.child.exitCode === null) {\n try {\n p.child.kill('SIGKILL');\n } catch {\n // Process may have already exited.\n }\n }\n }, graceMs);\n fallback.unref?.();\n } else {\n try {\n p.child.kill(force ? 'SIGKILL' : 'SIGTERM');\n } catch {\n // Process may have already exited.\n }\n }\n p.killed = true;\n return true;\n }\n\n // POSIX: kill the process group only when the tracked child is proven to\n // be the group leader. Otherwise use child.kill(); negative PID signaling\n // with untrusted/fake PIDs can target unrelated host processes.\n try {\n if (force) {\n this._killPosix(p, 'SIGKILL');\n } else {\n this._killPosix(p, 'SIGTERM');\n // Schedule SIGKILL as backup.\n const timer = setTimeout(() => {\n // Re-check: process may have exited on its own.\n if (this.processes.has(pid) && !p.child.killed) {\n this._killPosix(p, 'SIGKILL');\n }\n }, graceMs);\n timer.unref?.(); // Don't keep event loop alive.\n }\n } catch {\n // Process may have already exited.\n }\n p.killed = true;\n return true;\n }\n\n /**\n * Kill all tracked processes.\n * Returns the PIDs that were kill()ed.\n */\n killAll(opts: KillOpts = {}): number[] {\n const pids = Array.from(this.processes.keys());\n const killed: number[] = [];\n for (const pid of pids) {\n const p = this.processes.get(pid);\n if (p && !p.protected && this.kill(pid, opts)) killed.push(pid);\n }\n return killed;\n }\n\n /**\n * Kill all processes for a specific session.\n * Returns the PIDs that were kill()ed.\n */\n killSession(sessionId: string, opts: KillOpts = {}): number[] {\n const pids = this.bySession(sessionId).map((p) => p.pid);\n const killed: number[] = [];\n for (const pid of pids) {\n if (this.kill(pid, opts)) killed.push(pid);\n }\n return killed;\n }\n\n /**\n * Check whether a tracked process entry is stale — the child has exited\n * (exitCode !== null) AND it's been in the registry long enough that the\n * OS may have reused the PID for a new, unrelated process.\n *\n * P3 #24 (before-release.md): on POSIX, PIDs are reused after process\n * exit. If a tracked process exits but its 'close' event hasn't fired yet\n * (or was missed), the registry still holds the entry. A new process\n * gets the same PID, and PID-based lookups (get, kill, shouldBlockKill)\n * may incorrectly protect or target the wrong process.\n *\n * The 60s threshold is conservative — the OS typically waits much longer\n * before reusing a PID, but we want to clean up before that becomes a risk.\n */\n private _isStaleEntry(entry: TrackedProcess): boolean {\n return entry.child.exitCode !== null && Date.now() - entry.startedAt > 60_000;\n }\n\n /**\n * Remove a stale entry for a specific PID before any PID-based lookup.\n * This prevents PID reuse from causing the registry to act on a dead\n * process that has been replaced by a new one with the same PID.\n */\n private _pruneStale(pid: number): void {\n const entry = this.processes.get(pid);\n if (entry && this._isStaleEntry(entry)) {\n this.processes.delete(pid);\n }\n }\n}\n\n/** Module-level singleton. Initialized on first access. */\nlet _registry: ProcessRegistryImpl | undefined;\n\nexport function getProcessRegistry(): ProcessRegistryImpl {\n if (!_registry) {\n _registry = new ProcessRegistryImpl();\n }\n return _registry;\n}\n\n/** Reset for tests. */\nexport function _resetProcessRegistry(): void {\n _registry = undefined;\n}\n\n// ── Convenience re-exports ────────────────────────────────────────────────────\n\nexport type { KillOpts };\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * On Windows, Node.js `spawn()` without a shell does NOT resolve .cmd/.bat\n * extensions through PATHEXT — it only auto-resolves .exe. Most Node.js CLI\n * tools (npx, pnpm, biome, tsc, vitest, etc.) ship as .cmd wrappers on\n * Windows. This function resolves the command name to its full path so spawn\n * can find it without relying on shell-mode argument concatenation.\n *\n * On non-Windows, returns the command unchanged.\n */\nexport function resolveWin32Command(cmd: string): string {\n if (process.platform !== 'win32') return cmd;\n\n // Already has a path or extension — use as-is\n // Normalize forward slashes so path.extname correctly detects extensions\n // even when a Unix-style path is passed on Windows.\n if (cmd.includes('/') || cmd.includes('\\\\') || path.extname(cmd.replace(/\\//g, '\\\\'))) {\n return cmd;\n }\n\n const pathext = (process.env['PATHEXT'] ?? '.COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC')\n .toLowerCase()\n .split(';');\n\n const pathDirs = (process.env['PATH'] ?? '').split(path.delimiter);\n\n for (const dir of pathDirs) {\n const base = path.join(dir, cmd);\n // Check extensions in PATHEXT order. .EXE should win first because\n // it's typically listed first, and .exe doesn't need shell: true.\n for (const ext of pathext) {\n const full = `${base}${ext}`;\n try {\n fs.accessSync(full, fs.constants.X_OK);\n return full;\n } catch {\n // Not found with this extension — try next\n }\n }\n }\n\n // Not found — return original; let spawn report ENOENT with the\n // expected error message so tools can surface it properly.\n return cmd;\n}\n\n/**\n * Resolve a PowerShell binary by name. `pickShell` in `_shell-pick.ts`\n * already decides whether the user wants `'pwsh'` (PowerShell 7+) or\n * `'powershell'` (Windows PowerShell 5.1). This helper turns that decision\n * into a real on-disk path.\n *\n * Order:\n * 1. If `cmd` is `pwsh` and a `pwsh.exe` exists on PATH → return that.\n * 2. If `cmd` is `pwsh` and only `powershell.exe` exists → fall back to\n * that (the alternative is a cryptic ENOENT for the user).\n * 3. Symmetric for `powershell`: prefer `powershell.exe`, fall back to\n * `pwsh.exe` if installed and the legacy binary is missing.\n * 4. Anything else → delegate to `resolveWin32Command` (handles `.cmd`\n * shims a sysadmin might drop in place, etc.).\n *\n * Returns the original command on ENOENT — `spawn()` will surface a clean\n * ENOENT and the user sees \"PowerShell not installed\", which is the right\n * diagnostic. We never throw from here.\n */\nexport function resolvePowerShell(cmd: string): string {\n if (process.platform !== 'win32') return cmd;\n const lower = cmd.toLowerCase();\n if (lower !== 'pwsh' && lower !== 'powershell' && lower !== 'pwsh.exe' && lower !== 'powershell.exe') {\n return resolveWin32Command(cmd);\n }\n // Prefer the requested edition, fall back to the other one.\n const primary = lower.startsWith('pwsh') ? 'pwsh.exe' : 'powershell.exe';\n const fallback = lower.startsWith('pwsh') ? 'powershell.exe' : 'pwsh.exe';\n const resolved = resolveWin32Command(primary);\n if (resolved !== primary) {\n // resolveWin32Command returns the original string when not found.\n const fb = resolveWin32Command(fallback);\n return fb === fallback ? cmd : fb;\n }\n return resolved;\n}\n\n/**\n * cmd.exe metacharacters that chain a new command or redirect I/O. When a\n * `.cmd`/`.bat` wrapper is launched through `cmd.exe`, any argument carrying\n * one of these can break out of the intended command line and run an\n * attacker-chosen command (the CVE-2024-27980 / \"BatBadBut\" argument-injection\n * class). We use a single vetted command line for cmd shims, so this guard is\n * mandatory before spawning.\n *\n * The set is limited to the unambiguous command-separator / redirection chars\n * plus newlines and NUL. Legitimate package-manager / test-runner flags and\n * Windows file paths (which use `:` `\\` `/` `.` `-` `_` space `(` `)`) never\n * contain these, so the guard is false-positive-free. Double quotes are also\n * rejected because cmd.exe quote toggling can break argument grouping.\n */\nconst WIN32_SHELL_META = /[&|<>\"\\r\\n\\0]/;\n\nexport interface Win32CmdShimInvocation {\n command: string;\n args: string[];\n windowsVerbatimArguments: true;\n}\n\n/**\n * Throw if any argument contains a cmd.exe command-injection metacharacter.\n * Call this ONLY on the Windows `.cmd`/`.bat` shim path. A no-op for safe args.\n */\nexport function assertSafeWin32ShellArgs(args: readonly unknown[]): void {\n for (const arg of args) {\n if (typeof arg === 'string' && WIN32_SHELL_META.test(arg)) {\n throw new Error(\n 'win32 cmd shim spawn: argument contains a shell metacharacter ' +\n '(one of & | < > \", or a newline) that could enable command injection ' +\n 'through the .cmd/.bat wrapper - refusing to run. Offending argument: ' +\n JSON.stringify(arg),\n );\n }\n }\n}\n\nexport function buildWin32CmdShimInvocation(\n command: string,\n args: readonly string[] = [],\n): Win32CmdShimInvocation {\n assertSafeWin32ShellArgs([command, ...args]);\n const line = ['call', quoteWin32CmdArg(command), ...args.map(quoteWin32CmdArg)].join(' ');\n return {\n command: process.env['COMSPEC'] ?? 'cmd.exe',\n args: ['/d', '/c', line],\n windowsVerbatimArguments: true,\n };\n}\n\nfunction quoteWin32CmdArg(arg: string): string {\n return `\"${arg}\"`;\n}\n","import { spawn } from 'node:child_process';\nimport type { Tool } from '@wrongstack/core';\nimport { toErrorMessage } from '@wrongstack/core/utils/error';\nimport { buildChildEnv } from './_env.js';\nimport { createOutputSpool, spoolNote } from './_output-spool.js';\nimport { COMMAND_OUTPUT_MAX_BYTES, normalizeCommandOutput, safeResolveReal } from './_util.js';\nimport { getProcessRegistry, redactCommand } from './process-registry.js';\nimport {\n buildWin32CmdShimInvocation,\n resolveWin32Command,\n} from './_win32-resolve.js';\n\nconst isWin = process.platform === 'win32';\n\n// Curated default allowlist of command NAMES the `exec` tool may run. Only the\n// command name is gated (per-arg safety is the BLOCKED_ARG_PATTERNS denylist\n// below + the per-call `confirm` permission). A prior version mapped each\n// command to an allowed-args array, but those arrays were never enforced (dead\n// code) — a plain Set is the honest shape.\n//\n// Extend/trim at runtime via `configureExecPolicy()` (wired from\n// `config.tools.exec.{allow,deny}` at boot). `allow` is trusted-config-only;\n// see the security note on ExecToolConfig.\nconst DEFAULT_ALLOWED_COMMANDS: ReadonlySet<string> = new Set([\n // JS / TS toolchain\n 'node', 'npm', 'pnpm', 'yarn', 'npx', 'bun', 'deno',\n 'corepack', 'tsc', 'tsx', 'ts-node', 'vite', 'vitest', 'jest',\n 'biome', 'eslint', 'prettier', 'turbo', 'nx', 'webpack', 'rollup',\n 'parcel', 'next', 'astro', 'playwright', 'cypress',\n // version control\n 'git',\n // Rust\n 'cargo', 'rustc',\n // Go\n 'go',\n // Python\n 'python', 'python3', 'pip', 'pip3', 'pytest', 'ruff', 'mypy',\n 'uv', 'uvx', 'poetry', 'hatch', 'tox',\n // Ruby\n 'ruby', 'gem', 'bundle',\n // PHP\n 'php', 'composer', 'phpunit',\n // JVM\n 'java', 'javac', 'mvn', 'gradle', 'gradlew',\n // .NET\n 'dotnet',\n // C / C++ / native build\n 'make', 'cmake', 'ninja', 'clang', 'clang-cl', 'gcc', 'g++', 'link', 'msbuild',\n // containers / orchestration\n 'docker', 'podman', 'kubectl',\n // network (read-only intent; destructive ops still blocked by BLOCKED_ARG_PATTERNS)\n 'curl', 'wget',\n // common POSIX file/text utilities\n 'pwd', 'ls', 'cat', 'head', 'tail', 'wc', 'grep', 'rg', 'find',\n 'echo', 'sort', 'uniq', 'sed', 'awk', 'mkdir', 'cp', 'mv', 'rm',\n 'touch', 'tar',\n // Windows-native tooling (win32). All non-destructive binaries; per-arg\n // safety is still enforced by BLOCKED_ARG_PATTERNS + the destructive-ops\n // gate in bash-kill-guard.ts. `gh` is included even though it lives at\n // \"C:\\Program Files\\GitHub CLI\\gh.exe\" — resolveWin32Command handles the\n // space in the path.\n 'gh',\n 'where', 'tasklist', 'systeminfo', 'wmic', 'sc',\n 'netstat', 'ipconfig', 'nslookup', 'tracert', 'pathping',\n // Windows shell interpreters. Without these, `exec` cannot run cmd builtins\n // (`dir`, `type`, `copy`, …) or any PowerShell cmdlet on Windows — a major\n // gap since those are the platform's primary shells. Arbitrary execution\n // through `cmd /c …` / `powershell -c …` is NOT a new hole: the permission\n // policy reconstructs the full command line (shellCommandLineFromInput) and\n // still runs it through the YOLO destructive classifier, so a genuinely\n // destructive `cmd /c del /s /q C:\\…` continues to require confirmation.\n 'cmd', 'cmd.exe', 'powershell', 'powershell.exe', 'pwsh', 'pwsh.exe',\n // [core] Extended default allowlist (added 4b3d18d1 + this commit). All\n // non-destructive, broadly-used dev binaries. Per-arg safety is still\n // enforced by BLOCKED_ARG_PATTERNS + bash-kill-guard.ts.\n // --- Archives & compression ---\n '7z', '7za', 'bzip2', 'gzip', 'xz', 'unzip', 'zip', 'gtar', 'bsdtar', 'star', 'pax', 'cpio',\n // --- Android / mobile dev ---\n 'adb', 'fastboot', 'sdkmanager',\n // --- DevOps / config mgmt ---\n 'ansible', 'ansible-playbook', 'ansible-vault', 'ansible-lint', 'ansible-galaxy', 'molecule',\n // --- Cloud CLIs ---\n 'aws', 'aws-vault', 'awslocal', 'az', 'azcopy', 'gcloud', 'gsutil', 'doctl', 'linode-cli',\n // --- Native / C / C++ / linker tools ---\n 'clang++', 'clang-format', 'clang-tidy', 'clangd', 'lld', 'lldb', 'ctest', 'gmake', 'meson', 'conan', 'vcpkg', 'cl', 'rc', 'mt', 'dumpbin', 'dotnet-format',\n // --- Image / media / binary tools ---\n 'convert', 'ffmpeg', 'ffprobe', 'magick', 'gs', 'exiftool',\n // --- HTTP / fetch ---\n 'wget2', 'aria2c', 'axel', 'httpie', 'hey', 'ab', 'wrk', 'http',\n // --- Diff / patch / merge ---\n 'diff', 'diff3', 'patch', 'meld', 'kdiff3', 'kompare',\n // --- Encoding / file inspection ---\n 'dos2unix', 'unix2dos', 'iconv', 'file', 'stat', 'xxd', 'hexdump', 'od', 'base64',\n // --- SSH / crypto / signing ---\n 'ssh', 'ssh-add', 'ssh-keygen', 'ssh-keyscan', 'scp', 'sftp', 'rsync', 'gpg', 'gpg2', 'gpg-agent', 'openssl', 'step', 'keytool',\n // --- Search ---\n 'egrep', 'fgrep', 'ag', 'ack', 'sift', 'ugrep', 'fd', 'fdfind', 'jq', 'yq', 'xq', 'fx', 'gron',\n // --- K8s / container ecosystem ---\n 'kubectl.exe', 'kubeadm', 'kubelet', 'helm', 'k9s', 'kustomize', 'skaffold', 'tilt', 'minikube', 'kind', 'k3d', 'k3s',\n 'docker-compose', 'buildah', 'skopeo', 'nerdctl', 'ctr', 'ctr.exe',\n // --- Databases ---\n 'sqlite3', 'sqlite', 'psql', 'pg_dump', 'pg_restore', 'mysql', 'mysqladmin', 'mysqldump', 'mariadb', 'mariadb-dump',\n 'redis-cli', 'redis-server', 'memcached', 'etcdctl', 'consul', 'vault', 'nomad',\n 'mongosh', 'mongo', 'mongoexport', 'mongoimport', 'mongodump', 'mongorestore',\n // --- Windows extended (read-mostly ops) ---\n 'taskkill', 'gpupdate', 'gpresult', 'hostname', 'whoami', 'who', 'net', 'net1',\n // --- VCS ecosystem ---\n 'glab', 'hub', 'tea', 'git-lfs', 'tig', 'lazygit',\n // --- POSIX text utilities (extended; duplicates of pwd/ls/cat/head/tail/wc/\n // grep/find/echo/awk/mkdir/cp/mv/rm/touch from the base list above are\n // omitted — the Set is de-duplicated at runtime but a clean literal is\n // easier to maintain) ---\n 'gawk', 'tr', 'cut', 'paste', 'join', 'comm', 'expand', 'unexpand', 'fold', 'fmt', 'nl', 'pr', 'column', 'tsort',\n 'tty', 'ul', 'units', 'factor', 'seq', 'shuf', 'look', 'yes', 'true', 'false', 'test', '[', 'printf',\n 'env',\n 'tree', 'locate', 'which', 'whereis', 'type', 'hash', 'pushd', 'popd', 'dirs', 'history', 'fc', 'jobs', 'bg', 'fg', 'wait',\n 'ulimit', 'umask', 'nice', 'nohup', 'timeout', 'time', 'trap', 'exit', 'return', 'source', '.', 'alias', 'unalias',\n 'set', 'unset', 'export', 'readonly', 'typeset', 'declare', 'local', 'eval', 'exec',\n // --- Process / system inspection ---\n 'htop', 'top', 'atop', 'glances', 'iotop', 'nethogs', 'iftop', 'lsof', 'strace', 'ltrace', 'sysstat', 'vmstat', 'iostat', 'mpstat', 'sar',\n 'free', 'df', 'du', 'mount', 'umount', 'lsblk', 'blkid',\n 'kill', 'killall', 'pkill', 'pgrep', 'pidof', 'ps', 'ps.exe',\n // --- Network inspection ---\n 'ip', 'ss', 'route', 'arp', 'arping', 'ping', 'ping6', 'hping3', 'mtr', 'tracepath', 'tcpdump', 'nmap', 'netcat', 'nc', 'ncat', 'socat',\n // --- Sync / backup ---\n 'rclone', 'restic', 'borg', 'duplicati', 'duplicacy', 'syncthing', 'syncthing-cli',\n // --- Permissions / users / ACLs (POSIX) ---\n 'useradd', 'userdel', 'usermod', 'groupadd', 'groupdel', 'groupmod', 'chown', 'chmod', 'chgrp', 'getfacl', 'setfacl', 'setcap', 'getcap',\n // --- Crypto / cert mgmt (extended) ---\n 'certbot', 'mkcert', 'jarsigner',\n // --- Editors ---\n 'subl', 'code', 'code-insiders', 'cursor', 'atom', 'nano', 'vim', 'nvim', 'vi', 'emacs', 'helix', 'hx', 'micro', 'jed', 'ed', 'ex', 'mg',\n // --- Terminal multiplexers ---\n 'asciinema', 'script', 'scriptreplay', 'expect', 'screen', 'tmux', 'byobu', 'dtach', 'abduco',\n // --- Calculators / REPLs / scientific ---\n 'bc', 'dc', 'calc', 'qalc', 'genius', 'octave', 'R', 'Rscript', 'julia', 'irb', 'pry', 'ghci', 'stack', 'cabal', 'ghc',\n // --- PHP / Lua / Perl / Ruby ecosystem (extended) ---\n 'php8', 'php7', 'phpcs', 'phpcbf', 'phpmd', 'phpstan', 'psalm',\n 'lua', 'lua5.1', 'lua5.2', 'lua5.3', 'lua5.4', 'luarocks',\n 'perl', 'cpan', 'prove', 'plackup',\n 'rake', 'rspec', 'jekyll', 'node-gyp', 'node-pre-gyp',\n // --- JS / TS toolchain (extended) ---\n 'electron', 'electron-builder', 'electron-forge', 'vite-preview', 'swc', 'swc-cli', 'swcpack',\n 'mocha', 'chai', 'jasmine', 'puppeteer', 'lighthouse',\n // --- Linters / formatters (extended) ---\n 'tslint', 'stylelint', 'htmlhint', 'jshint', 'jslint', 'jscs',\n // --- Document conversion ---\n 'pandoc', 'weasyprint', 'wkhtmltopdf', 'wkhtmltoimage', 'prince', 'mdp', 'markdown', 'multimarkdown', 'cmark', 'cmark-gfm',\n // --- Office / spreadsheet ---\n 'soffice', 'libreoffice', 'unoconv', 'abiword', 'gnumeric',\n // --- Spell / grammar ---\n 'aspell', 'hunspell', 'enchant', 'languagetool',\n // --- Source-highlight / diff tools ---\n 'delta', 'bat', 'ccat', 'hl', 'highlight', 'source-highlight', 'ansifilter',\n // --- Job schedulers ---\n 'pueue', 'task-spooler', 'ts', 'at', 'atd', 'anacron', 'fcron', 'cronie', 'systemd-run', 'systemd-cat',\n // --- Plotting / visualization ---\n 'gnuplot', 'gnuplot-nox', 'veusz', 'scidavis', 'grace', 'xmgrace', 'labplot',\n // --- Security / recon (network + web) ---\n 'masscan', 'zmap', 'rustscan', 'amass', 'subfinder', 'httpx', 'nuclei', 'naabu', 'katana', 'dnsx', 'assetfinder', 'findomain', 'gau', 'waybackurls', 'httprobe', 'meg', 'subjack', 'sublert', 'chaos',\n]);\n\n// The live, effective allowlist: DEFAULT ∪ config.allow − config.deny. Replaced\n// wholesale by configureExecPolicy(); defaults until boot wires the config.\nlet allowedCommands: Set<string> = new Set(DEFAULT_ALLOWED_COMMANDS);\n\nconst normalizeCmd = (c: string): string => c.trim();\n\n/**\n * Apply the configured exec command policy. Recomputes the effective allowlist\n * as `DEFAULT ∪ allow − deny`. Call once at boot from\n * `config.tools.exec.{allow,deny}`. Idempotent (always rebuilt from defaults).\n *\n * SECURITY: `allow` must originate from TRUSTED config only — the config loader\n * strips `tools.exec.allow` from the untrusted in-project repo config before it\n * reaches here. `deny` is safe from any source (it only narrows).\n */\nexport function configureExecPolicy(opts: { allow?: readonly string[] | undefined; deny?: readonly string[] | undefined } = {}): void {\n const next = new Set(DEFAULT_ALLOWED_COMMANDS);\n for (const c of opts.allow ?? []) {\n const n = normalizeCmd(c);\n if (n) next.add(n);\n }\n for (const c of opts.deny ?? []) next.delete(normalizeCmd(c));\n allowedCommands = next;\n}\n\n/** Reset the exec allowlist to the built-in defaults (tests / re-init). */\nexport function resetExecPolicy(): void {\n allowedCommands = new Set(DEFAULT_ALLOWED_COMMANDS);\n}\n\n/** Whether `cmd` is currently in the effective exec allowlist. */\nexport function isExecCommandAllowed(cmd: string): boolean {\n return allowedCommands.has(normalizeCmd(cmd));\n}\n\n/** Snapshot of the effective allowlist (sorted) — for tests / diagnostics. */\nexport function getExecAllowlist(): string[] {\n return [...allowedCommands].sort();\n}\n\nconst MAX_ARGS = 20;\n// 200 KB — larger than bash's 32 KB cap. exec commands produce structured,\n// predictable output (build logs, test results, git diffs) that the agent\n// needs in full. 200 KB is safe for context windows ≥200K tokens while\n// still preventing a rogue build from filling the context.\nconst MAX_OUTPUT = 200_000;\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n// Per-command hard-blocks. Keep this list narrow: `exec` is already a\n// confirm-gated tool with argv passed as an array and cwd confined to the\n// project. These patterns should block clear sandbox escapes / destructive\n// operations, not normal development workflows that happen to execute code.\nconst BLOCKED_ARG_PATTERNS: Record<string, RegExp[]> = {\n python: [],\n // git --exec=<cmd> runs arbitrary commands via upload-pack/receive-pack;\n // -C <dir> changes working directory, bypassing cwd sandbox;\n // -c/--config <k>=<v> injects config that runs commands\n // (e.g. core.sshCommand, core.pager, http.proxy, alias.x=!cmd).\n git: [\n /^--exec=/,\n /^--upload-pack=/,\n /^--receive-pack=/,\n /^-C$/,\n /^-c$/,\n /^--config$/,\n /^-c=/,\n /^--config=/,\n /^--config-env=/,\n ],\n node: [],\n go: [],\n bun: [],\n docker: [],\n // find -exec/-ok/-execdir execute arbitrary commands\n find: [/^-exec$/, /^-exec;$/, /^-ok$/, /^-ok;$/, /^-execdir$/, /^-execdir;$/, /^-exec=/, /^-ok=/, /^-execdir=/],\n // rm -rf / is catastrophic — block absolute paths, home, dot-dirs,\n // and glob patterns that could expand to dangerous targets.\n // `rm -rf ./src/*` expands to project files; `rm -rf ../../` escapes upward;\n // `rm -rf /*` targets the filesystem root. All are blocked.\n rm: [/^\\//, /^~\\//, /^~$/, /^\\.$/, /^\\.\\.$/, /\\*$/, /\\/$/, /\\/\\*$/, /\\.\\//],\n // npm/pnpm subcommands are checked separately below. Matching every arg here\n // over-blocked normal dev flows such as `pnpm vitest run ...`.\n npm: [],\n pnpm: [],\n npx: [],\n};\n\n// Subcommand verbs only make sense in subcommand position. Keep externally\n// destructive actions blocked there without rejecting harmless downstream args\n// named \"run\", \"publish\", etc. passed to test runners or build tools.\nconst BLOCKED_SUBCOMMANDS: Record<string, ReadonlySet<string>> = {\n docker: new Set(['push']),\n podman: new Set(['push']),\n npm: new Set(['publish', 'deploy']),\n pnpm: new Set(['publish', 'deploy']),\n yarn: new Set(['publish']),\n};\n\nconst BLOCKED_SUBCOMMAND_SEQUENCES: Record<string, readonly (readonly string[])[]> = {\n yarn: [['npm', 'publish']],\n};\n\nfunction firstSubcommand(args: string[]): string | null {\n for (const arg of args) {\n if (arg === '--') return null;\n if (!arg.startsWith('-')) return arg;\n }\n return null;\n}\n\nfunction subcommandArgs(args: string[]): string[] {\n const out: string[] = [];\n for (const arg of args) {\n if (arg === '--') break;\n if (!arg.startsWith('-')) out.push(arg);\n }\n return out;\n}\n\nfunction validateArgs(cmd: string, args: string[]): string | null {\n const blockedSubcommands = BLOCKED_SUBCOMMANDS[cmd];\n const subcommand = firstSubcommand(args);\n if (blockedSubcommands && subcommand && blockedSubcommands.has(subcommand)) {\n return `Blocked subcommand \"${subcommand}\" for command \"${cmd}\"`;\n }\n\n const blockedSequences = BLOCKED_SUBCOMMAND_SEQUENCES[cmd];\n if (blockedSequences) {\n const actual = subcommandArgs(args);\n const blocked = blockedSequences.find((seq) => seq.every((part, idx) => actual[idx] === part));\n if (blocked) return `Blocked subcommand \"${blocked.join(' ')}\" for command \"${cmd}\"`;\n }\n\n const blocked = BLOCKED_ARG_PATTERNS[cmd];\n if (!blocked) return null;\n\n for (const arg of args) {\n for (const pattern of blocked) {\n if (pattern.test(arg)) {\n return `Blocked argument \"${arg}\" for command \"${cmd}\" (matches security pattern ${pattern})`;\n }\n }\n }\n return null;\n}\n\ninterface ExecInput {\n command: string;\n args?: string[] | undefined;\n cwd?: string | undefined;\n timeout?: number | undefined;\n}\n\ninterface ExecOutput {\n command: string;\n args: string[];\n stdout: string;\n stderr: string;\n exitCode: number;\n truncated: boolean;\n allowed: boolean;\n}\n\nexport const execTool: Tool<ExecInput, ExecOutput> = {\n name: 'exec',\n category: 'Shell',\n description:\n 'Execute a **whitelisted, restricted set of commands** with strict argument validation. ' +\n 'This is the **preferred and safer** alternative to the `bash` tool for running development tools (node, npm, pnpm, tsc, git, tests, linters, etc.). ' +\n 'It prevents arbitrary command injection and limits what the model can do.',\n usageHint:\n 'PREFERRED SHELL TOOL for most cases.\\n\\n' +\n 'Use this instead of `bash` whenever possible.\\n' +\n '- `command` must be in the allowlist. Defaults cover JS (node/npm/pnpm/yarn/bun/deno/tsc/vitest/eslint/biome), Go (`go build`/`go test`), Rust (cargo), Python (python/pip), Ruby (gem/bundle), JVM (java/mvn/gradle), .NET (dotnet), native (make/cmake), and git. Users can extend it via `tools.exec.allow` in config.\\n' +\n '- Arguments are passed as a clean array (no shell interpretation).\\n' +\n '- `cwd` is validated to stay inside the project.\\n' +\n '- If a command is not allowlisted, the error explains how to add it; for one-off arbitrary commands, fall back to `bash` (with strong justification).\\n' +\n 'This tool significantly reduces the risk compared to full shell access.',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n timeoutMs: DEFAULT_TIMEOUT_MS,\n capabilities: ['shell.restricted'],\n icon: 'terminal',\n inputSchema: {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n description: 'The base command to run. Must be in the internal allowlist (e.g. \"node\", \"pnpm\", \"git\", \"tsc\").',\n },\n args: {\n type: 'array',\n items: { type: 'string' },\n description: 'Arguments passed to the command. Passed as an array (no shell parsing).',\n },\n cwd: {\n type: 'string',\n description: 'Optional working directory. Must resolve inside the project root.',\n },\n timeout: {\n type: 'integer',\n description: 'Per-command timeout in milliseconds.',\n },\n },\n required: ['command'],\n },\n async execute(input, ctx, opts) {\n const registry = getProcessRegistry();\n if (!registry.canProceed) {\n return {\n command: input.command,\n args: input.args ?? [],\n stdout: '',\n stderr: 'Circuit breaker is open — too many consecutive failures. Use /kill reset to recover.',\n exitCode: 1,\n truncated: false,\n allowed: false,\n };\n }\n\n const cmd = input.command.trim();\n if (!cmd)\n return {\n command: cmd,\n args: [],\n stdout: '',\n stderr: 'Empty command',\n exitCode: 1,\n truncated: false,\n allowed: false,\n };\n\n if (!isExecCommandAllowed(cmd)) {\n return {\n command: cmd,\n args: input.args ?? [],\n stdout: '',\n stderr:\n `Command \"${cmd}\" not in allowlist. ` +\n `Add it to your ~/.wrongstack/config.json under \"tools\": { \"exec\": { \"allow\": [\"${cmd}\"] } }, ` +\n `or use the bash tool for one-off arbitrary commands.`,\n exitCode: 1,\n truncated: false,\n allowed: false,\n };\n }\n\n const args = (input.args ?? []).slice(0, MAX_ARGS);\n const timeout = Math.max(1, Math.min(input.timeout ?? DEFAULT_TIMEOUT_MS, DEFAULT_TIMEOUT_MS));\n\n // Validate args against per-command security patterns\n const argError = validateArgs(cmd, args);\n if (argError) {\n return {\n command: cmd,\n args,\n stdout: '',\n stderr: argError,\n exitCode: 1,\n truncated: false,\n allowed: false,\n };\n }\n\n let cwd: string;\n try {\n // Resolve cwd inside the project root and verify realpath containment so\n // an in-project symlink cannot redirect allowlisted commands outside.\n cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : await safeResolveReal(ctx.cwd, ctx);\n } catch {\n return {\n command: cmd,\n args,\n stdout: '',\n stderr: `cwd \"${input.cwd ?? ctx.cwd}\" resolves outside project root`,\n exitCode: 1,\n truncated: false,\n allowed: false,\n };\n }\n const signal = opts.signal;\n\n return runCommand(cmd, args, cwd, timeout, signal, ctx.session?.id);\n },\n};\n\nfunction runCommand(\n cmd: string,\n args: string[],\n cwd: string,\n timeout: number,\n signal: AbortSignal,\n sessionId: string | undefined,\n): Promise<ExecOutput> {\n return new Promise((resolve) => {\n let stdout = '';\n let stderr = '';\n let killed = false;\n const resolvedOnce = { value: false };\n const finish = (result: ExecOutput): void => {\n // Guard against double-resolve: 'error' and 'close' can both fire for\n // the same abort (Node's abort path emits both), and resolving twice\n // is a no-op but the extra work (normalizeCommandOutput, registry\n // bookkeeping, spool finalize) is wasted. First writer wins.\n if (resolvedOnce.value) return;\n resolvedOnce.value = true;\n resolve(result);\n };\n const startedAt = Date.now();\n // Full-output spool (stdout+stderr interleaved as they arrive): the\n // in-memory buffers keep only the first MAX_OUTPUT bytes; the spool\n // captures everything on disk and the result points at the file.\n const spool = createOutputSpool({ tool: `exec-${cmd}`, thresholdBytes: MAX_OUTPUT });\n\n // On Windows, .cmd/.bat files are not natively executable by CreateProcess.\n // resolveWin32Command() finds the full path, then the shim helper launches\n // it through cmd.exe without Node's deprecated shell+args path.\n const resolved = resolveWin32Command(cmd);\n const needsShell = isWin && (resolved.endsWith('.cmd') || resolved.endsWith('.bat'));\n const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;\n const spawnCmd = shim?.command ?? resolved;\n const spawnArgs = shim?.args ?? args;\n\n // Wrap the entire spawn lifecycle in try/catch so a synchronous throw\n // (bad argv, ENOENT for missing binary, ERR_INVALID_ARG_TYPE for bad\n // signal, etc.) resolves the promise with an error response instead\n // of producing an unhandled rejection. Without this guard the\n // promise executor itself can throw, which Node treats as an\n // unhandled rejection and surfaces in process.on('unhandledRejection').\n let child: ReturnType<typeof spawn>;\n try {\n // On Windows the abort signal is handled manually below: Node's built-in\n // handling kills only the direct child, orphaning grandchildren (vitest\n // forks, dev servers, anything under a .cmd shim) that keep the inherited\n // stdio pipes open. registry.kill() tree-kills via taskkill instead.\n child = spawn(spawnCmd, spawnArgs, {\n cwd,\n env: buildChildEnv(sessionId),\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n ...(isWin ? {} : { signal }),\n ...(shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {}),\n });\n } catch (err) {\n // spawn() can throw synchronously — e.g. ERR_INVALID_ARG_TYPE for a\n // malformed `signal`, or for some Node versions ENOENT when the binary\n // isn't on PATH. Convert to a graceful result so the tool caller\n // sees a structured error instead of an unhandled rejection that\n // would crash the host.\n spool.finalize();\n finish({\n command: cmd,\n args,\n stdout: '',\n stderr: `spawn failed: ${toErrorMessage(err)}`,\n exitCode: 1,\n truncated: false,\n allowed: true,\n });\n return;\n }\n\n // Attach the 'error' listener IMMEDIATELY after spawn, BEFORE any other\n // async setup (process registry call, setTimeout, abort listener). The\n // Node EventEmitter contract is that an 'error' event with no listener\n // rethrows on nextTick and crashes the entire process — this is the\n // exact failure mode issue #99 describes. Attach first, then do the\n // bookkeeping, so an abort / ENOENT / EPIPE that fires between spawn\n // and the rest of setup still has a listener attached.\n child.on('error', (err) => {\n // Distinguish an abort from a true spawn failure so the caller can\n // tell \"the user cancelled this\" apart from \"the binary is missing\".\n // The signal passed to spawn() is an AbortSignal; Node internally\n // converts the abort into an AbortError with `code: 'ABORT_ERR'`.\n const isAbort = err && (err as NodeJS.ErrnoException).code === 'ABORT_ERR';\n const stderrText = isAbort ? `Aborted: ${err.message}` : err.message;\n clearTimeout(timer);\n if (isWin) signal.removeEventListener('abort', onAbort);\n if (typeof pid === 'number') registry.unregister(pid);\n registry.afterCall(Date.now() - startedAt, true);\n spool.finalize();\n finish({\n command: cmd,\n args,\n stdout: normalizeCommandOutput(stdout),\n stderr: stderrText,\n exitCode: isAbort ? 124 : 1,\n truncated: Buffer.byteLength(stdout, 'utf8') > COMMAND_OUTPUT_MAX_BYTES,\n allowed: true,\n });\n });\n\n const registry = getProcessRegistry();\n const pid = child.pid;\n if (typeof pid === 'number') {\n const fullCommand = `${cmd} ${args.join(' ')}`;\n registry.register({ pid, name: 'exec', command: redactCommand(fullCommand), startedAt: Date.now(), sessionId, child });\n }\n\n const timer = setTimeout(() => {\n killed = true;\n if (typeof pid === 'number') registry.kill(pid);\n else child.kill('SIGTERM');\n }, timeout);\n\n const onAbort = () => {\n killed = true;\n if (typeof pid === 'number') registry.kill(pid, { force: true });\n else child.kill('SIGTERM');\n };\n if (isWin) {\n if (signal.aborted) onAbort();\n else signal.addEventListener('abort', onAbort, { once: true });\n }\n\n child.stdout?.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n if (stdout.length < MAX_OUTPUT) stdout += text;\n spool.write(text);\n });\n\n child.stderr?.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n if (stderr.length < MAX_OUTPUT) stderr += text;\n spool.write(text);\n });\n\n child.on('close', (code) => {\n clearTimeout(timer);\n if (isWin) signal.removeEventListener('abort', onAbort);\n if (typeof pid === 'number') registry.unregister(pid);\n const durationMs = Date.now() - startedAt;\n const exitCode = killed ? 124 : (code ?? 1);\n registry.afterCall(durationMs, exitCode !== 0);\n const spooled = spool.finalize();\n finish({\n command: cmd,\n args,\n stdout: normalizeCommandOutput(stdout) + (spooled ? spoolNote(spooled) : ''),\n stderr: normalizeCommandOutput(stderr),\n exitCode,\n truncated:\n Buffer.byteLength(stdout, 'utf8') > COMMAND_OUTPUT_MAX_BYTES ||\n Buffer.byteLength(stderr, 'utf8') > COMMAND_OUTPUT_MAX_BYTES,\n allowed: true,\n });\n });\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/_output-spool.ts","../src/_util.ts","../src/circuit-breaker.ts","../src/process-registry.ts","../src/_win32-resolve.ts","../src/_danger-detect.ts","../src/exec.ts"],"names":["path","fsp2","isWin","path3","blocked","resolve","spawn"],"mappings":"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","file":"exec.js","sourcesContent":["/**\n * _output-spool — file-based capture of FULL command output.\n *\n * Command tools (bash/exec and the _spawn-stream consumers) cap what they\n * keep in memory and what reaches the model (COMMAND_OUTPUT_MAX_BYTES head+\n * tail). Everything past the cap used to be silently dropped, which pushed\n * agents to re-run commands with bigger buffers or stuff huge outputs into\n * chat history. The spool keeps the host's memory and the context window\n * small while losing nothing: once a command's output exceeds the in-memory\n * threshold, the FULL stream is written to a log file under\n * `~/.wrongstack/tool-output/` and the capped tool result carries a\n * `[full output: <path>]` marker so the model can read/grep the file\n * selectively instead of dumping it into context.\n *\n * Properties:\n * - zero disk I/O for small outputs (file is created lazily on first byte\n * past the threshold; the buffered head is flushed at that moment)\n * - bounded memory: the head buffer never exceeds the threshold, and disk\n * backpressure drops chunks past a 4 MB writable-buffer high-water mark\n * (counted and reported in the marker) instead of queueing them on the heap\n * - best-effort: any fs error disables the spool silently — command tools\n * must never fail because diagnostics couldn't be written\n * - retention: spool files older than 7 days are swept once per process\n */\nimport { createWriteStream, mkdirSync, type WriteStream } from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { wstackGlobalRoot } from '@wrongstack/core';\n\nconst SPOOL_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;\n/** Stop queueing chunks on the heap when the fs stream falls this far behind. */\nconst SPOOL_WRITE_HWM_BYTES = 4 * 1024 * 1024;\n\nlet sweepStarted = false;\n\n/** Directory for spooled command output (under the wstack global root). */\nexport function toolOutputDir(): string {\n return path.join(wstackGlobalRoot(), 'tool-output');\n}\n\n/** Reset module state — test hook (per-process sweep memo + nothing else). */\nexport function _resetOutputSpoolForTests(): void {\n sweepStarted = false;\n}\n\nfunction sweepOldSpoolFiles(dir: string): void {\n if (sweepStarted) return;\n sweepStarted = true;\n void (async () => {\n try {\n const now = Date.now();\n for (const name of await fsp.readdir(dir)) {\n if (!name.endsWith('.log')) continue;\n const p = path.join(dir, name);\n try {\n const st = await fsp.stat(p);\n if (now - st.mtimeMs > SPOOL_RETENTION_MS) await fsp.unlink(p);\n } catch {\n /* concurrently removed — ignore */\n }\n }\n } catch {\n /* directory doesn't exist yet — nothing to sweep */\n }\n })();\n}\n\nexport interface SpoolInfo {\n /** Absolute path of the spool file. */\n path: string;\n /** Total bytes of output produced (including what reached the file). */\n bytes: number;\n /** Bytes dropped due to disk backpressure (0 in the normal case). */\n droppedBytes: number;\n}\n\nexport interface OutputSpool {\n /** Feed every raw output chunk. Never throws. */\n write(text: string): void;\n /**\n * Close the file (if one was opened) and return its info, or null when the\n * output never exceeded the threshold. Idempotent.\n */\n finalize(): SpoolInfo | null;\n}\n\nexport interface CreateOutputSpoolOptions {\n /** Tool name used in the spool filename (sanitized). */\n tool: string;\n /**\n * Output size at which the spool activates. Should match the tool's\n * in-memory cap so files are only created for output the model can't\n * already see in full. Default 32 KB.\n */\n thresholdBytes?: number | undefined;\n}\n\n/**\n * Render the marker line appended to a capped tool result. Kept in one place\n * so every command tool phrases it identically (and tests can match it).\n */\nexport function spoolNote(info: SpoolInfo): string {\n const dropped =\n info.droppedBytes > 0 ? `, ~${info.droppedBytes} bytes dropped under backpressure` : '';\n return `\\n[output truncated — full ${info.bytes} bytes at ${info.path}${dropped}; read/grep that file selectively instead of re-running with more output]`;\n}\n\nexport function createOutputSpool(opts: CreateOutputSpoolOptions): OutputSpool {\n const threshold = opts.thresholdBytes ?? 32_768;\n const safeTool = opts.tool.replace(/[^a-zA-Z0-9._-]+/g, '_').slice(0, 40) || 'tool';\n\n let head = '';\n let headBytes = 0;\n let totalBytes = 0;\n let droppedBytes = 0;\n let stream: WriteStream | null = null;\n let filePath: string | null = null;\n let failed = false;\n let finalized = false;\n\n const open = (): void => {\n if (stream || failed) return;\n try {\n const dir = toolOutputDir();\n // Synchronous on purpose: createWriteStream would race an async mkdir\n // and error with ENOENT. This runs at most once per oversized command,\n // and after the first call the dir exists (mkdirSync is a no-op stat).\n mkdirSync(dir, { recursive: true });\n sweepOldSpoolFiles(dir);\n const stamp = new Date().toISOString().replace(/[:.]/g, '-');\n const rand = Math.random().toString(36).slice(2, 6);\n filePath = path.join(dir, `${stamp}-${safeTool}-${rand}.log`);\n stream = createWriteStream(filePath, { flags: 'w', encoding: 'utf8' });\n stream.on('error', () => {\n // Disk full / permission — disable the spool, keep the tool alive.\n failed = true;\n stream = null;\n filePath = null;\n });\n // Flush the buffered head first so the file is the complete output.\n stream.write(head);\n } catch {\n failed = true;\n stream = null;\n filePath = null;\n }\n };\n\n return {\n write(text: string): void {\n if (finalized || !text) return;\n totalBytes += Buffer.byteLength(text, 'utf8');\n if (!stream && !failed) {\n if (headBytes + text.length <= threshold) {\n head += text;\n headBytes += text.length;\n return;\n }\n head += text; // include the crossing chunk so the file misses nothing\n open();\n head = ''; // flushed into the stream by open(); release the heap copy\n return;\n }\n if (stream) {\n if (stream.writableLength > SPOOL_WRITE_HWM_BYTES) {\n droppedBytes += Buffer.byteLength(text, 'utf8');\n return;\n }\n stream.write(text);\n }\n },\n finalize(): SpoolInfo | null {\n if (finalized) {\n return filePath ? { path: filePath, bytes: totalBytes, droppedBytes } : null;\n }\n finalized = true;\n head = '';\n if (!stream || !filePath) return null;\n try {\n stream.end();\n } catch {\n /* already closed */\n }\n return { path: filePath, bytes: totalBytes, droppedBytes };\n },\n };\n}\n","import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport * as Core from '@wrongstack/core';\nimport type { Context } from '@wrongstack/core';\n/** Detected package manager for a project directory. */\nexport type PackageManager = 'pnpm' | 'yarn' | 'npm';\n\n/**\n * Detect the project's package manager by inspecting lockfiles in `cwd`.\n * Order: pnpm → yarn → npm (default). Missing or unreadable directories fall\n * back to `npm` rather than throwing, so a `safeResolve`-checked cwd that\n * happens to be empty never aborts the tool.\n */\nexport async function detectPackageManager(cwd: string): Promise<PackageManager> {\n const { stat } = await import('node:fs/promises');\n try {\n await stat(`${cwd}/pnpm-lock.yaml`);\n return 'pnpm';\n } catch {\n /* not pnpm */\n }\n try {\n await stat(`${cwd}/yarn.lock`);\n return 'yarn';\n } catch {\n /* not yarn */\n }\n return 'npm';\n}\n\nexport function resolvePath(input: string, ctx: Context): string {\n return path.isAbsolute(input) ? path.normalize(input) : path.resolve(ctx.workingDir ?? ctx.cwd, input);\n}\n\n/**\n * Roots every file tool may always reach, even in restricted mode: the\n * project root and the user-global `~/.wrongstack` directory (config, memory,\n * sessions, skills). `~/.wrongstack` honors the `WRONGSTACK_HOME` override.\n */\nfunction allowedRoots(ctx: Context): string[] {\n return [path.resolve(ctx.projectRoot), path.resolve(Core.wstackGlobalRoot())];\n}\n\n/** True if `target` is `root` itself or nested inside any of `roots`. */\nfunction isInsideAny(target: string, roots: string[]): boolean {\n return roots.some((root) => {\n const rel = path.relative(root, target);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n });\n}\n\nexport function ensureInsideRoot(absPath: string, ctx: Context): string {\n const target = path.resolve(absPath);\n // Unrestricted filesystem access: skip the project-root containment check.\n if (ctx.allowOutsideProjectRoot) return target;\n if (isInsideAny(target, allowedRoots(ctx))) return target;\n throw new Error(`Path \"${absPath}\" is outside project root \"${path.resolve(ctx.projectRoot)}\"`);\n}\n\nexport function safeResolve(input: string, ctx: Context): string {\n return ensureInsideRoot(resolvePath(input, ctx), ctx);\n}\n\n/**\n * Defense against in-root→out-of-root symlink escape (CWE-59). `safeResolve`\n * only does a syntactic `../` check, so a symlink that lives *inside* the\n * project root but points outside still passes it. This resolves the path\n * through `fs.realpath` and re-verifies containment against the realpath of\n * the project root (comparing like-for-like, since the root itself may be a\n * symlink — macOS `/var`→`/private/var`, Windows 8.3 short names). For a path\n * that does not exist yet (e.g. a `write` to a new file) the nearest existing\n * ancestor directory is checked instead. Throws if the real target escapes.\n *\n * Mirrors the per-file guard already used in `replace.ts`/`grep.ts`; applied\n * to single-file `read`/`edit`/`write` it throws (rather than skips) because\n * the caller named exactly one file.\n */\nexport async function assertRealInsideRoot(absPath: string, ctx: Context): Promise<void> {\n // Unrestricted filesystem access: no symlink-escape check to perform.\n if (ctx.allowOutsideProjectRoot) return;\n // Compare like-for-like against the realpath of each always-allowed root\n // (project root + ~/.wrongstack), since a root may itself be a symlink.\n const realRoots = await Promise.all(\n allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path.resolve(r))),\n );\n let probe = absPath;\n for (;;) {\n let real: string;\n try {\n real = await fsp.realpath(probe);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n const parent = path.dirname(probe);\n if (parent === probe) return; // reached fs root without escaping\n probe = parent;\n continue;\n }\n throw err;\n }\n if (isInsideAny(real, realRoots)) return;\n throw new Error(\n `Path \"${absPath}\" resolves through a symlink outside project root \"${realRoots[0]}\"`,\n );\n }\n}\n\n/** `safeResolve` + symlink realpath containment check. Async. */\nexport async function safeResolveReal(input: string, ctx: Context): Promise<string> {\n const abs = safeResolve(input, ctx);\n await assertRealInsideRoot(abs, ctx);\n return abs;\n}\n\nexport function truncateMiddle(s: string, max: number): string {\n if (Buffer.byteLength(s, 'utf8') <= max) return s;\n const half = Math.floor(max / 2);\n return (\n s.slice(0, half) +\n `\\n…[truncated ${Buffer.byteLength(s, 'utf8') - max} bytes from middle]…\\n` +\n s.slice(-half)\n );\n}\n\nexport function isBinaryBuffer(buf: Buffer): boolean {\n const len = Math.min(buf.length, 8192);\n for (let i = 0; i < len; i++) {\n if (buf[i] === 0) return true;\n }\n return false;\n}\n\n// ─── Command-output normalization (token-saving) ────────────────────────────\n//\n// Raw process output is full of tokens the model gains nothing from: ANSI\n// escapes, carriage-return progress spam, runs of identical warning lines, and\n// huge tails of build noise. These helpers strip that noise before the output\n// reaches the LLM. They are scoped to COMMAND tools (bash/git/exec and the\n// _spawn-stream consumers) — never applied to structured/code outputs.\n\n/** Unified byte cap for all command tool output fed to the model. */\nexport const COMMAND_OUTPUT_MAX_BYTES = 32_768;\n\n/** Runs of >= this many identical consecutive lines are collapsed. */\nconst REPEAT_RUN_THRESHOLD = 3;\n\n/**\n * Collapse carriage-return overwrites the way a terminal would: `\\r\\n` becomes\n * `\\n`, and a bare `\\r` (progress redraw) keeps only the text after the LAST\n * `\\r` on its physical line. Without this, a single progress bar that redraws\n * 200 times explodes into 200 lines.\n */\nexport function collapseCarriageReturns(text: string): string {\n const lf = text.replace(/\\r\\n/g, '\\n');\n if (!lf.includes('\\r')) return lf;\n return lf\n .split('\\n')\n .map((line) => (line.includes('\\r') ? line.slice(line.lastIndexOf('\\r') + 1) : line))\n .join('\\n');\n}\n\n/**\n * Collapse a run of `minRun`+ identical consecutive lines into the line once\n * plus a marker. Consecutive-only — it never reorders or dedups non-adjacent\n * lines, so diffs/source stay intact.\n */\nexport function collapseConsecutiveDuplicates(text: string, minRun = REPEAT_RUN_THRESHOLD): string {\n const lines = text.split('\\n');\n const out: string[] = [];\n let i = 0;\n while (i < lines.length) {\n let j = i + 1;\n while (j < lines.length && lines[j] === lines[i]) j++;\n const run = j - i;\n if (run >= minRun) {\n out.push(lines[i]!, `… ⟨repeated ${run}×⟩`);\n } else {\n for (let k = i; k < j; k++) out.push(lines[k]!);\n }\n i = j;\n }\n return out.join('\\n');\n}\n\n/** Largest prefix of `s` whose UTF-8 byte length is <= `maxBytes`. */\nfunction takeHeadBytes(s: string, maxBytes: number): string {\n if (maxBytes <= 0) return '';\n /* v8 ignore next -- only caller (truncateHeadTail) passes a budget smaller than s; defensive. */\n if (Buffer.byteLength(s, 'utf8') <= maxBytes) return s;\n let lo = 0;\n let hi = s.length;\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (Buffer.byteLength(s.slice(0, mid), 'utf8') <= maxBytes) lo = mid;\n else hi = mid - 1;\n }\n return s.slice(0, lo);\n}\n\n/** Largest suffix of `s` whose UTF-8 byte length is <= `maxBytes`. */\nfunction takeTailBytes(s: string, maxBytes: number): string {\n if (maxBytes <= 0) return '';\n /* v8 ignore next -- only caller (truncateHeadTail) passes a budget smaller than s; defensive. */\n if (Buffer.byteLength(s, 'utf8') <= maxBytes) return s;\n let lo = 0;\n let hi = s.length;\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (Buffer.byteLength(s.slice(s.length - mid), 'utf8') <= maxBytes) lo = mid;\n else hi = mid - 1;\n }\n return s.slice(s.length - lo);\n}\n\n/**\n * Truncate to `maxBytes` keeping BOTH ends — the head (what ran / early context)\n * and the tail (errors and summaries usually land last), biased ~45/55 toward\n * the tail. The result never exceeds `maxBytes`.\n */\nexport function truncateHeadTail(s: string, maxBytes: number): string {\n const total = Buffer.byteLength(s, 'utf8');\n if (total <= maxBytes) return s;\n // Reserve a fixed allowance for the marker so the final string can't exceed\n // the cap even though the dropped-byte count's digit width varies.\n const MARKER_RESERVE = 64;\n const avail = Math.max(0, maxBytes - MARKER_RESERVE);\n const headBudget = Math.floor(avail * 0.45);\n const head = takeHeadBytes(s, headBudget);\n const tail = takeTailBytes(s, avail - Buffer.byteLength(head, 'utf8'));\n const kept = Buffer.byteLength(head, 'utf8') + Buffer.byteLength(tail, 'utf8');\n return `${head}\\n…[truncated ${total - kept} bytes]…\\n${tail}`;\n}\n\n/**\n * Full token-saving pipeline for command tool output: strip ANSI → collapse\n * carriage-return progress → trim trailing whitespace → collapse identical\n * consecutive lines → squeeze blank-line runs → head+tail truncate to the cap.\n */\nexport function normalizeCommandOutput(\n raw: string,\n opts: { maxBytes?: number | undefined } = {},\n): string {\n if (!raw) return raw;\n let text = Core.stripAnsi(raw);\n text = collapseCarriageReturns(text);\n text = text.replace(/[ \\t]+$/gm, ''); // trailing whitespace per line\n text = collapseConsecutiveDuplicates(text);\n text = text.replace(/\\n{3,}/g, '\\n\\n'); // >=2 blank lines → 1\n return truncateHeadTail(text, opts.maxBytes ?? COMMAND_OUTPUT_MAX_BYTES);\n}\n","/**\n * CircuitBreaker — prevents runaway bash/exec tool chains by:\n *\n * - Tripping on consecutive failures (models that keep repeating the\n * same failing command, e.g. `npm install` with wrong args in a loop)\n * - Tripping on slow call ratio (too many long-running commands suggest\n * a hung subprocess that the model doesn't know how to kill)\n * - Rate-limiting bursts (rapid succession of commands without reading\n * output suggests the model isn't processing results)\n * - Auto-recovering after a cooldown period so a fixed model can resume\n *\n * The breaker is owned by the ProcessRegistry so any tool that registers\n * a process participates in the same circuit. \"Per-tool\" isolation is\n * intentionally NOT implemented — the model treats bash/exec as one\n * resource pool; isolating them would let the model route around the\n * breaker by alternating which tool it uses.\n */\n\nexport interface CircuitBreakerConfig {\n /**\n * Consecutive failures before trip. Default: 5.\n * A single success resets this counter to 0.\n */\n maxConsecutiveFailures?: number | undefined;\n /**\n * Slow-call threshold in ms. A call that runs longer than this is\n * counted as \"slow\". Default: 60_000 (1 minute).\n */\n slowCallThresholdMs?: number | undefined;\n /**\n * Max slow calls before trip (within the sliding window). Default: 3.\n */\n maxSlowCalls?: number | undefined;\n /**\n * Sliding window for rate-limit and slow-call counting, in ms.\n * Default: 60_000 (1 minute).\n */\n windowMs?: number | undefined;\n /**\n * Max calls within the sliding window. Default: 30.\n * Burst exceeding this trips the breaker immediately.\n */\n maxCallsPerWindow?: number | undefined;\n /**\n * Cooldown before auto-recovery attempt, in ms. Default: 30_000 (30s).\n * After this the breaker enters \"half-open\" state and allows one call\n * through to test whether the problem is resolved.\n */\n cooldownMs?: number | undefined;\n}\n\ninterface CallRecord {\n at: number;\n /** True if the call threw or returned an is_error result. */\n failed: boolean;\n /** True if elapsed time exceeded slowCallThresholdMs. */\n slow: boolean;\n}\n\ntype BreakerState = 'closed' | 'open' | 'half-open';\n\nconst DEFAULT_MAX_CONSECUTIVE_FAILURES = 5;\nconst DEFAULT_SLOW_CALL_THRESHOLD_MS = 180_000;\n// 3 minutes — balanced against the 5-minute bash timeout. Commands\n// running <3min are normal; 3-5min are \"slow\" and count toward the\n// breaker. 3 consecutive slow calls trip the circuit.\nconst DEFAULT_MAX_SLOW_CALLS = 3;\nconst DEFAULT_WINDOW_MS = 60_000;\nconst DEFAULT_MAX_CALLS_PER_WINDOW = 30;\nconst DEFAULT_COOLDOWN_MS = 30_000;\n\nexport interface CircuitBreakerSnapshot {\n state: 'closed' | 'open' | 'half-open';\n consecutiveFailures: number;\n slowCallsInWindow: number;\n callsInWindow: number;\n windowMs: number;\n cooldownRemainingMs: number | null;\n lastFailureAt: number | null;\n lastSlowAt: number | null;\n}\n\nexport class CircuitBreaker {\n private readonly maxConsecutiveFailures: number;\n private readonly slowCallThresholdMs: number;\n private readonly maxSlowCalls: number;\n private readonly windowMs: number;\n private readonly maxCallsPerWindow: number;\n private readonly cooldownMs: number;\n\n private state: BreakerState = 'closed';\n private consecutiveFailures = 0;\n private window: CallRecord[] = [];\n private lastFailureAt: number | null = null;\n private lastSlowAt: number | null = null;\n /** Timestamp when the breaker was opened (for cooldown calculation). */\n private openedAt: number | null = null;\n\n /**\n * Master enable flag. When false the breaker is bypassed: `beforeCall`\n * always returns true and `afterCall` records nothing. The class itself\n * defaults to enabled (so the standalone unit tests exercise tripping); the\n * ProcessRegistry flips this off until the user opts in via `/settings`.\n */\n private enabled = true;\n\n /**\n * Fired (best-effort) when the breaker transitions into the `open` state.\n * The registry uses this to arm its auto kill/reset countdown.\n */\n onTrip?: (() => void) | undefined;\n /**\n * Fired (best-effort) when the breaker returns to `closed` after having been\n * open/half-open. The registry uses this to cancel a pending kill/reset.\n */\n onReset?: (() => void) | undefined;\n\n constructor(config: CircuitBreakerConfig = {}) {\n this.maxConsecutiveFailures = config.maxConsecutiveFailures ?? DEFAULT_MAX_CONSECUTIVE_FAILURES;\n this.slowCallThresholdMs = config.slowCallThresholdMs ?? DEFAULT_SLOW_CALL_THRESHOLD_MS;\n this.maxSlowCalls = config.maxSlowCalls ?? DEFAULT_MAX_SLOW_CALLS;\n this.windowMs = config.windowMs ?? DEFAULT_WINDOW_MS;\n this.maxCallsPerWindow = config.maxCallsPerWindow ?? DEFAULT_MAX_CALLS_PER_WINDOW;\n this.cooldownMs = config.cooldownMs ?? DEFAULT_COOLDOWN_MS;\n }\n\n /** Toggle the master enable. Disabling resets to a clean `closed` state. */\n setEnabled(enabled: boolean): void {\n if (this.enabled === enabled) return;\n this.enabled = enabled;\n if (!enabled) this._reset();\n }\n\n get isEnabled(): boolean {\n return this.enabled;\n }\n\n /**\n * Returns true if the circuit allows a new call to proceed.\n * When false, callers should abort the tool call and return a\n * circuit-breaker error instead of spawning a process.\n */\n get canProceed(): boolean {\n if (!this.enabled) return true;\n this._checkStateTransition();\n return this.state !== 'open';\n }\n\n /**\n * Snapshot of the current breaker state for observability (`/kill`).\n */\n snapshot(): CircuitBreakerSnapshot {\n this._checkStateTransition();\n const now = Date.now();\n let cooldownRemaining: number | null = null;\n if (this.openedAt !== null && this.state === 'open') {\n const elapsed = now - this.openedAt;\n cooldownRemaining = Math.max(0, this.cooldownMs - elapsed);\n }\n return {\n state: this.state,\n consecutiveFailures: this.consecutiveFailures,\n slowCallsInWindow: this.window.filter((c) => c.slow).length,\n callsInWindow: this.window.length,\n windowMs: this.windowMs,\n cooldownRemainingMs: cooldownRemaining,\n lastFailureAt: this.lastFailureAt,\n lastSlowAt: this.lastSlowAt,\n };\n }\n\n /**\n * Call this BEFORE spawning a bash/exec process.\n * Returns true if the call is allowed; false if the breaker is open.\n * When false, callers MUST NOT spawn a process.\n *\n * @param bypass - If true, skip the circuit breaker check entirely.\n * Use for background/fire-and-forget processes that should\n * not affect breaker state.\n */\n beforeCall(bypass = false): boolean {\n if (bypass || !this.enabled) return true;\n this._checkStateTransition();\n if (this.state === 'open') return false;\n return true;\n }\n\n /**\n * Call this AFTER a bash/exec process finishes (success or failure).\n * `durationMs` is the wall-clock time the process ran.\n * `failed` is true when the process returned a non-zero exit code or\n * threw an exception before spawning.\n *\n * @param bypass - If true, do not update breaker state.\n * Use for background/fire-and-forget processes.\n */\n afterCall(durationMs: number, failed: boolean, bypass = false): void {\n if (bypass || !this.enabled) return;\n\n const now = Date.now();\n\n if (this.state === 'half-open') {\n // First call through after cooldown — if it failed, go back to open.\n if (failed) {\n this._trip();\n return;\n }\n // Success in half-open → reset to closed.\n this._reset();\n return;\n }\n\n // Prune old records outside the sliding window.\n this._pruneWindow(now);\n\n const slow = durationMs >= this.slowCallThresholdMs;\n this.window.push({ at: now, failed, slow });\n\n if (failed) {\n this.consecutiveFailures++;\n this.lastFailureAt = now;\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n this._trip();\n }\n return;\n }\n\n // Success: reset consecutive failure counter.\n this.consecutiveFailures = 0;\n\n if (slow) {\n this.lastSlowAt = now;\n const slowCount = this.window.filter((c) => c.slow).length;\n if (slowCount >= this.maxSlowCalls) {\n this._trip();\n }\n }\n\n const callCount = this.window.length;\n if (callCount >= this.maxCallsPerWindow) {\n // Rate limit exceeded. This is a soft trip — we reset the window\n // and let the next call try immediately (the caller will still see\n // canProceed=false until the window drains naturally).\n this._trip();\n }\n }\n\n /** Force the breaker open. Used by /kill force and Ctrl+C. */\n forceOpen(): void {\n this._trip();\n }\n\n /** Force a reset to closed. Used by tests and /kill reset. */\n forceReset(): void {\n this._reset();\n }\n\n private _trip(): void {\n if (this.state === 'open') return; // already open\n this.state = 'open';\n this.openedAt = Date.now();\n // P3 #23 (before-release.md): clear the window on trip. Old records are\n // irrelevant once tripped — the breaker starts fresh after cooldown\n // (half-open → closed resets the counters). Without this the window array\n // holds onto CallRecord entries for its lifetime if no new afterCall()\n // arrives (which is the case when the breaker stays open and no new calls\n // are attempted).\n this.window = [];\n // Best-effort: never let a listener failure corrupt breaker state.\n try {\n this.onTrip?.();\n } catch {\n /* ignored — observability hook only */\n }\n }\n\n private _reset(): void {\n const wasRecovering = this.state !== 'closed';\n this.state = 'closed';\n this.consecutiveFailures = 0;\n this.window = [];\n this.openedAt = null;\n // Only notify on a real recovery (open/half-open → closed), not on the\n // initial closed state or an idempotent re-reset.\n if (wasRecovering) {\n try {\n this.onReset?.();\n } catch {\n /* ignored — observability hook only */\n }\n }\n }\n\n /** Transition from open → half-open when cooldown elapses. */\n private _checkStateTransition(): void {\n if (this.state !== 'open' || this.openedAt === null) return;\n const elapsed = Date.now() - this.openedAt;\n if (elapsed >= this.cooldownMs) {\n this.state = 'half-open';\n this.openedAt = null;\n }\n }\n\n private _pruneWindow(now: number): void {\n const cutoff = now - this.windowMs;\n this.window = this.window.filter((c) => c.at >= cutoff);\n }\n}","import { expectDefined } from '@wrongstack/core';\n/**\n * ProcessRegistry — global singleton that tracks all spawned child processes\n * from `bash` and `exec` tools. Enables:\n *\n * - Listing active processes (for TUI status bar)\n * - Killing individual processes or all processes (for Ctrl+C and /kill)\n * - Detecting runaway processes (hung, looping)\n * - Circuit breaker integration to prevent recursive/repeated failures\n *\n * Thread-safety: Node.js is single-threaded, but async callbacks can fire\n * in any order. All mutations go through synchronized Map methods.\n */\nimport { spawn } from 'node:child_process';\nimport type { ChildProcess } from 'node:child_process';\nimport * as os from 'node:os';\nimport { CircuitBreaker, type CircuitBreakerSnapshot, type CircuitBreakerConfig } from './circuit-breaker.js';\nexport type { CircuitBreakerSnapshot, CircuitBreakerConfig } from './circuit-breaker.js';\n\nexport interface TrackedProcess {\n pid: number;\n name: string;\n /** Display-safe redacted command string — safe for logs, /ps, crash dumps.\n * Contains [REDACTED] in place of sensitive flag values. */\n command: string;\n startedAt: number;\n sessionId?: string | undefined;\n /** The raw ChildProcess handle. Never call .kill() directly on this —\n * use `kill()` below which handles process groups correctly on POSIX\n * and degrades gracefully on Windows. */\n child: ChildProcess;\n /** True only when this child was spawned as a POSIX process-group/session\n * leader (for example `spawn(..., { detached: true })`) and `pid` is the\n * actual `child.pid`. Negative-PID signaling is host-wide dangerous for\n * values like -1, so tests and manually registered entries must not opt in. */\n processGroupLeader?: boolean | undefined;\n /** True once the process has been kill()ed but not yet exited.\n * We keep it in the registry until 'close' fires so callers can\n * distinguish \"still running\" from \"just exited\". */\n killed: boolean;\n /** If true, kill() and killAll() will refuse to kill this process.\n * Used for infrastructure processes (browser, dev servers, …) that\n * must outlive the agent session. */\n protected: boolean;\n}\n\n// Sensitive CLI flag patterns that may appear in process command lines.\n// Redacted to [REDACTED] so crash dumps /ps output cannot leak secrets.\nconst SENSITIVE_FLAG_PATTERNS: RegExp[] = [\n // --flag=value or --flag \"value\" (value captured up to next space or comma)\n /--(?:token|password|passwd|pwd|secret|api[-_]?key|api[-_]?secret|auth|credential|private[-_]?key|access[-_]?key|github[-_]?token|gh[-_]?token|bearer|jwt|oauth|pin|pincode|passphrase|access[-_]?token)(?:[=\\s,][^\\s]*)?/gi,\n // -f \"value\" style short flags\n /(?<!\\w)-t(?:\\s+|\\s*=\\s*)[^\\s,]+/,\n /(?<!\\w)-(?:p|password)(?:\\s+|\\s*=\\s*)[^\\s,]+/gi,\n // env var–style secrets: TOKEN=x, API_KEY=y, etc.\n /(?:TOKEN|API_KEY|API_SECRET|AUTH_TOKEN|GITHUB_TOKEN|GH_TOKEN|BEARER|JWT|OAUTH|CREDENTIAL|SECRET|PRIVATE_KEY|PASSWORD|PASSWD)\\s*[=:]\\s*[^\\s,]+/gi,\n // Generic high-entropy look: base64 strings >32 chars or hex strings >32 digits — but only\n // when preceded by a flag name (e.g. --github-token=EyJ...).\n /--\\w*(?:token|key|secret|password|passwd|auth|credential)\\w*[=\\s,][A-Za-z0-9+/=]{32,}/,\n];\n\n/**\n * Returns a display-safe copy of `cmd` with sensitive flag values replaced by [REDACTED].\n * The original string is unchanged; this is pure and has no side effects.\n */\nexport function redactCommand(cmd: string): string {\n let result = cmd;\n for (const pattern of SENSITIVE_FLAG_PATTERNS) {\n result = result.replace(pattern, (match) => {\n // Preserve the flag name portion; redact only the value part.\n // e.g. \"--token=sekrit_abc\" → \"--token=[REDACTED]\"\n const eq = match.indexOf('=');\n const sp = match.search(/\\s/);\n const delim = eq !== -1 ? '=' : sp !== -1 ? match[sp] : null;\n if (delim !== null) {\n const flag = match.slice(0, match.indexOf(expectDefined(delim)) + 1);\n return `${flag}[REDACTED]`;\n }\n // Nothing delimitable found; replace the whole token silently.\n // Short flags like -tVALUE are replaced entirely to avoid edge cases.\n const flagEnd = match.match(/^--?[a-zA-Z][a-zA-Z0-9_-]*/)?.[0] ?? match;\n return `${flagEnd}=**redacted**`;\n });\n }\n return result;\n}\n\ninterface KillOpts {\n /** SIGKILL instead of SIGTERM. Default: false (SIGTERM first). */\n force?: boolean | undefined;\n /** MS to wait between SIGTERM and SIGKILL on POSIX. Default: 2000. */\n graceMs?: number | undefined;\n}\n\n/**\n * Snapshot of the armed auto kill/reset countdown, or null when nothing is\n * armed. `remainingMs` ticks down in real time; the TUI statusline renders it.\n */\nexport interface BreakerCountdown {\n remainingMs: number;\n totalMs: number;\n}\n\ntype BreakerCountdownListener = (snapshot: BreakerCountdown | null) => void;\n\nexport interface RegistryStats {\n activeCount: number;\n totalCount: number;\n breaker: CircuitBreakerSnapshot;\n}\n\nconst DEFAULT_GRACE_MS = 2000;\n\n/**\n * Kill an entire process tree on Windows via `taskkill /T /F`.\n *\n * TerminateProcess (what `child.kill()` maps to) has no process-group\n * semantics, so killing a shell wrapper (`cmd.exe /c …`) orphans its\n * grandchildren (node, vitest forks, dev servers). The orphans inherit the\n * parent's stdio pipe handles and can keep streaming into this process for\n * the rest of the session — which both prevents the child's 'close' event\n * from ever firing and grows in-memory output buffers without bound.\n *\n * Fire-and-forget: returns true if taskkill was spawned, false if spawning\n * it failed (caller should fall back to a direct `child.kill()`).\n */\nexport function killWin32Tree(pid: number): boolean {\n try {\n const child = spawn('taskkill', ['/pid', String(pid), '/T', '/F'], {\n stdio: 'ignore',\n windowsHide: true,\n });\n // spawn() reports a failure to launch (e.g. taskkill not on PATH, blocked by\n // security software) via an ASYNC 'error' event — the surrounding try/catch\n // only traps synchronous throws. Without a listener that event is unhandled\n // and crashes the whole process. Swallow it: this is best-effort tree-kill\n // and the registry still has the direct child.kill() fallback.\n child.on('error', () => {});\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n\nexport class ProcessRegistryImpl {\n private readonly processes = new Map<number, TrackedProcess>();\n private readonly breaker: CircuitBreaker;\n\n /**\n * Auto kill/reset config. When the breaker trips and `autoKillResetMs > 0`,\n * a countdown is armed; on expiry all tracked processes are killed and the\n * breaker is reset to closed (forced recovery). Zero means manual recovery\n * only (`/kill reset`).\n */\n private autoKillResetMs = 0;\n private autoKillTimer: ReturnType<typeof setTimeout> | null = null;\n private autoKillArmedAt: number | null = null;\n private breakerCountdownListeners: BreakerCountdownListener[] = [];\n\n constructor(breakerConfig?: CircuitBreakerConfig) {\n this.breaker = new CircuitBreaker(breakerConfig);\n // Arm on trip, cancel on recovery. Listeners are best-effort.\n this.breaker.onTrip = () => this._armAutoKillReset();\n this.breaker.onReset = () => this._cancelAutoKillReset();\n // Protection is OFF by default — the user opts in via `/settings breaker on`.\n this.breaker.setEnabled(false);\n }\n\n register(info: Omit<TrackedProcess, 'killed' | 'protected'> & { protected?: boolean | undefined }): void {\n this.processes.set(info.pid, { ...info, killed: false, protected: info.protected ?? false });\n }\n\n private _isSafeSignalPid(pid: number): boolean {\n return Number.isInteger(pid) && pid > 1 && pid !== process.pid && pid !== process.ppid;\n }\n\n private _canSignalProcessGroup(p: TrackedProcess): boolean {\n return (\n os.platform() !== 'win32' &&\n p.processGroupLeader === true &&\n this._isSafeSignalPid(p.pid) &&\n typeof p.child.pid === 'number' &&\n p.child.pid === p.pid\n );\n }\n\n private _killChildDirect(p: TrackedProcess, signal: NodeJS.Signals): void {\n try {\n p.child.kill(signal);\n } catch {\n // Process may have already exited, or this may be a persistent entry\n // without a live ChildProcess handle in the current process.\n }\n }\n\n private _killPosix(p: TrackedProcess, signal: NodeJS.Signals): void {\n if (this._canSignalProcessGroup(p)) {\n try {\n process.kill(-p.pid, signal);\n return;\n } catch {\n // Process group may already be gone; fall back to the direct child.\n }\n }\n this._killChildDirect(p, signal);\n }\n\n /** Unregister a process by PID. Called on 'close' / 'exit' events. */\n unregister(pid: number): void {\n this.processes.delete(pid);\n }\n\n /** Get a single process by PID. */\n get(pid: number): TrackedProcess | undefined {\n this._pruneStale(pid);\n return this.processes.get(pid);\n }\n\n /** Get all tracked processes. */\n list(): TrackedProcess[] {\n return Array.from(this.processes.values());\n }\n\n /** Get processes filtered by name (e.g. 'bash', 'exec'). */\n byName(name: string): TrackedProcess[] {\n return this.list().filter((p) => p.name === name);\n }\n\n /** Get processes filtered by session. */\n bySession(sessionId: string): TrackedProcess[] {\n return this.list().filter((p) => p.sessionId === sessionId);\n }\n\n /** Count of active (non-killed) processes. */\n get activeCount(): number {\n let n = 0;\n for (const p of this.processes.values()) {\n if (!p.killed) n++;\n }\n return n;\n }\n\n /**\n * Combined stats for observability — used by /ps and the TUI status bar.\n */\n stats(): RegistryStats {\n return {\n activeCount: this.activeCount,\n totalCount: this.processes.size,\n breaker: this.breaker.snapshot(),\n };\n }\n\n /**\n * Returns true if the circuit allows a new bash/exec call to proceed.\n * When false, callers MUST NOT spawn a process.\n */\n get canProceed(): boolean {\n return this.breaker.canProceed;\n }\n\n /**\n * Called before spawning a process. Returns true if allowed; false if\n * the circuit breaker is open.\n *\n * @param bypass - If true, skip circuit breaker check (for background processes).\n */\n beforeCall(bypass = false): boolean {\n return this.breaker.beforeCall(bypass);\n }\n\n /**\n * Called after a process finishes. `durationMs` is wall-clock time;\n * `failed` is true for non-zero exit codes.\n *\n * @param bypass - If true, do not update circuit breaker state (for background processes).\n */\n afterCall(durationMs: number, failed: boolean, bypass = false): void {\n this.breaker.afterCall(durationMs, failed, bypass);\n }\n\n /** Force-open the circuit breaker (Ctrl+C, /kill force). */\n forceBreakerOpen(): void {\n this.breaker.forceOpen();\n }\n\n /** Force-reset the circuit breaker to closed (/kill reset). */\n forceBreakerReset(): void {\n this.breaker.forceReset();\n }\n\n /**\n * Configure circuit-breaker protection at runtime. Called from `/settings`\n * (instant, all modes) and on TUI mount (applies persisted config).\n *\n * - `enabled` toggles whether the breaker gates `bash`/`exec`.\n * - `autoKillResetMs` arms the auto kill/reset countdown when the breaker\n * trips (0 = manual recovery only).\n *\n * Re-applies cleanly on every call: cancels a pending countdown when the\n * timeout is cleared or protection disabled, and re-arms if the breaker is\n * currently open under the new settings.\n */\n setBreakerConfig(cfg: { enabled?: boolean | undefined; autoKillResetMs?: number | undefined }): void {\n if (cfg.enabled !== undefined) this.breaker.setEnabled(cfg.enabled);\n if (cfg.autoKillResetMs !== undefined) this.autoKillResetMs = Math.max(0, cfg.autoKillResetMs);\n\n if (this.autoKillResetMs <= 0) {\n this._cancelAutoKillReset();\n return;\n }\n // If protection is active and the breaker is currently tripped, ensure a\n // countdown is armed for the new window (covers a live config change while\n // the breaker is already open).\n if (this.breaker.isEnabled && this.breaker.snapshot().state === 'open') {\n this._armAutoKillReset();\n }\n }\n\n /**\n * Live countdown to the next auto kill/reset, or null when nothing is armed.\n * The TUI polls this on a 1s tick while armed so the statusline decrements.\n */\n getBreakerCountdown(): BreakerCountdown | null {\n if (this.autoKillArmedAt === null || this.autoKillResetMs <= 0) return null;\n const elapsed = Date.now() - this.autoKillArmedAt;\n return { remainingMs: Math.max(0, this.autoKillResetMs - elapsed), totalMs: this.autoKillResetMs };\n }\n\n /**\n * Subscribe to countdown arm/cancel events. Returns an unsubscribe function.\n * Use {@link getBreakerCountdown} for the live ticking value between events.\n */\n onBreakerCountdownChange(listener: BreakerCountdownListener): () => void {\n this.breakerCountdownListeners.push(listener);\n return () => {\n this.breakerCountdownListeners = this.breakerCountdownListeners.filter((l) => l !== listener);\n };\n }\n\n private _emitBreakerCountdown(): void {\n const snap = this.getBreakerCountdown();\n for (const l of this.breakerCountdownListeners) {\n try {\n l(snap);\n } catch {\n /* listener failure must never affect breaker behavior */\n }\n }\n }\n\n /**\n * Arm the auto kill/reset countdown. Idempotent: re-arming resets the window\n * (a fresh trip after a failed half-open probe restarts the clock). No-op\n * when protection is off or no timeout is configured.\n */\n private _armAutoKillReset(): void {\n if (this.autoKillResetMs <= 0 || !this.breaker.isEnabled) return;\n this._clearAutoKillTimer();\n this.autoKillArmedAt = Date.now();\n this.autoKillTimer = setTimeout(() => {\n this.autoKillTimer = null;\n this.autoKillArmedAt = null;\n // Forced recovery: nuke runaway processes and reopen the circuit.\n this.killAll({ force: false });\n this.breaker.forceReset();\n this._emitBreakerCountdown();\n }, this.autoKillResetMs);\n // Don't keep the event loop alive purely for auto-recovery.\n this.autoKillTimer.unref?.();\n this._emitBreakerCountdown();\n }\n\n private _cancelAutoKillReset(): void {\n const wasArmed = this.autoKillArmedAt !== null;\n this._clearAutoKillTimer();\n if (wasArmed) {\n this.autoKillArmedAt = null;\n this._emitBreakerCountdown();\n }\n }\n\n private _clearAutoKillTimer(): void {\n if (this.autoKillTimer !== null) {\n clearTimeout(this.autoKillTimer);\n this.autoKillTimer = null;\n }\n }\n\n /** Kill a single process by PID.\n *\n * On POSIX: sends SIGTERM to the *process group* (-pid) so that\n * runaway grandchild processes (`sleep 9999 & disown`) are also killed.\n * After `graceMs` a SIGKILL is sent if the process hasn't exited.\n *\n * On Windows: `child.kill()` maps to TerminateProcess — process groups\n * are not meaningfully supported. A second `force=true` call sends\n * SIGKILL (which maps to TerminateProcess again — the distinction is\n * in the exit code, not the signal).\n *\n * Returns true if the process was found and kill was attempted.\n */\n kill(pid: number, opts: KillOpts = {}): boolean {\n this._pruneStale(pid);\n const p = this.processes.get(pid);\n if (!p) return false;\n if (p.killed) return true; // already kill()ed, don't double-send\n if (p.protected) return false; // protected processes are never kill()ed\n\n const { force = false, graceMs = DEFAULT_GRACE_MS } = opts;\n const isWin = os.platform() === 'win32';\n\n if (isWin) {\n // Windows: no process group semantics. A direct kill terminates only\n // the immediate child — shell-wrapped commands (cmd.exe /c …) leave\n // grandchildren running that hold the inherited stdio pipes open and\n // keep feeding output into this process indefinitely. Kill the whole\n // tree via taskkill instead, but only for a real, still-running child\n // (exitCode === null); test fakes and already-exited processes take\n // the plain-kill path. The direct kill is deliberately NOT sent\n // immediately alongside taskkill: killing the root first would break\n // taskkill's parent-pid tree enumeration and orphan the grandchildren\n // again — it runs as a delayed fallback instead.\n const liveRealChild = p.child.exitCode === null && typeof p.child.pid === 'number';\n if (liveRealChild && killWin32Tree(pid)) {\n const fallback = setTimeout(() => {\n if (p.child.exitCode === null) {\n try {\n p.child.kill('SIGKILL');\n } catch {\n // Process may have already exited.\n }\n }\n }, graceMs);\n fallback.unref?.();\n } else {\n try {\n p.child.kill(force ? 'SIGKILL' : 'SIGTERM');\n } catch {\n // Process may have already exited.\n }\n }\n p.killed = true;\n return true;\n }\n\n // POSIX: kill the process group only when the tracked child is proven to\n // be the group leader. Otherwise use child.kill(); negative PID signaling\n // with untrusted/fake PIDs can target unrelated host processes.\n try {\n if (force) {\n this._killPosix(p, 'SIGKILL');\n } else {\n this._killPosix(p, 'SIGTERM');\n // Schedule SIGKILL as backup.\n const timer = setTimeout(() => {\n // Re-check: process may have exited on its own.\n if (this.processes.has(pid) && !p.child.killed) {\n this._killPosix(p, 'SIGKILL');\n }\n }, graceMs);\n timer.unref?.(); // Don't keep event loop alive.\n }\n } catch {\n // Process may have already exited.\n }\n p.killed = true;\n return true;\n }\n\n /**\n * Kill all tracked processes.\n * Returns the PIDs that were kill()ed.\n */\n killAll(opts: KillOpts = {}): number[] {\n const pids = Array.from(this.processes.keys());\n const killed: number[] = [];\n for (const pid of pids) {\n const p = this.processes.get(pid);\n if (p && !p.protected && this.kill(pid, opts)) killed.push(pid);\n }\n return killed;\n }\n\n /**\n * Kill all processes for a specific session.\n * Returns the PIDs that were kill()ed.\n */\n killSession(sessionId: string, opts: KillOpts = {}): number[] {\n const pids = this.bySession(sessionId).map((p) => p.pid);\n const killed: number[] = [];\n for (const pid of pids) {\n if (this.kill(pid, opts)) killed.push(pid);\n }\n return killed;\n }\n\n /**\n * Check whether a tracked process entry is stale — the child has exited\n * (exitCode !== null) AND it's been in the registry long enough that the\n * OS may have reused the PID for a new, unrelated process.\n *\n * P3 #24 (before-release.md): on POSIX, PIDs are reused after process\n * exit. If a tracked process exits but its 'close' event hasn't fired yet\n * (or was missed), the registry still holds the entry. A new process\n * gets the same PID, and PID-based lookups (get, kill, shouldBlockKill)\n * may incorrectly protect or target the wrong process.\n *\n * The 60s threshold is conservative — the OS typically waits much longer\n * before reusing a PID, but we want to clean up before that becomes a risk.\n */\n private _isStaleEntry(entry: TrackedProcess): boolean {\n return entry.child.exitCode !== null && Date.now() - entry.startedAt > 60_000;\n }\n\n /**\n * Remove a stale entry for a specific PID before any PID-based lookup.\n * This prevents PID reuse from causing the registry to act on a dead\n * process that has been replaced by a new one with the same PID.\n */\n private _pruneStale(pid: number): void {\n const entry = this.processes.get(pid);\n if (entry && this._isStaleEntry(entry)) {\n this.processes.delete(pid);\n }\n }\n}\n\n/** Module-level singleton. Initialized on first access. */\nlet _registry: ProcessRegistryImpl | undefined;\n\nexport function getProcessRegistry(): ProcessRegistryImpl {\n if (!_registry) {\n _registry = new ProcessRegistryImpl();\n }\n return _registry;\n}\n\n/** Reset for tests. */\nexport function _resetProcessRegistry(): void {\n _registry = undefined;\n}\n\n// ── Convenience re-exports ────────────────────────────────────────────────────\n\nexport type { KillOpts };\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * On Windows, Node.js `spawn()` without a shell does NOT resolve .cmd/.bat\n * extensions through PATHEXT — it only auto-resolves .exe. Most Node.js CLI\n * tools (npx, pnpm, biome, tsc, vitest, etc.) ship as .cmd wrappers on\n * Windows. This function resolves the command name to its full path so spawn\n * can find it without relying on shell-mode argument concatenation.\n *\n * On non-Windows, returns the command unchanged.\n */\nexport function resolveWin32Command(cmd: string): string {\n if (process.platform !== 'win32') return cmd;\n\n // Already has a path or extension — use as-is\n // Normalize forward slashes so path.extname correctly detects extensions\n // even when a Unix-style path is passed on Windows.\n if (cmd.includes('/') || cmd.includes('\\\\') || path.extname(cmd.replace(/\\//g, '\\\\'))) {\n return cmd;\n }\n\n const pathext = (process.env['PATHEXT'] ?? '.COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC')\n .toLowerCase()\n .split(';');\n\n const pathDirs = (process.env['PATH'] ?? '').split(path.delimiter);\n\n for (const dir of pathDirs) {\n const base = path.join(dir, cmd);\n // Check extensions in PATHEXT order. .EXE should win first because\n // it's typically listed first, and .exe doesn't need shell: true.\n for (const ext of pathext) {\n const full = `${base}${ext}`;\n try {\n fs.accessSync(full, fs.constants.X_OK);\n return full;\n } catch {\n // Not found with this extension — try next\n }\n }\n }\n\n // Not found — return original; let spawn report ENOENT with the\n // expected error message so tools can surface it properly.\n return cmd;\n}\n\n/**\n * Resolve a PowerShell binary by name. `pickShell` in `_shell-pick.ts`\n * already decides whether the user wants `'pwsh'` (PowerShell 7+) or\n * `'powershell'` (Windows PowerShell 5.1). This helper turns that decision\n * into a real on-disk path.\n *\n * Order:\n * 1. If `cmd` is `pwsh` and a `pwsh.exe` exists on PATH → return that.\n * 2. If `cmd` is `pwsh` and only `powershell.exe` exists → fall back to\n * that (the alternative is a cryptic ENOENT for the user).\n * 3. Symmetric for `powershell`: prefer `powershell.exe`, fall back to\n * `pwsh.exe` if installed and the legacy binary is missing.\n * 4. Anything else → delegate to `resolveWin32Command` (handles `.cmd`\n * shims a sysadmin might drop in place, etc.).\n *\n * Returns the original command on ENOENT — `spawn()` will surface a clean\n * ENOENT and the user sees \"PowerShell not installed\", which is the right\n * diagnostic. We never throw from here.\n */\nexport function resolvePowerShell(cmd: string): string {\n if (process.platform !== 'win32') return cmd;\n const lower = cmd.toLowerCase();\n if (lower !== 'pwsh' && lower !== 'powershell' && lower !== 'pwsh.exe' && lower !== 'powershell.exe') {\n return resolveWin32Command(cmd);\n }\n // Prefer the requested edition, fall back to the other one.\n const primary = lower.startsWith('pwsh') ? 'pwsh.exe' : 'powershell.exe';\n const fallback = lower.startsWith('pwsh') ? 'powershell.exe' : 'pwsh.exe';\n const resolved = resolveWin32Command(primary);\n if (resolved !== primary) {\n // resolveWin32Command returns the original string when not found.\n const fb = resolveWin32Command(fallback);\n return fb === fallback ? cmd : fb;\n }\n return resolved;\n}\n\n/**\n * cmd.exe metacharacters that chain a new command or redirect I/O. When a\n * `.cmd`/`.bat` wrapper is launched through `cmd.exe`, any argument carrying\n * one of these can break out of the intended command line and run an\n * attacker-chosen command (the CVE-2024-27980 / \"BatBadBut\" argument-injection\n * class). We use a single vetted command line for cmd shims, so this guard is\n * mandatory before spawning.\n *\n * The set is limited to the unambiguous command-separator / redirection chars\n * plus newlines and NUL. Legitimate package-manager / test-runner flags and\n * Windows file paths (which use `:` `\\` `/` `.` `-` `_` space `(` `)`) never\n * contain these, so the guard is false-positive-free. Double quotes are also\n * rejected because cmd.exe quote toggling can break argument grouping.\n */\nconst WIN32_SHELL_META = /[&|<>\"\\r\\n\\0]/;\n\nexport interface Win32CmdShimInvocation {\n command: string;\n args: string[];\n windowsVerbatimArguments: true;\n}\n\n/**\n * Throw if any argument contains a cmd.exe command-injection metacharacter.\n * Call this ONLY on the Windows `.cmd`/`.bat` shim path. A no-op for safe args.\n */\nexport function assertSafeWin32ShellArgs(args: readonly unknown[]): void {\n for (const arg of args) {\n if (typeof arg === 'string' && WIN32_SHELL_META.test(arg)) {\n throw new Error(\n 'win32 cmd shim spawn: argument contains a shell metacharacter ' +\n '(one of & | < > \", or a newline) that could enable command injection ' +\n 'through the .cmd/.bat wrapper - refusing to run. Offending argument: ' +\n JSON.stringify(arg),\n );\n }\n }\n}\n\nexport function buildWin32CmdShimInvocation(\n command: string,\n args: readonly string[] = [],\n): Win32CmdShimInvocation {\n assertSafeWin32ShellArgs([command, ...args]);\n const line = ['call', quoteWin32CmdArg(command), ...args.map(quoteWin32CmdArg)].join(' ');\n return {\n command: process.env['COMSPEC'] ?? 'cmd.exe',\n args: ['/d', '/c', line],\n windowsVerbatimArguments: true,\n };\n}\n\nfunction quoteWin32CmdArg(arg: string): string {\n return `\"${arg}\"`;\n}\n","/**\n * Heuristic danger detection for `exec` tool commands.\n *\n * Layered on top of `BLOCKED_ARG_PATTERNS` (which is a hard-deny list for\n * clear sandbox escapes) and `bash-kill-guard.ts` (which protects WrongStack\n * itself from kill). This module assigns a danger level to a command/arg\n * pair so the caller can decide whether to:\n *\n * - 'safe' → execute normally\n * - 'caution' → execute and emit a warning line to the tool output\n * - 'destructive' → route through the existing confirm flow\n * (`execTool.permission === 'confirm'`) instead of\n * hard-deny, so the user can still proceed if intentional\n *\n * Design constraints:\n * - Deterministic: no randomness, no I/O, no time. Same input → same output.\n * - No LLM calls. Patterns are regex / exact-match.\n * - Per-rule `id` so config can override specific rules via\n * `tools.exec.danger.bypass`.\n * - Reasons are human-readable, joined with \"; \" for the confirm prompt.\n *\n * Caution rules are deliberately permissive — they execute and emit a\n * warning rather than blocking. The rationale: many of these patterns\n * (python -c, sudo, curl | bash) are part of legitimate dev workflows,\n * so a hard deny would block too much. A warning gives the user a\n * chance to notice \"wait, I didn't mean to do that\" without forcing\n * them to add a config override for every script.\n */\n\nexport type DangerLevel = 'safe' | 'caution' | 'destructive';\n\nexport interface DangerAssessment {\n level: DangerLevel;\n reasons: string[];\n /** Stable id of the matched rule, for tests and config-override. */\n matchedRule?: string;\n}\n\ninterface DangerRule {\n id: string;\n level: DangerLevel;\n /** Match a (cmd, args) pair. Return true if this rule fires. */\n test: (cmd: string, args: readonly string[]) => boolean;\n /** Human-readable explanation, joined with \"; \" in the output. */\n reason: string;\n}\n\nconst argHas = (args: readonly string[], value: string): boolean => args.includes(value);\nconst argMatches = (args: readonly string[], re: RegExp): boolean => args.some((a) => re.test(a));\n/**\n * Check for a flag like `-rf`, `-fr`, `-r -f`, `-f -r` etc. where the *order*\n * (and whether the letters are joined into one token or split across\n * separate `-x` tokens) does not matter. We accumulate every short-flag\n * letter seen across all args, then check the required letters are all\n * present somewhere in that set.\n */\nconst hasShortFlags = (args: readonly string[], letters: string): boolean => {\n const seen = new Set<string>();\n for (const a of args) {\n if (!a.startsWith('-') || a.startsWith('--')) continue;\n for (const ch of a.replace(/^-+/, '')) seen.add(ch);\n }\n return letters.split('').every((l) => seen.has(l));\n};\n\nconst RULES: readonly DangerRule[] = [\n // ----- rm / rmdir: recursive force delete (any path) -----\n // Note: BLOCKED_ARG_PATTERNS already hard-denies root/home/glob paths,\n // but `rm -rf ./build` is a normal dev workflow that the user might\n // want to do intentionally. We downgrade it to 'destructive' so the\n // confirm prompt can approve.\n {\n id: 'rm-recursive',\n level: 'destructive',\n test: (cmd, args) => (cmd === 'rm' || cmd === 'rmdir') && hasShortFlags(args, 'rf'),\n reason: 'recursive force-delete',\n },\n // ----- Windows PowerShell Remove-Item: -Recurse -Force -----\n {\n id: 'powershell-remove-item-recursive-force',\n level: 'destructive',\n test: (cmd, args) => {\n if (cmd !== 'powershell' && cmd !== 'pwsh') return false;\n const hasRecurse = argMatches(args, /^-(?:R|Recurse|Recurse\\s)/);\n const hasForce = argHas(args, '-Force') || argHas(args, '-F');\n // Allow `-WhatIf` (dry-run) without confirmation\n if (argHas(args, '-WhatIf')) return false;\n return hasRecurse && hasForce;\n },\n reason: 'Remove-Item with -Recurse -Force',\n },\n // ----- find -exec / -ok / -execdir -----\n {\n id: 'find-exec',\n level: 'destructive',\n test: (cmd, args) => {\n if (cmd !== 'find') return false;\n return args.some(\n (a) =>\n a === '-exec' ||\n a === '-exec;' ||\n a === '-ok' ||\n a === '-ok;' ||\n a === '-execdir' ||\n a === '-execdir;' ||\n a.startsWith('-exec=') ||\n a.startsWith('-ok=') ||\n a.startsWith('-execdir='),\n );\n },\n reason: 'find with -exec/-ok (executes arbitrary command on matches)',\n },\n // ----- git --exec= / --upload-pack= / --receive-pack= -----\n // These run arbitrary commands via the git transport layer.\n {\n id: 'git-exec',\n level: 'destructive',\n test: (cmd, args) =>\n cmd === 'git' &&\n args.some(\n (a) =>\n a.startsWith('--exec=') ||\n a.startsWith('--upload-pack=') ||\n a.startsWith('--receive-pack=') ||\n a === '--exec' ||\n a === '--upload-pack' ||\n a === '--receive-pack',\n ),\n reason: 'git with --exec/--upload-pack/--receive-pack (runs arbitrary code)',\n },\n // ----- Windows: format / diskpart / bcdedit -----\n {\n id: 'win32-format',\n level: 'destructive',\n test: (cmd) => cmd === 'format' || cmd === 'format.exe',\n reason: 'format (Windows disk format)',\n },\n {\n id: 'win32-diskpart',\n level: 'destructive',\n test: (cmd) => cmd === 'diskpart' || cmd === 'diskpart.exe',\n reason: 'diskpart (Windows partition editor)',\n },\n {\n id: 'win32-bcdedit',\n level: 'destructive',\n test: (cmd) => cmd === 'bcdedit' || cmd === 'bcdedit.exe',\n reason: 'bcdedit (Windows boot config editor)',\n },\n // ----- mkfs family -----\n {\n id: 'mkfs',\n level: 'destructive',\n test: (cmd) => /^mkfs(\\.[a-z0-9]+)?$/.test(cmd) || cmd === 'mkswap',\n reason: 'mkfs (filesystem creation — destroys existing data)',\n },\n // ----- dd writing to a block device -----\n {\n id: 'dd-to-block-device',\n level: 'destructive',\n test: (cmd, args) => {\n if (cmd !== 'dd') return false;\n return args.some((a) => /of=\\/dev\\/(sd|hd|nvme|vd|mmcblk|xvd|loop|disk)/.test(a));\n },\n reason: 'dd writing to a block device',\n },\n // ----- Secure-erase tools -----\n {\n id: 'shred',\n level: 'destructive',\n test: (cmd) => cmd === 'shred' || cmd === 'shred.exe',\n reason: 'shred (secure file delete)',\n },\n {\n id: 'wipefs',\n level: 'destructive',\n test: (cmd) => cmd === 'wipefs' || cmd === 'wipefs.exe',\n reason: 'wipefs (signature wipe — destroys filesystem headers)',\n },\n {\n id: 'sdelete',\n level: 'destructive',\n test: (cmd) => cmd === 'sdelete' || cmd === 'sdelete.exe',\n reason: 'sdelete (Sysinternals secure delete)',\n },\n // ----- VCS history rewrite (destructive) -----\n // `git push --force` / `-f` rewrites remote history. `--force-with-lease`\n // is the safer variant (checks remote hasn't moved) but still rewrites.\n {\n id: 'git-push-force',\n level: 'destructive',\n test: (cmd, args) => {\n if (cmd !== 'git') return false;\n const pushIdx = args.indexOf('push');\n if (pushIdx < 0) return false;\n for (let i = pushIdx + 1; i < args.length; i++) {\n const a = args[i]!;\n if (a === '--force' || a === '-f' || a === '--force-with-lease') return true;\n if (!a.startsWith('-') && !a.includes('=')) continue;\n if (a.startsWith('--force') /* covers --force-with-lease already */) return true;\n }\n return false;\n },\n reason: 'git push with --force / -f (rewrites remote history)',\n },\n // ----- git reset --hard (destructive) -----\n {\n id: 'git-reset-hard',\n level: 'destructive',\n test: (cmd, args) =>\n cmd === 'git' && args.some((a) => a === '--hard' || a.startsWith('--hard=')),\n reason: 'git reset --hard (discards working tree + index)',\n },\n // ----- git clean -f / -fd (destructive) -----\n {\n id: 'git-clean-force',\n level: 'destructive',\n test: (cmd, args) => {\n if (cmd !== 'git') return false;\n const cleanIdx = args.indexOf('clean');\n if (cleanIdx < 0) return false;\n // Must include -f / --force (without it, git clean errors out and\n // does nothing). -fd / -fdX combinations are subsumed.\n return args\n .slice(cleanIdx + 1)\n .some(\n (a) =>\n a === '-f' ||\n a === '--force' ||\n a.startsWith('-f') /* -fd, -fdx, etc. */ ||\n a.startsWith('--force='),\n );\n },\n reason: 'git clean -f (deletes untracked files)',\n },\n // ----- package publish (destructive — public, irreversible) -----\n {\n id: 'npm-publish',\n level: 'destructive',\n test: (cmd, args) => {\n if (!['npm', 'pnpm', 'yarn', 'bun', 'cargo'].includes(cmd)) return false;\n // For npm/pnpm/yarn/bun: subcommand is \"publish\".\n // For cargo: subcommand is \"publish\" OR \"yank\" (both touch the\n // public registry; yank is reversible, publish is not, but yank\n // is rare enough we treat it the same).\n return args.includes('publish') || (cmd === 'cargo' && args.includes('yank'));\n },\n reason: 'publishing to a public package registry (hard to reverse)',\n },\n // ----- k8s cluster-wide destructive ops (destructive) -----\n {\n id: 'kubectl-delete-namespace',\n level: 'destructive',\n test: (cmd, args) => {\n if (cmd !== 'kubectl') return false;\n const delIdx = args.indexOf('delete');\n if (delIdx < 0) return false;\n // Match `kubectl delete namespace <name>` or `kubectl delete ns <name>`.\n // Generic `kubectl delete pod foo` is left out — too common.\n const after = args.slice(delIdx + 1);\n return after[0] === 'namespace' || after[0] === 'ns';\n },\n reason: 'kubectl delete namespace (deletes all resources in the namespace)',\n },\n {\n id: 'kubectl-drain',\n level: 'destructive',\n test: (cmd, args) => cmd === 'kubectl' && args.includes('drain'),\n reason: 'kubectl drain (evicts pods, marks node unschedulable)',\n },\n // ----- inline code evaluation (caution — high false-positive) -----\n // Common in scripts: `python -c \"...\"`, `node -e \"...\"`, `bash -c \"...\"`.\n // We tag 'caution' rather than 'destructive' because these are used in\n // many legitimate one-liners (e.g. `python -c \"print(1)\"`).\n {\n id: 'inline-eval',\n level: 'caution',\n test: (cmd, args) => {\n if (\n ![\n 'python',\n 'python3',\n 'python2',\n 'node',\n 'bash',\n 'sh',\n 'zsh',\n 'ruby',\n 'perl',\n 'lua',\n ].includes(cmd)\n ) {\n return false;\n }\n return args.some(\n (a) =>\n a === '-c' ||\n a === '-e' ||\n a === '--eval' ||\n a === '-eval' ||\n a === '-E' /* node --eval shorthand in some shells */,\n );\n },\n reason: 'inline script evaluation (-c / -e / --eval)',\n },\n // ----- pipe-to-shell (caution — well-known exfil pattern) -----\n // The classic `curl https://... | sh` download-and-run vector. Detected by\n // looking for a known fetcher followed by a shell sink. We use a simple\n // substring scan; false positives are limited because both tokens must\n // appear in the same argv.\n {\n id: 'pipe-to-shell',\n level: 'caution',\n test: (_cmd, args) => {\n const hasFetcher = args.some(\n (a) =>\n /^(curl|wget|fetch|httpie|http)$/i.test(a) ||\n a.startsWith('curl') /* curl.exe on Windows */ ||\n a.startsWith('wget'),\n );\n const hasShellSink = args.some(\n (a) =>\n a === 'sh' ||\n a === 'bash' ||\n a === 'zsh' ||\n a === 'fish' ||\n a === 'pwsh' ||\n a === 'powershell' ||\n a.endsWith('/sh') ||\n a.endsWith('/bash') ||\n a.endsWith('/zsh') ||\n a.endsWith('/pwsh'),\n );\n // Also catches the sh -c \"...\" form (where \"sh\" is the cmd, not in args)\n // — but that's covered by inline-eval. This rule is specifically\n // for the fetcher-pipe-shell case in a single command.\n return hasFetcher && hasShellSink;\n },\n reason: 'network fetch piped to a shell (download-and-run pattern)',\n },\n // ----- privilege escalation (caution) -----\n {\n id: 'sudo',\n level: 'caution',\n test: (cmd) => cmd === 'sudo' || cmd === 'doas',\n reason: 'privilege escalation (sudo / doas)',\n },\n {\n id: 'runas',\n level: 'caution',\n test: (cmd) => cmd === 'runas' || cmd === 'runas.exe',\n reason: 'Windows runas (run as different user)',\n },\n // ----- world-writable permissions (caution) -----\n // `chmod 777` is rarely correct. `chmod -R 777` is almost always wrong.\n // We only flag octal modes; symbolic modes like `chmod o+w` are\n // left to the operator's discretion.\n {\n id: 'chmod-world-writable',\n level: 'caution',\n test: (cmd, args) => {\n if (cmd !== 'chmod') return false;\n // Skip symbolic modes: anything starting with [ugoa]=\\w or [ugoa]+\\w.\n // The only thing we flag is a pure octal mode containing 7 anywhere\n // in the user/group/other triple (e.g. 777, 776, 747, 707).\n return args.some((a) => /^[0-7]{3,4}$/.test(a) && /7/.test(a));\n },\n reason: 'chmod with world-writable octal mode (e.g. 777)',\n },\n];\n\n/**\n * Evaluate the danger level of a (cmd, args) pair.\n *\n * Returns 'safe' if no rule fires, otherwise the highest level among all\n * matching rules. The 'matchedRule' field is the *last* rule that fired\n * (stable, since rules are evaluated in declaration order).\n *\n * Optional `bypass` argument: a set of rule ids that should be SKIPPED\n * even if they would otherwise match. Wired from\n * `config.tools.exec.danger.bypass` (see `ExecDangerConfig` in\n * `@wrongstack/core/src/types/config.ts`). Unknown ids are silently\n * ignored — forward-compat: a rule added in a future version can be\n * referenced before the user upgrades their config schema.\n *\n * This function is the single source of truth for danger classification;\n * it is pure (no side effects) and unit-tested in `danger-detect.test.ts`.\n */\nexport function detectDanger(\n cmd: string,\n args: readonly string[],\n bypass?: ReadonlySet<string>,\n): DangerAssessment {\n const reasons: string[] = [];\n let level: DangerLevel = 'safe';\n let matchedRule: string | undefined;\n\n for (const rule of RULES) {\n if (bypass?.has(rule.id)) continue;\n if (!rule.test(cmd, args)) continue;\n reasons.push(rule.reason);\n matchedRule = rule.id;\n if (levelRank(rule.level) > levelRank(level)) {\n level = rule.level;\n }\n }\n\n if (level === 'safe') return { level: 'safe', reasons: [] };\n // matchedRule is set above (last winning rule). For exactOptionalPropertyTypes\n // we build the object conditionally so the property is omitted when undefined.\n const result: DangerAssessment = { level, reasons };\n if (matchedRule !== undefined) result.matchedRule = matchedRule;\n return result;\n}\n\nfunction levelRank(level: DangerLevel): number {\n switch (level) {\n case 'safe':\n return 0;\n case 'caution':\n return 1;\n case 'destructive':\n return 2;\n }\n}\n","import { spawn } from 'node:child_process';\nimport type { Tool } from '@wrongstack/core';\nimport { toErrorMessage } from '@wrongstack/core/utils/error';\nimport { buildChildEnv } from './_env.js';\nimport { createOutputSpool, spoolNote } from './_output-spool.js';\nimport { COMMAND_OUTPUT_MAX_BYTES, normalizeCommandOutput, safeResolveReal } from './_util.js';\nimport { getProcessRegistry, redactCommand } from './process-registry.js';\nimport {\n buildWin32CmdShimInvocation,\n resolveWin32Command,\n} from './_win32-resolve.js';\nimport { detectDanger, type DangerAssessment } from './_danger-detect.js';\n\nconst isWin = process.platform === 'win32';\n\n// Curated default allowlist of command NAMES the `exec` tool may run. Only the\n// command name is gated (per-arg safety is the BLOCKED_ARG_PATTERNS denylist\n// below + the per-call `confirm` permission). A prior version mapped each\n// command to an allowed-args array, but those arrays were never enforced (dead\n// code) — a plain Set is the honest shape.\n//\n// Extend/trim at runtime via `configureExecPolicy()` (wired from\n// `config.tools.exec.{allow,deny}` at boot). `allow` is trusted-config-only;\n// see the security note on ExecToolConfig.\nconst DEFAULT_ALLOWED_COMMANDS: ReadonlySet<string> = new Set([\n // JS / TS toolchain\n 'node', 'npm', 'pnpm', 'yarn', 'npx', 'bun', 'deno',\n 'corepack', 'tsc', 'tsx', 'ts-node', 'vite', 'vitest', 'jest',\n 'biome', 'eslint', 'prettier', 'turbo', 'nx', 'webpack', 'rollup',\n 'parcel', 'next', 'astro', 'playwright', 'cypress',\n // version control\n 'git',\n // Rust\n 'cargo', 'rustc',\n // Go\n 'go',\n // Python\n 'python', 'python3', 'pip', 'pip3', 'pytest', 'ruff', 'mypy',\n 'uv', 'uvx', 'poetry', 'hatch', 'tox',\n // Ruby\n 'ruby', 'gem', 'bundle',\n // PHP\n 'php', 'composer', 'phpunit',\n // JVM\n 'java', 'javac', 'mvn', 'gradle', 'gradlew',\n // .NET\n 'dotnet',\n // C / C++ / native build\n 'make', 'cmake', 'ninja', 'clang', 'clang-cl', 'gcc', 'g++', 'link', 'msbuild',\n // containers / orchestration\n 'docker', 'podman', 'kubectl',\n // network (read-only intent; destructive ops still blocked by BLOCKED_ARG_PATTERNS)\n 'curl', 'wget',\n // common POSIX file/text utilities\n 'pwd', 'ls', 'cat', 'head', 'tail', 'wc', 'grep', 'rg', 'find',\n 'echo', 'sort', 'uniq', 'sed', 'awk', 'mkdir', 'cp', 'mv', 'rm',\n 'touch', 'tar',\n // Windows-native tooling (win32). All non-destructive binaries; per-arg\n // safety is still enforced by BLOCKED_ARG_PATTERNS + the destructive-ops\n // gate in bash-kill-guard.ts. `gh` is included even though it lives at\n // \"C:\\Program Files\\GitHub CLI\\gh.exe\" — resolveWin32Command handles the\n // space in the path.\n 'gh',\n 'where', 'tasklist', 'systeminfo', 'wmic', 'sc',\n 'netstat', 'ipconfig', 'nslookup', 'tracert', 'pathping',\n // Windows shell interpreters. Without these, `exec` cannot run cmd builtins\n // (`dir`, `type`, `copy`, …) or any PowerShell cmdlet on Windows — a major\n // gap since those are the platform's primary shells. Arbitrary execution\n // through `cmd /c …` / `powershell -c …` is NOT a new hole: the permission\n // policy reconstructs the full command line (shellCommandLineFromInput) and\n // still runs it through the YOLO destructive classifier, so a genuinely\n // destructive `cmd /c del /s /q C:\\…` continues to require confirmation.\n 'cmd', 'cmd.exe', 'powershell', 'powershell.exe', 'pwsh', 'pwsh.exe',\n // [core] Extended default allowlist (added 4b3d18d1 + this commit). All\n // non-destructive, broadly-used dev binaries. Per-arg safety is still\n // enforced by BLOCKED_ARG_PATTERNS + bash-kill-guard.ts.\n // --- Archives & compression ---\n '7z', '7za', 'bzip2', 'gzip', 'xz', 'unzip', 'zip', 'gtar', 'bsdtar', 'star', 'pax', 'cpio',\n // --- Android / mobile dev ---\n 'adb', 'fastboot', 'sdkmanager',\n // --- DevOps / config mgmt ---\n 'ansible', 'ansible-playbook', 'ansible-vault', 'ansible-lint', 'ansible-galaxy', 'molecule',\n // --- Cloud CLIs ---\n 'aws', 'aws-vault', 'awslocal', 'az', 'azcopy', 'gcloud', 'gsutil', 'doctl', 'linode-cli',\n // --- Native / C / C++ / linker tools ---\n 'clang++', 'clang-format', 'clang-tidy', 'clangd', 'lld', 'lldb', 'ctest', 'gmake', 'meson', 'conan', 'vcpkg', 'cl', 'rc', 'mt', 'dumpbin', 'dotnet-format',\n // --- Image / media / binary tools ---\n 'convert', 'ffmpeg', 'ffprobe', 'magick', 'gs', 'exiftool',\n // --- HTTP / fetch ---\n 'wget2', 'aria2c', 'axel', 'httpie', 'hey', 'ab', 'wrk', 'http',\n // --- Diff / patch / merge ---\n 'diff', 'diff3', 'patch', 'meld', 'kdiff3', 'kompare',\n // --- Encoding / file inspection ---\n 'dos2unix', 'unix2dos', 'iconv', 'file', 'stat', 'xxd', 'hexdump', 'od', 'base64',\n // --- SSH / crypto / signing ---\n 'ssh', 'ssh-add', 'ssh-keygen', 'ssh-keyscan', 'scp', 'sftp', 'rsync', 'gpg', 'gpg2', 'gpg-agent', 'openssl', 'step', 'keytool',\n // --- Search ---\n 'egrep', 'fgrep', 'ag', 'ack', 'sift', 'ugrep', 'fd', 'fdfind', 'jq', 'yq', 'xq', 'fx', 'gron',\n // --- K8s / container ecosystem ---\n 'kubectl.exe', 'kubeadm', 'kubelet', 'helm', 'k9s', 'kustomize', 'skaffold', 'tilt', 'minikube', 'kind', 'k3d', 'k3s',\n 'docker-compose', 'buildah', 'skopeo', 'nerdctl', 'ctr', 'ctr.exe',\n // --- Databases ---\n 'sqlite3', 'sqlite', 'psql', 'pg_dump', 'pg_restore', 'mysql', 'mysqladmin', 'mysqldump', 'mariadb', 'mariadb-dump',\n 'redis-cli', 'redis-server', 'memcached', 'etcdctl', 'consul', 'vault', 'nomad',\n 'mongosh', 'mongo', 'mongoexport', 'mongoimport', 'mongodump', 'mongorestore',\n // --- Windows extended (read-mostly ops) ---\n 'taskkill', 'gpupdate', 'gpresult', 'hostname', 'whoami', 'who', 'net', 'net1',\n // --- VCS ecosystem ---\n 'glab', 'hub', 'tea', 'git-lfs', 'tig', 'lazygit',\n // --- POSIX text utilities (extended; duplicates of pwd/ls/cat/head/tail/wc/\n // grep/find/echo/awk/mkdir/cp/mv/rm/touch from the base list above are\n // omitted — the Set is de-duplicated at runtime but a clean literal is\n // easier to maintain) ---\n 'gawk', 'tr', 'cut', 'paste', 'join', 'comm', 'expand', 'unexpand', 'fold', 'fmt', 'nl', 'pr', 'column', 'tsort',\n 'tty', 'ul', 'units', 'factor', 'seq', 'shuf', 'look', 'yes', 'true', 'false', 'test', '[', 'printf',\n 'env',\n 'tree', 'locate', 'which', 'whereis', 'type', 'hash', 'pushd', 'popd', 'dirs', 'history', 'fc', 'jobs', 'bg', 'fg', 'wait',\n 'ulimit', 'umask', 'nice', 'nohup', 'timeout', 'time', 'trap', 'exit', 'return', 'source', '.', 'alias', 'unalias',\n 'set', 'unset', 'export', 'readonly', 'typeset', 'declare', 'local', 'eval', 'exec',\n // --- Process / system inspection ---\n 'htop', 'top', 'atop', 'glances', 'iotop', 'nethogs', 'iftop', 'lsof', 'strace', 'ltrace', 'sysstat', 'vmstat', 'iostat', 'mpstat', 'sar',\n 'free', 'df', 'du', 'mount', 'umount', 'lsblk', 'blkid',\n 'kill', 'killall', 'pkill', 'pgrep', 'pidof', 'ps', 'ps.exe',\n // --- Network inspection ---\n 'ip', 'ss', 'route', 'arp', 'arping', 'ping', 'ping6', 'hping3', 'mtr', 'tracepath', 'tcpdump', 'nmap', 'netcat', 'nc', 'ncat', 'socat',\n // --- Sync / backup ---\n 'rclone', 'restic', 'borg', 'duplicati', 'duplicacy', 'syncthing', 'syncthing-cli',\n // --- Permissions / users / ACLs (POSIX) ---\n 'useradd', 'userdel', 'usermod', 'groupadd', 'groupdel', 'groupmod', 'chown', 'chmod', 'chgrp', 'getfacl', 'setfacl', 'setcap', 'getcap',\n // --- Crypto / cert mgmt (extended) ---\n 'certbot', 'mkcert', 'jarsigner',\n // --- Editors ---\n 'subl', 'code', 'code-insiders', 'cursor', 'atom', 'nano', 'vim', 'nvim', 'vi', 'emacs', 'helix', 'hx', 'micro', 'jed', 'ed', 'ex', 'mg',\n // --- Terminal multiplexers ---\n 'asciinema', 'script', 'scriptreplay', 'expect', 'screen', 'tmux', 'byobu', 'dtach', 'abduco',\n // --- Calculators / REPLs / scientific ---\n 'bc', 'dc', 'calc', 'qalc', 'genius', 'octave', 'R', 'Rscript', 'julia', 'irb', 'pry', 'ghci', 'stack', 'cabal', 'ghc',\n // --- PHP / Lua / Perl / Ruby ecosystem (extended) ---\n 'php8', 'php7', 'phpcs', 'phpcbf', 'phpmd', 'phpstan', 'psalm',\n 'lua', 'lua5.1', 'lua5.2', 'lua5.3', 'lua5.4', 'luarocks',\n 'perl', 'cpan', 'prove', 'plackup',\n 'rake', 'rspec', 'jekyll', 'node-gyp', 'node-pre-gyp',\n // --- JS / TS toolchain (extended) ---\n 'electron', 'electron-builder', 'electron-forge', 'vite-preview', 'swc', 'swc-cli', 'swcpack',\n 'mocha', 'chai', 'jasmine', 'puppeteer', 'lighthouse',\n // --- Linters / formatters (extended) ---\n 'tslint', 'stylelint', 'htmlhint', 'jshint', 'jslint', 'jscs',\n // --- Document conversion ---\n 'pandoc', 'weasyprint', 'wkhtmltopdf', 'wkhtmltoimage', 'prince', 'mdp', 'markdown', 'multimarkdown', 'cmark', 'cmark-gfm',\n // --- Office / spreadsheet ---\n 'soffice', 'libreoffice', 'unoconv', 'abiword', 'gnumeric',\n // --- Spell / grammar ---\n 'aspell', 'hunspell', 'enchant', 'languagetool',\n // --- Source-highlight / diff tools ---\n 'delta', 'bat', 'ccat', 'hl', 'highlight', 'source-highlight', 'ansifilter',\n // --- Job schedulers ---\n 'pueue', 'task-spooler', 'ts', 'at', 'atd', 'anacron', 'fcron', 'cronie', 'systemd-run', 'systemd-cat',\n // --- Plotting / visualization ---\n 'gnuplot', 'gnuplot-nox', 'veusz', 'scidavis', 'grace', 'xmgrace', 'labplot',\n // --- Security / recon (network + web) ---\n 'masscan', 'zmap', 'rustscan', 'amass', 'subfinder', 'httpx', 'nuclei', 'naabu', 'katana', 'dnsx', 'assetfinder', 'findomain', 'gau', 'waybackurls', 'httprobe', 'meg', 'subjack', 'sublert', 'chaos',\n]);\n\n// The live, effective allowlist: DEFAULT ∪ config.allow − config.deny. Replaced\n// wholesale by configureExecPolicy(); defaults until boot wires the config.\nlet allowedCommands: Set<string> = new Set(DEFAULT_ALLOWED_COMMANDS);\n\nconst normalizeCmd = (c: string): string => c.trim();\n\n/**\n * Apply the configured exec command policy. Recomputes the effective allowlist\n * as `DEFAULT ∪ allow − deny`. Call once at boot from\n * `config.tools.exec.{allow,deny}`. Idempotent (always rebuilt from defaults).\n *\n * SECURITY: `allow` must originate from TRUSTED config only — the config loader\n * strips `tools.exec.allow` from the untrusted in-project repo config before it\n * reaches here. `deny` is safe from any source (it only narrows).\n */\nexport function configureExecPolicy(opts: { allow?: readonly string[] | undefined; deny?: readonly string[] | undefined } = {}): void {\n const next = new Set(DEFAULT_ALLOWED_COMMANDS);\n for (const c of opts.allow ?? []) {\n const n = normalizeCmd(c);\n if (n) next.add(n);\n }\n for (const c of opts.deny ?? []) next.delete(normalizeCmd(c));\n allowedCommands = next;\n}\n\n/** Reset the exec allowlist to the built-in defaults (tests / re-init). */\nexport function resetExecPolicy(): void {\n allowedCommands = new Set(DEFAULT_ALLOWED_COMMANDS);\n}\n\n// -----------------------------------------------------------------------\n// Danger-detection bypass (config.tools.exec.danger.bypass)\n// -----------------------------------------------------------------------\n\n/**\n * Set of rule ids that should be skipped during danger detection. Wired\n * from `config.tools.exec.danger.bypass` at boot. Mirrors the\n * `allowedCommands` pattern above: defaults to empty, replaced wholesale\n * by `configureDangerBypass()`, reset by `resetDangerBypass()`.\n *\n * SECURITY: like `allow`, this is a per-rule weakening of the danger\n * gate. The boot path strips `tools.exec.danger.bypass` from in-project\n * repo config; only trusted config (user-global, system) sets it.\n */\nlet dangerBypass: ReadonlySet<string> = new Set();\n\n/**\n * Apply the configured danger-bypass policy. Each id in `bypass` is\n * added to the effective skip set; duplicates are fine. Idempotent.\n *\n * Call once at boot from `config.tools.exec.danger.bypass`.\n */\nexport function configureDangerBypass(opts: { bypass?: readonly string[] | undefined } = {}): void {\n const next = new Set<string>();\n for (const id of opts.bypass ?? []) {\n const trimmed = id.trim();\n if (trimmed) next.add(trimmed);\n }\n dangerBypass = next;\n}\n\n/** Reset the danger-bypass set to empty (tests / re-init). */\nexport function resetDangerBypass(): void {\n dangerBypass = new Set();\n}\n\n/**\n * Read-only view of the active bypass set. `detectDanger()` takes a\n * `bypass` argument directly, so consumers should prefer passing this\n * rather than reading the set and matching themselves.\n */\nexport function getDangerBypass(): ReadonlySet<string> {\n return dangerBypass;\n}\n\n/** Whether `cmd` is currently in the effective exec allowlist. */\nexport function isExecCommandAllowed(cmd: string): boolean {\n return allowedCommands.has(normalizeCmd(cmd));\n}\n\n/** Snapshot of the effective allowlist (sorted) — for tests / diagnostics. */\nexport function getExecAllowlist(): string[] {\n return [...allowedCommands].sort();\n}\n\nconst MAX_ARGS = 20;\n// 200 KB — larger than bash's 32 KB cap. exec commands produce structured,\n// predictable output (build logs, test results, git diffs) that the agent\n// needs in full. 200 KB is safe for context windows ≥200K tokens while\n// still preventing a rogue build from filling the context.\nconst MAX_OUTPUT = 200_000;\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n// Per-command hard-blocks. Keep this list narrow: `exec` is already a\n// confirm-gated tool with argv passed as an array and cwd confined to the\n// project. These patterns should block clear sandbox escapes / destructive\n// operations, not normal development workflows that happen to execute code.\nconst BLOCKED_ARG_PATTERNS: Record<string, RegExp[]> = {\n python: [],\n // git --exec=<cmd> runs arbitrary commands via upload-pack/receive-pack;\n // -C <dir> changes working directory, bypassing cwd sandbox;\n // -c/--config <k>=<v> injects config that runs commands\n // (e.g. core.sshCommand, core.pager, http.proxy, alias.x=!cmd).\n git: [\n /^--exec=/,\n /^--upload-pack=/,\n /^--receive-pack=/,\n /^-C$/,\n /^-c$/,\n /^--config$/,\n /^-c=/,\n /^--config=/,\n /^--config-env=/,\n ],\n node: [],\n go: [],\n bun: [],\n docker: [],\n // find -exec/-ok/-execdir execute arbitrary commands\n find: [/^-exec$/, /^-exec;$/, /^-ok$/, /^-ok;$/, /^-execdir$/, /^-execdir;$/, /^-exec=/, /^-ok=/, /^-execdir=/],\n // rm -rf / is catastrophic — block absolute paths, home, dot-dirs,\n // and glob patterns that could expand to dangerous targets.\n // `rm -rf ./src/*` expands to project files; `rm -rf ../../` escapes upward;\n // `rm -rf /*` targets the filesystem root. All are blocked.\n rm: [/^\\//, /^~\\//, /^~$/, /^\\.$/, /^\\.\\.$/, /\\*$/, /\\/$/, /\\/\\*$/, /\\.\\//],\n // npm/pnpm subcommands are checked separately below. Matching every arg here\n // over-blocked normal dev flows such as `pnpm vitest run ...`.\n npm: [],\n pnpm: [],\n npx: [],\n};\n\n// Subcommand verbs only make sense in subcommand position. Keep externally\n// destructive actions blocked there without rejecting harmless downstream args\n// named \"run\", \"publish\", etc. passed to test runners or build tools.\nconst BLOCKED_SUBCOMMANDS: Record<string, ReadonlySet<string>> = {\n docker: new Set(['push']),\n podman: new Set(['push']),\n npm: new Set(['publish', 'deploy']),\n pnpm: new Set(['publish', 'deploy']),\n yarn: new Set(['publish']),\n};\n\nconst BLOCKED_SUBCOMMAND_SEQUENCES: Record<string, readonly (readonly string[])[]> = {\n yarn: [['npm', 'publish']],\n};\n\nfunction firstSubcommand(args: string[]): string | null {\n for (const arg of args) {\n if (arg === '--') return null;\n if (!arg.startsWith('-')) return arg;\n }\n return null;\n}\n\nfunction subcommandArgs(args: string[]): string[] {\n const out: string[] = [];\n for (const arg of args) {\n if (arg === '--') break;\n if (!arg.startsWith('-')) out.push(arg);\n }\n return out;\n}\n\nfunction validateArgs(cmd: string, args: string[]): string | null {\n const blockedSubcommands = BLOCKED_SUBCOMMANDS[cmd];\n const subcommand = firstSubcommand(args);\n if (blockedSubcommands && subcommand && blockedSubcommands.has(subcommand)) {\n return `Blocked subcommand \"${subcommand}\" for command \"${cmd}\"`;\n }\n\n const blockedSequences = BLOCKED_SUBCOMMAND_SEQUENCES[cmd];\n if (blockedSequences) {\n const actual = subcommandArgs(args);\n const blocked = blockedSequences.find((seq) => seq.every((part, idx) => actual[idx] === part));\n if (blocked) return `Blocked subcommand \"${blocked.join(' ')}\" for command \"${cmd}\"`;\n }\n\n const blocked = BLOCKED_ARG_PATTERNS[cmd];\n if (!blocked) return null;\n\n for (const arg of args) {\n for (const pattern of blocked) {\n if (pattern.test(arg)) {\n return `Blocked argument \"${arg}\" for command \"${cmd}\" (matches security pattern ${pattern})`;\n }\n }\n }\n return null;\n}\n\ninterface ExecInput {\n command: string;\n args?: string[] | undefined;\n cwd?: string | undefined;\n timeout?: number | undefined;\n}\n\ninterface ExecOutput {\n command: string;\n args: string[];\n stdout: string;\n stderr: string;\n exitCode: number;\n truncated: boolean;\n allowed: boolean;\n /**\n * Heuristic danger assessment of the (cmd, args) pair. Populated for every\n * call (not just blocked ones) so the UI/TUI can render a banner when the\n * level is 'caution' or 'destructive'. See `_danger-detect.ts` for the\n * rule set.\n *\n * Pre-execution error returns (allowlist miss, circuit breaker, etc.)\n * report `level: 'safe'` because the command never actually ran; the UI\n * should surface the error separately and not also a danger warning.\n */\n danger: DangerAssessment;\n}\n\nconst SAFE_DANGER: DangerAssessment = { level: 'safe', reasons: [] };\n\nexport const execTool: Tool<ExecInput, ExecOutput> = {\n name: 'exec',\n category: 'Shell',\n description:\n 'Execute a **whitelisted, restricted set of commands** with strict argument validation. ' +\n 'This is the **preferred and safer** alternative to the `bash` tool for running development tools (node, npm, pnpm, tsc, git, tests, linters, etc.). ' +\n 'It prevents arbitrary command injection and limits what the model can do.',\n usageHint:\n 'PREFERRED SHELL TOOL for most cases.\\n\\n' +\n 'Use this instead of `bash` whenever possible.\\n' +\n '- `command` must be in the allowlist. Defaults cover JS (node/npm/pnpm/yarn/bun/deno/tsc/vitest/eslint/biome), Go (`go build`/`go test`), Rust (cargo), Python (python/pip), Ruby (gem/bundle), JVM (java/mvn/gradle), .NET (dotnet), native (make/cmake), and git. Users can extend it via `tools.exec.allow` in config.\\n' +\n '- Arguments are passed as a clean array (no shell interpretation).\\n' +\n '- `cwd` is validated to stay inside the project.\\n' +\n '- If a command is not allowlisted, the error explains how to add it; for one-off arbitrary commands, fall back to `bash` (with strong justification).\\n' +\n 'This tool significantly reduces the risk compared to full shell access.',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n timeoutMs: DEFAULT_TIMEOUT_MS,\n capabilities: ['shell.restricted'],\n icon: 'terminal',\n inputSchema: {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n description: 'The base command to run. Must be in the internal allowlist (e.g. \"node\", \"pnpm\", \"git\", \"tsc\").',\n },\n args: {\n type: 'array',\n items: { type: 'string' },\n description: 'Arguments passed to the command. Passed as an array (no shell parsing).',\n },\n cwd: {\n type: 'string',\n description: 'Optional working directory. Must resolve inside the project root.',\n },\n timeout: {\n type: 'integer',\n description: 'Per-command timeout in milliseconds.',\n },\n },\n required: ['command'],\n },\n async execute(input, ctx, opts) {\n const registry = getProcessRegistry();\n if (!registry.canProceed) {\n return {\n command: input.command,\n args: input.args ?? [],\n stdout: '',\n stderr: 'Circuit breaker is open — too many consecutive failures. Use /kill reset to recover.',\n exitCode: 1,\n truncated: false,\n allowed: false,\n danger: SAFE_DANGER,\n };\n }\n\n const cmd = input.command.trim();\n if (!cmd)\n return {\n command: cmd,\n args: [],\n stdout: '',\n stderr: 'Empty command',\n exitCode: 1,\n truncated: false,\n allowed: false,\n danger: SAFE_DANGER,\n };\n\n if (!isExecCommandAllowed(cmd)) {\n return {\n command: cmd,\n args: input.args ?? [],\n stdout: '',\n stderr:\n `Command \"${cmd}\" not in allowlist. ` +\n `Add it to your ~/.wrongstack/config.json under \"tools\": { \"exec\": { \"allow\": [\"${cmd}\"] } }, ` +\n `or use the bash tool for one-off arbitrary commands.`,\n exitCode: 1,\n truncated: false,\n allowed: false,\n danger: SAFE_DANGER,\n };\n }\n\n const args = (input.args ?? []).slice(0, MAX_ARGS);\n const timeout = Math.max(1, Math.min(input.timeout ?? DEFAULT_TIMEOUT_MS, DEFAULT_TIMEOUT_MS));\n\n // Heuristic danger assessment. Computed once here, attached to every\n // return from this point on (including error returns) so the UI can\n // render a banner for 'caution' / 'destructive' levels. The `bypass`\n // argument is wired from `config.tools.exec.danger.bypass` (see\n // `configureDangerBypass`); rule ids in that set are skipped.\n const danger: DangerAssessment = detectDanger(cmd, args, dangerBypass);\n\n // Validate args against per-command security patterns\n const argError = validateArgs(cmd, args);\n if (argError) {\n return {\n command: cmd,\n args,\n stdout: '',\n stderr: argError,\n exitCode: 1,\n truncated: false,\n allowed: false,\n danger,\n };\n }\n\n let cwd: string;\n try {\n // Resolve cwd inside the project root and verify realpath containment so\n // an in-project symlink cannot redirect allowlisted commands outside.\n cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : await safeResolveReal(ctx.cwd, ctx);\n } catch {\n return {\n command: cmd,\n args,\n stdout: '',\n stderr: `cwd \"${input.cwd ?? ctx.cwd}\" resolves outside project root`,\n exitCode: 1,\n truncated: false,\n allowed: false,\n danger,\n };\n }\n const signal = opts.signal;\n\n return runCommand(cmd, args, cwd, timeout, signal, ctx.session?.id, danger);\n },\n};\n\nfunction runCommand(\n cmd: string,\n args: string[],\n cwd: string,\n timeout: number,\n signal: AbortSignal,\n sessionId: string | undefined,\n danger: DangerAssessment,\n): Promise<ExecOutput> {\n return new Promise((resolve) => {\n let stdout = '';\n let stderr = '';\n let killed = false;\n const resolvedOnce = { value: false };\n const finish = (result: ExecOutput): void => {\n // Guard against double-resolve: 'error' and 'close' can both fire for\n // the same abort (Node's abort path emits both), and resolving twice\n // is a no-op but the extra work (normalizeCommandOutput, registry\n // bookkeeping, spool finalize) is wasted. First writer wins.\n if (resolvedOnce.value) return;\n resolvedOnce.value = true;\n resolve(result);\n };\n const startedAt = Date.now();\n // Full-output spool (stdout+stderr interleaved as they arrive): the\n // in-memory buffers keep only the first MAX_OUTPUT bytes; the spool\n // captures everything on disk and the result points at the file.\n const spool = createOutputSpool({ tool: `exec-${cmd}`, thresholdBytes: MAX_OUTPUT });\n\n // On Windows, .cmd/.bat files are not natively executable by CreateProcess.\n // resolveWin32Command() finds the full path, then the shim helper launches\n // it through cmd.exe without Node's deprecated shell+args path.\n const resolved = resolveWin32Command(cmd);\n const needsShell = isWin && (resolved.endsWith('.cmd') || resolved.endsWith('.bat'));\n const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;\n const spawnCmd = shim?.command ?? resolved;\n const spawnArgs = shim?.args ?? args;\n\n // Wrap the entire spawn lifecycle in try/catch so a synchronous throw\n // (bad argv, ENOENT for missing binary, ERR_INVALID_ARG_TYPE for bad\n // signal, etc.) resolves the promise with an error response instead\n // of producing an unhandled rejection. Without this guard the\n // promise executor itself can throw, which Node treats as an\n // unhandled rejection and surfaces in process.on('unhandledRejection').\n let child: ReturnType<typeof spawn>;\n try {\n // On Windows the abort signal is handled manually below: Node's built-in\n // handling kills only the direct child, orphaning grandchildren (vitest\n // forks, dev servers, anything under a .cmd shim) that keep the inherited\n // stdio pipes open. registry.kill() tree-kills via taskkill instead.\n child = spawn(spawnCmd, spawnArgs, {\n cwd,\n env: buildChildEnv(sessionId),\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n ...(isWin ? {} : { signal }),\n ...(shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {}),\n });\n } catch (err) {\n // spawn() can throw synchronously — e.g. ERR_INVALID_ARG_TYPE for a\n // malformed `signal`, or for some Node versions ENOENT when the binary\n // isn't on PATH. Convert to a graceful result so the tool caller\n // sees a structured error instead of an unhandled rejection that\n // would crash the host.\n spool.finalize();\n finish({\n command: cmd,\n args,\n stdout: '',\n stderr: `spawn failed: ${toErrorMessage(err)}`,\n exitCode: 1,\n truncated: false,\n allowed: true,\n danger,\n });\n return;\n }\n\n // Attach the 'error' listener IMMEDIATELY after spawn, BEFORE any other\n // async setup (process registry call, setTimeout, abort listener). The\n // Node EventEmitter contract is that an 'error' event with no listener\n // rethrows on nextTick and crashes the entire process — this is the\n // exact failure mode issue #99 describes. Attach first, then do the\n // bookkeeping, so an abort / ENOENT / EPIPE that fires between spawn\n // and the rest of setup still has a listener attached.\n child.on('error', (err) => {\n // Distinguish an abort from a true spawn failure so the caller can\n // tell \"the user cancelled this\" apart from \"the binary is missing\".\n // The signal passed to spawn() is an AbortSignal; Node internally\n // converts the abort into an AbortError with `code: 'ABORT_ERR'`.\n const isAbort = err && (err as NodeJS.ErrnoException).code === 'ABORT_ERR';\n const stderrText = isAbort ? `Aborted: ${err.message}` : err.message;\n clearTimeout(timer);\n if (isWin) signal.removeEventListener('abort', onAbort);\n if (typeof pid === 'number') registry.unregister(pid);\n registry.afterCall(Date.now() - startedAt, true);\n spool.finalize();\n finish({\n command: cmd,\n args,\n stdout: normalizeCommandOutput(stdout),\n stderr: stderrText,\n exitCode: isAbort ? 124 : 1,\n truncated: Buffer.byteLength(stdout, 'utf8') > COMMAND_OUTPUT_MAX_BYTES,\n allowed: true,\n danger,\n });\n });\n\n const registry = getProcessRegistry();\n const pid = child.pid;\n if (typeof pid === 'number') {\n const fullCommand = `${cmd} ${args.join(' ')}`;\n registry.register({ pid, name: 'exec', command: redactCommand(fullCommand), startedAt: Date.now(), sessionId, child });\n }\n\n const timer = setTimeout(() => {\n killed = true;\n if (typeof pid === 'number') registry.kill(pid);\n else child.kill('SIGTERM');\n }, timeout);\n\n const onAbort = () => {\n killed = true;\n if (typeof pid === 'number') registry.kill(pid, { force: true });\n else child.kill('SIGTERM');\n };\n if (isWin) {\n if (signal.aborted) onAbort();\n else signal.addEventListener('abort', onAbort, { once: true });\n }\n\n child.stdout?.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n if (stdout.length < MAX_OUTPUT) stdout += text;\n spool.write(text);\n });\n\n child.stderr?.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n if (stderr.length < MAX_OUTPUT) stderr += text;\n spool.write(text);\n });\n\n child.on('close', (code) => {\n clearTimeout(timer);\n if (isWin) signal.removeEventListener('abort', onAbort);\n if (typeof pid === 'number') registry.unregister(pid);\n const durationMs = Date.now() - startedAt;\n const exitCode = killed ? 124 : (code ?? 1);\n registry.afterCall(durationMs, exitCode !== 0);\n const spooled = spool.finalize();\n finish({\n command: cmd,\n args,\n stdout: normalizeCommandOutput(stdout) + (spooled ? spoolNote(spooled) : ''),\n stderr: normalizeCommandOutput(stderr),\n exitCode,\n truncated:\n Buffer.byteLength(stdout, 'utf8') > COMMAND_OUTPUT_MAX_BYTES ||\n Buffer.byteLength(stderr, 'utf8') > COMMAND_OUTPUT_MAX_BYTES,\n allowed: true,\n danger,\n });\n });\n });\n}\n"]}