ostia 0.2.6 → 0.2.8

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/cli.js CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{e,g,t,b,R,r,I,w,c,k,J,u,x,s,l,d}from"./chunk-8m8jb8gw.js";import{m,q,K,F,P,E,o,Y,A,ne,B,Z,X,W,v,p,i,Q}from"./chunk-85cap0sk.js";import{resolve as Be}from"path";function be(a){return e("cache",a.workloadId,a.phase,a.configFingerprint,a.bunVersion,a.toolVersion,a.instrumented,a.inputsDigest??null)}async function we(a,n=process.cwd()){if(a.length===0)return;let f=await A(a,n),h=await Promise.all(f.map(async(y)=>{let C=await Bun.file(Be(n,y)).arrayBuffer();return{path:y,sha256:Bun.CryptoHasher.hash("sha256",C,"hex")}}));return e("inputs",h)}function ke(a,n){return`${a}/cache/${n}.json`}async function ve(a,n){let f=Bun.file(ke(a,n));if(!await f.exists())return;return await f.json()}async function ye(a,n,f){await Bun.write(ke(a,n),`${JSON.stringify(f,null,2)}
4
- `)}var Ce=600000;class ce extends Error{path;constructor(a){super(`No baseline document at ${a}. Create one with: ostia baseline save ${a.split("/").pop().replace(/\.json$/,"")}`);this.path=a}}class ue extends Error{path;missing;total;constructor(a,n,f){super(`${n} of ${f} configured workload(s) have no matching row in baseline ${a} (by workload id). Re-seed with: ostia baseline save`);this.path=a;this.missing=n;this.total=f}}function _e(a,n,f){if(a)return a;return n===f?"fail":"warn"}async function pe(a,n){let f=a.noiseCheck===!1?void 0:l(),h=f?d(f):void 0,y=[];for(let C of a.workloads){if(C.suites){let _=await X(C.suites,process.cwd()),te=await W({suites:_,preload:[],bunFlags:[],noiseCheck:!1},a.bench),ee=await v({...te,outDir:te.outDir??a.outDir,timeoutMs:te.timeoutMs??Ce});for(let z of ee.workloads){let j=ee.measurements.find((oe)=>oe.workloadId===z.id&&oe.phase==="timing");if(!j)continue;if(h)j.warnings.push(h);y.push({workload:z,status:"executed",run:j,harnessFailed:!1})}continue}let D=I(C.command,C.label,{prepare:C.prepare,timeSource:C.timeSource}),M=await we(C.inputs??[]),S=c({samples:a.samples??null,budgetMs:a.budgetMs??null,minSamples:a.minSamples??null,warmup:a.warmup}),G=C.inputs!==void 0&&typeof C.prepare!=="function",L=be({workloadId:D.id,phase:"timing",configFingerprint:S,bunVersion:Bun.version,toolVersion:R,instrumented:!1,inputsDigest:M}),U=n||!G?void 0:await ve(a.outDir,L),O,T;if(U)O=U,T="cached";else{let _=await ne({argv:C.command,samples:a.samples,budgetMs:a.budgetMs,minSamples:a.minSamples,warmup:a.warmup,prepare:C.prepare,timeSource:C.timeSource,timeoutMs:C.timeoutMs??Ce,ignoreExitCodes:C.ignoreExitCodes});if(O=w({workload:D,configFingerprint:S,trials:_.trials,timing:_.timing,warnings:h?[..._.warnings,h]:_.warnings}),G)await ye(a.outDir,L,O);T="executed"}y.push({workload:D,status:T,run:O,harnessFailed:B(O,C.ignoreExitCodes)})}return{results:y,environment:f}}async function xe(a){let{config:n}=a,f=o(n,a.baselineName);if(!await Bun.file(f).exists())throw new ce(f);let y=await s(f),{results:C,environment:D}=await pe(n,a.full),M=C.map((j)=>({...j})),S=M.filter((j)=>j.status==="executed").length,G=M.length-S,L=M.filter((j)=>j.harnessFailed).length,U=r(M.map((j)=>j.workload),M.map((j)=>j.run),D),O=0,T=0,_=0,te=q(y,U,n.thresholds);for(let j of M){let oe=te.compare(j.workload.id);if(!oe){_++;continue}if(j.comparison=oe,oe.verdict==="pass")O++;else T++}if(_>0){if(_e(n.onMissingBaseline,_,M.length)==="fail")throw new ue(f,_,M.length)}let ee=M.map((j)=>j.comparison).filter((j)=>j!==void 0);U.comparisons=ee;let z=te.unmatched();return U.unmatched={baseOnly:z.baseOnly.map((j)=>j.id),candOnly:z.candOnly.map((j)=>j.id)},U.comparisonSummary=K(ee,te.effectiveTimingPct),{document:U,summary:{total:M.length,cached:G,executed:S,passed:O,regressed:T,missingBaseline:_,failed:L,results:M,unmatched:z},baseline:y}}function Pe(a){let n=[];if(n.push(`${a.total} workloads`),n.push(`${a.cached} cached`),n.push(`${a.executed} executed`),a.missingBaseline>0)n.push(`${a.missingBaseline} skipped (no matching baseline workload)`);if(a.failed>0){let h=a.results.filter((y)=>y.harnessFailed).map((y)=>t(y.workload));n.push(`${a.failed} failed (harness error, a command exited non-zero or produced no samples: ${h.join(", ")})`)}let f=a.results.filter((h)=>h.comparison?.verdict==="fail").map((h)=>{let y=h.comparison.timing,C=t(h.workload);return y?`${y.medianDeltaPct>0?"+":""}${y.medianDeltaPct.toFixed(1)}% median on ${C}`:C});return n.push(`${a.passed} passed ${a.regressed} regressed${f.length>0?` (${f.join(", ")})`:""}`),n.push(""),n.push(`Profile CI: ${a.regressed>0||a.failed>0?"\u2717":"\u2713"}`),`${n.join(`
3
+ import{e,w,t,y,N,r,B,x,i,P,Z,l,M,s,a,c}from"./chunk-17t12ta6.js";import{d,ne,te,L,T,E,u,re,R,j,H,ae,G,se,F,V,S,f,m,oe}from"./chunk-p3342c5c.js";import{resolve as Ue}from"path";function ve(o){return e("cache",o.workloadId,o.phase,o.configFingerprint,o.bunVersion,o.toolVersion,o.instrumented,o.inputsDigest??null)}async function ye(o,n=process.cwd()){if(o.length===0)return;let p=await H(o,n),h=await Promise.all(p.map(async(g)=>{let b=await Bun.file(Ue(n,g)).arrayBuffer();return{path:g,sha256:Bun.CryptoHasher.hash("sha256",b,"hex")}}));return e("inputs",h)}function Ce(o,n){return`${o}/cache/${n}.json`}async function xe(o,n){let p=Bun.file(Ce(o,n));if(!await p.exists())return;return await p.json()}async function Pe(o,n,p){await Bun.write(Ce(o,n),`${JSON.stringify(p,null,2)}
4
+ `)}var $e=600000;class me extends Error{path;constructor(o){super(`No baseline document at ${o}. Create one with: ostia baseline save ${o.split("/").pop().replace(/\.json$/,"")}`);this.path=o}}class de extends Error{path;missing;total;constructor(o,n,p){super(`${n} of ${p} configured workload(s) have no matching row in baseline ${o} (by workload id). Re-seed with: ostia baseline save`);this.path=o;this.missing=n;this.total=p}}function qe(o,n,p){if(o)return o;return n===p?"fail":"warn"}async function ge(o,n){let p=o.noiseCheck===!1?void 0:a(),h=p?c(p):void 0,g=[];for(let b of o.workloads){if(b.suites){let I=await F(b.suites,process.cwd()),K=await V({suites:I,preload:[],bunFlags:[],noiseCheck:!1},o.bench),Q=await S({...K,outDir:K.outDir??o.outDir,timeoutMs:K.timeoutMs??$e});for(let X of Q.workloads){let W=Q.measurements.find((ie)=>ie.workloadId===X.id&&ie.phase==="timing");if(!W)continue;if(h)W.warnings.push(h);g.push({workload:X,status:"executed",run:W,harnessFailed:!1})}continue}let A=B(b.command,b.label,{prepare:b.prepare,timeSource:b.timeSource}),k=await ye(b.inputs??[]),v=i({samples:o.samples??null,budgetMs:o.budgetMs??null,minSamples:o.minSamples??null,warmup:o.warmup}),J=b.inputs!==void 0&&typeof b.prepare!=="function",U=ve({workloadId:A.id,phase:"timing",configFingerprint:v,bunVersion:Bun.version,toolVersion:N,instrumented:!1,inputsDigest:k}),O=n||!J?void 0:await xe(o.outDir,U),D,C;if(O)D=O,C="cached";else{let I=await ae({argv:b.command,samples:o.samples,budgetMs:o.budgetMs,minSamples:o.minSamples,warmup:o.warmup,prepare:b.prepare,timeSource:b.timeSource,timeoutMs:b.timeoutMs??$e,ignoreExitCodes:b.ignoreExitCodes});if(D=x({workload:A,configFingerprint:v,trials:I.trials,timing:I.timing,warnings:h?[...I.warnings,h]:I.warnings}),J)await Pe(o.outDir,U,D);C="executed"}g.push({workload:A,status:C,run:D,harnessFailed:G(D,b.ignoreExitCodes)})}return{results:g,environment:p}}async function Ae(o){let{config:n}=o,p=u(n,o.baselineName);if(!await Bun.file(p).exists())throw new me(p);let g=await s(p),{results:b,environment:A}=await ge(n,o.full),k=b.map((W)=>({...W})),v=k.filter((W)=>W.status==="executed").length,J=k.length-v,U=k.filter((W)=>W.harnessFailed).length,O=r(k.map((W)=>W.workload),k.map((W)=>W.run),A),D=0,C=0,I=0,K=ne(g,O,n.thresholds);for(let W of k){let ie=K.compare(W.workload.id);if(!ie){I++;continue}if(W.comparison=ie,ie.verdict==="pass")D++;else C++}if(I>0){if(qe(n.onMissingBaseline,I,k.length)==="fail")throw new de(p,I,k.length)}let Q=k.map((W)=>W.comparison).filter((W)=>W!==void 0);O.comparisons=Q;let X=K.unmatched();return O.unmatched={baseOnly:X.baseOnly.map((W)=>W.id),candOnly:X.candOnly.map((W)=>W.id)},O.comparisonSummary=te(Q,K.effectiveTimingPct),{document:O,summary:{total:k.length,cached:J,executed:v,passed:D,regressed:C,missingBaseline:I,failed:U,results:k,unmatched:X},baseline:g}}function Me(o){let n=[];if(n.push(`${o.total} workloads`),n.push(`${o.cached} cached`),n.push(`${o.executed} executed`),o.missingBaseline>0)n.push(`${o.missingBaseline} skipped (no matching baseline workload)`);if(o.failed>0){let h=o.results.filter((g)=>g.harnessFailed).map((g)=>t(g.workload));n.push(`${o.failed} failed (harness error, a command exited non-zero or produced no samples: ${h.join(", ")})`)}let p=o.results.filter((h)=>h.comparison?.verdict==="fail").map((h)=>{let g=h.comparison.timing,b=t(h.workload);return g?`${g.medianDeltaPct>0?"+":""}${g.medianDeltaPct.toFixed(1)}% median on ${b}`:b});return n.push(`${o.passed} passed ${o.regressed} regressed${p.length>0?` (${p.join(", ")})`:""}`),n.push(""),n.push(`Profile CI: ${o.regressed>0||o.failed>0?"\u2717":"\u2713"}`),`${n.join(`
5
5
  `)}
6
- `}async function $e(a,n){let{results:f,environment:h}=await pe(a,!1),y=r(f.map((D)=>D.workload),f.map((D)=>D.run),h),C=o(a,n);return await u(y,C),C}async function Me(a){let n=[];try{let h=new Bun.Glob("*.json");for await(let y of h.scan({cwd:a.baselineDir,absolute:!1}))n.push(y.replace(/\.json$/,""))}catch{return[]}return n.sort(),(await Promise.all(n.map(async(h)=>{let y=o(a,h);try{let C=await s(y);return{name:h,path:y,createdAt:C.createdAt,toolVersion:C.toolVersion,bunVersion:C.bunVersion,workloads:C.workloads.length,...C.git!==void 0&&{git:C.git}}}catch{return}}))).filter((h)=>h!==void 0)}function ae(a){return a instanceof Error?a.message:String(a)}var H=(a)=>Bun.write(Bun.stdout,a),Se=(a)=>Bun.write(Bun.stderr,a);class se extends Error{}var Fe=[],Ae=new Set(["minimal","json","jsonl"]);async function We(a){let{isatty:n}=await import("tty");if(!n(2))return!0;return a.some((f,h)=>f==="--format"&&Ae.has(a[h+1]??"")||f.startsWith("--format=")&&Ae.has(f.slice(9)))}async function N(a,n,f){if(await Se(n.endsWith(`
6
+ `}async function Se(o,n){let{results:p,environment:h}=await ge(o,!1),g=r(p.map((A)=>A.workload),p.map((A)=>A.run),h),b=u(o,n);return await l(g,b),b}async function Fe(o){let n=[];try{let h=new Bun.Glob("*.json");for await(let g of h.scan({cwd:o.baselineDir,absolute:!1}))n.push(g.replace(/\.json$/,""))}catch{return[]}return n.sort(),(await Promise.all(n.map(async(h)=>{let g=u(o,h);try{let b=await s(g);return{name:h,path:g,createdAt:b.createdAt,toolVersion:b.toolVersion,bunVersion:b.bunVersion,workloads:b.workloads.length,...b.git!==void 0&&{git:b.git}}}catch{return}}))).filter((h)=>h!==void 0)}function ee(o){return o instanceof Error?o.message:String(o)}var q=(o)=>Bun.write(Bun.stdout,o),Te=(o)=>Bun.write(Bun.stderr,o);class Y extends Error{}var Ie=[],Ee=new Set(["minimal","json","jsonl"]);async function Le(o){let{isatty:n}=await import("tty");if(!n(2))return!0;return o.some((p,h)=>p==="--format"&&Ee.has(o[h+1]??"")||p.startsWith("--format=")&&Ee.has(p.slice(9)))}async function _(o,n,p){if(await Te(n.endsWith(`
7
7
  `)?n:`${n}
8
- `),!await We(Fe))return;await Se(`${JSON.stringify({event:"error",protocolVersion:p,code:a,message:n.split(`
9
- `)[0],...f&&{data:f}})}
10
- `)}async function V(a,n){return await H(a),n?0:2}async function Ue(a,n){return await N("invalid-flag",`${a.message}
11
- Run 'ostia ${n} --help'.`),2}function He(a,n,f={}){if(f.allowAuto&&n==="auto")return Z();let h=f.min??1,y=Number(n);if(!Number.isInteger(y)||y<h)throw new se(`Invalid ${a} "${n}": expected an integer \u2265 ${h}${f.allowAuto?' (or "auto")':""}`);return y}var Le=["ns","us","ms","s"],re=["table","json","jsonl","markdown","minimal"],ge=["collapsed","mermaid","speedscope","cpuprofile"],qe=[...re,...ge],fe=`No CPU evidence in this document; rerun with --cpu (ostia time) or --cpu (ostia bench)
12
- `;function De(a){return a.measurements.some((n)=>n.phase==="cpu")}async function he(a,n,f={}){if(n.format==="json"&&n.exportJson){let h=k(a);if(await J(h,n.exportJson),!n.quiet)await H(h);return 0}if(n.exportJson)await u(a,n.exportJson);if(n.quiet)return 0;if(ge.includes(n.format)&&!De(a))return await N("no-cpu-evidence",fe),2;return await ie(await i[n.format].render(a,f)),0}async function me(a){let n=await E();if(!n){await N("config-missing",a?`No ostia.config.json found. "${a}" needs configured workloads.`:"No ostia.config.json found.");return}if(a&&n.workloads.length===0){let f=await Y()??"ostia.config.json";await N("config-missing",`${f} has no "workloads" configured.`);return}return n}async function ie(a,n){if(a.text)await H(a.text);if(!a.files||a.files.length===0)return;if(n)for(let f of a.files){let h=f.path?`${n}/${f.path}`:n;await Bun.write(h,f.content),await H(`wrote ${h}
13
- `)}else if(a.files.length===1)await H(a.files[0].content);else for(let f of a.files)await H(`--- ${f.path??"(unnamed)"} ---
14
- ${f.content}
15
- `)}var Je=`ostia time [flags] <command...>
8
+ `),!await Le(Ie))return;await Te(`${JSON.stringify({event:"error",protocolVersion:f,code:o,message:n.split(`
9
+ `)[0],...p&&{data:p}})}
10
+ `)}async function z(o,n){return await q(o),n?0:2}async function Je(o,n){return await _("invalid-flag",`${o.message}
11
+ Run 'ostia ${n} --help'.`),2}function Ge(o,n,p={}){if(p.allowAuto&&n==="auto")return se();let h=p.min??1,g=Number(n);if(!Number.isInteger(g)||g<h)throw new Y(`Invalid ${o} "${n}": expected an integer \u2265 ${h}${p.allowAuto?' (or "auto")':""}`);return g}var Ve=["ns","us","ms","s"],le=["table","json","jsonl","markdown","minimal"],we=["collapsed","mermaid","speedscope","cpuprofile"],ze=[...le,...we],be=`No CPU evidence in this document; rerun with --cpu (ostia time) or --cpu (ostia bench)
12
+ `;function Ne(o){return o.measurements.some((n)=>n.phase==="cpu")}async function pe(o,n,p={}){if(n.format==="json"&&n.exportJson){let h=P(o);if(await Z(h,n.exportJson),!n.quiet)await q(h);return 0}if(n.exportJson)await l(o,n.exportJson);if(n.quiet)return 0;if(we.includes(n.format)&&!Ne(o))return await _("no-cpu-evidence",be),2;return await ue(await m[n.format].render(o,p)),0}async function fe(o){let n=await E();if(!n){await _("config-missing",o?`No ostia.config.json found. "${o}" needs configured workloads.`:"No ostia.config.json found.");return}if(o&&n.workloads.length===0){let p=await re()??"ostia.config.json";await _("config-missing",`${p} has no "workloads" configured.`);return}return n}async function ue(o,n){if(o.text)await q(o.text);if(!o.files||o.files.length===0)return;if(n)for(let p of o.files){let h=p.path?`${n}/${p.path}`:n;await Bun.write(h,p.content),await q(`wrote ${h}
13
+ `)}else if(o.files.length===1)await q(o.files[0].content);else for(let p of o.files)await q(`--- ${p.path??"(unnamed)"} ---
14
+ ${p.content}
15
+ `)}var Ke=`ostia time [flags] <command...>
16
16
  ostia time [flags] -- <argv...>
17
17
 
18
18
  Time commands as subprocesses. Each <command> is whitespace-split into argv (no shell);
@@ -48,7 +48,7 @@ Examples:
48
48
  ostia time --prepare "rm -rf dist" "bun build.ts"
49
49
  ostia time --time-source "built in (\\d+)ms" "bun build.ts"
50
50
  ostia time -- bun -e "console.log('a b')"
51
- `,Ge=Array.from({length:255},(a,n)=>n+1),Ee=`ostia bench [flags] <suite.ts...>
51
+ `,Xe=Array.from({length:255},(o,n)=>n+1),De=`ostia bench [flags] <suite.ts...>
52
52
 
53
53
  Run in-process group()/task() suites, each file in its own child process. With no files,
54
54
  uses ostia.config's "bench" section; each flag overrides its config field.
@@ -60,8 +60,12 @@ Flags:
60
60
  --jobs N|auto suite files at once (default: 1; >1 adds noise)
61
61
  --isolate one process per task, not per file (--no-isolate to undo config)
62
62
  --gc Bun.gc(true) between trials (--no-gc)
63
- --cpu extra per-task CPU profile with JIT tiers (--no-cpu)
64
- --alloc extra per-task bytes-allocated-per-call measurement (--no-alloc)
63
+ --cpu extra per-task CPU profile with JIT tiers, ~2,000 samples (--no-cpu)
64
+ --cpu-interval US CPU sampling interval (default: 100)
65
+ --alloc extra per-task retained-heap-per-call measurement: what calls keep
66
+ alive after a full GC, not what they allocate (--no-alloc)
67
+ --peak-mem extra per-task RSS rise during the task's first call, garbage
68
+ included; median of 3 fresh processes (--no-peak-mem)
65
69
  --filter REGEX only tasks whose "group/name" matches
66
70
  --preload PATH import before each suite file (repeatable, in order)
67
71
  --bun-flags FLAGS extra flags for the bun process running each suite (repeatable)
@@ -73,14 +77,46 @@ Flags:
73
77
  --quiet don't print the report
74
78
  --help show this message
75
79
 
76
- Per-task/per-group options ({ budgetMs, minSamples, gc, isolate, cpu, alloc }) override
80
+ Per-task/per-group options ({ budgetMs, minSamples, gc, isolate, cpu, alloc, peakMem }) override
77
81
  the suite-wide defaults. Exit codes: 0 ok, 2 a suite failed (or a bad flag), 130 Ctrl-C.
78
82
 
79
83
  Examples:
80
84
  ostia bench bench/*.ts
81
85
  ostia bench bench/*.ts --filter parse --cpu --alloc
82
86
  ostia bench --preload ./bench/dom-setup.ts --bun-flags="--conditions=browser" bench/*.ts
83
- `,Re=`ostia compare <base.json> <candidate.json>
87
+ `,Re=`ostia ab [flags] <suite.ts...>
88
+
89
+ Pair every task on a git ref's committed tree (base) against the working tree (candidate), in
90
+ one process, alternating ~10ms batches, and gate on the per-round time ratio. Drift between
91
+ the two sides cancels within a round. With no files, uses ostia.config's "bench" suites.
92
+
93
+ Flags:
94
+ --base REF git ref for the base side (default: HEAD)
95
+ --rounds N base/candidate rounds per task (default: 15)
96
+ --threshold PCT flag a task whose median ratio moves past PCT (default: 10)
97
+ --geomean-threshold PCT fail when the geometric mean of all ratios is slower than PCT
98
+ (default: 1.5)
99
+ --confirm N re-measure each flagged task in N fresh processes (default: 2; 0 skips)
100
+ --filter REGEX only tasks whose "group/name" matches
101
+ --preload PATH import before each suite file (repeatable, in order)
102
+ --bun-flags FLAGS extra flags for the bun process running each suite (repeatable)
103
+ --timeout MS kill a suite (or repeat) process after MS
104
+ --out-dir PATH scratch directory and base-tree cache (default: node_modules/.cache/ostia)
105
+ --no-noise-check skip the ~200ms noise-floor measurement
106
+ --export-json PATH write the ProfileDocument to PATH
107
+ --format FORMAT table | json | jsonl | markdown | minimal (default: table)
108
+ --quiet don't print the report
109
+ --help show this message
110
+
111
+ A flagged task counts only when every fresh-process repeat flags it the same way. Exit codes:
112
+ 0 pass, 1 a confirmed regression or the geomean over its threshold, 2 nothing paired or a
113
+ harness error (not a git repo, unknown ref, a suite failed), 130 Ctrl-C.
114
+
115
+ Examples:
116
+ ostia ab bench/parse.bench.ts
117
+ ostia ab bench/*.ts --base origin/main --rounds 21
118
+ ostia ab bench/*.ts --filter parse --format minimal
119
+ `,Oe=`ostia compare <base.json> <candidate.json>
84
120
  ostia compare <candidate.json> --baseline <base.json>
85
121
 
86
122
  Compare two ProfileDocuments by workload id. Gates on ostia.config's "thresholds" when
@@ -94,7 +130,7 @@ Flags:
94
130
  --help show this message
95
131
 
96
132
  Exit codes: 0 pass, 1 a workload regressed, 2 nothing matched or a harness error.
97
- `,Ve=`ostia report <document.json> [flags]
133
+ `,Ze=`ostia report <document.json> [flags]
98
134
 
99
135
  Render a saved ProfileDocument. Files, not a GUI for the visualization formats -
100
136
  hand the output to speedscope.app, flamegraph.pl, or a Mermaid renderer.
@@ -122,7 +158,7 @@ Examples:
122
158
  ostia report doc.json --format markdown
123
159
  ostia report doc.json --format speedscope --out-dir node_modules/.cache/ostia/viz
124
160
  ostia report doc.json --format collapsed | flamegraph.pl > flame.svg
125
- `,ze=`ostia ci [flags]
161
+ `,Qe=`ostia ci [flags]
126
162
 
127
163
  Run ostia.config's workloads (reusing cached runs whose declared inputs are unchanged),
128
164
  compare against a saved baseline, and gate on regressions.
@@ -139,7 +175,7 @@ Flags:
139
175
 
140
176
  Exit codes: 0 pass, 1 regression, 2 harness error (missing config/baseline, a workload
141
177
  failed or produced no samples, or an onMissingBaseline "fail" mismatch).
142
- `,de=`ostia baseline <save|list|show> [args]
178
+ `,he=`ostia baseline <save|list|show> [args]
143
179
 
144
180
  Manage the baseline ProfileDocuments "ostia ci" gates against and "ostia compare --baseline"
145
181
  reads.
@@ -158,32 +194,33 @@ Examples:
158
194
  ostia baseline list
159
195
  ostia baseline show main
160
196
  ostia baseline show main --format markdown
161
- `;function le(a,n,f,h,y,C){let D=h;for(let M=0;M<a.length;M++){let S=a[M],G=C?.(S,M,h);if(G!==void 0){M=G;continue}let L=S.startsWith("--")?S.indexOf("="):-1,U=L>0?S.slice(0,L):S,O=f[U];if(!O||L>0&&O.spec.kind==="bool"){if(S.startsWith("-"))throw new se(`Unknown flag "${S}" for "ostia ${n}".`);y(S,h);continue}let T=()=>L>0?S.slice(L+1):a[++M];switch(O.spec.kind){case"string":D[O.dest]=T();break;case"int":D[O.dest]=He(U,T(),O.spec);break;case"bool":D[O.dest]=O.spec.value;break;case"list":D[O.dest].push(T()??"");break;case"enum":{let _=T();if(!O.spec.values.includes(_))throw new se(`Invalid ${U} "${_}": expected one of: ${O.spec.values.join(", ")}`);D[O.dest]=_;break}}}return h}var Ke={"--samples":{dest:"samples",spec:{kind:"int",min:1}},"--budget":{dest:"budgetMs",spec:{kind:"int",min:1}},"--min-samples":{dest:"minSamples",spec:{kind:"int",min:1}},"--warmup":{dest:"warmup",spec:{kind:"int",min:0}},"--no-interleave":{dest:"interleave",spec:{kind:"bool",value:!1}},"--prepare":{dest:"prepare",spec:{kind:"list"}},"--time-source":{dest:"timeSource",spec:{kind:"string"}},"--time-unit":{dest:"timeUnit",spec:{kind:"enum",values:Le}},"--cpu":{dest:"cpu",spec:{kind:"bool",value:!0}},"--heap":{dest:"heap",spec:{kind:"bool",value:!0}},"--cpu-interval":{dest:"cpuIntervalUs",spec:{kind:"int",min:1}},"--timeout":{dest:"timeoutMs",spec:{kind:"int",min:1}},"--out-dir":{dest:"outDir",spec:{kind:"string"}},"--no-noise-check":{dest:"noiseCheck",spec:{kind:"bool",value:!1}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:re}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function Xe(a){return le(a,"time",Ke,{commands:[],prepare:[],interleave:!0,cpu:!1,heap:!1,ignoreExitCodes:[],noiseCheck:!0,format:"table",quiet:!1,help:!1},(f,h)=>h.commands.push(f),(f,h,y)=>{if(f==="--")return y.argvCommand=a.slice(h+1),a.length;if(f==="--ignore-failure"||f.startsWith("--ignore-failure=")){let C=f.startsWith("--ignore-failure=")?f.slice(17):void 0;return y.ignoreExitCodes.push(...C===void 0?Ge:C.split(",").map(Number)),h}return})}async function Oe(a){let n=new AbortController,f=()=>n.abort();process.on("SIGINT",f);try{return{result:await a(n.signal),aborted:n.signal.aborted}}finally{process.off("SIGINT",f)}}async function Ze(a){let n=Xe(a),f=(n.argvCommand?.length??0)>0;if(n.help||n.commands.length===0&&!f)return V(Je,n.help);let h=n.commands.length+(f?1:0);if(n.prepare.length>1&&n.prepare.length!==h)return await N("invalid-flag",`--prepare given ${n.prepare.length} times for ${h} command(s): give it once (applies to all) or once per command.`),2;if(n.timeSource!==void 0)try{new RegExp(n.timeSource)}catch(T){return await N("invalid-flag",`Invalid --time-source regex: ${ae(T)}`),2}let y=n.timeSource!==void 0?{pattern:n.timeSource,unit:n.timeUnit}:void 0,C=(T)=>n.prepare.length===1?n.prepare[0]:n.prepare[T],D=n.commands.map((T,_)=>({command:T,prepare:C(_)}));if(f)D.push({command:n.argvCommand,prepare:C(n.commands.length)});let M,S;try{({result:M,aborted:S}=await Oe((T)=>Q({commands:D,timeSource:y,samples:n.samples,budgetMs:n.budgetMs,minSamples:n.minSamples,warmup:n.warmup,interleave:n.interleave,cpu:n.cpu,heap:n.heap,cpuIntervalUs:n.cpuIntervalUs,timeoutMs:n.timeoutMs,ignoreExitCodes:n.ignoreExitCodes,outDir:n.outDir,noiseCheck:n.noiseCheck,signal:T})))}catch(T){return await N("spawn-failed",`Run failed: ${ae(T)}`),2}let G=await he(M,n);if(G!==0)return G;if(S)return 130;let L=M.workloads.map((T)=>M.measurements.find((_)=>_.workloadId===T.id&&_.phase==="timing")??{trials:[],timing:void 0}),U=L.some((T)=>!T.timing),O=L.some((T)=>T.timing&&B(T,n.ignoreExitCodes));if(O||U){let T=M.measurements.some((ee)=>ee.warnings.some((z)=>z.code==="timeout")),_=M.measurements.some((ee)=>ee.warnings.some((z)=>z.code==="time-source-no-match"));return await N(O?"command-failed":T?"timeout":_?"time-source-no-match":"command-failed","One or more commands failed to produce a clean measurement; see the report above for details."),2}return 0}var Qe={"--budget":{dest:"budgetMs",spec:{kind:"int",min:1}},"--samples":{dest:"samples",spec:{kind:"int",min:1}},"--min-samples":{dest:"minSamples",spec:{kind:"int",min:1}},"--jobs":{dest:"jobs",spec:{kind:"int",min:1,allowAuto:!0}},"--gc":{dest:"gc",spec:{kind:"bool",value:!0}},"--no-gc":{dest:"gc",spec:{kind:"bool",value:!1}},"--cpu":{dest:"cpu",spec:{kind:"bool",value:!0}},"--no-cpu":{dest:"cpu",spec:{kind:"bool",value:!1}},"--alloc":{dest:"alloc",spec:{kind:"bool",value:!0}},"--no-alloc":{dest:"alloc",spec:{kind:"bool",value:!1}},"--filter":{dest:"filter",spec:{kind:"string"}},"--isolate":{dest:"isolate",spec:{kind:"bool",value:!0}},"--no-isolate":{dest:"isolate",spec:{kind:"bool",value:!1}},"--preload":{dest:"preload",spec:{kind:"list"}},"--timeout":{dest:"timeoutMs",spec:{kind:"int",min:1}},"--out-dir":{dest:"outDir",spec:{kind:"string"}},"--no-noise-check":{dest:"noiseCheck",spec:{kind:"bool",value:!1}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:re}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function Ye(a){return le(a,"bench",Qe,{suites:[],preload:[],bunFlags:[],noiseCheck:!0,format:"table",quiet:!1,help:!1},(f,h)=>h.suites.push(f),(f,h,y)=>{if(f==="--bun-flags")return y.bunFlags.push(...b(a[h+1]??"")),h+1;if(f.startsWith("--bun-flags="))return y.bunFlags.push(...b(f.slice(12))),h;return})}async function en(a){let n=Ye(a);if(n.help)return V(Ee,!0);let f=await E(),h=await W(n,f?.bench);if(h.suites.length===0)return V(Ee,!1);if(h.jobs!==void 0&&!(h.jobs>=1))return await N("invalid-flag",'--jobs expects a positive integer or "auto".'),2;let y,C;try{({result:y,aborted:C}=await Oe((M)=>v({...h,signal:M})))}catch(M){return await N("spawn-failed",`Bench failed: ${ae(M)}`),2}let D=await he(y,n);if(D!==0)return D;return C?130:0}var nn={"--baseline":{dest:"baseline",spec:{kind:"string"}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:re}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function tn(a){return le(a,"compare",nn,{paths:[],format:"table",quiet:!1,help:!1},(f,h)=>h.paths.push(f))}async function sn(){let a=await E();if(!a)return{thresholds:m,source:"defaults"};return{thresholds:a.thresholds,source:await Y()??"ostia.config.json"}}async function on(a){let n=tn(a);if(n.help)return V(Re,!0);let f,h;if(n.baseline)f=n.baseline,h=n.paths[0];else f=n.paths[0],h=n.paths[1];if(!f||!h)return V(Re,!1);let y,C;try{[y,C]=await Promise.all([s(f),s(h)])}catch(T){return await N("document-load-failed",`Failed to load documents: ${ae(T)}`),2}let{thresholds:D,source:M}=await sn(),S=F(y,C,D),G={...C,comparisons:S.comparisons,comparisonSummary:S.summary,unmatched:{baseOnly:S.unmatched.baseOnly.map((T)=>T.id),candOnly:S.unmatched.candOnly.map((T)=>T.id)}},L=n.format==="table"||n.format==="markdown";if(!n.quiet&&L){if(await H(`thresholds: ${M}
162
- `),y.git&&C.git)await H(`base ${g(y.git)} \u2192 cand ${g(C.git)}
163
- `);if(n.format==="table"&&S.summary.effectiveTimingPct>D.timingPct)await H(`threshold ${D.timingPct}% (widened to ${S.summary.effectiveTimingPct.toFixed(1)}% by noise floor)
164
- `)}let U=S.summary.matched===0?2:S.summary.verdict==="fail"?1:0,O=await he(G,n,{protocol:{command:"compare",exitCode:U,unmatched:S.unmatched,baseGit:y.git,candGit:C.git,...n.exportJson&&{exportedTo:n.exportJson}}});if(O!==0)return O;if(!n.quiet&&(n.format==="table"||n.format==="markdown")&&(S.unmatched.baseOnly.length>0||S.unmatched.candOnly.length>0))await H(an(S.unmatched,n.format));if(S.summary.matched===0)await N("no-matches","No workload matched between base and candidate; nothing was compared.");return U}function an(a,n){let f=(y)=>y.map((C)=>t(C)).join(", ");if(n==="markdown"){let y=["### Unmatched",""];if(a.baseOnly.length>0)y.push(`- baseline only: ${f(a.baseOnly)}`);if(a.candOnly.length>0)y.push(`- candidate only: ${f(a.candOnly)}`);return y.push(""),`${y.join(`
197
+ `;function ce(o,n,p,h,g,b){let A=h;for(let k=0;k<o.length;k++){let v=o[k],J=b?.(v,k,h);if(J!==void 0){k=J;continue}let U=v.startsWith("--")?v.indexOf("="):-1,O=U>0?v.slice(0,U):v,D=p[O];if(!D||U>0&&D.spec.kind==="bool"){if(v.startsWith("-"))throw new Y(`Unknown flag "${v}" for "ostia ${n}".`);g(v,h);continue}let C=()=>U>0?v.slice(U+1):o[++k];switch(D.spec.kind){case"string":A[D.dest]=C();break;case"int":A[D.dest]=Ge(O,C(),D.spec);break;case"number":{let I=C(),K=Number(I);if(I===void 0||I===""||!Number.isFinite(K)||K<D.spec.min)throw new Y(`Invalid ${O} "${I}": expected a number \u2265 ${D.spec.min}`);A[D.dest]=K;break}case"bool":A[D.dest]=D.spec.value;break;case"list":A[D.dest].push(C()??"");break;case"enum":{let I=C();if(!D.spec.values.includes(I))throw new Y(`Invalid ${O} "${I}": expected one of: ${D.spec.values.join(", ")}`);A[D.dest]=I;break}}}return h}var Ye={"--samples":{dest:"samples",spec:{kind:"int",min:1}},"--budget":{dest:"budgetMs",spec:{kind:"int",min:1}},"--min-samples":{dest:"minSamples",spec:{kind:"int",min:1}},"--warmup":{dest:"warmup",spec:{kind:"int",min:0}},"--no-interleave":{dest:"interleave",spec:{kind:"bool",value:!1}},"--prepare":{dest:"prepare",spec:{kind:"list"}},"--time-source":{dest:"timeSource",spec:{kind:"string"}},"--time-unit":{dest:"timeUnit",spec:{kind:"enum",values:Ve}},"--cpu":{dest:"cpu",spec:{kind:"bool",value:!0}},"--heap":{dest:"heap",spec:{kind:"bool",value:!0}},"--cpu-interval":{dest:"cpuIntervalUs",spec:{kind:"int",min:1}},"--timeout":{dest:"timeoutMs",spec:{kind:"int",min:1}},"--out-dir":{dest:"outDir",spec:{kind:"string"}},"--no-noise-check":{dest:"noiseCheck",spec:{kind:"bool",value:!1}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:le}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function et(o){return ce(o,"time",Ye,{commands:[],prepare:[],interleave:!0,cpu:!1,heap:!1,ignoreExitCodes:[],noiseCheck:!0,format:"table",quiet:!1,help:!1},(p,h)=>h.commands.push(p),(p,h,g)=>{if(p==="--")return g.argvCommand=o.slice(h+1),o.length;if(p==="--ignore-failure"||p.startsWith("--ignore-failure=")){let b=p.startsWith("--ignore-failure=")?p.slice(17):void 0;return g.ignoreExitCodes.push(...b===void 0?Xe:b.split(",").map(Number)),h}return})}async function ke(o){let n=new AbortController,p=()=>n.abort();process.on("SIGINT",p);try{return{result:await o(n.signal),aborted:n.signal.aborted}}finally{process.off("SIGINT",p)}}async function tt(o){let n=et(o),p=(n.argvCommand?.length??0)>0;if(n.help||n.commands.length===0&&!p)return z(Ke,n.help);let h=n.commands.length+(p?1:0);if(n.prepare.length>1&&n.prepare.length!==h)return await _("invalid-flag",`--prepare given ${n.prepare.length} times for ${h} command(s): give it once (applies to all) or once per command.`),2;if(n.timeSource!==void 0)try{new RegExp(n.timeSource)}catch(C){return await _("invalid-flag",`Invalid --time-source regex: ${ee(C)}`),2}let g=n.timeSource!==void 0?{pattern:n.timeSource,unit:n.timeUnit}:void 0,b=(C)=>n.prepare.length===1?n.prepare[0]:n.prepare[C],A=n.commands.map((C,I)=>({command:C,prepare:b(I)}));if(p)A.push({command:n.argvCommand,prepare:b(n.commands.length)});let k,v;try{({result:k,aborted:v}=await ke((C)=>oe({commands:A,timeSource:g,samples:n.samples,budgetMs:n.budgetMs,minSamples:n.minSamples,warmup:n.warmup,interleave:n.interleave,cpu:n.cpu,heap:n.heap,cpuIntervalUs:n.cpuIntervalUs,timeoutMs:n.timeoutMs,ignoreExitCodes:n.ignoreExitCodes,outDir:n.outDir,noiseCheck:n.noiseCheck,signal:C})))}catch(C){return await _("spawn-failed",`Run failed: ${ee(C)}`),2}let J=await pe(k,n);if(J!==0)return J;if(v)return 130;let U=k.workloads.map((C)=>k.measurements.find((I)=>I.workloadId===C.id&&I.phase==="timing")??{trials:[],timing:void 0}),O=U.some((C)=>!C.timing),D=U.some((C)=>C.timing&&G(C,n.ignoreExitCodes));if(D||O){let C=k.measurements.some((Q)=>Q.warnings.some((X)=>X.code==="timeout")),I=k.measurements.some((Q)=>Q.warnings.some((X)=>X.code==="time-source-no-match"));return await _(D?"command-failed":C?"timeout":I?"time-source-no-match":"command-failed","One or more commands failed to produce a clean measurement; see the report above for details."),2}return 0}var nt={"--budget":{dest:"budgetMs",spec:{kind:"int",min:1}},"--samples":{dest:"samples",spec:{kind:"int",min:1}},"--min-samples":{dest:"minSamples",spec:{kind:"int",min:1}},"--jobs":{dest:"jobs",spec:{kind:"int",min:1,allowAuto:!0}},"--gc":{dest:"gc",spec:{kind:"bool",value:!0}},"--no-gc":{dest:"gc",spec:{kind:"bool",value:!1}},"--cpu":{dest:"cpu",spec:{kind:"bool",value:!0}},"--no-cpu":{dest:"cpu",spec:{kind:"bool",value:!1}},"--cpu-interval":{dest:"cpuIntervalUs",spec:{kind:"int",min:1}},"--alloc":{dest:"alloc",spec:{kind:"bool",value:!0}},"--no-alloc":{dest:"alloc",spec:{kind:"bool",value:!1}},"--peak-mem":{dest:"peakMem",spec:{kind:"bool",value:!0}},"--no-peak-mem":{dest:"peakMem",spec:{kind:"bool",value:!1}},"--filter":{dest:"filter",spec:{kind:"string"}},"--isolate":{dest:"isolate",spec:{kind:"bool",value:!0}},"--no-isolate":{dest:"isolate",spec:{kind:"bool",value:!1}},"--preload":{dest:"preload",spec:{kind:"list"}},"--timeout":{dest:"timeoutMs",spec:{kind:"int",min:1}},"--out-dir":{dest:"outDir",spec:{kind:"string"}},"--no-noise-check":{dest:"noiseCheck",spec:{kind:"bool",value:!1}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:le}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function st(o){return ce(o,"bench",nt,{suites:[],preload:[],bunFlags:[],noiseCheck:!0,format:"table",quiet:!1,help:!1},(p,h)=>h.suites.push(p),Be(o))}function Be(o){return(n,p,h)=>{if(n==="--bun-flags")return h.bunFlags.push(...y(o[p+1]??"")),p+1;if(n.startsWith("--bun-flags="))return h.bunFlags.push(...y(n.slice(12))),p;return}}async function ot(o){let n=st(o);if(n.help)return z(De,!0);let p=await E(),h=await V(n,p?.bench);if(h.suites.length===0)return z(De,!1);if(h.jobs!==void 0&&!(h.jobs>=1))return await _("invalid-flag",'--jobs expects a positive integer or "auto".'),2;let g,b;try{({result:g,aborted:b}=await ke((k)=>S({...h,signal:k})))}catch(k){return await _("spawn-failed",`Bench failed: ${ee(k)}`),2}let A=await pe(g,n);if(A!==0)return A;return b?130:0}var at={"--base":{dest:"base",spec:{kind:"string"}},"--rounds":{dest:"rounds",spec:{kind:"int",min:3}},"--threshold":{dest:"thresholdPct",spec:{kind:"number",min:0}},"--geomean-threshold":{dest:"geomeanThresholdPct",spec:{kind:"number",min:0}},"--confirm":{dest:"confirm",spec:{kind:"int",min:0}},"--filter":{dest:"filter",spec:{kind:"string"}},"--preload":{dest:"preload",spec:{kind:"list"}},"--timeout":{dest:"timeoutMs",spec:{kind:"int",min:1}},"--out-dir":{dest:"outDir",spec:{kind:"string"}},"--no-noise-check":{dest:"noiseCheck",spec:{kind:"bool",value:!1}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:le}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function it(o){return ce(o,"ab",at,{suites:[],preload:[],bunFlags:[],noiseCheck:!0,format:"table",quiet:!1,help:!1},(p,h)=>h.suites.push(p),Be(o))}async function rt(o){let n=it(o);if(n.help)return z(Re,!0);let p=(await E())?.bench,h=n.suites.length>0?n.suites:p?.suites?await F(p.suites,process.cwd()):[];if(h.length===0)return z(Re,!1);let g,b;try{({result:g,aborted:b}=await ke((O)=>j({suites:h,base:n.base,rounds:n.rounds,thresholdPct:n.thresholdPct,geomeanThresholdPct:n.geomeanThresholdPct,confirm:n.confirm,filter:n.filter??p?.filter,preload:n.preload.length>0?n.preload:p?.preload??[],bunFlags:n.bunFlags.length>0?n.bunFlags:p?.bunFlags??[],timeoutMs:n.timeoutMs??p?.timeoutMs,outDir:n.outDir??p?.outDir,noiseCheck:n.noiseCheck,signal:O})))}catch(O){if(O instanceof R)return await _("invalid-flag",`--base: ${O.message}`),2;return await _("spawn-failed",`A/B run failed: ${ee(O)}`),2}let A=g.ab,k=b?130:A.matched===0?2:A.verdict==="fail"?1:0,v=new Map(g.workloads.map((O)=>[O.id,O])),J=(O=[])=>O.flatMap((D)=>v.get(D)??[]),U=await pe(g,n,{protocol:{command:"ab",exitCode:k,unmatched:{baseOnly:J(g.unmatched?.baseOnly),candOnly:J(g.unmatched?.candOnly)},...n.exportJson&&{exportedTo:n.exportJson}}});if(U!==0)return U;if(k===2)await _("no-matches",`No task exists both at ${A.base.ref} and in the working tree; nothing was paired.`);return k}var lt={"--baseline":{dest:"baseline",spec:{kind:"string"}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:le}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function ct(o){return ce(o,"compare",lt,{paths:[],format:"table",quiet:!1,help:!1},(p,h)=>h.paths.push(p))}async function ut(){let o=await E();if(!o)return{thresholds:d,source:"defaults"};return{thresholds:o.thresholds,source:await re()??"ostia.config.json"}}async function mt(o){let n=ct(o);if(n.help)return z(Oe,!0);let p,h;if(n.baseline)p=n.baseline,h=n.paths[0];else p=n.paths[0],h=n.paths[1];if(!p||!h)return z(Oe,!1);let g,b;try{[g,b]=await Promise.all([s(p),s(h)])}catch(C){return await _("document-load-failed",`Failed to load documents: ${ee(C)}`),2}let{thresholds:A,source:k}=await ut(),v=L(g,b,A),J={...b,comparisons:v.comparisons,comparisonSummary:v.summary,unmatched:{baseOnly:v.unmatched.baseOnly.map((C)=>C.id),candOnly:v.unmatched.candOnly.map((C)=>C.id)}},U=n.format==="table"||n.format==="markdown";if(!n.quiet&&U){if(await q(`thresholds: ${k}
198
+ `),g.git&&b.git)await q(`base ${w(g.git)} \u2192 cand ${w(b.git)}
199
+ `);if(n.format==="table"&&v.summary.effectiveTimingPct>A.timingPct)await q(`threshold ${A.timingPct}% (widened to ${v.summary.effectiveTimingPct.toFixed(1)}% by noise floor)
200
+ `)}let O=v.summary.matched===0?2:v.summary.verdict==="fail"?1:0,D=await pe(J,n,{protocol:{command:"compare",exitCode:O,unmatched:v.unmatched,baseGit:g.git,candGit:b.git,...n.exportJson&&{exportedTo:n.exportJson}}});if(D!==0)return D;if(!n.quiet&&(n.format==="table"||n.format==="markdown")&&(v.unmatched.baseOnly.length>0||v.unmatched.candOnly.length>0))await q(dt(v.unmatched,n.format));if(v.summary.matched===0)await _("no-matches","No workload matched between base and candidate; nothing was compared.");return O}function dt(o,n){let p=(g)=>g.map((b)=>t(b)).join(", ");if(n==="markdown"){let g=["### Unmatched",""];if(o.baseOnly.length>0)g.push(`- baseline only: ${p(o.baseOnly)}`);if(o.candOnly.length>0)g.push(`- candidate only: ${p(o.candOnly)}`);return g.push(""),`${g.join(`
165
201
  `)}
166
- `}let h=["","Unmatched:"];if(a.baseOnly.length>0)h.push(` baseline only: ${f(a.baseOnly)}`);if(a.candOnly.length>0)h.push(` candidate only: ${f(a.candOnly)}`);return`${h.join(`
202
+ `}let h=["","Unmatched:"];if(o.baseOnly.length>0)h.push(` baseline only: ${p(o.baseOnly)}`);if(o.candOnly.length>0)h.push(` candidate only: ${p(o.candOnly)}`);return`${h.join(`
167
203
  `)}
168
- `}var rn={"--format":{dest:"format",spec:{kind:"enum",values:qe}},"--measurement":{dest:"measurementId",spec:{kind:"string"}},"--out-dir":{dest:"outDir",spec:{kind:"string"}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function ln(a){return le(a,"report",rn,{format:"table",help:!1},(f,h)=>{if(h.path!==void 0)throw new se(`"ostia report" takes exactly one document path, got "${h.path}" and "${f}".`);h.path=f})}async function je(a){let n=ln(a);if(n.help||!n.path)return V(Ve,n.help);let f;try{f=await s(n.path)}catch(C){return await N("document-load-failed",`Failed to load ${n.path}: ${ae(C)}`),2}if(ge.includes(n.format)&&!n.measurementId&&!De(f))return await N("no-cpu-evidence",fe),2;let y=await i[n.format].render(f,{measurementId:n.measurementId});if(!y.text&&(!y.files||y.files.length===0))return await N("no-cpu-evidence",n.measurementId?`No CPU evidence found for measurement "${n.measurementId}".`:fe),2;return await ie(y,n.outDir),0}var cn={"--full":{dest:"full",spec:{kind:"bool",value:!0}},"--baseline":{dest:"baseline",spec:{kind:"string"}},"--save-baseline":{dest:"saveBaseline",spec:{kind:"bool",value:!0}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:re}},"--no-noise-check":{dest:"noiseCheck",spec:{kind:"bool",value:!1}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function un(a){return le(a,"ci",cn,{full:!1,saveBaseline:!1,format:"table",quiet:!1,help:!1,noiseCheck:!0},(f)=>{throw new se(`Unknown flag "${f}" for "ostia ci".`)})}async function mn(a){let n=un(a);if(n.help)return V(ze,!0);let f=await me("ostia ci");if(!f)return 2;let h={...f,...!n.noiseCheck&&{noiseCheck:!1}},y;try{y=await xe({config:h,full:n.full,baselineName:n.baseline})}catch(M){if(M instanceof ce||M instanceof ue)return await N("baseline-missing",M.message),2;if(M instanceof x)return await N("document-load-failed",M.message),2;return await N("spawn-failed",`CI run failed: ${ae(M)}`),2}let C=n.format==="json"&&!n.quiet?k(y.document):void 0;if(n.exportJson)if(C)await J(C,n.exportJson);else await u(y.document,n.exportJson);if(n.saveBaseline&&y.summary.regressed===0&&y.summary.failed===0)await u(y.document,o(h,n.baseline));let D=y.summary.failed>0?2:y.summary.regressed>0?1:0;if(y.summary.failed>0){let M=y.summary.results.filter((S)=>S.harnessFailed).map((S)=>t(S.workload));await N("command-failed",`${y.summary.failed} workload(s) failed (harness error, a command exited non-zero or produced no samples): ${M.join(", ")}`)}if(!n.quiet){let M=n.baseline??h.baseline;if(n.format==="table"){if(await H(Pe(y.summary)),y.document.comparisons&&y.document.comparisons.length>0)await ie(await i.table.render(y.document,{}))}else if(C!==void 0)await H(C);else if(n.format==="markdown")await H(`## ostia ci
204
+ `}var pt={"--format":{dest:"format",spec:{kind:"enum",values:ze}},"--measurement":{dest:"measurementId",spec:{kind:"string"}},"--out-dir":{dest:"outDir",spec:{kind:"string"}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function ft(o){return ce(o,"report",pt,{format:"table",help:!1},(p,h)=>{if(h.path!==void 0)throw new Y(`"ostia report" takes exactly one document path, got "${h.path}" and "${p}".`);h.path=p})}async function _e(o){let n=ft(o);if(n.help||!n.path)return z(Ze,n.help);let p;try{p=await s(n.path)}catch(b){return await _("document-load-failed",`Failed to load ${n.path}: ${ee(b)}`),2}if(we.includes(n.format)&&!n.measurementId&&!Ne(p))return await _("no-cpu-evidence",be),2;let g=await m[n.format].render(p,{measurementId:n.measurementId});if(!g.text&&(!g.files||g.files.length===0))return await _("no-cpu-evidence",n.measurementId?`No CPU evidence found for measurement "${n.measurementId}".`:be),2;return await ue(g,n.outDir),0}var ht={"--full":{dest:"full",spec:{kind:"bool",value:!0}},"--baseline":{dest:"baseline",spec:{kind:"string"}},"--save-baseline":{dest:"saveBaseline",spec:{kind:"bool",value:!0}},"--export-json":{dest:"exportJson",spec:{kind:"string"}},"--format":{dest:"format",spec:{kind:"enum",values:le}},"--no-noise-check":{dest:"noiseCheck",spec:{kind:"bool",value:!1}},"--quiet":{dest:"quiet",spec:{kind:"bool",value:!0}},"--help":{dest:"help",spec:{kind:"bool",value:!0}},"-h":{dest:"help",spec:{kind:"bool",value:!0}}};function gt(o){return ce(o,"ci",ht,{full:!1,saveBaseline:!1,format:"table",quiet:!1,help:!1,noiseCheck:!0},(p)=>{throw new Y(`Unknown flag "${p}" for "ostia ci".`)})}async function bt(o){let n=gt(o);if(n.help)return z(Qe,!0);let p=await fe("ostia ci");if(!p)return 2;let h={...p,...!n.noiseCheck&&{noiseCheck:!1}},g;try{g=await Ae({config:h,full:n.full,baselineName:n.baseline})}catch(k){if(k instanceof me||k instanceof de)return await _("baseline-missing",k.message),2;if(k instanceof M)return await _("document-load-failed",k.message),2;return await _("spawn-failed",`CI run failed: ${ee(k)}`),2}let b=n.format==="json"&&!n.quiet?P(g.document):void 0;if(n.exportJson)if(b)await Z(b,n.exportJson);else await l(g.document,n.exportJson);if(n.saveBaseline&&g.summary.regressed===0&&g.summary.failed===0)await l(g.document,u(h,n.baseline));let A=g.summary.failed>0?2:g.summary.regressed>0?1:0;if(g.summary.failed>0){let k=g.summary.results.filter((v)=>v.harnessFailed).map((v)=>t(v.workload));await _("command-failed",`${g.summary.failed} workload(s) failed (harness error, a command exited non-zero or produced no samples): ${k.join(", ")}`)}if(!n.quiet){let k=n.baseline??h.baseline;if(n.format==="table"){if(await q(Me(g.summary)),g.document.comparisons&&g.document.comparisons.length>0)await ue(await m.table.render(g.document,{}))}else if(b!==void 0)await q(b);else if(n.format==="markdown")await q(`## ostia ci
169
205
 
170
- Baseline: \`${M}\` (\`${o(h,n.baseline)}\`) \xB7 ${y.summary.cached} cached, ${y.summary.executed} executed
206
+ Baseline: \`${k}\` (\`${u(h,n.baseline)}\`) \xB7 ${g.summary.cached} cached, ${g.summary.executed} executed
171
207
 
172
- `),await ie(await i.markdown.render(y.document,{}));else await ie(await i[n.format].render(y.document,{protocol:{command:"ci",exitCode:D,unmatched:y.summary.unmatched,baseGit:y.baseline.git,candGit:y.document.git,baseline:{name:M,path:o(h,n.baseline)},cached:y.summary.cached,executed:y.summary.executed,failed:y.summary.failed,missingBaseline:y.summary.missingBaseline,...n.exportJson&&{exportedTo:n.exportJson}}}))}return D}var Te=/^[A-Za-z0-9._-]+$/;function Ie(a){if(a.startsWith("-"))return`Invalid baseline name "${a}": names can't start with "-".`;if(!Te.test(a))return`Invalid baseline name "${a}": expected to match ${Te}.`;return}async function dn(a){if(a.includes("--help")||a.includes("-h"))return V(de,!0);if(a.length>1)return await N("invalid-flag",`"ostia baseline save" takes at most one name argument, got ${a.length}.
173
- Run 'ostia baseline --help'.`),2;let n=a[0];if(n!==void 0){let y=Ie(n);if(y)return await N("invalid-flag",`${y}
174
- Run 'ostia baseline --help'.`),2}let f=await me("ostia baseline save");if(!f)return 2;let h=await $e(f,n);return await H(`Wrote ${h}
175
- `),0}async function pn(a){if(a.includes("--help")||a.includes("-h"))return V(de,!0);let n=await me();if(!n)return 2;let f=await Me(n);if(f.length===0)return await H(`No baselines found in ${n.baselineDir}.
176
- `),0;for(let h of f){let y=h.git?` ${g(h.git)}`:"";await H(`${h.name} ${h.workloads} workloads created ${h.createdAt} toolVersion ${h.toolVersion}${y}
177
- `)}return 0}async function fn(a){let[n,...f]=a;if(!n||n==="--help"||n==="-h")return V(de,!!n);let h=Ie(n);if(h)return await N("invalid-flag",`${h}
178
- Run 'ostia baseline --help'.`),2;let y=await me();if(!y)return 2;return je([o(y,n),...f])}async function Ne(a,n,f,h,y,C=""){if(a===void 0||a==="--help"||a==="-h")return V(h,a!==void 0);let D=f[a];if(!D)return await N("invalid-flag",y(a)),2;try{return await D(n)}catch(M){if(M instanceof P)return await N("config-invalid",M.message),2;if(M instanceof se)return Ue(M,`${C}${a}`);return await N("internal",`Internal error: ${M instanceof Error?M.stack??M.message:String(M)}`),2}}async function gn(a){let[n,...f]=a;return Ne(n,f,{save:dn,list:pn,show:fn},de,(h)=>`Unknown "ostia baseline ${h}". Run "ostia baseline --help".`,"baseline ")}var hn=`ostia - profiling and benchmarking for Bun
208
+ `),await ue(await m.markdown.render(g.document,{}));else await ue(await m[n.format].render(g.document,{protocol:{command:"ci",exitCode:A,unmatched:g.summary.unmatched,baseGit:g.baseline.git,candGit:g.document.git,baseline:{name:k,path:u(h,n.baseline)},cached:g.summary.cached,executed:g.summary.executed,failed:g.summary.failed,missingBaseline:g.summary.missingBaseline,...n.exportJson&&{exportedTo:n.exportJson}}}))}return A}var je=/^[A-Za-z0-9._-]+$/;function He(o){if(o.startsWith("-"))return`Invalid baseline name "${o}": names can't start with "-".`;if(!je.test(o))return`Invalid baseline name "${o}": expected to match ${je}.`;return}async function wt(o){if(o.includes("--help")||o.includes("-h"))return z(he,!0);if(o.length>1)return await _("invalid-flag",`"ostia baseline save" takes at most one name argument, got ${o.length}.
209
+ Run 'ostia baseline --help'.`),2;let n=o[0];if(n!==void 0){let g=He(n);if(g)return await _("invalid-flag",`${g}
210
+ Run 'ostia baseline --help'.`),2}let p=await fe("ostia baseline save");if(!p)return 2;let h=await Se(p,n);return await q(`Wrote ${h}
211
+ `),0}async function kt(o){if(o.includes("--help")||o.includes("-h"))return z(he,!0);let n=await fe();if(!n)return 2;let p=await Fe(n);if(p.length===0)return await q(`No baselines found in ${n.baselineDir}.
212
+ `),0;for(let h of p){let g=h.git?` ${w(h.git)}`:"";await q(`${h.name} ${h.workloads} workloads created ${h.createdAt} toolVersion ${h.toolVersion}${g}
213
+ `)}return 0}async function vt(o){let[n,...p]=o;if(!n||n==="--help"||n==="-h")return z(he,!!n);let h=He(n);if(h)return await _("invalid-flag",`${h}
214
+ Run 'ostia baseline --help'.`),2;let g=await fe();if(!g)return 2;return _e([u(g,n),...p])}async function We(o,n,p,h,g,b=""){if(o===void 0||o==="--help"||o==="-h")return z(h,o!==void 0);let A=p[o];if(!A)return await _("invalid-flag",g(o)),2;try{return await A(n)}catch(k){if(k instanceof T)return await _("config-invalid",k.message),2;if(k instanceof Y)return Je(k,`${b}${o}`);return await _("internal",`Internal error: ${k instanceof Error?k.stack??k.message:String(k)}`),2}}async function yt(o){let[n,...p]=o;return We(n,p,{save:wt,list:kt,show:vt},he,(h)=>`Unknown "ostia baseline ${h}". Run "ostia baseline --help".`,"baseline ")}var Ct=`ostia - profiling and benchmarking for Bun
179
215
 
180
216
  Commands:
181
217
  time Time commands N times and report timing/CPU/heap
182
218
  bench Run in-process benchmark suites (group()/task())
219
+ ab Pair suites against a git ref in one process, gate on regressions
183
220
  compare Compare two ProfileDocuments
184
221
  report Render a saved ProfileDocument (table/json/markdown/collapsed/mermaid/speedscope/...)
185
222
  ci Run configured workloads against a baseline, gate on regressions
186
223
  baseline Manage baseline ProfileDocuments (save/list/show)
187
224
 
188
225
  Run "ostia <command> --help" for details.
189
- `;async function bn(){let[a,...n]=process.argv.slice(2);return Fe=n,Ne(a,n,{time:Ze,bench:en,compare:on,report:je,ci:mn,baseline:gn},hn,(f)=>`Unknown subcommand "${f}". Run "ostia --help".`)}if(import.meta.main)bn().then((a)=>process.exit(a));export{se as CliUsageError,He as parseIntFlag};
226
+ `;async function xt(){let[o,...n]=process.argv.slice(2);return Ie=n,We(o,n,{time:tt,bench:ot,ab:rt,compare:mt,report:_e,ci:bt,baseline:yt},Ct,(p)=>`Unknown subcommand "${p}". Run "ostia --help".`)}if(import.meta.main)xt().then((o)=>process.exit(o));export{Y as CliUsageError,Ge as parseIntFlag};