@jawache/flow 0.1.2 → 0.2.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/README.md +15 -9
- package/dist/flow.mjs +94 -73
- package/dist/index.mjs +22 -16
- package/dist/packs.mjs +103 -68
- package/dist/types/adapter/archive.d.ts +8 -1
- package/dist/types/adapter/claude.d.ts +46 -5
- package/dist/types/adapter/domain.d.ts +369 -9
- package/dist/types/checks/domain.d.ts +71 -14
- package/dist/types/engine/domain.d.ts +10 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/language/domain.d.ts +23 -0
- package/dist/types/packs/docs.d.ts +3 -4
- package/dist/types/packs/work.d.ts +18 -2
- package/package.json +1 -1
package/dist/flow.mjs
CHANGED
|
@@ -1,53 +1,76 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{existsSync as
|
|
3
|
-
`)}function
|
|
4
|
-
`),r=[];for(let o of n){let s=new RegExp(o);t.forEach((i,a)=>{s.test(i)&&r.push({pattern:o,line:a+1})})}return r}var
|
|
5
|
-
`),
|
|
6
|
-
`]),
|
|
2
|
+
import{existsSync as $l,readFileSync as Cl}from"node:fs";import{registerHooks as El,stripTypeScriptTypes as Ol}from"node:module";import{fileURLToPath as Al,pathToFileURL as Pl}from"node:url";import{dirname as Tl,join as jl,resolve as Pt}from"node:path";var Pe="0.2.1";function ce(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function _t(e){return e.startsWith("^")||e.includes("(?")||e.includes("|")||e.endsWith("$")}function xn(e){let n=[],t="",r=()=>{t!==""&&n.push({kind:"literal",text:t}),t=""};for(let o=0;o<e.length;o++){let s=e[o];if(s==="*")r(),e[o+1]==="*"?(n.push({kind:"globstar"}),o++,e[o+1]==="/"&&o++):n.push({kind:"star"});else if(s==="?")r(),n.push({kind:"single"});else if(s==="{"){let i=e.indexOf("}",o);if(i===-1){t+=s;continue}r(),n.push({kind:"options",options:e.slice(o+1,i).split(",")}),o=i}else t+=s??""}return r(),n}function Sn(e){switch(e.kind){case"literal":return ce(e.text);case"star":return"[^/]*";case"globstar":return".*";case"single":return"[^/]";case"options":return`(${e.options.map(ce).join("|")})`}}function ms(e){return new RegExp(`^${xn(e).map(Sn).join("")}$`)}function hs(e,n){return ms(n).test(e)}function M(e,n){return(n||[]).some(t=>hs(e,t))}function ks(e){let n=e.includes("/")?e.slice(0,e.lastIndexOf("/")):".",t=e.slice(e.lastIndexOf("/")+1),r=t.lastIndexOf("."),o=r>0?t.slice(0,r):t,s=n==="."?o:`${n}/${o}`;return{dir:n,base:t,name:o,path:s}}function Rn(e,n){let t=ks(n);return e.replace(/\{(dir|base|name|path)\}/g,(r,o)=>t[o])}var Nt={write:["edit"],command:["edit","commit"],commit:["commit"],delete:["delete"],"turn-end":["turn"]},bs=Object.keys(Nt),ws=["session","touch","command","turn-end"];function xs(e){let n=[];for(let t of e)for(let r of Nt[t])n.includes(r)||n.push(r);return n}function $n(e){return bs.includes(e)}function Cn(e){return ws.includes(e)}var En=["write","delete","commit","touch"];function Ss(e){return En.includes(e)}var Ft=[...En,"command"];function Rs(e,n){return e==="breadcrumb"?Ft.includes(n):Ss(n)}var vs=Symbol.for("flow.category");function vn(e,n){if(!(typeof e!="object"||e===null))return e[n]}function On(e){return vn(e,vs)===!0}var He={ok:()=>({ok:!0}),fail:e=>e===void 0?{ok:!1}:{ok:!1,detail:e}};function Ue(e,n,t){return{moment:e,...n,actor:n.actor??[],exec:r=>t.exec(r),fs:t.fs,git:t.git,ok:He.ok,fail:He.fail}}var Bt=Symbol.for("flow.settings"),Gt=Symbol.for("flow.faults");function An(e,n){return n.length>0&&Object.defineProperty(e,Gt,{value:n,enumerable:!1,configurable:!0}),e}function $s(e){if(e===void 0)return[];let n=e[Gt];return Array.isArray(n)?n:[]}function I(e){return n=>{let t=e(n);return Object.defineProperty(t,Bt,{value:n,enumerable:!1,configurable:!0}),t}}function Cs(e){return e===void 0?void 0:e[Bt]}function Es(e){return e?(e.pass?.length??0)+(e.block?.length??0)>0:!1}function Ke(e,n,t){let r=e.exec??{},o=e.fs??{};return{exec:s=>{let i=Object.hasOwn(r,s)?s:Object.keys(r).find(l=>s.includes(l)),a=i===void 0?void 0:r[i];return a===void 0?(t.push({kind:"exec",asked:s}),Promise.resolve({stdout:"",stderr:"",code:0})):Promise.resolve({stdout:a.stdout??"",stderr:a.stderr??"",code:a.code??0})},fs:{exists:s=>Promise.resolve(Object.hasOwn(o,s)),read:s=>{let i=o[s];return i===void 0?(t.push({kind:"read",asked:s}),Promise.resolve("")):Promise.resolve(i)}},git:{diff:()=>Promise.resolve(e.gitDiff??""),stagedFiles:()=>Promise.resolve([...n??e.staged??[]])}}}function re(e,n){return!(e.on&&!M(n,e.on)||e.ignore&&M(n,e.ignore))}var Os=["at","for","on","ignore","check","message","disabled","test","description"],As=["at","for","on","ignore","text","file","disabled","description"];function Ps(e){let n=vn(vn(e,"spec"),"kind");return n==="guardrail"||n==="breadcrumb"}function It(e,n,t){let r={};for(let o of Object.keys(e))r[o]=t?.[o]??"pack";for(let o of Object.keys(n))r[o]="override";return{spec:{...e,...n},source:r}}function ue(e){return[`flow: the config will not load \u2014 ${e.length} refusal${e.length===1?"":"s"}.`,...e.map(n=>` ${n.code}: ${n.detail}`)].join(`
|
|
3
|
+
`)}function Re(e){let n=[],t=[],r=new Map;for(let o of e.bindings){if(o.kind!=="pack")continue;if(!o.pack||o.pack.name===""){n.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:i,takesParams:a}=o.pack;if(a&&!o.hasParams){n.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:l,spec:c}of Dt(i(o.params))){let d={id:`${s}.${l}`,pack:s,key:l,...It(c,{})};if(r.get(d.id)){n.push({code:"duplicate-id",entry:d.id,detail:`Two entries claim the id \`${d.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(d.id,d),t.push(d)}}for(let o of e.bindings){if(o.kind!=="override")continue;let s=`${o.ref.pack}.${o.ref.id}`,i=r.get(s);if(!i){n.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 a=It(i.spec,o.spoken,i.source);i.spec=a.spec,i.source=a.source}for(let o of t)n.push(...Ts(o));return n.length>0?{ok:!1,refusals:n}:{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"?xs(o.spec.at??[]):[],settings:o.spec.kind==="guardrail"?Cs(o.spec.check):void 0}))}}function Dt(e,n=[]){let t=[];for(let[r,o]of Object.entries(e))Ps(o)?t.push({key:[...n,r].join("."),spec:o.spec}):typeof o=="object"&&o!==null&&t.push(...Dt(o,[...n,r]));return t}function Ts(e){let{id:n,spec:t}=e,r=[],o=(g,p)=>r.push({code:g,entry:n,detail:p}),s=t.kind==="guardrail"?Os:As,i=Object.keys(t).filter(g=>g!=="kind"&&!s.includes(g));i.length>0&&o("unknown-key",`\`${n}\` carries ${i.map(g=>`\`${g}\``).join(", ")}, which the ${t.kind} grammar does not have. It is closed: ${s.join(" \xB7 ")}.`);let a=t.at??[],l=t.kind==="guardrail"?$n:Cn,c=a.filter(g=>!l(g));if(c.length>0&&o("unknown-moment",`\`${n}\` fires at ${c.map(g=>`\`${g}\``).join(", ")}, which is not a moment a ${t.kind} has a rail for.`),(t.for??[]).some(g=>!On(g))&&o("undeclared-category",`\`${n}\` 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 u=[];a.length===0&&u.push(".at(\u2026)"),t.kind==="guardrail"?(t.check||u.push(".check(\u2026)"),t.message===void 0&&u.push(".message(\u2026)")):t.text===void 0&&t.file===void 0&&u.push(".text(\u2026) or .file(\u2026)"),u.length>0&&o("missing-mandatory",`\`${n}\` never said ${u.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)&&a.length>0&&!a.some(g=>Rs(t.kind,g))&&o("dead-scope",`\`${n}\` narrows by path but fires only at ${a.map(g=>`\`${g}\``).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"?Ft:En).join(" \xB7 ")}).`),t.kind==="guardrail"&&!Es(t.test)&&o("no-cases",`\`${n}\` 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.`);for(let g of $s(t.kind==="guardrail"?t.check:void 0))o("bad-check-options",`\`${n}\` ${g}`);return r}var ve=class extends Error{refusals;constructor(n){super(ue(n)),this.name="FlowConfigError",this.refusals=n}};function Wt(e){if(e.ok)return e.entries;throw new ve(e.refusals)}function oe(e,n,t=" \xB7 "){return n.length===0?e.ok():e.fail(n.join(t))}function ge(e){return e.file??{path:"",content:""}}function js(e,n){let t=e.split(`
|
|
4
|
+
`),r=[];for(let o of n){let s=new RegExp(o);t.forEach((i,a)=>{s.test(i)&&r.push({pattern:o,line:a+1})})}return r}var Vl=I(e=>n=>{let t=js(ge(n).content,e.ban);return oe(n,t.map(r=>`line ${r.line}: matches /${r.pattern}/`))}),ql=I(e=>n=>{let t=e.matchHeredocs===!0?n.command??"":Nn(n.command??""),r=e.ban.filter(o=>new RegExp(o).test(t));return oe(n,r.map(o=>`matches banned /${o}/`))});var Jl=["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(`
|
|
5
|
+
`),zl=I(e=>async n=>{let{path:t}=ge(n);return e.existingOnly===!0?n.moment!=="delete"&&!await n.fs.exists(t)?n.ok():n.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)`):n.fail(`'${t}' is a protected path (do not edit directly)`)}),Yl=I(e=>An(n=>{if(n.actor.some(o=>e.writers.includes(o)))return n.ok();let t=n.actor.length===0?"an actor with no category":`an actor wearing ${n.actor.join(", ")}`,r=n.moment==="delete"?"deleted":"written";return n.fail(`${n.file?.path??"a file"} was ${r} by ${t} \u2014 only ${e.writers.join(" or ")} may change files here`)},e.writers.length===0?["lists no `writers`, so it would refuse every change by every actor. Name the categories allowed to write."]:[])),Zl=I(e=>async n=>{let t=Rn(e.sibling,ge(n).path);return await n.fs.exists(t)?n.ok():n.fail(`required sibling missing: ${t}`)}),Ms=/\.(ts|tsx|mts|cts|js|mjs|cjs|jsx)$/;function _s(e,n){let t=e.replace(/\\/g,"/"),r=n.root.replace(/^\/+|\/+$/g,"")+"/",o=t.indexOf(r);if(o===-1)return{ok:!0};let s=t.slice(o+r.length);if(n.folders?.length){let d=s.split("/")[0]??"",u=d.replace(/\.[^.]+$/,"");if(d!==""&&!n.folders.includes(d)&&!n.folders.includes(u))return{ok:!1,tier:"folder",found:d}}if(!n.allow.length)return{ok:!0};let i=Ms.exec(t);if(!i)return{ok:!0};if(t.endsWith(".d.ts"))return{ok:!0};if(!s.includes("/"))return{ok:!0};let l=s.slice(s.lastIndexOf("/")+1).slice(0,-i[0].length);return(l.endsWith(".test")?l.slice(0,-5)!==(n.thinking??""):!n.allow.includes(l))?{ok:!1,tier:"filename"}:{ok:!0}}function Is(e,n,t){return e.ok?"":e.tier==="folder"?`'${e.found}' is not one of the names ${t.root}/ may hold: ${t.folders?.join(" \xB7 ")??""} (found ${n})`:`non-canonical file in a ${t.root} feature folder: ${n} (allowed: ${t.allow.join(" \xB7 ")}${t.thinking===void 0?"":` \u2014 only ${t.thinking} may carry a .test sibling`})`}var Xl=I(e=>n=>{let{path:t}=ge(n),r=_s(t,e);return r.ok?n.ok():n.fail(Is(r,t,e))});function Ns(e,n){let t=e;for(let r of(n??"").split(".").filter(Boolean)){if(t==null||typeof t!="object"||!(r in t))return{found:!1};t=t[r]}return{found:!0,value:t}}function Fs(e,n){let t=[],{path:r}=n,o=Ns(e,r);if(!o.found)return n.required===!0&&t.push(`"${r}" is missing (required)`),t;let s=o.value;if(n.keysPrefixedWith!==void 0){if(!s||typeof s!="object")return t;for(let i of Object.keys(s))i.startsWith(n.keysPrefixedWith)||t.push(`"${r}.${i}" must be prefixed "${n.keysPrefixedWith}"`)}return"equals"in n&&JSON.stringify(s)!==JSON.stringify(n.equals)&&t.push(`"${r}" must equal ${JSON.stringify(n.equals)} (is ${JSON.stringify(s)})`),n.matches!==void 0&&!new RegExp(n.matches).test(String(s))&&t.push(`"${r}" (${JSON.stringify(s)}) must match /${n.matches}/`),t}function Bs(e,n){let t;try{t=JSON.parse(e)}catch{return[]}return n.flatMap(r=>Fs(t,r))}var Ql=I(e=>n=>oe(n,Bs(ge(n).content,e.assert)));function Gs(e,n){return e.filter(t=>!new RegExp(`\\b${ce(t)}\\b`).test(n))}async function Ds(e){let{parse:n,Lang:t}=await import("@ast-grep/napi"),r=n(t.Tsx,e).root(),o=new Set;for(let s of["export function $N($$$) { $$$ }","export class $N { $$$ }","export const $N = $V"])for(let i of r.findAll(s)){let a=i.getMatch("N");a&&o.add(a.text())}return[...o]}var ed=I(e=>async n=>{let{path:t,content:r}=ge(n),o=Rn(e.sibling,t);if(!await n.fs.exists(o))return n.fail(`sibling test not found: ${o}`);let s=await n.fs.read(o),i=Gs(await Ds(r),s);return oe(n,i.map(a=>`exported '${a}' is never referenced in ${o}`))});async function Vt(e){return e.staged?e.staged:e.git.stagedFiles()}function Ws(e,n){let t=[];for(let r of n)e.some(o=>M(o,r.if))&&(e.some(o=>M(o,r.thenAny))||t.push(`${r.if.join(", ")} changed but none of [${r.thenAny.join(", ")}] did in the same commit`));return t}var nd=I(e=>async n=>oe(n,Ws(await Vt(n),e.groups))),Je=new Set([";","&&","||","|","&","|&",`
|
|
6
|
+
`]),jn=new Set(["-C","-c","--git-dir","--work-tree","--namespace","--exec-path","--config-env"]),Lt=/(?:'([^'\n]*)'|"([^"\n]*)"|\\?([^\s'";&|<>()`]+))/y;function Mn(e,n){if(!e.startsWith("<<",n)||e[n+2]==="<")return null;let t=e[n+2]==="-",r=n+(t?3:2);for(;e[r]===" "||e[r]===" ";)r++;Lt.lastIndex=r;let o=Lt.exec(e),s=o?.[1]??o?.[2]??o?.[3]??"";return o===null||s===""?null:{delim:s,tabs:t,end:r+o[0].length}}function _n(e){for(let n=e.indexOf("<<");n!==-1;){let t=Mn(e,n);if(t!==null)return t;for(;e[n]==="<";)n++;n=e.indexOf("<<",n)}return null}function In(e,n,t){let r=n;for(;r<e.length;){let o=r,s=e.indexOf(`
|
|
7
|
+
`,r),i=e.slice(r,s===-1?e.length:s);if(r=s===-1?e.length:s+1,(t.tabs?i.replace(/^\t+/,""):i)===t.delim)return{body:o,end:r}}return{body:r,end:r}}function pe(e,n){let t=1,r=[];for(let o=n;o<e.length;o++){let s=e[o];if(s==="\\")o++;else if(s==="'"||s==='"'){let i=s==="'"?e.indexOf("'",o+1):je(e,o+1);if(i===-1)return-1;o=i}else if(e.startsWith("$((",o)){let i=e.indexOf("))",o+3);if(i===-1)return-1;o=i+1}else if(e.startsWith("<<<",o))o+=2;else if(s==="<"){let i=Mn(e,o);i!==null&&(r.push(i),o=i.end-1)}else if(s===`
|
|
8
|
+
`)for(let i of r.splice(0))o=In(e,o+1,i).end-1;else if(s==="(")t++;else if(s===")"&&--t===0)return o}return-1}function je(e,n){for(let t=n;t<e.length;t++)if(e[t]==="\\")t++;else if(e[t]==="$"&&e[t+1]==="("){let r=pe(e,t+2);if(r===-1)return-1;t=r}else if(e[t]==='"')return t;return-1}var Ls=new Set(["bash","sh","zsh","dash","ksh","eval"]),Hs=new Set(["sudo","env","exec","command","builtin","nohup","nice","time","if","then","else","elif","while","until","do","!","{"]),Us=new Set([" "," ",`
|
|
9
|
+
`,";","&","|","(",")","<",">"]);function Te(e,n,t,r){for(let[o,s]of qt(e.slice(n,t)))r.push([o+n,s+n])}function Ks(e,n,t,r){for(let o=n;o<t;o++)if(e[o]==="\\")o++;else if(e.startsWith("$(",o)){let s=pe(e,o+2);e[o+2]!=="("&&Te(e,o+2,s,r),o=s}else if(e[o]==="`"){let s=e.indexOf("`",o+1);if(s===-1||s>t)return;Te(e,o+1,s,r),o=s}}function Vs(e,n,t){let r="",o=n;for(;o<e.length&&!Us.has(e[o]);){let s=e[o],i;if(s==="\\"){e[o+1]!==`
|
|
10
|
+
`&&(r+=e[o+1]??""),o+=2;continue}else if(s==="'")i=e.indexOf("'",o+1),i!==-1&&(r+=e.slice(o+1,i));else if(s==='"')i=je(e,o+1),i!==-1&&(r+=e.slice(o+1,i),Ks(e,o+1,i,t));else if(e.startsWith("$((",o))i=e.indexOf("))",o+3),i=i===-1?-1:i+1,r+="\0";else if(e.startsWith("$(",o))i=pe(e,o+2),i!==-1&&Te(e,o+2,i,t),r+="\0";else if(s==="`")i=e.indexOf("`",o+1),i!==-1&&Te(e,o+1,i,t),r+="\0";else{r+=s,o++;continue}if(i===-1)return null;o=i+1}return{end:o,text:r}}function qt(e){let n=[],t={shell:!1},r=[],o=!0,s=!1,i=!1,a=0;for(;a<e.length;){let l=e[a];if(l===`
|
|
11
|
+
`){a++;for(let{doc:c,pipeline:d}of r){let{body:u,end:f}=In(e,a,c);d.shell||n.push([a,u]),a=f}r=[],t={shell:!1},o=!0,s=!1}else if(l===" "||l===" ")a++;else if(e.startsWith(`\\
|
|
12
|
+
`,a))a+=2;else if(l==="#"){let c=e.indexOf(`
|
|
13
|
+
`,a);a=c===-1?e.length:c}else if(e.startsWith("<(",a)||e.startsWith(">(",a)){let c=pe(e,a+2);if(c===-1)break;Te(e,a+2,c,n),a=c+1,o=!1}else if(l==="<"||l===">"||e.startsWith("&>",a)){let c=Mn(e,a);c!==null?(r.push({doc:c,pipeline:t}),a=c.end):(a+=(/^(?:&>>|&>|<<<|<<-|<<|<>|<&|>>|>\||>&|<|>)/.exec(e.slice(a))?.[0]??l).length,i=!0)}else if(l===";"||l==="&"||l==="|"||l==="("||l===")"){let c=e.slice(a,a+2),d=["&&","||","|&",";;"].includes(c)?c:l;a+=d.length,d!=="|"&&d!=="|&"&&(t={shell:!1}),o=!0,s=!1}else{let c=Vs(e,a,n);if(c===null)break;if(a=c.end,i)i=!1;else if(o){let d=c.text.slice(c.text.lastIndexOf("/")+1);Hs.has(d)?s=!0:!/^[A-Za-z_]\w*=/.test(c.text)&&!(s&&c.text.startsWith("-"))&&(Ls.has(d)&&(t.shell=!0),o=!1)}}}return n.sort((l,c)=>l[0]-c[0])}function Nn(e){let n="",t=0;for(let[r,o]of qt(e))n+=e.slice(t,r),t=o;return n+e.slice(t)}function ze(e){let n=e,t=[],r="",o=!1,s=0,i=()=>{o&&t.push(r),r="",o=!1};for(;s<n.length;){let a=n[s];if(a==="'"||a==='"'){let l=a==="'"?n.indexOf("'",s+1):je(n,s+1);if(l===-1)return null;r+=a==='"'?n.slice(s+1,l).replace(/\\(["\\$`])/g,"$1"):n.slice(s+1,l),o=!0,s=l+1}else if(a==="\\"&&s+1<n.length)r+=n[s+1],o=!0,s+=2;else if(a===`
|
|
7
14
|
`)i(),t.push(`
|
|
8
|
-
`),s++;else if(/\s/.test(a))i(),s++;else if(a===";"||a==="|"||a==="&"){i();let
|
|
9
|
-
`).slice(1),s=o.findIndex(a=>a.trim()===t);if(s===-1)return null;let i=o.slice(0,s).join(`
|
|
10
|
-
`).trim();return i===""?null:i}function jo(e){let n=gt(e);if(!n)return null;let t=n.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 i=t.args[o+1];if(i===void 0)break;r.push(i),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(`
|
|
15
|
+
`),s++;else if(/\s/.test(a))i(),s++;else if(a===";"||a==="|"||a==="&"){i();let l=n.slice(s,s+2);l==="&&"||l==="||"||l==="|&"?(t.push(l),s+=2):(t.push(a),s++)}else r+=a,o=!0,s++}return i(),t}function Jt(e){let n=ze(e);if(!n)return null;let t=[],r=0,o=!0;for(;r<n.length;){let s=n[r];if(Je.has(s)){o=!0,r++;continue}if(o&&s==="git"){let i=[],a=r+1;for(;a<n.length&&!Je.has(n[a]);)i.push(n[a++]);let l=0;for(;l<i.length;){let c=i[l];if(jn.has(c))l+=2;else if(c.startsWith("-"))l+=1;else break}t.push({globals:i.slice(0,l),subcommand:i[l]??null,args:i.slice(l+1)}),r=a,o=!1;continue}o=!1,r++}return t}function qs(e){let n=Jt(e);if(!n)return null;let t=n.find(c=>c.subcommand==="commit");if(!t)return null;let r=[];for(let c=0;c<t.args.length;c++){let d=t.args[c];if(d==="-m"||d==="--message"){let u=t.args[c+1];if(u===void 0)break;r.push(u),c++;continue}d.startsWith("-m")&&d!=="-m"?r.push(d.slice(2)):d.startsWith("--message=")&&r.push(d.slice(10))}if(r.length)return r.join(`
|
|
11
16
|
|
|
12
|
-
`)
|
|
13
|
-
|
|
14
|
-
`)
|
|
17
|
+
`);if(!t.args.some((c,d)=>(c==="-F"||c==="--file")&&t.args[d+1]==="-"||c==="-F-"||c==="--file=-"))return null;let s=_n(e),i=s===null?-1:e.indexOf(`
|
|
18
|
+
`,s.end)+1;if(s===null||i===0)return null;let{body:a,end:l}=In(e,i,s);return a===l?null:e.slice(i,a).trim()||null}function fe(e){return`'${e.replace(/'/g,"'\\''")}'`}function Js(e){let n=[],t=ze(e),r=t?.[1];t?.[0]==="cd"&&r!==void 0&&!r.startsWith("-")&&!Je.has(r)&&Je.has(t[2]??"")&&n.push("-C",fe(r));let o=Jt(e)?.[0];if(!o)return n.join(" ");for(let s=0;s<o.globals.length-1;s++)o.globals[s]==="-C"&&n.push("-C",fe(o.globals[s+1]));return n.join(" ")}function zs(e,n){return new RegExp(`^[ \\t]*${ce(n)}[ \\t]*:`,"im").test(e)}function Ys(e,n,t=[]){let r=new Set(t),o=new Set;for(let s of e.split(`
|
|
19
|
+
`)){if(!s.startsWith("+")||s.startsWith("+++"))continue;let i=s.slice(1);for(let a of n){let l=new RegExp(a,"g"),c;for(;(c=l.exec(i))!==null;)c[1]!==void 0&&!r.has(c[1])&&o.add(c[1]),c[0]===""&&l.lastIndex++}}return[...o]}function Zs(e){let{message:n,state:t,whenChanged:r,whenAdded:o,except:s,namesAdded:i,token:a}=e,l=new Set(t.added),c=[];for(let d of t.changed)s&&M(d,s)||(l.has(d)&&o&&M(d,o)?c.push(`\`${d}\` (new)`):r&&M(d,r)&&c.push(`\`${d}\` (changed)`));for(let{name:d,file:u}of i??[])c.push(`\`${d}\` (added in ${u})`);return c.length?zs(n,a)?[]:[`${c.join(" \xB7 ")} \u2014 and this commit's message records no reason. Put \`${a}: <why>\` on a line of its own in the message; the act is fine, doing it silently is not.`]:[]}function Pn(e){return e.split(`
|
|
20
|
+
`).map(n=>n.trim()).filter(Boolean)}var td=I(e=>async n=>{let t=qs(n.command??"");if(t==null)return n.ok();let r=`git ${Js(n.command??"")}`.trimEnd(),o={changed:[],added:[]};if(e.whenChanged||e.whenAdded){let[a,l,c]=await Promise.all([n.exec(`${r} diff HEAD --name-only`),n.exec(`${r} diff HEAD --name-only --diff-filter=A`),n.exec(`${r} ls-files --others --exclude-standard`)]);if(a.code!==0||l.code!==0||c.code!==0)return n.ok();let d=Pn(c.stdout);o={changed:[...new Set([...Pn(a.stdout),...d])],added:[...Pn(l.stdout),...d]}}let s=[];for(let a of e.diffAdds??[]){let l=await n.exec(`${r} diff HEAD -- ${fe(a.file)}`);if(l.code!==0)return n.ok();for(let c of Ys(l.stdout,a.patterns,a.known??[]))s.push({name:c,file:a.file})}let i=Zs({message:t,state:o,whenChanged:e.whenChanged,whenAdded:e.whenAdded,except:e.except,namesAdded:s,token:e.token});return oe(n,i)});function Xs(e,n,t){if(t===""||n.length===0)return!1;let r=-1,o=-1;return e.forEach((s,i)=>{s.did==="edit"&&M(s.path,n)&&(r=i),s.did==="run"&&s.command.includes(t)&&(o=i)}),r>=0&&r>o}var rd=I(e=>n=>n.turn&&Xs(n.turn,e.edited,e.mustRun)?n.fail(`edited ${e.edited.join(", ")} this turn but never ran \`${e.mustRun}\` afterwards`):n.ok());function Qs(e,n){let t=n??[];return!t.length||!e.length?!1:!e.some(r=>M(r,t))}function zt(e,n=8){let t=e.trim().split(`
|
|
15
21
|
`).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,n).join(`
|
|
16
|
-
`)}var
|
|
17
|
-
${
|
|
18
|
-
`)}function
|
|
19
|
-
`),[...
|
|
22
|
+
`)}var od=I(e=>async n=>{let t=await Vt(n);if(Qs(t,e.changed))return n.ok();let r=e.run.includes("{files}");if(r&&t.length===0)return n.ok();let o=r?e.run.replace("{files}",t.map(fe).join(" ")):e.run,s=await n.exec(o);return s.code===0?n.ok():n.fail(`\`${o}\` failed (exit ${s.code}):
|
|
23
|
+
${zt(s.stderr||s.stdout)}`)});function qe(e){let n=xn(e),t=n[n.length-1]?.kind==="globstar";return`^${(t?n.slice(0,-1):n).map(Sn).join("")}${t?"":"$"}`}function Ht(e){return e==="node:*"?{core:!0}:e.startsWith("node:")?{path:`^${ce(e)}$`}:e.includes("/")||e.includes("*")||e.includes(".")?{path:qe(e)}:{path:`node_modules/${ce(e)}(/|$)`}}function Ye(e){return e===void 0?{path:[],not:[]}:Array.isArray(e)?{path:e,not:[]}:{path:e.path,not:e.not??[]}}function Ve(e,n){let t=[],r=[],o=!1;for(let i of e){let{path:a,not:l}=Ye(n[i]);for(let c of a){let d=Ht(c);d.core?o=!0:d.path&&t.push(d.path)}for(let c of l){let d=Ht(c);d.path&&r.push(d.path)}}let s={};return t.length&&(s.path=t),r.length&&(s.pathNot=r),o&&(s.dependencyTypes=["core"]),s}function ei(e){let n=e.layers,t=[],r=[],o=(e.except??[]).includes("type-only"),s=a=>o?{...a,dependencyTypesNot:["type-only"]}:a;for(let[a,l]of Object.entries(e.only??{})){let d={pathNot:Ve(l,n).path??[]};t.push({name:`${a}-only`,severity:"error",comment:`${a} may import only: ${l.join(", ")} \u2014 an unlisted import blocks here (add it to a layer, or keep it out).`,from:Ve([a],n),to:s(d)})}for(let a of e.forbid??[])if(a==="circular")t.push({name:"no-circular",severity:"error",comment:"no dependency cycles",from:{pathNot:"node_modules"},to:{circular:!0}});else if(a==="orphans")t.push({name:"no-orphans",severity:"warn",comment:"unreferenced module",from:{orphan:!0,pathNot:"node_modules|\\.d\\.ts$"},to:{}});else if(a.cyclesBetween!==void 0){let l=a.cyclesBetween,c=Ye(n[l]).path[0]??"",d=qe(c).replace(/\$$/,"").replace(/\[\^\/\]\*$/,"([^/]+)");t.push({name:`no-cycles-between-${l}`,severity:"error",comment:a.why??`${l} must not import sideways`,from:{path:`${d}/`},to:s({path:`${d.replace(/\(\[\^\/\]\+\)/,"[^/]+")}/`,pathNot:"$1/"})})}else if(a.from!==void 0&&a.to!==void 0){let l={...Ve([a.to],n)};a.transitive===!0&&(l.reachable=!0),t.push({name:`no-${a.from}-to-${a.to}${a.transitive===!0?"-transitive":""}`,severity:"error",comment:a.why??`${a.from} must not import ${a.to}`,from:Ve([a.from],n),to:s(l)})}for(let a of e.require??[])r.push({name:`must-import-${a.import}`,severity:"error",comment:a.why??`modules in ${a.in} must import ${a.import}`,module:{path:qe(a.in)},to:{path:qe(a.import)}});for(let a of e.warn??[])a==="sdp"&&t.push({name:"sdp",severity:"warn",comment:"depends on a more-unstable module (Stable Dependencies Principle)",from:{},to:{moreUnstable:!0}});let i={enhancedResolveOptions:{extensions:[".js",".jsx",".ts",".tsx",".mjs",".cjs",".json"]},doNotFollow:{path:"node_modules"},tsPreCompilationDeps:!1,...e.options??{}};return{forbidden:t,required:r,options:i}}var Ut="FLOW_DEPCRUISE_CONFIG";function ni(e){let n=JSON.stringify(ei(e));return["d=$(mktemp -d)",`cat > "$d/dc.json" <<'${Ut}'`,n,Ut,`npx --no-install depcruise --config "$d/dc.json" --output-type json ${fe(e.scan)}`,"rc=$?",'rm -rf "$d"',"exit $rc"].join(`
|
|
24
|
+
`)}function ti(e){let n;try{n=JSON.parse(e.stdout||"")}catch{return e.code===0?[]:[`depcruise failed (exit ${e.code}): ${zt(e.stderr||e.stdout,3)}`]}return(n.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}`:""}`})}function ri(e){let n=[];for(let[t,r]of Object.entries(e)){let{path:o,not:s}=Ye(r);s.includes("node:*")&&n.push(`binds a depcruise layer \`${t}\` whose \`not\` list excludes \`node:*\`. A builtin is matched as a dependency TYPE, not a path, and the only exclusion available says "not a core module at all" \u2014 wider than this layer means. Say the layer's globs without it, or forbid the edge you actually mean.`);for(let i of[...o,...s])_t(i)&&n.push(`binds a depcruise layer \`${t}\` whose entry is a regular expression, not a glob: \`${i}\`. Layers are GLOBS here \u2014 \`src/pages/**\`, \`src/lib/auth/**\` \u2014 and a regex is escaped into a literal, so the fence would load, report armed and match nothing. For a layer with holes in it, say \`{ path: ["src/pages/**"], not: ["src/pages/api/**"] }\` rather than a lookahead.`)}return n}function oi(e){let n=[];for(let[t,r]of Object.entries(e.only??{}))for(let o of r)Ye(e.layers[o]).not.length>0&&n.push(`binds a depcruise \`only\` for \`${t}\` naming the layer \`${o}\`, which has a \`not\` list. An allowlist is compiled by inverting the layers it names, and that inversion reads \`path\` alone \u2014 so \`${o}\`'s exclusions would be silently dropped and the allowlist would be wider than it reads. Give \`${o}\` plain globs, or say the exclusion as a \`forbid\` edge.`);return n}var sd=I(e=>An(async t=>oe(t,ti(await t.exec(ni(e))),`
|
|
25
|
+
`),[...ri(e.layers),...oi(e)])),Yt={html:"Html",css:"Css",javascript:"JavaScript",js:"JavaScript",typescript:"TypeScript",ts:"TypeScript",tsx:"Tsx",jsx:"Tsx"},si=Object.keys(Yt),Tn=new Set,Kt=Symbol.for("flow.grammars");function Zt(){let e=globalThis,n=e[Kt];if(n!==void 0)return n;let t={declared:[],present:()=>!1};return e[Kt]=t,t}function Fn(e,n){return`\`${e}\`: no library at ${n}. 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.`}function Xt(e,n=()=>!1){let t=Zt();t.declared=e,t.present=n}async function ii(e){let{Lang:n,registerDynamicLanguage:t}=await import("@ast-grep/napi"),r=Yt[e];if(r!==void 0)return{ok:!0,lang:n[r]};if(Tn.has(e))return{ok:!0,lang:e};let{declared:o,present:s}=Zt(),i=o.find(a=>a.name===e);if(i!==void 0)return s(i.libraryPath)?(t({[e]:{libraryPath:i.libraryPath,extensions:[...i.extensions],...i.languageSymbol===void 0?{}:{languageSymbol:i.languageSymbol}}}),Tn.add(e),{ok:!0,lang:e}):{ok:!1,detail:Fn(e,i.libraryPath)};try{let a=await import(`@ast-grep/lang-${e}`);return t({[e]:a.default??a}),Tn.add(e),{ok:!0,lang:e}}catch{return{ok:!1,detail:`unknown ast-grep grammar: '${e}'. Built in: ${si.join(", ")}. Anything else is either a published package \u2014 \`npm i -D @ast-grep/lang-${e}\` \u2014 or a grammar you build yourself and declare in flow.config.ts's \`grammars\` setting.`}}}async function ai(e,n,t){let r=await ii(t);if(!r.ok)return r;let{parse:o}=await import("@ast-grep/napi");return{ok:!0,hits:o(r.lang,e).root().findAll({rule:n}).map(i=>`${i.range().start.line+1}: ${i.text()}`)}}var id=I(e=>async n=>{let t=await ai(ge(n).content,e.rule,e.language);return t.ok?oe(n,t.hits):n.fail(t.detail)}),li={command:["command"],write:["write","delete"],commit:["commit"],"turn-end":["turn-end"]};function Qt(e){if(typeof e=="string")return{dialect:"command",facts:{command:e},world:{}};let n=e.world??{},t={actor:e.actor??[]};return"command"in e?{dialect:"command",facts:{command:e.command,...t},world:n}:"path"in e?{dialect:"write",facts:{file:{path:e.path,content:e.content},...t},world:n}:"staged"in e?{dialect:"commit",facts:{staged:e.staged,...t},world:n}:{dialect:"turn-end",facts:{turn:e.actions,...t},world:n}}function di(e,n){let{world:t,facts:r}=Qt(e);return{world:Ke(t,r.staged,n),facts:r}}async function ci(e,n,t,r){let{world:o,facts:s}=di(t,r);return(n==="commit"?await ui(e,s,o):[s]).map(a=>Ue(n,a,o))}async function ui(e,n,t){let r=n.staged??[];if(!e.spec.on)return[n];let o=[];for(let s of r)re(e.spec,s)&&await t.fs.exists(s)&&o.push({file:{path:s,content:await t.fs.read(s)},staged:r});return o}async function fi(e,n,t,r,o){let{dialect:s}=Qt(t),i=e.spec.kind==="guardrail"?e.spec.at??[]:[],a=i.find(p=>li[s].includes(p)),l={entry:e.id,expect:r,index:o};if(a===void 0)return{...l,ok:!1,detail:`this case speaks the ${s} dialect, and the entry fires at ${i.length?i.join(", "):"no moment at all"} \u2014 nothing here would ever be handed one`};let c=[],d,u={ok:!0};try{let p=[];for(let y of await ci(e,a,t,c))p.push(await n(y));u=p.find(y=>!y.ok)??{ok:!0},d=!u.ok}catch(p){return{...l,ok:!1,detail:`the check threw: ${p.message}`}}if(c.length)return{...l,ok:!1,detail:gi(c)};let f=r==="block";if(d===f)return{...l,ok:!0,detail:""};if(f)return{...l,ok:!1,detail:"expected a block and the check passed it \u2014 the rule does not catch what it says it catches"};let g=u.ok||u.detail===void 0?"":`: ${u.detail}`;return{...l,ok:!1,detail:`expected a pass and the check blocked it${g}`}}function gi(e){return e.map(n=>n.kind==="exec"?`the check ran \`${n.asked}\` and the case records no answer \u2014 add it under \`world.exec\``:`the check read \`${n.asked}\` and the case records no content \u2014 add it under \`world.fs\``).join(" \xB7 ")}async function er(e){let n=[];for(let t of e){let{spec:r}=t;if(r.kind!=="guardrail"||r.disabled||!r.check)continue;let o=r.check,s=r.test??{};for(let[i,a]of[["pass",s.pass],["block",s.block]])for(let[l,c]of(a??[]).entries())n.push(await fi(t,o,c,i,l))}return n}import{spawnSync as Ko}from"node:child_process";import{copyFileSync as Ia,existsSync as mn,mkdirSync as Na,readdirSync as Vo,readFileSync as be,rmSync as De,statSync as St,writeFileSync as qo}from"node:fs";import{homedir as Jo}from"node:os";import{dirname as Ho,isAbsolute as zo,join as K,resolve as Rt}from"node:path";import{pathToFileURL as Fa}from"node:url";import{join as X}from"node:path";function or(e){let n=[];for(let t of e)for(let r of t.spec.for??[])On(r)&&!n.some(o=>o.name===r.name)&&n.push(r);return n}function sr(e,n,t){if(e)return{wearing:e,faults:[],fresh:!1};let r=[],o=[];for(let s of t)try{s.classify(n)&&r.push(s.name)}catch(i){o.push({category:s.name,error:i.message})}return{wearing:r,faults:o,fresh:!0}}function Gn(e,n){return e.disabled?!1:(e.at??[]).includes(n)}function ir(e,n){return e.categories.length===0?!0:e.categories.some(t=>n.includes(t))}function Me(e,n){return(e.on?.length??0)>0&&re(e,n)}function Ze(e){return e.filter(n=>n.disabled===null&&(n.on?.length??0)>0)}async function pi(e,n,t){let{spec:r}=e;if(n.moment==="commit"){let o=n.staged??[];if(!r.on)return[{name:null,facts:{staged:o}}];let s=[];for(let i of o)re(r,i)&&await t.fs.exists(i)&&s.push({name:i,facts:{file:{path:i,content:await t.fs.read(i)},staged:o}});return s}if(n.moment==="write"||n.moment==="delete"){let o=n.file;return!o||!re(r,o.path)?[]:[{name:o.path,facts:{file:o}}]}if(n.moment==="command"){let o=n.command??"";return[{name:o,facts:{command:o}}]}return[{name:null,facts:{turn:n.turn??[]}}]}var Bn=["session","first-touch","drift","fault"],yi={effects:[],tallies:[]};function ye(e){return{do:"block",entry:null,message:e,subject:null,detail:""}}async function Xe({load:e,event:n,world:t,faults:r=[],off:o=!1}){if(o)return yi;if(!e.ok)return{effects:[ye(ue(e.refusals))],tallies:[]};if(r.length>0)return{effects:r.map(a=>ye(`flow: the category \`${a.category}\` could not classify this session, so a rule scoped to it cannot be trusted either way \u2014 ${a.error}`)),tallies:[]};let s=[],i=[];for(let a of e.entries){if(a.spec.kind!=="guardrail"||!Gn(a.spec,n.moment))continue;if(!ir(a,n.wearing)){i.push({id:a.id,evaluated:0,hits:0,silenced:1});continue}let l=a.spec.check;if(!l){s.push(ye(`flow: \`${a.id}\` fires at ${n.moment} and carries no check. A rail that cannot ask a question is not a rail that passes.`));continue}let c=0,d=0;for(let u of await pi(a,n,t)){c+=1;let f=await mi(l,Ue(n.moment,{...u.facts,actor:n.wearing},t));f.ok||(d+=1,s.push({do:"block",entry:a.id,message:a.spec.message??"",subject:u.name,detail:f.detail??""}))}i.push({id:a.id,evaluated:c,hits:d,silenced:0})}return{effects:s,tallies:i}}async function mi(e,n){try{return await e(n)}catch(t){return He.fail(`the check threw: ${t.message}`)}}var hi=2e5;function ki(e){return e.driftTokens??hi}function Dn({load:e,event:n,marks:t,settings:r,off:o=!1}){if(o)return{notices:[],marks:t};if(!e.ok)return{notices:[{do:"notice",entry:null,text:ue(e.refusals),file:void 0,cause:"fault"}],marks:t};let s=[],i={...t},a=ki(r);for(let l of e.entries){if(l.spec.kind!=="breadcrumb"||!Gn(l.spec,n.moment)||!ir(l,n.wearing)||n.path!==void 0&&!re(l.spec,n.path)||n.command!==void 0&&!re(l.spec,n.command))continue;let c=i[l.id],d=n.moment==="session"?"session":c===void 0?"first-touch":"drift";c!==void 0&&(d!=="drift"||n.tokens-c<a)||(s.push({do:"notice",entry:l.id,text:l.spec.text,file:l.spec.file,cause:d}),i[l.id]=n.tokens)}return{notices:s,marks:i}}function Wn(e,n){let t=new Set(n.filter(o=>Gn(o.spec,"session")).map(o=>o.id)),r={};for(let[o,s]of Object.entries(e))t.has(o)&&(r[o]=s);return r}function ar(e){let t=[e.entry===null?e.message:`\u2717 ${e.entry}${e.subject?` \xB7 ${e.subject}`:""}`];return e.entry!==null&&e.message&&t.push(` ${e.message}`),e.detail&&t.push(...e.detail.split(`
|
|
20
26
|
`).map(r=>` ${r}`)),t.join(`
|
|
21
|
-
`)}var
|
|
27
|
+
`)}var G=".flow",lr=`# flow's own state \u2014 telemetry and session marks, never committed.
|
|
22
28
|
*
|
|
23
|
-
`,
|
|
24
|
-
`);for(let t=n.length-1;t>=0;t--){let r=n[t];if(!(!r||!r.trim()))try{let o=JSON.parse(r).seq;if(typeof o=="number"&&Number.isFinite(o)&&o>=0)return Math.floor(o)+1}catch{continue}}return 1}function
|
|
25
|
-
`)){if(s.trim()==="")continue;let i;try{i=JSON.parse(s)}catch{continue}if(typeof i!="object"||i===null||Array.isArray(i))continue;let a=i;if(typeof a.v=="number"){r=a.v,typeof a.session=="string"&&(t=a.session);continue}(a.rail==="guard"||a.rail==="brief"||a.rail==="compaction")&&o.push(a)}return{v:r,session:t,steps:o}}function
|
|
26
|
-
`),
|
|
27
|
-
`,a+=1;return
|
|
28
|
-
`))if(r.trim())try{let o=JSON.parse(r);typeof o.kind=="string"&&n.push(o)}catch{continue}}catch{}return n}function
|
|
29
|
-
`),
|
|
29
|
+
`,bi=1;function J(e){return X(e,G)}function Z(e){return(e||"nosession").replace(/[^A-Za-z0-9_-]/g,"-")}function Ln(e,n){return X(J(e),"log",`${Z(n)}.jsonl`)}function Hn(e,n,t){return X(J(e),"state",`${Z(n)}-${Z(t)}.json`)}function Un(e){if(e==null||e.trim()==="")return{marks:{}};let n;try{n=JSON.parse(e)}catch{return{marks:{}}}if(typeof n!="object"||n===null)return{marks:{}};let t=n,r=Array.isArray(t.categories)&&t.categories.every(s=>typeof s=="string")?t.categories:void 0,o={};if(typeof t.marks=="object"&&t.marks!==null)for(let[s,i]of Object.entries(t.marks))typeof i=="number"&&Number.isFinite(i)&&(o[s]=i);return r===void 0?{marks:o}:{categories:r,marks:o}}function Kn(e,n){return X(J(e),n?`.session-${Z(n)}`:".session")}function dr(e){return X(J(e),"off")}function cr(e){return X(J(e),"record")}function ur(e,n){return X(J(e),"replay",`${Z(n)}.jsonl`)}function Qe(e){return X(J(e),"read")}function fr(e,n){return X(Qe(e),Z(n))}var wi=14400*1e3;function gr(e,n,t,r=wi){let o={session:n,agent:null};if(!e||typeof e.session!="string"||!e.session)return o;let s=Date.parse(String(e.ts));return!Number.isFinite(s)||Math.abs(t-s)>r?o:{session:e.session,agent:typeof e.agent=="string"&&e.agent?e.agent:null}}function pr(e){let n=e.split(`
|
|
30
|
+
`);for(let t=n.length-1;t>=0;t--){let r=n[t];if(!(!r||!r.trim()))try{let o=JSON.parse(r).seq;if(typeof o=="number"&&Number.isFinite(o)&&o>=0)return Math.floor(o)+1}catch{continue}}return 1}function yr(e,n,t,r){return{kind:"meta",v:bi,session:Z(e),started:r,branch:n,worktree:t}}function $e(e,n,t){let r=[{kind:"run",moment:e,subjects:t,rules:n.tallies}];for(let o of n.effects)o.do==="block"?r.push({kind:"guardrail",moment:e,id:o.entry,subject:o.subject,out:"deny",message:o.message,detail:o.detail}):r.push({kind:"breadcrumb",moment:e,id:o.entry,cause:o.cause});return r}function Ce(e){return e.map(n=>{let t=n.spec,r=t.kind==="guardrail"?t.message??null:t.text??t.file??null;return{kind:t.kind,id:n.id,pack:n.pack,at:[...t.at??[]],on:t.on,ignore:t.ignore,for:[...n.categories],description:t.description??null,says:r,disabled:t.disabled?t.disabled.reason??"":null}})}var nr=864e5;var xi=()=>({median:null,buckets:{0:0,"1-5":0,"6-19":0,"20+":0},noEdit:0});function Si(e){return e<=0?"0":e<=5?"1-5":e<=19?"6-19":"20+"}function Ri(e){if(e.length===0)return null;let n=[...e].sort((r,o)=>r-o),t=Math.floor(n.length/2);return n.length%2?n[t]:(n[t-1]+n[t])/2}function tr(e,n){let t={0:0,"1-5":0,"6-19":0,"20+":0};for(let r of e)t[Si(r)]+=1;return{median:Ri(e),buckets:t,noEdit:n}}var rr=e=>e.includes("/")?e.slice(0,e.lastIndexOf("/")):".";function Ee(e){return e!==""&&!e.startsWith("/")&&!e.startsWith("..")}function N(e,n){let t=e[n];return typeof t=="string"&&t!==""?t:null}function Vn(e){return N(e,"subject")??N(e,"path")??N(e,"command")}function vi(e){return e.kind==="tool"&&e.edit===!0&&Vn(e)!==null&&N(e,"path")!==null}function mr({sessions:e,entries:n,nowMs:t,minSessions:r=15,minDays:o=30}){let s=n.filter(k=>k.disabled===null),i=new Map(s.map(k=>[k.id,k])),a=Ze(n),l=new Map,c=new Map,d={},u={},f={},g=[],p=k=>{let S=l.get(k);return S===void 0&&(S={count:0,byCause:Object.fromEntries(Bn.map(H=>[H,0])),last:null,samples:[],noEdit:0},l.set(k,S)),S},y=k=>{let S=c.get(k);return S===void 0&&(S={runs:0,evaluated:0,hits:0,silenced:0,sessions:new Set,lastBlock:null,lastHit:null,repeats:0},c.set(k,S)),S},b=0,h=0;for(let{session:k,rows:S}of e){let H=[],xe=[],le=new Set,de=0;for(let E of S){let L=N(E,"ts");L!==null&&g.push(L);let Se=E.kind==="tool";if(Se||E.kind==="read"||E.kind==="write"){Se&&(de+=1,h+=1);let C=N(E,"path");if(C===null||!Ee(C)||(d[C]=(d[C]??0)+1,Se?!vi(E):E.kind==="read"))continue;u[C]=(u[C]??0)+1,H.push({at:de,path:C}),a.some(O=>Me(O,C))||(f[C]=(f[C]??0)+1);continue}if(E.kind==="compaction"){le.clear();continue}if(E.kind==="breadcrumb"){let C=N(E,"id");if(C===null)continue;let O=p(C);O.count+=1;let U=N(E,"cause");U!==null&&Bn.includes(U)&&(O.byCause[U]+=1),L!==null&&(O.last===null||L>O.last)&&(O.last=L),N(E,"moment")==="touch"&&(i.get(C)?.on?.length??0)>0&&xe.push({id:C,at:de});continue}if(E.kind==="run"){let C=E.rules??[];for(let O of C){if(typeof O?.id!="string")continue;let U=y(O.id);U.runs+=1,U.evaluated+=O.evaluated??0,U.silenced+=O.silenced??0,U.sessions.add(k)}continue}if(E.kind==="guardrail"&&E.out==="deny"){let C=N(E,"id");if(C===null)continue;let O=y(C);O.hits+=1,b+=1;let U=Vn(E);O.lastBlock={ts:L,subject:U},L!==null&&(O.lastHit===null||L>O.lastHit)&&(O.lastHit=L);let Mt=`${C} ${U??""}`;le.has(Mt)?O.repeats+=1:le.add(Mt)}}for(let E of xe){let L=i.get(E.id),Se=L===void 0?void 0:H.find(O=>O.at>=E.at&&Me(L,O.path)),C=p(E.id);Se===void 0?C.noEdit+=1:C.samples.push(Se.at-E.at)}}let R=[...g].sort(),$=R[0]??null,A=R[R.length-1]??null,P=e.filter(k=>k.session!=="commit"&&k.rows.length>0).length,_=$!==null&&A!==null?Math.round((Date.parse(A)-Date.parse($))/nr):0,m=P>=r||_>=o,v=new Set;for(let k of s)k.kind==="breadcrumb"&&(l.get(k.id)?.count??0)>0&&v.add(k.pack);let j=s.filter(k=>k.kind==="breadcrumb").map(k=>{let S=l.get(k.id);return{id:k.id,pack:k.pack,shown:S?.count??0,byCause:S?.byCause??Object.fromEntries(Bn.map(H=>[H,0])),lead:S===void 0?xi():tr(S.samples,S.noEdit),last:S?.last??null,dead:m&&(k.on?.length??0)>0&&(S?.count??0)===0&&v.has(k.pack)}}),W=s.filter(k=>k.kind==="guardrail").map(k=>{let S=c.get(k.id),H=S?.runs??0,xe=S?.evaluated??0;return{id:k.id,pack:k.pack,runs:H,evaluated:xe,hits:S?.hits??0,silenced:S?.silenced??0,lastBlock:S?.lastBlock??null,repeats:S?.repeats??0,dead:m&&(k.on?.length??0)>0&&H>0&&xe===0}}),x=new Map;for(let[k,S]of Object.entries(f))x.set(rr(k),(x.get(rr(k))??0)+S);let F=[...x.entries()].map(([k,S])=>({area:k,edits:S})).sort((k,S)=>S.edits-k.edits||k.area.localeCompare(S.area)),B=[],q=[],bn=[];for(let k of s){let S=c.get(k.id),H=l.get(k.id);if((S?.evaluated??0)+(H?.count??0)===0){(m?B:q).push(k.id);continue}let le=S?.lastHit??null;if(le===null)continue;let de=Math.round((t-Date.parse(le))/nr);m&&Number.isFinite(de)&&de>o&&bn.push({id:k.id,lastHit:le,daysSince:de})}let wn=[...l.values()].flatMap(k=>k.samples),ps=[...l.values()].reduce((k,S)=>k+S.noEdit,0),ys=[...j,...W].filter(k=>k.dead).map(k=>k.id).sort();return{headline:{blocks:b,lead:tr(wn,ps),gaps:F,dead:ys,retire:B.sort(),unproven:q.sort(),quiet:bn.sort((k,S)=>S.daysSince-k.daysSince)},breadcrumbs:j,guardrails:W,gaps:F,span:{sessions:P,days:_,first:$,last:A,ample:m,tools:h},heat:{touches:d,edits:u,uncovered:f}}}function hr({paths:e,heat:n,entries:t}){let r=new Set([...e,...Object.keys(n.touches),...Object.keys(n.edits)]),o=Ze(t),s=new Map,i=(a,l)=>{let c=s.get(a);return c===void 0&&(c={path:a,name:a.slice(a.lastIndexOf("/")+1),dir:l,depth:a.split("/").length-1,touches:0,edits:0,entries:[],uncovered:0},s.set(a,c)),c};for(let a of r){let l=a.split("/"),c=o.filter(g=>Me(g,a)).map(g=>g.id),d=n.touches[a]??0,u=n.edits[a]??0,f=n.uncovered[a]??0;for(let g=0;g<l.length;g++){let p=l.slice(0,g+1).join("/"),y=i(p,g<l.length-1);y.touches+=d,y.edits+=u,y.uncovered+=f;for(let b of c)y.entries.includes(b)||y.entries.push(b)}}for(let a of s.values())a.entries.sort();return[...s.values()].sort($i)}function $i(e,n){let t=e.path.split("/"),r=n.path.split("/");for(let o=0;o<Math.min(t.length,r.length);o++){let s=t[o],i=r[o];if(s===i)continue;let a=o===t.length-1&&!e.dir,l=o===r.length-1&&!n.dir;return a!==l?a?1:-1:s.localeCompare(i)}return t.length-r.length}var Ci=["session","touch","write","delete","command","commit","turn-end"];function en(e,n){let t=new Map((n?.breadcrumbs??[]).map(s=>[s.id,s])),r=new Map((n?.guardrails??[]).map(s=>[s.id,s])),o=e.map(s=>({...s,record:(s.kind==="breadcrumb"?t.get(s.id):r.get(s.id))??null}));return{moments:Ci.map(s=>({moment:s,entries:o.filter(i=>i.at.includes(s))})).filter(s=>s.entries.length>0),totals:{breadcrumbs:o.filter(s=>s.kind==="breadcrumb").length,guardrails:o.filter(s=>s.kind==="guardrail").length,disabled:o.filter(s=>s.disabled!==null).length}}}var kr=1;function qn(e,n=""){let t=n,r=kr,o=[];for(let s of e.split(`
|
|
31
|
+
`)){if(s.trim()==="")continue;let i;try{i=JSON.parse(s)}catch{continue}if(typeof i!="object"||i===null||Array.isArray(i))continue;let a=i;if(typeof a.v=="number"){r=a.v,typeof a.session=="string"&&(t=a.session);continue}(a.rail==="guard"||a.rail==="brief"||a.rail==="compaction")&&o.push(a)}return{v:r,session:t,steps:o}}function br(e){return{v:kr,session:e}}async function wr({load:e,recording:n,settings:t,marks:r={}}){let o=[],s=[],i=[],a=r;for(let l of n.steps){if(l.rail==="compaction"){a=e.ok?Wn(a,e.entries):a;let u={kind:"compaction"};s.push(u),o.push({step:l,effects:[],rows:[u]});continue}if(l.rail==="guard"){let u=await Xe({load:e,event:{moment:l.moment,file:l.file,command:l.command,staged:l.staged,turn:l.turn,wearing:l.wearing},world:Ke(l.world??{},l.staged,i)}),f=$e(l.moment,u,l.moment==="commit"?l.staged?.length??0:1);s.push(...f),o.push({step:l,effects:u.effects,rows:f});continue}let c=Dn({load:e,event:{moment:l.moment,path:l.path,command:l.command,wearing:l.wearing,tokens:l.tokens},marks:a,settings:t});a=c.marks;let d=c.notices.length===0?[]:$e(l.moment,{effects:c.notices,tallies:[]},1);s.push(...d),o.push({step:l,effects:c.notices,rows:d})}return{steps:o,rows:s,unanswered:i,marks:a}}function xr(e,n){let t=i=>i.filter(a=>a.kind==="guardrail"||a.kind==="breadcrumb").map(a=>a.kind==="guardrail"?`guardrail ${N(a,"moment")??""} ${N(a,"id")??"\u2014"} ${a.out} ${Vn(a)??""}`.trim():`breadcrumb ${N(a,"moment")??""} ${N(a,"id")??"\u2014"} ${N(a,"cause")??""}`.trim()),r=t(e),o=t(n),s=[];for(let i=0;i<Math.max(r.length,o.length);i++){let a=r[i],l=o[i];a!==l&&(a!==void 0&&s.push({side:"replay",at:i,row:a}),l!==void 0&&s.push({side:"live",at:i,row:l}))}return s}function Jn(e){let n={},t={},r,o;return{world:{exec:async s=>{let i=await e.exec(s);return n[s]={stdout:i.stdout,stderr:i.stderr,code:i.code},i},fs:{read:async s=>{let i=await e.fs.read(s);return t[s]=i,i},exists:async s=>{let i=await e.fs.exists(s);return i&&(t[s]??=""),i}},git:{diff:async s=>{let i=await e.git.diff(s);return r??=i,i},stagedFiles:async()=>{let s=await e.git.stagedFiles();return o=[...s],s}}},taken:()=>({...Object.keys(n).length>0?{exec:n}:{},...Object.keys(t).length>0?{fs:t}:{},...r===void 0?{}:{gitDiff:r},...o===void 0?{}:{staged:o}})}}import{appendFileSync as Sr,closeSync as Ei,existsSync as _e,mkdirSync as Ie,openSync as Oi,readFileSync as nn,readSync as Ai,readdirSync as Rr,statSync as Pi,writeFileSync as Oe}from"node:fs";import{dirname as Yn,join as Ti}from"node:path";function Q(e){try{let n=J(e);Ie(n,{recursive:!0});let t=`${n}/.gitignore`;return _e(t)||Oe(t,lr),!0}catch{return!1}}function Ne(e){try{return _e(dr(e))}catch{return!1}}function tn(e,n,t){try{return Un(nn(Hn(e,n,t),"utf8"))}catch{return Un(null)}}function Zn(e,n,t,r){try{let o=Hn(e,n,t);return Q(e),Ie(Yn(o),{recursive:!0}),Oe(o,JSON.stringify(r)),!0}catch{return!1}}function vr(e,n,t,r,o){let s=tn(e,n,t),i=sr(s.categories,r,o);return i.fresh&&i.faults.length===0&&Zn(e,n,t,{...s,categories:i.wearing}),i}var ji=4096,zn=new Map;function Mi(e){let n=null;try{let t=Pi(e).size,r=Math.min(t,ji);if(r<=0)return"";let o=Buffer.alloc(r);return n=Oi(e,"r"),Ai(n,o,0,r,t-r),o.toString("utf8")}catch{return""}finally{if(n!==null)try{Ei(n)}catch{}}}function Xn(e,n){try{if(n.length===0)return!0;let{root:t,session:r,branch:o}=e,s=e.now??(()=>new Date),i=Ln(t,r);Q(t),Ie(Yn(i),{recursive:!0}),_e(i)||(Oe(i,`${JSON.stringify(yr(r,o,t,s().toISOString()))}
|
|
32
|
+
`),zn.set(i,1));let a=zn.get(i)??pr(Mi(i)),l="";for(let c of n)l+=`${JSON.stringify({ts:s().toISOString(),seq:a,...c})}
|
|
33
|
+
`,a+=1;return zn.set(i,a),Sr(i,l),!0}catch{return!1}}function Qn(e){let n=[];try{let t=nn(e,"utf8");for(let r of t.split(`
|
|
34
|
+
`))if(r.trim())try{let o=JSON.parse(r);typeof o.kind=="string"&&n.push(o)}catch{continue}}catch{}return n}function et(e,n){return Qn(Ln(e,n))}function _i(e){try{return Rr(Ti(J(e),"log")).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort()}catch{return[]}}function $r(e){return _i(e).map(n=>({session:n,rows:et(e,n)}))}function Cr(e){try{return new Set(Rr(Qe(e)).filter(n=>!n.startsWith(".")))}catch{return new Set}}function Er(e,n){try{Q(e),Ie(Qe(e),{recursive:!0})}catch{return 0}let t=0;for(let r of n)try{Oe(fr(e,r),""),t+=1}catch{}return t}function nt(e){try{return _e(cr(e))}catch{return!1}}function tt(e,n,t){try{if(t.length===0)return!0;let r=ur(e,n);return Q(e),Ie(Yn(r),{recursive:!0}),_e(r)||Oe(r,`${JSON.stringify(br(n))}
|
|
35
|
+
`),Sr(r,`${t.map(o=>JSON.stringify(o)).join(`
|
|
30
36
|
`)}
|
|
31
|
-
`),!0}catch{return!1}}function
|
|
32
|
-
`),!0}catch{return!1}}function
|
|
33
|
-
`]);function
|
|
37
|
+
`),!0}catch{return!1}}function Or(e){let n=e.slice(e.lastIndexOf("/")+1).replace(/\.jsonl$/,"");try{return qn(nn(e,"utf8"),n)}catch{return qn("",n)}}function Ar(e,n,t,r,o=new Date){try{return Q(e),Oe(Kn(e,r),`${JSON.stringify({session:n,agent:t,ts:o.toISOString()})}
|
|
38
|
+
`),!0}catch{return!1}}function Pr(e,n,t=Date.now()){let r=null;try{r=JSON.parse(nn(Kn(e,n),"utf8"))}catch{}return gr(r,"commit",t)}import{posix as sn}from"node:path";var T="flow.config.ts";function Ii(e){let n=[];for(let[,,t]of e.matchAll(/\b(?:from|import)\s*\(?\s*(['"])([^'"\n]+)\1/g)){if(t===void 0||!t.startsWith("."))continue;let r=t.replace(/^\.\//,"");r===""||r.split("/").includes("..")||n.includes(r)||n.push(r)}return n}function at(e){let n=[T];for(let t of Ii(e??"")){n.includes(t)||n.push(t);let r=t.includes("/")?`${t.slice(0,t.lastIndexOf("/"))}/**`:null;r!==null&&!n.includes(r)&&n.push(r)}return n}var lt=["session-start","pre-tool-use","post-tool-use","post-tool-use-failure","stop","notification"];function dt(e){return lt.includes(e)}var Nr={"session-start":"SessionStart","pre-tool-use":"PreToolUse","post-tool-use":"PostToolUse","post-tool-use-failure":"PostToolUseFailure",stop:"Stop",notification:"Notification"},an={guard:["write","delete","command","commit","turn-end"],brief:["session","touch","command"]};function w(e){return typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):""}function D(e,n){return n&&e.startsWith(`${n}/`)?e.slice(n.length+1):e}function Tr(e,{old_string:n="",new_string:t="",replace_all:r=!1}){if(n==="")return t;if(r)return e.split(n).join(t);let o=e.indexOf(n);return o===-1?null:e.slice(0,o)+t+e.slice(o+n.length)}function Ni(e,n,t){let r=n.file_path;if(!r)return null;let o=D(w(r),t.root);if(e==="Write")return{path:o,content:w(n.content??"")};if(e==="Edit"){let s=Tr(t.read(o)??"",n);return s===null?null:{path:o,content:s}}if(e==="MultiEdit"){let s=t.read(o)??"";for(let i of n.edits??[])if(s=Tr(s,i),s===null)return null;return{path:o,content:s}}return null}var Fi=[{words:["rm"],renames:!1},{words:["git","rm"],renames:!1},{words:["mv"],renames:!0},{words:["git","mv"],renames:!0}],Bi=new Set([";","&&","||","|","&","|&",`
|
|
39
|
+
`]);function Fr(e){let n=ze(e);if(n===null)return[];let t=[],r=[],o=()=>{let s=r;r=[];for(let i of Fi){if(!i.words.every((l,c)=>s[c]===l))continue;let a=s.slice(i.words.length).filter(l=>!l.startsWith("-"));t.push(...i.renames?a.length>=2?a.slice(0,-1):[]:a);return}};for(let s of n)Bi.has(s)?o():r.push(s);return o(),t}var rt={valued:["-e","-f","-A","-B","-C","-m","-d","-D","--regexp","--file","--include","--exclude","--exclude-dir","--max-count","--context","--after-context","--before-context","--color","--colour","--label"],fileOpts:["-f","--file"],skip:1,supplied:["-e","-f","--regexp","--file"],dflt:"recursive"},Gi={cat:{},less:{},more:{},tac:{},wc:{},cmp:{},file:{},md5sum:{},sha256sum:{},bat:{valued:["-l","-r","--language","--line-range","--style","--theme"]},nl:{valued:["-b","-w","-s","-v","-i"]},head:{valued:["-n","-c"]},tail:{valued:["-n","-c","-b","-s"]},sed:{valued:["-e","-f","-l","--expression","--file"],fileOpts:["-f","--file"],skip:1,supplied:["-e","-f","--expression","--file"]},awk:{valued:["-F","-v","-f"],fileOpts:["-f"],skip:1,supplied:["-f"]},jq:{valued:["-f","--from-file","--indent","--arg","--argjson","--slurpfile","--rawfile"],fileOpts:["-f","--from-file"],skip:1,supplied:["-f","--from-file"]},grep:rt,egrep:rt,fgrep:rt,rg:{valued:["-e","-f","-g","-t","-T","-A","-B","-C","-m","-M","-d","-j","-r","-E","--regexp","--file","--glob","--iglob","--type","--type-not","--type-add","--max-count","--max-columns","--max-depth","--threads","--replace","--encoding","--sort","--sortr","--context","--after-context","--before-context","--ignore-file","--pre","--max-filesize","--colors","--color"],fileOpts:["-f","--file","--ignore-file"],skip:1,supplied:["-e","-f","--regexp","--file","--files","--type-list"],dflt:".",searches:!0},find:{stop:!0,dflt:".",searches:!0},ls:{valued:["-I","--ignore","--hide","-w","--width"],dflt:".",searches:!0},du:{valued:["-d","-B","--max-depth"],dflt:".",searches:!0},tree:{valued:["-L","-I","-P"],dflt:".",searches:!0},diff:{valued:["-U","-C","-x","-X","-I","-L","--label","--exclude"]},cut:{valued:["-d","-f","-c","-b"]},sort:{valued:["-k","-t","-o","-S","-T"]},uniq:{valued:["-f","-s"]},column:{valued:["-s","-c"]},xxd:{valued:["-l","-s","-c","-g"]},od:{valued:["-N","-j","-t","-A"]},hexdump:{valued:["-n","-s","-e"]},strings:{valued:["-n"]},md5:{valued:["-s"]},shasum:{valued:["-a"]},cp:{valued:["-t","-S"],lastIsDest:!0}},Di=new Set(["diff","log","show","status","add","blame","ls-files","grep"]),jr={timeout:{valued:["-s","-k","--signal","--kill-after"],positional:1},nohup:{valued:[]},time:{valued:[]},nice:{valued:["-n"]},sudo:{valued:["-u","-g","-C"]},env:{valued:["-u","-C"]},stdbuf:{valued:["-i","-o","-e"]},command:{valued:[]},builtin:{valued:[]},exec:{valued:[]},xargs:{valued:["-a","--arg-file","-n","-I","-L","-P","-d","-E","-s"]}},Be=e=>e!==null&&e.startsWith("-")&&e!=="-";function Wi(e){let n=[],t=[],r=e,o=r[0]===void 0||r[0]===null?"":sn.basename(r[0]),s=jr[o];for(;s!==void 0;){if(o==="command"&&(r[1]==="-v"||r[1]==="-V"))return{reads:n,searched:t};let y=1;for(;;){let b=r[y]??null;if(Be(b))o==="xargs"&&(b==="-a"||b==="--arg-file")&&typeof r[y+1]=="string"&&n.push(r[y+1]),y+=s.valued.includes(b)?2:1;else if(o==="env"&&/^[A-Za-z_]\w*=/.test(b??""))y+=1;else break}r=r.slice(y+(s.positional??0)),o=r[0]===void 0||r[0]===null?"":sn.basename(r[0]),s=jr[o]}let i=r.slice(1);if(o==="git")return Li(i,n);if(o==="ffmpeg")return i.forEach((y,b)=>{let h=i[b+1];y==="-i"&&typeof h=="string"&&n.push(h)}),{reads:n,searched:t};let a=Gi[o];if(a===void 0)return{reads:n,searched:t};let l=[],c=!1,d=!1,u=!1;for(let y=0;y<i.length;y++){let b=i[y];if(a.stop===!0&&b!==null&&(b.startsWith("-")||b==="("||b==="!"))break;if(u||!Be(b)){l.push(b);continue}let h=b;if(h==="--"){u=!0;continue}let R=h.startsWith("--")?h.indexOf("="):-1,$=R===-1?h:h.slice(0,R);if(a.supplied?.includes($)===!0&&(c=!0),(/^-[a-zA-Z]*[rR]/.test(h)||h==="--recursive")&&(d=!0),o==="sed"&&h==="-i"&&(i[y+1]===""||/^\.\w+$/.test(i[y+1]??"")))y++;else if(R!==-1)a.fileOpts?.includes($)===!0&&n.push(h.slice(R+1));else if(a.valued?.includes($)===!0){let A=i[y+1];a.fileOpts?.includes($)===!0&&typeof A=="string"&&n.push(A),y++}}let f=l.slice(c?0:a.skip??0);a.lastIsDest===!0&&(f=f.slice(0,-1));let g=a.dflt==="recursive"&&d,p=a.searches===!0||g?t:n;for(let y of f)y!==null&&y!=="-"&&y!==""&&p.push(y);return f.length===0&&(a.dflt==="."||g)&&p.push("."),{reads:n,searched:t}}function Li(e,n){let t=[],r,o=0;for(let d=e[0]??null;Be(d);d=e[o]??null){let u=e[o+1];d==="-C"&&typeof u=="string"&&(r=u),o+=jn.has(d)?2:1}let s=e[o],i=r===void 0?{reads:n,searched:t}:{reads:n,searched:t,base:r};if(typeof s!="string"||!Di.has(s))return i;let a=e.slice(o+1),l=a.indexOf("--"),c=d=>d!==null&&!Be(d)&&!d.includes("..")&&!d.includes(":")&&(d.includes("/")||/\.\w+$/.test(d));return t.push(...l===-1?a.filter(c):a.slice(l+1).filter(d=>d!==null&&d!=="")),i}function Br(e,n){let t=e[n+1]??"";if(e.startsWith("((",n+1)){let o=e.indexOf("))",n+3);return{part:{kind:"unknown"},end:o===-1?e.length:o+2}}if(t==="("){let o=pe(e,n+2);return o===-1?{part:{kind:"unknown"},end:e.length}:{part:{kind:"subst",command:e.slice(n+2,o)},end:o+1}}if(t==="{"){let o=e.indexOf("}",n+2),s=o===-1?"":e.slice(n+2,o);return{part:/^[A-Za-z_]\w*$/.test(s)?{kind:"var",name:s}:{kind:"unknown"},end:o===-1?e.length:o+1}}let r=/^[A-Za-z_]\w*/.exec(e.slice(n+1))?.[0];return r!==void 0?{part:{kind:"var",name:r},end:n+1+r.length}:/[0-9@*#?$!-]/.test(t)?{part:{kind:"unknown"},end:n+2}:{part:{kind:"text",text:"$"},end:n+1}}function Gr(e,n,t){let r=e.indexOf("`",n+1);return r===-1||r>t?{part:{kind:"unknown"},end:t}:{part:{kind:"subst",command:e.slice(n+1,r)},end:r+1}}function Hi(e,n,t){let r=[],o="",s=()=>{o!==""&&r.push({kind:"text",text:o}),o=""};for(let i=n;i<t;){let a=e[i];if(a==="\\"&&/["\\$`]/.test(e[i+1]??""))o+=e[i+1],i+=2;else if(a==="$"||a==="`"){s();let l=a==="$"?Br(e,i):Gr(e,i,t);r.push(l.part),i=l.end}else o+=a,i++}return s(),r}var Ui=new Set([";","&","|","(",")","<",">",`
|
|
40
|
+
`," "," ","'",'"',"\\","$","`"]);function Ki(e){let n=[],t=[],r="",o=!1,s=()=>{r!==""&&t.push({kind:"text",text:r}),o&&n.push({t:"word",word:t}),t=[],r="",o=!1},i=0;for(;i<e.length;){let a=e[i],l=e.slice(i);if(l.startsWith(`\\
|
|
41
|
+
`))i+=2;else if(!o&&a==="#"){let c=e.indexOf(`
|
|
42
|
+
`,i);i=c===-1?e.length:c}else if(a===`
|
|
43
|
+
`)s(),n.push({t:"op",op:`
|
|
44
|
+
`}),i++;else if(a===" "||a===" ")s(),i++;else if(l.startsWith("<(")||l.startsWith(">(")){s();let c=pe(e,i+2);n.push({t:"word",word:[c===-1?{kind:"unknown"}:{kind:"subst",command:e.slice(i+2,c)}]}),i=c===-1?e.length:c+1}else if(a==="<"||a===">"||l.startsWith("&>")){o&&t.length===0&&/^\d+$/.test(r)&&(r="",o=!1),s();let c=/^(&>>|&>|<<<|<<-|<<|<>|<&|<|>>|>\||>&|>)/.exec(l)?.[0]??a;n.push({t:"redir",op:c}),i+=c.length}else if(a===";"||a==="&"||a==="|"||a==="("||a===")"){s();let c=e.slice(i,i+2),d=["&&","||","|&",";;"].includes(c)?c:a;n.push({t:"op",op:d}),i+=d.length}else if(o=!0,a==="'"||l.startsWith("$'")){let c=a==="'"?i:i+1,d=e.indexOf("'",c+1);if(d===-1)return null;r+=e.slice(c+1,d),i=d+1}else if(a==='"'){let c=je(e,i+1);if(c===-1)return null;r!==""&&t.push({kind:"text",text:r}),r="",t.push(...Hi(e,i+1,c)),i=c+1}else if(a==="\\")r+=e[i+1]??"",i+=2;else if(a==="$"||a==="`"){r!==""&&t.push({kind:"text",text:r}),r="";let c=a==="$"?Br(e,i):Gr(e,i,e.length);t.push(c.part),i=c.end}else if(a==="~"&&r===""&&t.length===0)t.push({kind:"tilde"}),i++;else for(;i<e.length&&!Ui.has(e[i]);)r+=e[i++]}return s(),n}var Vi=new Set(["if","then","else","elif","fi","while","until","{","}","!","esac","do","done"]);function me(e){let[n]=e??[];return e?.length===1&&n?.kind==="text"?n.text:null}function Mr(e){let n=Ki(Nn(e));if(n===null)return null;let t=[{nodes:[],kind:"top",loop:null}],r=()=>t[t.length-1],o=null,s=[],i=[],a=null,l=()=>{let d=t.pop();d.kind==="subshell"?r().nodes.push({kind:"subshell",body:d.nodes}):d.loop!==null?r().nodes.push({kind:"for",...d.loop,body:d.nodes}):r().nodes.push(...d.nodes)},c=()=>{let d=s;for(let u=me(d[0]);u!==null&&Vi.has(u);u=me(d[0]))u==="do"?(t.push({nodes:[],kind:"do",loop:o}),o=null):u==="done"&&r().kind==="do"&&l(),d=d.slice(1);if(me(d[0])==="for"){let u=d.findIndex(f=>me(f)==="in");o={name:me(d[1])??"",values:u===-1?[]:d.slice(u+1)}}else me(d[0])!=="case"&&(d.length>0||i.length>0)&&r().nodes.push({kind:"cmd",words:d,inputs:i});s=[],i=[]};for(let d of n)if(d.t==="redir")a=d.op;else if(d.t==="word")a===null?s.push(d.word):(a==="<"||a==="<>")&&i.push(d.word),a=null;else{a=null;let u=d.op==="("&&s.length===0;if(c(),u)t.push({nodes:[],kind:"subshell",loop:null});else if(d.op===")"&&t.some(f=>f.kind==="subshell")){for(;r().kind!=="subshell";)l();l()}}for(c();t.length>1;)l();return r().nodes}function ct(e,n){let t=[],r=[],o=(u,f)=>u.startsWith("/")?sn.resolve(u):f===null?null:sn.resolve(f,u),s=(u,f)=>{let g=f!==null&&f.startsWith(`${n.root}/`)?f.slice(n.root.length+1):null;g!==null&&!u.includes(g)&&u.push(g)},i=(u,f)=>{let g="";for(let p of u){let y=null;p.kind==="text"?y=p.text:p.kind==="tilde"||p.kind==="var"&&p.name==="HOME"?y=n.home:p.kind==="var"?y=f.vars.get(p.name):p.kind==="subst"&&a(p.command,f),g=g===null||y===null||y===void 0?null:g+y}return g},a=(u,f)=>{d(Mr(u)??[],{cwd:f.cwd,old:f.old,vars:new Map(f.vars)})},l=(u,f)=>{let[g,...p]=u,y=g?.kind==="text"?/^([A-Za-z_]\w*)=/.exec(g.text):null;if(y===null||g?.kind!=="text")return!1;let b=i([{kind:"text",text:g.text.slice(y[0].length)},...p],f);return b===null?f.vars.delete(y[1]):f.vars.set(y[1],b),!0},c=(u,f)=>{for(let h of u.inputs){let R=i(h,f);s(t,R===null?null:o(R,f.cwd))}let g=u.words.findIndex(h=>!/^[A-Za-z_]\w*=/.test(me(h.slice(0,1))??""));if(g===-1){for(let h of u.words)l(h,f);return}let p=u.words.slice(g),y=p.map(h=>i(h,f)),b=y[0];if(b==="export"||b==="local"||b==="declare"||b==="readonly")for(let h of p.slice(1))l(h,f);else if(b==="cd"||b==="pushd"){let h=y.slice(1).find($=>!Be($)),R=h===void 0?n.home??null:h===null?null:h==="-"?f.old:o(h,f.cwd);f.old=f.cwd,f.cwd=R}else{let h=Wi(y),R=h.base===void 0?f.cwd:o(h.base,f.cwd);for(let $ of h.reads)s(t,o($,R));for(let $ of h.searched)s(r,o($,R))}},d=(u,f)=>{for(let g of u)if(g.kind==="subshell")d(g.body,{cwd:f.cwd,old:f.old,vars:new Map(f.vars)});else if(g.kind==="cmd")c(g,f);else{let p=g.values.map(y=>i(y,f));for(let y of p.length>0?p:[null])y===null?f.vars.delete(g.name):f.vars.set(g.name,y),d(g.body,f)}};return d(Mr(e)??[],{cwd:n.cwd,old:null,vars:new Map}),{reads:t,searched:r}}function ut(e,n,t){switch(e){case"session-start":return[{rail:"brief",moment:"session"}];case"pre-tool-use":{let r=w(n.tool_name),o=n.tool_input??{};if(!r)return[];if(r==="Bash"){let i=w(o.command);if(!i)return[];let a=[{rail:"guard",moment:"command",command:i}];for(let u of Fr(i)){let f=D(u,t.root),g=t.read(f);g!==null&&a.push({rail:"guard",moment:"delete",file:{path:f,content:g}})}a.push({rail:"brief",moment:"command",command:i});let l=w(n.cwd)||t.root,{reads:c,searched:d}=ct(i,{cwd:l,root:t.root,home:t.home});for(let u of new Set([...c,...d]))a.push({rail:"brief",moment:"touch",path:u});return a}let s=Ni(r,o,t);return s===null?[]:[{rail:"guard",moment:"write",file:s}]}case"post-tool-use":case"post-tool-use-failure":{let r=t.changes??[],o=Ji(n,t.root),s=[];for(let l of r)l.after!==null?o.writes.includes(l.path)||s.push({rail:"guard",moment:"write",file:{path:l.path,content:l.after},observed:!0}):l.before!==null&&!o.deletes.includes(l.path)&&s.push({rail:"guard",moment:"delete",file:{path:l.path,content:l.before},observed:!0});let i=qi(n,t.root),a=new Set([...i===null?[]:[i],...r.map(l=>l.path)]);for(let l of a)s.push({rail:"brief",moment:"touch",path:l});return s}case"stop":return n.stop_hook_active===!0?[]:[{rail:"guard",moment:"turn-end",turn:t.turn?.()??[]}];case"notification":return[]}}function qi(e,n){let t=e.tool_input??{},r=t.file_path??t.notebook_path??t.path??t.glob;return r?D(w(r),n):null}function Dr(e){let n=e.map(pn);return n.includes("")?["."]:[...new Set(n)]}function Wr(e,n){return e.filter(t=>t!==""&&M(t,n))}function Ge(e){return(e??"").split(`
|
|
45
|
+
`).map(n=>n.trim()).filter(n=>n!=="")}function Lr(e){let n=w(e.tool_use_id);return n===""?null:n}function Ji(e,n){let t=w(e.tool_name),r=e.tool_input??{};if(t==="Bash")return{writes:[],deletes:Fr(w(r.command)).map(o=>D(o,n))};if(t==="Write"||t==="Edit"||t==="MultiEdit"){let o=w(r.file_path);return{writes:o===""?[]:[D(o,n)],deletes:[]}}return{writes:[],deletes:[]}}function Hr(e,n){if(typeof n!="object"||n===null)return null;let t=n;return typeof t.at!="number"?null:{key:e,session:w(t.session),agent:w(t.agent),tool:w(t.tool),at:t.at,...typeof t.done=="number"?{done:t.done}:{}}}function Ur(e,n){return e.session===n.session&&e.agent===n.agent}function Kr(e,n){return e.done===void 0&&n.some(t=>Ur(t,e)&&t.done!==void 0&&t.at>e.at)}function zi(e){return Vr(e.tool)}function Vr(e){return e===po||e==="Task"}function qr(e,n){return n.filter(t=>t.key!==e.key&&!Ur(t,e)&&!zi(t)&&!Kr(t,n)&&(t.done===void 0||t.done>e.at))}function Jr(e){let n=e.filter(r=>r.done===void 0&&!Kr(r,e)).map(r=>r.at),t=n.length===0?Number.POSITIVE_INFINITY:Math.min(...n);return e.filter(r=>r.done!==void 0&&r.done<t).map(r=>r.key)}function Yi(e){return`${e.tool||"a tool"} ${e.key} (${e.agent==="main"?"main agent":`agent ${e.agent}`} of session ${e.session.slice(0,8)})`}var z={stdout:"",stderr:"",exitCode:0},_r={write:{head:"flow \u2014 blocked before the write landed",tail:"Adjust the change so it passes, then retry."},delete:{head:"flow \u2014 blocked before the delete",tail:"Keep the file, or change the rule that protects it."},command:{head:"flow \u2014 command blocked before it ran",tail:"Adjust the command, then retry."},commit:{head:"flow \u2014 commit blocked",tail:"Fix the above, then commit again."},"turn-end":{head:"flow \u2014 turn held open",tail:"Do the above, then end your turn."}},Zi={write:"flow \u2014 write reverted after it landed",delete:"flow \u2014 delete reverted after it landed"},zr={revert:"refused",overlap:[]};function Yr(e,n,t=zr){let r=new Set(n.flatMap(i=>i.observed===void 0?[]:[i.observed])),o=t.revert==="all"&&t.overlap.length===0&&r.size>0,s=i=>o||r.has(i.path);return{revert:e.filter(s),kept:e.filter(i=>!s(i)).map(i=>i.path)}}function ot(e){return e.length<=1?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e.at(-1)??""}`}function Xi(e,n){let t=new Set(n.failed.map(d=>d.path)),r=n.restored.filter(d=>!t.has(d.path)),o=r.filter(d=>d.before!==null&&d.after!==null).map(d=>d.path),s=r.filter(d=>d.before===null).map(d=>d.path),i=r.filter(d=>d.after===null).map(d=>d.path),l=[[o.length===0?"":`${ot(o)} ${o.length===1?"is back to its":"are back to their"} previous content.`,s.length===0?"":`${ot(s)} ${s.length===1?"is":"are"} gone again \u2014 the call created ${s.length===1?"it":"them"}.`,i.length===0?"":`${ot(i)} ${i.length===1?"is":"are"} restored.`,e.some(d=>d.moment==="write")?"Adjust the change so it passes and write it again \u2014 through Edit, which is judged before it lands.":"Keep the file, or change the rule that protects it."].filter(d=>d!=="").join(" ")];for(let d of n.failed)l.push(`flow could not put ${d.path} back (${d.why}) \u2014 it still holds what the call wrote.`);n.kept.length>0&&l.push(`Kept as the call wrote ${n.kept.length===1?"it":"them"}: ${n.kept.join(", ")}.`);let c=n.scope??zr;return c.overlap.length>0?l.push(`Other tool calls overlapped this one: ${Qi(c.overlap)}. Their writes can show up in this call's diff, so only the refused files were put back`+(c.revert==="all"?' \u2014 revert: "all" is set, and is not applied while calls overlap.':".")):c.revert==="all"&&l.push('revert: "all" is set, so every file this call changed was put back, not only the refused ones.'),l.push("Only file content was put back: anything else the call did has already happened."),l.join(`
|
|
46
|
+
`)}var st=5;function Qi(e){let n=e.slice(0,st).map(Yi);return e.length>st?`${n.join("; ")}; and ${e.length-st} more`:n.join("; ")}function ea(e,n){return e.rail!=="guard"||e.moment!=="write"&&e.moment!=="delete"?!1:e.file!==void 0&&M(e.file.path,n)}function Zr(e,n,t){let r=e.filter(o=>o.rail==="guard");return{refused:r.filter(o=>o.moment!=="turn-end"&&!ea(o,n)).map(o=>({moment:o.moment,block:ye(t),...o.observed===!0&&o.file!==void 0?{observed:o.file.path}:{}})),shown:e.filter(o=>o.rail==="brief").map(()=>({entry:null,cause:"fault",body:t})),told:r.some(o=>o.moment==="turn-end")?t:null}}function Xr(e){return e.refusals.length>0?2:e.green?0:1}function na(e){return e.filter(n=>n.body.trim()!=="").map(n=>`# breadcrumb: ${n.entry??"flow"} (${n.cause})
|
|
34
47
|
${n.body}`).join(`
|
|
35
48
|
|
|
36
|
-
`)}function
|
|
49
|
+
`)}function ft(e,n){let t=ln(n.refused,n.undone);if(t!==null)return t;let r=na(n.shown);return r===""?z:{stdout:ta(e,r),stderr:"",exitCode:0}}function ln(e,n){let t=e[0];if(t===void 0)return null;let r=e.map(a=>ar(a.block)).join(`
|
|
37
50
|
|
|
38
|
-
`);return{stdout:"",stderr:`
|
|
39
|
-
${
|
|
51
|
+
`),o=t.observed!==void 0&&(t.moment==="write"||t.moment==="delete"),s=o?Zi[t.moment]:_r[t.moment].head,i=o?Xi(e,n??{restored:[],kept:[],failed:[]}):_r[t.moment].tail;return{stdout:"",stderr:`
|
|
52
|
+
${s}:
|
|
40
53
|
|
|
41
54
|
${r}
|
|
42
55
|
|
|
43
|
-
${
|
|
44
|
-
`,exitCode:2}}function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
${i}
|
|
57
|
+
`,exitCode:2}}function Qr(e){return{stdout:"",stderr:`
|
|
58
|
+
flow \u2014 could not see what this call changed:
|
|
59
|
+
|
|
60
|
+
${e}
|
|
61
|
+
|
|
62
|
+
Nothing it wrote was judged and nothing was put back. Check what the call changed before you go on.
|
|
63
|
+
`,exitCode:2}}function ta(e,n){return JSON.stringify({hookSpecificOutput:{hookEventName:Nr[e],additionalContext:n}})}function ra(e,n,t){let r=n==="unreadable"?`could not READ its payload from stdin (${t})`:`could not PARSE its payload (${t})`;return`[flow hook ${e}] the guard ${r}.`}function eo(e,n,t){let r=ra(e,n,t);return e==="pre-tool-use"||e==="post-tool-use"||e==="post-tool-use-failure"?{stdout:"",stderr:`
|
|
64
|
+
${r}
|
|
65
|
+
`,exitCode:2}:{stdout:"",stderr:`${r}
|
|
66
|
+
`,exitCode:0}}function dn(e,n=0){let t=gt(e);if(t===null)return null;let r=w(t.timestamp);return{kind:w(t.type),record:t,line:n,ts:r===""?null:r}}function gt(e){if(e===null||e.trim()==="")return null;let n;try{n=JSON.parse(e)}catch{return null}return typeof n=="object"&&n!==null&&!Array.isArray(n)?n:null}function cn(e){let n=[],t=e.split(`
|
|
67
|
+
`);for(let r=0;r<t.length;r++){let o=dn(t[r],r+1);o!==null&&n.push(o)}return n}function oa(e){return(e?.input_tokens??0)+(e?.cache_read_input_tokens??0)+(e?.cache_creation_input_tokens??0)}function no(e){let n=e.split(`
|
|
68
|
+
`);for(let t=n.length-1;t>=0;t--){let r=dn(n[t])?.record.message;if(r?.usage)return oa(r.usage)}return 0}var un=new Set(["Edit","Write","MultiEdit","NotebookEdit"]),sa=["<system-reminder>","<command-name>","<command-message>","<local-command","<user-prompt-submit-hook","Caveat:","Result of calling","This session is being continued","[Request interrupted","DO NOT respond","<budget:","tool_use_id"];function ia(e){let n=e.trimStart();return sa.some(t=>n.startsWith(t))||n.slice(0,40).includes("<system-reminder>")}function pt(e){if(e.kind!=="user"||e.record.isMeta===!0)return null;let n=e.record.message?.content;return typeof n!="string"||ia(n)?null:n}function to(e,n=""){let t=cn(e),r=0;for(let s=t.length-1;s>=0;s--)if(pt(t[s])!==null){r=s;break}let o=[];for(let s of t.slice(r)){let i=s.record.message?.content;if(Array.isArray(i))for(let a of i){let l=a;if(!l||l.type!=="tool_use")continue;let c=w(l.name),d=l.input??{},u=d.file_path??d.notebook_path;un.has(c)&&u?o.push({did:"edit",path:D(w(u),n)}):c==="Bash"&&d.command&&o.push({did:"run",command:w(d.command)})}}return o}function aa(e,n=8e3){for(let t of e.split(`
|
|
69
|
+
`)){let r=dn(t),o=r===null?null:pt(r);if(o!==null)return o.slice(0,n)}return""}function ro(e){let n=e.trim();return/^ref:\s*refs\/heads\/(.+)$/.exec(n)?.[1]??(n===""?null:n.slice(0,12))}function oo(e){return e.endsWith(".jsonl")?`${e.slice(0,-6)}.meta.json`:null}function so(e){let n=typeof e.payload.agent_id=="string"&&e.payload.agent_id!=="",t=gt(e.sidecar),r=typeof t?.agentType=="string"?t.agentType:void 0,o=typeof t?.description=="string"?t.description:void 0;return{head:e.transcript===null?"":aa(e.transcript),subagent:n||t!==null,...r===void 0?{}:{agentType:r},...o===void 0?{}:{description:o}}}var la=["file_path","notebook_path"];function io(e,n=""){let t=w(e.tool_name);if(!t)return null;let r=e.tool_input??{},o=w(e.permission_mode)===""?{}:{mode:w(e.permission_mode)};for(let i of la)if(r[i])return{kind:"tool",tool:t,path:D(w(r[i]),n),edit:un.has(t),...o};if(t==="Bash"&&r.command)return{kind:"tool",tool:t,command:w(r.command),...o};if(!r.pattern)return{kind:"tool",tool:t,...o};let s=r.path?{scope:D(w(r.path),n)}:{};return{kind:"tool",tool:t,pattern:w(r.pattern),...s,...o}}function ao(e,n,t){let r=w(e.tool_input?.command);if(w(e.tool_name)!=="Bash"||r==="")return[];let o=w(e.cwd)||n;return ct(r,{cwd:o,root:n,home:t}).reads.map(s=>({kind:"read",tool:"Bash",path:s}))}function da(e){return e.before===null?"created":e.after===null?"deleted":"modified"}function lo(e,n,t){let r=w(e.tool_name);if(Vr(r))return[];let o=e.tool_input??{},s=un.has(r)?D(w(o.file_path??o.notebook_path),t):null;return n.filter(i=>i.path!==s).map(i=>({kind:"write",tool:r,path:i.path,change:da(i)}))}function co(e,n,t){let r=e.tool_response,o=typeof r=="object"&&r!==null?r.bashEditDiff:void 0;if(typeof o!="object"||o===null)return null;let s=o.changedFiles;if(!Array.isArray(s))return null;let i=[...new Set(s.map(u=>D(w(u),t)).filter(Ee))],a=n.map(u=>u.path),l=Number(o.moreFiles)>0,c=i.filter(u=>!a.includes(u)),d=l?[]:a.filter(u=>!i.includes(u));return c.length===0&&d.length===0?null:{kind:"mismatch",tool:w(e.tool_name),hostOnly:c,flowOnly:d}}var ca=["GIT_DIR","GIT_INDEX_FILE","GIT_WORK_TREE","GIT_PREFIX","GIT_OBJECT_DIRECTORY","GIT_COMMON_DIR","GIT_INDEX_VERSION","GIT_QUARANTINE_PATH","GIT_QUARANTINE_ID"];function yt(e){let n=new Set(ca);return Object.fromEntries(Object.entries(e).filter(([t])=>!n.has(t)))}function uo(e){return e.replace(/[^a-zA-Z0-9]/g,"-")}function fo(e){let n=new Set(e),t=[],r=[],o=[];for(let s of e){let i=s.split("/");if(i.length===1&&s.endsWith(".jsonl")){t.push({path:s,meta:null,session:s.slice(0,-6),agent:null});continue}if(i.length===3&&i[1]==="subagents"&&s.endsWith(".jsonl")){let a=`${s.slice(0,-6)}.meta.json`;r.push({path:s,meta:n.has(a)?a:null,session:i[0]??"",agent:(i[2]??"").slice(0,-6)});continue}i.length===3&&i[1]==="subagents"&&s.endsWith(".meta.json")||o.push(s)}return{transcripts:[...t,...r],ignored:o}}function mt(e){let n=gt(e);if(n===null)return null;let t=r=>typeof n[r]=="string"&&n[r]!==""?n[r]:null;return{agentType:t("agentType"),description:t("description"),toolUseId:t("toolUseId"),model:t("model"),spawnDepth:typeof n.spawnDepth=="number"?n.spawnDepth:null}}function go(e){let n=null,t=null,r=null;for(let o of cn(e))if(n??=w(o.record.cwd)||null,t??=w(o.record.gitBranch)||null,r??=o.ts,n!==null&&t!==null&&r!==null)break;return{cwd:n,branch:t,started:r}}var po="Agent";function yo(e){let n=new Map;for(let t of cn(e)){if(t.kind!=="assistant")continue;let r=t.record.message?.content;if(Array.isArray(r))for(let o of r){let s=o;if(!s||s.type!=="tool_use"||s.name!==po)continue;let i=w(s.id);if(i==="")continue;let a=s.input??{};n.set(i,{toolUseId:i,asked:w(a.subagent_type)||null,description:w(a.description)||null,ts:t.ts,line:t.line})}}return n}var ua=/\x1b\[[0-9;]*m/g;function mo(e){return w(e).replace(ua,"")}function he(e,n=140){let t=mo(e).replace(/\s+/g," ").trim();return t.length>n?`${t.slice(0,n-1)}\u2026`:t}function ho(e,n="",t){let r=[];for(let o of cn(e)){let s=o.record.message?.content;if(o.kind==="user"){let i=pt(o);if(i!==null){r.push({line:o.line,kind:"prompt",text:i});continue}if(!Array.isArray(s))continue;for(let a of s){let l=a;!l||l.type!=="tool_result"||r.push({line:o.line,kind:"result",id:w(l.tool_use_id),content:fa(l.content),failed:l.is_error===!0})}continue}if(!(o.kind!=="assistant"||!Array.isArray(s)))for(let i of s){let a=i;if(!a||a.type!=="tool_use")continue;let l=a.input??{},c=w(a.name),d=c==="Bash"&&n!==""?ct(w(l.command),{cwd:w(o.record.cwd)||n,root:n,home:t}).reads:[];r.push({line:o.line,kind:"use",ts:o.ts,id:w(a.id),name:c,input:l,path:D(w(l.file_path??l.notebook_path),n),...d.length===0?{}:{reads:d}})}}return r}function fa(e){return typeof e=="string"?e:Array.isArray(e)?e.map(n=>n.text??"").join(`
|
|
70
|
+
`):e===void 0?"":JSON.stringify(e)}var ga=new RegExp([String.raw`\b(actually|hold on|nope|revert|undo|instead|hmm)\b`,String.raw`\b(wait|no)[,!.](\s|$)`,String.raw`\b(stop|don'?t|do not)\s`,String.raw`\bthat'?s (wrong|not right|not what|not)\b`,String.raw`\byou (broke|shouldn'?t|missed|forgot|didn'?t)\b`,String.raw`\bwhy (did|are) you\b`,String.raw`\b(rather than|let'?s not)\b`].join("|"),"i");function pa(e){return ga.test(e)}var ya=new Set(["set","node","npx","just","cd","export","echo","then","fi","do","done","if","for","while","source"]);function ma(e){if(e.startsWith("["))return!1;let n=e.indexOf(":");if(n<0)return!1;let t=e.slice(0,n).trim();return t!==""&&/^[@A-Za-z_][\w-]*(\s|$)/.test(t)&&!t.includes("=")}function ko(e){let n=new Set,t=!1;for(let r of e.split(`
|
|
71
|
+
`)){if(r.trim()==="")continue;let o=/^\s/.test(r),s=r.trim();if(!s.startsWith("#")){if(!o){t=ma(s);continue}if(t)for(let i of s.split(/&&|\|\||\||;/)){let a=i.trim().split(/\s+/),l=(a[0]??"").replace(/^@/,""),c=l==="npx"?a[1]??"":l;c===""||!/^[A-Za-z]/.test(c)||c.includes("/")||ya.has(c)||n.add(c)}}}return[...n]}function ha(e,n){let t=mo(e);if(_n(t)!==null)return{recipes:[],bypasses:[],commits:!1};let r=[];for(let s of t.matchAll(/(?:^|\n|;|\||&&|\()\s*just\s+([a-z][\w-]*)/g))r.push(s[1]);let o=[];for(let s of n){let i=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=new RegExp(`(?:^|\\n|;|\\||&&|\\(|node_modules/\\.bin/|npx\\s+)\\s*(?:\\./)?${i}\\b`),l=new RegExp(`just\\s+\\S*\\b${i}\\b`);a.test(t)&&!l.test(t)&&o.push(s)}return{recipes:r,bypasses:o,commits:/\bgit\s+commit\b/.test(t)}}var ka=5,ba=3;function bo(e,n=[],t=[]){let r=0,o=0,s=0,i={writes:{},reads:{}},a=0,l={},c={},d={},u=[],f=[],g=[],p=[],y=[],b={},h=null,R=0,$=0,A=0,P=()=>{A>=ka&&h!==null&&p.push({path:h,count:A,from:R,to:$})};for(let m of e){if(m.kind==="prompt"){u.push({line:m.line,text:he(m.text,120)}),pa(m.text)&&f.push({line:m.line,text:he(m.text,140)});continue}if(m.kind!=="use")continue;if(un.has(m.name)){m.name==="Write"?o+=1:r+=1;let x=Ee(m.path);x&&m.path===h?(A+=1,$=m.line):(P(),h=x?m.path:null,R=m.line,$=m.line,A=x?1:0),x&&(d[m.path]=(d[m.path]??0)+1);continue}if(m.name==="Read"){Ee(m.path)&&(d[m.path]=(d[m.path]??0)+1);continue}if(m.name!=="Bash")continue;for(let x of m.reads??[])d[x]=(d[x]??0)+1,i.reads[x]=(i.reads[x]??0)+1,s+=1;let v=w(m.input.command),j=ha(v,n);for(let x of j.recipes)l[x]=(l[x]??0)+1;for(let x of j.bypasses)c[x]=(c[x]??0)+1,g.push({line:m.line,tool:x,text:he(v,120)});j.commits&&(a+=1);let W=he(v,400);(b[W]??=[]).push(m.line)}P();for(let[m,v]of Object.entries(b))v.length>=ba&&y.push({command:m,count:v.length,lines:v});let _=0;for(let m of t){let v=typeof m.path=="string"?m.path:"";m.kind!=="write"||!Ee(v)||(_+=1,i.writes[v]=(i.writes[v]??0)+1,d[v]=(d[v]??0)+1)}return{stats:{edits:r,writes:o,shellWrites:_,shellReads:s,commits:a,recipes:l,bypasses:c},prompts:u,corrections:f,bypassSites:g,loops:p,retries:y,shell:i,touched:d}}function wo(e){let n=(g,p)=>g.map(y=>({...y,session:p})),t={},r={},o={},s={prompts:[],corrections:[],bypassSites:[],loops:[],retries:[]},i=0,a=0,l=0,c=0,d=0,u={writes:{},reads:{}},f=(g,p)=>{for(let[y,b]of Object.entries(p))g[y]=(g[y]??0)+b};for(let{session:g,read:p}of e)s.prompts.push(...n(p.prompts,g)),s.corrections.push(...n(p.corrections,g)),s.bypassSites.push(...n(p.bypassSites,g)),s.loops.push(...n(p.loops,g)),s.retries.push(...n(p.retries,g)),i+=p.stats.edits,a+=p.stats.writes,l+=p.stats.shellWrites,c+=p.stats.shellReads,d+=p.stats.commits,f(t,p.stats.recipes),f(r,p.stats.bypasses),f(o,p.touched),f(u.writes,p.shell.writes),f(u.reads,p.shell.reads);return{stats:{edits:i,writes:a,shellWrites:l,shellReads:c,commits:d,recipes:t,bypasses:r},...s,shell:u,touched:o}}var wa=[".claude/settings.json",".claude/settings.local.json",".claude/agents/**"];function xo(e){return[...at(e),...wa]}function xa(e,n){return e!==""&&M(e,n.flatMap(t=>[t,`**/${t}`]))}function So(e,n,t){let r=e.filter(i=>i.kind==="guardrail"&&i.out==="deny"&&typeof i.ts=="string").map(i=>({entry:typeof i.id=="string"?i.id:null,ts:i.ts})),o=n.filter(i=>i.kind==="use").filter(i=>(i.name==="Edit"||i.name==="Write")&&i.ts!==null&&xa(i.path,t)).sort((i,a)=>i.ts.localeCompare(a.ts)),s=[];for(let i of r){let a=o.find(l=>l.ts>i.ts);a!==void 0&&s.push({entry:i.entry,line:a.line,path:a.path,gapSeconds:Math.round((Date.parse(a.ts)-Date.parse(i.ts))/1e3)})}return s}function rn(e){let n=Date.parse(String(e.started));return Number.isFinite(n)?n:e.mtimeMs}function Ro(e,n,t={}){let{limit:r=null,all:o=!1,largest:s=!1,since:i=null}=t,a=e.filter(p=>!n.has(p.id)),l=(p,y)=>rn(y)-rn(p)||p.id.localeCompare(y.id),c=(p,y)=>y.bytes-p.bytes||l(p,y),d=[...a].sort(s?c:l),u=[],f=d;if(i!==null){f=d.filter(p=>rn(p)>=i);for(let p of d)rn(p)<i&&u.push({id:p.id,reason:"since"})}let g=f;if(!o&&r!==null&&r>=0&&f.length>r){g=f.slice(0,r);for(let p of f.slice(r))u.push({id:p.id,reason:"limit"})}return{analyse:g,excluded:u,counts:{backlog:a.length,analysed:g.length,excluded:u.length}}}function vo({armed:e,rows:n,withRecord:t,analysed:r}){if(!e)return{blocked:'the record is NOT ARMED \u2014 no stream has ever been written here, so there are no numbers. This is not "nothing happened".',warn:[]};let o=[];return r>0&&t===0?o.push("none of the conversations read has a stream of its own \u2014 the hooks did not record for them, so everything below is narrative only."):n===0&&o.push("the record is armed and holds no events for what was read."),{blocked:null,warn:o}}function $o(e){let{session:n,agent:t,meta:r,spawns:o}=e,s=r?.toolUseId===void 0||r.toolUseId===null?void 0:o.get(r.toolUseId);return{session:n,agent:t,agentType:r?.agentType??null,description:r?.description??s?.description??null,model:r?.model??null,asked:s?.asked??null,at:s?.ts??null,line:s?.line??null}}function Co(e,n){let t=Ze(n);return Object.entries(e).filter(([r])=>!t.some(o=>Me(o,r))).map(([r,o])=>({path:r,touches:o})).sort((r,o)=>o.touches-r.touches||r.path.localeCompare(o.path))}function fn(e){let n=e.split(`
|
|
72
|
+
`);for(let t=n.length-1;t>=0;t--){let r=n[t];if(!r.includes('"auto_mode'))continue;let o=dn(r)?.record.attachment,s=o?.type;if(s==="auto_mode_exit")return null;if(s!=="auto_mode"||o===void 0)continue;let i=o.bashFirstSteer;return{shellFirst:o.bashFirst===!0,variant:typeof i=="string"&&i!==""?i:null}}return null}function Eo(e){for(let n=e.length-1;n>=0;n--){let t=e[n];if(t.kind==="tool"&&typeof t.mode=="string"&&t.mode!=="")return t.mode}return null}function Oo(e){let n={},t={},r=0,o=0;for(let{rows:s,steer:i}of e){for(let a of s)a.kind==="tool"&&typeof a.mode=="string"&&(n[a.mode]=(n[a.mode]??0)+1);i!==null&&(r+=1,i.shellFirst&&(o+=1,i.variant!==null&&(t[i.variant]=(t[i.variant]??0)+1)))}return{calls:n,auto:r,steered:o,variants:t}}function Ao(e){let n={},t={},r=0,o=(s,i)=>{if(Array.isArray(i))for(let a of i)typeof a=="string"&&(s[a]=(s[a]??0)+1)};for(let s of e)s.kind==="mismatch"&&(r+=1,o(n,s.hostOnly),o(t,s.flowOnly));return{calls:r,hostOnly:n,flowOnly:t}}var se=5;function on(e){let n=Object.entries(e).sort((r,o)=>o[1]-r[1]||r[0].localeCompare(o[0]));return n.slice(0,se).map(([r,o])=>o===1?r:`${r} ${o}\xD7`).join(" \xB7 ")+(n.length>se?` \xB7 \u2026and ${n.length-se} more`:"")}function Po(e){let n=[];e.health.blocked!==null&&n.push(`\u2717 ${e.health.blocked}`);for(let f of e.health.warn)n.push(`\u26A0 ${f}`);let{span:t,headline:r}=e.metrics;n.push(`flow facts \u2014 ${e.coverage.analysed} of ${e.selection.counts.backlog} unread conversations \xB7 ${e.coverage.withRecord} with a record \xB7 `+(e.store.exists?e.store.dir:`no store at ${e.store.dir}`),` recorded ${t.tools.toLocaleString()} tool calls \xB7 ${t.sessions} chats \xB7 ${t.days}d`+(t.ample?"":" (too thin to call anything dead)"),` blocks ${r.blocks}`," lead "+(r.lead.median===null?"nothing measurable yet":`median ${r.lead.median} tool calls`));for(let f of r.gaps.slice(0,se))n.push(` gap ${f.area} \u2014 ${f.edits} edit${f.edits===1?"":"s"}, nothing watches it`);r.dead.length>0&&n.push(` dead ${r.dead.join(" \xB7 ")}`),r.retire.length>0&&n.push(` retire ${r.retire.join(" \xB7 ")} \u2014 bound, never once reached`),r.quiet.length>0&&n.push(` quiet ${r.quiet.map(f=>`${f.id} (${f.daysSince}d)`).join(" \xB7 ")}`);let{stats:o,corrections:s,loops:i,retries:a,bypassSites:l,shell:c}=e.narrative;n.push(` session ${o.edits} edits \xB7 ${o.writes} writes \xB7 ${o.shellWrites} shell writes \xB7 ${o.shellReads} shell reads \xB7 ${o.commits} commits \xB7 ${s.length} corrections \xB7 ${i.length} edit loops \xB7 ${a.length} retries \xB7 ${l.length} bypasses`),o.shellWrites>0&&n.push(` shell wrote ${on(c.writes)}`),o.shellReads>0&&n.push(` shell read ${on(c.reads)}`);let d=Object.entries(e.modes.calls).sort((f,g)=>g[1]-f[1]||f[0].localeCompare(g[0]));if(d.length>0||e.modes.auto>0){let f=Object.entries(e.modes.variants).sort((g,p)=>p[1]-g[1]||g[0].localeCompare(p[0]));n.push(` mode ${d.length===0?"no call recorded a mode":d.map(([g,p])=>`${g} ${p} call${p===1?"":"s"}`).join(" \xB7 ")}`+(e.modes.auto===0?"":` \u2014 ${e.modes.steered} of ${e.modes.auto} auto-mode conversation${e.modes.auto===1?"":"s"} steered towards shell edits`+(f.length===0?"":` (${f.map(([g,p])=>`${g} ${p}`).join(" \xB7 ")})`)))}let{mismatches:u}=e;u.calls>0&&n.push(` \u26A0 Claude Code's changed-file list disagreed with flow's diff on ${u.calls} call${u.calls===1?"":"s"}`+(Object.keys(u.hostOnly).length===0?"":` \u2014 only Claude Code listed ${on(u.hostOnly)}`)+(Object.keys(u.flowOnly).length===0?"":` \u2014 only flow's diff held ${on(u.flowOnly)}`));for(let f of e.uncovered.slice(0,se))n.push(` unwatched ${f.path} \u2014 touched ${f.touches}\xD7, no entry reaches it`);for(let f of e.actors.slice(0,se))n.push(` actor ${f.agentType??"unknown"}${f.asked!==null&&f.asked!==f.agentType?` (spawned as ${f.asked})`:""}`+(f.description===null?"":` \u2014 ${f.description}`));e.actors.length>se&&n.push(` \u2026and ${e.actors.length-se} more`);for(let f of e.weakened)n.push(` \u26A0 the guard was edited after ${f.entry??"a block"} refused \u2014 ${f.path}:L${f.line}, ${f.gapSeconds}s later`);return e.marked!==null&&n.push(` marked ${e.marked} conversation(s) read`),n}var Sa=24;function To(e){if(!e.startsWith("file://"))return!1;let n=e.split(/[?#]/)[0]??e;return!n.endsWith(".ts")||n.endsWith(".d.ts")?!1:!n.includes("/node_modules/")}function gn(e,n,t){return/Unexpected token|Unknown file extension|strip|SyntaxError/i.test(n)?`flow: ${e} could not be loaded as TypeScript. flow needs Node >= ${Sa}, where type stripping is on by default; this is node ${t}. (${n})`:`flow: ${e} could not be loaded \u2014 ${n}`}var Ra=[{hook:"session-start",matcher:"startup|resume|clear|compact"},{hook:"pre-tool-use",matcher:"*"},{hook:"post-tool-use",matcher:"*"},{hook:"post-tool-use-failure",matcher:"*"},{hook:"stop"}],Fe=Ra.map(({hook:e,matcher:n})=>({event:Nr[e],command:`flow hook ${e}`,...n===void 0?{}:{matcher:n}}));function va(e){let n=/(^|[\s"'/\\])(?:flow|flow\.mjs)["']?\s+hook\s+([a-z-]+)\s*$/.exec(e.trim());return n?.[2]!==void 0&&dt(n[2])}function ht(e){let n=e&&typeof e=="object"?e:{},t=n.hooks&&typeof n.hooks=="object"?n.hooks:{},r={};for(let[o,s]of Object.entries(t))Array.isArray(s)&&(r[o]=s);return r}function kt(e){let n=e?.hooks;return Array.isArray(n)?n.some(t=>{let r=t?.command;return typeof r=="string"&&va(r)}):!1}function jo(e){let n=[];for(let[t,r]of Object.entries(ht(e)))r.some(kt)&&n.push(t);return n}function Mo(e){let n=ht(e);return Fe.filter(t=>(n[t.event]??[]).some(r=>kt(r)&&r.matcher!==t.matcher)).map(t=>t.event)}function $a(e){let n=e&&typeof e=="object"?e:{},t=new Set(jo(e)),r=Fe.filter(a=>!t.has(a.event)),o=new Set(Mo(e));if(r.length===0&&o.size===0)return{settings:n,added:[]};let s=ht(e),i={...n.hooks};for(let a of Fe.filter(l=>o.has(l.event)))i[a.event]=(s[a.event]??[]).map(l=>kt(l)?{...l,matcher:a.matcher}:l);for(let a of r)i[a.event]=[...s[a.event]??[],{...a.matcher===void 0?{}:{matcher:a.matcher},hooks:[{type:"command",command:a.command}]}];return{settings:{...n,hooks:i},added:Fe.filter(a=>o.has(a.event)||!t.has(a.event)).map(a=>o.has(a.event)?`${a.event} (widened to every tool)`:a.event)}}var ie=".githooks",ae=`${ie}/pre-commit`,bt=`git config core.hooksPath ${ie}`,_o="add `flow commit $(git diff --cached --name-only)` to it",Ca=`#!/bin/sh
|
|
73
|
+
# The flow commit gate. Written by \`flow init\`; \`${bt}\` arms it.
|
|
51
74
|
#
|
|
52
75
|
# Every at(commit) guardrail runs over the staged set and a block exits non-zero, which is how git
|
|
53
76
|
# refuses the commit. This is the half of the promise the PreToolUse rail cannot make: it fires for
|
|
@@ -56,7 +79,7 @@ staged=$(git diff --cached --name-only --diff-filter=ACMR)
|
|
|
56
79
|
[ -z "$staged" ] && exit 0
|
|
57
80
|
# shellcheck disable=SC2086
|
|
58
81
|
exec flow commit $staged
|
|
59
|
-
`;function
|
|
82
|
+
`;function Io(e){return e!==null&&/(^|[\s"'/\\])flow\b[^\n]*\bcommit\b/m.test(e)}var Ea=String.raw`// flow.config.ts — this repo's whole guard.
|
|
60
83
|
//
|
|
61
84
|
// A rule not reachable from this file does not run. Bind a pack with `+"`pack(x)`"+String.raw`, refine one of
|
|
62
85
|
// its entries with `+"`override(x.entry)`"+String.raw`, and ask `+"`flow status`"+String.raw` what is live.
|
|
@@ -64,7 +87,7 @@ exec flow commit $staged
|
|
|
64
87
|
import { defineConfig } from "@jawache/flow";
|
|
65
88
|
|
|
66
89
|
export default defineConfig([]);
|
|
67
|
-
`,
|
|
90
|
+
`,Oa=String.raw`// flow.config.ts — this repo's whole guard, and the only file that turns anything on.
|
|
68
91
|
//
|
|
69
92
|
// A rule not reachable from here does not run. Everything below is ordinary code: a pack is a
|
|
70
93
|
// module, a check is a function of its ctx, and a category is a name with its recognizer aboard.
|
|
@@ -73,7 +96,7 @@ export default defineConfig([]);
|
|
|
73
96
|
// flow status what is bound, at which moments, and what is not wired yet
|
|
74
97
|
// flow test every rule's own cases, run
|
|
75
98
|
|
|
76
|
-
import { command, commit, defineCategory, defineConfig, definePack, guardrail, pack } from "@jawache/flow";
|
|
99
|
+
import { banCommands, command, commit, defineCategory, defineConfig, definePack, guardrail, pack } from "@jawache/flow";
|
|
77
100
|
import { flow } from "@jawache/flow/packs";
|
|
78
101
|
|
|
79
102
|
// A category is a name and the HOST-WRITTEN evidence that recognises it — never a claim a session
|
|
@@ -88,11 +111,7 @@ const MARKER = ["DO", "NOT", "COMMIT"].join("-");
|
|
|
88
111
|
export const demo = definePack("demo", {
|
|
89
112
|
noForcePush: guardrail()
|
|
90
113
|
.at(command)
|
|
91
|
-
.check((
|
|
92
|
-
/git\s+push\b[^\n]*(--force|(^|\s)-f(\s|$))/.test(ctx.command ?? "")
|
|
93
|
-
? ctx.fail("rewrites history other clones already have")
|
|
94
|
-
: ctx.ok(),
|
|
95
|
-
)
|
|
114
|
+
.check(banCommands({ ban: ["git\\s+push\\b[^\\n]*(--force|(^|\\s)-f(\\s|$))"] }))
|
|
96
115
|
.message("Force-pushing rewrites history everyone else has. Push a correcting commit, or ask first.")
|
|
97
116
|
.test({ pass: ["git push origin main"], block: ["git push --force origin main"] }),
|
|
98
117
|
|
|
@@ -129,40 +148,42 @@ export default defineConfig([
|
|
|
129
148
|
pack(flow, { packs: [] }),
|
|
130
149
|
pack(demo),
|
|
131
150
|
]);
|
|
132
|
-
`;function
|
|
133
|
-
`)}],{id:"hooks",ok:t.length===0,detail:t.length===0?`${e.settingsPath} \u2014 ${n.join(" \xB7 ")}
|
|
134
|
-
`).map(n
|
|
135
|
-
`
|
|
136
|
-
${r}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
`,exitCode:0}}}async function
|
|
140
|
-
`).filter(t=>t.trim()!==""):[]}function
|
|
141
|
-
`)}
|
|
151
|
+
`;function Aa(e){return e?Ea:Oa}function No(e){let n=e.settingsUnreadable?{settings:e.settings,added:[]}:$a(e.settings);return{config:e.hasConfig?null:{path:T,body:Aa(e.empty)},gate:!e.isGit||e.gateText!==null?null:{path:ae,body:Ca,mode:493},gateKept:e.isGit&&e.gateText!==null&&!Io(e.gateText),notGit:!e.isGit,flowDir:!e.hasFlowDir,link:e.resolves?null:e.packageRoot,hooksPath:e.isGit&&e.hooksPath!==ie,settings:n.added.length===0?null:{path:e.settingsPath,value:n.settings},registered:n.added,settingsUnreadable:e.settingsUnreadable?e.settingsPath:null}}function Fo(e,n){let t=[];e.config&&t.push(e.config.path),e.gate&&t.push(e.gate.path),e.flowDir&&t.push(`${G}/ \u2014 flow's own state, self-ignoring, never committed`),e.link&&t.push(`node_modules/@jawache/flow \u2192 ${e.link} (a link to the flow that is running \u2014 nothing here resolved @jawache/flow)`),e.settings&&t.push(`${e.settings.path} \u2014 ${e.registered.join(" \xB7 ")}`),e.hooksPath&&t.push(bt);let r=t.length===0?["flow init \u2014 already set up here; nothing to do."]:["flow init \u2014 created:",...t.map(o=>` + ${o}`)];e.notGit&&r.push(" \xB7 not a git repo, so no commit gate was armed. Run `git init`, then `flow init` again."),e.gateKept&&r.push(` \xB7 kept the ${ae} already here \u2014 flow never overwrites one, so ${_o} yourself.`),e.settingsUnreadable!==null&&r.push(` \u2717 ${e.settingsUnreadable} is not valid JSON, so nothing was registered and NOTHING was written to it \u2014 every other key in that file is somebody's, and there is no safe merge into bytes nobody could parse. Fix the JSON (a trailing comma, or a // comment) and run \`flow init\` again. Until then no rail fires.`);for(let o of n)r.push(` \u2717 ${o}`);return r.push(" next: `flow status` \u2014 what is bound, and what is not wired yet."),r}function pn(e){let n=e.search(/[*?{]/);return n===-1?e:e.slice(0,e.lastIndexOf("/",n)+1)}function Ir(e,n){let t=pn(e);return t!==""&&t!==e&&n.startsWith(t)&&e.slice(t.length).startsWith("**")}function Bo(e){return e.filter(n=>n.kind==="guardrail"&&n.disabled===null&&n.at.some(t=>t==="write"||t==="delete"))}function Go(e){let n=Bo(Ce(e?.ok===!0?e.entries:[]));return[...new Set(n.flatMap(t=>(t.on??[]).filter(r=>pn(r)===r)))]}function Pa(e,n,t){let r=s=>M(s,t)||t.some(i=>Ir(i,s)),o=[];for(let s of Bo(e)){let i=s.on??[],a=new Set;for(let l of n){if(!l.endsWith("/")){M(l,i)&&!M(l,s.ignore??[])&&!r(l)&&a.add(l);continue}for(let c of i){let d=pn(c),u=d.startsWith(l)&&d!==""?d===c?c:d:Ir(c,l)?l:null;u!==null&&!r(u)&&a.add(u)}}for(let l of a)o.push({id:"snapshot",ok:!1,detail:`${s.id} guards ${l}, which git ignores, so a change a shell command makes there is never seen or judged. List it in snapshotInclude in ${T}, or narrow the rule.`})}return o}function Ta(e){let n=jo(e.settings),t=Fe.filter(s=>!n.includes(s.event)).map(s=>s.event),r=Mo(e.settings),o=Io(e.gateText);return[{id:"config",ok:e.hasConfig,detail:e.hasConfig?e.configPath:`no ${T} in ${e.root} \u2014 \`flow init\` writes one, with a demo you can read in a minute.`},{id:"commit-gate",ok:o,detail:o?`${ae} runs \`flow commit\` over the staged set`:e.gateText===null?`no ${ae} \u2014 \`flow init\` arms it. Until then nothing runs at the commit.`:`${ae} is here but does not call flow \u2014 ${_o}.`},{id:"hooks-path",ok:e.hooksPath===ie,detail:e.hooksPath===ie?`core.hooksPath = ${ie}`:`core.hooksPath is ${e.hooksPath??"unset"} \u2014 run \`${bt}\`. It is per-clone, so every fresh checkout needs it.`},...e.grammars.length===0?[]:[{id:"grammars",ok:e.grammars.every(s=>s.present),detail:e.grammars.every(s=>s.present)?`${e.grammars.map(s=>s.name).join(" \xB7 ")} \u2014 declared in ${T}, and their libraries are built`:e.grammars.filter(s=>!s.present).map(s=>Fn(s.name,s.libraryPath)).join(`
|
|
152
|
+
`)}],{id:"hooks",ok:t.length===0&&r.length===0,detail:t.length===0&&r.length===0?`${e.settingsPath} \u2014 ${n.join(" \xB7 ")}`:[t.length===0?"":`${e.settingsPath} does not call flow for ${t.join(" \xB7 ")} \u2014 re-run \`flow init\`. No live rail fires until it does.`,r.length===0?"":`${e.settingsPath} calls flow for ${r.join(" \xB7 ")} on some tools only \u2014 an older flow registered ${r.length===1?"it":"them"} that way, and a change another tool makes is not judged after it lands. Re-run \`flow init\` to widen ${r.length===1?"it":"them"}.`].filter(s=>s!=="").join(`
|
|
153
|
+
`)},...Pa(Ce(e.load?.ok===!0?e.load.entries:[]),e.ignored,e.snapshotInclude)]}function Do(e){return[...e.refusals.map(n=>`${n.code}: ${n.detail}`),...e.dark,...e.fittings.filter(n=>!n.ok).map(n=>`${n.id}: ${n.detail}`)]}function ja(e,n){return e==="guardrail"?$n(n)&&an.guard.includes(n):Cn(n)&&an.brief.includes(n)}function Wo(e){let n=e.load?.ok===!0?e.load.entries:[],t=e.load?.ok===!1?e.load.refusals:[],r=t.length>0?[]:Ce(n),o=r.filter(i=>i.disabled===null&&i.at.length>0&&!i.at.some(a=>ja(i.kind,a))).map(i=>i.id),s=Ta(e);return{root:e.root,version:e.version,armed:!e.off,configPath:e.configPath,moments:en(r,null),categories:[...new Set(n.flatMap(i=>i.categories))].sort(),session:e.session,dark:o,fittings:s,refusals:t,green:Do({refusals:t,dark:o,fittings:s}).length===0}}function Ma(e){let n=[(e.on?.length??0)>0?`on ${e.on?.join(" ")}`:"",(e.ignore?.length??0)>0?`not ${e.ignore?.join(" ")}`:"",e.for.length>0?`for ${e.for.join(" \xB7 ")}`:""].filter(o=>o!==""),r=[` ${e.disabled!==null?"\u25CB":e.kind==="guardrail"?"\u2717":"\u{1F35E}"} ${e.id}${n.length===0?"":` \u2014 ${n.join(" \xB7 ")}`}`];return e.disabled!==null?r.push(` off: ${e.disabled||"no reason given"}`):e.says!==null&&r.push(` ${he(e.says,100)}`),r}function Lo(e){if(!e.armed)return[`flow is OFF \u2014 every rail is silenced (${G}/off is there). Delete that file to turn it back on.`];let{breadcrumbs:n,guardrails:t,disabled:r}=e.moments.totals,o=[e.refusals.length>0?`flow ${e.version} \u2014 the config will not load, so every guardrail and breadcrumb here is OFF.`:`flow is ON \u2014 ${it(t,"guardrail")} \xB7 ${it(n,"breadcrumb")}`+(r===0?"":` \xB7 ${r} disabled`)+", every one resolved and able to fire",` config ${e.configPath}`,` state ${e.root}/${G}`," session "+(e.session===null?"no live session has marked this worktree yet":`${e.session.id}${e.session.agent===null?"":` \xB7 ${e.session.agent}`}, wearing ${e.session.wearing.length===0?"no category":e.session.wearing.join(" \xB7 ")}`)],s=e.session?.mode??null;s!==null&&o.push(` mode ${_a(s,e.session?.steer??null)}`),e.categories.length>0&&o.push(` categories ${e.categories.join(" \xB7 ")} \u2014 what the entries below bind to`);for(let{moment:i,entries:a}of e.moments.moments){o.push(` ${i}`);for(let l of a)o.push(...Ma(l))}for(let i of e.fittings)o.push(` ${i.ok?"\u2713":"\u2717"} ${i.id}: ${i.detail}`);for(let i of e.refusals)o.push(` \u2717 ${i.code}: ${i.detail}`);for(let i of e.dark)o.push(` \u2717 ${i}: bound only at a moment nothing delivers here \u2014 it loads, it counts, and it will never fire. This adapter carries ${an.guard.join(" \xB7 ")} for a guardrail and ${an.brief.join(" \xB7 ")} for a breadcrumb.`);return o.push(e.green?"green \u2014 every rule loads, every fitting is in place.":`${it(Do(e).length,"red line")} \u2014 flow is NOT fully in force here.`),o}var it=(e,n)=>`${e} ${n}${e===1?"":"s"}`;function _a(e,n){return e!=="auto"?e:n===null?"auto \u2014 no steer towards shell edits found in its transcript":n.shellFirst?`auto \u2014 steered towards shell edits${n.variant===null?"":` (${n.variant})`}`:"auto \u2014 not steered towards shell edits"}var Ba=16*1024*1024;function We(e,n){let t=Ko("bash",["-lc",e],{cwd:n,encoding:"utf8",maxBuffer:Ba,env:yt(process.env)});return t.error?{stdout:"",stderr:`flow could not run a command: ${t.error.message}`,code:127}:{stdout:t.stdout,stderr:t.stderr,code:t.status??1}}function vt(e,n){return zo(n)?n:K(e,n)}function V(e,n){try{return be(vt(e,n),"utf8")}catch{return null}}function xt(e){return{exec:n=>Promise.resolve(We(n,e)),fs:{read:n=>Promise.resolve(V(e,n)??""),exists:n=>Promise.resolve(mn(vt(e,n)))},git:{diff:n=>Promise.resolve(We(n?`git diff -- ${fe(n)}`:"git diff",e).stdout),stagedFiles:()=>Promise.resolve(Ge(We("git diff --cached --name-only --diff-filter=ACM",e).stdout))}}}function Yo(e){try{let n=K(e,".git"),t=St(n).isDirectory()?n:Rt(e,/gitdir:\s*(.+)/.exec(be(n,"utf8"))?.[1]?.trim()??"");return ro(be(K(t,"HEAD"),"utf8"))}catch{return null}}function $t(e){let n=Yo(e),{session:t,agent:r}=Pr(e,n);return{branch:n,session:t,agent:r,wearing:r===null?[]:tn(e,t,r).categories??[]}}var Ga=256*1024*1024;function ke(e,n,t={}){let r=Ko("git",n,{cwd:e,maxBuffer:Ga,...t.input===void 0?{}:{input:t.input},env:{...yt(process.env),...t.index===void 0?{}:{GIT_INDEX_FILE:t.index}}});return r.error?{ok:!1,stdout:Buffer.alloc(0),stderr:r.error.message}:{ok:r.status===0,stdout:r.stdout,stderr:r.stderr.toString("utf8").trim()}}function Da(e){try{let n=K(e,".git");return St(n).isDirectory()?n:Rt(e,/gitdir:\s*(.+)/.exec(be(n,"utf8"))?.[1]?.trim()??"")}catch{return null}}function yn(e,n){let t=K(e,G,"snapshots",Z(n));return{meta:`${t}.json`,index:`${t}.index`,after:`${t}.after.index`}}var Wa=1440*60*1e3;function Zo(e,n,t,r){try{t!==null&&mn(t)&&Ia(t,n)}catch(i){return{fault:`could not copy git's index (${i.message})`}}let o=ke(e,["add","-A"],{index:n});if(!o.ok)return{fault:`git add -A failed: ${o.stderr}`};if(r.length>0){let i=ke(e,["--literal-pathspecs","ls-files","-z","--others","--ignored","--exclude-standard","--",...Dr(r)],{index:n});if(!i.ok)return{fault:`git could not list the ignored paths snapshotInclude names: ${i.stderr}`};let a=Wr(i.stdout.toString("utf8").split("\0"),r);if(a.length>0){let l=ke(e,["--literal-pathspecs","add","-f","--pathspec-from-file=-","--pathspec-file-nul"],{index:n,input:`${a.join("\0")}\0`});if(!l.ok)return{fault:`git could not record the snapshotInclude paths: ${l.stderr}`}}}let s=ke(e,["write-tree"],{index:n});return s.ok?{tree:s.stdout.toString("utf8").trim()}:{fault:`git write-tree failed: ${s.stderr}`}}function La(e,n,t,r){let o=yn(e,n);try{Q(e),Na(Ho(o.meta),{recursive:!0}),Ha(Ho(o.meta))}catch{}let s=Da(e),i=s===null?{fault:`${e} is not a git checkout, so there is no tree to snapshot`}:Zo(e,o.index,K(s,"index"),t);try{qo(o.meta,JSON.stringify({...r,at:Date.now(),...i}))}catch{}}function Ha(e){let n=Date.now();for(let t of Vo(e)){let r=K(e,t);n-St(r).mtimeMs>Wa&&De(r,{force:!0})}}function Ua(e,n){if(n.length===0)return[];let t=ke(e,["cat-file","--batch"],{input:`${n.join(`
|
|
154
|
+
`)}
|
|
155
|
+
`});if(!t.ok)return null;let r=[],o=0;for(let s=0;s<n.length;s++){let i=t.stdout.indexOf(10,o);if(i===-1)return null;let a=t.stdout.subarray(o,i).toString("utf8");if(o=i+1,a.endsWith(" missing")){r.push(null);continue}let[,l,c]=a.split(" "),d=Number(c);r.push(l==="blob"?t.stdout.subarray(o,o+d).toString("utf8"):null),o+=d+1}return r}function Ka(e,n,t){let r=yn(e,n),o;try{o=JSON.parse(be(r.meta,"utf8"))}catch{return{ok:!1,fault:`No snapshot was taken before this call (tool_use_id ${n}), so there is nothing to compare the tree against.`}}if(typeof o.fault=="string")return{ok:!1,fault:`The snapshot before this call could not be taken: ${o.fault}.`};if(typeof o.tree!="string")return{ok:!1,fault:`The snapshot before this call (tool_use_id ${n}) is unreadable.`};let s=o.tree,i=Zo(e,r.after,r.index,t);if("fault"in i)return{ok:!1,fault:`The tree after this call could not be recorded: ${i.fault}.`};if(i.tree===s)return{ok:!0,changes:[],before:s};let a=ke(e,["diff-tree","-r","-z","--name-only","--no-renames","--ignore-submodules=all",s,i.tree]);if(!a.ok)return{ok:!1,fault:`git could not compare the trees: ${a.stderr}.`};let l=a.stdout.toString("utf8").split("\0").filter(d=>d!=="");if(l.some(d=>d.includes(`
|
|
156
|
+
`)))return{ok:!1,fault:"A changed path has a newline in its name, which flow cannot ask git about safely."};let c=Ua(e,l.flatMap(d=>[`${s}:${d}`,`${i.tree}:${d}`]));return c===null?{ok:!1,fault:"git could not read the changed files back out of the snapshot."}:{ok:!0,changes:l.map((d,u)=>({path:d,before:c[2*u]??null,after:c[2*u+1]??null})),before:s}}function Va(e,n,t){let r=[];for(let s of t.filter(i=>i.before===null))try{De(vt(e,s.path),{force:!0})}catch(i){r.push({path:s.path,why:i.message})}let o=t.filter(s=>s.before!==null).map(s=>s.path);if(o.length>0){let s=ke(e,["--literal-pathspecs","restore",`--source=${n}`,"--worktree","--",...o]);if(!s.ok)for(let i of o)r.push({path:i,why:s.stderr||"git restore failed"})}return r}function Xo(e){let n=K(e,G,"snapshots"),t;try{t=Vo(n).filter(r=>r.endsWith(".json"))}catch{return[]}return t.flatMap(r=>{try{let o=Hr(r.slice(0,-5),JSON.parse(be(K(n,r),"utf8")));return o===null?[]:[o]}catch{return[]}})}function qa(e,n,t=Date.now()){let r=yn(e,n);for(let a of[r.index,r.after])De(a,{force:!0});let o=Xo(e),s=o.find(a=>a.key===n);try{s===void 0?De(r.meta,{force:!0}):qo(r.meta,JSON.stringify({session:s.session,agent:s.agent,tool:s.tool,at:s.at,done:t}))}catch{}let i=o.map(a=>a.key===n?{...a,done:t}:a);for(let a of Jr(i))De(yn(e,a).meta,{force:!0})}function Ja(e){return process.env.CLAUDE_PROJECT_DIR||e}function Ct(e,n){return(e.grammars??[]).map(t=>zo(t.libraryPath)?t:{...t,libraryPath:K(n,t.libraryPath)})}function Et(e,n){Xt(Ct(e,n),mn)}async function hn(e){let n=K(e,T);if(!mn(n))return{kind:"none"};try{let r=(await import(Fa(n).href)).default;return!r||typeof r!="object"||!Array.isArray(r.bindings)?{kind:"broken",message:`flow: ${T} has no default export from \`defineConfig([\u2026])\` \u2014 that call IS the config, and its result is what flow reads.`}:(Et(r.settings,e),{kind:"loaded",config:r,load:Re(r)})}catch(t){return{kind:"broken",message:gn(T,t.message,process.versions.node)}}}function wt(e){let n=null;return()=>(n??={value:e()},n.value)}function za(e,n){let t=typeof e.transcript_path=="string"?e.transcript_path:"",r=wt(()=>t===""?null:V(n,t));return{root:n,id:typeof e.session_id=="string"&&e.session_id!==""?e.session_id:"unknown",agent:typeof e.agent_id=="string"&&e.agent_id!==""?e.agent_id:"main",branch:Yo(n),transcriptPath:t,transcript:r,tokens:wt(()=>{let o=r();return o===null?0:no(o)}),turn:wt(()=>{let o=r();return o===null?[]:to(o,n)})}}function Ya(e,n,t){if(t.length===0)return{wearing:[],faults:[],fresh:!1};let r=e.transcriptPath===""?null:oo(e.transcriptPath),o=so({payload:n,transcript:e.transcript(),sidecar:r===null?null:V(e.root,r)});return vr(e.root,e.id,e.agent,o,t)}function Uo(e,n,t){return{root:e,read:r=>V(e,r),turn:n.turn,home:Jo(),changes:t}}function Za(e,n){return n.text!==void 0?n.text:n.file===void 0?"":V(e,n.file)??""}function Xa(e){return e.rail==="guard"&&e.moment==="commit"?e.staged?.length??0:1}async function Qa(e,n,t){let r=await hn(t);if(r.kind==="none")return z;let o=Ne(t),s=za(n,t);e==="pre-tool-use"&&!o&&s.id!=="unknown"&&Ar(t,s.id,s.agent,s.branch);let i=r.kind==="loaded"?r.config.settings.snapshotInclude??[]:[],a=Lr(n),l=typeof n.tool_name=="string"?n.tool_name:"",c=(e==="post-tool-use"||e==="post-tool-use-failure")&&!o&&l!==""?a===null?{ok:!1,fault:"The host sent no tool_use_id with this call, so its snapshot cannot be found."}:Ka(t,a,i):null,d=Date.now(),u=()=>{a!==null&&qa(t,a,d)};if(c!==null&&!c.ok)return u(),Qr(c.fault);let f=c?.ok===!0?c.changes:void 0,g=r.kind==="loaded"&&r.config.settings.revert==="all"?"all":"refused",p=x=>{if(x.length===0||a===null)return{revert:g,overlap:[]};let F=Xo(t),B=F.find(q=>q.key===a);return{revert:g,overlap:B===void 0?[]:qr(B,F)}},y=x=>{if(c===null||a===null)return x;let F=p(c.changes),B=Yr(c.changes,x.refused,F),q=B.revert.length===0?[]:Va(t,c.before??"",B.revert);return u(),x.refused.some(wn=>wn.observed!==void 0)?{...x,undone:{restored:B.revert,kept:B.kept,failed:q,scope:F}}:x},b=x=>(e==="pre-tool-use"&&!o&&a!==null&&x.exitCode===0&&La(t,a,i,{session:s.id,agent:s.agent,tool:l}),x),h=x=>{if(o)return z;let F=at(V(t,T)),B=Zr(ut(e,n,Uo(t,s,f)),F,x),q=ft(e,y(B));return b(B.told===null||q.exitCode!==0?q:{...q,stderr:`${B.told}
|
|
157
|
+
`})};if(r.kind==="broken")return h(r.message);let{load:R,config:$}=r;if(!R.ok)return h(ue(R.refusals));let A=R.entries,P=Ya(s,n,or(A)),_=ut(e,n,Uo(t,s,f)),m=[];if(e==="pre-tool-use"&&!o){let x=io(n,t);x&&m.push(x),m.push(...ao(n,t,Jo()))}if(f!==void 0&&!o){m.push(...lo(n,f,t));let x=co(n,f,t);x!==null&&m.push(x)}let v=[],j=nt(t),W=await el({events:_,session:s,load:R,settings:$.settings,identity:P,off:o,hook:e,payload:n,rows:m,steps:j?v:null});return o||Xn({root:t,session:s.id,branch:s.branch},m),j&&tt(t,s.id,v),b(ft(e,y(W)))}async function el(e){let{events:n,session:t,load:r,settings:o,identity:s,off:i,hook:a,payload:l,rows:c,steps:d}=e,u=[],f=[],g=xt(t.root),p=a==="session-start"&&l.source==="compact",y=tn(t.root,t.id,t.agent),b=p&&r.ok?Wn(y.marks,r.entries):y.marks;p&&!i&&c.push({kind:"compaction"}),p&&d?.push({rail:"compaction"});for(let h of n){if(h.rail==="guard"){let P=d===null?null:Jn(g),_=await Xe({load:r,event:{moment:h.moment,file:h.file,command:h.command,staged:h.staged,turn:h.turn,wearing:s.wearing},world:P?.world??g,faults:s.faults,off:i});d?.push({rail:"guard",moment:h.moment,...h.file===void 0?{}:{file:h.file},...h.command===void 0?{}:{command:h.command},...h.staged===void 0?{}:{staged:h.staged},...h.turn===void 0?{}:{turn:h.turn},wearing:s.wearing,world:P?.taken()??{}});for(let m of _.effects)m.do==="block"&&u.push({moment:h.moment,block:m,...h.observed===!0&&h.file!==void 0?{observed:h.file.path}:{}});i||c.push(...$e(h.moment,_,Xa(h)));continue}if(u.length>0)continue;d?.push({rail:"brief",moment:h.moment,...h.path===void 0?{}:{path:h.path},...h.command===void 0?{}:{command:h.command},wearing:s.wearing,tokens:t.tokens()});let R=Dn({load:r,event:{moment:h.moment,path:h.path,command:h.command,wearing:s.wearing,tokens:t.tokens()},marks:b,settings:o,off:i}),$=[],A=[];for(let P of R.notices){let _=Za(t.root,P);if(_.trim()===""){P.entry!==null&&A.push(P.entry);continue}$.push(P),f.push({entry:P.entry,cause:P.cause,body:_})}b=nl(R.marks,b,A),!i&&$.length>0&&c.push(...$e(h.moment,{effects:$,tallies:[]},1))}return!i&&b!==y.marks&&Zn(t.root,t.id,t.agent,{...y,marks:b}),{refused:u,shown:f}}function nl(e,n,t){if(t.length===0)return e;let r={};for(let[o,s]of Object.entries(e))t.includes(o)||(r[o]=s);for(let o of t){let s=n[o];s!==void 0&&(r[o]=s)}return r}async function tl(e,n){let t=await hn(e);if(t.kind==="none")return z;if(Ne(e))return z;if(t.kind==="broken")return ln([{moment:"commit",block:ye(t.message)}])??z;if(n.length===0)return z;let{branch:r,session:o,wearing:s}=$t(e),{load:i}=t,a=nt(e)?Jn(xt(e)):null,l=await Xe({load:i,event:{moment:"commit",staged:n,wearing:s},world:a?.world??xt(e),off:!1});a!==null&&tt(e,o,[{rail:"guard",moment:"commit",staged:n,wearing:s,world:a.taken()}]),Xn({root:e,session:o,branch:r},$e("commit",l,n.length));let c=l.effects.filter(d=>d.do==="block").map(d=>({moment:"commit",block:d}));return ln(c)??z}function rl(){if(process.stdin.isTTY)return{ok:!0,payload:{}};let e;try{e=be(0,"utf8")}catch(t){return{ok:!1,why:"unreadable",detail:t.code??"unknown error"}}if(e.trim()==="")return{ok:!0,payload:{}};let n;try{n=JSON.parse(e)}catch{return{ok:!1,why:"unparseable",detail:`${e.length} bytes on stdin, and not JSON`}}return!n||typeof n!="object"||Array.isArray(n)?{ok:!1,why:"unparseable",detail:`JSON, but ${n===null?"null":Array.isArray(n)?"an array":typeof n} \u2014 a payload is an object`}:{ok:!0,payload:n}}async function Qo(e,n){try{if(!dt(e))return z;let t=rl();return t.ok?await Qa(e,t.payload,Ja(n)):eo(e,t.why,t.detail)}catch(t){return{stdout:"",stderr:`[flow hook ${e}] the guard itself failed \u2014 ${t.message}
|
|
158
|
+
`,exitCode:0}}}async function es(e,n){let t=Rt(n);return tl(t,e.map(r=>D(r,t)))}import{existsSync as ol,readFileSync as sl,readdirSync as il,statSync as al}from"node:fs";import{homedir as ns}from"node:os";import{join as ee}from"node:path";function Ae(e){try{return sl(e,"utf8")}catch{return null}}function ll(e,n){let t=n===void 0?process.env.CLAUDE_CONFIG_DIR||ee(ns(),".claude"):ee(n,".claude");return ee(t,"projects",uo(e))}function dl(e){let n=r=>{try{return il(r,{withFileTypes:!0}).map(o=>o.isDirectory()?`${o.name}/`:o.name)}catch{return[]}},t=[];for(let r of n(e)){if(!r.endsWith("/")){t.push(r);continue}let o=r.slice(0,-1);for(let s of n(ee(e,o,"subagents")))s.endsWith("/")||t.push(`${o}/subagents/${s}`)}return t.sort()}function Ot(e,n){let t=ll(e,n);if(!ol(t))return{dir:t,exists:!1,transcripts:[],ignored:[]};let{transcripts:r,ignored:o}=fo(dl(t));return{dir:t,exists:!0,transcripts:r.map(s=>{let i=ee(t,s.path),a=0,l=0;try{let c=al(i);a=c.size,l=c.mtimeMs}catch{}return{ref:s,file:i,bytes:a,mtimeMs:l}}),ignored:o}}function ts(e,n){return{jsonl:Ae(n.file)??"",meta:n.ref.meta===null?null:mt(Ae(ee(e,n.ref.meta)))}}function cl(e){let n=We("git ls-files",e);return n.code===0?n.stdout.split(`
|
|
159
|
+
`).filter(t=>t.trim()!==""):[]}function rs(e,n,t={}){let r=t.home??ns(),o=t.nowMs??Date.now(),s=Ot(e,t.home),i=[],a=new Map,l=new Map;for(let m of s.transcripts){if(m.ref.agent!==null){let W=l.get(m.ref.session)??[];W.push(m),l.set(m.ref.session,W);continue}let v=Ae(m.file)??"",j=go(v);j.cwd!==null&&j.cwd!==e||(a.set(m.ref.session,v),i.push({id:m.ref.session,bytes:m.bytes,mtimeMs:m.mtimeMs,started:j.started,branch:j.branch}))}let c=t.branch?i.filter(m=>m.branch===t.branch):i,d=t.session?{analyse:c.filter(m=>m.id===t.session),excluded:[],counts:{backlog:c.length,analysed:c.filter(m=>m.id===t.session).length,excluded:0}}:Ro(c,Cr(e),t),u=$r(e),f=new Map(u.map(m=>[m.session,m.rows])),g=n.ok?Ce(n.entries):[],p=ko(Ae(ee(e,"justfile"))??""),y=xo(Ae(ee(e,T))),b=[],h=[],R=[],$=[],A=0;for(let m of d.analyse){let v=f.get(m.id)??[];v.length>0&&(A+=1);let j=a.get(m.id)??"",W=ho(j,e,r);b.push({session:m.id,read:bo(W,p,v)}),$.push({rows:v,steer:fn(j)}),h.push(...So(v,W,y));let x=yo(j);for(let F of l.get(m.id)??[])R.push({...$o({session:m.id,agent:F.ref.agent??"",meta:F.ref.meta===null?null:mt(Ae(ee(s.dir,F.ref.meta))),spawns:x})})}let P=mr({sessions:u,entries:g,nowMs:o}),_=wo(b);return{root:e,store:{dir:s.dir,exists:s.exists,ignored:s.ignored},selection:d,coverage:{analysed:d.analyse.length,withRecord:A,narrativeOnly:d.analyse.length-A},health:vo({armed:u.length>0,rows:u.reduce((m,v)=>m+v.rows.length,0),withRecord:A,analysed:d.analyse.length}),metrics:P,moments:en(g,P),terrain:hr({paths:cl(e),heat:P.heat,entries:g}),narrative:_,uncovered:Co(_.touched,g),actors:R,weakened:h,modes:Oo($),mismatches:Ao($.flatMap(m=>m.rows)),marked:t.mark===!0?Er(e,d.analyse.map(m=>m.id)):null}}import{execFileSync as is,spawnSync as os}from"node:child_process";import{createRequire as ul}from"node:module";import{chmodSync as fl,existsSync as Le,lstatSync as gl,mkdirSync as At,symlinkSync as pl,unlinkSync as yl,writeFileSync as ss}from"node:fs";import{homedir as ml}from"node:os";import{dirname as kn,join as Y,resolve as as}from"node:path";import{fileURLToPath as hl}from"node:url";function ls(){return Y(process.env.CLAUDE_CONFIG_DIR||Y(ml(),".claude"),"settings.json")}function kl(){let e=kn(hl(import.meta.url));for(let n=0;n<6;n++){let t=V(e,"package.json");if(t!==null)try{if(JSON.parse(t).name==="@jawache/flow")return e}catch{}let r=kn(e);if(r===e)break;e=r}return null}function bl(e){try{return ul(Y(e,"noop.js")).resolve("@jawache/flow"),!0}catch{return!1}}function ds(e){try{let n=is("git",["-C",e,"config","--get","core.hooksPath"],{encoding:"utf8"}).trim();return n===""?null:n}catch{return null}}function wl(e,n){let t=os("git",["-C",e,"ls-files","--others","--ignored","--exclude-standard","--directory"],{encoding:"utf8"}),r=n.length===0?null:os("git",["-C",e,"check-ignore","--stdin"],{encoding:"utf8",input:`${n.join(`
|
|
160
|
+
`)}
|
|
161
|
+
`}),o=[...t.status===0?Ge(t.stdout):[],...Ge(r?.stdout??null)];return[...new Set(o)].filter(s=>s!==`${G}/`&&!s.startsWith(`${G}/`))}function cs(e,n){let t=V(e,n);if(t===null||t.trim()==="")return{value:null,unreadable:!1};try{return{value:JSON.parse(t),unreadable:!1}}catch{return{value:null,unreadable:!0}}}function xl(e){let{session:n,agent:t,wearing:r}=$t(e);if(t===null)return null;let o=Eo(et(e,n));return{id:n,agent:t,wearing:r,mode:o,steer:o==="auto"?fn(Sl(e,n,t)):null}}function Sl(e,n,t){let r=Ot(e),o=t==="main"?null:`agent-${t}`,s=r.transcripts.find(i=>i.ref.session===n&&i.ref.agent===o);return s===void 0?"":ts(r.dir,s).jsonl}function Rl(e,n){let t=ls(),r=cs(e,t);return{root:e,empty:n,isGit:Le(Y(e,".git")),hasConfig:Le(Y(e,T)),gateText:V(e,ae),hasFlowDir:Le(Y(e,G)),hooksPath:ds(e),settingsPath:t,settings:r.value,settingsUnreadable:r.unreadable,resolves:bl(e),packageRoot:kl()}}function vl(e,n){let t=[],r=(o,s)=>{try{s()}catch(i){t.push(`${o}: ${i.message}`)}};for(let o of[n.config,n.gate])o!==null&&r(`could not write ${o.path}`,()=>{let s=Y(e,o.path);At(kn(s),{recursive:!0}),ss(s,o.body),o.mode!==void 0&&fl(s,o.mode)});return n.flowDir&&r(`could not create ${G}/`,()=>{Q(e)}),n.link!==null&&r("could not link @jawache/flow",()=>{let o=Y(e,"node_modules","@jawache");At(o,{recursive:!0});let s=Y(o,"flow");gl(s,{throwIfNoEntry:!1})?.isSymbolicLink()&&!Le(s)&&yl(s),pl(n.link,s,"dir")}),n.settings!==null&&r(`could not write ${n.settings.path}`,()=>{At(kn(n.settings?.path??""),{recursive:!0}),ss(n.settings?.path??"",`${JSON.stringify(n.settings?.value,null,2)}
|
|
162
|
+
`)}),n.hooksPath&&r("could not set core.hooksPath",()=>is("git",["-C",e,"config","core.hooksPath",ie],{stdio:"ignore"})),t}function us(e,n){let t=as(e),r=No(Rl(t,n.includes("--empty"))),o=vl(t,r);return{stdout:`${Fo(r,o).join(`
|
|
142
163
|
`)}
|
|
143
|
-
`,stderr:"",exitCode:o.length===0?0:1}}async function
|
|
144
|
-
`,exitCode:2};let s=
|
|
145
|
-
`,stderr:"",exitCode:
|
|
164
|
+
`,stderr:"",exitCode:o.length===0?0:1}}async function fs(e,n){let t=as(e),r=Y(t,T),o=await hn(t);if(o.kind==="broken")return{stdout:"",stderr:`${o.message}
|
|
165
|
+
`,exitCode:2};let s=ls(),i={root:t,version:Pe,off:Ne(t),configPath:r,hasConfig:o.kind==="loaded",load:o.kind==="loaded"?o.load:null,gateText:V(t,ae),hooksPath:ds(t),settingsPath:s,settings:cs(t,s).value,grammars:o.kind==="loaded"?Ct(o.config.settings,t).map(c=>({name:c.name,libraryPath:c.libraryPath,present:Le(c.libraryPath)})):[],session:xl(t),ignored:wl(t,Go(o.kind==="loaded"?o.load:null)),snapshotInclude:o.kind==="loaded"?o.config.settings.snapshotInclude??[]:[]},a=Wo(i),l=Xr(a);return n.includes("--json")?{stdout:`${JSON.stringify(a,null,2)}
|
|
166
|
+
`,stderr:"",exitCode:l}:{stdout:`${Lo(a).join(`
|
|
146
167
|
`)}
|
|
147
|
-
`,stderr:"",exitCode:
|
|
148
|
-
`)});
|
|
168
|
+
`,stderr:"",exitCode:l}}var Tt=process.argv.slice(2);process.removeAllListeners("warning");process.on("warning",e=>{e.name!=="ExperimentalWarning"&&process.stderr.write(`${e.stack??e.message}
|
|
169
|
+
`)});El({load(e,n,t){if(!To(e))return t(e,n);let r=Cl(Al(e),"utf8");return{format:"module",shortCircuit:!0,source:Ol(r,{mode:"strip",sourceUrl:e})}}});async function jt(e){let n=Pt(process.cwd(),e),t;try{t=await import(Pl(n).href)}catch(o){throw new Error(gn(e,o.message,process.versions.node))}let r=t.default;if(!r||typeof r!="object"||!Array.isArray(r.bindings))throw new Error(`${e} has no default export from \`defineConfig([\u2026])\` \u2014 that call IS the config, and its result is what flow reads.`);return Et(r.settings,Tl(n)),r}function Ml(e,n){let t=n.filter(i=>!i.ok),r=e.filter(i=>i.spec.kind==="guardrail"&&!i.spec.disabled).length;for(let i of t)process.stdout.write(` \u2717 ${i.entry} \xB7 ${i.expect} case ${i.index+1}
|
|
149
170
|
${i.detail}
|
|
150
171
|
`);let o=e.filter(i=>i.spec.disabled).length,s=o?` \xB7 ${o} disabled, not run`:"";return t.length===0?(process.stdout.write(`flow test \u2014 ${n.length} cases over ${r} guardrails, all green${s}
|
|
151
172
|
`),0):(process.stdout.write(`flow test \u2014 ${t.length} of ${n.length} cases failed, over ${r} guardrails${s}
|
|
152
|
-
`),1)}async function
|
|
153
|
-
`),2;let r=await
|
|
154
|
-
`),2;let i=await
|
|
173
|
+
`),1)}async function _l(e){let n=await jt(e),t=Wt(Re(n));return Ml(t,await er(t))}function gs(e){e.stdout&&process.stdout.write(e.stdout),e.stderr&&process.stderr.write(e.stderr),process.exitCode=e.exitCode}function te(e,n){let t=e.indexOf(`--${n}`);if(t===-1)return null;let r=e[t+1];return r===void 0||r.startsWith("--")?"":r}var Il=e=>{let n=[];for(let t=0;t<e.length;t++){let r=e[t];if(!r.startsWith("--")){n.push(r);continue}let o=e[t+1];o!==void 0&&!o.startsWith("--")&&(t+=1)}return n};async function Nl(e){let[n,t]=Il(e);if(n===void 0)return process.stderr.write(`flow replay <recording.jsonl> [config] [--against <log.jsonl>]
|
|
174
|
+
`),2;let r=await jt(t??T),o=Re(r),s=Or(Pt(process.cwd(),n));if(s.steps.length===0)return process.stderr.write(`flow replay \u2014 ${n} holds no steps. Arm the recorder with \`touch .flow/record\`.
|
|
175
|
+
`),2;let i=await wr({load:o,recording:s,settings:r.settings}),a=(u,f)=>he(u[f],100),l=i.rows.filter(u=>u.kind==="guardrail"||u.kind==="breadcrumb");for(let u of l){let f=a(u,"subject");process.stdout.write(u.kind==="guardrail"?` \u2717 ${a(u,"id")} \xB7 ${a(u,"moment")}${f===""?"":` \xB7 ${f}`}
|
|
155
176
|
`:` \u{1F35E} ${a(u,"id")} \xB7 ${a(u,"moment")} \xB7 ${a(u,"cause")}
|
|
156
|
-
`)}process.stdout.write(`flow replay \u2014 ${s.steps.length} steps \xB7 ${
|
|
177
|
+
`)}process.stdout.write(`flow replay \u2014 ${s.steps.length} steps \xB7 ${l.filter(u=>u.kind==="guardrail").length} blocked \xB7 ${l.filter(u=>u.kind==="breadcrumb").length} shown, with no repo and no harness
|
|
157
178
|
`);for(let u of i.unanswered)process.stderr.write(` ! the recording never answered a ${u.kind} of \`${u.asked}\`
|
|
158
|
-
`);let
|
|
159
|
-
`);return process.stdout.write(
|
|
160
|
-
`:`flow replay \u2014 ${
|
|
161
|
-
`),
|
|
162
|
-
`),s.health.blocked===null?0:1;let i
|
|
179
|
+
`);let c=te(e,"against");if(c===null)return i.unanswered.length>0?1:0;let d=xr(i.rows,Qn(Pt(process.cwd(),c)));for(let u of d)process.stderr.write(` ${u.side==="replay"?"+":"-"} [${u.at}] ${u.row}
|
|
180
|
+
`);return process.stdout.write(d.length===0?`flow replay \u2014 the replay and ${c} agree on every block and every injection. Diff empty.
|
|
181
|
+
`:`flow replay \u2014 ${d.length} difference(s) against ${c}.
|
|
182
|
+
`),d.length===0&&i.unanswered.length===0?0:1}async function Fl(e){let n=process.cwd(),t=$l(jl(n,T))?Re(await jt(T)):{ok:!0,entries:[]},r=te(e,"limit"),o=te(e,"since"),s=rs(n,t,{session:te(e,"session"),branch:te(e,"branch"),limit:r===null||r===""?null:Number(r),all:te(e,"all")!==null,largest:te(e,"largest")!==null,since:o===null||o===""?null:Date.parse(o),mark:te(e,"mark")!==null});if(te(e,"json")!==null)return process.stdout.write(`${JSON.stringify(s,null,2)}
|
|
183
|
+
`),s.health.blocked===null?0:1;let i=Po(s);return process.stdout.write(`${i.join(`
|
|
163
184
|
`)}
|
|
164
|
-
`),s.health.blocked===null?0:1}var[
|
|
165
|
-
`);else if(
|
|
166
|
-
`),process.exitCode=2}else if(
|
|
167
|
-
`),process.exitCode=2}else process.stderr.write([`flow ${
|
|
185
|
+
`),s.health.blocked===null?0:1}var[ne,...we]=Tt;if(Tt.includes("--version")||Tt.includes("-v"))process.stdout.write(`${Pe}
|
|
186
|
+
`);else if(ne==="test")try{process.exitCode=await _l(we[0]??"flow.config.ts")}catch(e){process.stderr.write(`${e instanceof ve,e.message}
|
|
187
|
+
`),process.exitCode=2}else if(ne==="hook")gs(await Qo(we[0]??"",process.cwd()));else if(ne==="commit")gs(await es(we,process.cwd()));else if(ne==="init"||ne==="status"){let e=ne==="init"?us(process.cwd(),we):await fs(process.cwd(),we);e.stdout&&process.stdout.write(e.stdout),e.stderr&&process.stderr.write(e.stderr),process.exitCode=e.exitCode}else if(ne==="replay"||ne==="facts")try{process.exitCode=ne==="replay"?await Nl(we):await Fl(we)}catch(e){process.stderr.write(`${e instanceof ve,e.message}
|
|
188
|
+
`),process.exitCode=2}else process.stderr.write([`flow ${Pe}`,""," flow init [--empty] scaffold flow.config.ts, arm the git gate, register the hooks"," flow status [--json] what is bound here, at which moments \u2014 and what is not wired yet"," flow test [config] run every bound entry's cases (default: flow.config.ts)",` flow hook <event> a harness hook, payload on stdin \u2014 ${lt.join(" \xB7 ")}`," flow commit <files\u2026> the git pre-commit gate, over the staged set"," flow replay <file> a recorded session, back through the engine \u2014 --against <log> diffs it"," flow facts what the record and the conversations say about this repo \u2014 --json for all of it",""].join(`
|
|
168
189
|
`)),process.exitCode=2;
|