@paniolo/scan 0.0.2 → 0.0.3

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.
Files changed (3) hide show
  1. package/README.md +19 -0
  2. package/dist/cli.js +112 -46
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -3,12 +3,26 @@
3
3
  > Scan a repository for AI harness performance — how well your repo is set up for
4
4
  > coding agents across Copilot, Cursor, Codex, Antigravity, Claude Code, and Gemini.
5
5
 
6
+ **New here?** Read [Intelligence layer and meta-harness](./docs/intelligence-layer.md) — what
7
+ a meta-harness is, why your repo needs one, how this scan connects to
8
+ [Paniolo](https://paniolo.ai/), and where the open-source workflow fits.
9
+
6
10
  **100% diagnostic.** Reports findings only — no scaffolding, autofix, or file writes.
7
11
 
8
12
  ```bash
9
13
  npx @paniolo/scan
10
14
  ```
11
15
 
16
+ ## Cursor
17
+
18
+ Install the [**paniolo-ai/scan**](https://github.com/paniolo-ai/scan) skill to run the scan from
19
+ **Cursor Agent** and optionally remediate findings:
20
+
21
+ 1. `npx skills add paniolo-ai/scan -a cursor`
22
+ 2. In Agent chat: _"Use the paniolo-scan skill to scan this repo and summarize findings."_
23
+
24
+ Filter Cursor-specific rule output: `npx @paniolo/scan --harness cursor`.
25
+
12
26
  ## Quick start
13
27
 
14
28
  ```bash
@@ -27,6 +41,8 @@ npx @paniolo/scan ../songshare-effect
27
41
 
28
42
  ## Documentation
29
43
 
44
+ - [Intelligence layer and meta-harness](./docs/intelligence-layer.md) — why meta-harness
45
+ infrastructure matters, open-source scan/workflow, and [Paniolo](https://paniolo.ai/)
30
46
  - [Overview](./docs/overview.md) — problem, scope, supported harnesses
31
47
  - [Meta-harness model](./docs/meta-harness.md) — what “good” means, evaluation dimensions,
32
48
  calibration
@@ -35,6 +51,9 @@ npx @paniolo/scan ../songshare-effect
35
51
  intelligence-layer scanning
36
52
  - [Architecture](./docs/architecture.md) — pipeline, rule model, roadmap
37
53
  - [Rules catalog](./docs/rules-catalog.md) — built-in rules by dimension and status
54
+ - [Competitive analysis](./docs/competitive-analysis.md) — landscape, AgentLint reuse, ideas
55
+ - [Distribution and remediation](./docs/distribution-and-remediation.md) — diagnostic core plus
56
+ an optional agent-driven fix adapter
38
57
  - [CI integration](./docs/ci.md) — exit codes and GitHub Actions
39
58
  - [npm publishing steps](./docs/npm-publishing-steps.md) — release runbook for publishing
40
59
  `npx @paniolo/scan`
package/dist/cli.js CHANGED
@@ -1,22 +1,43 @@
1
1
  #!/usr/bin/env node
2
- import Qi from"node:path";function fe(e){process.stdout.write(`${JSON.stringify(e,null,2)}
3
- `)}import{readFile as Ke}from"node:fs/promises";import Ye from"node:path";var E=["copilot","cursor","codex","antigravity","claude","gemini"],We=new Set(["shared","skills","agents"]);function Ue(e,t){return e.harness!==void 0?t.includes(e.harness)?[e.harness]:[]:We.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 qe(e,t){return t.length>=2?!0:We.has(e.layer)||e.path==="AGENTS.md"}import{access as fn}from"node:fs/promises";import gn from"node:path";var v=75,ge=300,Y=["CLAUDE.md","GEMINI.md",".github/copilot-instructions.md"];function y(e,t){return e.files.some(n=>n.path===t)}function f(e,t){return e.fileContents.get(t)??null}function I(e,t){return e.files.find(s=>s.path===t)?.lines??null}function Be(e){return e.includes("AGENTS.md")||e.includes("docs/ai/rules.md")}function me(e){return e.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1]??null}function G(e,t){return new RegExp(`^${t}:`,"m").test(e)}async function _(e,t){try{return await fn(gn.join(e,t)),!0}catch{return!1}}function X(e,t){return e.files.filter(n=>n.path.startsWith(t)).map(n=>n.path)}function S(e){return e.files.some(t=>t.path.startsWith("skills/")&&t.path.endsWith("/SKILL.md"))}function Q(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 Z(e){return/agent routing/i.test(e)&&e.includes("|")&&/agents\/.*\.agent\.md/.test(e)}function w(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var mn=50,hn={copilot:".github/copilot-instructions.md",claude:"CLAUDE.md",gemini:"GEMINI.md"};function O(e,t,n){let s=e.settings?.[t];if(w(s)&&Object.keys(s).some(a=>a.startsWith(n)))return!0;if(e.settingsRaw===null)return!1;let i=t.replaceAll(".",String.raw`\.`);return new RegExp(`"${i}"\\s*:\\s*\\{[^}]*"${n}[^"]*"`).test(e.settingsRaw)}function Ve(e){return e.files.some(t=>t.path.startsWith("agents/")&&t.path.endsWith(".agent.md"))}function ee(e,t){let n=I(e,t);return n===null?!1:n<=mn}function N(e){return hn[e]??null}function ze(e,t){let n=f(e,t);return n===null?!1:n.includes("AGENTS.md")||n.includes("docs/ai/rules.md")}function he(e){return e.files.some(t=>t.path.startsWith(".agent/workflows/"))}function ye(e,t){if(!S(e))return!1;if(y(e,"docs/ai/available-skills.md"))return!0;let n=f(e,"AGENTS.md");if(n!==null&&Q(n))return!0;let s=N(t);if(s===null)return!1;let i=f(e,s);return i!==null&&i.includes("skills/")}function Je(e){let t=f(e,"CLAUDE.md");return t!==null&&Z(t)}var Xe={sharedSkillsDiscoverable:"Shared skills discoverable",customAgents:"Custom agents",lifecycleHooks:"Lifecycle hooks",thinAdapter:"Thin adapter",workflows:"Workflows / playbooks"},te=["sharedSkillsDiscoverable","customAgents","lifecycleHooks","thinAdapter","workflows"],yn="Harness not detected";async function kn(e){try{return await Ke(Ye.join(e,".claude/settings.json"),"utf8")}catch{return null}}async function Sn(e){try{return await Ke(Ye.join(e,".codex/hooks.json"),"utf8"),!0}catch{return!1}}function c(e,t){return{status:e,detail:t}}function wn(){function e(){return{copilot:c("na",""),cursor:c("na",""),codex:c("na",""),antigravity:c("na",""),claude:c("na",""),gemini:c("na","")}}return{sharedSkillsDiscoverable:e(),customAgents:e(),lifecycleHooks:e(),thinAdapter:e(),workflows:e()}}function bn(e,t){if(!S(t.context))return c("no","No skills/ tree");switch(e){case"copilot":case"cursor":return O(t.vscode,"chat.agentSkillsLocations","skills")?c("yes","skills/ wired in chat.agentSkillsLocations"):c("partial","skills/ present but not wired in VS Code settings");case"codex":return ye(t.context,"codex")?c("partial","skills/ with prose discovery via AGENTS.md or skill index"):c("partial","skills/ present; no documented discovery workflow");case"claude":case"gemini":return ye(t.context,e)?c("partial","Prose discovery via skill index or adapter pointers"):c("no","skills/ without index or adapter pointers");case"antigravity":return he(t.context)?c("yes","skills/ with workflow playbooks"):c("partial","skills/ present without workflow playbooks");default:return c("no","Unknown harness")}}function Cn(e,t){let n=Ve(t.context);switch(e){case"copilot":case"cursor":return O(t.vscode,"chat.agentFilesLocations","agents")&&n?c("yes","agents/ wired in chat.agentFilesLocations"):n?c("partial","agents/ present but not wired in VS Code settings"):c("no","No agents/ tree or VS Code agent locations");case"codex":return t.context.files.some(i=>i.path.startsWith(".codex/agents/"))&&n?c("yes",".codex/agents wrappers with shared agents/"):n?c("partial","agents/ present without .codex/agents wrappers"):c("no","No custom agents configured");case"claude":return Je(t.context)?c("yes","Agent routing table in CLAUDE.md"):n?c("partial","agents/ present without routing table in CLAUDE.md"):c("no","No agent routing or agents/ tree");case"gemini":{if(!n)return c("no","No agents/ tree");let s=N("gemini"),i=s===null?null:t.context.fileContents.get(s)??null;return i!==null&&i.includes("agents/")?c("partial","agents/ referenced from GEMINI.md"):c("partial","agents/ present; document routing in GEMINI.md")}case"antigravity":return c("na","Uses workflow playbooks instead of custom agents");default:return c("no","Unknown harness")}}function xn(e,t){let n=t.vscode.hooksDirExists,s=t.vscode.settings?.["chat.useCustomAgentHooks"]===!0;switch(e){case"copilot":case"cursor":return n&&s?c("yes",".github/hooks/ with chat.useCustomAgentHooks"):n||s?c("partial","Hooks partially configured in VS Code workspace"):c("no","No lifecycle hooks configured");case"codex":return t.codexHooksExists?c("yes",".codex/hooks.json present"):n?c("partial","Shared .github/hooks/ only; no .codex/hooks.json"):c("no","No Codex hooks configured");case"claude":return t.claudeSettingsRaw!==null&&/"hooks"\s*:/.test(t.claudeSettingsRaw)?c("yes","Hooks in .claude/settings.json"):n?c("partial","Shared .github/hooks/ only; no .claude hooks"):c("no","No Claude hooks configured");case"gemini":return n&&s?c("partial","Shared VS Code hooks only; no Gemini-native hooks"):c("no","No lifecycle hooks for Gemini");case"antigravity":return c("na","No hook surface for Antigravity workflows");default:return c("no","Unknown harness")}}function Ln(e,t){switch(e){case"copilot":{let n=N("copilot");return n===null||!t.context.files.some(s=>s.path===n)?c("no","Missing .github/copilot-instructions.md"):ee(t.context,n)?c("yes","Copilot instructions within line budget"):c("partial","Copilot instructions exceed thin adapter budget")}case"cursor":{let n=t.context.files.some(i=>i.path.startsWith(".cursor/rules/")),s=O(t.vscode,"chat.agentSkillsLocations","skills")&&O(t.vscode,"chat.agentFilesLocations","agents");return n||s?c("yes","Cursor rules or VS Code agent settings configured"):c("partial","Cursor detected without rules or agent settings")}case"codex":return t.context.files.some(s=>s.path.startsWith(".codex/"))?t.context.files.some(s=>s.path==="AGENTS.md")?c("yes",".codex/ with shared AGENTS.md entry"):c("partial",".codex/ without root AGENTS.md"):c("no","No .codex/ config surface");case"claude":{let n=N("claude");if(n===null||!t.context.files.some(o=>o.path===n))return c("no","Missing CLAUDE.md");let s=ee(t.context,n),i=ze(t.context,n);return s&&i?c("yes","Thin CLAUDE.md referencing shared layers"):s?c("partial","CLAUDE.md thin but missing shared layer pointers"):c("partial","CLAUDE.md exceeds thin adapter budget")}case"gemini":{let n=N("gemini");return n===null||!t.context.files.some(s=>s.path===n)?c("no","Missing GEMINI.md"):ee(t.context,n)?c("yes","Thin GEMINI.md adapter"):c("partial","GEMINI.md exceeds thin adapter budget")}case"antigravity":return c("partial","Workflows only; no classic root adapter");default:return c("no","Unknown harness")}}function An(e,t){return e!=="antigravity"?c("na","Workflow playbooks are Antigravity-specific"):he(t.context)?c("yes",".agent/workflows/ playbooks present"):c("no","No .agent/workflows/ playbooks")}function Rn(e,t,n){switch(e){case"sharedSkillsDiscoverable":return bn(t,n);case"customAgents":return Cn(t,n);case"lifecycleHooks":return xn(t,n);case"thinAdapter":return Ln(t,n);case"workflows":return An(t,n);default:return c("no","Unknown capability")}}async function En(e,t){let n=E.filter(o=>e.harnesses.includes(o)),s={context:e,vscode:t,claudeSettingsRaw:await kn(e.repoRoot),codexHooksExists:await Sn(e.repoRoot)},i=wn();for(let o of te){let r=i[o];for(let a of E){if(!e.harnesses.includes(a)){r[a]=c("na",yn);continue}r[a]=Rn(o,a,s)}}return{capabilities:te,harnesses:n,matrix:i}}function Qe(e){switch(e){case"yes":return"\u2713";case"partial":return"~";case"no":return"\u2717";case"na":return"\u2014"}}var Ze=En;var et=["error","warn","info"],vn={error:"ERROR",warn:"WARN",info:"INFO"},In={layering:"Layering",sharing:"Sharing",discoverability:"Discoverability",harnessWiring:"Harness wiring",maintainability:"Maintainability",guardrails:"Guardrails"},Fn=["layering","sharing","discoverability","harnessWiring","maintainability","guardrails"],Hn=["copilot","cursor","codex","antigravity","claude","gemini"];function Pn(e){let t=vn[e.severity],n=e.file===null?"":` ${e.file}${e.line===null?"":`:${String(e.line)}`}`,s=e.harnesses.length===0?"":`
2
+ import{readFile as Mr}from"node:fs/promises";import _r from"node:path";import{access as Ln}from"node:fs/promises";import Fn from"node:path";var L=75,ke=300,Q=["CLAUDE.md","GEMINI.md",".github/copilot-instructions.md"];function k(e,t){return e.files.some(n=>n.path===t)}function p(e,t){return e.fileContents.get(t)??null}function F(e,t){return e.files.find(s=>s.path===t)?.lines??null}function Je(e){return e.includes("AGENTS.md")||e.includes("docs/ai/rules.md")}function we(e){return e.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1]??null}function G(e,t){return new RegExp(`^${t}:`,"m").test(e)}async function O(e,t){try{return await Ln(Fn.join(e,t)),!0}catch{return!1}}function Z(e,t){return e.files.filter(n=>n.path.startsWith(t)).map(n=>n.path)}function S(e){return e.files.some(t=>t.path.startsWith("skills/")&&t.path.endsWith("/SKILL.md"))}function ee(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 te(e){return/agent routing/i.test(e)&&e.includes("|")&&/agents\/.*\.agent\.md/.test(e)}function h(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var Tn=[{min:85,grade:"excellent"},{min:70,grade:"good"},{min:50,grade:"fair"},{min:0,grade:"poor"}];function R(e){for(let{min:t,grade:n}of Tn)if(e>=t)return n;return"poor"}function ze(e,t){return t===0?0:e>=80?95:e>=65?82:e>=50?68:e>=30?52:35}var A={"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"]}};function Ye(e){return typeof e=="string"&&e in A}var Hn=12,Xe={status:"not-run",score:null,grade:"not-run",checks:[],findings:[]};function Qe(e){if(!h(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,s)=>Nn(n,s))}}function Nn(e,t){if(!h(e))throw new TypeError(`AI review result #${String(t)} must be an object.`);let{taskId:n,checkId:s,data:i}=e;if(typeof n!="string"||n.length===0)throw new TypeError(`AI review result #${String(t)} is missing a "taskId".`);if(!Ye(s))throw new TypeError(`AI review result "${n}" has an unknown checkId: ${String(s)}.`);return Pn(n,s,i),{taskId:n,checkId:s,data:i}}function Pn(e,t,n){let s=A[t];if(!h(n))throw new TypeError(`AI review result "${e}" data must be an object.`);let i=n[s.schemaKey];if(!Array.isArray(i))throw new TypeError(`AI review result "${e}" must have an array "${s.schemaKey}".`);for(let[r,o]of i.entries()){if(!h(o))throw new TypeError(`AI review result "${e}" ${s.schemaKey}[${String(r)}] must be an object.`);for(let a of s.entryFields){let c=o[a];if(typeof c!="string"||c.trim().length===0)throw new TypeError(`AI review result "${e}" ${s.schemaKey}[${String(r)}] is missing "${a}".`)}}}function Dn(e){let t=e.indexOf(":");return t===-1?null:e.slice(t+1)}function $n(e){if(!h(e.data))return[];let t=e.data[A[e.checkId].schemaKey];return Array.isArray(t)?t.filter(n=>h(n)):[]}function W(e,t){let n=e[t];return typeof n=="string"?n:""}function Mn(e){let t=$n(e);if(e.checkId==="AI1-contradiction")return t.map(s=>({ruleId:"ai-contradiction",severity:"warn",message:`Contradiction: ${W(s,"explanation")}`,file:null,line:null,harnesses:[],hint:`"${W(s,"ruleA")}" conflicts with "${W(s,"ruleB")}"`}));let n=Dn(e.taskId);return t.map(s=>({ruleId:"ai-adapter-fidelity",severity:"warn",message:`Adapter drift: ${W(s,"explanation")}`,file:n,line:null,harnesses:[],hint:`Adapter claim: "${W(s,"claim")}"`}))}function _n(e,t){let n={"AI1-contradiction":"ai-contradiction","AI2-adapter-fidelity":"ai-adapter-fidelity"},s=new Set,i=[];for(let r of e){if(s.has(r.checkId))continue;s.add(r.checkId);let o=n[r.checkId],a=t.filter(c=>c.ruleId===o).length;i.push({checkId:r.checkId,title:A[r.checkId].title,findingsCount:a,passed:a===0})}return i}function Ze(e){let t=e.flatMap(s=>Mn(s)),n=Math.max(0,100-Hn*t.length);return{status:"run",score:n,grade:R(n),checks:_n(e,t),findings:t}}function Se(e){process.stdout.write(`${JSON.stringify(e,null,2)}
3
+ `)}import{readFile as ot}from"node:fs/promises";import at from"node:path";var T=["copilot","cursor","codex","antigravity","claude","gemini"],et=new Set(["shared","skills","agents"]);function tt(e,t){return e.harness!==void 0?t.includes(e.harness)?[e.harness]:[]:et.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 nt(e,t){return t.length>=2?!0:et.has(e.layer)||e.path==="AGENTS.md"}var jn=50,Gn={copilot:".github/copilot-instructions.md",claude:"CLAUDE.md",gemini:"GEMINI.md"};function U(e,t,n){let s=e.settings?.[t];if(h(s)&&Object.keys(s).some(a=>a.startsWith(n)))return!0;if(e.settingsRaw===null)return!1;let i=t.replaceAll(".",String.raw`\.`);return new RegExp(`"${i}"\\s*:\\s*\\{[^}]*"${n}[^"]*"`).test(e.settingsRaw)}function st(e){return e.files.some(t=>t.path.startsWith("agents/")&&t.path.endsWith(".agent.md"))}function ne(e,t){let n=F(e,t);return n===null?!1:n<=jn}function $(e){return Gn[e]??null}function it(e,t){let n=p(e,t);return n===null?!1:n.includes("AGENTS.md")||n.includes("docs/ai/rules.md")}function be(e){return e.files.some(t=>t.path.startsWith(".agent/workflows/"))}function Ce(e,t){if(!S(e))return!1;if(k(e,"docs/ai/available-skills.md"))return!0;let n=p(e,"AGENTS.md");if(n!==null&&ee(n))return!0;let s=$(t);if(s===null)return!1;let i=p(e,s);return i!==null&&i.includes("skills/")}function rt(e){let t=p(e,"CLAUDE.md");return t!==null&&te(t)}var ct={sharedSkillsDiscoverable:"Shared skills discoverable",customAgents:"Custom agents",lifecycleHooks:"Lifecycle hooks",thinAdapter:"Thin adapter",workflows:"Workflows / playbooks"},se=["sharedSkillsDiscoverable","customAgents","lifecycleHooks","thinAdapter","workflows"],On="Harness not detected";async function Wn(e){try{return await ot(at.join(e,".claude/settings.json"),"utf8")}catch{return null}}async function Un(e){try{return await ot(at.join(e,".codex/hooks.json"),"utf8"),!0}catch{return!1}}function l(e,t){return{status:e,detail:t}}function qn(){function e(){return{copilot:l("na",""),cursor:l("na",""),codex:l("na",""),antigravity:l("na",""),claude:l("na",""),gemini:l("na","")}}return{sharedSkillsDiscoverable:e(),customAgents:e(),lifecycleHooks:e(),thinAdapter:e(),workflows:e()}}function Bn(e,t){if(!S(t.context))return l("no","No skills/ tree");switch(e){case"copilot":case"cursor":return U(t.vscode,"chat.agentSkillsLocations","skills")?l("yes","skills/ wired in chat.agentSkillsLocations"):l("partial","skills/ present but not wired in VS Code settings");case"codex":return Ce(t.context,"codex")?l("partial","skills/ with prose discovery via AGENTS.md or skill index"):l("partial","skills/ present; no documented discovery workflow");case"claude":case"gemini":return Ce(t.context,e)?l("partial","Prose discovery via skill index or adapter pointers"):l("no","skills/ without index or adapter pointers");case"antigravity":return be(t.context)?l("yes","skills/ with workflow playbooks"):l("partial","skills/ present without workflow playbooks");default:return l("no","Unknown harness")}}function Vn(e,t){let n=st(t.context);switch(e){case"copilot":case"cursor":return U(t.vscode,"chat.agentFilesLocations","agents")&&n?l("yes","agents/ wired in chat.agentFilesLocations"):n?l("partial","agents/ present but not wired in VS Code settings"):l("no","No agents/ tree or VS Code agent locations");case"codex":return t.context.files.some(i=>i.path.startsWith(".codex/agents/"))&&n?l("yes",".codex/agents wrappers with shared agents/"):n?l("partial","agents/ present without .codex/agents wrappers"):l("no","No custom agents configured");case"claude":return rt(t.context)?l("yes","Agent routing table in CLAUDE.md"):n?l("partial","agents/ present without routing table in CLAUDE.md"):l("no","No agent routing or agents/ tree");case"gemini":{if(!n)return l("no","No agents/ tree");let s=$("gemini"),i=s===null?null:t.context.fileContents.get(s)??null;return i!==null&&i.includes("agents/")?l("partial","agents/ referenced from GEMINI.md"):l("partial","agents/ present; document routing in GEMINI.md")}case"antigravity":return l("na","Uses workflow playbooks instead of custom agents");default:return l("no","Unknown harness")}}function Kn(e,t){let n=t.vscode.hooksDirExists,s=t.vscode.settings?.["chat.useCustomAgentHooks"]===!0;switch(e){case"copilot":case"cursor":return n&&s?l("yes",".github/hooks/ with chat.useCustomAgentHooks"):n||s?l("partial","Hooks partially configured in VS Code workspace"):l("no","No lifecycle hooks configured");case"codex":return t.codexHooksExists?l("yes",".codex/hooks.json present"):n?l("partial","Shared .github/hooks/ only; no .codex/hooks.json"):l("no","No Codex hooks configured");case"claude":return t.claudeSettingsRaw!==null&&/"hooks"\s*:/.test(t.claudeSettingsRaw)?l("yes","Hooks in .claude/settings.json"):n?l("partial","Shared .github/hooks/ only; no .claude hooks"):l("no","No Claude hooks configured");case"gemini":return n&&s?l("partial","Shared VS Code hooks only; no Gemini-native hooks"):l("no","No lifecycle hooks for Gemini");case"antigravity":return l("na","No hook surface for Antigravity workflows");default:return l("no","Unknown harness")}}function Jn(e,t){switch(e){case"copilot":{let n=$("copilot");return n===null||!t.context.files.some(s=>s.path===n)?l("no","Missing .github/copilot-instructions.md"):ne(t.context,n)?l("yes","Copilot instructions within line budget"):l("partial","Copilot instructions exceed thin adapter budget")}case"cursor":{let n=t.context.files.some(i=>i.path.startsWith(".cursor/rules/")),s=U(t.vscode,"chat.agentSkillsLocations","skills")&&U(t.vscode,"chat.agentFilesLocations","agents");return n||s?l("yes","Cursor rules or VS Code agent settings configured"):l("partial","Cursor detected without rules or agent settings")}case"codex":return t.context.files.some(s=>s.path.startsWith(".codex/"))?t.context.files.some(s=>s.path==="AGENTS.md")?l("yes",".codex/ with shared AGENTS.md entry"):l("partial",".codex/ without root AGENTS.md"):l("no","No .codex/ config surface");case"claude":{let n=$("claude");if(n===null||!t.context.files.some(r=>r.path===n))return l("no","Missing CLAUDE.md");let s=ne(t.context,n),i=it(t.context,n);return s&&i?l("yes","Thin CLAUDE.md referencing shared layers"):s?l("partial","CLAUDE.md thin but missing shared layer pointers"):l("partial","CLAUDE.md exceeds thin adapter budget")}case"gemini":{let n=$("gemini");return n===null||!t.context.files.some(s=>s.path===n)?l("no","Missing GEMINI.md"):ne(t.context,n)?l("yes","Thin GEMINI.md adapter"):l("partial","GEMINI.md exceeds thin adapter budget")}case"antigravity":return l("partial","Workflows only; no classic root adapter");default:return l("no","Unknown harness")}}function zn(e,t){return e!=="antigravity"?l("na","Workflow playbooks are Antigravity-specific"):be(t.context)?l("yes",".agent/workflows/ playbooks present"):l("no","No .agent/workflows/ playbooks")}function Yn(e,t,n){switch(e){case"sharedSkillsDiscoverable":return Bn(t,n);case"customAgents":return Vn(t,n);case"lifecycleHooks":return Kn(t,n);case"thinAdapter":return Jn(t,n);case"workflows":return zn(t,n);default:return l("no","Unknown capability")}}async function Xn(e,t){let n=T.filter(r=>e.harnesses.includes(r)),s={context:e,vscode:t,claudeSettingsRaw:await Wn(e.repoRoot),codexHooksExists:await Un(e.repoRoot)},i=qn();for(let r of se){let o=i[r];for(let a of T){if(!e.harnesses.includes(a)){o[a]=l("na",On);continue}o[a]=Yn(r,a,s)}}return{capabilities:se,harnesses:n,matrix:i}}function lt(e){switch(e){case"yes":return"\u2713";case"partial":return"~";case"no":return"\u2717";case"na":return"\u2014"}}var ut=Xn;var dt=`---
4
+
5
+ \u2139\uFE0F Need professional-grade agent infrastructure?
6
+
7
+ Paniolo builds precision infrastructure for autonomous engineering \u2014
8
+ the harness layer around your coding agents: project intelligence,
9
+ observability, guardrails, and the structural patterns that turn
10
+ generated code into production-grade output.
11
+
12
+ For professional or production-grade work, we strongly recommend
13
+ engaging Paniolo's professional services to design, tune, and evolve
14
+ your infrastructure. Learn more at https://paniolo.ai or contact us
15
+ directly at https://paniolo.ai/#contact.
16
+ `;var pt=["error","warn","info"],Qn={error:"ERROR",warn:"WARN",info:"INFO"},Zn={layering:"Layering",sharing:"Sharing",discoverability:"Discoverability",harnessWiring:"Harness wiring",maintainability:"Maintainability",guardrails:"Guardrails"},es=["layering","sharing","discoverability","harnessWiring","maintainability","guardrails"],ts=["copilot","cursor","codex","antigravity","claude","gemini"];function ns(e){let t=Qn[e.severity],n=e.file===null?"":` ${e.file}${e.line===null?"":`:${String(e.line)}`}`,s=e.harnesses.length===0?"":`
4
17
  Harnesses: ${e.harnesses.join(", ")}`,i=e.hint===void 0?"":`
5
18
  Hint: ${e.hint}`;return`[${t}] ${e.ruleId}
6
19
  ${e.message}${n?`
7
- ${n}`:""}${s}${i}`}function Tn(e){process.stdout.write(`## Guidance sharing
20
+ ${n}`:""}${s}${i}`}function ss(e){process.stdout.write(`## Guidance sharing
8
21
 
9
22
  `),process.stdout.write(`Shared (canonical / multi-harness): ${String(e.shared.lines)} lines (${String(e.shared.percentLines)}%) across ${String(e.shared.files)} file(s)
10
23
  `),process.stdout.write(`Harness-specific: ${String(e.unique.totals.lines)} lines (${String(e.unique.totals.percentLines)}%) across ${String(e.unique.totals.files)} file(s)
11
- `);let t=Hn.filter(n=>e.unique.byHarness[n].lines>0);if(t.length>0){process.stdout.write(`
24
+ `);let t=ts.filter(n=>e.unique.byHarness[n].lines>0);if(t.length>0){process.stdout.write(`
12
25
  Per-harness unique guidance:
13
26
  `);for(let n of t){let s=e.unique.byHarness[n];process.stdout.write(` ${n}: ${String(s.lines)} lines (${String(s.files)} file(s))
14
27
  `)}}process.stdout.write(`
15
- `)}function Nn(e){process.stdout.write(`## Meta-harness dimensions
28
+ `)}function is(e){process.stdout.write(`## Meta-harness dimensions
16
29
 
17
- `);for(let t of Fn){let n=e.dimensions[t],s=In[t],i=n.applicableRules===0?" (no rules yet)":` (${String(n.passedRules)}/${String(n.applicableRules)} rules)`;process.stdout.write(`${s}: ${String(n.score)}/100 (${n.grade})${i}
30
+ `);for(let t of es){let n=e.dimensions[t],s=Zn[t],i=n.applicableRules===0?" (no rules yet)":` (${String(n.passedRules)}/${String(n.applicableRules)} rules)`;process.stdout.write(`${s}: ${String(n.score)}/100 (${n.grade})${i}
18
31
  `)}process.stdout.write(`
19
- `)}function Dn(e){e!==void 0&&(process.stdout.write(`## Intelligence layer
32
+ `)}function rs(e){if(process.stdout.write(`## AI review (optional)
33
+
34
+ `),e.status==="not-run"){process.stdout.write(`Not run \u2014 pass --ingest-ai-results to score this dimension.
35
+
36
+ `);return}let t=e.score===null?"n/a":`${String(e.score)}/100`;process.stdout.write(`AI review: ${t} (${e.grade})
37
+ `);for(let n of e.checks){let s=n.passed?"\u2713":`\u2717 ${String(n.findingsCount)} finding(s)`;process.stdout.write(` ${s} ${n.title}
38
+ `)}for(let n of e.findings){let s=n.file===null?"":` (${n.file})`;process.stdout.write(` - ${n.message}${s}
39
+ `)}process.stdout.write(`
40
+ `)}function os(e){e!==void 0&&(process.stdout.write(`## Intelligence layer
20
41
 
21
42
  `),process.stdout.write(`Surfaces: ${String(e.surfaces.length)} detected
22
43
  `),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)
@@ -26,80 +47,125 @@ Per-harness unique guidance:
26
47
  `),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)
27
48
  `),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)
28
49
 
29
- `))}function Mn(e){if(e===void 0)return;let t=e.harnesses.filter(n=>n.detected);if(t.length!==0){process.stdout.write(`## Context budget
50
+ `))}function as(e){if(e===void 0)return;let t=e.harnesses.filter(n=>n.detected);if(t.length!==0){process.stdout.write(`## Context budget
30
51
 
31
52
  `);for(let n of t){process.stdout.write(`${n.harness}: ${String(n.totalLines)} always-loaded lines, ~${String(n.estimatedTokens)} tokens (${n.status})
32
53
  `);for(let s of n.files.slice(0,3))process.stdout.write(` ${s.path}: ${String(s.lines)} lines
33
54
  `)}process.stdout.write(`
34
- `)}}function $n(e){if(process.stdout.write(`## Harness gap matrix
55
+ `)}}function cs(e){if(process.stdout.write(`## Harness gap matrix
35
56
 
36
57
  `),e.harnesses.length===0){process.stdout.write(`No harnesses detected \u2014 add tool adapters to compare capabilities.
37
58
 
38
59
  `);return}let t=28,n=Math.max(...e.harnesses.map(i=>i.length),6)+2,s=`${"Capability".padEnd(t)}${e.harnesses.map(i=>i.padEnd(n)).join("")}`;process.stdout.write(`${s}
39
- `);for(let i of te){let o=Xe[i].padEnd(t),r=e.harnesses.map(a=>{let{status:l}=e.matrix[i][a];return Qe(l).padEnd(n)}).join("");process.stdout.write(`${o}${r}
60
+ `);for(let i of se){let r=ct[i].padEnd(t),o=e.harnesses.map(a=>{let{status:c}=e.matrix[i][a];return lt(c).padEnd(n)}).join("");process.stdout.write(`${r}${o}
40
61
  `)}process.stdout.write(`
41
62
  Legend: \u2713 yes ~ partial \u2717 no \u2014 not applicable
42
63
 
43
- `)}function jn(e){process.stdout.write(`## Harness optimization
64
+ `)}function ls(e){process.stdout.write(`## Harness optimization
44
65
 
45
66
  `);let t=e.filter(s=>s.detected);if(t.length===0){process.stdout.write(`No harnesses detected \u2014 add tool adapters to evaluate optimization.
46
67
 
47
68
  `);return}for(let s of t){let i=s.score===null?"n/a":`${String(s.score)}/100 (${s.grade})`;process.stdout.write(`${s.harness}: ${i}
48
69
  `),s.loadProfile!==null&&process.stdout.write(` Load profile: ${String(s.loadProfile.sharedLines)} shared + ${String(s.loadProfile.uniqueLines)} unique lines (${String(s.loadProfile.sharedPercent)}% shared)
49
- `);let o=s.checks.filter(a=>!a.passed),r=s.checks.length-o.length;process.stdout.write(` Checks: ${String(r)}/${String(s.checks.length)} passed`),s.findingsCount.error+s.findingsCount.warn>0&&process.stdout.write(`; findings: ${String(s.findingsCount.error)} error, ${String(s.findingsCount.warn)} warn`),process.stdout.write(`
50
- `);for(let a of o.slice(0,5))process.stdout.write(` \u2717 ${a.label}
51
- `);o.length>5&&process.stdout.write(` \u2026 and ${String(o.length-5)} more
70
+ `);let r=s.checks.filter(a=>!a.passed),o=s.checks.length-r.length;process.stdout.write(` Checks: ${String(o)}/${String(s.checks.length)} passed`),s.findingsCount.error+s.findingsCount.warn>0&&process.stdout.write(`; findings: ${String(s.findingsCount.error)} error, ${String(s.findingsCount.warn)} warn`),process.stdout.write(`
71
+ `);for(let a of r.slice(0,5))process.stdout.write(` \u2717 ${a.label}
72
+ `);r.length>5&&process.stdout.write(` \u2026 and ${String(r.length-5)} more
52
73
  `),process.stdout.write(`
53
74
  `)}let n=e.filter(s=>!s.detected);n.length>0&&process.stdout.write(`Not detected: ${n.map(s=>s.harness).join(", ")}
54
75
 
55
- `)}function ke(e){if(process.stdout.write(`paniolo-scan \u2014 AI harness diagnostic
76
+ `)}function xe(e){if(process.stdout.write(`paniolo-scan \u2014 AI harness diagnostic
56
77
 
57
78
  `),process.stdout.write(`Root: ${e.root}
58
79
  `),process.stdout.write(`Harnesses: ${e.harnesses.length===0?"(none detected)":e.harnesses.join(", ")}
59
80
  `),process.stdout.write(`Guidance files: ${String(e.inventory.fileCount)}
60
81
  `),process.stdout.write(`Findings: ${String(e.summary.error)} error(s), ${String(e.summary.warn)} warn(s), ${String(e.summary.info)} info
61
82
 
62
- `),Tn(e.sharing),Dn(e.intelligenceLayer),Mn(e.contextBudget),Nn(e.metaHarness),$n(e.harnessGapMatrix),jn(e.harnessOptimization),process.stdout.write(`## Findings
83
+ `),ss(e.sharing),os(e.intelligenceLayer),as(e.contextBudget),is(e.metaHarness),rs(e.aiReview),cs(e.harnessGapMatrix),ls(e.harnessOptimization),process.stdout.write(`## Findings
84
+
85
+ `),e.findings.length===0)process.stdout.write(`No findings.
86
+
87
+ `);else{let t=[...e.findings].sort((n,s)=>{let i=pt.indexOf(n.severity)-pt.indexOf(s.severity);return i!==0?i:n.ruleId.localeCompare(s.ruleId)});for(let n of t)process.stdout.write(`${ns(n)}
88
+
89
+ `)}process.stdout.write(dt)}import xn from"node:path";var ie="AGENTS.md",us=[ie,"docs/ai/rules.md"],ds=["CLAUDE.md","GEMINI.md",".github/copilot-instructions.md",".agent/README.md"];function ps(e,t){let n=[];for(let s of t){let i=p(e,s);i!==null&&i.trim().length>0&&n.push({path:s,content:i})}return n}function fs(e){return e.map(t=>`### FILE: ${t.path}
90
+
91
+ \`\`\`markdown
92
+ ${t.content}
93
+ \`\`\``).join(`
94
+
95
+ `)}function gs(e){let t=e.files.filter(r=>r.path.startsWith("skills/")&&r.path.endsWith("SKILL.md")).map(r=>r.path),n=ps(e,[...us,...t]);if(n.length<2)return null;let s=A["AI1-contradiction"],i=`You are auditing one repository's AI-agent guidance for internal contradictions.
96
+
97
+ Read every file below. Find places where one rule directly contradicts another \u2014
98
+ where an agent could not satisfy both at once. Be strict: only report clear,
99
+ actionable conflicts, not stylistic differences or complementary advice.
100
+
101
+ ${fs(n)}
102
+
103
+ Respond with JSON only, no prose, exactly this shape:
104
+ { "${s.schemaKey}": [ { "ruleA": "<quote>", "ruleB": "<quote>", "explanation": "<why they conflict>" } ] }
105
+ Return an empty array if there are no clear contradictions.`;return{taskId:"AI1-contradiction",checkId:s.checkId,title:s.title,targetPaths:n.map(r=>r.path),schemaKey:s.schemaKey,prompt:i}}function hs(e){let t=p(e,ie);if(t===null)return[];let n=A["AI2-adapter-fidelity"],s=[];for(let i of ds){let r=p(e,i);if(r===null||r.trim().length===0)continue;let o=`You are checking whether a thin per-tool adapter stays faithful to the shared guidance it points at.
106
+
107
+ The adapter should defer to the shared layer, not restate or contradict it. Find
108
+ claims in the ADAPTER that drift from the SHARED ENTRY: instructions the shared
109
+ layer does not support, stale pointers, or duplicated guidance that has diverged.
110
+ Be strict: only report real fidelity problems, not harmless adapter-only setup.
111
+
112
+ ### SHARED ENTRY: ${ie}
113
+
114
+ \`\`\`markdown
115
+ ${t}
116
+ \`\`\`
117
+
118
+ ### ADAPTER: ${i}
63
119
 
64
- `),e.findings.length===0){process.stdout.write(`No findings.
65
- `);return}let t=[...e.findings].sort((n,s)=>{let i=et.indexOf(n.severity)-et.indexOf(s.severity);return i!==0?i:n.ruleId.localeCompare(s.ruleId)});for(let n of t)process.stdout.write(`${Pn(n)}
120
+ \`\`\`markdown
121
+ ${r}
122
+ \`\`\`
66
123
 
67
- `)}import Yi from"node:path";function Gn(){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 ne(e,t){return t===0?0:Math.round(e/t*1e3)/10}function Se(e,t){let n={files:0,lines:0,bytes:0},s=Gn(),i={files:0,lines:0,bytes:0},o={files:0,lines:0,bytes:0},r=[];for(let a of e){let l=Ue(a,t);if(l.length===0)continue;o.files+=1,o.lines+=a.lines,o.bytes+=a.bytes;let d=qe(a,l),h=d?"shared":"unique";if(r.push({path:a.path,lines:a.lines,scope:h,harnesses:l}),d)n.files+=1,n.lines+=a.lines,n.bytes+=a.bytes;else{let[p]=l;p!==void 0&&(s[p].files+=1,s[p].lines+=a.lines,s[p].bytes+=a.bytes),i.files+=1,i.lines+=a.lines,i.bytes+=a.bytes}}return{totals:o,shared:{...n,percentLines:ne(n.lines,o.lines)},unique:{byHarness:s,totals:{...i,percentLines:ne(i.lines,o.lines)}},files:r}}function tt(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 i of t){let o=e.unique.byHarness[i].lines,r=e.shared.lines,a=r+o;s[i]={sharedLines:r,uniqueLines:o,totalLines:a,sharedPercent:ne(r,a),uniquePercent:ne(o,a)}}return s}import{access as Wn,readFile as Un}from"node:fs/promises";import k from"node:path";function W(e){try{let t=JSON.parse(e);if(w(t))return t}catch{}return _n(e)}function _n(e){let t={},n=/"([^"]+)"\s*:\s*(true|false|null|\d+(?:\.\d+)?|"[^"]*")/g;for(let[,s,i]of e.matchAll(n))s===void 0||i===void 0||(t[s]=On(i));return Object.keys(t).length===0?null:t}function On(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}async function b(e){try{return await Wn(e),!0}catch{return!1}}async function qn(e){try{let t=await Un(e,"utf8");return W(t)}catch{return null}}function Bn(e){return e===null?!1:e["chat.agentSkillsLocations"]!==void 0||e["chat.agentFilesLocations"]!==void 0||e["chat.useCustomAgentHooks"]===!0}async function we(e){let t=new Set;await b(k.join(e,".github/copilot-instructions.md"))&&t.add("copilot"),await b(k.join(e,".github/hooks"))&&t.add("copilot");let n=await qn(k.join(e,".vscode/settings.json"));return Bn(n)&&(t.add("cursor"),t.add("copilot")),await b(k.join(e,".cursor"))&&t.add("cursor"),await b(k.join(e,".codex/config.toml"))&&t.add("codex"),await b(k.join(e,".codex/hooks.json"))&&t.add("codex"),await b(k.join(e,".codex/agents"))&&t.add("codex"),await b(k.join(e,".agent/workflows"))&&t.add("antigravity"),await b(k.join(e,".agent/README.md"))&&t.add("antigravity"),await b(k.join(e,"CLAUDE.md"))&&t.add("claude"),await b(k.join(e,".claude/settings.json"))&&t.add("claude"),await b(k.join(e,"GEMINI.md"))&&t.add("gemini"),[...t].sort()}var se=250,Vn=150;function nt(e){return Math.ceil(e/4)}function U(e,t){return e.files.find(n=>n.path===t)??null}function F(e,t){return{path:e.path,lines:e.lines,bytes:e.bytes,estimatedTokens:nt(e.bytes),reason:t}}function zn(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 Jn(e,t){let n=[];if(t==="copilot"){let s=U(e,".github/copilot-instructions.md");s!==null&&n.push(F(s,"Copilot workspace instructions are loaded by Copilot Chat."))}if(t==="cursor")for(let s of e.files)s.path.startsWith(".cursor/rules/")&&zn(e,s)&&n.push(F(s,"Cursor rule declares alwaysApply: true."));if(t==="codex"){let s=U(e,"AGENTS.md");s!==null&&n.push(F(s,"Root AGENTS.md is the Codex repo instruction entry."));for(let i of e.files)i.path.startsWith(".codex/")&&i.layer==="adapter"&&n.push(F(i,"Codex adapter guidance under .codex/."))}if(t==="antigravity"){let s=U(e,".agent/README.md");s!==null&&n.push(F(s,"Antigravity workspace adapter README."))}if(t==="claude"){let s=U(e,"CLAUDE.md");s!==null&&n.push(F(s,"Claude Code root instruction file."))}if(t==="gemini"){let s=U(e,"GEMINI.md");s!==null&&n.push(F(s,"Gemini root instruction file."))}return n.toSorted((s,i)=>s.path.localeCompare(i.path))}function Kn(e,t){if(!e.harnesses.includes(t))return{harness:t,detected:!1,files:[],totalLines:0,totalBytes:0,estimatedTokens:0,maxRecommendedLines:se,status:"ok"};let s=Jn(e,t),i=s.reduce((r,a)=>r+a.lines,0),o=s.reduce((r,a)=>r+a.bytes,0);return{harness:t,detected:!0,files:s,totalLines:i,totalBytes:o,estimatedTokens:nt(o),maxRecommendedLines:se,status:i>se?"high":"ok"}}function be(e){return{harnesses:E.map(t=>Kn(e,t)),maxRecommendedLines:se,maxRecommendedFileLines:Vn}}import{access as Yn}from"node:fs/promises";import q from"node:path";var Xn=[{min:85,grade:"excellent"},{min:70,grade:"good"},{min:50,grade:"fair"},{min:0,grade:"poor"}],Ce={error:12,warn:5,info:1},Qn=40;async function B(e){try{return await Yn(e),!0}catch{return!1}}function x(e,t){return e.files.some(n=>n.path===t)}function it(e,t){return e.fileContents.get(t)??null}function Zn(e,t){return e.files.find(s=>s.path===t)?.lines??null}function es(e){return e.includes("AGENTS.md")||e.includes("docs/ai/rules.md")}function D(e){return e.files.some(t=>t.path.startsWith("skills/"))}function ie(e){return e.files.some(t=>t.path.startsWith("agents/"))}function st(e,t){return e.settings?.[t]===!0}function V(e,t,n){let s=e.settings?.[t];if(w(s)&&Object.keys(s).some(a=>a.startsWith(n)))return!0;if(e.settingsRaw===null)return!1;let i=t.replaceAll(".",String.raw`\.`);return new RegExp(`"${i}"\\s*:\\s*\\{[^}]*"${n}[^"]*"`).test(e.settingsRaw)}function xe(e,t){let n=Zn(e,t);return n===null?!1:n<=v}function Le(e,t){let n=it(e,t);return n===null?!1:es(n)}function ts(e){let t=it(e,".agent/README.md");return t===null?!1:/\.agent\/workflows\/|workflows\//i.test(t)&&/(workflow|playbook|slash command|mission|turbo)/i.test(t)}var ns={copilot:[{id:"copilot-instructions",label:"Copilot instructions file present",weight:15,run:({context:e})=>x(e,".github/copilot-instructions.md")},{id:"copilot-references-shared",label:"Copilot instructions reference shared layers",weight:15,run:({context:e})=>Le(e,".github/copilot-instructions.md")},{id:"copilot-adapter-thin",label:"Copilot instructions stay thin",weight:10,run:({context:e})=>xe(e,".github/copilot-instructions.md")},{id:"copilot-skills-location",label:"chat.agentSkillsLocations points at skills/",weight:15,run:({vscode:e})=>V(e,"chat.agentSkillsLocations","skills")},{id:"copilot-agents-location",label:"chat.agentFilesLocations points at agents/",weight:15,run:({vscode:e})=>V(e,"chat.agentFilesLocations","agents")},{id:"copilot-hooks-enabled",label:"Custom agent hooks enabled when .github/hooks/ exists",weight:15,run:({vscode:e})=>!e.hooksDirExists||st(e,"chat.useCustomAgentHooks")},{id:"copilot-shared-skills",label:"Shared skills/ tree present",weight:8,run:({context:e})=>D(e)},{id:"copilot-shared-agents",label:"Shared agents/ tree present",weight:7,run:({context:e})=>ie(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/"))||V(t,"chat.agentSkillsLocations","skills")},{id:"cursor-skills-location",label:"chat.agentSkillsLocations points at skills/",weight:20,run:({vscode:e})=>V(e,"chat.agentSkillsLocations","skills")},{id:"cursor-agents-location",label:"chat.agentFilesLocations points at agents/",weight:20,run:({vscode:e})=>V(e,"chat.agentFilesLocations","agents")},{id:"cursor-hooks-enabled",label:"Custom agent hooks enabled when .github/hooks/ exists",weight:15,run:({vscode:e})=>!e.hooksDirExists||st(e,"chat.useCustomAgentHooks")},{id:"cursor-shared-skills",label:"Shared skills/ tree present",weight:13,run:({context:e})=>D(e)},{id:"cursor-shared-agents",label:"Shared agents/ tree present",weight:12,run:({context:e})=>ie(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 B(q.join(e.repoRoot,"api/AGENTS.md"))||await B(q.join(e.repoRoot,"react/AGENTS.md"))||await B(q.join(e.repoRoot,"shared/AGENTS.md"))},{id:"codex-hooks",label:"Codex hooks.json present",weight:20,run:({context:e})=>B(q.join(e.repoRoot,".codex/hooks.json"))},{id:"codex-agents-wrappers",label:"Codex agent wrappers present",weight:20,run:({context:e})=>B(q.join(e.repoRoot,".codex/agents"))},{id:"codex-shared-entry",label:"Root AGENTS.md present",weight:20,run:({context:e})=>x(e,"AGENTS.md")},{id:"codex-shared-skills",label:"Shared skills/ tree present",weight:8,run:({context:e})=>D(e)},{id:"codex-shared-rules",label:"Canonical rules doc present",weight:7,run:({context:e})=>x(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})=>ts(e)},{id:"antigravity-shared-entry",label:"Root AGENTS.md present",weight:20,run:({context:e})=>x(e,"AGENTS.md")},{id:"antigravity-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>D(e)},{id:"antigravity-ai-system-doc",label:"AI system layout doc present",weight:15,run:({context:e})=>x(e,"docs/ai/ai-system.md")}],claude:[{id:"claude-adapter",label:"CLAUDE.md adapter present",weight:25,run:({context:e})=>x(e,"CLAUDE.md")},{id:"claude-references-shared",label:"CLAUDE.md references shared layers",weight:25,run:({context:e})=>Le(e,"CLAUDE.md")},{id:"claude-adapter-thin",label:"CLAUDE.md stays thin",weight:20,run:({context:e})=>xe(e,"CLAUDE.md")},{id:"claude-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>D(e)},{id:"claude-skills-index",label:"Skill index doc for prose discovery",weight:8,run:({context:e})=>x(e,"docs/ai/available-skills.md")},{id:"claude-shared-agents",label:"Shared agents/ tree present",weight:7,run:({context:e})=>ie(e)}],gemini:[{id:"gemini-adapter",label:"GEMINI.md adapter present",weight:30,run:({context:e})=>x(e,"GEMINI.md")},{id:"gemini-references-shared",label:"GEMINI.md references shared layers",weight:25,run:({context:e})=>Le(e,"GEMINI.md")},{id:"gemini-adapter-thin",label:"GEMINI.md stays thin",weight:20,run:({context:e})=>xe(e,"GEMINI.md")},{id:"gemini-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>D(e)},{id:"gemini-shared-agents",label:"Shared agents/ tree present",weight:10,run:({context:e})=>ie(e)}]};function ss(e){for(let{min:t,grade:n}of Xn)if(e>=t)return n;return"poor"}function is(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}function rs(e){let t=e.error*Ce.error+e.warn*Ce.warn+e.info*Ce.info;return Math.min(t,Qn)}async function os(e,t){let n=ns[e],s=[];for(let i of n){let o=await i.run(t);s.push({id:i.id,label:i.label,passed:o,weight:i.weight})}return s}function as(e){let t=e.reduce((s,i)=>s+i.weight,0);if(t===0)return 0;let n=e.filter(s=>s.passed).reduce((s,i)=>s+i.weight,0);return Math.round(n/t*100)}async function cs(e,t,n,s,i,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 l=await os(e,{context:t,vscode:n,harness:e}),d=is(s,e),h=as(l),p=rs(d),u=Math.max(0,Math.min(100,h-p));return{harness:e,detected:!0,score:u,grade:ss(u),checks:l,findingsCount:d,loadProfile:o[e]??null}}async function Ae(e,t,n,s){let i=tt(s,e.harnesses),o=[];for(let r of E){let a=await cs(r,e,t,n,s,i);o.push(a)}return o}import{readFile as ls,stat as us}from"node:fs/promises";import rt from"node:path";async function H(e){let t=rt.join(e,".github/hooks"),n=!1;try{n=(await us(t)).isDirectory()}catch{n=!1}let s=rt.join(e,".vscode/settings.json"),i=null,o=null;try{let r=await ls(s,"utf8");o=r,i=W(r)}catch{i=null,o=null}return{settings:i,settingsRaw:o,hooksDirExists:n}}function ds(e){return e.contextBudget!==void 0&&e.contextBudget.harnesses.length>0}function ot(e){return ds(e)}function at(e){let t=e.contextBudget;if(t===void 0)return[];let n=[];for(let s of t.harnesses)!s.detected||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 n}function ct(e){let t=e.contextBudget;if(t===void 0)return[];let n=[];for(let s of t.harnesses)if(s.detected)for(let i of s.files)i.lines<=t.maxRecommendedFileLines||n.push({ruleId:"adapter-context-budget",severity:"info",message:`${i.path} contributes ${String(i.lines)} always-loaded lines for ${s.harness}; recommended maximum per file is ${String(t.maxRecommendedFileLines)}.`,file:i.path,line:null,harnesses:[s.harness],hint:"Split detailed guidance into linked docs and keep always-loaded instruction files compact."});return n}import{readFile as gs}from"node:fs/promises";import ms from"node:path";var lt=/!?\[([^\]]*)\]\(([^)]+)\)/g;function M(e){let t=[],n=lt.exec(e);for(;n!==null;){let[s]=n;s.startsWith("!")||t.push({label:n[1]??"",href:(n[2]??"").trim()}),n=lt.exec(e)}return t}var ps=new Set(["url","path","href","link","..."]);function re(e){return e.length===0||ps.has(e.toLowerCase())||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("mailto:")||e.startsWith("tel:")?!0:(e.split("#")[0]??"").length===0}function oe(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 i=e.includes("/")?e.slice(0,e.lastIndexOf("/")):"",o=i.length===0?s:`${i}/${s}`;return fs(o)}function fs(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 ae(e,t){let n=e.split(`
68
- `);for(let s=0;s<n.length;s+=1){let i=n[s];if(i!==void 0&&i.includes(t))return s+1}return null}var ut="docs/ai/available-skills.md";async function hs(e){try{let t=await gs(ms.join(e,"package.json"),"utf8"),n=JSON.parse(t);if(w(n)&&"scripts"in n){let{scripts:s}=n;if(w(s))return s}return null}catch{return null}}function ys(e){return e===null?!1:Object.entries(e).some(([t,n])=>t.toLowerCase().includes("qmd")||typeof n=="string"&&n.toLowerCase().includes("qmd"))}function dt(e){return S(e)?y(e,ut)?[]:[{ruleId:"skills-index",severity:"info",message:`${ut} 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."}]:[]}function pt(e){if(!e.harnesses.includes("claude")||!y(e,"CLAUDE.md"))return[];let t=f(e,"CLAUDE.md");return t!==null&&Z(t)?[]:[{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."}]}function ft(e){if(!S(e)||!y(e,"AGENTS.md"))return[];let t=f(e,"AGENTS.md");return t!==null&&Q(t)?[]:[{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)."}]}var ks=50;function Ss(e){return!e.endsWith(".md")&&!e.endsWith(".mdc")?!1:e.startsWith("docs/")||e.includes("/docs/")}function ws(e,t){for(let n of M(t)){if(re(n.href))continue;let s=oe(e,n.href);if(s!==null&&Ss(s))return!0}return!1}function gt(e){let t=[];for(let n of e.files){if(!n.path.startsWith("skills/")||!n.path.endsWith("SKILL.md")||(n.lines??0)<=ks)continue;let s=f(e,n.path);s===null||ws(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 t}async function mt(e){let t=S(e),n=e.files.filter(i=>i.path.startsWith("docs/ai/")).length;if(!t&&n<2)return[];let s=await hs(e.repoRoot);return ys(s)?[]:[{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.'}]}var bs=["docs/","skills/","agents/",".cursor/",".github/",".codex/",".agent/",".claude/"],Cs=new Set(["AGENTS.md","CLAUDE.md","GEMINI.md","README.md",".github/copilot-instructions.md"]);function ht(e){let t=e.replaceAll("\\","/").replace(/\/+$/,"");return Cs.has(t)?!0:bs.some(n=>t===n.slice(0,-1)||t.startsWith(n))}var xs=["",".md","/README.md","/index.md"];async function yt(e,t){for(let n of xs){let s=`${t}${n}`.replaceAll("\\","/");if(await _(e,s))return!0}return!1}var Ls=8;function As(e){return/my-doc\.md|example\.spec\.|\/example\//i.test(e)}function Rs(e){return e.endsWith("/")?!0:e.endsWith(".md")||e.endsWith(".mdc")}async function kt(e){let t=[];for(let n of e.files){if(!n.path.endsWith(".md")&&!n.path.endsWith(".mdc"))continue;let s=f(e,n.path);if(s===null)continue;let i=0;for(let o of M(s)){if(re(o.href))continue;let r=oe(n.path,o.href);if(!(r===null||!ht(r)||!Rs(r)||As(r)||await yt(e.repoRoot,r))&&(t.push({ruleId:"guidance-links-resolve",severity:"warn",message:`Broken link in ${n.path}: (${o.href}) does not resolve.`,file:n.path,line:ae(s,o.href),harnesses:[],hint:"Fix the path or add the missing guidance file."}),i+=1,i>=Ls))break}}return t}var Re="docs/ai/rules.md",ce=3,Es=80;function Ee(e){return e.trim().replaceAll(/\s+/g," ")}function vs(e){let t=Ee(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 St(e){return e.map(t=>Ee(t)).filter(t=>t.length>0).join(`
69
- `)}function Is(e,t){let n=e.split(`
70
- `),s=St(t.split(`
71
- `)),i=[],o=new Set;for(let r=0;r<=n.length-ce;r+=1){if(o.has(r))continue;let a=n.slice(r,r+ce);if(!a.every(d=>vs(d)))continue;let l=St(a);if(!(l.length<Es)&&s.includes(l)){i.push({startLine:r+1,lineCount:ce,sample:Ee(a[0]??"")}),o.add(r);for(let d=1;d<ce;d+=1)o.add(r+d)}}return i}function wt(e){let t=f(e,Re);if(t===null)return[];let n=[];for(let s of Y){let i=f(e,s);if(i===null)continue;let o=Is(i,t);for(let r of o)n.push({ruleId:"adapter-content-duplication",severity:"warn",message:`${s} duplicates ${String(r.lineCount)} lines from ${Re} near line ${String(r.startLine)}.`,file:s,line:r.startLine,harnesses:[],hint:`Replace duplicated rules with a pointer to ${Re}.`})}return n}function le(e){return e.intelligenceLayer??null}function ue(e){return e.packageJson.path!==null||e.workflows.length>0||e.prTemplates.length>0}function bt(e){let t=le(e);return t!==null&&ue(t)}function ve(e,t,n,s){return{ruleId:e,severity:"info",message:t,file:s,line:null,harnesses:[],hint:n}}function Ct(e){let t=le(e);return t===null||!ue(t)?[]:t.guidanceMaintenanceScripts.length>0?[]:[ve("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)]}function xt(e){let t=le(e);return t===null||!ue(t)?[]:t.aiHarnessPrTemplates.length>0?[]:[ve("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")]}function Lt(e){let t=le(e);return t===null||!ue(t)?[]:t.guidanceCiWorkflows.length>0?[]:[ve("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)]}function L(e){return e.intelligenceLayer??null}function de(e){return Object.entries(e.packageJson.scripts).map(([t,n])=>({name:t,command:n}))}function Ie(e,t,n){return de(e).some(s=>t.test(s.name)||n.test(s.command))}function Fs(e,t){return de(e).filter(n=>t.test(n.name)||t.test(n.command)).map(n=>n.name).toSorted()}function Fe(e){return e.workflows.map(t=>t.commands.join(`
124
+ Respond with JSON only, no prose, exactly this shape:
125
+ { "${n.schemaKey}": [ { "claim": "<quote from adapter>", "explanation": "<how it drifts>" } ] }
126
+ Return an empty array if the adapter is faithful.`;s.push({taskId:`AI2-adapter-fidelity:${i}`,checkId:n.checkId,title:`${n.title} (${i})`,targetPaths:[i,ie],schemaKey:n.schemaKey,prompt:o})}return s}function Re(e){let t=[],n=gs(e);return n!==null&&t.push(n),t.push(...hs(e)),t}function ms(){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 re(e,t){return t===0?0:Math.round(e/t*1e3)/10}function Ae(e,t){let n={files:0,lines:0,bytes:0},s=ms(),i={files:0,lines:0,bytes:0},r={files:0,lines:0,bytes:0},o=[];for(let a of e){let c=tt(a,t);if(c.length===0)continue;r.files+=1,r.lines+=a.lines,r.bytes+=a.bytes;let u=nt(a,c),f=u?"shared":"unique";if(o.push({path:a.path,lines:a.lines,scope:f,harnesses:c}),u)n.files+=1,n.lines+=a.lines,n.bytes+=a.bytes;else{let[g]=c;g!==void 0&&(s[g].files+=1,s[g].lines+=a.lines,s[g].bytes+=a.bytes),i.files+=1,i.lines+=a.lines,i.bytes+=a.bytes}}return{totals:r,shared:{...n,percentLines:re(n.lines,r.lines)},unique:{byHarness:s,totals:{...i,percentLines:re(i.lines,r.lines)}},files:o}}function ft(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 i of t){let r=e.unique.byHarness[i].lines,o=e.shared.lines,a=o+r;s[i]={sharedLines:o,uniqueLines:r,totalLines:a,sharedPercent:re(o,a),uniquePercent:re(r,a)}}return s}import{access as ws,readFile as Ss}from"node:fs/promises";import w from"node:path";function q(e){try{let t=JSON.parse(e);if(h(t))return t}catch{}return ys(e)}function ys(e){let t={},n=/"([^"]+)"\s*:\s*(true|false|null|\d+(?:\.\d+)?|"[^"]*")/g;for(let[,s,i]of e.matchAll(n))s===void 0||i===void 0||(t[s]=ks(i));return Object.keys(t).length===0?null:t}function ks(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}async function b(e){try{return await ws(e),!0}catch{return!1}}async function bs(e){try{let t=await Ss(e,"utf8");return q(t)}catch{return null}}function Cs(e){return e===null?!1:e["chat.agentSkillsLocations"]!==void 0||e["chat.agentFilesLocations"]!==void 0||e["chat.useCustomAgentHooks"]===!0}async function oe(e){let t=new Set;await b(w.join(e,".github/copilot-instructions.md"))&&t.add("copilot"),await b(w.join(e,".github/hooks"))&&t.add("copilot");let n=await bs(w.join(e,".vscode/settings.json"));return Cs(n)&&(t.add("cursor"),t.add("copilot")),await b(w.join(e,".cursor"))&&t.add("cursor"),await b(w.join(e,".codex/config.toml"))&&t.add("codex"),await b(w.join(e,".codex/hooks.json"))&&t.add("codex"),await b(w.join(e,".codex/agents"))&&t.add("codex"),await b(w.join(e,".agent/workflows"))&&t.add("antigravity"),await b(w.join(e,".agent/README.md"))&&t.add("antigravity"),await b(w.join(e,"CLAUDE.md"))&&t.add("claude"),await b(w.join(e,".claude/settings.json"))&&t.add("claude"),await b(w.join(e,"GEMINI.md"))&&t.add("gemini"),[...t].sort()}var ae=250,xs=150;function gt(e){return Math.ceil(e/4)}function B(e,t){return e.files.find(n=>n.path===t)??null}function H(e,t){return{path:e.path,lines:e.lines,bytes:e.bytes,estimatedTokens:gt(e.bytes),reason:t}}function Rs(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 As(e,t){let n=[];if(t==="copilot"){let s=B(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/")&&Rs(e,s)&&n.push(H(s,"Cursor rule declares alwaysApply: true."));if(t==="codex"){let s=B(e,"AGENTS.md");s!==null&&n.push(H(s,"Root AGENTS.md is the Codex repo instruction entry."));for(let i of e.files)i.path.startsWith(".codex/")&&i.layer==="adapter"&&n.push(H(i,"Codex adapter guidance under .codex/."))}if(t==="antigravity"){let s=B(e,".agent/README.md");s!==null&&n.push(H(s,"Antigravity workspace adapter README."))}if(t==="claude"){let s=B(e,"CLAUDE.md");s!==null&&n.push(H(s,"Claude Code root instruction file."))}if(t==="gemini"){let s=B(e,"GEMINI.md");s!==null&&n.push(H(s,"Gemini root instruction file."))}return n.toSorted((s,i)=>s.path.localeCompare(i.path))}function vs(e,t){if(!e.harnesses.includes(t))return{harness:t,detected:!1,files:[],totalLines:0,totalBytes:0,estimatedTokens:0,maxRecommendedLines:ae,status:"ok"};let s=As(e,t),i=s.reduce((o,a)=>o+a.lines,0),r=s.reduce((o,a)=>o+a.bytes,0);return{harness:t,detected:!0,files:s,totalLines:i,totalBytes:r,estimatedTokens:gt(r),maxRecommendedLines:ae,status:i>ae?"high":"ok"}}function ve(e){return{harnesses:T.map(t=>vs(e,t)),maxRecommendedLines:ae,maxRecommendedFileLines:xs}}import{access as Is}from"node:fs/promises";import V from"node:path";var Es=[{min:85,grade:"excellent"},{min:70,grade:"good"},{min:50,grade:"fair"},{min:0,grade:"poor"}],Ie={error:12,warn:5,info:1},Ls=40;async function K(e){try{return await Is(e),!0}catch{return!1}}function v(e,t){return e.files.some(n=>n.path===t)}function mt(e,t){return e.fileContents.get(t)??null}function Fs(e,t){return e.files.find(s=>s.path===t)?.lines??null}function Ts(e){return e.includes("AGENTS.md")||e.includes("docs/ai/rules.md")}function M(e){return e.files.some(t=>t.path.startsWith("skills/"))}function ce(e){return e.files.some(t=>t.path.startsWith("agents/"))}function ht(e,t){return e.settings?.[t]===!0}function J(e,t,n){let s=e.settings?.[t];if(h(s)&&Object.keys(s).some(a=>a.startsWith(n)))return!0;if(e.settingsRaw===null)return!1;let i=t.replaceAll(".",String.raw`\.`);return new RegExp(`"${i}"\\s*:\\s*\\{[^}]*"${n}[^"]*"`).test(e.settingsRaw)}function Ee(e,t){let n=Fs(e,t);return n===null?!1:n<=L}function Le(e,t){let n=mt(e,t);return n===null?!1:Ts(n)}function Hs(e){let t=mt(e,".agent/README.md");return t===null?!1:/\.agent\/workflows\/|workflows\//i.test(t)&&/(workflow|playbook|slash command|mission|turbo)/i.test(t)}var Ns={copilot:[{id:"copilot-instructions",label:"Copilot instructions file present",weight:15,run:({context:e})=>v(e,".github/copilot-instructions.md")},{id:"copilot-references-shared",label:"Copilot instructions reference shared layers",weight:15,run:({context:e})=>Le(e,".github/copilot-instructions.md")},{id:"copilot-adapter-thin",label:"Copilot instructions stay thin",weight:10,run:({context:e})=>Ee(e,".github/copilot-instructions.md")},{id:"copilot-skills-location",label:"chat.agentSkillsLocations points at skills/",weight:15,run:({vscode:e})=>J(e,"chat.agentSkillsLocations","skills")},{id:"copilot-agents-location",label:"chat.agentFilesLocations points at agents/",weight:15,run:({vscode:e})=>J(e,"chat.agentFilesLocations","agents")},{id:"copilot-hooks-enabled",label:"Custom agent hooks enabled when .github/hooks/ exists",weight:15,run:({vscode:e})=>!e.hooksDirExists||ht(e,"chat.useCustomAgentHooks")},{id:"copilot-shared-skills",label:"Shared skills/ tree present",weight:8,run:({context:e})=>M(e)},{id:"copilot-shared-agents",label:"Shared agents/ tree present",weight:7,run:({context:e})=>ce(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/"))||J(t,"chat.agentSkillsLocations","skills")},{id:"cursor-skills-location",label:"chat.agentSkillsLocations points at skills/",weight:20,run:({vscode:e})=>J(e,"chat.agentSkillsLocations","skills")},{id:"cursor-agents-location",label:"chat.agentFilesLocations points at agents/",weight:20,run:({vscode:e})=>J(e,"chat.agentFilesLocations","agents")},{id:"cursor-hooks-enabled",label:"Custom agent hooks enabled when .github/hooks/ exists",weight:15,run:({vscode:e})=>!e.hooksDirExists||ht(e,"chat.useCustomAgentHooks")},{id:"cursor-shared-skills",label:"Shared skills/ tree present",weight:13,run:({context:e})=>M(e)},{id:"cursor-shared-agents",label:"Shared agents/ tree present",weight:12,run:({context:e})=>ce(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 K(V.join(e.repoRoot,"api/AGENTS.md"))||await K(V.join(e.repoRoot,"react/AGENTS.md"))||await K(V.join(e.repoRoot,"shared/AGENTS.md"))},{id:"codex-hooks",label:"Codex hooks.json present",weight:20,run:({context:e})=>K(V.join(e.repoRoot,".codex/hooks.json"))},{id:"codex-agents-wrappers",label:"Codex agent wrappers present",weight:20,run:({context:e})=>K(V.join(e.repoRoot,".codex/agents"))},{id:"codex-shared-entry",label:"Root AGENTS.md present",weight:20,run:({context:e})=>v(e,"AGENTS.md")},{id:"codex-shared-skills",label:"Shared skills/ tree present",weight:8,run:({context:e})=>M(e)},{id:"codex-shared-rules",label:"Canonical rules doc present",weight:7,run:({context:e})=>v(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})=>Hs(e)},{id:"antigravity-shared-entry",label:"Root AGENTS.md present",weight:20,run:({context:e})=>v(e,"AGENTS.md")},{id:"antigravity-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>M(e)},{id:"antigravity-ai-system-doc",label:"AI system layout doc present",weight:15,run:({context:e})=>v(e,"docs/ai/ai-system.md")}],claude:[{id:"claude-adapter",label:"CLAUDE.md adapter present",weight:25,run:({context:e})=>v(e,"CLAUDE.md")},{id:"claude-references-shared",label:"CLAUDE.md references shared layers",weight:25,run:({context:e})=>Le(e,"CLAUDE.md")},{id:"claude-adapter-thin",label:"CLAUDE.md stays thin",weight:20,run:({context:e})=>Ee(e,"CLAUDE.md")},{id:"claude-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>M(e)},{id:"claude-skills-index",label:"Skill index doc for prose discovery",weight:8,run:({context:e})=>v(e,"docs/ai/available-skills.md")},{id:"claude-shared-agents",label:"Shared agents/ tree present",weight:7,run:({context:e})=>ce(e)}],gemini:[{id:"gemini-adapter",label:"GEMINI.md adapter present",weight:30,run:({context:e})=>v(e,"GEMINI.md")},{id:"gemini-references-shared",label:"GEMINI.md references shared layers",weight:25,run:({context:e})=>Le(e,"GEMINI.md")},{id:"gemini-adapter-thin",label:"GEMINI.md stays thin",weight:20,run:({context:e})=>Ee(e,"GEMINI.md")},{id:"gemini-shared-skills",label:"Shared skills/ tree present",weight:15,run:({context:e})=>M(e)},{id:"gemini-shared-agents",label:"Shared agents/ tree present",weight:10,run:({context:e})=>ce(e)}]};function Ps(e){for(let{min:t,grade:n}of Es)if(e>=t)return n;return"poor"}function Ds(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}function $s(e){let t=e.error*Ie.error+e.warn*Ie.warn+e.info*Ie.info;return Math.min(t,Ls)}async function Ms(e,t){let n=Ns[e],s=[];for(let i of n){let r=await i.run(t);s.push({id:i.id,label:i.label,passed:r,weight:i.weight})}return s}function _s(e){let t=e.reduce((s,i)=>s+i.weight,0);if(t===0)return 0;let n=e.filter(s=>s.passed).reduce((s,i)=>s+i.weight,0);return Math.round(n/t*100)}async function js(e,t,n,s,i,r){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 Ms(e,{context:t,vscode:n,harness:e}),u=Ds(s,e),f=_s(c),g=$s(u),d=Math.max(0,Math.min(100,f-g));return{harness:e,detected:!0,score:d,grade:Ps(d),checks:c,findingsCount:u,loadProfile:r[e]??null}}async function Fe(e,t,n,s){let i=ft(s,e.harnesses),r=[];for(let o of T){let a=await js(o,e,t,n,s,i);r.push(a)}return r}import{readFile as Gs,stat as Os}from"node:fs/promises";import yt from"node:path";async function N(e){let t=yt.join(e,".github/hooks"),n=!1;try{n=(await Os(t)).isDirectory()}catch{n=!1}let s=yt.join(e,".vscode/settings.json"),i=null,r=null;try{let o=await Gs(s,"utf8");r=o,i=q(o)}catch{i=null,r=null}return{settings:i,settingsRaw:r,hooksDirExists:n}}function Ws(e){return e.contextBudget!==void 0&&e.contextBudget.harnesses.length>0}function kt(e){return Ws(e)}function wt(e){let t=e.contextBudget;if(t===void 0)return[];let n=[];for(let s of t.harnesses)!s.detected||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 n}function St(e){let t=e.contextBudget;if(t===void 0)return[];let n=[];for(let s of t.harnesses)if(s.detected)for(let i of s.files)i.lines<=t.maxRecommendedFileLines||n.push({ruleId:"adapter-context-budget",severity:"info",message:`${i.path} contributes ${String(i.lines)} always-loaded lines for ${s.harness}; recommended maximum per file is ${String(t.maxRecommendedFileLines)}.`,file:i.path,line:null,harnesses:[s.harness],hint:"Split detailed guidance into linked docs and keep always-loaded instruction files compact."});return n}import{readFile as Bs}from"node:fs/promises";import Vs from"node:path";var bt=/!?\[([^\]]*)\]\(([^)]+)\)/g;function _(e){let t=[],n=bt.exec(e);for(;n!==null;){let[s]=n;s.startsWith("!")||t.push({label:n[1]??"",href:(n[2]??"").trim()}),n=bt.exec(e)}return t}var Us=new Set(["url","path","href","link","..."]);function le(e){return e.length===0||Us.has(e.toLowerCase())||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("mailto:")||e.startsWith("tel:")?!0:(e.split("#")[0]??"").length===0}function ue(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 i=e.includes("/")?e.slice(0,e.lastIndexOf("/")):"",r=i.length===0?s:`${i}/${s}`;return qs(r)}function qs(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 de(e,t){let n=e.split(`
127
+ `);for(let s=0;s<n.length;s+=1){let i=n[s];if(i!==void 0&&i.includes(t))return s+1}return null}var Ct="docs/ai/available-skills.md";async function Ks(e){try{let t=await Bs(Vs.join(e,"package.json"),"utf8"),n=JSON.parse(t);if(h(n)&&"scripts"in n){let{scripts:s}=n;if(h(s))return s}return null}catch{return null}}function Js(e){return e===null?!1:Object.entries(e).some(([t,n])=>t.toLowerCase().includes("qmd")||typeof n=="string"&&n.toLowerCase().includes("qmd"))}function xt(e){return S(e)?k(e,Ct)?[]:[{ruleId:"skills-index",severity:"info",message:`${Ct} 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."}]:[]}function Rt(e){if(!e.harnesses.includes("claude")||!k(e,"CLAUDE.md"))return[];let t=p(e,"CLAUDE.md");return t!==null&&te(t)?[]:[{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."}]}function At(e){if(!S(e)||!k(e,"AGENTS.md"))return[];let t=p(e,"AGENTS.md");return t!==null&&ee(t)?[]:[{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)."}]}var zs=50;function Ys(e){return!e.endsWith(".md")&&!e.endsWith(".mdc")?!1:e.startsWith("docs/")||e.includes("/docs/")}function Xs(e,t){for(let n of _(t)){if(le(n.href))continue;let s=ue(e,n.href);if(s!==null&&Ys(s))return!0}return!1}function vt(e){let t=[];for(let n of e.files){if(!n.path.startsWith("skills/")||!n.path.endsWith("SKILL.md")||(n.lines??0)<=zs)continue;let s=p(e,n.path);s===null||Xs(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 t}async function It(e){let t=S(e),n=e.files.filter(i=>i.path.startsWith("docs/ai/")).length;if(!t&&n<2)return[];let s=await Ks(e.repoRoot);return Js(s)?[]:[{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.'}]}var Qs=["AGENTS.md","CLAUDE.md","GEMINI.md",".github/copilot-instructions.md",".agent/README.md"],Zs=["IMPORTANT","CRITICAL","MANDATORY","REQUIRED","MUST NOT","MUST","NEVER","ALWAYS","SHALL","DO NOT"],ei=.03,ti=40,ni=[{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 Et(e){return e.replaceAll(/```[\s\S]*?```/g," ")}function si(e){let t=e.match(/\S+/g);return t===null?0:t.length}function ii(e){let t=0;for(let n of Zs){let s=e.match(new RegExp(`\\b${n}\\b`,"g"));s!==null&&(t+=s.length)}return t}function Te(e){return Qs.filter(t=>p(e,t)!==null)}function Lt(e){return Te(e).length>0}function ri(e){let t=[];for(let n of Te(e)){let s=p(e,n);if(s===null)continue;let i=Et(s),r=si(i);if(r<ti)continue;let o=ii(i),a=o/r;if(a<=ei)continue;let c=(a*100).toFixed(1);t.push({ruleId:"emphasis-keyword-density",severity:"info",message:`${n} uses ${String(o)} all-caps emphasis keyword(s) across ${String(r)} 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 t}function oi(e){let t=[];for(let n of Te(e)){let s=p(e,n);if(s===null)continue;let i=Et(s),r=ni.filter(({pattern:o})=>o.test(i)).map(({label:o})=>o);r.length!==0&&t.push({ruleId:"identity-language-absent",severity:"info",message:`${n} contains identity/roleplay filler: ${r.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 t}var Ft=[{id:"emphasis-keyword-density",title:"Emphasis-keyword density",severity:"info",category:"instruction-quality",dimension:"maintainability",harnesses:[],check:ri},{id:"identity-language-absent",title:"No identity-language filler",severity:"info",category:"instruction-quality",dimension:"maintainability",harnesses:[],check:oi}];var ai=["docs/","skills/","agents/",".cursor/",".github/",".codex/",".agent/",".claude/"],ci=new Set(["AGENTS.md","CLAUDE.md","GEMINI.md","README.md",".github/copilot-instructions.md"]);function Tt(e){let t=e.replaceAll("\\","/").replace(/\/+$/,"");return ci.has(t)?!0:ai.some(n=>t===n.slice(0,-1)||t.startsWith(n))}var li=["",".md","/README.md","/index.md"];async function Ht(e,t){for(let n of li){let s=`${t}${n}`.replaceAll("\\","/");if(await O(e,s))return!0}return!1}var ui=8;function di(e){return/my-doc\.md|example\.spec\.|\/example\//i.test(e)}function pi(e){return e.endsWith("/")?!0:e.endsWith(".md")||e.endsWith(".mdc")}async function Nt(e){let t=[];for(let n of e.files){if(!n.path.endsWith(".md")&&!n.path.endsWith(".mdc"))continue;let s=p(e,n.path);if(s===null)continue;let i=0;for(let r of _(s)){if(le(r.href))continue;let o=ue(n.path,r.href);if(!(o===null||!Tt(o)||!pi(o)||di(o)||await Ht(e.repoRoot,o))&&(t.push({ruleId:"guidance-links-resolve",severity:"warn",message:`Broken link in ${n.path}: (${r.href}) does not resolve.`,file:n.path,line:de(s,r.href),harnesses:[],hint:"Fix the path or add the missing guidance file."}),i+=1,i>=ui))break}}return t}var He="docs/ai/rules.md",pe=3,fi=80;function Ne(e){return e.trim().replaceAll(/\s+/g," ")}function gi(e){let t=Ne(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 Pt(e){return e.map(t=>Ne(t)).filter(t=>t.length>0).join(`
128
+ `)}function hi(e,t){let n=e.split(`
129
+ `),s=Pt(t.split(`
130
+ `)),i=[],r=new Set;for(let o=0;o<=n.length-pe;o+=1){if(r.has(o))continue;let a=n.slice(o,o+pe);if(!a.every(u=>gi(u)))continue;let c=Pt(a);if(!(c.length<fi)&&s.includes(c)){i.push({startLine:o+1,lineCount:pe,sample:Ne(a[0]??"")}),r.add(o);for(let u=1;u<pe;u+=1)r.add(o+u)}}return i}function Dt(e){let t=p(e,He);if(t===null)return[];let n=[];for(let s of Q){let i=p(e,s);if(i===null)continue;let r=hi(i,t);for(let o of r)n.push({ruleId:"adapter-content-duplication",severity:"warn",message:`${s} duplicates ${String(o.lineCount)} lines from ${He} near line ${String(o.startLine)}.`,file:s,line:o.startLine,harnesses:[],hint:`Replace duplicated rules with a pointer to ${He}.`})}return n}function fe(e){return e.intelligenceLayer??null}function ge(e){return e.packageJson.path!==null||e.workflows.length>0||e.prTemplates.length>0}function $t(e){let t=fe(e);return t!==null&&ge(t)}function Pe(e,t,n,s){return{ruleId:e,severity:"info",message:t,file:s,line:null,harnesses:[],hint:n}}function Mt(e){let t=fe(e);return t===null||!ge(t)?[]:t.guidanceMaintenanceScripts.length>0?[]:[Pe("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)]}function _t(e){let t=fe(e);return t===null||!ge(t)?[]:t.aiHarnessPrTemplates.length>0?[]:[Pe("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")]}function jt(e){let t=fe(e);return t===null||!ge(t)?[]:t.guidanceCiWorkflows.length>0?[]:[Pe("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)]}function I(e){return e.intelligenceLayer??null}function he(e){return Object.entries(e.packageJson.scripts).map(([t,n])=>({name:t,command:n}))}function De(e,t,n){return he(e).some(s=>t.test(s.name)||n.test(s.command))}function mi(e,t){return he(e).filter(n=>t.test(n.name)||t.test(n.command)).map(n=>n.name).toSorted()}function $e(e){return e.workflows.map(t=>t.commands.join(`
72
131
  `)).join(`
73
- `)}function A(e){return e.packageJson.path!==null||e.configs.length>0||e.workflows.length>0}function At(e){let t=L(e);return t!==null&&A(t)}function P(e,t,n,s){return{ruleId:e,severity:"info",message:t,file:s,line:null,harnesses:[],hint:n}}function Rt(e){let t=L(e);if(t===null||!A(t))return[];let n=Ie(t,/(^|:)(typecheck|check:types)(:|$)/i,/\b(tsc\s+--noEmit|vue-tsc|svelte-check|mypy|pyright|cargo\s+check)\b/i),s=t.configs.some(o=>o.capabilities.includes("strict-typecheck")),i=de(t).some(o=>/\b(mypy|pyright|cargo\s+check)\b/i.test(o.command));return n&&(s||i)?[]:[P("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)]}function Et(e){let t=L(e);if(t===null||!A(t))return[];let n=Ie(t,/(^|:)(lint|check:lint)(:|$)/i,/\b(eslint|oxlint|biome|ruff)\b/i),s=t.configs.some(i=>i.kind==="lint");return n||s?[]:[P("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)]}function vt(e){let t=L(e);if(t===null||!A(t))return[];let n=Ie(t,/(^|:)(test|e2e|integration)(:|$)/i,/\b(vitest|jest|playwright|cypress|pytest|cargo\s+test|go\s+test)\b/i),s=t.configs.some(i=>i.kind==="test");return n||s?[]:[P("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)]}function It(e){let t=L(e);return t===null||!A(t)?[]:Fs(t,/(^|:)(test|e2e).*(file|focused|changed|related|unit|integration|watch|grep)|(--grep|--filter|--testNamePattern|--findRelatedTests)/i).length>0?[]:[P("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)]}function Ft(e){let t=L(e);if(t===null||!A(t))return[];let n=Fe(t);return/(typecheck|tsc\s+--noEmit|lint|oxlint|eslint|biome|ruff|check:md|lint:md)/i.test(n)?[]:[P("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)]}function Ht(e){let t=L(e);if(t===null||!A(t))return[];let n=Fe(t);return/(npm\s+test|npm\s+run\s+test|vitest|jest|playwright|cypress|pytest|cargo\s+test|go\s+test)/i.test(n)?[]:[P("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)]}function Pt(e){let t=L(e);if(t===null||!A(t))return[];let n=de(t).map(a=>`${a.name} ${a.command}`).join(`
74
- `),s=Fe(t),i=/(scan:self|check:ai-system|lint:md|check:links|qmd)/i.test(n),o=t.prTemplates.length>0,r=/(scan:self|check:ai-system|lint:md|check:links)/i.test(s);return i&&(o||r)?[]:[P("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)]}var Hs=[{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 Ps(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 Ts(e,t){let n=e.split(`
75
- `);for(let s=0;s<n.length;s+=1){let i=n[s]??"";if(!Ps(i)&&(t.lastIndex=0,t.test(i)))return s+1}return null}function Ns(e,t){return t.lastIndex=0,t.test(e)}function Tt(e){let t=[];for(let n of e.files){if(!n.path.endsWith(".md")&&!n.path.endsWith(".mdc"))continue;let s=f(e,n.path);if(s!==null)for(let i of Hs){let o=Ts(s,i.pattern);if(o!==null){t.push({ruleId:"forbidden-legacy-paths",severity:"warn",message:`${n.path} references a legacy guidance path (${i.id}).`,file:n.path,line:o,harnesses:[],hint:i.message});continue}for(let r of M(s))Ns(r.href,i.pattern)&&t.push({ruleId:"forbidden-legacy-paths",severity:"warn",message:`${n.path} links to a legacy guidance path (${i.id}).`,file:n.path,line:ae(s,r.href),harnesses:[],hint:i.message})}}return t}function pe(e){return e.intelligenceLayer??null}function Nt(e){let t=pe(e);return t===null?!1: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 Dt(e){let t=pe(e);return t!==null&&t.memoryDocs.length>0}function Mt(e){return Nt(e)}function Ds(e){return Object.entries(e.packageJson.scripts).some(([t,n])=>/qmd|search/i.test(t)||/qmd|search/i.test(n))}function $t(e){let t=pe(e);if(t===null||t.memoryDocs.length===0)return[];let n=t.memoryIndexes.length>0,i=!(t.packageJson.path!==null)||Ds(t);return n&&i?[]:[{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."}]}function jt(e){let t=pe(e);if(t===null||!Nt(e))return[];let n=t.localContextConventions.join(`
76
- `),s=/naming|codebase-map|local-context/i.test(n),i=/comment|codebase-map|local-context/i.test(n);return t.nestedAgentsFiles.length>0||s&&i?[]:[{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.'}]}var Ms=[wt,Tt,Rt,Et,vt,It,Ft,Ht,Pt,Ct,xt,Lt,$t,jt];function Gt(e){let t=[];for(let n of Ms)t.push(...n(e));return t}function _t(e,t,n,s){let i=t?.[n];if(w(i)&&Object.keys(i).some(l=>l.startsWith(s)))return!0;if(e===null)return!1;let o=n.replaceAll(".",String.raw`\.`);return new RegExp(`"${o}"\\s*:\\s*\\{[^}]*"${s}[^"]*"`).test(e)}async function Ot(e){let t=await H(e.repoRoot),n=[];return _t(t.settingsRaw,t.settings,"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.settingsRaw,t.settings,"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 }.'}),n}function Wt(e,t){return e.length===0?!0:e.some(n=>t.includes(n))}function He(e,t,n,s){return{ruleId:e,severity:"warn",message:`${t} has ${String(n)} lines; keep root adapters thin (max ${String(v)}).`,file:t,line:null,harnesses:[s],hint:"Move detailed guidance to docs/ai/ and skills/; keep the adapter as a pointer."}}function $s(e){let t=[];for(let n of X(e,"skills/")){if(!n.endsWith("/SKILL.md")&&!n.endsWith("SKILL.md"))continue;let s=f(e,n);if(s===null)continue;let i=me(s);if(i===null){t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing YAML frontmatter.`,file:n,line:null,harnesses:[]});continue}G(i,"name")||t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing a name field in frontmatter.`,file:n,line:null,harnesses:[]}),G(i,"description")||t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing a description field in frontmatter.`,file:n,line:null,harnesses:[]})}return t}function js(e){let t=[];for(let n of X(e,"skills/")){if(!n.endsWith("SKILL.md"))continue;let s=I(e,n);s!==null&&s>ge&&t.push({ruleId:"skill-line-count",severity:"warn",message:`${n} has ${String(s)} lines; keep skills under ${String(ge)}.`,file:n,line:null,harnesses:[],hint:"Move detail to docs/; keep SKILL.md as a pointer."})}return t}function Gs(e){let t=[];for(let n of X(e,"agents/")){if(!n.endsWith(".agent.md"))continue;let s=f(e,n);if(s===null)continue;let i=me(s);if(i===null){t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing YAML frontmatter.`,file:n,line:null,harnesses:[]});continue}G(i,"name")||t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing a name field in frontmatter.`,file:n,line:null,harnesses:[]}),G(i,"description")||t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing a description field in frontmatter.`,file:n,line:null,harnesses:[]})}return t}function _s(e){let t=[];for(let n of Y){if(!y(e,n))continue;let s=f(e,n);s===null||Be(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 t}async function Os(e){if(!e.files.some(i=>i.path.startsWith("skills/")))return[];let n=[],s=[".github/skills",".cursor/skills"];for(let i of s)await _(e.repoRoot,i)&&n.push({ruleId:"no-duplicate-skill-trees",severity:"error",message:`${i}/ duplicates root skills/; use skills/ only.`,file:i,line:null,harnesses:[],hint:"Remove the shadow tree and keep canonical skills/ at the repo root."});return n}async function Ws(e){return e.files.some(n=>n.path.startsWith("agents/"))?await _(e.repoRoot,".github/agents")?[{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."}]:[]:[]}async function Us(e){let t=await H(e.repoRoot);return t.hooksDirExists?t.settings?.["chat.useCustomAgentHooks"]===!0?[]:[{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.'}]:[]}var qs={id:"shared-agents-md",title:"Shared AGENTS.md entry point",severity:"warn",category:"structure",dimension:"layering",harnesses:[],check(e){return y(e,"AGENTS.md")?[]:[{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."}]}},Bs={id:"shared-rules-doc",title:"Canonical rules doc",severity:"warn",category:"structure",dimension:"layering",harnesses:[],check(e){return y(e,"docs/ai/rules.md")?[]:[{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."}]}},Vs={id:"adapter-thin-claude",title:"Thin CLAUDE.md adapter",severity:"warn",category:"adapter",dimension:"layering",harnesses:["claude"],check(e){let t=I(e,"CLAUDE.md");return t===null||t<=v?[]:[He("adapter-thin-claude","CLAUDE.md",t,"claude")]}},zs={id:"adapter-thin-gemini",title:"Thin GEMINI.md adapter",severity:"warn",category:"adapter",dimension:"layering",harnesses:["gemini"],check(e){let t=I(e,"GEMINI.md");return t===null||t<=v?[]:[He("adapter-thin-gemini","GEMINI.md",t,"gemini")]}},Js={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=I(e,t);return n===null||n<=v?[]:[He("adapter-thin-copilot",t,n,"copilot")]}},Ks={id:"adapter-points-to-shared",title:"Adapters reference shared layers",severity:"warn",category:"adapter",dimension:"layering",harnesses:[],check:_s},Ys={id:"skill-frontmatter",title:"Skill frontmatter",severity:"error",category:"skills",dimension:"maintainability",harnesses:[],check:$s},Xs={id:"skill-line-count",title:"Skill line budget",severity:"warn",category:"skills",dimension:"maintainability",harnesses:[],check:js},Qs={id:"agent-frontmatter",title:"Agent frontmatter",severity:"error",category:"agents",dimension:"maintainability",harnesses:[],check:Gs},Zs={id:"skills-index",title:"Skill slug index",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:dt},ei={id:"claude-agent-routing",title:"Claude agent routing table",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:["claude"],check:pt},ti={id:"agents-md-mentions-skills",title:"AGENTS.md skill discovery",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:ft},ni={id:"skill-doc-deep-links",title:"Skills deep-link into docs",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:gt},Ut=[qs,Bs,Vs,zs,Js,Ks,Ys,Xs,Qs,Zs,ei,ti,ni];function si(e,t,n){return Wt(e.harnesses,t.harnesses)?n===null||n.length===0||e.harnesses.length===0?!0:e.harnesses.some(s=>n.includes(s)):!1}function ii(e,t,n){return Wt(n,e.harnesses)?t===null||t.length===0?!0:n.some(s=>t.includes(s)):!1}async function qt(e,t){let n=[];for(let l of Ut)si(l,e,t)&&n.push(...l.check(e));if(ii(e,t,["cursor","copilot"])){let l=await Ot(e);n.push(...l);let d=await Us(e);n.push(...d)}let s=await Os(e);n.push(...s);let i=await Ws(e);n.push(...i);let o=await mt(e);n.push(...o);let r=await kt(e);n.push(...r),n.push(...Gt(e));let a=[...ct(e),...at(e)];return t===null||t.length===0?n.push(...a):n.push(...a.filter(l=>l.harnesses.some(d=>t.includes(d)))),n}var ri=new Set(["skills-index","agents-md-mentions-skills","skill-doc-deep-links"]),oi=new Set(["strict-typecheck-present","lint-gate-present","test-gates-present","focused-test-commands-present","ci-enforcement-gates","ci-validation-gates","correction-loop-documented"]),ai=new Set(["adapter-context-budget","always-loaded-budget"]),ci=new Set(["guidance-maintenance-script","pr-template-ai-harness-check","ci-guidance-lint"]);function Pe(e,t){return ri.has(e)?S(t):e==="qmd-script-present"?li(t):e==="claude-agent-routing"?t.harnesses.includes("claude")&&y(t,"CLAUDE.md"):oi.has(e)?At(t):ai.has(e)?ot(t):ci.has(e)?bt(t):e==="memory-docs-indexed"?Dt(t):e==="local-context-patterns"?Mt(t):!0}function li(e){return S(e)?!0:e.files.filter(n=>n.path.startsWith("docs/ai/")).length>=2}var Te={"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","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"};function Bt(e){return Te[e]??null}var ui=[{min:85,grade:"excellent"},{min:70,grade:"good"},{min:50,grade:"fair"},{min:0,grade:"poor"}];function $(e){for(let{min:t,grade:n}of ui)if(e>=t)return n;return"poor"}function Vt(e,t){return t===0?0:e>=80?95:e>=65?82:e>=50?68:e>=30?52:35}var di=["layering","sharing","discoverability","harnessWiring","maintainability","guardrails"],Ne={error:15,warn:6,info:2},pi=35;function fi(e){let t=e.filter(s=>s.detected&&s.score!==null);if(t.length===0)return 0;let n=t.reduce((s,i)=>s+(i.score??0),0);return Math.round(n/t.length)}function Jt(e){return Object.entries(Te).filter(([,t])=>t===e).map(([t])=>t)}function De(e,t){return e.filter(n=>Bt(n.ruleId)===t)}function gi(e){let t=0;for(let n of e)n.severity==="error"?t+=Ne.error:n.severity==="warn"?t+=Ne.warn:t+=Ne.info;return Math.min(t,pi)}function zt(e,t,n){let s=Jt(e).filter(l=>Pe(l,n)),i=s.length,o=new Set(De(t,e).map(l=>l.ruleId)),r=s.filter(l=>!o.has(l)).length,a=i===0?0:Math.round(r/i*100);return{score:a,grade:$(a),passedRules:r,applicableRules:i}}function mi(e,t,n){let s=Jt("sharing").filter(a=>Pe(a,t)),i=new Set(De(e,"sharing").map(a=>a.ruleId)),o=n.totals.lines>0,r=n.shared.percentLines>=65;return{passedRules:s.filter(a=>!i.has(a)).length+(r?1:0),applicableRules:s.length+(o?1:0)}}function hi(){let e={score:0,grade:$(0),passedRules:0,applicableRules:0};return{layering:{...e},sharing:{...e},discoverability:{...e},harnessWiring:{...e},maintainability:{...e},guardrails:{...e}}}function Me(e,t,n,s){let i=hi();for(let o of di){if(o==="sharing"){let r=Vt(t.shared.percentLines,t.totals.lines),a=gi(De(e,o)),l=Math.max(0,Math.min(100,r-a)),d=mi(e,s,t);i.sharing={score:l,grade:$(l),passedRules:d.passedRules,applicableRules:d.applicableRules};continue}if(o==="harnessWiring"){let r=zt(o,e,s),a=fi(n),l=a===0?r.score:Math.round((r.score+a)/2),d=Math.max(0,Math.min(100,l));i.harnessWiring={score:d,grade:$(d),passedRules:r.passedRules,applicableRules:r.applicableRules};continue}i[o]=zt(o,e,s)}return{profile:"meta-harness",dimensions:i}}import{readFile as Kt,readdir as yi,stat as Yt}from"node:fs/promises";import z from"node:path";var ki=[".md",".mdc"],Si=["AGENTS.md","docs/ai/rules.md","docs/ai/ai-system.md","docs/ai/available-skills.md","docs/ai/hooks.md"],wi=[{path:"CLAUDE.md",harness:"claude"},{path:"GEMINI.md",harness:"gemini"},{path:".github/copilot-instructions.md",harness:"copilot"},{path:".agent/README.md",harness:"antigravity"}],bi=[{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"}];function Ci(e){return ki.some(t=>e.endsWith(t))}function xi(e){return e.length===0?0:e.split(`
77
- `).length}async function Xt(e){let t=[],n=[];try{n=await yi(e)}catch{return t}for(let s of n){let i=z.join(e,s),o=await Yt(i);o.isDirectory()?t.push(...await Xt(i)):o.isFile()&&Ci(i)&&t.push(i)}return t}async function Li(e){let{repoRoot:t,relativePath:n,layer:s,harness:i}=e,o=z.join(t,n);try{let r=await Yt(o);if(!r.isFile())return null;let a=await Kt(o,"utf8"),l={path:n,layer:s,lines:xi(a),bytes:r.size};return i!==void 0&&(l.harness=i),l}catch{return null}}async function $e(e){let t=[],n=new Map,s=new Set;async function i(o,r,a){let l=o.replaceAll("\\","/");if(s.has(l))return;let d=await Li({repoRoot:e,relativePath:l,layer:r,harness:a});if(d===null)return;s.add(l),t.push(d);let h=z.join(e,l);try{let p=await Kt(h,"utf8");n.set(l,p)}catch{}}for(let o of Si)await i(o,"shared");for(let o of wi)await i(o.path,"adapter",o.harness);for(let{dir:o,layer:r,harness:a}of bi){let l=z.join(e,o),d=await Xt(l);for(let h of d){let p=z.relative(e,h).replaceAll("\\","/");await i(p,r,a)}}return t.sort((o,r)=>o.path.localeCompare(r.path)),{files:t,contents:n}}import{readFile as Ai}from"node:fs/promises";import Qt from"node:path";import{fileURLToPath as Ri}from"node:url";var Zt=null;function en(){return Zt??=Ei(),Zt}async function Ei(){let e=Qt.resolve(Qt.dirname(Ri(import.meta.url)),"../package.json"),t=await Ai(e,"utf8"),n=JSON.parse(t);if(!vi(n))throw new Error("package.json is missing a string version field");return{version:n.version}}function vi(e){return typeof e=="object"&&e!==null&&"version"in e&&typeof e.version=="string"}import{readFile as Ii,readdir as Fi,stat as Ge}from"node:fs/promises";import T from"node:path";var Hi=new Set([".git","node_modules","dist","coverage"]),Pi=[/^tsconfig(?:\..+)?\.json$/],Ti=[/^eslint\.config\.[cm]?[jt]s$/,/^\.eslintrc(?:\..+)?$/,/^\.oxlintrc(?:\..+)?$/,/^biome\.jsonc?$/,/^ruff\.toml$/,/^\.ruff\.toml$/],Ni=[/^\.prettierrc(?:\..+)?$/,/^\.markdownlint(?:rc)?(?:\..+)?$/],Di=[/^vitest\.config\.[cm]?[jt]s$/,/^jest\.config\.[cm]?[jt]s$/,/^playwright\.config\.[cm]?[jt]s$/,/^cypress\.config\.[cm]?[jt]s$/],Mi=[/^package\.json$/,/^pyproject\.toml$/,/^Cargo\.toml$/,/^go\.mod$/],tn=/(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;function ji(e){return e.length===0?0:e.split(`
78
- `).length}async function Gi(e,t){try{return(await Ge(T.join(e,t))).isFile()}catch{return!1}}async function K(e,t){try{return await Ii(T.join(e,t),"utf8")}catch{return null}}async function nn(e,t=""){let n=T.join(e,t),s=[];try{s=await Fi(n)}catch{return[]}let i=[];for(let o of s){if(Hi.has(o))continue;let r=T.join(t,o).replaceAll("\\","/"),a=T.join(e,r),l=await Ge(a);l.isDirectory()?i.push(...await nn(e,r)):l.isFile()&&i.push(r)}return i}function _i(e){if(e===null)return{path:null,scripts:{},dependencies:[],devDependencies:[]};try{let t=JSON.parse(e);if(!sn(t))return{path:"package.json",scripts:{},dependencies:[],devDependencies:[]};let n=je(t.scripts),s=Object.keys(je(t.dependencies)).toSorted(),i=Object.keys(je(t.devDependencies)).toSorted();return{path:"package.json",scripts:n,dependencies:s,devDependencies:i}}catch{return{path:"package.json",scripts:{},dependencies:[],devDependencies:[]}}}function sn(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function je(e){if(!sn(e))return{};let t={};for(let[n,s]of Object.entries(e))typeof s=="string"&&(t[n]=s);return t}function J(e,t){return t.some(n=>n.test(e))}function Oi(e){let t=T.posix.basename(e);return J(t,Pi)?{path:e,kind:"typecheck",capabilities:["typecheck"]}:J(t,Ti)?{path:e,kind:"lint",capabilities:["lint"]}:J(t,Ni)?{path:e,kind:"format",capabilities:["format"]}:J(t,Di)?{path:e,kind:"test",capabilities:["test"]}:J(t,Mi)?{path:e,kind:"manifest",capabilities:["project-manifest"]}:null}function Wi(e){let t=[],n=/^\s*-\s*run:\s*(.+)$/,s=/^\s*-\s*run:\s*[>|]/,i=!1;for(let o of e.split(/\r?\n/)){let r=o.match(n);if(r!==null){t.push(r[1]?.trim()??""),i=!1;continue}if(s.test(o)){i=!0;continue}i&&(/^\s{6,}\S/.test(o)?t.push(o.trim()):/^\s*-\s/.test(o)&&(i=!1))}return t.filter(o=>o.length>0)}function Ui(e){return/^\.github\/workflows\/.+\.ya?ml$/.test(e)}function qi(e){return e===".github/PULL_REQUEST_TEMPLATE.md"||/^\.github\/PULL_REQUEST_TEMPLATE\/.+\.md$/.test(e)||/^docs\/pull_request_template\.md$/i.test(e)}function rn(e,t){return tn.test(`${e}
79
- ${t}`)}function on(e){return tn.test(e.commands.join(`
80
- `))}function Bi(e){return $i.test(e)}function Vi(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 zi(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 Ji(e){let t=e.toLowerCase();return t.includes("naming")||t.includes("comment")||t.includes("local-context")||t.includes("codebase-map")}async function j(e,t,n,s,i){let o=T.join(e,t),r=await Ge(o),a=await K(e,t),l={path:t,kind:n,layer:s,capabilities:i,bytes:r.size};return a!==null&&(l.lines=ji(a)),l}async function Ki(e,t){let n=await K(e,t);return n===null?null:{path:t,commands:Wi(n),content:n}}function an(e){let t=Object.keys(e.packageJson.scripts),n=t.filter(r=>/(^|:)(typecheck|lint|format|check)(:|$)/i.test(r)),s=t.filter(r=>/(^|:)(test|e2e)(:|$)/i.test(r)),i=t.filter(r=>rn(r,e.packageJson.scripts[r]??"")),o=e.workflows.filter(on).map(r=>r.path).toSorted();return{surfaces:e.surfaces,enforcement:{scripts:n.toSorted(),configs:e.configs.filter(r=>r.kind==="typecheck"||r.kind==="lint").map(r=>r.path).toSorted(),ciWorkflows:e.workflows.filter(r=>/(typecheck|lint|format|check)/i.test(r.commands.join(`
81
- `))).map(r=>r.path).toSorted()},validation:{scripts:s.toSorted(),configs:e.configs.filter(r=>r.kind==="test").map(r=>r.path).toSorted(),ciWorkflows:e.workflows.filter(r=>/(npm test|npm run test|vitest|jest|playwright|cypress)/i.test(r.commands.join(`
82
- `))).map(r=>r.path).toSorted()},memory:{docs:e.memoryDocs.toSorted(),indexes:e.memoryIndexes.toSorted()},localContext:{conventions:e.localContextConventions.toSorted(),nestedAgentsFiles:e.nestedAgentsFiles.toSorted()},correctionLoop:{scripts:i.toSorted(),prTemplates:e.prTemplates.toSorted(),ciWorkflows:o,maintenanceScripts:e.guidanceMaintenanceScripts.toSorted(),prTemplateChecks:e.aiHarnessPrTemplates.toSorted(),guidanceCiWorkflows:o}}}async function _e(e){let t=await nn(e),n=_i(await K(e,"package.json")),s=[],i=[],o=[],r=[],a=[],l=[],d=[],h=[],p=[];for(let u of t){let g=Oi(u);if(g!==null){let m={...g};if(g.kind==="typecheck"){let C=await K(e,u);C!==null&&/"strict"\s*:\s*true/.test(C)&&(m.capabilities=[...g.capabilities,"strict-typecheck"])}s.push(m),p.push(await j(e,u,"enforcement","config",m.capabilities))}if(Ui(u)){let m=await Ki(e,u);if(m!==null){i.push(m);let C=await j(e,u,"workflow","automation",["ci-workflow"]);p.push(C)}}if(qi(u)){o.push(u);let m=await K(e,u);m!==null&&Bi(m)&&r.push(u);let C=await j(e,u,"automation","pull-request",["pr-template"]);p.push(C)}if(u.endsWith(".md")&&Vi(u)&&(a.push(u),zi(u)&&l.push(u),p.push(await j(e,u,"memory","docs",["memory"]))),u.endsWith(".md")&&Ji(u)&&d.push(u),u.endsWith("/AGENTS.md")){h.push(u);let m=await j(e,u,"local-context","nested-entry",["nested-agents-md"]);p.push(m)}}return n.path!==null&&await Gi(e,n.path)&&p.push(await j(e,n.path,"automation","project",["package-scripts"])),{packageJson:n,configs:s.toSorted((u,g)=>u.path.localeCompare(g.path)),workflows:i.toSorted((u,g)=>u.path.localeCompare(g.path)),prTemplates:o,guidanceMaintenanceScripts:Object.entries(n.scripts).filter(([u,g])=>rn(u,g)).map(([u])=>u).toSorted(),aiHarnessPrTemplates:r.toSorted(),guidanceCiWorkflows:i.filter(u=>on(u)).map(u=>u.path).toSorted(),memoryDocs:a,memoryIndexes:l.toSorted(),localContextConventions:d.toSorted(),nestedAgentsFiles:h,surfaces:p.toSorted((u,g)=>u.path.localeCompare(g.path))}}var cn={error:3,warn:2,info:1};function Xi(e){let t=0,n=0,s=0;for(let i of e)i.severity==="error"?t+=1:i.severity==="warn"?n+=1:s+=1;return{error:t,warn:n,info:s}}async function Oe(e){let t=Yi.resolve(e.repoRoot),n=en(),s=await we(t),{files:i,contents:o}=await $e(t),r=await _e(t),a={repoRoot:t,harnesses:s,files:i,fileContents:o,intelligenceLayer:r},l=be(a);a.contextBudget=l;let d=await qt(a,e.harnessFilter),h=Xi(d),p=Se(i,s),u=await H(t),g=await Ae(a,u,d,p),m=Me(d,p,g,a),C=await Ze(a,u),dn=await n,pn=an(r);return{version:dn.version,root:t,harnesses:s,inventory:{fileCount:i.length,files:i},sharing:p,metaHarness:m,harnessGapMatrix:C,harnessOptimization:g,intelligenceLayer:pn,contextBudget:l,findings:d,summary:h}}function ln(e,t){let n=cn[t];return e.some(s=>cn[s.severity]>=n)}var un=0,Zi=1,R=2;function er(){process.stdout.write(`paniolo-scan \u2014 AI harness diagnostic (read-only)
132
+ `)}function E(e){return e.packageJson.path!==null||e.configs.length>0||e.workflows.length>0}function Gt(e){let t=I(e);return t!==null&&E(t)}function P(e,t,n,s){return{ruleId:e,severity:"info",message:t,file:s,line:null,harnesses:[],hint:n}}function Ot(e){let t=I(e);if(t===null||!E(t))return[];let n=De(t,/(^|:)(typecheck|check:types)(:|$)/i,/\b(tsc\s+--noEmit|vue-tsc|svelte-check|mypy|pyright|cargo\s+check)\b/i),s=t.configs.some(r=>r.capabilities.includes("strict-typecheck")),i=he(t).some(r=>/\b(mypy|pyright|cargo\s+check)\b/i.test(r.command));return n&&(s||i)?[]:[P("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)]}function Wt(e){let t=I(e);if(t===null||!E(t))return[];let n=De(t,/(^|:)(lint|check:lint)(:|$)/i,/\b(eslint|oxlint|biome|ruff)\b/i),s=t.configs.some(i=>i.kind==="lint");return n||s?[]:[P("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)]}function Ut(e){let t=I(e);if(t===null||!E(t))return[];let n=De(t,/(^|:)(test|e2e|integration)(:|$)/i,/\b(vitest|jest|playwright|cypress|pytest|cargo\s+test|go\s+test)\b/i),s=t.configs.some(i=>i.kind==="test");return n||s?[]:[P("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)]}function qt(e){let t=I(e);return t===null||!E(t)?[]:mi(t,/(^|:)(test|e2e).*(file|focused|changed|related|unit|integration|watch|grep)|(--grep|--filter|--testNamePattern|--findRelatedTests)/i).length>0?[]:[P("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)]}function Bt(e){let t=I(e);if(t===null||!E(t))return[];let n=$e(t);return/(typecheck|tsc\s+--noEmit|lint|oxlint|eslint|biome|ruff|check:md|lint:md)/i.test(n)?[]:[P("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)]}function Vt(e){let t=I(e);if(t===null||!E(t))return[];let n=$e(t);return/(npm\s+test|npm\s+run\s+test|vitest|jest|playwright|cypress|pytest|cargo\s+test|go\s+test)/i.test(n)?[]:[P("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)]}function Kt(e){let t=I(e);if(t===null||!E(t))return[];let n=he(t).map(a=>`${a.name} ${a.command}`).join(`
133
+ `),s=$e(t),i=/(scan:self|check:ai-system|lint:md|check:links|qmd)/i.test(n),r=t.prTemplates.length>0,o=/(scan:self|check:ai-system|lint:md|check:links)/i.test(s);return i&&(r||o)?[]:[P("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)]}var yi=[{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 ki(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 wi(e,t){let n=e.split(`
134
+ `);for(let s=0;s<n.length;s+=1){let i=n[s]??"";if(!ki(i)&&(t.lastIndex=0,t.test(i)))return s+1}return null}function Si(e,t){return t.lastIndex=0,t.test(e)}function Jt(e){let t=[];for(let n of e.files){if(!n.path.endsWith(".md")&&!n.path.endsWith(".mdc"))continue;let s=p(e,n.path);if(s!==null)for(let i of yi){let r=wi(s,i.pattern);if(r!==null){t.push({ruleId:"forbidden-legacy-paths",severity:"warn",message:`${n.path} references a legacy guidance path (${i.id}).`,file:n.path,line:r,harnesses:[],hint:i.message});continue}for(let o of _(s))Si(o.href,i.pattern)&&t.push({ruleId:"forbidden-legacy-paths",severity:"warn",message:`${n.path} links to a legacy guidance path (${i.id}).`,file:n.path,line:de(s,o.href),harnesses:[],hint:i.message})}}return t}function me(e){return e.intelligenceLayer??null}function zt(e){let t=me(e);return t===null?!1: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 Yt(e){let t=me(e);return t!==null&&t.memoryDocs.length>0}function Xt(e){return zt(e)}function bi(e){return Object.entries(e.packageJson.scripts).some(([t,n])=>/qmd|search/i.test(t)||/qmd|search/i.test(n))}function Qt(e){let t=me(e);if(t===null||t.memoryDocs.length===0)return[];let n=t.memoryIndexes.length>0,i=!(t.packageJson.path!==null)||bi(t);return n&&i?[]:[{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."}]}function Zt(e){let t=me(e);if(t===null||!zt(e))return[];let n=t.localContextConventions.join(`
135
+ `),s=/naming|codebase-map|local-context/i.test(n),i=/comment|codebase-map|local-context/i.test(n);return t.nestedAgentsFiles.length>0||s&&i?[]:[{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.'}]}var Ci=[Dt,Jt,Ot,Wt,Ut,qt,Bt,Vt,Kt,Mt,_t,jt,Qt,Zt];function en(e){let t=[];for(let n of Ci)t.push(...n(e));return t}function tn(e,t,n,s){let i=t?.[n];if(h(i)&&Object.keys(i).some(c=>c.startsWith(s)))return!0;if(e===null)return!1;let r=n.replaceAll(".",String.raw`\.`);return new RegExp(`"${r}"\\s*:\\s*\\{[^}]*"${s}[^"]*"`).test(e)}async function nn(e){let t=await N(e.repoRoot),n=[];return tn(t.settingsRaw,t.settings,"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 }.'}),tn(t.settingsRaw,t.settings,"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 }.'}),n}function sn(e,t){return e.length===0?!0:e.some(n=>t.includes(n))}function Me(e,t,n,s){return{ruleId:e,severity:"warn",message:`${t} has ${String(n)} lines; keep root adapters thin (max ${String(L)}).`,file:t,line:null,harnesses:[s],hint:"Move detailed guidance to docs/ai/ and skills/; keep the adapter as a pointer."}}function xi(e){let t=[];for(let n of Z(e,"skills/")){if(!n.endsWith("/SKILL.md")&&!n.endsWith("SKILL.md"))continue;let s=p(e,n);if(s===null)continue;let i=we(s);if(i===null){t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing YAML frontmatter.`,file:n,line:null,harnesses:[]});continue}G(i,"name")||t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing a name field in frontmatter.`,file:n,line:null,harnesses:[]}),G(i,"description")||t.push({ruleId:"skill-frontmatter",severity:"error",message:`${n} is missing a description field in frontmatter.`,file:n,line:null,harnesses:[]})}return t}function Ri(e){let t=[];for(let n of Z(e,"skills/")){if(!n.endsWith("SKILL.md"))continue;let s=F(e,n);s!==null&&s>ke&&t.push({ruleId:"skill-line-count",severity:"warn",message:`${n} has ${String(s)} lines; keep skills under ${String(ke)}.`,file:n,line:null,harnesses:[],hint:"Move detail to docs/; keep SKILL.md as a pointer."})}return t}function Ai(e){let t=[];for(let n of Z(e,"agents/")){if(!n.endsWith(".agent.md"))continue;let s=p(e,n);if(s===null)continue;let i=we(s);if(i===null){t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing YAML frontmatter.`,file:n,line:null,harnesses:[]});continue}G(i,"name")||t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing a name field in frontmatter.`,file:n,line:null,harnesses:[]}),G(i,"description")||t.push({ruleId:"agent-frontmatter",severity:"error",message:`${n} is missing a description field in frontmatter.`,file:n,line:null,harnesses:[]})}return t}function vi(e){let t=[];for(let n of Q){if(!k(e,n))continue;let s=p(e,n);s===null||Je(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 t}async function Ii(e){if(!e.files.some(i=>i.path.startsWith("skills/")))return[];let n=[],s=[".github/skills",".cursor/skills"];for(let i of s)await O(e.repoRoot,i)&&n.push({ruleId:"no-duplicate-skill-trees",severity:"error",message:`${i}/ duplicates root skills/; use skills/ only.`,file:i,line:null,harnesses:[],hint:"Remove the shadow tree and keep canonical skills/ at the repo root."});return n}async function Ei(e){return e.files.some(n=>n.path.startsWith("agents/"))?await O(e.repoRoot,".github/agents")?[{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."}]:[]:[]}async function Li(e){let t=await N(e.repoRoot);return t.hooksDirExists?t.settings?.["chat.useCustomAgentHooks"]===!0?[]:[{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.'}]:[]}var Fi={id:"shared-agents-md",title:"Shared AGENTS.md entry point",severity:"warn",category:"structure",dimension:"layering",harnesses:[],check(e){return k(e,"AGENTS.md")?[]:[{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."}]}},Ti={id:"shared-rules-doc",title:"Canonical rules doc",severity:"warn",category:"structure",dimension:"layering",harnesses:[],check(e){return k(e,"docs/ai/rules.md")?[]:[{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."}]}},Hi={id:"adapter-thin-claude",title:"Thin CLAUDE.md adapter",severity:"warn",category:"adapter",dimension:"layering",harnesses:["claude"],check(e){let t=F(e,"CLAUDE.md");return t===null||t<=L?[]:[Me("adapter-thin-claude","CLAUDE.md",t,"claude")]}},Ni={id:"adapter-thin-gemini",title:"Thin GEMINI.md adapter",severity:"warn",category:"adapter",dimension:"layering",harnesses:["gemini"],check(e){let t=F(e,"GEMINI.md");return t===null||t<=L?[]:[Me("adapter-thin-gemini","GEMINI.md",t,"gemini")]}},Pi={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=F(e,t);return n===null||n<=L?[]:[Me("adapter-thin-copilot",t,n,"copilot")]}},Di={id:"adapter-points-to-shared",title:"Adapters reference shared layers",severity:"warn",category:"adapter",dimension:"layering",harnesses:[],check:vi},$i={id:"skill-frontmatter",title:"Skill frontmatter",severity:"error",category:"skills",dimension:"maintainability",harnesses:[],check:xi},Mi={id:"skill-line-count",title:"Skill line budget",severity:"warn",category:"skills",dimension:"maintainability",harnesses:[],check:Ri},_i={id:"agent-frontmatter",title:"Agent frontmatter",severity:"error",category:"agents",dimension:"maintainability",harnesses:[],check:Ai},ji={id:"skills-index",title:"Skill slug index",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:xt},Gi={id:"claude-agent-routing",title:"Claude agent routing table",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:["claude"],check:Rt},Oi={id:"agents-md-mentions-skills",title:"AGENTS.md skill discovery",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:At},Wi={id:"skill-doc-deep-links",title:"Skills deep-link into docs",severity:"info",category:"discoverability",dimension:"discoverability",harnesses:[],check:vt},rn=[Fi,Ti,Hi,Ni,Pi,Di,$i,Mi,_i,ji,Gi,Oi,Wi,...Ft];function Ui(e,t,n){return sn(e.harnesses,t.harnesses)?n===null||n.length===0||e.harnesses.length===0?!0:e.harnesses.some(s=>n.includes(s)):!1}function qi(e,t,n){return sn(n,e.harnesses)?t===null||t.length===0?!0:n.some(s=>t.includes(s)):!1}async function on(e,t){let n=[];for(let c of rn)Ui(c,e,t)&&n.push(...c.check(e));if(qi(e,t,["cursor","copilot"])){let c=await nn(e);n.push(...c);let u=await Li(e);n.push(...u)}let s=await Ii(e);n.push(...s);let i=await Ei(e);n.push(...i);let r=await It(e);n.push(...r);let o=await Nt(e);n.push(...o),n.push(...en(e));let a=[...St(e),...wt(e)];return t===null||t.length===0?n.push(...a):n.push(...a.filter(c=>c.harnesses.some(u=>t.includes(u)))),n}var Bi=new Set(["skills-index","agents-md-mentions-skills","skill-doc-deep-links"]),Vi=new Set(["strict-typecheck-present","lint-gate-present","test-gates-present","focused-test-commands-present","ci-enforcement-gates","ci-validation-gates","correction-loop-documented"]),Ki=new Set(["emphasis-keyword-density","identity-language-absent"]),Ji=new Set(["adapter-context-budget","always-loaded-budget"]),zi=new Set(["guidance-maintenance-script","pr-template-ai-harness-check","ci-guidance-lint"]);function _e(e,t){return Bi.has(e)?S(t):e==="qmd-script-present"?Yi(t):e==="claude-agent-routing"?t.harnesses.includes("claude")&&k(t,"CLAUDE.md"):Vi.has(e)?Gt(t):Ki.has(e)?Lt(t):Ji.has(e)?kt(t):zi.has(e)?$t(t):e==="memory-docs-indexed"?Yt(t):e==="local-context-patterns"?Xt(t):!0}function Yi(e){return S(e)?!0:e.files.filter(n=>n.path.startsWith("docs/ai/")).length>=2}var je={"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","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"};function an(e){return je[e]??null}var Xi=["layering","sharing","discoverability","harnessWiring","maintainability","guardrails"],Ge={error:15,warn:6,info:2},Qi=35;function Zi(e){let t=e.filter(s=>s.detected&&s.score!==null);if(t.length===0)return 0;let n=t.reduce((s,i)=>s+(i.score??0),0);return Math.round(n/t.length)}function ln(e){return Object.entries(je).filter(([,t])=>t===e).map(([t])=>t)}function Oe(e,t){return e.filter(n=>an(n.ruleId)===t)}function er(e){let t=0;for(let n of e)n.severity==="error"?t+=Ge.error:n.severity==="warn"?t+=Ge.warn:t+=Ge.info;return Math.min(t,Qi)}function cn(e,t,n){let s=ln(e).filter(c=>_e(c,n)),i=s.length,r=new Set(Oe(t,e).map(c=>c.ruleId)),o=s.filter(c=>!r.has(c)).length,a=i===0?0:Math.round(o/i*100);return{score:a,grade:R(a),passedRules:o,applicableRules:i}}function tr(e,t,n){let s=ln("sharing").filter(a=>_e(a,t)),i=new Set(Oe(e,"sharing").map(a=>a.ruleId)),r=n.totals.lines>0,o=n.shared.percentLines>=65;return{passedRules:s.filter(a=>!i.has(a)).length+(o?1:0),applicableRules:s.length+(r?1:0)}}function nr(){let e={score:0,grade:R(0),passedRules:0,applicableRules:0};return{layering:{...e},sharing:{...e},discoverability:{...e},harnessWiring:{...e},maintainability:{...e},guardrails:{...e}}}function We(e,t,n,s){let i=nr();for(let r of Xi){if(r==="sharing"){let o=ze(t.shared.percentLines,t.totals.lines),a=er(Oe(e,r)),c=Math.max(0,Math.min(100,o-a)),u=tr(e,s,t);i.sharing={score:c,grade:R(c),passedRules:u.passedRules,applicableRules:u.applicableRules};continue}if(r==="harnessWiring"){let o=cn(r,e,s),a=Zi(n),c=a===0?o.score:Math.round((o.score+a)/2),u=Math.max(0,Math.min(100,c));i.harnessWiring={score:u,grade:R(u),passedRules:o.passedRules,applicableRules:o.applicableRules};continue}i[r]=cn(r,e,s)}return{profile:"meta-harness",dimensions:i}}import{readFile as un,readdir as sr,stat as dn}from"node:fs/promises";import z from"node:path";var ir=[".md",".mdc"],rr=["AGENTS.md","docs/ai/rules.md","docs/ai/ai-system.md","docs/ai/available-skills.md","docs/ai/hooks.md"],or=[{path:"CLAUDE.md",harness:"claude"},{path:"GEMINI.md",harness:"gemini"},{path:".github/copilot-instructions.md",harness:"copilot"},{path:".agent/README.md",harness:"antigravity"}],ar=[{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"}];function cr(e){return ir.some(t=>e.endsWith(t))}function lr(e){return e.length===0?0:e.split(`
136
+ `).length}async function pn(e){let t=[],n=[];try{n=await sr(e)}catch{return t}for(let s of n){let i=z.join(e,s),r=await dn(i);r.isDirectory()?t.push(...await pn(i)):r.isFile()&&cr(i)&&t.push(i)}return t}async function ur(e){let{repoRoot:t,relativePath:n,layer:s,harness:i}=e,r=z.join(t,n);try{let o=await dn(r);if(!o.isFile())return null;let a=await un(r,"utf8"),c={path:n,layer:s,lines:lr(a),bytes:o.size};return i!==void 0&&(c.harness=i),c}catch{return null}}async function ye(e){let t=[],n=new Map,s=new Set;async function i(r,o,a){let c=r.replaceAll("\\","/");if(s.has(c))return;let u=await ur({repoRoot:e,relativePath:c,layer:o,harness:a});if(u===null)return;s.add(c),t.push(u);let f=z.join(e,c);try{let g=await un(f,"utf8");n.set(c,g)}catch{}}for(let r of rr)await i(r,"shared");for(let r of or)await i(r.path,"adapter",r.harness);for(let{dir:r,layer:o,harness:a}of ar){let c=z.join(e,r),u=await pn(c);for(let f of u){let g=z.relative(e,f).replaceAll("\\","/");await i(g,o,a)}}return t.sort((r,o)=>r.path.localeCompare(o.path)),{files:t,contents:n}}import{readFile as dr}from"node:fs/promises";import fn from"node:path";import{fileURLToPath as pr}from"node:url";var gn=null;function hn(){return gn??=fr(),gn}async function fr(){let e=fn.resolve(fn.dirname(pr(import.meta.url)),"../package.json"),t=await dr(e,"utf8"),n=JSON.parse(t);if(!gr(n))throw new Error("package.json is missing a string version field");return{version:n.version}}function gr(e){return typeof e=="object"&&e!==null&&"version"in e&&typeof e.version=="string"}import{readFile as hr,readdir as mr,stat as qe}from"node:fs/promises";import D from"node:path";var yr=new Set([".git","node_modules","dist","coverage"]),kr=[/^tsconfig(?:\..+)?\.json$/],wr=[/^eslint\.config\.[cm]?[jt]s$/,/^\.eslintrc(?:\..+)?$/,/^\.oxlintrc(?:\..+)?$/,/^biome\.jsonc?$/,/^ruff\.toml$/,/^\.ruff\.toml$/],Sr=[/^\.prettierrc(?:\..+)?$/,/^\.markdownlint(?:rc)?(?:\..+)?$/],br=[/^vitest\.config\.[cm]?[jt]s$/,/^jest\.config\.[cm]?[jt]s$/,/^playwright\.config\.[cm]?[jt]s$/,/^cypress\.config\.[cm]?[jt]s$/],Cr=[/^package\.json$/,/^pyproject\.toml$/,/^Cargo\.toml$/,/^go\.mod$/],mn=/(scan:self|check:ai-system|check:md|lint:md|check:links|qmd|markdownlint|textlint|remark|cspell|paniolo-scan)/i,xr=/(correction loop|intelligence layer|diagnostic rule|rules catalog|canonical rules|paired skill|guidance hygiene|adapters stayed thin|json output keys are stable)/i;function Rr(e){return e.length===0?0:e.split(`
137
+ `).length}async function Ar(e,t){try{return(await qe(D.join(e,t))).isFile()}catch{return!1}}async function X(e,t){try{return await hr(D.join(e,t),"utf8")}catch{return null}}async function yn(e,t=""){let n=D.join(e,t),s=[];try{s=await mr(n)}catch{return[]}let i=[];for(let r of s){if(yr.has(r))continue;let o=D.join(t,r).replaceAll("\\","/"),a=D.join(e,o),c=await qe(a);c.isDirectory()?i.push(...await yn(e,o)):c.isFile()&&i.push(o)}return i}function vr(e){if(e===null)return{path:null,scripts:{},dependencies:[],devDependencies:[]};try{let t=JSON.parse(e);if(!kn(t))return{path:"package.json",scripts:{},dependencies:[],devDependencies:[]};let n=Ue(t.scripts),s=Object.keys(Ue(t.dependencies)).toSorted(),i=Object.keys(Ue(t.devDependencies)).toSorted();return{path:"package.json",scripts:n,dependencies:s,devDependencies:i}}catch{return{path:"package.json",scripts:{},dependencies:[],devDependencies:[]}}}function kn(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Ue(e){if(!kn(e))return{};let t={};for(let[n,s]of Object.entries(e))typeof s=="string"&&(t[n]=s);return t}function Y(e,t){return t.some(n=>n.test(e))}function Ir(e){let t=D.posix.basename(e);return Y(t,kr)?{path:e,kind:"typecheck",capabilities:["typecheck"]}:Y(t,wr)?{path:e,kind:"lint",capabilities:["lint"]}:Y(t,Sr)?{path:e,kind:"format",capabilities:["format"]}:Y(t,br)?{path:e,kind:"test",capabilities:["test"]}:Y(t,Cr)?{path:e,kind:"manifest",capabilities:["project-manifest"]}:null}function Er(e){let t=[],n=/^\s*-\s*run:\s*(.+)$/,s=/^\s*-\s*run:\s*[>|]/,i=!1;for(let r of e.split(/\r?\n/)){let o=r.match(n);if(o!==null){t.push(o[1]?.trim()??""),i=!1;continue}if(s.test(r)){i=!0;continue}i&&(/^\s{6,}\S/.test(r)?t.push(r.trim()):/^\s*-\s/.test(r)&&(i=!1))}return t.filter(r=>r.length>0)}function Lr(e){return/^\.github\/workflows\/.+\.ya?ml$/.test(e)}function Fr(e){return e===".github/PULL_REQUEST_TEMPLATE.md"||/^\.github\/PULL_REQUEST_TEMPLATE\/.+\.md$/.test(e)||/^docs\/pull_request_template\.md$/i.test(e)}function wn(e,t){return mn.test(`${e}
138
+ ${t}`)}function Sn(e){return mn.test(e.commands.join(`
139
+ `))}function Tr(e){return xr.test(e)}function Hr(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 Nr(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 Pr(e){let t=e.toLowerCase();return t.includes("naming")||t.includes("comment")||t.includes("local-context")||t.includes("codebase-map")}async function j(e,t,n,s,i){let r=D.join(e,t),o=await qe(r),a=await X(e,t),c={path:t,kind:n,layer:s,capabilities:i,bytes:o.size};return a!==null&&(c.lines=Rr(a)),c}async function Dr(e,t){let n=await X(e,t);return n===null?null:{path:t,commands:Er(n),content:n}}function bn(e){let t=Object.keys(e.packageJson.scripts),n=t.filter(o=>/(^|:)(typecheck|lint|format|check)(:|$)/i.test(o)),s=t.filter(o=>/(^|:)(test|e2e)(:|$)/i.test(o)),i=t.filter(o=>wn(o,e.packageJson.scripts[o]??"")),r=e.workflows.filter(Sn).map(o=>o.path).toSorted();return{surfaces:e.surfaces,enforcement:{scripts:n.toSorted(),configs:e.configs.filter(o=>o.kind==="typecheck"||o.kind==="lint").map(o=>o.path).toSorted(),ciWorkflows:e.workflows.filter(o=>/(typecheck|lint|format|check)/i.test(o.commands.join(`
140
+ `))).map(o=>o.path).toSorted()},validation:{scripts:s.toSorted(),configs:e.configs.filter(o=>o.kind==="test").map(o=>o.path).toSorted(),ciWorkflows:e.workflows.filter(o=>/(npm test|npm run test|vitest|jest|playwright|cypress)/i.test(o.commands.join(`
141
+ `))).map(o=>o.path).toSorted()},memory:{docs:e.memoryDocs.toSorted(),indexes:e.memoryIndexes.toSorted()},localContext:{conventions:e.localContextConventions.toSorted(),nestedAgentsFiles:e.nestedAgentsFiles.toSorted()},correctionLoop:{scripts:i.toSorted(),prTemplates:e.prTemplates.toSorted(),ciWorkflows:r,maintenanceScripts:e.guidanceMaintenanceScripts.toSorted(),prTemplateChecks:e.aiHarnessPrTemplates.toSorted(),guidanceCiWorkflows:r}}}async function Be(e){let t=await yn(e),n=vr(await X(e,"package.json")),s=[],i=[],r=[],o=[],a=[],c=[],u=[],f=[],g=[];for(let d of t){let m=Ir(d);if(m!==null){let y={...m};if(m.kind==="typecheck"){let x=await X(e,d);x!==null&&/"strict"\s*:\s*true/.test(x)&&(y.capabilities=[...m.capabilities,"strict-typecheck"])}s.push(y),g.push(await j(e,d,"enforcement","config",y.capabilities))}if(Lr(d)){let y=await Dr(e,d);if(y!==null){i.push(y);let x=await j(e,d,"workflow","automation",["ci-workflow"]);g.push(x)}}if(Fr(d)){r.push(d);let y=await X(e,d);y!==null&&Tr(y)&&o.push(d);let x=await j(e,d,"automation","pull-request",["pr-template"]);g.push(x)}if(d.endsWith(".md")&&Hr(d)&&(a.push(d),Nr(d)&&c.push(d),g.push(await j(e,d,"memory","docs",["memory"]))),d.endsWith(".md")&&Pr(d)&&u.push(d),d.endsWith("/AGENTS.md")){f.push(d);let y=await j(e,d,"local-context","nested-entry",["nested-agents-md"]);g.push(y)}}return n.path!==null&&await Ar(e,n.path)&&g.push(await j(e,n.path,"automation","project",["package-scripts"])),{packageJson:n,configs:s.toSorted((d,m)=>d.path.localeCompare(m.path)),workflows:i.toSorted((d,m)=>d.path.localeCompare(m.path)),prTemplates:r,guidanceMaintenanceScripts:Object.entries(n.scripts).filter(([d,m])=>wn(d,m)).map(([d])=>d).toSorted(),aiHarnessPrTemplates:o.toSorted(),guidanceCiWorkflows:i.filter(d=>Sn(d)).map(d=>d.path).toSorted(),memoryDocs:a,memoryIndexes:c.toSorted(),localContextConventions:u.toSorted(),nestedAgentsFiles:f,surfaces:g.toSorted((d,m)=>d.path.localeCompare(m.path))}}var Cn={error:3,warn:2,info:1};function $r(e){let t=0,n=0,s=0;for(let i of e)i.severity==="error"?t+=1:i.severity==="warn"?n+=1:s+=1;return{error:t,warn:n,info:s}}async function Ve(e){let t=xn.resolve(e.repoRoot),n=hn(),s=await oe(t),{files:i,contents:r}=await ye(t),o=await Be(t),a={repoRoot:t,harnesses:s,files:i,fileContents:r,intelligenceLayer:o},c=ve(a);a.contextBudget=c;let u=await on(a,e.harnessFilter),f=$r(u),g=Ae(i,s),d=await N(t),m=await Fe(a,d,u,g),y=We(u,g,m,a),x=await ut(a,d),vn=await n,In=bn(o),En=e.aiReviewResults===void 0?Xe:Ze(e.aiReviewResults);return{version:vn.version,root:t,harnesses:s,inventory:{fileCount:i.length,files:i},sharing:g,metaHarness:y,harnessGapMatrix:x,harnessOptimization:m,intelligenceLayer:In,contextBudget:c,aiReview:En,findings:u,summary:f}}async function Rn(e){let t=xn.resolve(e),n=await oe(t),{files:s,contents:i}=await ye(t);return{version:1,root:t,tasks:Re({repoRoot:t,harnesses:n,files:s,fileContents:i})}}function An(e,t){let n=Cn[t];return e.some(s=>Cn[s.severity]>=n)}var Ke=0,jr=1,C=2;function Gr(){process.stdout.write(`paniolo-scan \u2014 AI harness diagnostic (read-only)
83
142
 
84
143
  Usage:
85
144
  paniolo-scan [options] [path]
86
145
 
87
146
  Options:
88
- --harness <list> Comma-separated harness filter (copilot,cursor,codex,antigravity,claude,gemini)
89
- --format <type> Output format: terminal (default) | json
90
- --fail-on <level> Exit 1 when findings at or above level: error (default) | warn | info
91
- -h, --help Show help
147
+ --harness <list> Comma-separated harness filter (copilot,cursor,codex,antigravity,claude,gemini)
148
+ --format <type> Output format: terminal (default) | json
149
+ --fail-on <level> Exit 1 when findings at or above level: error (default) | warn | info
150
+ --emit-ai-tasks Print optional AI-review prompt tasks as JSON, then exit (no scan)
151
+ --ingest-ai-results <f> Fold AI-review answers from file <f> into the scan's AI dimension
152
+ -h, --help Show help
92
153
 
93
154
  Examples:
94
155
  npx @paniolo/scan
95
156
  npx @paniolo/scan --format json
96
157
  npx @paniolo/scan --harness cursor,codex --fail-on warn
97
- `)}function tr(e){let t=e.split(",").map(i=>i.trim()).filter(i=>i.length>0);if(t.length===0)return null;let n=[],s=[];for(let i of t)i==="copilot"||i==="cursor"||i==="codex"||i==="antigravity"||i==="claude"||i==="gemini"?n.push(i):s.push(i);return s.length>0?(process.stderr.write(`error: unknown harness(es): ${s.join(", ")}
98
- `),process.exit(R),[]):n}function nr(e){return e==="error"||e==="warn"||e==="info"?e:(process.stderr.write(`error: invalid --fail-on value: ${e}
99
- `),process.exit(R),"error")}function sr(e){return e==="terminal"||e==="json"?e:(process.stderr.write(`error: invalid --format value: ${e}
100
- `),process.exit(R),"terminal")}function ir(e){let t=process.cwd(),n=null,s="terminal",i="error",o=!1;for(let r=0;r<e.length;r+=1){let a=e[r];if(a!==void 0){if(a==="-h"||a==="--help"){o=!0;continue}if(a==="--harness"){let l=e[r+1];l===void 0&&(process.stderr.write(`error: --harness requires a value
101
- `),process.exit(R)),n=tr(l),r+=1;continue}if(a==="--format"){let l=e[r+1];l===void 0&&(process.stderr.write(`error: --format requires a value
102
- `),process.exit(R)),s=sr(l),r+=1;continue}if(a==="--fail-on"){let l=e[r+1];l===void 0&&(process.stderr.write(`error: --fail-on requires a value
103
- `),process.exit(R)),i=nr(l),r+=1;continue}a.startsWith("-")&&(process.stderr.write(`error: unknown option: ${a}
104
- `),process.exit(R)),t=Qi.resolve(a)}}return{repoRoot:t,harnessFilter:n,format:s,failOn:i,help:o}}async function rr(){let e=ir(process.argv.slice(2));e.help&&(er(),process.exit(un));try{let t=await Oe({repoRoot:e.repoRoot,harnessFilter:e.harnessFilter});e.format==="json"?fe(t):ke(t),ln(t.findings,e.failOn)&&process.exit(Zi),process.exit(un)}catch(t){let n=t instanceof Error?t.message:String(t);process.stderr.write(`error: ${n}
105
- `),process.exit(R)}}await rr();
158
+ npx @paniolo/scan --emit-ai-tasks
159
+ npx @paniolo/scan --ingest-ai-results answers.json --format json
160
+ `)}function Or(e){let t=e.split(",").map(i=>i.trim()).filter(i=>i.length>0);if(t.length===0)return null;let n=[],s=[];for(let i of t)i==="copilot"||i==="cursor"||i==="codex"||i==="antigravity"||i==="claude"||i==="gemini"?n.push(i):s.push(i);return s.length>0?(process.stderr.write(`error: unknown harness(es): ${s.join(", ")}
161
+ `),process.exit(C),[]):n}function Wr(e){return e==="error"||e==="warn"||e==="info"?e:(process.stderr.write(`error: invalid --fail-on value: ${e}
162
+ `),process.exit(C),"error")}function Ur(e){return e==="terminal"||e==="json"?e:(process.stderr.write(`error: invalid --format value: ${e}
163
+ `),process.exit(C),"terminal")}function qr(e){let t=process.cwd(),n=null,s="terminal",i="error",r=!1,o=!1,a=null;for(let c=0;c<e.length;c+=1){let u=e[c];if(u!==void 0){if(u==="-h"||u==="--help"){r=!0;continue}if(u==="--emit-ai-tasks"){o=!0;continue}if(u==="--ingest-ai-results"){let f=e[c+1];f===void 0&&(process.stderr.write(`error: --ingest-ai-results requires a file path
164
+ `),process.exit(C)),a=f,c+=1;continue}if(u==="--harness"){let f=e[c+1];f===void 0&&(process.stderr.write(`error: --harness requires a value
165
+ `),process.exit(C)),n=Or(f),c+=1;continue}if(u==="--format"){let f=e[c+1];f===void 0&&(process.stderr.write(`error: --format requires a value
166
+ `),process.exit(C)),s=Ur(f),c+=1;continue}if(u==="--fail-on"){let f=e[c+1];f===void 0&&(process.stderr.write(`error: --fail-on requires a value
167
+ `),process.exit(C)),i=Wr(f),c+=1;continue}u.startsWith("-")&&(process.stderr.write(`error: unknown option: ${u}
168
+ `),process.exit(C)),t=_r.resolve(u)}}return{repoRoot:t,harnessFilter:n,format:s,failOn:i,help:r,emitAiTasks:o,ingestResultsPath:a}}async function Br(e){let t=await Mr(e,"utf8"),n=JSON.parse(t);return Qe(n).results}async function Vr(){let e=qr(process.argv.slice(2));if(e.help&&(Gr(),process.exit(Ke)),e.emitAiTasks)try{let t=await Rn(e.repoRoot);process.stdout.write(`${JSON.stringify(t,null,2)}
169
+ `),process.exit(Ke)}catch(t){let n=t instanceof Error?t.message:String(t);process.stderr.write(`error: ${n}
170
+ `),process.exit(C)}try{let t=e.ingestResultsPath===null?void 0:await Br(e.ingestResultsPath),n=await Ve({repoRoot:e.repoRoot,harnessFilter:e.harnessFilter,...t===void 0?{}:{aiReviewResults:t}});e.format==="json"?Se(n):xe(n),An(n.findings,e.failOn)&&process.exit(jr),process.exit(Ke)}catch(t){let n=t instanceof Error?t.message:String(t);process.stderr.write(`error: ${n}
171
+ `),process.exit(C)}}await Vr();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paniolo/scan",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Scan a repository for AI coding agent harness best practices (diagnostic only)",
5
5
  "keywords": [
6
6
  "agents",
@@ -34,8 +34,8 @@
34
34
  "check:ai-system": "npm run build && npm run scan:self",
35
35
  "check:md": "npm run check:md:style && npm run check:md:text",
36
36
  "check:md:style": "markdownlint-cli2",
37
- "check:md:text": "textlint --rulesdir textlint-rules --config .textlintrc.json \"docs/**/*.md\" && textlint --config .textlintrc.skills.json \"skills/*/SKILL.md\" \"agents/**/*.md\" && textlint --config .textlintrc.instructions.json \"AGENTS.md\" \"CLAUDE.md\" \"GEMINI.md\" \".github/copilot-instructions.md\"",
38
- "check:links": "remark --quiet --frail \"docs/**/*.md\" \"skills/**/*.md\" \"agents/**/*.md\" \".github/*.md\" \"*.md\"",
37
+ "check:md:text": "textlint --rulesdir textlint-rules --config .textlintrc.json \"docs/**/*.md\" \".claude/**/*.md\" && textlint --config .textlintrc.skills.json \"skills/*/SKILL.md\" \"agents/**/*.md\" && textlint --config .textlintrc.instructions.json \"AGENTS.md\" \"CLAUDE.md\" \"GEMINI.md\" \".github/copilot-instructions.md\"",
38
+ "check:links": "remark --quiet --frail \"docs/**/*.md\" \"skills/**/*.md\" \"agents/**/*.md\" \".github/*.md\" \".claude/**/*.md\" \"*.md\"",
39
39
  "check:spelling": "cspell --no-progress --no-summary \"**/*.md\"",
40
40
  "lint:md": "npm run check:md && npm run check:links && npm run check:spelling",
41
41
  "start": "node dist/cli.js",