@kaptures/cli 0.6.0 → 0.6.1

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.
Files changed (2) hide show
  1. package/dist/index.js +3 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import{createRequire as e}from"node:module";import{formatWithOptions as t,parseA
3
3
  `)}function Ie(e){return typeof e==`function`?e():e}function Le(e=[],t={}){let r=new Set(t.boolean||[]),i=new Set(t.string||[]),a=t.alias||{},o=t.default||{},s=new Map,c=new Map;for(let[e,t]of Object.entries(a)){let n=t;for(let t of n)s.set(e,t),c.has(t)||c.set(t,[]),c.get(t).push(e),s.set(t,e),c.has(e)||c.set(e,[]),c.get(e).push(t)}let l={};function u(e){if(r.has(e))return`boolean`;let t=c.get(e)||[];for(let e of t)if(r.has(e))return`boolean`;return`string`}let d=new Set([...r,...i,...Object.keys(a),...Object.values(a).flat(),...Object.keys(o)]);for(let e of d)l[e]||(l[e]={type:u(e),default:o[e]});for(let[e,t]of s.entries())e.length===1&&l[t]&&!l[t].short&&(l[t].short=e);let f=[],p={};for(let t=0;t<e.length;t++){let n=e[t];if(n===`--`){f.push(...e.slice(t));break}if(n.startsWith(`--no-`)){let e=n.slice(5);p[e]=!0;continue}f.push(n)}let m;try{m=n({args:f,options:Object.keys(l).length>0?l:void 0,allowPositionals:!0,strict:!1})}catch{m={values:{},positionals:f}}let h={_:[]};h._=m.positionals;for(let[e,t]of Object.entries(m.values))h[e]=t;for(let[e]of Object.entries(p)){h[e]=!1;let t=s.get(e);t&&(h[t]=!1);let n=c.get(e);if(n)for(let e of n)h[e]=!1}for(let[e,t]of s.entries())h[e]!==void 0&&h[t]===void 0&&(h[t]=h[e]),h[t]!==void 0&&h[e]===void 0&&(h[e]=h[t]);return h}function Re(e,t){let n={boolean:[],string:[],alias:{},default:{}},r=ze(t);for(let e of r){if(e.type===`positional`)continue;e.type===`string`||e.type===`enum`?n.string.push(e.name):e.type===`boolean`&&n.boolean.push(e.name),e.default!==void 0&&(n.default[e.name]=e.default),e.alias&&(n.alias[e.name]=e.alias);let t=ke(e.name),r=Ae(e.name);if(t!==e.name||r!==e.name){let i=Pe(n.alias[e.name]||[]);t!==e.name&&!i.includes(t)&&i.push(t),r!==e.name&&!i.includes(r)&&i.push(r),i.length>0&&(n.alias[e.name]=i)}}let i=Le(e,n),[...a]=i._,o=new Proxy(i,{get(e,t){return e[t]??e[ke(t)]??e[Ae(t)]}});for(let[,e]of r.entries())if(e.type===`positional`){let t=a.shift();if(t!==void 0)o[e.name]=t;else if(e.default===void 0&&e.required!==!1)throw new Ge(`Missing required positional argument: ${e.name.toUpperCase()}`,`EARG`);else o[e.name]=e.default}else if(e.type===`enum`){let t=o[e.name],n=e.options||[];if(t!==void 0&&n.length>0&&!n.includes(t))throw new Ge(`Invalid value for argument: ${Ye(`--${e.name}`)} (${Ye(t)}). Expected one of: ${n.map(e=>Ye(e)).join(`, `)}.`,`EARG`)}else if(e.required&&o[e.name]===void 0)throw new Ge(`Missing required argument: --${e.name}`,`EARG`);return o}function ze(e){let t=[];for(let[n,r]of Object.entries(e||{}))t.push({...r,name:n,alias:Pe(r.alias)});return t}function D(e){return e}async function Be(e,t){let n=await Ie(e.args||{}),r=Re(t.rawArgs,n),i={rawArgs:t.rawArgs,args:r,data:t.data,cmd:e};typeof e.setup==`function`&&await e.setup(i);let a;try{let n=await Ie(e.subCommands);if(n&&Object.keys(n).length>0){let r=t.rawArgs.findIndex(e=>!e.startsWith(`-`)),i=t.rawArgs[r];if(i){if(!n[i])throw new Ge(`Unknown command ${Ye(i)}`,`E_UNKNOWN_COMMAND`);let e=await Ie(n[i]);e&&await Be(e,{rawArgs:t.rawArgs.slice(r+1)})}else if(!e.run)throw new Ge(`No command specified.`,`E_NO_COMMAND`)}typeof e.run==`function`&&(a=await e.run(i))}finally{typeof e.cleanup==`function`&&await e.cleanup(i)}return{result:a}}async function Ve(e,t,n){let r=await Ie(e.subCommands);if(r&&Object.keys(r).length>0){let n=t.findIndex(e=>!e.startsWith(`-`)),i=t[n],a=await Ie(r[i]);if(a)return Ve(a,t.slice(n+1),e)}return[e,n]}async function He(e,t){try{console.log(await Ue(e,t)+`
4
4
  `)}catch(e){console.error(e)}}async function Ue(e,t){let n=await Ie(e.meta||{}),r=ze(await Ie(e.args||{})),i=await Ie(t?.meta||{}),a=`${i.name?`${i.name} `:``}`+(n.name||process.argv[1]),o=[],s=[],c=[],l=[];for(let e of r)if(e.type===`positional`){let t=e.name.toUpperCase(),n=e.required!==!1&&e.default===void 0,r=e.default?`="${e.default}"`:``;s.push([Ye(t+r),e.description||``,e.valueHint?`<${e.valueHint}>`:``]),l.push(n?`<${t}>`:`[${t}]`)}else{let t=e.required===!0&&e.default===void 0,n=[...(e.alias||[]).map(e=>`-${e}`),`--${e.name}`].join(`, `)+(e.type===`string`&&(e.valueHint||e.default)?`=${e.valueHint?`<${e.valueHint}>`:`"${e.default||``}"`}`:``)+(e.type===`enum`&&e.options?`=<${e.options.join(`|`)}>`:``);if(o.push([Ye(n+(t?` (required)`:``)),e.description||``]),e.type===`boolean`&&(e.default===!0||e.negativeDescription)&&!Qe.test(e.name)){let n=[...(e.alias||[]).map(e=>`--no-${e}`),`--no-${e.name}`].join(`, `);o.push([Ye(n+(t?` (required)`:``)),e.negativeDescription||``])}t&&l.push(n)}if(e.subCommands){let t=[],n=await Ie(e.subCommands);for(let[e,r]of Object.entries(n)){let n=await Ie((await Ie(r))?.meta);n?.hidden||(c.push([Ye(e),n?.description||``]),t.push(e))}l.push(t.join(`|`))}let u=[],d=n.version||i.version;u.push(Xe(`${n.description} (${a+(d?` v${d}`:``)})`),``);let f=o.length>0||s.length>0;return u.push(`${Ze(Je(`USAGE`))} ${Ye(`${a}${f?` [OPTIONS]`:``} ${l.join(` `)}`)}`,``),s.length>0&&(u.push(Ze(Je(`ARGUMENTS`)),``),u.push(Fe(s,` `)),u.push(``)),o.length>0&&(u.push(Ze(Je(`OPTIONS`)),``),u.push(Fe(o,` `)),u.push(``)),c.length>0&&(u.push(Ze(Je(`COMMANDS`)),``),u.push(Fe(c,` `)),u.push(``,`Use ${Ye(`${a} <command> --help`)} for more information about a command.`)),u.filter(e=>typeof e==`string`).join(`
5
5
  `)}async function We(e,t={}){let n=t.rawArgs||process.argv.slice(2),r=t.showUsage||He;try{if(n.includes(`--help`)||n.includes(`-h`))await r(...await Ve(e,n)),process.exit(0);else if(n.length===1&&n[0]===`--version`){let t=typeof e.meta==`function`?await e.meta():await e.meta;if(!t?.version)throw new Ge(`No version specified`,`E_NO_VERSION`);console.log(t.version)}else await Be(e,{rawArgs:n})}catch(t){t instanceof Ge?(await r(...await Ve(e,n)),console.error(t.message)):console.error(t,`
6
- `),process.exit(1)}}var Ge,Ke,qe,Je,Ye,Xe,Ze,Qe,O=w((()=>{Ne(),Ge=class extends Error{code;constructor(e,t){super(e),this.name=`CLIError`,this.code=t}},Ke=(()=>{let e=globalThis.process?.env??{};return e.NO_COLOR===`1`||e.TERM===`dumb`||e.TEST||e.CI})(),qe=(e,t=39)=>n=>Ke?n:`\u001B[${e}m${n}\u001B[${t}m`,Je=qe(1,22),Ye=qe(36),Xe=qe(90),Ze=qe(4,24),Qe=/^no[-A-Z]/}));O();var $e=`0.6.0`;const et=e(import.meta.url);async function tt(e=!1){let t=et.resolve(`agent-browser/package.json`),n=[f(a(t),`bin`,`agent-browser.js`),`install`];e&&n.push(`--with-deps`);let i=await new Promise((e,t)=>{let i=r(process.execPath,n,{stdio:`inherit`});i.once(`error`,t),i.once(`exit`,(n,r)=>{r?t(Error(`agent-browser install stopped by ${r}`)):e(n??1)})});if(i!==0)throw Error(`agent-browser install exited with code ${i}`)}const nt=D({meta:{name:`browser`,description:`Manage the Kapture browser runtime`},subCommands:{install:D({meta:{name:`install`,description:`Install the Chrome runtime used by agent-browser`},args:{"with-deps":{type:`boolean`,default:!1,description:`Also install Linux system dependencies`}},async run({args:e}){await tt(e[`with-deps`])}})}}),rt=[`npm`,`yarn`,`pnpm`,`bun`],it={node:`actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38`,bun:`oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6`,checkout:`actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803`,upload:`actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f`,download:`actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53`},k=e=>`\${{ ${e} }}`,at=JSON.stringify,ot=(e,t=10)=>e.split(`
6
+ `),process.exit(1)}}var Ge,Ke,qe,Je,Ye,Xe,Ze,Qe,O=w((()=>{Ne(),Ge=class extends Error{code;constructor(e,t){super(e),this.name=`CLIError`,this.code=t}},Ke=(()=>{let e=globalThis.process?.env??{};return e.NO_COLOR===`1`||e.TERM===`dumb`||e.TEST||e.CI})(),qe=(e,t=39)=>n=>Ke?n:`\u001B[${e}m${n}\u001B[${t}m`,Je=qe(1,22),Ye=qe(36),Xe=qe(90),Ze=qe(4,24),Qe=/^no[-A-Z]/}));O();var $e=`0.6.1`;const et=e(import.meta.url);async function tt(e=!1){let t=et.resolve(`agent-browser/package.json`),n=[f(a(t),`bin`,`agent-browser.js`),`install`];e&&n.push(`--with-deps`);let i=await new Promise((e,t)=>{let i=r(process.execPath,n,{stdio:`inherit`});i.once(`error`,t),i.once(`exit`,(n,r)=>{r?t(Error(`agent-browser install stopped by ${r}`)):e(n??1)})});if(i!==0)throw Error(`agent-browser install exited with code ${i}`)}const nt=D({meta:{name:`browser`,description:`Manage the Kapture browser runtime`},subCommands:{install:D({meta:{name:`install`,description:`Install the Chrome runtime used by agent-browser`},args:{"with-deps":{type:`boolean`,default:!1,description:`Also install Linux system dependencies`}},async run({args:e}){await tt(e[`with-deps`])}})}}),rt=[`npm`,`yarn`,`pnpm`,`bun`],it={node:`actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38`,bun:`oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6`,checkout:`actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803`,upload:`actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f`,download:`actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53`},k=e=>`\${{ ${e} }}`,at=JSON.stringify,ot=(e,t=10)=>e.split(`
7
7
  `).map(e=>`${` `.repeat(t)}${e}`).join(`
8
8
  `);function st(e){let t=` - uses: ${it.node}\n with: { node-version: "24" }\n`;return e===`bun`?`${t} - uses: ${it.bun}\n`:e===`yarn`||e===`pnpm`?`${t} - run: corepack enable\n`:t}function ct(e,t){if(!/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(t))throw Error(`CLI version must be exact SemVer`);let n=`@kaptures/cli@${t}`;switch(e){case`npm`:return`npx --yes ${n}`;case`yarn`:return`yarn dlx --package ${n} kapture`;case`pnpm`:return`pnpm dlx ${n}`;case`bun`:return`bunx ${n}`}}function lt(e){let t=e.packageManager;if(!rt.includes(t))throw Error(`Unsupported package manager`);let n=ct(`npm`,e.cliVersion),r=st(`npm`),i=st(t),a=e.baseBranch??`main`,o=e.storybookDirectory??`storybook-static`,s=e.adapterPackageJson;for(let e of[o,...s?[s]:[]])if(!/^[A-Za-z0-9._/-]+$/.test(e)||e.split(`/`).some(e=>!e||e===`.`||e===`..`))throw Error(`Expected safe project-relative paths`);if(!a||[...a].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127))throw Error(`Expected a branch name`);let c=e.installCommand??{npm:`npm ci`,yarn:`case "$(yarn --version)" in
9
9
  1.*) yarn install --frozen-lockfile ;;
@@ -627,5 +627,5 @@ ${r}`)}formatType(e,t,n){let r=fh[e.type]||ph[e.level]||`gray`;if(t)return xh(r)
627
627
  `+r.join(`
628
628
  `):``),e.type===`trace`){let t=Error(`Trace: `+e.message);l+=this.formatStack(t.stack||``,t.message)}return o?`
629
629
  `+l+`
630
- `:l}};function yh(e){return e.replace(/`([^`]+)`/gm,(e,t)=>Kf.cyan(t)).replace(/\s+_([^_]+)_\s+/gm,(e,t)=>` ${Kf.underline(t)} `)}function bh(e=`white`){return Kf[e]||Kf.white}function xh(e=`bgWhite`){return Kf[`bg${e[0].toUpperCase()}${e.slice(1)}`]||Kf.bgWhite}function Sh(e={}){let t=Ch();return process.env.CONSOLA_LEVEL&&(t=Number.parseInt(process.env.CONSOLA_LEVEL)??t),Ef({level:t,defaults:{level:t},stdout:process.stdout,stderr:process.stderr,prompt:(...e)=>Promise.resolve().then(()=>(Em(),$f)).then(t=>t.prompt(...e)),reporters:e.reporters||[e.fancy??!(Im||zm)?new vh:new Af],...e})}function Ch(){return Rm?K.debug:zm?K.warn:K.info}const Q=Sh();function wh(e){let t=qh.safeParse(Th(e));if(!t.success){let e=t.error.issues[0],n=e?.path.length?` at ${e.path.join(`.`)}`:``;throw Error(`Invalid Kapture report${n}: ${e?.message??`unknown error`}`)}return t.data}function Th(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e;return t.version!==2||!t.summary||typeof t.summary!=`object`?e:{...t,version:3,summary:{...t.summary,unstable:0}}}async function Eh(e){let t=f(e),n=await C(t);if(!n.isFile()||n.size>10485760)throw Error(`Kapture report must be a file no larger than ${Oh} bytes`);let r;try{r=JSON.parse(await x(t,`utf8`))}catch{throw Error(`Kapture report does not contain valid JSON`)}return wh(r)}function Dh(e){try{let t=new URL(e);return t.protocol===`https:`&&!t.username&&!t.password}catch{return!1}}var Oh,kh,Ah,$,jh,Mh,Nh,Ph,Fh,Ih,Lh,Rh,zh,Bh,Vh,Hh,Uh,Wh,Gh,Kh,qh,Jh=w((()=>{Td(),Nc(),Oh=10485760,kh=2e4,Ah=R().max(4096),$=R().min(1).max(512),jh=$.refine(e=>Array.from(e).every(e=>{let t=e.codePointAt(0)??0;return t>31&&t!==127}),`must not contain control characters`),Mh=z().int().min(0).max(2**53-1),Nh=z().int().positive().max(2**53-1),Ph=z().min(0).max(1),Fh=B({name:$,width:z().int().positive().max(16384),height:z().int().positive().max(16384)}),Ih=B({pixelColorThreshold:Ph,maxChangedPixelRatio:Ph}),Lh=B({id:$,browser:$,browserVersion:$,orchestratorRuntime:$,operatingSystem:$,architecture:$,deviceScaleFactor:z().positive().max(8),locale:$,timezone:$,colorScheme:Es([`light`,`dark`]),reducedMotion:Es([`reduce`,`no-preference`]),frozenTime:$,randomSeed:z().int().min(0).max(2**53-1),fontsFingerprint:$,stateIsolation:H(`fresh-browser-process-per-story-side-v1`).optional(),network:B({mode:H(`allowlist`),allowedDomains:xs($).max(100),webRtc:H(`disabled`)})}),Rh=B({id:$,storyId:$,title:Ah,name:Ah,viewport:Fh,status:Es([`unchanged`,`changed`,`unstable`,`added`,`removed`,`error`]),baseImage:Ah.optional(),headImage:Ah.optional(),diffImage:Ah.optional(),ignoredRegions:xs(B({x:z().int().min(0).max(16384),y:z().int().min(0).max(32768),width:z().int().positive().max(16384),height:z().int().positive().max(32768)})).max(1e4).optional(),changedPixels:Mh.optional(),diffRatio:Ph.optional(),threshold:Ih.optional(),instability:B({base:B({repeatImage:Ah,diffImage:Ah,changedPixels:Mh,diffRatio:Ph}).optional(),head:B({repeatImage:Ah,diffImage:Ah,changedPixels:Mh,diffRatio:Ph}).optional()}).optional(),error:Ah.optional()}).superRefine((e,t)=>{e.status===`unstable`&&!e.instability?.base&&!e.instability?.head&&t.addIssue({code:`custom`,path:[`instability`],message:`unstable snapshots require base or head instability evidence`}),e.status!==`unstable`&&e.instability&&t.addIssue({code:`custom`,path:[`instability`],message:`only unstable snapshots can contain instability evidence`})}),zh=xs($).max(kh).refine(e=>new Set(e).size===e.length,`must not contain duplicates`).refine(e=>e.every((t,n)=>n===0||e[n-1]<t),`must be sorted`),Bh=B({code:Es([`base-manifest-missing`,`base-manifest-invalid`,`head-manifest-missing`,`head-manifest-invalid`,`changed-files-incomplete`,`manifest-incomplete`,`global-input`,`global-output`,`global-runtime`,`unknown-input`,`story-import-missing`,`story-module-missing`,`fallback-reasons-truncated`]),path:Ah.optional(),storyId:$.optional(),side:Es([`base`,`head`]).optional()}),Vh=B({provider:H(`github-pull-request-files`),manifestDigest:R().regex(/^[0-9a-f]{64}$/),pullRequestNumber:Nh,baseSha:R().regex(/^[0-9a-f]{40}$/),headSha:R().regex(/^[0-9a-f]{40}$/)}),Hh=R().regex(/^[0-9a-f]{64}$/),Uh=ws(`state`,[B({state:H(`valid`),digest:Hh,revision:$}),B({state:H(`invalid`),digest:Hh.optional(),revision:$}),B({state:H(`missing`),revision:$})]),Wh=B({base:Uh,head:Uh}),Gh=B({repository:$.regex(/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/),number:Nh,url:Ah.refine(Dh,`must be an HTTPS URL without credentials`),baseBranch:jh,headBranch:jh,workflowRunUrl:Ah.refine(Dh,`must be an HTTPS URL without credentials`)}),Kh=B({plannerVersion:H(1),mode:Es([`full`,`affected`,`full-fallback`]),changedFilesEvidence:Vh.optional(),dependencyManifests:Wh.optional(),storyIds:zh,selectedStoryIds:zh,skippedStoryIds:zh,addedStoryIds:zh.optional(),removedStoryIds:zh.optional(),fallbackReasons:xs(Bh).max(yd),baseline:B({mode:H(`reused`),revision:$,manifestDigest:Hh}).optional()}).superRefine((e,t)=>{let n=new Set(e.storyIds),r=new Set(e.selectedStoryIds),i=new Set(e.skippedStoryIds);if((r.size+i.size!==n.size||[...r].some(e=>!n.has(e)||i.has(e))||[...i].some(e=>!n.has(e)))&&t.addIssue({code:`custom`,message:`selected and skipped stories must exactly partition the story catalog`}),e.mode!==`affected`&&i.size>0&&t.addIssue({code:`custom`,path:[`skippedStoryIds`],message:`full coverage modes cannot skip stories`}),e.mode===`full-fallback`&&e.fallbackReasons.length===0&&t.addIssue({code:`custom`,path:[`fallbackReasons`],message:`full-fallback coverage requires at least one reason`}),e.mode!==`full-fallback`&&e.fallbackReasons.length>0&&t.addIssue({code:`custom`,path:[`fallbackReasons`],message:`only full-fallback coverage can contain fallback reasons`}),e.addedStoryIds===void 0!=(e.removedStoryIds===void 0)&&t.addIssue({code:`custom`,message:`added and removed story catalogs must be provided together`}),e.addedStoryIds&&e.removedStoryIds){let i=new Set(e.addedStoryIds),a=new Set(e.removedStoryIds);([...i].some(e=>!n.has(e)||!r.has(e)||a.has(e))||[...a].some(e=>!n.has(e)||!r.has(e)))&&t.addIssue({code:`custom`,message:`added and removed stories must be disjoint selected catalog members`})}}),qh=B({version:H(3),contentDigest:R().regex(/^[0-9a-f]{64}$/).optional(),baseRevision:$,headRevision:$,headBranch:jh.optional(),baseBranch:jh.optional(),pullRequest:Gh.optional(),storybookUrl:Ah.refine(e=>e===`./storybook/`||Dh(e),`must be an HTTPS URL or ./storybook/ without credentials`).optional(),environment:Lh,createdAt:$,threshold:Ih,summary:B({total:Mh,unchanged:Mh,changed:Mh,unstable:Mh,added:Mh,removed:Mh,errors:Mh}),coverage:Kh.optional(),entries:V(R(),Rh)}).superRefine((e,t)=>{let n=Object.entries(e.entries);if(n.length>2e4){t.addIssue({code:`custom`,message:`Report contains more than ${kh} entries`,path:[`entries`]});return}for(let[e,r]of n)e!==r.id&&t.addIssue({code:`custom`,message:`Entry key must match entry.id`,path:[`entries`,e,`id`]});let r={unchanged:0,changed:0,unstable:0,added:0,removed:0,error:0};for(let t of Object.values(e.entries))r[t.status]+=1;if((e.summary.total!==n.length||e.summary.unchanged!==r.unchanged||e.summary.changed!==r.changed||e.summary.unstable!==r.unstable||e.summary.added!==r.added||e.summary.removed!==r.removed||e.summary.errors!==r.error)&&t.addIssue({code:`custom`,message:`Report summary does not match its entries`,path:[`summary`]}),e.coverage){let r=e.coverage.changedFilesEvidence;r&&(r.baseSha!==e.baseRevision||r.headSha!==e.headRevision)&&t.addIssue({code:`custom`,message:`Changed-files evidence must match the report base and head revisions`,path:[`coverage`,`changedFilesEvidence`]});let i=e.coverage.dependencyManifests;i&&(i.base.revision!==e.baseRevision||i.head.revision!==e.headRevision)&&t.addIssue({code:`custom`,message:`Dependency manifest evidence must match the report base and head revisions`,path:[`coverage`,`dependencyManifests`]});let a=new Set(e.coverage.selectedStoryIds),o=new Set(e.coverage.addedStoryIds??[]),s=new Set(e.coverage.removedStoryIds??[]);for(let[e,r]of n)a.has(r.storyId)||t.addIssue({code:`custom`,message:`Report entries must belong to selected stories`,path:[`entries`,e,`storyId`]}),o.has(r.storyId)&&r.status!==`added`&&r.status!==`error`&&t.addIssue({code:`custom`,message:`Entries for an added story must be added or error snapshots`,path:[`entries`,e,`status`]}),s.has(r.storyId)&&r.status!==`removed`&&r.status!==`error`&&t.addIssue({code:`custom`,message:`Entries for a removed story must be removed or error snapshots`,path:[`entries`,e,`status`]})}})}));Td(),O();var Yh=Bt();Jh();const Xh=26214400,Zh=Buffer.from([137,80,78,71,13,10,26,10]),Qh=new Set([`acTL`,`fcTL`,`fdAT`]),$h=[`baseImage`,`headImage`,`diffImage`,`baseRepeatImage`,`baseInstabilityDiffImage`,`headRepeatImage`,`headInstabilityDiffImage`],eg=D({meta:{name:`build`,description:`Rebuild a trusted static report from an untrusted Kapture artifact`},args:{input:{type:`string`,required:!0,description:`Untrusted artifact report directory containing report.json and images`},output:{type:`string`,required:!0,description:`New directory for the trusted static report`},"storybook-url":{type:`string`,description:`Trusted HTTPS Storybook URL or the fixed same-origin ./storybook/ directory`},"base-branch":{type:`string`,description:`Trusted base branch display label (not a comparison revision)`},"head-branch":{type:`string`,description:`Trusted head branch display label (not a comparison revision)`}},async run({args:e}){let t=await tg({inputDir:e.input,outputDir:e.output,storybookUrl:e[`storybook-url`],trustedBaseBranch:e[`base-branch`],trustedHeadBranch:e[`head-branch`]});Q.success(`Trusted report: ${t.report.summary.total} snapshots, ${t.imageCount} verified PNGs (${t.imageBytes} bytes)`),Q.info(`Output: ${t.outputDir}`)}});async function tg(e){let t=f(e.inputDir),n=f(e.outputDir),r=ng(e.trustedHeadBranch),i=ng(e.trustedBaseBranch);if(await mg(t),_g(t,n))throw Error(`Trusted report output must be outside the untrusted input directory`);await hg(n);let o=e.dashboardDir?f(e.dashboardDir):f(a(pe(import.meta.url)),`dashboard`),s=a(n);await y(s,{recursive:!0});let c=await b(`${s}${p}.kapture-report-`),l;try{l=await ig(t,async(e,t)=>{let n=f(c,e.relativePath);await y(a(n),{recursive:!0}),await ie(n,t,{flag:`wx`})});let{report:s,imageDigests:u,calculatedContentDigest:d}=l;if(s.contentDigest&&s.contentDigest!==d)throw Error(`Report content digest does not match its referenced PNGs: expected ${s.contentDigest}, calculated ${d}`);r?s.headBranch=r:delete s.headBranch,i?s.baseBranch=i:delete s.baseBranch,e.trustedPullRequest?s.pullRequest={...e.trustedPullRequest}:delete s.pullRequest;let p=zd(e.storybookUrl);p?s.storybookUrl=p:delete s.storybookUrl,s.contentDigest=Qc(s,u),await ie(f(c,`report.json`),`${JSON.stringify(s)}\n`,{flag:`wx`}),await Wu(o,c),await ne(c,n)}catch(e){throw await re(c,{recursive:!0,force:!0}),e}if(!l)throw Error(`Trusted report validation did not complete`);return{report:l.report,outputDir:n,imageCount:l.references.length,imageBytes:l.imageBytes}}function ng(e){if(e!==void 0){if(e.length<1||e.length>512||Array.from(e).some(e=>{let t=e.codePointAt(0)??0;return t<=31||t===127}))throw Error(`Trusted head branch must contain between 1 and 512 non-control characters`);return e}}async function rg(e,t){if(!/^[0-9a-f]{64}$/.test(t))throw Error(`Expected trusted report content digest must be a lowercase SHA-256 digest`);let n=f(e);if(n!==f(a(n),`report.json`))throw Error(`Trusted report path must end in report.json`);let r=a(n);await mg(r);let i=await ig(r);if(i.report.contentDigest!==t||i.calculatedContentDigest!==t)throw Error(`Trusted report content digest does not match its actual structure and referenced PNGs`);return i.report}async function ig(e,t){let n=ag(await gg(e,`report.json`,Oh)),r=og(n);if(r.length>6e4)throw Error(`Report references more than 60000 PNG images`);let i=new Map,a=[],o=0;for(let n of r){let r=await gg(e,n.relativePath,Xh);if(o+=r.byteLength,o>536870912)throw Error(`Referenced PNGs exceed 536870912 total bytes`);i.set(n.relativePath,dg(r,n.relativePath)),a.push({path:n.relativePath,sha256:ae(`sha256`).update(r).digest(`hex`)}),await t?.(n,r)}return pg(n,i),{report:n,references:r,imageDigests:a,imageBytes:o,calculatedContentDigest:Qc(n,a)}}function ag(e){let t;try{t=JSON.parse(e.toString(`utf8`))}catch{throw Error(`Input report.json does not contain valid JSON`)}return wh(t)}function og(e){let t=new Map;for(let n of Object.values(e.entries)){let e=sg(n);for(let r of $h){let i=lg(n,r);if(e.has(r)&&!i)throw Error(`Report entry ${n.id} is missing ${r} for status ${n.status}`);if(!e.has(r)&&i)throw Error(`Report entry ${n.id} cannot contain ${r} for status ${n.status}`);if(!i)continue;let a=ug(i,cg(r),n.id),o=t.get(a);if(o&&o.entryId!==n.id)throw Error(`Report entries ${o.entryId} and ${n.id} reference the same PNG: ${a}`);t.set(a,{relativePath:a,entryId:n.id})}}return[...t.values()]}function sg(e){if(e.status===`changed`)return new Set([`baseImage`,`headImage`,`diffImage`]);if(e.status===`unstable`){if(!e.instability?.base&&!e.instability?.head)throw Error(`Report entry ${e.id} is unstable without instability evidence`);let t=[`baseImage`,`headImage`,`diffImage`];return e.instability.base&&t.push(`baseRepeatImage`,`baseInstabilityDiffImage`),e.instability.head&&t.push(`headRepeatImage`,`headInstabilityDiffImage`),new Set(t)}return e.status===`added`?new Set([`headImage`]):e.status===`removed`?new Set([`baseImage`]):new Set}function cg(e){return e===`baseImage`?`base`:e===`headImage`?`head`:e===`diffImage`?`diff`:e===`baseRepeatImage`?`base-repeat`:e===`baseInstabilityDiffImage`?`base-instability-diff`:e===`headRepeatImage`?`head-repeat`:`head-instability-diff`}function lg(e,t){return t===`baseImage`||t===`headImage`||t===`diffImage`?e[t]:t===`baseRepeatImage`?e.instability?.base?.repeatImage:t===`baseInstabilityDiffImage`?e.instability?.base?.diffImage:t===`headRepeatImage`?e.instability?.head?.repeatImage:e.instability?.head?.diffImage}function ug(e,t,n){let r=`images/${t}/`,i=e.slice(r.length);if(!e.startsWith(r)||!i||i.includes(`/`)||i.includes(`\\`)||i.length>255||!/^[a-zA-Z0-9][a-zA-Z0-9._-]*\.png$/.test(i))throw Error(`Report entry ${n} has an invalid ${t} PNG path: ${e}`);return e}function dg(e,t){if(e.byteLength<33||!e.subarray(0,8).equals(Zh))throw Error(`Referenced image is not a PNG: ${t}`);let n=e.readUInt32BE(8),r=e.toString(`ascii`,12,16);if(n!==13||r!==`IHDR`)throw Error(`Referenced PNG has an invalid IHDR chunk: ${t}`);let i=e.readUInt32BE(16),a=e.readUInt32BE(20);if(i<1||a<1||i>16384||a>32768||i*a>33554432)throw Error(`Referenced PNG dimensions are outside the supported limits: ${t} (${i}x${a})`);fg(e,t);try{let t=Yh.PNG.sync.read(e,{checkCRC:!0,skipRescale:!0});if(t.width!==i||t.height!==a)throw Error(`decoded dimensions differ from IHDR`)}catch{throw Error(`Referenced PNG cannot be decoded safely: ${t}`)}return{width:i,height:a}}function fg(e,t){let n=Zh.byteLength,r=!1;for(;n+12<=e.byteLength;){let i=e.readUInt32BE(n),a=e.toString(`ascii`,n+4,n+8),o=n+12+i;if(o>e.byteLength)throw Error(`Referenced PNG has an invalid chunk boundary: ${t}`);if(Qh.has(a))throw Error(`Animated PNG is not supported in a static report: ${t}`);if(n=o,a===`IEND`){r=!0;break}}if(!r||n!==e.byteLength)throw Error(`Referenced PNG has an invalid chunk structure: ${t}`)}function pg(e,t){for(let n of Object.values(e.entries)){if(n.status!==`changed`&&n.status!==`unstable`||!n.baseImage||!n.headImage||!n.diffImage)continue;let e=t.get(n.baseImage),r=t.get(n.headImage),i=t.get(n.diffImage);if(!e||!r||!i)throw Error(`Report entry ${n.id} is missing validated PNG dimensions`);let a=Math.max(e.width,r.width),o=Math.max(e.height,r.height);for(let e of n.ignoredRegions??[])if(e.x+e.width>a||e.y+e.height>o)throw Error(`Report entry ${n.id} ignored region exceeds its comparison canvas`);if(i.width!==a||i.height!==o)throw Error(`Report entry ${n.id} diff PNG must match the padded comparison canvas ${a}x${o}`);if(n.changedPixels!==void 0&&n.changedPixels>a*o)throw Error(`Report entry ${n.id} changedPixels exceeds its diff PNG pixel count`);for(let i of[n.instability?.base,n.instability?.head]){if(!i)continue;let a=t.get(i.repeatImage),o=t.get(i.diffImage);if(!a||!o)throw Error(`Report entry ${n.id} is missing instability PNG dimensions`);let s=i===n.instability?.base?e:r,c=Math.max(s.width,a.width),l=Math.max(s.height,a.height);if(o.width!==c||o.height!==l)throw Error(`Report entry ${n.id} instability diff PNG must match ${c}x${l}`);if(i.changedPixels>c*l)throw Error(`Report entry ${n.id} instability changedPixels exceeds its diff PNG pixel count`)}}}async function mg(e){let t;try{t=await v(e)}catch(t){throw vg(t)?Error(`Input report directory does not exist: ${e}`):t}if(t.isSymbolicLink()||!t.isDirectory())throw Error(`Input report path must be a real directory, not a symbolic link`)}async function hg(e){try{await v(e)}catch(e){if(vg(e))return;throw e}throw Error(`Trusted report output already exists: ${e}`)}async function gg(e,t,n){if(s(t)||t.includes(`\\`))throw Error(`Input file must be a normalized relative path: ${t}`);let r=t.split(`/`),i=e;for(let[e,n]of r.entries()){if(!n||n===`.`||n===`..`)throw Error(`Input file must be a normalized relative path: ${t}`);i=f(i,n);let a;try{a=await v(i)}catch(e){throw vg(e)?Error(`Referenced input file does not exist: ${t}`):e}if(a.isSymbolicLink())throw Error(`Referenced input path cannot contain a symbolic link: ${t}`);let o=e===r.length-1;if(!o&&!a.isDirectory()||o&&!a.isFile())throw Error(`Referenced input path is not a regular file: ${t}`)}let a=fe.O_RDONLY|(fe.O_NOFOLLOW??0),o=await ee(i,a);try{let e=await o.stat();if(!e.isFile()||e.size>n)throw Error(`Input file exceeds ${n} bytes: ${t}`);let r=Buffer.alloc(e.size),i=0;for(;i<r.byteLength;){let{bytesRead:e}=await o.read(r,i,r.byteLength-i,i);if(e===0)throw Error(`Input file changed while being read: ${t}`);i+=e}let a=Buffer.alloc(1),{bytesRead:s}=await o.read(a,0,1,r.byteLength);if(s>0)throw Error(`Input file changed while being read: ${t}`);return r}finally{await o.close()}}function _g(e,t){let n=d(e,t);return n===``||!n.startsWith(`..${p}`)&&n!==`..`&&!s(n)}function vg(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}function yg(e,t){return xg(e,t).map(({path:e,compressedBytes:t,uncompressedBytes:n})=>({path:e,compressedBytes:t,uncompressedBytes:n}))}async function bg(e,t,n){let r=xg(e,n),i=f(t);await y(i,{recursive:!0});for(let t of r){let n=e.subarray(t.dataOffset,t.dataOffset+t.compressedBytes),r=t.compression===0?Buffer.from(n):xe(n,{maxOutputLength:t.uncompressedBytes+1});if(r.byteLength!==t.uncompressedBytes)throw Error(`ZIP entry size mismatch: ${t.path}`);if(be(r)!==t.crc)throw Error(`ZIP entry checksum mismatch: ${t.path}`);let o=f(i,t.path);if(!o.startsWith(`${i}${p}`))throw Error(`ZIP entry escapes the output directory: ${t.path}`);await y(a(o),{recursive:!0}),await ie(o,r,{flag:`wx`})}return r}function xg(e,t){Eg(t);let n=Sg(e),r=e.readUInt16LE(n+4),i=e.readUInt16LE(n+6),a=e.readUInt16LE(n+8),o=e.readUInt16LE(n+10),s=e.readUInt32LE(n+12),c=e.readUInt32LE(n+16),l=e.readUInt16LE(n+20);if(n+22+l!==e.byteLength)throw Error(`ZIP end record does not match the archive size`);if(r!==0||i!==0||a!==o)throw Error(`Multi-disk ZIP archives are not supported`);if(o===65535||s===4294967295||c===4294967295)throw Error(`ZIP64 archives are not supported`);if(o>t.maxEntries)throw Error(`ZIP archive contains more than ${t.maxEntries} entries`);if(c+s!==n)throw Error(`ZIP central directory is malformed`);let u=[],d=new Set,f=c,p=0;for(let r=0;r<o;r+=1){if(f+46>n||e.readUInt32LE(f)!==33639248)throw Error(`ZIP central directory entry is malformed`);let r=e.readUInt16LE(f+4),i=e.readUInt16LE(f+8),a=e.readUInt16LE(f+10),o=e.readUInt32LE(f+16),s=e.readUInt32LE(f+20),l=e.readUInt32LE(f+24),m=e.readUInt16LE(f+28),h=e.readUInt16LE(f+30),g=e.readUInt16LE(f+32),_=e.readUInt16LE(f+34),v=e.readUInt32LE(f+38),y=e.readUInt32LE(f+42),b=f+46+m+h+g;if(b>n)throw Error(`ZIP central directory entry exceeds its bounds`);if(i&1)throw Error(`Encrypted ZIP entries are not supported`);if(a!==0&&a!==8)throw Error(`ZIP compression method ${a} is not supported`);if(_!==0)throw Error(`Multi-disk ZIP entries are not supported`);if(s===4294967295||l===4294967295||y===4294967295)throw Error(`ZIP64 entries are not supported`);let ee=e.subarray(f+46,f+46+m),x=wg(ee);f=b;let S=x.endsWith(`/`);if(Tg(r,v,x,S),d.has(x))throw Error(`ZIP archive contains duplicate path: ${x}`);if(d.add(x),S){if(!t.allowDirectoryPath(x))throw Error(`ZIP archive contains unexpected directory: ${x}`);if(i&8||a!==0||o!==0||s!==0||l!==0)throw Error(`ZIP directory entry must be empty and stored: ${x}`);Cg(e,y,ee,i,a,o,s,l,c);continue}if(!t.allowPath(x))throw Error(`ZIP archive contains unexpected path: ${x}`);if(l>t.maxFileBytes)throw Error(`ZIP entry exceeds ${t.maxFileBytes} bytes: ${x}`);if(p+=l,p>t.maxTotalBytes)throw Error(`ZIP archive exceeds ${t.maxTotalBytes} uncompressed bytes`);let te=Cg(e,y,ee,i,a,o,s,l,c);u.push({path:x,compression:a,crc:o,compressedBytes:s,uncompressedBytes:l,dataOffset:te})}if(f!==n)throw Error(`ZIP central directory size is inconsistent`);return u}function Sg(e){let t=Math.max(0,e.byteLength-65557);for(let n=e.byteLength-22;n>=t;--n)if(e.readUInt32LE(n)===101010256)return n;throw Error(`ZIP end-of-central-directory record is missing`)}function Cg(e,t,n,r,i,a,o,s,c){if(t+30>c||e.readUInt32LE(t)!==67324752)throw Error(`ZIP local entry header is malformed`);let l=e.readUInt16LE(t+6),u=e.readUInt16LE(t+8),d=e.readUInt32LE(t+14),f=e.readUInt32LE(t+18),p=e.readUInt32LE(t+22),m=e.readUInt16LE(t+26),h=e.readUInt16LE(t+28),g=t+30+m+h;if(g>c)throw Error(`ZIP local entry header exceeds its bounds`);let _=e.subarray(t+30,t+30+m);if(l!==r||u!==i||!_.equals(n))throw Error(`ZIP local and central directory entries do not match`);if(!(l&8)&&(d!==a||f!==o||p!==s))throw Error(`ZIP local and central directory sizes or checksum do not match`);if(g+o>c)throw Error(`ZIP entry data exceeds the archive bounds`);return g}function wg(e){let t=e.toString(`utf8`);if(!Buffer.from(t,`utf8`).equals(e))throw Error(`ZIP path is not valid UTF-8`);let n=t.endsWith(`/`),r=t.split(`/`),i=n?r.slice(0,-1):r;if(t.length<1||t.startsWith(`/`)||t.includes(`\\`)||t.includes(`\0`)||i.some(e=>!e||e===`.`||e===`..`)||Array.from(t).some(e=>{let t=e.codePointAt(0)??0;return t<=31||t===127}))throw Error(`ZIP path is unsafe: ${JSON.stringify(t)}`);return t}function Tg(e,t,n,r){if(e>>>8!=3)return;let i=t>>>16&61440;if(i!==0&&i!==(r?16384:32768))throw Error(r?`ZIP entry is not a directory: ${n}`:`ZIP entry is not a regular file: ${n}`)}function Eg(e){for(let[t,n]of Object.entries({maxEntries:e.maxEntries,maxFileBytes:e.maxFileBytes,maxTotalBytes:e.maxTotalBytes}))if(!Number.isSafeInteger(n)||n<=0)throw Error(`${t} must be positive`)}function Dg(e,t){let n=Fg(e,`GitHub pull_request event`),r=Fg(n.pull_request,`pull_request`),i=Ag(Fg(n.repository,`repository`)),a=Fg(r.base,`pull_request.base`),o=Fg(r.head,`pull_request.head`),s=Ag(Fg(a.repo,`pull_request.base.repo`)),c=Fg(o.repo,`pull_request.head.repo`),l=Mg(a.ref,`pull_request.base.ref`),u=Mg(o.ref,`pull_request.head.ref`),d=Ng(r.number,`pull request number`);if(s!==i)throw Error(`Pull request base repository must match the workflow repository`);if(t!==void 0&&l!==Mg(t,`base branch`))throw Error(`Pull request targets ${l}, expected ${t}`);return{schemaVersion:1,runId:Ng(n.run_id??process.env.GITHUB_RUN_ID,`workflow run ID`),prNumber:d,base:{repository:s,ref:l,sha:jg(a.sha,`pull_request.base.sha`)},head:{repository:Ag(c),repositoryId:Ng(c.id,`head repository ID`),ref:u,sha:jg(o.sha,`pull_request.head.sha`)},preview:{branch:u,alias:kg(d,u)}}}function Og(e){return`pr-${e.prNumber}-base-${e.base.sha}-head-${e.head.sha}`}function kg(e,t){let n=`pr-${Ng(e,`pull request number`)}-`,r=Mg(t,`head branch`),i=r.normalize(`NFKD`).toLowerCase().replace(/[^a-z0-9-]+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``),a=`-${ae(`sha256`).update(r).digest(`hex`).slice(0,10)}`,o=Math.max(1,63-n.length-a.length);return`${n}${(i||`branch`).slice(0,o).replace(/-$/g,``)||`b`}${a}`}function Ag(e){let t=Pg(e.full_name,`repository full name`);if(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(t))throw Error(`GitHub event contains an invalid repository full name`);return t}function jg(e,t){let n=Pg(e,t).toLowerCase();if(!/^[0-9a-f]{40}$/.test(n))throw Error(`${t} must be a full SHA`);return n}function Mg(e,t){let n=Pg(e,t);if(n.length<1||n.length>512)throw Error(`${t} is invalid`);for(let e of n){let n=e.codePointAt(0)??0;if(n<=31||n===127)throw Error(`${t} is invalid`)}return n}function Ng(e,t){let n=typeof e==`string`&&/^[1-9][0-9]*$/.test(e)?Number(e):e;if(typeof n!=`number`||!Number.isSafeInteger(n)||n<=0)throw Error(`${t} must be a positive integer`);return n}function Pg(e,t){if(typeof e!=`string`)throw Error(`${t} must be a string`);return e}function Fg(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}const Ig=3e3;async function Lg(e,t){let n=await e.getPullRequestForCapture(t.prNumber);Bg(n,t);let r=Zg(n.changed_files,`pull request changed_files`),i=[],a=[],o=0;if(r>3e3)i.push({code:`github-file-limit`});else for(let n=1;n<=Math.ceil(r/100);n+=1){let s=await e.listPullRequestFilesPage(t.prNumber,n,100);if(o=n,!Array.isArray(s)){i.push({code:`pagination-incomplete`,page:n});break}let c=s.slice(0,100);s.length>100&&i.push({code:`pagination-incomplete`,page:n});for(let[e,t]of c.entries())a.push({value:t,page:n,index:e});if(c.length<100){a.length<r&&i.push({code:`pagination-incomplete`,page:n});break}}a.length!==r&&i.push({code:`file-count-mismatch`});let s=new Set,c=new Set;for(let e of a)Vg(e,s,c,i);let l=await e.getPullRequestForCapture(t.prNumber);if(Bg(l,t),l.changed_files!==r)throw Error(`Pull request changed while Kapture discovered changed files`);let u=Wg(i);return{kind:`kapture-changed-files`,version:1,complete:u.length===0,pullRequest:{number:t.prNumber,baseSha:t.base.sha,headSha:t.head.sha},files:[...s].sort(),source:{provider:`github-pull-request-files`,expectedFileCount:r,fetchedFileCount:a.length,pageCount:o,perPage:100,maxFiles:Ig},diagnostics:u}}function Rg(e){let t=Qg(e,`changed-files manifest`);if(Jg(t,[`kind`,`version`,`complete`,`pullRequest`,`files`,`source`,`diagnostics`],`changed-files manifest`),t.kind!==`kapture-changed-files`||t.version!==1)throw Error(`changed-files manifest must use kapture-changed-files version 1`);if(typeof t.complete!=`boolean`)throw Error(`changed-files manifest complete must be a boolean`);if(!Array.isArray(t.files)||t.files.length>6e3)throw Error(`changed-files manifest files must be a bounded array`);let n=t.files.map(e=>zg(e,`changed file path`));if(!Gg(n))throw Error(`changed-files manifest files must be unique and sorted`);let r=Qg(t.pullRequest,`changed-files manifest pullRequest`);Jg(r,[`number`,`baseSha`,`headSha`],`changed-files manifest pullRequest`);let i=Qg(t.source,`changed-files manifest source`);if(Jg(i,[`provider`,`expectedFileCount`,`fetchedFileCount`,`pageCount`,`perPage`,`maxFiles`],`changed-files manifest source`),i.provider!==`github-pull-request-files`)throw Error(`changed-files manifest source provider is invalid`);if(i.perPage!==100||i.maxFiles!==3e3)throw Error(`changed-files manifest source limits are invalid`);if(!Array.isArray(t.diagnostics)||t.diagnostics.length>6e3)throw Error(`changed-files manifest diagnostics must be a bounded array`);let a=t.diagnostics.map(Ug);if(!Gg(a.map(Kg)))throw Error(`changed-files manifest diagnostics must be unique and sorted`);if(t.complete!==(a.length===0))throw Error(`changed-files manifest completeness disagrees with diagnostics`);let o=Zg(i.expectedFileCount,`changed-files expected file count`),s=Zg(i.fetchedFileCount,`changed-files fetched file count`),c=Zg(i.pageCount,`changed-files page count`);if(s>3e3||c>30||s>c*100||n.length>s*2)throw Error(`changed-files manifest source counts are inconsistent`);if(t.complete&&(o!==s||o>3e3||c!==Math.ceil(s/100)||n.length<s))throw Error(`complete changed-files manifest source counts are inconsistent`);return{kind:`kapture-changed-files`,version:1,complete:t.complete,pullRequest:{number:Xg(r.number,`changed-files pull request number`),baseSha:Yg(r.baseSha,`changed-files base SHA`),headSha:Yg(r.headSha,`changed-files head SHA`)},files:n,source:{provider:`github-pull-request-files`,expectedFileCount:o,fetchedFileCount:s,pageCount:c,perPage:100,maxFiles:Ig},diagnostics:a}}function zg(e,t=`GitHub file path`){if(typeof e!=`string`)throw Error(`${t} must be a string`);let n=Array.from(e);if(e.length===0||e.length>4096||e.startsWith(`/`)||/^[A-Za-z]:[\\/]/.test(e)||e.startsWith(`./`)||e===`.`||e===`..`||e.startsWith(`../`)||e.endsWith(`/`)||e.includes(`//`)||e.includes(`\\`)||e.split(`/`).some(e=>e===`.`||e===`..`)||n.some(e=>{let t=e.codePointAt(0)??0;return t<=31||t>=127&&t<=159}))throw Error(`${t} must be a normalized project-relative path`);return e}function Bg(e,t){let n=e.head.repo;if(e.number!==t.prNumber||e.state!==`open`||e.base.ref!==t.base.ref||e.base.sha.toLowerCase()!==t.base.sha||e.base.repo.full_name!==t.base.repository||e.head.ref!==t.head.ref||e.head.sha.toLowerCase()!==t.head.sha||n?.id!==t.head.repositoryId||n.full_name!==t.head.repository)throw Error(`Live pull request does not match the exact Kapture capture context`)}function Vg(e,t,n,r){if(!e.value||typeof e.value!=`object`||Array.isArray(e.value)){r.push({code:`invalid-file-record`,page:e.page,index:e.index});return}let i=e.value;if(typeof i.status!=`string`||typeof i.filename!=`string`){r.push({code:`invalid-file-record`,page:e.page,index:e.index});return}let a=JSON.stringify([i.status,i.filename,i.previous_filename]);if(n.has(a)&&r.push({code:`duplicate-file-entry`,page:e.page,index:e.index}),n.add(a),Hg(i.filename,e,t,r),i.status===`renamed`||i.previous_filename!==void 0){if(typeof i.previous_filename!=`string`){r.push({code:`rename-source-missing`,page:e.page,index:e.index});return}Hg(i.previous_filename,e,t,r)}}function Hg(e,t,n,r){try{n.add(zg(e))}catch{r.push({code:`invalid-file-path`,page:t.page,index:t.index})}}function Ug(e){let t=Qg(e,`changed-files diagnostic`);if(Jg(t,[`code`,`page`,`index`],`changed-files diagnostic`,!0),typeof t.code!=`string`||![`github-file-limit`,`pagination-incomplete`,`file-count-mismatch`,`invalid-file-record`,`invalid-file-path`,`rename-source-missing`,`duplicate-file-entry`].includes(t.code))throw Error(`changed-files diagnostic code is invalid`);let n=t.page===void 0?void 0:Xg(t.page,`page`),r=t.index===void 0?void 0:Zg(t.index,`diagnostic index`),i={code:t.code,...n===void 0?{}:{page:n},...r===void 0?{}:{index:r}};if(i.code===`github-file-limit`||i.code===`file-count-mismatch`?n!==void 0||r!==void 0:i.code===`pagination-incomplete`?n===void 0||n>30||r!==void 0:n===void 0||n>30||r===void 0||r>=100)throw Error(`changed-files diagnostic location is invalid`);return i}function Wg(e){return[...new Map(e.map(e=>[JSON.stringify(e),e])).values()].sort((e,t)=>qg(Kg(e),Kg(t)))}function Gg(e){return e.every((t,n)=>n===0||(e[n-1]??``)<t)}function Kg(e){return`${e.code}:${String(e.page??0).padStart(2,`0`)}:${String(e.index??0).padStart(3,`0`)}`}function qg(e,t){return e<t?-1:+(e>t)}function Jg(e,t,n,r=!1){let i=Object.keys(e).sort(),a=r?i.filter(e=>t.includes(e)).sort():[...t].sort();if(i.some(e=>!t.includes(e))||!r&&(i.length!==a.length||i.some((e,t)=>e!==a[t])))throw Error(`${n} contains unexpected or missing fields`)}function Yg(e,t){if(typeof e!=`string`||!/^[0-9a-f]{40}$/.test(e))throw Error(`${t} must be a full lowercase SHA`);return e}function Xg(e,t){let n=Zg(e,t);if(n===0)throw Error(`${t} must be a positive integer`);return n}function Zg(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw Error(`${t} must be a non-negative integer`);return e}function Qg(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}Nc(),Jh();const $g=2e4,e_=26214400,t_=1073741824,n_=/^[0-9a-f]{40}$/,r_=/^sha256:[0-9a-f]{64}$/,i_=/^[0-9a-f]{64}$/,a_=/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/,o_=/^\.github\/workflows\/[A-Za-z0-9_./-]+\.ya?ml$/,s_=/^images\/(?:base|head|diff)\/[A-Za-z0-9][A-Za-z0-9._-]*\.png$/,c_=R().min(1).max(512).refine(e=>!vv(e),`must not contain control characters`),l_=R().regex(n_),u_=z().int().positive().max(2**53-1),d_=R().regex(a_),f_=R().regex(r_),p_=B({schemaVersion:H(1),runId:u_,prNumber:u_,base:B({repository:d_,ref:c_,sha:l_}),head:B({repository:d_,repositoryId:u_,ref:c_,sha:l_}),preview:B({branch:c_,alias:c_})}),m_=B({id:u_,name:c_,sizeInBytes:u_,digest:f_}),h_=B({id:u_,name:c_,digest:f_}),g_=B({schemaVersion:H(1),artifacts:B({context:h_,baseStorybook:h_,headStorybook:h_})}),__=B({schemaVersion:H(2),repository:B({id:u_,fullName:d_}),context:p_,captureRun:B({id:u_,runNumber:u_,attempt:u_,workflowId:u_,workflowPath:c_,headSha:l_,headBranch:c_,headRepositoryId:u_,headRepository:d_}),artifacts:B({context:m_,baseStorybook:m_,headStorybook:m_,report:m_}),report:B({contentDigest:R().regex(i_)}),trustedArtifactName:c_});async function v_(e,t){let n=uv(t.captureWorkflowPath),r=mv(t.baseBranch,`base branch`),i=f(t.outputDir),a=f(t.receiptPath);if(xv(i,a))throw Error(`Trusted receipt must be outside the publicly deployed report directory`);await lv(a,`Trusted receipt`);let o=S_(t.event,n),s=await e.getWorkflowRun(o.run.id);K_(s,o),await w_(e,s);let c=T_(await e.listRunArtifacts(s.id),o),l=await sv(t.temporaryRoot),u=!1;try{let d=await O_(e,c.context,33685504),p=f(l,`context`);N_(d),await bg(d,p,k_);let m=await R_(f(p,`context.json`)),h=await z_(f(p,`changed-files.json`),m);V_(m,c.context),H_(m,o,s,r),W_(await e.getPullRequest(m.prNumber),m,o,r),await G_(e,m,n);let g=await O_(e,c.report,629145600),_=f(l,`untrusted-report`);P_(g),await bg(g,_,j_),L_(await I_(f(_,`capture-boundary.json`)),c);let v=await Eh(f(_,`report.json`));B_(v,h),await df(e,av(o,m),v);let y=await tg({inputDir:_,outputDir:i,trustedHeadBranch:m.head.ref,trustedPullRequest:{repository:m.base.repository,number:m.prNumber,url:`https://github.com/${m.base.repository}/pull/${m.prNumber}`,baseBranch:m.base.ref,headBranch:m.head.ref,workflowRunUrl:`https://github.com/${m.base.repository}/actions/runs/${o.run.id}`},...t.storybookUrl?{storybookUrl:t.storybookUrl}:{},...t.dashboardDir?{dashboardDir:f(t.dashboardDir)}:{}});if(u=!0,!y.report.contentDigest)throw Error(`Trusted report build did not produce an image-bound content digest`);await iv(e,o,s,m,r,n);let b=q_(o,s,m,c,y.report);return await cv(a,b),{receipt:b,report:y.report,reportDirectory:i,reportPath:f(i,`report.json`),receiptPath:a,changedFiles:h}}catch(e){throw u&&await re(i,{recursive:!0,force:!0}),e}finally{await re(l,{recursive:!0,force:!0})}}async function y_(e,t,n){let r=await C_(n.receiptPath),i=S_(n.event,r.captureRun.workflowPath);X_(r,i);let a=await e.getWorkflowRun(r.captureRun.id);Z_(a,r),await w_(e,a),await Q_(e,r,i),W_(await e.getPullRequest(r.context.prNumber),r.context,i,r.context.base.ref),await G_(e,r.context,r.captureRun.workflowPath);let o=await rg(n.reportPath,r.report.contentDigest);if(o.headBranch!==r.context.head.ref)throw Error(`Trusted report branch does not match its verified pull request context`);let s=av(i,r.context);return await df(e,s,o),ff(t,s,o,n.statusContext,n.reportUrl,n.commentLanguage)}async function b_(e,t){let n=uv(t.captureWorkflowPath),r=mv(t.baseBranch,`base branch`),i=f(t.outputDir),o=f(t.receiptPath);await lv(i,`Trusted Storybook output`);let s=await C_(o),c=S_(t.event,n);X_(s,c);let l=await e.getWorkflowRun(s.captureRun.id);Z_(l,s),await w_(e,l),await Q_(e,s,c),W_(await e.getPullRequest(s.context.prNumber),s.context,c,r),await G_(e,s.context,n);let u=f(t.temporaryRoot??a(i));if(xv(i,u))throw Error(`Trusted Storybook temporary root must be outside its output directory`);let d=await sv(u),p=f(d,`storybook`);try{let t=await O_(e,s.artifacts.headStorybook,536870912);return F_(t),await bg(t,p,M_),await iv(e,c,l,s.context,r,n),await Q_(e,s,c),await lv(i,`Trusted Storybook output`),await y(a(i),{recursive:!0}),await ne(p,i),{receipt:s,receiptPath:o,context:s.context,artifact:s.artifacts.headStorybook,storybookDirectory:i}}finally{await re(d,{recursive:!0,force:!0})}}async function x_(e,t){let n=await C_(t.receiptPath),r=S_(t.event,n.captureRun.workflowPath);X_(n,r),Z_(await e.getWorkflowRun(n.captureRun.id),n);let i=t.trustedArtifactId,a=t.trustedArtifactDigest?nv(t.trustedArtifactDigest):void 0,o=[i,a];if(o.some(e=>e!==void 0)&&o.some(e=>e===void 0))throw Error(`trusted-artifact-id and trusted-artifact-digest must be provided together`);if(i!==void 0&&!_v(i))throw Error(`trusted-artifact-id must be a positive integer`);let s=i!==void 0&&a!==void 0?rv():void 0,c=[];for(let t of $_(n)){let n=await e.getArtifact(t.id);n&&(ev(n,t,r),c.push({artifact:n,expected:t}))}if(i!==void 0&&a!==void 0&&s!==void 0){if($_(n).some(e=>e.id===i))throw Error(`trusted-artifact-id must not duplicate a source artifact ID`);let t=await e.getArtifact(i);t&&(tv(t,a,s,n),c.push({artifact:t,expected:{id:t.id,name:t.name,sizeInBytes:t.sizeInBytes,digest:t.digest}}))}let l=[...new Set(c.map(({artifact:e})=>e.id))];for(let t of l)await e.deleteArtifact(t);return l}function S_(e,t){let n=yv(e,`GitHub workflow_run event`);if(n.action!==`completed`)throw Error(`Kapture trusted run requires a completed workflow_run event`);let r=yv(n.repository,`event repository`),i=dv(r.full_name,`event repository`),a=fv(i),o=gv(r.id,`event repository ID`),s=yv(n.workflow_run,`workflow_run`),c=uv(hv(s.path,`workflow path`));if(c!==uv(t))throw Error(`workflow_run path ${c} does not match ${t}`);if(s.status!==`completed`||s.conclusion!==`success`||s.event!==`pull_request`)throw Error(`Kapture trusted run requires one successful pull_request capture run`);let l=yv(s.head_repository,`workflow_run head repository`),u=bv(s.pull_requests,`workflow_run pull_requests`);if(u.length>1)throw Error(`workflow_run must contain at most one pull request`);let d=u[0]?ov(u[0]):void 0;return{repository:{id:o,fullName:i,ref:a},run:{id:gv(s.id,`workflow run ID`),runNumber:gv(s.run_number,`workflow run number`),attempt:gv(s.run_attempt,`workflow run attempt`),workflowId:gv(s.workflow_id,`workflow ID`),workflowPath:c,status:`completed`,conclusion:`success`,event:`pull_request`,headSha:pv(s.head_sha,`workflow run head SHA`),headBranch:mv(s.head_branch,`workflow run head branch`),headRepository:{id:gv(l.id,`workflow run head repository ID`),fullName:dv(l.full_name,`workflow run head repository`)}},...d?{pullRequest:d}:{}}}async function C_(e){let t=f(e),n=await C(t);if(!n.isFile()||n.size<1||n.size>65536)throw Error(`Trusted receipt must be a file no larger than 65536 bytes`);let r;try{r=JSON.parse(await x(t,`utf8`))}catch{throw Error(`Trusted receipt does not contain valid JSON`)}let i=__.safeParse(r);if(!i.success){let e=i.error.issues[0];throw Error(`Invalid trusted receipt${e?.path.length?` at ${e.path.join(`.`)}`:``}: ${e?.message??`unknown error`}`)}return Y_(i.data),i.data}async function w_(e,t){let n=(await e.listWorkflowRuns(t.workflowId,t.headBranch)).filter(e=>e.headRepositoryId===t.headRepository.id).reduce((e,t)=>e?t.runNumber===e.runNumber?t.id>e.id?t:e:t.runNumber>e.runNumber?t:e:t,void 0);if(!n||n.id!==t.id)throw Error(`A newer Kapture capture run owns this repository and branch`)}function T_(e,t){let n=/^kapture-context-pr-([1-9][0-9]*)-base-([0-9a-f]{40})-head-([0-9a-f]{40})$/,r=e.filter(e=>n.test(e.name)?D_(e,t):!1);if(r.length!==1||!r[0])throw Error(`Triggering run must contain exactly one immutable Kapture context artifact`);let i=r[0];if(i.sizeInBytes>33685504)throw Error(`Kapture context artifact exceeds its compressed size limit`);let a=i.name.match(n);if(!a?.[1]||!a[2]||!a[3])throw Error(`Kapture context artifact name is invalid`);let o=`kapture-visual-report-pr-${a[1]}-base-${a[2]}-head-${a[3]}`,s=e.filter(e=>e.name===o&&D_(e,t));if(s.length!==1||!s[0])throw Error(`Triggering run must contain exactly one matching Kapture report artifact`);if(s[0].sizeInBytes>629145600)throw Error(`Kapture report artifact exceeds its compressed size limit`);let c=`pr-${a[1]}-base-${a[2]}-head-${a[3]}`,l=E_(e,`kapture-storybook-base-${c}`,t),u=E_(e,`kapture-storybook-head-${c}`,t),d=[i,l,u,s[0]];if(new Set(d.map(e=>e.id)).size!==d.length||new Set(d.map(e=>e.name)).size!==d.length)throw Error(`Kapture artifact IDs and names must be distinct`);return{context:i,baseStorybook:l,headStorybook:u,report:s[0]}}function E_(e,t,n){let r=e.filter(e=>e.name===t&&D_(e,n));if(r.length!==1||!r[0])throw Error(`Triggering run must contain exactly one non-expired ${t} artifact`);if(r[0].sizeInBytes>536870912)throw Error(`${t} exceeds its compressed size limit`);return r[0]}function D_(e,t){return!e.expired&&e.workflowRun.id===t.run.id&&e.workflowRun.repositoryId===t.repository.id&&e.workflowRun.headRepositoryId===t.run.headRepository.id&&e.workflowRun.headBranch===t.run.headBranch&&e.workflowRun.headSha===t.run.headSha&&r_.test(e.digest)&&_v(e.id)&&_v(e.sizeInBytes)}async function O_(e,t,n){let r=await e.downloadArtifactArchive(t.id,n);if(r.byteLength!==t.sizeInBytes)throw Error(`Artifact ${t.id} download size does not match GitHub metadata`);if(`sha256:${ae(`sha256`).update(r).digest(`hex`)}`!==t.digest)throw Error(`Artifact ${t.id} download digest does not match GitHub metadata`);return r}const k_={maxEntries:2,maxFileBytes:33554432,maxTotalBytes:33619968,allowPath:e=>e===`context.json`||e===`changed-files.json`,allowDirectoryPath:()=>!1},A_=new Set([`images/`,`images/base/`,`images/head/`,`images/diff/`]),j_={maxEntries:60006,maxFileBytes:Xh,maxTotalBytes:629145600,allowPath:e=>e===`report.json`||e===`capture-boundary.json`||s_.test(e),allowDirectoryPath:e=>A_.has(e)},M_={maxEntries:$g,maxFileBytes:e_,maxTotalBytes:t_,allowPath:()=>!0,allowDirectoryPath:()=>!0};function N_(e){let t=yg(e,k_);if(t.length!==2)throw Error(`Context archive must contain exactly context.json and changed-files.json`);let n=t.find(e=>e.path===`context.json`),r=t.find(e=>e.path===`changed-files.json`);if(!n||n.uncompressedBytes<1||n.uncompressedBytes>65536||!r||r.uncompressedBytes<1||r.uncompressedBytes>33554432)throw Error(`Context archive entries are outside their fixed size contract`)}function P_(e){let t=yg(e,j_),n=new Set,r=0,i=0;for(let e of t){let t=e.path.toLocaleLowerCase(`en-US`);if(n.has(t))throw Error(`Report archive contains a case-insensitive duplicate: ${e.path}`);if(n.add(t),e.uncompressedBytes<1)throw Error(`Report archive contains an empty file: ${e.path}`);if(e.path===`report.json`&&(r+=1,e.uncompressedBytes>10485760))throw Error(`report.json exceeds its uncompressed size limit`);if(e.path===`capture-boundary.json`&&(i+=1,e.uncompressedBytes>65536))throw Error(`capture-boundary.json exceeds its uncompressed size limit`)}if(r!==1)throw Error(`Report archive must contain one root report.json file`);if(i!==1)throw Error(`Report archive must contain one root capture-boundary.json file`)}function F_(e){let t=yg(e,M_),n=new Set,r=0;for(let e of t){let t=e.path.toLocaleLowerCase(`en-US`);if(n.has(t))throw Error(`Storybook archive contains a case-insensitive duplicate: ${e.path}`);n.add(t),e.path===`index.html`&&e.uncompressedBytes>0&&(r+=1)}if(r!==1)throw Error(`Storybook archive must contain one non-empty root index.html file`)}async function I_(e){let t;try{t=JSON.parse(await x(e,`utf8`))}catch(e){throw Error(`capture-boundary.json must contain valid JSON`,{cause:e})}return g_.parse(t)}function L_(e,t){for(let n of[`context`,`baseStorybook`,`headStorybook`]){let r=e.artifacts[n],i=t[n];if(i.id!==r.id||i.name!==r.name||i.digest!==r.digest)throw Error(`Capture ${n} artifact does not match its exact downloaded identity`)}}async function R_(e){let t;try{t=JSON.parse(await x(e,`utf8`))}catch{throw Error(`Kapture context artifact does not contain valid JSON`)}let n=p_.safeParse(t);if(!n.success){let e=n.error.issues[0];throw Error(`Invalid Kapture capture context${e?.path.length?` at ${e.path.join(`.`)}`:``}: ${e?.message??`unknown error`}`)}if(n.data.preview.branch!==n.data.head.ref||n.data.preview.alias!==kg(n.data.prNumber,n.data.head.ref))throw Error(`Kapture context preview identity is not derived from its pull request branch`);return n.data}async function z_(e,t){let n=await C(e);if(!n.isFile()||n.size<1||n.size>33554432)throw Error(`changed-files.json is outside its fixed size contract`);let r;try{r=JSON.parse(await x(e,`utf8`))}catch{throw Error(`changed-files.json does not contain valid JSON`)}let i=Rg(r);if(i.pullRequest.number!==t.prNumber||i.pullRequest.baseSha!==t.base.sha||i.pullRequest.headSha!==t.head.sha)throw Error(`changed-files.json does not belong to the exact capture context`);return i}function B_(e,t){let n=e.coverage;if(!n)throw Error(`Trusted workflow reports must include audited story coverage`);let r=n.changedFilesEvidence;if(!r)throw Error(`Trusted workflow report coverage must include changed-files evidence`);let i=ae(`sha256`).update(JSON.stringify(t)).digest(`hex`);if(r.provider!==t.source.provider||r.manifestDigest!==i||r.pullRequestNumber!==t.pullRequest.number||r.baseSha!==t.pullRequest.baseSha||r.headSha!==t.pullRequest.headSha)throw Error(`Trusted workflow report changed-files evidence does not match its verified context manifest`)}function V_(e,t){let n=`kapture-context-${Og(e)}`;if(t.name!==n)throw Error(`Kapture context contents do not match the immutable artifact name`)}function H_(e,t,n,r){if(e.runId!==n.id||e.base.repository!==t.repository.fullName||e.base.ref!==r||e.head.repository!==n.headRepository.fullName||e.head.repositoryId!==n.headRepository.id||e.head.ref!==n.headBranch)throw Error(`Kapture capture context does not belong to the triggering workflow run`);U_(t,e)}function U_(e,t){let n=e.pullRequest;if(n&&(n.number!==t.prNumber||n.base.repositoryId!==e.repository.id||n.base.ref!==t.base.ref||n.base.sha!==t.base.sha||n.head.repositoryId!==t.head.repositoryId||n.head.ref!==t.head.ref||n.head.sha!==t.head.sha))throw Error(`workflow_run pull request metadata conflicts with the capture context`)}function W_(e,t,n,r){if(e.number!==t.prNumber||e.state!==`open`||e.base.repository.id!==n.repository.id||e.base.repository.fullName!==t.base.repository||e.base.ref!==r||e.base.sha!==t.base.sha||e.head.repository.id!==t.head.repositoryId||e.head.repository.fullName!==t.head.repository||e.head.ref!==t.head.ref||e.head.sha!==t.head.sha)throw Error(`Kapture artifacts are stale or do not belong to the current open pull request`);U_(n,t)}async function G_(e,t,n){let[r,i]=await Promise.all([e.getContentSha(t.base.repository,n,t.base.sha),e.getContentSha(t.head.repository,n,t.head.sha)]);if(!n_.test(r)||i!==r)throw Error(`Pull requests that modify the capture workflow require separate review before publishing`)}function K_(e,t){if(e.id!==t.run.id||e.runNumber!==t.run.runNumber||e.runAttempt!==t.run.attempt||e.workflowId!==t.run.workflowId||e.path!==t.run.workflowPath||e.status!==`completed`||e.conclusion!==`success`||e.event!==`pull_request`||e.headSha!==t.run.headSha||e.headBranch!==t.run.headBranch||e.headRepository.id!==t.run.headRepository.id||e.headRepository.fullName!==t.run.headRepository.fullName||e.repository.id!==t.repository.id||e.repository.fullName!==t.repository.fullName)throw Error(`Triggering capture run metadata changed or no longer matches the event`)}function q_(e,t,n,r,i){if(!i.contentDigest)throw Error(`Trusted report is missing contentDigest`);if(i.headBranch!==n.head.ref)throw Error(`Trusted report branch does not match its verified pull request context`);let a=Og(n);return{schemaVersion:2,repository:{id:e.repository.id,fullName:e.repository.fullName},context:n,captureRun:{id:t.id,runNumber:t.runNumber,attempt:t.runAttempt,workflowId:t.workflowId,workflowPath:t.path,headSha:t.headSha,headBranch:t.headBranch,headRepositoryId:t.headRepository.id,headRepository:t.headRepository.fullName},artifacts:{context:J_(r.context),baseStorybook:J_(r.baseStorybook),headStorybook:J_(r.headStorybook),report:J_(r.report)},report:{contentDigest:i.contentDigest},trustedArtifactName:`kapture-trusted-report-${a}`}}function J_(e){return{id:e.id,name:e.name,sizeInBytes:e.sizeInBytes,digest:e.digest}}function Y_(e){let t=Og(e.context);if(e.context.runId!==e.captureRun.id||e.context.base.repository!==e.repository.fullName||e.context.head.repository!==e.captureRun.headRepository||e.context.head.repositoryId!==e.captureRun.headRepositoryId||e.context.head.ref!==e.captureRun.headBranch||e.context.preview.branch!==e.context.head.ref||e.context.preview.alias!==kg(e.context.prNumber,e.context.head.ref)||e.artifacts.context.name!==`kapture-context-${t}`||e.artifacts.baseStorybook.name!==`kapture-storybook-base-${t}`||e.artifacts.headStorybook.name!==`kapture-storybook-head-${t}`||e.artifacts.report.name!==`kapture-visual-report-${t}`||e.trustedArtifactName!==`kapture-trusted-report-${t}`||new Set($_(e).map(e=>e.id)).size!==4||new Set($_(e).map(e=>e.name)).size!==4||e.artifacts.context.sizeInBytes>33685504||e.artifacts.baseStorybook.sizeInBytes>536870912||e.artifacts.headStorybook.sizeInBytes>536870912||e.artifacts.report.sizeInBytes>629145600||!o_.test(e.captureRun.workflowPath))throw Error(`Trusted receipt fields are not internally consistent`)}function X_(e,t){if(Y_(e),e.repository.id!==t.repository.id||e.repository.fullName!==t.repository.fullName||e.captureRun.id!==t.run.id||e.captureRun.runNumber!==t.run.runNumber||e.captureRun.attempt!==t.run.attempt||e.captureRun.workflowId!==t.run.workflowId||e.captureRun.workflowPath!==t.run.workflowPath||e.captureRun.headSha!==t.run.headSha||e.captureRun.headBranch!==t.run.headBranch||e.captureRun.headRepositoryId!==t.run.headRepository.id||e.captureRun.headRepository!==t.run.headRepository.fullName)throw Error(`Trusted receipt does not belong to the triggering workflow_run event`);U_(t,e.context)}function Z_(e,t){if(e.id!==t.captureRun.id||e.runNumber!==t.captureRun.runNumber||e.runAttempt!==t.captureRun.attempt||e.workflowId!==t.captureRun.workflowId||e.path!==t.captureRun.workflowPath||e.status!==`completed`||e.conclusion!==`success`||e.event!==`pull_request`||e.headSha!==t.captureRun.headSha||e.headBranch!==t.captureRun.headBranch||e.headRepository.id!==t.captureRun.headRepositoryId||e.headRepository.fullName!==t.captureRun.headRepository||e.repository.id!==t.repository.id||e.repository.fullName!==t.repository.fullName)throw Error(`Capture run changed after prepare-run verification`)}async function Q_(e,t,n){let r=await e.listRunArtifacts(t.captureRun.id);for(let e of $_(t)){let t=r.filter(t=>t.id===e.id);if(t.length!==1||!t[0])throw Error(`Receipt-bound artifact ${e.id} is no longer available`);ev(t[0],e,n)}}function $_(e){return[e.artifacts.context,e.artifacts.baseStorybook,e.artifacts.headStorybook,e.artifacts.report]}function ev(e,t,n){if(e.id!==t.id||e.name!==t.name||e.sizeInBytes!==t.sizeInBytes||e.digest!==t.digest||!D_(e,n))throw Error(`Artifact ${t.id} no longer matches its trusted receipt binding`)}function tv(e,t,n,r){if(e.expired||e.name!==r.trustedArtifactName||e.digest!==t||e.workflowRun.id!==n||e.workflowRun.repositoryId!==r.repository.id||e.workflowRun.headRepositoryId!==r.repository.id||e.sizeInBytes>629145600)throw Error(`Trusted report artifact does not match the exact cleanup binding`)}function nv(e){let t=e.startsWith(`sha256:`)?e:`sha256:${e}`;if(!r_.test(t))throw Error(`trusted-artifact-digest must be a 64-character SHA-256 digest`);return t}function rv(){let e=process.env.GITHUB_RUN_ID;if(!e||!/^[1-9][0-9]*$/.test(e))throw Error(`GITHUB_RUN_ID must identify the current trusted reporter workflow run`);let t=Number(e);if(!Number.isSafeInteger(t))throw Error(`GITHUB_RUN_ID must be a safe positive integer`);return t}async function iv(e,t,n,r,i,a){let o=await e.getWorkflowRun(n.id);K_(o,t),await w_(e,o),W_(await e.getPullRequest(r.prNumber),r,t,i),await G_(e,r,a)}function av(e,t){return{repository:e.repository.ref,issueNumber:t.prNumber,headSha:t.head.sha,captureRunId:e.run.id,captureRunAttempt:e.run.attempt,captureWorkflowId:e.run.workflowId,captureRunHeadBranch:e.run.headBranch,captureRunHeadRepositoryId:e.run.headRepository.id}}function ov(e){let t=yv(e,`workflow_run pull request`),n=yv(t.base,`workflow_run pull request base`),r=yv(t.head,`workflow_run pull request head`);return{number:gv(t.number,`workflow_run pull request number`),base:{repositoryId:gv(yv(n.repo,`workflow_run pull request base repository`).id,`workflow_run pull request base repository ID`),ref:mv(n.ref,`workflow_run pull request base ref`),sha:pv(n.sha,`workflow_run pull request base SHA`)},head:{repositoryId:gv(yv(r.repo,`workflow_run pull request head repository`).id,`workflow_run pull request head repository ID`),ref:mv(r.ref,`workflow_run pull request head ref`),sha:pv(r.sha,`workflow_run pull request head SHA`)}}}async function sv(e){let t=f(e??process.env.RUNNER_TEMP??ue());return await y(t,{recursive:!0}),b(`${t}${p}kapture-prepare-`)}async function cv(e,t){let n=f(e),r=f(n,`..`);await y(r,{recursive:!0}),await ie(n,`${JSON.stringify(t,null,2)}\n`,{flag:`wx`})}async function lv(e,t){try{await C(e)}catch(e){if(e.code===`ENOENT`)return;throw e}throw Error(`${t} already exists: ${e}`)}function uv(e){if(!o_.test(e)||e.includes(`//`)||e.includes(`..`))throw Error(`capture-workflow-path must be a safe .github/workflows YAML path`);return e}function dv(e,t){let n=hv(e,`${t} full name`);if(!a_.test(n))throw Error(`${t} full name is invalid`);return n}function fv(e){let[t,n,...r]=e.split(`/`);if(!t||!n||r.length>0)throw Error(`Repository full name is invalid`);return{owner:t,repo:n}}function pv(e,t){let n=hv(e,t);if(!n_.test(n))throw Error(`${t} must be a lowercase full SHA`);return n}function mv(e,t){let n=hv(e,t);if(vv(n))throw Error(`${t} contains control characters`);return n}function hv(e,t){if(typeof e!=`string`||e.length<1||e.length>512)throw Error(`${t} must be a non-empty bounded string`);return e}function gv(e,t){if(!_v(e))throw Error(`${t} must be a positive integer`);return e}function _v(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>0}function vv(e){return Array.from(e).some(e=>{let t=e.codePointAt(0)??0;return t<=31||t===127})}function yv(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}function bv(e,t){if(!Array.isArray(e))throw Error(`${t} must be an array`);return e}function xv(e,t){let n=d(e,t);return n===``||!s(n)&&n!==`..`&&!n.startsWith(`..${p}`)}function Sv(e){let t=e.KAPTURE_ARTIFACT_SUFFIX;if(!t||!/^pr-[1-9][0-9]*-base-[0-9a-f]{40}-head-[0-9a-f]{40}$/.test(t))throw Error(`KAPTURE_ARTIFACT_SUFFIX must identify exact PR/base/head revisions`);let n=(n,r)=>{let i=e[`KAPTURE_${n}_ARTIFACT_ID`]??``,a=e[`KAPTURE_${n}_ARTIFACT_DIGEST`]??``;if(!/^[1-9][0-9]*$/.test(i)||!/^[0-9a-f]{64}$/.test(a))throw Error(`${n} requires an artifact ID and SHA-256 digest`);return{id:Number(i),name:`${r}-${t}`,digest:`sha256:${a}`}};return g_.parse({schemaVersion:1,artifacts:{context:n(`CONTEXT`,`kapture-context`),baseStorybook:n(`BASE`,`kapture-storybook-base`),headStorybook:n(`HEAD`,`kapture-storybook-head`)}})}O();const Cv=D({meta:{name:`bind-artifacts`,description:`Record the exact downloaded artifact identities for trusted publication`},args:{output:{type:`string`,required:!0,description:`New capture-boundary.json path inside the raw report`}},async run({args:e}){let t=Sv(process.env);await ie(f(e.output),`${JSON.stringify(t)}\n`,{flag:`wx`,mode:384})}});var wv=class{#e;#t;#n;constructor(e,t,n=fetch){if(!e)throw Error(`GITHUB_TOKEN is required`);this.#e=e,this.#t=t,this.#n=n}async getWorkflowRun(e){return Ev(await this.#i(`GET`,`${this.#r()}/actions/runs/${e}`))}async listWorkflowRuns(e,t){let n=[];for(let r=1;r<=10;r+=1){let i=new URLSearchParams({event:`pull_request`,branch:t,per_page:`100`,page:String(r)}),a=Nv(Mv(await this.#i(`GET`,`${this.#r()}/actions/workflows/${e}/runs?${i}`),`workflow runs response`).workflow_runs,`workflow_runs`).map(Dv);if(n.push(...a),a.length<100)return n}throw Error(`GitHub returned more than 1000 workflow runs`)}async listRunArtifacts(e){let t=[];for(let n=1;n<=10;n+=1){let r=new URLSearchParams({per_page:`100`,page:String(n)}),i=Nv(Mv(await this.#i(`GET`,`${this.#r()}/actions/runs/${e}/artifacts?${r}`),`artifacts response`).artifacts,`artifacts`).map(Ov);if(t.push(...i),i.length<100)return t}throw Error(`GitHub returned more than 1000 workflow artifacts`)}async getArtifact(e){let t=await this.#o(`GET`,`${this.#r()}/actions/artifacts/${e}`);return t.status===404?null:(await Tv(t,`GET`,`/actions/artifacts/${e}`),Ov(await t.json()))}async downloadArtifactArchive(e,t){if(!Number.isSafeInteger(t)||t<=0)throw Error(`Artifact download byte limit must be positive`);let n=await this.#o(`GET`,`${this.#r()}/actions/artifacts/${e}/zip`,`manual`),r=await this.#a(n,e);await Tv(r,`GET`,`/actions/artifacts/${e}/zip`);let i=r.headers.get(`content-length`);if(i!==null){let n=Number(i);if(!Number.isSafeInteger(n)||n<0||n>t)throw Error(`Artifact ${e} exceeds the ${t} byte download limit`)}if(!r.body)throw Error(`Artifact ${e} download returned no body`);let a=r.body.getReader(),o=[],s=0;try{for(;;){let{done:n,value:r}=await a.read();if(n)break;if(s+=r.byteLength,s>t)throw await a.cancel(),Error(`Artifact ${e} exceeds the ${t} byte download limit`);o.push(Buffer.from(r))}}finally{a.releaseLock()}if(s<1)throw Error(`Artifact ${e} download is empty`);return Buffer.concat(o,s)}async deleteArtifact(e){let t=await this.#o(`DELETE`,`${this.#r()}/actions/artifacts/${e}`);t.status!==404&&await Tv(t,`DELETE`,`/actions/artifacts/${e}`)}async getPullRequest(e){return kv(await this.#i(`GET`,`${this.#r()}/pulls/${e}`))}async listOpenPullRequestsForHead(e,t,n){let r=jv(e),i=[];for(let e=1;e<=10;e+=1){let a=new URLSearchParams({state:`open`,base:n,head:`${r.owner}:${t}`,per_page:`100`,page:String(e)}),o=Nv(await this.#i(`GET`,`${this.#r()}/pulls?${a}`),`pull requests response`).map(kv);if(i.push(...o),o.length<100)return i}throw Error(`GitHub returned more than 1000 matching pull requests`)}async getContentSha(e,t,n){let r=jv(e),i=t.split(`/`).map(encodeURIComponent).join(`/`),a=new URLSearchParams({ref:n});return Rv(Mv(await this.#i(`GET`,`/repos/${encodeURIComponent(r.owner)}/${encodeURIComponent(r.repo)}/contents/${i}?${a}`),`contents response`).sha,`contents SHA`)}#r(){let{owner:e,repo:t}=this.#t;return`/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}`}async#i(e,t){let n=await this.#o(e,t);return await Tv(n,e,t),n.json()}async#a(e,t){if(e.status<300||e.status>399)return e;let n=e.headers.get(`location`);if(!n)throw Error(`Artifact ${t} redirect is missing its location`);let r;try{r=new URL(n)}catch{throw Error(`Artifact ${t} redirect location is invalid`)}if(r.protocol!==`https:`||r.username||r.password)throw Error(`Artifact ${t} redirect must be a credential-free HTTPS URL`);return this.#n(r,{method:`GET`,headers:{Accept:`application/octet-stream`,"User-Agent":`kapture-cli`},redirect:`follow`})}#o(e,t,n=`follow`){return this.#n(`https://api.github.com${t}`,{method:e,headers:{Accept:`application/vnd.github+json`,Authorization:`Bearer ${this.#e}`,"X-GitHub-Api-Version":`2022-11-28`,"User-Agent":`kapture-cli`},redirect:n})}};async function Tv(e,t,n){if(!e.ok)throw Error(`GitHub API ${t} ${n} failed with status ${e.status}`)}function Ev(e){let t=Mv(e,`workflow run`);return{id:Pv(t.id,`workflow run ID`),runNumber:Pv(t.run_number,`workflow run number`),runAttempt:Pv(t.run_attempt,`workflow run attempt`),workflowId:Pv(t.workflow_id,`workflow ID`),path:Fv(t.path,`workflow path`),status:Fv(t.status,`workflow run status`),conclusion:Iv(t.conclusion,`workflow run conclusion`),event:Fv(t.event,`workflow run event`),headSha:Rv(t.head_sha,`workflow run head SHA`),headBranch:Fv(t.head_branch,`workflow run head branch`),headRepository:Av(t.head_repository,`workflow run head repository`),repository:Av(t.repository,`workflow run repository`)}}function Dv(e){let t=Mv(e,`workflow run candidate`);return{id:Pv(t.id,`workflow run ID`),runNumber:Pv(t.run_number,`workflow run number`),headRepositoryId:Pv(Mv(t.head_repository,`workflow run head repository`).id,`workflow run head repository ID`)}}function Ov(e){let t=Mv(e,`workflow artifact`),n=Mv(t.workflow_run,`artifact workflow run`);return{id:Pv(t.id,`artifact ID`),name:Fv(t.name,`artifact name`),sizeInBytes:Pv(t.size_in_bytes,`artifact size`),digest:zv(t.digest,`artifact digest`),expired:Lv(t.expired,`artifact expired`),workflowRun:{id:Pv(n.id,`artifact workflow run ID`),repositoryId:Pv(n.repository_id,`artifact workflow repository ID`),headRepositoryId:Pv(n.head_repository_id,`artifact workflow head repository ID`),headBranch:Fv(n.head_branch,`artifact workflow head branch`),headSha:Rv(n.head_sha,`artifact workflow head SHA`)}}}function kv(e){let t=Mv(e,`pull request`),n=Mv(t.base,`pull request base`),r=Mv(t.head,`pull request head`),i=Fv(t.state,`pull request state`);if(i!==`open`&&i!==`closed`)throw Error(`Pull request state is invalid`);return{number:Pv(t.number,`pull request number`),state:i,base:{ref:Fv(n.ref,`pull request base ref`),sha:Rv(n.sha,`pull request base SHA`),repository:Av(n.repo,`pull request base repository`)},head:{ref:Fv(r.ref,`pull request head ref`),sha:Rv(r.sha,`pull request head SHA`),repository:Av(r.repo,`pull request head repository`)}}}function Av(e,t){let n=Mv(e,t),r=Fv(n.full_name,`${t} full name`);return jv(r),{id:Pv(n.id,`${t} ID`),fullName:r}}function jv(e){let t=e.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!t?.[1]||!t[2])throw Error(`Repository full name is invalid`);return{owner:t[1],repo:t[2]}}function Mv(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}function Nv(e,t){if(!Array.isArray(e))throw Error(`${t} must be an array`);return e}function Pv(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<=0)throw Error(`${t} must be a positive integer`);return e}function Fv(e,t){if(typeof e!=`string`||e.length<1||e.length>512)throw Error(`${t} must be a non-empty bounded string`);for(let n of e){let e=n.codePointAt(0)??0;if(e<=31||e===127)throw Error(`${t} contains control characters`)}return e}function Iv(e,t){return e===null?null:Fv(e,t)}function Lv(e,t){if(typeof e!=`boolean`)throw Error(`${t} must be a boolean`);return e}function Rv(e,t){if(typeof e!=`string`||!/^[0-9a-f]{40}$/.test(e))throw Error(`${t} must be a lowercase full SHA`);return e}function zv(e,t){if(typeof e!=`string`||!/^sha256:[0-9a-f]{64}$/.test(e))throw Error(`${t} must be a SHA-256 digest`);return e}O();const Bv=D({meta:{name:`cleanup`,description:`Delete only exact receipt-bound Kapture artifact IDs`},args:{receipt:{type:`string`,required:!0,description:`Path to the strict prepare-run receipt`},"trusted-artifact-id":{type:`string`,description:`Exact current trusted report artifact ID`},"trusted-artifact-digest":{type:`string`,description:`upload-artifact SHA-256 digest for the current trusted report artifact`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=Hv(n),i=e[`trusted-artifact-id`]?Vv(e[`trusted-artifact-id`],`trusted-artifact-id`):void 0,a=await x_(new wv(t,r),{event:n,receiptPath:f(e.receipt),...i===void 0?{}:{trustedArtifactId:i},...e[`trusted-artifact-digest`]?{trustedArtifactDigest:e[`trusted-artifact-digest`]}:{}});await G({"deleted-artifact-count":a.length,"deleted-artifact-ids":a.join(`,`)})}});function Vv(e,t){if(!/^[1-9][0-9]*$/.test(e))throw Error(`${t} must be a positive integer`);let n=Number(e);if(!Number.isSafeInteger(n))throw Error(`${t} must be a safe integer`);return n}function Hv(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O();const Uv=D({meta:{name:`context`,description:`Validate a pull request event and write immutable Kapture capture context`},args:{"adapter-package-json":{type:`string`,description:`Optional project-relative package.json to check for the adapter on the exact base revision`},output:{type:`string`,required:!0,description:`Path for the normalized context JSON`},"changed-files-output":{type:`string`,required:!0,description:`Path for the versioned changed-files manifest`},"base-branch":{type:`string`,description:`Expected pull request base branch`}},async run({args:e}){let t=Dg(await ef(),e[`base-branch`]),n=process.env.GITHUB_TOKEN;if(!n)throw Error(`GITHUB_TOKEN is required`);let[r,i]=t.base.repository.split(`/`);if(!r||!i)throw Error(`Capture context repository is invalid`);let o=new Zd(n,{owner:r,repo:i}),s=await Lg(o,t),c=e[`adapter-package-json`]?Wv(await o.readPackageManifest(e[`adapter-package-json`],t.base.sha)):`compare`,l=f(e.output),u=f(e[`changed-files-output`]);if(l===u)throw Error(`output and changed-files-output must be different paths`);await Promise.all([y(a(l),{recursive:!0}),y(a(u),{recursive:!0})]),await Promise.all([ie(l,`${JSON.stringify(t,null,2)}\n`,{flag:`wx`}),ie(u,`${JSON.stringify(s,null,2)}\n`,{flag:`wx`})]),await G({"integration-mode":c,"artifact-suffix":Og(t),"base-repository":t.base.repository,"base-ref":t.base.ref,"base-sha":t.base.sha,"changed-files-complete":String(s.complete),"changed-files-count":s.files.length,"changed-files-path":u,"context-path":l,"head-repository":t.head.repository,"head-repository-id":t.head.repositoryId,"head-ref":t.head.ref,"head-sha":t.head.sha,"pr-number":t.prNumber,"preview-branch":t.preview.branch,"preview-alias":t.preview.alias})}});function Wv(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`Invalid package manifest`);let t=e;for(let e of[`dependencies`,`devDependencies`]){let n=t[e];if(n!==void 0&&(!n||typeof n!=`object`||Array.isArray(n)))throw Error(`Invalid package dependencies`);let r=n?.[`@kaptures/storybook`];if(typeof r==`string`&&r.trim())return`compare`}throw Error(`The selected base package manifest does not declare @kaptures/storybook. Select the adapter's workspace manifest or omit --adapter-package-json to validate the built Storybook at capture time.`)}const Gv=/^[0-9a-f]{40}$/,Kv=/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/,qv=/^\.github\/workflows\/[A-Za-z0-9_./-]+\.ya?ml$/,Jv=`Base branch changed; rerun visual capture`,Yv=new Set([`action_required`,`cancelled`,`failure`,`neutral`,`skipped`,`stale`,`startup_failure`,`success`,`timed_out`]);async function Xv(e,t,n){let r=gy(n.captureWorkflowPath),i=by(n.baseBranch,`base branch`),a=Bd(n.statusContext),o=$v(n.event,r),s=await ey(e,o,i);if(!s.ok)return py(s.reason);if(await ay(t,o,s.target))return py(`final-report-exists`,s.target);let c=await ey(e,o,i);if(!c.ok)return py(c.reason,s.target);if(!fy(s.target,c.target))return py(`pull-request-changed`,c.target);if(await ay(t,o,c.target))return py(`final-report-exists`,c.target);let l=uy(o,c.target);return await t.setReviewStatus(c.target.headSha,l.state,l.description,a),{status:l.state,reason:`status-written`,prNumber:c.target.prNumber,headSha:c.target.headSha}}async function Zv(e,t,n){let r=gy(n.captureWorkflowPath),i=by(n.baseBranch,`base branch`),a=Bd(n.statusContext),o=Qv(n.event,r),s=await ey(e,o,i);if(!s.ok)return my(s.reason);let c=sy(o,await oy(t,o,s.target,a),s.target);if(c)return my(c,s.target);let l=await ey(e,o,i);if(!l.ok)return my(l.reason,s.target);if(!fy(s.target,l.target))return my(`pull-request-changed`,l.target);let u=sy(o,await oy(t,o,l.target,a),l.target);if(u)return my(u,l.target);let d=l.target.baseDrift?Jv:o.run.conclusion===`success`?`Visual report publication did not complete`:`Visual capture did not succeed (${o.run.conclusion})`;return await t.setReviewStatus(l.target.headSha,`error`,d,a),{status:`error`,reason:`status-written`,prNumber:l.target.prNumber,headSha:l.target.headSha}}function Qv(e,t){let n=$v(e,t);if(n.run.status!==`completed`)throw Error(`Kapture finalize-run requires a completed workflow_run event`);return{...n,run:{...n.run,status:`completed`}}}function $v(e,t){let n=Ty(e,`GitHub workflow_run event`),r=Sy(n.action,`workflow_run action`);if(r!==`in_progress`&&r!==`completed`)throw Error(`Kapture reconcile-run requires an in_progress or completed workflow_run event`);let i=Ty(n.repository,`event repository`),a=_y(i.full_name,`event repository`),o=Cy(i.id,`event repository ID`),s=Ty(n.workflow_run,`workflow_run`),c=gy(Sy(s.path,`workflow path`));if(c!==gy(t))throw Error(`workflow_run path ${c} does not match ${t}`);if(s.event!==`pull_request`)throw Error(`Kapture reconcile-run requires a pull_request capture run`);let l=Sy(s.status,`workflow run status`),u=xy(s.conclusion,`workflow run conclusion`);if(r===`in_progress`&&(l!==`in_progress`||u!==null))throw Error(`An in_progress workflow_run event must describe an unfinished run`);if(r===`completed`&&(l!==`completed`||u===null||!Yv.has(u)))throw Error(`A completed workflow_run event must have a supported conclusion`);let d=Ty(s.head_repository,`workflow_run head repository`),f={id:Cy(d.id,`workflow run head repository ID`),fullName:_y(d.full_name,`workflow run head repository`)},p=by(s.head_branch,`workflow run head branch`),m=Ey(s.pull_requests,`workflow_run pull requests`);if(m.length>1)throw Error(`workflow_run must contain at most one pull request`);let h=m[0]?hy(m[0]):void 0;if(h&&(h.base.repositoryId!==o||h.head.repositoryId!==f.id||h.head.ref!==p))throw Error(`workflow_run pull request metadata conflicts with run provenance`);return{repository:{id:o,fullName:a,ref:vy(a)},run:{id:Cy(s.id,`workflow run ID`),runNumber:Cy(s.run_number,`workflow run number`),attempt:Cy(s.run_attempt,`workflow run attempt`),workflowId:Cy(s.workflow_id,`workflow ID`),workflowPath:c,status:l,conclusion:u,event:`pull_request`,headSha:yy(s.head_sha,`workflow run head SHA`),headBranch:p,headRepository:f},...h?{pullRequest:h}:{}}}async function ey(e,t,n){let r=await e.getWorkflowRun(t.run.id);return ty(r,t),r.runAttempt===t.run.attempt?r.status!==t.run.status||r.conclusion!==t.run.conclusion?{ok:!1,reason:`stale-run-state`}:await ny(e,r)?ry(e,t,n):{ok:!1,reason:`superseded-run`}:{ok:!1,reason:`stale-run-attempt`}}function ty(e,t){if(e.id!==t.run.id||e.runNumber!==t.run.runNumber||e.workflowId!==t.run.workflowId||gy(e.path)!==t.run.workflowPath||e.event!==`pull_request`||e.headSha!==t.run.headSha||e.headBranch!==t.run.headBranch||e.headRepository.id!==t.run.headRepository.id||e.headRepository.fullName!==t.run.headRepository.fullName||e.repository.id!==t.repository.id||e.repository.fullName!==t.repository.fullName)throw Error(`Triggering capture run identity no longer matches the workflow_run event`)}async function ny(e,t){let n=(await e.listWorkflowRuns(t.workflowId,t.headBranch)).filter(e=>e.headRepositoryId===t.headRepository.id);if(n.filter(e=>e.id===t.id).some(e=>e.runNumber!==t.runNumber))throw Error(`Latest workflow run metadata conflicts with the triggering run`);return n.reduce((e,t)=>e?t.runNumber===e.runNumber?t.id>e.id?t:e:t.runNumber>e.runNumber?t:e:t,void 0)?.id===t.id}async function ry(e,t,n){if(t.pullRequest){if(t.pullRequest.base.ref!==n)return{ok:!1,reason:`base-branch-mismatch`};let r=await e.getPullRequest(t.pullRequest.number);return iy(r,t,n)?{ok:!0,target:dy(r,r.base.sha!==t.pullRequest.base.sha)}:{ok:!1,reason:`pull-request-not-current`}}let r=(await e.listOpenPullRequestsForHead(t.run.headRepository.fullName,t.run.headBranch,n)).filter(e=>e.state===`open`&&e.base.repository.id===t.repository.id&&e.base.repository.fullName===t.repository.fullName&&e.base.ref===n&&e.head.repository.id===t.run.headRepository.id&&e.head.repository.fullName===t.run.headRepository.fullName&&e.head.ref===t.run.headBranch);return r.length===0?{ok:!1,reason:`pull-request-not-found`}:r.length===1?{ok:!0,target:dy(r[0])}:{ok:!1,reason:`pull-request-ambiguous`}}function iy(e,t,n){let r=t.pullRequest;return!!(r&&e.number===r.number&&e.state===`open`&&e.base.repository.id===t.repository.id&&e.base.repository.fullName===t.repository.fullName&&e.base.ref===n&&e.head.repository.id===t.run.headRepository.id&&e.head.repository.fullName===t.run.headRepository.fullName&&e.head.ref===t.run.headBranch&&e.head.sha===r.head.sha)}async function ay(e,t,n){return ly(await e.findCurrentReportMarker(n.prNumber,n.baseSha,n.headSha),t)}async function oy(e,t,n,r){let i=await e.findCurrentReportMarker(n.prNumber,n.baseSha,n.headSha),a=await e.getLatestReviewStatus(n.headSha,r);return{marker:ly(i,t)?i:null,status:a}}function sy(e,t,n){return n.baseDrift&&t.status?.state===`error`&&t.status.description===Jv?`base-drift-already-recorded`:e.run.conclusion===`success`?cy(t)?`final-report-exists`:t.status?.state===`error`&&t.status.description===`Visual report publication did not complete`?`publication-failure-already-recorded`:void 0:t.status?.state===`error`?`capture-failure-already-recorded`:void 0}function cy(e){let{marker:t,status:n}=e;return!t?.reportUrl||!n||t.reportUrl!==n.targetUrl?!1:t.status===`clean`?n.state===`success`&&n.description===`No visual changes`:t.status===`changed`?n.state===`pending`&&n.description===`Visual changes require approval`:n.state===`failure`}function ly(e,t){return!!(e&&e.captureRunId===t.run.id&&e.captureRunAttempt===t.run.attempt&&e.captureWorkflowId===t.run.workflowId&&e.captureRunHeadBranch===t.run.headBranch&&e.captureRunHeadRepositoryId===t.run.headRepository.id)}function uy(e,t){return t.baseDrift?{state:`error`,description:Jv}:e.run.status===`in_progress`?{state:`pending`,description:`Visual capture is in progress`}:e.run.conclusion===`success`?{state:`pending`,description:`Visual report is awaiting publication`}:{state:`error`,description:`Visual capture did not succeed (${e.run.conclusion})`}}function dy(e,t=!1){return{prNumber:e.number,baseSha:e.base.sha,headSha:e.head.sha,baseDrift:t}}function fy(e,t){return e.prNumber===t.prNumber&&e.baseSha===t.baseSha&&e.headSha===t.headSha&&e.baseDrift===t.baseDrift}function py(e,t){return{status:`noop`,reason:e,...t?{prNumber:t.prNumber,headSha:t.headSha}:{}}}function my(e,t){return{status:`noop`,reason:e,...t?{prNumber:t.prNumber,headSha:t.headSha}:{}}}function hy(e){let t=Ty(e,`workflow_run pull request`),n=Ty(t.base,`workflow_run pull request base`),r=Ty(t.head,`workflow_run pull request head`);return{number:Cy(t.number,`workflow_run pull request number`),base:{repositoryId:Cy(Ty(n.repo,`workflow_run pull request base repository`).id,`workflow_run pull request base repository ID`),ref:by(n.ref,`workflow_run pull request base ref`),sha:yy(n.sha,`workflow_run pull request base SHA`)},head:{repositoryId:Cy(Ty(r.repo,`workflow_run pull request head repository`).id,`workflow_run pull request head repository ID`),ref:by(r.ref,`workflow_run pull request head ref`),sha:yy(r.sha,`workflow_run pull request head SHA`)}}}function gy(e){if(!qv.test(e)||e.includes(`//`)||e.includes(`..`))throw Error(`capture-workflow-path must be a safe .github/workflows YAML path`);return e}function _y(e,t){let n=Sy(e,`${t} full name`);if(!Kv.test(n))throw Error(`${t} full name is invalid`);return n}function vy(e){let[t,n,...r]=e.split(`/`);if(!t||!n||r.length>0)throw Error(`Repository full name is invalid`);return{owner:t,repo:n}}function yy(e,t){let n=Sy(e,t);if(!Gv.test(n))throw Error(`${t} must be a lowercase full SHA`);return n}function by(e,t){let n=Sy(e,t);if(wy(n))throw Error(`${t} contains control characters`);return n}function xy(e,t){return e===null?null:Sy(e,t)}function Sy(e,t){if(typeof e!=`string`||e.length<1||e.length>512)throw Error(`${t} must be a non-empty bounded string`);if(wy(e))throw Error(`${t} contains control characters`);return e}function Cy(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<=0)throw Error(`${t} must be a positive integer`);return e}function wy(e){return Array.from(e).some(e=>{let t=e.codePointAt(0)??0;return t<=31||t===127})}function Ty(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}function Ey(e,t){if(!Array.isArray(e))throw Error(`${t} must be an array`);return e}O();const Dy=D({meta:{name:`finalize-run`,description:`Close an unfinished status for the exact completed trusted workflow run`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/visual-capture.yml`,description:`Trusted path of the pull_request capture workflow`},"base-branch":{type:`string`,required:!0,description:`Expected pull request base branch`},"status-context":{type:`string`,default:`Kapture Visual Review`,description:`GitHub commit status context`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=Oy(n),i=await Zv(new wv(t,r),new Zd(t,r),{event:n,captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],statusContext:Bd(e[`status-context`])});await G({status:i.status,"finalize-reason":i.reason,...i.prNumber===void 0?{}:{"pr-number":i.prNumber},...i.headSha?{"head-sha":i.headSha}:{}})}});function Oy(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}const ky={files:$g,fileBytes:e_,totalBytes:t_};function Ay(e,t){if(!t||s(t)||!/^[A-Za-z0-9._/-]+$/.test(t)||t.split(`/`).some(e=>!e||e===`.`||e===`..`))throw Error(`Storybook directory must be a project-relative path without dot segments`);return f(e,t)}async function jy(e,t,n=ky){let r=Ay(e,t),i=await te(e),a=f(e);for(let e of t.split(`/`)){a=c(a,e);let t=await v(a);if(t.isSymbolicLink()||!t.isDirectory())throw Error(`Storybook path must contain only non-symlink directories`)}let o=await te(r),l=d(i,o);if(l===`..`||l.startsWith(`..${p}`)||s(l))throw Error(`Storybook directory escapes the project root`);let u=(await v(r)).dev,m=[r],h=0,g=0,_=0;for(;m.length;){let e=m.pop();if(!e)break;for(let t of await S(e)){if(_++,_>n.files)throw Error(`Storybook exceeds its entry count boundary`);let r=c(e,t),i=await v(r);if(i.isSymbolicLink()||i.dev!==u)throw Error(`Storybook must not contain symbolic links or cross-device entries`);if(i.isDirectory()){m.push(r);continue}if(!i.isFile())throw Error(`Storybook must contain only regular files and directories`);if(h++,g+=i.size,h>n.files||i.size>n.fileBytes||g>n.totalBytes)throw Error(`Storybook exceeds its file or size boundary`)}}for(let e of[`index.html`,`iframe.html`,`index.json`])if(!(await v(c(r,e))).isFile())throw Error(`Storybook is missing a regular ${e}`);return{directory:r,files:h,bytes:g}}const My=`<!-- kapture-preview -->`;function Ny(e,t,n,r){if(e.base.repository!==e.head.repository||t.id!==e.runId||t.runAttempt!==n||t.path!==r||t.event!==`pull_request`||t.headBranch!==e.head.ref||t.headRepository.id!==e.head.repositoryId||t.headRepository.fullName!==e.head.repository||t.repository.fullName!==e.base.repository)throw Error(`Preview requires the exact same-repository pull request workflow run`)}function Py(e,t){if(t.baseRevision!==e.base.sha||t.headRevision!==e.head.sha)throw Error(`Preview report must match the exact event base/head revisions`)}function Fy(e,t){let{summary:n}=e;return[My,`## Kapture preview`,``,`[Pixel comparison dashboard](${t})`,``,`Snapshots: ${n.total} · Changed: ${n.changed} · Unchanged: ${n.unchanged} · Unstable: ${n.unstable} · Added: ${n.added} · Removed: ${n.removed} · Errors: ${n.errors}`,``,`Head: \`${e.headRevision}\``,`Report digest: \`${e.contentDigest}\``,``,`> Preview only. This result does not approve visual changes. Event-driven approval requires the production workflows on the default branch.`].join(`
631
- `)}O();const Iy=D({meta:{name:`prepare-preview`,description:`Rebuild a same-repository pre-adoption preview without an approval gate`},args:{input:{type:`string`,required:!0},output:{type:`string`,required:!0},"base-branch":{type:`string`,required:!0},"storybook-directory":{type:`string`}},async run({args:e}){if(process.env.GITHUB_EVENT_NAME!==`pull_request`)throw Error(`Preview requires pull_request`);let t=Dg(await ef(),e[`base-branch`]);if(t.base.repository!==t.head.repository)throw Error(`Fork previews are not supported`);let n=f(e.output),r=await tg({inputDir:f(e.input),outputDir:n,trustedBaseBranch:t.base.ref,trustedHeadBranch:t.head.ref,...e[`storybook-directory`]?{storybookUrl:`./storybook/`}:{}});if(Py(t,r.report),e[`storybook-directory`]){let t=f(e[`storybook-directory`]);await jy(a(t),i(t)),await _(t,f(n,`storybook`),{recursive:!0,errorOnExist:!0,force:!1})}await G({"report-directory":n,"report-path":f(n,`report.json`),"report-digest":r.report.contentDigest??``,"head-sha":t.head.sha,"preview-alias":t.preview.alias})}});O();const Ly=D({meta:{name:`prepare-run`,description:`Download, verify, and rebuild a completed workflow_run report`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/visual-capture.yml`,description:`Trusted path of the pull_request capture workflow`},"base-branch":{type:`string`,required:!0,description:`Expected pull request base branch`},output:{type:`string`,default:`.kapture/trusted-report`,description:`New directory for the trusted static report`},receipt:{type:`string`,default:`.kapture/trusted-run-receipt.json`,description:`Path for the strict trusted-run receipt`},"storybook-url":{type:`string`,description:`Trusted HTTPS Storybook URL or the fixed same-origin ./storybook/ directory`},"temporary-root":{type:`string`,description:`Trusted temporary directory root (defaults to RUNNER_TEMP)`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=await v_(new wv(t,Ry(n)),{event:n,captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],outputDir:f(e.output),receiptPath:f(e.receipt),...e[`storybook-url`]?{storybookUrl:e[`storybook-url`]}:{},...e[`temporary-root`]?{temporaryRoot:f(e[`temporary-root`])}:{}});await G({"base-sha":r.receipt.context.base.sha,"context-artifact-id":r.receipt.artifacts.context.id,"head-repository":r.receipt.context.head.repository,"head-sha":r.receipt.context.head.sha,"pr-number":r.receipt.context.prNumber,"preview-branch":r.receipt.context.preview.branch,"preview-alias":r.receipt.context.preview.alias,"raw-report-artifact-id":r.receipt.artifacts.report.id,"report-digest":r.receipt.report.contentDigest,"report-directory":r.reportDirectory,"report-path":r.reportPath,receipt:r.receiptPath,"run-attempt":r.receipt.captureRun.attempt,"run-head-branch":r.receipt.captureRun.headBranch,"run-head-repository-id":r.receipt.captureRun.headRepositoryId,"run-head-sha":r.receipt.captureRun.headSha,"run-id":r.receipt.captureRun.id,"changed-files-complete":String(r.changedFiles.complete),"changed-files-count":r.changedFiles.files.length,"trusted-artifact-name":r.receipt.trustedArtifactName,"workflow-id":r.receipt.captureRun.workflowId})}});function Ry(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O();const zy=D({meta:{name:`prepare-storybook-run`,description:`Verify and extract the exact receipt-bound head Storybook artifact`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/visual-capture.yml`,description:`Trusted path of the pull_request capture workflow`},"base-branch":{type:`string`,required:!0,description:`Expected pull request base branch`},output:{type:`string`,required:!0,description:`New directory for the verified head Storybook`},receipt:{type:`string`,required:!0,description:`Path to the strict prepare-run receipt`},"temporary-root":{type:`string`,description:`Trusted temporary directory root (defaults beside output)`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=await b_(new wv(t,By(n)),{event:n,captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],outputDir:f(e.output),receiptPath:f(e.receipt),...e[`temporary-root`]?{temporaryRoot:f(e[`temporary-root`])}:{}});await G({"head-ref":r.context.head.ref,"head-repository":r.context.head.repository,"head-sha":r.context.head.sha,"head-storybook-artifact-id":r.artifact.id,"pr-number":r.context.prNumber,"preview-branch":r.context.preview.branch,"preview-alias":r.context.preview.alias,receipt:r.receiptPath,"storybook-directory":r.storybookDirectory})}});function By(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O();const Vy=D({meta:{name:`reconcile-run`,description:`Reconcile a trusted workflow_run event with the current PR status`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/visual-capture.yml`,description:`Trusted path of the pull_request capture workflow`},"base-branch":{type:`string`,required:!0,description:`Expected pull request base branch`},"status-context":{type:`string`,default:`Kapture Visual Review`,description:`GitHub commit status context`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=Hy(n),i=await Xv(new wv(t,r),new Zd(t,r),{event:n,captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],statusContext:Bd(e[`status-context`])});await G({status:i.status,"reconcile-reason":i.reason,...i.prNumber===void 0?{}:{"pr-number":i.prNumber},...i.headSha?{"head-sha":i.headSha}:{}})}});function Hy(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O();async function Uy(e,t,n=async(e,t)=>{switch(e){case`reconcile-run`:await Be(Vy,{rawArgs:t});break;case`prepare-run`:await Be(Ly,{rawArgs:t});break;case`prepare-storybook-run`:await Be(zy,{rawArgs:t})}}){let r=[`--capture-workflow-path`,t.captureWorkflowPath,`--base-branch`,t.baseBranch];if(await n(`reconcile-run`,[...r,`--status-context`,t.statusContext]),!e||typeof e!=`object`)throw Error(`Invalid workflow_run event`);let i=e;return i.action!==`completed`||i.workflow_run?.conclusion!==`success`?!1:(await n(`prepare-run`,[...r,`--output`,t.output,`--receipt`,t.receipt,...t.includeStorybook?[`--storybook-url`,`./storybook/`]:[]]),t.includeStorybook&&await n(`prepare-storybook-run`,[...r,`--output`,f(t.output,`storybook`),`--receipt`,t.receipt]),!0)}const Wy=D({meta:{name:`prepare-review`,description:`Reconcile a workflow run and prepare verified static files for any hosting provider`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/kapture-capture.yml`},"base-branch":{type:`string`,required:!0},output:{type:`string`,required:!0},receipt:{type:`string`,required:!0},"include-storybook":{type:`boolean`,default:!1},"status-context":{type:`string`,default:`Kapture Visual Review`}},async run({args:e}){await G({ready:`false`});let t=await Uy(await ef(),{captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],output:f(e.output),receipt:f(e.receipt),includeStorybook:e[`include-storybook`],statusContext:e[`status-context`]});await G({ready:String(t)})}});O();const Gy=D({meta:{name:`publish-preview`,description:`Publish a preview-only status and comment; never issue an approval marker`},args:{report:{type:`string`,required:!0},"report-digest":{type:`string`,required:!0},"report-url":{type:`string`,required:!0},"base-branch":{type:`string`,required:!0},"capture-workflow-path":{type:`string`,default:`.github/workflows/kapture-capture.yml`}},async run({args:e}){if(process.env.GITHUB_EVENT_NAME!==`pull_request`)throw Error(`Preview requires pull_request`);let t=Dg(await ef(),e[`base-branch`]),n=process.env.GITHUB_TOKEN;if(!n)throw Error(`GITHUB_TOKEN is required`);let[r,i]=t.base.repository.split(`/`);if(!r||!i)throw Error(`Invalid repository`);let a=new Zd(n,{owner:r,repo:i}),o=new wv(n,{owner:r,repo:i}),s=await o.getWorkflowRun(t.runId);Ny(t,s,Number(process.env.GITHUB_RUN_ATTEMPT),e[`capture-workflow-path`]);let c=await rg(f(e.report),e[`report-digest`]);Py(t,c);let l=Rd(e[`report-url`]);if(!l)throw Error(`Preview report URL is required`);let u=async()=>{let n=await a.getPullRequest(t.prNumber);if(n.number!==t.prNumber||n.state!==`open`||n.head.sha!==t.head.sha||n.base.sha!==t.base.sha)throw Error(`Ignoring an obsolete preview result`);let r=await o.getWorkflowRun(t.runId);Ny(t,r,s.runAttempt,e[`capture-workflow-path`]),await w_(o,r)};await u();let d=await a.postOrUpdateReportComment(t.prNumber,Fy(c,l),My);if(await u(),await a.setReviewStatus(t.head.sha,c.summary.errors?`failure`:`success`,`Preview only; visual changes require separate review`,`Kapture Preview`,l),await G({"comment-id":d,"report-digest":c.contentDigest??``}),c.summary.errors)throw Error(`Preview contains capture errors`)}});O();const Ky=D({meta:{name:`publish-run`,description:`Revalidate a prepare-run receipt and publish its deployed visual report`},args:{receipt:{type:`string`,required:!0,description:`Path to the strict prepare-run receipt`},report:{type:`string`,required:!0,description:`Path to the trusted image-bound report.json`},"report-url":{type:`string`,required:!0,description:`Immutable HTTPS URL of the deployed dashboard`},"status-context":{type:`string`,default:`Kapture Visual Review`,description:`GitHub commit status context`},"comment-language":{type:`string`,default:`en`,description:`PR comment language (en or ko)`}},async run({args:e}){try{let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=qy(n),i=Rd(e[`report-url`]);if(!i)throw Error(`report-url is required`);let a=await y_(new wv(t,r),new Zd(t,r),{event:n,receiptPath:f(e.receipt),reportPath:f(e.report),reportUrl:i,statusContext:Bd(e[`status-context`]),commentLanguage:Od(e[`comment-language`])});if(await G({status:a.status,"changed-count":a.changedCount,"comment-id":a.commentId,"report-digest":a.reportDigest}),a.status===`error`)throw Error(`Visual capture errors were published to the trusted report`)}catch(e){throw await G({status:`error`}),e}}});function qy(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O(),Jh();const Jy=D({meta:{name:`report`,description:`Publish a trusted Kapture PR report and commit status`},args:{report:{type:`string`,required:!0,description:`Path to image-bound trusted report.json`},"report-url":{type:`string`,description:`HTTPS URL for the full report or workflow run`},"status-context":{type:`string`,default:`Kapture Visual Review`,description:`GitHub commit status context`},"comment-language":{type:`string`,default:`en`,description:`PR comment language (en or ko)`}},async run({args:e}){try{let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await Eh(e.report),r=tf(await ef()),i=Bd(e[`status-context`]),a=Rd(e[`report-url`]),o=await ff(new Zd(t,r.repository),r,n,i,a,Od(e[`comment-language`]));if(await G({status:o.status,"changed-count":o.changedCount,"comment-id":o.commentId,"report-digest":o.reportDigest}),o.status===`error`)throw Error(`${n.summary.errors} visual capture error(s)`)}catch(e){throw await G({status:`error`}),e}}});O();const Yy=D({meta:{name:`validate-build`,description:`Validate a Storybook artifact boundary before upload or capture`},args:{root:{type:`string`,required:!0,description:`Trusted checkout or artifact extraction root`},directory:{type:`string`,required:!0,description:`Storybook directory relative to root`},"path-only":{type:`boolean`,default:!1,description:`Validate the input path before building`}},async run({args:e}){if(e[`path-only`]){await G({directory:Ay(e.root,e.directory)});return}let t=await jy(e.root,e.directory);await G(t),console.log(`Validated ${t.files} Storybook files (${t.bytes} bytes).`)}});O(),Jh();const Xy=D({meta:{name:`verify`,description:`Verify that a Kapture report matches the current pull request`},args:{report:{type:`string`,required:!0,description:`Path to untrusted report.json`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await Eh(e.report),r=tf(await ef());await df(new Zd(t,r.repository),r,n)}});O();const Zy=D({meta:{name:`github`,description:`Verify, publish, and approve GitHub visual reviews`},subCommands:{context:Uv,"validate-build":Yy,"bind-artifacts":Cv,"prepare-review":Wy,"prepare-preview":Iy,"publish-preview":Gy,verify:Xy,report:Jy,approve:hf,"prepare-run":Ly,"prepare-storybook-run":zy,"publish-run":Ky,"reconcile-run":Vy,"finalize-run":Dy,cleanup:Bv}});async function Qy(e,t){let{report:n,resolveImage:r}=await $y(e),i=n.entries[t];if(!i)throw Error(`Kapture report does not contain snapshot ${t}`);let a=[],o=(e,t)=>{t&&(ib(e,t),a.push({role:e,mediaType:`image/png`,source:r(t)}))};return o(`base`,i.baseImage),o(`head`,i.headImage),o(`diff`,i.diffImage),o(`base-repeat`,i.instability?.base?.repeatImage),o(`base-instability-diff`,i.instability?.base?.diffImage),o(`head-repeat`,i.instability?.head?.repeatImage),o(`head-instability-diff`,i.instability?.head?.diffImage),{version:1,report:{baseRevision:n.baseRevision,headRevision:n.headRevision,...n.contentDigest?{contentDigest:n.contentDigest}:{}},snapshot:{id:i.id,storyId:i.storyId,title:i.title,name:i.name,viewport:i.viewport,status:i.status,...i.changedPixels===void 0?{}:{changedPixels:i.changedPixels},...i.diffRatio===void 0?{}:{diffRatio:i.diffRatio},...i.threshold?{threshold:i.threshold}:{},...i.error?{error:i.error}:{}},images:a}}async function $y(e){let t=rb(e);return t?tb(t):eb(e)}async function eb(e){let t=f(e),n=await C(t);if(!n.isFile()||n.size>10485760)throw Error(`Kapture report must be a file no larger than ${Oh} bytes`);let r=nb(await x(t,`utf8`)),i=a(t);return{report:r,resolveImage:e=>{let t=f(i,e);if(d(i,t).startsWith(`..`))throw Error(`Kapture report contains an unsafe image path: ${e}`);return{type:`path`,value:t}}}}async function tb(e){let t=await fetch(e,{redirect:`error`});if(!t.ok)throw Error(`Kapture report request failed with HTTP ${t.status}`);let n=Number(t.headers.get(`content-length`));if(Number.isFinite(n)&&n>10485760)throw Error(`Kapture report must be no larger than ${Oh} bytes`);let r=await t.text();if(Buffer.byteLength(r)>10485760)throw Error(`Kapture report must be no larger than ${Oh} bytes`);return{report:nb(r),resolveImage:t=>{let n=new URL(t,e);if(n.origin!==e.origin||n.protocol!==`https:`)throw Error(`Kapture report contains an unsafe image URL: ${t}`);return{type:`url`,value:n.toString()}}}}function nb(e){try{return wh(JSON.parse(e))}catch(e){throw e instanceof SyntaxError?Error(`Kapture report does not contain valid JSON`):e}}function rb(e){let t;try{t=new URL(e)}catch{return}if(t.protocol!==`https:`||t.username||t.password)throw Error(`Remote Kapture report must be an HTTPS URL without credentials`);return t}function ib(e,t){let n=`images/${e}/`,r=t.slice(n.length);if(!t.startsWith(n)||!r||r.includes(`/`)||r.includes(`\\`)||!r.endsWith(`.png`))throw Error(`Kapture report contains an invalid ${e} image path: ${t}`)}var ab,ob=w((()=>{O(),Jh(),ab=D({meta:{name:`inspect`,description:`Print machine-readable snapshot evidence for agents and review tools`},args:{report:{type:`string`,required:!0,description:`Local report.json path or public HTTPS report.json URL`},snapshot:{type:`string`,required:!0,description:`Exact snapshot ID`}},async run({args:e}){let t=await Qy(e.report,e.snapshot);process.stdout.write(`${JSON.stringify(t,null,2)}\n`)}})})),sb=w((()=>{Mc()})),cb=w((()=>{sb()})),lb=Ce({createKaptureMcpServer:()=>db,getSnapshotEvidenceResult:()=>fb,startKaptureMcpServer:()=>ub});async function ub(e){let{serveStdio:t}=await import(`@modelcontextprotocol/server/stdio`);t(()=>db(e),{onerror:e=>console.error(e.message)})}async function db(e){let{McpServer:t}=await import(`@modelcontextprotocol/server`),n=new t({name:`kapture`,version:$e},{instructions:`Use list_snapshots to find visual changes, then get_snapshot_evidence to inspect the exact PNG evidence. Unstable snapshots are nondeterministic and do not represent an approvable baseline change.`});return n.registerTool(`list_snapshots`,{title:`List Kapture snapshots`,description:`List snapshot IDs, statuses, stories, viewports, and diff metrics from a report.`,inputSchema:Ss({status:Es([`unchanged`,`changed`,`unstable`,`added`,`removed`,`error`]).optional().describe(`Optional exact status filter`)}),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0}},async({status:t})=>{let{report:n}=await $y(e),r=Object.values(n.entries).filter(e=>!t||e.status===t).map(e=>({id:e.id,storyId:e.storyId,title:e.title,name:e.name,viewport:e.viewport,status:e.status,changedPixels:e.changedPixels,changedPixelPercentage:e.diffRatio===void 0?void 0:e.diffRatio*100})),i={baseRevision:n.baseRevision,headRevision:n.headRevision,summary:n.summary,snapshots:r};return{content:[{type:`text`,text:JSON.stringify(i,null,2)}],structuredContent:i}}),n.registerTool(`get_snapshot_evidence`,{title:`Get Kapture snapshot evidence`,description:`Return machine-readable metadata and the actual base, head, diff, and instability PNGs for one snapshot.`,inputSchema:Ss({snapshotId:R().min(1).max(512).describe(`Exact ID returned by list_snapshots`)}),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0}},async({snapshotId:t})=>fb(e,t)),n}async function fb(e,t){let n=await Qy(e,t),r=await Promise.all(n.images.map(pb));return{content:[{type:`text`,text:JSON.stringify(_b(n),null,2)},...r],structuredContent:_b(n)}}async function pb(e){return{type:`image`,data:(e.source.type===`path`?await mb(e.source.value):await hb(e.source.value)).toString(`base64`),mimeType:`image/png`,_meta:{"kapture/role":e.role}}}async function mb(e){let t=await v(e);if(t.isSymbolicLink()||!t.isFile()||t.size>vb)throw Error(`Kapture evidence image must be no larger than ${vb} bytes`);return gb(await x(e),e)}async function hb(e){let t=await fetch(e,{redirect:`error`});if(!t.ok)throw Error(`Kapture evidence request failed with HTTP ${t.status}`);let n=Number(t.headers.get(`content-length`));if(Number.isFinite(n)&&n>vb)throw Error(`Kapture evidence image must be no larger than ${vb} bytes`);return gb(Buffer.from(await t.arrayBuffer()),e)}function gb(e,t){if(e.byteLength>vb||!e.subarray(0,8).equals(yb))throw Error(`Kapture evidence is not a supported PNG: ${t}`);return e}function _b(e){return{...e,images:e.images.map(t=>({role:t.role,mediaType:t.mediaType,source:t.source,contentBlockIndex:e.images.indexOf(t)+1}))}}var vb,yb,bb=w((()=>{cb(),ob(),vb=26214400,yb=Buffer.from([137,80,78,71,13,10,26,10])}));O();const xb=D({meta:{name:`mcp`,description:`Serve Kapture snapshot evidence to agents over MCP stdio`},args:{report:{type:`string`,required:!0,description:`Local report.json path or public HTTPS report.json URL`}},async run({args:e}){let{startKaptureMcpServer:t}=await Promise.resolve().then(()=>(bb(),lb));await t(e.report)}});Td(),O();const Sb=D({meta:{name:`plan`,description:`Select affected Storybook stories from base/head dependency manifests`},args:{"base-dir":{type:`string`,required:!0,description:`Built base Storybook directory`},"head-dir":{type:`string`,required:!0,description:`Built head Storybook directory`},"changed-files":{type:`string`,required:!0,description:`Path to a versioned changed-files manifest or legacy JSON path array`},output:{type:`string`,default:`.kapture/plan.json`,description:`Affected-story plan output path`}},async run({args:e}){let t=await Cb(f(e[`changed-files`])),n=await El({baseDir:f(e[`base-dir`]),headDir:f(e[`head-dir`]),changedFiles:t.files,changedFilesComplete:t.complete,...t.evidence?{changedFilesEvidence:t.evidence}:{}}),r=f(e.output);await y(a(r),{recursive:!0}),await ie(r,`${JSON.stringify(n,null,2)}\n`,`utf8`),n.selectionMode===`affected`?Q.success(`Selected ${n.selectedStoryIds.length} of ${n.totalStoryIds.length} affected stories`):Q.warn(`Selected all ${n.totalStoryIds.length} stories (${n.fallbackReasons.map(e=>e.code).join(`, `)})`),Q.info(`Plan: ${r}`)}});async function Cb(e){let t;try{t=JSON.parse(await x(e,`utf8`))}catch(t){throw Error(`Failed to read changed files JSON from ${e}`,{cause:t})}if(!Array.isArray(t)){let e=Rg(t);return{files:e.files,complete:e.complete,evidence:{provider:e.source.provider,manifestDigest:ae(`sha256`).update(JSON.stringify(e)).digest(`hex`),pullRequestNumber:e.pullRequest.number,baseSha:e.pullRequest.baseSha,headSha:e.pullRequest.headSha}}}if(t.length>1e5)throw Error(`changed-files contains too many paths`);return{files:t.map(e=>zg(e,`changed file path`)),complete:!0}}O();const wb=D({meta:{name:`report`,description:`Build trusted static Kapture reports`},subCommands:{build:eg}});Td(),O();const Tb=D({meta:{name:`test`,description:`Capture and compare base/head Storybooks in one hermetic browser environment`},args:{"github-artifacts":{type:`boolean`,default:!1,description:`Validate downloaded builds, bind Actions artifact identities and preserve error reports for publication`},"base-dir":{type:`string`,required:!0,description:`Built base Storybook directory`},"head-dir":{type:`string`,required:!0,description:`Built head Storybook directory`},"base-capture-dir":{type:`string`,description:`Verified capture directory for the exact base revision; captures head only`},"base-revision":{type:`string`,required:!0,description:`Base Git revision`},"head-revision":{type:`string`,required:!0,description:`Head Git revision`},"changed-files":{type:`string`,description:`Versioned changed-files manifest used to capture only provably affected stories`},"install-browser":{type:`boolean`,default:!1,description:`Install the pinned Chrome runtime only when at least one story is selected`},"browser-with-deps":{type:`boolean`,default:!1,description:`Install Linux browser dependencies together with Chrome`},output:{type:`string`,default:`.kapture`,description:`Output directory`},workers:{type:`string`,default:`4`,description:`Concurrent isolated story lanes`},"pixel-color-threshold":{type:`string`,default:`0.2`,description:`Per-pixel perceptual color threshold`},"max-changed-pixel-percentage":{type:`string`,default:`0`,description:`Maximum percentage of changed pixels allowed without review (0 to 100)`},"frozen-time":{type:`string`,default:`2026-01-01T00:00:00.000Z`,description:`ISO time exposed to stories`},"random-seed":{type:`string`,default:`20260101`,description:`Math.random seed`},locale:{type:`string`,default:`en-US`,description:`BCP 47 browser locale`},timezone:{type:`string`,default:`UTC`,description:`IANA browser time zone`},"dashboard-dir":{type:`string`,description:`Dashboard build directory (defaults to the CLI embedded dashboard)`}},async run({args:e}){let t=Ab(e.workers),n=jb(e[`pixel-color-threshold`],`pixel-color-threshold`),r=Mb(e[`max-changed-pixel-percentage`],`max-changed-pixel-percentage`),o=kb(e[`random-seed`],`random-seed`),s=f(e[`base-dir`]),c=f(e[`head-dir`]),l=e[`github-artifacts`]?Sv(process.env):void 0;if(l){let t=`-base-${e[`base-revision`]}-head-${e[`head-revision`]}`;if(!l.artifacts.context.name.endsWith(t))throw Error(`Artifact identities must match the requested base/head revisions`);await Promise.all([s,c].map(e=>jy(a(e),i(e))))}let u=e[`changed-files`]?await Eb(s,c,f(e[`changed-files`]),e[`base-revision`],e[`head-revision`]):void 0;Ob(u),e[`install-browser`]&&Db(u)&&(Q.start(`Installing the Kapture browser runtime…`),await tt(e[`browser-with-deps`])),Q.start(e[`base-capture-dir`]?`Reusing the verified base capture and capturing affected head stories…`:`Capturing base and head Storybooks in one hermetic environment…`);let d=await bu({baseDir:s,headDir:c,...e[`base-capture-dir`]?{baseCaptureDir:f(e[`base-capture-dir`])}:{},baseRevision:e[`base-revision`],headRevision:e[`head-revision`],outputDir:f(e.output),workers:t,threshold:{pixelColorThreshold:n,maxChangedPixelRatio:r/100},frozenTime:e[`frozen-time`],randomSeed:o,locale:e.locale,timezone:e.timezone,adapterVersion:$e,selectionPlan:u});await Wu(e[`dashboard-dir`]?f(e[`dashboard-dir`]):f(a(pe(import.meta.url)),`dashboard`),f(e.output,`report`)),l&&(await ie(f(e.output,`report`,`capture-boundary.json`),`${JSON.stringify(l)}\n`,{flag:`wx`,mode:384}),await G({"report-directory":f(e.output,`report`),"report-path":f(e.output,`report`,`report.json`),"capture-errors":d.report.summary.errors}));let{summary:p}=d.report;Q.success(`${p.total} snapshots: ${p.changed} changed, ${p.unstable} unstable, ${p.added} added, ${p.removed} removed, ${p.unchanged} unchanged, ${p.errors} errors`),Q.info(`Environment: ${d.report.environment.id}`),Q.info(`Report: ${f(e.output,`report`,`report.json`)}`),p.errors>0&&!l&&(process.exitCode=2)}});async function Eb(e,t,n,r,i){let a=await Cb(n);if(a.evidence&&(a.evidence.baseSha!==r||a.evidence.headSha!==i))throw Error(`changed-files manifest base/head SHAs must match --base-revision and --head-revision`);return El({baseDir:e,headDir:t,changedFiles:a.files,changedFilesComplete:a.complete,...a.evidence?{changedFilesEvidence:a.evidence}:{}})}function Db(e){return!e||e.selectedStoryIds.length>0}function Ob(e){if(!e){Q.info(`Story coverage: full capture (no changed-files manifest)`);return}if(e.selectionMode===`affected`){Q.info(`Story coverage: ${e.selectedStoryIds.length} affected, ${e.skippedStoryIds.length} proven unaffected`);return}Q.warn(`Story coverage: full fallback (${e.fallbackReasons.map(e=>e.code).join(`, `)})`)}function kb(e,t){let n=Number.parseInt(e,10);if(!Number.isInteger(n)||n<=0)throw Error(`${t} must be a positive integer`);return n}function Ab(e){let t=kb(e,`workers`);if(t>8)throw Error(`workers must be between 1 and 8`);return t}function jb(e,t){let n=Number.parseFloat(e);if(!Number.isFinite(n)||n<0||n>1)throw Error(`${t} must be between 0 and 1`);return n}function Mb(e,t){let n=Number(e);if(!Number.isFinite(n)||n<0||n>100)throw Error(`${t} must be between 0 and 100`);return n}O(),Jh();const Nb=D({meta:{name:`validate`,description:`Validate a Kapture report as a CI gate`},args:{report:{type:`string`,required:!0,description:`Path to report.json`},"fail-on-diff":{type:`boolean`,default:!1,description:`Exit 1 when visual changes require review`}},async run({args:e}){let t=f(e.report),n=await C(t);if(!n.isFile()||n.size>10485760)throw Error(`Kapture report must be a file no larger than ${Oh} bytes`);let r=wh(JSON.parse(await x(t,`utf8`)));if(r.summary.errors>0){Q.error(`${r.summary.errors} capture or comparison error(s)`),process.exitCode=2;return}let i=r.summary.changed+r.summary.added+r.summary.removed;if(r.summary.unstable>0&&Q.warn(`${r.summary.unstable} unstable snapshot(s) are non-blocking`),i>0&&e[`fail-on-diff`]){Q.warn(`${i} visual change(s) require human approval`),process.exitCode=1;return}Q.success(i>0?`${i} visual change(s) detected`:`No visual changes`)}});O(),ob(),We(D({meta:{name:`kapture`,version:$e,description:`Hermetic Storybook visual review`},subCommands:{test:Tb,validate:Nb,browser:nt,ci:ut,plan:Sb,report:wb,github:Zy,inspect:ab,mcp:xb}}));export{};
630
+ `:l}};function yh(e){return e.replace(/`([^`]+)`/gm,(e,t)=>Kf.cyan(t)).replace(/\s+_([^_]+)_\s+/gm,(e,t)=>` ${Kf.underline(t)} `)}function bh(e=`white`){return Kf[e]||Kf.white}function xh(e=`bgWhite`){return Kf[`bg${e[0].toUpperCase()}${e.slice(1)}`]||Kf.bgWhite}function Sh(e={}){let t=Ch();return process.env.CONSOLA_LEVEL&&(t=Number.parseInt(process.env.CONSOLA_LEVEL)??t),Ef({level:t,defaults:{level:t},stdout:process.stdout,stderr:process.stderr,prompt:(...e)=>Promise.resolve().then(()=>(Em(),$f)).then(t=>t.prompt(...e)),reporters:e.reporters||[e.fancy??!(Im||zm)?new vh:new Af],...e})}function Ch(){return Rm?K.debug:zm?K.warn:K.info}const Q=Sh();function wh(e){let t=qh.safeParse(Th(e));if(!t.success){let e=t.error.issues[0],n=e?.path.length?` at ${e.path.join(`.`)}`:``;throw Error(`Invalid Kapture report${n}: ${e?.message??`unknown error`}`)}return t.data}function Th(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e;return t.version!==2||!t.summary||typeof t.summary!=`object`?e:{...t,version:3,summary:{...t.summary,unstable:0}}}async function Eh(e){let t=f(e),n=await C(t);if(!n.isFile()||n.size>10485760)throw Error(`Kapture report must be a file no larger than ${Oh} bytes`);let r;try{r=JSON.parse(await x(t,`utf8`))}catch{throw Error(`Kapture report does not contain valid JSON`)}return wh(r)}function Dh(e){try{let t=new URL(e);return t.protocol===`https:`&&!t.username&&!t.password}catch{return!1}}var Oh,kh,Ah,$,jh,Mh,Nh,Ph,Fh,Ih,Lh,Rh,zh,Bh,Vh,Hh,Uh,Wh,Gh,Kh,qh,Jh=w((()=>{Td(),Nc(),Oh=10485760,kh=2e4,Ah=R().max(4096),$=R().min(1).max(512),jh=$.refine(e=>Array.from(e).every(e=>{let t=e.codePointAt(0)??0;return t>31&&t!==127}),`must not contain control characters`),Mh=z().int().min(0).max(2**53-1),Nh=z().int().positive().max(2**53-1),Ph=z().min(0).max(1),Fh=B({name:$,width:z().int().positive().max(16384),height:z().int().positive().max(16384)}),Ih=B({pixelColorThreshold:Ph,maxChangedPixelRatio:Ph}),Lh=B({id:$,browser:$,browserVersion:$,orchestratorRuntime:$,operatingSystem:$,architecture:$,deviceScaleFactor:z().positive().max(8),locale:$,timezone:$,colorScheme:Es([`light`,`dark`]),reducedMotion:Es([`reduce`,`no-preference`]),frozenTime:$,randomSeed:z().int().min(0).max(2**53-1),fontsFingerprint:$,stateIsolation:H(`fresh-browser-process-per-story-side-v1`).optional(),network:B({mode:H(`allowlist`),allowedDomains:xs($).max(100),webRtc:H(`disabled`)})}),Rh=B({id:$,storyId:$,title:Ah,name:Ah,viewport:Fh,status:Es([`unchanged`,`changed`,`unstable`,`added`,`removed`,`error`]),baseImage:Ah.optional(),headImage:Ah.optional(),diffImage:Ah.optional(),ignoredRegions:xs(B({x:z().int().min(0).max(16384),y:z().int().min(0).max(32768),width:z().int().positive().max(16384),height:z().int().positive().max(32768)})).max(1e4).optional(),changedPixels:Mh.optional(),diffRatio:Ph.optional(),threshold:Ih.optional(),instability:B({base:B({repeatImage:Ah,diffImage:Ah,changedPixels:Mh,diffRatio:Ph}).optional(),head:B({repeatImage:Ah,diffImage:Ah,changedPixels:Mh,diffRatio:Ph}).optional()}).optional(),error:Ah.optional()}).superRefine((e,t)=>{e.status===`unstable`&&!e.instability?.base&&!e.instability?.head&&t.addIssue({code:`custom`,path:[`instability`],message:`unstable snapshots require base or head instability evidence`}),e.status!==`unstable`&&e.instability&&t.addIssue({code:`custom`,path:[`instability`],message:`only unstable snapshots can contain instability evidence`})}),zh=xs($).max(kh).refine(e=>new Set(e).size===e.length,`must not contain duplicates`).refine(e=>e.every((t,n)=>n===0||e[n-1]<t),`must be sorted`),Bh=B({code:Es([`base-manifest-missing`,`base-manifest-invalid`,`head-manifest-missing`,`head-manifest-invalid`,`changed-files-incomplete`,`manifest-incomplete`,`global-input`,`global-output`,`global-runtime`,`unknown-input`,`story-import-missing`,`story-module-missing`,`fallback-reasons-truncated`]),path:Ah.optional(),storyId:$.optional(),side:Es([`base`,`head`]).optional()}),Vh=B({provider:H(`github-pull-request-files`),manifestDigest:R().regex(/^[0-9a-f]{64}$/),pullRequestNumber:Nh,baseSha:R().regex(/^[0-9a-f]{40}$/),headSha:R().regex(/^[0-9a-f]{40}$/)}),Hh=R().regex(/^[0-9a-f]{64}$/),Uh=ws(`state`,[B({state:H(`valid`),digest:Hh,revision:$}),B({state:H(`invalid`),digest:Hh.optional(),revision:$}),B({state:H(`missing`),revision:$})]),Wh=B({base:Uh,head:Uh}),Gh=B({repository:$.regex(/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/),number:Nh,url:Ah.refine(Dh,`must be an HTTPS URL without credentials`),baseBranch:jh,headBranch:jh,workflowRunUrl:Ah.refine(Dh,`must be an HTTPS URL without credentials`)}),Kh=B({plannerVersion:H(1),mode:Es([`full`,`affected`,`full-fallback`]),changedFilesEvidence:Vh.optional(),dependencyManifests:Wh.optional(),storyIds:zh,selectedStoryIds:zh,skippedStoryIds:zh,addedStoryIds:zh.optional(),removedStoryIds:zh.optional(),fallbackReasons:xs(Bh).max(yd),baseline:B({mode:H(`reused`),revision:$,manifestDigest:Hh}).optional()}).superRefine((e,t)=>{let n=new Set(e.storyIds),r=new Set(e.selectedStoryIds),i=new Set(e.skippedStoryIds);if((r.size+i.size!==n.size||[...r].some(e=>!n.has(e)||i.has(e))||[...i].some(e=>!n.has(e)))&&t.addIssue({code:`custom`,message:`selected and skipped stories must exactly partition the story catalog`}),e.mode!==`affected`&&i.size>0&&t.addIssue({code:`custom`,path:[`skippedStoryIds`],message:`full coverage modes cannot skip stories`}),e.mode===`full-fallback`&&e.fallbackReasons.length===0&&t.addIssue({code:`custom`,path:[`fallbackReasons`],message:`full-fallback coverage requires at least one reason`}),e.mode!==`full-fallback`&&e.fallbackReasons.length>0&&t.addIssue({code:`custom`,path:[`fallbackReasons`],message:`only full-fallback coverage can contain fallback reasons`}),e.addedStoryIds===void 0!=(e.removedStoryIds===void 0)&&t.addIssue({code:`custom`,message:`added and removed story catalogs must be provided together`}),e.addedStoryIds&&e.removedStoryIds){let i=new Set(e.addedStoryIds),a=new Set(e.removedStoryIds);([...i].some(e=>!n.has(e)||!r.has(e)||a.has(e))||[...a].some(e=>!n.has(e)||!r.has(e)))&&t.addIssue({code:`custom`,message:`added and removed stories must be disjoint selected catalog members`})}}),qh=B({version:H(3),contentDigest:R().regex(/^[0-9a-f]{64}$/).optional(),baseRevision:$,headRevision:$,headBranch:jh.optional(),baseBranch:jh.optional(),pullRequest:Gh.optional(),storybookUrl:Ah.refine(e=>e===`./storybook/`||Dh(e),`must be an HTTPS URL or ./storybook/ without credentials`).optional(),environment:Lh,createdAt:$,threshold:Ih,summary:B({total:Mh,unchanged:Mh,changed:Mh,unstable:Mh,added:Mh,removed:Mh,errors:Mh}),coverage:Kh.optional(),entries:V(R(),Rh)}).superRefine((e,t)=>{let n=Object.entries(e.entries);if(n.length>2e4){t.addIssue({code:`custom`,message:`Report contains more than ${kh} entries`,path:[`entries`]});return}for(let[e,r]of n)e!==r.id&&t.addIssue({code:`custom`,message:`Entry key must match entry.id`,path:[`entries`,e,`id`]});let r={unchanged:0,changed:0,unstable:0,added:0,removed:0,error:0};for(let t of Object.values(e.entries))r[t.status]+=1;if((e.summary.total!==n.length||e.summary.unchanged!==r.unchanged||e.summary.changed!==r.changed||e.summary.unstable!==r.unstable||e.summary.added!==r.added||e.summary.removed!==r.removed||e.summary.errors!==r.error)&&t.addIssue({code:`custom`,message:`Report summary does not match its entries`,path:[`summary`]}),e.coverage){let r=e.coverage.changedFilesEvidence;r&&(r.baseSha!==e.baseRevision||r.headSha!==e.headRevision)&&t.addIssue({code:`custom`,message:`Changed-files evidence must match the report base and head revisions`,path:[`coverage`,`changedFilesEvidence`]});let i=e.coverage.dependencyManifests;i&&(i.base.revision!==e.baseRevision||i.head.revision!==e.headRevision)&&t.addIssue({code:`custom`,message:`Dependency manifest evidence must match the report base and head revisions`,path:[`coverage`,`dependencyManifests`]});let a=new Set(e.coverage.selectedStoryIds),o=new Set(e.coverage.addedStoryIds??[]),s=new Set(e.coverage.removedStoryIds??[]);for(let[e,r]of n)a.has(r.storyId)||t.addIssue({code:`custom`,message:`Report entries must belong to selected stories`,path:[`entries`,e,`storyId`]}),o.has(r.storyId)&&r.status!==`added`&&r.status!==`error`&&t.addIssue({code:`custom`,message:`Entries for an added story must be added or error snapshots`,path:[`entries`,e,`status`]}),s.has(r.storyId)&&r.status!==`removed`&&r.status!==`error`&&t.addIssue({code:`custom`,message:`Entries for a removed story must be removed or error snapshots`,path:[`entries`,e,`status`]})}})}));Td(),O();var Yh=Bt();Jh();const Xh=26214400,Zh=Buffer.from([137,80,78,71,13,10,26,10]),Qh=new Set([`acTL`,`fcTL`,`fdAT`]),$h=[`baseImage`,`headImage`,`diffImage`,`baseRepeatImage`,`baseInstabilityDiffImage`,`headRepeatImage`,`headInstabilityDiffImage`],eg=D({meta:{name:`build`,description:`Rebuild a trusted static report from an untrusted Kapture artifact`},args:{input:{type:`string`,required:!0,description:`Untrusted artifact report directory containing report.json and images`},output:{type:`string`,required:!0,description:`New directory for the trusted static report`},"storybook-url":{type:`string`,description:`Trusted HTTPS Storybook URL or the fixed same-origin ./storybook/ directory`},"base-branch":{type:`string`,description:`Trusted base branch display label (not a comparison revision)`},"head-branch":{type:`string`,description:`Trusted head branch display label (not a comparison revision)`}},async run({args:e}){let t=await tg({inputDir:e.input,outputDir:e.output,storybookUrl:e[`storybook-url`],trustedBaseBranch:e[`base-branch`],trustedHeadBranch:e[`head-branch`]});Q.success(`Trusted report: ${t.report.summary.total} snapshots, ${t.imageCount} verified PNGs (${t.imageBytes} bytes)`),Q.info(`Output: ${t.outputDir}`)}});async function tg(e){let t=f(e.inputDir),n=f(e.outputDir),r=ng(e.trustedHeadBranch),i=ng(e.trustedBaseBranch);if(await mg(t),_g(t,n))throw Error(`Trusted report output must be outside the untrusted input directory`);await hg(n);let o=e.dashboardDir?f(e.dashboardDir):f(a(pe(import.meta.url)),`dashboard`),s=a(n);await y(s,{recursive:!0});let c=await b(`${s}${p}.kapture-report-`),l;try{l=await ig(t,async(e,t)=>{let n=f(c,e.relativePath);await y(a(n),{recursive:!0}),await ie(n,t,{flag:`wx`})});let{report:s,imageDigests:u,calculatedContentDigest:d}=l;if(s.contentDigest&&s.contentDigest!==d)throw Error(`Report content digest does not match its referenced PNGs: expected ${s.contentDigest}, calculated ${d}`);r?s.headBranch=r:delete s.headBranch,i?s.baseBranch=i:delete s.baseBranch,e.trustedPullRequest?s.pullRequest={...e.trustedPullRequest}:delete s.pullRequest;let p=zd(e.storybookUrl);p?s.storybookUrl=p:delete s.storybookUrl,s.contentDigest=Qc(s,u),await ie(f(c,`report.json`),`${JSON.stringify(s)}\n`,{flag:`wx`}),await Wu(o,c),await ne(c,n)}catch(e){throw await re(c,{recursive:!0,force:!0}),e}if(!l)throw Error(`Trusted report validation did not complete`);return{report:l.report,outputDir:n,imageCount:l.references.length,imageBytes:l.imageBytes}}function ng(e){if(e!==void 0){if(e.length<1||e.length>512||Array.from(e).some(e=>{let t=e.codePointAt(0)??0;return t<=31||t===127}))throw Error(`Trusted head branch must contain between 1 and 512 non-control characters`);return e}}async function rg(e,t){if(!/^[0-9a-f]{64}$/.test(t))throw Error(`Expected trusted report content digest must be a lowercase SHA-256 digest`);let n=f(e);if(n!==f(a(n),`report.json`))throw Error(`Trusted report path must end in report.json`);let r=a(n);await mg(r);let i=await ig(r);if(i.report.contentDigest!==t||i.calculatedContentDigest!==t)throw Error(`Trusted report content digest does not match its actual structure and referenced PNGs`);return i.report}async function ig(e,t){let n=ag(await gg(e,`report.json`,Oh)),r=og(n);if(r.length>6e4)throw Error(`Report references more than 60000 PNG images`);let i=new Map,a=[],o=0;for(let n of r){let r=await gg(e,n.relativePath,Xh);if(o+=r.byteLength,o>536870912)throw Error(`Referenced PNGs exceed 536870912 total bytes`);i.set(n.relativePath,dg(r,n.relativePath)),a.push({path:n.relativePath,sha256:ae(`sha256`).update(r).digest(`hex`)}),await t?.(n,r)}return pg(n,i),{report:n,references:r,imageDigests:a,imageBytes:o,calculatedContentDigest:Qc(n,a)}}function ag(e){let t;try{t=JSON.parse(e.toString(`utf8`))}catch{throw Error(`Input report.json does not contain valid JSON`)}return wh(t)}function og(e){let t=new Map;for(let n of Object.values(e.entries)){let e=sg(n);for(let r of $h){let i=lg(n,r);if(e.has(r)&&!i)throw Error(`Report entry ${n.id} is missing ${r} for status ${n.status}`);if(!e.has(r)&&i)throw Error(`Report entry ${n.id} cannot contain ${r} for status ${n.status}`);if(!i)continue;let a=ug(i,cg(r),n.id),o=t.get(a);if(o&&o.entryId!==n.id)throw Error(`Report entries ${o.entryId} and ${n.id} reference the same PNG: ${a}`);t.set(a,{relativePath:a,entryId:n.id})}}return[...t.values()]}function sg(e){if(e.status===`changed`)return new Set([`baseImage`,`headImage`,`diffImage`]);if(e.status===`unstable`){if(!e.instability?.base&&!e.instability?.head)throw Error(`Report entry ${e.id} is unstable without instability evidence`);let t=[`baseImage`,`headImage`,`diffImage`];return e.instability.base&&t.push(`baseRepeatImage`,`baseInstabilityDiffImage`),e.instability.head&&t.push(`headRepeatImage`,`headInstabilityDiffImage`),new Set(t)}return e.status===`added`?new Set([`headImage`]):e.status===`removed`?new Set([`baseImage`]):new Set}function cg(e){return e===`baseImage`?`base`:e===`headImage`?`head`:e===`diffImage`?`diff`:e===`baseRepeatImage`?`base-repeat`:e===`baseInstabilityDiffImage`?`base-instability-diff`:e===`headRepeatImage`?`head-repeat`:`head-instability-diff`}function lg(e,t){return t===`baseImage`||t===`headImage`||t===`diffImage`?e[t]:t===`baseRepeatImage`?e.instability?.base?.repeatImage:t===`baseInstabilityDiffImage`?e.instability?.base?.diffImage:t===`headRepeatImage`?e.instability?.head?.repeatImage:e.instability?.head?.diffImage}function ug(e,t,n){let r=`images/${t}/`,i=e.slice(r.length);if(!e.startsWith(r)||!i||i.includes(`/`)||i.includes(`\\`)||i.length>255||!/^[a-zA-Z0-9][a-zA-Z0-9._-]*\.png$/.test(i))throw Error(`Report entry ${n} has an invalid ${t} PNG path: ${e}`);return e}function dg(e,t){if(e.byteLength<33||!e.subarray(0,8).equals(Zh))throw Error(`Referenced image is not a PNG: ${t}`);let n=e.readUInt32BE(8),r=e.toString(`ascii`,12,16);if(n!==13||r!==`IHDR`)throw Error(`Referenced PNG has an invalid IHDR chunk: ${t}`);let i=e.readUInt32BE(16),a=e.readUInt32BE(20);if(i<1||a<1||i>16384||a>32768||i*a>33554432)throw Error(`Referenced PNG dimensions are outside the supported limits: ${t} (${i}x${a})`);fg(e,t);try{let t=Yh.PNG.sync.read(e,{checkCRC:!0,skipRescale:!0});if(t.width!==i||t.height!==a)throw Error(`decoded dimensions differ from IHDR`)}catch{throw Error(`Referenced PNG cannot be decoded safely: ${t}`)}return{width:i,height:a}}function fg(e,t){let n=Zh.byteLength,r=!1;for(;n+12<=e.byteLength;){let i=e.readUInt32BE(n),a=e.toString(`ascii`,n+4,n+8),o=n+12+i;if(o>e.byteLength)throw Error(`Referenced PNG has an invalid chunk boundary: ${t}`);if(Qh.has(a))throw Error(`Animated PNG is not supported in a static report: ${t}`);if(n=o,a===`IEND`){r=!0;break}}if(!r||n!==e.byteLength)throw Error(`Referenced PNG has an invalid chunk structure: ${t}`)}function pg(e,t){for(let n of Object.values(e.entries)){if(n.status!==`changed`&&n.status!==`unstable`||!n.baseImage||!n.headImage||!n.diffImage)continue;let e=t.get(n.baseImage),r=t.get(n.headImage),i=t.get(n.diffImage);if(!e||!r||!i)throw Error(`Report entry ${n.id} is missing validated PNG dimensions`);let a=Math.max(e.width,r.width),o=Math.max(e.height,r.height);for(let e of n.ignoredRegions??[])if(e.x+e.width>a||e.y+e.height>o)throw Error(`Report entry ${n.id} ignored region exceeds its comparison canvas`);if(i.width!==a||i.height!==o)throw Error(`Report entry ${n.id} diff PNG must match the padded comparison canvas ${a}x${o}`);if(n.changedPixels!==void 0&&n.changedPixels>a*o)throw Error(`Report entry ${n.id} changedPixels exceeds its diff PNG pixel count`);for(let i of[n.instability?.base,n.instability?.head]){if(!i)continue;let a=t.get(i.repeatImage),o=t.get(i.diffImage);if(!a||!o)throw Error(`Report entry ${n.id} is missing instability PNG dimensions`);let s=i===n.instability?.base?e:r,c=Math.max(s.width,a.width),l=Math.max(s.height,a.height);if(o.width!==c||o.height!==l)throw Error(`Report entry ${n.id} instability diff PNG must match ${c}x${l}`);if(i.changedPixels>c*l)throw Error(`Report entry ${n.id} instability changedPixels exceeds its diff PNG pixel count`)}}}async function mg(e){let t;try{t=await v(e)}catch(t){throw vg(t)?Error(`Input report directory does not exist: ${e}`):t}if(t.isSymbolicLink()||!t.isDirectory())throw Error(`Input report path must be a real directory, not a symbolic link`)}async function hg(e){try{await v(e)}catch(e){if(vg(e))return;throw e}throw Error(`Trusted report output already exists: ${e}`)}async function gg(e,t,n){if(s(t)||t.includes(`\\`))throw Error(`Input file must be a normalized relative path: ${t}`);let r=t.split(`/`),i=e;for(let[e,n]of r.entries()){if(!n||n===`.`||n===`..`)throw Error(`Input file must be a normalized relative path: ${t}`);i=f(i,n);let a;try{a=await v(i)}catch(e){throw vg(e)?Error(`Referenced input file does not exist: ${t}`):e}if(a.isSymbolicLink())throw Error(`Referenced input path cannot contain a symbolic link: ${t}`);let o=e===r.length-1;if(!o&&!a.isDirectory()||o&&!a.isFile())throw Error(`Referenced input path is not a regular file: ${t}`)}let a=fe.O_RDONLY|(fe.O_NOFOLLOW??0),o=await ee(i,a);try{let e=await o.stat();if(!e.isFile()||e.size>n)throw Error(`Input file exceeds ${n} bytes: ${t}`);let r=Buffer.alloc(e.size),i=0;for(;i<r.byteLength;){let{bytesRead:e}=await o.read(r,i,r.byteLength-i,i);if(e===0)throw Error(`Input file changed while being read: ${t}`);i+=e}let a=Buffer.alloc(1),{bytesRead:s}=await o.read(a,0,1,r.byteLength);if(s>0)throw Error(`Input file changed while being read: ${t}`);return r}finally{await o.close()}}function _g(e,t){let n=d(e,t);return n===``||!n.startsWith(`..${p}`)&&n!==`..`&&!s(n)}function vg(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}function yg(e,t){return xg(e,t).map(({path:e,compressedBytes:t,uncompressedBytes:n})=>({path:e,compressedBytes:t,uncompressedBytes:n}))}async function bg(e,t,n){let r=xg(e,n),i=f(t);await y(i,{recursive:!0});for(let t of r){let n=e.subarray(t.dataOffset,t.dataOffset+t.compressedBytes),r=t.compression===0?Buffer.from(n):xe(n,{maxOutputLength:t.uncompressedBytes+1});if(r.byteLength!==t.uncompressedBytes)throw Error(`ZIP entry size mismatch: ${t.path}`);if(be(r)!==t.crc)throw Error(`ZIP entry checksum mismatch: ${t.path}`);let o=f(i,t.path);if(!o.startsWith(`${i}${p}`))throw Error(`ZIP entry escapes the output directory: ${t.path}`);await y(a(o),{recursive:!0}),await ie(o,r,{flag:`wx`})}return r}function xg(e,t){Eg(t);let n=Sg(e),r=e.readUInt16LE(n+4),i=e.readUInt16LE(n+6),a=e.readUInt16LE(n+8),o=e.readUInt16LE(n+10),s=e.readUInt32LE(n+12),c=e.readUInt32LE(n+16),l=e.readUInt16LE(n+20);if(n+22+l!==e.byteLength)throw Error(`ZIP end record does not match the archive size`);if(r!==0||i!==0||a!==o)throw Error(`Multi-disk ZIP archives are not supported`);if(o===65535||s===4294967295||c===4294967295)throw Error(`ZIP64 archives are not supported`);if(o>t.maxEntries)throw Error(`ZIP archive contains more than ${t.maxEntries} entries`);if(c+s!==n)throw Error(`ZIP central directory is malformed`);let u=[],d=new Set,f=c,p=0;for(let r=0;r<o;r+=1){if(f+46>n||e.readUInt32LE(f)!==33639248)throw Error(`ZIP central directory entry is malformed`);let r=e.readUInt16LE(f+4),i=e.readUInt16LE(f+8),a=e.readUInt16LE(f+10),o=e.readUInt32LE(f+16),s=e.readUInt32LE(f+20),l=e.readUInt32LE(f+24),m=e.readUInt16LE(f+28),h=e.readUInt16LE(f+30),g=e.readUInt16LE(f+32),_=e.readUInt16LE(f+34),v=e.readUInt32LE(f+38),y=e.readUInt32LE(f+42),b=f+46+m+h+g;if(b>n)throw Error(`ZIP central directory entry exceeds its bounds`);if(i&1)throw Error(`Encrypted ZIP entries are not supported`);if(a!==0&&a!==8)throw Error(`ZIP compression method ${a} is not supported`);if(_!==0)throw Error(`Multi-disk ZIP entries are not supported`);if(s===4294967295||l===4294967295||y===4294967295)throw Error(`ZIP64 entries are not supported`);let ee=e.subarray(f+46,f+46+m),x=wg(ee);f=b;let S=x.endsWith(`/`);if(Tg(r,v,x,S),d.has(x))throw Error(`ZIP archive contains duplicate path: ${x}`);if(d.add(x),S){if(!t.allowDirectoryPath(x))throw Error(`ZIP archive contains unexpected directory: ${x}`);if(i&8||a!==0||o!==0||s!==0||l!==0)throw Error(`ZIP directory entry must be empty and stored: ${x}`);Cg(e,y,ee,i,a,o,s,l,c);continue}if(!t.allowPath(x))throw Error(`ZIP archive contains unexpected path: ${x}`);if(l>t.maxFileBytes)throw Error(`ZIP entry exceeds ${t.maxFileBytes} bytes: ${x}`);if(p+=l,p>t.maxTotalBytes)throw Error(`ZIP archive exceeds ${t.maxTotalBytes} uncompressed bytes`);let te=Cg(e,y,ee,i,a,o,s,l,c);u.push({path:x,compression:a,crc:o,compressedBytes:s,uncompressedBytes:l,dataOffset:te})}if(f!==n)throw Error(`ZIP central directory size is inconsistent`);return u}function Sg(e){let t=Math.max(0,e.byteLength-65557);for(let n=e.byteLength-22;n>=t;--n)if(e.readUInt32LE(n)===101010256)return n;throw Error(`ZIP end-of-central-directory record is missing`)}function Cg(e,t,n,r,i,a,o,s,c){if(t+30>c||e.readUInt32LE(t)!==67324752)throw Error(`ZIP local entry header is malformed`);let l=e.readUInt16LE(t+6),u=e.readUInt16LE(t+8),d=e.readUInt32LE(t+14),f=e.readUInt32LE(t+18),p=e.readUInt32LE(t+22),m=e.readUInt16LE(t+26),h=e.readUInt16LE(t+28),g=t+30+m+h;if(g>c)throw Error(`ZIP local entry header exceeds its bounds`);let _=e.subarray(t+30,t+30+m);if(l!==r||u!==i||!_.equals(n))throw Error(`ZIP local and central directory entries do not match`);if(!(l&8)&&(d!==a||f!==o||p!==s))throw Error(`ZIP local and central directory sizes or checksum do not match`);if(g+o>c)throw Error(`ZIP entry data exceeds the archive bounds`);return g}function wg(e){let t=e.toString(`utf8`);if(!Buffer.from(t,`utf8`).equals(e))throw Error(`ZIP path is not valid UTF-8`);let n=t.endsWith(`/`),r=t.split(`/`),i=n?r.slice(0,-1):r;if(t.length<1||t.startsWith(`/`)||t.includes(`\\`)||t.includes(`\0`)||i.some(e=>!e||e===`.`||e===`..`)||Array.from(t).some(e=>{let t=e.codePointAt(0)??0;return t<=31||t===127}))throw Error(`ZIP path is unsafe: ${JSON.stringify(t)}`);return t}function Tg(e,t,n,r){if(e>>>8!=3)return;let i=t>>>16&61440;if(i!==0&&i!==(r?16384:32768))throw Error(r?`ZIP entry is not a directory: ${n}`:`ZIP entry is not a regular file: ${n}`)}function Eg(e){for(let[t,n]of Object.entries({maxEntries:e.maxEntries,maxFileBytes:e.maxFileBytes,maxTotalBytes:e.maxTotalBytes}))if(!Number.isSafeInteger(n)||n<=0)throw Error(`${t} must be positive`)}function Dg(e,t){let n=Fg(e,`GitHub pull_request event`),r=Fg(n.pull_request,`pull_request`),i=Ag(Fg(n.repository,`repository`)),a=Fg(r.base,`pull_request.base`),o=Fg(r.head,`pull_request.head`),s=Ag(Fg(a.repo,`pull_request.base.repo`)),c=Fg(o.repo,`pull_request.head.repo`),l=Mg(a.ref,`pull_request.base.ref`),u=Mg(o.ref,`pull_request.head.ref`),d=Ng(r.number,`pull request number`);if(s!==i)throw Error(`Pull request base repository must match the workflow repository`);if(t!==void 0&&l!==Mg(t,`base branch`))throw Error(`Pull request targets ${l}, expected ${t}`);return{schemaVersion:1,runId:Ng(n.run_id??process.env.GITHUB_RUN_ID,`workflow run ID`),prNumber:d,base:{repository:s,ref:l,sha:jg(a.sha,`pull_request.base.sha`)},head:{repository:Ag(c),repositoryId:Ng(c.id,`head repository ID`),ref:u,sha:jg(o.sha,`pull_request.head.sha`)},preview:{branch:u,alias:kg(d,u)}}}function Og(e){return`pr-${e.prNumber}-base-${e.base.sha}-head-${e.head.sha}`}function kg(e,t){let n=`pr-${Ng(e,`pull request number`)}-`,r=Mg(t,`head branch`),i=r.normalize(`NFKD`).toLowerCase().replace(/[^a-z0-9-]+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``),a=`-${ae(`sha256`).update(r).digest(`hex`).slice(0,10)}`,o=Math.max(1,63-n.length-a.length);return`${n}${(i||`branch`).slice(0,o).replace(/-$/g,``)||`b`}${a}`}function Ag(e){let t=Pg(e.full_name,`repository full name`);if(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(t))throw Error(`GitHub event contains an invalid repository full name`);return t}function jg(e,t){let n=Pg(e,t).toLowerCase();if(!/^[0-9a-f]{40}$/.test(n))throw Error(`${t} must be a full SHA`);return n}function Mg(e,t){let n=Pg(e,t);if(n.length<1||n.length>512)throw Error(`${t} is invalid`);for(let e of n){let n=e.codePointAt(0)??0;if(n<=31||n===127)throw Error(`${t} is invalid`)}return n}function Ng(e,t){let n=typeof e==`string`&&/^[1-9][0-9]*$/.test(e)?Number(e):e;if(typeof n!=`number`||!Number.isSafeInteger(n)||n<=0)throw Error(`${t} must be a positive integer`);return n}function Pg(e,t){if(typeof e!=`string`)throw Error(`${t} must be a string`);return e}function Fg(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}const Ig=3e3;async function Lg(e,t){let n=await e.getPullRequestForCapture(t.prNumber);Bg(n,t);let r=Zg(n.changed_files,`pull request changed_files`),i=[],a=[],o=0;if(r>3e3)i.push({code:`github-file-limit`});else for(let n=1;n<=Math.ceil(r/100);n+=1){let s=await e.listPullRequestFilesPage(t.prNumber,n,100);if(o=n,!Array.isArray(s)){i.push({code:`pagination-incomplete`,page:n});break}let c=s.slice(0,100);s.length>100&&i.push({code:`pagination-incomplete`,page:n});for(let[e,t]of c.entries())a.push({value:t,page:n,index:e});if(c.length<100){a.length<r&&i.push({code:`pagination-incomplete`,page:n});break}}a.length!==r&&i.push({code:`file-count-mismatch`});let s=new Set,c=new Set;for(let e of a)Vg(e,s,c,i);let l=await e.getPullRequestForCapture(t.prNumber);if(Bg(l,t),l.changed_files!==r)throw Error(`Pull request changed while Kapture discovered changed files`);let u=Wg(i);return{kind:`kapture-changed-files`,version:1,complete:u.length===0,pullRequest:{number:t.prNumber,baseSha:t.base.sha,headSha:t.head.sha},files:[...s].sort(),source:{provider:`github-pull-request-files`,expectedFileCount:r,fetchedFileCount:a.length,pageCount:o,perPage:100,maxFiles:Ig},diagnostics:u}}function Rg(e){let t=Qg(e,`changed-files manifest`);if(Jg(t,[`kind`,`version`,`complete`,`pullRequest`,`files`,`source`,`diagnostics`],`changed-files manifest`),t.kind!==`kapture-changed-files`||t.version!==1)throw Error(`changed-files manifest must use kapture-changed-files version 1`);if(typeof t.complete!=`boolean`)throw Error(`changed-files manifest complete must be a boolean`);if(!Array.isArray(t.files)||t.files.length>6e3)throw Error(`changed-files manifest files must be a bounded array`);let n=t.files.map(e=>zg(e,`changed file path`));if(!Gg(n))throw Error(`changed-files manifest files must be unique and sorted`);let r=Qg(t.pullRequest,`changed-files manifest pullRequest`);Jg(r,[`number`,`baseSha`,`headSha`],`changed-files manifest pullRequest`);let i=Qg(t.source,`changed-files manifest source`);if(Jg(i,[`provider`,`expectedFileCount`,`fetchedFileCount`,`pageCount`,`perPage`,`maxFiles`],`changed-files manifest source`),i.provider!==`github-pull-request-files`)throw Error(`changed-files manifest source provider is invalid`);if(i.perPage!==100||i.maxFiles!==3e3)throw Error(`changed-files manifest source limits are invalid`);if(!Array.isArray(t.diagnostics)||t.diagnostics.length>6e3)throw Error(`changed-files manifest diagnostics must be a bounded array`);let a=t.diagnostics.map(Ug);if(!Gg(a.map(Kg)))throw Error(`changed-files manifest diagnostics must be unique and sorted`);if(t.complete!==(a.length===0))throw Error(`changed-files manifest completeness disagrees with diagnostics`);let o=Zg(i.expectedFileCount,`changed-files expected file count`),s=Zg(i.fetchedFileCount,`changed-files fetched file count`),c=Zg(i.pageCount,`changed-files page count`);if(s>3e3||c>30||s>c*100||n.length>s*2)throw Error(`changed-files manifest source counts are inconsistent`);if(t.complete&&(o!==s||o>3e3||c!==Math.ceil(s/100)||n.length<s))throw Error(`complete changed-files manifest source counts are inconsistent`);return{kind:`kapture-changed-files`,version:1,complete:t.complete,pullRequest:{number:Xg(r.number,`changed-files pull request number`),baseSha:Yg(r.baseSha,`changed-files base SHA`),headSha:Yg(r.headSha,`changed-files head SHA`)},files:n,source:{provider:`github-pull-request-files`,expectedFileCount:o,fetchedFileCount:s,pageCount:c,perPage:100,maxFiles:Ig},diagnostics:a}}function zg(e,t=`GitHub file path`){if(typeof e!=`string`)throw Error(`${t} must be a string`);let n=Array.from(e);if(e.length===0||e.length>4096||e.startsWith(`/`)||/^[A-Za-z]:[\\/]/.test(e)||e.startsWith(`./`)||e===`.`||e===`..`||e.startsWith(`../`)||e.endsWith(`/`)||e.includes(`//`)||e.includes(`\\`)||e.split(`/`).some(e=>e===`.`||e===`..`)||n.some(e=>{let t=e.codePointAt(0)??0;return t<=31||t>=127&&t<=159}))throw Error(`${t} must be a normalized project-relative path`);return e}function Bg(e,t){let n=e.head.repo;if(e.number!==t.prNumber||e.state!==`open`||e.base.ref!==t.base.ref||e.base.sha.toLowerCase()!==t.base.sha||e.base.repo.full_name!==t.base.repository||e.head.ref!==t.head.ref||e.head.sha.toLowerCase()!==t.head.sha||n?.id!==t.head.repositoryId||n.full_name!==t.head.repository)throw Error(`Live pull request does not match the exact Kapture capture context`)}function Vg(e,t,n,r){if(!e.value||typeof e.value!=`object`||Array.isArray(e.value)){r.push({code:`invalid-file-record`,page:e.page,index:e.index});return}let i=e.value;if(typeof i.status!=`string`||typeof i.filename!=`string`){r.push({code:`invalid-file-record`,page:e.page,index:e.index});return}let a=JSON.stringify([i.status,i.filename,i.previous_filename]);if(n.has(a)&&r.push({code:`duplicate-file-entry`,page:e.page,index:e.index}),n.add(a),Hg(i.filename,e,t,r),i.status===`renamed`||i.previous_filename!==void 0){if(typeof i.previous_filename!=`string`){r.push({code:`rename-source-missing`,page:e.page,index:e.index});return}Hg(i.previous_filename,e,t,r)}}function Hg(e,t,n,r){try{n.add(zg(e))}catch{r.push({code:`invalid-file-path`,page:t.page,index:t.index})}}function Ug(e){let t=Qg(e,`changed-files diagnostic`);if(Jg(t,[`code`,`page`,`index`],`changed-files diagnostic`,!0),typeof t.code!=`string`||![`github-file-limit`,`pagination-incomplete`,`file-count-mismatch`,`invalid-file-record`,`invalid-file-path`,`rename-source-missing`,`duplicate-file-entry`].includes(t.code))throw Error(`changed-files diagnostic code is invalid`);let n=t.page===void 0?void 0:Xg(t.page,`page`),r=t.index===void 0?void 0:Zg(t.index,`diagnostic index`),i={code:t.code,...n===void 0?{}:{page:n},...r===void 0?{}:{index:r}};if(i.code===`github-file-limit`||i.code===`file-count-mismatch`?n!==void 0||r!==void 0:i.code===`pagination-incomplete`?n===void 0||n>30||r!==void 0:n===void 0||n>30||r===void 0||r>=100)throw Error(`changed-files diagnostic location is invalid`);return i}function Wg(e){return[...new Map(e.map(e=>[JSON.stringify(e),e])).values()].sort((e,t)=>qg(Kg(e),Kg(t)))}function Gg(e){return e.every((t,n)=>n===0||(e[n-1]??``)<t)}function Kg(e){return`${e.code}:${String(e.page??0).padStart(2,`0`)}:${String(e.index??0).padStart(3,`0`)}`}function qg(e,t){return e<t?-1:+(e>t)}function Jg(e,t,n,r=!1){let i=Object.keys(e).sort(),a=r?i.filter(e=>t.includes(e)).sort():[...t].sort();if(i.some(e=>!t.includes(e))||!r&&(i.length!==a.length||i.some((e,t)=>e!==a[t])))throw Error(`${n} contains unexpected or missing fields`)}function Yg(e,t){if(typeof e!=`string`||!/^[0-9a-f]{40}$/.test(e))throw Error(`${t} must be a full lowercase SHA`);return e}function Xg(e,t){let n=Zg(e,t);if(n===0)throw Error(`${t} must be a positive integer`);return n}function Zg(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw Error(`${t} must be a non-negative integer`);return e}function Qg(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}Nc(),Jh();const $g=2e4,e_=26214400,t_=1073741824,n_=/^[0-9a-f]{40}$/,r_=/^sha256:[0-9a-f]{64}$/,i_=/^[0-9a-f]{64}$/,a_=/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/,o_=/^\.github\/workflows\/[A-Za-z0-9_./-]+\.ya?ml$/,s_=/^images\/(?:base|head|diff)\/[A-Za-z0-9][A-Za-z0-9._-]*\.png$/,c_=R().min(1).max(512).refine(e=>!vv(e),`must not contain control characters`),l_=R().regex(n_),u_=z().int().positive().max(2**53-1),d_=R().regex(a_),f_=R().regex(r_),p_=B({schemaVersion:H(1),runId:u_,prNumber:u_,base:B({repository:d_,ref:c_,sha:l_}),head:B({repository:d_,repositoryId:u_,ref:c_,sha:l_}),preview:B({branch:c_,alias:c_})}),m_=B({id:u_,name:c_,sizeInBytes:u_,digest:f_}),h_=B({id:u_,name:c_,digest:f_}),g_=B({schemaVersion:H(1),artifacts:B({context:h_,baseStorybook:h_,headStorybook:h_})}),__=B({schemaVersion:H(2),repository:B({id:u_,fullName:d_}),context:p_,captureRun:B({id:u_,runNumber:u_,attempt:u_,workflowId:u_,workflowPath:c_,headSha:l_,headBranch:c_,headRepositoryId:u_,headRepository:d_}),artifacts:B({context:m_,baseStorybook:m_,headStorybook:m_,report:m_}),report:B({contentDigest:R().regex(i_)}),trustedArtifactName:c_});async function v_(e,t){let n=uv(t.captureWorkflowPath),r=mv(t.baseBranch,`base branch`),i=f(t.outputDir),a=f(t.receiptPath);if(xv(i,a))throw Error(`Trusted receipt must be outside the publicly deployed report directory`);await lv(a,`Trusted receipt`);let o=S_(t.event,n),s=await e.getWorkflowRun(o.run.id);K_(s,o),await w_(e,s);let c=T_(await e.listRunArtifacts(s.id),o),l=await sv(t.temporaryRoot),u=!1;try{let d=await O_(e,c.context,33685504),p=f(l,`context`);N_(d),await bg(d,p,k_);let m=await R_(f(p,`context.json`)),h=await z_(f(p,`changed-files.json`),m);V_(m,c.context),H_(m,o,s,r),W_(await e.getPullRequest(m.prNumber),m,o,r),await G_(e,m,n);let g=await O_(e,c.report,629145600),_=f(l,`untrusted-report`);P_(g),await bg(g,_,j_),L_(await I_(f(_,`capture-boundary.json`)),c);let v=await Eh(f(_,`report.json`));B_(v,h),await df(e,av(o,m),v);let y=await tg({inputDir:_,outputDir:i,trustedHeadBranch:m.head.ref,trustedPullRequest:{repository:m.base.repository,number:m.prNumber,url:`https://github.com/${m.base.repository}/pull/${m.prNumber}`,baseBranch:m.base.ref,headBranch:m.head.ref,workflowRunUrl:`https://github.com/${m.base.repository}/actions/runs/${o.run.id}`},...t.storybookUrl?{storybookUrl:t.storybookUrl}:{},...t.dashboardDir?{dashboardDir:f(t.dashboardDir)}:{}});if(u=!0,!y.report.contentDigest)throw Error(`Trusted report build did not produce an image-bound content digest`);await iv(e,o,s,m,r,n);let b=q_(o,s,m,c,y.report);return await cv(a,b),{receipt:b,report:y.report,reportDirectory:i,reportPath:f(i,`report.json`),receiptPath:a,changedFiles:h}}catch(e){throw u&&await re(i,{recursive:!0,force:!0}),e}finally{await re(l,{recursive:!0,force:!0})}}async function y_(e,t,n){let r=await C_(n.receiptPath),i=S_(n.event,r.captureRun.workflowPath);X_(r,i);let a=await e.getWorkflowRun(r.captureRun.id);Z_(a,r),await w_(e,a),await Q_(e,r,i),W_(await e.getPullRequest(r.context.prNumber),r.context,i,r.context.base.ref),await G_(e,r.context,r.captureRun.workflowPath);let o=await rg(n.reportPath,r.report.contentDigest);if(o.headBranch!==r.context.head.ref)throw Error(`Trusted report branch does not match its verified pull request context`);let s=av(i,r.context);return await df(e,s,o),ff(t,s,o,n.statusContext,n.reportUrl,n.commentLanguage)}async function b_(e,t){let n=uv(t.captureWorkflowPath),r=mv(t.baseBranch,`base branch`),i=f(t.outputDir),o=f(t.receiptPath);await lv(i,`Trusted Storybook output`);let s=await C_(o),c=S_(t.event,n);X_(s,c);let l=await e.getWorkflowRun(s.captureRun.id);Z_(l,s),await w_(e,l),await Q_(e,s,c),W_(await e.getPullRequest(s.context.prNumber),s.context,c,r),await G_(e,s.context,n);let u=f(t.temporaryRoot??a(i));if(xv(i,u))throw Error(`Trusted Storybook temporary root must be outside its output directory`);let d=await sv(u),p=f(d,`storybook`);try{let t=await O_(e,s.artifacts.headStorybook,536870912);return F_(t),await bg(t,p,M_),await iv(e,c,l,s.context,r,n),await Q_(e,s,c),await lv(i,`Trusted Storybook output`),await y(a(i),{recursive:!0}),await ne(p,i),{receipt:s,receiptPath:o,context:s.context,artifact:s.artifacts.headStorybook,storybookDirectory:i}}finally{await re(d,{recursive:!0,force:!0})}}async function x_(e,t){let n=await C_(t.receiptPath),r=S_(t.event,n.captureRun.workflowPath);X_(n,r),Z_(await e.getWorkflowRun(n.captureRun.id),n);let i=t.trustedArtifactId,a=t.trustedArtifactDigest?nv(t.trustedArtifactDigest):void 0,o=[i,a];if(o.some(e=>e!==void 0)&&o.some(e=>e===void 0))throw Error(`trusted-artifact-id and trusted-artifact-digest must be provided together`);if(i!==void 0&&!_v(i))throw Error(`trusted-artifact-id must be a positive integer`);let s=i!==void 0&&a!==void 0?rv():void 0,c=[];for(let t of $_(n)){let n=await e.getArtifact(t.id);n&&(ev(n,t,r),c.push({artifact:n,expected:t}))}if(i!==void 0&&a!==void 0&&s!==void 0){if($_(n).some(e=>e.id===i))throw Error(`trusted-artifact-id must not duplicate a source artifact ID`);let t=await e.getArtifact(i);t&&(tv(t,a,s,n),c.push({artifact:t,expected:{id:t.id,name:t.name,sizeInBytes:t.sizeInBytes,digest:t.digest}}))}let l=[...new Set(c.map(({artifact:e})=>e.id))];for(let t of l)await e.deleteArtifact(t);return l}function S_(e,t){let n=yv(e,`GitHub workflow_run event`);if(n.action!==`completed`)throw Error(`Kapture trusted run requires a completed workflow_run event`);let r=yv(n.repository,`event repository`),i=dv(r.full_name,`event repository`),a=fv(i),o=gv(r.id,`event repository ID`),s=yv(n.workflow_run,`workflow_run`),c=uv(hv(s.path,`workflow path`));if(c!==uv(t))throw Error(`workflow_run path ${c} does not match ${t}`);if(s.status!==`completed`||s.conclusion!==`success`||s.event!==`pull_request`)throw Error(`Kapture trusted run requires one successful pull_request capture run`);let l=yv(s.head_repository,`workflow_run head repository`),u=bv(s.pull_requests,`workflow_run pull_requests`);if(u.length>1)throw Error(`workflow_run must contain at most one pull request`);let d=u[0]?ov(u[0]):void 0;return{repository:{id:o,fullName:i,ref:a},run:{id:gv(s.id,`workflow run ID`),runNumber:gv(s.run_number,`workflow run number`),attempt:gv(s.run_attempt,`workflow run attempt`),workflowId:gv(s.workflow_id,`workflow ID`),workflowPath:c,status:`completed`,conclusion:`success`,event:`pull_request`,headSha:pv(s.head_sha,`workflow run head SHA`),headBranch:mv(s.head_branch,`workflow run head branch`),headRepository:{id:gv(l.id,`workflow run head repository ID`),fullName:dv(l.full_name,`workflow run head repository`)}},...d?{pullRequest:d}:{}}}async function C_(e){let t=f(e),n=await C(t);if(!n.isFile()||n.size<1||n.size>65536)throw Error(`Trusted receipt must be a file no larger than 65536 bytes`);let r;try{r=JSON.parse(await x(t,`utf8`))}catch{throw Error(`Trusted receipt does not contain valid JSON`)}let i=__.safeParse(r);if(!i.success){let e=i.error.issues[0];throw Error(`Invalid trusted receipt${e?.path.length?` at ${e.path.join(`.`)}`:``}: ${e?.message??`unknown error`}`)}return Y_(i.data),i.data}async function w_(e,t){let n=(await e.listWorkflowRuns(t.workflowId,t.headBranch)).filter(e=>e.headRepositoryId===t.headRepository.id).reduce((e,t)=>e?t.runNumber===e.runNumber?t.id>e.id?t:e:t.runNumber>e.runNumber?t:e:t,void 0);if(!n||n.id!==t.id)throw Error(`A newer Kapture capture run owns this repository and branch`)}function T_(e,t){let n=/^kapture-context-pr-([1-9][0-9]*)-base-([0-9a-f]{40})-head-([0-9a-f]{40})$/,r=e.filter(e=>n.test(e.name)?D_(e,t):!1);if(r.length!==1||!r[0])throw Error(`Triggering run must contain exactly one immutable Kapture context artifact`);let i=r[0];if(i.sizeInBytes>33685504)throw Error(`Kapture context artifact exceeds its compressed size limit`);let a=i.name.match(n);if(!a?.[1]||!a[2]||!a[3])throw Error(`Kapture context artifact name is invalid`);let o=`kapture-visual-report-pr-${a[1]}-base-${a[2]}-head-${a[3]}`,s=e.filter(e=>e.name===o&&D_(e,t));if(s.length!==1||!s[0])throw Error(`Triggering run must contain exactly one matching Kapture report artifact`);if(s[0].sizeInBytes>629145600)throw Error(`Kapture report artifact exceeds its compressed size limit`);let c=`pr-${a[1]}-base-${a[2]}-head-${a[3]}`,l=E_(e,`kapture-storybook-base-${c}`,t),u=E_(e,`kapture-storybook-head-${c}`,t),d=[i,l,u,s[0]];if(new Set(d.map(e=>e.id)).size!==d.length||new Set(d.map(e=>e.name)).size!==d.length)throw Error(`Kapture artifact IDs and names must be distinct`);return{context:i,baseStorybook:l,headStorybook:u,report:s[0]}}function E_(e,t,n){let r=e.filter(e=>e.name===t&&D_(e,n));if(r.length!==1||!r[0])throw Error(`Triggering run must contain exactly one non-expired ${t} artifact`);if(r[0].sizeInBytes>536870912)throw Error(`${t} exceeds its compressed size limit`);return r[0]}function D_(e,t){return!e.expired&&e.workflowRun.id===t.run.id&&e.workflowRun.repositoryId===t.repository.id&&e.workflowRun.headRepositoryId===t.run.headRepository.id&&e.workflowRun.headBranch===t.run.headBranch&&e.workflowRun.headSha===t.run.headSha&&r_.test(e.digest)&&_v(e.id)&&_v(e.sizeInBytes)}async function O_(e,t,n){let r=await e.downloadArtifactArchive(t.id,n);if(r.byteLength!==t.sizeInBytes)throw Error(`Artifact ${t.id} download size does not match GitHub metadata`);if(`sha256:${ae(`sha256`).update(r).digest(`hex`)}`!==t.digest)throw Error(`Artifact ${t.id} download digest does not match GitHub metadata`);return r}const k_={maxEntries:2,maxFileBytes:33554432,maxTotalBytes:33619968,allowPath:e=>e===`context.json`||e===`changed-files.json`,allowDirectoryPath:()=>!1},A_=new Set([`images/`,`images/base/`,`images/head/`,`images/diff/`]),j_={maxEntries:60006,maxFileBytes:Xh,maxTotalBytes:629145600,allowPath:e=>e===`report.json`||e===`capture-boundary.json`||s_.test(e),allowDirectoryPath:e=>A_.has(e)},M_={maxEntries:$g,maxFileBytes:e_,maxTotalBytes:t_,allowPath:()=>!0,allowDirectoryPath:()=>!0};function N_(e){let t=yg(e,k_);if(t.length!==2)throw Error(`Context archive must contain exactly context.json and changed-files.json`);let n=t.find(e=>e.path===`context.json`),r=t.find(e=>e.path===`changed-files.json`);if(!n||n.uncompressedBytes<1||n.uncompressedBytes>65536||!r||r.uncompressedBytes<1||r.uncompressedBytes>33554432)throw Error(`Context archive entries are outside their fixed size contract`)}function P_(e){let t=yg(e,j_),n=new Set,r=0,i=0;for(let e of t){let t=e.path.toLocaleLowerCase(`en-US`);if(n.has(t))throw Error(`Report archive contains a case-insensitive duplicate: ${e.path}`);if(n.add(t),e.uncompressedBytes<1)throw Error(`Report archive contains an empty file: ${e.path}`);if(e.path===`report.json`&&(r+=1,e.uncompressedBytes>10485760))throw Error(`report.json exceeds its uncompressed size limit`);if(e.path===`capture-boundary.json`&&(i+=1,e.uncompressedBytes>65536))throw Error(`capture-boundary.json exceeds its uncompressed size limit`)}if(r!==1)throw Error(`Report archive must contain one root report.json file`);if(i!==1)throw Error(`Report archive must contain one root capture-boundary.json file`)}function F_(e){let t=yg(e,M_),n=new Set,r=0;for(let e of t){let t=e.path.toLocaleLowerCase(`en-US`);if(n.has(t))throw Error(`Storybook archive contains a case-insensitive duplicate: ${e.path}`);n.add(t),e.path===`index.html`&&e.uncompressedBytes>0&&(r+=1)}if(r!==1)throw Error(`Storybook archive must contain one non-empty root index.html file`)}async function I_(e){let t;try{t=JSON.parse(await x(e,`utf8`))}catch(e){throw Error(`capture-boundary.json must contain valid JSON`,{cause:e})}return g_.parse(t)}function L_(e,t){for(let n of[`context`,`baseStorybook`,`headStorybook`]){let r=e.artifacts[n],i=t[n];if(i.id!==r.id||i.name!==r.name||i.digest!==r.digest)throw Error(`Capture ${n} artifact does not match its exact downloaded identity`)}}async function R_(e){let t;try{t=JSON.parse(await x(e,`utf8`))}catch{throw Error(`Kapture context artifact does not contain valid JSON`)}let n=p_.safeParse(t);if(!n.success){let e=n.error.issues[0];throw Error(`Invalid Kapture capture context${e?.path.length?` at ${e.path.join(`.`)}`:``}: ${e?.message??`unknown error`}`)}if(n.data.preview.branch!==n.data.head.ref||n.data.preview.alias!==kg(n.data.prNumber,n.data.head.ref))throw Error(`Kapture context preview identity is not derived from its pull request branch`);return n.data}async function z_(e,t){let n=await C(e);if(!n.isFile()||n.size<1||n.size>33554432)throw Error(`changed-files.json is outside its fixed size contract`);let r;try{r=JSON.parse(await x(e,`utf8`))}catch{throw Error(`changed-files.json does not contain valid JSON`)}let i=Rg(r);if(i.pullRequest.number!==t.prNumber||i.pullRequest.baseSha!==t.base.sha||i.pullRequest.headSha!==t.head.sha)throw Error(`changed-files.json does not belong to the exact capture context`);return i}function B_(e,t){let n=e.coverage;if(!n)throw Error(`Trusted workflow reports must include audited story coverage`);let r=n.changedFilesEvidence;if(!r)throw Error(`Trusted workflow report coverage must include changed-files evidence`);let i=ae(`sha256`).update(JSON.stringify(t)).digest(`hex`);if(r.provider!==t.source.provider||r.manifestDigest!==i||r.pullRequestNumber!==t.pullRequest.number||r.baseSha!==t.pullRequest.baseSha||r.headSha!==t.pullRequest.headSha)throw Error(`Trusted workflow report changed-files evidence does not match its verified context manifest`)}function V_(e,t){let n=`kapture-context-${Og(e)}`;if(t.name!==n)throw Error(`Kapture context contents do not match the immutable artifact name`)}function H_(e,t,n,r){if(e.runId!==n.id||e.base.repository!==t.repository.fullName||e.base.ref!==r||e.head.repository!==n.headRepository.fullName||e.head.repositoryId!==n.headRepository.id||e.head.ref!==n.headBranch)throw Error(`Kapture capture context does not belong to the triggering workflow run`);U_(t,e)}function U_(e,t){let n=e.pullRequest;if(n&&(n.number!==t.prNumber||n.base.repositoryId!==e.repository.id||n.base.ref!==t.base.ref||n.base.sha!==t.base.sha||n.head.repositoryId!==t.head.repositoryId||n.head.ref!==t.head.ref||n.head.sha!==t.head.sha))throw Error(`workflow_run pull request metadata conflicts with the capture context`)}function W_(e,t,n,r){if(e.number!==t.prNumber||e.state!==`open`||e.base.repository.id!==n.repository.id||e.base.repository.fullName!==t.base.repository||e.base.ref!==r||e.base.sha!==t.base.sha||e.head.repository.id!==t.head.repositoryId||e.head.repository.fullName!==t.head.repository||e.head.ref!==t.head.ref||e.head.sha!==t.head.sha)throw Error(`Kapture artifacts are stale or do not belong to the current open pull request`);U_(n,t)}async function G_(e,t,n){let[r,i]=await Promise.all([e.getContentSha(t.base.repository,n,t.base.sha),e.getContentSha(t.head.repository,n,t.head.sha)]);if(!n_.test(r)||i!==r)throw Error(`Pull requests that modify the capture workflow require separate review before publishing`)}function K_(e,t){if(e.id!==t.run.id||e.runNumber!==t.run.runNumber||e.runAttempt!==t.run.attempt||e.workflowId!==t.run.workflowId||e.path!==t.run.workflowPath||e.status!==`completed`||e.conclusion!==`success`||e.event!==`pull_request`||e.headSha!==t.run.headSha||e.headBranch!==t.run.headBranch||e.headRepository.id!==t.run.headRepository.id||e.headRepository.fullName!==t.run.headRepository.fullName||e.repository.id!==t.repository.id||e.repository.fullName!==t.repository.fullName)throw Error(`Triggering capture run metadata changed or no longer matches the event`)}function q_(e,t,n,r,i){if(!i.contentDigest)throw Error(`Trusted report is missing contentDigest`);if(i.headBranch!==n.head.ref)throw Error(`Trusted report branch does not match its verified pull request context`);let a=Og(n);return{schemaVersion:2,repository:{id:e.repository.id,fullName:e.repository.fullName},context:n,captureRun:{id:t.id,runNumber:t.runNumber,attempt:t.runAttempt,workflowId:t.workflowId,workflowPath:t.path,headSha:t.headSha,headBranch:t.headBranch,headRepositoryId:t.headRepository.id,headRepository:t.headRepository.fullName},artifacts:{context:J_(r.context),baseStorybook:J_(r.baseStorybook),headStorybook:J_(r.headStorybook),report:J_(r.report)},report:{contentDigest:i.contentDigest},trustedArtifactName:`kapture-trusted-report-${a}`}}function J_(e){return{id:e.id,name:e.name,sizeInBytes:e.sizeInBytes,digest:e.digest}}function Y_(e){let t=Og(e.context);if(e.context.runId!==e.captureRun.id||e.context.base.repository!==e.repository.fullName||e.context.head.repository!==e.captureRun.headRepository||e.context.head.repositoryId!==e.captureRun.headRepositoryId||e.context.head.ref!==e.captureRun.headBranch||e.context.preview.branch!==e.context.head.ref||e.context.preview.alias!==kg(e.context.prNumber,e.context.head.ref)||e.artifacts.context.name!==`kapture-context-${t}`||e.artifacts.baseStorybook.name!==`kapture-storybook-base-${t}`||e.artifacts.headStorybook.name!==`kapture-storybook-head-${t}`||e.artifacts.report.name!==`kapture-visual-report-${t}`||e.trustedArtifactName!==`kapture-trusted-report-${t}`||new Set($_(e).map(e=>e.id)).size!==4||new Set($_(e).map(e=>e.name)).size!==4||e.artifacts.context.sizeInBytes>33685504||e.artifacts.baseStorybook.sizeInBytes>536870912||e.artifacts.headStorybook.sizeInBytes>536870912||e.artifacts.report.sizeInBytes>629145600||!o_.test(e.captureRun.workflowPath))throw Error(`Trusted receipt fields are not internally consistent`)}function X_(e,t){if(Y_(e),e.repository.id!==t.repository.id||e.repository.fullName!==t.repository.fullName||e.captureRun.id!==t.run.id||e.captureRun.runNumber!==t.run.runNumber||e.captureRun.attempt!==t.run.attempt||e.captureRun.workflowId!==t.run.workflowId||e.captureRun.workflowPath!==t.run.workflowPath||e.captureRun.headSha!==t.run.headSha||e.captureRun.headBranch!==t.run.headBranch||e.captureRun.headRepositoryId!==t.run.headRepository.id||e.captureRun.headRepository!==t.run.headRepository.fullName)throw Error(`Trusted receipt does not belong to the triggering workflow_run event`);U_(t,e.context)}function Z_(e,t){if(e.id!==t.captureRun.id||e.runNumber!==t.captureRun.runNumber||e.runAttempt!==t.captureRun.attempt||e.workflowId!==t.captureRun.workflowId||e.path!==t.captureRun.workflowPath||e.status!==`completed`||e.conclusion!==`success`||e.event!==`pull_request`||e.headSha!==t.captureRun.headSha||e.headBranch!==t.captureRun.headBranch||e.headRepository.id!==t.captureRun.headRepositoryId||e.headRepository.fullName!==t.captureRun.headRepository||e.repository.id!==t.repository.id||e.repository.fullName!==t.repository.fullName)throw Error(`Capture run changed after prepare-run verification`)}async function Q_(e,t,n){let r=await e.listRunArtifacts(t.captureRun.id);for(let e of $_(t)){let t=r.filter(t=>t.id===e.id);if(t.length!==1||!t[0])throw Error(`Receipt-bound artifact ${e.id} is no longer available`);ev(t[0],e,n)}}function $_(e){return[e.artifacts.context,e.artifacts.baseStorybook,e.artifacts.headStorybook,e.artifacts.report]}function ev(e,t,n){if(e.id!==t.id||e.name!==t.name||e.sizeInBytes!==t.sizeInBytes||e.digest!==t.digest||!D_(e,n))throw Error(`Artifact ${t.id} no longer matches its trusted receipt binding`)}function tv(e,t,n,r){if(e.expired||e.name!==r.trustedArtifactName||e.digest!==t||e.workflowRun.id!==n||e.workflowRun.repositoryId!==r.repository.id||e.workflowRun.headRepositoryId!==r.repository.id||e.sizeInBytes>629145600)throw Error(`Trusted report artifact does not match the exact cleanup binding`)}function nv(e){let t=e.startsWith(`sha256:`)?e:`sha256:${e}`;if(!r_.test(t))throw Error(`trusted-artifact-digest must be a 64-character SHA-256 digest`);return t}function rv(){let e=process.env.GITHUB_RUN_ID;if(!e||!/^[1-9][0-9]*$/.test(e))throw Error(`GITHUB_RUN_ID must identify the current trusted reporter workflow run`);let t=Number(e);if(!Number.isSafeInteger(t))throw Error(`GITHUB_RUN_ID must be a safe positive integer`);return t}async function iv(e,t,n,r,i,a){let o=await e.getWorkflowRun(n.id);K_(o,t),await w_(e,o),W_(await e.getPullRequest(r.prNumber),r,t,i),await G_(e,r,a)}function av(e,t){return{repository:e.repository.ref,issueNumber:t.prNumber,headSha:t.head.sha,captureRunId:e.run.id,captureRunAttempt:e.run.attempt,captureWorkflowId:e.run.workflowId,captureRunHeadBranch:e.run.headBranch,captureRunHeadRepositoryId:e.run.headRepository.id}}function ov(e){let t=yv(e,`workflow_run pull request`),n=yv(t.base,`workflow_run pull request base`),r=yv(t.head,`workflow_run pull request head`);return{number:gv(t.number,`workflow_run pull request number`),base:{repositoryId:gv(yv(n.repo,`workflow_run pull request base repository`).id,`workflow_run pull request base repository ID`),ref:mv(n.ref,`workflow_run pull request base ref`),sha:pv(n.sha,`workflow_run pull request base SHA`)},head:{repositoryId:gv(yv(r.repo,`workflow_run pull request head repository`).id,`workflow_run pull request head repository ID`),ref:mv(r.ref,`workflow_run pull request head ref`),sha:pv(r.sha,`workflow_run pull request head SHA`)}}}async function sv(e){let t=f(e??process.env.RUNNER_TEMP??ue());return await y(t,{recursive:!0}),b(`${t}${p}kapture-prepare-`)}async function cv(e,t){let n=f(e),r=f(n,`..`);await y(r,{recursive:!0}),await ie(n,`${JSON.stringify(t,null,2)}\n`,{flag:`wx`})}async function lv(e,t){try{await C(e)}catch(e){if(e.code===`ENOENT`)return;throw e}throw Error(`${t} already exists: ${e}`)}function uv(e){if(!o_.test(e)||e.includes(`//`)||e.includes(`..`))throw Error(`capture-workflow-path must be a safe .github/workflows YAML path`);return e}function dv(e,t){let n=hv(e,`${t} full name`);if(!a_.test(n))throw Error(`${t} full name is invalid`);return n}function fv(e){let[t,n,...r]=e.split(`/`);if(!t||!n||r.length>0)throw Error(`Repository full name is invalid`);return{owner:t,repo:n}}function pv(e,t){let n=hv(e,t);if(!n_.test(n))throw Error(`${t} must be a lowercase full SHA`);return n}function mv(e,t){let n=hv(e,t);if(vv(n))throw Error(`${t} contains control characters`);return n}function hv(e,t){if(typeof e!=`string`||e.length<1||e.length>512)throw Error(`${t} must be a non-empty bounded string`);return e}function gv(e,t){if(!_v(e))throw Error(`${t} must be a positive integer`);return e}function _v(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>0}function vv(e){return Array.from(e).some(e=>{let t=e.codePointAt(0)??0;return t<=31||t===127})}function yv(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}function bv(e,t){if(!Array.isArray(e))throw Error(`${t} must be an array`);return e}function xv(e,t){let n=d(e,t);return n===``||!s(n)&&n!==`..`&&!n.startsWith(`..${p}`)}function Sv(e){let t=e.KAPTURE_ARTIFACT_SUFFIX;if(!t||!/^pr-[1-9][0-9]*-base-[0-9a-f]{40}-head-[0-9a-f]{40}$/.test(t))throw Error(`KAPTURE_ARTIFACT_SUFFIX must identify exact PR/base/head revisions`);let n=(n,r)=>{let i=e[`KAPTURE_${n}_ARTIFACT_ID`]??``,a=e[`KAPTURE_${n}_ARTIFACT_DIGEST`]??``;if(!/^[1-9][0-9]*$/.test(i)||!/^[0-9a-f]{64}$/.test(a))throw Error(`${n} requires an artifact ID and SHA-256 digest`);return{id:Number(i),name:`${r}-${t}`,digest:`sha256:${a}`}};return g_.parse({schemaVersion:1,artifacts:{context:n(`CONTEXT`,`kapture-context`),baseStorybook:n(`BASE`,`kapture-storybook-base`),headStorybook:n(`HEAD`,`kapture-storybook-head`)}})}O();const Cv=D({meta:{name:`bind-artifacts`,description:`Record the exact downloaded artifact identities for trusted publication`},args:{output:{type:`string`,required:!0,description:`New capture-boundary.json path inside the raw report`}},async run({args:e}){let t=Sv(process.env);await ie(f(e.output),`${JSON.stringify(t)}\n`,{flag:`wx`,mode:384})}});var wv=class{#e;#t;#n;constructor(e,t,n=fetch){if(!e)throw Error(`GITHUB_TOKEN is required`);this.#e=e,this.#t=t,this.#n=n}async getWorkflowRun(e){return Ev(await this.#i(`GET`,`${this.#r()}/actions/runs/${e}`))}async listWorkflowRuns(e,t){let n=[];for(let r=1;r<=10;r+=1){let i=new URLSearchParams({event:`pull_request`,branch:t,per_page:`100`,page:String(r)}),a=Nv(Mv(await this.#i(`GET`,`${this.#r()}/actions/workflows/${e}/runs?${i}`),`workflow runs response`).workflow_runs,`workflow_runs`).map(Dv);if(n.push(...a),a.length<100)return n}throw Error(`GitHub returned more than 1000 workflow runs`)}async listRunArtifacts(e){let t=[];for(let n=1;n<=10;n+=1){let r=new URLSearchParams({per_page:`100`,page:String(n)}),i=Nv(Mv(await this.#i(`GET`,`${this.#r()}/actions/runs/${e}/artifacts?${r}`),`artifacts response`).artifacts,`artifacts`).map(Ov);if(t.push(...i),i.length<100)return t}throw Error(`GitHub returned more than 1000 workflow artifacts`)}async getArtifact(e){let t=await this.#o(`GET`,`${this.#r()}/actions/artifacts/${e}`);return t.status===404?null:(await Tv(t,`GET`,`/actions/artifacts/${e}`),Ov(await t.json()))}async downloadArtifactArchive(e,t){if(!Number.isSafeInteger(t)||t<=0)throw Error(`Artifact download byte limit must be positive`);let n=await this.#o(`GET`,`${this.#r()}/actions/artifacts/${e}/zip`,`manual`),r=await this.#a(n,e);await Tv(r,`GET`,`/actions/artifacts/${e}/zip`);let i=r.headers.get(`content-length`);if(i!==null){let n=Number(i);if(!Number.isSafeInteger(n)||n<0||n>t)throw Error(`Artifact ${e} exceeds the ${t} byte download limit`)}if(!r.body)throw Error(`Artifact ${e} download returned no body`);let a=r.body.getReader(),o=[],s=0;try{for(;;){let{done:n,value:r}=await a.read();if(n)break;if(s+=r.byteLength,s>t)throw await a.cancel(),Error(`Artifact ${e} exceeds the ${t} byte download limit`);o.push(Buffer.from(r))}}finally{a.releaseLock()}if(s<1)throw Error(`Artifact ${e} download is empty`);return Buffer.concat(o,s)}async deleteArtifact(e){let t=await this.#o(`DELETE`,`${this.#r()}/actions/artifacts/${e}`);t.status!==404&&await Tv(t,`DELETE`,`/actions/artifacts/${e}`)}async getPullRequest(e){return kv(await this.#i(`GET`,`${this.#r()}/pulls/${e}`))}async listOpenPullRequestsForHead(e,t,n){let r=jv(e),i=[];for(let e=1;e<=10;e+=1){let a=new URLSearchParams({state:`open`,base:n,head:`${r.owner}:${t}`,per_page:`100`,page:String(e)}),o=Nv(await this.#i(`GET`,`${this.#r()}/pulls?${a}`),`pull requests response`).map(kv);if(i.push(...o),o.length<100)return i}throw Error(`GitHub returned more than 1000 matching pull requests`)}async getContentSha(e,t,n){let r=jv(e),i=t.split(`/`).map(encodeURIComponent).join(`/`),a=new URLSearchParams({ref:n});return Rv(Mv(await this.#i(`GET`,`/repos/${encodeURIComponent(r.owner)}/${encodeURIComponent(r.repo)}/contents/${i}?${a}`),`contents response`).sha,`contents SHA`)}#r(){let{owner:e,repo:t}=this.#t;return`/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}`}async#i(e,t){let n=await this.#o(e,t);return await Tv(n,e,t),n.json()}async#a(e,t){if(e.status<300||e.status>399)return e;let n=e.headers.get(`location`);if(!n)throw Error(`Artifact ${t} redirect is missing its location`);let r;try{r=new URL(n)}catch{throw Error(`Artifact ${t} redirect location is invalid`)}if(r.protocol!==`https:`||r.username||r.password)throw Error(`Artifact ${t} redirect must be a credential-free HTTPS URL`);return this.#n(r,{method:`GET`,headers:{Accept:`application/octet-stream`,"User-Agent":`kapture-cli`},redirect:`follow`})}#o(e,t,n=`follow`){return this.#n(`https://api.github.com${t}`,{method:e,headers:{Accept:`application/vnd.github+json`,Authorization:`Bearer ${this.#e}`,"X-GitHub-Api-Version":`2022-11-28`,"User-Agent":`kapture-cli`},redirect:n})}};async function Tv(e,t,n){if(!e.ok)throw Error(`GitHub API ${t} ${n} failed with status ${e.status}`)}function Ev(e){let t=Mv(e,`workflow run`);return{id:Pv(t.id,`workflow run ID`),runNumber:Pv(t.run_number,`workflow run number`),runAttempt:Pv(t.run_attempt,`workflow run attempt`),workflowId:Pv(t.workflow_id,`workflow ID`),path:Fv(t.path,`workflow path`),status:Fv(t.status,`workflow run status`),conclusion:Iv(t.conclusion,`workflow run conclusion`),event:Fv(t.event,`workflow run event`),headSha:Rv(t.head_sha,`workflow run head SHA`),headBranch:Fv(t.head_branch,`workflow run head branch`),headRepository:Av(t.head_repository,`workflow run head repository`),repository:Av(t.repository,`workflow run repository`)}}function Dv(e){let t=Mv(e,`workflow run candidate`);return{id:Pv(t.id,`workflow run ID`),runNumber:Pv(t.run_number,`workflow run number`),headRepositoryId:Pv(Mv(t.head_repository,`workflow run head repository`).id,`workflow run head repository ID`)}}function Ov(e){let t=Mv(e,`workflow artifact`),n=Mv(t.workflow_run,`artifact workflow run`);return{id:Pv(t.id,`artifact ID`),name:Fv(t.name,`artifact name`),sizeInBytes:Pv(t.size_in_bytes,`artifact size`),digest:zv(t.digest,`artifact digest`),expired:Lv(t.expired,`artifact expired`),workflowRun:{id:Pv(n.id,`artifact workflow run ID`),repositoryId:Pv(n.repository_id,`artifact workflow repository ID`),headRepositoryId:Pv(n.head_repository_id,`artifact workflow head repository ID`),headBranch:Fv(n.head_branch,`artifact workflow head branch`),headSha:Rv(n.head_sha,`artifact workflow head SHA`)}}}function kv(e){let t=Mv(e,`pull request`),n=Mv(t.base,`pull request base`),r=Mv(t.head,`pull request head`),i=Fv(t.state,`pull request state`);if(i!==`open`&&i!==`closed`)throw Error(`Pull request state is invalid`);return{number:Pv(t.number,`pull request number`),state:i,base:{ref:Fv(n.ref,`pull request base ref`),sha:Rv(n.sha,`pull request base SHA`),repository:Av(n.repo,`pull request base repository`)},head:{ref:Fv(r.ref,`pull request head ref`),sha:Rv(r.sha,`pull request head SHA`),repository:Av(r.repo,`pull request head repository`)}}}function Av(e,t){let n=Mv(e,t),r=Fv(n.full_name,`${t} full name`);return jv(r),{id:Pv(n.id,`${t} ID`),fullName:r}}function jv(e){let t=e.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!t?.[1]||!t[2])throw Error(`Repository full name is invalid`);return{owner:t[1],repo:t[2]}}function Mv(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}function Nv(e,t){if(!Array.isArray(e))throw Error(`${t} must be an array`);return e}function Pv(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<=0)throw Error(`${t} must be a positive integer`);return e}function Fv(e,t){if(typeof e!=`string`||e.length<1||e.length>512)throw Error(`${t} must be a non-empty bounded string`);for(let n of e){let e=n.codePointAt(0)??0;if(e<=31||e===127)throw Error(`${t} contains control characters`)}return e}function Iv(e,t){return e===null?null:Fv(e,t)}function Lv(e,t){if(typeof e!=`boolean`)throw Error(`${t} must be a boolean`);return e}function Rv(e,t){if(typeof e!=`string`||!/^[0-9a-f]{40}$/.test(e))throw Error(`${t} must be a lowercase full SHA`);return e}function zv(e,t){if(typeof e!=`string`||!/^sha256:[0-9a-f]{64}$/.test(e))throw Error(`${t} must be a SHA-256 digest`);return e}O();const Bv=D({meta:{name:`cleanup`,description:`Delete only exact receipt-bound Kapture artifact IDs`},args:{receipt:{type:`string`,required:!0,description:`Path to the strict prepare-run receipt`},"trusted-artifact-id":{type:`string`,description:`Exact current trusted report artifact ID`},"trusted-artifact-digest":{type:`string`,description:`upload-artifact SHA-256 digest for the current trusted report artifact`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=Hv(n),i=e[`trusted-artifact-id`]?Vv(e[`trusted-artifact-id`],`trusted-artifact-id`):void 0,a=await x_(new wv(t,r),{event:n,receiptPath:f(e.receipt),...i===void 0?{}:{trustedArtifactId:i},...e[`trusted-artifact-digest`]?{trustedArtifactDigest:e[`trusted-artifact-digest`]}:{}});await G({"deleted-artifact-count":a.length,"deleted-artifact-ids":a.join(`,`)})}});function Vv(e,t){if(!/^[1-9][0-9]*$/.test(e))throw Error(`${t} must be a positive integer`);let n=Number(e);if(!Number.isSafeInteger(n))throw Error(`${t} must be a safe integer`);return n}function Hv(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O();const Uv=D({meta:{name:`context`,description:`Validate a pull request event and write immutable Kapture capture context`},args:{"adapter-package-json":{type:`string`,description:`Optional project-relative package.json to check for the adapter on the exact base revision`},output:{type:`string`,required:!0,description:`Path for the normalized context JSON`},"changed-files-output":{type:`string`,required:!0,description:`Path for the versioned changed-files manifest`},"base-branch":{type:`string`,description:`Expected pull request base branch`}},async run({args:e}){let t=Dg(await ef(),e[`base-branch`]),n=process.env.GITHUB_TOKEN;if(!n)throw Error(`GITHUB_TOKEN is required`);let[r,i]=t.base.repository.split(`/`);if(!r||!i)throw Error(`Capture context repository is invalid`);let o=new Zd(n,{owner:r,repo:i}),s=await Lg(o,t),c=e[`adapter-package-json`]?Wv(await o.readPackageManifest(e[`adapter-package-json`],t.base.sha)):`compare`,l=f(e.output),u=f(e[`changed-files-output`]);if(l===u)throw Error(`output and changed-files-output must be different paths`);await Promise.all([y(a(l),{recursive:!0}),y(a(u),{recursive:!0})]),await Promise.all([ie(l,`${JSON.stringify(t,null,2)}\n`,{flag:`wx`}),ie(u,`${JSON.stringify(s,null,2)}\n`,{flag:`wx`})]),await G({"integration-mode":c,"artifact-suffix":Og(t),"base-repository":t.base.repository,"base-ref":t.base.ref,"base-sha":t.base.sha,"changed-files-complete":String(s.complete),"changed-files-count":s.files.length,"changed-files-path":u,"context-path":l,"head-repository":t.head.repository,"head-repository-id":t.head.repositoryId,"head-ref":t.head.ref,"head-sha":t.head.sha,"pr-number":t.prNumber,"preview-branch":t.preview.branch,"preview-alias":t.preview.alias})}});function Wv(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`Invalid package manifest`);let t=e;for(let e of[`dependencies`,`devDependencies`]){let n=t[e];if(n!==void 0&&(!n||typeof n!=`object`||Array.isArray(n)))throw Error(`Invalid package dependencies`);let r=n?.[`@kaptures/storybook`];if(typeof r==`string`&&r.trim())return`compare`}throw Error(`The selected base package manifest does not declare @kaptures/storybook. Select the adapter's workspace manifest or omit --adapter-package-json to validate the built Storybook at capture time.`)}const Gv=/^[0-9a-f]{40}$/,Kv=/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/,qv=/^\.github\/workflows\/[A-Za-z0-9_./-]+\.ya?ml$/,Jv=`Base branch changed; rerun visual capture`,Yv=new Set([`action_required`,`cancelled`,`failure`,`neutral`,`skipped`,`stale`,`startup_failure`,`success`,`timed_out`]);async function Xv(e,t,n){let r=gy(n.captureWorkflowPath),i=by(n.baseBranch,`base branch`),a=Bd(n.statusContext),o=$v(n.event,r),s=await ey(e,o,i);if(!s.ok)return py(s.reason);if(await ay(t,o,s.target))return py(`final-report-exists`,s.target);let c=await ey(e,o,i);if(!c.ok)return py(c.reason,s.target);if(!fy(s.target,c.target))return py(`pull-request-changed`,c.target);if(await ay(t,o,c.target))return py(`final-report-exists`,c.target);let l=uy(o,c.target);return await t.setReviewStatus(c.target.headSha,l.state,l.description,a),{status:l.state,reason:`status-written`,prNumber:c.target.prNumber,headSha:c.target.headSha}}async function Zv(e,t,n){let r=gy(n.captureWorkflowPath),i=by(n.baseBranch,`base branch`),a=Bd(n.statusContext),o=Qv(n.event,r),s=await ey(e,o,i);if(!s.ok)return my(s.reason);let c=sy(o,await oy(t,o,s.target,a),s.target);if(c)return my(c,s.target);let l=await ey(e,o,i);if(!l.ok)return my(l.reason,s.target);if(!fy(s.target,l.target))return my(`pull-request-changed`,l.target);let u=sy(o,await oy(t,o,l.target,a),l.target);if(u)return my(u,l.target);let d=l.target.baseDrift?Jv:o.run.conclusion===`success`?`Visual report publication did not complete`:`Visual capture did not succeed (${o.run.conclusion})`;return await t.setReviewStatus(l.target.headSha,`error`,d,a),{status:`error`,reason:`status-written`,prNumber:l.target.prNumber,headSha:l.target.headSha}}function Qv(e,t){let n=$v(e,t);if(n.run.status!==`completed`)throw Error(`Kapture finalize-run requires a completed workflow_run event`);return{...n,run:{...n.run,status:`completed`}}}function $v(e,t){let n=Ty(e,`GitHub workflow_run event`),r=Sy(n.action,`workflow_run action`);if(r!==`in_progress`&&r!==`completed`)throw Error(`Kapture reconcile-run requires an in_progress or completed workflow_run event`);let i=Ty(n.repository,`event repository`),a=_y(i.full_name,`event repository`),o=Cy(i.id,`event repository ID`),s=Ty(n.workflow_run,`workflow_run`),c=gy(Sy(s.path,`workflow path`));if(c!==gy(t))throw Error(`workflow_run path ${c} does not match ${t}`);if(s.event!==`pull_request`)throw Error(`Kapture reconcile-run requires a pull_request capture run`);let l=Sy(s.status,`workflow run status`),u=xy(s.conclusion,`workflow run conclusion`);if(r===`in_progress`&&(l!==`in_progress`||u!==null))throw Error(`An in_progress workflow_run event must describe an unfinished run`);if(r===`completed`&&(l!==`completed`||u===null||!Yv.has(u)))throw Error(`A completed workflow_run event must have a supported conclusion`);let d=Ty(s.head_repository,`workflow_run head repository`),f={id:Cy(d.id,`workflow run head repository ID`),fullName:_y(d.full_name,`workflow run head repository`)},p=by(s.head_branch,`workflow run head branch`),m=Ey(s.pull_requests,`workflow_run pull requests`);if(m.length>1)throw Error(`workflow_run must contain at most one pull request`);let h=m[0]?hy(m[0]):void 0;if(h&&(h.base.repositoryId!==o||h.head.repositoryId!==f.id||h.head.ref!==p))throw Error(`workflow_run pull request metadata conflicts with run provenance`);return{repository:{id:o,fullName:a,ref:vy(a)},run:{id:Cy(s.id,`workflow run ID`),runNumber:Cy(s.run_number,`workflow run number`),attempt:Cy(s.run_attempt,`workflow run attempt`),workflowId:Cy(s.workflow_id,`workflow ID`),workflowPath:c,status:l,conclusion:u,event:`pull_request`,headSha:yy(s.head_sha,`workflow run head SHA`),headBranch:p,headRepository:f},...h?{pullRequest:h}:{}}}async function ey(e,t,n){let r=await e.getWorkflowRun(t.run.id);return ty(r,t),r.runAttempt===t.run.attempt?r.status!==t.run.status||r.conclusion!==t.run.conclusion?{ok:!1,reason:`stale-run-state`}:await ny(e,r)?ry(e,t,n):{ok:!1,reason:`superseded-run`}:{ok:!1,reason:`stale-run-attempt`}}function ty(e,t){if(e.id!==t.run.id||e.runNumber!==t.run.runNumber||e.workflowId!==t.run.workflowId||gy(e.path)!==t.run.workflowPath||e.event!==`pull_request`||e.headSha!==t.run.headSha||e.headBranch!==t.run.headBranch||e.headRepository.id!==t.run.headRepository.id||e.headRepository.fullName!==t.run.headRepository.fullName||e.repository.id!==t.repository.id||e.repository.fullName!==t.repository.fullName)throw Error(`Triggering capture run identity no longer matches the workflow_run event`)}async function ny(e,t){let n=(await e.listWorkflowRuns(t.workflowId,t.headBranch)).filter(e=>e.headRepositoryId===t.headRepository.id);if(n.filter(e=>e.id===t.id).some(e=>e.runNumber!==t.runNumber))throw Error(`Latest workflow run metadata conflicts with the triggering run`);return n.reduce((e,t)=>e?t.runNumber===e.runNumber?t.id>e.id?t:e:t.runNumber>e.runNumber?t:e:t,void 0)?.id===t.id}async function ry(e,t,n){if(t.pullRequest){if(t.pullRequest.base.ref!==n)return{ok:!1,reason:`base-branch-mismatch`};let r=await e.getPullRequest(t.pullRequest.number);return iy(r,t,n)?{ok:!0,target:dy(r,r.base.sha!==t.pullRequest.base.sha)}:{ok:!1,reason:`pull-request-not-current`}}let r=(await e.listOpenPullRequestsForHead(t.run.headRepository.fullName,t.run.headBranch,n)).filter(e=>e.state===`open`&&e.base.repository.id===t.repository.id&&e.base.repository.fullName===t.repository.fullName&&e.base.ref===n&&e.head.repository.id===t.run.headRepository.id&&e.head.repository.fullName===t.run.headRepository.fullName&&e.head.ref===t.run.headBranch);return r.length===0?{ok:!1,reason:`pull-request-not-found`}:r.length===1?{ok:!0,target:dy(r[0])}:{ok:!1,reason:`pull-request-ambiguous`}}function iy(e,t,n){let r=t.pullRequest;return!!(r&&e.number===r.number&&e.state===`open`&&e.base.repository.id===t.repository.id&&e.base.repository.fullName===t.repository.fullName&&e.base.ref===n&&e.head.repository.id===t.run.headRepository.id&&e.head.repository.fullName===t.run.headRepository.fullName&&e.head.ref===t.run.headBranch&&e.head.sha===r.head.sha)}async function ay(e,t,n){return ly(await e.findCurrentReportMarker(n.prNumber,n.baseSha,n.headSha),t)}async function oy(e,t,n,r){let i=await e.findCurrentReportMarker(n.prNumber,n.baseSha,n.headSha),a=await e.getLatestReviewStatus(n.headSha,r);return{marker:ly(i,t)?i:null,status:a}}function sy(e,t,n){return n.baseDrift&&t.status?.state===`error`&&t.status.description===Jv?`base-drift-already-recorded`:e.run.conclusion===`success`?cy(t)?`final-report-exists`:t.status?.state===`error`&&t.status.description===`Visual report publication did not complete`?`publication-failure-already-recorded`:void 0:t.status?.state===`error`?`capture-failure-already-recorded`:void 0}function cy(e){let{marker:t,status:n}=e;return!t?.reportUrl||!n||t.reportUrl!==n.targetUrl?!1:t.status===`clean`?n.state===`success`&&n.description===`No visual changes`:t.status===`changed`?n.state===`pending`&&n.description===`Visual changes require approval`:n.state===`failure`}function ly(e,t){return!!(e&&e.captureRunId===t.run.id&&e.captureRunAttempt===t.run.attempt&&e.captureWorkflowId===t.run.workflowId&&e.captureRunHeadBranch===t.run.headBranch&&e.captureRunHeadRepositoryId===t.run.headRepository.id)}function uy(e,t){return t.baseDrift?{state:`error`,description:Jv}:e.run.status===`in_progress`?{state:`pending`,description:`Visual capture is in progress`}:e.run.conclusion===`success`?{state:`pending`,description:`Visual report is awaiting publication`}:{state:`error`,description:`Visual capture did not succeed (${e.run.conclusion})`}}function dy(e,t=!1){return{prNumber:e.number,baseSha:e.base.sha,headSha:e.head.sha,baseDrift:t}}function fy(e,t){return e.prNumber===t.prNumber&&e.baseSha===t.baseSha&&e.headSha===t.headSha&&e.baseDrift===t.baseDrift}function py(e,t){return{status:`noop`,reason:e,...t?{prNumber:t.prNumber,headSha:t.headSha}:{}}}function my(e,t){return{status:`noop`,reason:e,...t?{prNumber:t.prNumber,headSha:t.headSha}:{}}}function hy(e){let t=Ty(e,`workflow_run pull request`),n=Ty(t.base,`workflow_run pull request base`),r=Ty(t.head,`workflow_run pull request head`);return{number:Cy(t.number,`workflow_run pull request number`),base:{repositoryId:Cy(Ty(n.repo,`workflow_run pull request base repository`).id,`workflow_run pull request base repository ID`),ref:by(n.ref,`workflow_run pull request base ref`),sha:yy(n.sha,`workflow_run pull request base SHA`)},head:{repositoryId:Cy(Ty(r.repo,`workflow_run pull request head repository`).id,`workflow_run pull request head repository ID`),ref:by(r.ref,`workflow_run pull request head ref`),sha:yy(r.sha,`workflow_run pull request head SHA`)}}}function gy(e){if(!qv.test(e)||e.includes(`//`)||e.includes(`..`))throw Error(`capture-workflow-path must be a safe .github/workflows YAML path`);return e}function _y(e,t){let n=Sy(e,`${t} full name`);if(!Kv.test(n))throw Error(`${t} full name is invalid`);return n}function vy(e){let[t,n,...r]=e.split(`/`);if(!t||!n||r.length>0)throw Error(`Repository full name is invalid`);return{owner:t,repo:n}}function yy(e,t){let n=Sy(e,t);if(!Gv.test(n))throw Error(`${t} must be a lowercase full SHA`);return n}function by(e,t){let n=Sy(e,t);if(wy(n))throw Error(`${t} contains control characters`);return n}function xy(e,t){return e===null?null:Sy(e,t)}function Sy(e,t){if(typeof e!=`string`||e.length<1||e.length>512)throw Error(`${t} must be a non-empty bounded string`);if(wy(e))throw Error(`${t} contains control characters`);return e}function Cy(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<=0)throw Error(`${t} must be a positive integer`);return e}function wy(e){return Array.from(e).some(e=>{let t=e.codePointAt(0)??0;return t<=31||t===127})}function Ty(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}function Ey(e,t){if(!Array.isArray(e))throw Error(`${t} must be an array`);return e}O();const Dy=D({meta:{name:`finalize-run`,description:`Close an unfinished status for the exact completed trusted workflow run`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/visual-capture.yml`,description:`Trusted path of the pull_request capture workflow`},"base-branch":{type:`string`,required:!0,description:`Expected pull request base branch`},"status-context":{type:`string`,default:`Kapture Visual Review`,description:`GitHub commit status context`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=Oy(n),i=await Zv(new wv(t,r),new Zd(t,r),{event:n,captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],statusContext:Bd(e[`status-context`])});await G({status:i.status,"finalize-reason":i.reason,...i.prNumber===void 0?{}:{"pr-number":i.prNumber},...i.headSha?{"head-sha":i.headSha}:{}})}});function Oy(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}const ky={files:$g,fileBytes:e_,totalBytes:t_};function Ay(e,t){if(!t||s(t)||!/^[A-Za-z0-9._/-]+$/.test(t)||t.split(`/`).some(e=>!e||e===`.`||e===`..`))throw Error(`Storybook directory must be a project-relative path without dot segments`);return f(e,t)}async function jy(e,t,n=ky){let r=Ay(e,t),i=await te(e),a=f(e);for(let e of t.split(`/`)){a=c(a,e);let t=await v(a);if(t.isSymbolicLink()||!t.isDirectory())throw Error(`Storybook path must contain only non-symlink directories`)}let o=await te(r),l=d(i,o);if(l===`..`||l.startsWith(`..${p}`)||s(l))throw Error(`Storybook directory escapes the project root`);let u=(await v(r)).dev,m=[r],h=0,g=0,_=0;for(;m.length;){let e=m.pop();if(!e)break;for(let t of await S(e)){if(_++,_>n.files)throw Error(`Storybook exceeds its entry count boundary`);let r=c(e,t),i=await v(r);if(i.isSymbolicLink()||i.dev!==u)throw Error(`Storybook must not contain symbolic links or cross-device entries`);if(i.isDirectory()){m.push(r);continue}if(!i.isFile())throw Error(`Storybook must contain only regular files and directories`);if(h++,g+=i.size,h>n.files||i.size>n.fileBytes||g>n.totalBytes)throw Error(`Storybook exceeds its file or size boundary`)}}for(let e of[`index.html`,`iframe.html`,`index.json`])if(!(await v(c(r,e))).isFile())throw Error(`Storybook is missing a regular ${e}`);return{directory:r,files:h,bytes:g}}const My=`<!-- kapture-preview -->`;function Ny(e,t,n,r){if(e.base.repository!==e.head.repository||t.id!==e.runId||t.runAttempt!==n||t.path!==r||t.event!==`pull_request`||t.headBranch!==e.head.ref||t.headRepository.id!==e.head.repositoryId||t.headRepository.fullName!==e.head.repository||t.repository.fullName!==e.base.repository)throw Error(`Preview requires the exact same-repository pull request workflow run`)}function Py(e,t){if(t.baseRevision!==e.base.sha||t.headRevision!==e.head.sha)throw Error(`Preview report must match the exact event base/head revisions`)}function Fy(e,t,n){let{summary:r}=e,i=Rd(t);if(!i)throw Error(`Preview report URL is required`);let a=Object.values(e.entries).filter(e=>e.status===`changed`).sort((e,t)=>e.id.localeCompare(t.id)),o=a.slice(0,10).map(e=>{let t=new URL(i);return t.hash=encodeURIComponent(e.id),`- [${Wd(`${e.title} / ${e.name} · ${e.viewport.name}`)}](${Rd(t.toString())})`});return a.length>10&&o.push(`- [View ${a.length-10} more changed snapshots](${i})`),[My,`## Kapture preview`,``,`[Pixel comparison dashboard](${i})`,``,`Base: ${Wd(n.base.ref)} → Head: ${Wd(n.head.ref)}`,``,`Snapshots: ${r.total} · Changed: ${r.changed} · Unchanged: ${r.unchanged} · Unstable: ${r.unstable} · Added: ${r.added} · Removed: ${r.removed} · Errors: ${r.errors}`,...o.length?[``,`### Changed snapshots`,``,...o]:[],``,`Head: \`${e.headRevision}\``,`Report digest: \`${e.contentDigest}\``,``,`> Preview only. This result does not approve visual changes. Event-driven approval requires the production workflows on the default branch.`].join(`
631
+ `)}O();const Iy=D({meta:{name:`prepare-preview`,description:`Rebuild a same-repository pre-adoption preview without an approval gate`},args:{input:{type:`string`,required:!0},output:{type:`string`,required:!0},"base-branch":{type:`string`,required:!0},"storybook-directory":{type:`string`}},async run({args:e}){if(process.env.GITHUB_EVENT_NAME!==`pull_request`)throw Error(`Preview requires pull_request`);let t=Dg(await ef(),e[`base-branch`]);if(t.base.repository!==t.head.repository)throw Error(`Fork previews are not supported`);let n=f(e.output),r=await tg({inputDir:f(e.input),outputDir:n,trustedBaseBranch:t.base.ref,trustedHeadBranch:t.head.ref,...e[`storybook-directory`]?{storybookUrl:`./storybook/`}:{}});if(Py(t,r.report),e[`storybook-directory`]){let t=f(e[`storybook-directory`]);await jy(a(t),i(t)),await _(t,f(n,`storybook`),{recursive:!0,errorOnExist:!0,force:!1})}await G({"report-directory":n,"report-path":f(n,`report.json`),"report-digest":r.report.contentDigest??``,"head-sha":t.head.sha,"preview-alias":t.preview.alias})}});O();const Ly=D({meta:{name:`prepare-run`,description:`Download, verify, and rebuild a completed workflow_run report`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/visual-capture.yml`,description:`Trusted path of the pull_request capture workflow`},"base-branch":{type:`string`,required:!0,description:`Expected pull request base branch`},output:{type:`string`,default:`.kapture/trusted-report`,description:`New directory for the trusted static report`},receipt:{type:`string`,default:`.kapture/trusted-run-receipt.json`,description:`Path for the strict trusted-run receipt`},"storybook-url":{type:`string`,description:`Trusted HTTPS Storybook URL or the fixed same-origin ./storybook/ directory`},"temporary-root":{type:`string`,description:`Trusted temporary directory root (defaults to RUNNER_TEMP)`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=await v_(new wv(t,Ry(n)),{event:n,captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],outputDir:f(e.output),receiptPath:f(e.receipt),...e[`storybook-url`]?{storybookUrl:e[`storybook-url`]}:{},...e[`temporary-root`]?{temporaryRoot:f(e[`temporary-root`])}:{}});await G({"base-sha":r.receipt.context.base.sha,"context-artifact-id":r.receipt.artifacts.context.id,"head-repository":r.receipt.context.head.repository,"head-sha":r.receipt.context.head.sha,"pr-number":r.receipt.context.prNumber,"preview-branch":r.receipt.context.preview.branch,"preview-alias":r.receipt.context.preview.alias,"raw-report-artifact-id":r.receipt.artifacts.report.id,"report-digest":r.receipt.report.contentDigest,"report-directory":r.reportDirectory,"report-path":r.reportPath,receipt:r.receiptPath,"run-attempt":r.receipt.captureRun.attempt,"run-head-branch":r.receipt.captureRun.headBranch,"run-head-repository-id":r.receipt.captureRun.headRepositoryId,"run-head-sha":r.receipt.captureRun.headSha,"run-id":r.receipt.captureRun.id,"changed-files-complete":String(r.changedFiles.complete),"changed-files-count":r.changedFiles.files.length,"trusted-artifact-name":r.receipt.trustedArtifactName,"workflow-id":r.receipt.captureRun.workflowId})}});function Ry(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O();const zy=D({meta:{name:`prepare-storybook-run`,description:`Verify and extract the exact receipt-bound head Storybook artifact`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/visual-capture.yml`,description:`Trusted path of the pull_request capture workflow`},"base-branch":{type:`string`,required:!0,description:`Expected pull request base branch`},output:{type:`string`,required:!0,description:`New directory for the verified head Storybook`},receipt:{type:`string`,required:!0,description:`Path to the strict prepare-run receipt`},"temporary-root":{type:`string`,description:`Trusted temporary directory root (defaults beside output)`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=await b_(new wv(t,By(n)),{event:n,captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],outputDir:f(e.output),receiptPath:f(e.receipt),...e[`temporary-root`]?{temporaryRoot:f(e[`temporary-root`])}:{}});await G({"head-ref":r.context.head.ref,"head-repository":r.context.head.repository,"head-sha":r.context.head.sha,"head-storybook-artifact-id":r.artifact.id,"pr-number":r.context.prNumber,"preview-branch":r.context.preview.branch,"preview-alias":r.context.preview.alias,receipt:r.receiptPath,"storybook-directory":r.storybookDirectory})}});function By(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O();const Vy=D({meta:{name:`reconcile-run`,description:`Reconcile a trusted workflow_run event with the current PR status`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/visual-capture.yml`,description:`Trusted path of the pull_request capture workflow`},"base-branch":{type:`string`,required:!0,description:`Expected pull request base branch`},"status-context":{type:`string`,default:`Kapture Visual Review`,description:`GitHub commit status context`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=Hy(n),i=await Xv(new wv(t,r),new Zd(t,r),{event:n,captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],statusContext:Bd(e[`status-context`])});await G({status:i.status,"reconcile-reason":i.reason,...i.prNumber===void 0?{}:{"pr-number":i.prNumber},...i.headSha?{"head-sha":i.headSha}:{}})}});function Hy(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O();async function Uy(e,t,n=async(e,t)=>{switch(e){case`reconcile-run`:await Be(Vy,{rawArgs:t});break;case`prepare-run`:await Be(Ly,{rawArgs:t});break;case`prepare-storybook-run`:await Be(zy,{rawArgs:t})}}){let r=[`--capture-workflow-path`,t.captureWorkflowPath,`--base-branch`,t.baseBranch];if(await n(`reconcile-run`,[...r,`--status-context`,t.statusContext]),!e||typeof e!=`object`)throw Error(`Invalid workflow_run event`);let i=e;return i.action!==`completed`||i.workflow_run?.conclusion!==`success`?!1:(await n(`prepare-run`,[...r,`--output`,t.output,`--receipt`,t.receipt,...t.includeStorybook?[`--storybook-url`,`./storybook/`]:[]]),t.includeStorybook&&await n(`prepare-storybook-run`,[...r,`--output`,f(t.output,`storybook`),`--receipt`,t.receipt]),!0)}const Wy=D({meta:{name:`prepare-review`,description:`Reconcile a workflow run and prepare verified static files for any hosting provider`},args:{"capture-workflow-path":{type:`string`,default:`.github/workflows/kapture-capture.yml`},"base-branch":{type:`string`,required:!0},output:{type:`string`,required:!0},receipt:{type:`string`,required:!0},"include-storybook":{type:`boolean`,default:!1},"status-context":{type:`string`,default:`Kapture Visual Review`}},async run({args:e}){await G({ready:`false`});let t=await Uy(await ef(),{captureWorkflowPath:e[`capture-workflow-path`],baseBranch:e[`base-branch`],output:f(e.output),receipt:f(e.receipt),includeStorybook:e[`include-storybook`],statusContext:e[`status-context`]});await G({ready:String(t)})}});O();const Gy=D({meta:{name:`publish-preview`,description:`Publish a preview-only status and comment; never issue an approval marker`},args:{report:{type:`string`,required:!0},"report-digest":{type:`string`,required:!0},"report-url":{type:`string`,required:!0},"base-branch":{type:`string`,required:!0},"capture-workflow-path":{type:`string`,default:`.github/workflows/kapture-capture.yml`}},async run({args:e}){if(process.env.GITHUB_EVENT_NAME!==`pull_request`)throw Error(`Preview requires pull_request`);let t=Dg(await ef(),e[`base-branch`]),n=process.env.GITHUB_TOKEN;if(!n)throw Error(`GITHUB_TOKEN is required`);let[r,i]=t.base.repository.split(`/`);if(!r||!i)throw Error(`Invalid repository`);let a=new Zd(n,{owner:r,repo:i}),o=new wv(n,{owner:r,repo:i}),s=await o.getWorkflowRun(t.runId);Ny(t,s,Number(process.env.GITHUB_RUN_ATTEMPT),e[`capture-workflow-path`]);let c=await rg(f(e.report),e[`report-digest`]);Py(t,c);let l=Rd(e[`report-url`]);if(!l)throw Error(`Preview report URL is required`);let u=async()=>{let n=await a.getPullRequest(t.prNumber);if(n.number!==t.prNumber||n.state!==`open`||n.head.sha!==t.head.sha||n.base.sha!==t.base.sha)throw Error(`Ignoring an obsolete preview result`);let r=await o.getWorkflowRun(t.runId);Ny(t,r,s.runAttempt,e[`capture-workflow-path`]),await w_(o,r)};await u();let d=await a.postOrUpdateReportComment(t.prNumber,Fy(c,l,t),My);if(await u(),await a.setReviewStatus(t.head.sha,c.summary.errors?`failure`:`success`,`Preview only; visual changes require separate review`,`Kapture Preview`,l),await G({"comment-id":d,"report-digest":c.contentDigest??``}),c.summary.errors)throw Error(`Preview contains capture errors`)}});O();const Ky=D({meta:{name:`publish-run`,description:`Revalidate a prepare-run receipt and publish its deployed visual report`},args:{receipt:{type:`string`,required:!0,description:`Path to the strict prepare-run receipt`},report:{type:`string`,required:!0,description:`Path to the trusted image-bound report.json`},"report-url":{type:`string`,required:!0,description:`Immutable HTTPS URL of the deployed dashboard`},"status-context":{type:`string`,default:`Kapture Visual Review`,description:`GitHub commit status context`},"comment-language":{type:`string`,default:`en`,description:`PR comment language (en or ko)`}},async run({args:e}){try{let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await ef(),r=qy(n),i=Rd(e[`report-url`]);if(!i)throw Error(`report-url is required`);let a=await y_(new wv(t,r),new Zd(t,r),{event:n,receiptPath:f(e.receipt),reportPath:f(e.report),reportUrl:i,statusContext:Bd(e[`status-context`]),commentLanguage:Od(e[`comment-language`])});if(await G({status:a.status,"changed-count":a.changedCount,"comment-id":a.commentId,"report-digest":a.reportDigest}),a.status===`error`)throw Error(`Visual capture errors were published to the trusted report`)}catch(e){throw await G({status:`error`}),e}}});function qy(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`GitHub event payload must be an object`);let t=e.repository;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`GitHub event repository must be an object`);let n=t.full_name;if(typeof n!=`string`)throw Error(`GitHub event repository is invalid`);let r=n.match(/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/);if(!r?.[1]||!r[2])throw Error(`GitHub event repository is invalid`);return{owner:r[1],repo:r[2]}}O(),Jh();const Jy=D({meta:{name:`report`,description:`Publish a trusted Kapture PR report and commit status`},args:{report:{type:`string`,required:!0,description:`Path to image-bound trusted report.json`},"report-url":{type:`string`,description:`HTTPS URL for the full report or workflow run`},"status-context":{type:`string`,default:`Kapture Visual Review`,description:`GitHub commit status context`},"comment-language":{type:`string`,default:`en`,description:`PR comment language (en or ko)`}},async run({args:e}){try{let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await Eh(e.report),r=tf(await ef()),i=Bd(e[`status-context`]),a=Rd(e[`report-url`]),o=await ff(new Zd(t,r.repository),r,n,i,a,Od(e[`comment-language`]));if(await G({status:o.status,"changed-count":o.changedCount,"comment-id":o.commentId,"report-digest":o.reportDigest}),o.status===`error`)throw Error(`${n.summary.errors} visual capture error(s)`)}catch(e){throw await G({status:`error`}),e}}});O();const Yy=D({meta:{name:`validate-build`,description:`Validate a Storybook artifact boundary before upload or capture`},args:{root:{type:`string`,required:!0,description:`Trusted checkout or artifact extraction root`},directory:{type:`string`,required:!0,description:`Storybook directory relative to root`},"path-only":{type:`boolean`,default:!1,description:`Validate the input path before building`}},async run({args:e}){if(e[`path-only`]){await G({directory:Ay(e.root,e.directory)});return}let t=await jy(e.root,e.directory);await G(t),console.log(`Validated ${t.files} Storybook files (${t.bytes} bytes).`)}});O(),Jh();const Xy=D({meta:{name:`verify`,description:`Verify that a Kapture report matches the current pull request`},args:{report:{type:`string`,required:!0,description:`Path to untrusted report.json`}},async run({args:e}){let t=process.env.GITHUB_TOKEN;if(!t)throw Error(`GITHUB_TOKEN is required`);let n=await Eh(e.report),r=tf(await ef());await df(new Zd(t,r.repository),r,n)}});O();const Zy=D({meta:{name:`github`,description:`Verify, publish, and approve GitHub visual reviews`},subCommands:{context:Uv,"validate-build":Yy,"bind-artifacts":Cv,"prepare-review":Wy,"prepare-preview":Iy,"publish-preview":Gy,verify:Xy,report:Jy,approve:hf,"prepare-run":Ly,"prepare-storybook-run":zy,"publish-run":Ky,"reconcile-run":Vy,"finalize-run":Dy,cleanup:Bv}});async function Qy(e,t){let{report:n,resolveImage:r}=await $y(e),i=n.entries[t];if(!i)throw Error(`Kapture report does not contain snapshot ${t}`);let a=[],o=(e,t)=>{t&&(ib(e,t),a.push({role:e,mediaType:`image/png`,source:r(t)}))};return o(`base`,i.baseImage),o(`head`,i.headImage),o(`diff`,i.diffImage),o(`base-repeat`,i.instability?.base?.repeatImage),o(`base-instability-diff`,i.instability?.base?.diffImage),o(`head-repeat`,i.instability?.head?.repeatImage),o(`head-instability-diff`,i.instability?.head?.diffImage),{version:1,report:{baseRevision:n.baseRevision,headRevision:n.headRevision,...n.contentDigest?{contentDigest:n.contentDigest}:{}},snapshot:{id:i.id,storyId:i.storyId,title:i.title,name:i.name,viewport:i.viewport,status:i.status,...i.changedPixels===void 0?{}:{changedPixels:i.changedPixels},...i.diffRatio===void 0?{}:{diffRatio:i.diffRatio},...i.threshold?{threshold:i.threshold}:{},...i.error?{error:i.error}:{}},images:a}}async function $y(e){let t=rb(e);return t?tb(t):eb(e)}async function eb(e){let t=f(e),n=await C(t);if(!n.isFile()||n.size>10485760)throw Error(`Kapture report must be a file no larger than ${Oh} bytes`);let r=nb(await x(t,`utf8`)),i=a(t);return{report:r,resolveImage:e=>{let t=f(i,e);if(d(i,t).startsWith(`..`))throw Error(`Kapture report contains an unsafe image path: ${e}`);return{type:`path`,value:t}}}}async function tb(e){let t=await fetch(e,{redirect:`error`});if(!t.ok)throw Error(`Kapture report request failed with HTTP ${t.status}`);let n=Number(t.headers.get(`content-length`));if(Number.isFinite(n)&&n>10485760)throw Error(`Kapture report must be no larger than ${Oh} bytes`);let r=await t.text();if(Buffer.byteLength(r)>10485760)throw Error(`Kapture report must be no larger than ${Oh} bytes`);return{report:nb(r),resolveImage:t=>{let n=new URL(t,e);if(n.origin!==e.origin||n.protocol!==`https:`)throw Error(`Kapture report contains an unsafe image URL: ${t}`);return{type:`url`,value:n.toString()}}}}function nb(e){try{return wh(JSON.parse(e))}catch(e){throw e instanceof SyntaxError?Error(`Kapture report does not contain valid JSON`):e}}function rb(e){let t;try{t=new URL(e)}catch{return}if(t.protocol!==`https:`||t.username||t.password)throw Error(`Remote Kapture report must be an HTTPS URL without credentials`);return t}function ib(e,t){let n=`images/${e}/`,r=t.slice(n.length);if(!t.startsWith(n)||!r||r.includes(`/`)||r.includes(`\\`)||!r.endsWith(`.png`))throw Error(`Kapture report contains an invalid ${e} image path: ${t}`)}var ab,ob=w((()=>{O(),Jh(),ab=D({meta:{name:`inspect`,description:`Print machine-readable snapshot evidence for agents and review tools`},args:{report:{type:`string`,required:!0,description:`Local report.json path or public HTTPS report.json URL`},snapshot:{type:`string`,required:!0,description:`Exact snapshot ID`}},async run({args:e}){let t=await Qy(e.report,e.snapshot);process.stdout.write(`${JSON.stringify(t,null,2)}\n`)}})})),sb=w((()=>{Mc()})),cb=w((()=>{sb()})),lb=Ce({createKaptureMcpServer:()=>db,getSnapshotEvidenceResult:()=>fb,startKaptureMcpServer:()=>ub});async function ub(e){let{serveStdio:t}=await import(`@modelcontextprotocol/server/stdio`);t(()=>db(e),{onerror:e=>console.error(e.message)})}async function db(e){let{McpServer:t}=await import(`@modelcontextprotocol/server`),n=new t({name:`kapture`,version:$e},{instructions:`Use list_snapshots to find visual changes, then get_snapshot_evidence to inspect the exact PNG evidence. Unstable snapshots are nondeterministic and do not represent an approvable baseline change.`});return n.registerTool(`list_snapshots`,{title:`List Kapture snapshots`,description:`List snapshot IDs, statuses, stories, viewports, and diff metrics from a report.`,inputSchema:Ss({status:Es([`unchanged`,`changed`,`unstable`,`added`,`removed`,`error`]).optional().describe(`Optional exact status filter`)}),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0}},async({status:t})=>{let{report:n}=await $y(e),r=Object.values(n.entries).filter(e=>!t||e.status===t).map(e=>({id:e.id,storyId:e.storyId,title:e.title,name:e.name,viewport:e.viewport,status:e.status,changedPixels:e.changedPixels,changedPixelPercentage:e.diffRatio===void 0?void 0:e.diffRatio*100})),i={baseRevision:n.baseRevision,headRevision:n.headRevision,summary:n.summary,snapshots:r};return{content:[{type:`text`,text:JSON.stringify(i,null,2)}],structuredContent:i}}),n.registerTool(`get_snapshot_evidence`,{title:`Get Kapture snapshot evidence`,description:`Return machine-readable metadata and the actual base, head, diff, and instability PNGs for one snapshot.`,inputSchema:Ss({snapshotId:R().min(1).max(512).describe(`Exact ID returned by list_snapshots`)}),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0}},async({snapshotId:t})=>fb(e,t)),n}async function fb(e,t){let n=await Qy(e,t),r=await Promise.all(n.images.map(pb));return{content:[{type:`text`,text:JSON.stringify(_b(n),null,2)},...r],structuredContent:_b(n)}}async function pb(e){return{type:`image`,data:(e.source.type===`path`?await mb(e.source.value):await hb(e.source.value)).toString(`base64`),mimeType:`image/png`,_meta:{"kapture/role":e.role}}}async function mb(e){let t=await v(e);if(t.isSymbolicLink()||!t.isFile()||t.size>vb)throw Error(`Kapture evidence image must be no larger than ${vb} bytes`);return gb(await x(e),e)}async function hb(e){let t=await fetch(e,{redirect:`error`});if(!t.ok)throw Error(`Kapture evidence request failed with HTTP ${t.status}`);let n=Number(t.headers.get(`content-length`));if(Number.isFinite(n)&&n>vb)throw Error(`Kapture evidence image must be no larger than ${vb} bytes`);return gb(Buffer.from(await t.arrayBuffer()),e)}function gb(e,t){if(e.byteLength>vb||!e.subarray(0,8).equals(yb))throw Error(`Kapture evidence is not a supported PNG: ${t}`);return e}function _b(e){return{...e,images:e.images.map(t=>({role:t.role,mediaType:t.mediaType,source:t.source,contentBlockIndex:e.images.indexOf(t)+1}))}}var vb,yb,bb=w((()=>{cb(),ob(),vb=26214400,yb=Buffer.from([137,80,78,71,13,10,26,10])}));O();const xb=D({meta:{name:`mcp`,description:`Serve Kapture snapshot evidence to agents over MCP stdio`},args:{report:{type:`string`,required:!0,description:`Local report.json path or public HTTPS report.json URL`}},async run({args:e}){let{startKaptureMcpServer:t}=await Promise.resolve().then(()=>(bb(),lb));await t(e.report)}});Td(),O();const Sb=D({meta:{name:`plan`,description:`Select affected Storybook stories from base/head dependency manifests`},args:{"base-dir":{type:`string`,required:!0,description:`Built base Storybook directory`},"head-dir":{type:`string`,required:!0,description:`Built head Storybook directory`},"changed-files":{type:`string`,required:!0,description:`Path to a versioned changed-files manifest or legacy JSON path array`},output:{type:`string`,default:`.kapture/plan.json`,description:`Affected-story plan output path`}},async run({args:e}){let t=await Cb(f(e[`changed-files`])),n=await El({baseDir:f(e[`base-dir`]),headDir:f(e[`head-dir`]),changedFiles:t.files,changedFilesComplete:t.complete,...t.evidence?{changedFilesEvidence:t.evidence}:{}}),r=f(e.output);await y(a(r),{recursive:!0}),await ie(r,`${JSON.stringify(n,null,2)}\n`,`utf8`),n.selectionMode===`affected`?Q.success(`Selected ${n.selectedStoryIds.length} of ${n.totalStoryIds.length} affected stories`):Q.warn(`Selected all ${n.totalStoryIds.length} stories (${n.fallbackReasons.map(e=>e.code).join(`, `)})`),Q.info(`Plan: ${r}`)}});async function Cb(e){let t;try{t=JSON.parse(await x(e,`utf8`))}catch(t){throw Error(`Failed to read changed files JSON from ${e}`,{cause:t})}if(!Array.isArray(t)){let e=Rg(t);return{files:e.files,complete:e.complete,evidence:{provider:e.source.provider,manifestDigest:ae(`sha256`).update(JSON.stringify(e)).digest(`hex`),pullRequestNumber:e.pullRequest.number,baseSha:e.pullRequest.baseSha,headSha:e.pullRequest.headSha}}}if(t.length>1e5)throw Error(`changed-files contains too many paths`);return{files:t.map(e=>zg(e,`changed file path`)),complete:!0}}O();const wb=D({meta:{name:`report`,description:`Build trusted static Kapture reports`},subCommands:{build:eg}});Td(),O();const Tb=D({meta:{name:`test`,description:`Capture and compare base/head Storybooks in one hermetic browser environment`},args:{"github-artifacts":{type:`boolean`,default:!1,description:`Validate downloaded builds, bind Actions artifact identities and preserve error reports for publication`},"base-dir":{type:`string`,required:!0,description:`Built base Storybook directory`},"head-dir":{type:`string`,required:!0,description:`Built head Storybook directory`},"base-capture-dir":{type:`string`,description:`Verified capture directory for the exact base revision; captures head only`},"base-revision":{type:`string`,required:!0,description:`Base Git revision`},"head-revision":{type:`string`,required:!0,description:`Head Git revision`},"changed-files":{type:`string`,description:`Versioned changed-files manifest used to capture only provably affected stories`},"install-browser":{type:`boolean`,default:!1,description:`Install the pinned Chrome runtime only when at least one story is selected`},"browser-with-deps":{type:`boolean`,default:!1,description:`Install Linux browser dependencies together with Chrome`},output:{type:`string`,default:`.kapture`,description:`Output directory`},workers:{type:`string`,default:`4`,description:`Concurrent isolated story lanes`},"pixel-color-threshold":{type:`string`,default:`0.2`,description:`Per-pixel perceptual color threshold`},"max-changed-pixel-percentage":{type:`string`,default:`0`,description:`Maximum percentage of changed pixels allowed without review (0 to 100)`},"frozen-time":{type:`string`,default:`2026-01-01T00:00:00.000Z`,description:`ISO time exposed to stories`},"random-seed":{type:`string`,default:`20260101`,description:`Math.random seed`},locale:{type:`string`,default:`en-US`,description:`BCP 47 browser locale`},timezone:{type:`string`,default:`UTC`,description:`IANA browser time zone`},"dashboard-dir":{type:`string`,description:`Dashboard build directory (defaults to the CLI embedded dashboard)`}},async run({args:e}){let t=Ab(e.workers),n=jb(e[`pixel-color-threshold`],`pixel-color-threshold`),r=Mb(e[`max-changed-pixel-percentage`],`max-changed-pixel-percentage`),o=kb(e[`random-seed`],`random-seed`),s=f(e[`base-dir`]),c=f(e[`head-dir`]),l=e[`github-artifacts`]?Sv(process.env):void 0;if(l){let t=`-base-${e[`base-revision`]}-head-${e[`head-revision`]}`;if(!l.artifacts.context.name.endsWith(t))throw Error(`Artifact identities must match the requested base/head revisions`);await Promise.all([s,c].map(e=>jy(a(e),i(e))))}let u=e[`changed-files`]?await Eb(s,c,f(e[`changed-files`]),e[`base-revision`],e[`head-revision`]):void 0;Ob(u),e[`install-browser`]&&Db(u)&&(Q.start(`Installing the Kapture browser runtime…`),await tt(e[`browser-with-deps`])),Q.start(e[`base-capture-dir`]?`Reusing the verified base capture and capturing affected head stories…`:`Capturing base and head Storybooks in one hermetic environment…`);let d=await bu({baseDir:s,headDir:c,...e[`base-capture-dir`]?{baseCaptureDir:f(e[`base-capture-dir`])}:{},baseRevision:e[`base-revision`],headRevision:e[`head-revision`],outputDir:f(e.output),workers:t,threshold:{pixelColorThreshold:n,maxChangedPixelRatio:r/100},frozenTime:e[`frozen-time`],randomSeed:o,locale:e.locale,timezone:e.timezone,adapterVersion:$e,selectionPlan:u});await Wu(e[`dashboard-dir`]?f(e[`dashboard-dir`]):f(a(pe(import.meta.url)),`dashboard`),f(e.output,`report`)),l&&(await ie(f(e.output,`report`,`capture-boundary.json`),`${JSON.stringify(l)}\n`,{flag:`wx`,mode:384}),await G({"report-directory":f(e.output,`report`),"report-path":f(e.output,`report`,`report.json`),"capture-errors":d.report.summary.errors}));let{summary:p}=d.report;Q.success(`${p.total} snapshots: ${p.changed} changed, ${p.unstable} unstable, ${p.added} added, ${p.removed} removed, ${p.unchanged} unchanged, ${p.errors} errors`),Q.info(`Environment: ${d.report.environment.id}`),Q.info(`Report: ${f(e.output,`report`,`report.json`)}`),p.errors>0&&!l&&(process.exitCode=2)}});async function Eb(e,t,n,r,i){let a=await Cb(n);if(a.evidence&&(a.evidence.baseSha!==r||a.evidence.headSha!==i))throw Error(`changed-files manifest base/head SHAs must match --base-revision and --head-revision`);return El({baseDir:e,headDir:t,changedFiles:a.files,changedFilesComplete:a.complete,...a.evidence?{changedFilesEvidence:a.evidence}:{}})}function Db(e){return!e||e.selectedStoryIds.length>0}function Ob(e){if(!e){Q.info(`Story coverage: full capture (no changed-files manifest)`);return}if(e.selectionMode===`affected`){Q.info(`Story coverage: ${e.selectedStoryIds.length} affected, ${e.skippedStoryIds.length} proven unaffected`);return}Q.warn(`Story coverage: full fallback (${e.fallbackReasons.map(e=>e.code).join(`, `)})`)}function kb(e,t){let n=Number.parseInt(e,10);if(!Number.isInteger(n)||n<=0)throw Error(`${t} must be a positive integer`);return n}function Ab(e){let t=kb(e,`workers`);if(t>8)throw Error(`workers must be between 1 and 8`);return t}function jb(e,t){let n=Number.parseFloat(e);if(!Number.isFinite(n)||n<0||n>1)throw Error(`${t} must be between 0 and 1`);return n}function Mb(e,t){let n=Number(e);if(!Number.isFinite(n)||n<0||n>100)throw Error(`${t} must be between 0 and 100`);return n}O(),Jh();const Nb=D({meta:{name:`validate`,description:`Validate a Kapture report as a CI gate`},args:{report:{type:`string`,required:!0,description:`Path to report.json`},"fail-on-diff":{type:`boolean`,default:!1,description:`Exit 1 when visual changes require review`}},async run({args:e}){let t=f(e.report),n=await C(t);if(!n.isFile()||n.size>10485760)throw Error(`Kapture report must be a file no larger than ${Oh} bytes`);let r=wh(JSON.parse(await x(t,`utf8`)));if(r.summary.errors>0){Q.error(`${r.summary.errors} capture or comparison error(s)`),process.exitCode=2;return}let i=r.summary.changed+r.summary.added+r.summary.removed;if(r.summary.unstable>0&&Q.warn(`${r.summary.unstable} unstable snapshot(s) are non-blocking`),i>0&&e[`fail-on-diff`]){Q.warn(`${i} visual change(s) require human approval`),process.exitCode=1;return}Q.success(i>0?`${i} visual change(s) detected`:`No visual changes`)}});O(),ob(),We(D({meta:{name:`kapture`,version:$e,description:`Hermetic Storybook visual review`},subCommands:{test:Tb,validate:Nb,browser:nt,ci:ut,plan:Sb,report:wb,github:Zy,inspect:ab,mcp:xb}}));export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaptures/cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Hermetic Storybook visual review from the command line",
5
5
  "type": "module",
6
6
  "license": "MIT",