@kitschpatrol/shared-config 8.12.0 → 8.12.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.
package/bin/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{cosmiconfig as e}from"cosmiconfig";import{TypeScriptLoader as t}from"cosmiconfig-typescript-loader";import{execa as n}from"execa";import r from"fs-extra";import i,{constants as a}from"node:fs";import{availableParallelism as o}from"node:os";import s from"node:path";import{PassThrough as c,Transform as l}from"node:stream";import{packageUp as u,packageUpSync as d}from"package-up";import f from"yargs";import{hideBin as p}from"yargs/helpers";import m from"picocolors";import{stripVTControlCharacters as h}from"node:util";import g from"@pinojs/json-colorizer";import ee from"decircular";import te from"deepmerge";import _ from"json-stringify-pretty-compact";import{findWorkspaces as v,findWorkspacesRoot as ne}from"find-workspaces";import y,{access as re}from"node:fs/promises";import{getDefaultConfigLoader as b,resolveConfigFileImports as ie}from"cspell-lib";import{fileURLToPath as x}from"node:url";import{createReaderWriter as ae}from"cspell-config-lib";import{loadFile as oe,writeFile as se}from"magicast";import{getDefaultExportOptions as ce}from"magicast/helpers";import{lint as le}from"cspell";import"deepmerge-ts";import{loadConfig as ue}from"mdat";import{globby as de}from"globby";import S,{gt as fe,minVersion as pe}from"semver";import{readWantedLockfile as me}from"@pnpm/lockfile.fs";import he from"stylelint";var ge=`8.12.0`;const _e=[`json`,`machine`,`native`],ve=_e;function ye(e){return typeof e==`string`&&_e.includes(e)}function C(){let e=process.env.KSC_FORMAT;return ye(e)?e:`native`}function be(){let{argv:e}=process;for(let[t,n]of e.entries()){let r;n===`--format`?r=e[t+1]:n.startsWith(`--format=`)&&(r=n.slice(9)),ye(r)&&(process.env.KSC_FORMAT=r)}}function xe(){let{env:e}=process;return e.NO_COLOR!==void 0&&e.NO_COLOR!==``?!1:e.FORCE_COLOR===void 0?e.TERM!==`dumb`&&void 0:e.FORCE_COLOR!==`0`&&e.FORCE_COLOR!==`false`}function w(e,{ciColor:t=!0}={}){return xe()??(e.isTTY===!0||t&&!!process.env.CI)}function Se(){return C()===`json`?process.stderr:process.stdout}function T(){return C()===`machine`?m.createColors(!1):m.createColors(w(Se()))}function Ce(e){if(!e)return{FORCE_COLOR:`0`,NO_COLOR:`1`};let t=process.env.FORCE_COLOR;return t===void 0||t===``?{FORCE_COLOR:`1`}:{}}function E(e,t){let n=s.isAbsolute(e)?e:s.resolve(t,e),r=s.relative(process.cwd(),n);return r===``?`.`:r}const we=/\s*\n\s*/gv,Te=/\r?\n/v;function Ee(e){let t=e.message.replaceAll(we,` `),n=e.rule===void 0?e.tool:`${e.tool}/${e.rule}`;return e.file===void 0?`${e.severity}: ${t} [${n}]`:`${e.file}:${e.line??1}:${e.column??1}: ${e.severity}: ${t} [${n}]`}function De(e,t){let n=(e.file??`￿`).localeCompare(t.file??`￿`);if(n!==0)return n;let r=(e.line??0)-(t.line??0);return r===0?(e.column??0)-(t.column??0):r}function Oe(e,t){let n=t.toSorted(De);return{cwd:process.cwd(),diagnostics:n,success:e.every(e=>e.exitCode===0),summary:{errors:n.filter(e=>e.severity===`error`).length,infos:n.filter(e=>e.severity===`info`).length,warnings:n.filter(e=>e.severity===`warning`).length},tools:e,version:1}}function D(e){return h(e).split(Te).map(e=>e.trimEnd()).filter(e=>e.trim().length>0)}function ke(e){return e instanceof Error&&`exitCode`in e&&typeof e.exitCode==`number`}function O(e){return w(process.stdout,{ciColor:!1})?je(e):Ae(e)}function Ae(e){return _(ee(e),{indent:2,replacer(e,t){return typeof t==`function`?t.name:t}})}function je(e){return g(Ae(e),{colors:{BRACKET:`gray`}})}const Me=(e,t,n)=>{let r=[...e];for(let[i,a]of t.entries())r[i]===void 0?r[i]=n.cloneUnlessOtherwiseSpecified(a,n):n.isMergeableObject(a)?r[i]=k(e[i],a,n):e.includes(a)||r.push(a);return r};function k(e,t,n={arrayMerge:Me}){return te(e,t,n)}function Ne(e){let{tasks:t}=e;return Array.isArray(t)?t:[]}function Pe(e,t){let n=[...Ne(e)];for(let e of Ne(t)){let t=n.findIndex(t=>t.label!==void 0&&t.label===e.label);t===-1?n.push(e):n[t]=e}return{...e,...t,tasks:n}}function Fe(e,t){return e.startsWith(t+s.sep)}function A(){let e=j(),t=/* @__PURE__ */ new Set([e]),n=v();if(n!==null)for(let r of n){let n=s.resolve(r.location);Fe(n,e)&&t.add(n)}return[...t]}function j(){let e=d();if(e===void 0)throw Error(`No package.json found.`);return s.dirname(e)}function Ie(){return ne()!==null}function M(){let e=ne();return e===null?j():s.resolve(e.location)}function Le(e){let t=s.join(M(),e);return r.existsSync(t)?t:void 0}function Re(e){if(e===`workspace-root`)return M();if(e===`package-dir`)return j();if(typeof e==`string`){if(!r.pathExistsSync(e))throw Error(`Custom cwd directory does not exist: ${e}`);return e}return process.cwd()}async function ze(e,t){try{let{default:n}=await import(`prettier`),r=await n.resolveConfig(e),i=await n.format(t,{filepath:e,...r});await y.writeFile(e,i,`utf8`)}catch{console.warn(`Skipped formatting ${e} since Prettier is not installed.`)}}async function N(e){try{await ze(e,await y.readFile(e,`utf8`))}catch{}}const Be=/\r?\n/v;function Ve(e){let t=``,n=t=>t.filter(t=>{let n=h(t);return n.trim()!==``&&!e(n)}).map(e=>`${e}\n`).join(``);return new l({flush(e){e(void 0,n([t]))},transform(e,r,i){let a=(t+e.toString()).split(Be);t=a.pop()??``,i(void 0,n(a))}})}function P(e,t){let n=C()===`native`?e:void 0,r=n===void 0||n===``?``:t===void 0?n:T()[t](n),i=``,a=e=>e.filter(e=>e.trim().length>0).map(e=>r===``?`${e}\n`:`${r} ${e}\n`).join(``);return new l({flush(e){e(void 0,a([i]))},transform(e,t,n){let r=(i+e.toString()).split(Be);i=r.pop()??``,n(void 0,a(r))}})}async function He(e){let t=[];return new Promise((n,r)=>{e.on(`data`,e=>{t.push(e)}),e.on(`error`,e=>{r(e)}),e.on(`end`,()=>{n(Buffer.concat(t).toString(`utf8`))})})}function Ue(e){return e.replaceAll(/[A-Z\u{C0}-\u{D6}\u{D8}-\u{DE}]/gv,e=>`-`+e.toLowerCase())}function F(e,t){return t===1?e:e+`s`}async function I(e){return typeof e==`function`?e():e}async function We(e,t,n,r,i){let a;if(r.logPrefix===void 0)a=e;else{let t=P(r.logPrefix,r.logColor);t.pipe(e),a=t}i&&a.write(T().bold(`Running: "${r.name}() with Positional arguments: ${String(t)} and Option flags: ${String(n)}"`)+`
2
+ import{cosmiconfig as e}from"cosmiconfig";import{TypeScriptLoader as t}from"cosmiconfig-typescript-loader";import{execa as n}from"execa";import r from"fs-extra";import i,{constants as a}from"node:fs";import{availableParallelism as o}from"node:os";import s from"node:path";import{PassThrough as c,Transform as l}from"node:stream";import{packageUp as u,packageUpSync as d}from"package-up";import f from"yargs";import{hideBin as p}from"yargs/helpers";import m from"picocolors";import{stripVTControlCharacters as h}from"node:util";import g from"@pinojs/json-colorizer";import ee from"decircular";import te from"deepmerge";import _ from"json-stringify-pretty-compact";import{findWorkspaces as v,findWorkspacesRoot as ne}from"find-workspaces";import y,{access as re}from"node:fs/promises";import{getDefaultConfigLoader as b,resolveConfigFileImports as ie}from"cspell-lib";import{fileURLToPath as x}from"node:url";import{createReaderWriter as ae}from"cspell-config-lib";import{loadFile as oe,writeFile as se}from"magicast";import{getDefaultExportOptions as ce}from"magicast/helpers";import{lint as le}from"cspell";import"deepmerge-ts";import{loadConfig as ue}from"mdat";import{globby as de}from"globby";import S,{gt as fe,minVersion as pe}from"semver";import{readWantedLockfile as me}from"@pnpm/lockfile.fs";import he from"stylelint";var ge=`8.12.1`;const _e=[`json`,`machine`,`native`],ve=_e;function ye(e){return typeof e==`string`&&_e.includes(e)}function C(){let e=process.env.KSC_FORMAT;return ye(e)?e:`native`}function be(){let{argv:e}=process;for(let[t,n]of e.entries()){let r;n===`--format`?r=e[t+1]:n.startsWith(`--format=`)&&(r=n.slice(9)),ye(r)&&(process.env.KSC_FORMAT=r)}}function xe(){let{env:e}=process;return e.NO_COLOR!==void 0&&e.NO_COLOR!==``?!1:e.FORCE_COLOR===void 0?e.TERM!==`dumb`&&void 0:e.FORCE_COLOR!==`0`&&e.FORCE_COLOR!==`false`}function w(e,{ciColor:t=!0}={}){return xe()??(e.isTTY===!0||t&&!!process.env.CI)}function Se(){return C()===`json`?process.stderr:process.stdout}function T(){return C()===`machine`?m.createColors(!1):m.createColors(w(Se()))}function Ce(e){if(!e)return{FORCE_COLOR:`0`,NO_COLOR:`1`};let t=process.env.FORCE_COLOR;return t===void 0||t===``?{FORCE_COLOR:`1`}:{}}function E(e,t){let n=s.isAbsolute(e)?e:s.resolve(t,e),r=s.relative(process.cwd(),n);return r===``?`.`:r}const we=/\s*\n\s*/gv,Te=/\r?\n/v;function Ee(e){let t=e.message.replaceAll(we,` `),n=e.rule===void 0?e.tool:`${e.tool}/${e.rule}`;return e.file===void 0?`${e.severity}: ${t} [${n}]`:`${e.file}:${e.line??1}:${e.column??1}: ${e.severity}: ${t} [${n}]`}function De(e,t){let n=(e.file??`￿`).localeCompare(t.file??`￿`);if(n!==0)return n;let r=(e.line??0)-(t.line??0);return r===0?(e.column??0)-(t.column??0):r}function Oe(e,t){let n=t.toSorted(De);return{cwd:process.cwd(),diagnostics:n,success:e.every(e=>e.exitCode===0),summary:{errors:n.filter(e=>e.severity===`error`).length,infos:n.filter(e=>e.severity===`info`).length,warnings:n.filter(e=>e.severity===`warning`).length},tools:e,version:1}}function D(e){return h(e).split(Te).map(e=>e.trimEnd()).filter(e=>e.trim().length>0)}function ke(e){return e instanceof Error&&`exitCode`in e&&typeof e.exitCode==`number`}function O(e){return w(process.stdout,{ciColor:!1})?je(e):Ae(e)}function Ae(e){return _(ee(e),{indent:2,replacer(e,t){return typeof t==`function`?t.name:t}})}function je(e){return g(Ae(e),{colors:{BRACKET:`gray`}})}const Me=(e,t,n)=>{let r=[...e];for(let[i,a]of t.entries())r[i]===void 0?r[i]=n.cloneUnlessOtherwiseSpecified(a,n):n.isMergeableObject(a)?r[i]=k(e[i],a,n):e.includes(a)||r.push(a);return r};function k(e,t,n={arrayMerge:Me}){return te(e,t,n)}function Ne(e){let{tasks:t}=e;return Array.isArray(t)?t:[]}function Pe(e,t){let n=[...Ne(e)];for(let e of Ne(t)){let t=n.findIndex(t=>t.label!==void 0&&t.label===e.label);t===-1?n.push(e):n[t]=e}return{...e,...t,tasks:n}}function Fe(e,t){return e.startsWith(t+s.sep)}function A(){let e=j(),t=/* @__PURE__ */ new Set([e]),n=v();if(n!==null)for(let r of n){let n=s.resolve(r.location);Fe(n,e)&&t.add(n)}return[...t]}function j(){let e=d();if(e===void 0)throw Error(`No package.json found.`);return s.dirname(e)}function Ie(){return ne()!==null}function M(){let e=ne();return e===null?j():s.resolve(e.location)}function Le(e){let t=s.join(M(),e);return r.existsSync(t)?t:void 0}function Re(e){if(e===`workspace-root`)return M();if(e===`package-dir`)return j();if(typeof e==`string`){if(!r.pathExistsSync(e))throw Error(`Custom cwd directory does not exist: ${e}`);return e}return process.cwd()}async function ze(e,t){try{let{default:n}=await import(`prettier`),r=await n.resolveConfig(e),i=await n.format(t,{filepath:e,...r});await y.writeFile(e,i,`utf8`)}catch{console.warn(`Skipped formatting ${e} since Prettier is not installed.`)}}async function N(e){try{await ze(e,await y.readFile(e,`utf8`))}catch{}}const Be=/\r?\n/v;function Ve(e){let t=``,n=t=>t.filter(t=>{let n=h(t);return n.trim()!==``&&!e(n)}).map(e=>`${e}\n`).join(``);return new l({flush(e){e(void 0,n([t]))},transform(e,r,i){let a=(t+e.toString()).split(Be);t=a.pop()??``,i(void 0,n(a))}})}function P(e,t){let n=C()===`native`?e:void 0,r=n===void 0||n===``?``:t===void 0?n:T()[t](n),i=``,a=e=>e.filter(e=>e.trim().length>0).map(e=>r===``?`${e}\n`:`${r} ${e}\n`).join(``);return new l({flush(e){e(void 0,a([i]))},transform(e,t,n){let r=(i+e.toString()).split(Be);i=r.pop()??``,n(void 0,a(r))}})}async function He(e){let t=[];return new Promise((n,r)=>{e.on(`data`,e=>{t.push(e)}),e.on(`error`,e=>{r(e)}),e.on(`end`,()=>{n(Buffer.concat(t).toString(`utf8`))})})}function Ue(e){return e.replaceAll(/[A-Z\u{C0}-\u{D6}\u{D8}-\u{DE}]/gv,e=>`-`+e.toLowerCase())}function F(e,t){return t===1?e:e+`s`}async function I(e){return typeof e==`function`?e():e}async function We(e,t,n,r,i){let a;if(r.logPrefix===void 0)a=e;else{let t=P(r.logPrefix,r.logColor);t.pipe(e),a=t}i&&a.write(T().bold(`Running: "${r.name}() with Positional arguments: ${String(t)} and Option flags: ${String(n)}"`)+`
3
3
  `);try{return await r.execute(a,t,n)}catch(e){return console.error(String(e)),1}}function Ge(e,t,n,r,i){return[...e.subcommands??[],...e.receiveOptionFlags?n:[],...r??[],...i&&e.cache!==void 0?[...e.cache.flags,`--cache-location`,s.join(M(),`node_modules`,`.cache`,`ksc`,e.cache.name)]:[],...e.receivePositionalArguments?t:[],...e.positionalArguments??[]]}async function Ke(e,t,r,i,a,o){let s=1,l;if(i.logPrefix===void 0)l=e;else{let t=P(i.logPrefix,i.logColor);t.pipe(e),l=t}let u=Ge(i,t,r,i.optionFlags,a),d=Re(i.cwdOverride);o&&l.write(`Running: "${i.name} ${u.join(` `)}"\n`);let f=i.prettyJsonOutput?new c:void 0,p=f??l,m=Ce(C()===`native`&&i.prettyJsonOutput!==!0&&w(Se()));try{let e=n(i.name,u,{cwd:d,env:m,preferLocal:!0,reject:!1,stdin:`inherit`});if(i.outputFilter){let t=Ve(i.outputFilter),n=Ve(i.outputFilter);e.stdout.pipe(t).pipe(p,{end:!1}),e.stderr.pipe(n).pipe(p,{end:!1})}else e.stdout.pipe(p,{end:!1}),e.stderr.pipe(p,{end:!1});let t=await e;if(f!==void 0){f.end();let e=await He(f),t=O(JSON.parse(e)).split(`
4
4
  `);for(let e of t)l.write(`${e}\n`)}s=t.exitCode??1}catch(e){console.error(`${i.name} failed with error:`),console.error(e),ke(e)&&(s=typeof e.exitCode==`number`?e.exitCode:1)}return s}function L(e){return`execute`in e}function R(e){return`kind`in e}async function qe(e,t,r,i,a){let o=Ge(r,e,t,r.collect?.optionFlags??r.optionFlags,i),s=Re(r.cwdOverride);try{let e=n(r.name,o,{cwd:s,env:Ce(!1),preferLocal:!0,reject:!1,stdin:`inherit`});a!==void 0&&e.stderr.pipe(a,{end:!1});let t=await e;return{cwd:s,exitCode:t.exitCode??1,stderr:t.stderr,stdout:t.stdout}}catch(e){return console.error(`${r.name} failed with error:`),console.error(e),{cwd:s,exitCode:ke(e)&&typeof e.exitCode==`number`?e.exitCode:1,stderr:``,stdout:``}}}function Je(e){return typeof e==`object`&&!!e&&`version`in e&&e.version===1&&`diagnostics`in e&&Array.isArray(e.diagnostics)&&`success`in e&&typeof e.success==`boolean`&&`tools`in e&&Array.isArray(e.tools)}function Ye(e,t){return e===0&&t.some(({severity:e})=>e===`error`)?1:e}async function Xe(e,t,n,r,i){let a=Date.now(),o=()=>Date.now()-a;if(L(r)){if(r.collect!==void 0)try{let e=await r.collect(t,n),i=Ye(e.exitCode,e.diagnostics);return{diagnostics:e.diagnostics,exitCode:i,tools:[{durationMs:o(),exitCode:i,name:r.name,unparsed:e.unparsed}]}}catch(e){return{diagnostics:[],exitCode:1,tools:[{durationMs:o(),exitCode:1,name:r.name,unparsed:[String(e)]}]}}let e=``,i=new c;i.on(`data`,t=>{e+=t.toString()});let a;try{a=await r.execute(i,t,n)}catch(t){e+=`\n${String(t)}`,a=1}return{diagnostics:[],exitCode:a,tools:[{durationMs:o(),exitCode:a,name:r.name,unparsed:D(e)}]}}if(R(r))throw Error(`Command groups must be expanded before collection`);if(r.outputFormatAware){let a=await qe(t,n,r,i,e);try{let e=JSON.parse(a.stdout);if(!Je(e))throw Error(`Child output is not a lint report`);return{diagnostics:e.diagnostics,exitCode:a.exitCode===0&&e.success&&e.diagnostics.every(({severity:e})=>e!==`error`)?0:1,tools:e.tools}}catch{return{diagnostics:[],exitCode:a.exitCode,tools:[{durationMs:o(),exitCode:a.exitCode,name:r.name,unparsed:D(a.stdout)}]}}}let s=await qe(t,n,r,i);if(r.collect!==void 0)try{let{diagnostics:e,unparsed:t}=r.collect.parse(s),n=Ye(s.exitCode,e);return{diagnostics:e,exitCode:n,tools:[{durationMs:o(),exitCode:n,name:r.name,unparsed:t}]}}catch(e){return{diagnostics:[],exitCode:s.exitCode,tools:[{durationMs:o(),exitCode:s.exitCode,name:r.name,unparsed:[...D(s.stdout),...D(s.stderr),String(e)]}]}}return{diagnostics:[],exitCode:s.exitCode,tools:[{durationMs:o(),exitCode:s.exitCode,name:r.name,unparsed:[...D(s.stdout),...D(s.stderr)]}]}}const Ze=/^ksc-/v;function z(e){return e.replace(Ze,``)}function B(e){return e===void 0||e.length===0?[]:e.flatMap(e=>e.split(`,`)).map(e=>z(e.trim()))}function V(e){return e.option(`skip`,{array:!0,describe:`Tool names to skip (with or without "ksc-" prefix).`,type:`string`})}function Qe(e){return e.option(`format`,{choices:ve,default:`native`,describe:`Output format: "native" streams each tool's own output, "machine" prints one parseable line per issue for editor problem matchers, "json" prints an aggregate report.`})}function $e(e){return e.option(`cache`,{boolean:!0,default:!0,describe:`Use tool-native caches stored below node_modules/.cache/ksc at the workspace root. Disable with --no-cache.`})}function et(e,t){return t===`native`||t===`machine`&&!L(e)&&!R(e)&&e.outputFormatAware===!0}function tt(e,t){for(let n of t.diagnostics)e.write(`${Ee(n)}\n`);for(let n of t.tools)for(let t of n.unparsed)e.write(`${t}\n`)}function nt(){return Math.min(4,o())}var rt=class{concurrency;active=0;queue=[];constructor(e){this.concurrency=e}async run(e){this.active>=this.concurrency&&await new Promise(e=>{this.queue.push(e)}),this.active+=1;try{return await e()}finally{--this.active,this.queue.shift()?.()}}};async function it(e){let t=e.cache??!1,n=e.concurrency??nt();if(!Number.isInteger(n)||n<1)throw Error(`Concurrency must be a positive integer.`);return t&&await r.ensureDir(s.join(M(),`node_modules`,`.cache`,`ksc`)),{cache:t,scheduler:new rt(n)}}const at=/[*?\[\]\{\}]/v;function H(e,t){return t===void 0?e:e.filter(e=>at.test(e)||i.statSync(e,{throwIfNoEntry:!1})?.isDirectory()===!0||t.includes(s.extname(e).slice(1).toLowerCase()))}function ot(e,t){return e.length===0||H(e,t).length>0}function st(e,t){return e.positionalArgumentMode===`none`?[]:t.length>0?H(t,e.positionalArgumentExtensions):e.positionalArgumentDefault===void 0?[]:[e.positionalArgumentDefault]}function ct(e,t){if(t.logPrefix===void 0)return e;let n=P(t.logPrefix,t.logColor);return n.pipe(e),n}function lt(e){return R(e)?`${e.name} ${e.subcommand}`:!L(e)&&e.subcommands!==void 0?[e.name,...e.subcommands].join(` `):e.name}async function ut(e,t){if(R(e)){let n=ct(t.logStream,e);try{let r=await I(e.commands);if(t.nativeVerbose){let n=[e.subcommand,...t.positionalArguments].join(` `),i=e.showResolvedCommands?` (${r.map(e=>lt(e)).join(`, `)})`:``;t.logStream.write(`Running: "${e.name} ${n}"${i}\n`)}let i=await dt(r,{...t,logStream:n,nativeVerbose:e.verbose,positionalArguments:st(e,t.positionalArguments)},e.parallel===!0);return{diagnostics:i.flatMap(({diagnostics:e})=>e),exitCode:+!i.every(({exitCode:e})=>e===0),machineOutcomes:i.flatMap(({machineOutcomes:e})=>e),name:e.name,tools:i.flatMap(({tools:e})=>e)}}catch(r){let i=String(r),a={durationMs:0,exitCode:1,name:e.name,unparsed:[i]};return t.format===`native`&&n.write(`${i}\n`),{diagnostics:[],exitCode:1,machineOutcomes:[{diagnostics:[],exitCode:1,tools:[a]}],name:e.name,tools:[a]}}}return t.scheduler.run(async()=>{if(et(e,t.format))return{diagnostics:[],exitCode:await(L(e)?We(t.logStream,t.positionalArguments,t.optionFlags,e,t.nativeVerbose):Ke(t.logStream,t.positionalArguments,t.optionFlags,e,t.cache,t.nativeVerbose)),machineOutcomes:[],name:e.name,tools:[]};let n=await Xe(t.logStream,t.positionalArguments,t.optionFlags,e,t.cache);return{diagnostics:n.diagnostics,exitCode:n.exitCode,machineOutcomes:[n],name:e.name,tools:n.tools}})}async function dt(e,t,n){if(!n||t.scheduler.concurrency===1){let n=[];for(let r of e)n.push(await ut(r,t));return n}await Promise.resolve();let r=/* @__PURE__ */ new Map;for(let[t,n]of e.entries()){let e=n.stage??0,i=r.get(e)??[];i.push({command:n,index:t}),r.set(e,i)}let i=Array.from({length:e.length}),a=r.keys().toArray().toSorted((e,t)=>e-t);for(let e of a){let n=r.get(e)??[],a=await Promise.all(n.map(async({command:e,index:n})=>({index:n,outcome:await ut(e,t)})));for(let{index:e,outcome:t}of a)i[e]=t}return i.filter(e=>e!==void 0)}function ft(e,t,n,r,i){let a=[],o=[],s=ot(r,i);for(let e of t){let t=!R(e)||ot(r,e.positionalArgumentExtensions);!s||!t||n.includes(z(e.name))?o.push(e):a.push(e)}if(n.length>0){let r=new Set(o.map(e=>z(e.name))),i=n.filter(e=>!r.has(e));if(i.length>0){let n=t.map(e=>z(e.name)).join(`, `);e.write(`⚠️ ${T().yellow(`Unrecognized --skip ${F(`value`,i.length)}: ${i.join(`, `)}. Available: ${n}`)}\n`)}}return{commandsToRun:a,skippedCommands:o}}async function U(e,t,n,r,i,a,o,s=`native`){let c=typeof s==`string`?{}:s,l=typeof s==`string`?s:c.format??`native`,{commandsToRun:u,skippedCommands:d}=ft(e,r,o??[],t,c.positionalArgumentExtensions),f=l===`native`&&i,{cache:p,scheduler:m}=await it(c),h=await dt(u,{cache:p,format:l,logStream:e,nativeVerbose:f,optionFlags:n,positionalArguments:H(t,c.positionalArgumentExtensions),scheduler:m},c.parallel===!0),g=h.map(({exitCode:e,name:t})=>({exitCode:e,name:t})),ee=h.flatMap(({tools:e})=>e),te=h.flatMap(({diagnostics:e})=>e);if(l===`machine`)for(let t of h)for(let n of t.machineOutcomes)tt(e,n);let _=r.length,v=T();if(l===`native`&&d.length>0){let t=d.map(({name:e})=>e),n=v.bold(`${t.length} / ${_} ${F(`Command`,t.length)} Skipped:`);e.write(`⏭️ ${v.dim(n)} ${v.dim(t.join(`, `))}\n`)}if(l===`native`&&a){let t=g.filter(({exitCode:e})=>e===0).map(({name:e})=>e),n=g.filter(({exitCode:e})=>e!==0).map(({name:e})=>e);if(t.length>0){let n=v.bold(`${t.length} / ${_} ${F(`Command`,t.length)} Succeeded:`);e.write(`✅ ${v.green(n)} ${v.green(t.join(`, `))}\n`)}if(n.length>0){let t=v.bold(`${n.length} / ${_} ${F(`Command`,n.length)} Failed:`);e.write(`❌ ${v.red(t)} ${v.red(n.join(`, `))}\n`)}}return{exitCode:+!g.every(({exitCode:e})=>e===0),report:l===`json`?Oe(ee,te):void 0}}async function pt(e){let t=await u({cwd:e});return t===void 0?void 0:s.join(s.dirname(t),`init`)}async function mt(e,t,n,a){let o=await u();if(o===void 0)throw Error("The `init` command must be used in a directory with a package.json file");let c=await pt(import.meta.dirname);if(c===void 0)return e.write(`Error: Could not locate the package containing this CLI.
5
5
  `),1;let l=s.dirname(o),d=(t===`file`||t===`package`)&&n!==void 0&&a!==void 0;try{if(d){let n=Object.keys(a)[0],i=r.readJsonSync(o);if(t===`package`){e.write(`Merging: \nPackage config key "${n}" → "${l}" (Because --location is set to "package")\n`);let t=k(i,a);r.writeJSONSync(o,t,{spaces:` `}),await N(o)}else n!==void 0&&Object.keys(i).includes(n)&&(e.write(`Deleting: \nPackage config key "${n}" in "${l}" (Because --location is set to "file")\n`),delete i[n],r.writeJSONSync(o,i,{spaces:` `}),await N(o))}if(!await r.pathExists(c))return 0;if((await r.readdir(c)).length===0)return e.write(`Source directory "${c}" is empty.\n`),0;e.write(`Adding initial configuration files from:\n"${c}" → "${l}"\n`),await r.copy(c,l,{async filter(a,o){let c=i.statSync(a).isFile(),l=i.existsSync(o);if(c){if(d&&t===`package`&&a.includes(n))return l?(e.write(`Deleting: \n"${a}" → "${o}" (Because --location is set to "package")\n`),r.removeSync(o)):e.write(`Skipping: \n"${a}" → "${o}" (Because --location is set to "package")\n`),!1;if(l&&(o.includes(`.vscode/`)||o.includes(`package.json`))&&s.extname(o)===`.json`){e.write(`Merging: \n"${a}" → "${o}"\n`);let t=r.readJSONSync(a),n=r.readJSONSync(o),i=o.endsWith(`.vscode/tasks.json`)?Pe(n,t):k(n,t);return r.writeJSONSync(o,i,{spaces:` `}),await N(o),!1}return l?(e.write(`Overwriting: \n"${a}" → "${o}"\n`),await N(o),!0):(e.write(`Copying: \n"${a}" → "${o}"\n`),await N(o),!0)}return!0},overwrite:!0})}catch(e){return console.error(String(e)),1}return 0}async function ht(e){let{commands:{fix:t,init:n,lint:r,printConfig:i},description:a,logColor:o,logPrefix:s,name:c,showSummary:l,verbose:u}=e;be();let d=P(s,o);d.pipe(Se());let m=f(p(process.argv)).scriptName(c).usage(`$0 <command>`,a);n!==void 0&&m.command({builder(e){let t=n.locationOptionFlag?e.option(`location`,{choices:[`file`,`package`],default:`file`,describe:`Where to store the configuration.`,type:`string`}):e;return l?V(t):t},command:`init`,describe:n.description??`Initialize by copying starter config files to your project root${n.locationOptionFlag?` or to your package.json file.`:`.`}`,async handler(e){let t=n.locationOptionFlag?e.location:void 0,r=B(e.skip),{exitCode:i}=await U(d,[],t===void 0?[]:[`--location`,t],[{async execute(e,t,r){return mt(e,r.at(1),n.configFile,n.configPackageJson)},name:`copyAndMergeInitFiles`},...n.commands??[]],void 0,void 0,r);process.exitCode=i}}),r!==void 0&&m.command({builder(e){let t=$e(Qe(r.positionalArgumentMode===`none`?e:e.positional(`files`,{array:!0,...r.positionalArgumentDefault!==void 0&&{default:r.positionalArgumentDefault},describe:`Files or glob pattern to lint.`,type:`string`})));return l?V(t):t},command:r.positionalArgumentMode===`none`?`lint`:r.positionalArgumentMode===`optional`?`lint [files..]`:`lint <files..>`,describe:r.description,async handler(e){let t=e.files??[],n=B(e.skip),i=C(),{exitCode:a,report:o}=await U(d,t,[],await I(r.commands),u,l,n,{cache:e.cache,format:i,parallel:r.parallel,positionalArgumentExtensions:r.positionalArgumentExtensions});o!==void 0&&process.stdout.write(`${O(o)}\n`),process.exitCode=a}}),t!==void 0&&m.command({builder(e){let n=$e(Qe(t.positionalArgumentMode===`none`?e:e.positional(`files`,{array:!0,...t.positionalArgumentDefault!==void 0&&{default:t.positionalArgumentDefault},describe:`Files or glob pattern to fix.`,type:`string`})));return l?V(n):n},command:t.positionalArgumentMode===`none`?`fix`:t.positionalArgumentMode===`optional`?`fix [files..]`:`fix <files..>`,describe:t.description,async handler(e){let n=e.files??[],r=B(e.skip),i=C(),{exitCode:a,report:o}=await U(d,n,[],await I(t.commands),void 0,void 0,r,{cache:e.cache,format:i,parallel:t.parallel,positionalArgumentExtensions:t.positionalArgumentExtensions});o!==void 0&&process.stdout.write(`${O(o)}\n`),process.exitCode=a}}),i!==void 0&&m.command({builder(e){let t=i.positionalArgumentMode===`none`?e:e.positional(`file`,{...i.positionalArgumentDefault!==void 0&&{default:i.positionalArgumentDefault},describe:`File or glob pattern to print configuration for.`,type:`string`});return l?V(t):t},command:i.positionalArgumentMode===`none`?`print-config`:i.positionalArgumentMode===`optional`?`print-config [file]`:`print-config <file>`,describe:i.description,async handler(e){let t=e.file??void 0,n=t===void 0?[]:[t],r=B(e.skip),{exitCode:a}=await U(d,n,[],await I(i.commands),u,l,r);process.exitCode=a}}),m.alias(`h`,`help`),m.version(ge),m.alias(`v`,`version`),m.help(),m.wrap(process.stdout.isTTY?Math.min(120,m.terminalWidth()):0),await m.parseAsync()}function W(e){return{async execute(t){let n=await G(e);if(n===void 0)return 1;let{config:r,filepath:i,isEmpty:a}=n;if(t.write(`Found ${e} configuration at "${i}"\n`),a)return t.write(`Configuration is empty.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitschpatrol/shared-config",
3
- "version": "8.12.0",
3
+ "version": "8.12.1",
4
4
  "description": "A collection of shared configurations, linters, and formatting tools for TypeScript projects. All managed as a single dependency. All invoked via a single CLI command.",
5
5
  "keywords": [
6
6
  "shared-config",
@@ -54,15 +54,15 @@
54
54
  "skills/*"
55
55
  ],
56
56
  "dependencies": {
57
- "@kitschpatrol/cspell-config": "8.12.0",
58
- "@kitschpatrol/eslint-config": "8.12.0",
59
- "@kitschpatrol/knip-config": "8.12.0",
60
- "@kitschpatrol/mdat-config": "8.12.0",
61
- "@kitschpatrol/prettier-config": "8.12.0",
62
- "@kitschpatrol/remark-config": "8.12.0",
63
- "@kitschpatrol/repo-config": "8.12.0",
64
- "@kitschpatrol/stylelint-config": "8.12.0",
65
- "@kitschpatrol/typescript-config": "8.12.0",
57
+ "@kitschpatrol/cspell-config": "8.12.1",
58
+ "@kitschpatrol/eslint-config": "8.12.1",
59
+ "@kitschpatrol/knip-config": "8.12.1",
60
+ "@kitschpatrol/mdat-config": "8.12.1",
61
+ "@kitschpatrol/prettier-config": "8.12.1",
62
+ "@kitschpatrol/remark-config": "8.12.1",
63
+ "@kitschpatrol/repo-config": "8.12.1",
64
+ "@kitschpatrol/stylelint-config": "8.12.1",
65
+ "@kitschpatrol/typescript-config": "8.12.1",
66
66
  "@pinojs/json-colorizer": "^4.0.0",
67
67
  "@pnpm/lockfile.fs": "^1100.2.12",
68
68
  "cosmiconfig": "^10.0.1",
@@ -44,11 +44,13 @@ instruction below to ask, confirm, or await a decision:
44
44
  including explicit approval for runtime-range restrictions and Node-types
45
45
  changes, still apply.
46
46
  - **Other decisions and missing prerequisites:** without prior authorization,
47
- leave approval-dependent changes unapplied, including range restrictions and
48
- peer-warning suppressions. Report missing consumer information, credentials,
49
- permissions, or validation resources instead of requesting them. Continue
50
- independent work; if a required prerequisite prevents progress, report the
51
- affected work as blocked or incomplete without waiting or bypassing it.
47
+ leave approval-dependent changes unapplied, including range restrictions.
48
+ Scoped peer-warning suppressions with verified compatibility (step 5) are not
49
+ approval-dependent: apply them and report them. Report missing consumer
50
+ information, credentials, permissions, or validation resources instead of
51
+ requesting them. Continue independent work; if a required prerequisite
52
+ prevents progress, report the affected work as blocked or incomplete without
53
+ waiting or bypassing it.
52
54
 
53
55
  Review and validation remain required in both modes. Defer candidates whose
54
56
  impact cannot be established or whose migration cannot be validated. If safe
@@ -83,12 +85,17 @@ nothing can be applied, produce the report without manufacturing a change.
83
85
  apply.
84
86
  - **Release maturity:** third-party releases must be at least 24 hours old
85
87
  (`--maturity-period 1` for Taze, `--min-age 1` for Actions Up, pnpm
86
- `minimumReleaseAge` of 1440 minutes). Never disable installation safeguards to
87
- make an update succeed.
88
+ `minimumReleaseAge` of 1440 minutes). The period governs which releases a run
89
+ may introduce; it never requires downgrading a version that was locked before
90
+ the run. Never disable installation safeguards to make an update succeed.
88
91
  - **Authored packages:** packages owned by `kitschpatrol` (discovered at runtime
89
92
  in Setup) are exempt from maturity and target their latest stable release,
90
- including majors. The exemption does not bypass security or compatibility
91
- review.
93
+ including majors. pnpm enforces `minimumReleaseAge` silently by selecting the
94
+ newest mature version, so the exemption is only real while a
95
+ `minimumReleaseAgeExclude` entry for the young release exists: add it when
96
+ needed (step 5) and keep it through cleanup (step 6). The maturity period
97
+ must never hold an authored package back or downgrade it. The exemption does
98
+ not bypass security or compatibility review.
92
99
  - **Consumer ranges:** review the newest published version allowed by each
93
100
  runtime dependency's declared range, as well as the lockfile. A fresh consumer
94
101
  install can resolve that version even when CI locks an older one. Holding
@@ -113,8 +120,8 @@ nothing can be applied, produce the report without manufacturing a change.
113
120
  exception.
114
121
  - **No new noise:** every check is compared against the Setup baseline. A new
115
122
  warning, deprecation, or peer issue is a finding to trace and report, not
116
- background noise. Report compatibility-preserving lint disables from step 5;
117
- ask before silencing other findings.
123
+ background noise. Report compatibility-preserving lint disables and scoped
124
+ peer-warning entries from step 5; ask before silencing other findings.
118
125
 
119
126
  ## Environment
120
127
 
@@ -178,24 +185,37 @@ Under Claude Code's sandbox:
178
185
  separately in any independent package root. Check Taze config for anything
179
186
  that overrides mode, adds maturity exemptions, or auto-writes/installs.
180
187
  Record current project and published package versions to determine where the
181
- zero-versioned exception applies.
188
+ zero-versioned exception applies. Record every existing
189
+ `minimumReleaseAgeExclude` entry with the publish time of that exact version
190
+ (`time` in the registry metadata), so step 6 can tell which entries still
191
+ matter.
182
192
  Create the baseline folder and preserve the starting manifests and lockfile
183
193
  before the package-manager sync or any other edit.
184
- 3. Sync `packageManager` before installs and parsed pnpm output. Read the actual
185
- installed pnpm from an empty directory so the project's stale pin cannot
186
- select or download another version:
187
-
188
- ```bash
189
- pnpm --version
190
- ```
191
-
192
- Run that command with a new empty directory under `${TMPDIR:-/tmp}` as its
193
- working directory. Then edit only the workspace root's `packageManager`
194
- directly to `pnpm@<observed-version>`, preserving all other manifest fields.
195
- Use the editor or a structured JSON edit, not `pnpm pkg set`; use direct
196
- edits for later specifiers and engines too. pnpm commands can trigger
197
- version-manager downloads after the pin changes. If this crosses a pnpm
198
- major, report it and verify the CI installer supports the selected version.
194
+ 3. Sync `packageManager` before installs and parsed pnpm output. Choose the
195
+ newest of three versions, so the pin only ever moves up:
196
+
197
+ - the current `packageManager` pin;
198
+ - the pnpm installed on this host, read from a new empty directory under
199
+ `${TMPDIR:-/tmp}` so the project's stale pin cannot select or download
200
+ another version:
201
+
202
+ ```bash
203
+ pnpm --version
204
+ ```
205
+
206
+ - the newest stable pnpm release at least 24 hours old, from `versions` and
207
+ `time` in `https://registry.npmjs.org/pnpm` (`dist-tags.latest` when it
208
+ qualifies).
209
+
210
+ A CI runner usually installs the pinned version itself, so the installed
211
+ pnpm alone never moves the pin; the registry lookup is what keeps it
212
+ current. Then edit only the workspace root's `packageManager` directly to
213
+ `pnpm@<chosen-version>`, preserving all other manifest fields. Use the
214
+ editor or a structured JSON edit, not `pnpm pkg set`; use direct edits for
215
+ later specifiers and engines too. pnpm downloads and runs the pinned
216
+ version on demand after the pin changes. If this crosses a pnpm major,
217
+ report it, review the pnpm release notes for lockfile and settings changes,
218
+ and verify the CI installer supports the selected version.
199
219
 
200
220
  4. Install the starting dependency declarations and record a baseline before
201
221
  dependency updates. Keep the original files saved in Setup 2 even if
@@ -478,8 +498,13 @@ production changes fully and development-only transitives under step 3's
478
498
  narrower checks. If a deferred version is still allowed by a published runtime
479
499
  range, use the explicit range/consumer decision path rather than fighting the
480
500
  resolver with an older lockfile or an unapproved override.
481
- If an authored release is blocked by `minimumReleaseAge`, add only that
482
- package/version to `minimumReleaseAgeExclude`; never its dependencies.
501
+ After every `pnpm update -r`, confirm each accepted authored package resolved
502
+ to its accepted version. pnpm does not report a maturity holdback, so a lower
503
+ resolved version means the release is blocked by `minimumReleaseAge`: add only
504
+ that package/version to `minimumReleaseAgeExclude`, never its dependencies,
505
+ and update again. If the release still cannot resolve because its own
506
+ third-party dependencies are too young, defer that authored update, keep the
507
+ previously locked version, and report the date it becomes installable.
483
508
 
484
509
  Compare every result with the baseline:
485
510
 
@@ -499,12 +524,16 @@ Compare every result with the baseline:
499
524
  - **Logs:** for each new warning, deprecation, or peer issue, find the package
500
525
  that introduced it (`pnpm why`) and search upstream for a known issue. Report
501
526
  it with the link. For a peer declaration lagging a verified compatible
502
- version, offer a scoped `peerDependencyRules.allowedVersions` entry such as
503
- `"parent@range>peer": "tested-range"` in `pnpm-workspace.yaml`, explaining
504
- that it suppresses a warning rather than fixing incompatibility. Show the
505
- exact entry and evidence, and ask before applying unless already authorized.
506
- Do not use broad `allowAny` or disable strict peer checks. Revisit such
507
- workarounds during step 8.
527
+ version, add a scoped `peerDependencyRules.allowedVersions` entry such as
528
+ `"parent@range>peer": "tested-range"` to `pnpm-workspace.yaml` in both modes,
529
+ and report the entry, the evidence, and that it suppresses a warning rather
530
+ than fixing incompatibility. Compatibility is verified when the checks pass
531
+ with the installed combination and no upstream report contradicts it. Apply
532
+ the entry even when the lagging declaration arrives through an authored
533
+ package: the consumer's `pnpm-workspace.yaml` is where the warning is
534
+ silenced, and the report flags the upstream fix separately. Do not use broad
535
+ `allowAny` or disable strict peer checks. Revisit such workarounds during
536
+ step 9.
508
537
  - **Build output:** if the baseline includes build output, rebuild with the
509
538
  same command and environment and diff the trees with content-hashed filenames
510
539
  normalized (`name.[hash].js`). Explain every remaining difference with an
@@ -541,15 +570,31 @@ rerun from the failing step:
541
570
  step 3; resetting a specifier or lockfile may not exclude it.
542
571
 
543
572
  Add focused tests only where a compatibility change touches behavior not
544
- already covered. Review `readme.md` accuracy and automation opportunities in step 7.
573
+ already covered. Review `readme.md` accuracy and automation opportunities in step 8.
545
574
 
546
575
  ## 6. Exclusion cleanup
547
576
 
548
577
  Only if `minimumReleaseAgeExclude` is non-empty in any `pnpm-workspace.yaml`
549
- (at the start, or after step 5). Empty the list (`[]` or remove the key),
550
- preserving neighboring keys and comments. Repeat step 5's separate bare
578
+ (at the start, or after step 5). Cleanup removes entries that no longer do
579
+ anything; it never changes which version is installed and never downgrades a
580
+ package.
581
+
582
+ Decide each entry from the publish time recorded in Setup, or look it up now:
583
+
584
+ - **Mature** (published at least 24 hours before the run): remove it; the
585
+ version resolves without it.
586
+ - **Young, authored package:** keep it while that version is the release this
587
+ run installs. Removing it would hold the package back to an older release.
588
+ - **Young, third-party package:** keep it while it holds a version that is
589
+ already locked; removing it would downgrade an installed package rather than
590
+ block a new one. Report it as pending with the date it can be removed. Do not
591
+ add new third-party entries.
592
+ - **Unused** (the version is neither locked nor targeted): remove it.
593
+
594
+ Edit the list directly, preserving neighboring keys and comments; use `[]` or
595
+ remove the key when nothing remains. Then repeat step 5's separate bare
551
596
  `pnpm update -r` and `pnpm dedupe --check` invocations, followed by a separate
552
- `pnpm dedupe` only when the check reports available changes. Then run each check
597
+ `pnpm dedupe` only when the check reports available changes, and run each check
553
598
  separately:
554
599
 
555
600
  ```bash
@@ -558,19 +603,46 @@ pnpm test
558
603
  pnpm lint
559
604
  ```
560
605
 
606
+ Compare the resolved versions with the lockfile saved before cleanup. pnpm
607
+ does not report a maturity holdback; it silently selects the newest mature
608
+ version. An authored package that resolved below its latest stable release, or
609
+ any package that resolved below its previous locked version, means a removed
610
+ entry was still needed: re-add that narrowest package/version entry and resolve
611
+ again. Never restore the whole previous list.
612
+
561
613
  If `pnpm-lock.yaml` comes out byte-identical and no ranges or build settings
562
614
  changed, the installed tree did not change; rerun only `pnpm lint`.
563
615
 
564
- If resolution is blocked: for an authored release, re-add the narrowest
565
- package/version entry; for a third-party release, choose a mature version or
566
- defer that upgrade. Obtain approval if that choice requires narrowing a
567
- published runtime range. Never restore the whole previous list.
568
-
569
616
  If the list was empty throughout, skip this section and continue to step 7.
570
617
  If cleanup changes resolution, repeat step 5's consumer compatibility review
571
618
  before reviewing documentation.
572
619
 
573
- ## 7. Documentation review
620
+ ## 7. Side effects declaration
621
+
622
+ For each published package, check that `sideEffects` in `package.json` tells
623
+ the truth about the shipped code. Bundlers drop any import they consider
624
+ side-effect-free when the declaration says `false`, and keep every module
625
+ otherwise, so a wrong `false` silently removes code consumers rely on and a
626
+ missing `false` on a pure package forfeits tree shaking.
627
+
628
+ 1. Read the declaration: `false`, an array of file patterns, `true`, or absent,
629
+ which means `true`.
630
+ 2. Inspect the published entry points and every module they reach, in the
631
+ build output that actually ships (`dist/` and the `files` list), including
632
+ bundled dependencies. Look for work that runs on import rather than on
633
+ call: assignments to globals or prototypes, polyfills, registrations such
634
+ as `customElements.define`, event listeners, process or environment setup,
635
+ CSS and asset imports, and bare imports kept only for their effects.
636
+ 3. Set the declaration to match: `false` when nothing runs on import, an array
637
+ naming the exact shipped files that do when only some do, and `true` when
638
+ most modules have effects. A package with no importable entry point, such
639
+ as a `bin`-only CLI, is unaffected either way; leave its declaration as is.
640
+ 4. Report every evaluation: the package, which modules were inspected, what
641
+ runs on import if anything, the declaration before and after, and why it
642
+ changed or stayed. A wrong `false` is a bug; a newly added `false` is a
643
+ performance improvement. Count either under the release recommendation.
644
+
645
+ ## 8. Documentation review
574
646
 
575
647
  Review `readme.md` against the updated project. Correct stale installation
576
648
  instructions, requirements, commands, examples, configuration guidance, and
@@ -594,7 +666,7 @@ no further changes. Validate any new dependency under steps 5 and 6 before
594
666
  continuing. Include documentation corrections and mdat conversions in the
595
667
  final report.
596
668
 
597
- ## 8. @kitschpatrol/shared-config override minimization
669
+ ## 9. @kitschpatrol/shared-config override minimization
598
670
 
599
671
  Run this as the final cleanup after all accepted updates, migrations,
600
672
  validation, release-age exclusion cleanup, and documentation review, before
@@ -637,7 +709,8 @@ from the largest dependency version bump:
637
709
 
638
710
  - **Patch:** compatible bug or security fixes, performance improvements, or
639
711
  dependency/tooling maintenance with no new consumer-facing capability. A
640
- development-only Node.js increase with the required notice can remain a patch.
712
+ development-only Node.js increase with the required notice can remain a
713
+ patch, and so does a corrected or newly added `sideEffects` declaration.
641
714
  - **Minor:** backward-compatible functionality or capabilities actually exposed
642
715
  to consumers by the accepted updates. Explain what consumers gain; an upstream
643
716
  minor or major alone is not a reason for a minor release. For zero-versioned
@@ -674,11 +747,14 @@ accepted under the zero-versioned policy;
674
747
  output differences and their upstream or migration explanations;
675
748
  consumer Node.js requirements before and after, development Node.js changes and
676
749
  their `devEngines.runtime` notices; the release recommendation and its rationale;
677
- baseline lockfile drift; runtime ranges, fresh-install exposure, and approved
750
+ baseline lockfile drift; the `packageManager` version chosen and its source;
751
+ `sideEffects` evaluations with their evidence and outcome; runtime ranges,
752
+ fresh-install exposure, and approved
678
753
  range restrictions; TypeScript migrations; new warnings and scoped peer
679
754
  workarounds; what was validated, at which exact Node.js versions, and in which
680
755
  known consumers, including CLI/fixture comparisons and unavailable baselines;
681
- remaining `minimumReleaseAgeExclude` entries with reasons; deferred upgrades,
756
+ remaining `minimumReleaseAgeExclude` entries with reasons and the dates they can
757
+ be removed; deferred upgrades,
682
758
  documentation corrections and mdat conversions;
683
759
  shared-config overrides removed or retained with their justifications and any
684
760
  unresolved override reviews; unresolved failures, checks that could not run,