ssrwire 0.1.0 → 0.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stability.js","sourceRoot":"","sources":["../src/stability.ts"],"names":[],"mappings":"AAYA,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAC7D,MAAM,gBAAgB,GAAG;IACvB,CAAC,OAAO,EAAE,SAAS,CAAC;IACpB,CAAC,QAAQ,EAAE,UAAU,CAAC;IACtB,CAAC,SAAS,EAAE,WAAW,CAAC;IACxB,CAAC,SAAS,EAAE,WAAW,CAAC;IACxB,CAAC,WAAW,EAAE,aAAa,CAAC;IAC5B,CAAC,YAAY,EAAE,cAAc,CAAC;CACtB,CAAC;AAOX,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,OAAgB;IACnD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC7E,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;QACd,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa,EAAE,OAAe;IACxD,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,sBAAsB,CAC7B,OAAiC,EACjC,YAAuC,aAAa;IAEpD,OAAO;QACL,GAAG,IAAI,GAAG,CACR,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CACrF;KACF,CAAC,IAAI,EAAE,CAAC;AACX,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAmB;IACjD,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IACzD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAkB;IAChD,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IACtF,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAC1C,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC;AAChG,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAgC;IAC7D,MAAM,UAAU,GAAG,IAAI,GAAG,CACxB,OAAO;SACJ,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;SAC5E,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;SACpC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAC/C,CAAC;IACF,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1B,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxB,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IACD,KAAK,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,gBAAgB,EAAE,CAAC;QACzD,IAAI,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC;AACzD,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAkB;IAC9C,OAAO,qBAAqB,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,oBAAoB,CAC3B,OAAiC,EACjC,YAAuC,aAAa;IAEpD,MAAM,OAAO,GAAG,OAAO;SACpB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAU,CAAC;SACpE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACvF,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,EAAE;QACzD,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACvD,OAAO,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACnF,CAAC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAkB;IAC9C,MAAM,OAAO,GAAG,sBAAsB,CAAC,KAAK,CAAC;SAC1C,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAU,CAAC;SAC5E,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACvF,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAC3E,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAkB;IAChD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,KAAK,EAAE,sBAAsB,CAAC,MAAM,CAAC;QACrC,WAAW,EAAE,sBAAsB,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;QAC/D,SAAS,EAAE,sBAAsB,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CACpE,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAC1C;QACD,MAAM,EAAE,oBAAoB,CAAC,KAAK,CAAC;KACpC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAkB;IACnD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,KAAK,EAAE,oBAAoB,CAAC,MAAM,CAAC;QACnC,WAAW,EAAE,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;QAC7D,SAAS,EAAE,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAClE,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAC1C;QACD,MAAM,EAAE,oBAAoB,CAAC,KAAK,CAAC;KACpC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAkB;IAChD,OAAO,IAAI,CAAC,SAAS,CACnB,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACjC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,GAAG,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC/B,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC;KACxD,CAAC,CAAC,CACJ,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,MAAyB;IAC5C,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAyB;IAC5D,MAAM,MAAM,GAAG,MAAM;SAClB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;SACvD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE1C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,QAAQ,GACZ,MAAM,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;QACnE,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;QACrB,CAAC,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC;IAEjD,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,MAAM;QACtB,KAAK;QACL,QAAQ;QACR,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK;QAChC,KAAK;QACL,QAAQ,EAAE,KAAK,GAAG,KAAK;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,OAAiC;IACtD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,MAAmB,EACnB,KAAkB;IAElB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAChC,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,MAAM,WAAW,GAAG,CAAC,MAAiC,EAAW,EAAE;QACjE,QAAQ,IAAI,CAAC,CAAC;QACd,IAAI,MAAM,KAAK,SAAS,IAAI,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACnF,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,IAAI,YAAY,CAAC,YAAY,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACrF,IAAI,YAAY,CAAC,kBAAkB,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QAC/F,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,YAAY,CAAC,gBAAgB,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAC7C,CAAC,MAAM,EAAE,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CACxE,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAChD,CAAC;IACD,IAAI,YAAY,CAAC,SAAS,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/F,IAAI,YAAY,CAAC,eAAe,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC;QAAE,OAAO,SAAS,CAAC;IAEhG,OAAO,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,QAAQ,CACf,MAAyB,EACzB,GAA6D,EAC7D,MAAmC;IAEnC,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAC/C,CAAC;AAED,SAAS,cAAc,CAAC,MAAmB,EAAE,MAA8B;IACzE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;IAC/B,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IAC3E,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAClC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAC9E,CAAC;IACF,MAAM,OAAO,GAAgC,EAAE,CAAC;IAEhD,QAAQ,CACN,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EACtD,SAAS,EACT,OAAO,CACR,CAAC;IACF,QAAQ,CACN,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACvB,KAAK,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAC3E,EACD,WAAW,EACX,OAAO,CACR,CAAC;IACF,QAAQ,CACN,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACzB,MAAM,KAAK,GAAG,wBAAwB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACtD,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC,CAAC,EACF,iBAAiB,EACjB,OAAO,CACR,CAAC;IACF,QAAQ,CACN,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACzB,KAAK,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CACzE,EACD,UAAU,EACV,OAAO,CACR,CAAC;IAEF,OAAO;QACL,KAAK;QACL,OAAO,EAAE,MAAM,CAAC,MAAM;QACtB,QAAQ,EAAE,QAAQ,CAAC,MAAM;QACzB,UAAU,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM;QAC3C,OAAO;QACP,QAAQ,EAAE;YACR,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAChE,MAAM,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YACxE,QAAQ,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClF,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YAC9D,UAAU,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,IAAI,WAAW,CAAC,CAAC;YACjF,cAAc,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACjE,iBAAiB,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;SACxE;KACF,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CACd,MAAmB,EACnB,OAAuB,EACvB,IAAmD,EACnD,QAA4B,EAC5B,MAAyB;IAEzB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,OAAO;QACL,IAAI;QACJ,QAAQ;QACR,OAAO,EACL,IAAI,KAAK,sBAAsB;YAC7B,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,+DAA+D;YACvF,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,+DAA+D;QAC3F,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG;QACxB,QAAQ,EAAE;YACR,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,eAAe,EAAE,OAAO,CAAC,QAAQ;YACjC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;YACzB,aAAa,EAAE,MAAM;iBAClB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,QAAQ,CAAC,KAA8B,CAAC,EAAE,CAAC;iBACtE,IAAI,CAAC,IAAI,CAAC;SACd;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,MAAmB,EAAE,OAAuB;IAC/D,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,cAAc,GAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,CAAW,CAAC,MAAM,CAC5F,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CACvC,CAAC;IACF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,YAAY,GAAI,CAAC,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,CAAW,CAAC,MAAM,CAC1F,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CACvC,CAAC;IACF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,eAAe,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC;QAC7E,QAAQ,CAAC,IAAI,CACX,OAAO,CACL,MAAM,EACN,OAAO,EACP,oBAAoB,EACpB,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EACpC,YAAY,CACb,CACF,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAAmB,EACnB,MAA8B;IAE9B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;IAChD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,SAAS,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACrF,OAAO;QACL,SAAS;QACT,QAAQ,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACvE,CAAC;AACJ,CAAC"}
package/dist/types.d.ts CHANGED
@@ -78,6 +78,8 @@ export interface ProbeResult {
78
78
  readonly signals: DocumentSignals;
79
79
  readonly completion: ProbeCompletion;
80
80
  readonly error?: string;
81
+ /** One-based audit sample number. Low-level probeUrl() calls leave this unset. */
82
+ readonly sample?: number;
81
83
  }
82
84
  export interface TargetExpectations {
83
85
  readonly statuses: readonly number[];
@@ -101,6 +103,39 @@ export interface SsrWireConfig {
101
103
  readonly timeoutMs: number;
102
104
  readonly maxBytes: number;
103
105
  readonly maxRedirects: number;
106
+ /** Total samples per target and agent. Defaults to one for programmatic callers. */
107
+ readonly repeat?: number;
108
+ }
109
+ export interface TimingStats {
110
+ readonly samples: number;
111
+ readonly minMs: number;
112
+ readonly medianMs: number;
113
+ readonly p95Ms: number;
114
+ readonly maxMs: number;
115
+ readonly spreadMs: number;
116
+ }
117
+ export interface StabilityTimings {
118
+ readonly headers?: TimingStats;
119
+ readonly firstByte?: TimingStats;
120
+ readonly criticalSignals?: TimingStats;
121
+ readonly complete?: TimingStats;
122
+ }
123
+ export interface StabilityVariants {
124
+ readonly completion: number;
125
+ readonly status: number;
126
+ readonly finalUrl: number;
127
+ readonly redirectChain: number;
128
+ readonly bodySha256: number;
129
+ readonly metadataValues: number;
130
+ readonly metadataLocations: number;
131
+ }
132
+ export interface AgentStability {
133
+ readonly agent: AgentProfile;
134
+ readonly samples: number;
135
+ readonly complete: number;
136
+ readonly incomplete: number;
137
+ readonly timings: StabilityTimings;
138
+ readonly variants: StabilityVariants;
104
139
  }
105
140
  export interface Finding {
106
141
  readonly code: string;
@@ -114,6 +149,7 @@ export interface TargetAuditResult {
114
149
  readonly target: AuditTarget;
115
150
  readonly probes: readonly ProbeResult[];
116
151
  readonly findings: readonly Finding[];
152
+ readonly stability?: readonly AgentStability[];
117
153
  }
118
154
  export interface AuditSummary {
119
155
  readonly targets: number;
@@ -127,6 +163,7 @@ export interface AuditResult {
127
163
  readonly version: string;
128
164
  readonly generatedAt: string;
129
165
  readonly durationMs: number;
166
+ readonly repeat?: number;
130
167
  readonly results: readonly TargetAuditResult[];
131
168
  readonly summary: AuditSummary;
132
169
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -27,7 +27,7 @@ jobs:
27
27
  if: github.event_name == 'pull_request'
28
28
  continue-on-error: true
29
29
  run: >-
30
- npx --yes ssrwire@0.1.0 check
30
+ npx --yes ssrwire@0.2.0 check
31
31
  --config ssrwire.config.yml
32
32
  --format sarif
33
33
  --output reports/ssrwire.sarif
@@ -38,7 +38,7 @@ jobs:
38
38
  if: github.event_name != 'pull_request'
39
39
  continue-on-error: true
40
40
  run: >-
41
- npx --yes ssrwire@0.1.0 check
41
+ npx --yes ssrwire@0.2.0 check
42
42
  --config ssrwire.config.yml
43
43
  --format sarif
44
44
  --output reports/ssrwire.sarif
@@ -32,6 +32,10 @@ timeoutMs: 15000
32
32
  maxBytes: 10485760
33
33
  maxRedirects: 10
34
34
 
35
+ # Run each target-agent pair sequentially three times to expose intermittent SSR output.
36
+ # Total requests are targets × agents × repeat, plus redirects.
37
+ repeat: 3
38
+
35
39
  # Keep preview credentials in a CI secret or exported environment variable.
36
40
  # headers:
37
41
  # x-preview-token: "${PREVIEW_TOKEN}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ssrwire",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Inspect streamed SSR HTML, metadata timing, and crawler-specific delivery from the command line.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/audit.ts CHANGED
@@ -1,7 +1,15 @@
1
1
  import { analyzeTarget, summarizeAudit } from "./analyze.js";
2
2
  import { probeUrl } from "./http-probe.js";
3
3
  import { redactAudit } from "./redact.js";
4
- import type { AuditResult, ProbeOptions, SsrWireConfig, TargetAuditResult } from "./types.js";
4
+ import { analyzeStability } from "./stability.js";
5
+ import type {
6
+ AuditResult,
7
+ Finding,
8
+ ProbeOptions,
9
+ ProbeResult,
10
+ SsrWireConfig,
11
+ TargetAuditResult,
12
+ } from "./types.js";
5
13
  import { VERSION } from "./version.js";
6
14
 
7
15
  const DEFAULT_CONCURRENCY = 4;
@@ -12,6 +20,16 @@ interface ProbeTask {
12
20
  readonly options: ProbeOptions;
13
21
  }
14
22
 
23
+ interface ProbeLane {
24
+ readonly task: ProbeTask;
25
+ readonly probes: readonly ProbeResult[];
26
+ }
27
+
28
+ interface SampleFinding {
29
+ readonly sample: number;
30
+ readonly finding: Finding;
31
+ }
32
+
15
33
  async function runPool<T, R>(
16
34
  inputs: readonly T[],
17
35
  limit: number,
@@ -37,8 +55,75 @@ async function runPool<T, R>(
37
55
  return results;
38
56
  }
39
57
 
58
+ function repeatCount(value: number | undefined): number {
59
+ const repeat = value ?? 1;
60
+ if (!Number.isInteger(repeat) || repeat < 1 || repeat > 10) {
61
+ throw new RangeError("repeat must be an integer between 1 and 10.");
62
+ }
63
+ return repeat;
64
+ }
65
+
66
+ function mergeEvidence(
67
+ sampled: readonly SampleFinding[],
68
+ repeat: number,
69
+ ): Readonly<Record<string, string | number | boolean>> {
70
+ const merged: Record<string, string | number | boolean> & {
71
+ occurrences?: number;
72
+ sampleNumbers?: string;
73
+ totalSamples?: number;
74
+ } = {};
75
+ const keys = [
76
+ ...new Set(sampled.flatMap(({ finding }) => Object.keys(finding.evidence ?? {}))),
77
+ ].sort();
78
+
79
+ for (const key of keys) {
80
+ const values = sampled.flatMap(({ finding }) => {
81
+ const value = finding.evidence?.[key];
82
+ return value === undefined ? [] : [value];
83
+ });
84
+ const unique = [
85
+ ...new Map(values.map((value) => [`${typeof value}:${String(value)}`, value])).values(),
86
+ ];
87
+ const first = unique[0];
88
+ if (first !== undefined) {
89
+ merged[key] = unique.length === 1 ? first : unique.map(String).join(" | ");
90
+ }
91
+ }
92
+
93
+ merged.sampleNumbers = [...new Set(sampled.map((item) => item.sample))]
94
+ .sort((a, b) => a - b)
95
+ .join(", ");
96
+ merged.occurrences = sampled.length;
97
+ merged.totalSamples = repeat;
98
+ return merged;
99
+ }
100
+
101
+ function coalesceFindings(sampled: readonly SampleFinding[], repeat: number): readonly Finding[] {
102
+ const groups = new Map<string, SampleFinding[]>();
103
+ for (const item of sampled) {
104
+ const { finding } = item;
105
+ const key = JSON.stringify([
106
+ finding.code,
107
+ finding.severity,
108
+ finding.message,
109
+ finding.url,
110
+ finding.agent ?? "",
111
+ ]);
112
+ const group = groups.get(key) ?? [];
113
+ group.push(item);
114
+ groups.set(key, group);
115
+ }
116
+
117
+ return [...groups.values()].map((group) => {
118
+ const first = group[0]?.finding;
119
+ if (first === undefined) throw new Error("Cannot coalesce an empty finding group.");
120
+ return { ...first, evidence: mergeEvidence(group, repeat) };
121
+ });
122
+ }
123
+
40
124
  export async function runAudit(config: SsrWireConfig): Promise<AuditResult> {
41
125
  const started = performance.now();
126
+ const repeat = repeatCount(config.repeat);
42
127
  const tasks: ProbeTask[] = [];
43
128
 
44
129
  for (const [targetIndex, target] of config.targets.entries()) {
@@ -60,21 +145,43 @@ export async function runAudit(config: SsrWireConfig): Promise<AuditResult> {
60
145
  }
61
146
 
62
147
  const secrets = Object.values(config.headers);
63
- const probes = await runPool(tasks, DEFAULT_CONCURRENCY, async (task) => {
64
- const probe = await probeUrl(task.options);
65
- return { task, probe };
148
+ const lanes = await runPool<ProbeTask, ProbeLane>(tasks, DEFAULT_CONCURRENCY, async (task) => {
149
+ const probes: ProbeResult[] = [];
150
+ for (let sample = 1; sample <= repeat; sample += 1) {
151
+ const probe = await probeUrl(task.options);
152
+ probes.push(repeat === 1 ? probe : { ...probe, sample });
153
+ }
154
+ return { task, probes };
66
155
  });
67
156
 
68
157
  const results: TargetAuditResult[] = config.targets.map((target, targetIndex) => {
69
- const targetProbes = probes
70
- .filter((item) => item.task.targetIndex === targetIndex)
158
+ const targetProbes = lanes
159
+ .filter((lane) => lane.task.targetIndex === targetIndex)
71
160
  .sort((a, b) => a.task.agentIndex - b.task.agentIndex)
72
- .map((item) => item.probe);
161
+ .flatMap((lane) => lane.probes);
162
+
163
+ if (repeat === 1) {
164
+ return {
165
+ target,
166
+ probes: targetProbes,
167
+ findings: analyzeTarget(target, targetProbes),
168
+ };
169
+ }
170
+
171
+ const sampledFindings: SampleFinding[] = [];
172
+ for (let sample = 1; sample <= repeat; sample += 1) {
173
+ const sampleProbes = targetProbes.filter((probe) => probe.sample === sample);
174
+ sampledFindings.push(
175
+ ...analyzeTarget(target, sampleProbes).map((finding) => ({ sample, finding })),
176
+ );
177
+ }
178
+ const stability = analyzeStability(target, targetProbes);
73
179
 
74
180
  return {
75
181
  target,
76
182
  probes: targetProbes,
77
- findings: analyzeTarget(target, targetProbes),
183
+ findings: [...coalesceFindings(sampledFindings, repeat), ...stability.findings],
184
+ stability: stability.stability,
78
185
  };
79
186
  });
80
187
 
@@ -82,6 +189,7 @@ export async function runAudit(config: SsrWireConfig): Promise<AuditResult> {
82
189
  version: VERSION,
83
190
  generatedAt: new Date().toISOString(),
84
191
  durationMs: Math.round(performance.now() - started),
192
+ ...(repeat === 1 ? {} : { repeat }),
85
193
  results,
86
194
  summary: summarizeAudit(results),
87
195
  };
package/src/cli.ts CHANGED
@@ -14,6 +14,7 @@ interface CliOptions {
14
14
  readonly timeout?: number;
15
15
  readonly maxBytes?: number;
16
16
  readonly maxRedirects?: number;
17
+ readonly repeat?: number;
17
18
  readonly format: ReportFormat;
18
19
  readonly output?: string;
19
20
  readonly failOn: "error" | "warning" | "never";
@@ -40,6 +41,7 @@ agents:
40
41
  timeoutMs: 15000
41
42
  maxBytes: 10485760
42
43
  maxRedirects: 10
44
+ repeat: 1
43
45
 
44
46
  # Keep preview credentials in environment variables. SSRWire redacts configured values from reports.
45
47
  # headers:
@@ -80,6 +82,7 @@ function addCheckOptions(command: Command): Command {
80
82
  .option("--timeout <ms>", "request timeout in milliseconds", parseInteger)
81
83
  .option("--max-bytes <bytes>", "maximum response bytes", parseInteger)
82
84
  .option("--max-redirects <count>", "maximum redirects", parseInteger)
85
+ .option("--repeat <count>", "sequential samples per URL and agent", parseInteger)
83
86
  .option("-f, --format <format>", "terminal, json, or sarif", parseFormat, "terminal")
84
87
  .option("-o, --output <path>", "write the report to a file")
85
88
  .option("--fail-on <level>", "error, warning, or never", parseFailOn, "error")
@@ -124,6 +127,7 @@ async function check(urls: readonly string[], options: CliOptions): Promise<void
124
127
  ...(options.timeout === undefined ? {} : { timeoutMs: options.timeout }),
125
128
  ...(options.maxBytes === undefined ? {} : { maxBytes: options.maxBytes }),
126
129
  ...(options.maxRedirects === undefined ? {} : { maxRedirects: options.maxRedirects }),
130
+ ...(options.repeat === undefined ? {} : { repeat: options.repeat }),
127
131
  });
128
132
  const audit = await runAudit(config);
129
133
  const color =
package/src/config.ts CHANGED
@@ -8,6 +8,7 @@ import type { AgentProfile, AuditTarget, SsrWireConfig, TargetExpectations } fro
8
8
  const DEFAULT_TIMEOUT_MS = 15_000;
9
9
  const DEFAULT_MAX_BYTES = 10 * 1024 * 1024;
10
10
  const DEFAULT_MAX_REDIRECTS = 10;
11
+ const DEFAULT_REPEAT = 1;
11
12
  const DEFAULT_AGENTS = ["browser", "googlebot", "bingbot", "twitterbot"] as const;
12
13
  const DEFAULT_CONFIG_FILES = [
13
14
  "ssrwire.config.yml",
@@ -66,6 +67,7 @@ const fileConfigSchema = z
66
67
  .max(50 * 1024 * 1024)
67
68
  .optional(),
68
69
  maxRedirects: z.number().int().min(0).max(20).optional(),
70
+ repeat: z.number().int().min(1).max(10).optional(),
69
71
  })
70
72
  .strict();
71
73
 
@@ -79,6 +81,7 @@ export interface LoadConfigOptions {
79
81
  readonly timeoutMs?: number;
80
82
  readonly maxBytes?: number;
81
83
  readonly maxRedirects?: number;
84
+ readonly repeat?: number;
82
85
  readonly cwd?: string;
83
86
  }
84
87
 
@@ -291,6 +294,7 @@ export async function loadConfig(options: LoadConfigOptions = {}): Promise<SsrWi
291
294
  const timeoutMs = options.timeoutMs ?? file.timeoutMs ?? DEFAULT_TIMEOUT_MS;
292
295
  const maxBytes = options.maxBytes ?? file.maxBytes ?? DEFAULT_MAX_BYTES;
293
296
  const maxRedirects = options.maxRedirects ?? file.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
297
+ const repeat = options.repeat ?? file.repeat ?? DEFAULT_REPEAT;
294
298
 
295
299
  if (!Number.isInteger(timeoutMs) || timeoutMs < 100 || timeoutMs > 120_000) {
296
300
  throw new ConfigError("timeoutMs must be an integer between 100 and 120000.");
@@ -301,6 +305,9 @@ export async function loadConfig(options: LoadConfigOptions = {}): Promise<SsrWi
301
305
  if (!Number.isInteger(maxRedirects) || maxRedirects < 0 || maxRedirects > 20) {
302
306
  throw new ConfigError("maxRedirects must be an integer between 0 and 20.");
303
307
  }
308
+ if (!Number.isInteger(repeat) || repeat < 1 || repeat > 10) {
309
+ throw new ConfigError("repeat must be an integer between 1 and 10.");
310
+ }
304
311
 
305
312
  return {
306
313
  targets,
@@ -309,5 +316,6 @@ export async function loadConfig(options: LoadConfigOptions = {}): Promise<SsrWi
309
316
  timeoutMs,
310
317
  maxBytes,
311
318
  maxRedirects,
319
+ repeat,
312
320
  };
313
321
  }
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export { renderJson, renderReport, renderSarif, renderTerminal } from "./reporte
8
8
  export { createStreamInspector } from "./stream-parser.js";
9
9
  export type {
10
10
  AgentProfile,
11
+ AgentStability,
11
12
  AuditResult,
12
13
  AuditSummary,
13
14
  AuditTarget,
@@ -27,8 +28,11 @@ export type {
27
28
  RobotsSignal,
28
29
  Severity,
29
30
  SsrWireConfig,
31
+ StabilityTimings,
32
+ StabilityVariants,
30
33
  TargetAuditResult,
31
34
  TargetExpectations,
32
35
  TimingMark,
36
+ TimingStats,
33
37
  } from "./types.js";
34
38
  export { VERSION } from "./version.js";
package/src/redact.ts CHANGED
@@ -160,6 +160,18 @@ export function redactAudit(audit: AuditResult, secrets: readonly string[]): Aud
160
160
  },
161
161
  },
162
162
  probes: result.probes.map((probe) => redactProbeWithPlan(probe, plan)),
163
+ ...(result.stability === undefined
164
+ ? {}
165
+ : {
166
+ stability: result.stability.map((summary) => ({
167
+ ...summary,
168
+ agent: {
169
+ ...summary.agent,
170
+ label: redactText(summary.agent.label, plan),
171
+ userAgent: redactText(summary.agent.userAgent, plan),
172
+ },
173
+ })),
174
+ }),
163
175
  findings: result.findings.map((finding) => ({
164
176
  ...finding,
165
177
  message: redactText(finding.message, plan),
package/src/reporters.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type {
2
+ AgentStability,
2
3
  AuditResult,
3
4
  ElementSignal,
4
5
  Finding,
@@ -70,8 +71,9 @@ function firstSignal(signals: readonly ElementSignal[]): ElementSignal | undefin
70
71
  return signals.find((signal) => signal.value.trim().length > 0) ?? signals[0];
71
72
  }
72
73
 
73
- function probeRow(probe: ProbeResult): readonly string[] {
74
+ function probeRow(probe: ProbeResult, showSample: boolean): readonly string[] {
74
75
  return [
76
+ ...(showSample ? [String(probe.sample ?? "—")] : []),
75
77
  truncate(probe.agent.label, 24),
76
78
  probe.status === undefined ? "—" : String(probe.status),
77
79
  probe.completion,
@@ -84,6 +86,34 @@ function probeRow(probe: ProbeResult): readonly string[] {
84
86
  ];
85
87
  }
86
88
 
89
+ function stabilityRows(stability: readonly AgentStability[]): readonly (readonly string[])[] {
90
+ const labels: Readonly<Record<keyof AgentStability["timings"], string>> = {
91
+ headers: "Headers",
92
+ firstByte: "First byte",
93
+ criticalSignals: "Critical signals",
94
+ complete: "Complete",
95
+ };
96
+ const rows: string[][] = [];
97
+ for (const summary of stability) {
98
+ for (const key of ["headers", "firstByte", "criticalSignals", "complete"] as const) {
99
+ const stats = summary.timings[key];
100
+ if (stats === undefined) continue;
101
+ rows.push([
102
+ truncate(summary.agent.label, 24),
103
+ `${summary.complete}/${summary.samples}`,
104
+ labels[key],
105
+ String(stats.samples),
106
+ formatMs(stats.minMs),
107
+ formatMs(stats.medianMs),
108
+ formatMs(stats.p95Ms),
109
+ formatMs(stats.maxMs),
110
+ formatMs(stats.spreadMs),
111
+ ]);
112
+ }
113
+ }
114
+ return rows;
115
+ }
116
+
87
117
  function renderTable(headers: readonly string[], rows: readonly (readonly string[])[]): string {
88
118
  const widths = headers.map((header, column) =>
89
119
  Math.max(header.length, ...rows.map((row) => row[column]?.length ?? 0)),
@@ -116,12 +146,17 @@ export function renderTerminal(audit: AuditResult, options: ReporterOptions = {}
116
146
  paint(`SSRWire ${audit.version}`, ANSI.bold, color),
117
147
  paint(`Generated ${audit.generatedAt} in ${formatMs(audit.durationMs)}`, ANSI.dim, color),
118
148
  ];
149
+ if ((audit.repeat ?? 1) > 1) {
150
+ lines.push(paint(`${audit.repeat} sequential samples per URL and agent`, ANSI.dim, color));
151
+ }
119
152
 
120
153
  for (const result of audit.results) {
154
+ const showSample = (audit.repeat ?? 1) > 1;
121
155
  lines.push("", paint(terminalSafe(result.target.url), ANSI.bold, color));
122
156
  lines.push(
123
157
  renderTable(
124
158
  [
159
+ ...(showSample ? ["Sample"] : []),
125
160
  "Agent",
126
161
  "HTTP",
127
162
  "Result",
@@ -132,10 +167,24 @@ export function renderTerminal(audit: AuditResult, options: ReporterOptions = {}
132
167
  "Canonical",
133
168
  "Main",
134
169
  ],
135
- result.probes.map(probeRow),
170
+ result.probes.map((probe) => probeRow(probe, showSample)),
136
171
  ),
137
172
  );
138
173
 
174
+ if (result.stability !== undefined) {
175
+ const rows = stabilityRows(result.stability);
176
+ if (rows.length > 0) {
177
+ lines.push(
178
+ "",
179
+ "Stability timings (nearest-rank p95)",
180
+ renderTable(
181
+ ["Agent", "Complete", "Metric", "N", "Min", "Median", "P95", "Max", "Spread"],
182
+ rows,
183
+ ),
184
+ );
185
+ }
186
+ }
187
+
139
188
  if (result.findings.length === 0) {
140
189
  lines.push("Findings: none");
141
190
  } else {