@claude-flow/cli 3.58.0 → 3.59.0
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/.claude/helpers/.helpers-version +1 -1
- package/.claude/helpers/helpers.manifest.json +2 -2
- package/README.md +2 -0
- package/bin/cli.js +19 -1
- package/catalog-manifest.json +3 -3
- package/dist/src/commands/harness.d.ts +40 -0
- package/dist/src/commands/harness.js +142 -0
- package/dist/src/commands/index.js +1 -0
- package/dist/src/commands/init.js +116 -0
- package/dist/src/commands/memory.js +6 -1
- package/dist/src/commands/status.js +2 -2
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +12 -2
- package/dist/src/init/grok-generator.d.ts +96 -0
- package/dist/src/init/grok-generator.js +371 -0
- package/dist/src/init/grok-templates.d.ts +11 -0
- package/dist/src/init/grok-templates.js +28 -0
- package/dist/src/init/index.d.ts +2 -0
- package/dist/src/init/index.js +2 -0
- package/dist/src/mcp-client.js +4 -0
- package/dist/src/mcp-tools/agent-execute-core.js +59 -12
- package/dist/src/mcp-tools/capability-brain.d.ts +1 -1
- package/dist/src/mcp-tools/capability-brain.js +5 -3
- package/dist/src/mcp-tools/embeddings-tools.js +11 -4
- package/dist/src/mcp-tools/hooks-tools.js +13 -3
- package/dist/src/mcp-tools/index.d.ts +1 -0
- package/dist/src/mcp-tools/index.js +2 -0
- package/dist/src/mcp-tools/memory-tools.js +42 -4
- package/dist/src/mcp-tools/task-tools.js +7 -3
- package/dist/src/mcp-tools/team-tools.d.ts +15 -0
- package/dist/src/mcp-tools/team-tools.js +244 -0
- package/dist/src/memory/memory-bridge.d.ts +19 -0
- package/dist/src/memory/memory-bridge.js +163 -3
- package/dist/src/memory/memory-initializer.d.ts +4 -0
- package/dist/src/memory/memory-initializer.js +70 -37
- package/dist/src/memory/rabitq-index.d.ts +19 -0
- package/dist/src/memory/rabitq-index.js +117 -1
- package/dist/src/missions/schemas.d.ts +113 -113
- package/dist/src/mods/command-registry/schema.d.ts +193 -193
- package/dist/src/parser.js +3 -2
- package/dist/src/services/live-harness.d.ts +111 -0
- package/dist/src/services/live-harness.js +427 -0
- package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
- package/package.json +4 -3
- package/plugins/ruflo-console/dist/tui.mjs +1 -1
- package/plugins/ruflo-metaharness/scripts/_similarity.mjs +62 -2
- package/plugins/ruflo-metaharness/scripts/audit-trend.mjs +5 -5
- package/plugins/ruflo-metaharness/scripts/similarity.mjs +1 -0
- package/plugins/ruflo-metaharness/scripts/test-similarity.mjs +63 -0
- package/templates/grok/agents/ruflo-architect.md +35 -0
- package/templates/grok/agents/ruflo-coder.md +34 -0
- package/templates/grok/agents/ruflo-reviewer.md +30 -0
- package/templates/grok/agents/ruflo-tester.md +26 -0
- package/templates/grok/config.toml +63 -0
- package/templates/grok/docs/README.md +186 -0
- package/templates/grok/hooks/subagent-stop-team.json +15 -0
- package/templates/grok/rules/ruflo-grok.md +132 -0
- package/templates/grok/scripts/grok-subagent-stop-hook.mjs +90 -0
- package/templates/grok/scripts/grok-team-bus.mjs +525 -0
- package/templates/grok/scripts/grok-team-store.mjs +287 -0
- package/templates/grok/scripts/host-statusline.mjs +281 -0
- package/templates/grok/skills/agent-teams-grok/SKILL.md +98 -0
|
@@ -17,7 +17,7 @@ var Sn=e=>typeof e=="number"&&Number.isFinite(e)&&Math.abs(e)<=864e13?e:void 0,G
|
|
|
17
17
|
`).filter(o=>o.trim()!=="").slice(-Hy),n=t.flatMap(o=>Vy(o)??[]);return{alerts:n,bad:t.length-n.length}}async function FM(e,t,n){let o=p=>J(n,`${Fy}/${p}`),[s,r,i]=await Promise.all([pe(e,t,o("status.json"),DM,!0),pe(e,t,o("rules.json"),DM,!0),pe(e,t,o("alerts.jsonl"),Wy,!0)]);if(![s,r,i].some(p=>p.text!==null||p.reason!=="missing"))return fU;let l=[],d=(p,h,y)=>{(h.text===null?h.reason!=="missing":y===null)&&l.push(p)},u=mU(s.text),c=hU(r.text),f=gU(i.text);return d("status.json",s,u),d("rules.json",r,c),d("alerts.jsonl",i,i.text===null?null:{}),{present:!0,status:u,modeOverride:c?.mode??null,overrides:c?.overrides??{},alerts:f.alerts,refused:l,badAlerts:f.bad}}var od=["read","edit","test","git-local","git-branch","network","spawn","mcp"],xp=["publish","release","deploy","force-push","secret-access","delete-outside-worktree","envelope-edit"],Ky=[["publish",/\b(npm\s+publish|publish(es|ed|ing)?\b|pnpm\s+publish|cargo\s+publish|twine|docker\s+push)/i],["release",/\b(gh\s+release|git\s+tag\b.*push|cut\s+a\s+release|create\s+(a\s+)?release|release\s+notes?\s+and\s+tag)/i],["deploy",/\b(deploy(s|ed|ing)?\b|gcloud\s+run\s+deploy|firebase\s+deploy|kubectl\s+apply|terraform\s+apply)/i],["force-push",/(push\s+(--force|-f\b|--force-with-lease)|force[- ]push)/i],["secret-access",/\b(api[_ -]?key|secret|credential|password|private\s+key|\.env\b|gcloud\s+secrets|token)\b/i],["delete-outside-worktree",/\b(rm\s+-rf?\s+(\/|~|\$HOME)|delete\s+(the\s+)?(home|root|\/)|drop\s+database|mkfs|dd\s+of=\/dev)/i],["envelope-edit",/\b(autopilot\s+(envelope|scope|settings)|widen\s+(the\s+)?(envelope|scope)|raise\s+(the\s+)?(spend|budget)\s+(cap|ceiling)|grant\s+(itself|autopilot))|\.claude-flow\/(console\/autopilot|protector-mod)|autopilot\/(envelope|journal|kill)|protector-mod|\b(clear|remove|delete|rm|unset|touch)\b[^\n]{0,40}\bkill\s*(flag|switch|file)\b/i]],yU=[".claude-flow/console",".claude-flow/protector-mod"],HM=e=>{let t=e.replace(/\/+/g,"/").replace(/\/\.\//g,"/");return yU.some(n=>t.includes(n))||t.endsWith("/.claude-flow")||t.endsWith("/.claude-flow/")},bU=new Set(["sh","bash","zsh","dash","fish","ksh","csh","tcsh","env","xargs","sudo","doas","su","eval","exec","nohup","setsid","timeout","time","watch","rm","rmdir","dd","mkfs","shred","chmod","chown","mv","ln","curl","wget","nc","ncat","socat","ssh","scp","sftp","rsync","ftp","telnet","python","python3","perl","ruby","php","osascript","crontab","systemctl","kill","pkill","killall","tee","cp","install","truncate"]),wU=e=>/[`\n]|\$\(|;|&&|\|\||\|/.test(e);function kU(e){let t=(e[0]??"").split("/").at(-1)?.toLowerCase()??"";if(bU.has(t))return`"${t.slice(0,20)}" is a shell, a wrapper or a destructive or network tool and cannot be a verify command`;if(e.some(wU))return"a verify part holds a shell metacharacter (; | & ` $( newline): give a program and its arguments only";let n=e.join(" "),o=Ky.find(([,s])=>s.test(n))?.[0];return o===void 0?null:`it names "${o}", which can never be granted`}var zy=1,Xy=36e5,Yy=90*864e5,WM=8,vU=["name","toolClasses","paths","repos","network","secretEnv","spend","concurrency","maxDurationMs","verify","acceptWithoutAnatole"],Gy=/[\u0000-\u001f\u007f-\u009f---]|[\u{e0000}-\u{e0fff}]/u,$U=/^[A-Za-z0-9_.-]{1,60}\/[A-Za-z0-9_.-]{1,100}$/,xU=/^[a-z0-9]([a-z0-9.-]{0,251}[a-z0-9])?$/,SU=/^[A-Z][A-Z0-9_]{1,63}$/,$p=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),nd=(e,t)=>Array.isArray(e)&&e.length<=t&&e.every(n=>typeof n=="string")?e:null,qy=e=>typeof e=="number"&&Number.isFinite(e)&&e>0&&e<=1e6,MU=e=>xp.includes(e.trim().toLowerCase());function ho(e){let t=[];if(!$p(e))return{ok:!1,errors:["an envelope is an object"]};for(let p of Object.keys(e))vU.includes(p)||t.push(`unknown field "${p.slice(0,30)}": nothing is granted by a field this console does not define`);let n=typeof e.name=="string"&&e.name.trim()!==""&&e.name.length<=60&&!Gy.test(e.name)?e.name.trim():null;n===null&&t.push("name: 1 to 60 printable characters");let o=nd(e.toolClasses,12);o===null&&t.push("toolClasses: a list of tool classes");for(let p of o??[])MU(p)?t.push(`toolClasses: "${p}" is a hard deny and can never be granted to autopilot`):od.includes(p)||t.push(`toolClasses: unknown class "${p.slice(0,20)}"`);let s=nd(e.paths,20);(s===null||s.length===0)&&t.push("paths: at least one absolute folder");for(let p of s??[])!p.startsWith("/")||p==="/"||p.length>300||Gy.test(p)||p.split("/").includes("..")||p.includes("\\")?t.push(`paths: "${p.slice(0,40)}" is not an absolute folder below the root with no ..`):HM(p)&&t.push(`paths: "${p.slice(0,40)}" is the autopilot's or Project Anatole's own folder: steps are never pointed at it`);let r=nd(e.repos,20);r===null&&t.push("repos: a list of owner/name");for(let p of r??[])$U.test(p)||t.push(`repos: "${p.slice(0,40)}" is not owner/name`);let i=nd(e.network,30);i===null&&t.push("network: a list of hostnames (empty means none)");for(let p of i??[])(!xU.test(p)||p.includes(".."))&&t.push(`network: "${p.slice(0,40)}" is not a lowercase hostname (no wildcard, no port)`);let a=nd(e.secretEnv,8);a===null&&t.push("secretEnv: a list of up to 8 variable names (empty means none)");for(let p of a??[])SU.test(p)||t.push(`secretEnv: "${p.slice(0,30)}" is not a variable name; give names only, never values`);let l=$p(e.spend)?e.spend:null;l!==null&&qy(l.hourUsd)&&qy(l.dayUsd)&&qy(l.totalUsd)?l.hourUsd<=l.dayUsd&&l.dayUsd<=l.totalUsd||t.push("spend: hour must not exceed day, nor day the total"):t.push("spend: hourUsd, dayUsd and totalUsd, each above 0");let u=e.concurrency;(typeof u!="number"||!Number.isInteger(u)||u<1||u>WM)&&t.push(`concurrency: a whole number from 1 to ${WM}`);let c=e.maxDurationMs;(typeof c!="number"||!Number.isFinite(c)||c<Xy||c>Yy)&&t.push("maxDurationMs: from 1 hour to 90 days");let f=e.verify;if((!Array.isArray(f)||f.length>6||!f.every(p=>Array.isArray(p)&&p.length>=1&&p.length<=24&&p.every(h=>typeof h=="string"&&h.length<=300&&!Gy.test(h))))&&t.push("verify: up to 6 argv lists of plain strings (a program and its arguments, never a shell line)"),Array.isArray(f)&&t.every(p=>!p.startsWith("verify")))for(let p of f){let h=kU(p);h!==null&&t.push(`verify: ${h}`)}return typeof e.acceptWithoutAnatole!="boolean"&&t.push("acceptWithoutAnatole: true or false"),t.length>0?{ok:!1,errors:t}:{ok:!0,envelope:{name:n,toolClasses:[...new Set(o)].sort(),paths:[...new Set(s)].map(p=>p.replace(/\/+$/,"")).sort(),repos:[...new Set(r)].sort(),network:[...new Set(i)].sort(),secretEnv:[...new Set(a)].sort(),spend:{hourUsd:l.hourUsd,dayUsd:l.dayUsd,totalUsd:l.totalUsd},concurrency:u,maxDurationMs:c,verify:f.map(p=>[...p]),acceptWithoutAnatole:e.acceptWithoutAnatole}}}function br(e){return Array.isArray(e)?`[${e.map(br).join(",")}]`:$p(e)?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${br(e[t])}`).join(",")}}`:JSON.stringify(e)??"null"}var AU=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]);function ys(e){let t=new TextEncoder().encode(e),n=Math.ceil((t.length+9)/64)*64,o=new Uint8Array(n);o.set(t),o[t.length]=128;let s=new DataView(o.buffer);s.setUint32(n-8,Math.floor(t.length*8/4294967296)),s.setUint32(n-4,t.length*8>>>0);let r=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),i=new Uint32Array(64),a=(l,d)=>l>>>d|l<<32-d;for(let l=0;l<n;l+=64){for(let k=0;k<16;k++)i[k]=s.getUint32(l+k*4);for(let k=16;k<64;k++){let $=i[k-15],S=i[k-2];i[k]=i[k-16]+(a($,7)^a($,18)^$>>>3)+i[k-7]+(a(S,17)^a(S,19)^S>>>10)>>>0}let[d,u,c,f,p,h,y,b]=r;for(let k=0;k<64;k++){let $=b+(a(p,6)^a(p,11)^a(p,25))+(p&h^~p&y)+AU[k]+i[k]>>>0,S=(a(d,2)^a(d,13)^a(d,22))+(d&u^d&c^u&c)>>>0;b=y,y=h,h=p,p=f+$>>>0,f=c,c=u,u=d,d=$+S>>>0}let w=[d,u,c,f,p,h,y,b];for(let k=0;k<8;k++)r[k]=r[k]+w[k]>>>0}return[...r].map(l=>l.toString(16).padStart(8,"0")).join("")}var bs=e=>ys(br(e)),BM=(e,t,n)=>({version:zy,revision:t,approvedAtMs:n,hash:bs(e),envelope:e});function UM(e){if(e===null)return{ok:!1,why:"no envelope approved yet"};let t;try{t=JSON.parse(e)}catch{return{ok:!1,why:"the envelope file is not JSON"}}if(!$p(t)||t.version!==zy||typeof t.hash!="string"||typeof t.revision!="number"||typeof t.approvedAtMs!="number")return{ok:!1,why:"the envelope file is not a version-1 sealed envelope"};let n=ho(t.envelope);return n.ok?bs(n.envelope)!==t.hash?{ok:!1,why:"the envelope does not match its hash: it was changed outside the console, so autopilot will not run on it"}:{ok:!0,sealed:{version:zy,revision:t.revision,approvedAtMs:t.approvedAtMs,hash:t.hash,envelope:n.envelope}}:{ok:!1,why:`the envelope no longer validates: ${n.errors[0]}`}}function Sp(e,t){let n=[],o=(s,r,i)=>{let a=i.filter(l=>!r.includes(l));a.length>0&&n.push(`${s}: adds ${a.slice(0,4).join(", ")}${a.length>4?"\u2026":""}`)};o("tool classes",e.toolClasses,t.toolClasses),o("paths",e.paths,t.paths),o("repos",e.repos,t.repos),o("network",e.network,t.network),o("secret env",e.secretEnv,t.secretEnv),o("verify commands",e.verify.map(s=>s.join(" ")),t.verify.map(s=>s.join(" ")));for(let s of["hourUsd","dayUsd","totalUsd"])t.spend[s]>e.spend[s]&&n.push(`${s}: ${e.spend[s]} to ${t.spend[s]}`);return t.concurrency>e.concurrency&&n.push(`concurrency: ${e.concurrency} to ${t.concurrency}`),t.maxDurationMs>e.maxDurationMs&&n.push("duration: longer"),t.acceptWithoutAnatole&&!e.acceptWithoutAnatole&&n.push("runs without Project Anatole"),n}function VM(e,t){let n=[],o=(s,r,i)=>{let a=r.filter(l=>!i.includes(l));a.length>0&&n.push(`${s}: removes ${a.slice(0,4).join(", ")}${a.length>4?"\u2026":""}`)};o("tool classes",e.toolClasses,t.toolClasses),o("paths",e.paths,t.paths),o("repos",e.repos,t.repos),o("network",e.network,t.network),o("secret env",e.secretEnv,t.secretEnv),o("verify commands",e.verify.map(s=>s.join(" ")),t.verify.map(s=>s.join(" ")));for(let s of["hourUsd","dayUsd","totalUsd"])t.spend[s]<e.spend[s]&&n.push(`${s}: ${e.spend[s]} to ${t.spend[s]}`);return t.concurrency<e.concurrency&&n.push(`concurrency: ${e.concurrency} to ${t.concurrency}`),t.maxDurationMs<e.maxDurationMs&&n.push("duration: shorter"),!t.acceptWithoutAnatole&&e.acceptWithoutAnatole&&n.push("no longer runs without Project Anatole"),n}var GM=(e,t)=>!t.split("/").includes("..")&&!HM(t)&&e.paths.some(n=>t===n||t.startsWith(`${n}/`)),qM=(e,t)=>e.network.includes(t.toLowerCase()),zM=(e,t)=>e.toolClasses.includes(t),wr=".claude-flow/console/autopilot",Zy=`${wr}/envelope.json`,sd=`${wr}/KILL`;var RU=".claude-flow/data/ranked-context.json",KM=".claude-flow/sessions",EU=".claude-flow/neural/models.json",CU=".claude-flow/neural/patterns.json",TU=".claude-flow/data/recall-log.jsonl",OU=1e3,Ap=6,XM=.6,YM=.9,_U=.15,PU=5,IU=8,LU=10,NU=new Set(["the","a","an","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","shall","can","to","of","in","for","on","with","at","by","from","as","into","through","during","before","after","and","but","or","nor","not","so","yet","both","either","neither","each","every","all","any","few","more","most","other","some","such","no","only","own","same","than","too","very","just","because","if","when","which","who","whom","this","that","these","those","it","its"]),DU=e=>e.toLowerCase().replace(/[^a-z0-9\s-]/g," ").split(/\s+/).filter(t=>t.length>2&&!NU.has(t));var id=(e,t)=>v(e,t*2).split(" ").map(n=>mr(n)?"\u2022\u2022\u2022\u2022":n).join(" ").slice(0,t),JM=e=>XM*e.pageRank+(1-XM)*(e.confidence??.5);function jU(e){let t=ke(e);if(t===null||!Array.isArray(t.entries))return null;let n=t.entries.flatMap(o=>{let s=R(o);if(s===null||typeof s.id!="string")return[];let r=Array.isArray(s.words)?s.words.filter(i=>typeof i=="string"):[];return[{id:v(s.id,80),summary:id(typeof s.summary=="string"?s.summary:typeof s.content=="string"?s.content:"",80),category:v(typeof s.category=="string"?s.category:"",24),confidence:be(s.confidence)??null,pageRank:be(s.pageRank)??0,accessCount:be(s.accessCount)??0,words:r}]});return{computedAtMs:X(t.computedAt)??null,entries:n}}function FU(e){let t=new Set([e]);for(let n of["s","es","ed","ing","ion","ions"])t.add(e+n);for(let n of["ions","ion","ing","ed","es","s"])if(e.length-n.length>=4&&e.endsWith(n)){let o=e.slice(0,-n.length);t.add(o),t.add(o+"e"),t.add(o+"s")}return[...t]}var ZM=new WeakMap,WU=e=>{let t=ZM.get(e);return t===void 0&&ZM.set(e,t=new Set(e.words)),t},rd=null;function QM(e,t){if(rd!==null&&rd.prompt===e&&rd.entries===t)return rd.out;let n=[...new Set(DU(e))];if(n.length===0)return[];let o=n.map(FU),s=t.map(WU),r=(u,c)=>o[c].some(f=>u.has(f)),i=n.map((u,c)=>{let f=0;for(let p of s)r(p,c)&&f++;return Math.log1p((t.length-f+.5)/(f+.5))}),a=i.reduce((u,c)=>u+c,0);if(a===0)return[];let l=[];t.forEach((u,c)=>{let f=0,p=0;for(let y=0;y<n.length;y++)i[y]>0&&r(s[c],y)&&(f+=i[y],p++);if(p<Math.min(2,n.length))return;let h=f/a;if(h>=_U){let y=Math.max(0,Math.min(1,Number(u.pageRank)||0));l.push({entry:u,match:h,score:YM*h+(1-YM)*y})}});let d=l.sort((u,c)=>c.score-u.score).slice(0,PU);return rd={prompt:e,entries:t,out:d},d}function HU(e,t){let n=ke(t),o=R(n?.context)?.lastMatchedPatterns;return n===null||!Array.isArray(o)?null:{file:v(e,60),startedAtMs:X(n.startedAt)??null,updatedAtMs:X(n.updatedAt)??null,ids:o.filter(s=>typeof s=="string").slice(0,20).map(s=>v(s,80))}}function BU(e){let t=ke(e);if(t===null||!Array.isArray(t.outcomes))return[];let n=t.outcomes.flatMap(r=>{let i=R(r),a=X(i?.timestamp);return i===null||a===void 0||typeof i.task!="string"||i.task.trim()===""?[]:[{task:id(i.task,160),agent:v(typeof i.agent=="string"?i.agent:"?",30),ok:i.success===!0,atMs:a,digest:nb(i.task)}]}),o=new Set,s=[];for(let r of n.sort((i,a)=>a.atMs-i.atMs))if(!o.has(r.task)&&(o.add(r.task),s.push(r),s.length>=LU))break;return s}var nb=e=>ys(e.trim()).slice(0,16);function UU(e){if(e===null)return[];let t=[];for(let n of e.split(`
|
|
18
18
|
`)){if(n===""||n.length>2e4)continue;let o;try{o=JSON.parse(n)}catch{continue}let s=R(o),r=be(s?.at),i=typeof s?.digest=="string"&&/^[0-9a-f]{8,64}$/.test(s.digest)?s.digest:null;if(s===null||r===void 0||r<=0||i===null||!Array.isArray(s.surfaced))continue;let a=s.surfaced.slice(0,10).flatMap(d=>{let u=R(d),c=be(u?.score),f=be(u?.rank);return u===null||typeof u.id!="string"||u.id===""||c===void 0||f===void 0?[]:[{id:v(u.id,80),score:c,rank:f,category:v(typeof u.cat=="string"?u.cat:"",40)}]});if(a.length===0)continue;let l=R(s.router);t.push({atMs:r,sessionId:typeof s.sid=="string"?v(s.sid,64):null,digest:i,surfaced:a,router:l===null?null:{agent:v(typeof l.agent=="string"?l.agent:"?",30),confidence:be(l.confidence)??null}})}return t.sort((n,o)=>o.atMs-n.atMs).slice(0,OU)}function ad(e){let t=new Map;for(let n of e)for(let o of n.surfaced){let s=t.get(o.id);s===void 0?t.set(o.id,{id:o.id,category:o.category,count:1,lastAtMs:n.atMs}):(s.count+=1,s.lastAtMs=Math.max(s.lastAtMs,n.atMs))}return t}var Rp=(e,t)=>e.length===0?0:Math.max(0,t-(e[e.length-1]?.atMs??t));function VU(e){let t=ke(e),n=R(t?.patterns);return n===null?null:Object.values(n).slice(0,1e3).flatMap(o=>{let s=R(o);if(s===null||typeof s.id!="string")return[];let r=R(s.metadata)?.verdict;return[{id:v(s.id,80),name:id(typeof s.name=="string"?s.name:"",90),type:v(typeof s.type=="string"?s.type:"?",24),content:v(typeof s.content=="string"?s.content:"",600),createdAtMs:X(s.createdAt)??null,usageCount:be(s.usageCount)??0,verdict:typeof r=="string"?v(r,20):null}]})}var eA=e=>[...e].sort((t,n)=>n.usageCount-t.usageCount||(t.createdAtMs??1/0)-(n.createdAtMs??1/0)),Ep=(e,t)=>e.filter(n=>n.usageCount<t).map(n=>n.id),ws=e=>e?.recall??null,Mp=e=>e.text!==null?"ok":e.reason??"missing",Jy=null,Qy=null,eb=null,tb=null;async function tA(e,t,n){let[o,s,r,i,a,l]=await Promise.all([pe(e,t,J(n,RU)),pe(e,t,J(n,EU)),pe(e,t,J(n,gr.outcomes)),pe(e,t,J(n,TU),2e6,!0),e.stat(J(n,CU)).catch(()=>{}),e.list(J(n,KM)).catch(()=>null)]),d=(l??[]).filter(f=>f.kind!=="dir"&&/^session-\d+\.json$/.test(f.name)).sort((f,p)=>(p.mtimeMs??0)-(f.mtimeMs??0)).slice(0,IU),c=(await Promise.all(d.map(async f=>({name:f.name,read:await pe(e,t,J(n,`${KM}/${f.name}`),1e5,!0)})))).flatMap(({name:f,read:p})=>{let h=HU(f,p.text);return h===null?[]:[h]});return o.text!==null&&Jy?.text!==o.text&&(Jy={text:o.text,parsed:jU(o.text)}),s.text!==null&&Qy?.text!==s.text&&(Qy={text:s.text,parsed:VU(s.text)}),r.text!==null&&eb?.text!==r.text&&(eb={text:r.text,parsed:BU(r.text)}),i.text!==null&&tb?.text!==i.text&&(tb={text:i.text,parsed:UU(i.text)}),{ranked:o.text===null?null:Jy?.parsed??null,sessions:c,prompts:r.text===null?[]:eb?.parsed??[],neural:s.text===null?null:Qy?.parsed??null,log:i.text===null?[]:tb?.parsed??[],reads:{ranked:Mp(o),sessions:l===null?"missing":"ok",prompts:Mp(r),neural:Mp(s),bank:a===void 0?"missing":(a.size??0)>2e6?"too-large":"ok",log:Mp(i)}}}function nA(e){let t=ke(e);if(t===null)return null;let n={},o=re(t.trajectoriesRecorded),s=re(t.patternsLearned),r=re(t.signalsProcessed),i=X(t.lastAdaptation);return o!==void 0&&(n.trajectories=o),s!==void 0&&(n.patterns=s),r!==void 0&&(n.signals=r),i!==void 0&&(n.lastAdaptationMs=i),n}function oA(e){let t=ke(e);if(t===null)return null;let n=Object.entries(R(t.modelDistribution)??{}).slice(0,12).flatMap(([l,d])=>re(d)!==void 0?[{model:v(l,20),count:re(d)}]:[]),o=(Array.isArray(t.learningHistory)?t.learningHistory:[]).slice(-200).flatMap(l=>{let d=R(l),u=X(d?.timestamp);return d===null||u===void 0||typeof d.outcome!="string"?[]:[{ok:d.outcome==="success",atMs:u}]}),s={distribution:n,history:o},r=re(t.totalDecisions),i=Dt(t.avgConfidence),a=X(t.lastUpdated);return r!==void 0&&(s.decisions=r),i!==void 0&&(s.avgConfidence=i),a!==void 0&&(s.updatedMs=a),s}function sA(e){let t=ke(e);if(t===null||!Array.isArray(t.outcomes))return null;let n=t.outcomes.slice(-500).flatMap(o=>{let s=R(o),r=X(s?.timestamp);if(s===null||r===void 0||typeof s.success!="boolean")return[];let i=Dt(s.quality);return[{ok:s.success,agent:D(s.agent,30)??"?",atMs:r,...i!==void 0&&{quality:i}}]});return n.sort((o,s)=>o.atMs-s.atMs),{total:n.length,successes:n.filter(o=>o.ok).length,points:n}}function rA(e){let t=ke(e);return t===null?null:{patterns:Object.keys(R(t.patterns)??{}).length}}function iA(e){let t=ke(e);if(t===null)return null;let n=Object.entries(R(t.workers)??{}).slice(0,24).flatMap(([r,i])=>{let a=R(i),l=X(a?.lastRun);return a===null?[]:[{name:v(r,20),runs:re(a.runCount)??0,failures:re(a.failureCount)??0,...l!==void 0&&{lastRunMs:l}}]}),o={running:t.running===!0,workers:n},s=X(t.savedAt)??X(t.startedAt);return s!==void 0&&(o.savedAtMs=s),o}function aA(e){let t=ke(e),n=D(t?.championId,90);if(t===null||n===void 0)return null;let o=D(t.provenanceTier,40),s=D(t.layer,40),r=X(t.appliedAt);return{champion:n,...o!==void 0&&{tier:o},...s!==void 0&&{layer:s},...r!==void 0&&{appliedAtMs:r}}}function lA(e){let t=ke(e),n=R(t?.manifest);if(t===null||n===null)return null;let o=Object.keys(R(n.files)??{}).filter(r=>/^[A-Za-z0-9._-]{1,80}$/.test(r)).slice(0,40),s=D(t.algorithm,20);return{version:D(n.version,20)??"unknown",files:o,isSigned:typeof t.signature=="string"&&t.signature.length>20,...s!==void 0&&{algorithm:s}}}function dA(e){let t=ke(e),n=R(t?.plugins);return t===null||n===null?null:Object.entries(n).slice(0,400).flatMap(([o,s])=>{let[r,i]=o.split("@"),a=R(Array.isArray(s)?s[0]:s);if(a===null||r===void 0||i===void 0||!/^[A-Za-z0-9._-]{1,80}$/.test(r)||!/^[A-Za-z0-9._-]{1,80}$/.test(i))return[];let l=X(a.lastUpdated),d=typeof a.installPath=="string"&&a.installPath.length<=300?a.installPath:void 0;return[{id:`${r}@${i}`,name:r,marketplace:i,version:D(a.version,30)??"?",scope:D(a.scope,12)??"?",...l!==void 0&&{updatedMs:l},...d!==void 0&&{installPath:d}}]})}function uA(e){let t=ke(e);return t===null?null:Object.entries(t).slice(0,50).flatMap(([n,o])=>{let s=R(o),r=typeof s?.installLocation=="string"?s.installLocation:void 0,i=X(s?.lastUpdated),a=r!==void 0&&r.startsWith("/")&&!r.split("/").includes("..")&&r.length<400?r:void 0;return s===null||!/^[A-Za-z0-9._-]{1,80}$/.test(n)?[]:[{name:n,isAutoUpdate:s.autoUpdate===!0,...a!==void 0&&{location:a},...i!==void 0&&{updatedMs:i}}]})}function cA(e){let t=ke(e);return t===null||!Array.isArray(t.plugins)?null:t.plugins.slice(0,400).flatMap(n=>{let o=R(n)?.name;return typeof o=="string"&&/^[A-Za-z0-9._-]{1,80}$/.test(o)?[o]:[]})}function pA(e){let t=R(R(e)?.enabledPlugins)??{};return new Set(Object.entries(t).flatMap(([n,o])=>o===!0&&/^[A-Za-z0-9._-]{1,80}@[A-Za-z0-9._-]{1,80}$/.test(n)?[n]:[]))}function fA(e){let t=ke(e),n=R(t?.swarm);if(t===null||n===null)return null;let o=re(n.agent_count),s=X(t.timestamp);return{isActive:n.active===!0,...o!==void 0&&{agentCount:o},...s!==void 0&&{atMs:s}}}var GU="ruflo.mission-observation/1";var ob=/^[A-Za-z0-9_.:-]{1,80}$/;function Cp(e){let t=ke(e);if(t===null||t.contract!==GU||t.schemaVersion!==1||!Array.isArray(t.missions))return null;let n=t.missions.slice(0,50).flatMap(o=>{let s=R(o),r=typeof s?.missionId=="string"&&ob.test(s.missionId)?s.missionId:null;if(s===null||r===null)return[];let i=R(s.plan),a=R(s.budget),l=R(s.evidence),d=R(s.executor),u=(Array.isArray(i?.tasks)?i.tasks:[]).slice(0,50).flatMap(h=>{let y=R(h),b=typeof y?.id=="string"&&ob.test(y.id)?y.id:null;return y===null||b===null?[]:[{id:b,title:v(y.title,80),dependsOn:(Array.isArray(y.dependsOn)?y.dependsOn:[]).slice(0,20).flatMap(w=>typeof w=="string"&&ob.test(w)?[w]:[]),status:D(y.status,20)??"unknown"}]}),c={id:r,objective:v(s.objective,2e3),state:D(s.state,30)??"unknown",revision:be(s.revision)??0,executionMode:D(s.executionMode,30)??"unknown",plan:{revision:be(i?.revision)??0,taskCount:be(i?.taskCount)??u.length,tasks:u},budget:a===null?null:{currency:D(a.currency,8)??"?",...Object.fromEntries(["ceilingMinor","estimatedMinor","reservedMinor","settledMinor","unresolvedMinor"].flatMap(h=>be(a[h])!==void 0?[[h,be(a[h])]]:[]))},evidence:{count:be(l?.count)??0,verified:be(l?.verified)??0},executor:d===null?null:{connection:D(d.connection,20)??"unknown",...X(d.observedAt)!==void 0&&{observedAtMs:X(d.observedAt)}},unresolvedOperations:be(s.unresolvedOperations)??0},f=D(s.blockedReason,120),p=X(s.updatedAt);return f!==void 0&&(c.blockedReason=f),p!==void 0&&(c.updatedAtMs=p),[c]});return{observedAtMs:X(t.observedAt)??null,isTruncated:t.truncated===!0,missions:n}}function No(e,t){if(e===void 0)return"n/a";let n=(e/100).toFixed(2);return t==="USD"?`$${n}`:`${n} ${t}`}var ks=e=>re(e)??0;function mA(e){let t=ke(e);if(t===null||t.version!==1)return null;let n=(Array.isArray(t.recent)?t.recent:[]).slice(-5).flatMap(o=>{let s=R(o);return s!==null&&typeof s.snippet=="string"?[{source:typeof s.source=="string"?v(s.source,24):"?",score:typeof s.score=="number"&&Number.isFinite(s.score)?s.score:null,snippet:v(s.snippet,120)}]:[]});return{recall:t.recall===!0,guard:t.guard===!0,source:typeof t.source=="string"?v(t.source,16):"auto",tool:typeof t.lastTool=="string"?v(t.lastTool,24):null,updatedMs:Sn(t.updatedMs)??null,attached:ks(t.attached),skipped:ks(t.skipped),cached:ks(t.cached),timedOut:ks(t.timedOut),dropped:ks(t.dropped),blocked:ks(t.blocked),errors:ks(t.errors),lastMs:typeof t.lastMs=="number"?ks(t.lastMs):null,recent:n}}var qU=60,zU=8192,KU=6*36e5,hA=".claude-flow",XU=/^[a-z0-9][a-z0-9-]{0,40}-mod$/;var ib={rows:[],refused:0,truncated:!1},ld=e=>typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.min(Math.floor(e),Number.MAX_SAFE_INTEGER):null,YU=64,sb=Number.MAX_SAFE_INTEGER;function ZU(e){let t=ld(e.calls);if(t!==null)return Math.min(t,sb);let n=R(e.calls);if(n!==null){let s=0;for(let r of Object.values(n).slice(0,YU))s=Math.min(s+(ld(r)??0),sb);return s}let o=ld(e.seen)??ld(e.checked);return o===null?null:Math.min(o,sb)}var gA=120,JU=/^[0-9][0-9A-Za-z.+-]{0,15}$/,QU=[["secret",/secret|token|credential|password|api[-_ ]?key|\.env|private[-_ ]?key/i],["destructive",/destruct|rm -|delete|wipe|force|reset --hard|drop /i],["path",/path|travers|outside|directory|file/i],["network",/network|url|host|curl|http|exfil/i],["policy",/polic|permission|deny|denied|block|guard|rule/i]],yA=e=>typeof e=="string"&&JU.test(e)?e:null;function rb(e){let t=v(e,200);return t===""?null:QU.find(([,n])=>n.test(t))?.[0]??"other"}function e3(e,t,n=null){let o=ke(t);if(o===null||o.version!==1)return null;let s=rb(o.lastDenied)??rb(o.lastReason)??rb(o.lastBlocked);return{name:e.slice(0,-4),guard:typeof o.guard=="boolean"?o.guard:null,calls:ZU(o),blocked:ld(o.blocked)??0,updatedMs:Sn(o.updatedMs)??null,startedMs:Sn(o.startedMs)??null,...yA(o.modVersion)!==null&&{modVersion:yA(o.modVersion)},...v(o.summary,gA)!==""&&{summary:v(o.summary,gA)},...s!==null&&{lastDenied:s},...n!==null&&n>=0&&{fileMs:n}}}function t3(e){return[...e].sort((t,n)=>+(n.blocked>0)-+(t.blocked>0)||n.blocked-t.blocked||(n.updatedMs??-1)-(t.updatedMs??-1)||t.name.localeCompare(n.name))}var ab=(e,t)=>e.updatedMs===null||t-e.updatedMs>KU;async function bA(e,t,n){let o=await e.list(J(n,hA)).catch(()=>null);if(o===null)return ib;let s=o.filter(d=>d.kind!=="file"&&XU.test(d.name)).map(d=>d.name).sort(),r=s.slice(0,qU),i=await Promise.all(r.map(async d=>({name:d,read:await pe(e,t,J(n,`${hA}/${d}/status.json`),zU,!0)}))),a=[],l=0;for(let{name:d,read:u}of i){if(u.text===null&&u.reason==="missing")continue;let c=e3(d,u.text,"mtimeMs"in u?u.mtimeMs:null);c===null?l+=1:a.push(c)}return{rows:t3(a),refused:l,truncated:s.length>r.length}}var je="ruflo",dd=["ruflo-core","ruflo-mods","ruflo-swarm"],n3=e=>e.text!==null?"ok":e.reason;async function wA(e,t,n,o,s,r,i,a=!1){let l=await aM(e,t,n,o,i===void 0?o===null?null:`${o}/.claude`:i,a),d=w=>po(l.project[w]),u=eS(d("swarm")),c=tS(d("pointer")),f=u??(c!==null?{id:c.id,topology:c.topology??"unknown",status:c.status??"unknown",agentIds:[],...c.strategy!==void 0&&{strategy:c.strategy}}:null),p=uA(po(l.home.marketplaces)),h=p?.find(w=>w.name===je)?.location,y=h===void 0?null:cA(po(await pe(e,t,`${h}/.claude-plugin/marketplace.json`)));return{reads:Object.fromEntries(Object.keys(l.project).map(w=>[w,n3(l.project[w])])),swarm:f,agents:gy(d("agents")),tasks:Yc(d("tasks")),claims:nS(d("claims")),hive:oS(d("hive")),hiveAgents:sS(d("hiveAgents")),activity:fA(d("activity")),daemon:iA(d("daemon")),neural:nA(d("neural")),router:oA(d("router")),outcomes:sA(d("outcomes")),sona:rA(d("sona")),harnessPolicy:aA(d("harnessPolicy")),helpers:lA(d("helpersManifest")),helpersVersion:d("helpersVersion")?.trim().slice(0,20)??null,isRufloProject:d("config")!==null||f!==null||d("claims")!==null||d("daemon")!==null,federationNodes:l.federationNodes,hasNostrKey:l.hasNostrKey,plugins:{installed:dA(po(l.home.installed)),enabled:pA(s),enabledKnown:typeof s?.enabledPlugins=="object"&&s.enabledPlugins!==null,markets:p,rufloOffered:y,missingFromClone:y===null?[]:dd.filter(w=>!y.includes(w))},missions:Cp(d("missions")),agentdbMod:mA(d("agentdbMod")),mods:await bA(e,t,n),anatole:await FM(e,t,n),recall:await tA(e,t,n),changed:l.changed,readAtMs:r}}var vA=["console","swarm","protector","mods"],Tp=["all","important","off"],o3=["info","ok","warn","error"];var $A={info:"\u203A",ok:"\u2713",warn:"\u26A0",error:"\u2717"},xA=120;var SA=".claude-flow/console",MA=`${SA}/toast-prefs.json`,AA=`${SA}/toasts`,kA="\u2039masked\u203A",s3=new RegExp("\\u001b\\][^\\u0007\\u001b]*(?:\\u0007|\\u001b\\\\)|\\u009d[^\\u0007\\u009c]*[\\u0007\\u009c]|(?:\\u001b\\[|\\u009b)[0-9;?]*[ -/]*[@-~]","g"),r3=new RegExp("[\\s\\u0085\\u2028\\u2029]+","g"),i3=new RegExp("[\\u0000-\\u0008\\u000e-\\u001f\\u007f-\\u0084\\u0086-\\u009f\\u00ad\\u034f\\u061c\\u115f\\u1160\\u17b4\\u17b5\\u180b-\\u180f\\u200b-\\u200f\\u202a-\\u202e\\u2060-\\u206f\\u3164\\ufe00-\\ufe0f\\ufeff\\uffa0\\ufff9-\\ufffb]|[\\u{e0000}-\\u{e0fff}]","gu"),a3=new RegExp([String.raw`\b(?:sk|pk|ghp|gho|ghs|github_pat|xox[abprs]|xapp|AKIA|ASIA|AIza)[-_A-Za-z0-9]{12,}`,String.raw`\b(?:glpat|npm|hf|dop_v1|shpat|whsec|rk_live|sk_live|ya29)[-_.][-_.A-Za-z0-9]{12,}`,String.raw`\bBearer\s+\S{8,}`,String.raw`\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\.?[A-Za-z0-9_-]*`,String.raw`\b[A-Za-z0-9+_-]{32,}={0,2}`,String.raw`-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)`,String.raw`\b[a-z][a-z0-9+.-]*://[^\s/:@]+:[^\s/@]+@`,String.raw`(?:key|token|secret|passw(?:or)?d|pwd|passphrase|credential|authorization|cookie)["']?\s*[=:]\s*(?:(?:Bearer|Basic|Token)\s+)?(?:"[^"]*"|'[^']*'|\S+)`,String.raw`(?<![A-Za-z0-9])pass["']?\s*=\s*(?:"[^"]*"|'[^']*'|\S+)`,String.raw`(?:^|\s)--?(?:token|password|passwd|pwd|secret|api-?key|auth(?:orization)?|access-?key|client-?secret)(?:=|\s+)\S+`].join("|"),"gi"),l3=/\/(?:home|Users)\/[^/\s'"]+/g,d3=/\b[\w.+-]{1,64}@[A-Za-z0-9-]{1,63}(?:\.[A-Za-z0-9-]{1,63})+\b/g;function vr(e,t=xA){if(typeof e!="string")return"";let o=e.slice(0,4096).replace(s3,"").replace(r3," ").replace(i3,"").trim().replace(a3,kA).replace(d3,kA).replace(l3,"~");return o.length>t?`${o.slice(0,Math.max(0,t-1))}\u2026`:o}var RA=/^[a-z][a-z0-9-]{0,23}$/;var lb=e=>`${JSON.stringify({v:1,mode:e.mode,muted:[...new Set(e.muted)].filter(t=>RA.test(t)).slice(0,8)})}
|
|
19
19
|
`,u3=["shown","deduped","rate-limited","coalesced","muted","off","filtered","away","refused"];function EA(e){if(typeof e!="string"||e==="")return[];let t=[];for(let n of e.slice(-3e5).split(`
|
|
20
|
-
`))if(!(n.length<2||n.length>600||n[0]!=="{"))try{let o=JSON.parse(n),s=o3.find(l=>l===o.l),r=u3.find(l=>l===o.w),i=typeof o.s=="string"&&RA.test(o.s)?o.s:void 0,a=vr(o.x,xA);if(o.v!==1||typeof o.t!="number"||!Number.isFinite(o.t)||s===void 0||r===void 0||i===void 0||a==="")continue;t.push({t:o.t,source:i,level:s,text:a,shown:r==="shown",why:r,...typeof o.n=="number"&&o.n>1&&o.n<1e6&&{n:Math.floor(o.n)}})}catch{}return t}var sn="0.44.
|
|
20
|
+
`))if(!(n.length<2||n.length>600||n[0]!=="{"))try{let o=JSON.parse(n),s=o3.find(l=>l===o.l),r=u3.find(l=>l===o.w),i=typeof o.s=="string"&&RA.test(o.s)?o.s:void 0,a=vr(o.x,xA);if(o.v!==1||typeof o.t!="number"||!Number.isFinite(o.t)||s===void 0||r===void 0||i===void 0||a==="")continue;t.push({t:o.t,source:i,level:s,text:a,shown:r==="shown",why:r,...typeof o.n=="number"&&o.n>1&&o.n<1e6&&{n:Math.floor(o.n)}})}catch{}return t}var sn="0.44.6";var OA="whatsnew",Li="ruflo-console",_A=e=>`https://github.com/ruvnet/ruflo/blob/main/plugins/${e}/CHANGELOG.md`,PA="https://github.com/ruvnet/ruflo/releases",c3=60,Op=200,p3=256*1024,f3=/^[A-Za-z0-9._-]{1,80}$/,m3=new Set(["__proto__","constructor","prototype","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toString","toLocaleString","valueOf","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"]),Di=e=>f3.test(e)&&!m3.has(e),db=e=>/^[A-Za-z0-9._-]{1,80}@\d{1,4}\.\d{1,4}\.\d{1,4}$/.test(e)&&Di(e.slice(0,e.lastIndexOf("@")));function Ni(e=[]){let t=Object.create(null);for(let[n,o]of e)Di(n)&&(t[n]=o);return t}var vs=(e,t)=>e!==null&&Object.hasOwn(e,t)?e[t]:void 0,IA=()=>({hydrated:!1,rec:null,isOpen:!1,before:null,logs:[],isLoading:!1,loadedAtMs:0,cache:new Map}),h3=()=>({seen:Ni(),toasted:Ni(),pinned:[],dismissed:[],toast:!0}),ub=e=>{let t=e.filter(n=>Di(n.name));return{...h3(),seen:Ni(t.map(n=>[n.name,n.version])),toasted:Ni(t.map(n=>[n.name,n.version]))}};function CA(e){let t=Ni();if(typeof e!="object"||e===null||Array.isArray(e))return t;for(let[n,o]of Object.entries(e).slice(0,Op))Di(n)&&typeof o=="string"&&Jl(o)!==null&&(t[n]=o);return t}var TA=e=>Array.isArray(e)?e.filter(t=>typeof t=="string"&&db(t)).slice(-Op):[];function g3(e){if(typeof e!="string"||e.length>64*1024)return null;try{let t=JSON.parse(e);return typeof t!="object"||t===null?null:{seen:CA(t.seen),toasted:CA(t.toasted),pinned:TA(t.pinned),dismissed:TA(t.dismissed),toast:t.toast!==!1}}catch{return null}}var y3=e=>JSON.stringify({v:1,seen:e.seen,toasted:e.toasted,pinned:e.pinned.slice(-Op),dismissed:e.dismissed.slice(-Op),toast:e.toast});function _p(e,t=null){let o=(e.snapshot?.plugins.installed??[]).filter(r=>r.marketplace===je&&Di(r.name)&&Jl(r.version)!==null).slice(0,c3).map(r=>({name:r.name,version:r.version,path:gs(r.installPath)??null})),s=o.find(r=>r.name===Li);return s===void 0?o.unshift({name:Li,version:sn,path:t!==null?gs(t)??null:null}):hs(sn,s.version)>0&&(s.version=sn),o}function LA(e,t){return t===null?[]:e.filter(n=>Di(n.name)&&(vs(t.seen,n.name)===void 0||hs(n.version,vs(t.seen,n.name))>0))}var NA=e=>e.whatsnew.hydrated&&LA(_p(e),e.whatsnew.rec).length>0;function b3(e){let t=e.slice(0,2).map(o=>`${o.name} ${o.version}`),n=e.length-t.length;return vr(`What's new: ${t.join(", ")}${n>0?` and ${n} more`:""} (TOOLS \u2192 What's new)`,118)}var ud=(e,t)=>{e.whatsnew.rec!==null&&t.storeSet(OA,y3(e.whatsnew.rec)).catch(()=>{})};async function w3(e,t){e.whatsnew.hydrated||(e.whatsnew.rec=await t.storeGet(OA).then(g3,()=>null),e.whatsnew.hydrated=!0,t.invalidate())}function DA(e,t){let n=e.whatsnew;if(!n.hydrated||e.snapshot===null)return;let o=_p(e,t.pluginRoot);if(n.rec===null){n.rec=ub(o),ud(e,t);return}let s=LA(o,n.rec);if(s.length===0)return;if(n.isOpen){for(let i of s)n.rec.seen[i.name]=i.version;ud(e,t),t.invalidate();return}let r=s.filter(i=>n.rec!==null&&(vs(n.rec.toasted,i.name)===void 0||hs(i.version,vs(n.rec.toasted,i.name))>0));if(r.length!==0){for(let i of r)n.rec.toasted[i.name]=i.version;ud(e,t),n.rec.toast&&e.isInteractive&&t.toast(b3(r),9e3,"info"),t.invalidate()}}var k3=e=>e.changes.some(t=>t.kind==="breaking");async function v3(e,t,n){let o=async r=>{if(r.path===null)return{...r,result:{ok:!1,reason:"missing"}};let i=await pe(e.fs,t,`${r.path.replace(/\/+$/,"")}/CHANGELOG.md`,p3,!0).catch(()=>null);return i===null?{...r,result:{ok:!1,reason:"unreadable"}}:i.text===null?{...r,result:{ok:!1,reason:i.reason==="too-large"?"too-large":i.reason==="missing"?"missing":"unreadable"}}:{...r,result:IM(i.text)}},s=[];for(let r=0;r<n.length;r+=8)s.push(...await Promise.all(n.slice(r,r+8).map(o)));return s}async function jA(e,t){let n=e.whatsnew;if(n.isOpen)return;n.isOpen=!0,n.isLoading=!0,t.invalidate(),await w3(e,t);let o=_p(e,t.pluginRoot);n.rec===null&&(n.rec=ub(o)),n.before=Ni(Object.entries(n.rec.seen));let s=n.before,r=n.rec,i=await v3(t,n.cache,o);if(n.isOpen){n.logs=i;for(let a of i)if(a.result.ok)for(let l of kp(a.result.entries,vs(s,a.name))){let d=`${a.name}@${l.version}`;k3(l)&&!r.pinned.includes(d)&&!r.dismissed.includes(d)&&vs(s,a.name)!==void 0&&db(d)&&r.pinned.push(d)}for(let a of o)r.seen[a.name]=a.version;n.isLoading=!1,n.loadedAtMs=Date.now(),ud(e,t),t.invalidate()}}function FA(e){e.whatsnew.isOpen=!1,e.whatsnew.before=null}function cb(e){let{rec:t,logs:n}=e.whatsnew;return t===null?[]:t.pinned.filter(o=>!t.dismissed.includes(o)).map(o=>{let[s="",r=""]=o.split("@"),i=n.find(l=>l.name===s&&l.result.ok)?.result,a=i!==void 0&&i.ok?i.entries.find(l=>l.version===r):void 0;return{key:o,name:s,version:r,texts:a===void 0?[]:a.changes.filter(l=>l.kind==="breaking").map(l=>l.text)}}).slice(0,20)}function WA(e,t){let n=()=>{ud(e,t),t.invalidate()},o=s=>{let r=e.whatsnew.rec;r===null||!db(s)||(r.pinned=r.pinned.filter(i=>i!==s),r.dismissed.includes(s)||r.dismissed.push(s),n())};return{dismiss:o,dismissAll:()=>{for(let s of cb(e))o(s.key)},toggleToast:()=>{e.whatsnew.rec??=ub(_p(e,t.pluginRoot)),e.whatsnew.rec.toast=!e.whatsnew.rec.toast,n()}}}var pb=80,$3=100,x3=/^(Transformers\.js loaded|✅ Using native|\[INFO\] Executing tool|Parameters:|\[OK\] Tool executed|Result:|─+$)/;function S3(e,t){return`${e}
|
|
21
21
|
${t}`.split(`
|
|
22
22
|
`).map(n=>v(n,200)).filter(n=>/^\[(WARN|ERROR)\]/.test(n)).map(n=>`\u26A0 ${n.replace(/^\[(WARN|ERROR)\]\s*/,"")}`).slice(0,3)}function M3(e,t=$3){let n=[];for(let o of e.split(`
|
|
23
23
|
`)){let s="";for(let r of v(o,2e4).split(" ")){let i=r;for(;i.length>t;)s!==""&&n.push(s),n.push(i.slice(0,t)),i=i.slice(t),s="";s===""?s=i:s.length+1+i.length<=t?s=`${s} ${i}`:(n.push(s),s=i)}n.push(s)}return n}var kt=(e,t)=>typeof e=="string"?v(e,t):typeof e=="number"?String(Ne(e)??"n/a"):typeof e=="boolean"?String(e):"",A3=e=>Ne(e)?.toFixed(3)??" n/a";function R3(e){let t=e.content??e.value,n=typeof t=="string"?t:JSON.stringify(t??null,null,2),o=X(e.updatedAt??e.storedAt);return[`${kt(e.namespace,40)}/${kt(e.key,128)} \xB7 ${n.length} chars \xB7 read ${re(e.accessCount)??"n/a"}\xD7 \xB7 ${e.hasEmbedding===!0?"has a vector":"no vector"}${o!==void 0?` \xB7 updated ${Ge(o).slice(0,16).replace("T"," ")}`:""}`,...Array.isArray(e.tags)&&e.tags.length>0?[`tags: ${e.tags.map(r=>kt(r,24)).join(", ")}`]:[],"",...M3(n)]}function E3(e,t){let n=t.map(R).filter(r=>r!==null),o=`${n.length} hit${n.length===1?"":"s"}${e.searchType!==void 0?` \xB7 ${kt(e.searchType,20)}`:""}${e.searchTime!==void 0?` \xB7 ${kt(e.searchTime,20)}`:""}${Array.isArray(e.searchedNamespaces)?` \xB7 searched ${e.searchedNamespaces.map(r=>kt(r,24)).join(", ")}`:""}`,s=[e.degraded===!0?`degraded: ${kt(e.reason,80)}`:"",kt(e.note,160)].filter(r=>r!=="");return n.length===0?[o,...s,"(no matches)"]:[o,...s,...n.slice(0,20).map(r=>{let i=r.namespace!==void 0?`${kt(r.namespace,24)}/${kt(r.key??r.id,60)}`:kt(r.key??r.id??r.pattern??r.nodeId,60),a=kt(r.preview??r.content??r.value??r.pattern??r.text??"",90);return`${A3(r.score??r.similarity??r.confidence??r.distance)} ${i}${r.source!==void 0?` [${kt(r.source,12)}]`:""}${a!==""?` ${a}`:""}`})]}function HA(e){let t=e.map(R).filter(n=>n!==null);return t.length===0?["(no entries)"]:[`${t.length} entr${t.length===1?"y":"ies"}`,...t.slice(0,60).map(n=>{let o=X(n.updatedAt??n.createdAt??n.storedAt);return`${n.hasEmbedding===!0?"\u25C6":"\u25C7"} ${kt(n.namespace,24)}/${kt(n.key,80)} \xB7 ${re(n.size)??"n/a"} B${o!==void 0?` \xB7 ${Ge(o).slice(0,16).replace("T"," ")}`:""}`})]}function C3(e,t){let n=t.map(R).filter(s=>s!==null),o=n.filter(s=>s.enabled===!0).length;return[`AgentDB ${e.available===!0?"available":"NOT available"} \xB7 ${o}/${n.length} controllers on`,...n.map(s=>`${s.enabled===!0?"\u2713":"\xB7"} ${kt(s.name,40)}${s.level!==void 0?` L${kt(s.level,4)}`:""}`)]}function T3(e){let t=Array.isArray(e.embedding)?e.embedding:Array.isArray(e.vector)?e.vector:null;if(t===null)return null;let n=t.flatMap(s=>Ne(s)??[]),o=Math.sqrt(n.reduce((s,r)=>s+r*r,0));return[`${n.length} dimensions \xB7 norm ${Ne(o)?.toFixed(3)??"n/a"}${e.model!==void 0?` \xB7 ${kt(e.model,40)}`:""}`,`head: ${n.slice(0,8).map(s=>s.toFixed(4)).join(" ")} \u2026`]}function O3(e){if(Array.isArray(e))return HA(e);let t=R(e);return t===null?[]:t.content!==void 0||t.value!==void 0&&t.key!==void 0?R3(t):Array.isArray(t.results)?E3(t,t.results):Array.isArray(t.entries)&&t.total!==void 0?HA(t.entries):Array.isArray(t.controllers)?C3(t,t.controllers):T3(t)??[]}function BA(e,t,n=""){let o=S3(t,n),s=de(t),r=s===null?[]:O3(s);if(r.length>0)return[...o,...r].slice(0,pb);let i=t.split(`
|
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
//
|
|
14
14
|
// CONTRACT (PUBLIC)
|
|
15
15
|
// projectToVec(input) → 9-dim numerical feature vector
|
|
16
|
+
// normalizeCost(usd) → [0,1] log-band normalization (vector index 8)
|
|
16
17
|
// cosine(a, b) → [0,1]
|
|
17
18
|
// categoricalAgreement(a, b) → [0,1] over 4 enum fields
|
|
18
19
|
// jaccard(a, b) → [0,1] over agent_topology[]
|
|
19
|
-
//
|
|
20
|
+
// verdictFor(overall) → 'near-identical' | 'minor-drift' | 'moderate-drift' | 'major-drift'
|
|
21
|
+
// VERDICT_THRESHOLDS → the bands verdictFor() walks, highest first
|
|
22
|
+
// similarity(a, b, opts?) → { overall, verdict, components, perDimension? }
|
|
20
23
|
//
|
|
21
24
|
// WEIGHT DEFAULTS (from ADR-152 §Decision)
|
|
22
25
|
// overall = 0.60·cosine + 0.25·categorical + 0.15·jaccard
|
|
@@ -29,6 +32,59 @@ const DEFAULT_WEIGHTS = Object.freeze({ cosine: 0.6, categorical: 0.25, jaccard:
|
|
|
29
32
|
|
|
30
33
|
const CATEGORICAL_FIELDS = Object.freeze(['repo_type', 'archetype', 'template', 'recommendedMode']);
|
|
31
34
|
|
|
35
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
36
|
+
// Cost normalization — vector index 8.
|
|
37
|
+
//
|
|
38
|
+
// ADR-152 Table 1 specified `log10(usd + 0.001) / log10(10)` clamped to
|
|
39
|
+
// [0,1]. `Math.log10(10)` is 1, so the division was a no-op, and the raw
|
|
40
|
+
// log is negative for every cost below $0.999 — the outer clamp then
|
|
41
|
+
// flattened that whole range to 0. Every realistic per-run cost collapsed
|
|
42
|
+
// to the same value, so the documented 9-dim vector was effectively
|
|
43
|
+
// 8-dim and `estCostPerRunUsd` could not influence any score.
|
|
44
|
+
//
|
|
45
|
+
// The replacement is a real log band: costs at or below `min` map to 0,
|
|
46
|
+
// at or above `max` map to 1, log-interpolated in between. It is
|
|
47
|
+
// monotonic and live across the whole realistic range ($0.001–$10), and
|
|
48
|
+
// non-finite or missing input degrades to the band floor rather than NaN.
|
|
49
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
export const COST_BAND_USD = Object.freeze({ min: 0.001, max: 10 });
|
|
52
|
+
|
|
53
|
+
export function normalizeCost(usd) {
|
|
54
|
+
const lo = Math.log10(COST_BAND_USD.min);
|
|
55
|
+
const hi = Math.log10(COST_BAND_USD.max);
|
|
56
|
+
const finite = typeof usd === 'number' && Number.isFinite(usd) ? usd : COST_BAND_USD.min;
|
|
57
|
+
const clamped = Math.min(COST_BAND_USD.max, Math.max(COST_BAND_USD.min, finite));
|
|
58
|
+
return (Math.log10(clamped) - lo) / (hi - lo);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
62
|
+
// Verdict bands — single source of truth.
|
|
63
|
+
//
|
|
64
|
+
// These bands previously lived inline in `audit-trend.mjs` with a
|
|
65
|
+
// `minor-drift` floor of 0.80, while `docs/metaharness-user-guide.md`
|
|
66
|
+
// documented 0.85 for the same band. Two encodings of one policy, and
|
|
67
|
+
// they disagreed. Consumers now import this table instead of re-encoding
|
|
68
|
+
// the bands, so the primitive and its documentation cannot drift apart.
|
|
69
|
+
//
|
|
70
|
+
// Ordered highest-first; `verdictFor` returns the first band whose `min`
|
|
71
|
+
// the score reaches.
|
|
72
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
export const VERDICT_THRESHOLDS = Object.freeze([
|
|
75
|
+
Object.freeze({ min: 0.95, verdict: 'near-identical' }),
|
|
76
|
+
Object.freeze({ min: 0.85, verdict: 'minor-drift' }),
|
|
77
|
+
Object.freeze({ min: 0.5, verdict: 'moderate-drift' }),
|
|
78
|
+
Object.freeze({ min: Number.NEGATIVE_INFINITY, verdict: 'major-drift' }),
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
export function verdictFor(overall) {
|
|
82
|
+
for (const band of VERDICT_THRESHOLDS) {
|
|
83
|
+
if (overall >= band.min) return band.verdict;
|
|
84
|
+
}
|
|
85
|
+
return 'major-drift';
|
|
86
|
+
}
|
|
87
|
+
|
|
32
88
|
// ─────────────────────────────────────────────────────────────────────
|
|
33
89
|
// 9-dim feature vector. The mapping mirrors ADR-152 §Decision Table 1.
|
|
34
90
|
// Missing fields default to 0 — that's the graceful-degradation path.
|
|
@@ -46,7 +102,7 @@ export function projectToVec(input) {
|
|
|
46
102
|
g.risk_score ?? 0,
|
|
47
103
|
g.test_confidence ?? 0,
|
|
48
104
|
g.publish_readiness ?? 0,
|
|
49
|
-
|
|
105
|
+
normalizeCost(s.estCostPerRunUsd),
|
|
50
106
|
];
|
|
51
107
|
}
|
|
52
108
|
|
|
@@ -99,6 +155,10 @@ export function similarity(a, b, opts = {}) {
|
|
|
99
155
|
|
|
100
156
|
const result = {
|
|
101
157
|
overall: round4(overall),
|
|
158
|
+
// The verdict is derived here, next to the score it classifies, so
|
|
159
|
+
// every consumer (similarity.mjs, audit-trend.mjs) reports the same
|
|
160
|
+
// band for the same number.
|
|
161
|
+
verdict: verdictFor(round4(overall)),
|
|
102
162
|
components: {
|
|
103
163
|
cosine: round4(cos),
|
|
104
164
|
categorical: round4(cat),
|
|
@@ -31,7 +31,10 @@ import { runRufloCli } from './_invoke.mjs';
|
|
|
31
31
|
// iter 38 — structural-distance drift via ADR-152 §3.1 production module.
|
|
32
32
|
// Falls back to null if either record predates iter-38 oia-audit (no
|
|
33
33
|
// fingerprint field) — graceful degradation, never throws.
|
|
34
|
-
|
|
34
|
+
// The verdict bands come from the module, not a local literal: this file
|
|
35
|
+
// previously re-encoded them with a 0.80 minor-drift floor while
|
|
36
|
+
// docs/metaharness-user-guide.md documented 0.85.
|
|
37
|
+
import { similarity, verdictFor } from './_similarity.mjs';
|
|
35
38
|
// iter 63 — shared SEVERITY_RANK from _harness.mjs (was a local literal
|
|
36
39
|
// missing info/warn/error/critical, which caused NaN-compare hazards).
|
|
37
40
|
import { SEVERITY_RANK, rankSeverity } from './_harness.mjs';
|
|
@@ -168,10 +171,7 @@ function main() {
|
|
|
168
171
|
// Distance is the complement of similarity in [0,1]
|
|
169
172
|
distance: Number((1 - sim.overall).toFixed(4)),
|
|
170
173
|
components: sim.components,
|
|
171
|
-
verdict: sim.overall
|
|
172
|
-
: sim.overall >= 0.80 ? 'minor-drift'
|
|
173
|
-
: sim.overall >= 0.50 ? 'moderate-drift'
|
|
174
|
-
: 'major-drift',
|
|
174
|
+
verdict: verdictFor(sim.overall),
|
|
175
175
|
};
|
|
176
176
|
} else {
|
|
177
177
|
structuralDistance = {
|
|
@@ -147,6 +147,7 @@ function main() {
|
|
|
147
147
|
console.log(`| jaccard | ${components.jaccard.toFixed(4)} | ${weights.jaccard} | ${(components.jaccard * weights.jaccard).toFixed(4)} |`);
|
|
148
148
|
console.log('');
|
|
149
149
|
console.log(`**Overall:** ${payload.overall.toFixed(4)}`);
|
|
150
|
+
console.log(`**Verdict:** ${payload.verdict}`);
|
|
150
151
|
if (payload.alert) {
|
|
151
152
|
console.log('');
|
|
152
153
|
console.log(payload.alert.triggered ? `⚠ ALERT: ${payload.alert.reason}` : `✓ ${payload.alert.reason}`);
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import {
|
|
25
25
|
projectToVec, cosine, categoricalAgreement, jaccard, similarity,
|
|
26
|
+
normalizeCost, COST_BAND_USD, verdictFor, VERDICT_THRESHOLDS,
|
|
26
27
|
} from './_similarity.mjs';
|
|
27
28
|
// iter 64 — also test the iter-63 shared severity primitives
|
|
28
29
|
import { SEVERITY_RANK, rankSeverity, parseMcpScanText } from './_harness.mjs';
|
|
@@ -174,6 +175,68 @@ assert(typeof hf.contribution === 'number', 'perDimension has numeric contributi
|
|
|
174
175
|
const sNoPD = similarity(A, B);
|
|
175
176
|
assert(!('perDimension' in sNoPD), 'perDimension omitted by default');
|
|
176
177
|
|
|
178
|
+
console.log('\nPhase 7b — normalizeCost (vector index 8, ADR-152 Table 1)');
|
|
179
|
+
// The pre-fix transform was `log10(usd + 0.001) / log10(10)` clamped to
|
|
180
|
+
// [0,1]. `Math.log10(10)` is 1, so the division was a no-op and the raw
|
|
181
|
+
// log — negative for every cost below $0.999 — clamped to a flat 0. That
|
|
182
|
+
// dead zone covered the whole realistic per-run range, including ruflo's
|
|
183
|
+
// own $0.048 Phase-0 baseline.
|
|
184
|
+
assert(normalizeCost(COST_BAND_USD.min) === 0, 'band floor → 0');
|
|
185
|
+
assert(normalizeCost(COST_BAND_USD.max) === 1, 'band ceiling → 1');
|
|
186
|
+
assert(normalizeCost(50) === 1, 'above band ceiling clamps to 1');
|
|
187
|
+
assert(normalizeCost(0) === 0, 'zero cost clamps to 0');
|
|
188
|
+
assert(normalizeCost(-5) === 0, 'negative cost clamps to 0');
|
|
189
|
+
// The regression that motivated the fix: realistic costs must not collide.
|
|
190
|
+
assert(normalizeCost(0.048) !== normalizeCost(0.11),
|
|
191
|
+
'ruflo baseline $0.048 and $0.11 must not collapse to the same value (dead-zone regression)');
|
|
192
|
+
assert(normalizeCost(0.048) > 0,
|
|
193
|
+
'$0.048 (ruflo Phase-0 baseline) must be strictly inside the band');
|
|
194
|
+
// Monotonic non-decreasing across the band, sampled log-evenly.
|
|
195
|
+
const costSamples = [0.001, 0.005, 0.02, 0.048, 0.11, 0.5, 1, 5, 10];
|
|
196
|
+
const costVec = costSamples.map(normalizeCost);
|
|
197
|
+
assert(costVec.every((v, i) => i === 0 || v >= costVec[i - 1]),
|
|
198
|
+
'normalizeCost is monotonic non-decreasing across the band');
|
|
199
|
+
assert(costVec.every((v) => v >= 0 && v <= 1), 'normalizeCost bounded to [0, 1]');
|
|
200
|
+
// End-to-end: the dimension must now reach the composite. Two harnesses
|
|
201
|
+
// identical except for cost previously scored cosine === 1 because both
|
|
202
|
+
// collapsed to 0; they must now differ.
|
|
203
|
+
const costTwin = (usd) => ({
|
|
204
|
+
score: { ...A.score, estCostPerRunUsd: usd }, genome: A.genome,
|
|
205
|
+
});
|
|
206
|
+
const cheapTwin = similarity(costTwin(0.048), A);
|
|
207
|
+
const priceyTwin = similarity(costTwin(1), A);
|
|
208
|
+
assert(cheapTwin.components.cosine !== priceyTwin.components.cosine,
|
|
209
|
+
'cost now influences cosine (was a dead dimension below $0.999)');
|
|
210
|
+
assert(priceyTwin.components.cosine < cheapTwin.components.cosine,
|
|
211
|
+
'a same-shaped harness with a higher cost is less similar to a cheap one');
|
|
212
|
+
|
|
213
|
+
console.log('\nPhase 7c — verdictFor + VERDICT_THRESHOLDS (single source of truth)');
|
|
214
|
+
assert(VERDICT_THRESHOLDS.length === 4, 'four verdict bands');
|
|
215
|
+
assert(VERDICT_THRESHOLDS.every((b, i) => i === 0 || b.min < VERDICT_THRESHOLDS[i - 1].min),
|
|
216
|
+
'bands are ordered highest-first');
|
|
217
|
+
const LAST_BAND = VERDICT_THRESHOLDS[VERDICT_THRESHOLDS.length - 1];
|
|
218
|
+
assert(LAST_BAND.min === Number.NEGATIVE_INFINITY,
|
|
219
|
+
'final band is unbounded so verdictFor always returns a verdict');
|
|
220
|
+
assert(verdictFor(1) === 'near-identical', 'overall 1 → near-identical');
|
|
221
|
+
assert(verdictFor(0.95) === 'near-identical', 'boundary 0.95 → near-identical (inclusive)');
|
|
222
|
+
assert(verdictFor(0.9499) === 'minor-drift', 'just below 0.95 → minor-drift');
|
|
223
|
+
assert(verdictFor(0.85) === 'minor-drift', 'boundary 0.85 → minor-drift (inclusive, the documented floor)');
|
|
224
|
+
assert(verdictFor(0.8499) === 'moderate-drift', 'just below 0.85 → moderate-drift');
|
|
225
|
+
assert(verdictFor(0.5) === 'moderate-drift', 'boundary 0.5 → moderate-drift (inclusive)');
|
|
226
|
+
assert(verdictFor(0.4999) === 'major-drift', 'just below 0.5 → major-drift');
|
|
227
|
+
assert(verdictFor(0) === 'major-drift', 'overall 0 → major-drift');
|
|
228
|
+
// Regression: audit-trend.mjs used to inline a 0.80 minor-drift floor while
|
|
229
|
+
// docs/metaharness-user-guide.md documented 0.85. 0.80 must resolve to
|
|
230
|
+
// moderate-drift now that the bands live in one place.
|
|
231
|
+
assert(verdictFor(0.80) === 'moderate-drift',
|
|
232
|
+
'0.80 resolves via the shared bands (was a divergent inline 0.80 floor in audit-trend.mjs)');
|
|
233
|
+
|
|
234
|
+
console.log('\nPhase 7d — verdict on the similarity() return shape');
|
|
235
|
+
assert(typeof sAA.verdict === 'string', 'similarity() includes a verdict string');
|
|
236
|
+
assert(sAA.verdict === 'near-identical', 'self-match verdict is near-identical');
|
|
237
|
+
assert(sPD.verdict === verdictFor(sPD.overall),
|
|
238
|
+
'similarity().verdict agrees with verdictFor(overall)');
|
|
239
|
+
|
|
177
240
|
console.log('\nPhase 8 — round-trip with the iter-35 spike fixtures (regression anchor)');
|
|
178
241
|
// Hard-coded spike numbers from `_spike-similarity.mjs` — ANY change
|
|
179
242
|
// here means the production module drifted from the spike's frozen
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ruflo-architect
|
|
3
|
+
description: >
|
|
4
|
+
Ruflo swarm architect for Grok. Designs implementation blueprints, ADRs, and
|
|
5
|
+
file-level plans. Use for multi-file features before coding. Read-only by default;
|
|
6
|
+
hand off to ruflo-coder via team bus.
|
|
7
|
+
prompt_mode: full
|
|
8
|
+
permission_mode: plan
|
|
9
|
+
agents_md: true
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
You are the **architect** on a Ruflo Agent Team running under **Grok Build**.
|
|
13
|
+
|
|
14
|
+
This file is a session profile (`grok --agent-profile ruflo-architect` or `/agents`). On Grok Build 1.0.41, `spawn_subagent` does not select it. A spawned child is general-purpose, follows the spawn prompt, and must not call `spawn_subagent`.
|
|
15
|
+
|
|
16
|
+
## Comms protocol (mandatory)
|
|
17
|
+
|
|
18
|
+
- There is **no** Claude `SendMessage` tool.
|
|
19
|
+
- At start, drain your inbox:
|
|
20
|
+
`node scripts/grok-team-bus.mjs inbox --team <TEAM> --agent architect`
|
|
21
|
+
- When design is ready, hand off:
|
|
22
|
+
`node scripts/grok-team-bus.mjs send --team <TEAM> --to developer --from architect --summary "design-ready" --message "<paths + decisions>"`
|
|
23
|
+
- Prefer storing durable design under memory namespace `team:<TEAM>` when Ruflo MCP is available.
|
|
24
|
+
|
|
25
|
+
## Deliverable
|
|
26
|
+
|
|
27
|
+
Produce a decisive blueprint:
|
|
28
|
+
|
|
29
|
+
1. Patterns found (file:line)
|
|
30
|
+
2. Chosen architecture + trade-offs
|
|
31
|
+
3. Files to create/modify
|
|
32
|
+
4. Build sequence for developer → tester → reviewer
|
|
33
|
+
5. Risks / security notes
|
|
34
|
+
|
|
35
|
+
Do **not** implement code. Do not wait for Ruflo to execute — you design; the lead/developer executes.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ruflo-coder
|
|
3
|
+
description: >
|
|
4
|
+
Ruflo implementation agent for Grok. Writes production code from architect designs.
|
|
5
|
+
Prefer isolation=worktree when spawned. Handoffs via team bus, not SendMessage.
|
|
6
|
+
prompt_mode: full
|
|
7
|
+
agents_md: true
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the **developer/coder** on a Ruflo Agent Team under **Grok Build**.
|
|
11
|
+
|
|
12
|
+
This file is a session profile (`grok --agent-profile ruflo-coder` or `/agents`). On Grok Build 1.0.41, `spawn_subagent` does not select it. A spawned child is general-purpose, follows the spawn prompt (worktree isolation when the plan says so), and must not call `spawn_subagent`.
|
|
13
|
+
|
|
14
|
+
## Comms protocol (mandatory)
|
|
15
|
+
|
|
16
|
+
- No Claude `SendMessage`.
|
|
17
|
+
- Start: `node scripts/grok-team-bus.mjs inbox --team <TEAM> --agent developer`
|
|
18
|
+
- If architect design is in the inbox or memory `team:<TEAM>`, follow it.
|
|
19
|
+
- When implementation is ready:
|
|
20
|
+
`node scripts/grok-team-bus.mjs send --team <TEAM> --to tester --from developer --summary "impl-ready" --message "<files changed + how to test>"`
|
|
21
|
+
- On stop: `node scripts/grok-team-bus.mjs on-stop --team <TEAM> --agent developer`
|
|
22
|
+
|
|
23
|
+
## Rules
|
|
24
|
+
|
|
25
|
+
- Prefer editing existing files; keep changes focused.
|
|
26
|
+
- Match project conventions (Claude.md / Agents.md / ADRs).
|
|
27
|
+
- Run available unit tests for touched areas when practical.
|
|
28
|
+
- If using a git worktree, leave a clear summary of the worktree path and branch for the lead to merge.
|
|
29
|
+
|
|
30
|
+
## Anti-patterns
|
|
31
|
+
|
|
32
|
+
- Waiting after `swarm_init` for code to appear by magic
|
|
33
|
+
- Inventing Claude Task / SendMessage APIs
|
|
34
|
+
- Parallel uncoordinated edits outside your worktree
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ruflo-reviewer
|
|
3
|
+
description: >
|
|
4
|
+
Ruflo code review agent for Grok. Reviews quality, security, and test evidence.
|
|
5
|
+
Read-oriented; reports findings to the team lead via team bus.
|
|
6
|
+
prompt_mode: full
|
|
7
|
+
permission_mode: plan
|
|
8
|
+
agents_md: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You are the **reviewer** on a Ruflo Agent Team under **Grok Build**.
|
|
12
|
+
|
|
13
|
+
This file is a session profile (`grok --agent-profile ruflo-reviewer` or `/agents`). On Grok Build 1.0.41, `spawn_subagent` does not select it. A spawned child is general-purpose, follows the spawn prompt, and must not call `spawn_subagent`.
|
|
14
|
+
|
|
15
|
+
## Comms protocol
|
|
16
|
+
|
|
17
|
+
- Inbox: `node scripts/grok-team-bus.mjs inbox --team <TEAM> --agent reviewer`
|
|
18
|
+
- Final report to lead:
|
|
19
|
+
`node scripts/grok-team-bus.mjs send --team <TEAM> --to lead --from reviewer --summary "review-complete" --message "<findings>"`
|
|
20
|
+
(If `lead` mailbox is unused, print the full review as your final response for the parent session.)
|
|
21
|
+
- `node scripts/grok-team-bus.mjs on-stop --team <TEAM> --agent reviewer`
|
|
22
|
+
|
|
23
|
+
## Review focus
|
|
24
|
+
|
|
25
|
+
1. Correctness vs design handoff
|
|
26
|
+
2. Security (injection, secrets, path traversal)
|
|
27
|
+
3. Test evidence quality
|
|
28
|
+
4. Maintainability / ADR alignment
|
|
29
|
+
|
|
30
|
+
Severity: blocker / major / minor / nit. Blockers must be explicit.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ruflo-tester
|
|
3
|
+
description: >
|
|
4
|
+
Ruflo tester for Grok. Writes and runs tests from implementation handoffs.
|
|
5
|
+
Use worktree isolation when modifying the tree. Reports to reviewer via team bus.
|
|
6
|
+
prompt_mode: full
|
|
7
|
+
agents_md: true
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the **tester** on a Ruflo Agent Team under **Grok Build**.
|
|
11
|
+
|
|
12
|
+
This file is a session profile (`grok --agent-profile ruflo-tester` or `/agents`). On Grok Build 1.0.41, `spawn_subagent` does not select it. A spawned child is general-purpose, follows the spawn prompt, and must not call `spawn_subagent`.
|
|
13
|
+
|
|
14
|
+
## Comms protocol
|
|
15
|
+
|
|
16
|
+
- Inbox: `node scripts/grok-team-bus.mjs inbox --team <TEAM> --agent tester`
|
|
17
|
+
- After tests:
|
|
18
|
+
`node scripts/grok-team-bus.mjs send --team <TEAM> --to reviewer --from tester --summary "tests-ready" --message "<commands, pass/fail, coverage gaps>"`
|
|
19
|
+
- `node scripts/grok-team-bus.mjs on-stop --team <TEAM> --agent tester`
|
|
20
|
+
|
|
21
|
+
## Deliverable
|
|
22
|
+
|
|
23
|
+
- Test plan + implemented tests
|
|
24
|
+
- Exact commands to run
|
|
25
|
+
- Failures with file:line
|
|
26
|
+
- Gaps you did not cover
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Ruflo on Grok Build — project-scoped host config
|
|
2
|
+
# Loaded by Grok when this folder is trusted (see ~/.grok/trusted_folders.toml).
|
|
3
|
+
#
|
|
4
|
+
# Goal: full harness (MCP + hooks + skills + agent teams path), not a thin CLI wrapper.
|
|
5
|
+
# See: .grok/rules/ruflo-grok.md and v3/docs/adr/ADR-402-host-agnostic-agent-teams.md
|
|
6
|
+
#
|
|
7
|
+
# After editing: restart Grok (or reload MCPs) so tool lists refresh.
|
|
8
|
+
|
|
9
|
+
# ---------------------------------------------------------------------------
|
|
10
|
+
# Ruflo MCP — orchestrator / ledger (memory, swarm, hooks, team bus, neural)
|
|
11
|
+
# `ruflo init --grok` pins this to the Ruflo version that ran it, because the
|
|
12
|
+
# team_* tools ship in that same release (an older @latest may lack them).
|
|
13
|
+
# From a source checkout it points at that checkout's bin/cli.js instead.
|
|
14
|
+
# Cold npx can exceed 30s; keep timeouts high.
|
|
15
|
+
# ---------------------------------------------------------------------------
|
|
16
|
+
[mcp_servers.ruflo]
|
|
17
|
+
command = {{RUFLO_MCP_COMMAND}}
|
|
18
|
+
args = {{RUFLO_MCP_ARGS}}
|
|
19
|
+
enabled = true
|
|
20
|
+
startup_timeout_sec = 120
|
|
21
|
+
tool_timeout_sec = 180
|
|
22
|
+
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
# Optional: RuvNet Brain grounding (search_ruvnet over embedded rUv source)
|
|
25
|
+
# Install: npx ruvnet-brain@latest → kb under ~/.cache/ruvnet-brain/kb
|
|
26
|
+
#
|
|
27
|
+
# forge-mcp-all defaults KB_DIR to process.cwd(). When Grok spawns MCP from the
|
|
28
|
+
# project root, search fails with "passages sidecar not found: ./agentdb…".
|
|
29
|
+
# Always set env.KB_DIR to the absolute kb path. tool_timeout_sec high for cold
|
|
30
|
+
# BGE model download (first big search can take minutes).
|
|
31
|
+
# init --grok fills in your home directory for the {{HOME}} paths below.
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
# [mcp_servers.ruvnet-brain]
|
|
34
|
+
# command = "node"
|
|
35
|
+
# args = ["{{HOME}}/.cache/ruvnet-brain/kb/forge-mcp-all.mjs"]
|
|
36
|
+
# env = { KB_DIR = "{{HOME}}/.cache/ruvnet-brain/kb" }
|
|
37
|
+
# enabled = true
|
|
38
|
+
# startup_timeout_sec = 90
|
|
39
|
+
# tool_timeout_sec = 600
|
|
40
|
+
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
# Permissions — allow Ruflo CLI + helpers without re-prompting every turn
|
|
43
|
+
# (deny still wins over allow; PreToolUse hooks can still block)
|
|
44
|
+
# ---------------------------------------------------------------------------
|
|
45
|
+
[permission]
|
|
46
|
+
allow = [
|
|
47
|
+
"Bash(npx ruflo*)",
|
|
48
|
+
"Bash(npx @claude-flow*)",
|
|
49
|
+
"Bash(npx claude-flow*)",
|
|
50
|
+
"Bash(node .claude/*)",
|
|
51
|
+
"Bash(npx -y ruflo*)",
|
|
52
|
+
"Bash(node scripts/grok-team-bus.mjs*)",
|
|
53
|
+
"MCPTool(ruflo__*)",
|
|
54
|
+
"MCPTool(ruvnet-brain__*)",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
# Subagent defaults are user-level on Grok Build 1.0.41.
|
|
59
|
+
# Project .grok/config.toml contributes only [mcp_servers], [plugins],
|
|
60
|
+
# [permission], and [mcp].max_output_bytes. A [subagents] table here is ignored.
|
|
61
|
+
# Put role defaults in ~/.grok/config.toml if you need them.
|
|
62
|
+
# Team children: pass host.grok.spawn from team_spawn (see docs/grok/README.md).
|
|
63
|
+
# ---------------------------------------------------------------------------
|