@paniolo/scan 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +92 -90
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFile as
|
|
3
|
-
`),process.exit(2),"error")}function
|
|
4
|
-
`),process.exit(2),"terminal")}function
|
|
5
|
-
`),process.exit(2),[]):n}var
|
|
6
|
-
`),process.exit(2)),l=g,
|
|
7
|
-
`),process.exit(2));let
|
|
8
|
-
`),process.exit(2)),
|
|
9
|
-
`),process.exit(2)),a=g,
|
|
10
|
-
`),process.exit(2)),n
|
|
11
|
-
`),process.exit(2)),
|
|
12
|
-
`),process.exit(2)),
|
|
13
|
-
`),process.exit(2)),t=
|
|
2
|
+
import{readFile as Aa}from"node:fs/promises";var Et={status:"not-run",score:null,grade:"not-run",checks:[],findings:[]};var Ra=[{min:85,grade:"excellent"},{min:70,grade:"good"},{min:50,grade:"fair"},{min:0,grade:"poor"}];function be(e){for(let{min:t,grade:n}of Ra)if(e>=t)return n;return"poor"}function vt(e){let t=(e.hint??"").toLowerCase().match(/[a-z0-9]+/g),n=t===null?"":[...new Set(t)].toSorted().join(" ");return`${e.ruleId}::${e.file??""}::${n}`}function fo(e){let t=e.indexOf(":");return t===-1?null:e.slice(t+1)}function v(e,t){let n=e[t];return typeof n=="string"?n:""}import{access as wa}from"node:fs/promises";import ba from"node:path";var W=75,Tt=300,qe=["CLAUDE.md","GEMINI.md",".github/copilot-instructions.md"];function k(e,t){return e.files.some(n=>n.path===t)}function h(e,t){return e.fileContents.get(t)??null}function U(e,t){return e.files.find(r=>r.path===t)?.lines??null}function go(e){return e.includes("AGENTS.md")||e.includes("docs/ai/rules.md")}function Ke(e){return e.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1]??null}function me(e,t){return new RegExp(`^${t}:`,"m").test(e)}async function fe(e,t){try{return await wa(ba.join(e,t)),!0}catch{return!1}}function ge(e,t){return e.files.filter(n=>n.path.startsWith(t)).map(n=>n.path)}function I(e){return e.files.some(t=>t.path.startsWith("skills/")&&t.path.endsWith("/SKILL.md"))}function Ye(e){return e.includes("available-skills.md")||e.includes("skills/*/SKILL.md")||e.includes("npm run qmd")||e.includes("skills/")&&e.includes("available-skills")}function Je(e){return/agent routing/i.test(e)&&e.includes("|")&&/agents\/.*\.agent\.md/.test(e)}function S(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var C={"AI1-contradiction":{checkId:"AI1-contradiction",title:"Cross-guidance contradictions",schemaKey:"contradictions",entryFields:["ruleA","ruleB","explanation"]},"AI2-adapter-fidelity":{checkId:"AI2-adapter-fidelity",title:"Adapter fidelity to shared layer",schemaKey:"drifts",entryFields:["claim","explanation"]},"AI3-security-review":{checkId:"AI3-security-review",title:"Semantic security review (advisory)",schemaKey:"risks",entryFields:["location","risk","explanation"]},"AI4-deadweight":{checkId:"AI4-deadweight",title:"Dead-weight instructions (deletion test)",schemaKey:"deadweight",entryFields:["rule","reason"]},"AI5-vague-rules":{checkId:"AI5-vague-rules",title:"Vague rules lacking a decision boundary",schemaKey:"vague",entryFields:["rule","reason"]}};function ho(e){return typeof e=="string"&&e in C}function Lt(e){if(!S(e.data))return[];let t=e.data[C[e.checkId].schemaKey];return Array.isArray(t)?t.filter(n=>S(n)):[]}function _t(e){let t=Lt(e);if(e.checkId==="AI1-contradiction")return t.map(r=>({ruleId:"ai-contradiction",severity:"warn",message:`Contradiction: ${v(r,"explanation")}`,file:null,line:null,harnesses:[],hint:`"${v(r,"ruleA")}" conflicts with "${v(r,"ruleB")}"`}));if(e.checkId==="AI4-deadweight")return t.map(r=>({ruleId:"ai-deadweight",severity:"warn",message:`Dead weight: ${v(r,"reason")}`,file:null,line:null,harnesses:[],hint:`Rule: "${v(r,"rule")}" \u2014 a capable agent would follow it unprompted.`}));if(e.checkId==="AI5-vague-rules")return t.map(r=>({ruleId:"ai-vague-rule",severity:"warn",message:`Vague rule: ${v(r,"reason")}`,file:null,line:null,harnesses:[],hint:`Rule: "${v(r,"rule")}" \u2014 give it a testable decision boundary.`}));if(e.checkId==="AI3-security-review")return t.map(r=>({ruleId:"ai-security-review",severity:"info",message:`Possible security risk (${v(r,"risk")}): ${v(r,"explanation")}`,file:null,line:null,harnesses:[],hint:`LLM-judged at ${v(r,"location")} \u2014 verify manually before acting.`}));let n=fo(e.taskId);return t.map(r=>({ruleId:"ai-adapter-fidelity",severity:"warn",message:`Adapter drift: ${v(r,"explanation")}`,file:n,line:null,harnesses:[],hint:`Adapter claim: "${v(r,"claim")}"`}))}function Ft(e){return e.map(t=>{let n=new Map;for(let r of _t(t)){let s=vt(r);n.has(s)||n.set(s,r)}return n})}function Nt(e,t,n,r){let s=0,o;for(let i of e){let a=i.get(t);a!==void 0&&(s+=1,o??=a)}if(o!==void 0)return s>=n?o:{...o,severity:"info",message:`${o.message} [low-confidence: LLM judge variance, agreed in ${String(s)}/${String(r)} runs]`}}function Pt(e){let t=new Map;for(let r of e){let s=t.get(r.taskId)??[];s.push(r),t.set(r.taskId,s)}let n=[];for(let r of t.values()){let s=Ft(r),o=Math.ceil(r.length/2),i=new Set;for(let a of s)for(let c of a.keys())i.add(c);for(let a of i){let c=Nt(s,a,o,r.length);c!==void 0&&n.push(c)}}return n}function Mt(e,t){let n={"AI1-contradiction":"ai-contradiction","AI2-adapter-fidelity":"ai-adapter-fidelity","AI3-security-review":"ai-security-review","AI4-deadweight":"ai-deadweight","AI5-vague-rules":"ai-vague-rule"},r=new Set,s=[];for(let o of e){if(r.has(o.checkId))continue;r.add(o.checkId);let i=n[o.checkId],a=t.filter(c=>c.ruleId===i).length;s.push({checkId:o.checkId,title:C[o.checkId].title,findingsCount:a,passed:a===0})}return s}var Ca=12;function Xe(e){let t=Pt(e),n=t.filter(s=>s.severity!=="info"),r=Math.max(0,100-Ca*n.length);return{status:"run",score:r,grade:be(r),checks:Mt(e,t),findings:t}}function Ht(e,t,n){let r=C[t];if(!S(n))throw new TypeError(`AI review result "${e}" data must be an object.`);let s=n[r.schemaKey];if(!Array.isArray(s))throw new TypeError(`AI review result "${e}" must have an array "${r.schemaKey}".`);for(let[o,i]of s.entries()){if(!S(i))throw new TypeError(`AI review result "${e}" ${r.schemaKey}[${String(o)}] must be an object.`);for(let a of r.entryFields){let c=i[a];if(typeof c!="string"||c.trim().length===0)throw new TypeError(`AI review result "${e}" ${r.schemaKey}[${String(o)}] is missing "${a}".`)}}}function Dt(e,t){if(!S(e))throw new TypeError(`AI review result #${String(t)} must be an object.`);let{taskId:n,checkId:r,data:s}=e;if(typeof n!="string"||n.length===0)throw new TypeError(`AI review result #${String(t)} is missing a "taskId".`);if(!ho(r))throw new TypeError(`AI review result "${n}" has an unknown checkId: ${String(r)}.`);return Ht(n,r,s),{taskId:n,checkId:r,data:s}}function Qe(e){if(!S(e))throw new TypeError("AI review results must be a JSON object.");if(e.version!==1)throw new TypeError('AI review results must have "version": 1.');let{results:t}=e;if(!Array.isArray(t))throw new TypeError('AI review results must include a "results" array.');return{version:1,results:t.map((n,r)=>Dt(n,r))}}async function Ot(e){let t=await Aa(e,"utf8"),n=JSON.parse(t);return Qe(n).results}import Ea from"node:path";function yo(e){return e==="error"||e==="warn"||e==="info"?e:(process.stderr.write(`error: invalid --fail-on value: ${e}
|
|
3
|
+
`),process.exit(2),"error")}function So(e){return e==="terminal"||e==="json"?e:(process.stderr.write(`error: invalid --format value: ${e}
|
|
4
|
+
`),process.exit(2),"terminal")}function $t(e){let t=e.split(",").map(s=>s.trim()).filter(s=>s.length>0);if(t.length===0)return null;let n=[],r=[];for(let s of t)s==="copilot"||s==="cursor"||s==="codex"||s==="antigravity"||s==="claude"||s==="gemini"?n.push(s):r.push(s);return r.length>0?(process.stderr.write(`error: unknown harness(es): ${r.join(", ")}
|
|
5
|
+
`),process.exit(2),[]):n}var ko=[/\balways\b/i,/\bnever\b/i,/\bdont\b/i,/\bdon't\b/i,/\bmake sure\b/i,/\bremember to\b/i],xo=[/\bno\b/i,/\bwrong\b/i,/\bnot that\b/i,/\bi said\b/i,/\bstop\b/i,/\bthat's not right\b/i,/\bthats not right\b/i,/\bnot correct\b/i,/\btry again\b/i,/\bnot right\b/i],Ro=/\b(run|npm|pnpm|yarn|node|python|python3|pytest|make|docker|git|curl|bash|sh|cat|ls|find|grep|sed|awk|rm|cp|mv|touch|tee|mkdir|rmdir)\b/i,wo=[/^<[a-z-]+>/i,/^<\/[a-z-]+>/i,/^─{4,}/,/^={4,}/,/^-{4,}/,/^\*{4,}/,/^#{4,}\s*$/,/^UserPromptSubmit/,/^SessionStart/,/^OK$/,/^Tool loaded/],_={SS1:"Repeated instructions",SS2:"Ignored rules",SS3:"Friction hotspots",SS4:"Missing rule suggestions"};function Gt(e){let t=process.cwd(),n=null,r="terminal",s="error",o=!1,i=!1,a=null,c=!1,l=null,m=30,u=!1;for(let f=0;f<e.length;f+=1){let d=e[f];if(d!==void 0){if(d==="-h"||d==="--help"){o=!0;continue}if(d==="--emit-ai-tasks"){i=!0;continue}if(d==="--session-analysis"){c=!0;continue}if(d==="--include-raw-snippets"){u=!0;continue}if(d==="--session-root"){let g=e[f+1];g===void 0&&(process.stderr.write(`error: --session-root requires a path
|
|
6
|
+
`),process.exit(2)),l=g,f+=1;continue}if(d==="--max-sessions"){let g=e[f+1];g===void 0&&(process.stderr.write(`error: --max-sessions requires a value
|
|
7
|
+
`),process.exit(2));let y=Number.parseInt(g,10);(!Number.isFinite(y)||y<=0)&&(process.stderr.write(`error: --max-sessions must be a positive integer
|
|
8
|
+
`),process.exit(2)),m=y,f+=1;continue}if(d==="--ingest-ai-results"){let g=e[f+1];g===void 0&&(process.stderr.write(`error: --ingest-ai-results requires a file path
|
|
9
|
+
`),process.exit(2)),a=g,f+=1;continue}if(d==="--harness"){let g=e[f+1];g===void 0&&(process.stderr.write(`error: --harness requires a value
|
|
10
|
+
`),process.exit(2)),n=$t(g),f+=1;continue}if(d==="--format"){let g=e[f+1];g===void 0&&(process.stderr.write(`error: --format requires a value
|
|
11
|
+
`),process.exit(2)),r=So(g),f+=1;continue}if(d==="--fail-on"){let g=e[f+1];g===void 0&&(process.stderr.write(`error: --fail-on requires a value
|
|
12
|
+
`),process.exit(2)),s=yo(g),f+=1;continue}d.startsWith("-")&&(process.stderr.write(`error: unknown option: ${d}
|
|
13
|
+
`),process.exit(2)),t=Ea.resolve(d)}}return{repoRoot:t,harnessFilter:n,format:r,failOn:s,help:o,emitAiTasks:i,ingestResultsPath:a,sessionAnalysis:c,sessionRoot:l,maxSessions:m,includeRawSnippets:u}}function jt(){process.stdout.write(`paniolo-scan \u2014 AI harness diagnostic (read-only)
|
|
14
14
|
|
|
15
15
|
Usage:
|
|
16
16
|
paniolo-scan [options] [path]
|
|
@@ -36,26 +36,26 @@ Examples:
|
|
|
36
36
|
npx @paniolo/scan --ingest-ai-results paniolo-ai-results.json --format json
|
|
37
37
|
npx @paniolo/scan --session-analysis
|
|
38
38
|
npx @paniolo/scan --session-analysis --format json --include-raw-snippets
|
|
39
|
-
`)}function
|
|
40
|
-
`)}var
|
|
39
|
+
`)}function Wt(e){process.stdout.write(`${JSON.stringify(e,null,2)}
|
|
40
|
+
`)}var va=["SS4","SS2","SS3","SS1"];function Ut(e){if(process.stdout.write(`# paniolo-scan \u2014 Session Analysis (extended)
|
|
41
41
|
|
|
42
42
|
`),e.status==="no-sessions"){process.stdout.write(`No ${e.harness} session logs found for this repo. Nothing to analyze.
|
|
43
|
-
`);return}let t=e.findings.filter(
|
|
43
|
+
`);return}let t=e.findings.filter(r=>r.checkId==="SS4").length,n=e.findings.filter(r=>r.checkId==="SS3"&&r.snippet!==null).length;if(process.stdout.write(`Analyzed ${String(e.sessionsAnalyzed)} session(s): ${String(t)} candidate missing rule(s), ${String(n)} recurring friction theme(s).
|
|
44
44
|
`),process.stdout.write(e.redacted?`Snippets are redacted; re-run with --include-raw-snippets to reveal them.
|
|
45
45
|
|
|
46
46
|
`:`Snippets shown verbatim (--include-raw-snippets).
|
|
47
47
|
|
|
48
48
|
`),e.findings.length===0){process.stdout.write(`No recurring instructions, ignored rules, or friction detected.
|
|
49
|
-
`);return}for(let
|
|
49
|
+
`);return}for(let r of va){let s=e.findings.filter(o=>o.checkId===r);if(s.length!==0){process.stdout.write(`## ${r} \u2014 ${_[r]}
|
|
50
50
|
|
|
51
|
-
`);for(let o of
|
|
51
|
+
`);for(let o of s)process.stdout.write(`- ${o.detail}
|
|
52
52
|
`);process.stdout.write(`
|
|
53
|
-
`)}}}var
|
|
54
|
-
Harnesses: ${e.harnesses.join(", ")}`,
|
|
55
|
-
Hint: ${e.hint}`,o=
|
|
53
|
+
`)}}}var Ta={"shared-agents-md":["Memory","Planning"],"shared-rules-doc":["Planning","Action"],"adapter-thin-claude":["Memory"],"adapter-thin-gemini":["Memory"],"adapter-thin-copilot":["Memory"],"adapter-points-to-shared":["Memory"],"skills-index":["Action"],"claude-agent-routing":["Planning"],"agents-md-mentions-skills":["Action"],"skill-doc-deep-links":["Memory"],"qmd-script-present":["Memory"],"memory-docs-indexed":["Memory"],"focused-test-commands-present":["Reflection"],"skill-frontmatter":["Action"],"skill-line-count":["Memory"],"agent-frontmatter":["Action"],"no-duplicate-skill-trees":["Memory"],"no-duplicate-agent-trees":["Memory"],"guidance-links-resolve":["Memory"],"forbidden-legacy-paths":["Memory"],"local-context-patterns":["Memory"],"correction-loop-documented":["Reflection"],"guidance-maintenance-script":["Reflection"],"pr-template-ai-harness-check":["Reflection"],"emphasis-keyword-density":["Memory"],"identity-language-absent":["Memory"],"adapter-content-duplication":["Memory"],"adapter-context-budget":["Memory"],"always-loaded-budget":["Memory"],"strict-typecheck-present":["Reflection","System Operation"],"lint-gate-present":["Reflection","System Operation"],"jsdoc-enforcement-present":["Reflection"],"test-gates-present":["Reflection"],"ci-enforcement-gates":["Reflection","System Operation"],"ci-validation-gates":["Reflection","System Operation"],"ci-guidance-lint":["Reflection"],"vscode-skills-location":["Action"],"vscode-agents-location":["Action"],"vscode-custom-hooks":["Reflection","System Operation"],"no-dangerous-auto-approve":["Action"],"hook-no-network-exfil":["Action","System Operation"],"hook-stop-circuit-breaker":["Reflection","System Operation"],"env-files-gitignored":["Action"],"secret-scanning-configured":["System Operation"],"no-pull-request-target":["System Operation"],"actions-sha-pinned":["System Operation"],"claude-hooks-valid":["System Operation"],"codex-hooks-valid":["System Operation"],"model-interface-pinned":["System Operation","Action"],"llm-output-schema-validated":["Action"],"tool-contract-tests-present":["Action","System Operation"],"escalation-protocol-discoverability":["Planning","Reflection"],"agent-resource-budget-caps":["System Operation"],"tool-allowlist-inventory":["Action"],"untrusted-input-action-boundary":["Action","Memory"],"memory-write-provenance":["Memory"],"high-impact-action-confirmation":["Action"]};function Ze(e){return Ta[e]??[]}var Bt=["error","warn","info"],bo={error:"ERROR",warn:"WARN",info:"INFO"},Co={layering:"Layering",sharing:"Sharing",discoverability:"Discoverability",harnessWiring:"Harness wiring",maintainability:"Maintainability",guardrails:"Guardrails"},Ao=["layering","sharing","discoverability","harnessWiring","maintainability","guardrails"],Io=["copilot","cursor","codex","antigravity","claude","gemini"];function Vt(e){let t=bo[e.severity],n=e.file===null?"":` ${e.file}${e.line===null?"":`:${String(e.line)}`}`,r=e.harnesses.length===0?"":`
|
|
54
|
+
Harnesses: ${e.harnesses.join(", ")}`,s=e.hint===void 0?"":`
|
|
55
|
+
Hint: ${e.hint}`,o=Ze(e.ruleId),i=o.length===0?"":`
|
|
56
56
|
Prevents: ${o.join(", ")}-class agent failures`;return`[${t}] ${e.ruleId}
|
|
57
57
|
${e.message}${n?`
|
|
58
|
-
${n}`:""}${
|
|
58
|
+
${n}`:""}${r}${i}${s}`}var Eo=`---
|
|
59
59
|
|
|
60
60
|
\u2139\uFE0F Need professional-grade agent infrastructure?
|
|
61
61
|
|
|
@@ -68,38 +68,38 @@ For professional or production-grade work, we strongly recommend
|
|
|
68
68
|
engaging Paniolo's professional services to design, tune, and evolve
|
|
69
69
|
your infrastructure. Learn more at https://paniolo.ai or contact us
|
|
70
70
|
directly at https://paniolo.ai/#contact.
|
|
71
|
-
`;function
|
|
71
|
+
`;function zt(e){if(process.stdout.write(`## AI review (optional)
|
|
72
72
|
|
|
73
73
|
`),e.status==="not-run"){process.stdout.write(`Not run \u2014 pass --ingest-ai-results to score this dimension.
|
|
74
74
|
|
|
75
75
|
`);return}let t=e.score===null?"n/a":`${String(e.score)}/100`;process.stdout.write(`AI review: ${t} (${e.grade})
|
|
76
|
-
`);for(let n of e.checks){let
|
|
77
|
-
`)}for(let n of e.findings){let
|
|
76
|
+
`);for(let n of e.checks){let r=n.passed?"\u2713":`\u2717 ${String(n.findingsCount)} finding(s)`;process.stdout.write(` ${r} ${n.title}
|
|
77
|
+
`)}for(let n of e.findings){let r=n.file===null?"":` (${n.file})`;process.stdout.write(` - ${n.message}${r}
|
|
78
78
|
`)}process.stdout.write(`
|
|
79
|
-
`)}function
|
|
79
|
+
`)}function qt(e){if(e===void 0)return;let t=e.harnesses.filter(n=>n.detected);if(t.length!==0){process.stdout.write(`## Context budget
|
|
80
80
|
|
|
81
81
|
`);for(let n of t){process.stdout.write(`${n.harness}: ${String(n.totalLines)} always-loaded lines, ~${String(n.estimatedTokens)} tokens (${n.status})
|
|
82
|
-
`);for(let
|
|
82
|
+
`);for(let r of n.files.slice(0,3))process.stdout.write(` ${r.path}: ${String(r.lines)} lines
|
|
83
83
|
`)}process.stdout.write(`
|
|
84
|
-
`)}}function
|
|
84
|
+
`)}}function Kt(e){if(process.stdout.write(`## Predicted runtime failure exposure
|
|
85
85
|
|
|
86
86
|
`),e.byDimension.length===0){process.stdout.write(`No findings map to a runtime failure class.
|
|
87
87
|
|
|
88
|
-
`);return}let t=[...e.byDimension].sort((n,
|
|
88
|
+
`);return}let t=[...e.byDimension].sort((n,r)=>r.findingCount-n.findingCount);for(let n of t){let r=`${String(n.error)} error / ${String(n.warn)} warn / ${String(n.info)} info`;process.stdout.write(`${n.dimension}: ${String(n.findingCount)} finding(s) \u2014 ${r}
|
|
89
89
|
`),process.stdout.write(` Rules: ${n.ruleIds.join(", ")}
|
|
90
90
|
`)}e.untaggedFindings>0&&process.stdout.write(`
|
|
91
91
|
${String(e.untaggedFindings)} finding(s) not yet mapped to a failure class.
|
|
92
92
|
`),process.stdout.write(`
|
|
93
|
-
`)}var
|
|
93
|
+
`)}var Yt=new Set(["shared","skills","agents"]),Q=["copilot","cursor","codex","antigravity","claude","gemini"];function vo(e,t){return t.length>=2?!0:Yt.has(e.layer)||e.path==="AGENTS.md"}function et(e){switch(e){case"yes":return"\u2713";case"partial":return"~";case"no":return"\u2717";case"na":return"\u2014"}}import{readFile as La}from"node:fs/promises";import _a from"node:path";async function Jt(e){try{return await La(_a.join(e,".codex/hooks.json"),"utf8"),!0}catch{return!1}}function p(e,t){return{status:e,detail:t}}function Xt(){let e={copilot:p("na",""),cursor:p("na",""),codex:p("na",""),antigravity:p("na",""),claude:p("na",""),gemini:p("na","")};return{sharedSkillsDiscoverable:{...e},customAgents:{...e},lifecycleHooks:{...e},thinAdapter:{...e},workflows:{...e}}}var Fa={copilot:".github/copilot-instructions.md",claude:"CLAUDE.md",gemini:"GEMINI.md"};function P(e){return Fa[e]??null}function Ce(e,t){if(!I(e))return!1;if(k(e,"docs/ai/available-skills.md"))return!0;let n=h(e,"AGENTS.md");if(n!==null&&Ye(n))return!0;let r=P(t);if(r===null)return!1;let s=h(e,r);return s!==null&&s.includes("skills/")}function T(e,t,n){let r=e.settings?.[t];if(S(r)&&Object.keys(r).some(a=>a.startsWith(n)))return!0;if(e.settingsRaw===null)return!1;let s=t.replaceAll(".",String.raw`\.`);return new RegExp(`"${s}"\\s*:\\s*\\{[^}]*"${n}[^"]*"`).test(e.settingsRaw)}var Na=50;function To(e){return e.files.some(t=>t.path.startsWith("agents/")&&t.path.endsWith(".agent.md"))}function tt(e,t){let n=U(e,t);return n===null?!1:n<=Na}function Lo(e,t){let n=h(e,t);return n===null?!1:n.includes("AGENTS.md")||n.includes("docs/ai/rules.md")}function nt(e){return e.files.some(t=>t.path.startsWith(".agent/workflows/"))}function _o(e){let t=h(e,"CLAUDE.md");return t!==null&&Je(t)}function Qt(e,t){let n=To(t.context);switch(e){case"copilot":case"cursor":return T(t.vscode,"chat.agentFilesLocations","agents")&&n?p("yes","agents/ wired in chat.agentFilesLocations"):n?p("partial","agents/ present but not wired in VS Code settings"):p("no","No agents/ tree or VS Code agent locations");case"codex":return t.context.files.some(s=>s.path.startsWith(".codex/agents/"))&&n?p("yes",".codex/agents wrappers with shared agents/"):n?p("partial","agents/ present without .codex/agents wrappers"):p("no","No custom agents configured");case"claude":return _o(t.context)?p("yes","Agent routing table in CLAUDE.md"):n?p("partial","agents/ present without routing table in CLAUDE.md"):p("no","No agent routing or agents/ tree");case"gemini":{if(!n)return p("no","No agents/ tree");let r=P("gemini"),s=r===null?null:t.context.fileContents.get(r)??null;return s!==null&&s.includes("agents/")?p("partial","agents/ referenced from GEMINI.md"):p("partial","agents/ present; document routing in GEMINI.md")}case"antigravity":return p("na","Uses workflow playbooks instead of custom agents");default:return p("no","Unknown harness")}}function Zt(e,t){let n=t.vscode.hooksDirExists,r=t.vscode.settings?.["chat.useCustomAgentHooks"]===!0;switch(e){case"copilot":case"cursor":return n&&r?p("yes",".github/hooks/ with chat.useCustomAgentHooks"):n||r?p("partial","Hooks partially configured in VS Code workspace"):p("no","No lifecycle hooks configured");case"codex":return t.codexHooksExists?p("yes",".codex/hooks.json present"):n?p("partial","Shared .github/hooks/ only; no .codex/hooks.json"):p("no","No Codex hooks configured");case"claude":return t.claudeSettingsRaw!==null&&/"hooks"\s*:/.test(t.claudeSettingsRaw)?p("yes","Hooks in .claude/settings.json"):n?p("partial","Shared .github/hooks/ only; no .claude hooks"):p("no","No Claude hooks configured");case"gemini":return n&&r?p("partial","Shared VS Code hooks only; no Gemini-native hooks"):p("no","No lifecycle hooks for Gemini");case"antigravity":return p("na","No hook surface for Antigravity workflows");default:return p("no","Unknown harness")}}function en(e,t){if(!I(t.context))return p("no","No skills/ tree");switch(e){case"copilot":case"cursor":return T(t.vscode,"chat.agentSkillsLocations","skills")?p("yes","skills/ wired in chat.agentSkillsLocations"):p("partial","skills/ present but not wired in VS Code settings");case"codex":return Ce(t.context,"codex")?p("partial","skills/ with prose discovery via AGENTS.md or skill index"):p("partial","skills/ present; no documented discovery workflow");case"claude":case"gemini":return Ce(t.context,e)?p("partial","Prose discovery via skill index or adapter pointers"):p("no","skills/ without index or adapter pointers");case"antigravity":return nt(t.context)?p("yes","skills/ with workflow playbooks"):p("partial","skills/ present without workflow playbooks");default:return p("no","Unknown harness")}}function tn(e,t){switch(e){case"copilot":{let n=P("copilot");return n===null||!t.context.files.some(r=>r.path===n)?p("no","Missing .github/copilot-instructions.md"):tt(t.context,n)?p("yes","Copilot instructions within line budget"):p("partial","Copilot instructions exceed thin adapter budget")}case"cursor":{let n=t.context.files.some(s=>s.path.startsWith(".cursor/rules/")),r=T(t.vscode,"chat.agentSkillsLocations","skills")&&T(t.vscode,"chat.agentFilesLocations","agents");return n||r?p("yes","Cursor rules or VS Code agent settings configured"):p("partial","Cursor detected without rules or agent settings")}case"codex":return t.context.files.some(r=>r.path.startsWith(".codex/"))?t.context.files.some(r=>r.path==="AGENTS.md")?p("yes",".codex/ with shared AGENTS.md entry"):p("partial",".codex/ without root AGENTS.md"):p("no","No .codex/ config surface");case"claude":{let n=P("claude");if(n===null||!t.context.files.some(o=>o.path===n))return p("no","Missing CLAUDE.md");let r=tt(t.context,n),s=Lo(t.context,n);return r&&s?p("yes","Thin CLAUDE.md referencing shared layers"):r?p("partial","CLAUDE.md thin but missing shared layer pointers"):p("partial","CLAUDE.md exceeds thin adapter budget")}case"gemini":{let n=P("gemini");return n===null||!t.context.files.some(r=>r.path===n)?p("no","Missing GEMINI.md"):tt(t.context,n)?p("yes","Thin GEMINI.md adapter"):p("partial","GEMINI.md exceeds thin adapter budget")}case"antigravity":return p("partial","Workflows only; no classic root adapter");default:return p("no","Unknown harness")}}function nn(e,t){return e!=="antigravity"?p("na","Workflow playbooks are Antigravity-specific"):nt(t.context)?p("yes",".agent/workflows/ playbooks present"):p("no","No .agent/workflows/ playbooks")}function rn(e,t,n){switch(e){case"sharedSkillsDiscoverable":return en(t,n);case"customAgents":return Qt(t,n);case"lifecycleHooks":return Zt(t,n);case"thinAdapter":return tn(t,n);case"workflows":return nn(t,n);default:return p("no","Unknown capability")}}var sn={sharedSkillsDiscoverable:"Shared skills discoverable",customAgents:"Custom agents",lifecycleHooks:"Lifecycle hooks",thinAdapter:"Thin adapter",workflows:"Workflows / playbooks"},Ae=["sharedSkillsDiscoverable","customAgents","lifecycleHooks","thinAdapter","workflows"],Fo="Harness not detected";import{readFile as Pa}from"node:fs/promises";import Ma from"node:path";async function on(e){try{return await Pa(Ma.join(e,".claude/settings.json"),"utf8")}catch{return null}}async function an(e,t){let n=Q.filter(o=>e.harnesses.includes(o)),r={context:e,vscode:t,claudeSettingsRaw:await on(e.repoRoot),codexHooksExists:await Jt(e.repoRoot)},s=Xt();for(let o of Ae){let i=s[o];for(let a of Q){if(!e.harnesses.includes(a)){i[a]=p("na",Fo);continue}i[a]=rn(o,a,r)}}return{capabilities:Ae,harnesses:n,matrix:s}}function cn(e){if(process.stdout.write(`## Harness gap matrix
|
|
94
94
|
|
|
95
95
|
`),e.harnesses.length===0){process.stdout.write(`No harnesses detected \u2014 add tool adapters to compare capabilities.
|
|
96
96
|
|
|
97
|
-
`);return}let t=28,n=Math.max(...e.harnesses.map(
|
|
98
|
-
`);for(let
|
|
97
|
+
`);return}let t=28,n=Math.max(...e.harnesses.map(s=>s.length),6)+2,r=`${"Capability".padEnd(t)}${e.harnesses.map(s=>s.padEnd(n)).join("")}`;process.stdout.write(`${r}
|
|
98
|
+
`);for(let s of Ae){let o=sn[s].padEnd(t),i=e.harnesses.map(a=>{let{status:c}=e.matrix[s][a];return et(c).padEnd(n)}).join("");process.stdout.write(`${o}${i}
|
|
99
99
|
`)}process.stdout.write(`
|
|
100
100
|
Legend: \u2713 yes ~ partial \u2717 no \u2014 not applicable
|
|
101
101
|
|
|
102
|
-
`)}function
|
|
102
|
+
`)}function ln(e){e!==void 0&&(process.stdout.write(`## Intelligence layer
|
|
103
103
|
|
|
104
104
|
`),process.stdout.write(`Surfaces: ${String(e.surfaces.length)} detected
|
|
105
105
|
`),process.stdout.write(`Enforcement: ${String(e.enforcement.scripts.length)} script(s), ${String(e.enforcement.configs.length)} config(s), ${String(e.enforcement.ciWorkflows.length)} CI workflow(s)
|
|
@@ -109,83 +109,85 @@ Legend: \u2713 yes ~ partial \u2717 no \u2014 not applicable
|
|
|
109
109
|
`),process.stdout.write(`Correction loop: ${String(e.correctionLoop.scripts.length)} script(s), ${String(e.correctionLoop.prTemplates.length)} PR template(s), ${String(e.correctionLoop.ciWorkflows.length)} CI workflow(s)
|
|
110
110
|
`),process.stdout.write(`Correction checks: ${String(e.correctionLoop.maintenanceScripts.length)} maintenance script(s), ${String(e.correctionLoop.prTemplateChecks.length)} PR reminder(s), ${String(e.correctionLoop.guidanceCiWorkflows.length)} CI guidance gate(s)
|
|
111
111
|
|
|
112
|
-
`))}function
|
|
112
|
+
`))}function un(e){process.stdout.write(`## Meta-harness dimensions
|
|
113
113
|
|
|
114
|
-
`);for(let
|
|
115
|
-
`)}process.stdout.write(
|
|
116
|
-
`)}
|
|
114
|
+
`);for(let c of Ao){let l=e.dimensions[c];if(l===void 0)continue;let m=Co[c],u=l.applicableRules===0?" (no rules yet)":` (${String(l.passedRules)}/${String(l.applicableRules)} rules)`;process.stdout.write(`${m}: ${String(l.score)}/100 (${l.grade})${u}
|
|
115
|
+
`)}let{coverage:t}=e,n=`Total: ${String(e.total_score)}/100 (${e.score_scope}) \u2014 ${String(t.rulesApplied)} rules across ${String(t.dimensionsRun)}/${String(t.dimensionsTotal)} core dimensions`,r=t.level==="partial"?` (partial coverage: ${t.dimensionsNotRun.join(", ")} did not run \u2014 the score reflects evaluated surfaces only)`:"";process.stdout.write(`${n}${r}
|
|
116
|
+
`);let{harnessNet:s}=e,o=s.score>0?"+":"",i=s.repoReadiness===null?"":` \xB7 repo readiness ${String(s.repoReadiness)}/100`,a=s.status==="implicit-only"?" (implicit infrastructure only \u2014 tests, gates, and enforced comments count as harness; no guidance files detected)":` (${String(s.contributions.length)} contributions, ${String(s.liabilities.length)} liabilities)`;process.stdout.write(`Harness net: ${o}${String(s.score)} vs bare-repo baseline 0${a}${i}
|
|
117
|
+
|
|
118
|
+
`)}function dn(e){process.stdout.write(`## Harness optimization
|
|
117
119
|
|
|
118
|
-
`);let t=e.filter(
|
|
120
|
+
`);let t=e.filter(r=>r.detected);if(t.length===0){process.stdout.write(`No harnesses detected \u2014 add tool adapters to evaluate optimization.
|
|
119
121
|
|
|
120
|
-
`);return}for(let
|
|
121
|
-
`),
|
|
122
|
-
`);let o=
|
|
122
|
+
`);return}for(let r of t){let s=r.score===null?"n/a":`${String(r.score)}/100 (${r.grade})`;process.stdout.write(`${r.harness}: ${s}
|
|
123
|
+
`),r.loadProfile!==null&&process.stdout.write(` Load profile: ${String(r.loadProfile.sharedLines)} shared + ${String(r.loadProfile.uniqueLines)} unique lines (${String(r.loadProfile.sharedPercent)}% shared)
|
|
124
|
+
`);let o=r.checks.filter(a=>!a.passed),i=r.checks.length-o.length;process.stdout.write(` Checks: ${String(i)}/${String(r.checks.length)} passed`),r.findingsCount.error+r.findingsCount.warn>0&&process.stdout.write(`; findings: ${String(r.findingsCount.error)} error, ${String(r.findingsCount.warn)} warn`),process.stdout.write(`
|
|
123
125
|
`);for(let a of o.slice(0,5))process.stdout.write(` \u2717 ${a.label}
|
|
124
126
|
`);o.length>5&&process.stdout.write(` \u2026 and ${String(o.length-5)} more
|
|
125
127
|
`),process.stdout.write(`
|
|
126
|
-
`)}let n=e.filter(
|
|
128
|
+
`)}let n=e.filter(r=>!r.detected);n.length>0&&process.stdout.write(`Not detected: ${n.map(r=>r.harness).join(", ")}
|
|
127
129
|
|
|
128
|
-
`)}function
|
|
130
|
+
`)}function pn(e){process.stdout.write(`## Guidance sharing
|
|
129
131
|
|
|
130
132
|
`),process.stdout.write(`Shared (canonical / multi-harness): ${String(e.shared.lines)} lines (${String(e.shared.percentLines)}%) across ${String(e.shared.files)} file(s)
|
|
131
133
|
`),process.stdout.write(`Harness-specific: ${String(e.unique.totals.lines)} lines (${String(e.unique.totals.percentLines)}%) across ${String(e.unique.totals.files)} file(s)
|
|
132
|
-
`);let t=
|
|
134
|
+
`);let t=Io.filter(n=>e.unique.byHarness[n].lines>0);if(t.length>0){process.stdout.write(`
|
|
133
135
|
Per-harness unique guidance:
|
|
134
|
-
`);for(let n of t){let
|
|
136
|
+
`);for(let n of t){let r=e.unique.byHarness[n];process.stdout.write(` ${n}: ${String(r.lines)} lines (${String(r.files)} file(s))
|
|
135
137
|
`)}}process.stdout.write(`
|
|
136
|
-
`)}function
|
|
138
|
+
`)}function mn(e){if(process.stdout.write(`paniolo-scan \u2014 AI harness diagnostic
|
|
137
139
|
|
|
138
140
|
`),process.stdout.write(`Root: ${e.root}
|
|
139
141
|
`),process.stdout.write(`Harnesses: ${e.harnesses.length===0?"(none detected)":e.harnesses.join(", ")}
|
|
140
142
|
`),process.stdout.write(`Guidance files: ${String(e.inventory.fileCount)}
|
|
141
143
|
`),process.stdout.write(`Findings: ${String(e.summary.error)} error(s), ${String(e.summary.warn)} warn(s), ${String(e.summary.info)} info
|
|
142
144
|
|
|
143
|
-
`),
|
|
145
|
+
`),pn(e.sharing),ln(e.intelligenceLayer),qt(e.contextBudget),un(e.metaHarness),zt(e.aiReview),cn(e.harnessGapMatrix),dn(e.harnessOptimization),Kt(e.failureModeExposure),process.stdout.write(`## Findings
|
|
144
146
|
|
|
145
147
|
`),e.findings.length===0)process.stdout.write(`No findings.
|
|
146
148
|
|
|
147
|
-
`);else{let t=[...e.findings].sort((n,
|
|
148
|
-
|
|
149
|
-
`)}process.stdout.write(fo)}import yl from"node:path";function cn(){return{copilot:{files:0,lines:0,bytes:0},cursor:{files:0,lines:0,bytes:0},codex:{files:0,lines:0,bytes:0},antigravity:{files:0,lines:0,bytes:0},claude:{files:0,lines:0,bytes:0},gemini:{files:0,lines:0,bytes:0}}}function ln(e,t){return e.harness!==void 0?t.includes(e.harness)?[e.harness]:[]:Ut.has(e.layer)?t:e.path.startsWith(".cursor/")?t.includes("cursor")?["cursor"]:[]:e.path.startsWith(".codex/")?t.includes("codex")?["codex"]:[]:e.path.startsWith(".agent/")?t.includes("antigravity")?["antigravity"]:[]:e.path==="AGENTS.md"||e.path.startsWith("docs/ai/")?t:[]}function Y(e,t){return t===0?0:Math.round(e/t*1e3)/10}function un(e,t){let n={files:0,lines:0,bytes:0},s=cn(),r={files:0,lines:0,bytes:0},o={files:0,lines:0,bytes:0},i=[];for(let a of e){let c=ln(a,t);if(c.length===0)continue;o.files+=1,o.lines+=a.lines,o.bytes+=a.bytes;let l=mo(a,c),p=l?"shared":"unique";if(i.push({path:a.path,lines:a.lines,scope:p,harnesses:c}),l)n.files+=1,n.lines+=a.lines,n.bytes+=a.bytes;else{let[f]=c;f!==void 0&&(s[f].files+=1,s[f].lines+=a.lines,s[f].bytes+=a.bytes),r.files+=1,r.lines+=a.lines,r.bytes+=a.bytes}}return{totals:o,shared:{...n,percentLines:Y(n.lines,o.lines)},unique:{byHarness:s,totals:{...r,percentLines:Y(r.lines,o.lines)}},files:i}}import T from"node:path";import{access as ga}from"node:fs/promises";async function x(e){try{return await ga(e),!0}catch{return!1}}function dn(e){return e===null?!1:e["chat.agentSkillsLocations"]!==void 0||e["chat.agentFilesLocations"]!==void 0||e["chat.useCustomAgentHooks"]===!0}import{readFile as ha}from"node:fs/promises";function pn(e){if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e.startsWith('"')&&e.endsWith('"'))return e.slice(1,-1);let t=Number(e);return Number.isNaN(t)?e:t}function fn(e){let t={},n=/"([^"]+)"\s*:\s*(true|false|null|\d+(?:\.\d+)?|"[^"]*")/g;for(let[,s,r]of e.matchAll(n))s===void 0||r===void 0||(t[s]=pn(r));return Object.keys(t).length===0?null:t}function Ce(e){try{let t=JSON.parse(e);if(y(t))return t}catch{}return fn(e)}async function mn(e){try{let t=await ha(e,"utf8");return Ce(t)}catch{return null}}async function Ae(e){let t=new Set;await x(T.join(e,".github/copilot-instructions.md"))&&t.add("copilot"),await x(T.join(e,".github/hooks"))&&t.add("copilot");let n=await mn(T.join(e,".vscode/settings.json"));return dn(n)&&(t.add("cursor"),t.add("copilot")),await x(T.join(e,".cursor"))&&t.add("cursor"),await x(T.join(e,".codex/config.toml"))&&t.add("codex"),await x(T.join(e,".codex/hooks.json"))&&t.add("codex"),await x(T.join(e,".codex/agents"))&&t.add("codex"),await x(T.join(e,".agent/workflows"))&&t.add("antigravity"),await x(T.join(e,".agent/README.md"))&&t.add("antigravity"),await x(T.join(e,"CLAUDE.md"))&&t.add("claude"),await x(T.join(e,".claude/settings.json"))&&t.add("claude"),await x(T.join(e,"GEMINI.md"))&&t.add("gemini"),[...t].sort()}function Ie(e){return Math.ceil(e/4)}function H(e,t){return{path:e.path,lines:e.lines,bytes:e.bytes,estimatedTokens:Ie(e.bytes),reason:t}}function gn(e,t){let n=e.fileContents.get(t.path);return n===void 0?!1:/^alwaysApply:\s*true\s*$/im.test(n)||/^always_apply:\s*true\s*$/im.test(n)}function J(e,t){return e.files.find(n=>n.path===t)??null}function hn(e,t){let n=[];if(t==="copilot"){let s=J(e,".github/copilot-instructions.md");s!==null&&n.push(H(s,"Copilot workspace instructions are loaded by Copilot Chat."))}if(t==="cursor")for(let s of e.files)s.path.startsWith(".cursor/rules/")&&gn(e,s)&&n.push(H(s,"Cursor rule declares alwaysApply: true."));if(t==="codex"){let s=J(e,"AGENTS.md");s!==null&&n.push(H(s,"Root AGENTS.md is the Codex repo instruction entry."));for(let r of e.files)r.path.startsWith(".codex/")&&r.layer==="adapter"&&n.push(H(r,"Codex adapter guidance under .codex/."))}if(t==="antigravity"){let s=J(e,".agent/README.md");s!==null&&n.push(H(s,"Antigravity workspace adapter README."))}if(t==="claude"){let s=J(e,"CLAUDE.md");s!==null&&n.push(H(s,"Claude Code root instruction file."))}if(t==="gemini"){let s=J(e,"GEMINI.md");s!==null&&n.push(H(s,"Gemini root instruction file."))}return n.toSorted((s,r)=>s.path.localeCompare(r.path))}function yn(e,t){if(!e.harnesses.includes(t))return{harness:t,detected:!1,files:[],totalLines:0,totalBytes:0,estimatedTokens:0,maxRecommendedLines:250,status:"ok"};let s=hn(e,t),r=s.reduce((i,a)=>i+a.lines,0),o=s.reduce((i,a)=>i+a.bytes,0);return{harness:t,detected:!0,files:s,totalLines:r,totalBytes:o,estimatedTokens:Ie(o),maxRecommendedLines:250,status:r>250?"high":"ok"}}function Sn(e){return{harnesses:K.map(t=>yn(e,t)),maxRecommendedLines:250,maxRecommendedFileLines:150}}var kn=["Memory","Reflection","Planning","Action","System Operation"];function xn(e){let t=new Map(kn.map(i=>[i,{dimension:i,findingCount:0,error:0,warn:0,info:0,ruleIds:[]}])),n=new Map(kn.map(i=>[i,new Set])),s=0,r=0;for(let i of e){let a=Ye(i.ruleId);if(a.length===0){r+=1;continue}s+=1;for(let c of a){let l=t.get(c),p=n.get(c);l===void 0||p===void 0||(l.findingCount+=1,l[i.severity]+=1,p.has(i.ruleId)||(p.add(i.ruleId),l.ruleIds.push(i.ruleId)))}}return{byDimension:kn.map(i=>t.get(i)).filter(i=>i.findingCount>0),taggedFindings:s,untaggedFindings:r}}function wn(e,t){let n={sharedLines:0,uniqueLines:0,totalLines:0,sharedPercent:0,uniquePercent:0},s={copilot:{...n},cursor:{...n},codex:{...n},antigravity:{...n},claude:{...n},gemini:{...n}};for(let r of t){let o=e.unique.byHarness[r].lines,i=e.shared.lines,a=i+o;s[r]={sharedLines:i,uniqueLines:o,totalLines:a,sharedPercent:Y(i,a),uniquePercent:Y(o,a)}}return s}function Rn(e,t){let n={error:0,warn:0,info:0};for(let s of e)s.harnesses.includes(t)&&(s.severity==="error"?n.error+=1:s.severity==="warn"?n.warn+=1:n.info+=1);return n}var xo=[{min:85,grade:"excellent"},{min:70,grade:"good"},{min:50,grade:"fair"},{min:0,grade:"poor"}],Ze={error:12,warn:5,info:1},wo=40;function bn(e){let t=e.error*Ze.error+e.warn*Ze.warn+e.info*Ze.info;return Math.min(t,wo)}import ve from"node:path";function M(e,t){return e.files.some(n=>n.path===t)}function Cn(e,t){return e.fileContents.get(t)??null}function ya(e,t){return e.files.find(s=>s.path===t)?.lines??null}function Sa(e){return e.includes("AGENTS.md")||e.includes("docs/ai/rules.md")}function X(e){return e.files.some(t=>t.path.startsWith("skills/"))}function Ee(e){return e.files.some(t=>t.path.startsWith("agents/"))}function An(e,t){return e.settings?.[t]===!0}function et(e,t){let n=ya(e,t);return n===null?!1:n<=W}function tt(e,t){let n=Cn(e,t);return n===null?!1:Sa(n)}function In(e){let t=Cn(e,".agent/README.md");return t===null?!1:/\.agent\/workflows\/|workflows\//i.test(t)&&/(workflow|playbook|slash command|mission|turbo)/i.test(t)}function Q(e,t,n){let s=e.settings?.[t];if(y(s)&&Object.keys(s).some(a=>a.startsWith(n)))return!0;if(e.settingsRaw===null)return!1;let r=t.replaceAll(".",String.raw`\.`);return new RegExp(`"${r}"\\s*:\\s*\\{[^}]*"${n}[^"]*"`).test(e.settingsRaw)}var Ro={copilot:[{id:"copilot-instructions",label:"Copilot instructions file present",weight:15,run:({context:e})=>M(e,".github/copilot-instructions.md")},{id:"copilot-references-shared",label:"Copilot instructions reference shared layers",weight:15,run:({context:e})=>tt(e,".github/copilot-instructions.md")},{id:"copilot-adapter-thin",label:"Copilot instructions stay thin",weight:10,run:({context:e})=>et(e,".github/copilot-instructions.md")},{id:"copilot-skills-location",label:"chat.agentSkillsLocations points at skills/",weight:15,run:({vscode:e})=>Q(e,"chat.agentSkillsLocations","skills")},{id:"copilot-agents-location",label:"chat.agentFilesLocations points at agents/",weight:15,run:({vscode:e})=>Q(e,"chat.agentFilesLocations","agents")},{id:"copilot-hooks-enabled",label:"Custom agent hooks enabled when .github/hooks/ exists",weight:15,run:({vscode:e})=>!e.hooksDirExists||An(e,"chat.useCustomAgentHooks")},{id:"copilot-shared-skills",label:"Shared skills/ tree present",weight:8,run:({context:e})=>X(e)},{id:"copilot-shared-agents",label:"Shared agents/ tree present",weight:7,run:({context:e})=>Ee(e)}],cursor:[{id:"cursor-rules-or-settings",label:"Cursor rules or VS Code agent settings present",weight:20,run:({context:e,vscode:t})=>e.files.some(n=>n.path.startsWith(".cursor/rules/"))||Q(t,"chat.agentSkillsLocations","skills")},{id:"cursor-skills-location",label:"chat.agentSkillsLocations points at skills/",weight:20,run:({vscode:e})=>Q(e,"chat.agentSkillsLocations","skills")},{id:"cursor-agents-location",label:"chat.agentFilesLocations points at agents/",weight:20,run:({vscode:e})=>Q(e,"chat.agentFilesLocations","agents")},{id:"cursor-hooks-enabled",label:"Custom agent hooks enabled when .github/hooks/ exists",weight:15,run:({vscode:e})=>!e.hooksDirExists||An(e,"chat.useCustomAgentHooks")},{id:"cursor-shared-skills",label:"Shared skills/ tree present",weight:13,run:({context:e})=>X(e)},{id:"cursor-shared-agents",label:"Shared agents/ tree present",weight:12,run:({context:e})=>Ee(e)}],codex:[{id:"codex-config-surface",label:"Codex config surface present (.codex/ or nested AGENTS.md)",weight:25,run:async({context:e})=>e.files.some(t=>t.path.startsWith(".codex/"))?!0:await x(ve.join(e.repoRoot,"api/AGENTS.md"))||await x(ve.join(e.repoRoot,"react/AGENTS.md"))||await x(ve.join(e.repoRoot,"shared/AGENTS.md"))},{id:"codex-hooks",label:"Codex hooks.json present",weight:20,run:({context:e})=>x(ve.join(e.repoRoot,".codex/hooks.json"))},{id:"codex-agents-wrappers",label:"Codex agent wrappers present",weight:20,run:({context:e})=>x(ve.join(e.repoRoot,".codex/agents"))},{id:"codex-shared-entry",label:"Root AGENTS.md present",weight:20,run:({context:e})=>M(e,"AGENTS.md")},{id:"codex-shared-skills",label:"Shared skills/ tree present",weight:8,run:({context:e})=>X(e)},{id:"codex-shared-rules",label:"Canonical rules doc present",weight:7,run:({context:e})=>M(e,"docs/ai/rules.md")}],antigravity:[{id:"antigravity-workflows",label:"Workflow playbooks present (.agent/workflows/)",weight:35,run:({context:e})=>e.files.some(t=>t.path.startsWith(".agent/workflows/"))},{id:"antigravity-readme",label:".agent/README.md documents workflow layout",weight:15,run:({context:e})=>In(e)},{id:"antigravity-shared-entry",label:"Root AGENTS.md present",weight:20,run:({context:e})=>M(e,"AGENTS.md")},{id:"antigravity-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>X(e)},{id:"antigravity-ai-system-doc",label:"AI system layout doc present",weight:15,run:({context:e})=>M(e,"docs/ai/ai-system.md")}],claude:[{id:"claude-adapter",label:"CLAUDE.md adapter present",weight:25,run:({context:e})=>M(e,"CLAUDE.md")},{id:"claude-references-shared",label:"CLAUDE.md references shared layers",weight:25,run:({context:e})=>tt(e,"CLAUDE.md")},{id:"claude-adapter-thin",label:"CLAUDE.md stays thin",weight:20,run:({context:e})=>et(e,"CLAUDE.md")},{id:"claude-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>X(e)},{id:"claude-skills-index",label:"Skill index doc for prose discovery",weight:8,run:({context:e})=>M(e,"docs/ai/available-skills.md")},{id:"claude-shared-agents",label:"Shared agents/ tree present",weight:7,run:({context:e})=>Ee(e)}],gemini:[{id:"gemini-adapter",label:"GEMINI.md adapter present",weight:30,run:({context:e})=>M(e,"GEMINI.md")},{id:"gemini-references-shared",label:"GEMINI.md references shared layers",weight:25,run:({context:e})=>tt(e,"GEMINI.md")},{id:"gemini-adapter-thin",label:"GEMINI.md stays thin",weight:20,run:({context:e})=>et(e,"GEMINI.md")},{id:"gemini-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>X(e)},{id:"gemini-shared-agents",label:"Shared agents/ tree present",weight:10,run:({context:e})=>Ee(e)}]};async function En(e,t){let n=Ro[e],s=[];for(let r of n){let o=await r.run(t);s.push({id:r.id,label:r.label,passed:o,weight:r.weight})}return s}function vn(e){let t=e.reduce((s,r)=>s+r.weight,0);if(t===0)return 0;let n=e.filter(s=>s.passed).reduce((s,r)=>s+r.weight,0);return Math.round(n/t*100)}function Tn(e){for(let{min:t,grade:n}of xo)if(e>=t)return n;return"poor"}async function Ln(e,t,n,s,r,o){if(!t.harnesses.includes(e))return{harness:e,detected:!1,score:null,grade:"not-detected",checks:[],findingsCount:{error:0,warn:0,info:0},loadProfile:null};let c=await En(e,{context:t,vscode:n,harness:e}),l=Rn(s,e),p=vn(c),f=bn(l),m=Math.max(0,Math.min(100,p-f));return{harness:e,detected:!0,score:m,grade:Tn(m),checks:c,findingsCount:l,loadProfile:o[e]??null}}async function Fn(e,t,n,s){let r=wn(s,e.harnesses),o=[];for(let i of K){let a=await Ln(i,e,t,n,s,r);o.push(a)}return o}import{readFileSync as ka}from"node:fs";import{dirname as xa,join as bo}from"node:path";import{fileURLToPath as wa}from"node:url";var Ra=wa(import.meta.url),Co=xa(Ra);function nt(e){return typeof e=="object"&&e!==null}function ba(e){return nt(e)&&nt(e.dimensions)&&nt(e.check_weights)}function Ca(e){return nt(e)}function Ao(e,t){let n=JSON.parse(ka(e,"utf8"));if(!t(n))throw new Error(`Invalid standards file: ${e}`);return n}var _n=Ao(bo(Co,"standards","weights.json"),ba),Nn=Ao(bo(Co,"standards","reference-thresholds.json"),Ca);function Pn(e){return!Number.isFinite(e)||e<0?0:e<=1?e:e<=10?e/10:e<=100?e/100:1}function Io(e,t){return e>=t?1:0}function Eo(e,t){return e<=t?1:e===0?0:t/e}function vo(e,t){if(t<=0)return 0;let n=e/t;return Math.max(0,Math.min(1,n))}function Hn(e,t,n){return e>=t&&e<=n?1:e<t?t===0?0:e/t:e===0?0:n/e}function Mn(e){if(e.curve===void 0)return Pn(e.rawScore??0);let t=e.measuredValue??0,n=e.referenceValue,s=typeof n=="number"?n:0;switch(e.curve){case"binary":return Io(t,s);case"asymptoticDecay":return Eo(t,s);case"ratio":return vo(t,s);case"goldilocks":{let[r,o]=Array.isArray(n)?n:[0,s];return Hn(t,r??0,o??0)}}}function Dn(e,t){let n={};for(let r of Object.keys(t.dimensions))n[r]={weightedSum:0,weightSum:0,ran:!1,passedRules:0,applicableRules:0};for(let r of e){let o=n[r.dimension];if(!o)continue;o.ran=!0,o.applicableRules+=1;let i=Mn(r);i===1&&(o.passedRules+=1);let a=r.weight??t.check_weights[r.checkId]??1;!Number.isFinite(a)||a<=0||(o.weightedSum+=i*a,o.weightSum+=a)}let s={};for(let[r,o]of Object.entries(t.dimensions)){let i=n[r];if(!i||!i.ran){s[r]={status:"not_run",score:null,grade:"not-run",passedRules:0,applicableRules:0};continue}let a=i.weightSum>0?i.weightedSum/i.weightSum*o.max_score:0,c=Number.isFinite(a)?Math.round(a):0;s[r]={status:"run",score:c,grade:we(c),passedRules:i.passedRules,applicableRules:i.applicableRules}}return s}function On(e,t){let n=0,s=0;for(let[r,o]of Object.entries(t.dimensions)){let i=e[r];if(!i||i.status!=="run"||i.score===null)continue;let a=Number(o.weight);!Number.isFinite(a)||a<=0||(n+=i.score/o.max_score*a,s+=a)}return s===0?0:Math.round(n/s*100)}var Aa=new Set(["deep","session"]);function $n(e){for(let[t,n]of Object.entries(e))if(Aa.has(t)&&n.status==="run")return"core+extended";return"core"}function Gn(e,t,n,s,r){if(n.totals.lines>0){let l=typeof Nn.sharing_target_percent=="number"?Nn.sharing_target_percent:65;e.push({checkId:"sharing-percent",dimension:"sharing",curve:"ratio",measuredValue:n.shared.percentLines,referenceValue:l})}let o=s.filter(l=>l.detected&&l.score!==null);if(o.length>0){let l=o.reduce((p,f)=>p+(f.score??0),0)/o.length;e.push({checkId:"harness-optimization-avg",dimension:"harnessWiring",curve:"ratio",measuredValue:l,referenceValue:100})}let i=Dn(e,_n),a=On(i,_n),c=$n(i);return{profile:"meta-harness",total_score:a,score_scope:c,dimensions:i}}import{readFile as Fa}from"node:fs/promises";import Un from"node:path";import{readdir as Ia}from"node:fs/promises";import Ea from"node:path";async function st(e){let t=[".md",".mdc"];function n(o){return t.some(i=>o.endsWith(i))}let s=[],r=[];try{r=await Ia(e,{withFileTypes:!0})}catch{return s}for(let o of r){if(o.isSymbolicLink())continue;let i=Ea.join(e,o.name);o.isDirectory()?s.push(...await st(i)):o.isFile()&&n(i)&&s.push(i)}return s}import{readFile as va,stat as Ta}from"node:fs/promises";import La from"node:path";function jn(e){return e.length===0?0:e.split(`
|
|
150
|
-
`).length}async function Wn(e,t,n,s){let r=La.join(e,t);try{if(!(await Ta(r)).isFile())return null;let i=await va(r,"utf8"),a=jn(i),c={path:t,layer:n,lines:a,bytes:Buffer.byteLength(i,"utf8")};return s!==void 0&&(c.harness=s),c}catch{return null}}var _a=["AGENTS.md","docs/ai/rules.md","docs/ai/ai-system.md","docs/ai/available-skills.md","docs/ai/hooks.md"],Na=[{path:"CLAUDE.md",harness:"claude"},{path:"GEMINI.md",harness:"gemini"},{path:".github/copilot-instructions.md",harness:"copilot"},{path:".agent/README.md",harness:"antigravity"}],Pa=[{dir:"skills",layer:"skills"},{dir:"agents",layer:"agents"},{dir:".cursor/rules",layer:"adapter",harness:"cursor"},{dir:".agent/workflows",layer:"workflows",harness:"antigravity"},{dir:".codex",layer:"adapter",harness:"codex"},{dir:"docs/ai",layer:"shared"}];async function Te(e){let t=[],n=new Map,s=new Set;async function r(o,i,a){let c=o.replaceAll("\\","/");if(s.has(c))return;let l=await Wn(e,c,i,a);if(l===null)return;s.add(c),t.push(l);let p=Un.join(e,c);try{let f=await Fa(p,"utf8");n.set(c,f)}catch{}}for(let o of _a)await r(o,"shared");for(let o of Na)await r(o.path,"adapter",o.harness);for(let{dir:o,layer:i,harness:a}of Pa){let c=Un.join(e,o),l=await st(c);for(let p of l){let f=Un.relative(e,p).replaceAll("\\","/");await r(f,i,a)}}return t.sort((o,i)=>o.path.localeCompare(i.path)),{files:t,contents:n}}import{readFile as Ha}from"node:fs/promises";import To from"node:path";import{fileURLToPath as Ma}from"node:url";function Bn(e){return typeof e=="object"&&e!==null&&"version"in e&&typeof e.version=="string"}async function Vn(){let e=To.resolve(To.dirname(Ma(import.meta.url)),"../package.json"),t=await Ha(e,"utf8"),n=JSON.parse(t);if(!Bn(n))throw new Error("package.json is missing a string version field");return{version:n.version}}var Lo=null;function Fo(){return Lo??=Vn(),Lo}import{extname as ja}from"node:path";import{readdir as Da}from"node:fs/promises";import $o from"node:path";var _o=new Set([".git","node_modules","dist","coverage"]),No=[/^tsconfig(?:\..+)?\.json$/],Po=[/^eslint\.config\.[cm]?[jt]s$/,/^\.eslintrc(?:\..+)?$/,/^\.oxlintrc(?:\..+)?$/,/^biome\.jsonc?$/,/^ruff\.toml$/,/^\.ruff\.toml$/],Ho=[/^\.prettierrc(?:\..+)?$/,/^\.markdownlint(?:rc)?(?:\..+)?$/],Mo=[/^vitest\.config\.[cm]?[jt]s$/,/^jest\.config\.[cm]?[jt]s$/,/^playwright\.config\.[cm]?[jt]s$/,/^cypress\.config\.[cm]?[jt]s$/],Do=[/^package\.json$/,/^pyproject\.toml$/,/^Cargo\.toml$/,/^go\.mod$/],zn=/(scan:self|check:ai-system|check:md|lint:md|check:links|qmd|markdownlint|textlint|remark|cspell|paniolo-scan)/i,Oo=/(correction loop|intelligence layer|diagnostic rule|rules catalog|canonical rules|paired skill|guidance hygiene|adapters stayed thin|json output keys are stable)/i;async function pe(e,t=""){let n=$o.join(e,t),s=[];try{s=await Da(n,{withFileTypes:!0})}catch{return[]}let r=[];for(let o of s){if(o.isSymbolicLink()||_o.has(o.name))continue;let i=$o.join(t,o.name).replaceAll("\\","/");o.isDirectory()?r.push(...await pe(e,i)):o.isFile()&&r.push(i)}return r}var Go=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".json",".jsonc",".yaml",".yml",".toml"]),jo=new Set(["package-lock.json","npm-shrinkwrap.json","yarn.lock","pnpm-lock.yaml","bun.lock","bun.lockb","cargo.lock","poetry.lock","uv.lock","composer.lock","gemfile.lock"]),Wo=512*1024,qn=/(?:\.(?:test|spec)\.[a-z]+$|(?:^|\/)(?:__tests__|__fixtures__|fixtures|test|tests)\/)/i,Uo=/\b(?:claude|gpt|chatgpt|gemini|mistral|codestral|llama|grok|deepseek|command|qwen|o1|o3|o4)[a-z0-9.]*(?:-[a-z0-9.]+)*-latest\b/i,Le=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py"]),Bo=/\b(?:anthropic|openai|mistralai|cohere|generativeai|langchain|chat\.completions|messages\.create|responses\.create|generateobject|generatetext|streamtext|generate_content)\b/i,Vo=/\.choices\s*\[|tool_?calls?\b|function_?call|\.content\s*\[|\bJSON\.parse\s*\(|\bjson\.loads\s*\(/i,zo=/\b(?:zod|valibot|superstruct|typebox|class-validator|ajv|yup|pydantic|basemodel|model_validate|parse_obj|typeadapter|jsonschema|marshmallow)\b|\.safeparse\s*\(|\bz\.object\s*\(/i,rt=/\btools\s*:\s*\[|\btool_choice\s*[:=]|\bfunction_?declarations\s*[:=]|\b(?:defineTool|zodFunction|registerTool)\s*\(|\bserver\.tool\s*\(|\binput_?schema\s*[:=]|^\s*@tool\b/im,qo=/\btool\b|\barguments?\b|\bfunction_?call|\bparameters?\b|\binput_?schema\b/i,Ko=/\btothrow\b|\.rejects\b|\bassert_?raises\b|pytest\.raises|\binvalid\b|\bmalformed\b|\bmissing\b|\bsafeparse\b|\berrors?\b/i;import Yo from"node:path";function Kn(e){let t=Yo.basename(e).toLowerCase();return jo.has(t)?!1:Go.has(Yo.extname(t))}import{readFile as Oa,stat as $a}from"node:fs/promises";import Ga from"node:path";async function Yn(e,t){let n=Ga.join(e,t);try{return(await $a(n)).size>Wo?null:{path:t,content:await Oa(n,"utf8")}}catch{return null}}async function Jn(e){let n=(await pe(e)).filter(o=>Kn(o)),r=(await Promise.all(n.map(o=>Yn(e,o)))).filter(o=>o!==null);return{sourceFiles:r.filter(o=>!qn.test(o.path)).toSorted((o,i)=>o.path.localeCompare(i.path)),testFiles:r.filter(o=>qn.test(o.path)&&Le.has(ja(o.path))).toSorted((o,i)=>o.path.localeCompare(i.path))}}async function Xn(e){let{sourceFiles:t,testFiles:n}=await Jn(e);return{sourceFiles:t,testFiles:n}}import Ba from"node:path";import{readFile as Wa,stat as Ua}from"node:fs/promises";import Jo from"node:path";function Xo(e){return e.length===0?0:e.split(`
|
|
151
|
-
`).length}async function Qo(e,t){try{return(await Ua(Jo.join(e,t))).isFile()}catch{return!1}}async function D(e,t){try{return await Wa(Jo.join(e,t),"utf8")}catch{return null}}function ot(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function fe(e,t){return t.some(n=>n.test(e))}function Zo(e){return/^\.github\/workflows\/.+\.ya?ml$/.test(e)}function ei(e){return e===".github/PULL_REQUEST_TEMPLATE.md"||/^\.github\/PULL_REQUEST_TEMPLATE\/.+\.md$/.test(e)||/^docs\/pull_request_template\.md$/i.test(e)}function it(e,t){return zn.test(`${e}
|
|
152
|
-
${t}`)}function at(e){return zn.test(e.commands.join(`
|
|
153
|
-
`))}function ti(e){return Oo.test(e)}function ni(e){let t=e.toLowerCase();return t.includes("naming")||t.includes("comment")||t.includes("local-context")||t.includes("codebase-map")}function Qn(e){let t=Ba.posix.basename(e);return fe(t,No)?{path:e,kind:"typecheck",capabilities:["typecheck"]}:fe(t,Po)?{path:e,kind:"lint",capabilities:["lint"]}:fe(t,Ho)?{path:e,kind:"format",capabilities:["format"]}:fe(t,Mo)?{path:e,kind:"test",capabilities:["test"]}:fe(t,Do)?{path:e,kind:"manifest",capabilities:["project-manifest"]}:null}function Zn(e){let t=e.toLowerCase();return t==="docs/architecture.md"||t==="docs/overview.md"||t==="docs/meta-harness.md"||t==="docs/ai/codebase-map.md"||t==="docs/ai/ai-system.md"||t.includes("/adr")||t.includes("architecture")||t.includes("codebase-map")||t.includes("design")}function es(e){let t=e.toLowerCase();return t==="docs/ai/codebase-map.md"||t==="docs/ai/ai-system.md"||t==="docs/overview.md"||t.endsWith("/adr/index.md")||t.endsWith("/adrs/index.md")}function Fe(e){if(!ot(e))return{};let t={};for(let[n,s]of Object.entries(e))typeof s=="string"&&(t[n]=s);return t}function ts(e){if(e===null)return{path:null,scripts:{},dependencies:[],devDependencies:[]};try{let t=JSON.parse(e);if(!ot(t))return{path:"package.json",scripts:{},dependencies:[],devDependencies:[]};let n=Fe(t.scripts),s=Object.keys(Fe(t.dependencies)).toSorted(),r=Object.keys(Fe(t.devDependencies)).toSorted();return{path:"package.json",scripts:n,dependencies:s,devDependencies:r}}catch{return{path:"package.json",scripts:{},dependencies:[],devDependencies:[]}}}import{stat as Va}from"node:fs/promises";import za from"node:path";async function B(e,t,n,s,r){let o=za.join(e,t),i=await Va(o),a=await D(e,t),c={path:t,kind:n,layer:s,capabilities:r,bytes:i.size};return a!==null&&(c.lines=Xo(a)),c}function ns(e){let t=[],n=/^\s*-\s*run:\s*(.+)$/,s=/^\s*-\s*run:\s*[>|]/,r=!1;for(let o of e.split(/\r?\n/)){let i=o.match(n);if(i!==null){t.push(i[1]?.trim()??""),r=!1;continue}if(s.test(o)){r=!0;continue}r&&(/^\s{6,}\S/.test(o)?t.push(o.trim()):/^\s*-\s/.test(o)&&(r=!1))}return t.filter(o=>o.length>0)}async function ss(e,t){let n=await D(e,t);return n===null?null:{path:t,commands:ns(n),content:n}}function ct(e){let t=Object.keys(e.packageJson.scripts),n=t.filter(i=>/(^|:)(typecheck|lint|format|check)(:|$)/i.test(i)),s=t.filter(i=>/(^|:)(test|e2e)(:|$)/i.test(i)),r=t.filter(i=>it(i,e.packageJson.scripts[i]??"")),o=e.workflows.filter(at).map(i=>i.path).toSorted();return{surfaces:e.surfaces,enforcement:{scripts:n.toSorted(),configs:e.configs.filter(i=>i.kind==="typecheck"||i.kind==="lint").map(i=>i.path).toSorted(),ciWorkflows:e.workflows.filter(i=>/(typecheck|lint|format|check)/i.test(i.commands.join(`
|
|
154
|
-
`))).map(i=>i.path).toSorted()},validation:{scripts:s.toSorted(),configs:e.configs.filter(i=>i.kind==="test").map(i=>i.path).toSorted(),ciWorkflows:e.workflows.filter(i=>/(npm test|npm run test|vitest|jest|playwright|cypress)/i.test(i.commands.join(`
|
|
155
|
-
`))).map(i=>i.path).toSorted()},memory:{docs:e.memoryDocs.toSorted(),indexes:e.memoryIndexes.toSorted()},localContext:{conventions:e.localContextConventions.toSorted(),nestedAgentsFiles:e.nestedAgentsFiles.toSorted()},correctionLoop:{scripts:r.toSorted(),prTemplates:e.prTemplates.toSorted(),ciWorkflows:o,maintenanceScripts:e.guidanceMaintenanceScripts.toSorted(),prTemplateChecks:e.aiHarnessPrTemplates.toSorted(),guidanceCiWorkflows:o}}}async function rs(e){let t=await pe(e),n=ts(await D(e,"package.json")),s=[],r=[],o=[],i=[],a=[],c=[],l=[],p=[],f=[],m={customChecker:!1,packageScript:!1,lintRules:!1,stopHook:!1,guidance:!1};m.packageScript=Object.entries(n.scripts).some(([d,g])=>/(^|:)(lint:jsdoc|check:jsdoc)(:|$)/i.test(d)||/find-missing-jsdoc|check-jsdoc-files/i.test(g));for(let d of t){let g=Qn(d);if(g!==null){let S={...g},A=await D(e,d);g.kind==="typecheck"&&A!==null&&/"strict"\s*:\s*true/.test(A)&&(S.capabilities=[...g.capabilities,"strict-typecheck"]),g.kind==="lint"&&A!==null&&/jsdoc\/require-(returns|param)/i.test(A)&&(m.lintRules=!0),s.push(S),f.push(await B(e,d,"enforcement","config",S.capabilities))}if(Zo(d)){let S=await ss(e,d);if(S!==null){r.push(S);let A=await B(e,d,"workflow","automation",["ci-workflow"]);f.push(A)}}if(ei(d)){o.push(d);let S=await D(e,d);S!==null&&ti(S)&&i.push(d);let A=await B(e,d,"automation","pull-request",["pr-template"]);f.push(A)}if(d.endsWith(".md")&&Zn(d)&&(a.push(d),es(d)&&c.push(d),f.push(await B(e,d,"memory","docs",["memory"]))),d.endsWith(".md")&&ni(d)&&l.push(d),(d==="scripts/find-missing-jsdoc/analyzeFile.ts"||d==="scripts/find-missing-jsdoc/check-jsdoc-files.bun.ts")&&(m.customChecker=!0),(d==="docs/ai/code-comment-best-practices.md"||d==="skills/code-comment-best-practices/SKILL.md")&&(m.guidance=!0),d.startsWith(".github/hooks/")&&d.endsWith(".json")){let S=await D(e,d);S!==null&&/lint-on-stop|find-missing-jsdoc|jsdoc/i.test(S)&&(m.stopHook=!0)}if(d.endsWith("/AGENTS.md")){p.push(d);let S=await B(e,d,"local-context","nested-entry",["nested-agents-md"]);f.push(S)}}return n.path!==null&&await Qo(e,n.path)&&f.push(await B(e,n.path,"automation","project",["package-scripts"])),{packageJson:n,configs:s.toSorted((d,g)=>d.path.localeCompare(g.path)),workflows:r.toSorted((d,g)=>d.path.localeCompare(g.path)),prTemplates:o,guidanceMaintenanceScripts:Object.entries(n.scripts).filter(([d,g])=>it(d,g)).map(([d])=>d).toSorted(),aiHarnessPrTemplates:i.toSorted(),guidanceCiWorkflows:r.filter(d=>at(d)).map(d=>d.path).toSorted(),memoryDocs:a,memoryIndexes:c.toSorted(),localContextConventions:l.toSorted(),nestedAgentsFiles:p,surfaces:f.toSorted((d,g)=>d.path.localeCompare(g.path)),jsdocEnforcement:m}}import Xa from"node:path";import{readdir as qa}from"node:fs/promises";import Ka from"node:path";async function os(e,t){let n=[];try{n=await qa(Ka.join(e,t),{withFileTypes:!0})}catch{return[]}return n.filter(s=>s.isFile()).map(s=>`${t}/${s.name}`)}import{readFile as Ya,stat as Ja}from"node:fs/promises";import ui from"node:path";var si=[".claude/settings.json",".claude/settings.local.json"],ri=[".env",".env.local",".env.development",".env.development.local",".env.production",".env.production.local",".env.test"],oi=[".gitleaks.toml",".github/gitleaks.toml",".github/secret_scanning.yml",".github/secret_scanning.yaml"],ii=[".pre-commit-config.yaml",".pre-commit-config.yml"],ai=["config/worker-vars.list","config/env-secrets.dev.list","config/env-secrets.staging.list","config/env-secrets.production.list","scripts/env/run-with-env/run-with-env.bun.ts"],ci=/gitleaks|trufflehog|detect-secrets|ggshield/i,li=/(?:\.\/)?(?:[\w.-]+\/)+[\w.-]+\.(?:tsx?|mts|cts|mjs|cjs|js|sh|bash|py)/g;async function F(e,t){try{return await Ya(ui.join(e,t),"utf8")}catch{return null}}async function O(e,t){try{return(await Ja(ui.join(e,t))).isFile()}catch{return!1}}function V(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function lt(e){try{return{ok:!0,value:JSON.parse(e)}}catch{return{ok:!1,value:null}}}function di(e){let{permissions:t}=e;return!V(t)||!Array.isArray(t.allow)?[]:t.allow.filter(n=>typeof n=="string")}function pi(e){let{permissions:t}=e;return!V(t)||typeof t.defaultMode!="string"?null:t.defaultMode}function ut(e){let t=e.match(li)??[];return[...new Set(t.map(n=>n.replace(/^\.\//,"")))]}async function fi(e,t,n){let s=await O(e,n),r=s?await F(e,n):null;return{reference:{source:t,path:n,exists:s},content:r}}async function is(e,t){for(let n of await os(e,".claude/hooks")){let s=await F(e,n);s!==null&&t.push({source:n,path:n,isStop:/stop/i.test(Xa.posix.basename(n)),content:s})}}async function as(e){for(let t of ai)if(await O(e,t))return!0;return!1}function cs(e){let t=e.hooks;if(t===void 0)return{hooks:[],malformed:!1};if(!V(t))return{hooks:[],malformed:!0};let n=[],s=!1;for(let[r,o]of Object.entries(t)){if(!Array.isArray(o)){s=!0;continue}for(let i of o){if(!V(i)||!Array.isArray(i.hooks)){s=!0;continue}for(let a of i.hooks){if(!V(a)||typeof a.command!="string"){s=!0;continue}n.push({event:r,command:a.command})}}}return{hooks:n,malformed:s}}async function ls(e,t){let n=await F(e,t);if(n===null)return null;let{ok:s,value:r}=lt(n);if(!s||!V(r))return{path:t,valid:!1,allow:[],defaultMode:null,hooks:[],hooksMalformed:!1};let{hooks:o,malformed:i}=cs(r);return{path:t,valid:!0,allow:di(r),defaultMode:pi(r),hooks:o,hooksMalformed:i}}async function us(e){let t=".codex/hooks.json",n=await F(e,t);if(n===null)return null;let{ok:s,value:r}=lt(n);if(!s)return{path:t,valid:!1,referencedScripts:[]};let o=[];for(let i of ut(JSON.stringify(r))){let a=await O(e,i);o.push({source:t,path:i,exists:a})}return{path:t,valid:!0,referencedScripts:o}}async function ds(e){let t=[];for(let n of ri)await O(e,n)&&t.push(n);return t}async function ps(e,t){let n=[],s=[],r=t.flatMap(o=>o.hooks.map(i=>({surface:o,hook:i})));for(let{surface:o,hook:i}of r){let a=`${o.path} (${i.event} hook)`,c=[i.command];for(let l of ut(i.command)){let{reference:p,content:f}=await fi(e,a,l);s.push(p),f!==null&&c.push(f)}n.push({source:a,path:null,isStop:i.event==="Stop",content:c.join(`
|
|
156
|
-
`)})}return{hookScripts:n,referencedClaudeScripts:s}}async function fs(e){let t=[];for(let n of oi)await O(e,n)&&t.push(n);for(let n of ii){let s=await F(e,n);s!==null&&ci.test(s)&&t.push(n)}return t}async function _e(e){let t=[];for(let l of si){let p=await ls(e,l);p!==null&&t.push(p)}let{hookScripts:n,referencedClaudeScripts:s}=await ps(e,t);await is(e,n);let[r,o,i,a,c]=await Promise.all([us(e),F(e,".gitignore"),ds(e),fs(e),as(e)]);return{claudeSettings:t,referencedClaudeScripts:s,hookScripts:n,codexHooks:r,gitignore:o,envFilesPresent:i,secretScanningFiles:a,usesKeyringSecrets:c}}import{readFile as Qa,stat as Za}from"node:fs/promises";import mi from"node:path";async function Z(e){let t=mi.join(e,".github/hooks"),n=!1;try{n=(await Za(t)).isDirectory()}catch{n=!1}let s=mi.join(e,".vscode/settings.json"),r=null,o=null;try{let i=await Qa(s,"utf8");o=i,r=Ce(i)}catch{r=null,o=null}return{settings:r,settingsRaw:o,hooksDirExists:n}}function Ne(e,t,n,s){return{ruleId:e,severity:"warn",message:`${t} has ${String(n)} lines; keep root adapters thin (max ${String(W)}).`,file:t,line:null,harnesses:[s],hint:"Move detailed guidance to docs/ai/ and skills/; keep the adapter as a pointer."}}import{extname as gi}from"node:path";function ms(e){let t=[],n=e.split(`
|
|
157
|
-
`);for(let s=0;s<n.length;s+=1){let r=Uo.exec(n[s]??"");r!==null&&t.push({line:s+1,alias:r[0]})}return t}function gs(e){if(!Bo.test(e)||zo.test(e))return null;let t=e.split(`
|
|
158
|
-
`);for(let n=0;n<t.length;n+=1)if(Vo.test(t[n]??""))return n+1;return null}var Pe={findings:[],records:[]},ec={id:"model-interface-pinned",title:"Model interface pinned",severity:"warn",category:"reliability",dimension:"guardrails",harnesses:[],check(e){let t=e.boundary?.sourceFiles;if(t===void 0)return Pe;let n=[];for(let s of t)for(let{line:r,alias:o}of ms(s.content))n.push({ruleId:"model-interface-pinned",severity:"warn",message:`${s.path} references the floating model alias "${o}"; the model behind a "latest" tag can change without notice.`,file:s.path,line:r,harnesses:[],hint:"Pin a dated/versioned model snapshot (e.g. a -YYYYMMDD or explicit-version id) so model upgrades are a deliberate, reviewable change."});return{findings:n,records:[]}}},tc={id:"llm-output-schema-validated",title:"LLM output schema-validated",severity:"warn",category:"reliability",dimension:"guardrails",harnesses:[],check(e){let t=e.boundary?.sourceFiles;if(t===void 0)return Pe;let n=[];for(let s of t){if(!Le.has(gi(s.path)))continue;let r=gs(s.content);r!==null&&n.push({ruleId:"llm-output-schema-validated",severity:"warn",message:`${s.path} consumes LLM/tool output (line ${String(r)}) without a schema validator; a shape change in the model response surfaces as a downstream type error.`,file:s.path,line:r,harnesses:[],hint:"Validate the parsed response against a Zod/Pydantic/JSON-Schema schema at the boundary before reading its fields."})}return{findings:n,records:[]}}},nc={id:"tool-contract-tests-present",title:"Tool contract tests present",severity:"info",category:"reliability",dimension:"guardrails",harnesses:[],check(e){let{boundary:t}=e;if(t===void 0)return Pe;let n=t.sourceFiles.find(r=>Le.has(gi(r.path))&&rt.test(r.content));return n===void 0||t.testFiles.some(r=>qo.test(r.content)&&Ko.test(r.content))?Pe:{findings:[{ruleId:"tool-contract-tests-present",severity:"info",message:`${n.path} declares model-callable tools, but no test exercises tool-call argument validation or error responses \u2014 only happy-path behavior is covered.`,file:n.path,line:null,harnesses:[],hint:"Add tests that feed malformed or missing tool-call arguments and assert the error path, per declared tool."}],records:[]}}},hi=[ec,tc,nc];function hs(e){let t=[];for(let n of Ue){if(!E(e,n))continue;let s=h(e,n);s===null||eo(s)||t.push({ruleId:"adapter-points-to-shared",severity:"warn",message:`${n} should reference AGENTS.md and docs/ai/rules.md.`,file:n,line:null,harnesses:[],hint:"Keep adapters thin; point at shared layers instead of duplicating rules."})}return{findings:t,records:[]}}function ys(e){let t=[];for(let n of ue(e,"agents/")){if(!n.endsWith(".agent.md"))continue;let s=h(e,n);if(s===null)continue;let r=Be(s);if(r===null){t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing YAML frontmatter.`,file:n,line:null,harnesses:[]});continue}ce(r,"name")||t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing a name field in frontmatter.`,file:n,line:null,harnesses:[]}),ce(r,"description")||t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing a description field in frontmatter.`,file:n,line:null,harnesses:[]})}return{findings:t,records:[]}}function Ss(e){if(!N(e)||!E(e,"AGENTS.md"))return{findings:[],records:[]};let t=h(e,"AGENTS.md");return t!==null&&Ve(t)?{findings:[],records:[]}:{findings:[{ruleId:"agents-md-mentions-skills",severity:"info",message:"AGENTS.md should point at docs/ai/available-skills.md or the qmd search workflow.",file:"AGENTS.md",line:null,harnesses:[],hint:"Document how agents discover skills (index doc or npm run qmd -- search)."}],records:[]}}function ks(e){if(!e.harnesses.includes("claude")||!E(e,"CLAUDE.md"))return{findings:[],records:[]};let t=h(e,"CLAUDE.md");return t!==null&&ze(t)?{findings:[],records:[]}:{findings:[{ruleId:"claude-agent-routing",severity:"info",message:"CLAUDE.md should include an Agent Routing table pointing at agents/*.agent.md.",file:"CLAUDE.md",line:null,harnesses:["claude"],hint:"Add a markdown table mapping task types to shared agents/*.agent.md files."}],records:[]}}var yi=/!?\[([^\]]*)\]\(([^)]+)\)/g;function ee(e){let t=[],n=yi.exec(e);for(;n!==null;){let[s]=n;s.startsWith("!")||t.push({label:n[1]??"",href:(n[2]??"").trim()}),n=yi.exec(e)}return t}var sc=new Set(["url","path","href","link","..."]);function He(e){return e.length===0||sc.has(e.toLowerCase())||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("mailto:")||e.startsWith("tel:")?!0:(e.split("#")[0]??"").length===0}function xs(e){let t=e.replaceAll("\\","/").split("/"),n=[];for(let s of t)if(!(s===""||s===".")){if(s===".."){n.pop();continue}n.push(s)}return n.join("/")}function Me(e,t){let n=(t.split("#")[0]??"").trim();if(n.length===0)return null;let s=n;try{s=decodeURIComponent(n)}catch{s=n}if(s.startsWith("/"))return s.slice(1).replaceAll("\\","/");let r=e.includes("/")?e.slice(0,e.lastIndexOf("/")):"",o=r.length===0?s:`${r}/${s}`;return xs(o)}function ws(e){return!e.endsWith(".md")&&!e.endsWith(".mdc")?!1:e.startsWith("docs/")||e.includes("/docs/")}function Rs(e,t){for(let n of ee(t)){if(He(n.href))continue;let s=Me(e,n.href);if(s!==null&&ws(s))return!0}return!1}var rc=50;function bs(e){let t=[];for(let n of e.files){if(!n.path.startsWith("skills/")||!n.path.endsWith("SKILL.md")||(n.lines??0)<=rc)continue;let s=h(e,n.path);s===null||Rs(n.path,s)||t.push({ruleId:"skill-doc-deep-links",severity:"info",message:`${n.path} does not deep-link into a durable doc under docs/.`,file:n.path,line:null,harnesses:[],hint:"Pair the skill with a docs/ reference and link it (for example a **Details:** link to a docs/ page) instead of inlining all detail."})}return{findings:t,records:[]}}function Cs(e){let t=[];for(let n of ue(e,"skills/")){if(!n.endsWith("/SKILL.md")&&!n.endsWith("SKILL.md"))continue;let s=h(e,n);if(s===null)continue;let r=Be(s);if(r===null){t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing YAML frontmatter.`,file:n,line:null,harnesses:[]});continue}ce(r,"name")||t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing a name field in frontmatter.`,file:n,line:null,harnesses:[]}),ce(r,"description")||t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing a description field in frontmatter.`,file:n,line:null,harnesses:[]})}return{findings:t,records:[]}}function As(e){let t=[];for(let n of ue(e,"skills/")){if(!n.endsWith("SKILL.md"))continue;let s=U(e,n);s!==null&&s>bt&&t.push({ruleId:"skill-line-count",severity:"warn",message:`${n} has ${String(s)} lines; keep skills under ${String(bt)}.`,file:n,line:null,harnesses:[],hint:"Move detail to docs/; keep SKILL.md as a pointer."})}return{findings:t,records:[]}}var Si="docs/ai/available-skills.md";function Is(e){return N(e)?E(e,Si)?{findings:[],records:[]}:{findings:[{ruleId:"skills-index",severity:"info",message:`${Si} is missing; add a skill slug index when using skills/.`,file:null,line:null,harnesses:[],hint:"List each skills/<slug>/ folder so agents can pick a minimal skill set."}],records:[]}:{findings:[],records:[]}}var oc=["AGENTS.md","CLAUDE.md","GEMINI.md",".github/copilot-instructions.md",".agent/README.md"],ki=["IMPORTANT","CRITICAL","MANDATORY","REQUIRED","MUST NOT","MUST","NEVER","ALWAYS","SHALL","DO NOT"],xi=.03,wi=40,Ri=[{pattern:/\byou are an? (?:expert|senior|world[- ]class|10x|highly skilled|seasoned|professional)\b/i,label:"identity framing (\u201Cyou are a/an \u2026\u201D)"},{pattern:/\bact as an?\b/i,label:"roleplay framing (\u201Cact as a \u2026\u201D)"},{pattern:/\bas an ai (?:language model|assistant)\b/i,label:"AI self-reference"},{pattern:/\bworld[- ]class\b/i,label:"superlative filler (\u201Cworld-class\u201D)"}];function dt(e){return e.replaceAll(/```[\s\S]*?```/g," ")}function bi(e){let t=e.match(/\S+/g);return t===null?0:t.length}function me(e){return oc.filter(t=>h(e,t)!==null)}function Es(e){let t=0;for(let n of ki){let s=e.match(new RegExp(`\\b${n}\\b`,"g"));s!==null&&(t+=s.length)}return t}function vs(e){let t=[];for(let n of me(e)){let s=h(e,n);if(s===null)continue;let r=dt(s),o=bi(r);if(o<wi)continue;let i=Es(r),a=i/o;if(a<=xi)continue;let c=(a*100).toFixed(1);t.push({ruleId:"emphasis-keyword-density",severity:"info",message:`${n} uses ${String(i)} all-caps emphasis keyword(s) across ${String(o)} words (${c}%); emphasis loses force when overused.`,file:n,line:null,harnesses:[],hint:"Reserve IMPORTANT/MUST/NEVER for the few rules that truly need them; rewrite the rest as plain, action-oriented instructions."})}return{findings:t,records:[]}}function Ts(e){let t=[];for(let n of me(e)){let s=h(e,n);if(s===null)continue;let r=dt(s),o=Ri.filter(({pattern:i})=>i.test(r)).map(({label:i})=>i);o.length!==0&&t.push({ruleId:"identity-language-absent",severity:"info",message:`${n} contains identity/roleplay filler: ${o.join(", ")}.`,file:n,line:null,harnesses:[],hint:"Drop identity framing; state what to do, not who to be. Action-oriented rules outperform persona prompts."})}return{findings:t,records:[]}}var Ci=[{id:"emphasis-keyword-density",title:"Emphasis-keyword density",severity:"info",category:"instruction-quality",dimension:"maintainability",harnesses:[],check:vs},{id:"identity-language-absent",title:"No identity-language filler",severity:"info",category:"instruction-quality",dimension:"maintainability",harnesses:[],check:Ts}];var Ai=/\bask\s+(?:the\s+)?(?:user|human|maintainer)\b|\bask\s+for\s+clarif|\brequest\s+clarification|\bseek\s+clarification|\bclarifying\s+questions?|\bwhen\s+(?:in\s+doubt|unsure|uncertain)\b|\bstop\s+and\s+ask\b|\bask\s+before\s+(?:assum|guess|proceed)|\bescalat(?:e|ion)\b|\b(?:ambiguous|unclear|contradictory|conflicting|incomplete)\b[^.\n]{0,40}\b(?:ask|clarif|escalat|confirm)/i,Ii=/\bmax[_\s-]?(?:iterations?|steps?|turns?|calls?|requests?|attempts?|retries|tokens?|cost|budget)\b|\bmax_calls_per_minute\b|\bcurrency_limits?\b|\brate[_\s-]?limit|\bbudget[_\s-]?(?:cap|limit)|\biteration[_\s-]?(?:cap|limit)|\bcost[_\s-]?(?:cap|limit)/i,Ei=/\blanggraph\b|\bcrewai\b|\bautogen\b|\bAgentExecutor\b|\bcreateReactAgent\b|@modelcontextprotocol|\bmcp\.server\b|\bserver\.tool\s*\(/i;function te(e){return[...e.fileContents.values()].join(`
|
|
159
|
-
`)}function De(e){return(e.boundary?.sourceFiles??[]).map(t=>t.content).join(`
|
|
160
|
-
`)}var vi=/\bmcpservers\b|\.mcp\.json\b|\bmcp__|modelcontextprotocol|\bmcp\s+servers?\b/i,Ti=/\ballow[\s_-]?list\b|\bmcpservers\b|allowed[_\s-]?tools|permitted[_\s-]?tools|"allow"\s*:|pinned\s+(?:tool|server|mcp)/i,Li=/\bmem0\b|memory\.(?:add|write|store|save|upsert)\b|vector[\s_-]?(?:store|db|database)|\bupsert\s*\(|\bembeddings?\b|\bpinecone\b|\bweaviate\b|\bchroma(?:db)?\b|\bqdrant\b|persistent\s+memory/i,Fi=/\bprovenance\b|\bquarantin|\buntrusted\b|\btaint(?:ed)?\b|trust[\s_-]?(?:level|tag|boundary)|source[\s_-]?tag|re-?validat/i,_i=/\bfetch\s*\(|\bwebfetch\b|\baxios\b|requests?\.get\b|\burllib\b|\bhttpx\b|\bscrap(?:e|ing)\b|\bcrawl|retriev(?:e|al)|web[\s_-]?search/i,Ni=/\bexec(?:Sync)?\s*\(|child_process|\bspawn\s*\(|\bsubprocess\b|os\.system|writeFileSync|\bfs\.write|\bunlink\s*\(|\brm\s+-rf\b/i,Pi=/saniti[sz]|\bvalidat|\ballow[\s_-]?list\b|\bescape\b|\bconfirm|\bapproval\b|\bguard(?:rail)?\b/i,Hi=/force[\s_-]?push|push\s+--force|\brm\s+-rf\b|delete\s+from\b|\.delete\s*\(|\bdestroy\s*\(|\bstripe\b|\bpayment|\bcharge\s*\(|wire\s+transfer|send[_\s-]?email|\bsendmail\b|\bdeploy\b|drop\s+table/i,Mi=/human[\s_-]?in[\s_-]?the[\s_-]?loop|\bconfirm(?:ation)?\b|\bapproval\b|\bescalat|requires?\s+(?:approval|confirmation)|dry[\s_-]?run|are\s+you\s+sure/i;function Ls(e){return e.files.some(n=>n.layer==="agents")?!0:(e.boundary?.sourceFiles??[]).some(n=>rt.test(n.content)||Ei.test(n.content))}function pt(e,t,n,s){return{findings:[{ruleId:e,severity:t,message:n,file:null,line:null,harnesses:[],hint:s}],records:[]}}var $={findings:[],records:[]},ic={id:"escalation-protocol-discoverability",title:"Escalation protocol discoverable",severity:"info",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=me(e);return t.length===0||Ai.test(te(e))?$:{findings:[{ruleId:"escalation-protocol-discoverability",severity:"info",message:"No discoverable escalation protocol in guidance: nothing documents when or how the agent should ask for clarification on missing, ambiguous, or contradictory specs.",file:t[0]??null,line:null,harnesses:[],hint:"Document an 'ask before guessing' protocol in AGENTS.md or the rules doc \u2014 the epistemic counterpart to action confirmation (HiL-Bench's 53-82pp finding)."}],records:[]}}},ac={id:"agent-resource-budget-caps",title:"Agent resource budget caps",severity:"info",category:"security",dimension:"guardrails",harnesses:[],check(e){if(!Ls(e))return $;let t=(e.boundary?.sourceFiles??[]).map(n=>n.content).join(`
|
|
161
|
-
`);return Ii.test(`${te(e)}
|
|
162
|
-
${t}`)?$:{findings:[{ruleId:"agent-resource-budget-caps",severity:"info",message:"An agent/tool surface is present but no resource caps are declared (max iterations, cost, or rate limit); an unbounded loop is a resource-drain (R7) risk.",file:null,line:null,harnesses:[],hint:"Declare max-iteration, max-cost, or rate-limit caps, mirroring OAP's max_calls_per_minute / currency_limits."}],records:[]}}},cc={id:"tool-allowlist-inventory",title:"Tool allowlist inventory",severity:"info",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=`${te(e)}
|
|
163
|
-
${De(e)}`;return!vi.test(t)||Ti.test(t)?$:pt("tool-allowlist-inventory","info","Repo references MCP/tool servers but declares no explicit, pinned tool allowlist; arbitrary tool discovery widens the attack surface (R1/R3).","Declare an explicit allowlist of tools/MCP servers with pinned versions instead of allowing arbitrary discovery.")}},lc={id:"untrusted-input-action-boundary",title:"Untrusted input / action boundary",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=De(e);if(!(_i.test(t)&&Ni.test(t)))return $;let s=`${te(e)}
|
|
164
|
-
${t}`;return Pi.test(s)?$:pt("untrusted-input-action-boundary","warn","Source ingests external/untrusted content and takes actions (exec, file write) with no sanitization, validation, or confirmation in evidence (R2/R3 unconstrained data flow).","Sanitize, allow-list, or confirm untrusted content before it reaches shell exec, file writes, or tool dispatch.")}},uc={id:"memory-write-provenance",title:"Memory write provenance",severity:"info",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=`${te(e)}
|
|
165
|
-
${De(e)}`;return!Li.test(t)||Fi.test(t)?$:pt("memory-write-provenance","info","Repo writes to persistent agent memory but shows no provenance/trust tagging or re-validation; memory writes from untrusted sources can later be read as trusted (R6).","Tag or quarantine memory writes derived from untrusted sources and re-validate them before trusted reads.")}},dc={id:"high-impact-action-confirmation",title:"High-impact action confirmation",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=De(e);if(!Hi.test(t))return $;let n=`${te(e)}
|
|
166
|
-
${t}`;return Mi.test(n)?$:pt("high-impact-action-confirmation","warn","Source performs high-impact actions (deletion, payment, force-push, deploy, external send) with no human-in-the-loop confirmation or escalation in evidence (R6/R7).","Gate high-impact actions behind an explicit confirmation/escalation step, not just allow/deny (OWASP LLM06).")}},Di=[ic,ac,cc,lc,uc,dc];var pc=/\b(?:curl|wget|ncat|telnet|scp)\b|\bnc\s|Invoke-WebRequest|\bfetch\s*\(|\baxios\b|http\.request|urllib|requests\.(?:get|post|put|patch)/i,fc=/localhost|127\.0\.0\.1|0\.0\.0\.0|::1/i;function Fs(e){let t=[];for(let n of e.content.split(/\r?\n/)){let s=n.trim();pc.test(s)&&!fc.test(s)&&t.push(s)}return t}var mc=new Set(["Bash","Write","Edit","MultiEdit","NotebookEdit"]);function _s(e){let t=e.trim();if(t==="")return!1;if(t==="*")return!0;if(t.startsWith("mcp__"))return t.includes("*");let n=t.match(/^([A-Za-z_][\w-]*)(?:\((.*)\))?$/);if(n===null)return!1;let[,s="",r]=n;if(!mc.has(s))return!1;if(r===void 0)return!0;let o=r.trim();return o===""||o==="*"||o===":*"}var gc=/^[0-9a-f]{40}$/i;function Ns(e){let t=new Set,n=/^\s*-?\s*uses:\s*['"]?([^'"\s#]+)['"]?/gm;for(let s of e.matchAll(n)){let[,r]=s;if(r===void 0||r.startsWith("./")||r.startsWith("docker://"))continue;let o=r.includes("@")?r.slice(r.lastIndexOf("@")+1):"";gc.test(o)||t.add(r)}return[...t]}var G={findings:[],records:[]},hc=new Set(["bypassPermissions","acceptEdits"]),yc="stop_hook_active";function ne(e){return e.security??null}var Sc={id:"no-dangerous-auto-approve",title:"No dangerous auto-approve permissions",severity:"error",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ne(e);if(t===null)return G;let n=[];for(let s of t.claudeSettings){s.defaultMode!==null&&hc.has(s.defaultMode)&&n.push({ruleId:"no-dangerous-auto-approve",severity:"error",message:`${s.path} sets permissions.defaultMode "${s.defaultMode}", auto-approving actions without prompting.`,file:s.path,line:null,harnesses:["claude"],hint:'Use "default" or "plan" mode and allow-list specific commands instead of bypassing prompts.'});for(let r of s.allow.filter(_s))n.push({ruleId:"no-dangerous-auto-approve",severity:"error",message:`${s.path} auto-approves "${r}", a blanket grant over a dangerous capability.`,file:s.path,line:null,harnesses:["claude"],hint:"Scope allow-list entries to specific commands, e.g. Bash(npm run test:*) instead of Bash(*)."})}return{findings:n,records:[]}}},kc={id:"hook-no-network-exfil",title:"Hooks do not exfiltrate over the network",severity:"error",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ne(e);if(t===null)return G;let n=[];for(let s of t.hookScripts){let[r]=Fs(s);r!==void 0&&n.push({ruleId:"hook-no-network-exfil",severity:"error",message:`${s.source} makes a network call (\`${r.slice(0,80)}\`); hooks run automatically and can exfiltrate repo data.`,file:s.path,line:null,harnesses:[],hint:"Remove the network call or restrict it to localhost; move outbound calls into explicit, reviewable steps."})}return{findings:n,records:[]}}},xc={id:"hook-stop-circuit-breaker",title:"Stop hooks guard against infinite loops",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ne(e);if(t===null)return G;let n=[];for(let s of t.hookScripts)!s.isStop||s.content.includes(yc)||n.push({ruleId:"hook-stop-circuit-breaker",severity:"warn",message:`${s.source} is a Stop hook that never checks stop_hook_active; a blocking Stop hook can loop the agent indefinitely.`,file:s.path,line:null,harnesses:[],hint:"Read stop_hook_active from the hook input and exit without blocking when it is true."});return{findings:n,records:[]}}},wc={id:"env-files-gitignored",title:"Env files are gitignored",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ne(e);if(t===null)return G;let s=t.gitignore!==null&&/^\s*!?[*.]*\.env(?:[.*]|\b|\/)?/m.test(t.gitignore)?[]:t.envFilesPresent;if(s.length===0)return G;let r=t.usesKeyringSecrets?"This repo uses keyring-managed secrets; delete the committed .env file rather than relying on it.":"Gitignore `.env`/`.env.*`, or move secrets to an OS keyring (the run-with-env pattern) so they never touch disk.";return{findings:[{ruleId:"env-files-gitignored",severity:"warn",message:`${s.join(", ")} present but not gitignored; secrets risk being committed.`,file:s[0]??null,line:null,harnesses:[],hint:r}],records:[]}}};function Rc(e){return e.some(t=>/gitleaks|trufflehog|detect-secrets|ggshield/i.test(t.content))}var bc={id:"secret-scanning-configured",title:"Secret scanning is configured",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ne(e);if(t===null)return G;let n=e.intelligenceLayer?.workflows??[];return t.secretScanningFiles.length>0||Rc(n)?G:{findings:[{ruleId:"secret-scanning-configured",severity:"warn",message:"No secret-scanning configuration found (gitleaks, trufflehog, detect-secrets, or a pre-commit secret hook).",file:null,line:null,harnesses:[],hint:"Add a gitleaks/trufflehog CI step or a detect-secrets pre-commit hook so committed credentials are caught."}],records:[]}}},Cc={id:"no-pull-request-target",title:"No risky pull_request_target workflows",severity:"error",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=e.intelligenceLayer?.workflows??[],n=[];for(let s of t)/\bpull_request_target\b/.test(s.content)&&n.push({ruleId:"no-pull-request-target",severity:"error",message:`${s.path} triggers on pull_request_target, which runs with repo secrets against untrusted PR code.`,file:s.path,line:null,harnesses:[],hint:"Prefer pull_request; if pull_request_target is required, never check out or execute PR head code with secrets in scope."});return{findings:n,records:[]}}},Ac={id:"actions-sha-pinned",title:"GitHub Actions pinned to commit SHAs",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=e.intelligenceLayer?.workflows??[],n=[];for(let s of t){let r=Ns(s.content);r.length!==0&&n.push({ruleId:"actions-sha-pinned",severity:"warn",message:`${s.path} uses actions pinned to mutable refs: ${r.join(", ")}.`,file:s.path,line:null,harnesses:[],hint:"Pin each action to a full 40-character commit SHA (e.g. actions/checkout@<sha>) to prevent tag-hijack supply-chain attacks."})}return{findings:n,records:[]}}},Ic={id:"claude-hooks-valid",title:"Claude hooks config is valid",severity:"error",category:"hooks",dimension:"guardrails",harnesses:["claude"],check(e){let t=ne(e);if(t===null)return G;let n=[];for(let s of t.claudeSettings){if(!s.valid){n.push({ruleId:"claude-hooks-valid",severity:"error",message:`${s.path} is not valid JSON.`,file:s.path,line:null,harnesses:["claude"],hint:"Fix the JSON syntax; an unparseable settings file disables every configured hook silently."});continue}s.hooksMalformed&&n.push({ruleId:"claude-hooks-valid",severity:"error",message:`${s.path} has a malformed hooks block; entries must be { matcher?, hooks: [{ type, command }] }.`,file:s.path,line:null,harnesses:["claude"],hint:"Match the documented hooks schema so the configured commands actually run."})}for(let s of t.referencedClaudeScripts.filter(r=>!r.exists))n.push({ruleId:"claude-hooks-valid",severity:"error",message:`${s.source} references missing script ${s.path}.`,file:s.path,line:null,harnesses:["claude"],hint:"Create the script or fix the path; a missing hook command fails open and skips the check."});return{findings:n,records:[]}}},Ec={id:"codex-hooks-valid",title:"Codex hooks config is valid",severity:"error",category:"hooks",dimension:"guardrails",harnesses:["codex"],check(e){let t=ne(e);if(t===null||t.codexHooks===null)return G;let n=t.codexHooks,s=[];n.valid||s.push({ruleId:"codex-hooks-valid",severity:"error",message:`${n.path} is not valid JSON.`,file:n.path,line:null,harnesses:["codex"],hint:"Fix the JSON syntax so the configured codex hooks load."});for(let r of n.referencedScripts.filter(o=>!o.exists))s.push({ruleId:"codex-hooks-valid",severity:"error",message:`${n.path} references missing script ${r.path}.`,file:r.path,line:null,harnesses:["codex"],hint:"Create the script or fix the path so the hook command runs."});return{findings:s,records:[]}}},Oi=[Sc,kc,xc,wc,bc,Cc,Ac,Ic,Ec];var vc={id:"shared-agents-md",title:"Shared AGENTS.md entry point",severity:"warn",category:"structure",dimension:"layering",harnesses:[],check(e){return E(e,"AGENTS.md")?{findings:[],records:[]}:{findings:[{ruleId:"shared-agents-md",severity:"warn",message:"AGENTS.md is missing.",file:null,line:null,harnesses:[],hint:"Add AGENTS.md as the repo-wide AI entry point with workflow, safety, and pointers to canonical docs."}],records:[]}}},Tc={id:"shared-rules-doc",title:"Canonical rules doc",severity:"warn",category:"structure",dimension:"layering",harnesses:[],check(e){return E(e,"docs/ai/rules.md")?{findings:[],records:[]}:{findings:[{ruleId:"shared-rules-doc",severity:"warn",message:"docs/ai/rules.md is missing.",file:null,line:null,harnesses:[],hint:"Add docs/ai/rules.md as the canonical coding-rules reference."}],records:[]}}},Lc={id:"adapter-thin-claude",title:"Thin CLAUDE.md adapter",severity:"warn",category:"adapter",dimension:"layering",harnesses:["claude"],check(e){let t=U(e,"CLAUDE.md");return t===null||t<=W?{findings:[],records:[]}:{findings:[Ne("adapter-thin-claude","CLAUDE.md",t,"claude")],records:[]}}},Fc={id:"adapter-thin-gemini",title:"Thin GEMINI.md adapter",severity:"warn",category:"adapter",dimension:"layering",harnesses:["gemini"],check(e){let t=U(e,"GEMINI.md");return t===null||t<=W?{findings:[],records:[]}:{findings:[Ne("adapter-thin-gemini","GEMINI.md",t,"gemini")],records:[]}}},_c={id:"adapter-thin-copilot",title:"Thin Copilot instructions",severity:"warn",category:"adapter",dimension:"layering",harnesses:["copilot"],check(e){let t=".github/copilot-instructions.md",n=U(e,t);return n===null||n<=W?{findings:[],records:[]}:{findings:[Ne("adapter-thin-copilot",t,n,"copilot")],records:[]}}},Nc={id:"adapter-points-to-shared",title:"Adapters reference shared layers",severity:"warn",category:"adapter",dimension:"layering",harnesses:[],check:hs},Pc={id:"skill-frontmatter",title:"Skill frontmatter",severity:"error",category:"skills",dimension:"maintainability",harnesses:[],check:Cs},Hc={id:"skill-line-count",title:"Skill line budget",severity:"warn",category:"skills",dimension:"maintainability",harnesses:[],check:As},Mc={id:"agent-frontmatter",title:"Agent frontmatter",severity:"error",category:"agents",dimension:"maintainability",harnesses:[],check:ys},Dc={id:"skills-index",title:"Skill slug index",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:Is},Oc={id:"claude-agent-routing",title:"Claude agent routing table",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:["claude"],check:ks},$c={id:"agents-md-mentions-skills",title:"AGENTS.md skill discovery",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:Ss},Gc={id:"skill-doc-deep-links",title:"Skills deep-link into docs",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:bs},$i=[vc,Tc,Lc,Fc,_c,Nc,Pc,Hc,Mc,Dc,Oc,$c,Gc,...Ci,...Oi,...hi,...Di];function Ps(e){let t=e.contextBudget;if(t===void 0)return{findings:[],records:[]};let n=[],s=[];for(let r of t.harnesses)if(r.detected)for(let o of r.files)s.push({checkId:"adapter-context-budget",dimension:"maintainability",curve:"asymptoticDecay",measuredValue:o.lines,referenceValue:t.maxRecommendedFileLines}),!(o.lines<=t.maxRecommendedFileLines)&&n.push({ruleId:"adapter-context-budget",severity:"info",message:`${o.path} contributes ${String(o.lines)} always-loaded lines for ${r.harness}; recommended maximum per file is ${String(t.maxRecommendedFileLines)}.`,file:o.path,line:null,harnesses:[r.harness],hint:"Split detailed guidance into linked docs and keep always-loaded instruction files compact."});return{findings:n,records:s}}function Hs(e){let t=e.contextBudget;if(t===void 0)return{findings:[],records:[]};let n=[],s=[];for(let r of t.harnesses)r.detected&&(s.push({checkId:"always-loaded-budget",dimension:"maintainability",curve:"asymptoticDecay",measuredValue:r.totalLines,referenceValue:r.maxRecommendedLines}),r.status!=="ok"&&n.push({ruleId:"always-loaded-budget",severity:"info",message:`${r.harness} always-loaded context is ${String(r.totalLines)} lines; recommended maximum is ${String(r.maxRecommendedLines)}.`,file:null,line:null,harnesses:[r.harness],hint:"Keep root adapters as short indexes and move deep guidance into linked docs, skills, agents, or workflows."}));return{findings:n,records:s}}async function Ms(e){return e.files.some(n=>n.path.startsWith("agents/"))?await le(e.repoRoot,".github/agents")?{findings:[{ruleId:"no-duplicate-agent-trees",severity:"error",message:".github/agents/ duplicates root agents/; use agents/ only.",file:".github/agents",line:null,harnesses:[],hint:"Remove .github/agents/ and keep canonical agents/ at the repo root."}],records:[]}:{findings:[],records:[]}:{findings:[],records:[]}}async function Ds(e){if(!e.files.some(r=>r.path.startsWith("skills/")))return{findings:[],records:[]};let n=[],s=[".github/skills",".cursor/skills"];for(let r of s)await le(e.repoRoot,r)&&n.push({ruleId:"no-duplicate-skill-trees",severity:"error",message:`${r}/ duplicates root skills/; use skills/ only.`,file:r,line:null,harnesses:[],hint:"Remove the shadow tree and keep canonical skills/ at the repo root."});return{findings:n,records:[]}}var jc=["docs/","skills/","agents/",".cursor/",".github/",".codex/",".agent/",".claude/"],Wc=new Set(["AGENTS.md","CLAUDE.md","GEMINI.md","README.md",".github/copilot-instructions.md"]);function Gi(e){let t=e.replaceAll("\\","/").replace(/\/+$/,"");return Wc.has(t)?!0:jc.some(n=>t===n.slice(0,-1)||t.startsWith(n))}function Oe(e,t){let n=e.split(`
|
|
167
|
-
`);for(let s=0;s<n.length;s+=1){let r=n[s];if(r!==void 0&&r.includes(t))return s+1}return null}var Uc=["",".md","/README.md","/index.md"];async function ji(e,t){for(let n of Uc){let s=`${t}${n}`.replaceAll("\\","/");if(await le(e,s))return!0}return!1}function Os(e){return/my-doc\.md|example\.spec\.|\/example\//i.test(e)}function $s(e){return e.endsWith("/")?!0:e.endsWith(".md")||e.endsWith(".mdc")}var Bc=8;async function Gs(e){let t=[];for(let n of e.files){if(!n.path.endsWith(".md")&&!n.path.endsWith(".mdc"))continue;let s=h(e,n.path);if(s===null)continue;let r=0;for(let o of ee(s)){if(He(o.href))continue;let i=Me(n.path,o.href);if(!(i===null||!Gi(i)||!$s(i)||Os(i)||await ji(e.repoRoot,i))&&(t.push({ruleId:"guidance-links-resolve",severity:"warn",message:`Broken link in ${n.path}: (${o.href}) does not resolve.`,file:n.path,line:Oe(s,o.href),harnesses:[],hint:"Fix the path or add the missing guidance file."}),r+=1,r>=Bc))break}}return{findings:t,records:[]}}import{readFile as Vc}from"node:fs/promises";import zc from"node:path";async function js(e){try{let t=await Vc(zc.join(e,"package.json"),"utf8"),n=JSON.parse(t);if(y(n)&&"scripts"in n){let{scripts:s}=n;if(y(s))return s}return null}catch{return null}}function Ws(e){return e===null?!1:Object.entries(e).some(([t,n])=>t.toLowerCase().includes("qmd")||typeof n=="string"&&n.toLowerCase().includes("qmd"))}async function Us(e){let t=N(e),n=e.files.filter(r=>r.path.startsWith("docs/ai/")).length;if(!t&&n<2)return{findings:[],records:[]};let s=await js(e.repoRoot);return Ws(s)?{findings:[],records:[]}:{findings:[{ruleId:"qmd-script-present",severity:"info",message:'package.json is missing a "qmd" (or equivalent) script for skill/doc search.',file:"package.json",line:null,harnesses:[],hint:'Add something like "qmd": "bun run ./scripts/qmd/qmd.bun.ts" and document usage in AGENTS.md.'}],records:[]}}async function Bs(e){let t=await Z(e.repoRoot);return t.hooksDirExists?t.settings?.["chat.useCustomAgentHooks"]===!0?{findings:[],records:[]}:{findings:[{ruleId:"vscode-custom-hooks",severity:"warn",message:".github/hooks/ exists but chat.useCustomAgentHooks is not true in .vscode/settings.json.",file:".vscode/settings.json",line:null,harnesses:["cursor","copilot"],hint:'Set "chat.useCustomAgentHooks": true so Cursor and Copilot load workspace hooks.'}],records:[]}:{findings:[],records:[]}}async function Vs(e){let t=await Z(e.repoRoot),n=[];return v(t,"chat.agentSkillsLocations","skills")||n.push({ruleId:"vscode-skills-location",severity:"warn",message:"chat.agentSkillsLocations should point at skills/ in .vscode/settings.json.",file:".vscode/settings.json",line:null,harnesses:["cursor","copilot"],hint:'Set "chat.agentSkillsLocations": { "skills/": true }.'}),v(t,"chat.agentFilesLocations","agents")||n.push({ruleId:"vscode-agents-location",severity:"warn",message:"chat.agentFilesLocations should point at agents/ in .vscode/settings.json.",file:".vscode/settings.json",line:null,harnesses:["cursor","copilot"],hint:'Set "chat.agentFilesLocations": { "agents/": true }.'}),{findings:n,records:[]}}function z(e,t,n,s,r){e.push(...r.findings),t.push(...r.records),r.records.length===0&&t.push({checkId:n,dimension:s,rawScore:r.findings.length>0?0:1})}function $e(e,t){return e.length===0?!0:e.some(n=>t.includes(n))}function zs(e,t,n){return $e(n,e.harnesses)?t===null||t.length===0?!0:n.some(s=>t.includes(s)):!1}function qs(e,t,n){return $e(e.harnesses,t.harnesses)?n===null||n.length===0||e.harnesses.length===0?!0:e.harnesses.some(s=>n.includes(s)):!1}function se(e){return e.trim().replaceAll(/\s+/g," ")}function Ks(e){let t=se(e);return!(t.length<20||/^#{1,6}\s/.test(t)||/^[-*]\s/.test(t)&&t.length<40||t.includes("AGENTS.md")||t.includes("docs/ai/rules.md"))}function ft(e){return e.map(t=>se(t)).filter(t=>t.length>0).join(`
|
|
168
|
-
`)}var mt=3,qc=80;function Ys(e,t){let n=e.split(`
|
|
169
|
-
`),s=ft(t.split(`
|
|
170
|
-
`)),r=[],o=new Set;for(let i=0;i<=n.length-mt;i+=1){if(o.has(i))continue;let a=n.slice(i,i+mt);if(!a.every(l=>Ks(l)))continue;let c=ft(a);if(!(c.length<qc)&&s.includes(c)){r.push({startLine:i+1,lineCount:mt,sample:se(a[0]??"")}),o.add(i);for(let l=1;l<mt;l+=1)o.add(i+l)}}return r}var Js="docs/ai/rules.md";function Xs(e){let t=h(e,Js);if(t===null)return{findings:[],records:[]};let n=[];for(let s of Ue){let r=h(e,s);if(r===null)continue;let o=Ys(r,t);for(let i of o)n.push({ruleId:"adapter-content-duplication",severity:"warn",message:`${s} duplicates ${String(i.lineCount)} lines from ${Js} near line ${String(i.startLine)}.`,file:s,line:i.startLine,harnesses:[],hint:`Replace duplicated rules with a pointer to ${Js}.`})}return{findings:n,records:[]}}function b(e){return e.intelligenceLayer??null}function ge(e){return Object.entries(e.packageJson.scripts).map(([t,n])=>({name:t,command:n}))}function he(e,t,n){return ge(e).some(s=>t.test(s.name)||n.test(s.command))}function Wi(e,t){return ge(e).filter(n=>t.test(n.name)||t.test(n.command)).map(n=>n.name).toSorted()}function ye(e){return e.workflows.map(t=>t.commands.join(`
|
|
149
|
+
`);else{let t=[...e.findings].sort((n,r)=>{let s=Bt.indexOf(n.severity)-Bt.indexOf(r.severity);return s!==0?s:n.ruleId.localeCompare(r.ruleId)});for(let n of t)process.stdout.write(`${Vt(n)}
|
|
150
|
+
|
|
151
|
+
`)}process.stdout.write(Eo)}import Bl from"node:path";function fn(){return{copilot:{files:0,lines:0,bytes:0},cursor:{files:0,lines:0,bytes:0},codex:{files:0,lines:0,bytes:0},antigravity:{files:0,lines:0,bytes:0},claude:{files:0,lines:0,bytes:0},gemini:{files:0,lines:0,bytes:0}}}function gn(e,t){return e.harness!==void 0?t.includes(e.harness)?[e.harness]:[]:Yt.has(e.layer)?t:e.path.startsWith(".cursor/")?t.includes("cursor")?["cursor"]:[]:e.path.startsWith(".codex/")?t.includes("codex")?["codex"]:[]:e.path.startsWith(".agent/")?t.includes("antigravity")?["antigravity"]:[]:e.path==="AGENTS.md"||e.path.startsWith("docs/ai/")?t:[]}function Z(e,t){return t===0?0:Math.round(e/t*1e3)/10}function hn(e,t){let n={files:0,lines:0,bytes:0},r=fn(),s={files:0,lines:0,bytes:0},o={files:0,lines:0,bytes:0},i=[];for(let a of e){let c=gn(a,t);if(c.length===0)continue;o.files+=1,o.lines+=a.lines,o.bytes+=a.bytes;let l=vo(a,c),m=l?"shared":"unique";if(i.push({path:a.path,lines:a.lines,scope:m,harnesses:c}),l)n.files+=1,n.lines+=a.lines,n.bytes+=a.bytes;else{let[u]=c;u!==void 0&&(r[u].files+=1,r[u].lines+=a.lines,r[u].bytes+=a.bytes),s.files+=1,s.lines+=a.lines,s.bytes+=a.bytes}}return{totals:o,shared:{...n,percentLines:Z(n.lines,o.lines)},unique:{byHarness:r,totals:{...s,percentLines:Z(s.lines,o.lines)}},files:i}}import L from"node:path";import{access as Ha}from"node:fs/promises";async function R(e){try{return await Ha(e),!0}catch{return!1}}function yn(e){return e===null?!1:e["chat.agentSkillsLocations"]!==void 0||e["chat.agentFilesLocations"]!==void 0||e["chat.useCustomAgentHooks"]===!0}import{readFile as Da}from"node:fs/promises";function Sn(e){if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e.startsWith('"')&&e.endsWith('"'))return e.slice(1,-1);let t=Number(e);return Number.isNaN(t)?e:t}function kn(e){let t={},n=/"([^"]+)"\s*:\s*(true|false|null|\d+(?:\.\d+)?|"[^"]*")/g;for(let[,r,s]of e.matchAll(n))r===void 0||s===void 0||(t[r]=Sn(s));return Object.keys(t).length===0?null:t}function Ie(e){try{let t=JSON.parse(e);if(S(t))return t}catch{}return kn(e)}async function xn(e){try{let t=await Da(e,"utf8");return Ie(t)}catch{return null}}async function Ee(e){let t=new Set;await R(L.join(e,".github/copilot-instructions.md"))&&t.add("copilot"),await R(L.join(e,".github/hooks"))&&t.add("copilot");let n=await xn(L.join(e,".vscode/settings.json"));return yn(n)&&(t.add("cursor"),t.add("copilot")),await R(L.join(e,".cursor"))&&t.add("cursor"),await R(L.join(e,".codex/config.toml"))&&t.add("codex"),await R(L.join(e,".codex/hooks.json"))&&t.add("codex"),await R(L.join(e,".codex/agents"))&&t.add("codex"),await R(L.join(e,".agent/workflows"))&&t.add("antigravity"),await R(L.join(e,".agent/README.md"))&&t.add("antigravity"),await R(L.join(e,"CLAUDE.md"))&&t.add("claude"),await R(L.join(e,".claude/settings.json"))&&t.add("claude"),await R(L.join(e,"GEMINI.md"))&&t.add("gemini"),[...t].sort()}function ve(e){return Math.ceil(e/4)}function M(e,t){return{path:e.path,lines:e.lines,bytes:e.bytes,estimatedTokens:ve(e.bytes),reason:t}}function Rn(e,t){let n=e.fileContents.get(t.path);return n===void 0?!1:/^alwaysApply:\s*true\s*$/im.test(n)||/^always_apply:\s*true\s*$/im.test(n)}function ee(e,t){return e.files.find(n=>n.path===t)??null}function wn(e,t){let n=[];if(t==="copilot"){let r=ee(e,".github/copilot-instructions.md");r!==null&&n.push(M(r,"Copilot workspace instructions are loaded by Copilot Chat."))}if(t==="cursor")for(let r of e.files)r.path.startsWith(".cursor/rules/")&&Rn(e,r)&&n.push(M(r,"Cursor rule declares alwaysApply: true."));if(t==="codex"){let r=ee(e,"AGENTS.md");r!==null&&n.push(M(r,"Root AGENTS.md is the Codex repo instruction entry."));for(let s of e.files)s.path.startsWith(".codex/")&&s.layer==="adapter"&&n.push(M(s,"Codex adapter guidance under .codex/."))}if(t==="antigravity"){let r=ee(e,".agent/README.md");r!==null&&n.push(M(r,"Antigravity workspace adapter README."))}if(t==="claude"){let r=ee(e,"CLAUDE.md");r!==null&&n.push(M(r,"Claude Code root instruction file."))}if(t==="gemini"){let r=ee(e,"GEMINI.md");r!==null&&n.push(M(r,"Gemini root instruction file."))}return n.toSorted((r,s)=>r.path.localeCompare(s.path))}function bn(e,t){if(!e.harnesses.includes(t))return{harness:t,detected:!1,files:[],totalLines:0,totalBytes:0,estimatedTokens:0,maxRecommendedLines:250,status:"ok"};let r=wn(e,t),s=r.reduce((i,a)=>i+a.lines,0),o=r.reduce((i,a)=>i+a.bytes,0);return{harness:t,detected:!0,files:r,totalLines:s,totalBytes:o,estimatedTokens:ve(o),maxRecommendedLines:250,status:s>250?"high":"ok"}}function Cn(e){return{harnesses:Q.map(t=>bn(e,t)),maxRecommendedLines:250,maxRecommendedFileLines:150}}var An=["Memory","Reflection","Planning","Action","System Operation"];function In(e){let t=new Map(An.map(i=>[i,{dimension:i,findingCount:0,error:0,warn:0,info:0,ruleIds:[]}])),n=new Map(An.map(i=>[i,new Set])),r=0,s=0;for(let i of e){let a=Ze(i.ruleId);if(a.length===0){s+=1;continue}r+=1;for(let c of a){let l=t.get(c),m=n.get(c);l===void 0||m===void 0||(l.findingCount+=1,l[i.severity]+=1,m.has(i.ruleId)||(m.add(i.ruleId),l.ruleIds.push(i.ruleId)))}}return{byDimension:An.map(i=>t.get(i)).filter(i=>i.findingCount>0),taggedFindings:r,untaggedFindings:s}}function En(e,t){let n={sharedLines:0,uniqueLines:0,totalLines:0,sharedPercent:0,uniquePercent:0},r={copilot:{...n},cursor:{...n},codex:{...n},antigravity:{...n},claude:{...n},gemini:{...n}};for(let s of t){let o=e.unique.byHarness[s].lines,i=e.shared.lines,a=i+o;r[s]={sharedLines:i,uniqueLines:o,totalLines:a,sharedPercent:Z(i,a),uniquePercent:Z(o,a)}}return r}function vn(e,t){let n={error:0,warn:0,info:0};for(let r of e)r.harnesses.includes(t)&&(r.severity==="error"?n.error+=1:r.severity==="warn"?n.warn+=1:n.info+=1);return n}var Po=[{min:85,grade:"excellent"},{min:70,grade:"good"},{min:50,grade:"fair"},{min:0,grade:"poor"}],rt={error:12,warn:5,info:1},Mo=40;function Tn(e){let t=e.error*rt.error+e.warn*rt.warn+e.info*rt.info;return Math.min(t,Mo)}import Le from"node:path";function H(e,t){return e.files.some(n=>n.path===t)}function Ln(e,t){return e.fileContents.get(t)??null}function Oa(e,t){return e.files.find(r=>r.path===t)?.lines??null}function $a(e){return e.includes("AGENTS.md")||e.includes("docs/ai/rules.md")}function te(e){return e.files.some(t=>t.path.startsWith("skills/"))}function Te(e){return e.files.some(t=>t.path.startsWith("agents/"))}function _n(e,t){return e.settings?.[t]===!0}function st(e,t){let n=Oa(e,t);return n===null?!1:n<=W}function ot(e,t){let n=Ln(e,t);return n===null?!1:$a(n)}function Fn(e){let t=Ln(e,".agent/README.md");return t===null?!1:/\.agent\/workflows\/|workflows\//i.test(t)&&/(workflow|playbook|slash command|mission|turbo)/i.test(t)}function ne(e,t,n){let r=e.settings?.[t];if(S(r)&&Object.keys(r).some(a=>a.startsWith(n)))return!0;if(e.settingsRaw===null)return!1;let s=t.replaceAll(".",String.raw`\.`);return new RegExp(`"${s}"\\s*:\\s*\\{[^}]*"${n}[^"]*"`).test(e.settingsRaw)}var Ho={copilot:[{id:"copilot-instructions",label:"Copilot instructions file present",weight:15,run:({context:e})=>H(e,".github/copilot-instructions.md")},{id:"copilot-references-shared",label:"Copilot instructions reference shared layers",weight:15,run:({context:e})=>ot(e,".github/copilot-instructions.md")},{id:"copilot-adapter-thin",label:"Copilot instructions stay thin",weight:10,run:({context:e})=>st(e,".github/copilot-instructions.md")},{id:"copilot-skills-location",label:"chat.agentSkillsLocations points at skills/",weight:15,run:({vscode:e})=>ne(e,"chat.agentSkillsLocations","skills")},{id:"copilot-agents-location",label:"chat.agentFilesLocations points at agents/",weight:15,run:({vscode:e})=>ne(e,"chat.agentFilesLocations","agents")},{id:"copilot-hooks-enabled",label:"Custom agent hooks enabled when .github/hooks/ exists",weight:15,run:({vscode:e})=>!e.hooksDirExists||_n(e,"chat.useCustomAgentHooks")},{id:"copilot-shared-skills",label:"Shared skills/ tree present",weight:8,run:({context:e})=>te(e)},{id:"copilot-shared-agents",label:"Shared agents/ tree present",weight:7,run:({context:e})=>Te(e)}],cursor:[{id:"cursor-rules-or-settings",label:"Cursor rules or VS Code agent settings present",weight:20,run:({context:e,vscode:t})=>e.files.some(n=>n.path.startsWith(".cursor/rules/"))||ne(t,"chat.agentSkillsLocations","skills")},{id:"cursor-skills-location",label:"chat.agentSkillsLocations points at skills/",weight:20,run:({vscode:e})=>ne(e,"chat.agentSkillsLocations","skills")},{id:"cursor-agents-location",label:"chat.agentFilesLocations points at agents/",weight:20,run:({vscode:e})=>ne(e,"chat.agentFilesLocations","agents")},{id:"cursor-hooks-enabled",label:"Custom agent hooks enabled when .github/hooks/ exists",weight:15,run:({vscode:e})=>!e.hooksDirExists||_n(e,"chat.useCustomAgentHooks")},{id:"cursor-shared-skills",label:"Shared skills/ tree present",weight:13,run:({context:e})=>te(e)},{id:"cursor-shared-agents",label:"Shared agents/ tree present",weight:12,run:({context:e})=>Te(e)}],codex:[{id:"codex-config-surface",label:"Codex config surface present (.codex/ or nested AGENTS.md)",weight:25,run:async({context:e})=>e.files.some(t=>t.path.startsWith(".codex/"))?!0:await R(Le.join(e.repoRoot,"api/AGENTS.md"))||await R(Le.join(e.repoRoot,"react/AGENTS.md"))||await R(Le.join(e.repoRoot,"shared/AGENTS.md"))},{id:"codex-hooks",label:"Codex hooks.json present",weight:20,run:({context:e})=>R(Le.join(e.repoRoot,".codex/hooks.json"))},{id:"codex-agents-wrappers",label:"Codex agent wrappers present",weight:20,run:({context:e})=>R(Le.join(e.repoRoot,".codex/agents"))},{id:"codex-shared-entry",label:"Root AGENTS.md present",weight:20,run:({context:e})=>H(e,"AGENTS.md")},{id:"codex-shared-skills",label:"Shared skills/ tree present",weight:8,run:({context:e})=>te(e)},{id:"codex-shared-rules",label:"Canonical rules doc present",weight:7,run:({context:e})=>H(e,"docs/ai/rules.md")}],antigravity:[{id:"antigravity-workflows",label:"Workflow playbooks present (.agent/workflows/)",weight:35,run:({context:e})=>e.files.some(t=>t.path.startsWith(".agent/workflows/"))},{id:"antigravity-readme",label:".agent/README.md documents workflow layout",weight:15,run:({context:e})=>Fn(e)},{id:"antigravity-shared-entry",label:"Root AGENTS.md present",weight:20,run:({context:e})=>H(e,"AGENTS.md")},{id:"antigravity-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>te(e)},{id:"antigravity-ai-system-doc",label:"AI system layout doc present",weight:15,run:({context:e})=>H(e,"docs/ai/ai-system.md")}],claude:[{id:"claude-adapter",label:"CLAUDE.md adapter present",weight:25,run:({context:e})=>H(e,"CLAUDE.md")},{id:"claude-references-shared",label:"CLAUDE.md references shared layers",weight:25,run:({context:e})=>ot(e,"CLAUDE.md")},{id:"claude-adapter-thin",label:"CLAUDE.md stays thin",weight:20,run:({context:e})=>st(e,"CLAUDE.md")},{id:"claude-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>te(e)},{id:"claude-skills-index",label:"Skill index doc for prose discovery",weight:8,run:({context:e})=>H(e,"docs/ai/available-skills.md")},{id:"claude-shared-agents",label:"Shared agents/ tree present",weight:7,run:({context:e})=>Te(e)}],gemini:[{id:"gemini-adapter",label:"GEMINI.md adapter present",weight:30,run:({context:e})=>H(e,"GEMINI.md")},{id:"gemini-references-shared",label:"GEMINI.md references shared layers",weight:25,run:({context:e})=>ot(e,"GEMINI.md")},{id:"gemini-adapter-thin",label:"GEMINI.md stays thin",weight:20,run:({context:e})=>st(e,"GEMINI.md")},{id:"gemini-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>te(e)},{id:"gemini-shared-agents",label:"Shared agents/ tree present",weight:10,run:({context:e})=>Te(e)}]};async function Nn(e,t){let n=Ho[e],r=[];for(let s of n){let o=await s.run(t);r.push({id:s.id,label:s.label,passed:o,weight:s.weight})}return r}function Pn(e){let t=e.reduce((r,s)=>r+s.weight,0);if(t===0)return 0;let n=e.filter(r=>r.passed).reduce((r,s)=>r+s.weight,0);return Math.round(n/t*100)}function Mn(e){for(let{min:t,grade:n}of Po)if(e>=t)return n;return"poor"}async function Hn(e,t,n,r,s,o){if(!t.harnesses.includes(e))return{harness:e,detected:!1,score:null,grade:"not-detected",checks:[],findingsCount:{error:0,warn:0,info:0},loadProfile:null};let c=await Nn(e,{context:t,vscode:n,harness:e}),l=vn(r,e),m=Pn(c),u=Tn(l),f=Math.max(0,Math.min(100,m-u));return{harness:e,detected:!0,score:f,grade:Mn(f),checks:c,findingsCount:l,loadProfile:o[e]??null}}async function Dn(e,t,n,r){let s=En(r,e.harnesses),o=[];for(let i of Q){let a=await Hn(i,e,t,n,r,s);o.push(a)}return o}import{readFileSync as Ga}from"node:fs";import{dirname as ja,join as Do}from"node:path";import{fileURLToPath as Wa}from"node:url";var Ua=Wa(import.meta.url),Oo=ja(Ua);function it(e){return typeof e=="object"&&e!==null}function Ba(e){return it(e)&&it(e.dimensions)&&it(e.check_weights)}function Va(e){return it(e)}function $o(e,t){let n=JSON.parse(Ga(e,"utf8"));if(!t(n))throw new Error(`Invalid standards file: ${e}`);return n}var On=$o(Do(Oo,"standards","weights.json"),Ba),$n=$o(Do(Oo,"standards","reference-thresholds.json"),Va);function Gn(e){return!Number.isFinite(e)||e<0?0:e<=1?e:e<=10?e/10:e<=100?e/100:1}function Go(e,t){return e>=t?1:0}function jo(e,t){return e<=t?1:e===0?0:t/e}function Wo(e,t){if(t<=0)return 0;let n=e/t;return Math.max(0,Math.min(1,n))}function jn(e,t,n){return e>=t&&e<=n?1:e<t?t===0?0:e/t:e===0?0:n/e}function B(e){if(e.curve===void 0)return Gn(e.rawScore??0);let t=e.measuredValue??0,n=e.referenceValue,r=typeof n=="number"?n:0;switch(e.curve){case"binary":return Go(t,r);case"asymptoticDecay":return jo(t,r);case"ratio":return Wo(t,r);case"goldilocks":{let[s,o]=Array.isArray(n)?n:[0,r];return jn(t,s??0,o??0)}}}function Wn(e,t){let n={};for(let s of Object.keys(t.dimensions))n[s]={weightedSum:0,weightSum:0,ran:!1,passedRules:0,applicableRules:0};for(let s of e){let o=n[s.dimension];if(!o)continue;o.ran=!0,o.applicableRules+=1;let i=B(s);i===1&&(o.passedRules+=1);let a=s.weight??t.check_weights[s.checkId]??1;!Number.isFinite(a)||a<=0||(o.weightedSum+=i*a,o.weightSum+=a)}let r={};for(let[s,o]of Object.entries(t.dimensions)){let i=n[s];if(!i||!i.ran){r[s]={status:"not_run",score:null,grade:"not-run",passedRules:0,applicableRules:0};continue}let a=i.weightSum>0?i.weightedSum/i.weightSum*o.max_score:0,c=Number.isFinite(a)?Math.round(a):0;r[s]={status:"run",score:c,grade:be(c),passedRules:i.passedRules,applicableRules:i.applicableRules}}return r}function Un(e,t){let n=0,r=0;for(let[s,o]of Object.entries(t.dimensions)){let i=e[s];if(!i||i.status!=="run"||i.score===null)continue;let a=Number(o.weight);!Number.isFinite(a)||a<=0||(n+=i.score/o.max_score*a,r+=a)}return r===0?0:Math.round(n/r*100)}function Bn(e){return e.contextBudget!==void 0&&e.contextBudget.harnesses.length>0}function V(e){return e.intelligenceLayer??null}function z(e){return e.packageJson.path!==null||e.workflows.length>0||e.prTemplates.length>0}function Vn(e){let t=V(e);return t!==null&&z(t)}function w(e){return e.intelligenceLayer??null}function ye(e){return Object.entries(e.packageJson.scripts).map(([t,n])=>({name:t,command:n}))}function Se(e,t,n){return ye(e).some(r=>t.test(r.name)||n.test(r.command))}function Uo(e,t){return ye(e).filter(n=>t.test(n.name)||t.test(n.command)).map(n=>n.name).toSorted()}function ke(e){return e.workflows.map(t=>t.commands.join(`
|
|
171
152
|
`)).join(`
|
|
172
|
-
`)}function
|
|
173
|
-
`)
|
|
174
|
-
`)
|
|
175
|
-
`),s
|
|
153
|
+
`)}function b(e){return e.packageJson.path!==null||e.configs.length>0||e.workflows.length>0}function zn(e){let t=w(e);return t!==null&&b(t)}var za=["AGENTS.md","CLAUDE.md","GEMINI.md",".github/copilot-instructions.md",".agent/README.md"],Bo=["IMPORTANT","CRITICAL","MANDATORY","REQUIRED","MUST NOT","MUST","NEVER","ALWAYS","SHALL","DO NOT"],Vo=.03,zo=40,qo=[{pattern:/\byou are an? (?:expert|senior|world[- ]class|10x|highly skilled|seasoned|professional)\b/i,label:"identity framing (\u201Cyou are a/an \u2026\u201D)"},{pattern:/\bact as an?\b/i,label:"roleplay framing (\u201Cact as a \u2026\u201D)"},{pattern:/\bas an ai (?:language model|assistant)\b/i,label:"AI self-reference"},{pattern:/\bworld[- ]class\b/i,label:"superlative filler (\u201Cworld-class\u201D)"}];function at(e){return e.replaceAll(/```[\s\S]*?```/g," ")}function Ko(e){let t=e.match(/\S+/g);return t===null?0:t.length}function q(e){return za.filter(t=>h(e,t)!==null)}function qn(e){return q(e).length>0}function _e(e,t){return e.files.some(n=>n.path==="AGENTS.md"||n.path.startsWith("docs/ai/")||n.path.startsWith("skills/")||n.path.startsWith("agents/"))||t.memoryDocs.length>0||t.nestedAgentsFiles.length>0}function Kn(e){let t=e.intelligenceLayer;return t===void 0?!1:_e(e,t)}function Yn(e){let t=e.intelligenceLayer;return t!==void 0&&t.memoryDocs.length>0}function Jn(e){return I(e)?!0:e.files.filter(n=>n.path.startsWith("docs/ai/")).length>=2}var qa=new Set(["skills-index","agents-md-mentions-skills","skill-doc-deep-links"]),Ka=new Set(["strict-typecheck-present","lint-gate-present","jsdoc-enforcement-present","test-gates-present","focused-test-commands-present","ci-enforcement-gates","ci-validation-gates","correction-loop-documented"]),Ya=new Set(["emphasis-keyword-density","identity-language-absent"]),Ja=new Set(["adapter-context-budget","always-loaded-budget"]),Xa=new Set(["guidance-maintenance-script","pr-template-ai-harness-check","ci-guidance-lint"]);function re(e,t){return qa.has(e)?I(t):e==="qmd-script-present"?Jn(t):e==="claude-agent-routing"?t.harnesses.includes("claude")&&k(t,"CLAUDE.md"):Ka.has(e)?zn(t):Ya.has(e)?qn(t):Ja.has(e)?Bn(t):Xa.has(e)?Vn(t):e==="memory-docs-indexed"?Yn(t):e==="local-context-patterns"?Kn(t):!0}var ct={"strict-typecheck-present":"repo","lint-gate-present":"repo","jsdoc-enforcement-present":"repo","test-gates-present":"repo","focused-test-commands-present":"repo","ci-enforcement-gates":"repo","ci-validation-gates":"repo","env-files-gitignored":"repo","secret-scanning-configured":"repo","actions-sha-pinned":"repo","no-pull-request-target":"repo","llm-output-schema-validated":"repo","model-interface-pinned":"repo","tool-contract-tests-present":"repo","untrusted-input-action-boundary":"repo","high-impact-action-confirmation":"repo","memory-write-provenance":"repo","shared-agents-md":"aspirational","adapter-thin-claude":"harness-core","adapter-thin-gemini":"harness-core","adapter-thin-copilot":"harness-core","adapter-points-to-shared":"harness-core","adapter-content-duplication":"harness-core","adapter-context-budget":"harness-core","always-loaded-budget":"harness-core","skills-index":"harness-core","claude-agent-routing":"harness-core","agents-md-mentions-skills":"harness-core","skill-doc-deep-links":"harness-core","skill-frontmatter":"harness-core","skill-line-count":"harness-core","agent-frontmatter":"harness-core","no-duplicate-skill-trees":"harness-core","no-duplicate-agent-trees":"harness-core","forbidden-legacy-paths":"harness-core","guidance-links-resolve":"harness-core","emphasis-keyword-density":"harness-core","identity-language-absent":"harness-core","vscode-skills-location":"harness-core","vscode-agents-location":"harness-core","vscode-custom-hooks":"harness-core","codex-hooks-valid":"harness-core","claude-hooks-valid":"harness-core","hook-stop-circuit-breaker":"harness-core","hook-no-network-exfil":"harness-core","no-dangerous-auto-approve":"harness-core","escalation-protocol-discoverability":"harness-core","agent-resource-budget-caps":"harness-core","tool-allowlist-inventory":"harness-core","shared-rules-doc":"aspirational","correction-loop-documented":"aspirational","guidance-maintenance-script":"aspirational","pr-template-ai-harness-check":"aspirational","ci-guidance-lint":"aspirational","qmd-script-present":"aspirational","local-context-patterns":"aspirational","memory-docs-indexed":"aspirational"};function Xn(e,t){let n=0,r=0,s=new Set;for(let o of e)ct[o.checkId]!=="repo"||s.has(o.checkId)||!re(o.checkId,t)||(s.add(o.checkId),r+=1,B(o)===1&&(n+=1));return r===0?null:Math.round(n/r*100)}var Yo={error:8,warn:3,info:1},Jo=4,Xo=1;var Qo=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".json",".jsonc",".yaml",".yml",".toml"]),Zo=new Set(["package-lock.json","npm-shrinkwrap.json","yarn.lock","pnpm-lock.yaml","bun.lock","bun.lockb","cargo.lock","poetry.lock","uv.lock","composer.lock","gemfile.lock"]),ei=512*1024,Qn=/(?:\.(?:test|spec)\.[a-z]+$|(?:^|\/)(?:__tests__|__fixtures__|fixtures|test|tests)\/)/i,ti=/\b(?:claude|gpt|chatgpt|gemini|mistral|codestral|llama|grok|deepseek|command|qwen|o1|o3|o4)[a-z0-9.]*(?:-[a-z0-9.]+)*-latest\b/i,Fe=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py"]),ni=/\b(?:anthropic|openai|mistralai|cohere|generativeai|langchain|chat\.completions|messages\.create|responses\.create|generateobject|generatetext|streamtext|generate_content)\b/i,ri=/\.choices\s*\[|tool_?calls?\b|function_?call|\.content\s*\[|\bJSON\.parse\s*\(|\bjson\.loads\s*\(/i,si=/\b(?:zod|valibot|superstruct|typebox|class-validator|ajv|yup|pydantic|basemodel|model_validate|parse_obj|typeadapter|jsonschema|marshmallow)\b|\.safeparse\s*\(|\bz\.object\s*\(/i,lt=/\btools\s*:\s*\[|\btool_choice\s*[:=]|\bfunction_?declarations\s*[:=]|\b(?:defineTool|zodFunction|registerTool)\s*\(|\bserver\.tool\s*\(|\binput_?schema\s*[:=]|^\s*@tool\b/im,oi=/\btool\b|\barguments?\b|\bfunction_?call|\bparameters?\b|\binput_?schema\b/i,ii=/\btothrow\b|\.rejects\b|\bassert_?raises\b|pytest\.raises|\binvalid\b|\bmalformed\b|\bmissing\b|\bsafeparse\b|\berrors?\b/i;var ai=/\bask\s+(?:the\s+)?(?:user|human|maintainer)\b|\bask\s+for\s+clarif|\brequest\s+clarification|\bseek\s+clarification|\bclarifying\s+questions?|\bwhen\s+(?:in\s+doubt|unsure|uncertain)\b|\bstop\s+and\s+ask\b|\bask\s+before\s+(?:assum|guess|proceed)|\bescalat(?:e|ion)\b|\b(?:ambiguous|unclear|contradictory|conflicting|incomplete)\b[^.\n]{0,40}\b(?:ask|clarif|escalat|confirm)/i,ci=/\bmax[_\s-]?(?:iterations?|steps?|turns?|calls?|requests?|attempts?|retries|tokens?|cost|budget)\b|\bmax_calls_per_minute\b|\bcurrency_limits?\b|\brate[_\s-]?limit|\bbudget[_\s-]?(?:cap|limit)|\biteration[_\s-]?(?:cap|limit)|\bcost[_\s-]?(?:cap|limit)/i,li=/\blanggraph\b|\bcrewai\b|\bautogen\b|\bAgentExecutor\b|\bcreateReactAgent\b|@modelcontextprotocol|\bmcp\.server\b|\bserver\.tool\s*\(/i;function se(e){return[...e.fileContents.values()].join(`
|
|
154
|
+
`)}function Ne(e){return(e.boundary?.sourceFiles??[]).map(t=>t.content).join(`
|
|
155
|
+
`)}var ui=/\bmcpservers\b|\.mcp\.json\b|\bmcp__|modelcontextprotocol|\bmcp\s+servers?\b/i,di=/\ballow[\s_-]?list\b|\bmcpservers\b|allowed[_\s-]?tools|permitted[_\s-]?tools|"allow"\s*:|pinned\s+(?:tool|server|mcp)/i,pi=/\bmem0\b|memory\.(?:add|write|store|save|upsert)\b|vector[\s_-]?(?:store|db|database)|\bupsert\s*\(|\bembeddings?\b|\bpinecone\b|\bweaviate\b|\bchroma(?:db)?\b|\bqdrant\b|persistent\s+memory/i,mi=/\bprovenance\b|\bquarantin|\buntrusted\b|\btaint(?:ed)?\b|trust[\s_-]?(?:level|tag|boundary)|source[\s_-]?tag|re-?validat/i,fi=/\bfetch\s*\(|\bwebfetch\b|\baxios\b|requests?\.get\b|\burllib\b|\bhttpx\b|\bscrap(?:e|ing)\b|\bcrawl|retriev(?:e|al)|web[\s_-]?search/i,gi=/\bexec(?:Sync)?\s*\(|child_process|\bspawn\s*\(|\bsubprocess\b|os\.system|writeFileSync|\bfs\.write|\bunlink\s*\(|\brm\s+-rf\b/i,hi=/saniti[sz]|\bvalidat|\ballow[\s_-]?list\b|\bescape\b|\bconfirm|\bapproval\b|\bguard(?:rail)?\b/i,yi=/force[\s_-]?push|push\s+--force|\brm\s+-rf\b|delete\s+from\b|\.delete\s*\(|\bdestroy\s*\(|\bstripe\b|\bpayment|\bcharge\s*\(|wire\s+transfer|send[_\s-]?email|\bsendmail\b|\bdeploy\b|drop\s+table/i,Si=/human[\s_-]?in[\s_-]?the[\s_-]?loop|\bconfirm(?:ation)?\b|\bapproval\b|\bescalat|requires?\s+(?:approval|confirmation)|dry[\s_-]?run|are\s+you\s+sure/i;function Pe(e){return e.files.some(n=>n.layer==="agents")?!0:(e.boundary?.sourceFiles??[]).some(n=>lt.test(n.content)||li.test(n.content))}var ki=new Set(["shared-agents-md","shared-rules-doc","adapter-thin-claude","adapter-thin-gemini","adapter-thin-copilot","adapter-points-to-shared","adapter-context-budget","always-loaded-budget","skills-index","claude-agent-routing","agents-md-mentions-skills","skill-doc-deep-links","skill-frontmatter","skill-line-count","agent-frontmatter","vscode-skills-location","vscode-agents-location","vscode-custom-hooks","codex-hooks-valid","claude-hooks-valid","correction-loop-documented","guidance-maintenance-script","pr-template-ai-harness-check","ci-guidance-lint","qmd-script-present","local-context-patterns","memory-docs-indexed"]),xi=new Set(["strict-typecheck-present","lint-gate-present","jsdoc-enforcement-present","test-gates-present","focused-test-commands-present","ci-enforcement-gates","ci-validation-gates","secret-scanning-configured"]),Qa=["CLAUDE.md","GEMINI.md",".github/copilot-instructions.md"];function Zn(e,t){if(!re(e,t))return!1;switch(e){case"skill-frontmatter":case"skill-line-count":return I(t);case"agent-frontmatter":return Pe(t);case"adapter-thin-claude":return k(t,"CLAUDE.md");case"adapter-thin-gemini":return k(t,"GEMINI.md");case"adapter-thin-copilot":return k(t,".github/copilot-instructions.md");case"adapter-points-to-shared":return Qa.some(n=>k(t,n));case"claude-hooks-valid":return k(t,".claude/settings.json");case"codex-hooks-valid":return k(t,".codex/hooks.json");case"vscode-skills-location":case"vscode-agents-location":case"vscode-custom-hooks":return k(t,".vscode/settings.json");default:return!0}}var Ri={error:3,warn:2,info:1};function er(e,t,n){let r=Xn(e,n),s=e.some(u=>u.checkId==="shared-agents-md"&&B(u)===1),o=n.harnesses.length===0&&!s?"implicit-only":"scored",i=new Map;for(let u of t){if(ct[u.ruleId]!=="harness-core")continue;let f=i.get(u.ruleId);(f===void 0||Ri[u.severity]>Ri[f])&&i.set(u.ruleId,u.severity)}let a=[],c=new Set;for(let u of e){let f=ki.has(u.checkId),d=xi.has(u.checkId);if(!f&&!d||c.has(u.checkId)||(c.add(u.checkId),f&&(i.has(u.checkId)||!Zn(u.checkId,n)))||d&&!re(u.checkId,n))continue;let y=Math.round((f?2:Xo)*B(u)*10)/10;y>0&&a.push({signal:u.checkId,points:y})}let l=[];for(let[u,f]of i)l.push({signal:u,points:-Yo[f]});for(let u of n.contextBudget?.harnesses??[])u.status==="high"&&l.push({signal:`context-budget-high:${u.harness}`,points:-Jo});let m=a.reduce((u,f)=>u+f.points,0)+l.reduce((u,f)=>u+f.points,0);return{status:o,score:Math.round(m),repoReadiness:r,contributions:a,liabilities:l}}var ut=new Set(["deep","session"]);function tr(e){let t=0,n=0,r=0,s=[];for(let[o,i]of Object.entries(e))ut.has(o)||(r+=1,i.status==="run"?(n+=1,t+=i.applicableRules):s.push(o));return{rulesApplied:t,dimensionsRun:n,dimensionsTotal:r,level:n===r?"full":"partial",dimensionsNotRun:s}}function nr(e){for(let[t,n]of Object.entries(e))if(ut.has(t)&&n.status==="run")return"core+extended";return"core"}function rr(e,t,n,r,s){if(n.totals.lines>0){let u=typeof $n.sharing_target_percent=="number"?$n.sharing_target_percent:65;e.push({checkId:"sharing-percent",dimension:"sharing",curve:"ratio",measuredValue:n.shared.percentLines,referenceValue:u})}let o=r.filter(u=>u.detected&&u.score!==null);if(o.length>0){let u=o.reduce((f,d)=>f+(d.score??0),0)/o.length;e.push({checkId:"harness-optimization-avg",dimension:"harnessWiring",curve:"ratio",measuredValue:u,referenceValue:100})}let i=Wn(e,On),a=Un(i,On),c=nr(i),l=tr(i),m=er(e,t,s);return{profile:"meta-harness",total_score:a,score_scope:c,coverage:l,harnessNet:m,dimensions:i}}import{readFile as oc}from"node:fs/promises";import ir from"node:path";import{readdir as ec}from"node:fs/promises";import tc from"node:path";async function dt(e){let t=[".md",".mdc"];function n(o){return t.some(i=>o.endsWith(i))}let r=[],s=[];try{s=await ec(e,{withFileTypes:!0})}catch{return r}for(let o of s){if(o.isSymbolicLink())continue;let i=tc.join(e,o.name);o.isDirectory()?r.push(...await dt(i)):o.isFile()&&n(i)&&r.push(i)}return r}import{readFile as nc,stat as rc}from"node:fs/promises";import sc from"node:path";function sr(e){return e.length===0?0:e.split(`
|
|
156
|
+
`).length}async function or(e,t,n,r){let s=sc.join(e,t);try{if(!(await rc(s)).isFile())return null;let i=await nc(s,"utf8"),a=sr(i),c={path:t,layer:n,lines:a,bytes:Buffer.byteLength(i,"utf8")};return r!==void 0&&(c.harness=r),c}catch{return null}}var ic=["AGENTS.md","docs/ai/rules.md","docs/ai/ai-system.md","docs/ai/available-skills.md","docs/ai/hooks.md"],ac=[{path:"CLAUDE.md",harness:"claude"},{path:"GEMINI.md",harness:"gemini"},{path:".github/copilot-instructions.md",harness:"copilot"},{path:".agent/README.md",harness:"antigravity"}],cc=[{dir:"skills",layer:"skills"},{dir:"agents",layer:"agents"},{dir:".cursor/rules",layer:"adapter",harness:"cursor"},{dir:".agent/workflows",layer:"workflows",harness:"antigravity"},{dir:".codex",layer:"adapter",harness:"codex"},{dir:"docs/ai",layer:"shared"}];async function Me(e){let t=[],n=new Map,r=new Set;async function s(o,i,a){let c=o.replaceAll("\\","/");if(r.has(c))return;let l=await or(e,c,i,a);if(l===null)return;r.add(c),t.push(l);let m=ir.join(e,c);try{let u=await oc(m,"utf8");n.set(c,u)}catch{}}for(let o of ic)await s(o,"shared");for(let o of ac)await s(o.path,"adapter",o.harness);for(let{dir:o,layer:i,harness:a}of cc){let c=ir.join(e,o),l=await dt(c);for(let m of l){let u=ir.relative(e,m).replaceAll("\\","/");await s(u,i,a)}}return t.sort((o,i)=>o.path.localeCompare(i.path)),{files:t,contents:n}}import{readFile as lc}from"node:fs/promises";import wi from"node:path";import{fileURLToPath as uc}from"node:url";function ar(e){return typeof e=="object"&&e!==null&&"version"in e&&typeof e.version=="string"}async function cr(){let e=wi.resolve(wi.dirname(uc(import.meta.url)),"../package.json"),t=await lc(e,"utf8"),n=JSON.parse(t);if(!ar(n))throw new Error("package.json is missing a string version field");return{version:n.version}}var bi=null;function Ci(){return bi??=cr(),bi}import{extname as gc}from"node:path";import{readdir as dc}from"node:fs/promises";import Fi from"node:path";var Ai=new Set([".git","node_modules","dist","coverage"]),Ii=[/^tsconfig(?:\..+)?\.json$/],Ei=[/^eslint\.config\.[cm]?[jt]s$/,/^\.eslintrc(?:\..+)?$/,/^\.oxlintrc(?:\..+)?$/,/^biome\.jsonc?$/,/^ruff\.toml$/,/^\.ruff\.toml$/],vi=[/^\.prettierrc(?:\..+)?$/,/^\.markdownlint(?:rc)?(?:\..+)?$/],Ti=[/^vitest\.config\.[cm]?[jt]s$/,/^jest\.config\.[cm]?[jt]s$/,/^playwright\.config\.[cm]?[jt]s$/,/^cypress\.config\.[cm]?[jt]s$/],Li=[/^package\.json$/,/^pyproject\.toml$/,/^Cargo\.toml$/,/^go\.mod$/],lr=/(scan:self|check:ai-system|check:md|lint:md|check:links|qmd|markdownlint|textlint|remark|cspell|paniolo-scan)/i,_i=/(correction loop|intelligence layer|diagnostic rule|rules catalog|canonical rules|paired skill|guidance hygiene|adapters stayed thin|json output keys are stable)/i;async function xe(e,t=""){let n=Fi.join(e,t),r=[];try{r=await dc(n,{withFileTypes:!0})}catch{return[]}let s=[];for(let o of r){if(o.isSymbolicLink()||Ai.has(o.name))continue;let i=Fi.join(t,o.name).replaceAll("\\","/");o.isDirectory()?s.push(...await xe(e,i)):o.isFile()&&s.push(i)}return s}import Ni from"node:path";function ur(e){let t=Ni.basename(e).toLowerCase();return Zo.has(t)?!1:Qo.has(Ni.extname(t))}import{readFile as pc,stat as mc}from"node:fs/promises";import fc from"node:path";async function dr(e,t){let n=fc.join(e,t);try{return(await mc(n)).size>ei?null:{path:t,content:await pc(n,"utf8")}}catch{return null}}async function pr(e){let n=(await xe(e)).filter(o=>ur(o)),s=(await Promise.all(n.map(o=>dr(e,o)))).filter(o=>o!==null);return{sourceFiles:s.filter(o=>!Qn.test(o.path)).toSorted((o,i)=>o.path.localeCompare(i.path)),testFiles:s.filter(o=>Qn.test(o.path)&&Fe.has(gc(o.path))).toSorted((o,i)=>o.path.localeCompare(i.path))}}async function mr(e){let{sourceFiles:t,testFiles:n}=await pr(e);return{sourceFiles:t,testFiles:n}}import Sc from"node:path";import{readFile as hc,stat as yc}from"node:fs/promises";import Pi from"node:path";function Mi(e){return e.length===0?0:e.split(`
|
|
157
|
+
`).length}async function Hi(e,t){try{return(await yc(Pi.join(e,t))).isFile()}catch{return!1}}async function D(e,t){try{return await hc(Pi.join(e,t),"utf8")}catch{return null}}function pt(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Re(e,t){return t.some(n=>n.test(e))}function Di(e){return/^\.github\/workflows\/.+\.ya?ml$/.test(e)}function Oi(e){return e===".github/PULL_REQUEST_TEMPLATE.md"||/^\.github\/PULL_REQUEST_TEMPLATE\/.+\.md$/.test(e)||/^docs\/pull_request_template\.md$/i.test(e)}function mt(e,t){return lr.test(`${e}
|
|
158
|
+
${t}`)}function ft(e){return lr.test(e.commands.join(`
|
|
159
|
+
`))}function $i(e){return _i.test(e)}function Gi(e){let t=e.toLowerCase();return t.includes("naming")||t.includes("comment")||t.includes("local-context")||t.includes("codebase-map")}function fr(e){let t=Sc.posix.basename(e);return Re(t,Ii)?{path:e,kind:"typecheck",capabilities:["typecheck"]}:Re(t,Ei)?{path:e,kind:"lint",capabilities:["lint"]}:Re(t,vi)?{path:e,kind:"format",capabilities:["format"]}:Re(t,Ti)?{path:e,kind:"test",capabilities:["test"]}:Re(t,Li)?{path:e,kind:"manifest",capabilities:["project-manifest"]}:null}function gr(e){let t=e.toLowerCase();return t==="docs/architecture.md"||t==="docs/overview.md"||t==="docs/meta-harness.md"||t==="docs/ai/codebase-map.md"||t==="docs/ai/ai-system.md"||t.includes("/adr")||t.includes("architecture")||t.includes("codebase-map")||t.includes("design")}function hr(e){let t=e.toLowerCase();return t==="docs/ai/codebase-map.md"||t==="docs/ai/ai-system.md"||t==="docs/overview.md"||t.endsWith("/adr/index.md")||t.endsWith("/adrs/index.md")}function He(e){if(!pt(e))return{};let t={};for(let[n,r]of Object.entries(e))typeof r=="string"&&(t[n]=r);return t}function yr(e){if(e===null)return{path:null,scripts:{},dependencies:[],devDependencies:[]};try{let t=JSON.parse(e);if(!pt(t))return{path:"package.json",scripts:{},dependencies:[],devDependencies:[]};let n=He(t.scripts),r=Object.keys(He(t.dependencies)).toSorted(),s=Object.keys(He(t.devDependencies)).toSorted();return{path:"package.json",scripts:n,dependencies:r,devDependencies:s}}catch{return{path:"package.json",scripts:{},dependencies:[],devDependencies:[]}}}import{stat as kc}from"node:fs/promises";import xc from"node:path";async function K(e,t,n,r,s){let o=xc.join(e,t),i=await kc(o),a=await D(e,t),c={path:t,kind:n,layer:r,capabilities:s,bytes:i.size};return a!==null&&(c.lines=Mi(a)),c}function Sr(e){let t=[],n=/^\s*-\s*run:\s*(.+)$/,r=/^\s*-\s*run:\s*[>|]/,s=!1;for(let o of e.split(/\r?\n/)){let i=o.match(n);if(i!==null){t.push(i[1]?.trim()??""),s=!1;continue}if(r.test(o)){s=!0;continue}s&&(/^\s{6,}\S/.test(o)?t.push(o.trim()):/^\s*-\s/.test(o)&&(s=!1))}return t.filter(o=>o.length>0)}async function kr(e,t){let n=await D(e,t);return n===null?null:{path:t,commands:Sr(n),content:n}}function gt(e){let t=Object.keys(e.packageJson.scripts),n=t.filter(i=>/(^|:)(typecheck|lint|format|check)(:|$)/i.test(i)),r=t.filter(i=>/(^|:)(test|e2e)(:|$)/i.test(i)),s=t.filter(i=>mt(i,e.packageJson.scripts[i]??"")),o=e.workflows.filter(ft).map(i=>i.path).toSorted();return{surfaces:e.surfaces,enforcement:{scripts:n.toSorted(),configs:e.configs.filter(i=>i.kind==="typecheck"||i.kind==="lint").map(i=>i.path).toSorted(),ciWorkflows:e.workflows.filter(i=>/(typecheck|lint|format|check)/i.test(i.commands.join(`
|
|
160
|
+
`))).map(i=>i.path).toSorted()},validation:{scripts:r.toSorted(),configs:e.configs.filter(i=>i.kind==="test").map(i=>i.path).toSorted(),ciWorkflows:e.workflows.filter(i=>/(npm test|npm run test|vitest|jest|playwright|cypress)/i.test(i.commands.join(`
|
|
161
|
+
`))).map(i=>i.path).toSorted()},memory:{docs:e.memoryDocs.toSorted(),indexes:e.memoryIndexes.toSorted()},localContext:{conventions:e.localContextConventions.toSorted(),nestedAgentsFiles:e.nestedAgentsFiles.toSorted()},correctionLoop:{scripts:s.toSorted(),prTemplates:e.prTemplates.toSorted(),ciWorkflows:o,maintenanceScripts:e.guidanceMaintenanceScripts.toSorted(),prTemplateChecks:e.aiHarnessPrTemplates.toSorted(),guidanceCiWorkflows:o}}}async function xr(e){let t=await xe(e),n=yr(await D(e,"package.json")),r=[],s=[],o=[],i=[],a=[],c=[],l=[],m=[],u=[],f={customChecker:!1,packageScript:!1,lintRules:!1,stopHook:!1,guidance:!1};f.packageScript=Object.entries(n.scripts).some(([d,g])=>/(^|:)(lint:jsdoc|check:jsdoc)(:|$)/i.test(d)||/find-missing-jsdoc|check-jsdoc-files/i.test(g));for(let d of t){let g=fr(d);if(g!==null){let y={...g},E=await D(e,d);g.kind==="typecheck"&&E!==null&&/"strict"\s*:\s*true/.test(E)&&(y.capabilities=[...g.capabilities,"strict-typecheck"]),g.kind==="lint"&&E!==null&&/jsdoc\/require-(returns|param)/i.test(E)&&(f.lintRules=!0),r.push(y),u.push(await K(e,d,"enforcement","config",y.capabilities))}if(Di(d)){let y=await kr(e,d);if(y!==null){s.push(y);let E=await K(e,d,"workflow","automation",["ci-workflow"]);u.push(E)}}if(Oi(d)){o.push(d);let y=await D(e,d);y!==null&&$i(y)&&i.push(d);let E=await K(e,d,"automation","pull-request",["pr-template"]);u.push(E)}if(d.endsWith(".md")&&gr(d)&&(a.push(d),hr(d)&&c.push(d),u.push(await K(e,d,"memory","docs",["memory"]))),d.endsWith(".md")&&Gi(d)&&l.push(d),(d==="scripts/find-missing-jsdoc/analyzeFile.ts"||d==="scripts/find-missing-jsdoc/check-jsdoc-files.bun.ts")&&(f.customChecker=!0),(d==="docs/ai/code-comment-best-practices.md"||d==="skills/code-comment-best-practices/SKILL.md")&&(f.guidance=!0),d.startsWith(".github/hooks/")&&d.endsWith(".json")){let y=await D(e,d);y!==null&&/lint-on-stop|find-missing-jsdoc|jsdoc/i.test(y)&&(f.stopHook=!0)}if(d.endsWith("/AGENTS.md")){m.push(d);let y=await K(e,d,"local-context","nested-entry",["nested-agents-md"]);u.push(y)}}return n.path!==null&&await Hi(e,n.path)&&u.push(await K(e,n.path,"automation","project",["package-scripts"])),{packageJson:n,configs:r.toSorted((d,g)=>d.path.localeCompare(g.path)),workflows:s.toSorted((d,g)=>d.path.localeCompare(g.path)),prTemplates:o,guidanceMaintenanceScripts:Object.entries(n.scripts).filter(([d,g])=>mt(d,g)).map(([d])=>d).toSorted(),aiHarnessPrTemplates:i.toSorted(),guidanceCiWorkflows:s.filter(d=>ft(d)).map(d=>d.path).toSorted(),memoryDocs:a,memoryIndexes:c.toSorted(),localContextConventions:l.toSorted(),nestedAgentsFiles:m,surfaces:u.toSorted((d,g)=>d.path.localeCompare(g.path)),jsdocEnforcement:f}}import Ac from"node:path";import{readdir as Rc}from"node:fs/promises";import wc from"node:path";async function Rr(e,t){let n=[];try{n=await Rc(wc.join(e,t),{withFileTypes:!0})}catch{return[]}return n.filter(r=>r.isFile()).map(r=>`${t}/${r.name}`)}import{readFile as bc,stat as Cc}from"node:fs/promises";import Ki from"node:path";var ji=[".claude/settings.json",".claude/settings.local.json"],Wi=[".env",".env.local",".env.development",".env.development.local",".env.production",".env.production.local",".env.test"],Ui=[".gitleaks.toml",".github/gitleaks.toml",".github/secret_scanning.yml",".github/secret_scanning.yaml"],Bi=[".pre-commit-config.yaml",".pre-commit-config.yml"],Vi=["config/worker-vars.list","config/env-secrets.dev.list","config/env-secrets.staging.list","config/env-secrets.production.list","scripts/env/run-with-env/run-with-env.bun.ts"],zi=/gitleaks|trufflehog|detect-secrets|ggshield/i,qi=/(?:\.\/)?(?:[\w.-]+\/)+[\w.-]+\.(?:tsx?|mts|cts|mjs|cjs|js|sh|bash|py)/g;async function F(e,t){try{return await bc(Ki.join(e,t),"utf8")}catch{return null}}async function O(e,t){try{return(await Cc(Ki.join(e,t))).isFile()}catch{return!1}}function Y(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ht(e){try{return{ok:!0,value:JSON.parse(e)}}catch{return{ok:!1,value:null}}}function Yi(e){let{permissions:t}=e;return!Y(t)||!Array.isArray(t.allow)?[]:t.allow.filter(n=>typeof n=="string")}function Ji(e){let{permissions:t}=e;return!Y(t)||typeof t.defaultMode!="string"?null:t.defaultMode}function yt(e){let t=e.match(qi)??[];return[...new Set(t.map(n=>n.replace(/^\.\//,"")))]}async function Xi(e,t,n){let r=await O(e,n),s=r?await F(e,n):null;return{reference:{source:t,path:n,exists:r},content:s}}async function wr(e,t){for(let n of await Rr(e,".claude/hooks")){let r=await F(e,n);r!==null&&t.push({source:n,path:n,isStop:/stop/i.test(Ac.posix.basename(n)),content:r})}}async function br(e){for(let t of Vi)if(await O(e,t))return!0;return!1}function Cr(e){let t=e.hooks;if(t===void 0)return{hooks:[],malformed:!1};if(!Y(t))return{hooks:[],malformed:!0};let n=[],r=!1;for(let[s,o]of Object.entries(t)){if(!Array.isArray(o)){r=!0;continue}for(let i of o){if(!Y(i)||!Array.isArray(i.hooks)){r=!0;continue}for(let a of i.hooks){if(!Y(a)||typeof a.command!="string"){r=!0;continue}n.push({event:s,command:a.command})}}}return{hooks:n,malformed:r}}async function Ar(e,t){let n=await F(e,t);if(n===null)return null;let{ok:r,value:s}=ht(n);if(!r||!Y(s))return{path:t,valid:!1,allow:[],defaultMode:null,hooks:[],hooksMalformed:!1};let{hooks:o,malformed:i}=Cr(s);return{path:t,valid:!0,allow:Yi(s),defaultMode:Ji(s),hooks:o,hooksMalformed:i}}async function Ir(e){let t=".codex/hooks.json",n=await F(e,t);if(n===null)return null;let{ok:r,value:s}=ht(n);if(!r)return{path:t,valid:!1,referencedScripts:[]};let o=[];for(let i of yt(JSON.stringify(s))){let a=await O(e,i);o.push({source:t,path:i,exists:a})}return{path:t,valid:!0,referencedScripts:o}}async function Er(e){let t=[];for(let n of Wi)await O(e,n)&&t.push(n);return t}async function vr(e,t){let n=[],r=[],s=t.flatMap(o=>o.hooks.map(i=>({surface:o,hook:i})));for(let{surface:o,hook:i}of s){let a=`${o.path} (${i.event} hook)`,c=[i.command];for(let l of yt(i.command)){let{reference:m,content:u}=await Xi(e,a,l);r.push(m),u!==null&&c.push(u)}n.push({source:a,path:null,isStop:i.event==="Stop",content:c.join(`
|
|
162
|
+
`)})}return{hookScripts:n,referencedClaudeScripts:r}}async function Tr(e){let t=[];for(let n of Ui)await O(e,n)&&t.push(n);for(let n of Bi){let r=await F(e,n);r!==null&&zi.test(r)&&t.push(n)}return t}async function De(e){let t=[];for(let l of ji){let m=await Ar(e,l);m!==null&&t.push(m)}let{hookScripts:n,referencedClaudeScripts:r}=await vr(e,t);await wr(e,n);let[s,o,i,a,c]=await Promise.all([Ir(e),F(e,".gitignore"),Er(e),Tr(e),br(e)]);return{claudeSettings:t,referencedClaudeScripts:r,hookScripts:n,codexHooks:s,gitignore:o,envFilesPresent:i,secretScanningFiles:a,usesKeyringSecrets:c}}import{readFile as Ic,stat as Ec}from"node:fs/promises";import Qi from"node:path";async function oe(e){let t=Qi.join(e,".github/hooks"),n=!1;try{n=(await Ec(t)).isDirectory()}catch{n=!1}let r=Qi.join(e,".vscode/settings.json"),s=null,o=null;try{let i=await Ic(r,"utf8");o=i,s=Ie(i)}catch{s=null,o=null}return{settings:s,settingsRaw:o,hooksDirExists:n}}function Oe(e,t,n,r){return{ruleId:e,severity:"warn",message:`${t} has ${String(n)} lines; keep root adapters thin (max ${String(W)}).`,file:t,line:null,harnesses:[r],hint:"Move detailed guidance to docs/ai/ and skills/; keep the adapter as a pointer."}}import{extname as Zi}from"node:path";function Lr(e){let t=[],n=e.split(`
|
|
163
|
+
`);for(let r=0;r<n.length;r+=1){let s=ti.exec(n[r]??"");s!==null&&t.push({line:r+1,alias:s[0]})}return t}function _r(e){if(!ni.test(e)||si.test(e))return null;let t=e.split(`
|
|
164
|
+
`);for(let n=0;n<t.length;n+=1)if(ri.test(t[n]??""))return n+1;return null}var $e={findings:[],records:[]},vc={id:"model-interface-pinned",title:"Model interface pinned",severity:"warn",category:"reliability",dimension:"guardrails",harnesses:[],check(e){let t=e.boundary?.sourceFiles;if(t===void 0)return $e;let n=[];for(let r of t)for(let{line:s,alias:o}of Lr(r.content))n.push({ruleId:"model-interface-pinned",severity:"warn",message:`${r.path} references the floating model alias "${o}"; the model behind a "latest" tag can change without notice.`,file:r.path,line:s,harnesses:[],hint:"Pin a dated/versioned model snapshot (e.g. a -YYYYMMDD or explicit-version id) so model upgrades are a deliberate, reviewable change."});return{findings:n,records:[]}}},Tc={id:"llm-output-schema-validated",title:"LLM output schema-validated",severity:"warn",category:"reliability",dimension:"guardrails",harnesses:[],check(e){let t=e.boundary?.sourceFiles;if(t===void 0)return $e;let n=[];for(let r of t){if(!Fe.has(Zi(r.path)))continue;let s=_r(r.content);s!==null&&n.push({ruleId:"llm-output-schema-validated",severity:"warn",message:`${r.path} consumes LLM/tool output (line ${String(s)}) without a schema validator; a shape change in the model response surfaces as a downstream type error.`,file:r.path,line:s,harnesses:[],hint:"Validate the parsed response against a Zod/Pydantic/JSON-Schema schema at the boundary before reading its fields."})}return{findings:n,records:[]}}},Lc={id:"tool-contract-tests-present",title:"Tool contract tests present",severity:"info",category:"reliability",dimension:"guardrails",harnesses:[],check(e){let{boundary:t}=e;if(t===void 0)return $e;let n=t.sourceFiles.find(s=>Fe.has(Zi(s.path))&<.test(s.content));return n===void 0||t.testFiles.some(s=>oi.test(s.content)&&ii.test(s.content))?$e:{findings:[{ruleId:"tool-contract-tests-present",severity:"info",message:`${n.path} declares model-callable tools, but no test exercises tool-call argument validation or error responses \u2014 only happy-path behavior is covered.`,file:n.path,line:null,harnesses:[],hint:"Add tests that feed malformed or missing tool-call arguments and assert the error path, per declared tool."}],records:[]}}},ea=[vc,Tc,Lc];function Fr(e){let t=[];for(let n of qe){if(!k(e,n))continue;let r=h(e,n);r===null||go(r)||t.push({ruleId:"adapter-points-to-shared",severity:"warn",message:`${n} should reference AGENTS.md and docs/ai/rules.md.`,file:n,line:null,harnesses:[],hint:"Keep adapters thin; point at shared layers instead of duplicating rules."})}return{findings:t,records:[]}}function Nr(e){let t=[];for(let n of ge(e,"agents/")){if(!n.endsWith(".agent.md"))continue;let r=h(e,n);if(r===null)continue;let s=Ke(r);if(s===null){t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing YAML frontmatter.`,file:n,line:null,harnesses:[]});continue}me(s,"name")||t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing a name field in frontmatter.`,file:n,line:null,harnesses:[]}),me(s,"description")||t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing a description field in frontmatter.`,file:n,line:null,harnesses:[]})}return{findings:t,records:[]}}function Pr(e){if(!I(e)||!k(e,"AGENTS.md"))return{findings:[],records:[]};let t=h(e,"AGENTS.md");return t!==null&&Ye(t)?{findings:[],records:[]}:{findings:[{ruleId:"agents-md-mentions-skills",severity:"info",message:"AGENTS.md should point at docs/ai/available-skills.md or the qmd search workflow.",file:"AGENTS.md",line:null,harnesses:[],hint:"Document how agents discover skills (index doc or npm run qmd -- search)."}],records:[]}}function Mr(e){if(!e.harnesses.includes("claude")||!k(e,"CLAUDE.md"))return{findings:[],records:[]};let t=h(e,"CLAUDE.md");return t!==null&&Je(t)?{findings:[],records:[]}:{findings:[{ruleId:"claude-agent-routing",severity:"info",message:"CLAUDE.md should include an Agent Routing table pointing at agents/*.agent.md.",file:"CLAUDE.md",line:null,harnesses:["claude"],hint:"Add a markdown table mapping task types to shared agents/*.agent.md files."}],records:[]}}var ta=/!?\[([^\]]*)\]\(([^)]+)\)/g;function ie(e){let t=[],n=ta.exec(e);for(;n!==null;){let[r]=n;r.startsWith("!")||t.push({label:n[1]??"",href:(n[2]??"").trim()}),n=ta.exec(e)}return t}var _c=new Set(["url","path","href","link","..."]);function Ge(e){return e.length===0||_c.has(e.toLowerCase())||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("mailto:")||e.startsWith("tel:")?!0:(e.split("#")[0]??"").length===0}function Hr(e){let t=e.replaceAll("\\","/").split("/"),n=[];for(let r of t)if(!(r===""||r===".")){if(r===".."){n.pop();continue}n.push(r)}return n.join("/")}function je(e,t){let n=(t.split("#")[0]??"").trim();if(n.length===0)return null;let r=n;try{r=decodeURIComponent(n)}catch{r=n}if(r.startsWith("/"))return r.slice(1).replaceAll("\\","/");let s=e.includes("/")?e.slice(0,e.lastIndexOf("/")):"",o=s.length===0?r:`${s}/${r}`;return Hr(o)}function Dr(e){return!e.endsWith(".md")&&!e.endsWith(".mdc")?!1:e.startsWith("docs/")||e.includes("/docs/")}function Or(e,t){for(let n of ie(t)){if(Ge(n.href))continue;let r=je(e,n.href);if(r!==null&&Dr(r))return!0}return!1}var Fc=50;function $r(e){let t=[];for(let n of e.files){if(!n.path.startsWith("skills/")||!n.path.endsWith("SKILL.md")||(n.lines??0)<=Fc)continue;let r=h(e,n.path);r===null||Or(n.path,r)||t.push({ruleId:"skill-doc-deep-links",severity:"info",message:`${n.path} does not deep-link into a durable doc under docs/.`,file:n.path,line:null,harnesses:[],hint:"Pair the skill with a docs/ reference and link it (for example a **Details:** link to a docs/ page) instead of inlining all detail."})}return{findings:t,records:[]}}function Gr(e){let t=[];for(let n of ge(e,"skills/")){if(!n.endsWith("/SKILL.md")&&!n.endsWith("SKILL.md"))continue;let r=h(e,n);if(r===null)continue;let s=Ke(r);if(s===null){t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing YAML frontmatter.`,file:n,line:null,harnesses:[]});continue}me(s,"name")||t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing a name field in frontmatter.`,file:n,line:null,harnesses:[]}),me(s,"description")||t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing a description field in frontmatter.`,file:n,line:null,harnesses:[]})}return{findings:t,records:[]}}function jr(e){let t=[];for(let n of ge(e,"skills/")){if(!n.endsWith("SKILL.md"))continue;let r=U(e,n);r!==null&&r>Tt&&t.push({ruleId:"skill-line-count",severity:"warn",message:`${n} has ${String(r)} lines; keep skills under ${String(Tt)}.`,file:n,line:null,harnesses:[],hint:"Move detail to docs/; keep SKILL.md as a pointer."})}return{findings:t,records:[]}}var na="docs/ai/available-skills.md";function Wr(e){return I(e)?k(e,na)?{findings:[],records:[]}:{findings:[{ruleId:"skills-index",severity:"info",message:`${na} is missing; add a skill slug index when using skills/.`,file:null,line:null,harnesses:[],hint:"List each skills/<slug>/ folder so agents can pick a minimal skill set."}],records:[]}:{findings:[],records:[]}}function Ur(e){let t=0;for(let n of Bo){let r=e.match(new RegExp(`\\b${n}\\b`,"g"));r!==null&&(t+=r.length)}return t}function Br(e){let t=[];for(let n of q(e)){let r=h(e,n);if(r===null)continue;let s=at(r),o=Ko(s);if(o<zo)continue;let i=Ur(s),a=i/o;if(a<=Vo)continue;let c=(a*100).toFixed(1);t.push({ruleId:"emphasis-keyword-density",severity:"info",message:`${n} uses ${String(i)} all-caps emphasis keyword(s) across ${String(o)} words (${c}%); emphasis loses force when overused.`,file:n,line:null,harnesses:[],hint:"Reserve IMPORTANT/MUST/NEVER for the few rules that truly need them; rewrite the rest as plain, action-oriented instructions."})}return{findings:t,records:[]}}function Vr(e){let t=[];for(let n of q(e)){let r=h(e,n);if(r===null)continue;let s=at(r),o=qo.filter(({pattern:i})=>i.test(s)).map(({label:i})=>i);o.length!==0&&t.push({ruleId:"identity-language-absent",severity:"info",message:`${n} contains identity/roleplay filler: ${o.join(", ")}.`,file:n,line:null,harnesses:[],hint:"Drop identity framing; state what to do, not who to be. Action-oriented rules outperform persona prompts."})}return{findings:t,records:[]}}var ra=[{id:"emphasis-keyword-density",title:"Emphasis-keyword density",severity:"info",category:"instruction-quality",dimension:"maintainability",harnesses:[],check:Br},{id:"identity-language-absent",title:"No identity-language filler",severity:"info",category:"instruction-quality",dimension:"maintainability",harnesses:[],check:Vr}];function St(e,t,n,r){return{findings:[{ruleId:e,severity:t,message:n,file:null,line:null,harnesses:[],hint:r}],records:[]}}var $={findings:[],records:[]},Nc={id:"escalation-protocol-discoverability",title:"Escalation protocol discoverable",severity:"info",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=q(e);return t.length===0||ai.test(se(e))?$:{findings:[{ruleId:"escalation-protocol-discoverability",severity:"info",message:"No discoverable escalation protocol in guidance: nothing documents when or how the agent should ask for clarification on missing, ambiguous, or contradictory specs.",file:t[0]??null,line:null,harnesses:[],hint:"Document an 'ask before guessing' protocol in AGENTS.md or the rules doc \u2014 the epistemic counterpart to action confirmation (HiL-Bench's 53-82pp finding)."}],records:[]}}},Pc={id:"agent-resource-budget-caps",title:"Agent resource budget caps",severity:"info",category:"security",dimension:"guardrails",harnesses:[],check(e){if(!Pe(e))return $;let t=(e.boundary?.sourceFiles??[]).map(n=>n.content).join(`
|
|
165
|
+
`);return ci.test(`${se(e)}
|
|
166
|
+
${t}`)?$:{findings:[{ruleId:"agent-resource-budget-caps",severity:"info",message:"An agent/tool surface is present but no resource caps are declared (max iterations, cost, or rate limit); an unbounded loop is a resource-drain (R7) risk.",file:null,line:null,harnesses:[],hint:"Declare max-iteration, max-cost, or rate-limit caps, mirroring OAP's max_calls_per_minute / currency_limits."}],records:[]}}},Mc={id:"tool-allowlist-inventory",title:"Tool allowlist inventory",severity:"info",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=`${se(e)}
|
|
167
|
+
${Ne(e)}`;return!ui.test(t)||di.test(t)?$:St("tool-allowlist-inventory","info","Repo references MCP/tool servers but declares no explicit, pinned tool allowlist; arbitrary tool discovery widens the attack surface (R1/R3).","Declare an explicit allowlist of tools/MCP servers with pinned versions instead of allowing arbitrary discovery.")}},Hc={id:"untrusted-input-action-boundary",title:"Untrusted input / action boundary",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=Ne(e);if(!(fi.test(t)&&gi.test(t)))return $;let r=`${se(e)}
|
|
168
|
+
${t}`;return hi.test(r)?$:St("untrusted-input-action-boundary","warn","Source ingests external/untrusted content and takes actions (exec, file write) with no sanitization, validation, or confirmation in evidence (R2/R3 unconstrained data flow).","Sanitize, allow-list, or confirm untrusted content before it reaches shell exec, file writes, or tool dispatch.")}},Dc={id:"memory-write-provenance",title:"Memory write provenance",severity:"info",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=`${se(e)}
|
|
169
|
+
${Ne(e)}`;return!pi.test(t)||mi.test(t)?$:St("memory-write-provenance","info","Repo writes to persistent agent memory but shows no provenance/trust tagging or re-validation; memory writes from untrusted sources can later be read as trusted (R6).","Tag or quarantine memory writes derived from untrusted sources and re-validate them before trusted reads.")}},Oc={id:"high-impact-action-confirmation",title:"High-impact action confirmation",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=Ne(e);if(!yi.test(t))return $;let n=`${se(e)}
|
|
170
|
+
${t}`;return Si.test(n)?$:St("high-impact-action-confirmation","warn","Source performs high-impact actions (deletion, payment, force-push, deploy, external send) with no human-in-the-loop confirmation or escalation in evidence (R6/R7).","Gate high-impact actions behind an explicit confirmation/escalation step, not just allow/deny (OWASP LLM06).")}},sa=[Nc,Pc,Mc,Hc,Dc,Oc];var $c=/\b(?:curl|wget|ncat|telnet|scp)\b|\bnc\s|Invoke-WebRequest|\bfetch\s*\(|\baxios\b|http\.request|urllib|requests\.(?:get|post|put|patch)/i,Gc=/localhost|127\.0\.0\.1|0\.0\.0\.0|::1/i;function zr(e){let t=[];for(let n of e.content.split(/\r?\n/)){let r=n.trim();$c.test(r)&&!Gc.test(r)&&t.push(r)}return t}var jc=new Set(["Bash","Write","Edit","MultiEdit","NotebookEdit"]);function qr(e){let t=e.trim();if(t==="")return!1;if(t==="*")return!0;if(t.startsWith("mcp__"))return t.includes("*");let n=t.match(/^([A-Za-z_][\w-]*)(?:\((.*)\))?$/);if(n===null)return!1;let[,r="",s]=n;if(!jc.has(r))return!1;if(s===void 0)return!0;let o=s.trim();return o===""||o==="*"||o===":*"}var Wc=/^[0-9a-f]{40}$/i;function Kr(e){let t=new Set,n=/^\s*-?\s*uses:\s*['"]?([^'"\s#]+)['"]?/gm;for(let r of e.matchAll(n)){let[,s]=r;if(s===void 0||s.startsWith("./")||s.startsWith("docker://"))continue;let o=s.includes("@")?s.slice(s.lastIndexOf("@")+1):"";Wc.test(o)||t.add(s)}return[...t]}var G={findings:[],records:[]},Uc=new Set(["bypassPermissions","acceptEdits"]),Bc="stop_hook_active";function ae(e){return e.security??null}var Vc={id:"no-dangerous-auto-approve",title:"No dangerous auto-approve permissions",severity:"error",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ae(e);if(t===null)return G;let n=[];for(let r of t.claudeSettings){r.defaultMode!==null&&Uc.has(r.defaultMode)&&n.push({ruleId:"no-dangerous-auto-approve",severity:"error",message:`${r.path} sets permissions.defaultMode "${r.defaultMode}", auto-approving actions without prompting.`,file:r.path,line:null,harnesses:["claude"],hint:'Use "default" or "plan" mode and allow-list specific commands instead of bypassing prompts.'});for(let s of r.allow.filter(qr))n.push({ruleId:"no-dangerous-auto-approve",severity:"error",message:`${r.path} auto-approves "${s}", a blanket grant over a dangerous capability.`,file:r.path,line:null,harnesses:["claude"],hint:"Scope allow-list entries to specific commands, e.g. Bash(npm run test:*) instead of Bash(*)."})}return{findings:n,records:[]}}},zc={id:"hook-no-network-exfil",title:"Hooks do not exfiltrate over the network",severity:"error",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ae(e);if(t===null)return G;let n=[];for(let r of t.hookScripts){let[s]=zr(r);s!==void 0&&n.push({ruleId:"hook-no-network-exfil",severity:"error",message:`${r.source} makes a network call (\`${s.slice(0,80)}\`); hooks run automatically and can exfiltrate repo data.`,file:r.path,line:null,harnesses:[],hint:"Remove the network call or restrict it to localhost; move outbound calls into explicit, reviewable steps."})}return{findings:n,records:[]}}},qc={id:"hook-stop-circuit-breaker",title:"Stop hooks guard against infinite loops",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ae(e);if(t===null)return G;let n=[];for(let r of t.hookScripts)!r.isStop||r.content.includes(Bc)||n.push({ruleId:"hook-stop-circuit-breaker",severity:"warn",message:`${r.source} is a Stop hook that never checks stop_hook_active; a blocking Stop hook can loop the agent indefinitely.`,file:r.path,line:null,harnesses:[],hint:"Read stop_hook_active from the hook input and exit without blocking when it is true."});return{findings:n,records:[]}}},Kc={id:"env-files-gitignored",title:"Env files are gitignored",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ae(e);if(t===null)return G;let r=t.gitignore!==null&&/^\s*!?[*.]*\.env(?:[.*]|\b|\/)?/m.test(t.gitignore)?[]:t.envFilesPresent;if(r.length===0)return G;let s=t.usesKeyringSecrets?"This repo uses keyring-managed secrets; delete the committed .env file rather than relying on it.":"Gitignore `.env`/`.env.*`, or move secrets to an OS keyring (the run-with-env pattern) so they never touch disk.";return{findings:[{ruleId:"env-files-gitignored",severity:"warn",message:`${r.join(", ")} present but not gitignored; secrets risk being committed.`,file:r[0]??null,line:null,harnesses:[],hint:s}],records:[]}}};function Yc(e){return e.some(t=>/gitleaks|trufflehog|detect-secrets|ggshield/i.test(t.content))}var Jc={id:"secret-scanning-configured",title:"Secret scanning is configured",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=ae(e);if(t===null)return G;let n=e.intelligenceLayer?.workflows??[];return t.secretScanningFiles.length>0||Yc(n)?G:{findings:[{ruleId:"secret-scanning-configured",severity:"warn",message:"No secret-scanning configuration found (gitleaks, trufflehog, detect-secrets, or a pre-commit secret hook).",file:null,line:null,harnesses:[],hint:"Add a gitleaks/trufflehog CI step or a detect-secrets pre-commit hook so committed credentials are caught."}],records:[]}}},Xc={id:"no-pull-request-target",title:"No risky pull_request_target workflows",severity:"error",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=e.intelligenceLayer?.workflows??[],n=[];for(let r of t)/\bpull_request_target\b/.test(r.content)&&n.push({ruleId:"no-pull-request-target",severity:"error",message:`${r.path} triggers on pull_request_target, which runs with repo secrets against untrusted PR code.`,file:r.path,line:null,harnesses:[],hint:"Prefer pull_request; if pull_request_target is required, never check out or execute PR head code with secrets in scope."});return{findings:n,records:[]}}},Qc={id:"actions-sha-pinned",title:"GitHub Actions pinned to commit SHAs",severity:"warn",category:"security",dimension:"guardrails",harnesses:[],check(e){let t=e.intelligenceLayer?.workflows??[],n=[];for(let r of t){let s=Kr(r.content);s.length!==0&&n.push({ruleId:"actions-sha-pinned",severity:"warn",message:`${r.path} uses actions pinned to mutable refs: ${s.join(", ")}.`,file:r.path,line:null,harnesses:[],hint:"Pin each action to a full 40-character commit SHA (e.g. actions/checkout@<sha>) to prevent tag-hijack supply-chain attacks."})}return{findings:n,records:[]}}},Zc={id:"claude-hooks-valid",title:"Claude hooks config is valid",severity:"error",category:"hooks",dimension:"guardrails",harnesses:["claude"],check(e){let t=ae(e);if(t===null)return G;let n=[];for(let r of t.claudeSettings){if(!r.valid){n.push({ruleId:"claude-hooks-valid",severity:"error",message:`${r.path} is not valid JSON.`,file:r.path,line:null,harnesses:["claude"],hint:"Fix the JSON syntax; an unparseable settings file disables every configured hook silently."});continue}r.hooksMalformed&&n.push({ruleId:"claude-hooks-valid",severity:"error",message:`${r.path} has a malformed hooks block; entries must be { matcher?, hooks: [{ type, command }] }.`,file:r.path,line:null,harnesses:["claude"],hint:"Match the documented hooks schema so the configured commands actually run."})}for(let r of t.referencedClaudeScripts.filter(s=>!s.exists))n.push({ruleId:"claude-hooks-valid",severity:"error",message:`${r.source} references missing script ${r.path}.`,file:r.path,line:null,harnesses:["claude"],hint:"Create the script or fix the path; a missing hook command fails open and skips the check."});return{findings:n,records:[]}}},el={id:"codex-hooks-valid",title:"Codex hooks config is valid",severity:"error",category:"hooks",dimension:"guardrails",harnesses:["codex"],check(e){let t=ae(e);if(t===null||t.codexHooks===null)return G;let n=t.codexHooks,r=[];n.valid||r.push({ruleId:"codex-hooks-valid",severity:"error",message:`${n.path} is not valid JSON.`,file:n.path,line:null,harnesses:["codex"],hint:"Fix the JSON syntax so the configured codex hooks load."});for(let s of n.referencedScripts.filter(o=>!o.exists))r.push({ruleId:"codex-hooks-valid",severity:"error",message:`${n.path} references missing script ${s.path}.`,file:s.path,line:null,harnesses:["codex"],hint:"Create the script or fix the path so the hook command runs."});return{findings:r,records:[]}}},oa=[Vc,zc,qc,Kc,Jc,Xc,Qc,Zc,el];var tl={id:"shared-agents-md",title:"Shared AGENTS.md entry point",severity:"warn",category:"structure",dimension:"layering",harnesses:[],check(e){return k(e,"AGENTS.md")?{findings:[],records:[]}:{findings:[{ruleId:"shared-agents-md",severity:"warn",message:"AGENTS.md is missing.",file:null,line:null,harnesses:[],hint:"Add AGENTS.md as the repo-wide AI entry point with workflow, safety, and pointers to canonical docs."}],records:[]}}},nl={id:"shared-rules-doc",title:"Canonical rules doc",severity:"warn",category:"structure",dimension:"layering",harnesses:[],check(e){return k(e,"docs/ai/rules.md")?{findings:[],records:[]}:{findings:[{ruleId:"shared-rules-doc",severity:"warn",message:"docs/ai/rules.md is missing.",file:null,line:null,harnesses:[],hint:"Add docs/ai/rules.md as the canonical coding-rules reference."}],records:[]}}},rl={id:"adapter-thin-claude",title:"Thin CLAUDE.md adapter",severity:"warn",category:"adapter",dimension:"layering",harnesses:["claude"],check(e){let t=U(e,"CLAUDE.md");return t===null||t<=W?{findings:[],records:[]}:{findings:[Oe("adapter-thin-claude","CLAUDE.md",t,"claude")],records:[]}}},sl={id:"adapter-thin-gemini",title:"Thin GEMINI.md adapter",severity:"warn",category:"adapter",dimension:"layering",harnesses:["gemini"],check(e){let t=U(e,"GEMINI.md");return t===null||t<=W?{findings:[],records:[]}:{findings:[Oe("adapter-thin-gemini","GEMINI.md",t,"gemini")],records:[]}}},ol={id:"adapter-thin-copilot",title:"Thin Copilot instructions",severity:"warn",category:"adapter",dimension:"layering",harnesses:["copilot"],check(e){let t=".github/copilot-instructions.md",n=U(e,t);return n===null||n<=W?{findings:[],records:[]}:{findings:[Oe("adapter-thin-copilot",t,n,"copilot")],records:[]}}},il={id:"adapter-points-to-shared",title:"Adapters reference shared layers",severity:"warn",category:"adapter",dimension:"layering",harnesses:[],check:Fr},al={id:"skill-frontmatter",title:"Skill frontmatter",severity:"error",category:"skills",dimension:"maintainability",harnesses:[],check:Gr},cl={id:"skill-line-count",title:"Skill line budget",severity:"warn",category:"skills",dimension:"maintainability",harnesses:[],check:jr},ll={id:"agent-frontmatter",title:"Agent frontmatter",severity:"error",category:"agents",dimension:"maintainability",harnesses:[],check:Nr},ul={id:"skills-index",title:"Skill slug index",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:Wr},dl={id:"claude-agent-routing",title:"Claude agent routing table",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:["claude"],check:Mr},pl={id:"agents-md-mentions-skills",title:"AGENTS.md skill discovery",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:Pr},ml={id:"skill-doc-deep-links",title:"Skills deep-link into docs",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:$r},ia=[tl,nl,rl,sl,ol,il,al,cl,ll,ul,dl,pl,ml,...ra,...oa,...ea,...sa];function Yr(e){let t=e.contextBudget;if(t===void 0)return{findings:[],records:[]};let n=[],r=[];for(let s of t.harnesses)if(s.detected)for(let o of s.files)r.push({checkId:"adapter-context-budget",dimension:"maintainability",curve:"asymptoticDecay",measuredValue:o.lines,referenceValue:t.maxRecommendedFileLines}),!(o.lines<=t.maxRecommendedFileLines)&&n.push({ruleId:"adapter-context-budget",severity:"info",message:`${o.path} contributes ${String(o.lines)} always-loaded lines for ${s.harness}; recommended maximum per file is ${String(t.maxRecommendedFileLines)}.`,file:o.path,line:null,harnesses:[s.harness],hint:"Split detailed guidance into linked docs and keep always-loaded instruction files compact."});return{findings:n,records:r}}function Jr(e){let t=e.contextBudget;if(t===void 0)return{findings:[],records:[]};let n=[],r=[];for(let s of t.harnesses)s.detected&&(r.push({checkId:"always-loaded-budget",dimension:"maintainability",curve:"asymptoticDecay",measuredValue:s.totalLines,referenceValue:s.maxRecommendedLines}),s.status!=="ok"&&n.push({ruleId:"always-loaded-budget",severity:"info",message:`${s.harness} always-loaded context is ${String(s.totalLines)} lines; recommended maximum is ${String(s.maxRecommendedLines)}.`,file:null,line:null,harnesses:[s.harness],hint:"Keep root adapters as short indexes and move deep guidance into linked docs, skills, agents, or workflows."}));return{findings:n,records:r}}async function Xr(e){return e.files.some(n=>n.path.startsWith("agents/"))?await fe(e.repoRoot,".github/agents")?{findings:[{ruleId:"no-duplicate-agent-trees",severity:"error",message:".github/agents/ duplicates root agents/; use agents/ only.",file:".github/agents",line:null,harnesses:[],hint:"Remove .github/agents/ and keep canonical agents/ at the repo root."}],records:[]}:{findings:[],records:[]}:{findings:[],records:[]}}async function Qr(e){if(!e.files.some(s=>s.path.startsWith("skills/")))return{findings:[],records:[]};let n=[],r=[".github/skills",".cursor/skills"];for(let s of r)await fe(e.repoRoot,s)&&n.push({ruleId:"no-duplicate-skill-trees",severity:"error",message:`${s}/ duplicates root skills/; use skills/ only.`,file:s,line:null,harnesses:[],hint:"Remove the shadow tree and keep canonical skills/ at the repo root."});return{findings:n,records:[]}}var fl=["docs/","skills/","agents/",".cursor/",".github/",".codex/",".agent/",".claude/"],gl=new Set(["AGENTS.md","CLAUDE.md","GEMINI.md","README.md",".github/copilot-instructions.md"]);function aa(e){let t=e.replaceAll("\\","/").replace(/\/+$/,"");return gl.has(t)?!0:fl.some(n=>t===n.slice(0,-1)||t.startsWith(n))}function We(e,t){let n=e.split(`
|
|
171
|
+
`);for(let r=0;r<n.length;r+=1){let s=n[r];if(s!==void 0&&s.includes(t))return r+1}return null}var hl=["",".md","/README.md","/index.md"];async function ca(e,t){for(let n of hl){let r=`${t}${n}`.replaceAll("\\","/");if(await fe(e,r))return!0}return!1}function Zr(e){return/my-doc\.md|example\.spec\.|\/example\//i.test(e)}function es(e){return e.endsWith("/")?!0:e.endsWith(".md")||e.endsWith(".mdc")}var yl=8;async function ts(e){let t=[];for(let n of e.files){if(!n.path.endsWith(".md")&&!n.path.endsWith(".mdc"))continue;let r=h(e,n.path);if(r===null)continue;let s=0;for(let o of ie(r)){if(Ge(o.href))continue;let i=je(n.path,o.href);if(!(i===null||!aa(i)||!es(i)||Zr(i)||await ca(e.repoRoot,i))&&(t.push({ruleId:"guidance-links-resolve",severity:"warn",message:`Broken link in ${n.path}: (${o.href}) does not resolve.`,file:n.path,line:We(r,o.href),harnesses:[],hint:"Fix the path or add the missing guidance file."}),s+=1,s>=yl))break}}return{findings:t,records:[]}}import{readFile as Sl}from"node:fs/promises";import kl from"node:path";async function ns(e){try{let t=await Sl(kl.join(e,"package.json"),"utf8"),n=JSON.parse(t);if(S(n)&&"scripts"in n){let{scripts:r}=n;if(S(r))return r}return null}catch{return null}}function rs(e){return e===null?!1:Object.entries(e).some(([t,n])=>t.toLowerCase().includes("qmd")||typeof n=="string"&&n.toLowerCase().includes("qmd"))}async function ss(e){let t=I(e),n=e.files.filter(s=>s.path.startsWith("docs/ai/")).length;if(!t&&n<2)return{findings:[],records:[]};let r=await ns(e.repoRoot);return rs(r)?{findings:[],records:[]}:{findings:[{ruleId:"qmd-script-present",severity:"info",message:'package.json is missing a "qmd" (or equivalent) script for skill/doc search.',file:"package.json",line:null,harnesses:[],hint:'Add something like "qmd": "bun run ./scripts/qmd/qmd.bun.ts" and document usage in AGENTS.md.'}],records:[]}}async function os(e){let t=await oe(e.repoRoot);return t.hooksDirExists?t.settings?.["chat.useCustomAgentHooks"]===!0?{findings:[],records:[]}:{findings:[{ruleId:"vscode-custom-hooks",severity:"warn",message:".github/hooks/ exists but chat.useCustomAgentHooks is not true in .vscode/settings.json.",file:".vscode/settings.json",line:null,harnesses:["cursor","copilot"],hint:'Set "chat.useCustomAgentHooks": true so Cursor and Copilot load workspace hooks.'}],records:[]}:{findings:[],records:[]}}async function is(e){let t=await oe(e.repoRoot),n=[];return T(t,"chat.agentSkillsLocations","skills")||n.push({ruleId:"vscode-skills-location",severity:"warn",message:"chat.agentSkillsLocations should point at skills/ in .vscode/settings.json.",file:".vscode/settings.json",line:null,harnesses:["cursor","copilot"],hint:'Set "chat.agentSkillsLocations": { "skills/": true }.'}),T(t,"chat.agentFilesLocations","agents")||n.push({ruleId:"vscode-agents-location",severity:"warn",message:"chat.agentFilesLocations should point at agents/ in .vscode/settings.json.",file:".vscode/settings.json",line:null,harnesses:["cursor","copilot"],hint:'Set "chat.agentFilesLocations": { "agents/": true }.'}),{findings:n,records:[]}}function J(e,t,n,r,s){e.push(...s.findings),t.push(...s.records),s.records.length===0&&t.push({checkId:n,dimension:r,rawScore:s.findings.length>0?0:1})}function Ue(e,t){return e.length===0?!0:e.some(n=>t.includes(n))}function as(e,t,n){return Ue(n,e.harnesses)?t===null||t.length===0?!0:n.some(r=>t.includes(r)):!1}function cs(e,t,n){return Ue(e.harnesses,t.harnesses)?n===null||n.length===0||e.harnesses.length===0?!0:e.harnesses.some(r=>n.includes(r)):!1}function ce(e){return e.trim().replaceAll(/\s+/g," ")}function ls(e){let t=ce(e);return!(t.length<20||/^#{1,6}\s/.test(t)||/^[-*]\s/.test(t)&&t.length<40||t.includes("AGENTS.md")||t.includes("docs/ai/rules.md"))}function kt(e){return e.map(t=>ce(t)).filter(t=>t.length>0).join(`
|
|
172
|
+
`)}var xt=3,xl=80;function us(e,t){let n=e.split(`
|
|
173
|
+
`),r=kt(t.split(`
|
|
174
|
+
`)),s=[],o=new Set;for(let i=0;i<=n.length-xt;i+=1){if(o.has(i))continue;let a=n.slice(i,i+xt);if(!a.every(l=>ls(l)))continue;let c=kt(a);if(!(c.length<xl)&&r.includes(c)){s.push({startLine:i+1,lineCount:xt,sample:ce(a[0]??"")}),o.add(i);for(let l=1;l<xt;l+=1)o.add(i+l)}}return s}var ds="docs/ai/rules.md";function ps(e){let t=h(e,ds);if(t===null)return{findings:[],records:[]};let n=[];for(let r of qe){let s=h(e,r);if(s===null)continue;let o=us(s,t);for(let i of o)n.push({ruleId:"adapter-content-duplication",severity:"warn",message:`${r} duplicates ${String(i.lineCount)} lines from ${ds} near line ${String(i.startLine)}.`,file:r,line:i.startLine,harnesses:[],hint:`Replace duplicated rules with a pointer to ${ds}.`})}return{findings:n,records:[]}}function x(e,t,n,r){return{ruleId:e,severity:"info",message:t,file:r,line:null,harnesses:[],hint:n}}function ms(e){let t=w(e);if(t===null||!b(t))return{findings:[],records:[]};let n=ke(t);return/(typecheck|tsc\s+--noEmit|lint|oxlint|eslint|biome|ruff|check:md|lint:md)/i.test(n)?{findings:[],records:[]}:{findings:[x("ci-enforcement-gates","CI workflow enforcement gates were not detected.","Wire typecheck, lint, or static-analysis scripts into CI so AI-facing standards stay enforced.",t.workflows[0]?.path??t.packageJson.path)],records:[]}}function fs(e){let t=V(e);return t===null||!z(t)?{findings:[],records:[]}:t.guidanceCiWorkflows.length>0?{findings:[],records:[]}:{findings:[x("ci-guidance-lint","No CI guidance-maintenance gate was detected.","Run lint:md, check:ai-system, check:links, scan:self, or an equivalent guidance check in CI.",t.workflows[0]?.path??t.packageJson.path)],records:[]}}function gs(e){let t=w(e);if(t===null||!b(t))return{findings:[],records:[]};let n=ke(t);return/(npm\s+test|npm\s+run\s+test|vitest|jest|playwright|cypress|pytest|cargo\s+test|go\s+test)/i.test(n)?{findings:[],records:[]}:{findings:[x("ci-validation-gates","CI workflow validation gates were not detected.","Wire test scripts into CI so generated changes are checked by the same validation loop humans use.",t.workflows[0]?.path??t.packageJson.path)],records:[]}}function hs(e){let t=w(e);if(t===null||!b(t))return{findings:[],records:[]};let n=ye(t).map(a=>`${a.name} ${a.command}`).join(`
|
|
175
|
+
`),r=ke(t),s=/(scan:self|check:ai-system|lint:md|check:links|qmd)/i.test(n),o=t.prTemplates.length>0,i=/(scan:self|check:ai-system|lint:md|check:links)/i.test(r);return s&&(o||i)?{findings:[],records:[]}:{findings:[x("correction-loop-documented","No durable AI correction-loop signal was detected.","Document when repeated AI mistakes should become rules, docs, skills, tests, hooks, or CI checks, and wire guidance checks into routine validation.",t.prTemplates[0]??t.packageJson.path)],records:[]}}function ys(e){let t=w(e);return t===null||!b(t)?{findings:[],records:[]}:Uo(t,/(^|:)(test|e2e).*(file|focused|changed|related|unit|integration|watch|grep)|(--grep|--filter|--testNamePattern|--findRelatedTests)/i).length>0?{findings:[],records:[]}:{findings:[x("focused-test-commands-present","No focused validation command was detected.","Add targeted test scripts for common changed areas or file/grep-based workflows so agents do not over-run broad suites.",t.packageJson.path)],records:[]}}function Ss(e,t){return t.lastIndex=0,t.test(e)}function ks(e){return/do not|don't|not create|instead of|removed|never use|avoid|legacy|not use|no longer|there is no|\(not `|not `\.cursor\/skills|use \/skills\/|use \/agents\//i.test(e)}function xs(e,t){let n=e.split(`
|
|
176
|
+
`);for(let r=0;r<n.length;r+=1){let s=n[r]??"";if(!ks(s)&&(t.lastIndex=0,t.test(s)))return r+1}return null}var Rl=[{id:"github-skills-shadow",pattern:/\.github\/skills\//,message:"use skills/ instead of the removed .github/skills/ path"},{id:"github-agents-shadow",pattern:/\.github\/agents\//,message:"use agents/ instead of the removed .github/agents/ path"},{id:"github-hooks-scripts",pattern:/\.github\/hooks\/scripts\//,message:"use agents/scripts/ instead of .github/hooks/scripts/"},{id:"cursor-skills-shadow",pattern:/\.cursor\/skills\//,message:"use skills/ instead of .cursor/skills/"},{id:"legacy-agent-docs",pattern:/\.agent\/(rules|codebase-map|troubleshooting)\.md/,message:"move legacy .agent docs to docs/ai/ equivalents"}];function Rs(e){let t=[];for(let n of e.files){if(!n.path.endsWith(".md")&&!n.path.endsWith(".mdc"))continue;let r=h(e,n.path);if(r!==null)for(let s of Rl){let o=xs(r,s.pattern);if(o!==null){t.push({ruleId:"forbidden-legacy-paths",severity:"warn",message:`${n.path} references a legacy guidance path (${s.id}).`,file:n.path,line:o,harnesses:[],hint:s.message});continue}for(let i of ie(r))Ss(i.href,s.pattern)&&t.push({ruleId:"forbidden-legacy-paths",severity:"warn",message:`${n.path} links to a legacy guidance path (${s.id}).`,file:n.path,line:We(r,i.href),harnesses:[],hint:s.message})}}return{findings:t,records:[]}}function ws(e){let t=V(e);return t===null||!z(t)?{findings:[],records:[]}:t.guidanceMaintenanceScripts.length>0?{findings:[],records:[]}:{findings:[x("guidance-maintenance-script","No guidance maintenance script was detected.","Expose a script such as check:ai-system, lint:md, check:links, or scan:self so agents and CI can validate AI guidance drift.",t.packageJson.path)],records:[]}}function bs(e){let t=w(e);if(t===null||!b(t))return{findings:[],records:[]};let n=t.jsdocEnforcement;return[n.customChecker,n.packageScript,n.lintRules,n.stopHook].filter(Boolean).length>=2&&n.guidance||n.customChecker&&n.lintRules?{findings:[],records:[]}:{findings:[x("jsdoc-enforcement-present","JSDoc comment enforcement was not detected.","Wire oxlint jsdoc rules, a code-comment guidance doc or skill, and a custom find-missing-jsdoc checker or Stop hook so agents get deterministic JSDoc feedback.",t.packageJson.path)],records:[]}}function Cs(e){let t=w(e);if(t===null||!b(t))return{findings:[],records:[]};let n=Se(t,/(^|:)(lint|check:lint)(:|$)/i,/\b(eslint|oxlint|biome|ruff)\b/i),r=t.configs.some(s=>s.kind==="lint");return n||r?{findings:[],records:[]}:{findings:[x("lint-gate-present","No lint/static-analysis gate was detected.","Expose a lint script or static-analysis config so agents get deterministic correction messages.",t.packageJson.path)],records:[]}}function As(e){let t=e.intelligenceLayer;if(t===void 0||!_e(e,t))return{findings:[],records:[]};let n=t.localContextConventions.join(`
|
|
177
|
+
`),r=/naming|codebase-map|local-context/i.test(n),s=/comment|codebase-map|local-context/i.test(n);return t.nestedAgentsFiles.length>0||r&&s?{findings:[],records:[]}:{findings:[{ruleId:"local-context-patterns",severity:"info",message:"Local context conventions for AI-readable code were not detected.",file:"docs/ai",line:null,harnesses:[],hint:'Document naming conventions and useful "why" comment patterns, or add nested AGENTS.md files for subprojects.'}],records:[]}}function Is(e){let t=e.intelligenceLayer;if(t===void 0||t.memoryDocs.length===0)return{findings:[],records:[]};let n=t.memoryIndexes.length>0,s=!(t.packageJson.path!==null)||Object.entries(t.packageJson.scripts).some(([o,i])=>/qmd|search/i.test(o)||/qmd|search/i.test(i));return n&&s?{findings:[],records:[]}:{findings:[{ruleId:"memory-docs-indexed",severity:"info",message:"Durable memory docs should be indexed and searchable.",file:t.memoryDocs[0]??null,line:null,harnesses:[],hint:"Add a memory index such as docs/ai/codebase-map.md or docs/ai/ai-system.md, and expose a qmd/search script when package.json exists."}],records:[]}}function Es(e){let t=V(e);return t===null||!z(t)?{findings:[],records:[]}:t.aiHarnessPrTemplates.length>0?{findings:[],records:[]}:{findings:[x("pr-template-ai-harness-check","No PR template reminder for durable AI harness updates was detected.","Add a PR checklist item for recurring AI mistakes: update rules, docs, skills, tests, or diagnostics when needed.",t.prTemplates[0]??".github/PULL_REQUEST_TEMPLATE.md")],records:[]}}function vs(e){let t=w(e);if(t===null||!b(t))return{findings:[],records:[]};let n=Se(t,/(^|:)(typecheck|check:types)(:|$)/i,/\b(tsc\s+--noEmit|vue-tsc|svelte-check|mypy|pyright|cargo\s+check)\b/i),r=t.configs.some(o=>o.capabilities.includes("strict-typecheck")),s=ye(t).some(o=>/\b(mypy|pyright|cargo\s+check)\b/i.test(o.command));return n&&(r||s)?{findings:[],records:[]}:{findings:[x("strict-typecheck-present","No strict typecheck/static-analysis gate was detected.","Expose a discoverable typecheck script and strict type/static-analysis config so agents can verify structural correctness.",t.packageJson.path)],records:[]}}function Ts(e){let t=w(e);if(t===null||!b(t))return{findings:[],records:[]};let n=Se(t,/(^|:)(test|e2e|integration)(:|$)/i,/\b(vitest|jest|playwright|cypress|pytest|cargo\s+test|go\s+test)\b/i),r=t.configs.some(s=>s.kind==="test");return n||r?{findings:[],records:[]}:{findings:[x("test-gates-present","No validation test gate was detected.","Expose discoverable unit, integration, or E2E test scripts so agents can choose a safe verification loop.",t.packageJson.path)],records:[]}}var la={"shared-agents-md":"layering","shared-rules-doc":"layering","adapter-thin-claude":"layering","adapter-thin-gemini":"layering","adapter-thin-copilot":"layering","adapter-points-to-shared":"layering","skill-frontmatter":"maintainability","skill-line-count":"maintainability","agent-frontmatter":"maintainability","no-duplicate-skill-trees":"maintainability","no-duplicate-agent-trees":"maintainability","vscode-skills-location":"harnessWiring","vscode-agents-location":"harnessWiring","vscode-custom-hooks":"guardrails","skills-index":"discoverability","claude-agent-routing":"discoverability","agents-md-mentions-skills":"discoverability","skill-doc-deep-links":"discoverability","qmd-script-present":"discoverability","guidance-links-resolve":"maintainability","adapter-content-duplication":"sharing","forbidden-legacy-paths":"maintainability","strict-typecheck-present":"guardrails","lint-gate-present":"guardrails","jsdoc-enforcement-present":"guardrails","test-gates-present":"guardrails","focused-test-commands-present":"discoverability","ci-enforcement-gates":"guardrails","ci-validation-gates":"guardrails","correction-loop-documented":"maintainability","guidance-maintenance-script":"maintainability","pr-template-ai-harness-check":"maintainability","ci-guidance-lint":"guardrails","adapter-context-budget":"sharing","always-loaded-budget":"sharing","memory-docs-indexed":"discoverability","local-context-patterns":"maintainability","emphasis-keyword-density":"maintainability","identity-language-absent":"maintainability","model-interface-pinned":"guardrails","llm-output-schema-validated":"guardrails","tool-contract-tests-present":"guardrails","escalation-protocol-discoverability":"guardrails","agent-resource-budget-caps":"guardrails","tool-allowlist-inventory":"guardrails","untrusted-input-action-boundary":"guardrails","memory-write-provenance":"guardrails","high-impact-action-confirmation":"guardrails"};var wl=[["adapter-content-duplication",ps],["forbidden-legacy-paths",Rs],["strict-typecheck-present",vs],["lint-gate-present",Cs],["jsdoc-enforcement-present",bs],["test-gates-present",Ts],["focused-test-commands-present",ys],["ci-enforcement-gates",ms],["ci-validation-gates",gs],["correction-loop-documented",hs],["guidance-maintenance-script",ws],["pr-template-ai-harness-check",Es],["ci-guidance-lint",fs],["memory-docs-indexed",Is],["local-context-patterns",As]];function ua(e){let t=[],n=[];for(let[r,s]of wl){let o=s(e);t.push(...o.findings),n.push(...o.records),o.records.length===0&&n.push({checkId:r,dimension:la[r]??"maintainability",rawScore:o.findings.length>0?0:1})}return{findings:t,records:n}}async function Rt(e,t){let n=[],r=[],s=ia.filter(c=>cs(c,e,t)),o=await Promise.all(s.map(async c=>({rule:c,result:await c.check(e)})));for(let{rule:c,result:l}of o)J(n,r,c.id,c.dimension,l);if(as(e,t,["cursor","copilot"])){let c=await is(e);n.push(...c.findings),r.push(...c.records),c.records.length===0&&(r.push({checkId:"vscode-skills-location",dimension:"harnessWiring",rawScore:c.findings.some(l=>l.ruleId==="vscode-skills-location")?0:1}),r.push({checkId:"vscode-agents-location",dimension:"harnessWiring",rawScore:c.findings.some(l=>l.ruleId==="vscode-agents-location")?0:1})),J(n,r,"vscode-custom-hooks","harnessWiring",await os(e))}J(n,r,"no-duplicate-skill-trees","layering",await Qr(e)),J(n,r,"no-duplicate-agent-trees","layering",await Xr(e)),J(n,r,"qmd-script-present","discoverability",await ss(e)),J(n,r,"guidance-links-resolve","maintainability",await ts(e));let i=ua(e);n.push(...i.findings),r.push(...i.records);let a=[...Yr(e).findings,...Jr(e).findings];if(t===null||t.length===0)n.push(...a);else{let c=a.filter(l=>l.harnesses.some(m=>t.includes(m)));n.push(...c)}return{findings:n,records:r}}function Ls(e){let t=0,n=0,r=0;for(let s of e)s.severity==="error"?t+=1:s.severity==="warn"?n+=1:r+=1;return{error:t,warn:n,info:r}}import bl from"node:path";var le="AGENTS.md",da=[le,"docs/ai/rules.md"],wt=["CLAUDE.md","GEMINI.md",".github/copilot-instructions.md",".agent/README.md"];function _s(e){let t=h(e,le);if(t===null)return[];let n=C["AI2-adapter-fidelity"],r=[];for(let s of wt){let o=h(e,s);if(o===null||o.trim().length===0)continue;let i=`You are checking whether a thin per-tool adapter stays faithful to the shared guidance it points at.
|
|
176
178
|
|
|
177
179
|
The adapter should defer to the shared layer, not restate or contradict it. Find
|
|
178
180
|
claims in the ADAPTER that drift from the SHARED ENTRY: instructions the shared
|
|
179
181
|
layer does not support, stale pointers, or duplicated guidance that has diverged.
|
|
180
182
|
Be strict: only report real fidelity problems, not harmless adapter-only setup.
|
|
181
183
|
|
|
182
|
-
### SHARED ENTRY: ${
|
|
184
|
+
### SHARED ENTRY: ${le}
|
|
183
185
|
|
|
184
186
|
\`\`\`markdown
|
|
185
187
|
${t}
|
|
186
188
|
\`\`\`
|
|
187
189
|
|
|
188
|
-
### ADAPTER: ${
|
|
190
|
+
### ADAPTER: ${s}
|
|
189
191
|
|
|
190
192
|
\`\`\`markdown
|
|
191
193
|
${o}
|
|
@@ -193,13 +195,13 @@ ${o}
|
|
|
193
195
|
|
|
194
196
|
Respond with JSON only, no prose, exactly this shape:
|
|
195
197
|
{ "${n.schemaKey}": [ { "claim": "<quote from adapter>", "explanation": "<how it drifts>" } ] }
|
|
196
|
-
Return an empty array if the adapter is faithful.`;
|
|
198
|
+
Return an empty array if the adapter is faithful.`;r.push({taskId:`AI2-adapter-fidelity:${s}`,checkId:n.checkId,title:`${n.title} (${s})`,targetPaths:[s,le],schemaKey:n.schemaKey,prompt:i})}return r}function Be(e,t){let n=[];for(let r of t){let s=h(e,r);s!==null&&s.trim().length>0&&n.push({path:r,content:s})}return n}function ue(e){let t=e.files.filter(n=>n.path.startsWith("skills/")&&n.path.endsWith("SKILL.md")).map(n=>n.path);return Be(e,[...da,...t])}function j(e){return e.map(t=>`### FILE: ${t.path}
|
|
197
199
|
|
|
198
200
|
\`\`\`markdown
|
|
199
201
|
${t.content}
|
|
200
202
|
\`\`\``).join(`
|
|
201
203
|
|
|
202
|
-
`)}function
|
|
204
|
+
`)}function Fs(e){let t=ue(e);if(t.length<2)return null;let n=C["AI1-contradiction"],r=`You are auditing one repository's AI-agent guidance for internal contradictions.
|
|
203
205
|
|
|
204
206
|
Read every file below. Find places where one rule directly contradicts another \u2014
|
|
205
207
|
where an agent could not satisfy both at once. Be strict: only report clear,
|
|
@@ -209,7 +211,7 @@ ${j(t)}
|
|
|
209
211
|
|
|
210
212
|
Respond with JSON only, no prose, exactly this shape:
|
|
211
213
|
{ "${n.schemaKey}": [ { "ruleA": "<quote>", "ruleB": "<quote>", "explanation": "<why they conflict>" } ] }
|
|
212
|
-
Return an empty array if there are no clear contradictions.`;return{taskId:"AI1-contradiction",checkId:n.checkId,title:n.title,targetPaths:t.map(
|
|
214
|
+
Return an empty array if there are no clear contradictions.`;return{taskId:"AI1-contradiction",checkId:n.checkId,title:n.title,targetPaths:t.map(s=>s.path),schemaKey:n.schemaKey,prompt:r}}function Ns(e){let t=ue(e);if(t.length===0)return null;let n=C["AI4-deadweight"],r=`You are auditing one repository's AI-agent guidance for dead weight.
|
|
213
215
|
|
|
214
216
|
Apply the deletion test to each rule or instruction below: if this line were
|
|
215
217
|
deleted, would a competent coding agent behave any differently? Flag the lines a
|
|
@@ -221,7 +223,7 @@ ${j(t)}
|
|
|
221
223
|
|
|
222
224
|
Respond with JSON only, no prose, exactly this shape:
|
|
223
225
|
{ "${n.schemaKey}": [ { "rule": "<quote>", "reason": "<why deleting it changes nothing>" } ] }
|
|
224
|
-
Return an empty array if every line earns its place.`;return{taskId:"AI4-deadweight",checkId:n.checkId,title:n.title,targetPaths:t.map(
|
|
226
|
+
Return an empty array if every line earns its place.`;return{taskId:"AI4-deadweight",checkId:n.checkId,title:n.title,targetPaths:t.map(s=>s.path),schemaKey:n.schemaKey,prompt:r}}function Ps(e){let t=[le,"docs/ai/rules.md",...wt,...e.files.filter(r=>r.path.startsWith("skills/")&&r.path.endsWith("SKILL.md")).map(r=>r.path),...e.files.filter(r=>r.path.startsWith("agents/")&&r.path.endsWith(".agent.md")).map(r=>r.path)],n=Be(e,t);for(let r of e.security?.hookScripts??[])r.content.trim().length>0&&n.push({path:r.path??r.source,content:r.content});return n}function Ms(e){let t=Ps(e);if(t.length===0)return null;let n=C["AI3-security-review"],r=`You are performing a security review of one repository's AI-agent configuration:
|
|
225
227
|
its always-loaded instructions, skills, agent definitions, and lifecycle hook
|
|
226
228
|
scripts.
|
|
227
229
|
|
|
@@ -245,7 +247,7 @@ ${j(t)}
|
|
|
245
247
|
|
|
246
248
|
Respond with JSON only, no prose, exactly this shape:
|
|
247
249
|
{ "${n.schemaKey}": [ { "location": "<file or area>", "risk": "<short category>", "explanation": "<quote and why it is a risk>" } ] }
|
|
248
|
-
Return an empty array if you find no clear risks.`;return{taskId:"AI3-security-review",checkId:n.checkId,title:n.title,targetPaths:t.map(
|
|
250
|
+
Return an empty array if you find no clear risks.`;return{taskId:"AI3-security-review",checkId:n.checkId,title:n.title,targetPaths:t.map(s=>s.path),schemaKey:n.schemaKey,prompt:r}}function Hs(e){let t=ue(e);if(t.length===0)return null;let n=C["AI5-vague-rules"],r=`You are auditing one repository's AI-agent guidance for vague rules.
|
|
249
251
|
|
|
250
252
|
Flag each rule below that lacks a clear, testable decision boundary \u2014 where an
|
|
251
253
|
agent cannot determine whether it is complying. Examples: "keep files small"
|
|
@@ -257,12 +259,12 @@ ${j(t)}
|
|
|
257
259
|
|
|
258
260
|
Respond with JSON only, no prose, exactly this shape:
|
|
259
261
|
{ "${n.schemaKey}": [ { "rule": "<quote>", "reason": "<what decision boundary is missing>" } ] }
|
|
260
|
-
Return an empty array if every rule has a clear boundary.`;return{taskId:"AI5-vague-rules",checkId:n.checkId,title:n.title,targetPaths:t.map(
|
|
261
|
-
`);if(
|
|
262
|
-
`).trim()}let r
|
|
263
|
-
`)){let
|
|
264
|
-
`),process.
|
|
265
|
-
`),process.
|
|
266
|
-
`):
|
|
267
|
-
`),process.
|
|
268
|
-
`),process.
|
|
262
|
+
Return an empty array if every rule has a clear boundary.`;return{taskId:"AI5-vague-rules",checkId:n.checkId,title:n.title,targetPaths:t.map(s=>s.path),schemaKey:n.schemaKey,prompt:r}}function Ds(e){let t=[],n=Fs(e);n!==null&&t.push(n);let r=Ns(e);r!==null&&t.push(r);let s=Hs(e);s!==null&&t.push(s),t.push(..._s(e));let o=Ms(e);return o!==null&&t.push(o),t}async function bt(e){let t=bl.resolve(e),n=await Ee(t),{files:r,contents:s}=await Me(t),o=await De(t);return{version:1,root:t,tasks:Ds({repoRoot:t,harnesses:n,files:r,fileContents:s,security:o})}}import Ul from"node:path";function Os(e){let t=Array.from({length:e},(o,i)=>i),n=Array.from({length:e},()=>0);function r(o){let i=o;for(;(t[i]??i)!==i;)i=t[i]??i;let a=o;for(;a!==i;){let c=t[a]??i;t[a]=i,a=c}return i}function s(o,i){let a=r(o),c=r(i);if(a===c)return;let l=n[a]??0,m=n[c]??0;if(l<m){t[a]=c;return}if(l>m){t[c]=a;return}t[c]=a,n[a]=l+1}return{findRoot:r,union:s}}function N(e){return String(e??"").replaceAll(/\s+/g," ").trim().toLowerCase()}function Gs(e,t=20){let n=new Set,r=N(e);if(r.length<t)return n;let s=Math.max(5,Math.floor(t/4));for(let i=0;i+t<=r.length;i+=s)n.add(r.slice(i,i+t));let o=r.length-t;return o>0&&n.add(r.slice(o)),n}function js(e){let t=null,n=0,r=0;for(let[s,o]of e.entries()){let i=o.sessions.size;(i>n||i===n&&o.occurrences>r)&&(t=s,n=i,r=o.occurrences)}return t}function de(e,t=20,n=Number.POSITIVE_INFINITY){let r=e.map(m=>({sessionId:m.sessionId,normalized:N(m.text)})).filter(m=>m.normalized.length>=t),s=r.length;if(s<2)return[];let o=r.map(m=>Gs(m.normalized,t)),i=new Map;for(let[m,u]of o.entries())for(let f of u){let d=i.get(f);d===void 0?i.set(f,[m]):d.push(m)}let a=Os(s);for(let m of i.values()){let[u,...f]=m;if(u!==void 0)for(let d of f)a.union(u,d)}let c=new Map;for(let m=0;m<s;m+=1){let u=a.findRoot(m),f=c.get(u)??[];f.push(m),c.set(u,f)}let l=[];for(let m of c.values()){if(m.length<2)continue;let u=new Set,f=new Map;for(let g of m){let y=r[g],E=o[g];if(!(y===void 0||E===void 0)){u.add(y.sessionId);for(let we of E){let X=f.get(we)??{sessions:new Set,occurrences:0};X.occurrences+=1,X.sessions.add(y.sessionId),f.set(we,X)}}}if(u.size<2&&m.length<n)continue;let d=js(f);d!==null&&l.push({instruction:d,occurrences:m.length,sessions:u.size})}return l.toSorted((m,u)=>u.sessions-m.sessions||u.occurrences-m.occurrences)}import{createHash as Al}from"node:crypto";function Ws(e){let t=String(e??""),n=Al("sha256").update(t).digest("hex").slice(0,8);return`[redacted ${t.length}ch #${n}]`}function pe(e,t){return t?String(e??""):Ws(e)}function Ve(e,t){return t.some(n=>n.test(e))}function ze(e){return Ve(e,xo)}function Us(e,t){let n=e.filter(l=>l.role==="user"&&ze(l.text));if(n.length===0)return[];let r=new Set(n.map(l=>l.sessionId)),s=new Set(e.filter(l=>l.role==="user").map(l=>l.sessionId)).size,o=s===0?0:n.length/s,i={checkId:"SS3",name:_.SS3,detail:`${n.length} corrections across ${r.size} of ${s} sessions (${o.toFixed(2)} per session)`,sessions:r.size,occurrences:n.length,snippet:null},a=n.map(l=>({sessionId:l.sessionId,text:l.text})),c=de(a).map(l=>{let m=pe(l.instruction,t);return{checkId:"SS3",name:_.SS3,detail:`Recurring friction ${m}: corrected in ${l.sessions} sessions (${l.occurrences} times)`,sessions:l.sessions,occurrences:l.occurrences,snippet:m}});return[i,...c]}function Bs(e,t){return e.keywords.length===0?t.includes(N(e.text)):e.keywords.some(n=>new RegExp(`\\b${n}\\b`).test(t))}function Vs(e,t){if(t.length===0)return[];let n=new Map;for(let s of e){let o=n.get(s.sessionId)??[];o.push(s),n.set(s.sessionId,o)}let r=new Map;for(let[s,o]of n.entries()){let i=o.map(a=>N(a.text));for(let[a,c]of o.entries()){if(c.role!=="user"||!ze(c.text))continue;let l=[i[a-1],i[a],i[a+1]].filter(m=>typeof m=="string").join(`
|
|
263
|
+
`);if(Ro.test(l))for(let m of t){if(!Bs(m,l))continue;let u=r.get(m.text)??{rule:m.text,occurrences:0,sessions:new Set};u.occurrences+=1,u.sessions.add(s),r.set(m.text,u)}}}return[...r.values()].toSorted((s,o)=>o.sessions.size-s.sessions.size||o.occurrences-s.occurrences).map(s=>({checkId:"SS2",name:_.SS2,detail:`Possibly ignored rule "${s.rule}": ${s.occurrences} corrections in tool-use context across ${s.sessions.size} sessions`,sessions:s.sessions.size,occurrences:s.occurrences,snippet:s.rule}))}function zs(e){return Ve(e,ko)}function qs(e,t){let n=e.filter(r=>r.role==="user"&&zs(r.text)).map(r=>({sessionId:r.sessionId,text:r.text}));return de(n,void 0,3).map(r=>{let s=pe(r.instruction,t),o=r.sessions>=2?`repeated across ${r.sessions} sessions (${r.occurrences} times)`:`repeated ${r.occurrences} times within a single session`;return{checkId:"SS4",name:_.SS4,detail:`Candidate missing rule ${s}: ${o} but likely not in committed guidance`,sessions:r.sessions,occurrences:r.occurrences,snippet:s}})}function Ks(e,t){let n=e.filter(r=>r.role==="user").map(r=>({sessionId:r.sessionId,text:r.text}));return de(n).map(r=>{let s=pe(r.instruction,t);return{checkId:"SS1",name:_.SS1,detail:`Repeated prompt ${s} seen in ${r.sessions} sessions (${r.occurrences} times)`,sessions:r.sessions,occurrences:r.occurrences,snippet:s}})}function Ys(e,t,n){return[...qs(e,n),...Vs(e,t),...Us(e,n),...Ks(e,n)]}import{homedir as El}from"node:os";import ma from"node:path";function Js(e){return e!==null&&e.length>0?ma.resolve(e):ma.join(El(),".claude","projects")}import fa from"node:path";import{lstatSync as vl}from"node:fs";function Xs(e){try{return vl(e).mtimeMs}catch{return null}}import{readdirSync as Tl}from"node:fs";function Qs(e){try{return Tl(e,{withFileTypes:!0})}catch{return[]}}function Zs(e,t){let n=[];for(let r of Qs(e)){if(r.isSymbolicLink()||!r.isFile()||fa.extname(r.name).toLowerCase()!==".jsonl")continue;let s=fa.join(e,r.name),o=Xs(s);o!==null&&n.push({file:s,mtimeMs:o})}return n.toSorted((r,s)=>s.mtimeMs-r.mtimeMs).slice(0,Math.max(0,t)).map(r=>r.file)}import{existsSync as _l,statSync as Fl}from"node:fs";import Nl from"node:path";import Ll from"node:path";function eo(e){return Ll.resolve(e).replaceAll(/[/\\]/g,"-")}function to(e,t){let n=Nl.join(e,eo(t));return!_l(n)||!Fl(n).isDirectory()?null:n}import{createReadStream as Pl}from"node:fs";import Ml from"node:path";import{createInterface as Hl}from"node:readline";function no(e){let{type:t,message:n}=e;return typeof t=="string"&&t.trim().length>0?t.trim().toLowerCase():S(n)&&typeof n.role=="string"?n.role.trim().toLowerCase():""}function ro(e){let t=e.trim();return t.length<5?!0:wo.some(n=>n.test(t))}function so(e){if(!S(e))return"";let{message:t}=e;if(!S(t))return"";let{content:n}=t,r="";if(typeof n=="string")r=n.trim();else if(Array.isArray(n)){let o=[];for(let i of n)S(i)&&i.type==="text"&&typeof i.text=="string"&&o.push(i.text);r=o.join(`
|
|
264
|
+
`).trim()}let s=r.replaceAll(/<system-reminder>[\s\S]*?<\/system-reminder>/g,"").trim();return ro(s)?"":s}function oo(e){try{return JSON.parse(e)}catch{return}}async function io(e){let t=Ml.basename(e,".jsonl"),n=[],r=Hl({input:Pl(e,{encoding:"utf8"}),crlfDelay:1/0});try{for await(let s of r){let o=s.trim();if(o.length===0)continue;let i=oo(o);if(!S(i))continue;let a=so(i);a.length!==0&&n.push({sessionId:t,role:no(i),text:a})}}catch{return n}return n}async function Dl(e){let t=Js(e.sessionRoot),n=to(t,e.repoRoot);if(n===null)return[];let r=Zs(n,e.maxSessions);return(await Promise.all(r.map(o=>io(o)))).flat()}var Ol={harness:"claude",collectMessages:Dl},ga=Ol;import jl from"node:path";import{readFile as $l}from"node:fs/promises";async function ao(e){try{return await $l(e,"utf8")}catch{return null}}function co(e){return N(e).replaceAll(/[^a-z0-9 ]/g," ").replaceAll(/\s+/g," ").trim()}var Gl=new Set(["the","and","that","with","from","this","they","have","been","were","what","just","when","where","your","you","are","was","for","not","out","into","about","them","then","than","its","our","all","any","can","has","had","but","only","still","very","well","like","use","using","should","must"]);function lo(e){let t=[];for(let n of e.split(`
|
|
265
|
+
`)){let r=n.trim();if(/^[-*]\s*(don't|dont|never|always|do not|important)\b[:\s-]*(.*)$/i.exec(r)===null)continue;let o=r.replace(/^[-*]\s*/,""),i=co(o).split(/\s+/).filter(a=>a.length>=3&&!Gl.has(a));t.push({text:o,keywords:i})}return t}var Wl=["CLAUDE.md","AGENTS.md"];async function uo(e){let t=await Promise.all(Wl.map(n=>ao(jl.join(e,n))));for(let n of t){if(n===null)continue;let r=lo(n);if(r.length>0)return r}return[]}async function Ct(e,t=ga){let n=Ul.resolve(e.repoRoot),r=await t.collectMessages({...e,repoRoot:n}),s=new Set(r.map(a=>a.sessionId)).size;if(r.length===0)return{version:1,root:n,harness:t.harness,tier:"extended",status:"no-sessions",sessionsAnalyzed:0,redacted:!e.includeRawSnippets,findings:[]};let o=await uo(n),i=Ys(r,o,e.includeRawSnippets);return{version:1,root:n,harness:t.harness,tier:"extended",status:"run",sessionsAnalyzed:s,redacted:!e.includeRawSnippets,findings:i}}var ha={error:3,warn:2,info:1};function At(e,t){let n=ha[t];return e.some(r=>ha[r.severity]>=n)}async function po(e){let t=Bl.resolve(e.repoRoot),n=Ci(),r=await Ee(t),{files:s,contents:o}=await Me(t),i=await xr(t),a=await De(t),c=await mr(t),l={repoRoot:t,harnesses:r,files:s,fileContents:o,intelligenceLayer:i,security:a,boundary:c},m=Cn(l);l.contextBudget=m;let{findings:u,records:f}=await Rt(l,e.harnessFilter),d=Ls(u),g=In(u),y=hn(s,r),E=await oe(t),we=await Dn(l,E,u,y),X=rr(f,u,y,we,l),ya=await an(l,E),Sa=await n,ka=gt(i),xa=e.aiReviewResults===void 0?Et:Xe(e.aiReviewResults);return{version:Sa.version,root:t,harnesses:r,total_score:X.total_score,score_scope:X.score_scope,inventory:{fileCount:s.length,files:s},sharing:y,metaHarness:X,harnessGapMatrix:ya,harnessOptimization:we,intelligenceLayer:ka,contextBudget:m,aiReview:xa,findings:u,failureModeExposure:g,summary:d}}async function mo(){let e=Gt(process.argv.slice(2));if(e.help){jt(),process.exitCode=0;return}if(e.emitAiTasks){try{let t=await bt(e.repoRoot);process.stdout.write(`${JSON.stringify(t,null,2)}
|
|
266
|
+
`),process.exitCode=0}catch(t){let n=t instanceof Error?t.message:String(t);process.stderr.write(`error: ${n}
|
|
267
|
+
`),process.exitCode=2}return}if(e.sessionAnalysis){try{let t=await Ct({repoRoot:e.repoRoot,sessionRoot:e.sessionRoot,maxSessions:e.maxSessions,includeRawSnippets:e.includeRawSnippets});e.format==="json"?process.stdout.write(`${JSON.stringify(t,null,2)}
|
|
268
|
+
`):Ut(t),process.exitCode=0}catch(t){let n=t instanceof Error?t.message:String(t);process.stderr.write(`error: ${n}
|
|
269
|
+
`),process.exitCode=2}return}try{let t=e.ingestResultsPath===null?void 0:await Ot(e.ingestResultsPath),n=await po({repoRoot:e.repoRoot,harnessFilter:e.harnessFilter,...t===void 0?{}:{aiReviewResults:t}});e.format==="json"?Wt(n):mn(n),process.exitCode=At(n.findings,e.failOn)?1:0}catch(t){let n=t instanceof Error?t.message:String(t);process.stderr.write(`error: ${n}
|
|
270
|
+
`),process.exitCode=2}}await mo();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paniolo/scan",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "The AI Technical Debt Scanner — diagnostic-only CLI that scores your repo's AI harness across Copilot, Cursor, Codex, Antigravity, Claude Code, and Gemini. No writes, no telemetry.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|