@jawache/flow 0.1.0 → 0.1.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/dist/index.mjs CHANGED
@@ -1,18 +1,18 @@
1
- function y(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function $(n){let e=[],t="",r=()=>{t!==""&&e.push({kind:"literal",text:t}),t=""};for(let o=0;o<n.length;o++){let s=n[o];if(s==="*")r(),n[o+1]==="*"?(e.push({kind:"globstar"}),o++,n[o+1]==="/"&&o++):e.push({kind:"star"});else if(s==="?")r(),e.push({kind:"single"});else if(s==="{"){let a=n.indexOf("}",o);if(a===-1){t+=s;continue}r(),e.push({kind:"options",options:n.slice(o+1,a).split(",")}),o=a}else t+=s??""}return r(),e}function v(n){switch(n.kind){case"literal":return y(n.text);case"star":return"[^/]*";case"globstar":return".*";case"single":return"[^/]";case"options":return`(${n.options.map(y).join("|")})`}}function Z(n){return new RegExp(`^${$(n).map(v).join("")}$`)}function X(n,e){return Z(e).test(n)}function g(n,e){return(e||[]).some(t=>X(n,t))}function ee(n){let e=n.includes("/")?n.slice(0,n.lastIndexOf("/")):".",t=n.slice(n.lastIndexOf("/")+1),r=t.lastIndexOf("."),o=r>0?t.slice(0,r):t,s=e==="."?o:`${e}/${o}`;return{dir:e,base:t,name:o,path:s}}function O(n,e){let t=ee(e);return n.replace(/\{(dir|base|name|path)\}/g,(r,o)=>t[o])}var T={write:["edit"],command:["edit","commit"],commit:["commit"],delete:["delete"],"turn-end":["turn"]},ne=Object.keys(T),te=["session","touch","turn-end"],re="write",oe="command",se="commit",ie="delete",ae="turn-end",de="session",le="touch";function ce(n){let e=[];for(let t of n)for(let r of T[t])e.includes(r)||e.push(r);return e}function ue(n){return ne.includes(n)}function fe(n){return te.includes(n)}var j=["write","delete","commit","touch"];function pe(n){return j.includes(n)}var G=Symbol.for("flow.category");function ge(n,e){return{[G]:!0,name:n,classify:e}}function h(n,e){if(!(typeof n!="object"||n===null))return n[e]}function D(n){return h(n,G)===!0}var N=Symbol.for("flow.settings");function f(n){return e=>{let t=n(e);return Object.defineProperty(t,N,{value:e,enumerable:!1,configurable:!0}),t}}function ye(n){return n===void 0?void 0:n[N]}function me(n){return n?(n.pass?.length??0)+(n.block?.length??0)>0:!1}var he=["at","for","on","ignore","check","message","disabled","test","description"],ke=["at","for","on","ignore","text","file","disabled","description"];function x(n,e){let t=r=>x({...n,...r},e);return{...e(n),at:(...r)=>t({at:r}),for:(...r)=>t({for:r}),on:(...r)=>t({on:r}),ignore:(...r)=>t({ignore:r}),check:r=>t({check:r}),message:r=>t({message:r}),text:r=>t({text:r}),file:r=>t({file:r}),disabled:r=>t({disabled:r===void 0?{}:{reason:r}}),test:r=>t({test:r}),description:r=>t({description:r})}}var L=n=>({spec:n});function be(){return x({kind:"guardrail"},L)}function xe(){return x({kind:"breadcrumb"},L)}function we(n){let e=h(h(n,"spec"),"kind");return e==="guardrail"||e==="breadcrumb"}var F=Symbol.for("flow.pack"),I=Symbol.for("flow.ref");function Se(n,e){let t=typeof e=="function"&&e.length>0;return W(n,[],{name:n,build:o=>typeof e=="function"?e(o):e,takesParams:t})}function W(n,e,t){let r={[I]:{pack:n,id:e.join(".")}};return t&&(r[F]=t),new Proxy(r,{get(o,s){return s in o?o[s]:typeof s=="string"?W(n,[...e,s]):void 0}})}function Re(n){let e=h(n,F);return Ce(e)?e:void 0}function Ce(n){return typeof n=="object"&&n!==null&&typeof n.name=="string"&&typeof n.build=="function"}function Ee(n){let e=h(n,I),t=h(e,"pack"),r=h(e,"id");return typeof t=="string"&&typeof r=="string"?{pack:t,id:r}:void 0}function $e(n,...e){return{kind:"pack",pack:Re(n),params:e[0],hasParams:e.length>0}}function ve(n){let e=Ee(n)??{pack:"",id:""};return x({},t=>({binding:{kind:"override",ref:e,spoken:t}}))}function Oe(n,e={}){return{bindings:n.map(t=>"binding"in t?t.binding:t),settings:e}}function B(n,e,t){let r={};for(let o of Object.keys(n))r[o]=t?.[o]??"pack";for(let o of Object.keys(e))r[o]="override";return{spec:{...n,...e},source:r}}var Me=["not-a-pack","missing-parameter","unknown-entry","unknown-key","unknown-moment","missing-mandatory","undeclared-category","no-cases","duplicate-id","dead-scope"];function w(n){return[`flow: the config will not load \u2014 ${n.length} refusal${n.length===1?"":"s"}.`,...n.map(e=>` ${e.code}: ${e.detail}`)].join(`
2
- `)}function Ae(n){let e=[],t=[],r=new Map;for(let o of n.bindings){if(o.kind!=="pack")continue;if(!o.pack||o.pack.name===""){e.push({code:"not-a-pack",entry:"",detail:"A `pack(\u2026)` line was given a value that no `definePack` ever made. Import the pack's default export, not one of its entries."});continue}let{name:s,build:a,takesParams:i}=o.pack;if(i&&!o.hasParams){e.push({code:"missing-parameter",entry:s,detail:`The pack \`${s}\` declares parameters and was bound without any \u2014 write \`pack(${s}, { \u2026 })\`. Which fields it needs is stated by its factory's type.`});continue}for(let{key:d,spec:c}of K(a(o.params))){let l={id:`${s}.${d}`,pack:s,key:d,...B(c,{})};if(r.get(l.id)){e.push({code:"duplicate-id",entry:l.id,detail:`Two entries claim the id \`${l.id}\`. An id is its property name inside its pack, so this is one pack bound twice, or two packs sharing a name.`});continue}r.set(l.id,l),t.push(l)}}for(let o of n.bindings){if(o.kind!=="override")continue;let s=`${o.ref.pack}.${o.ref.id}`,a=r.get(s);if(!a){e.push({code:"unknown-entry",entry:s,detail:`\`override(${s})\` names an entry no bound pack has. Bind the pack it lives in, or correct the reference.`});continue}let i=B(a.spec,o.spoken,a.source);a.spec=i.spec,a.source=i.source}for(let o of t)e.push(...Pe(o));return e.length>0?{ok:!1,refusals:e}:{ok:!0,entries:t.map(o=>({id:o.id,pack:o.pack,key:o.key,spec:o.spec,source:o.source,categories:(o.spec.for??[]).map(s=>s.name),phases:o.spec.kind==="guardrail"?ce(o.spec.at??[]):[],settings:o.spec.kind==="guardrail"?ye(o.spec.check):void 0}))}}function K(n,e=[]){let t=[];for(let[r,o]of Object.entries(n))we(o)?t.push({key:[...e,r].join("."),spec:o.spec}):typeof o=="object"&&o!==null&&t.push(...K(o,[...e,r]));return t}function Pe(n){let{id:e,spec:t}=n,r=[],o=(u,Q)=>r.push({code:u,entry:e,detail:Q}),s=t.kind==="guardrail"?he:ke,a=Object.keys(t).filter(u=>u!=="kind"&&!s.includes(u));a.length>0&&o("unknown-key",`\`${e}\` carries ${a.map(u=>`\`${u}\``).join(", ")}, which the ${t.kind} grammar does not have. It is closed: ${s.join(" \xB7 ")}.`);let i=t.at??[],d=t.kind==="guardrail"?ue:fe,c=i.filter(u=>!d(u));if(c.length>0&&o("unknown-moment",`\`${e}\` fires at ${c.map(u=>`\`${u}\``).join(", ")}, which is not a moment a ${t.kind} has a rail for.`),(t.for??[]).some(u=>!D(u))&&o("undeclared-category",`\`${e}\` is scoped with \`.for(\u2026)\` to something \`defineCategory\` never made. A category is a value with its recognizer aboard \u2014 import the one you mean.`),t.disabled)return r;let p=[];return i.length===0&&p.push(".at(\u2026)"),t.kind==="guardrail"?(t.check||p.push(".check(\u2026)"),t.message===void 0&&p.push(".message(\u2026)")):t.text===void 0&&t.file===void 0&&p.push(".text(\u2026) or .file(\u2026)"),p.length>0&&o("missing-mandatory",`\`${e}\` never said ${p.join(" and ")}. Nothing in this grammar defaults \u2014 an absent key is absent, not a fallback.`),((t.on?.length??0)>0||(t.ignore?.length??0)>0)&&i.length>0&&!i.some(u=>pe(u))&&o("dead-scope",`\`${e}\` narrows by path but fires only at ${i.map(u=>`\`${u}\``).join(", ")}, which name no path \u2014 its \`on\`/\`ignore\` would be read by nothing. Drop the scope, or add a moment that carries a file (${j.join(" \xB7 ")}).`),t.kind==="guardrail"&&!me(t.test)&&o("no-cases",`\`${e}\` carries no cases. A rule declares what must pass it and what it must block (\`.test({ pass, block })\`) \u2014 a fence whose block-case was never written is a fence nothing proves is alive.`),r}function m(n,e,t=" \xB7 "){return e.length===0?n.ok():n.fail(e.join(t))}function k(n){return n.file??{path:"",content:""}}function Ge(n,e){let t=n.split(`
3
- `),r=[];for(let o of e){let s=new RegExp(o);t.forEach((a,i)=>{s.test(a)&&r.push({pattern:o,line:i+1})})}return r}var De=f(n=>e=>{let t=Ge(k(e).content,n.ban);return m(e,t.map(r=>`line ${r.line}: matches /${r.pattern}/`))}),Ne=f(n=>e=>{let t=e.command??"",r=n.ban.filter(o=>new RegExp(o).test(t));return m(e,r.map(o=>`matches banned /${o}/`))});function Le(n){return`(?:${n.join("|")})[^"\`]*(?:"(?:(?!<<-?')[^"])*"[^"\`]*)*"(?:(?!<<-?')[^"])*\``}var Fe=["You are recording prose through a shell command, and a backtick inside a DOUBLE-quoted argument is not Markdown \u2014 the shell RUNS it and splices its output into your text before the command ever sees it.","On an append-only record there is no undo: no amend, no redact. And once the binary has argv the splice has already happened, so this is the only moment it can be caught.","Fix: SINGLE-quote the argument (backticks are literal there), or feed the prose on stdin with a QUOTED heredoc \u2014 `git commit -F -` plus `<<'EOF'`, which this rule treats as safe.","ALREADY single-quoted and still blocked? Then your PROSE carries an unbalanced double quote before the backtick, and the matcher cannot tell that quote from a real open argument. Nothing would splice \u2014 this one is the rule's cost, not your mistake. Balance the quote, drop it, or use the heredoc; do not go back to double quotes to make it pass."].join(`
4
- `),Ie=f(n=>async e=>{let{path:t}=k(e);return n.existingOnly===!0?e.moment!=="delete"&&!await e.fs.exists(t)?e.ok():e.fail(`'${t}' is append-only \u2014 an existing file here is history and may not be edited or deleted (adding a new one is fine)`):e.fail(`'${t}' is a protected path (do not edit directly)`)}),We=f(n=>async e=>{let t=O(n.sibling,k(e).path);return await e.fs.exists(t)?e.ok():e.fail(`required sibling missing: ${t}`)}),Ke=/\.(ts|tsx|mts|cts|js|mjs|cjs|jsx)$/;function _e(n,e){let t=n.replace(/\\/g,"/"),r=e.root.replace(/^\/+|\/+$/g,"")+"/",o=t.indexOf(r);if(o===-1)return{ok:!0};let s=t.slice(o+r.length);if(e.folders?.length){let l=s.split("/")[0]??"",p=l.replace(/\.[^.]+$/,"");if(l!==""&&!e.folders.includes(l)&&!e.folders.includes(p))return{ok:!1,tier:"folder",found:l}}if(!e.allow.length)return{ok:!0};let a=Ke.exec(t);if(!a)return{ok:!0};if(t.endsWith(".d.ts"))return{ok:!0};if(!s.includes("/"))return{ok:!0};let d=s.slice(s.lastIndexOf("/")+1).slice(0,-a[0].length);return(d.endsWith(".test")?d.slice(0,-5)!==(e.thinking??""):!e.allow.includes(d))?{ok:!1,tier:"filename"}:{ok:!0}}function qe(n,e,t){return n.ok?"":n.tier==="folder"?`'${n.found}' is not one of the names ${t.root}/ may hold: ${t.folders?.join(" \xB7 ")??""} (found ${e})`:`non-canonical file in a ${t.root} feature folder: ${e} (allowed: ${t.allow.join(" \xB7 ")}${t.thinking===void 0?"":` \u2014 only ${t.thinking} may carry a .test sibling`})`}var Ue=f(n=>e=>{let{path:t}=k(e),r=_e(t,n);return r.ok?e.ok():e.fail(qe(r,t,n))});function Ve(n,e){let t=n;for(let r of(e??"").split(".").filter(Boolean)){if(t==null||typeof t!="object"||!(r in t))return{found:!1};t=t[r]}return{found:!0,value:t}}function He(n,e){let t=[],{path:r}=e,o=Ve(n,r);if(!o.found)return e.required===!0&&t.push(`"${r}" is missing (required)`),t;let s=o.value;if(e.keysPrefixedWith!==void 0){if(!s||typeof s!="object")return t;for(let a of Object.keys(s))a.startsWith(e.keysPrefixedWith)||t.push(`"${r}.${a}" must be prefixed "${e.keysPrefixedWith}"`)}return"equals"in e&&JSON.stringify(s)!==JSON.stringify(e.equals)&&t.push(`"${r}" must equal ${JSON.stringify(e.equals)} (is ${JSON.stringify(s)})`),e.matches!==void 0&&!new RegExp(e.matches).test(String(s))&&t.push(`"${r}" (${JSON.stringify(s)}) must match /${e.matches}/`),t}function Je(n,e){let t;try{t=JSON.parse(n)}catch{return[]}return e.flatMap(r=>He(t,r))}var Ye=f(n=>e=>m(e,Je(k(e).content,n.assert)));function ze(n,e){return n.filter(t=>!new RegExp(`\\b${y(t)}\\b`).test(e))}async function Qe(n){let{parse:e,Lang:t}=await import("@ast-grep/napi"),r=e(t.Tsx,n).root(),o=new Set;for(let s of["export function $N($$$) { $$$ }","export class $N { $$$ }","export const $N = $V"])for(let a of r.findAll(s)){let i=a.getMatch("N");i&&o.add(i.text())}return[...o]}var Ze=f(n=>async e=>{let{path:t,content:r}=k(e),o=O(n.sibling,t);if(!await e.fs.exists(o))return e.fail(`sibling test not found: ${o}`);let s=await e.fs.read(o),a=ze(await Qe(r),s);return m(e,a.map(i=>`exported '${i}' is never referenced in ${o}`))});async function U(n){return n.staged?n.staged:n.git.stagedFiles()}function Xe(n,e){let t=[];for(let r of e)n.some(o=>g(o,r.if))&&(n.some(o=>g(o,r.thenAny))||t.push(`${r.if.join(", ")} changed but none of [${r.thenAny.join(", ")}] did in the same commit`));return t}var en=f(n=>async e=>m(e,Xe(await U(e),n.groups))),C=new Set([";","&&","||","|","&","|&",`
5
- `]),nn=new Set(["-C","-c","--git-dir","--work-tree","--namespace","--exec-path","--config-env"]);function tn(n,e){for(let t=e;t<n.length;t++){if(n[t]==="\\"){t++;continue}if(n[t]==='"')return t}return-1}function A(n){let e=n,t=[],r="",o=!1,s=0,a=()=>{o&&t.push(r),r="",o=!1};for(;s<e.length;){let i=e[s];if(i==="'"||i==='"'){let d=i==="'"?e.indexOf("'",s+1):tn(e,s+1);if(d===-1)return null;r+=i==='"'?e.slice(s+1,d).replace(/\\(["\\$`])/g,"$1"):e.slice(s+1,d),o=!0,s=d+1}else if(i==="\\"&&s+1<e.length)r+=e[s+1],o=!0,s+=2;else if(i===`
1
+ function y(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function $(n){let e=[],t="",r=()=>{t!==""&&e.push({kind:"literal",text:t}),t=""};for(let o=0;o<n.length;o++){let s=n[o];if(s==="*")r(),n[o+1]==="*"?(e.push({kind:"globstar"}),o++,n[o+1]==="/"&&o++):e.push({kind:"star"});else if(s==="?")r(),e.push({kind:"single"});else if(s==="{"){let a=n.indexOf("}",o);if(a===-1){t+=s;continue}r(),e.push({kind:"options",options:n.slice(o+1,a).split(",")}),o=a}else t+=s??""}return r(),e}function v(n){switch(n.kind){case"literal":return y(n.text);case"star":return"[^/]*";case"globstar":return".*";case"single":return"[^/]";case"options":return`(${n.options.map(y).join("|")})`}}function ee(n){return new RegExp(`^${$(n).map(v).join("")}$`)}function ne(n,e){return ee(e).test(n)}function g(n,e){return(e||[]).some(t=>ne(n,t))}function te(n){let e=n.includes("/")?n.slice(0,n.lastIndexOf("/")):".",t=n.slice(n.lastIndexOf("/")+1),r=t.lastIndexOf("."),o=r>0?t.slice(0,r):t,s=e==="."?o:`${e}/${o}`;return{dir:e,base:t,name:o,path:s}}function O(n,e){let t=te(e);return n.replace(/\{(dir|base|name|path)\}/g,(r,o)=>t[o])}var j={write:["edit"],command:["edit","commit"],commit:["commit"],delete:["delete"],"turn-end":["turn"]},re=Object.keys(j),oe=["session","touch","command","turn-end"],se="write",ie="command",ae="commit",de="delete",le="turn-end",ce="session",ue="touch";function fe(n){let e=[];for(let t of n)for(let r of j[t])e.includes(r)||e.push(r);return e}function pe(n){return re.includes(n)}function ge(n){return oe.includes(n)}var M=["write","delete","commit","touch"];function ye(n){return M.includes(n)}var D=[...M,"command"];function me(n,e){return n==="breadcrumb"?D.includes(e):ye(e)}var N=Symbol.for("flow.category");function he(n,e){return{[N]:!0,name:n,classify:e}}function h(n,e){if(!(typeof n!="object"||n===null))return n[e]}function L(n){return h(n,N)===!0}var F=Symbol.for("flow.settings");function f(n){return e=>{let t=n(e);return Object.defineProperty(t,F,{value:e,enumerable:!1,configurable:!0}),t}}function ke(n){return n===void 0?void 0:n[F]}function be(n){return n?(n.pass?.length??0)+(n.block?.length??0)>0:!1}var xe=["at","for","on","ignore","check","message","disabled","test","description"],we=["at","for","on","ignore","text","file","disabled","description"];function x(n,e){let t=r=>x({...n,...r},e);return{...e(n),at:(...r)=>t({at:r}),for:(...r)=>t({for:r}),on:(...r)=>t({on:r}),ignore:(...r)=>t({ignore:r}),check:r=>t({check:r}),message:r=>t({message:r}),text:r=>t({text:r}),file:r=>t({file:r}),disabled:r=>t({disabled:r===void 0?{}:{reason:r}}),test:r=>t({test:r}),description:r=>t({description:r})}}var I=n=>({spec:n});function Se(){return x({kind:"guardrail"},I)}function Re(){return x({kind:"breadcrumb"},I)}function Ce(n){let e=h(h(n,"spec"),"kind");return e==="guardrail"||e==="breadcrumb"}var W=Symbol.for("flow.pack"),K=Symbol.for("flow.ref");function Ee(n,e){let t=typeof e=="function"&&e.length>0;return _(n,[],{name:n,build:o=>typeof e=="function"?e(o):e,takesParams:t})}function _(n,e,t){let r={[K]:{pack:n,id:e.join(".")}};return t&&(r[W]=t),new Proxy(r,{get(o,s){return s in o?o[s]:typeof s=="string"?_(n,[...e,s]):void 0}})}function $e(n){let e=h(n,W);return ve(e)?e:void 0}function ve(n){return typeof n=="object"&&n!==null&&typeof n.name=="string"&&typeof n.build=="function"}function Oe(n){let e=h(n,K),t=h(e,"pack"),r=h(e,"id");return typeof t=="string"&&typeof r=="string"?{pack:t,id:r}:void 0}function Me(n,...e){return{kind:"pack",pack:$e(n),params:e[0],hasParams:e.length>0}}function Pe(n){let e=Oe(n)??{pack:"",id:""};return x({},t=>({binding:{kind:"override",ref:e,spoken:t}}))}function Ae(n,e={}){return{bindings:n.map(t=>"binding"in t?t.binding:t),settings:e}}function T(n,e,t){let r={};for(let o of Object.keys(n))r[o]=t?.[o]??"pack";for(let o of Object.keys(e))r[o]="override";return{spec:{...n,...e},source:r}}var Be=["not-a-pack","missing-parameter","unknown-entry","unknown-key","unknown-moment","missing-mandatory","undeclared-category","no-cases","duplicate-id","dead-scope"];function w(n){return[`flow: the config will not load \u2014 ${n.length} refusal${n.length===1?"":"s"}.`,...n.map(e=>` ${e.code}: ${e.detail}`)].join(`
2
+ `)}function Ge(n){let e=[],t=[],r=new Map;for(let o of n.bindings){if(o.kind!=="pack")continue;if(!o.pack||o.pack.name===""){e.push({code:"not-a-pack",entry:"",detail:"A `pack(\u2026)` line was given a value that no `definePack` ever made. Import the pack's default export, not one of its entries."});continue}let{name:s,build:a,takesParams:i}=o.pack;if(i&&!o.hasParams){e.push({code:"missing-parameter",entry:s,detail:`The pack \`${s}\` declares parameters and was bound without any \u2014 write \`pack(${s}, { \u2026 })\`. Which fields it needs is stated by its factory's type.`});continue}for(let{key:d,spec:c}of q(a(o.params))){let l={id:`${s}.${d}`,pack:s,key:d,...T(c,{})};if(r.get(l.id)){e.push({code:"duplicate-id",entry:l.id,detail:`Two entries claim the id \`${l.id}\`. An id is its property name inside its pack, so this is one pack bound twice, or two packs sharing a name.`});continue}r.set(l.id,l),t.push(l)}}for(let o of n.bindings){if(o.kind!=="override")continue;let s=`${o.ref.pack}.${o.ref.id}`,a=r.get(s);if(!a){e.push({code:"unknown-entry",entry:s,detail:`\`override(${s})\` names an entry no bound pack has. Bind the pack it lives in, or correct the reference.`});continue}let i=T(a.spec,o.spoken,a.source);a.spec=i.spec,a.source=i.source}for(let o of t)e.push(...Te(o));return e.length>0?{ok:!1,refusals:e}:{ok:!0,entries:t.map(o=>({id:o.id,pack:o.pack,key:o.key,spec:o.spec,source:o.source,categories:(o.spec.for??[]).map(s=>s.name),phases:o.spec.kind==="guardrail"?fe(o.spec.at??[]):[],settings:o.spec.kind==="guardrail"?ke(o.spec.check):void 0}))}}function q(n,e=[]){let t=[];for(let[r,o]of Object.entries(n))Ce(o)?t.push({key:[...e,r].join("."),spec:o.spec}):typeof o=="object"&&o!==null&&t.push(...q(o,[...e,r]));return t}function Te(n){let{id:e,spec:t}=n,r=[],o=(u,X)=>r.push({code:u,entry:e,detail:X}),s=t.kind==="guardrail"?xe:we,a=Object.keys(t).filter(u=>u!=="kind"&&!s.includes(u));a.length>0&&o("unknown-key",`\`${e}\` carries ${a.map(u=>`\`${u}\``).join(", ")}, which the ${t.kind} grammar does not have. It is closed: ${s.join(" \xB7 ")}.`);let i=t.at??[],d=t.kind==="guardrail"?pe:ge,c=i.filter(u=>!d(u));if(c.length>0&&o("unknown-moment",`\`${e}\` fires at ${c.map(u=>`\`${u}\``).join(", ")}, which is not a moment a ${t.kind} has a rail for.`),(t.for??[]).some(u=>!L(u))&&o("undeclared-category",`\`${e}\` is scoped with \`.for(\u2026)\` to something \`defineCategory\` never made. A category is a value with its recognizer aboard \u2014 import the one you mean.`),t.disabled)return r;let p=[];return i.length===0&&p.push(".at(\u2026)"),t.kind==="guardrail"?(t.check||p.push(".check(\u2026)"),t.message===void 0&&p.push(".message(\u2026)")):t.text===void 0&&t.file===void 0&&p.push(".text(\u2026) or .file(\u2026)"),p.length>0&&o("missing-mandatory",`\`${e}\` never said ${p.join(" and ")}. Nothing in this grammar defaults \u2014 an absent key is absent, not a fallback.`),((t.on?.length??0)>0||(t.ignore?.length??0)>0)&&i.length>0&&!i.some(u=>me(t.kind,u))&&o("dead-scope",`\`${e}\` narrows by path but fires only at ${i.map(u=>`\`${u}\``).join(", ")}, which name no subject to narrow \u2014 its \`on\`/\`ignore\` would be read by nothing. Drop the scope, or add a moment that carries one (${(t.kind==="breadcrumb"?D:M).join(" \xB7 ")}).`),t.kind==="guardrail"&&!be(t.test)&&o("no-cases",`\`${e}\` carries no cases. A rule declares what must pass it and what it must block (\`.test({ pass, block })\`) \u2014 a fence whose block-case was never written is a fence nothing proves is alive.`),r}function m(n,e,t=" \xB7 "){return e.length===0?n.ok():n.fail(e.join(t))}function k(n){return n.file??{path:"",content:""}}function Le(n,e){let t=n.split(`
3
+ `),r=[];for(let o of e){let s=new RegExp(o);t.forEach((a,i)=>{s.test(a)&&r.push({pattern:o,line:i+1})})}return r}var Fe=f(n=>e=>{let t=Le(k(e).content,n.ban);return m(e,t.map(r=>`line ${r.line}: matches /${r.pattern}/`))}),Ie=f(n=>e=>{let t=e.command??"",r=n.ban.filter(o=>new RegExp(o).test(t));return m(e,r.map(o=>`matches banned /${o}/`))});function We(n){return`(?:${n.join("|")})[^"\`]*(?:"(?:(?!<<-?')[^"])*"[^"\`]*)*"(?:(?!<<-?')[^"])*\``}var Ke=["You are recording prose through a shell command, and a backtick inside a DOUBLE-quoted argument is not Markdown \u2014 the shell RUNS it and splices its output into your text before the command ever sees it.","On an append-only record there is no undo: no amend, no redact. And once the binary has argv the splice has already happened, so this is the only moment it can be caught.","Fix: SINGLE-quote the argument (backticks are literal there), or feed the prose on stdin with a QUOTED heredoc \u2014 `git commit -F -` plus `<<'EOF'`, which this rule treats as safe.","ALREADY single-quoted and still blocked? Then your PROSE carries an unbalanced double quote before the backtick, and the matcher cannot tell that quote from a real open argument. Nothing would splice \u2014 this one is the rule's cost, not your mistake. Balance the quote, drop it, or use the heredoc; do not go back to double quotes to make it pass."].join(`
4
+ `),_e=f(n=>async e=>{let{path:t}=k(e);return n.existingOnly===!0?e.moment!=="delete"&&!await e.fs.exists(t)?e.ok():e.fail(`'${t}' is append-only \u2014 an existing file here is history and may not be edited or deleted (adding a new one is fine)`):e.fail(`'${t}' is a protected path (do not edit directly)`)}),qe=f(n=>async e=>{let t=O(n.sibling,k(e).path);return await e.fs.exists(t)?e.ok():e.fail(`required sibling missing: ${t}`)}),Ue=/\.(ts|tsx|mts|cts|js|mjs|cjs|jsx)$/;function Ve(n,e){let t=n.replace(/\\/g,"/"),r=e.root.replace(/^\/+|\/+$/g,"")+"/",o=t.indexOf(r);if(o===-1)return{ok:!0};let s=t.slice(o+r.length);if(e.folders?.length){let l=s.split("/")[0]??"",p=l.replace(/\.[^.]+$/,"");if(l!==""&&!e.folders.includes(l)&&!e.folders.includes(p))return{ok:!1,tier:"folder",found:l}}if(!e.allow.length)return{ok:!0};let a=Ue.exec(t);if(!a)return{ok:!0};if(t.endsWith(".d.ts"))return{ok:!0};if(!s.includes("/"))return{ok:!0};let d=s.slice(s.lastIndexOf("/")+1).slice(0,-a[0].length);return(d.endsWith(".test")?d.slice(0,-5)!==(e.thinking??""):!e.allow.includes(d))?{ok:!1,tier:"filename"}:{ok:!0}}function He(n,e,t){return n.ok?"":n.tier==="folder"?`'${n.found}' is not one of the names ${t.root}/ may hold: ${t.folders?.join(" \xB7 ")??""} (found ${e})`:`non-canonical file in a ${t.root} feature folder: ${e} (allowed: ${t.allow.join(" \xB7 ")}${t.thinking===void 0?"":` \u2014 only ${t.thinking} may carry a .test sibling`})`}var Je=f(n=>e=>{let{path:t}=k(e),r=Ve(t,n);return r.ok?e.ok():e.fail(He(r,t,n))});function Ye(n,e){let t=n;for(let r of(e??"").split(".").filter(Boolean)){if(t==null||typeof t!="object"||!(r in t))return{found:!1};t=t[r]}return{found:!0,value:t}}function ze(n,e){let t=[],{path:r}=e,o=Ye(n,r);if(!o.found)return e.required===!0&&t.push(`"${r}" is missing (required)`),t;let s=o.value;if(e.keysPrefixedWith!==void 0){if(!s||typeof s!="object")return t;for(let a of Object.keys(s))a.startsWith(e.keysPrefixedWith)||t.push(`"${r}.${a}" must be prefixed "${e.keysPrefixedWith}"`)}return"equals"in e&&JSON.stringify(s)!==JSON.stringify(e.equals)&&t.push(`"${r}" must equal ${JSON.stringify(e.equals)} (is ${JSON.stringify(s)})`),e.matches!==void 0&&!new RegExp(e.matches).test(String(s))&&t.push(`"${r}" (${JSON.stringify(s)}) must match /${e.matches}/`),t}function Qe(n,e){let t;try{t=JSON.parse(n)}catch{return[]}return e.flatMap(r=>ze(t,r))}var Ze=f(n=>e=>m(e,Qe(k(e).content,n.assert)));function Xe(n,e){return n.filter(t=>!new RegExp(`\\b${y(t)}\\b`).test(e))}async function en(n){let{parse:e,Lang:t}=await import("@ast-grep/napi"),r=e(t.Tsx,n).root(),o=new Set;for(let s of["export function $N($$$) { $$$ }","export class $N { $$$ }","export const $N = $V"])for(let a of r.findAll(s)){let i=a.getMatch("N");i&&o.add(i.text())}return[...o]}var nn=f(n=>async e=>{let{path:t,content:r}=k(e),o=O(n.sibling,t);if(!await e.fs.exists(o))return e.fail(`sibling test not found: ${o}`);let s=await e.fs.read(o),a=Xe(await en(r),s);return m(e,a.map(i=>`exported '${i}' is never referenced in ${o}`))});async function H(n){return n.staged?n.staged:n.git.stagedFiles()}function tn(n,e){let t=[];for(let r of e)n.some(o=>g(o,r.if))&&(n.some(o=>g(o,r.thenAny))||t.push(`${r.if.join(", ")} changed but none of [${r.thenAny.join(", ")}] did in the same commit`));return t}var rn=f(n=>async e=>m(e,tn(await H(e),n.groups))),C=new Set([";","&&","||","|","&","|&",`
5
+ `]),on=new Set(["-C","-c","--git-dir","--work-tree","--namespace","--exec-path","--config-env"]);function sn(n,e){for(let t=e;t<n.length;t++){if(n[t]==="\\"){t++;continue}if(n[t]==='"')return t}return-1}function B(n){let e=n,t=[],r="",o=!1,s=0,a=()=>{o&&t.push(r),r="",o=!1};for(;s<e.length;){let i=e[s];if(i==="'"||i==='"'){let d=i==="'"?e.indexOf("'",s+1):sn(e,s+1);if(d===-1)return null;r+=i==='"'?e.slice(s+1,d).replace(/\\(["\\$`])/g,"$1"):e.slice(s+1,d),o=!0,s=d+1}else if(i==="\\"&&s+1<e.length)r+=e[s+1],o=!0,s+=2;else if(i===`
6
6
  `)a(),t.push(`
7
- `),s++;else if(/\s/.test(i))a(),s++;else if(i===";"||i==="|"||i==="&"){a();let d=e.slice(s,s+2);d==="&&"||d==="||"||d==="|&"?(t.push(d),s+=2):(t.push(i),s++)}else r+=i,o=!0,s++}return a(),t}function P(n){let e=A(n);if(!e)return null;let t=[],r=0,o=!0;for(;r<e.length;){let s=e[r];if(C.has(s)){o=!0,r++;continue}if(o&&s==="git"){let a=[],i=r+1;for(;i<e.length&&!C.has(e[i]);)a.push(e[i++]);let d=0;for(;d<a.length;){let c=a[d];if(nn.has(c))d+=2;else if(c.startsWith("-"))d+=1;else break}t.push({globals:a.slice(0,d),subcommand:a[d]??null,args:a.slice(d+1)}),r=i,o=!1;continue}o=!1,r++}return t}function rn(n){let e=/<<-?\s*(['"]?)([A-Za-z_][A-Za-z0-9_]*)\1/.exec(n);if(!e)return null;let t=e[2],o=n.slice(e.index+e[0].length).split(`
7
+ `),s++;else if(/\s/.test(i))a(),s++;else if(i===";"||i==="|"||i==="&"){a();let d=e.slice(s,s+2);d==="&&"||d==="||"||d==="|&"?(t.push(d),s+=2):(t.push(i),s++)}else r+=i,o=!0,s++}return a(),t}function G(n){let e=B(n);if(!e)return null;let t=[],r=0,o=!0;for(;r<e.length;){let s=e[r];if(C.has(s)){o=!0,r++;continue}if(o&&s==="git"){let a=[],i=r+1;for(;i<e.length&&!C.has(e[i]);)a.push(e[i++]);let d=0;for(;d<a.length;){let c=a[d];if(on.has(c))d+=2;else if(c.startsWith("-"))d+=1;else break}t.push({globals:a.slice(0,d),subcommand:a[d]??null,args:a.slice(d+1)}),r=i,o=!1;continue}o=!1,r++}return t}function an(n){let e=/<<-?\s*(['"]?)([A-Za-z_][A-Za-z0-9_]*)\1/.exec(n);if(!e)return null;let t=e[2],o=n.slice(e.index+e[0].length).split(`
8
8
  `).slice(1),s=o.findIndex(i=>i.trim()===t);if(s===-1)return null;let a=o.slice(0,s).join(`
9
- `).trim();return a===""?null:a}function V(n){let e=P(n);if(!e)return null;let t=e.find(o=>o.subcommand==="commit");if(!t)return null;let r=[];for(let o=0;o<t.args.length;o++){let s=t.args[o];if(s==="-m"||s==="--message"){let a=t.args[o+1];if(a===void 0)break;r.push(a),o++;continue}s.startsWith("-m")&&s!=="-m"?r.push(s.slice(2)):s.startsWith("--message=")&&r.push(s.slice(10))}return r.length?r.join(`
9
+ `).trim();return a===""?null:a}function J(n){let e=G(n);if(!e)return null;let t=e.find(o=>o.subcommand==="commit");if(!t)return null;let r=[];for(let o=0;o<t.args.length;o++){let s=t.args[o];if(s==="-m"||s==="--message"){let a=t.args[o+1];if(a===void 0)break;r.push(a),o++;continue}s.startsWith("-m")&&s!=="-m"?r.push(s.slice(2)):s.startsWith("--message=")&&r.push(s.slice(10))}return r.length?r.join(`
10
10
 
11
- `):rn(n)}function b(n){return`'${n.replace(/'/g,"'\\''")}'`}function H(n){let e=[],t=A(n),r=t?.[1];t?.[0]==="cd"&&r!==void 0&&!r.startsWith("-")&&!C.has(r)&&C.has(t[2]??"")&&e.push("-C",b(r));let o=P(n)?.[0];if(!o)return e.join(" ");for(let s=0;s<o.globals.length-1;s++)o.globals[s]==="-C"&&e.push("-C",b(o.globals[s+1]));return e.join(" ")}function J(n,e){return new RegExp(`^[ \\t]*${y(e)}[ \\t]*:`,"im").test(n)}function on(n,e,t=[]){let r=new Set(t),o=new Set;for(let s of n.split(`
12
- `)){if(!s.startsWith("+")||s.startsWith("+++"))continue;let a=s.slice(1);for(let i of e){let d=new RegExp(i,"g"),c;for(;(c=d.exec(a))!==null;)c[1]!==void 0&&!r.has(c[1])&&o.add(c[1]),c[0]===""&&d.lastIndex++}}return[...o]}function sn(n){let{message:e,state:t,whenChanged:r,whenAdded:o,except:s,namesAdded:a,token:i}=n,d=new Set(t.added),c=[];for(let l of t.changed)s&&g(l,s)||(d.has(l)&&o&&g(l,o)?c.push(`\`${l}\` (new)`):r&&g(l,r)&&c.push(`\`${l}\` (changed)`));for(let{name:l,file:p}of a??[])c.push(`\`${l}\` (added in ${p})`);return c.length?J(e,i)?[]:[`${c.join(" \xB7 ")} \u2014 and this commit's message records no reason. Put \`${i}: <why>\` on a line of its own in the message; the act is fine, doing it silently is not.`]:[]}function M(n){return n.split(`
13
- `).map(e=>e.trim()).filter(Boolean)}var an=f(n=>async e=>{let t=V(e.command??"");if(t==null)return e.ok();let r=`git ${H(e.command??"")}`.trimEnd(),o={changed:[],added:[]};if(n.whenChanged||n.whenAdded){let[i,d,c]=await Promise.all([e.exec(`${r} diff HEAD --name-only`),e.exec(`${r} diff HEAD --name-only --diff-filter=A`),e.exec(`${r} ls-files --others --exclude-standard`)]);if(i.code!==0||d.code!==0||c.code!==0)return e.ok();let l=M(c.stdout);o={changed:[...new Set([...M(i.stdout),...l])],added:[...M(d.stdout),...l]}}let s=[];for(let i of n.diffAdds??[]){let d=await e.exec(`${r} diff HEAD -- ${b(i.file)}`);if(d.code!==0)return e.ok();for(let c of on(d.stdout,i.patterns,i.known??[]))s.push({name:c,file:i.file})}let a=sn({message:t,state:o,whenChanged:n.whenChanged,whenAdded:n.whenAdded,except:n.except,namesAdded:s,token:n.token});return m(e,a)});function dn(n,e,t){if(t===""||e.length===0)return!1;let r=-1,o=-1;return n.forEach((s,a)=>{s.did==="edit"&&g(s.path,e)&&(r=a),s.did==="run"&&s.command.includes(t)&&(o=a)}),r>=0&&r>o}var ln=f(n=>e=>e.turn&&dn(e.turn,n.edited,n.mustRun)?e.fail(`edited ${n.edited.join(", ")} this turn but never ran \`${n.mustRun}\` afterwards`):e.ok());function cn(n,e){let t=e??[];return!t.length||!n.length?!1:!n.some(r=>g(r,t))}function Y(n,e=8){let t=n.trim().split(`
11
+ `):an(n)}function b(n){return`'${n.replace(/'/g,"'\\''")}'`}function Y(n){let e=[],t=B(n),r=t?.[1];t?.[0]==="cd"&&r!==void 0&&!r.startsWith("-")&&!C.has(r)&&C.has(t[2]??"")&&e.push("-C",b(r));let o=G(n)?.[0];if(!o)return e.join(" ");for(let s=0;s<o.globals.length-1;s++)o.globals[s]==="-C"&&e.push("-C",b(o.globals[s+1]));return e.join(" ")}function z(n,e){return new RegExp(`^[ \\t]*${y(e)}[ \\t]*:`,"im").test(n)}function dn(n,e,t=[]){let r=new Set(t),o=new Set;for(let s of n.split(`
12
+ `)){if(!s.startsWith("+")||s.startsWith("+++"))continue;let a=s.slice(1);for(let i of e){let d=new RegExp(i,"g"),c;for(;(c=d.exec(a))!==null;)c[1]!==void 0&&!r.has(c[1])&&o.add(c[1]),c[0]===""&&d.lastIndex++}}return[...o]}function ln(n){let{message:e,state:t,whenChanged:r,whenAdded:o,except:s,namesAdded:a,token:i}=n,d=new Set(t.added),c=[];for(let l of t.changed)s&&g(l,s)||(d.has(l)&&o&&g(l,o)?c.push(`\`${l}\` (new)`):r&&g(l,r)&&c.push(`\`${l}\` (changed)`));for(let{name:l,file:p}of a??[])c.push(`\`${l}\` (added in ${p})`);return c.length?z(e,i)?[]:[`${c.join(" \xB7 ")} \u2014 and this commit's message records no reason. Put \`${i}: <why>\` on a line of its own in the message; the act is fine, doing it silently is not.`]:[]}function P(n){return n.split(`
13
+ `).map(e=>e.trim()).filter(Boolean)}var cn=f(n=>async e=>{let t=J(e.command??"");if(t==null)return e.ok();let r=`git ${Y(e.command??"")}`.trimEnd(),o={changed:[],added:[]};if(n.whenChanged||n.whenAdded){let[i,d,c]=await Promise.all([e.exec(`${r} diff HEAD --name-only`),e.exec(`${r} diff HEAD --name-only --diff-filter=A`),e.exec(`${r} ls-files --others --exclude-standard`)]);if(i.code!==0||d.code!==0||c.code!==0)return e.ok();let l=P(c.stdout);o={changed:[...new Set([...P(i.stdout),...l])],added:[...P(d.stdout),...l]}}let s=[];for(let i of n.diffAdds??[]){let d=await e.exec(`${r} diff HEAD -- ${b(i.file)}`);if(d.code!==0)return e.ok();for(let c of dn(d.stdout,i.patterns,i.known??[]))s.push({name:c,file:i.file})}let a=ln({message:t,state:o,whenChanged:n.whenChanged,whenAdded:n.whenAdded,except:n.except,namesAdded:s,token:n.token});return m(e,a)});function un(n,e,t){if(t===""||e.length===0)return!1;let r=-1,o=-1;return n.forEach((s,a)=>{s.did==="edit"&&g(s.path,e)&&(r=a),s.did==="run"&&s.command.includes(t)&&(o=a)}),r>=0&&r>o}var fn=f(n=>e=>e.turn&&un(e.turn,n.edited,n.mustRun)?e.fail(`edited ${n.edited.join(", ")} this turn but never ran \`${n.mustRun}\` afterwards`):e.ok());function pn(n,e){let t=e??[];return!t.length||!n.length?!1:!n.some(r=>g(r,t))}function Q(n,e=8){let t=n.trim().split(`
14
14
  `).filter(Boolean),r=t.filter(o=>/\b(fail|failed|error|not ok|assert|expected|cannot|undefined)\b/i.test(o)||/[✖✗✘]/.test(o));return(r.length?r:t.slice(-6)).slice(0,e).join(`
15
- `)}var un=f(n=>async e=>{let t=await U(e);if(cn(t,n.changed))return e.ok();let r=n.run.includes("{files}");if(r&&t.length===0)return e.ok();let o=r?n.run.replace("{files}",t.map(b).join(" ")):n.run,s=await e.exec(o);return s.code===0?e.ok():e.fail(`\`${o}\` failed (exit ${s.code}):
16
- ${Y(s.stderr||s.stdout)}`)});function R(n){let e=$(n),t=e[e.length-1]?.kind==="globstar";return`^${(t?e.slice(0,-1):e).map(v).join("")}${t?"":"$"}`}function fn(n){return n==="node:*"?{core:!0}:n.startsWith("node:")?{path:`^${y(n)}$`}:n.includes("/")||n.includes("*")||n.includes(".")?{path:R(n)}:{path:`node_modules/${y(n)}(/|$)`}}function S(n,e){let t=[],r=!1;for(let s of n)for(let a of e[s]??[]){let i=fn(a);i.core?r=!0:i.path&&t.push(i.path)}let o={};return t.length&&(o.path=t),r&&(o.dependencyTypes=["core"]),o}function pn(n){let e=n.layers,t=[],r=[],o=(n.except??[]).includes("type-only"),s=i=>o?{...i,dependencyTypesNot:["type-only"]}:i;for(let[i,d]of Object.entries(n.only??{})){let l={pathNot:S(d,e).path??[]};t.push({name:`${i}-only`,severity:"error",comment:`${i} may import only: ${d.join(", ")} \u2014 an unlisted import blocks here (add it to a layer, or keep it out).`,from:S([i],e),to:s(l)})}for(let i of n.forbid??[])if(i==="circular")t.push({name:"no-circular",severity:"error",comment:"no dependency cycles",from:{pathNot:"node_modules"},to:{circular:!0}});else if(i==="orphans")t.push({name:"no-orphans",severity:"warn",comment:"unreferenced module",from:{orphan:!0,pathNot:"node_modules|\\.d\\.ts$"},to:{}});else if(i.cyclesBetween!==void 0){let d=i.cyclesBetween,c=(e[d]??[])[0]??"",l=R(c).replace(/\$$/,"").replace(/\[\^\/\]\*$/,"([^/]+)");t.push({name:`no-cycles-between-${d}`,severity:"error",comment:i.why??`${d} must not import sideways`,from:{path:`${l}/`},to:s({path:`${l.replace(/\(\[\^\/\]\+\)/,"[^/]+")}/`,pathNot:"$1/"})})}else if(i.from!==void 0&&i.to!==void 0){let d={...S([i.to],e)};i.transitive===!0&&(d.reachable=!0),t.push({name:`no-${i.from}-to-${i.to}${i.transitive===!0?"-transitive":""}`,severity:"error",comment:i.why??`${i.from} must not import ${i.to}`,from:S([i.from],e),to:s(d)})}for(let i of n.require??[])r.push({name:`must-import-${i.import}`,severity:"error",comment:i.why??`modules in ${i.in} must import ${i.import}`,module:{path:R(i.in)},to:{path:R(i.import)}});for(let i of n.warn??[])i==="sdp"&&t.push({name:"sdp",severity:"warn",comment:"depends on a more-unstable module (Stable Dependencies Principle)",from:{},to:{moreUnstable:!0}});let a={enhancedResolveOptions:{extensions:[".js",".jsx",".ts",".tsx",".mjs",".cjs",".json"]},doNotFollow:{path:"node_modules"},tsPreCompilationDeps:!1,...n.options??{}};return{forbidden:t,required:r,options:a}}var _="FLOW_DEPCRUISE_CONFIG";function gn(n){let e=JSON.stringify(pn(n));return["d=$(mktemp -d)",`cat > "$d/dc.json" <<'${_}'`,e,_,`npx --no-install depcruise --config "$d/dc.json" --output-type json ${b(n.scan)}`,"rc=$?",'rm -rf "$d"',"exit $rc"].join(`
17
- `)}function yn(n){let e;try{e=JSON.parse(n.stdout||"")}catch{return n.code===0?[]:[`depcruise failed (exit ${n.code}): ${Y(n.stderr||n.stdout,3)}`]}return(e.summary?.violations??[]).map(t=>{let r=t.rule?.name??"fence",o=t.comment??t.rule?.comment??"";return`${r}: ${t.from} \u2192 ${t.to}${o?` \u2014 ${o}`:""}`})}var mn=f(n=>async e=>m(e,yn(await e.exec(gn(n))),`
18
- `)),z={html:"Html",css:"Css",javascript:"JavaScript",js:"JavaScript",typescript:"TypeScript",ts:"TypeScript",tsx:"Tsx",jsx:"Tsx"},hn=Object.keys(z),q=new Set;async function kn(n){let{Lang:e,registerDynamicLanguage:t}=await import("@ast-grep/napi"),r=z[n];if(r!==void 0)return{ok:!0,lang:e[r]};if(q.has(n))return{ok:!0,lang:n};try{let o=await import(`@ast-grep/lang-${n}`);return t({[n]:o.default??o}),q.add(n),{ok:!0,lang:n}}catch{return{ok:!1,detail:`unknown ast-grep grammar: '${n}'. Built in: ${hn.join(", ")}. Anything else installs as a package \u2014 \`npm i -D @ast-grep/lang-${n}\` \u2014 and is picked up here on the next run.`}}}async function bn(n,e,t){let r=await kn(t);if(!r.ok)return r;let{parse:o}=await import("@ast-grep/napi");return{ok:!0,hits:o(r.lang,n).root().findAll({rule:e}).map(a=>`${a.range().start.line+1}: ${a.text()}`)}}var xn=f(n=>async e=>{let t=await bn(k(e).content,n.rule,n.language);return t.ok?m(e,t.hits):e.fail(t.detail)});function wn(n){return e=>{let t=e.agentType;return n.parent===!0?!e.subagent&&t===void 0:t===void 0?!1:(n.types??[]).includes(t)?!0:(n.generic??[]).includes(t)?(n.brief??[]).some(r=>e.head.includes(r)):!1}}var Bn=14400*1e3;var E=class extends Error{refusals;constructor(e){super(w(e)),this.name="FlowConfigError",this.refusals=e}};function Sn(n){if(n.ok)return n.entries;throw new E(n.refusals)}export{E as FlowConfigError,Me as REFUSAL_CODES,Fe as SUBSTITUTION_MESSAGE,xn as astGrep,Ne as banCommands,xe as breadcrumb,Ue as canonicalFiles,en as changeTogether,oe as command,se as commit,V as commitMessage,an as commitReason,ge as defineCategory,f as defineCheck,Oe as defineConfig,Se as definePack,ie as deletion,mn as depcruise,Sn as entriesOrThrow,y as escapeRe,un as execPasses,H as gitDirPrefix,P as gitInvocations,J as givesReason,be as guardrail,Ye as jsonInvariant,Ae as loadConfig,ve as override,$e as pack,Ie as protectedPath,b as quoteArg,ln as ranSinceEdit,w as refusalText,de as session,We as siblingExists,wn as spawnedAs,Le as substitutionInProse,Ze as symbolsInSibling,De as textBan,A as tokenizeCommand,le as touch,ae as turnEnd,re as write};
15
+ `)}var gn=f(n=>async e=>{let t=await H(e);if(pn(t,n.changed))return e.ok();let r=n.run.includes("{files}");if(r&&t.length===0)return e.ok();let o=r?n.run.replace("{files}",t.map(b).join(" ")):n.run,s=await e.exec(o);return s.code===0?e.ok():e.fail(`\`${o}\` failed (exit ${s.code}):
16
+ ${Q(s.stderr||s.stdout)}`)});function R(n){let e=$(n),t=e[e.length-1]?.kind==="globstar";return`^${(t?e.slice(0,-1):e).map(v).join("")}${t?"":"$"}`}function yn(n){return n==="node:*"?{core:!0}:n.startsWith("node:")?{path:`^${y(n)}$`}:n.includes("/")||n.includes("*")||n.includes(".")?{path:R(n)}:{path:`node_modules/${y(n)}(/|$)`}}function S(n,e){let t=[],r=!1;for(let s of n)for(let a of e[s]??[]){let i=yn(a);i.core?r=!0:i.path&&t.push(i.path)}let o={};return t.length&&(o.path=t),r&&(o.dependencyTypes=["core"]),o}function mn(n){let e=n.layers,t=[],r=[],o=(n.except??[]).includes("type-only"),s=i=>o?{...i,dependencyTypesNot:["type-only"]}:i;for(let[i,d]of Object.entries(n.only??{})){let l={pathNot:S(d,e).path??[]};t.push({name:`${i}-only`,severity:"error",comment:`${i} may import only: ${d.join(", ")} \u2014 an unlisted import blocks here (add it to a layer, or keep it out).`,from:S([i],e),to:s(l)})}for(let i of n.forbid??[])if(i==="circular")t.push({name:"no-circular",severity:"error",comment:"no dependency cycles",from:{pathNot:"node_modules"},to:{circular:!0}});else if(i==="orphans")t.push({name:"no-orphans",severity:"warn",comment:"unreferenced module",from:{orphan:!0,pathNot:"node_modules|\\.d\\.ts$"},to:{}});else if(i.cyclesBetween!==void 0){let d=i.cyclesBetween,c=(e[d]??[])[0]??"",l=R(c).replace(/\$$/,"").replace(/\[\^\/\]\*$/,"([^/]+)");t.push({name:`no-cycles-between-${d}`,severity:"error",comment:i.why??`${d} must not import sideways`,from:{path:`${l}/`},to:s({path:`${l.replace(/\(\[\^\/\]\+\)/,"[^/]+")}/`,pathNot:"$1/"})})}else if(i.from!==void 0&&i.to!==void 0){let d={...S([i.to],e)};i.transitive===!0&&(d.reachable=!0),t.push({name:`no-${i.from}-to-${i.to}${i.transitive===!0?"-transitive":""}`,severity:"error",comment:i.why??`${i.from} must not import ${i.to}`,from:S([i.from],e),to:s(d)})}for(let i of n.require??[])r.push({name:`must-import-${i.import}`,severity:"error",comment:i.why??`modules in ${i.in} must import ${i.import}`,module:{path:R(i.in)},to:{path:R(i.import)}});for(let i of n.warn??[])i==="sdp"&&t.push({name:"sdp",severity:"warn",comment:"depends on a more-unstable module (Stable Dependencies Principle)",from:{},to:{moreUnstable:!0}});let a={enhancedResolveOptions:{extensions:[".js",".jsx",".ts",".tsx",".mjs",".cjs",".json"]},doNotFollow:{path:"node_modules"},tsPreCompilationDeps:!1,...n.options??{}};return{forbidden:t,required:r,options:a}}var U="FLOW_DEPCRUISE_CONFIG";function hn(n){let e=JSON.stringify(mn(n));return["d=$(mktemp -d)",`cat > "$d/dc.json" <<'${U}'`,e,U,`npx --no-install depcruise --config "$d/dc.json" --output-type json ${b(n.scan)}`,"rc=$?",'rm -rf "$d"',"exit $rc"].join(`
17
+ `)}function kn(n){let e;try{e=JSON.parse(n.stdout||"")}catch{return n.code===0?[]:[`depcruise failed (exit ${n.code}): ${Q(n.stderr||n.stdout,3)}`]}return(e.summary?.violations??[]).map(t=>{let r=t.rule?.name??"fence",o=t.comment??t.rule?.comment??"";return`${r}: ${t.from} \u2192 ${t.to}${o?` \u2014 ${o}`:""}`})}var bn=f(n=>async e=>m(e,kn(await e.exec(hn(n))),`
18
+ `)),Z={html:"Html",css:"Css",javascript:"JavaScript",js:"JavaScript",typescript:"TypeScript",ts:"TypeScript",tsx:"Tsx",jsx:"Tsx"},xn=Object.keys(Z),A=new Set,V=Symbol.for("flow.grammars");function wn(){let n=globalThis,e=n[V];if(e!==void 0)return e;let t={declared:[],present:()=>!1};return n[V]=t,t}function Sn(n,e){return`\`${n}\`: no library at ${e}. A grammar is a BUILD ARTEFACT \u2014 machine-specific, never committed \u2014 so this is the ordinary state of a fresh clone. Build it (the repo that declares a grammar carries the recipe that builds it), or every ast-grep rule on that language refuses rather than passing quietly.`}async function Rn(n){let{Lang:e,registerDynamicLanguage:t}=await import("@ast-grep/napi"),r=Z[n];if(r!==void 0)return{ok:!0,lang:e[r]};if(A.has(n))return{ok:!0,lang:n};let{declared:o,present:s}=wn(),a=o.find(i=>i.name===n);if(a!==void 0)return s(a.libraryPath)?(t({[n]:{libraryPath:a.libraryPath,extensions:[...a.extensions],...a.languageSymbol===void 0?{}:{languageSymbol:a.languageSymbol}}}),A.add(n),{ok:!0,lang:n}):{ok:!1,detail:Sn(n,a.libraryPath)};try{let i=await import(`@ast-grep/lang-${n}`);return t({[n]:i.default??i}),A.add(n),{ok:!0,lang:n}}catch{return{ok:!1,detail:`unknown ast-grep grammar: '${n}'. Built in: ${xn.join(", ")}. Anything else is either a published package \u2014 \`npm i -D @ast-grep/lang-${n}\` \u2014 or a grammar you build yourself and declare in flow.config.ts's \`grammars\` setting.`}}}async function Cn(n,e,t){let r=await Rn(t);if(!r.ok)return r;let{parse:o}=await import("@ast-grep/napi");return{ok:!0,hits:o(r.lang,n).root().findAll({rule:e}).map(a=>`${a.range().start.line+1}: ${a.text()}`)}}var En=f(n=>async e=>{let t=await Cn(k(e).content,n.rule,n.language);return t.ok?m(e,t.hits):e.fail(t.detail)});function $n(n){return e=>{let t=e.agentType;return n.parent===!0?!e.subagent&&t===void 0:t===void 0?!1:(n.types??[]).includes(t)?!0:(n.generic??[]).includes(t)?(n.brief??[]).some(r=>e.head.includes(r)):!1}}var Nn=14400*1e3;var E=class extends Error{refusals;constructor(e){super(w(e)),this.name="FlowConfigError",this.refusals=e}};function vn(n){if(n.ok)return n.entries;throw new E(n.refusals)}export{E as FlowConfigError,Be as REFUSAL_CODES,Ke as SUBSTITUTION_MESSAGE,En as astGrep,Ie as banCommands,Re as breadcrumb,Je as canonicalFiles,rn as changeTogether,ie as command,ae as commit,J as commitMessage,cn as commitReason,he as defineCategory,f as defineCheck,Ae as defineConfig,Ee as definePack,de as deletion,bn as depcruise,vn as entriesOrThrow,y as escapeRe,gn as execPasses,Y as gitDirPrefix,G as gitInvocations,z as givesReason,Se as guardrail,Ze as jsonInvariant,Ge as loadConfig,Pe as override,Me as pack,_e as protectedPath,b as quoteArg,fn as ranSinceEdit,w as refusalText,ce as session,qe as siblingExists,$n as spawnedAs,We as substitutionInProse,nn as symbolsInSibling,Fe as textBan,B as tokenizeCommand,ue as touch,le as turnEnd,se as write};