@mthanh/vespercli 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/assets/CATALOG.md +9 -2
- package/assets/claude/.claude-plugin/marketplace.json +9 -9
- package/assets/claude/.claude-plugin/plugin.json +1 -1
- package/assets/claude/agents/code-planner.md +1 -1
- package/assets/claude/agents/code-reviewer.md +1 -1
- package/assets/claude/agents/code-tester.md +1 -1
- package/assets/claude/agents/copywriter.md +1 -1
- package/assets/claude/agents/feature-wrap-document.md +1 -1
- package/assets/claude/agents/janitor.md +1 -1
- package/assets/claude/agents/modernization.md +1 -1
- package/assets/claude/agents/principal-software-engineer.md +1 -1
- package/assets/claude/agents/refine-issue.md +1 -1
- package/assets/claude/agents/se-system-architecture-reviewer.md +1 -1
- package/assets/claude/agents/se-technical-writer.md +1 -1
- package/assets/claude/agents/skill-creator.md +1 -1
- package/assets/claude/agents/task-researcher.md +1 -1
- package/assets/claude/agents/technical-product-manager.md +1 -1
- package/assets/claude/agents/vision-analyst.md +1 -1
- package/assets/claude/agents/vitest.md +1 -1
- package/assets/claude/agents/workspace-learner.md +2 -2
- package/assets/claude/packs/backend/.claude-plugin/plugin.json +1 -1
- package/assets/claude/packs/backend/agents/firebase-developer.md +1 -1
- package/assets/claude/packs/backend/agents/nodejs-express-developer.md +1 -1
- package/assets/claude/packs/docs/.claude-plugin/plugin.json +1 -1
- package/assets/claude/packs/frontend/.claude-plugin/plugin.json +1 -1
- package/assets/claude/packs/frontend/agents/expert-nextjs-developer.md +1 -1
- package/assets/claude/packs/frontend/agents/expert-react-frontend-engineer.md +1 -1
- package/assets/claude/packs/frontend/agents/jest-react-component-analyzer.md +1 -1
- package/assets/claude/packs/frontend/agents/jest-react-scenario-scanner.md +1 -1
- package/assets/claude/packs/frontend/agents/jest-react-test-generator.md +1 -1
- package/assets/claude/packs/frontend/agents/jest-react-test-planner.md +1 -1
- package/assets/claude/packs/frontend/skills/design-taste-frontend/LICENSE +21 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/SKILL.md +529 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/UPSTREAM.json +7 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/app.css +216 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/base.css +105 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/base.js +37 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/charts.js +617 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/scenes/stage.css +28 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/scenes/stage.js +133 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/evals/evals.json +76 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/app.json +1327 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/directions.json +1078 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/heroes.json +1086 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/motions.json +92 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/palettes.json +1485 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/photos.json +7240 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/sections.json +4429 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/sites.json +8350 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/library/type.json +2024 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/app-screens.md +1199 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/colour.md +141 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/copy.md +177 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/critique.md +182 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/imagery.md +791 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/layout.md +292 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/motion.md +980 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/research.md +356 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/scenes.md +174 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/tells.md +115 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/references/type.md +170 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/assets.mjs +865 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/draw.mjs +584 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/inspect.mjs +303 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lib/app-draw.mjs +203 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lib/cdp.mjs +248 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lib/probe.mjs +909 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lib/rules.mjs +243 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lint.mjs +119 -0
- package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/scenes.mjs +124 -0
- package/assets/claude/packs/graphify/.claude-plugin/plugin.json +1 -1
- package/assets/claude/packs/integrations/.claude-plugin/plugin.json +1 -1
- package/assets/claude/packs/playwright/.claude-plugin/plugin.json +1 -1
- package/assets/claude/packs/playwright/agents/playwright-component-analyzer.md +1 -1
- package/assets/claude/packs/playwright/agents/playwright-scenario-scanner.md +1 -1
- package/assets/claude/packs/playwright/agents/playwright-test-generator.md +1 -1
- package/assets/claude/packs/playwright/agents/playwright-test-planner.md +1 -1
- package/assets/claude/packs/playwright/agents/playwright-tester.md +1 -1
- package/assets/claude/packs/polyglot/.claude-plugin/plugin.json +1 -1
- package/assets/claude/packs/styles/.claude-plugin/plugin.json +1 -1
- package/assets/copilot/agents/code-planner.agent.md +1 -1
- package/assets/copilot/agents/code-reviewer.agent.md +1 -1
- package/assets/copilot/agents/code-tester.agent.md +1 -1
- package/assets/copilot/agents/copywriter.agent.md +1 -1
- package/assets/copilot/agents/feature-wrap-document.agent.md +1 -1
- package/assets/copilot/agents/janitor.agent.md +1 -1
- package/assets/copilot/agents/modernization.agent.md +1 -1
- package/assets/copilot/agents/principal-software-engineer.agent.md +1 -1
- package/assets/copilot/agents/refine-issue.agent.md +1 -1
- package/assets/copilot/agents/se-system-architecture-reviewer.agent.md +1 -1
- package/assets/copilot/agents/se-technical-writer.agent.md +1 -1
- package/assets/copilot/agents/skill-creator.agent.md +1 -1
- package/assets/copilot/agents/task-researcher.agent.md +1 -1
- package/assets/copilot/agents/technical-product-manager.agent.md +1 -1
- package/assets/copilot/agents/vision-analyst.agent.md +1 -1
- package/assets/copilot/agents/vitest.agent.md +1 -1
- package/assets/copilot/agents/workspace-learner.agent.md +2 -2
- package/assets/copilot/packs/backend/agents/firebase-developer.agent.md +1 -1
- package/assets/copilot/packs/backend/agents/nodejs-express-developer.agent.md +1 -1
- package/assets/copilot/packs/frontend/agents/expert-nextjs-developer.agent.md +1 -1
- package/assets/copilot/packs/frontend/agents/expert-react-frontend-engineer.agent.md +1 -1
- package/assets/copilot/packs/frontend/agents/jest-react-component-analyzer.agent.md +1 -1
- package/assets/copilot/packs/frontend/agents/jest-react-scenario-scanner.agent.md +1 -1
- package/assets/copilot/packs/frontend/agents/jest-react-test-generator.agent.md +1 -1
- package/assets/copilot/packs/frontend/agents/jest-react-test-planner.agent.md +1 -1
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/LICENSE +21 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/SKILL.md +529 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/UPSTREAM.json +7 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/app.css +216 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/base.css +105 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/base.js +37 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/charts.js +617 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/scenes/stage.css +28 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/scenes/stage.js +133 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/evals/evals.json +76 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/app.json +1327 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/directions.json +1078 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/heroes.json +1086 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/motions.json +92 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/palettes.json +1485 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/photos.json +7240 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/sections.json +4429 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/sites.json +8350 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/type.json +2024 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/app-screens.md +1199 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/colour.md +141 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/copy.md +177 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/critique.md +182 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/imagery.md +791 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/layout.md +292 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/motion.md +980 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/research.md +356 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/scenes.md +174 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/tells.md +115 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/type.md +170 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/assets.mjs +865 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/draw.mjs +584 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/inspect.mjs +303 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lib/app-draw.mjs +203 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lib/cdp.mjs +248 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lib/probe.mjs +909 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lib/rules.mjs +243 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lint.mjs +119 -0
- package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/scenes.mjs +124 -0
- package/assets/copilot/packs/playwright/agents/playwright-component-analyzer.agent.md +1 -1
- package/assets/copilot/packs/playwright/agents/playwright-scenario-scanner.agent.md +1 -1
- package/assets/copilot/packs/playwright/agents/playwright-test-generator.agent.md +1 -1
- package/assets/copilot/packs/playwright/agents/playwright-test-planner.agent.md +1 -1
- package/assets/copilot/packs/playwright/agents/playwright-tester.agent.md +1 -1
- package/assets/manifest.json +2 -0
- package/dist/cli.min.js +102 -102
- package/package.json +1 -1
- package/scripts/__snapshots__/generate-claude-assets.test.js.snap +1 -1
- package/scripts/generate-claude-assets.strict.test.js +1 -1
- package/scripts/generate-claude-assets.test.js +6 -6
- package/scripts/packs-layout.test.js +2 -1
package/dist/cli.min.js
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,1)[0].replace(/\r$/,""),i=
|
|
1
|
+
var sg=Object.defineProperty;var Z=(e,t)=>()=>(e&&(t=e(e=0)),t);var Nn=(e,t)=>{for(var r in t)sg(e,r,{get:t[r],enumerable:!0})};var Ql={};Nn(Ql,{HOOK_GUARD_END:()=>qt,HOOK_GUARD_START:()=>it,classifyForeignHook:()=>Wr,findTopLevelExit:()=>Xl,hookInterpreter:()=>ql,isBinaryHook:()=>la,removeHookRegion:()=>kr});function la(e){let t=Buffer.isBuffer(e)?e:Buffer.from(e??[]);if(t.subarray(0,8192).includes(0))return!0;let r=t.subarray(0,4).toString("hex");return r==="7f454c46"||["feedface","feedfacf","cefaedfe","cffaedfe","cafebabe"].includes(r)?!0:t.length>=2&&t[0]===77&&t[1]===90}function ql(e){if(!e.startsWith("#!"))return"sh";let t=e.slice(2).trim().split(/\s+/).filter(Boolean),r=o=>(o??"").split("/").pop(),n=0,s=r(t[n]);if(s==="env"){for(n+=1;n<t.length;){let o=t[n];if(o.startsWith("-S")&&o.length>2){t[n]=o.slice(2);break}if(o==="-u"||o==="-C"||o==="--unset"||o==="--chdir"){n+=2;continue}if(o.startsWith("-")||/^[A-Za-z_][A-Za-z0-9_]*=/.test(o)){n+=1;continue}break}s=r(t[n])}if(s==="busybox"){let o=r(t[n+1]);return o==="sh"||o==="ash"?o:"busybox"}return s||"sh"}function Wr(e,{whole:t}={}){let r=c=>Buffer.isBuffer(c)?c:Buffer.from(String(c??""),"utf-8"),n=r(e);if(la(r(t??n))||la(n))return{ok:!1,reason:"foreign-hook-language",interpreter:"binary"};let s=n.toString("utf-8"),o=s.split(`
|
|
2
|
+
`,1)[0].replace(/\r$/,""),i=ql(o);if(!og.test(i))return{ok:!1,reason:"foreign-hook-language",interpreter:i};let a=Xl(s);return a?{ok:!1,reason:"foreign-hook-exits",interpreter:i,line:a}:{ok:!0,interpreter:i}}function kr(e){let t=e.indexOf(it);if(t===-1)return null;let r=e.indexOf(qt,t);if(r===-1)return null;let n=t,s=r+qt.length;return n>0&&e[n-1]===`
|
|
3
3
|
`&&(n-=1),e[s]===`
|
|
4
|
-
`&&(s+=1),e.slice(0,n)+e.slice(s)}function
|
|
5
|
-
`&&(s+=1),v==="'"&&g==="("){let S=e.indexOf("'",h+1);if(S===-1)return-1;s+=
|
|
4
|
+
`&&(s+=1),e.slice(0,n)+e.slice(s)}function ug(e){let t=[],r=[],n=0,s=1,o="",i=1,a=!1,c=e.length,l=()=>{(o!==""||a)&&t.push({t:"word",v:o,line:i,quoted:a}),o="",a=!1},d=h=>{o===""&&!a&&(i=s),o+=h},p=(h,g,y)=>{let k=0;for(;h<c;h+=1){let v=e[h];if(v==="\\"){h+=1;continue}if(v===`
|
|
5
|
+
`&&(s+=1),v==="'"&&g==="("){let S=e.indexOf("'",h+1);if(S===-1)return-1;s+=Jl(e,h,S),h=S;continue}if(v==='"'){let S=f(h+1);if(S===-1)return-1;h=S;continue}if(v==="`"){let S=m(h+1);if(S===-1)return-1;h=S;continue}if(v===g)k+=1;else if(v===y&&(k-=1,k===0))return h}return-1},f=h=>{for(;h<c;h+=1){let g=e[h];if(g==="\\"){h+=1;continue}if(g===`
|
|
6
6
|
`&&(s+=1),g==='"')return h;if(g==="$"&&(e[h+1]==="("||e[h+1]==="{")){let y=p(h+1,e[h+1],e[h+1]==="("?")":"}");if(y===-1)return-1;h=y;continue}if(g==="`"){let y=m(h+1);if(y===-1)return-1;h=y}}return-1},m=h=>{for(;h<c;h+=1){let g=e[h];if(g==="\\"){h+=1;continue}if(g===`
|
|
7
7
|
`&&(s+=1),g==="`")return h}return-1};for(;n<c;){let h=e[n];if(h==="\\"){if(e[n+1]===`
|
|
8
|
-
`){n+=2,s+=1;continue}d(e.slice(n,n+2)),n+=2;continue}if(h==="'"){let g=e.indexOf("'",n+1);if(g===-1)return null;o===""&&!a&&(i=s),s+=
|
|
8
|
+
`){n+=2,s+=1;continue}d(e.slice(n,n+2)),n+=2;continue}if(h==="'"){let g=e.indexOf("'",n+1);if(g===-1)return null;o===""&&!a&&(i=s),s+=Jl(e,n,g),o+=e.slice(n+1,g),a=!0,n=g+1;continue}if(h==='"'){let g=s,y=f(n+1);if(y===-1)return null;o===""&&!a&&(i=g),o+=e.slice(n+1,y),a=!0,n=y+1;continue}if(h==="`"){let g=m(n+1);if(g===-1)return null;d(e.slice(n,g+1)),n=g+1;continue}if(h==="$"&&(e[n+1]==="("||e[n+1]==="{")){let g=s,y=p(n+1,e[n+1],e[n+1]==="("?")":"}");if(y===-1)return null;o===""&&!a&&(i=g),o+=e.slice(n,y+1),n=y+1;continue}if(h==="#"&&o===""&&!a){let g=e.indexOf(`
|
|
9
9
|
`,n);n=g===-1?c:g;continue}if(h===`
|
|
10
10
|
`){for(l(),t.push({t:"op",v:`
|
|
11
11
|
`,line:s}),s+=1,n+=1;r.length>0;){let{delim:g,strip:y}=r.shift(),k=!1;for(;n<c;){let v=e.indexOf(`
|
|
12
|
-
`,n),S=e.slice(n,v===-1?c:v),C=y?S.replace(/^\t+/,""):S;if(n=v===-1?c:v+1,s+=1,C===g){k=!0;break}}if(!k)return null}continue}if(h===" "||h===" "||h==="\r"){l(),n+=1;continue}if(h===";"){if(l(),e[n+1]===";"){t.push({t:"op",v:";;",line:s}),n+=e[n+2]==="&"?3:2;continue}if(e[n+1]==="&"){t.push({t:"op",v:";;",line:s}),n+=2;continue}t.push({t:"op",v:";",line:s}),n+=1;continue}if(h==="&"){if(o!==""&&/[<>]$/.test(o)){d("&"),n+=1;continue}if(e[n+1]===">"){d("&"),n+=1;continue}if(l(),e[n+1]==="&"){t.push({t:"op",v:"&&",line:s}),n+=2;continue}t.push({t:"op",v:"&",line:s}),n+=1;continue}if(h==="|"){if(o!==""&&/[>]$/.test(o)){d("|"),n+=1;continue}if(l(),e[n+1]==="|"){t.push({t:"op",v:"||",line:s}),n+=2;continue}t.push({t:"op",v:"|",line:s}),n+=1;continue}if(h==="("||h===")"){if(h==="("&&o!==""&&/[<>]$/.test(o)){let g=p(n,"(",")");if(g===-1)return null;o+=e.slice(n,g+1),n=g+1;continue}l(),t.push({t:"op",v:h,line:s}),n+=1;continue}if(h==="<"&&e[n+1]==="<"&&e[n+2]!=="<"){l();let g=n+2,y=e[g]==="-";for(y&&(g+=1);e[g]===" "||e[g]===" ";)g+=1;let k="";for(;g<c&&!/[\s;&|<>()]/.test(e[g]);){if(e[g]==="'"||e[g]==='"'){let v=e[g],S=e.indexOf(v,g+1);if(S===-1)return null;k+=e.slice(g+1,S),g=S+1;continue}if(e[g]==="\\"){k+=e[g+1]??"",g+=2;continue}k+=e[g],g+=1}if(k==="")return null;r.push({delim:k,strip:y}),t.push({t:"word",v:`<<${k}`,line:s,heredoc:!0}),n=g;continue}d(h),n+=1}return l(),r.length>0?null:t}function
|
|
13
|
-
`&&(n+=1);return n}function
|
|
12
|
+
`,n),S=e.slice(n,v===-1?c:v),C=y?S.replace(/^\t+/,""):S;if(n=v===-1?c:v+1,s+=1,C===g){k=!0;break}}if(!k)return null}continue}if(h===" "||h===" "||h==="\r"){l(),n+=1;continue}if(h===";"){if(l(),e[n+1]===";"){t.push({t:"op",v:";;",line:s}),n+=e[n+2]==="&"?3:2;continue}if(e[n+1]==="&"){t.push({t:"op",v:";;",line:s}),n+=2;continue}t.push({t:"op",v:";",line:s}),n+=1;continue}if(h==="&"){if(o!==""&&/[<>]$/.test(o)){d("&"),n+=1;continue}if(e[n+1]===">"){d("&"),n+=1;continue}if(l(),e[n+1]==="&"){t.push({t:"op",v:"&&",line:s}),n+=2;continue}t.push({t:"op",v:"&",line:s}),n+=1;continue}if(h==="|"){if(o!==""&&/[>]$/.test(o)){d("|"),n+=1;continue}if(l(),e[n+1]==="|"){t.push({t:"op",v:"||",line:s}),n+=2;continue}t.push({t:"op",v:"|",line:s}),n+=1;continue}if(h==="("||h===")"){if(h==="("&&o!==""&&/[<>]$/.test(o)){let g=p(n,"(",")");if(g===-1)return null;o+=e.slice(n,g+1),n=g+1;continue}l(),t.push({t:"op",v:h,line:s}),n+=1;continue}if(h==="<"&&e[n+1]==="<"&&e[n+2]!=="<"){l();let g=n+2,y=e[g]==="-";for(y&&(g+=1);e[g]===" "||e[g]===" ";)g+=1;let k="";for(;g<c&&!/[\s;&|<>()]/.test(e[g]);){if(e[g]==="'"||e[g]==='"'){let v=e[g],S=e.indexOf(v,g+1);if(S===-1)return null;k+=e.slice(g+1,S),g=S+1;continue}if(e[g]==="\\"){k+=e[g+1]??"",g+=2;continue}k+=e[g],g+=1}if(k==="")return null;r.push({delim:k,strip:y}),t.push({t:"word",v:`<<${k}`,line:s,heredoc:!0}),n=g;continue}d(h),n+=1}return l(),r.length>0?null:t}function Jl(e,t,r){let n=0;for(let s=t;s<r;s+=1)e[s]===`
|
|
13
|
+
`&&(n+=1);return n}function Xl(e){let t=ug(e);if(!t)return"(unparsable)";let r=e.split(`
|
|
14
14
|
`),n=m=>(r[m-1]??"").trim(),s=[],o=!0,i="start",a=!1,c=0,l=!1,d=!1,p=()=>s.every(m=>m.kind==="group"&&m.uncond),f=()=>["start",";","nl","&"].includes(i);for(let m=0;m<t.length;m+=1){let h=t[m],g=s[s.length-1];if(h.t==="op"){let v=h.v;if(v==="("){if(g?.kind==="case")continue;if(!o&&t[m+1]?.t==="op"&&t[m+1].v===")"){m+=1,a=!0,o=!0;continue}s.push({kind:"sub",close:")",uncond:f()}),o=!0,i="kw";continue}if(v===")"){if(g?.kind==="case"){l=!1,o=!0,i="kw";continue}if(!g||g.kind!=="sub")return"(unparsable)";s.pop(),o=!1;continue}if(v===";;"){if(g?.kind!=="case")return"(unparsable)";l=!0,o=!0,i=";";continue}if(o=!0,i=v===`
|
|
15
15
|
`?i==="&&"||i==="||"||i==="|"?i:"nl":v,g?.kind==="case"&&l&&v===`
|
|
16
|
-
`)continue;continue}let y=h.quoted?null:h.v;if(d){y==="in"&&(d=!1,l=!0,o=!0,i="kw");continue}if(g?.kind==="case"&&l){if(y==="esac"){s.pop(),o=!1,l=!1;continue}continue}if(c===1){c=0,a=!0,o=!0;continue}if(!o){y==="{"&&a&&(s.push({kind:"func",close:"}",uncond:!1}),a=!1,o=!0,i="kw");continue}if(y==="{"){s.push({kind:a?"func":"group",close:"}",uncond:!a&&f()&&p()}),a=!1,o=!0,i="start";continue}if(a=!1,y==="}"){if(!g||g.kind!=="group"&&g.kind!=="func")return"(unparsable)";s.pop(),o=!1;continue}if(y!==null&&
|
|
17
|
-
`),n=setInterval(o,80),o()},update(i){s=i},stop(){n&&(clearInterval(n),n=null,process.stdout.write("\r"+" ".repeat(s.length+4)+"\r"))},succeed(i){this.stop(),console.log(`${pe.green("\u2713")} ${i||s}`)},fail(i){this.stop(),console.log(`${pe.red("\u2717")} ${i||s}`)}}}var u,Te=Z(()=>{u={success:ng,error:sg,warn:aa,info:og,dim:ig,formatPath:ag,formatName:cg,header:lg,listItem:ug,vesperTip:dg,createSpinner:pg}});import{fileURLToPath as fg}from"node:url";import{dirname as ca,join as Rn,resolve as hg}from"node:path";import{readdir as mg}from"node:fs/promises";import{existsSync as gg,readFileSync as yg}from"node:fs";function kg(e){let t=e;for(;t!==ca(t);){if(gg(Rn(t,"package.json")))return t;t=ca(t)}return hg(e,"..","..","..")}function Qs(){try{return JSON.parse(yg(Rn(Nn,"package.json"),"utf-8")).version??null}catch{return null}}function la(e){if(!e||typeof e!="string")throw new Error("Asset name is required");if(e.includes("..")||e.includes("/")||e.includes("\\"))throw new Error(`Invalid asset name: ${e}`)}async function Zs(e){let t=qe[e];if(!t)throw new Error(`Unknown asset type: ${e}`);try{let r=await mg(Rn(Ot,t.dir),{withFileTypes:!0});if(e==="skills")return r.filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>s.name).sort();let n=/\.(agent|prompt|instructions)\.md$|\.md$/;return r.filter(s=>s.isFile()&&s.name.endsWith(".md")).map(s=>s.name.replace(n,"")).sort()}catch{return[]}}var wg,vg,Nn,O,Ot,qe,Ee=Z(()=>{wg=fg(import.meta.url),vg=ca(wg);Nn=kg(vg),O=Rn(Nn,"assets");Ot=Rn(O,"copilot");qe={agents:{dir:"agents",extension:".agent.md",isFolder:!1},prompts:{dir:"prompts",extension:".prompt.md",isFolder:!1},instructions:{dir:"instructions",extension:".instructions.md",isFolder:!1},skills:{dir:"skills",extension:"",isFolder:!0}}});var ua={};jn(ua,{DEFAULT_GIT_TIMEOUT_MS:()=>Sg,default:()=>Eg,runGit:()=>D,runGitCapture:()=>Tt});async function D(e,{cwd:t,timeout:r=3e4,env:n,detached:s=!1}={}){if(s){let c=await Tt(e,{cwd:t,timeout:r,env:n,detached:!0});return c.ok?c.stdout.trim():null}let{execFile:o}=await import("node:child_process"),{promisify:i}=await import("node:util"),a=i(o);try{let{stdout:c}=await a("git",e,{cwd:t,timeout:r,maxBuffer:16777216,...n?{env:n}:{}});return c.trim()}catch{return null}}async function Tt(e,{cwd:t,timeout:r=3e4,env:n,detached:s=!1}={}){let{spawn:o}=await import("node:child_process"),i=s&&process.platform!=="win32";return new Promise(a=>{let c;try{c=o("git",e,{cwd:t,env:n??process.env,detached:i,stdio:["ignore","pipe","pipe"]})}catch(g){a({ok:!1,stdout:"",stderr:String(g?.message??g),timedOut:!1});return}let l="",d="",p=!1,f=!1;c.stdout.on("data",g=>{l+=g}),c.stderr.on("data",g=>{d+=g});let m=r?setTimeout(()=>{p=!0;try{i?process.kill(-c.pid,"SIGKILL"):c.kill("SIGKILL")}catch{}},r):null,h=g=>{if(!f){if(f=!0,m&&clearTimeout(m),i)try{process.kill(-c.pid,"SIGKILL")}catch{}a({ok:g,stdout:l,stderr:d,timedOut:p})}};c.on("error",g=>{d+=String(g?.message??g),h(!1)}),c.on("close",g=>h(g===0&&!p))})}var Sg,Eg,ot=Z(()=>{Sg=3e4;Eg=D});import{access as bg,constants as xg,readFile as Zl,readdir as Ag}from"node:fs/promises";import{execFile as _g}from"node:child_process";import{join as da}from"node:path";import Cg from"strip-json-comments";async function eu(e){try{return await bg(e,xg.F_OK),!0}catch{return!1}}function tu(e,t){let r=e?.visible;if(r===null||r instanceof Set)return r;throw new TypeError(`${t}: \`visible\` is required \u2014 a Set of git-visible paths, or null for no repository`)}async function pa(e,t){let r=tu(t,"findCodeWorkspaceFile");try{let s=(await Ag(e,{withFileTypes:!0})).find(o=>o.isFile()&&o.name.endsWith(".code-workspace")&&(!r||r.has(o.name)));return s?da(e,s.name):null}catch{return null}}function kr(e){let t=typeof e=="string"?$g.exec(e):null;return t?t[1]:null}function Pe(e){return`.vesper/instructions/${e}.instructions.md`}function vr({path:e,parse:t,test:r,describe:n,vscodeSettings:s=!1}){if(typeof e!="string"||!e)throw new Error("keyFingerprintEntry: `path` must be a non-empty string");if(!Object.hasOwn(su,t))throw new Error(`keyFingerprintEntry: \`parse\` for "${e}" must be 'json', 'jsonc' or 'text'`);if(typeof r!="function")throw new Error(`keyFingerprintEntry: \`test\` for "${e}" must be a function`);if(typeof n!="string"||!n)throw new Error(`keyFingerprintEntry: \`describe\` for "${e}" must be a non-empty string`);if(s&&t!=="jsonc")throw new Error(`keyFingerprintEntry: a \`vscodeSettings\` entry ("${e}") must parse as 'jsonc'`);let o={path:e,parse:t,test:r,describe:n,...s?{vscodeSettings:!0}:{}};return Object.defineProperty(o,fa,{value:!0,enumerable:!1}),Object.freeze(o)}function zr(e){return!!e&&typeof e=="object"&&e[fa]===!0&&typeof e.test=="function"}function ou(e){if(typeof e!="string"&&!(e&&typeof e=="object"&&e[fa]===!0))throw new TypeError(`fingerprint entry must be a bare path string or an object built by fingerprintEntry() \u2014 received ${e===null?"null":typeof e}. Never hand-roll join(root, entry) or String(entry) over a fingerprint set; route through fingerprintPath/fingerprintMatchesEntry.`)}function ht(e){return ou(e),typeof e=="string"?e:e.path}async function qt(e,t,r){let n=tu(r,"fingerprintMatchesEntry"),s=ht(t),o=da(e,s);if(typeof t=="string")return(!n||n.has(s))&&eu(o);let i=zr(t)&&t.vscodeSettings?await pa(e,{visible:n}):null;if(i)o=i;else if(n&&!n.has(s))return!1;let a;try{a=await Zl(o,"utf-8")}catch{return!1}return ha(t,a,{fromWorkspaceFile:!!i})}function ha(e,t,{fromWorkspaceFile:r=!1}={}){if(zr(e)){let n;try{n=su[e.parse](t),r&&(n=n?.settings||{})}catch{return!1}try{return e.test(n)===!0}catch{return!1}}return e.anyOf.some(n=>t.includes(n))}function ma(e,t){return new Promise(r=>{_g("git",t,{cwd:e,maxBuffer:16777216,timeout:5e3,env:Pg(process.env)},(s,o)=>{r(s?null:String(o))}).stdin?.end()})}function Pg(e){let t={...e,...Og};return!t.GIT_SSH_COMMAND&&!t.GIT_SSH&&(t.GIT_SSH_COMMAND=Tg),t}async function Ig(e,t){return ma(e,["show",`HEAD:./${t}`])}async function jg(e){let t=await ma(e,["ls-tree","-z","HEAD"]);if(!t)return null;for(let r of t.split("\0")){let n=r.indexOf(" ");if(n===-1)continue;let[,s]=r.slice(0,n).split(" "),o=r.slice(n+1);if(s==="blob"&&!o.includes("/")&&o.endsWith(".code-workspace"))return o}return null}async function Rg(e,t){let r=ht(t);if(typeof t=="string"){let a=await ma(e,["cat-file","-e",`HEAD:./${r}`])!==null;return{matched:a,path:a?r:null}}let n=zr(t)&&t.vscodeSettings?await jg(e):null,s=n||r,o=await Ig(e,s);if(o===null)return{matched:!1,path:null};let i=ha(t,o,{fromWorkspaceFile:!!n});return{matched:i,path:i?s:null}}async function ga(e,t,r){let n=da(e,r);if(typeof t=="string")return eu(n);ht(t);let s;try{s=await Zl(n,"utf-8")}catch{return!1}let o=zr(t)&&!!t.vscodeSettings&&r.endsWith(".code-workspace");return ha(t,s,{fromWorkspaceFile:o})}async function iu(e,{fingerprints:t=Zt()}={}){let r={};for(let s of Object.keys(t)){let o=[];for(let i of t[s]||[]){let a=await Rg(e,i);a.matched&&o.push({entry:i,path:a.path})}o.length&&(r[s]=o)}let n=Object.keys(r);return n.length===0?{host:null,matched:[]}:n.length>1?{host:"both",matched:[]}:{host:n[0],matched:r[n[0]]}}function ya(e){return ou(e),typeof e!="string"?!0:e.toLowerCase().includes("vesper")}function Ng(e){if(!e||typeof e!="object")return!1;for(let r of["extraKnownMarketplaces","enabledPlugins"])if(e[r]&&typeof e[r]!="object")return!1;return!!e.enabledPlugins&&mt in e.enabledPlugins||e.agent===L}function au(e){return!e||typeof e!="object"||Array.isArray(e)?!1:e.default_agent===L}function Lg(e){return!e||typeof e!="object"?!1:nu.some(t=>{let r=e[t];return!!r&&Object.keys(r).includes(ru)})}function Mg(e){return Array.isArray(e?.tasks)&&e.tasks.some(t=>t?.label===to&&typeof t.command=="string"&&Fg.test(t.command))}function Gg(e){let t=new Set([Ln,Mn,Fn]),r=e?.hooks?.SessionStart;return Array.isArray(r)?r.some(n=>Array.isArray(n?.hooks)&&n.hooks.some(s=>typeof s?.command=="string"&&t.has(s.command.trim()))):!1}function Dg(e){if(typeof e!="string")return!1;let t=/<!-- vesper:start -->([\s\S]*?)<!-- vesper:end -->/.exec(e);return!!t&&/^@\.claude\/vesper\/[a-z-]+\.md\s*$/m.test(t[1])}function wa(e){let t=ro.exec(String(e).replace(/\\/g,"/"));if(!t)return!1;let r=t[1].replace(/\/+$/,"");return Vg.some(n=>n.endsWith("/")?r.startsWith(n):r===n||r.startsWith(`${n}/`))}function cu(e){return!e||typeof e!="object"?!1:nu.some(t=>{let r=e[t];return!!r&&typeof r=="object"&&Object.keys(r).some(wa)})}function Zt(){return{...lu,...uu}}function Hg(){return{...du,...pu}}async function Gn(e,t){let r=[];for(let n of Hg()[t]||[])await hu(e,n)&&r.push(ht(n));return r.sort()}async function no(e,t){return(await Gn(e,t)).length>0}async function fu(e,{vscodeSettings:t}={}){let r={claude:!1,copilot:!1},n=[];for(let o of["claude","copilot"])for(let i of Ql.primaryByHost[o])await qt(e,i,{visible:null})&&(r[o]=!0,n.push(ht(i)));!r.copilot&&t&&cu(t)&&(r.copilot=!0,n.push("<workspace settings>"));let s=[];for(let o of Ql.residue)await qt(e,o,{visible:null})&&s.push(ht(o));return{primary:r.claude||r.copilot,residue:s,hosts:r,matched:[...new Set(n)].sort()}}async function Sr(e,t,{fingerprints:r=Zt()}={}){for(let n of r[t]||[])if(await hu(e,n))return!0;return!1}async function hu(e,t){return qt(e,t,{visible:null})}var L,mt,$g,Pt,Xt,eo,to,It,Jt,Kr,Br,ru,nu,Qt,Ln,Mn,Fn,fa,su,Og,Tg,Fg,ro,Vg,lu,uu,du,pu,Jl,ql,Xl,Ql,fe=Z(()=>{L="vesper-orchestrator",mt="vesper@vesper-marketplace",$g=/^vesper-([a-z0-9][a-z0-9-]*)@vesper-marketplace$/;Pt=`.vesper/agents/${L}.agent.md`;Xt=".vscode/settings.json",eo=".vscode/tasks.json",to="Vesper: worktree bootstrap",It=".claude/settings.json",Jt="opencode.json",Kr=`.opencode/agents/${L}.md`,Br=".opencode/plugins/vesper.js",ru="${workspaceFolder}/.vesper/agents",nu=Object.freeze(["chat.agentFilesLocations","chat.instructionsFilesLocations","chat.promptFilesLocations","chat.agentSkillsLocations"]),Qt=Object.freeze(["reinit","compact-knowledge","revalidate-knowledge","revalidate-team"]),Ln=`node -e "['orchestrator','orchestration','context'].forEach(n=>{try{process.stdout.write(require('fs').readFileSync('.claude/vesper/'+n+'.md','utf8')+'\\n\\n')}catch(e){}})"`,Mn=`node -e "const fs=require('fs');['orchestrator','orchestration','context'].forEach(n=>{try{process.stdout.write(fs.readFileSync('.claude/vesper/'+n+'.md','utf8')+'\\n\\n')}catch(e){}});try{fs.readdirSync('.claude/rules').filter(f=>f.endsWith('.md')).sort().forEach(f=>{try{process.stdout.write(fs.readFileSync('.claude/rules/'+f,'utf8')+'\\n\\n')}catch(e){}})}catch(e){}"`,Fn="command -v vespercli >/dev/null 2>&1 && vespercli worktree bootstrap --quiet || true",fa=Symbol.for("vesper.fingerprintEntry"),su=Object.freeze({json:e=>JSON.parse(e),jsonc:e=>JSON.parse(Cg(e,{trailingCommas:!0})),text:e=>e});Og=Object.freeze({GIT_NO_LAZY_FETCH:"1",GIT_OPTIONAL_LOCKS:"0",GIT_TERMINAL_PROMPT:"0",GCM_INTERACTIVE:"never",SSH_ASKPASS_REQUIRE:"never",LC_ALL:"C"}),Tg="ssh -o BatchMode=yes -o ConnectTimeout=10";Fg=/(^|[\s;&|(])vespercli\s+guard\s+--running-host(\s+|=)copilot(?![\w-])/;ro=/node_modules\/(?:@[^/]+\/)?(?:vesper-cli|vespercli)\/(.+)$/,Vg=Object.freeze(["assets/core/","assets/skills","assets/agents/","assets/prompts/","assets/instructions/"]);lu=Object.freeze({claude:Object.freeze([vr({path:It,parse:"json",test:Ng,describe:`"enabledPlugins[${mt}]" or "agent": "${L}"`}),vr({path:Jt,parse:"json",test:au,describe:`"default_agent": "${L}" in ${Jt}`})])}),uu=Object.freeze({copilot:Object.freeze([vr({path:eo,parse:"jsonc",test:Mg,describe:`task "${to}"`}),vr({path:Xt,parse:"jsonc",test:Lg,describe:`"${ru}" in a chat.*FilesLocations setting (of the root *.code-workspace file when one exists)`,vscodeSettings:!0})])});du=Object.freeze({claude:Object.freeze([".claude/rules/vesper-orchestrator.md",`.claude/agents/${L}.md`,...Qt.map(e=>`.claude/skills/${e}/SKILL.md`),Kr,Br])}),pu=Object.freeze({copilot:Object.freeze([Pt,Pe(L)])});Jl=vr({path:It,parse:"json",test:Gg,describe:"an exact 1.x SessionStart command"}),ql=vr({path:"CLAUDE.md",parse:"text",test:Dg,describe:"the 1.x guard block importing .claude/vesper/*.md"}),Xl=vr({path:Xt,parse:"jsonc",test:cu,describe:"a 1.x package location (assets/core, assets/skills, assets/<type>/<name>)"}),Ql=Object.freeze({primary:Object.freeze([Jl,ql,Xl]),primaryByHost:Object.freeze({claude:Object.freeze([Jl,ql]),copilot:Object.freeze([Xl])}),residue:Object.freeze([".claude/vesper/orchestrator.md"])})});var Ea={};jn(Ea,{AUTH_FAILURE_RE:()=>ka,BATCH_SSH:()=>gu,CONFIG_VARS_KEPT:()=>mu,NON_INTERACTIVE:()=>Dn,NO_PROMPT_PROGRAM:()=>va,READ_ONLY_GIT_ENV:()=>jt,REPO_LOCATION_VARS:()=>oo,authFailureLine:()=>Sa,nonInteractiveGitEnv:()=>Vn,repoLocationVars:()=>io,stripRepoLocationEnv:()=>Er});import{execFileSync as Ug}from"node:child_process";function io(){if(so)return so;let e=[];try{let r={...process.env,LC_ALL:"C"};for(let n of oo)delete r[n];e=Ug("git",["rev-parse","--local-env-vars"],{encoding:"utf-8",timeout:5e3,env:r,stdio:["ignore","pipe","ignore"]}).split(`
|
|
18
|
-
`).map(n=>n.trim()).filter(n=>/^GIT_[A-Z0-9_]+$/.test(n))}catch{e=[]}let t=e.filter(r=>!
|
|
19
|
-
`),n=new RegExp(`${
|
|
16
|
+
`)continue;continue}let y=h.quoted?null:h.v;if(d){y==="in"&&(d=!1,l=!0,o=!0,i="kw");continue}if(g?.kind==="case"&&l){if(y==="esac"){s.pop(),o=!1,l=!1;continue}continue}if(c===1){c=0,a=!0,o=!0;continue}if(!o){y==="{"&&a&&(s.push({kind:"func",close:"}",uncond:!1}),a=!1,o=!0,i="kw");continue}if(y==="{"){s.push({kind:a?"func":"group",close:"}",uncond:!a&&f()&&p()}),a=!1,o=!0,i="start";continue}if(a=!1,y==="}"){if(!g||g.kind!=="group"&&g.kind!=="func")return"(unparsable)";s.pop(),o=!1;continue}if(y!==null&&Yl.has(y)){s.push({kind:y==="if"?"if":y==="case"?"case":"loop",close:Yl.get(y)}),y==="case"?(d=!0,o=!1):(o=y==="if"||y==="while"||y==="until",i="kw");continue}if(y!==null&&cg.has(y)){if(!g||g.close!==y)return"(unparsable)";s.pop(),o=!1;continue}if(y!==null&&lg.has(y)){i="kw";continue}if(y==="function"){c=1,o=!1;continue}if(y!==null&&/^[A-Za-z_][A-Za-z0-9_]*=/.test(y))continue;let k=h.v;if(!h.quoted&&p()&&f()){if(k==="exit")return n(h.line);if(k==="exec"){let v=!0,S=!1;for(let C=m+1;C<t.length;C+=1){let N=t[C];if(N.t==="op")break;if(S){S=!1;continue}if(!N.heredoc){if(!N.quoted&&ig.test(N.v)){ag.test(N.v)&&(S=!0);continue}v=!1;break}}if(!v)return n(h.line)}}o=!1}return s.length>0||d||a||c?"(unparsable)":null}var it,qt,og,ig,ag,Yl,cg,lg,Kr=Z(()=>{it="# <!-- vesper:hook:start -->",qt="# <!-- vesper:hook:end -->",og=/^(sh|bash|dash|zsh|ksh|mksh|ash)(\d[\d.]*)?$/,ig=/^[0-9]*(>>|<>|<&|>&|>\||&>>|&>|<|>)/,ag=/^[0-9]*(>>|<>|<&|>&|>\||&>>|&>|<|>)$/;Yl=new Map([["if","fi"],["case","esac"],["for","done"],["while","done"],["until","done"],["select","done"]]),cg=new Set(["fi","esac","done"]),lg=new Set(["then","do","else","elif","!","time"])});import pe from"picocolors";function dg(e){console.log(`${pe.green("\u2713")} ${e}`)}function pg(e){console.log(`${pe.red("\u2717")} ${e}`)}function ua(e){console.log(`${pe.yellow("!")} ${e}`)}function fg(e){console.log(`${pe.cyan("\u2192")} ${e}`)}function hg(e){console.log(pe.dim(e))}function mg(e){return pe.cyan(e)}function gg(e){return pe.bold(e)}function yg(e){console.log(),console.log(pe.bold(pe.underline(e)))}function wg(e,t=!1){let r=t?pe.green("\u25CF"):pe.dim("\u25CB");console.log(` ${r} ${e}`)}function vg(){console.log(),console.log(pe.bold(pe.magenta("\u{1F3AF} Ready to use Vesper!"))),console.log(pe.cyan(' In VS Code Chat, select "Vesper" from the agent dropdown')),console.log(pe.cyan(" and start requesting!")),console.log()}function kg(e){let t=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],r=0,n=null,s=e,o=()=>{let i=pe.cyan(t[r]);process.stdout.write(`\r${i} ${s}`),r=(r+1)%t.length};return{start(){process.stdout.write(`
|
|
17
|
+
`),n=setInterval(o,80),o()},update(i){s=i},stop(){n&&(clearInterval(n),n=null,process.stdout.write("\r"+" ".repeat(s.length+4)+"\r"))},succeed(i){this.stop(),console.log(`${pe.green("\u2713")} ${i||s}`)},fail(i){this.stop(),console.log(`${pe.red("\u2717")} ${i||s}`)}}}var u,Ie=Z(()=>{u={success:dg,error:pg,warn:ua,info:fg,dim:hg,formatPath:mg,formatName:gg,header:yg,listItem:wg,vesperTip:vg,createSpinner:kg}});import{fileURLToPath as Sg}from"node:url";import{dirname as da,join as Ln,resolve as Eg}from"node:path";import{readdir as bg}from"node:fs/promises";import{existsSync as xg,readFileSync as Ag}from"node:fs";function $g(e){let t=e;for(;t!==da(t);){if(xg(Ln(t,"package.json")))return t;t=da(t)}return Eg(e,"..","..","..")}function to(){try{return JSON.parse(Ag(Ln(Mn,"package.json"),"utf-8")).version??null}catch{return null}}function pa(e){if(!e||typeof e!="string")throw new Error("Asset name is required");if(e.includes("..")||e.includes("/")||e.includes("\\"))throw new Error(`Invalid asset name: ${e}`)}async function ro(e){let t=Xe[e];if(!t)throw new Error(`Unknown asset type: ${e}`);try{let r=await bg(Ln(Tt,t.dir),{withFileTypes:!0});if(e==="skills")return r.filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>s.name).sort();let n=/\.(agent|prompt|instructions)\.md$|\.md$/;return r.filter(s=>s.isFile()&&s.name.endsWith(".md")).map(s=>s.name.replace(n,"")).sort()}catch{return[]}}var _g,Cg,Mn,O,Tt,Xe,xe=Z(()=>{_g=Sg(import.meta.url),Cg=da(_g);Mn=$g(Cg),O=Ln(Mn,"assets");Tt=Ln(O,"copilot");Xe={agents:{dir:"agents",extension:".agent.md",isFolder:!1},prompts:{dir:"prompts",extension:".prompt.md",isFolder:!1},instructions:{dir:"instructions",extension:".instructions.md",isFolder:!1},skills:{dir:"skills",extension:"",isFolder:!0}}});var fa={};Nn(fa,{DEFAULT_GIT_TIMEOUT_MS:()=>Og,default:()=>Tg,runGit:()=>D,runGitCapture:()=>Pt});async function D(e,{cwd:t,timeout:r=3e4,env:n,detached:s=!1}={}){if(s){let c=await Pt(e,{cwd:t,timeout:r,env:n,detached:!0});return c.ok?c.stdout.trim():null}let{execFile:o}=await import("node:child_process"),{promisify:i}=await import("node:util"),a=i(o);try{let{stdout:c}=await a("git",e,{cwd:t,timeout:r,maxBuffer:16777216,...n?{env:n}:{}});return c.trim()}catch{return null}}async function Pt(e,{cwd:t,timeout:r=3e4,env:n,detached:s=!1}={}){let{spawn:o}=await import("node:child_process"),i=s&&process.platform!=="win32";return new Promise(a=>{let c;try{c=o("git",e,{cwd:t,env:n??process.env,detached:i,stdio:["ignore","pipe","pipe"]})}catch(g){a({ok:!1,stdout:"",stderr:String(g?.message??g),timedOut:!1});return}let l="",d="",p=!1,f=!1;c.stdout.on("data",g=>{l+=g}),c.stderr.on("data",g=>{d+=g});let m=r?setTimeout(()=>{p=!0;try{i?process.kill(-c.pid,"SIGKILL"):c.kill("SIGKILL")}catch{}},r):null,h=g=>{if(!f){if(f=!0,m&&clearTimeout(m),i)try{process.kill(-c.pid,"SIGKILL")}catch{}a({ok:g,stdout:l,stderr:d,timedOut:p})}};c.on("error",g=>{d+=String(g?.message??g),h(!1)}),c.on("close",g=>h(g===0&&!p))})}var Og,Tg,at=Z(()=>{Og=3e4;Tg=D});import{access as Pg,constants as Ig,readFile as nu,readdir as jg}from"node:fs/promises";import{execFile as Rg}from"node:child_process";import{join as ha}from"node:path";import Ng from"strip-json-comments";async function su(e){try{return await Pg(e,Ig.F_OK),!0}catch{return!1}}function ou(e,t){let r=e?.visible;if(r===null||r instanceof Set)return r;throw new TypeError(`${t}: \`visible\` is required \u2014 a Set of git-visible paths, or null for no repository`)}async function ma(e,t){let r=ou(t,"findCodeWorkspaceFile");try{let s=(await jg(e,{withFileTypes:!0})).find(o=>o.isFile()&&o.name.endsWith(".code-workspace")&&(!r||r.has(o.name)));return s?ha(e,s.name):null}catch{return null}}function Er(e){let t=typeof e=="string"?Lg.exec(e):null;return t?t[1]:null}function je(e){return`.vesper/instructions/${e}.instructions.md`}function Sr({path:e,parse:t,test:r,describe:n,vscodeSettings:s=!1}){if(typeof e!="string"||!e)throw new Error("keyFingerprintEntry: `path` must be a non-empty string");if(!Object.hasOwn(cu,t))throw new Error(`keyFingerprintEntry: \`parse\` for "${e}" must be 'json', 'jsonc' or 'text'`);if(typeof r!="function")throw new Error(`keyFingerprintEntry: \`test\` for "${e}" must be a function`);if(typeof n!="string"||!n)throw new Error(`keyFingerprintEntry: \`describe\` for "${e}" must be a non-empty string`);if(s&&t!=="jsonc")throw new Error(`keyFingerprintEntry: a \`vscodeSettings\` entry ("${e}") must parse as 'jsonc'`);let o={path:e,parse:t,test:r,describe:n,...s?{vscodeSettings:!0}:{}};return Object.defineProperty(o,ga,{value:!0,enumerable:!1}),Object.freeze(o)}function Yr(e){return!!e&&typeof e=="object"&&e[ga]===!0&&typeof e.test=="function"}function lu(e){if(typeof e!="string"&&!(e&&typeof e=="object"&&e[ga]===!0))throw new TypeError(`fingerprint entry must be a bare path string or an object built by fingerprintEntry() \u2014 received ${e===null?"null":typeof e}. Never hand-roll join(root, entry) or String(entry) over a fingerprint set; route through fingerprintPath/fingerprintMatchesEntry.`)}function yt(e){return lu(e),typeof e=="string"?e:e.path}async function Qt(e,t,r){let n=ou(r,"fingerprintMatchesEntry"),s=yt(t),o=ha(e,s);if(typeof t=="string")return(!n||n.has(s))&&su(o);let i=Yr(t)&&t.vscodeSettings?await ma(e,{visible:n}):null;if(i)o=i;else if(n&&!n.has(s))return!1;let a;try{a=await nu(o,"utf-8")}catch{return!1}return ya(t,a,{fromWorkspaceFile:!!i})}function ya(e,t,{fromWorkspaceFile:r=!1}={}){if(Yr(e)){let n;try{n=cu[e.parse](t),r&&(n=n?.settings||{})}catch{return!1}try{return e.test(n)===!0}catch{return!1}}return e.anyOf.some(n=>t.includes(n))}function wa(e,t){return new Promise(r=>{Rg("git",t,{cwd:e,maxBuffer:16777216,timeout:5e3,env:Fg(process.env)},(s,o)=>{r(s?null:String(o))}).stdin?.end()})}function Fg(e){let t={...e,...Mg};return!t.GIT_SSH_COMMAND&&!t.GIT_SSH&&(t.GIT_SSH_COMMAND=Gg),t}async function Dg(e,t){return wa(e,["show",`HEAD:./${t}`])}async function Vg(e){let t=await wa(e,["ls-tree","-z","HEAD"]);if(!t)return null;for(let r of t.split("\0")){let n=r.indexOf(" ");if(n===-1)continue;let[,s]=r.slice(0,n).split(" "),o=r.slice(n+1);if(s==="blob"&&!o.includes("/")&&o.endsWith(".code-workspace"))return o}return null}async function Hg(e,t){let r=yt(t);if(typeof t=="string"){let a=await wa(e,["cat-file","-e",`HEAD:./${r}`])!==null;return{matched:a,path:a?r:null}}let n=Yr(t)&&t.vscodeSettings?await Vg(e):null,s=n||r,o=await Dg(e,s);if(o===null)return{matched:!1,path:null};let i=ya(t,o,{fromWorkspaceFile:!!n});return{matched:i,path:i?s:null}}async function va(e,t,r){let n=ha(e,r);if(typeof t=="string")return su(n);yt(t);let s;try{s=await nu(n,"utf-8")}catch{return!1}let o=Yr(t)&&!!t.vscodeSettings&&r.endsWith(".code-workspace");return ya(t,s,{fromWorkspaceFile:o})}async function uu(e,{fingerprints:t=tr()}={}){let r={};for(let s of Object.keys(t)){let o=[];for(let i of t[s]||[]){let a=await Hg(e,i);a.matched&&o.push({entry:i,path:a.path})}o.length&&(r[s]=o)}let n=Object.keys(r);return n.length===0?{host:null,matched:[]}:n.length>1?{host:"both",matched:[]}:{host:n[0],matched:r[n[0]]}}function ka(e){return lu(e),typeof e!="string"?!0:e.toLowerCase().includes("vesper")}function Ug(e){if(!e||typeof e!="object")return!1;for(let r of["extraKnownMarketplaces","enabledPlugins"])if(e[r]&&typeof e[r]!="object")return!1;return!!e.enabledPlugins&&wt in e.enabledPlugins||e.agent===L}function du(e){return!e||typeof e!="object"||Array.isArray(e)?!1:e.default_agent===L}function Wg(e){return!e||typeof e!="object"?!1:au.some(t=>{let r=e[t];return!!r&&Object.keys(r).includes(iu)})}function Kg(e){return Array.isArray(e?.tasks)&&e.tasks.some(t=>t?.label===so&&typeof t.command=="string"&&Bg.test(t.command))}function zg(e){let t=new Set([Gn,Fn,Dn]),r=e?.hooks?.SessionStart;return Array.isArray(r)?r.some(n=>Array.isArray(n?.hooks)&&n.hooks.some(s=>typeof s?.command=="string"&&t.has(s.command.trim()))):!1}function Yg(e){if(typeof e!="string")return!1;let t=/<!-- vesper:start -->([\s\S]*?)<!-- vesper:end -->/.exec(e);return!!t&&/^@\.claude\/vesper\/[a-z-]+\.md\s*$/m.test(t[1])}function Sa(e){let t=oo.exec(String(e).replace(/\\/g,"/"));if(!t)return!1;let r=t[1].replace(/\/+$/,"");return Jg.some(n=>n.endsWith("/")?r.startsWith(n):r===n||r.startsWith(`${n}/`))}function pu(e){return!e||typeof e!="object"?!1:au.some(t=>{let r=e[t];return!!r&&typeof r=="object"&&Object.keys(r).some(Sa)})}function tr(){return{...fu,...hu}}function qg(){return{...mu,...gu}}async function Vn(e,t){let r=[];for(let n of qg()[t]||[])await wu(e,n)&&r.push(yt(n));return r.sort()}async function io(e,t){return(await Vn(e,t)).length>0}async function yu(e,{vscodeSettings:t}={}){let r={claude:!1,copilot:!1},n=[];for(let o of["claude","copilot"])for(let i of ru.primaryByHost[o])await Qt(e,i,{visible:null})&&(r[o]=!0,n.push(yt(i)));!r.copilot&&t&&pu(t)&&(r.copilot=!0,n.push("<workspace settings>"));let s=[];for(let o of ru.residue)await Qt(e,o,{visible:null})&&s.push(yt(o));return{primary:r.claude||r.copilot,residue:s,hosts:r,matched:[...new Set(n)].sort()}}async function br(e,t,{fingerprints:r=tr()}={}){for(let n of r[t]||[])if(await wu(e,n))return!0;return!1}async function wu(e,t){return Qt(e,t,{visible:null})}var L,wt,Lg,It,Zt,no,so,jt,Xt,Br,zr,iu,au,er,Gn,Fn,Dn,ga,cu,Mg,Gg,Bg,oo,Jg,fu,hu,mu,gu,Zl,eu,tu,ru,fe=Z(()=>{L="vesper-orchestrator",wt="vesper@vesper-marketplace",Lg=/^vesper-([a-z0-9][a-z0-9-]*)@vesper-marketplace$/;It=`.vesper/agents/${L}.agent.md`;Zt=".vscode/settings.json",no=".vscode/tasks.json",so="Vesper: worktree bootstrap",jt=".claude/settings.json",Xt="opencode.json",Br=`.opencode/agents/${L}.md`,zr=".opencode/plugins/vesper.js",iu="${workspaceFolder}/.vesper/agents",au=Object.freeze(["chat.agentFilesLocations","chat.instructionsFilesLocations","chat.promptFilesLocations","chat.agentSkillsLocations"]),er=Object.freeze(["reinit","compact-knowledge","revalidate-knowledge","revalidate-team"]),Gn=`node -e "['orchestrator','orchestration','context'].forEach(n=>{try{process.stdout.write(require('fs').readFileSync('.claude/vesper/'+n+'.md','utf8')+'\\n\\n')}catch(e){}})"`,Fn=`node -e "const fs=require('fs');['orchestrator','orchestration','context'].forEach(n=>{try{process.stdout.write(fs.readFileSync('.claude/vesper/'+n+'.md','utf8')+'\\n\\n')}catch(e){}});try{fs.readdirSync('.claude/rules').filter(f=>f.endsWith('.md')).sort().forEach(f=>{try{process.stdout.write(fs.readFileSync('.claude/rules/'+f,'utf8')+'\\n\\n')}catch(e){}})}catch(e){}"`,Dn="command -v vespercli >/dev/null 2>&1 && vespercli worktree bootstrap --quiet || true",ga=Symbol.for("vesper.fingerprintEntry"),cu=Object.freeze({json:e=>JSON.parse(e),jsonc:e=>JSON.parse(Ng(e,{trailingCommas:!0})),text:e=>e});Mg=Object.freeze({GIT_NO_LAZY_FETCH:"1",GIT_OPTIONAL_LOCKS:"0",GIT_TERMINAL_PROMPT:"0",GCM_INTERACTIVE:"never",SSH_ASKPASS_REQUIRE:"never",LC_ALL:"C"}),Gg="ssh -o BatchMode=yes -o ConnectTimeout=10";Bg=/(^|[\s;&|(])vespercli\s+guard\s+--running-host(\s+|=)copilot(?![\w-])/;oo=/node_modules\/(?:@[^/]+\/)?(?:vesper-cli|vespercli)\/(.+)$/,Jg=Object.freeze(["assets/core/","assets/skills","assets/agents/","assets/prompts/","assets/instructions/"]);fu=Object.freeze({claude:Object.freeze([Sr({path:jt,parse:"json",test:Ug,describe:`"enabledPlugins[${wt}]" or "agent": "${L}"`}),Sr({path:Xt,parse:"json",test:du,describe:`"default_agent": "${L}" in ${Xt}`})])}),hu=Object.freeze({copilot:Object.freeze([Sr({path:no,parse:"jsonc",test:Kg,describe:`task "${so}"`}),Sr({path:Zt,parse:"jsonc",test:Wg,describe:`"${iu}" in a chat.*FilesLocations setting (of the root *.code-workspace file when one exists)`,vscodeSettings:!0})])});mu=Object.freeze({claude:Object.freeze([".claude/rules/vesper-orchestrator.md",`.claude/agents/${L}.md`,...er.map(e=>`.claude/skills/${e}/SKILL.md`),Br,zr])}),gu=Object.freeze({copilot:Object.freeze([It,je(L)])});Zl=Sr({path:jt,parse:"json",test:zg,describe:"an exact 1.x SessionStart command"}),eu=Sr({path:"CLAUDE.md",parse:"text",test:Yg,describe:"the 1.x guard block importing .claude/vesper/*.md"}),tu=Sr({path:Zt,parse:"jsonc",test:pu,describe:"a 1.x package location (assets/core, assets/skills, assets/<type>/<name>)"}),ru=Object.freeze({primary:Object.freeze([Zl,eu,tu]),primaryByHost:Object.freeze({claude:Object.freeze([Zl,eu]),copilot:Object.freeze([tu])}),residue:Object.freeze([".claude/vesper/orchestrator.md"])})});var Aa={};Nn(Aa,{AUTH_FAILURE_RE:()=>ba,BATCH_SSH:()=>ku,CONFIG_VARS_KEPT:()=>vu,NON_INTERACTIVE:()=>Hn,NO_PROMPT_PROGRAM:()=>Ea,READ_ONLY_GIT_ENV:()=>Rt,REPO_LOCATION_VARS:()=>co,authFailureLine:()=>xa,nonInteractiveGitEnv:()=>Un,repoLocationVars:()=>lo,stripRepoLocationEnv:()=>xr});import{execFileSync as Xg}from"node:child_process";function lo(){if(ao)return ao;let e=[];try{let r={...process.env,LC_ALL:"C"};for(let n of co)delete r[n];e=Xg("git",["rev-parse","--local-env-vars"],{encoding:"utf-8",timeout:5e3,env:r,stdio:["ignore","pipe","ignore"]}).split(`
|
|
18
|
+
`).map(n=>n.trim()).filter(n=>/^GIT_[A-Z0-9_]+$/.test(n))}catch{e=[]}let t=e.filter(r=>!vu.includes(r)&&!Qg.includes(r)&&!co.includes(r));return ao=Object.freeze([...co,...t]),ao}function xr(e=process.env){let t={...e};for(let r of lo())delete t[r];return t}function Un(e=process.env,{sshCommandConfigured:t=!1}={}){let r={...e,...Hn};!r.GIT_SSH_COMMAND&&!r.GIT_SSH&&!t&&(r.GIT_SSH_COMMAND=ku),r.GIT_ASKPASS=Ea,r.SSH_ASKPASS=Ea;let n=Number.parseInt(r.GIT_CONFIG_COUNT??"0",10),s=Number.isFinite(n)&&n>=0?n:0;return r[`GIT_CONFIG_KEY_${s}`]="core.askPass",r[`GIT_CONFIG_VALUE_${s}`]="",r.GIT_CONFIG_COUNT=String(s+1),r}function xa(e){return`${e} skipped: authentication needs interaction, which background runs never do (most likely an SSH key passphrase or a credential prompt). Load the key into ssh-agent (\`ssh-add\`), or run \`vespercli init\` in a terminal to sync attended.`}var co,vu,Qg,ao,Hn,ku,Ea,Rt,ba,vt=Z(()=>{co=Object.freeze(["GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_OBJECT_DIRECTORY","GIT_DIR","GIT_WORK_TREE","GIT_IMPLICIT_WORK_TREE","GIT_GRAFT_FILE","GIT_INDEX_FILE","GIT_NO_REPLACE_OBJECTS","GIT_REPLACE_REF_BASE","GIT_PREFIX","GIT_SHALLOW_FILE","GIT_COMMON_DIR"]),vu=Object.freeze(["GIT_CONFIG","GIT_CONFIG_PARAMETERS","GIT_CONFIG_COUNT"]),Qg=Object.freeze(["GIT_INTERNAL_SUPER_PREFIX"]),ao=null;Hn=Object.freeze({GIT_TERMINAL_PROMPT:"0",GCM_INTERACTIVE:"never",SSH_ASKPASS_REQUIRE:"never",LC_ALL:"C"}),ku="ssh -o BatchMode=yes -o ConnectTimeout=10";Ea=process.platform==="win32"?"false":"/bin/false",Rt=Object.freeze({GIT_NO_LAZY_FETCH:"1",GIT_OPTIONAL_LOCKS:"0",...Hn}),ba=/Permission denied \(publickey|Host key verification failed|could not read (Username|Password)|terminal prompts disabled|Authentication failed|passphrase|sign_and_send_pubkey|BatchMode/i});var Da={};Nn(Da,{ADDITIONAL_READ_ACCESS_PATHS_SETTING:()=>oe,AGENT_MAX_REQUESTS_SETTING:()=>mo,CHAT_AGENT_ENABLED_SETTING:()=>wo,COPILOT_PACKS_DIR:()=>fo,CORE_INSTRUCTIONS_DIR:()=>zn,CUSTOM_AGENT_IN_SUBAGENT_SETTING:()=>yo,EXTENDED_INSTRUCTIONS_DIR:()=>po,GIT_PLUMBING_TIMEOUT_MS:()=>Ta,GUARD_TRIGGER_MARKERS:()=>Xn,INCLUDE_REFERENCED_INSTRUCTIONS_SETTING:()=>go,INIT_DEFAULTS:()=>Re,LOCAL_STATE:()=>Pa,MCP_AUTO_START_SETTING:()=>So,MCP_DISCOVERY_ENABLED_SETTING:()=>ko,MCP_SERVERS:()=>we,MCP_TOOLS_AUTO_APPROVAL:()=>$u,MCP_TOOLS_BY_AGENT:()=>xo,MCP_TOOLS_CORE:()=>Ne,NEVER_WRITE_USER_PATHS:()=>ja,OMIT_BASE_AGENT_INSTRUCTIONS_SETTING:()=>vo,PERMITTED_USER_PATHS:()=>Ra,SAFE_AUTO_APPROVAL_COMMANDS:()=>Bn,SIBLING_GIT_ARGS:()=>tn,TERMINAL_AUTO_APPROVAL_SETTING:()=>Nt,TERMINAL_ENABLE_AUTO_APPROVAL_SETTING:()=>ho,TOOLS_AUTO_APPROVE_SETTING:()=>qr,TOOLS_ELIGIBLE_FOR_AUTO_APPROVAL_SETTING:()=>V,VESPER_BOOTSTRAP_TASK_LABEL:()=>Eo,VESPER_GIT_PATHS:()=>sy,VESPER_LOCAL_PATHS:()=>Kn,VESPER_MANAGED_GIT_HOOKS:()=>lt,VESPER_MANAGED_MCP_SERVERS:()=>me,VESPER_MANAGED_SETTINGS:()=>Lt,VSCODE_SETTINGS_MAP:()=>We,WORKSPACE_TYPES:()=>he,addAgentToolsToAutoApproval:()=>Gu,addMcpServer:()=>ir,addReadAccessPath:()=>Io,addToSettings:()=>Zr,allPackAssetEntries:()=>ju,buildGuardCommand:()=>Xr,classifyForeignHook:()=>Wr,configureChatSettings:()=>Po,configureMcpServer:()=>_r,configureMcpToolsAutoApproval:()=>Fo,configureTerminalAutoApproval:()=>To,configureVesperMergeDriver:()=>os,default:()=>my,deriveHost:()=>Yn,ensureCopilotFolderOpenTask:()=>Zn,ensureCoreSettings:()=>No,ensureFolderOpenTask:()=>bo,ensureVesperGitattributes:()=>ss,ensureVesperGitignore:()=>Jn,findNestedVesperrc:()=>es,findTrackedLocalPaths:()=>qn,findWorkspaceFile:()=>Na,getAutoApprovalCommands:()=>Ru,getConfiguredMcpServers:()=>Do,getCoreAssetEntries:()=>$o,getExtendedInstructionEntry:()=>Co,getInstalledTargets:()=>ge,getMcpConfigPath:()=>Qe,getPackAssetEntries:()=>sr,getReadAccessPaths:()=>Ro,getSettingsPath:()=>Ou,getTrackedPaths:()=>xt,getTrackingPath:()=>Qr,getTrackingPathAsync:()=>bt,getVesperIndexingPath:()=>Be,getWorkspaceConfig:()=>q,getWorkspaceFolders:()=>La,gitHookResultLines:()=>rs,gitHooksEnsured:()=>Ga,gitHooksSkipMessage:()=>Mu,installVesperGitHook:()=>Lu,installVesperGitHooks:()=>ns,isHookTrackedByGit:()=>nr,isInsideRepository:()=>St,isMcpServerConfigured:()=>Go,isUserLevelViolation:()=>Ar,listCopilotPackNames:()=>Oo,listExtendedInstructions:()=>_o,listMcpServers:()=>Fu,listWorktrees:()=>Mo,migrateVesperrcToWorkspaceLevel:()=>Ao,parseJsonc:()=>Mt,parseWorktreeList:()=>Lo,pruneLegacySettingsEntries:()=>en,readMcpConfig:()=>Ze,readTracking:()=>x,readVSCodeSettings:()=>K,realOrNearestAncestor:()=>ct,removeFolderOpenTask:()=>Qn,removeFromSettings:()=>ts,removeHookRegion:()=>kr,removeLegacyTracking:()=>Pu,removeMcpServer:()=>nn,removePathsFromSettings:()=>Ma,removeReadAccessPath:()=>jo,repositoryRoots:()=>Nu,resetVesperConfig:()=>Tu,resolveGitHooksDir:()=>or,resolveHookWriteTarget:()=>rn,sweepResetLocalState:()=>Ia,writeHookAtomic:()=>kt,writeTracking:()=>T,writeVSCodeSettings:()=>ce});import{readFile as Ke,readdir as Zg,rename as ey}from"node:fs/promises";import{existsSync as Jr,readdirSync as ty}from"node:fs";import{join as M,dirname as Et}from"node:path";import*as ry from"node:path";import{homedir as Oa}from"node:os";import ny from"strip-json-comments";function rr(e){let t=Oa();return e.startsWith(t)?"~"+e.slice(t.length).replace(/\\/g,"/"):e.replace(/\\/g,"/")}function Cu(e){return e==="vesper-cli"||e.startsWith("vesper-cli ")||e.endsWith("/vesper-cli")}async function Ia(e){let{rm:t,readdir:r,lstat:n}=await import("node:fs/promises"),s=[],o=async i=>{let a=M(e,i.replace(/\/+$/,"")),c;try{c=await n(a)}catch{return}if(c.isSymbolicLink())return;await t(a,{force:!0,recursive:!0});let l=!1;try{await n(a)}catch{l=!0}l&&s.push(i)};for(let{path:i}of Pa.filter(a=>a.resetRemoves)){let a=i.endsWith("/")?null:Et(i);if(i.includes("*")){let c=i.split("/").pop(),l=new RegExp(`^${c.split("*").map(p=>p.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join("[^/]*")}$`),d=[];try{d=await r(M(e,a))}catch{d=[]}for(let p of d)l.test(p)&&await o(`${a}/${p}`)}else await o(i)}return s}function Ar(e){if(typeof e!="string"||e.length===0)return!1;let t=Oa(),r=e.startsWith("~")?M(t,e.slice(1)):e;r=r.replace(/\\/g,"/");let n=t.replace(/\\/g,"/");if(r!==n&&!r.startsWith(`${n}/`))return!1;let s=r.slice(n.length).replace(/^\/+/,""),o=i=>s===i||s.startsWith(`${i}/`);return Ra.some(o)?!1:!!ja.some(o)}function Yn(e){return e&&(e.host==="claude"||e.host==="copilot")?e.host:e&&e.claude?"claude":e&&Array.isArray(e.paths)&&e.paths.length>0?"copilot":null}async function Jn(e){let t=M(e,".gitignore"),r=[Su,...Kn,Eu].join(`
|
|
19
|
+
`),n=new RegExp(`${Su}[\\s\\S]*?${Eu}`),s="";try{s=await Ke(t,"utf-8")}catch(i){if(i.code!=="ENOENT")throw i;return await A(t,`${r}
|
|
20
20
|
`,"utf-8"),{created:!0,updated:!1}}if(n.test(s)){let i=s.replace(n,r);return i!==s?(await A(t,i,"utf-8"),{created:!1,updated:!0}):{created:!1,updated:!1}}let o=s.endsWith(`
|
|
21
21
|
`)?`
|
|
22
22
|
`:`
|
|
23
23
|
|
|
24
24
|
`;return await A(t,`${s}${o}${r}
|
|
25
|
-
`,"utf-8"),{created:!1,updated:!0}}function Xg(e,t){let r=e.endsWith("/"),n=r?e.slice(0,-1):e;return new RegExp(`^${n.split("*").map(o=>o.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join("[^/]*")}${r?"/":"$"}`).test(t)}async function Yn(e){let{execFile:t}=await import("node:child_process"),{promisify:r}=await import("node:util"),n=r(t),s=async l=>{try{let{stdout:d}=await n("git",l,{cwd:e,timeout:Ca,maxBuffer:16777216});return d}catch{return null}},o=await s(["rev-parse","--is-inside-work-tree"]);if(o===null||o.trim()!=="true")return[];let i=Un.map(l=>l.endsWith("/")?`${l}*`:l),a=await s(["ls-files","-z","--",...i]);if(!a)return[];let c=l=>{let d=Un.findIndex(p=>Xg(p,l));return d===-1?Un.length:d};return[...new Set(a.split("\0").filter(Boolean))].sort((l,d)=>c(l)-c(d)||(l<d?-1:l>d?1:0))}function qr(e){return`vespercli guard --running-host ${e}`}async function ko(e,t,{createOnly:r=!1}={}){let n=M(e,".vscode","tasks.json"),s={label:t.label,type:"shell",command:t.command,presentation:t.presentation||{reveal:"silent",panel:"shared"},problemMatcher:[],runOptions:{runOn:"folderOpen"}},o={version:"2.0.0",tasks:[]},i=!1;try{let c=await Ue(n,"utf-8");o=Lt(c),Array.isArray(o.tasks)||(o.tasks=[]),i=!0}catch(c){if(c.code!=="ENOENT")throw c}let a=o.tasks.findIndex(c=>c?.label===t.label);if(a===-1)o.tasks.push(s);else if(JSON.stringify(o.tasks[a])!==JSON.stringify(s)){if(r)return{created:!1,updated:!1,kept:!0};o.tasks[a]=s}else return{created:!1,updated:!1};return await P(vt(n),{recursive:!0}),await A(n,JSON.stringify(o,null," "),"utf-8"),{created:!i,updated:i}}async function qn(e,t,{removeFileIfEmpty:r=!1}={}){let n=M(e,".vscode","tasks.json"),s;try{s=Lt(await Ue(n,"utf-8"))}catch{return{removed:!1,fileRemoved:!1}}if(!Array.isArray(s?.tasks))return{removed:!1,fileRemoved:!1};let o=s.tasks.filter(a=>a?.label!==t);if(o.length===s.tasks.length)return{removed:!1,fileRemoved:!1};if(s.tasks=o,o.length===0&&Object.keys(s).every(a=>a==="version"||a==="tasks")&&r){let{rm:a}=await import("node:fs/promises");return await a(n,{force:!0}),{removed:!0,fileRemoved:!0}}return await A(n,JSON.stringify(s,null," "),"utf-8"),{removed:!0,fileRemoved:!1}}async function Xn(e,{createOnly:t=!1}={}){return ko(e,{label:vo,command:qr("copilot"),presentation:{reveal:"silent",panel:"shared"}},{createOnly:t})}async function Ia(e){return pa(e,{visible:null})}async function q(e){let t=await Ia(e);return t?{type:he.WORKSPACE_FILE,settingsPath:t,workspaceFile:t}:{type:he.FOLDER,settingsPath:M(e,".vscode","settings.json"),workspaceFile:null}}function Au(e){return M(e,".vscode","settings.json")}function Xr(e,t=null){return t?.workspaceFile?M(vt(t.workspaceFile),".vesperrc"):M(e,".vesperrc")}async function kt(e){let t=await q(e);return Xr(e,t)}function Lt(e){let t=Jg(e,{trailingCommas:!0});return JSON.parse(t)}async function K(e){let t=await q(e);try{let r=await Ue(t.settingsPath,"utf-8"),n=Lt(r);return t.type===he.WORKSPACE_FILE?n.settings||{}:n}catch(r){if(r.code==="ENOENT")return{};if(r instanceof SyntaxError){if(t.type===he.WORKSPACE_FILE)throw new Error(`Failed to parse workspace file: ${t.settingsPath}. ${r.message}`);return{}}throw r}}async function ce(e,t){let r=await q(e);if(r.type===he.WORKSPACE_FILE){let n;try{let s=await Ue(r.settingsPath,"utf-8");n=Lt(s)}catch(s){if(s.code==="ENOENT")n={folders:[],settings:{}};else throw new Error(`Failed to read workspace file: ${r.settingsPath}. ${s.message}`)}n.settings=t,await A(r.settingsPath,JSON.stringify(n,null," "),"utf-8")}else{let n=vt(r.settingsPath);await P(n,{recursive:!0}),await A(r.settingsPath,JSON.stringify(t,null," "),"utf-8")}}function Qg(e){return M(e,".vesper","tracking.json")}function ba(){return{schemaVersion:2,manifest:[]}}async function xa(e){let t;try{t=await Ue(e,"utf-8")}catch(r){return r&&r.code==="ENOENT"?{}:{corrupt:!0}}try{return{parsed:JSON.parse(t)}}catch{return{corrupt:!0,raw:t}}}async function Aa(e,t){let r=`${e}.corrupt-${Date.now()}`,n=!1;try{await Bg(e,r),n=!0}catch{if(typeof t=="string")try{await A(r,t,"utf-8"),n=!0}catch{}}vu.has(e)||(vu.add(e),aa(n?`Unreadable Vesper config at ${e} \u2014 backed up to ${r} and continuing with a fresh default. Restore it from the backup if this was unexpected.`:`Unreadable Vesper config at ${e} that could not be backed up \u2014 continuing with a fresh default. Inspect the file manually before re-running if this was unexpected.`))}async function x(e){let t=await q(e),r=Xr(e,t),n=Qg(e),s=M(e,".vesperrc"),o=await xa(r);if(o.parsed!==void 0)return o.parsed;if(o.corrupt)return await Aa(r,o.raw),ba();if(r!==s){let a=await xa(s);if(a.parsed!==void 0)return a.parsed;if(a.corrupt)return await Aa(s,a.raw),ba()}let i=await xa(n);return i.parsed!==void 0?i.parsed:(i.corrupt&&await Aa(n,i.raw),ba())}async function _u(e){return await Zn(e)}async function Cu(e){return await _u(e)}async function ja(e){try{let t=await Ue(e,"utf-8"),n=Lt(t).folders||[],s=vt(e);return n.map(o=>{let i=o.path||o;return i.startsWith("/")||i.startsWith("~")?i.replace(/^~/,_a()):M(s,i)})}catch{return[]}}async function Qn(e){let t=await q(e);if(t.type!==he.WORKSPACE_FILE)return{found:!1,paths:[]};let r=vt(t.workspaceFile),n=M(r,".vesperrc"),s=await ja(t.workspaceFile),o=[];for(let i of s){let a=M(i,".vesperrc");if(a!==n)try{let c=await Ue(a,"utf-8"),l=JSON.parse(c);o.push({folderPath:i,vesperrcPath:a,tracking:l})}catch{}}return{found:o.length>0,paths:o}}async function Eo(e,t,r){let n=await q(e),s=Xr(e,n),o={...r,workspaceType:he.WORKSPACE_FILE,settingsPath:n.settingsPath,migratedFrom:t,migratedAt:new Date().toISOString()};await A(s,JSON.stringify(o,null,2),"utf-8");try{let{unlink:i}=await import("node:fs/promises");await i(t)}catch{}return{success:!0,newPath:s}}async function T(e,t){let r=await q(e),n=Xr(e,r);try{let s=JSON.parse(await Ue(n,"utf-8"));if(ku(s)===ku(t))return}catch{}await Ar(n,JSON.stringify(t,null,2))}function ku(e){let t=r=>{if(Array.isArray(r))return r.map(t);if(r&&typeof r=="object"){let n={};for(let s of Object.keys(r).sort())s==="updatedAt"||r[s]===void 0||(n[s]=t(r[s]));return n}return r};return JSON.stringify(t(e))}async function Qr(e,t){let r=await q(e),n=await K(e),s=await x(e);Array.isArray(s.paths)||(s.paths=[]);let o=[],i=[];for(let{path:a,settingKey:c}of t){if(n[c]||(n[c]={}),n[c][a]){i.push(a),s.paths.includes(a)||s.paths.push(a);continue}n[c][a]=!0,o.push(a),s.paths.includes(a)||s.paths.push(a)}return o.length>0&&await ce(e,n),s.paths.length>0&&(s.addedAt=s.addedAt||new Date().toISOString(),s.updatedAt=new Date().toISOString(),s.workspaceType=r.type,s.settingsPath=r.settingsPath,await T(e,s)),{added:o,skipped:i,workspaceType:r.type}}async function Zn(e){let t=await K(e),r=await x(e),n={paths:[],settings:[],mcpServers:[],agentTools:[]},s=/vespercli|vesper-cli/,o=[...new Set([...$u(r),...Ao().map(f=>f.path),...Ou().map(f=>f.path)])];for(let f of Object.values(He))if(t[f]){for(let m of Object.keys(t[f])){let h=o.includes(m),g=s.test(m);(h||g)&&(delete t[f][m],n.paths.includes(m)||n.paths.push(m))}Object.keys(t[f]).length===0&&delete t[f]}let i=[...new Set([...r.readAccessPaths||[],O])];if(i.length>0){let f=t[oe]||[],m=f.filter(h=>!i.includes(h));m.length!==f.length&&(m.length>0?t[oe]=m:delete t[oe],n.settings.push(oe))}let a=ey();for(let f of Nt){if(t[f]===void 0)continue;let m=t[f];if(Zg.has(f)&&m&&typeof m=="object"&&!Array.isArray(m)){let h=!1;for(let g of Object.keys(m))(a.has(g)||bu(g))&&(delete m[g],h=!0);Object.keys(m).length===0?(delete t[f],n.settings.push(f)):h&&n.settings.push(f);continue}delete t[f],n.settings.push(f)}let c=r.mcp?.agentTools||{};for(let[f,m]of Object.entries(c))n.agentTools.push({agent:f,tools:m});(n.paths.length>0||n.settings.length>0)&&await ce(e,t);let l=await Qe(e),d=r.mcp?.servers||[],p=[...new Set([...me,...d])];if(l.servers){for(let f of p)l.servers[f]&&(delete l.servers[f],n.mcpServers.push(f));if(n.mcpServers.length>0){let f=Xe(e),m=vt(f);await P(m,{recursive:!0}),await A(f,JSON.stringify(l,null," "),"utf-8")}}return r.paths=[],r.readAccessPaths=[],r.addedAt=null,r.workspaceType=null,r.settingsPath=null,r.mcp=null,await T(e,r),{removed:n}}function ey(){return new Set([...Wn,...je,...Object.values(So).flat()])}async function Zr(e,{trackedPaths:t=[],trackedReadAccess:r=[]}={}){let n={removed:[],rehomed:[],readAccessRemoved:[],commandKeysRemoved:[]},s;try{s=await K(e)}catch{return n}let o=new Set(t),i=/\/assets\/(?:core\/|skills(?:\/|$)|agents\/|prompts\/|instructions\/)/,a=!1;for(let d of Object.values(He)){let p=s[d];if(!(!p||typeof p!="object"||Array.isArray(p))){for(let f of Object.keys(p)){let m=f.replace(/\\/g,"/");if(wa(m)||o.has(f)&&i.test(m)){delete p[f],n.removed.push(f),a=!0;continue}let h=ro.exec(m);if(h&&h[1].startsWith("assets/copilot/")){let g=er(M(Nn,h[1]));if(g!==f){let y=p[f];delete p[f],p[g]=p[g]===!0?!0:y,n.rehomed.push(f),a=!0}}}Object.keys(p).length===0&&(delete s[d],a=!0)}}let c=s[oe];if(Array.isArray(c)){let d=new Set([O,er(O)]),p=new Set(r.filter(m=>typeof m=="string"&&/\/assets\/?$/.test(m.replace(/\\/g,"/")))),f=c.filter(m=>{if(typeof m!="string"||d.has(m))return!0;let h=ro.exec(m.replace(/\\/g,"/")),g=!!h&&/^assets\/?$/.test(h[1])||p.has(m);return g&&n.readAccessRemoved.push(m),!g});f.length!==c.length&&(f.length?s[oe]=f:delete s[oe],a=!0)}let l=s[Rt];if(l&&typeof l=="object"&&!Array.isArray(l))for(let d of Object.keys(l))bu(d)&&(delete l[d],n.commandKeysRemoved.push(d),a=!0);if(a&&await ce(e,s),n.removed.length||n.rehomed.length||n.readAccessRemoved.length){let d=await x(e),p=!1,f=new Set([...n.removed,...n.rehomed]);Array.isArray(d.paths)&&d.paths.some(h=>f.has(h))&&(d.paths=d.paths.filter(h=>!f.has(h)),p=!0);let m=new Set(n.readAccessRemoved);Array.isArray(d.readAccessPaths)&&d.readAccessPaths.some(h=>m.has(h))&&(d.readAccessPaths=d.readAccessPaths.filter(h=>!m.has(h)),p=!0),p&&await T(e,d)}return n}function $u(e){let r=(Array.isArray(e?.manifest)?e.manifest:[]).find(n=>n&&n.path===".vscode/settings.json"&&n.category==="settings");return r&&Array.isArray(r.owns?.entries)&&r.owns.entries.length?[...r.owns.entries]:Array.isArray(e?.paths)?[...e.paths]:[]}async function ge(e){let t=await x(e);if(Number(t.schemaVersion)>=2)return[];let r=[];return Array.isArray(t.paths)&&t.paths.length>0&&r.push("copilot"),t.claude&&r.push("claude"),r}async function bo(){try{return(await Kg(co,{withFileTypes:!0})).filter(t=>t.isDirectory()&&!t.name.startsWith(".")).map(t=>t.name).sort()}catch{return[]}}function xo(e){la(e);let t=M(co,e);if(!Yr(M(t,`${e}.instructions.md`)))throw new Error(`Unknown instruction "${e}" \u2014 not in ${co}`);return{path:er(t),settingKey:He.instructions,type:"instructions",name:e}}function Ao(){let e=[];for(let s of ry){let o=qe[s],i=He[s];i&&o&&e.push({path:er(M(ty,o.dir)),settingKey:i,type:s})}He.instructions&&Yr(Kn)&&e.push({path:er(Kn),settingKey:He.instructions,type:"instructions"});let t=He.agents;t&&e.push({path:"${workspaceFolder}/.vesper/agents",settingKey:t,type:"agents"});let r=He.instructions;r&&e.push({path:"${workspaceFolder}/.vesper/instructions",settingKey:r,type:"instructions"});let n=He.skills;return n&&e.push({path:"${workspaceFolder}/.vesper/skills",settingKey:n,type:"skills"}),e}function _o(){try{return zg(lo,{withFileTypes:!0}).filter(e=>e.isDirectory()&&!e.name.startsWith(".")).map(e=>e.name).sort()}catch{return[]}}function rr(e){la(e);let t=M(lo,e);if(!Yr(t))throw new Error(`Unknown pack "${e}" \u2014 not in ${lo}`);let r=[];for(let n of["agents","skills"]){let s=M(t,n);Yr(s)&&r.push({path:er(s),settingKey:He[n],type:n,pack:e})}return r}function Ou(){return _o().flatMap(e=>rr(e))}async function Ra(e,t){let r=await K(e),n=await x(e),s=new Set(t),o=[];for(let i of Object.values(He)){let a=r[i];if(!(!a||typeof a!="object")){for(let c of Object.keys(a))s.has(c)&&(delete a[c],o.includes(c)||o.push(c));Object.keys(a).length===0&&delete r[i]}}return o.length>0&&await ce(e,r),Array.isArray(n.paths)&&n.paths.some(i=>s.has(i))&&(n.paths=n.paths.filter(i=>!s.has(i)),n.updatedAt=new Date().toISOString(),await T(e,n)),{removed:o}}async function Co(e,t=!0){let r=await q(e),n=await K(e);if(n[uo]=t,t){n[Rt]||(n[Rt]={});for(let s of Wn)n[Rt][s]=!0}return await ce(e,n),{configured:t?Wn.length:0,workspaceType:r.type}}async function $o(e,t={}){let{maxRequests:r=Ie.maxRequests,omitBaseAgentInstructions:n=Ie.omitBaseAgentInstructions}=t,s=await K(e);s[po]=r,s[fo]=!0,s[ho]=!0,s[mo]=!0,s[go]=n,s[yo]=!0,s[wo]="newAndOutdated",s[oe]||(s[oe]=[]),await ce(e,s)}async function Tu(e){let r=(await K(e))[Rt]||{};return Object.entries(r).filter(([,n])=>n===!0).map(([n])=>n)}async function Oo(e,t){let r=await K(e),n=r[oe]||[];n.includes(t)||(n.push(t),r[oe]=n,await ce(e,r));let s=await x(e);return s.readAccessPaths||(s.readAccessPaths=[]),s.readAccessPaths.includes(t)||(s.readAccessPaths.push(t),s.updatedAt=new Date().toISOString(),await T(e,s)),n}async function To(e,t){let r=await K(e),n=r[oe]||[],s=n.indexOf(t);s!==-1&&(n.splice(s,1),r[oe]=n,await ce(e,r));let o=await x(e);if(o.readAccessPaths){let i=o.readAccessPaths.indexOf(t);i!==-1&&(o.readAccessPaths.splice(i,1),o.updatedAt=new Date().toISOString(),await T(e,o))}return n}async function Po(e){return(await K(e))[oe]||[]}async function St(e){let t=await x(e);return $u(t)}async function Io(e){let t=await q(e),r=await K(e),n=await x(e);Array.isArray(n.paths)||(n.paths=[]);let s=Ao(),o=[],i=[];for(let{path:l,settingKey:d}of s)r[d]||(r[d]={}),r[d][l]===!0?i.push(l):(r[d][l]=!0,o.push(l)),n.paths.includes(l)||n.paths.push(l);let a=O,c=r[oe]||[];return c.includes(a)||(c.push(a),r[oe]=c,o.push(a)),n.readAccessPaths||(n.readAccessPaths=[]),n.readAccessPaths.includes(a)||n.readAccessPaths.push(a),o.length>0&&await ce(e,r),n.addedAt=n.addedAt||new Date().toISOString(),n.updatedAt=new Date().toISOString(),n.workspaceType=t.type,n.settingsPath=t.settingsPath,await T(e,n),{added:o,existed:i,workspaceType:t.type}}async function ny(e,{cwd:t,env:r,gitArgs:n=[],timeout:s=Ca}={}){let{execFile:o}=await import("node:child_process");return new Promise(i=>{try{o("git",[...n,...e],{cwd:t,timeout:s,maxBuffer:16777216,encoding:"utf-8",...r?{env:r}:{}},(c,l)=>{i(c?null:l)}).stdin?.end()}catch{i(null)}})}function jo(e){if(!e)return[];let t=e.includes("\0")?"\0":`
|
|
26
|
-
`,r=[],n=null;for(let s of e.split(t)){if(s===""){n&&r.push(n),n=null;continue}n??={};let o=s.indexOf(" "),i=o===-1?s:s.slice(0,o),a=o===-1?null:s.slice(o+1);i==="worktree"?n.worktree=a:i==="HEAD"?n.head=a:i==="branch"?n.branch=a:i==="bare"?n.bare=!0:i==="detached"?n.detached=!0:i==="locked"?n.locked=a??!0:i==="prunable"&&(n.prunable=a??!0)}return n&&r.push(n),r}async function
|
|
25
|
+
`,"utf-8"),{created:!1,updated:!0}}function oy(e,t){let r=e.endsWith("/"),n=r?e.slice(0,-1):e;return new RegExp(`^${n.split("*").map(o=>o.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join("[^/]*")}${r?"/":"$"}`).test(t)}async function qn(e){let{execFile:t}=await import("node:child_process"),{promisify:r}=await import("node:util"),n=r(t),s=async l=>{try{let{stdout:d}=await n("git",l,{cwd:e,timeout:Ta,maxBuffer:16777216});return d}catch{return null}},o=await s(["rev-parse","--is-inside-work-tree"]);if(o===null||o.trim()!=="true")return[];let i=Kn.map(l=>l.endsWith("/")?`${l}*`:l),a=await s(["ls-files","-z","--",...i]);if(!a)return[];let c=l=>{let d=Kn.findIndex(p=>oy(p,l));return d===-1?Kn.length:d};return[...new Set(a.split("\0").filter(Boolean))].sort((l,d)=>c(l)-c(d)||(l<d?-1:l>d?1:0))}function Xr(e){return`vespercli guard --running-host ${e}`}async function bo(e,t,{createOnly:r=!1}={}){let n=M(e,".vscode","tasks.json"),s={label:t.label,type:"shell",command:t.command,presentation:t.presentation||{reveal:"silent",panel:"shared"},problemMatcher:[],runOptions:{runOn:"folderOpen"}},o={version:"2.0.0",tasks:[]},i=!1;try{let c=await Ke(n,"utf-8");o=Mt(c),Array.isArray(o.tasks)||(o.tasks=[]),i=!0}catch(c){if(c.code!=="ENOENT")throw c}let a=o.tasks.findIndex(c=>c?.label===t.label);if(a===-1)o.tasks.push(s);else if(JSON.stringify(o.tasks[a])!==JSON.stringify(s)){if(r)return{created:!1,updated:!1,kept:!0};o.tasks[a]=s}else return{created:!1,updated:!1};return await P(Et(n),{recursive:!0}),await A(n,JSON.stringify(o,null," "),"utf-8"),{created:!i,updated:i}}async function Qn(e,t,{removeFileIfEmpty:r=!1}={}){let n=M(e,".vscode","tasks.json"),s;try{s=Mt(await Ke(n,"utf-8"))}catch{return{removed:!1,fileRemoved:!1}}if(!Array.isArray(s?.tasks))return{removed:!1,fileRemoved:!1};let o=s.tasks.filter(a=>a?.label!==t);if(o.length===s.tasks.length)return{removed:!1,fileRemoved:!1};if(s.tasks=o,o.length===0&&Object.keys(s).every(a=>a==="version"||a==="tasks")&&r){let{rm:a}=await import("node:fs/promises");return await a(n,{force:!0}),{removed:!0,fileRemoved:!0}}return await A(n,JSON.stringify(s,null," "),"utf-8"),{removed:!0,fileRemoved:!1}}async function Zn(e,{createOnly:t=!1}={}){return bo(e,{label:Eo,command:Xr("copilot"),presentation:{reveal:"silent",panel:"shared"}},{createOnly:t})}async function Na(e){return ma(e,{visible:null})}async function q(e){let t=await Na(e);return t?{type:he.WORKSPACE_FILE,settingsPath:t,workspaceFile:t}:{type:he.FOLDER,settingsPath:M(e,".vscode","settings.json"),workspaceFile:null}}function Ou(e){return M(e,".vscode","settings.json")}function Qr(e,t=null){return t?.workspaceFile?M(Et(t.workspaceFile),".vesperrc"):M(e,".vesperrc")}async function bt(e){let t=await q(e);return Qr(e,t)}function Mt(e){let t=ny(e,{trailingCommas:!0});return JSON.parse(t)}async function K(e){let t=await q(e);try{let r=await Ke(t.settingsPath,"utf-8"),n=Mt(r);return t.type===he.WORKSPACE_FILE?n.settings||{}:n}catch(r){if(r.code==="ENOENT")return{};if(r instanceof SyntaxError){if(t.type===he.WORKSPACE_FILE)throw new Error(`Failed to parse workspace file: ${t.settingsPath}. ${r.message}`);return{}}throw r}}async function ce(e,t){let r=await q(e);if(r.type===he.WORKSPACE_FILE){let n;try{let s=await Ke(r.settingsPath,"utf-8");n=Mt(s)}catch(s){if(s.code==="ENOENT")n={folders:[],settings:{}};else throw new Error(`Failed to read workspace file: ${r.settingsPath}. ${s.message}`)}n.settings=t,await A(r.settingsPath,JSON.stringify(n,null," "),"utf-8")}else{let n=Et(r.settingsPath);await P(n,{recursive:!0}),await A(r.settingsPath,JSON.stringify(t,null," "),"utf-8")}}function iy(e){return M(e,".vesper","tracking.json")}function _a(){return{schemaVersion:2,manifest:[]}}async function Ca(e){let t;try{t=await Ke(e,"utf-8")}catch(r){return r&&r.code==="ENOENT"?{}:{corrupt:!0}}try{return{parsed:JSON.parse(t)}}catch{return{corrupt:!0,raw:t}}}async function $a(e,t){let r=`${e}.corrupt-${Date.now()}`,n=!1;try{await ey(e,r),n=!0}catch{if(typeof t=="string")try{await A(r,t,"utf-8"),n=!0}catch{}}bu.has(e)||(bu.add(e),ua(n?`Unreadable Vesper config at ${e} \u2014 backed up to ${r} and continuing with a fresh default. Restore it from the backup if this was unexpected.`:`Unreadable Vesper config at ${e} that could not be backed up \u2014 continuing with a fresh default. Inspect the file manually before re-running if this was unexpected.`))}async function x(e){let t=await q(e),r=Qr(e,t),n=iy(e),s=M(e,".vesperrc"),o=await Ca(r);if(o.parsed!==void 0)return o.parsed;if(o.corrupt)return await $a(r,o.raw),_a();if(r!==s){let a=await Ca(s);if(a.parsed!==void 0)return a.parsed;if(a.corrupt)return await $a(s,a.raw),_a()}let i=await Ca(n);return i.parsed!==void 0?i.parsed:(i.corrupt&&await $a(n,i.raw),_a())}async function Tu(e){return await ts(e)}async function Pu(e){return await Tu(e)}async function La(e){try{let t=await Ke(e,"utf-8"),n=Mt(t).folders||[],s=Et(e);return n.map(o=>{let i=o.path||o;return i.startsWith("/")||i.startsWith("~")?i.replace(/^~/,Oa()):M(s,i)})}catch{return[]}}async function es(e){let t=await q(e);if(t.type!==he.WORKSPACE_FILE)return{found:!1,paths:[]};let r=Et(t.workspaceFile),n=M(r,".vesperrc"),s=await La(t.workspaceFile),o=[];for(let i of s){let a=M(i,".vesperrc");if(a!==n)try{let c=await Ke(a,"utf-8"),l=JSON.parse(c);o.push({folderPath:i,vesperrcPath:a,tracking:l})}catch{}}return{found:o.length>0,paths:o}}async function Ao(e,t,r){let n=await q(e),s=Qr(e,n),o={...r,workspaceType:he.WORKSPACE_FILE,settingsPath:n.settingsPath,migratedFrom:t,migratedAt:new Date().toISOString()};await A(s,JSON.stringify(o,null,2),"utf-8");try{let{unlink:i}=await import("node:fs/promises");await i(t)}catch{}return{success:!0,newPath:s}}async function T(e,t){let r=await q(e),n=Qr(e,r);try{let s=JSON.parse(await Ke(n,"utf-8"));if(xu(s)===xu(t))return}catch{}await Cr(n,JSON.stringify(t,null,2))}function xu(e){let t=r=>{if(Array.isArray(r))return r.map(t);if(r&&typeof r=="object"){let n={};for(let s of Object.keys(r).sort())s==="updatedAt"||r[s]===void 0||(n[s]=t(r[s]));return n}return r};return JSON.stringify(t(e))}async function Zr(e,t){let r=await q(e),n=await K(e),s=await x(e);Array.isArray(s.paths)||(s.paths=[]);let o=[],i=[];for(let{path:a,settingKey:c}of t){if(n[c]||(n[c]={}),n[c][a]){i.push(a),s.paths.includes(a)||s.paths.push(a);continue}n[c][a]=!0,o.push(a),s.paths.includes(a)||s.paths.push(a)}return o.length>0&&await ce(e,n),s.paths.length>0&&(s.addedAt=s.addedAt||new Date().toISOString(),s.updatedAt=new Date().toISOString(),s.workspaceType=r.type,s.settingsPath=r.settingsPath,await T(e,s)),{added:o,skipped:i,workspaceType:r.type}}async function ts(e){let t=await K(e),r=await x(e),n={paths:[],settings:[],mcpServers:[],agentTools:[]},s=/vespercli|vesper-cli/,o=[...new Set([...Iu(r),...$o().map(f=>f.path),...ju().map(f=>f.path)])];for(let f of Object.values(We))if(t[f]){for(let m of Object.keys(t[f])){let h=o.includes(m),g=s.test(m);(h||g)&&(delete t[f][m],n.paths.includes(m)||n.paths.push(m))}Object.keys(t[f]).length===0&&delete t[f]}let i=[...new Set([...r.readAccessPaths||[],O])];if(i.length>0){let f=t[oe]||[],m=f.filter(h=>!i.includes(h));m.length!==f.length&&(m.length>0?t[oe]=m:delete t[oe],n.settings.push(oe))}let a=cy();for(let f of Lt){if(t[f]===void 0)continue;let m=t[f];if(ay.has(f)&&m&&typeof m=="object"&&!Array.isArray(m)){let h=!1;for(let g of Object.keys(m))(a.has(g)||Cu(g))&&(delete m[g],h=!0);Object.keys(m).length===0?(delete t[f],n.settings.push(f)):h&&n.settings.push(f);continue}delete t[f],n.settings.push(f)}let c=r.mcp?.agentTools||{};for(let[f,m]of Object.entries(c))n.agentTools.push({agent:f,tools:m});(n.paths.length>0||n.settings.length>0)&&await ce(e,t);let l=await Ze(e),d=r.mcp?.servers||[],p=[...new Set([...me,...d])];if(l.servers){for(let f of p)l.servers[f]&&(delete l.servers[f],n.mcpServers.push(f));if(n.mcpServers.length>0){let f=Qe(e),m=Et(f);await P(m,{recursive:!0}),await A(f,JSON.stringify(l,null," "),"utf-8")}}return r.paths=[],r.readAccessPaths=[],r.addedAt=null,r.workspaceType=null,r.settingsPath=null,r.mcp=null,await T(e,r),{removed:n}}function cy(){return new Set([...Bn,...Ne,...Object.values(xo).flat()])}async function en(e,{trackedPaths:t=[],trackedReadAccess:r=[]}={}){let n={removed:[],rehomed:[],readAccessRemoved:[],commandKeysRemoved:[]},s;try{s=await K(e)}catch{return n}let o=new Set(t),i=/\/assets\/(?:core\/|skills(?:\/|$)|agents\/|prompts\/|instructions\/)/,a=!1;for(let d of Object.values(We)){let p=s[d];if(!(!p||typeof p!="object"||Array.isArray(p))){for(let f of Object.keys(p)){let m=f.replace(/\\/g,"/");if(Sa(m)||o.has(f)&&i.test(m)){delete p[f],n.removed.push(f),a=!0;continue}let h=oo.exec(m);if(h&&h[1].startsWith("assets/copilot/")){let g=rr(M(Mn,h[1]));if(g!==f){let y=p[f];delete p[f],p[g]=p[g]===!0?!0:y,n.rehomed.push(f),a=!0}}}Object.keys(p).length===0&&(delete s[d],a=!0)}}let c=s[oe];if(Array.isArray(c)){let d=new Set([O,rr(O)]),p=new Set(r.filter(m=>typeof m=="string"&&/\/assets\/?$/.test(m.replace(/\\/g,"/")))),f=c.filter(m=>{if(typeof m!="string"||d.has(m))return!0;let h=oo.exec(m.replace(/\\/g,"/")),g=!!h&&/^assets\/?$/.test(h[1])||p.has(m);return g&&n.readAccessRemoved.push(m),!g});f.length!==c.length&&(f.length?s[oe]=f:delete s[oe],a=!0)}let l=s[Nt];if(l&&typeof l=="object"&&!Array.isArray(l))for(let d of Object.keys(l))Cu(d)&&(delete l[d],n.commandKeysRemoved.push(d),a=!0);if(a&&await ce(e,s),n.removed.length||n.rehomed.length||n.readAccessRemoved.length){let d=await x(e),p=!1,f=new Set([...n.removed,...n.rehomed]);Array.isArray(d.paths)&&d.paths.some(h=>f.has(h))&&(d.paths=d.paths.filter(h=>!f.has(h)),p=!0);let m=new Set(n.readAccessRemoved);Array.isArray(d.readAccessPaths)&&d.readAccessPaths.some(h=>m.has(h))&&(d.readAccessPaths=d.readAccessPaths.filter(h=>!m.has(h)),p=!0),p&&await T(e,d)}return n}function Iu(e){let r=(Array.isArray(e?.manifest)?e.manifest:[]).find(n=>n&&n.path===".vscode/settings.json"&&n.category==="settings");return r&&Array.isArray(r.owns?.entries)&&r.owns.entries.length?[...r.owns.entries]:Array.isArray(e?.paths)?[...e.paths]:[]}async function ge(e){let t=await x(e);if(Number(t.schemaVersion)>=2)return[];let r=[];return Array.isArray(t.paths)&&t.paths.length>0&&r.push("copilot"),t.claude&&r.push("claude"),r}async function _o(){try{return(await Zg(po,{withFileTypes:!0})).filter(t=>t.isDirectory()&&!t.name.startsWith(".")).map(t=>t.name).sort()}catch{return[]}}function Co(e){pa(e);let t=M(po,e);if(!Jr(M(t,`${e}.instructions.md`)))throw new Error(`Unknown instruction "${e}" \u2014 not in ${po}`);return{path:rr(t),settingKey:We.instructions,type:"instructions",name:e}}function $o(){let e=[];for(let s of uy){let o=Xe[s],i=We[s];i&&o&&e.push({path:rr(M(ly,o.dir)),settingKey:i,type:s})}We.instructions&&Jr(zn)&&e.push({path:rr(zn),settingKey:We.instructions,type:"instructions"});let t=We.agents;t&&e.push({path:"${workspaceFolder}/.vesper/agents",settingKey:t,type:"agents"});let r=We.instructions;r&&e.push({path:"${workspaceFolder}/.vesper/instructions",settingKey:r,type:"instructions"});let n=We.skills;return n&&e.push({path:"${workspaceFolder}/.vesper/skills",settingKey:n,type:"skills"}),e}function Oo(){try{return ty(fo,{withFileTypes:!0}).filter(e=>e.isDirectory()&&!e.name.startsWith(".")).map(e=>e.name).sort()}catch{return[]}}function sr(e){pa(e);let t=M(fo,e);if(!Jr(t))throw new Error(`Unknown pack "${e}" \u2014 not in ${fo}`);let r=[];for(let n of["agents","skills"]){let s=M(t,n);Jr(s)&&r.push({path:rr(s),settingKey:We[n],type:n,pack:e})}return r}function ju(){return Oo().flatMap(e=>sr(e))}async function Ma(e,t){let r=await K(e),n=await x(e),s=new Set(t),o=[];for(let i of Object.values(We)){let a=r[i];if(!(!a||typeof a!="object")){for(let c of Object.keys(a))s.has(c)&&(delete a[c],o.includes(c)||o.push(c));Object.keys(a).length===0&&delete r[i]}}return o.length>0&&await ce(e,r),Array.isArray(n.paths)&&n.paths.some(i=>s.has(i))&&(n.paths=n.paths.filter(i=>!s.has(i)),n.updatedAt=new Date().toISOString(),await T(e,n)),{removed:o}}async function To(e,t=!0){let r=await q(e),n=await K(e);if(n[ho]=t,t){n[Nt]||(n[Nt]={});for(let s of Bn)n[Nt][s]=!0}return await ce(e,n),{configured:t?Bn.length:0,workspaceType:r.type}}async function Po(e,t={}){let{maxRequests:r=Re.maxRequests,omitBaseAgentInstructions:n=Re.omitBaseAgentInstructions}=t,s=await K(e);s[mo]=r,s[go]=!0,s[yo]=!0,s[wo]=!0,s[vo]=n,s[ko]=!0,s[So]="newAndOutdated",s[oe]||(s[oe]=[]),await ce(e,s)}async function Ru(e){let r=(await K(e))[Nt]||{};return Object.entries(r).filter(([,n])=>n===!0).map(([n])=>n)}async function Io(e,t){let r=await K(e),n=r[oe]||[];n.includes(t)||(n.push(t),r[oe]=n,await ce(e,r));let s=await x(e);return s.readAccessPaths||(s.readAccessPaths=[]),s.readAccessPaths.includes(t)||(s.readAccessPaths.push(t),s.updatedAt=new Date().toISOString(),await T(e,s)),n}async function jo(e,t){let r=await K(e),n=r[oe]||[],s=n.indexOf(t);s!==-1&&(n.splice(s,1),r[oe]=n,await ce(e,r));let o=await x(e);if(o.readAccessPaths){let i=o.readAccessPaths.indexOf(t);i!==-1&&(o.readAccessPaths.splice(i,1),o.updatedAt=new Date().toISOString(),await T(e,o))}return n}async function Ro(e){return(await K(e))[oe]||[]}async function xt(e){let t=await x(e);return Iu(t)}async function No(e){let t=await q(e),r=await K(e),n=await x(e);Array.isArray(n.paths)||(n.paths=[]);let s=$o(),o=[],i=[];for(let{path:l,settingKey:d}of s)r[d]||(r[d]={}),r[d][l]===!0?i.push(l):(r[d][l]=!0,o.push(l)),n.paths.includes(l)||n.paths.push(l);let a=O,c=r[oe]||[];return c.includes(a)||(c.push(a),r[oe]=c,o.push(a)),n.readAccessPaths||(n.readAccessPaths=[]),n.readAccessPaths.includes(a)||n.readAccessPaths.push(a),o.length>0&&await ce(e,r),n.addedAt=n.addedAt||new Date().toISOString(),n.updatedAt=new Date().toISOString(),n.workspaceType=t.type,n.settingsPath=t.settingsPath,await T(e,n),{added:o,existed:i,workspaceType:t.type}}async function dy(e,{cwd:t,env:r,gitArgs:n=[],timeout:s=Ta}={}){let{execFile:o}=await import("node:child_process");return new Promise(i=>{try{o("git",[...n,...e],{cwd:t,timeout:s,maxBuffer:16777216,encoding:"utf-8",...r?{env:r}:{}},(c,l)=>{i(c?null:l)}).stdin?.end()}catch{i(null)}})}function Lo(e){if(!e)return[];let t=e.includes("\0")?"\0":`
|
|
26
|
+
`,r=[],n=null;for(let s of e.split(t)){if(s===""){n&&r.push(n),n=null;continue}n??={};let o=s.indexOf(" "),i=o===-1?s:s.slice(0,o),a=o===-1?null:s.slice(o+1);i==="worktree"?n.worktree=a:i==="HEAD"?n.head=a:i==="branch"?n.branch=a:i==="bare"?n.bare=!0:i==="detached"?n.detached=!0:i==="locked"?n.locked=a??!0:i==="prunable"&&(n.prunable=a??!0)}return n&&r.push(n),r}async function py(){if(uo)return uo;let e=await D(["version"]),t=/(\d+)\.(\d+)/.exec(e||"");return uo=t?[Number(t[1]),Number(t[2])]:[0,0],uo}async function Mo(e,{env:t,gitArgs:r=[],gitVersion:n}={}){let[s,o]=n??await py(),i=s>2||s===2&&o>=36,a=await dy(["worktree","list","--porcelain",...i?["-z"]:[]],{cwd:e,env:t,gitArgs:r});return a===null?null:{out:a,nul:i}}async function Wn(e){let{realpath:t}=await import("node:fs/promises"),{resolve:r}=await import("node:path");try{return await t(e)}catch{return r(e)}}async function ct(e){let{realpath:t}=await import("node:fs/promises"),{resolve:r,join:n,dirname:s,basename:o}=await import("node:path"),i=r(e),a=[];for(;;)try{let c=await t(i);return a.length?n(c,...a.reverse()):c}catch{let c=s(i);if(c===i)return r(e);a.push(o(i)),i=c}}async function Nu(e,{top:t,common:r},{git:n=D,env:s,gitArgs:o=[]}={}){let i=new Set([await Wn(t),await Wn(r)]);await n(["rev-parse","--is-bare-repository"],{cwd:e})==="true"||i.add(await Wn(Et(r)));let c=await Mo(e,{env:s,gitArgs:o});for(let l of Lo(c?.out??null))l.worktree&&!l.bare&&i.add(await Wn(l.worktree));return[...i]}function St(e,t){let{sep:r}=ry;return(t||[]).some(n=>e===n||e.startsWith(`${n}${r}`))}async function or(e,{runGit:t=D,env:r,gitArgs:n=[]}={}){let s=(E,b={})=>t([...n,...E],{...b,...r?{env:r}:{}}),{isAbsolute:o,resolve:i}=await import("node:path"),{realpath:a,stat:c}=await import("node:fs/promises");if(await s(["rev-parse","--is-inside-work-tree"],{cwd:e})!=="true")return{dir:null,reason:"not-a-repo"};let l=await s(["rev-parse","--show-toplevel"],{cwd:e}),d=await s(["rev-parse","--git-common-dir"],{cwd:e});if(!l||!d)return{dir:null,reason:"not-a-repo"};let p=o(d)?d:i(e,d),f=await Nu(e,{top:l,common:p},{git:s,env:r,gitArgs:n}),m={top:l,common:p,roots:f},h=await s(["config","--type=path","--show-scope","--get","core.hooksPath"],{cwd:e});if(h===null){let E=await s(["config","--get","core.hooksPath"],{cwd:e});if(E)return{dir:null,disabled:!0,reason:"unverifiable",configured:E};let b=M(p,"hooks"),F=await ct(b);if(!St(F,f))return{dir:null,disabled:!0,reason:"outside-repository",configured:b,defaultDir:!0};if(Jr(b))try{if(!(await c(F)).isDirectory())return{dir:null,disabled:!0,reason:"not-a-directory",configured:b,defaultDir:!0}}catch{}return{dir:b,default:!0,...m}}let g=h.indexOf(" "),y=g===-1?"":h.slice(0,g),k=g===-1?h:h.slice(g+1);if(!["local","worktree"].includes(y))return{dir:null,disabled:!0,reason:"machine-wide",scope:y,configured:k};let v=o(k)?k:i(l,k);if(fy(v))return{dir:null,disabled:!0,reason:"husky-v9",scope:y,configured:k};let S=null;try{S=await a(v)}catch{S=null}let C=!1;if(S!==null)try{C=(await c(S)).isDirectory()}catch{C=!1}if(S!==null&&!C)return{dir:null,disabled:!0,reason:"not-a-directory",scope:y,configured:k};let N=S??i(v);return St(N,f)?C?{dir:v,scope:y,configured:k,...m}:{dir:null,disabled:!0,reason:"not-a-directory",scope:y,configured:k}:{dir:null,disabled:!0,reason:"outside-repository",scope:y,configured:k}}function fy(e){let t=e.replace(/\\/g,"/").replace(/\/+$/,"").split("/");return t.at(-1)==="_"&&t.at(-2)===".husky"&&Jr(M(e,"h"))}async function rn(e){let{lstat:t,realpath:r}=await import("node:fs/promises"),n;try{n=await t(e)}catch(s){if(s.code==="ENOENT")return{path:e};throw s}if(!n.isSymbolicLink())return{path:e};try{return{path:await r(e)}}catch{return{path:null,reason:"dangling-symlink"}}}async function kt(e,t){let{basename:r}=await import("node:path");await Cr(e,t,{mode:493,tempName:n=>M(Et(n),`.${r(n)}.vesper-${process.pid}.tmp`),sweepPattern:/^\..+\.vesper-\d+\.tmp$/})}async function nr(e,t,{dir:r=!1}={}){let{relative:n}=await import("node:path"),s=await Wn(t.common??"");if(St(e,[s]))return!1;let o=(t.roots||[]).filter(l=>l!==s&&St(e,[l])).sort((l,d)=>d.length-l.length),{stripRepoLocationEnv:i,READ_ONLY_GIT_ENV:a}=await Promise.resolve().then(()=>(vt(),Aa)),c={...i(process.env),...a};for(let l of o){let d=n(l,e);if(d===""||d.startsWith(".."))continue;let p=r?["ls-files","-z","--",d]:["ls-files","--error-unmatch","--",d],f=await D([...tn,...p],{cwd:l,env:c,timeout:1e4});return r?!!f:f!==null}return!1}async function Lu(e,t,{resolved:r,dirTracked:n}={}){let s=r??await or(e);if(!s.dir){let{reason:N,disabled:E,scope:b,configured:F,defaultDir:X}=s;return{installed:!1,updated:!1,hooksDir:null,reason:N,...E?{disabled:E}:{},...b?{scope:b}:{},...F!==void 0?{configured:F}:{},...X?{defaultDir:X}:{}}}let o=s.dir,i=(N,E={})=>({installed:!1,updated:!1,hooksDir:o,hook:t,reason:N,...E}),a=M(O,"hooks",t),c=await Ke(a,"utf-8"),l=c.match(new RegExp(`${it}[\\s\\S]*?${qt}`));if(!l)throw new Error(`Hook source ${a} is missing its vesper:hook guard markers`);let d=Buffer.from(l[0],"utf-8").toString("latin1"),p=new RegExp(`${it}[\\s\\S]*?${qt}`);if(n??(!s.default&&await nr(await ct(o),s,{dir:!0})))return{installed:!1,updated:!1,hooksDir:null,reason:"tracked-by-git",configured:o};let m=M(o,t),h=await rn(m);if(!h.path)return i(h.reason,{configured:m});let g=await ct(h.path);if(!St(g,s.roots))return i("outside-repository",{configured:h.path});if(Ar(h.path))return i("write-refused",{configured:h.path});if(await nr(g,s))return i("tracked-by-git",{configured:g});s.default&&await P(o,{recursive:!0});let y=null;try{y=await Ke(h.path)}catch(N){if(N.code!=="ENOENT")throw N}if(y===null)return await kt(h.path,c),{installed:!0,updated:!1,hooksDir:o};let k=y.toString("latin1"),v=k.indexOf(it);if(v!==-1&&p.test(k)){let N=Wr(y.subarray(0,v),{whole:y});if(!N.ok){let b=kr(k);return b!==null&&b!==k&&await kt(h.path,Buffer.from(b,"latin1")),{installed:!1,updated:!0,hooksDir:o,hook:t,reason:"foreign-hook-repaired",interpreter:N.interpreter}}let E=k.replace(p,()=>d);return E!==k?(await kt(h.path,Buffer.from(E,"latin1")),{installed:!1,updated:!0,hooksDir:o}):{installed:!1,updated:!1,hooksDir:o}}let S=Wr(y);if(!S.ok){let{reason:N,interpreter:E,line:b}=S;return i(N,{interpreter:E,...b!==void 0?{line:b}:{}})}let C=k.endsWith(`
|
|
27
27
|
`)?`
|
|
28
28
|
`:`
|
|
29
29
|
|
|
30
|
-
`;return await
|
|
31
|
-
`,"latin1")),{installed:!1,updated:!0,hooksDir:o}}function
|
|
32
|
-
`),n=new RegExp(`${
|
|
30
|
+
`;return await kt(h.path,Buffer.from(`${k}${C}${d}
|
|
31
|
+
`,"latin1")),{installed:!1,updated:!0,hooksDir:o}}function Mu(e){if(!e||!e.reason||e.reason==="not-a-repo")return null;let t=e.configured??"",r=e.hook??"hook",n=r==="pre-commit"?`copy the block from ${M(O,"hooks","pre-commit")} into it yourself.`:"Add a call to `vespercli guard` to it yourself.",s=`${n[0].toUpperCase()}${n.slice(1)}`;switch(e.reason){case"not-a-directory":return e.defaultDir?`Git hooks not installed: git's hooks directory "${t}" is not a directory.`:`Git hooks not installed: core.hooksPath is "${t}", which is not a directory (hooks disabled for this repository).`;case"machine-wide":return`Git hooks not installed: core.hooksPath is set machine-wide (${e.scope}) \u2014 Vesper does not write shared hooks.`;case"outside-repository":return e.hooksDir?`Git hook ${r} not written: it resolves outside this repository (${t}) \u2014 Vesper does not write shared hooks.`:e.defaultDir?`Git hooks not installed: git's hooks directory "${t}" resolves outside this repository (a symlink) \u2014 Vesper does not write shared hooks.`:`Git hooks not installed: core.hooksPath points outside this repository ("${t}") \u2014 Vesper does not write shared hooks.`;case"unverifiable":return`Git hooks not installed: this git cannot report where core.hooksPath ("${t}") is set \u2014 Vesper does not write hooks it cannot scope.`;case"husky-v9":return"Git hooks not installed: husky v9 manages .husky/_ \u2014 to keep Vesper's bootstrap on checkout, add `vespercli guard` to .husky/post-checkout.";case"dangling-symlink":return`Git hook ${r} left untouched: ${t||r} is a symlink whose target does not exist.`;case"write-refused":return`Git hook ${r} not written: its real location (${t||r}) is a user-level path Vesper never writes.`;case"opted-out":return"Git hooks not installed: disabled for this repository (git config vesper.hooks false).";case"tracked-by-git":return`Git hooks not installed: ${t} is committed to this repository (team-managed hooks) \u2014 Vesper does not edit tracked hooks; add \`vespercli guard\` to its post-checkout yourself.`;case"foreign-hook-language":return e.interpreter==="binary"?`Git hook ${r} is a compiled executable \u2014 Vesper did not modify it (appending would break it). ${s}`:`Git hook ${r} is a ${e.interpreter} script \u2014 Vesper did not modify it. ${s}`;case"foreign-hook-exits":return r==="pre-commit"?`Git hook ${r} ends its run early (\`${e.line}\`) \u2014 Vesper did not modify it, because its block would never run. To keep it, ${n}`:`Git hook ${r} ends its run early (\`${e.line}\`) \u2014 Vesper did not modify it, because its block would never run. Add \`vespercli guard >/dev/null 2>&1 || true\` before that line yourself.`;case"foreign-hook-repaired":return`Git hook ${r} is a ${e.interpreter} ${e.interpreter==="binary"?"executable":"script"}: Vesper's block, added by an earlier version, was removed from it (it broke the hook). ${r==="pre-commit"?`To keep it, ${n}`:"Add `vespercli guard` yourself."}`;default:return`Git hooks not installed (${e.reason}).`}}function rs(e){let t=[];for(let r of lt){let n=e?.[r];if(!n)continue;let s=Mu({...n,hook:n.hook??r});s&&!t.includes(s)&&t.push(s)}return t}function Ga(e){return lt.every(t=>e?.[t]&&!e[t].reason)}async function ns(e){let t={};if(await D(["config","--type=bool","--get","vesper.hooks"],{cwd:e})==="false"){for(let s of lt)t[s]={installed:!1,updated:!1,hooksDir:null,reason:"opted-out"};return t}let r=await or(e),n=!!r.dir&&!r.default&&await nr(await ct(r.dir),r,{dir:!0});for(let s of lt)t[s]=await Lu(e,s,{resolved:r,dirTracked:n});return t}async function ss(e){if(await D(["rev-parse","--is-inside-work-tree"],{cwd:e})!=="true")return{created:!1,updated:!1,skipped:"not-a-repo"};let t=M(e,".gitattributes"),r=[Au,...hy,_u].join(`
|
|
32
|
+
`),n=new RegExp(`${Au}[\\s\\S]*?${_u}`),s="";try{s=await Ke(t,"utf-8")}catch(i){if(i.code!=="ENOENT")throw i;return await A(t,`${r}
|
|
33
33
|
`,"utf-8"),{created:!0,updated:!1}}if(n.test(s)){let i=s.replace(n,r);return i!==s?(await A(t,i,"utf-8"),{created:!1,updated:!0}):{created:!1,updated:!1}}let o=s.endsWith(`
|
|
34
34
|
`)?`
|
|
35
35
|
`:`
|
|
36
36
|
|
|
37
37
|
`;return await A(t,`${s}${o}${r}
|
|
38
|
-
`,"utf-8"),{created:!1,updated:!0}}async function ns(e){if(await D(["rev-parse","--is-inside-work-tree"],{cwd:e})!=="true")return{configured:!1};let n=`node "${M(O,"hooks","merge-memory-jsonl.js")}" %O %A %B`;return await D(["config","merge.vesper-memory.name","Vesper memory.jsonl entity-aware merge"],{cwd:e}),{configured:await D(["config","merge.vesper-memory.driver",n],{cwd:e})!==null}}function Xe(e){return M(e,".vscode","mcp.json")}function We(){return M(Nn,"src","mcp","vesper-indexing","dist","index.js")}async function Qe(e){let t=Xe(e);try{let r=await Ue(t,"utf-8");return Lt(r)}catch(r){if(r.code==="ENOENT")return{servers:{}};if(r instanceof SyntaxError)return{servers:{}};throw r}}async function La(e,t){let r=Xe(e),n=vt(r);await P(n,{recursive:!0}),await A(r,JSON.stringify(t,null," "),"utf-8")}async function xr(e,t=!0,{record:r=!0}={}){let n=await Qe(e),s=er(We()),o=[];if(n.servers||(n.servers={}),t?(n.servers["vesper-indexing"]={type:"stdio",command:"node",args:[s],env:{VESPER_INDEX_ROOT:"${workspaceFolder}"}},o.push("vesper-indexing"),n.servers["sequential-thinking"]={type:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-sequential-thinking"]},o.push("sequential-thinking"),n.servers.memory={type:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-memory"],env:{MEMORY_FILE_PATH:"${workspaceFolder}/.vesper/memory.jsonl"}},o.push("memory")):(delete n.servers["vesper-indexing"],delete n.servers["sequential-thinking"],delete n.servers.memory),await La(e,n),r&&t&&o.length>0){let i=await x(e);i.mcp=i.mcp||{},i.mcp.servers=[...new Set([...Array.isArray(i.mcp.servers)?i.mcp.servers:[],...o])],i.mcp.updatedAt=new Date().toISOString(),await T(e,i)}return{configured:t,mcpPath:Xe(e),servers:o}}async function No(e){return!!(await Qe(e)).servers?.["vesper-indexing"]}async function Lo(e){let t=await q(e),r=await K(e);r[Jr]=!1,r[V]||(r[V]={});for(let n of je)r[V][n]=!0;return await ce(e,r),{configured:je.length,workspaceType:t.type}}async function Ru(e,t){let r=So[t];if(!r||r.length===0)return{added:[],agentName:t};let n=await K(e),s=await q(e),o=await x(e,s);n[V]||(n[V]={});let i=[];for(let a of r)n[V][a]||(n[V][a]=!0,i.push(a));return i.length>0&&(await ce(e,n),o.mcp=o.mcp||{},o.mcp.agentTools=o.mcp.agentTools||{},o.mcp.agentTools[t]=r,o.mcp.updatedAt=new Date().toISOString(),await T(e,o)),{added:i,agentName:t}}async function sr(e,t){let r=we[t];if(!r)return{added:!1,serverName:t,tools:[],error:`Unknown MCP server: ${t}`};let n=await Qe(e),s=await K(e),o=await q(e),i=await x(e,o);if(n.servers||(n.servers={}),n.servers[t])return{added:!1,serverName:t,tools:[],error:"Already configured"};let a=JSON.parse(JSON.stringify(r.config));if(t==="vesper-indexing"){let l=er(We());a.args&&(a.args=a.args.map(d=>d==="${VESPER_INDEXING_PATH}"?l:d))}n.servers[t]=a,await La(e,n),s[V]||(s[V]={});let c=[];for(let l of r.tools||[])s[V][l]||(s[V][l]=!0,c.push(l));return s[Jr]=!1,await ce(e,s),i.mcp=i.mcp||{},i.mcp.servers=i.mcp.servers||[],i.mcp.servers.includes(t)||i.mcp.servers.push(t),i.mcp.updatedAt=new Date().toISOString(),await T(e,i),{added:!0,serverName:t,tools:c}}async function rn(e,t){let r=we[t],n=await Qe(e),s=await K(e),o=await q(e),i=await x(e,o),a=!1;n.servers&&n.servers[t]&&(delete n.servers[t],await La(e,n),a=!0);let c=[];if(r&&s[V]){for(let l of r.tools||[])s[V][l]&&(delete s[V][l],c.push(l));c.length>0&&await ce(e,s)}return i.mcp?.servers&&(i.mcp.servers=i.mcp.servers.filter(l=>l!==t),i.mcp.updatedAt=new Date().toISOString(),await T(e,i)),{removed:a,serverName:t,tools:c}}function Nu(){return Object.entries(we).map(([e,t])=>({name:e,description:t.description,tools:t.tools?.length||0}))}async function Mo(e){let t=await Qe(e);return Object.keys(t.servers||{})}var Ca,He,Rt,uo,Jr,V,po,fo,ho,mo,go,yo,wo,oe,Ie,Nt,me,$a,Un,Ta,Pa,qg,yu,wu,vo,Jn,Wn,je,So,we,xu,he,vu,Zg,ty,ry,Kn,co,lo,en,ao,at,Su,Eu,iy,ay,H=Z(()=>{Wr();U();Te();Ee();ot();fe();Wr();Ca=1e4;He={agents:"chat.agentFilesLocations",instructions:"chat.instructionsFilesLocations",prompts:"chat.promptFilesLocations",skills:"chat.agentSkillsLocations"},Rt="chat.tools.terminal.autoApprove",uo="chat.tools.terminal.enableAutoApprove",Jr="chat.tools.autoApprove",V="chat.tools.eligibleForAutoApproval",po="chat.agent.maxRequests",fo="chat.includeReferencedInstructions",ho="chat.customAgentInSubagent.enabled",mo="chat.agent.enabled",go="github.copilot.chat.omitBaseAgentInstructions",yo="chat.mcp.discovery.enabled",wo="chat.mcp.autoStart",oe="github.copilot.chat.additionalReadAccessPaths",Ie={maxRequests:300,terminalEnableAutoApprove:!0,omitBaseAgentInstructions:!0,enableMcpServer:!0},Nt=[po,fo,ho,mo,go,yo,wo,uo,Rt,Jr,V],me=["vesper-indexing","sequential-thinking","memory"],$a=Object.freeze([Object.freeze({path:".vesperrc"}),Object.freeze({path:".vesperrc.*.tmp"}),Object.freeze({path:".vesperrc.corrupt-*"}),Object.freeze({path:".mcp.json"}),Object.freeze({path:".vscode/mcp.json"}),Object.freeze({path:".vesper/index.db"}),Object.freeze({path:".vesper/index.db-wal"}),Object.freeze({path:".vesper/index.db-shm"}),Object.freeze({path:".vesper/indexing-status.json"}),Object.freeze({path:".claude/settings.local.json"}),Object.freeze({path:".vesper/.host-switch-journal.json"}),Object.freeze({path:".vesper/.host-switch-journal.json.*.tmp"}),Object.freeze({path:".vesper/.migration-backup/"})]),Un=$a.map(e=>e.path);Ta=[".claude/skills",".claude/rules",".claude/agents",".claude/commands",".claude/CLAUDE.md",".claude/settings.json",".copilot/agents",".copilot/skills",".copilot/instructions"],Pa=[".claude/plugins",".vesperrc"];qg=[".claude/vesper/context",".claude/agents",".claude/commands",".claude/skills",".claude/rules",".vesper/skills",".vesper/instructions",".vesper/agents",".vesper/context",".vesper/.tracking",".vesper/memory.jsonl",".vesper/gates.json","CLAUDE.md","opencode.json",".opencode"],yu="# <!-- vesper:gitignore:start -->",wu="# <!-- vesper:gitignore:end -->";vo="Vesper: worktree bootstrap",Jn=Object.freeze({taskLabel:"Vesper: host guard",hookCommandMarker:"vespercli guard --running-host"});Wn=["react-scripts","**/node_modules/.bin/react-scripts","next","**/node_modules/.bin/next","vite","**/node_modules/.bin/vite","webpack","**/node_modules/.bin/webpack","turbo","**/node_modules/.bin/turbo","tsc","**/node_modules/.bin/tsc","tsup","**/node_modules/.bin/tsup","esbuild","**/node_modules/.bin/esbuild","rollup","**/node_modules/.bin/rollup","parcel","**/node_modules/.bin/parcel","jest","**/node_modules/.bin/jest","vitest","**/node_modules/.bin/vitest","npx vitest","pnpm vitest","pnpm vitest run","pnpm exec vitest","pnpm dlx vitest","mocha","**/node_modules/.bin/mocha","playwright","**/node_modules/.bin/playwright","npx playwright open","npx playwright test","npx playwright show-report","npx playwright codegen","open playwright","open playwright-report/index.html",'ps aux | grep "playwright test" | grep -v grep | wc -l',"cypress","**/node_modules/.bin/cypress","pytest","npx","pnpm dlx","pnpm exec","yarn dlx","npm test","npm run","npm start","npm run test","npm run build","npm run dev","npm run lint","pnpm test","pnpm run","pnpm start","pnpm tsc","yarn test","yarn run","yarn start","eslint","**/node_modules/.bin/eslint","pnpm eslint","prettier","**/node_modules/.bin/prettier","biome","**/node_modules/.bin/biome","stylelint","**/node_modules/.bin/stylelint","mkdir","touch","cat","ls","head","tail","wc","grep","find","tree","file","stat","realpath","basename","dirname","awk","sed","cut","sort","uniq","tr","xargs","column","paste","join","comm","diff","cmp","git status","git log","git diff","git branch","git show","git remote","git tag","git rev-parse","git describe","git ls-files","git ls-tree","git blame","git shortlog","pushd","popd","dirs","echo","pwd","which","type","env","printenv","date","hostname","whoami","uname","lsof","pkill","node --version","npm --version","pnpm --version","yarn --version","python --version","python3 --version","curl -I *","curl --head *","curl -sI *","curl -s http://localhost:*","curl -s http://127.0.0.1:*","curl -sf http://localhost:*","curl -sf http://127.0.0.1:*","curl --fail http://localhost:*","curl --fail http://127.0.0.1:*","tsx","**/node_modules/.bin/tsx","npx tsx","/^(\\w+=\\S+\\s+)+(npx|node|tsx|npm|pnpm|yarn)\\b/","vespercli","vespercli init","vespercli add","vespercli list","vespercli ls","vespercli reset","vespercli catalog","**/node_modules/.bin/vespercli","mcp: vesper-indexing: vesper_search","mcp: vesper-indexing: vesper_symbols","mcp: vesper-indexing: vesper_status","mcp: vesper-indexing: vesper_reindex","python3 << 'PYEOF'",'python3 << "PYEOF"',"python3 << 'EOF'",'python3 << "EOF"',"python3 << 'END'","python << 'PYEOF'",'python << "PYEOF"',"python << 'EOF'","cat << 'EOF'",'cat << "EOF"',"cat << 'END'","bash << 'EOF'","sh << 'EOF'","cat << 'RESEARCH_EOF'",'cat << "RESEARCH_EOF"',"RESEARCH_EOF","tee","node -e","python3 -c","python -c"],je=["vesper_search","vesper_symbols","vesper_status","vesper_reindex","resolve-library-id","get-library-docs","query-docs","sequentialthinking","create_entities","create_relations","add_observations","delete_entities","delete_observations","delete_relations","read_graph","search_nodes","open_nodes"],So={"clickup-agent":["clickup_add_tag_to_task","clickup_add_time_entry","clickup_attach_task_file","clickup_create_document","clickup_create_document_page","clickup_create_folder","clickup_create_list","clickup_create_list_in_folder","clickup_create_task","clickup_create_task_comment","clickup_find_member_by_name","clickup_get_chat_channels","clickup_get_current_time_entry","clickup_get_document_pages","clickup_get_folder","clickup_get_list","clickup_get_task","clickup_get_task_comments","clickup_get_task_time_entries","clickup_get_workspace_hierarchy","clickup_get_workspace_members","clickup_list_document_pages","clickup_remove_tag_from_task","clickup_resolve_assignees","clickup_search","clickup_send_chat_message","clickup_start_time_tracking","clickup_stop_time_tracking","clickup_update_document_page","clickup_update_folder","clickup_update_list","clickup_update_task"]},we={"vesper-indexing":{description:"Fast code search with semantic indexing",config:{type:"stdio",command:"node",args:["${VESPER_INDEXING_PATH}"],env:{VESPER_INDEX_ROOT:"${workspaceFolder}"}},tools:["vesper_search","vesper_symbols","vesper_status","vesper_reindex"]},context7:{description:"Documentation lookup for libraries",config:{type:"stdio",command:"npx",args:["-y","@upstash/context7-mcp"]},tools:["resolve-library-id","get-library-docs","query-docs"]},"sequential-thinking":{description:"Step-by-step reasoning for complex problems",config:{type:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-sequential-thinking"]},tools:["sequentialthinking"]},clickup:{description:"ClickUp project management integration",config:{type:"stdio",command:"npx",args:["-y","@anthropics/mcp-clickup"],env:{CLICKUP_API_KEY:"${env:CLICKUP_API_KEY}",CLICKUP_TEAM_ID:"${env:CLICKUP_TEAM_ID}"}},tools:["clickup_add_tag_to_task","clickup_add_time_entry","clickup_attach_task_file","clickup_create_document","clickup_create_document_page","clickup_create_folder","clickup_create_list","clickup_create_list_in_folder","clickup_create_task","clickup_create_task_comment","clickup_find_member_by_name","clickup_get_chat_channels","clickup_get_current_time_entry","clickup_get_document_pages","clickup_get_folder","clickup_get_list","clickup_get_task","clickup_get_task_comments","clickup_get_task_time_entries","clickup_get_workspace_hierarchy","clickup_get_workspace_members","clickup_list_document_pages","clickup_remove_tag_from_task","clickup_resolve_assignees","clickup_search","clickup_send_chat_message","clickup_start_time_tracking","clickup_stop_time_tracking","clickup_update_document_page","clickup_update_folder","clickup_update_list","clickup_update_task"]},memory:{description:"Persistent knowledge graph memory for AI agents",config:{type:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-memory"],env:{MEMORY_FILE_PATH:"${workspaceFolder}/.vesper/memory.jsonl"}},tools:["create_entities","create_relations","add_observations","delete_entities","delete_observations","delete_relations","read_graph","search_nodes","open_nodes"]},graphify:{description:"Code knowledge graph (graphify, opt-in pack) \u2014 impact, path and architecture queries",config:{type:"stdio",command:"vespercli",args:["mcp","serve","graphify"]},tools:["query_graph","get_node","get_neighbors","shortest_path","get_pr_impact"]}},xu=je,he={FOLDER:"folder",WORKSPACE_FILE:"workspace"};vu=new Set;Zg=new Set([Rt,Jr,V]);ty=Ot,ry=["agents","prompts","skills"],Kn=M(O,"copilot","instructions"),co=M(O,"copilot","instructions-extended");lo=M(Ot,"packs");en=Object.freeze(["-c","core.fsmonitor=false","-c","core.untrackedCache=false"]),ao=null;at=["pre-commit","post-checkout"];Su="# <!-- vesper:gitattributes:start -->",Eu="# <!-- vesper:gitattributes:end -->",iy=[".vesper/memory.jsonl merge=vesper-memory",".claude/vesper/context/recent-decisions.md merge=union",".vesper/context/recent-decisions.md merge=union"];ay={VSCODE_SETTINGS_MAP:He,WORKSPACE_TYPES:he,TERMINAL_AUTO_APPROVAL_SETTING:Rt,TERMINAL_ENABLE_AUTO_APPROVAL_SETTING:uo,TOOLS_AUTO_APPROVE_SETTING:Jr,TOOLS_ELIGIBLE_FOR_AUTO_APPROVAL_SETTING:V,AGENT_MAX_REQUESTS_SETTING:po,INCLUDE_REFERENCED_INSTRUCTIONS_SETTING:fo,CUSTOM_AGENT_IN_SUBAGENT_SETTING:ho,CHAT_AGENT_ENABLED_SETTING:mo,OMIT_BASE_AGENT_INSTRUCTIONS_SETTING:go,MCP_DISCOVERY_ENABLED_SETTING:yo,MCP_AUTO_START_SETTING:wo,ADDITIONAL_READ_ACCESS_PATHS_SETTING:oe,SAFE_AUTO_APPROVAL_COMMANDS:Wn,MCP_TOOLS_CORE:je,MCP_TOOLS_BY_AGENT:So,MCP_SERVERS:we,MCP_TOOLS_AUTO_APPROVAL:xu,INIT_DEFAULTS:Ie,VESPER_MANAGED_SETTINGS:Nt,VESPER_MANAGED_MCP_SERVERS:me,findWorkspaceFile:Ia,getWorkspaceConfig:q,getSettingsPath:Au,getTrackingPath:Xr,getTrackingPathAsync:kt,readVSCodeSettings:K,writeVSCodeSettings:ce,readTracking:x,writeTracking:T,removeLegacyTracking:Cu,addToSettings:Qr,removeFromSettings:Zn,getCoreAssetEntries:Ao,pruneLegacySettingsEntries:Zr,listExtendedInstructions:bo,getExtendedInstructionEntry:xo,getTrackedPaths:St,configureTerminalAutoApproval:Co,configureChatSettings:$o,getAutoApprovalCommands:Tu,addReadAccessPath:Oo,removeReadAccessPath:To,getReadAccessPaths:Po,getMcpConfigPath:Xe,getVesperIndexingPath:We,readMcpConfig:Qe,configureMcpServer:xr,isMcpServerConfigured:No,configureMcpToolsAutoApproval:Lo,addAgentToolsToAutoApproval:Ru,addMcpServer:sr,removeMcpServer:rn,listMcpServers:Nu,getConfiguredMcpServers:Mo,getWorkspaceFolders:ja,findNestedVesperrc:Qn,migrateVesperrcToWorkspaceLevel:Eo,ensureCoreSettings:Io}});import{access as cy,constants as ly,stat as Kx,lstat as uy,readdir as dy,readFile as py,readlink as fy,rename as hy,writeFile as my,mkdir as gy,cp as yy,appendFile as Lu}from"node:fs/promises";import{createHash as wy}from"node:crypto";import{isAbsolute as vy,join as ky,relative as Sy,resolve as Fo,sep as Ey}from"node:path";function Ga(e){Fa=e?{root:Fo(e.root),log:e.log,exclude:e.exclude||(()=>!1)}:null}async function Mu(e,t,r){let n=await uy(e);if(n.isSymbolicLink())r.push([t,`link:${await fy(e)}`]);else if(n.isDirectory())for(let s of await dy(e))await Mu(ky(e,s),`${t}/${s}`,r);else n.isFile()&&r.push([t,wy("sha256").update(await py(e)).digest("hex")])}function Fu(e,t){let r=Fo(t),n=Sy(e.root,r);if(!n||n.startsWith("..")||vy(n))return null;let s=n.split(Ey).join("/");return e.exclude(s)?null:s}async function Da(e){let t=Fa;if(t)try{let r=Fu(t,e);r&&await Lu(t.log,`${JSON.stringify([r,ss])}
|
|
39
|
-
`,"utf-8")}catch{}}async function
|
|
40
|
-
`).join("");o&&await
|
|
41
|
-
`);return`sha256:${
|
|
42
|
-
`);return`sha256:${Hy("sha256").update(t,"utf8").digest("hex")}`}async function ye(e){try{return us(await rd(e,"utf-8"))}catch{return null}}function F({path:e,host:t,category:r,hash:n=null}){if(Wy.has(r)&&!n)throw new Error(`wholeFileEntry: category "${r}" is content-hash verified but was given a null/empty hash for "${e}". Provide a hash (from hashFile) or use an existence-checked category \u2014 a content-hash entry without a hash is never verified.`);return{path:e,host:t,category:r,hash:n}}function Y({path:e,host:t,category:r,owns:n}){return{path:e,host:t,category:r,owns:n||{}}}async function sn(e){return(await B(e)).host}async function sd(e,t){if(!z.includes(t))throw new Error(`Invalid host "${t}". Vesper 2.0 provisions exactly one of: ${z.join(", ")}.`);let r=await x(e);return r.schemaVersion=ve,r.host=t,await T(e,r),t}async function Uo(e,t){return(await x(e))[t]}async function Ky(e,t,r){let n=await x(e);return n[t]=r,await T(e,n),r}async function id(e){return await Uo(e,za)===Ya}function ad(e){return Ky(e,za,Ya)}async function cd(e,t){let r=await x(e);if(r[za]===Ya)return[];let n=J(r),s=[],o=n.filter(i=>{let a=i.host===t&&i.category!=="added-asset"&&Gt[i.category]?.ownership==="whole-file";return a&&s.push(i.path),!a});return s.length===0?[]:(r.manifest=o,await T(e,r),s)}function ls(e){return e&&typeof e.path=="string"&&typeof e.host=="string"&&typeof e.category=="string"}async function ne(e){let t=await x(e);return J(t)}function J(e){let t=e?.manifest;return Array.isArray(t)?t.filter(ls):[]}function et(e){return[...e].sort((t,r)=>String(t.path).localeCompare(String(r.path))||String(t.host).localeCompare(String(r.host)))}function Ja(e,t){let r=[...e];for(let n of t){if(!ls(n))continue;let s=r.findIndex(o=>o.path===n.path&&o.host===n.host);s===-1?r.push(n):r[s]=n}return r}async function W(e,t){let r=await x(e);return r.schemaVersion=ve,r.manifest=et(Ja(J(r),t||[])),await T(e,r),r.manifest}function By(e){return typeof e=="string"&&e.length>0&&!e.includes("..")&&!e.startsWith("/")}function Ko(e,{host:t,keep:r,purgeProjectAuthored:n=!1}={}){return!e||typeof e.path!="string"||e.host==="shared"||Re.has(e.category)&&!n||t&&e.host!==t||Gt[e.category]?.ownership!=="whole-file"||r&&r.has(e.path)?!1:By(e.path)}async function an(e,t,{prune:r=!0,categories:n}={}){let s=await ne(e),o=(t||[]).filter(ls),i=new Set(n||o.map(h=>h.category)),a=new Set(o.map(h=>h.host)),c=h=>i.has(h.category)&&(a.size===0||a.has(h.host)),l=new Set(o.map(h=>h.path)),d=[],p=[];if(r)for(let h of s){if(!c(h)||!Ko(h,{keep:l}))continue;let g=nn(e,h.path);if(await w(g)){let y=await le(g,h);(y==="kept"||y==="partial")&&p.push(h.path),y!=="kept"&&d.push(h.path)}}let f=s.filter(h=>!c(h)),m=await x(e);return m.schemaVersion=ve,m.manifest=et(Ja(f,o)),await T(e,m),{pruned:d,kept:p,manifest:m.manifest}}async function ld(e,t,{host:r,purgeProjectAuthored:n=!1}={}){let s=new Set(t||[]),o=await ne(e),i=[],a=[],c=[],l=p=>p.category==="per-project-authored"&&o.some(f=>f&&f.path===p.path&&f.host!==p.host&&f.category==="per-project-authored");for(let p of o){if(Ko(p,{host:r,keep:s,purgeProjectAuthored:n})){let f=nn(e,p.path);if(l(p)){i.push(p.path);continue}if(await w(f)){let m=await le(f,p,{purgeProjectAuthored:n});(m==="kept"||m==="partial")&&a.push(p.path)}i.push(p.path);continue}c.push(p)}let d=await x(e);return d.manifest=et(c),await T(e,d),{pruned:i,kept:a,manifest:d.manifest}}async function ud(e){let t=await ne(e),r={missing:[],modified:[],clean:[],userLevelViolations:[]};for(let n of t){let s=Uy(n.path)?n.path:nn(e,n.path);br(s)&&r.userLevelViolations.push(n);let o=Gt[n.category]||{doctor:"existence"},i=await w(s);if(o.doctor==="content-hash"){if(!i){r.missing.push(n);continue}let a=await ye(s);n.hash&&a&&a!==n.hash?r.modified.push(n):r.clean.push(n);continue}if(o.doctor==="server-drift"){if(!i){r.missing.push(n);continue}let a=n.owns?.keys||[],c=await Ba(s),l=a.every(d=>c.includes(d));a.length&&!l?r.modified.push(n):r.clean.push(n);continue}i?r.clean.push(n):r.missing.push(n)}return r}async function Ba(e){try{let t=JSON.parse(await rd(e,"utf-8"));return Object.keys(t.mcpServers||t.servers||{})}catch{return[]}}async function td(e){try{return(await nd(e,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".md")).map(r=>r.name)}catch{return[]}}async function zy(e){try{return(await nd(e,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>r.name)}catch{return[]}}async function qa(e,t,{settingsEntries:r,hooksDir:n,hookNames:s,provisionedSkillNames:o,provisionedInstructionNames:i}={}){let a=[],c=d=>nn(e,d),l=async(d,p)=>{a.push(F({path:d,host:t,category:p,hash:await ye(c(d))}))};if(t==="claude"){for(let p of await td(c(".claude/agents")))await l(`.claude/agents/${p}`,"catalog-agent");for(let p of await td(c(".claude/commands")))await l(`.claude/commands/${p}`,"catalog-command");let d=new Set(o||[]);for(let p of await zy(c(".claude/skills")))d.has(p)&&a.push(F({path:`.claude/skills/${p}`,host:t,category:"catalog-skill",hash:null}));await w(c(".claude/vesper/orchestrator.md"))&&await l(".claude/vesper/orchestrator.md","playbook");for(let p of[".claude/vesper/orchestration.md",".claude/vesper/context.md"])await w(c(p))&&a.push(F({path:p,host:t,category:"per-project-authored",hash:null}));await w(c("CLAUDE.md"))&&a.push(Y({path:"CLAUDE.md",host:t,category:"pointer",owns:{region:"vesper"}})),await w(c(".mcp.json"))&&a.push(Y({path:".mcp.json",host:t,category:"mcp-config",owns:{keys:await Ba(c(".mcp.json"))}})),await w(c(".claude/settings.json"))&&a.push(Y({path:".claude/settings.json",host:t,category:"settings",owns:{keys:["permissions.allow","hooks.SessionStart","hooks.SubagentStart"]}}))}if(t==="copilot"&&(await w(c(".vscode/settings.json"))&&a.push(Y({path:".vscode/settings.json",host:t,category:"settings",owns:{keys:[...Nt],entries:r?[...r]:[]}})),await w(c(".vscode/mcp.json"))&&a.push(Y({path:".vscode/mcp.json",host:t,category:"mcp-config",owns:{keys:await Ba(c(".vscode/mcp.json"))}})),await w(c(".vscode/tasks.json"))&&a.push(Y({path:".vscode/tasks.json",host:t,category:"bootstrap-task",owns:{keys:["Vesper: worktree bootstrap"]}}))),await w(c(".gitignore"))&&a.push(Y({path:".gitignore",host:"shared",category:"gitignore",owns:{region:"vesper:gitignore"}})),n)for(let d of Array.isArray(s)?s:["pre-commit","post-checkout"]){let p=nn(n,d);await w(p)&&a.push(Y({path:p,host:"shared",category:"hook",owns:{region:"vesper:hook"}}))}return a}function Xa(e){return(e||[]).filter(t=>t&&t.host==="shared")}function Yy(e){let t=!1;for(let r of ds)r in e&&(delete e[r],t=!0);return t}async function dd(e){!await w(nn(e,".vesperrc"))||(await x(e)).schemaVersion!==ve||await cn(e)}async function cn(e,{frameworkVersion:t,legacyEntries:r=[],host:n}={}){let s=await x(e);if(s.schemaVersion===ve){let h=!1;if("host"in s&&!z.includes(s.host)&&(delete s.host,h=!0),!Array.isArray(s.manifest))s.manifest=[],h=!0;else{let g=s.manifest.filter(ls);g.length!==s.manifest.length&&(s.manifest=g,h=!0)}return Yy(s)&&(h=!0),h&&await T(e,s),s}let o=(z.includes(n)?n:null)||Bn(s)||(await B(e)).host,i=o==="both"?null:o,a=s.claude?.namePrefix??s.namePrefix,c=s.claude?.pluginPath??s.pluginPath,l=Array.isArray(s.paths)?[...s.paths]:[],d=await qa(e,i,{settingsEntries:l}),p=et(Ja(Xa(d),(r||[]).filter(ls))),f={schemaVersion:ve,host:i||void 0,frameworkVersion:t??s.frameworkVersion,manifest:p};a!==void 0&&(f.namePrefix=a),c!==void 0&&(f.pluginPath=c),s.vendored!==void 0&&(f.vendored=s.vendored),s.mcp!==void 0&&(f.mcp=s.mcp),s.readAccessPaths!==void 0&&(f.readAccessPaths=s.readAccessPaths);let m=new Set([...ds,"schemaVersion","host","frameworkVersion","manifest","namePrefix","pluginPath","vendored","mcp","readAccessPaths"]);for(let[h,g]of Object.entries(s))m.has(h)||(f[h]=g);return await T(e,f),f}async function Tr(e,t){let r=await x(e);return!!(J(r).some(s=>s.host===t&&!Re.has(s.category))||t==="claude"&&r.claude||t==="copilot"&&Array.isArray(r.paths)&&r.paths.length>0)}async function Et(e){let t=await x(e),n=J(t).find(s=>s.path===".vscode/settings.json"&&s.category==="settings");return n&&Array.isArray(n.owns?.entries)&&n.owns.entries.length?[...n.owns.entries]:Array.isArray(t.paths)?[...t.paths]:[]}var ve,z,Ze,Ho,Gt,Wy,Wo,on,od,za,Ya,Re,ds,te=Z(()=>{H();U();Be();be();fe();ve=2,z=["claude","copilot"],Ze="This workspace carries both Copilot and Claude targets from a pre-2.0 install. Vesper 2.0 uses a single host per workspace \u2014 run `vespercli init --host <claude|copilot>` to choose one, or pass an explicit `--target claude|copilot`.",Ho="This workspace carries both Copilot and Claude targets from a pre-2.0 install. Vesper 2.0 uses a single host per workspace \u2014 run `vespercli init --host <claude|copilot>` to choose one, or `vespercli reset --host <claude|copilot>` to remove one host's artifacts.",Gt={"catalog-agent":{ownership:"whole-file",doctor:"content-hash"},"catalog-command":{ownership:"whole-file",doctor:"content-hash"},"catalog-skill":{ownership:"whole-file",doctor:"existence"},playbook:{ownership:"whole-file",doctor:"content-hash"},"pack-rule":{ownership:"whole-file",doctor:"existence"},"vendored-body":{ownership:"whole-file",doctor:"existence"},"vendored-activation":{ownership:"whole-file",doctor:"content-hash"},"per-project-authored":{ownership:"whole-file",doctor:"existence"},"mcp-config":{ownership:"key",doctor:"server-drift"},settings:{ownership:"key",doctor:"key-presence"},pointer:{ownership:"region",doctor:"region-presence"},hook:{ownership:"region",doctor:"region-presence"},gitignore:{ownership:"region",doctor:"region-presence"},"bootstrap-task":{ownership:"key",doctor:"key-presence"},"guard-trigger":{ownership:"key",doctor:"key-presence"},"added-asset":{ownership:"whole-file",doctor:"existence"},"opencode-agent":{ownership:"whole-file",doctor:"existence"},"opencode-overlay":{ownership:"whole-file",doctor:"existence"},"opencode-config":{ownership:"key",doctor:"key-presence"}},Wy=new Set(Object.entries(Gt).filter(([,e])=>e.doctor==="content-hash").map(([e])=>e));Wo=e=>Uo(e,"frameworkVersion"),on=async e=>await Uo(e,"namePrefix")??"",od=e=>Uo(e,"pluginPath"),za="manifestProvenance",Ya="granular";Re=new Set(["per-project-authored"]);ds=Object.freeze(["paths","claude","addedAt","workspaceType","settingsPath","updatedAt","catalogVersion","targets"])});import{readdir as Qa}from"node:fs/promises";import{join as ps}from"node:path";function hd(e){let t=[],r=null;return{text:String(e||"").split(`
|
|
43
|
-
`).filter(s=>{if(!/^\s*\|/.test(s))return r=null,!0;let o=
|
|
44
|
-
`),removed:t}}function
|
|
45
|
-
`).map(s=>{if(!/^\s*\|/.test(s))return n=null,s;let o=
|
|
46
|
-
`)}function
|
|
38
|
+
`,"utf-8"),{created:!1,updated:!0}}async function os(e){if(await D(["rev-parse","--is-inside-work-tree"],{cwd:e})!=="true")return{configured:!1};let n=`node "${M(O,"hooks","merge-memory-jsonl.js")}" %O %A %B`;return await D(["config","merge.vesper-memory.name","Vesper memory.jsonl entity-aware merge"],{cwd:e}),{configured:await D(["config","merge.vesper-memory.driver",n],{cwd:e})!==null}}function Qe(e){return M(e,".vscode","mcp.json")}function Be(){return M(Mn,"src","mcp","vesper-indexing","dist","index.js")}async function Ze(e){let t=Qe(e);try{let r=await Ke(t,"utf-8");return Mt(r)}catch(r){if(r.code==="ENOENT")return{servers:{}};if(r instanceof SyntaxError)return{servers:{}};throw r}}async function Fa(e,t){let r=Qe(e),n=Et(r);await P(n,{recursive:!0}),await A(r,JSON.stringify(t,null," "),"utf-8")}async function _r(e,t=!0,{record:r=!0}={}){let n=await Ze(e),s=rr(Be()),o=[];if(n.servers||(n.servers={}),t?(n.servers["vesper-indexing"]={type:"stdio",command:"node",args:[s],env:{VESPER_INDEX_ROOT:"${workspaceFolder}"}},o.push("vesper-indexing"),n.servers["sequential-thinking"]={type:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-sequential-thinking"]},o.push("sequential-thinking"),n.servers.memory={type:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-memory"],env:{MEMORY_FILE_PATH:"${workspaceFolder}/.vesper/memory.jsonl"}},o.push("memory")):(delete n.servers["vesper-indexing"],delete n.servers["sequential-thinking"],delete n.servers.memory),await Fa(e,n),r&&t&&o.length>0){let i=await x(e);i.mcp=i.mcp||{},i.mcp.servers=[...new Set([...Array.isArray(i.mcp.servers)?i.mcp.servers:[],...o])],i.mcp.updatedAt=new Date().toISOString(),await T(e,i)}return{configured:t,mcpPath:Qe(e),servers:o}}async function Go(e){return!!(await Ze(e)).servers?.["vesper-indexing"]}async function Fo(e){let t=await q(e),r=await K(e);r[qr]=!1,r[V]||(r[V]={});for(let n of Ne)r[V][n]=!0;return await ce(e,r),{configured:Ne.length,workspaceType:t.type}}async function Gu(e,t){let r=xo[t];if(!r||r.length===0)return{added:[],agentName:t};let n=await K(e),s=await q(e),o=await x(e,s);n[V]||(n[V]={});let i=[];for(let a of r)n[V][a]||(n[V][a]=!0,i.push(a));return i.length>0&&(await ce(e,n),o.mcp=o.mcp||{},o.mcp.agentTools=o.mcp.agentTools||{},o.mcp.agentTools[t]=r,o.mcp.updatedAt=new Date().toISOString(),await T(e,o)),{added:i,agentName:t}}async function ir(e,t){let r=we[t];if(!r)return{added:!1,serverName:t,tools:[],error:`Unknown MCP server: ${t}`};let n=await Ze(e),s=await K(e),o=await q(e),i=await x(e,o);if(n.servers||(n.servers={}),n.servers[t])return{added:!1,serverName:t,tools:[],error:"Already configured"};let a=JSON.parse(JSON.stringify(r.config));if(t==="vesper-indexing"){let l=rr(Be());a.args&&(a.args=a.args.map(d=>d==="${VESPER_INDEXING_PATH}"?l:d))}n.servers[t]=a,await Fa(e,n),s[V]||(s[V]={});let c=[];for(let l of r.tools||[])s[V][l]||(s[V][l]=!0,c.push(l));return s[qr]=!1,await ce(e,s),i.mcp=i.mcp||{},i.mcp.servers=i.mcp.servers||[],i.mcp.servers.includes(t)||i.mcp.servers.push(t),i.mcp.updatedAt=new Date().toISOString(),await T(e,i),{added:!0,serverName:t,tools:c}}async function nn(e,t){let r=we[t],n=await Ze(e),s=await K(e),o=await q(e),i=await x(e,o),a=!1;n.servers&&n.servers[t]&&(delete n.servers[t],await Fa(e,n),a=!0);let c=[];if(r&&s[V]){for(let l of r.tools||[])s[V][l]&&(delete s[V][l],c.push(l));c.length>0&&await ce(e,s)}return i.mcp?.servers&&(i.mcp.servers=i.mcp.servers.filter(l=>l!==t),i.mcp.updatedAt=new Date().toISOString(),await T(e,i)),{removed:a,serverName:t,tools:c}}function Fu(){return Object.entries(we).map(([e,t])=>({name:e,description:t.description,tools:t.tools?.length||0}))}async function Do(e){let t=await Ze(e);return Object.keys(t.servers||{})}var Ta,We,Nt,ho,qr,V,mo,go,yo,wo,vo,ko,So,oe,Re,Lt,me,Pa,Kn,ja,Ra,sy,Su,Eu,Eo,Xn,Bn,Ne,xo,we,$u,he,bu,ay,ly,uy,zn,po,fo,tn,uo,lt,Au,_u,hy,my,H=Z(()=>{Kr();U();Ie();xe();at();fe();Kr();Ta=1e4;We={agents:"chat.agentFilesLocations",instructions:"chat.instructionsFilesLocations",prompts:"chat.promptFilesLocations",skills:"chat.agentSkillsLocations"},Nt="chat.tools.terminal.autoApprove",ho="chat.tools.terminal.enableAutoApprove",qr="chat.tools.autoApprove",V="chat.tools.eligibleForAutoApproval",mo="chat.agent.maxRequests",go="chat.includeReferencedInstructions",yo="chat.customAgentInSubagent.enabled",wo="chat.agent.enabled",vo="github.copilot.chat.omitBaseAgentInstructions",ko="chat.mcp.discovery.enabled",So="chat.mcp.autoStart",oe="github.copilot.chat.additionalReadAccessPaths",Re={maxRequests:300,terminalEnableAutoApprove:!0,omitBaseAgentInstructions:!0,enableMcpServer:!0},Lt=[mo,go,yo,wo,vo,ko,So,ho,Nt,qr,V],me=["vesper-indexing","sequential-thinking","memory"],Pa=Object.freeze([Object.freeze({path:".vesperrc"}),Object.freeze({path:".vesperrc.*.tmp"}),Object.freeze({path:".vesperrc.corrupt-*"}),Object.freeze({path:".mcp.json"}),Object.freeze({path:".vscode/mcp.json"}),Object.freeze({path:".vesper/index.db"}),Object.freeze({path:".vesper/index.db-wal"}),Object.freeze({path:".vesper/index.db-shm"}),Object.freeze({path:".vesper/indexing-status.json"}),Object.freeze({path:".claude/settings.local.json"}),Object.freeze({path:".vesper/.host-switch-journal.json"}),Object.freeze({path:".vesper/.host-switch-journal.json.*.tmp"}),Object.freeze({path:".vesper/.migration-backup/"})]),Kn=Pa.map(e=>e.path);ja=[".claude/skills",".claude/rules",".claude/agents",".claude/commands",".claude/CLAUDE.md",".claude/settings.json",".copilot/agents",".copilot/skills",".copilot/instructions"],Ra=[".claude/plugins",".vesperrc"];sy=[".claude/vesper/context",".claude/agents",".claude/commands",".claude/skills",".claude/rules",".vesper/skills",".vesper/instructions",".vesper/agents",".vesper/context",".vesper/.tracking",".vesper/memory.jsonl",".vesper/gates.json","CLAUDE.md","opencode.json",".opencode"],Su="# <!-- vesper:gitignore:start -->",Eu="# <!-- vesper:gitignore:end -->";Eo="Vesper: worktree bootstrap",Xn=Object.freeze({taskLabel:"Vesper: host guard",hookCommandMarker:"vespercli guard --running-host"});Bn=["react-scripts","**/node_modules/.bin/react-scripts","next","**/node_modules/.bin/next","vite","**/node_modules/.bin/vite","webpack","**/node_modules/.bin/webpack","turbo","**/node_modules/.bin/turbo","tsc","**/node_modules/.bin/tsc","tsup","**/node_modules/.bin/tsup","esbuild","**/node_modules/.bin/esbuild","rollup","**/node_modules/.bin/rollup","parcel","**/node_modules/.bin/parcel","jest","**/node_modules/.bin/jest","vitest","**/node_modules/.bin/vitest","npx vitest","pnpm vitest","pnpm vitest run","pnpm exec vitest","pnpm dlx vitest","mocha","**/node_modules/.bin/mocha","playwright","**/node_modules/.bin/playwright","npx playwright open","npx playwright test","npx playwright show-report","npx playwright codegen","open playwright","open playwright-report/index.html",'ps aux | grep "playwright test" | grep -v grep | wc -l',"cypress","**/node_modules/.bin/cypress","pytest","npx","pnpm dlx","pnpm exec","yarn dlx","npm test","npm run","npm start","npm run test","npm run build","npm run dev","npm run lint","pnpm test","pnpm run","pnpm start","pnpm tsc","yarn test","yarn run","yarn start","eslint","**/node_modules/.bin/eslint","pnpm eslint","prettier","**/node_modules/.bin/prettier","biome","**/node_modules/.bin/biome","stylelint","**/node_modules/.bin/stylelint","mkdir","touch","cat","ls","head","tail","wc","grep","find","tree","file","stat","realpath","basename","dirname","awk","sed","cut","sort","uniq","tr","xargs","column","paste","join","comm","diff","cmp","git status","git log","git diff","git branch","git show","git remote","git tag","git rev-parse","git describe","git ls-files","git ls-tree","git blame","git shortlog","pushd","popd","dirs","echo","pwd","which","type","env","printenv","date","hostname","whoami","uname","lsof","pkill","node --version","npm --version","pnpm --version","yarn --version","python --version","python3 --version","curl -I *","curl --head *","curl -sI *","curl -s http://localhost:*","curl -s http://127.0.0.1:*","curl -sf http://localhost:*","curl -sf http://127.0.0.1:*","curl --fail http://localhost:*","curl --fail http://127.0.0.1:*","tsx","**/node_modules/.bin/tsx","npx tsx","/^(\\w+=\\S+\\s+)+(npx|node|tsx|npm|pnpm|yarn)\\b/","vespercli","vespercli init","vespercli add","vespercli list","vespercli ls","vespercli reset","vespercli catalog","**/node_modules/.bin/vespercli","mcp: vesper-indexing: vesper_search","mcp: vesper-indexing: vesper_symbols","mcp: vesper-indexing: vesper_status","mcp: vesper-indexing: vesper_reindex","python3 << 'PYEOF'",'python3 << "PYEOF"',"python3 << 'EOF'",'python3 << "EOF"',"python3 << 'END'","python << 'PYEOF'",'python << "PYEOF"',"python << 'EOF'","cat << 'EOF'",'cat << "EOF"',"cat << 'END'","bash << 'EOF'","sh << 'EOF'","cat << 'RESEARCH_EOF'",'cat << "RESEARCH_EOF"',"RESEARCH_EOF","tee","node -e","python3 -c","python -c"],Ne=["vesper_search","vesper_symbols","vesper_status","vesper_reindex","resolve-library-id","get-library-docs","query-docs","sequentialthinking","create_entities","create_relations","add_observations","delete_entities","delete_observations","delete_relations","read_graph","search_nodes","open_nodes"],xo={"clickup-agent":["clickup_add_tag_to_task","clickup_add_time_entry","clickup_attach_task_file","clickup_create_document","clickup_create_document_page","clickup_create_folder","clickup_create_list","clickup_create_list_in_folder","clickup_create_task","clickup_create_task_comment","clickup_find_member_by_name","clickup_get_chat_channels","clickup_get_current_time_entry","clickup_get_document_pages","clickup_get_folder","clickup_get_list","clickup_get_task","clickup_get_task_comments","clickup_get_task_time_entries","clickup_get_workspace_hierarchy","clickup_get_workspace_members","clickup_list_document_pages","clickup_remove_tag_from_task","clickup_resolve_assignees","clickup_search","clickup_send_chat_message","clickup_start_time_tracking","clickup_stop_time_tracking","clickup_update_document_page","clickup_update_folder","clickup_update_list","clickup_update_task"]},we={"vesper-indexing":{description:"Fast code search with semantic indexing",config:{type:"stdio",command:"node",args:["${VESPER_INDEXING_PATH}"],env:{VESPER_INDEX_ROOT:"${workspaceFolder}"}},tools:["vesper_search","vesper_symbols","vesper_status","vesper_reindex"]},context7:{description:"Documentation lookup for libraries",config:{type:"stdio",command:"npx",args:["-y","@upstash/context7-mcp"]},tools:["resolve-library-id","get-library-docs","query-docs"]},"sequential-thinking":{description:"Step-by-step reasoning for complex problems",config:{type:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-sequential-thinking"]},tools:["sequentialthinking"]},clickup:{description:"ClickUp project management integration",config:{type:"stdio",command:"npx",args:["-y","@anthropics/mcp-clickup"],env:{CLICKUP_API_KEY:"${env:CLICKUP_API_KEY}",CLICKUP_TEAM_ID:"${env:CLICKUP_TEAM_ID}"}},tools:["clickup_add_tag_to_task","clickup_add_time_entry","clickup_attach_task_file","clickup_create_document","clickup_create_document_page","clickup_create_folder","clickup_create_list","clickup_create_list_in_folder","clickup_create_task","clickup_create_task_comment","clickup_find_member_by_name","clickup_get_chat_channels","clickup_get_current_time_entry","clickup_get_document_pages","clickup_get_folder","clickup_get_list","clickup_get_task","clickup_get_task_comments","clickup_get_task_time_entries","clickup_get_workspace_hierarchy","clickup_get_workspace_members","clickup_list_document_pages","clickup_remove_tag_from_task","clickup_resolve_assignees","clickup_search","clickup_send_chat_message","clickup_start_time_tracking","clickup_stop_time_tracking","clickup_update_document_page","clickup_update_folder","clickup_update_list","clickup_update_task"]},memory:{description:"Persistent knowledge graph memory for AI agents",config:{type:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-memory"],env:{MEMORY_FILE_PATH:"${workspaceFolder}/.vesper/memory.jsonl"}},tools:["create_entities","create_relations","add_observations","delete_entities","delete_observations","delete_relations","read_graph","search_nodes","open_nodes"]},graphify:{description:"Code knowledge graph (graphify, opt-in pack) \u2014 impact, path and architecture queries",config:{type:"stdio",command:"vespercli",args:["mcp","serve","graphify"]},tools:["query_graph","get_node","get_neighbors","shortest_path","get_pr_impact"]}},$u=Ne,he={FOLDER:"folder",WORKSPACE_FILE:"workspace"};bu=new Set;ay=new Set([Nt,qr,V]);ly=Tt,uy=["agents","prompts","skills"],zn=M(O,"copilot","instructions"),po=M(O,"copilot","instructions-extended");fo=M(Tt,"packs");tn=Object.freeze(["-c","core.fsmonitor=false","-c","core.untrackedCache=false"]),uo=null;lt=["pre-commit","post-checkout"];Au="# <!-- vesper:gitattributes:start -->",_u="# <!-- vesper:gitattributes:end -->",hy=[".vesper/memory.jsonl merge=vesper-memory",".claude/vesper/context/recent-decisions.md merge=union",".vesper/context/recent-decisions.md merge=union"];my={VSCODE_SETTINGS_MAP:We,WORKSPACE_TYPES:he,TERMINAL_AUTO_APPROVAL_SETTING:Nt,TERMINAL_ENABLE_AUTO_APPROVAL_SETTING:ho,TOOLS_AUTO_APPROVE_SETTING:qr,TOOLS_ELIGIBLE_FOR_AUTO_APPROVAL_SETTING:V,AGENT_MAX_REQUESTS_SETTING:mo,INCLUDE_REFERENCED_INSTRUCTIONS_SETTING:go,CUSTOM_AGENT_IN_SUBAGENT_SETTING:yo,CHAT_AGENT_ENABLED_SETTING:wo,OMIT_BASE_AGENT_INSTRUCTIONS_SETTING:vo,MCP_DISCOVERY_ENABLED_SETTING:ko,MCP_AUTO_START_SETTING:So,ADDITIONAL_READ_ACCESS_PATHS_SETTING:oe,SAFE_AUTO_APPROVAL_COMMANDS:Bn,MCP_TOOLS_CORE:Ne,MCP_TOOLS_BY_AGENT:xo,MCP_SERVERS:we,MCP_TOOLS_AUTO_APPROVAL:$u,INIT_DEFAULTS:Re,VESPER_MANAGED_SETTINGS:Lt,VESPER_MANAGED_MCP_SERVERS:me,findWorkspaceFile:Na,getWorkspaceConfig:q,getSettingsPath:Ou,getTrackingPath:Qr,getTrackingPathAsync:bt,readVSCodeSettings:K,writeVSCodeSettings:ce,readTracking:x,writeTracking:T,removeLegacyTracking:Pu,addToSettings:Zr,removeFromSettings:ts,getCoreAssetEntries:$o,pruneLegacySettingsEntries:en,listExtendedInstructions:_o,getExtendedInstructionEntry:Co,getTrackedPaths:xt,configureTerminalAutoApproval:To,configureChatSettings:Po,getAutoApprovalCommands:Ru,addReadAccessPath:Io,removeReadAccessPath:jo,getReadAccessPaths:Ro,getMcpConfigPath:Qe,getVesperIndexingPath:Be,readMcpConfig:Ze,configureMcpServer:_r,isMcpServerConfigured:Go,configureMcpToolsAutoApproval:Fo,addAgentToolsToAutoApproval:Gu,addMcpServer:ir,removeMcpServer:nn,listMcpServers:Fu,getConfiguredMcpServers:Do,getWorkspaceFolders:La,findNestedVesperrc:es,migrateVesperrcToWorkspaceLevel:Ao,ensureCoreSettings:No}});import{access as gy,constants as yy,stat as Xx,lstat as wy,readdir as vy,readFile as ky,readlink as Sy,rename as Ey,writeFile as by,mkdir as xy,cp as Ay,appendFile as Du}from"node:fs/promises";import{createHash as _y}from"node:crypto";import{isAbsolute as Cy,join as $y,relative as Oy,resolve as Vo,sep as Ty}from"node:path";function Ha(e){Va=e?{root:Vo(e.root),log:e.log,exclude:e.exclude||(()=>!1)}:null}async function Vu(e,t,r){let n=await wy(e);if(n.isSymbolicLink())r.push([t,`link:${await Sy(e)}`]);else if(n.isDirectory())for(let s of await vy(e))await Vu($y(e,s),`${t}/${s}`,r);else n.isFile()&&r.push([t,_y("sha256").update(await ky(e)).digest("hex")])}function Hu(e,t){let r=Vo(t),n=Oy(e.root,r);if(!n||n.startsWith("..")||Cy(n))return null;let s=n.split(Ty).join("/");return e.exclude(s)?null:s}async function Ua(e){let t=Va;if(t)try{let r=Hu(t,e);r&&await Du(t.log,`${JSON.stringify([r,is])}
|
|
39
|
+
`,"utf-8")}catch{}}async function Wa(e){let t=Va;if(t)try{let r=Vo(e),n=Hu(t,e);if(!n)return;let s=[];await Vu(r,n,s);let o=s.filter(([i])=>!t.exclude(i)).map(i=>`${JSON.stringify(i)}
|
|
40
|
+
`).join("");o&&await Du(t.log,o,"utf-8")}catch{}}async function w(e){try{return await gy(e,yy.F_OK),!0}catch{return!1}}function Ka(e){let t=Vo(e);if(Ar(t)||Ar(e))throw new Error(`Refusing to write a user-level path (Vesper is project-scoped, D7): ${e}. Only the project workspace and the permitted plugin cache (~/.claude/plugins) may be written.`)}async function A(e,t,r){Ka(e),await Ua(e);let n=await by(e,t,r);return await Wa(e),n}async function P(e,t){return Ka(e),xy(e,t)}async function as(e,t,r){Ka(t),await Ua(t);let n=await Ay(e,t,r);return await Wa(t),n}async function Py(e,t){await Ua(t);let r=await Ey(e,t);return await Wa(t),r}async function Cr(e,t,{mode:r,encoding:n="utf-8",tempName:s,sweepPattern:o,sweep:i=!0}={}){let{dirname:a,basename:c,join:l}=await import("node:path"),d=await import("node:fs/promises"),p=a(e);if(i){let m=c(e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),h=o??new RegExp(`^${m}\\.\\d+\\.tmp$`),g=[];try{g=await d.readdir(p)}catch{g=[]}for(let y of g){if(!h.test(y))continue;let k=l(p,y);try{Date.now()-(await d.stat(k)).mtimeMs>Iy&&await d.unlink(k)}catch{}}}let f=s?s(e):`${e}.${process.pid}.tmp`;try{await A(f,t,r===void 0?n:{encoding:n,mode:r}),r!==void 0&&await d.chmod(f,r).catch(()=>{}),await Py(f,e)}catch(m){throw await d.unlink(f).catch(()=>{}),m}}var Va,is,Iy,U=Z(()=>{H();Va=null;is="intent";Iy=5*60*1e3});import{existsSync as Uu,readdirSync as jy}from"node:fs";import{readdir as Wu,readFile as Ku}from"node:fs/promises";import{join as ar}from"node:path";function zu(e=O){try{return jy(ar(e,"claude","packs"),{withFileTypes:!0}).filter(t=>t.isDirectory()&&!t.name.startsWith(".")).map(t=>t.name).sort()}catch{return[]}}function Or(e,t=O){if(typeof e!="string"||!e||/[\\/]|\.\./.test(e))return null;for(let r of zu(t)){let n=ar(t,"claude","packs",r,"skills",e);if(Uu(ar(n,Ba)))return{pack:r,dir:n}}return null}async function Ho(e){let t={},r=async n=>{let s=await Wu(ar(e,n),{withFileTypes:!0});for(let o of s.sort((i,a)=>i.name.localeCompare(a.name))){let i=n?`${n}/${o.name}`:o.name;o.isDirectory()?await r(i):o.isFile()&&i!==Ba&&(t[i]=await Ku(ar(e,i)))}};return await r(""),t}async function Yu(e=O){let t=[];for(let r of zu(e)){let n=[];try{n=(await Wu(ar(e,"claude","packs",r,"skills"),{withFileTypes:!0})).filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>s.name).sort()}catch{n=[]}for(let s of n){let o=ar(e,"claude","packs",r,"skills",s),i=ar(o,Ba);if(!Uu(i))continue;let a=null;try{let c=JSON.parse(await Ku(i,"utf-8"));a=c&&typeof c=="object"&&!Array.isArray(c)?c:null}catch{a=null}t.push({pack:r,skill:s,dir:o,record:a})}}return t}var Ba,$r,Bu,Tr=Z(()=>{xe();Ba="UPSTREAM.json",$r=Object.freeze(["gitlab-ci-skill","github-actions-to-gitlab-ci","i-have-adhd","ponytail"]),Bu="styles"});import{lstat as Xu,readdir as Qu,readFile as Uo,rm as Zu,rmdir as Ju}from"node:fs/promises";import{basename as ed,join as ze,relative as Ry,sep as Ny}from"node:path";import{existsSync as za}from"node:fs";import{createHash as td}from"node:crypto";async function ut(e){let t=[],r=[],n=[],s=async o=>{let i=await Qu(o,{withFileTypes:!0});for(let a of i){let c=ze(o,a.name),l=Ry(e,c).split(Ny).join("/");a.isSymbolicLink()?r.push(l):a.isDirectory()?(await s(c),n.push(l)):a.isFile()?t.push(l):r.push(l)}};return await s(e),t.sort(),r.sort(),n.sort((o,i)=>i.split("/").length-o.split("/").length||i.localeCompare(o)),{files:t,others:r,dirs:n}}function Ly(e){return`sha256:${td("sha256").update(e).digest("hex")}`}function dt(e){let t=e.toString("utf-8").replace(/\r\n/g,`
|
|
41
|
+
`);return`sha256:${td("sha256").update(t,"utf8").digest("hex")}`}function qu(e){if(!e.includes(13))return e;let t=Buffer.allocUnsafe(e.length),r=0;for(let n=0;n<e.length;n+=1)e[n]===13&&e[n+1]===10||(t[r]=e[n],r+=1);return t.subarray(0,r)}function ee(e,t){let r=Buffer.isBuffer(e)?e:Buffer.from(String(e),"utf-8"),n=Buffer.isBuffer(t)?t:Buffer.from(String(t),"utf-8");return qu(r).equals(qu(n))}async function My({sourceDir:e,sourceFiles:t,sourceHashes:r,sourceLfHashes:n}={}){let s=new Map,o=(i,a)=>{let c=s.get(i);s.set(i,c?async l=>await c(l)||a(l):a)};if(r)for(let[i,a]of Object.entries(r))typeof a=="string"&&a&&o(i,async c=>Ly(c)===a);if(t)for(let[i,a]of Object.entries(t)){let c=Buffer.isBuffer(a)?a:Buffer.from(a,"utf-8");o(i,async l=>ee(l,c))}if(e&&za(e)){let{files:i}=await ut(e);for(let a of i)o(a,async c=>ee(c,await Uo(ze(e,a))))}if(n)for(let[i,a]of Object.entries(n)){let c=new Set((Array.isArray(a)?a:[a]).filter(l=>typeof l=="string"&&l));c.size&&o(i,async l=>c.has(dt(l)))}return s}async function Gt(e,{sourceDir:t,sourceFiles:r,sourceHashes:n,sourceLfHashes:s,sourceMatch:o,anchor:i="SKILL.md"}={}){let a;try{a=await Xu(e)}catch{return{status:"absent",proven:[],kept:[],dirs:[]}}if(!a.isDirectory())return{status:"not-directory",proven:[],kept:[ed(e)],dirs:[]};let c=await My({sourceDir:t,sourceFiles:r,sourceHashes:n,sourceLfHashes:s}),{files:l,others:d,dirs:p}=await ut(e),f=[],m=[...d];for(let h of l){let y=c.get(h)||(o?async k=>!!await o(h,k):null);if(!y){m.push(h);continue}try{await y(await Uo(ze(e,h)))?f.push(h):m.push(h)}catch{m.push(h)}}return m.sort(),i&&(c.has(i)||o&&l.includes(i))&&!f.includes(i)?{status:"anchor-unproven",proven:[],kept:[...l,...d].sort(),dirs:p}:{status:"classified",proven:f,kept:m,dirs:p}}async function cs(e,t={}){let r=await Gt(e,t);if(r.status==="absent")return{status:"absent",removed:[],kept:[]};if(r.status!=="classified")return{status:"kept",removed:[],kept:r.kept};for(let o of r.proven)await Zu(ze(e,o),{force:!0});for(let o of r.dirs)try{await Ju(ze(e,o))}catch{}let n=!1;try{await Ju(e),n=!0}catch{}let s="kept";return n?s="removed":r.proven.length>0&&(s="partial"),{status:s,removed:r.proven,kept:r.kept}}async function Gy(e){let t=ed(String(e?.path||""));if(!t||t==="."||t==="..")return null;if(e.category==="vendored-body"){let r=e.placedFiles??e.syncedFiles,n=r&&typeof r=="object"&&Object.keys(r).length?{...r}:null,s=Or(t);return s?{sourceFiles:await Ho(s.dir),...n?{sourceHashes:n}:{}}:n?{sourceHashes:n}:null}if(e.category==="catalog-skill"||e.category==="added-asset"){let r;for(let s of["claude-committed","claude"]){let o=ze(O,s,"skills",t);if(za(o)){r=o;break}}if(!r){let s=[];try{s=(await Qu(ze(O,"claude","packs"),{withFileTypes:!0})).filter(o=>o.isDirectory()&&!o.name.startsWith(".")).map(o=>o.name).sort()}catch{s=[]}for(let o of s){let i=ze(O,"claude","packs",o,"skills",t);if(za(i)){r=i;break}}}let n=e.fileHashes&&typeof e.fileHashes=="object"&&Object.keys(e.fileHashes).length?{...e.fileHashes}:null;if(r||n)return{...r?{sourceDir:r}:{},...n?{sourceLfHashes:n}:{}}}return null}async function Fy(e){let t=String(e?.path||""),r=[];t===".claude/rules/vesper-orchestrator.md"&&r.push(ze(O,"claude","vesper-orchestrator.md"));let n=/^\.claude\/agents\/([^/]+\.md)$/.exec(t);n&&r.push(ze(O,"claude-committed","agents",n[1]),ze(O,"claude","agents",n[1])),n=/^\.claude\/commands\/([^/]+\.md)$/.exec(t),n&&r.push(ze(O,"claude","commands",n[1])),t===".opencode/plugins/vesper.js"&&r.push(ze(O,"opencode","vesper-plugin.js"));let s=[];for(let o of r)try{s.push(await Uo(o))}catch{}return s}async function ls(e,t,{expected:r=[]}={}){let n;try{n=await Uo(e)}catch{return!1}return typeof t?.hash=="string"&&t.hash&&dt(n)===t.hash?!0:[...r.map(o=>Buffer.isBuffer(o)?o:Buffer.from(String(o),"utf-8")),...await Fy(t)].some(o=>ee(n,o))}async function le(e,t,{expected:r=[],purgeProjectAuthored:n=!1}={}){let s;try{s=await Xu(e)}catch{return"absent"}if(s.isFile())return!(n===!0&&t?.category==="per-project-authored")&&!await ls(e,t,{expected:r})?"kept":(await Zu(e,{force:!0}),"removed");if(!s.isDirectory())return"kept";let o=await Gy(t);return o?(await cs(e,o)).status:"kept"}var Ye=Z(()=>{xe();Tr()});import{access as Dy,constants as Vy,readFile as nd,readdir as Hy}from"node:fs/promises";import{execFile as Uy}from"node:child_process";import{join as Wo}from"node:path";async function Wy(e){try{return await Dy(e,Vy.F_OK),!0}catch{return!1}}async function Ft(e){try{let t=JSON.parse(await nd(Wo(e,cr),"utf-8"));if(t&&typeof t=="object"&&t.snapshot&&us.includes(t.from))return t}catch{}return null}async function Ya(e){return await Wy(Wo(e,cr))?await Ft(e)===null:!1}async function Ky(e){let t;try{t=[await bt(e),Wo(e,".vesperrc")]}catch{t=[Wo(e,".vesperrc")]}let r=new Set;for(let n of t)if(!r.has(n)){r.add(n);try{return JSON.parse(await nd(n,"utf-8"))}catch(s){if(s&&s.code==="ENOENT")continue;return null}}return null}function sd(e,t,{env:r,gitArgs:n=[]}={}){return new Promise(s=>{let o;try{o=Uy("git",[...n,...t],{cwd:e,timeout:5e3,maxBuffer:16*1024*1024,encoding:"utf-8",env:{...r??process.env,...Rt}},(i,a,c)=>{let l=i&&typeof i.code=="string"?i:null;s({ok:!i,stdout:String(a??""),stderr:String(c??""),spawnError:l})}),o.stdin?.end()}catch(i){s({ok:!1,stdout:"",stderr:"",spawnError:i})}})}async function By(e,t={}){let r=await sd(e,["rev-parse","--is-inside-work-tree"],t);return r.ok&&r.stdout.trim()==="true"?{state:"repo"}:/dubious ownership/i.test(r.stderr)?{state:"error",gitError:"dubious-ownership"}:/not a git repository/i.test(r.stderr)?{state:"no-repo"}:r.spawnError?.code==="ENOENT"?{state:"no-repo"}:{state:"error",gitError:"unknown"}}async function zy(e,t){if(!t?.host)return!1;try{let{host:r,matched:n}=await uu(e);if(r!==t.host||n.length===0)return!1;for(let{entry:s,path:o}of n)if(!await va(e,s,o))return!1;return!0}catch{return!1}}async function Yy(e){try{return(await Hy(e,{withFileTypes:!0})).filter(t=>t.isFile()&&t.name.endsWith(".code-workspace")).map(t=>t.name).sort()}catch{return[]}}function Jy(e){let t=[];for(let r of us)for(let n of e[r]||[])t.push(yt(n));return[...new Set(t)]}async function rd(e,t,r,n){let s=[],o=null;for(let i of us){let a=!1,c=[...t[i]||[]].sort((l,d)=>+!!d?.vscodeSettings-+!!l?.vscodeSettings);for(let l of c){let d=yt(l),p=Yr(l)&&l.vscodeSettings?[...n,d]:[d];for(let f of p)if(!r.has(f)&&await va(e,l,f)){a=!0,o??=f;break}if(a)break}a&&s.push(i)}return s.length===0?{ignoredEvidence:null,ignoredFile:null}:{ignoredEvidence:s.length>1?"both":s[0],ignoredFile:o}}async function B(e,{requireCommitted:t=!1,withCommitted:r=!1,env:n,gitArgs:s}={}){let o={env:n,gitArgs:s},i=await Pr(e),a={host:null,source:null,ambiguous:!1,committed:!1,ignoredEvidence:null,ignoredFile:null,candidate:null,visible:null,gitError:null};try{let c=await By(e,o);if(c.state==="error")return{...a,gitError:c.gitError};let l=tr(),d=await Yy(e),p=null;if(c.state==="repo"){let h=[...new Set([...Jy(l),...d])],g=await sd(e,["--literal-pathspecs","ls-files","-z","--cached","--others","--exclude-standard","--",...h],o);if(!g.ok)return{...a,gitError:"unknown"};p=new Set(g.stdout.split("\0").filter(Boolean))}a.visible=p;let f=[];for(let h of us)for(let g of l[h]||[])if(await Qt(e,g,{visible:p})){f.push(h);break}if(f.length>1)return{...a,ambiguous:!0};let m=f[0]??null;if(m){if(t||r){let h=await zy(e,{host:m});return a.committed=h,t&&!h?(p&&Object.assign(a,await rd(e,l,p,d)),{...a,candidate:m}):{...a,host:m,source:h?"committed":"working-tree"}}return{...a,host:m,source:"working-tree"}}return c.state!=="repo"?a:(Object.assign(a,await rd(e,l,p,d)),!t&&a.ignoredEvidence&&a.ignoredEvidence!=="both"&&a.ignoredEvidence===i?{...a,host:i,source:"local"}:a)}catch{return a}}async function Pr(e){try{let t=await Ky(e);return t&&us.includes(t.host)?t.host:null}catch{return null}}var us,cr,Ae=Z(()=>{fe();H();vt();us=Object.freeze(["claude","copilot"]),cr=".vesper/.host-switch-journal.json"});import{createHash as qy}from"node:crypto";import{readFile as id,readdir as ad}from"node:fs/promises";import{join as sn,isAbsolute as Xy}from"node:path";function ps(e){let t=String(e).replace(/\r\n/g,`
|
|
42
|
+
`);return`sha256:${qy("sha256").update(t,"utf8").digest("hex")}`}async function ye(e){try{return ps(await id(e,"utf-8"))}catch{return null}}function G({path:e,host:t,category:r,hash:n=null}){if(Qy.has(r)&&!n)throw new Error(`wholeFileEntry: category "${r}" is content-hash verified but was given a null/empty hash for "${e}". Provide a hash (from hashFile) or use an existence-checked category \u2014 a content-hash entry without a hash is never verified.`);return{path:e,host:t,category:r,hash:n}}function Y({path:e,host:t,category:r,owns:n}){return{path:e,host:t,category:r,owns:n||{}}}async function on(e){return(await B(e)).host}async function cd(e,t){if(!z.includes(t))throw new Error(`Invalid host "${t}". Vesper 2.0 provisions exactly one of: ${z.join(", ")}.`);let r=await x(e);return r.schemaVersion=ve,r.host=t,await T(e,r),t}async function Bo(e,t){return(await x(e))[t]}async function Zy(e,t,r){let n=await x(e);return n[t]=r,await T(e,n),r}async function ud(e){return await Bo(e,qa)===Xa}function dd(e){return Zy(e,qa,Xa)}async function pd(e,t){let r=await x(e);if(r[qa]===Xa)return[];let n=J(r),s=[],o=n.filter(i=>{let a=i.host===t&&i.category!=="added-asset"&&Dt[i.category]?.ownership==="whole-file";return a&&s.push(i.path),!a});return s.length===0?[]:(r.manifest=o,await T(e,r),s)}function ds(e){return e&&typeof e.path=="string"&&typeof e.host=="string"&&typeof e.category=="string"}async function ne(e){let t=await x(e);return J(t)}function J(e){let t=e?.manifest;return Array.isArray(t)?t.filter(ds):[]}function tt(e){return[...e].sort((t,r)=>String(t.path).localeCompare(String(r.path))||String(t.host).localeCompare(String(r.host)))}function Qa(e,t){let r=[...e];for(let n of t){if(!ds(n))continue;let s=r.findIndex(o=>o.path===n.path&&o.host===n.host);s===-1?r.push(n):r[s]=n}return r}async function W(e,t){let r=await x(e);return r.schemaVersion=ve,r.manifest=tt(Qa(J(r),t||[])),await T(e,r),r.manifest}function ew(e){return typeof e=="string"&&e.length>0&&!e.includes("..")&&!e.startsWith("/")}function Yo(e,{host:t,keep:r,purgeProjectAuthored:n=!1}={}){return!e||typeof e.path!="string"||e.host==="shared"||Le.has(e.category)&&!n||t&&e.host!==t||Dt[e.category]?.ownership!=="whole-file"||r&&r.has(e.path)?!1:ew(e.path)}async function cn(e,t,{prune:r=!0,categories:n}={}){let s=await ne(e),o=(t||[]).filter(ds),i=new Set(n||o.map(h=>h.category)),a=new Set(o.map(h=>h.host)),c=h=>i.has(h.category)&&(a.size===0||a.has(h.host)),l=new Set(o.map(h=>h.path)),d=[],p=[];if(r)for(let h of s){if(!c(h)||!Yo(h,{keep:l}))continue;let g=sn(e,h.path);if(await w(g)){let y=await le(g,h);(y==="kept"||y==="partial")&&p.push(h.path),y!=="kept"&&d.push(h.path)}}let f=s.filter(h=>!c(h)),m=await x(e);return m.schemaVersion=ve,m.manifest=tt(Qa(f,o)),await T(e,m),{pruned:d,kept:p,manifest:m.manifest}}async function fd(e,t,{host:r,purgeProjectAuthored:n=!1}={}){let s=new Set(t||[]),o=await ne(e),i=[],a=[],c=[],l=p=>p.category==="per-project-authored"&&o.some(f=>f&&f.path===p.path&&f.host!==p.host&&f.category==="per-project-authored");for(let p of o){if(Yo(p,{host:r,keep:s,purgeProjectAuthored:n})){let f=sn(e,p.path);if(l(p)){i.push(p.path);continue}if(await w(f)){let m=await le(f,p,{purgeProjectAuthored:n});(m==="kept"||m==="partial")&&a.push(p.path)}i.push(p.path);continue}c.push(p)}let d=await x(e);return d.manifest=tt(c),await T(e,d),{pruned:i,kept:a,manifest:d.manifest}}async function hd(e){let t=await ne(e),r={missing:[],modified:[],clean:[],userLevelViolations:[]};for(let n of t){let s=Xy(n.path)?n.path:sn(e,n.path);Ar(s)&&r.userLevelViolations.push(n);let o=Dt[n.category]||{doctor:"existence"},i=await w(s);if(o.doctor==="content-hash"){if(!i){r.missing.push(n);continue}let a=await ye(s);n.hash&&a&&a!==n.hash?r.modified.push(n):r.clean.push(n);continue}if(o.doctor==="server-drift"){if(!i){r.missing.push(n);continue}let a=n.owns?.keys||[],c=await Ja(s),l=a.every(d=>c.includes(d));a.length&&!l?r.modified.push(n):r.clean.push(n);continue}i?r.clean.push(n):r.missing.push(n)}return r}async function Ja(e){try{let t=JSON.parse(await id(e,"utf-8"));return Object.keys(t.mcpServers||t.servers||{})}catch{return[]}}async function od(e){try{return(await ad(e,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".md")).map(r=>r.name)}catch{return[]}}async function tw(e){try{return(await ad(e,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>r.name)}catch{return[]}}async function Za(e,t,{settingsEntries:r,hooksDir:n,hookNames:s,provisionedSkillNames:o,provisionedInstructionNames:i}={}){let a=[],c=d=>sn(e,d),l=async(d,p)=>{a.push(G({path:d,host:t,category:p,hash:await ye(c(d))}))};if(t==="claude"){for(let p of await od(c(".claude/agents")))await l(`.claude/agents/${p}`,"catalog-agent");for(let p of await od(c(".claude/commands")))await l(`.claude/commands/${p}`,"catalog-command");let d=new Set(o||[]);for(let p of await tw(c(".claude/skills")))d.has(p)&&a.push(G({path:`.claude/skills/${p}`,host:t,category:"catalog-skill",hash:null}));await w(c(".claude/vesper/orchestrator.md"))&&await l(".claude/vesper/orchestrator.md","playbook");for(let p of[".claude/vesper/orchestration.md",".claude/vesper/context.md"])await w(c(p))&&a.push(G({path:p,host:t,category:"per-project-authored",hash:null}));await w(c("CLAUDE.md"))&&a.push(Y({path:"CLAUDE.md",host:t,category:"pointer",owns:{region:"vesper"}})),await w(c(".mcp.json"))&&a.push(Y({path:".mcp.json",host:t,category:"mcp-config",owns:{keys:await Ja(c(".mcp.json"))}})),await w(c(".claude/settings.json"))&&a.push(Y({path:".claude/settings.json",host:t,category:"settings",owns:{keys:["permissions.allow","hooks.SessionStart","hooks.SubagentStart"]}}))}if(t==="copilot"&&(await w(c(".vscode/settings.json"))&&a.push(Y({path:".vscode/settings.json",host:t,category:"settings",owns:{keys:[...Lt],entries:r?[...r]:[]}})),await w(c(".vscode/mcp.json"))&&a.push(Y({path:".vscode/mcp.json",host:t,category:"mcp-config",owns:{keys:await Ja(c(".vscode/mcp.json"))}})),await w(c(".vscode/tasks.json"))&&a.push(Y({path:".vscode/tasks.json",host:t,category:"bootstrap-task",owns:{keys:["Vesper: worktree bootstrap"]}}))),await w(c(".gitignore"))&&a.push(Y({path:".gitignore",host:"shared",category:"gitignore",owns:{region:"vesper:gitignore"}})),n)for(let d of Array.isArray(s)?s:["pre-commit","post-checkout"]){let p=sn(n,d);await w(p)&&a.push(Y({path:p,host:"shared",category:"hook",owns:{region:"vesper:hook"}}))}return a}function ec(e){return(e||[]).filter(t=>t&&t.host==="shared")}function rw(e){let t=!1;for(let r of fs)r in e&&(delete e[r],t=!0);return t}async function md(e){!await w(sn(e,".vesperrc"))||(await x(e)).schemaVersion!==ve||await ln(e)}async function ln(e,{frameworkVersion:t,legacyEntries:r=[],host:n}={}){let s=await x(e);if(s.schemaVersion===ve){let h=!1;if("host"in s&&!z.includes(s.host)&&(delete s.host,h=!0),!Array.isArray(s.manifest))s.manifest=[],h=!0;else{let g=s.manifest.filter(ds);g.length!==s.manifest.length&&(s.manifest=g,h=!0)}return rw(s)&&(h=!0),h&&await T(e,s),s}let o=(z.includes(n)?n:null)||Yn(s)||(await B(e)).host,i=o==="both"?null:o,a=s.claude?.namePrefix??s.namePrefix,c=s.claude?.pluginPath??s.pluginPath,l=Array.isArray(s.paths)?[...s.paths]:[],d=await Za(e,i,{settingsEntries:l}),p=tt(Qa(ec(d),(r||[]).filter(ds))),f={schemaVersion:ve,host:i||void 0,frameworkVersion:t??s.frameworkVersion,manifest:p};a!==void 0&&(f.namePrefix=a),c!==void 0&&(f.pluginPath=c),s.vendored!==void 0&&(f.vendored=s.vendored),s.mcp!==void 0&&(f.mcp=s.mcp),s.readAccessPaths!==void 0&&(f.readAccessPaths=s.readAccessPaths);let m=new Set([...fs,"schemaVersion","host","frameworkVersion","manifest","namePrefix","pluginPath","vendored","mcp","readAccessPaths"]);for(let[h,g]of Object.entries(s))m.has(h)||(f[h]=g);return await T(e,f),f}async function Ir(e,t){let r=await x(e);return!!(J(r).some(s=>s.host===t&&!Le.has(s.category))||t==="claude"&&r.claude||t==="copilot"&&Array.isArray(r.paths)&&r.paths.length>0)}async function At(e){let t=await x(e),n=J(t).find(s=>s.path===".vscode/settings.json"&&s.category==="settings");return n&&Array.isArray(n.owns?.entries)&&n.owns.entries.length?[...n.owns.entries]:Array.isArray(t.paths)?[...t.paths]:[]}var ve,z,et,Ko,Dt,Qy,zo,an,ld,qa,Xa,Le,fs,te=Z(()=>{H();U();Ye();Ae();fe();ve=2,z=["claude","copilot"],et="This workspace carries both Copilot and Claude targets from a pre-2.0 install. Vesper 2.0 uses a single host per workspace \u2014 run `vespercli init --host <claude|copilot>` to choose one, or pass an explicit `--target claude|copilot`.",Ko="This workspace carries both Copilot and Claude targets from a pre-2.0 install. Vesper 2.0 uses a single host per workspace \u2014 run `vespercli init --host <claude|copilot>` to choose one, or `vespercli reset --host <claude|copilot>` to remove one host's artifacts.",Dt={"catalog-agent":{ownership:"whole-file",doctor:"content-hash"},"catalog-command":{ownership:"whole-file",doctor:"content-hash"},"catalog-skill":{ownership:"whole-file",doctor:"existence"},playbook:{ownership:"whole-file",doctor:"content-hash"},"pack-rule":{ownership:"whole-file",doctor:"existence"},"vendored-body":{ownership:"whole-file",doctor:"existence"},"vendored-activation":{ownership:"whole-file",doctor:"content-hash"},"per-project-authored":{ownership:"whole-file",doctor:"existence"},"mcp-config":{ownership:"key",doctor:"server-drift"},settings:{ownership:"key",doctor:"key-presence"},pointer:{ownership:"region",doctor:"region-presence"},hook:{ownership:"region",doctor:"region-presence"},gitignore:{ownership:"region",doctor:"region-presence"},"bootstrap-task":{ownership:"key",doctor:"key-presence"},"guard-trigger":{ownership:"key",doctor:"key-presence"},"added-asset":{ownership:"whole-file",doctor:"existence"},"opencode-agent":{ownership:"whole-file",doctor:"existence"},"opencode-overlay":{ownership:"whole-file",doctor:"existence"},"opencode-config":{ownership:"key",doctor:"key-presence"}},Qy=new Set(Object.entries(Dt).filter(([,e])=>e.doctor==="content-hash").map(([e])=>e));zo=e=>Bo(e,"frameworkVersion"),an=async e=>await Bo(e,"namePrefix")??"",ld=e=>Bo(e,"pluginPath"),qa="manifestProvenance",Xa="granular";Le=new Set(["per-project-authored"]);fs=Object.freeze(["paths","claude","addedAt","workspaceType","settingsPath","updatedAt","catalogVersion","targets"])});import{readdir as tc}from"node:fs/promises";import{join as hs}from"node:path";function wd(e){let t=[],r=null;return{text:String(e||"").split(`
|
|
43
|
+
`).filter(s=>{if(!/^\s*\|/.test(s))return r=null,!0;let o=kd(s);if(Sd(o))return!0;if(r===null)return r=o.map((i,a)=>/agent/i.test(i)?a:-1).filter(i=>i>=0),!0;for(let i of r){let a=vd.exec(o[i]||"")?.[2],c=a?un(a).name:null;if(c&&Object.hasOwn(Jo,c))return t.push({role:(o[0]||"").trim(),agent:c,replacement:Jo[c]}),!1}return!0}).join(`
|
|
44
|
+
`),removed:t}}function Me(e){return`${Vt}-${e}`}async function gd(e){try{return(await tc(e)).filter(t=>t.endsWith(".md")).map(t=>t.slice(0,-3))}catch{return[]}}async function yd(e){try{return(await tc(e,{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>t.name)}catch{return[]}}async function _t(e=O){let t={agents:new Set,skills:new Set,agentPlugin:new Map,skillPlugin:new Map,agentPack:new Map,skillPack:new Map},r=(s,o,i,a)=>{t[s].add(o);let c=s==="agents"?t.agentPlugin:t.skillPlugin,l=s==="agents"?t.agentPack:t.skillPack;c.has(o)||(c.set(o,i),l.set(o,a))};for(let s of await gd(hs(e,"claude","agents")))r("agents",s,Vt,"core");for(let s of await yd(hs(e,"claude","skills")))r("skills",s,Vt,"core");let n=[];try{n=(await tc(hs(e,"claude","packs"),{withFileTypes:!0})).filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>s.name).sort()}catch{n=[]}for(let s of n){let o=Me(s);for(let i of await gd(hs(e,"claude","packs",s,"agents")))r("agents",i,o,s);for(let i of await yd(hs(e,"claude","packs",s,"skills")))r("skills",i,o,s)}return t}function kd(e){return e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|")}function Sd(e){return e.every(t=>/^:?-{2,}:?$/.test(t.trim()))}function Ed(e,t,r){let n=null;return e.split(`
|
|
45
|
+
`).map(s=>{if(!/^\s*\|/.test(s))return n=null,s;let o=kd(s);if(Sd(o))return s;if(n===null)return n=o.map((c,l)=>t.test(c)?l:-1).filter(c=>c>=0),s;let i=!1;for(let c of n){if(o[c]===void 0)continue;let l=r(o[c]);l!==null&&l!==o[c]&&(o[c]=l,i=!0)}return i?`${/^\s*/.exec(s)[0]}|${o.join("|")}|`:s}).join(`
|
|
46
|
+
`)}function rc(e,t){return Ed(e,/agent/i,r=>{let n=vd.exec(r);if(!n)return null;let s=t(n[2]);return!s||s===n[2]?null:n[1]+s+r.slice(n[0].length)})}function un(e){let t=e.lastIndexOf(":");return t===-1?{plugin:null,name:e}:{plugin:e.slice(0,t),name:e.slice(t+1)}}function bd(e,t){let r=new Set;return rc(e,n=>(!n.includes(":")&&t.has(n)&&r.add(n),null)),[...r].sort()}function qo(e,t,{skip:r=new Set}={}){let n=t instanceof Set?t:t.agents,s=a=>t instanceof Set?Vt:t.agentPlugin?.get(a)??Vt,o=new Set;return{text:rc(e,a=>{let{plugin:c,name:l}=un(a);if(!n.has(l)||r.has(l))return null;let d=s(l);return c===d||c!==null&&!(c===Vt||c.startsWith(`${Vt}-`))?null:(o.add(l),`${d}:${l}`)}),qualified:[...o].sort()}}function xd(e){return String(e||"").replace(/<!--[\s\S]*?-->/g,"")}function Ad(e){let t=new Set;return rc(xd(e),r=>(t.add(un(r).name),null)),[...t].sort()}function _d(e){let t=new Set;return Ed(xd(e),/skill/i,r=>{for(let n of r.split(",")){let s=n.trim().replace(/^`|`$/g,"").trim();if(!s||s==="\u2014"||s==="-"||s==="\u2013")continue;let o=/^\/?(?:[a-z0-9-]+:)?([a-z0-9][a-z0-9-]*)$/i.exec(s);o&&t.add(o[1].toLowerCase())}return null}),[...t].sort()}var Jo,Vt,vd,dn=Z(()=>{xe();Jo=Object.freeze({"history-logger":"vespercli log (the run ledger)"});Vt="vesper";vd=/^(\s*`?)([a-z0-9:-]+)/});import{readFile as Cd}from"node:fs/promises";import{join as ms,dirname as nw}from"node:path";function $d(){return Object.keys(nc).sort()}function jr(e){return Object.prototype.hasOwnProperty.call(nc,e)}function ys(e,t){return nc[e]?.[t]??null}function sc(e,t){if(e!=="styles"||!ys(e,t))return null;let n=["# Vesper styles (always on)","","This project enables the `vesper-styles` pack. Apply the `i-have-adhd` output style and the",`\`ponytail\` decision ladder on every reply: ${t==="claude"?"load `/vesper-styles:i-have-adhd` and `/vesper-styles:ponytail` at session start":"read the `i-have-adhd` and `ponytail` skills under the pack's injected `skills/` location at session start"}, and keep both in effect for the`,`whole session (until the user says "normal mode"). Safety, correctness and the harness's own`,"instructions always outrank either style.","","Written by Vesper (`vespercli packs enable styles`); `vespercli packs disable styles` removes it.",""].join(`
|
|
47
47
|
`);return t==="claude"?n:`---
|
|
48
48
|
applyTo: '**'
|
|
49
49
|
description: 'Vesper styles pack \u2014 apply the i-have-adhd output style and the ponytail decision ladder on every reply.'
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
-
${n}`}async function
|
|
53
|
-
`)}function
|
|
54
|
-
`)}function
|
|
52
|
+
${n}`}async function Od(e,t,r){return(await ne(e)).find(n=>n.host===t&&n.path===r&&n.category===gs)||null}async function sw(e,t,r){let n=await x(e),s=J(n),o=s.filter(i=>!(i.host===t&&i.path===r&&i.category===gs));return o.length===s.length?!1:(n.manifest=tt(o),await T(e,n),!0)}async function Td(e,t,r){let n=ys(r,t);if(!n)return null;let s=sc(r,t),o=ms(e,n),i=async()=>W(e,[G({path:n,host:t,category:gs,hash:ps(s)})]),a=null;try{a=await Cd(o)}catch{a=null}if(a===null)return await P(nw(o),{recursive:!0}),await A(o,s,"utf-8"),await i(),{path:n,status:"created"};if(ee(a,s))return await i(),{path:n,status:"unchanged"};let c=await Od(e,t,n);return c?.hash&&await ye(o)===c.hash?(await A(o,s,"utf-8"),await i(),{path:n,status:"updated"}):{path:n,status:"kept-edited"}}async function oc(e,t,r){let n=ys(r,t);if(!n)return null;let o=await Od(e,t,n)??{path:n,category:gs,hash:null},i=await le(ms(e,n),o,{expected:[sc(r,t)]});return await sw(e,t,n),{path:n,status:i==="partial"?"kept":i}}async function Xo(e,t){let r={removed:[],kept:[]};for(let n of $d()){let s=await oc(e,t,n);s?.status==="removed"?r.removed.push(s.path):s?.status==="kept"&&r.kept.push(s.path)}return r}async function Pd(e,t){let r=[];for(let n of $d()){let s=ys(n,t);if(!s||!await w(ms(e,s)))continue;let o=null;try{o=await Cd(ms(e,s))}catch{o=null}!o||!ee(o,sc(n,t))||r.push(G({path:s,host:t,category:gs,hash:await ye(ms(e,s))}))}return r}function ic(e){return`Kept your edited ${e} \u2014 Vesper never overwrites or deletes a file that differs from what it wrote. Delete it by hand to take Vesper's version.`}var gs,nc,pn=Z(()=>{U();H();te();Ye();fe();gs="pack-rule",nc=Object.freeze({styles:Object.freeze({claude:".claude/rules/vesper-styles.md",copilot:je("vesper-styles")})})});import{accessSync as ow,constants as iw,statSync as uc,readFileSync as jd,existsSync as aw}from"node:fs";import{readFile as ks}from"node:fs/promises";import{spawn as Rd}from"node:child_process";import{join as Ht,delimiter as cw}from"node:path";function Nd(){return[Qo,...dw,Zo].join(`
|
|
53
|
+
`)}function lc(){return[ws,"# Vesper graphify pack: refresh the code knowledge graph (graphify-out/graph.json) after an",`# attached branch checkout. No-op without the graphify tool on PATH (\`${ei}\`),`,"# honours `git config vesper.hooks false`, never fails the checkout. Removed by","# `vespercli packs disable graphify`.",'if [ "$3" = "1" ] && [ "$(git config --type=bool --get vesper.hooks 2>/dev/null)" != "false" ] \\'," && command -v graphify >/dev/null 2>&1 && git symbolic-ref -q HEAD >/dev/null 2>&1; then",` ${Se} >/dev/null 2>&1 || true`,"fi",vs].join(`
|
|
54
|
+
`)}function dc(e,t,r){let n=e.indexOf(t);if(n===-1)return null;let s=e.indexOf(r,n);return s===-1?null:{start:n,end:s+r.length}}function ti(e,t,r){let n=dc(e,t,r);return n?e.slice(n.start,n.end):null}function pc(e,t,r){let n=dc(e,t,r);if(!n)return null;let{start:s,end:o}=n;return s>0&&e[s-1]===`
|
|
55
55
|
`&&(s-=1),e[o]===`
|
|
56
|
-
`&&(o+=1),e.slice(0,s)+e.slice(o)}async function
|
|
57
|
-
`,"utf-8"),await o(),{path:r,status:"created"};let a=
|
|
56
|
+
`&&(o+=1),e.slice(0,s)+e.slice(o)}async function Ld(e,{path:t,host:r,category:n,region:s}){await W(e,[Y({path:t,host:r,category:n,owns:{region:s}})])}async function Md(e,{host:t,category:r,region:n}){let s=await x(e),o=J(s),i=o.filter(a=>!(a.host===t&&a.category===r&&a.owns?.region===n));return i.length===o.length?!1:(s.manifest=tt(i),await T(e,s),!0)}async function pw(e,t){return(await ne(e)).find(r=>r.host===t&&r.category==="hook"&&r.owns?.region===fn)||null}async function hn(e,t){if(t==="claude")try{let n=JSON.parse(await ks(Ht(e,jt),"utf-8"))?.enabledPlugins;return!n||typeof n!="object"||Array.isArray(n)?!1:Object.entries(n).some(([s,o])=>o===!0&&Er(s)===Ge)}catch{return!1}if(t==="copilot"){let r=await K(e);return sr(Ge).some(({path:n,settingKey:s})=>r[s]?.[n]===!0)}return!1}async function fw(e,t){let r=".gitignore",n=Ht(e,r),s=Nd(),o=()=>Ld(e,{path:r,host:t,category:"gitignore",region:Ss}),i=null;try{i=await ks(n,"utf-8")}catch(l){if(l.code!=="ENOENT")throw l}if(i===null)return await A(n,`${s}
|
|
57
|
+
`,"utf-8"),await o(),{path:r,status:"created"};let a=ti(i,Qo,Zo);if(a!==null)return await o(),ee(a,s)?{path:r,status:"unchanged"}:{path:r,status:"kept-edited"};let c=i.endsWith(`
|
|
58
58
|
`)?`
|
|
59
59
|
`:`
|
|
60
60
|
|
|
61
61
|
`;return await A(n,`${i}${c}${s}
|
|
62
|
-
`,"utf-8"),await o(),{path:r,status:"updated"}}async function
|
|
62
|
+
`,"utf-8"),await o(),{path:r,status:"updated"}}async function hw(e,t){let r=".gitignore",n=Ht(e,r);await Md(e,{host:t,category:"gitignore",region:Ss});let s=null;try{s=await ks(n,"utf-8")}catch{s=null}if(s===null)return{path:r,status:"absent"};let o=ti(s,Qo,Zo);if(o===null)return{path:r,status:"absent"};if(!ee(o,Nd()))return{path:r,status:"kept"};let i=pc(s,Qo,Zo);return await A(n,i,"utf-8"),{path:r,status:"removed"}}async function Gd(e){let t=await or(e);if(!t.dir)return{path:null,reason:t.reason||"not-installable"};let r=Ht(t.dir,uw),n=await rn(r);if(!n.path)return{path:null,reason:n.reason};let s=await ct(n.path);return St(s,t.roots)?await nr(s,t)?{path:null,reason:"tracked-by-git"}:{path:n.path}:{path:null,reason:"outside-repository"}}async function mw(e,t){let r=await Gd(e);if(!r.path)return{path:null,status:"skipped",reason:r.reason};let n=null;try{n=await ks(r.path)}catch{n=null}if(n===null)return{path:r.path,status:"skipped",reason:"hook-missing"};let s=n.toString("latin1"),o=dc(s,it,qt);if(!o)return{path:r.path,status:"skipped",reason:"vesper-block-missing"};let i=Buffer.from(lc(),"utf-8").toString("latin1"),a=()=>Ld(e,{path:r.path,host:t,category:"hook",region:fn}),c=ti(s,ws,vs);if(c!==null)return await a(),ee(Buffer.from(c,"latin1"),lc())?{path:r.path,status:"unchanged"}:{path:r.path,status:"kept-edited"};let l=o.end;s[l]===`
|
|
63
63
|
`&&(l+=1);let d=`${s.slice(0,l)}
|
|
64
64
|
${i}
|
|
65
|
-
${s.slice(l)}`;return await
|
|
66
|
-
`,"utf-8"),{created:!0,path:ue,checks:s.checks.map(o=>o.name)}}function
|
|
67
|
-
`)}function
|
|
65
|
+
${s.slice(l)}`;return await kt(r.path,Buffer.from(d,"latin1")),await a(),{path:r.path,status:"created"}}async function gw(e,t){let r=await pw(e,t);await Md(e,{host:t,category:"hook",region:fn});let n=[];r?.path&&n.push(r.path);let s=await Gd(e);s.path&&!n.includes(s.path)&&n.push(s.path);for(let o of n){let i=null;try{i=await ks(o)}catch{continue}let a=i.toString("latin1"),c=ti(a,ws,vs);if(c!==null){if(!ee(Buffer.from(c,"latin1"),lc()))return{path:o,status:"kept"};if(o===s.path)return await kt(o,Buffer.from(pc(a,ws,vs),"latin1")),{path:o,status:"removed"}}}return{path:n[0]??null,status:"absent"}}function Fd(e){return pc(e,ws,vs)}async function Es(e,t){return{gitignore:await fw(e,t),hook:await mw(e,t)}}async function mn(e,t){let r=await hw(e,t),n=await gw(e,t),s=[];return r.status==="kept"&&s.push(r.path),n.status==="kept"&&n.path&&s.push(n.path),{gitignore:r,hook:n,kept:s}}function bs(e){return`Kept the edited graphify block in ${e} \u2014 Vesper never deletes a block that differs from what it wrote. Remove the \`${Ss}\` / \`${fn}\` markers by hand to drop it.`}function Dd({plan:e=gn(),onPath:t=!!rt()}={}){let r=`run \`${Se}\` to build the graph (${ke} is committed and shared; the post-checkout hook keeps it fresh)`,n=Vd.map(o=>`\`${o.command}\``).join(" / ");return[t?`graphify found on PATH \u2014 ${r}.`:e.command?`graphify is an external tool: install it with \`${e.command}\` (routes: ${n}), then ${r}.`:`graphify is an external tool: ${e.hint} Then ${r}.`,"Code never leaves the machine; a code-only build costs 0 tokens. Doc/PDF extraction and community labels call an LLM (`--no-label` skips the labels)."]}function gn({env:e=process.env,which:t=r=>ni(r,e)}={}){for(let r of Vd){let n=r.needs.find(i=>t(i));if(!n)continue;let s=r.argv.map(i=>i.replace("${python}",n)),o=s.join(" ");return{tool:r.tool,command:o,argv:s,hint:`Install graphify with \`${o}\`, then run \`${Se}\`.`}}return{tool:null,command:null,argv:null,hint:`No uv, pipx or python on PATH \u2014 install uv first (\`${lw}\`, or \`pip install uv\`), then \`${ei}\`.`}}function xs(e=gn()){return e.command??e.hint}function Hd(e,{spawn:t=Rd}={}){return e?.argv?.length?new Promise(r=>{let n;try{n=t(e.argv[0],e.argv.slice(1),{stdio:"inherit",shell:process.platform==="win32"})}catch(s){return r({ok:!1,code:null,error:s?.message||String(s)})}n.on("error",s=>r({ok:!1,code:null,error:s?.message||String(s)})),n.on("close",s=>r({ok:s===0,code:s}))}):Promise.resolve({ok:!1,code:null,error:"no install command for this machine"})}function Ud(e,{spawn:t=Rd,env:r=process.env}={}){let[n,...s]=Se.split(" ");return new Promise(o=>{let i;try{i=t(n,s,{cwd:e,env:r,stdio:"inherit",shell:process.platform==="win32"})}catch(a){return o({ok:!1,code:null,error:a?.message||String(a)})}i.on("error",a=>o({ok:!1,code:null,error:a?.message||String(a)})),i.on("close",a=>o({ok:a===0,code:a}))})}function Wd(e){return aw(Ht(e,ke))}function Kd(e,{env:t=process.env,which:r=n=>ni(n,t)}={}){try{let n=jd(Ht(e,Ut),"utf-8").split(/\r?\n/)[0].trim();if(n&&uc(n).isFile())return n}catch{}return r("python3")?"python3":r("python")?"python":"python3"}function ri(e,{env:t=process.env,which:r=n=>ni(n,t)}={}){try{let n=jd(Ht(e,Ut),"utf-8").split(/\r?\n/)[0].trim();if(n&&uc(n).isFile())return!0}catch{}return!!r("python3")||!!r("python")}async function Bd(e,{execFileAsync:t,timeout:r=5e3}={}){if(!t){let{execFile:n}=await import("node:child_process"),{promisify:s}=await import("node:util");t=s(n)}try{return await t(e,["-c","import graphify"],{timeout:r}),!0}catch{return!1}}function rt(e=process.env){return ni("graphify",e)}function ni(e,t=process.env){let r=t.PATH??t.Path??"",n=process.platform==="win32"?(t.PATHEXT||".EXE;.CMD;.BAT;.COM").split(";"):[""];for(let s of r.split(cw).filter(Boolean))for(let o of n){let i=Ht(s,`${e}${o}`);try{if(!uc(i).isFile())continue;return process.platform!=="win32"&&ow(i,iw.X_OK),i}catch{}}return null}async function zd(e){let t=Ht(e,ke);if(!await w(t))return{present:!1,commit:null,key:null};let r="";try{let{open:s}=await import("node:fs/promises"),o=await s(t,"r");try{let i=Buffer.alloc(65536),{bytesRead:a}=await o.read(i,0,i.length,0);r=i.subarray(0,a).toString("utf-8")}finally{await o.close()}}catch{return{present:!0,commit:null,key:null}}let n=yw(r);return{present:!0,commit:n?.commit??null,key:n?.key??null}}function cc(e,t){if(!e||typeof e!="object"||Array.isArray(e))return null;for(let[r,n]of Object.entries(e))if(/commit/i.test(r)){if(typeof n=="string"&&Id.test(n.trim()))return{key:t?`${t}.${r}`:r,commit:n.trim()};if(n&&typeof n=="object"&&!Array.isArray(n)){for(let[s,o]of Object.entries(n))if(typeof o=="string"&&Id.test(o.trim()))return{key:`${t?`${t}.`:""}${r}.${s}`,commit:o.trim()}}}return null}function yw(e){let t=null;try{t=JSON.parse(e)}catch{t=null}if(t&&typeof t=="object")return cc(t,"")||cc(t.graph,"graph")||cc(t.metadata,"metadata");let r=e.match(/"([A-Za-z0-9_.-]*commit[A-Za-z0-9_.-]*)"\s*:\s*"([0-9a-fA-F]{7,40})"/i);return r?{key:r[1],commit:r[2]}:null}var Ge,pt,ke,ei,ac,lw,Ut,Se,uw,Ss,fn,Qo,Zo,ws,vs,dw,Vd,Id,ft=Z(()=>{U();H();te();Ye();fe();Kr();Ge="graphify",pt="graphify",ke="graphify-out/graph.json",ei="uv tool install graphifyy",ac="graphifyy",lw="curl -LsSf https://astral.sh/uv/install.sh | sh",Ut="graphify-out/.graphify_python",Se="graphify update .",uw="post-checkout",Ss="vesper:gitignore:graphify",fn="vesper:hook:graphify",Qo=`# <!-- ${Ss}:start -->`,Zo=`# <!-- ${Ss}:end -->`,ws=`# <!-- ${fn}:start -->`,vs=`# <!-- ${fn}:end -->`,dw=Object.freeze(["graphify-out/*",`!${ke}`]);Vd=Object.freeze([Object.freeze({tool:"uv",needs:["uv"],argv:Object.freeze(["uv","tool","install",ac])}),Object.freeze({tool:"pipx",needs:["pipx"],argv:Object.freeze(["pipx","install",ac])}),Object.freeze({tool:"pip",needs:["python3","python"],argv:Object.freeze(["${python}","-m","pip","install","--user",ac])})].map(e=>({...e,command:e.argv.join(" ").replace("${python}","python3")})));Id=/^[0-9a-f]{7,40}$/i});import{readFile as si,readdir as ww}from"node:fs/promises";import{join as wn,dirname as Jd,basename as vw}from"node:path";import{spawnSync as qd}from"node:child_process";function _w(e,t=[]){let r=typeof e?.packageManager=="string"?e.packageManager.trim().split("@")[0]:"";if(xw.includes(r))return r;let n=new Set(t);for(let[s,o]of Aw)if(n.has(s))return o;return"npm"}function Cw(e,t){switch(e){case"pnpm":return`pnpm ${t}`;case"yarn":return`yarn ${t}`;case"bun":return`bun run ${t}`;default:return t==="test"?"npm test":`npm run ${t}`}}function $w(e,t="npm"){let r=[];if(!e||typeof e!="object")return r;for(let n of bw){let s=n.candidates.find(o=>typeof e[o]=="string"&&e[o].trim()!=="");s&&r.push({name:s,command:Cw(t,s),detected:!0})}return r}function Ow(e,t=[]){return{schemaVersion:hc,checks:$w(e?.scripts,_w(e,t)),diffSizeCap:{...Xd},protectedPaths:[]}}async function oi(e){let t=wn(e,ue);if(await w(t))return{created:!1,path:ue,checks:[]};let r=null;try{r=JSON.parse(await si(wn(e,"package.json"),"utf-8"))}catch{r=null}let n=[];try{n=await ww(e)}catch{n=[]}let s=Ow(r,n);return await P(Jd(t),{recursive:!0}),await A(t,`${JSON.stringify(s,null,2)}
|
|
66
|
+
`,"utf-8"),{created:!0,path:ue,checks:s.checks.map(o=>o.name)}}function Tw(e){let t=[];if(!e||typeof e!="object"||Array.isArray(e))return["config is not an object"];e.schemaVersion!==hc&&t.push(`schemaVersion must be ${hc}`),Array.isArray(e.checks)?e.checks.forEach((n,s)=>{if(!n||typeof n!="object"){t.push(`checks[${s}] is not an object`);return}(typeof n.name!="string"||!n.name.trim())&&t.push(`checks[${s}].name must be a non-empty string`),(typeof n.command!="string"||!n.command.trim())&&t.push(`checks[${s}].command must be a non-empty string`)}):t.push("checks must be an array");let r=e.diffSizeCap;if(r!==void 0)if(!r||typeof r!="object")t.push("diffSizeCap must be an object");else for(let n of["files","lines"])r[n]!==void 0&&!(Number.isInteger(r[n])&&r[n]>=0)&&t.push(`diffSizeCap.${n} must be a non-negative integer`);return e.protectedPaths!==void 0&&(!Array.isArray(e.protectedPaths)||e.protectedPaths.some(n=>typeof n!="string"))&&t.push("protectedPaths must be an array of strings"),t}async function Qd(e){let t;try{t=await si(wn(e,ue),"utf-8")}catch{return{ok:!1,reason:"missing",errors:[`${ue} not found`]}}let r;try{r=JSON.parse(t)}catch(s){return{ok:!1,reason:"invalid",errors:[`${ue} is not valid JSON: ${s.message}`]}}let n=Tw(r);return n.length?{ok:!1,reason:"invalid",errors:n}:{ok:!0,config:{...r,diffSizeCap:{...Xd,...r.diffSizeCap||{}},protectedPaths:r.protectedPaths||[]}}}function Yd(e){let t=String(e).trim().replace(/^`+|`+$/g,"").replace(/^\*\*|\*\*$/g,"");if(t=t.replace(/[:,;)\]}.]+$/g,""),t=t.replace(/^\.\//,""),!t||/\s/.test(t)||/^(https?:|www\.|--|-)/.test(t))return null;let r=t.endsWith("/"),n=r?t.slice(0,-1):t;return!Pw.test(n)||!r&&!n.includes("/")&&!Iw.test(n)||/^\.+$/.test(n)?null:r?`${n}/`:n}function Mw(e){let t=new Set,r=String(e||"");for(let i of r.matchAll(/`([^`\n]+)`/g)){let a=Yd(i[1]);a&&t.add(a)}let n=r.split(/\r?\n/),s=!1,o=-1;for(let i of n){if(jw.test(i)){s=!0,o=-1;continue}if(!s)continue;if(!i.trim()){o>=0&&(s=!1);continue}if(Rw.test(i)||Nw.test(i)){s=!1;continue}let a=Lw.exec(i);if(!a){o>=0&&(s=!1);continue}let c=i.length-i.trimStart().length;if(o<0)o=c;else if(c<o){s=!1;continue}let l=a[1].trim().split(/\s+/)[0],d=Yd(l);d&&t.add(d)}return[...t].sort()}function Gw(e){let t=vw(e);if(!/-plan\.md$/i.test(t))return[];let r=t.replace(/-plan\.md$/i,"-details.md"),n=Jd(e);return[wn(n,"..","details",r),wn(n,r)]}async function Zd(e){let t=[e];for(let s of Gw(e))if(await w(s)){t.push(s);break}let r=await Promise.all(t.map(s=>si(s,"utf-8"))),n=new Set;for(let s of r)for(let o of Mw(s))n.add(o);return{planned:[...n].sort(),sources:t}}function Fw(e,t){for(let r of t)if(r===e||r.endsWith("/")&&e.startsWith(r))return!0;return!1}function Dw(e,t){let r=e.filter(n=>!n.startsWith(Sw)).filter(n=>!Fw(n,t)).sort();return{planned:[...t].sort(),unplanned:r,skipped:null}}function Vw(e){if(fc.has(e))return fc.get(e);let t=String(e).replace(/^\.\//,"").replace(/\/+$/,""),r="";for(let s=0;s<t.length;s+=1){let o=t[s];o==="*"?t[s+1]==="*"?t[s+2]==="/"?(r+="(?:.*/)?",s+=2):(r+=".*",s+=1):r+="[^/]*":o==="?"?r+="[^/]":r+=o.replace(/[.+^${}()|[\]\\]/g,"\\$&")}let n=new RegExp(`^${r}(?:/.*)?$`);return fc.set(e,n),n}function Hw(e,t){return Vw(t).test(String(e).replace(/^\.\//,""))}function Uw(e,t){return t?.length?e.filter(r=>t.some(n=>Hw(r,n))).sort():[]}function ep({config:e,checks:t,diff:r,planned:n,diffSkipped:s=null}){let o=[],i=t.map(p=>({name:p.name,command:p.command,exitCode:p.exitCode,durationMs:p.durationMs,tail:p.tail||[]}));for(let p of i)p.exitCode!==0&&o.push(`${p.name} exit ${p.exitCode===null?"signal":p.exitCode}`);let a={files:e.diffSizeCap.files,lines:e.diffSizeCap.lines},c,l,d=[];if(r)n===null?c={planned:[],unplanned:[],skipped:"no --plan given"}:(c=Dw(r.changed,n),c.unplanned.length&&o.push(`unplanned files: ${c.unplanned.join(", ")}`)),l={files:r.changed.length,lines:r.lines,cap:a,skipped:null},l.files>a.files&&o.push(`size ${l.files} files > cap ${a.files}`),l.lines>a.lines&&o.push(`size ${l.lines} lines > cap ${a.lines}`),d=Uw(r.changed,e.protectedPaths),d.length&&o.push(`protected path touched: ${d.join(", ")}`);else{let p=s||"not a git repository";c={planned:n?[...n].sort():[],unplanned:[],skipped:p},l={files:null,lines:null,cap:a,skipped:p}}return{pass:o.length===0,reasons:o,checks:i,plan:c,size:l,protected:d}}function tp(e){let t=[];for(let r of e.checks)if(r.exitCode===0)t.push(`\u2713 ${r.name} (${(r.durationMs/1e3).toFixed(1)}s)`);else{t.push(`\u2717 ${r.name} (${r.exitCode===null?"killed by signal":`exit ${r.exitCode}`})`);for(let n of r.tail)t.push(` ${n}`)}return e.plan.skipped?t.push(`plan: skipped (${e.plan.skipped})`):e.plan.unplanned.length?t.push(`plan: unplanned: ${e.plan.unplanned.join(", ")}`):t.push("plan: ok"),e.size.skipped?t.push(`size: skipped (${e.size.skipped})`):t.push(`size: ${e.size.files} files / ${e.size.lines} lines (cap ${e.size.cap.files} / ${e.size.cap.lines})`),e.size.skipped?t.push(`protected: skipped (${e.size.skipped})`):e.protected.length?t.push(`protected: ${e.protected.join(", ")}`):t.push("protected: ok"),t.push(e.pass?"GATE PASS":`GATE FAIL: ${e.reasons.join("; ")}`),t.join(`
|
|
67
|
+
`)}function Ww(e,t=kw){let r=String(e||"").replace(/\r\n/g,`
|
|
68
68
|
`).split(`
|
|
69
|
-
`);for(;r.length&&r[r.length-1]==="";)r.pop();for(;r.length&&r[0]==="";)r.shift();return r.slice(-t)}function
|
|
70
|
-
${n.error.message}`:""}`,i=n.error&&n.status===null?127:n.status;return{name:e.name,command:e.command,exitCode:i,durationMs:s,tail:
|
|
71
|
-
`),i=new Set([""]);typeof s=="string"&&s&&i.add(s);for(let a of e.keys()){if(!a.startsWith(`${r}/`))continue;let c=a.slice(r.length+1);if(n.length>c.length&&n.endsWith(c)){let l=n.slice(0,n.length-c.length);/^[a-z0-9-]+$/.test(l)&&i.add(l)}}for(let a of i){if(a&&!n.startsWith(a))continue;let c=e.get(`${r}/${n.slice(a.length)}`);if(c){for(let l of new Set([o,
|
|
72
|
-
`),r=/^---\n([\s\S]*?)\n---(?:\n|$)/.exec(t);return r?{raw:r[1],body:t.slice(r[0].length)}:{raw:"",body:t}}function
|
|
69
|
+
`);for(;r.length&&r[r.length-1]==="";)r.pop();for(;r.length&&r[0]==="";)r.shift();return r.slice(-t)}function rp(e,t){let r=Date.now(),n=qd("sh",["-c",e.command],{cwd:t,env:process.env,encoding:"utf-8",stdio:["ignore","pipe","pipe"],maxBuffer:64*1024*1024}),s=Date.now()-r,o=`${n.stdout||""}${n.stderr||""}${n.error?`
|
|
70
|
+
${n.error.message}`:""}`,i=n.error&&n.status===null?127:n.status;return{name:e.name,command:e.command,exitCode:i,durationMs:s,tail:Ww(o)}}function yn(e,t){let r=qd("git",t,{cwd:e,env:{...process.env,...Rt},encoding:"utf-8",stdio:["ignore","pipe","ignore"],maxBuffer:67108864});return{status:r.error?-1:r.status,stdout:r.stdout||""}}async function Kw(e){try{let t=await si(e);if(t.includes(0))return 0;let r=0;for(let n of t)n===10&&(r+=1);return t.length&&t[t.length-1]!==10&&(r+=1),r}catch{return 0}}async function np(e,t){let r=yn(e,["rev-parse","--is-inside-work-tree"]);if(r.status!==0||r.stdout.trim()!=="true")return{skipped:"not a git repository"};let n=t;if(!n)n=yn(e,["rev-parse","--verify","--quiet","HEAD"]).status===0?"HEAD":Ew;else if(yn(e,["rev-parse","--verify","--quiet",`${n}^{commit}`]).status!==0)return{skipped:`unknown --base ref "${t}"`};let s=yn(e,["diff","--name-only","-z",n,"--"]);if(s.status!==0)return{skipped:`git diff against ${n} failed`};let o=yn(e,["diff","--numstat","-z",n,"--"]),i=yn(e,["ls-files","--others","--exclude-standard","-z"]),a=new Set(s.stdout.split("\0").filter(Boolean)),c=i.status===0?i.stdout.split("\0").filter(Boolean):[];for(let d of c)a.add(d);let l=0;for(let d of o.stdout.split("\0")){let p=/^(\d+|-)\t(\d+|-)\t?/.exec(d);p&&(p[1]!=="-"&&(l+=Number(p[1])),p[2]!=="-"&&(l+=Number(p[2])))}for(let d of c)l+=await Kw(wn(e,d));return{changed:[...a].sort(),lines:l}}var ue,hc,Xd,kw,Sw,Rr,Ew,bw,xw,Aw,Pw,Iw,jw,Rw,Nw,Lw,fc,As=Z(()=>{U();vt();ue=".vesper/gates.json",hc=1,Xd=Object.freeze({files:40,lines:1500}),kw=30,Sw=".vesper/.tracking/",Rr=Object.freeze({PASS:0,FAIL:1,NO_CONFIG:2}),Ew="4b825dc642cb6eb9a060e54bf8d69288fbee4904",bw=Object.freeze([{candidates:["test"]},{candidates:["lint"]},{candidates:["typecheck","tsc","type-check"]},{candidates:["build"]}]),xw=Object.freeze(["npm","pnpm","yarn","bun"]),Aw=Object.freeze([["pnpm-lock.yaml","pnpm"],["yarn.lock","yarn"],["bun.lockb","bun"],["bun.lock","bun"],["package-lock.json","npm"]]);Pw=/^(?:[\w.@-]+\/)*[\w.@-]+(?:\.[A-Za-z0-9]+)?$/,Iw=/\.[A-Za-z0-9]{1,10}$/;jw=/^\s*(?:#{1,6}\s*|[-*]\s*\*\*)(?:files?(?:\s+operations?)?|file\s+list)\*{0,2}\s*:?\s*$/i,Rw=/^\s*#{1,6}\s/,Nw=/^\s*[-*]\s*\*\*[^*]+\*\*\s*:?/,Lw=/^\s*[-*+]\s+(.*)$/;fc=new Map});import{readFileSync as Bw}from"node:fs";import{join as zw}from"node:path";function vn(){if(ii)return ii;let e={};try{e=JSON.parse(Bw(Yw,"utf-8"))}catch{e={}}return ii={files:mc(e.files),playbook:new Set(Array.isArray(e.playbook)?e.playbook.filter(t=>typeof t=="string"):[]),pluginFiles:mc(e.pluginFiles),pluginDescriptions:new Set(Array.isArray(e.pluginManifestDescriptions)?e.pluginManifestDescriptions.filter(t=>typeof t=="string"):[]),vendoredFiles:mc(e.vendoredFiles)},ii}function Jw(e,t){return t?e.replace(/^(name:\s*)([a-z0-9-]+)/m,(r,n,s)=>s.startsWith(t)?`${n}${s.slice(t.length)}`:r):e}function sp(e,t,r,n,s){let o=t.toString("utf-8").replace(/\r\n/g,`
|
|
71
|
+
`),i=new Set([""]);typeof s=="string"&&s&&i.add(s);for(let a of e.keys()){if(!a.startsWith(`${r}/`))continue;let c=a.slice(r.length+1);if(n.length>c.length&&n.endsWith(c)){let l=n.slice(0,n.length-c.length);/^[a-z0-9-]+$/.test(l)&&i.add(l)}}for(let a of i){if(a&&!n.startsWith(a))continue;let c=e.get(`${r}/${n.slice(a.length)}`);if(c){for(let l of new Set([o,Jw(o,a)]))if(c.has(dt(Buffer.from(l,"utf-8"))))return!0}}return!1}function ai(e,t,{namePrefix:r}={}){let n=/^(agents|commands)\/([^/]+\.md)$/.exec(String(t||""));return n?sp(vn().files,e,n[1],n[2],r):!1}function op(e){return vn().playbook.has(dt(e))}function ip(e){if(!e||e.includes("/")||e.includes(".."))return null;let t=`skills/${e}/`,r={};for(let[n,s]of vn().files)n.startsWith(t)&&(r[n.slice(t.length)]=[...s]);return Object.keys(r).length?r:null}function ci(e,t,r){let{files:n}=vn();return n.has(`${e}/${t}`)?!0:!!r&&t.startsWith(r)&&n.has(`${e}/${t.slice(r.length)}`)}function ap(e,t,{pluginName:r="vesper"}={}){let n=String(t||""),{pluginFiles:s,pluginDescriptions:o}=vn();if(n===".claude-plugin/plugin.json"){let c;try{c=JSON.parse(e.toString("utf-8"))}catch{return!1}return!c||typeof c!="object"||Array.isArray(c)?!1:Object.keys(c).sort().join(",")==="description,name,version"&&c.name===r&&o.has(c.description)&&typeof c.version=="string"}let i=/^(agents|commands)\/([^/]+\.md)$/.exec(n);if(i)return sp(s,e,i[1],i[2]);let a=s.get(n);return!!a&&a.has(dt(e))}function gc(e,t){let r=vn().vendoredFiles.get(String(t||""));return!!r&&r.has(dt(e))}var Yw,ii,mc,_s=Z(()=>{xe();Ye();Yw=zw(O,"legacy","claude-1x-digests.json"),ii=null,mc=e=>{let t=new Map;for(let[r,n]of Object.entries(e||{}))Array.isArray(n)&&t.set(r,new Set(n.filter(s=>typeof s=="string")));return t}});import{readFile as cp,readdir as qw}from"node:fs/promises";import{join as Nr}from"node:path";import{homedir as Xw}from"node:os";function lp(e=yc,t=Xw()){return Nr(t,".claude","skills",e)}async function Zw(e){for(let t of["agents","commands","skills"])if(!await w(Nr(e,t)))return!1;for(let t of["agents","commands"]){let r;try{r=await qw(Nr(e,t),{withFileTypes:!0})}catch{continue}if(r.some(n=>n.isFile()&&n.name.startsWith("vesper-")))return!0}return!1}function up({pluginName:e,workspaceRoot:t}){return async(r,n)=>{if(ap(n,r,{pluginName:e}))return!0;let s=/^skills\/([^/]+)\/(.+)$/.exec(r);if(!s||!Qw.includes(s[1]))return!1;let o=Or(s[1]),i=[...o?[o.dir]:[],...t?[Nr(t,".claude","skills",s[1]),Nr(t,".vesper","skills",s[1])]:[]];for(let a of i)try{if(ee(n,await cp(Nr(a,s[2]))))return!0}catch{}return!1}}async function Cs({pluginName:e=yc,staleDir:t,homeDir:r,workspaceRoot:n}={}){if(typeof e!="string"||e===""||/[\\/]|\.\./.test(e))return{reason:"not-ours",proven:[],kept:[]};let s=t??lp(e,r);if(!await w(s))return{reason:"absent",proven:[],kept:[]};let o="not-ours",i=null;try{let c=JSON.parse(await cp(Nr(s,".claude-plugin","plugin.json"),"utf-8"));c&&c.name===e&&(o="match",typeof c.version=="string"&&/^1\.\d+\.\d+/.test(c.version)&&(i=c.version))}catch{}if(o==="not-ours"&&await Zw(s)&&(o="manifest-less-ours"),o==="not-ours")return{reason:o,path:s,proven:[],kept:[]};let a=await Gt(s,{sourceMatch:up({pluginName:e,workspaceRoot:n}),anchor:null});return{reason:o,path:s,proven:a.proven,kept:a.kept,version:i}}async function dp({pluginName:e=yc,staleDir:t,homeDir:r,workspaceRoot:n,backup:s}={}){let o=await Cs({pluginName:e,staleDir:t,homeDir:r,workspaceRoot:n});if(o.reason==="absent"||o.reason==="not-ours")return{removed:!1,reason:o.reason,...o.path?{path:o.path}:{}};if(!o.proven.length)return{removed:!1,reason:"nothing-proven",path:o.path,kept:o.kept};if(typeof s!="function")return{removed:!1,reason:"no-backup",path:o.path,kept:o.kept};let i,a;try{i=await s(o.path),a=await cs(o.path,{sourceMatch:up({pluginName:e,workspaceRoot:n}),anchor:null})}catch(c){return{removed:!1,reason:"remove-failed",path:o.path,error:c&&c.message?c.message:String(c),...i?{backedUpTo:i}:{}}}return{removed:a.status==="removed",partial:a.status==="partial",reason:o.reason,path:o.path,removedFiles:a.removed,kept:a.kept,backedUpTo:i}}var yc,Qw,wc=Z(()=>{U();Ye();_s();Tr();yc="vesper",Qw=Object.freeze(["gitlab-ci-skill","github-actions-to-gitlab-ci"])});function nv(e){return String(e).replace(/[^a-zA-Z0-9_-]/g,"_")}function sv(e,t=li){return`${t||li}:${e}`}function ov(e){let t=String(e??"").trim();if(!(!t||t==="inherit")){if(t.includes("/"))return t;if(t.startsWith("claude-"))return`${ev}${t}`}}function iv(e){if(e==null)return null;let r=(Array.isArray(e)?e:String(e).split(",")).map(n=>String(n).trim()).filter(Boolean);return r.length?r:null}function av(e){let t=iv(e);if(t===null)return{permission:{},unmapped:[],restricted:!1};let r=new Set,n=new Set,s=[];for(let i of t){let a=/^mcp__(.+?)__(.+)$/.exec(i);if(a){n.add(`${nv(a[1])}_*`);continue}let c=tv[i];c?r.add(c):s.push(i)}let o={};for(let i of rv)o[i]=r.has(i)?"allow":"deny";for(let i of r)i in o||(o[i]="allow");for(let i of[...n].sort())o[i]="allow";return{permission:o,unmapped:s,restricted:!0}}function cv(e){let t=String(e??"").replace(/\r\n/g,`
|
|
72
|
+
`),r=/^---\n([\s\S]*?)\n---(?:\n|$)/.exec(t);return r?{raw:r[1],body:t.slice(r[0].length)}:{raw:"",body:t}}function vc(e){let t=String(e).trim();if(t.startsWith('"')&&t.endsWith('"')&&t.length>=2)try{return JSON.parse(t)}catch{return t.slice(1,-1)}return t.startsWith("'")&&t.endsWith("'")&&t.length>=2?t.slice(1,-1).replace(/''/g,"'"):t}function lv(e){let t={},r=String(e??"").replace(/\r\n/g,`
|
|
73
73
|
`).split(`
|
|
74
74
|
`);for(let n=0;n<r.length;n++){let s=r[n];if(!s.trim()||/^\s*#/.test(s))continue;let o=/^([A-Za-z0-9_-]+):\s*(.*)$/.exec(s);if(!o)continue;let i=o[1],a=o[2].trim();if(/^[>|]-?$/.test(a)){let c=[];for(;n+1<r.length&&(/^\s+\S/.test(r[n+1])||r[n+1].trim()==="");)c.push(r[++n].trim());for(;c.length&&c[c.length-1]==="";)c.pop();t[i]=a.startsWith(">")?c.join(" ").replace(/\s+/g," "):c.join(`
|
|
75
|
-
`);continue}if(a===""){let c=[];for(;n+1<r.length&&/^\s*-\s/.test(r[n+1]);)c.push(
|
|
76
|
-
`)}function
|
|
77
|
-
${d}`;return{id:
|
|
78
|
-
`);return`${
|
|
75
|
+
`);continue}if(a===""){let c=[];for(;n+1<r.length&&/^\s*-\s/.test(r[n+1]);)c.push(vc(r[++n].replace(/^\s*-\s*/,"")));t[i]=c.length?c:"";continue}if(a.startsWith("[")&&a.endsWith("]")){t[i]=a.slice(1,-1).split(",").map(c=>vc(c)).filter(c=>c!=="");continue}t[i]=vc(a)}return t}function kc(e){let{raw:t,body:r}=cv(e);return{frontmatter:lv(t),body:r}}function uv(e){return/^[A-Za-z_][A-Za-z0-9_-]*$/.test(e)?e:JSON.stringify(e)}function pp({description:e,mode:t,model:r,permission:n}){let s=["---",`description: ${JSON.stringify(e)}`,`mode: ${t}`];if(r&&s.push(`model: ${r}`),n&&Object.keys(n).length){s.push("permission:");for(let[o,i]of Object.entries(n))s.push(` ${uv(o)}: ${i}`)}return s.push("---"),s.join(`
|
|
76
|
+
`)}function fp({name:e,frontmatter:t={},body:r="",plugin:n=li}={}){if(!e||typeof e!="string")throw new Error("convertClaudeAgent: `name` is required");let s=t&&typeof t=="object"?t:{},o=String(s.description??"").replace(/\s+/g," ").trim()||`Vesper specialist: ${e}`,i=ov(s.model),{permission:a,unmapped:c,restricted:l}=av(s.tools),d=String(r??""),p={description:o,mode:"subagent"};i&&(p.model=i),l&&(p.permission=a),p.prompt=d;let f=`${pp({description:o,mode:"subagent",model:i,permission:l?a:void 0})}
|
|
77
|
+
${d}`;return{id:sv(e,n),name:e,plugin:n||li,markdown:f,config:p,unmapped:c}}function ui({source:e,description:t}={}){let r=t;!r&&e&&(r=kc(e).frontmatter.description),r=String(r||pv).replace(/\s+/g," ").trim();let n=["# Vesper (Super Orchestrator) \u2014 OpenCode primary agent","","You are Vesper, the super-orchestrator for this project. Your complete operating playbook \u2014","the mandatory delegation law, the purpose router, every pipeline, the degraded-mode carve-out","and the host-mismatch warning \u2014 is the **always-on rules** `opencode.json` loads through","`instructions` into every session:","",...dv.map(([s,o])=>`- \`${s}\` \u2014 ${o}.`),"","This agent file is intentionally thin: it exists so `opencode.json` `default_agent:",'"vesper-orchestrator"` resolves a real primary agent. All behavior lives in the rules above \u2014',"follow them exactly. Do not restate or override them here.","","Specialists are delegated to by their namespaced names (`vesper:<name>` for the core catalog,","`vesper-<pack>:<name>` for an enabled pack), registered by the Vesper plugin","(`.opencode/plugins/vesper.js`) from the installed `@mthanh/vespercli` package \u2014 or, when",'`vesper.agentsMode` is `"files"`, from the generated `.opencode/agents/<id>.md` files. The',"committed maintenance skills resolve from `.claude/skills/` and are invoked unqualified","(`/reinit`, `/compact-knowledge`, `/revalidate-knowledge`, `/revalidate-team`).",""].join(`
|
|
78
|
+
`);return`${pp({description:r,mode:"primary"})}
|
|
79
79
|
|
|
80
|
-
${n}`}var
|
|
81
|
-
`),t=/^---\n[\s\S]*?\n---\n/.exec(e);return(t?e.slice(t[0].length):e).trim()}catch{return null}}async function
|
|
80
|
+
${n}`}var li,Lr,ev,tv,rv,dv,pv,di=Z(()=>{li="vesper",Lr=".opencode/agents",ev="anthropic/",tv=Object.freeze({Read:"read",Write:"edit",Edit:"edit",MultiEdit:"edit",NotebookEdit:"edit",Bash:"bash",Grep:"grep",Glob:"glob",LS:"list",WebFetch:"webfetch",WebSearch:"websearch",Task:"task",Agent:"task",TodoWrite:"todowrite",TodoRead:"todowrite",AskUserQuestion:"question",Skill:"skill"}),rv=Object.freeze(["read","edit","glob","grep","bash","task","todowrite","webfetch","websearch","question"]);dv=Object.freeze([[".claude/rules/vesper-orchestrator.md","the orchestrator playbook (delegation law, purpose router, pipelines, degraded mode, host-mismatch warning)"],[".claude/rules/vesper-orchestration.md","the team roster + task-management config (the single authority for which `vesper:<name>` specialist fills which role)"],[".claude/rules/vesper-context.md","the slim project whitepaper (architecture, domain model, workflows, freshness)"]]),pv="Vesper super-orchestrator \u2014 the primary agent of a Vesper-managed project on OpenCode. Routes every request to the specialist team per the always-on orchestrator playbook and team roster in `.claude/rules/`."});import{readFileSync as fv}from"node:fs";import{readFile as hp}from"node:fs/promises";import{join as Sc,dirname as hv}from"node:path";function gp(e){return`${Me(e)}@${Oe}`}function mv(e){return Er(e)!==null}function pi(e=O){let t=null;try{t=JSON.parse(fv(Sc(e,"manifest.json"),"utf-8"))}catch{t=null}return{packs:Array.isArray(t?.packs)?[...t.packs]:[],agents:Array.isArray(t?.agents)?[...t.agents]:[],skills:Array.isArray(t?.skills)?[...t.skills]:[],assetPacks:{agents:{...t?.assetPacks?.agents||{}},skills:{...t?.assetPacks?.skills||{}}}}}function nt(e=O){return[...pi(e).packs].sort()}function yp(e,t=O){let r=pi(t),n=s=>Object.keys(s).filter(o=>s[o]===e).sort();return{agents:n(r.assetPacks.agents),skills:n(r.assetPacks.skills)}}async function Ec(e){try{let t=JSON.parse(await hp(Fe(e),"utf-8"));return t&&typeof t=="object"&&!Array.isArray(t)?t:null}catch{return null}}async function Mr(e,t){let r=new Set(nt()),n=new Set,s=new Set;if(t==="claude"){let i=(await Ec(e))?.enabledPlugins;if(i&&typeof i=="object"&&!Array.isArray(i))for(let[a,c]of Object.entries(i)){let l=Er(a);!l||c!==!0||(r.has(l)?n:s).add(l)}}else if(t==="copilot"){let o=await K(e);for(let i of Oo())for(let{path:a,settingKey:c}of sr(i))if(o[c]?.[a]===!0){n.add(i);break}}return{enabled:[...n].sort(),unknown:[...s].sort()}}async function Wt(e,t){return(await Mr(e,t)).enabled}async function wp(e,t){let n=(await ne(e)).find(i=>i&&i.path===jt&&i.host==="claude"&&i.category==="settings"),o={keys:Array.isArray(n?.owns?.keys)&&n.owns.keys.length?[...n.owns.keys]:[...gv]};t.length&&(o.entries=[...t].sort()),await W(e,[Y({path:jt,host:"claude",category:"settings",owns:o})])}async function vp(e){let r=(await ne(e)).find(n=>n&&n.path===jt&&n.host==="claude"&&n.category==="settings");return(Array.isArray(r?.owns?.entries)?r.owns.entries:[]).filter(mv).sort()}async function kp(e,t){if(!await w(Sc(e,Zt)))return;await W(e,[Y({path:Zt,host:"copilot",category:"settings",owns:{keys:[...Lt],entries:[...t]}})]);let r=await x(e);if(Number(r.schemaVersion)===2&&fs.some(n=>n in r)){for(let n of fs)delete r[n];await T(e,r)}}function Sp(e){if(!nt().includes(e))throw new Error(`Unknown pack "${e}". Available packs: ${nt().join(", ")||"none"}.`)}async function lr(e,t,r){Sp(r);let n=await yv(e,t,r);if(jr(r)){let s=await Td(e,t,r);s&&(n.rule=s)}return r===Ge&&(n.graphify=await Es(e,t),n.graphify.mcp=t==="claude"?await Sn(e,pt):await ir(e,pt)),n}async function yv(e,t,r){if(t==="claude"){let n=Fe(e),s=await Ec(e);if(s===null&&await w(n))throw new Error(`${jt} is malformed \u2014 fix it before enabling a pack (nothing was written).`);s=s||{},(!s.enabledPlugins||typeof s.enabledPlugins!="object"||Array.isArray(s.enabledPlugins))&&(s.enabledPlugins={});let o=gp(r),i=s.enabledPlugins[o]===!0;i||(s.enabledPlugins[o]=!0,await P(hv(n),{recursive:!0}),await A(n,JSON.stringify(s,null," "),"utf-8"));let a=new Set([...await vp(e),o]);return await wp(e,[...a]),await fi(e,await Wt(e,"claude")),{pack:r,enabled:!i}}if(t==="copilot"){let n=sr(r),{added:s}=await Zr(e,n),o=new Set([...await At(e),...n.map(i=>i.path)]);return await kp(e,[...o]),{pack:r,enabled:s.length>0}}throw new Error(`Unknown host "${t}"`)}async function Ep(e,t,r){Sp(r);let n=await wv(e,t,r);if(jr(r)){let s=await oc(e,t,r);s&&(n.rule=s)}return r===Ge&&(n.graphify=await mn(e,t),n.graphify.mcp=t==="claude"?await hi(e,pt):await nn(e,pt)),n}async function wv(e,t,r){if(t==="claude"){let n=Fe(e),s=await Ec(e),o=gp(r),i=!1;s?.enabledPlugins&&typeof s.enabledPlugins=="object"&&o in s.enabledPlugins&&(delete s.enabledPlugins[o],Object.keys(s.enabledPlugins).length===0&&delete s.enabledPlugins,await A(n,JSON.stringify(s,null," "),"utf-8"),i=!0);let a=(await vp(e)).filter(c=>c!==o);return await wp(e,a),await fi(e,await Wt(e,"claude")),{pack:r,disabled:i}}if(t==="copilot"){let n=sr(r).map(i=>i.path),{removed:s}=await Ma(e,n),o=(await At(e)).filter(i=>!n.includes(i));return await kp(e,o),{pack:r,disabled:s.length>0}}throw new Error(`Unknown host "${t}"`)}async function ur(e,t){let r=kn[t];if(!r)return null;try{return await hp(Sc(e,r),"utf-8")}catch{return null}}async function dr(e,t){let r=t||await _t(),n={},s=(a,c,l)=>{n[a]||(n[a]={agents:[],skills:[]}),n[a][c].includes(l)||n[a][c].push(l)},o=[],i=[];for(let a of Ad(e||"")){let c=r.agentPack.get(a);if(c===void 0){Object.hasOwn(Jo,a)||o.push(a);continue}c!=="core"&&s(c,"agents",a)}for(let a of _d(e||"")){let c=r.skillPack.get(a);if(c===void 0){i.push(a);continue}c!=="core"&&s(c,"skills",a)}for(let a of Object.values(n))a.agents.sort(),a.skills.sort();return{needed:n,packs:Object.keys(n).sort(),unknownAgents:o,unknownSkills:i}}async function pr(e,t,{dryRun:r=!1}={}){let n=kn[t],s=await ur(e,t),o=await dr(s||""),i=await Wt(e,t),a=[],c=[];for(let d of o.packs){if(i.includes(d)){c.push(d);continue}r||await lr(e,t,d),a.push(d)}let l=i.filter(d=>!o.packs.includes(d));return!r&&i.includes(Ge)&&await Es(e,t),t==="claude"&&!r&&await fi(e,await Wt(e,"claude")),{host:t,rosterPath:n,rosterFound:s!==null,needed:o.needed,packs:o.packs,enabled:a,already:c,unused:l,unknownAgents:o.unknownAgents,unknownSkills:o.unknownSkills}}async function bp(e){let r=(await _t()).agentPlugin.get(un(e).name);return r?`${r}:${un(e).name}`:null}var R_,kn,mp,gv,Kt=Z(()=>{xe();H();te();fe();_e();U();dn();pn();$s();ft();R_=Object.freeze(["graphify","styles"]),kn=Object.freeze({claude:".claude/rules/vesper-orchestration.md",copilot:".vesper/instructions/vesper-orchestration.instructions.md"}),mp="vespercli packs sync";gv=Object.freeze(["permissions.allow","hooks.SessionStart","agent","enabledPlugins"])});var Cp={};Nn(Cp,{OPENCODE_AGENTS_MODES:()=>bc,OPENCODE_AGENT_CATEGORY:()=>Os,OPENCODE_CONFIG_RELATIVE:()=>Ts,default:()=>Sv,listCatalogAgentSources:()=>Ac,openCodeAgentRelative:()=>_c,orchestratorAgentMarkdown:()=>_p,readOpenCodeVesperSettings:()=>xc,recordedOpenCodeAgentFiles:()=>Ap,renderOpenCodeAgentFiles:()=>gi,renderOpenCodeAgents:()=>Cc});import{readdir as vv,readFile as mi}from"node:fs/promises";import{join as fr}from"node:path";async function xc(e){let t={packs:null,agentsMode:"plugin"};try{let r=JSON.parse(await mi(fr(e,Ts),"utf-8")),n=r&&typeof r=="object"?r.vesper:null;n&&typeof n=="object"&&(Array.isArray(n.packs)&&(t.packs=n.packs.filter(s=>typeof s=="string")),bc.includes(n.agentsMode)&&(t.agentsMode=n.agentsMode))}catch{}return t}async function xp(e){try{return(await vv(e)).filter(t=>t.endsWith(".md")).sort()}catch{return[]}}async function Ac(e=[],t=O){let r=[],n=fr(t,"claude","agents");for(let o of await xp(n))r.push({name:o.slice(0,-3),plugin:Vt,pack:"core",path:fr(n,o)});let s=new Set(nt(t));for(let o of[...new Set(e)].sort()){if(!s.has(o))continue;let i=fr(t,"claude","packs",o,"agents");for(let a of await xp(i))r.push({name:a.slice(0,-3),plugin:Me(o),pack:o,path:fr(i,a)})}return r}function _c(e){return`${Lr}/${e}.md`}async function Cc(e=[],t=O){let r=[];for(let n of await Ac(e,t)){let{frontmatter:s,body:o}=kc(await mi(n.path,"utf-8")),i=fp({name:n.name,frontmatter:s,body:o,plugin:n.plugin});r.push({...i,pack:n.pack,path:_c(i.id)})}return r}async function kv(e,t){if(Array.isArray(t))return[...new Set(t)].sort();let r=(await xc(e)).packs;return r?[...new Set(r)].sort():Wt(e,"claude")}async function gi(e,{packs:t}={}){let r=await kv(e,t),n=await Cc(r),s=fr(e,Lr);n.length&&await P(s,{recursive:!0});let o=[],i=[],a=[];for(let d of n){let p=fr(e,d.path),f=null;if(await w(p))try{f=await mi(p,"utf-8")}catch{f=null}f===d.markdown?i.push(d.path):(await A(p,d.markdown,"utf-8"),o.push(d.path)),a.push(G({path:d.path,host:"claude",category:Os,hash:ps(d.markdown)}))}let{pruned:c,kept:l}=await cn(e,a,{categories:[Os]});return{packs:r,written:o,unchanged:i,pruned:c,kept:l,agents:n.map(d=>d.id)}}async function Ap(e){return(await ne(e)).filter(r=>r.host==="claude"&&r.category===Os).map(r=>r.path).sort()}async function _p(e=O){let t;try{t=await mi(fr(e,"claude-committed","agents","vesper-orchestrator.md"),"utf-8")}catch{t=void 0}return ui({source:t})}var Os,Ts,bc,Sv,$c=Z(()=>{xe();U();te();Kt();dn();di();Os="opencode-agent",Ts="opencode.json",bc=Object.freeze(["plugin","files"]);Sv={OPENCODE_AGENT_CATEGORY:Os,OPENCODE_CONFIG_RELATIVE:Ts,OPENCODE_AGENTS_MODES:bc,readOpenCodeVesperSettings:xc,listCatalogAgentSources:Ac,openCodeAgentRelative:_c,renderOpenCodeAgents:Cc,renderOpenCodeAgentFiles:gi,recordedOpenCodeAgentFiles:Ap,orchestratorAgentMarkdown:_p}});import{readFile as js,rm as Ev,rmdir as bv}from"node:fs/promises";import{join as Bt,dirname as Op}from"node:path";function Ov(e){return{type:"local",command:["vespercli","mcp","serve",e],enabled:!0}}async function Tc(){try{let e=ui();if(typeof e=="string"&&e.trim())return e}catch{}return Pv()}async function Tv(){try{let e=(await js(Bt(O,"claude-committed","agents",`${L}.md`),"utf-8")).replace(/\r\n/g,`
|
|
81
|
+
`),t=/^---\n[\s\S]*?\n---\n/.exec(e);return(t?e.slice(t[0].length):e).trim()}catch{return null}}async function Pv(){return["---","description: Vesper super-orchestrator \u2014 routes every request to the specialist team per the always-on playbook and Team Roster in .claude/rules/ (Claude Code host, OpenCode overlay).","mode: primary","---","",await Tv()||`# Vesper (Super Orchestrator)
|
|
82
82
|
|
|
83
|
-
Follow the always-on rules in \`${
|
|
84
|
-
`)}async function $c(){return Ts(wv)}function fi(e){return Wt(e,Jt)}async function hi(e){let t;try{t=await Ts(fi(e),"utf-8")}catch{return{present:!1,malformed:!1,config:null}}try{let r=JSON.parse(t);return!r||typeof r!="object"||Array.isArray(r)?{present:!0,malformed:!0,config:null}:{present:!0,malformed:!1,config:r}}catch{return{present:!0,malformed:!0,config:null}}}async function mi(e,t){let r=fi(e);await P(Sp(r),{recursive:!0}),await A(r,JSON.stringify(t,null," "),"utf-8")}async function Ap(e){let t=await x(e),r=Array.isArray(t.mcp?.servers)?t.mcp.servers.filter(n=>typeof n=="string"&&n):[];return[...new Set([...me,...r])]}function Cp(e,t){let r=gi(e.vesper)?e.vesper:{},n=Os(t===void 0?r.packs:t),s=kv.includes(r.agentsMode)?r.agentsMode:Sv,o={...r,packs:n,agentsMode:s};return _p(e.vesper,o)?!1:(e.vesper=o,!0)}function $p(e,t){let r=!1;gi(e.mcp)||(e.mcp={},r=!0);for(let n of t){let s=bv(n);_p(e.mcp[n],s)||(e.mcp[n]=s,r=!0)}return r}function kp(e,t,r){let n=!1;Array.isArray(e[t])||(e[t]=[],n=!0);for(let s of r)e[t].includes(s)||(e[t].push(s),n=!0);return n}function _v(e,{servers:t,packs:r}){let n=!1;return e.default_agent!==L&&(e.default_agent=L,n=!0),kp(e,"instructions",_c)&&(n=!0),$p(e,t)&&(n=!0),kp(e,"plugin",[xp])&&(n=!0),Cp(e,r)&&(n=!0),n}function Cv(e,{servers:t}){let r=!1;e.default_agent===L&&(delete e.default_agent,r=!0);let n=(s,o)=>{if(!Array.isArray(e[s]))return;let i=e[s].filter(a=>!o.includes(a));i.length!==e[s].length&&(i.length?e[s]=i:delete e[s],r=!0)};if(n("instructions",_c),n("plugin",[xp]),gi(e.mcp)){let s=!1;for(let o of t)o in e.mcp&&(delete e.mcp[o],s=!0);s&&(r=!0,Object.keys(e.mcp).length===0&&delete e.mcp)}return"vesper"in e&&(delete e.vesper,r=!0),r}async function Op(e,t){await W(e,[Y({path:Jt,host:"claude",category:Ep,owns:{keys:[...vv],entries:Os(t)}})])}async function $v(e){return(await ne(e)).find(t=>t&&t.path===Jt&&t.host==="claude"&&t.category===Ep)||null}async function Tp(e,{record:t=!0}={}){let r=fi(e),{present:n,malformed:s,config:o}=await hi(e);if(s)return{configured:!1,configPath:r,status:"skipped-malformed",servers:[]};let i=o||{$schema:Ev},a=await Ap(e),c=_v(i,{servers:a});return(c||!n)&&await mi(e,i),t&&await Op(e,a),{configured:!0,configPath:r,status:n?c?"updated":"unchanged":"created",servers:a}}async function li(e,t){let{present:r,malformed:n,config:s}=await hi(e);if(!r)return{mirrored:!1,reason:"absent"};if(n)return{mirrored:!1,reason:"malformed"};let o=Cp(s,t);o&&await mi(e,s);let i=s.vesper.agentsMode,a=!1;if(i==="files"){let c=await Promise.resolve().then(()=>(Ac(),vp)).catch(()=>null);if(c&&typeof c.renderOpenCodeAgentFiles=="function")try{await c.renderOpenCodeAgentFiles(e,{packs:Os(t)}),a=!0}catch(l){u.dim(` OpenCode agent files not rendered (${l?.message||l}) \u2014 run \`vespercli opencode render-agents\`.`)}else u.dim(' OpenCode agentsMode "files": the agent-file renderer is not available in this build \u2014 run `vespercli opencode render-agents` once it ships.')}return{mirrored:!0,changed:o,agentsMode:i,rendered:a}}async function Oc(e){let{present:t,malformed:r,config:n}=await hi(e);if(!t)return{synced:!1,reason:"absent"};if(r)return{synced:!1,reason:"malformed"};let s=await Ap(e),o=await $v(e),i=new Set([...Array.isArray(o?.owns?.entries)?o.owns.entries:[],...me]),a=!1;if(gi(n.mcp))for(let c of i)!s.includes(c)&&c in n.mcp&&(delete n.mcp[c],a=!0);return $p(n,s)&&(a=!0),a&&await mi(e,n),await Op(e,s),{synced:!0,changed:a,servers:s}}async function Ov(e,t,r,n){let s=Wt(e,t),o=null;try{o=await Ts(s)}catch{o=null}if(o!==null&&ee(o,r))return"unchanged";if(o!==null){let i=n.find(a=>a&&a.path===t&&a.host==="claude")||{path:t,category:$s,hash:null};if(!await as(s,i))return"kept-edited"}return await P(Sp(s),{recursive:!0}),await A(s,r),o===null?"created":"refreshed"}async function Pp(e){let t=await ne(e),r=[["agent",Kr,await Cc()],["plugin",Br,await $c()]],n={agent:"unchanged",plugin:"unchanged",keptEdited:[]},s=[];for(let[o,i,a]of r){let c=await Ov(e,i,a,t);if(n[o]=c,c==="kept-edited"){n.keptEdited.push(i);continue}s.push(F({path:i,host:"claude",category:$s,hash:await ye(Wt(e,i))}))}return await an(e,s,{categories:[$s],prune:!1}),n}async function Ip(e){let t=[],r=[[Kr,await Cc()],[Br,await $c()]];for(let[n,s]of r){let o=null;try{o=await Ts(Wt(e,n))}catch{continue}ee(o,s)&&t.push(F({path:n,host:"claude",category:$s,hash:await ye(Wt(e,n))}))}return t}async function jp(e,{manifest:t=[],ownedServers:r=[]}={}){let n={kept:[],config:"absent"},{present:s,malformed:o,config:i}=await hi(e);if(s&&o&&(n.config="malformed"),s&&!o){let c=t.find(m=>m&&m.path===Jt&&m.host==="claude")||null,l=await x(e),d=Array.isArray(l.mcp?.servers)?l.mcp.servers:[],p=Os([...me,...Array.isArray(c?.owns?.entries)?c.owns.entries:[],...d,...r]);Cv(i,{servers:p})?Object.keys(i).every(m=>m==="$schema")?(await gv(fi(e),{force:!0}),n.config="removed"):(await mi(e,i),n.config="stripped"):n.config="unchanged"}let a=[[Kr,[await Cc()]],[Br,[await $c()]]];for(let[c,l]of a){let d=Wt(e,c);if(!await w(d))continue;let p=t.find(m=>m&&m.path===c&&m.host==="claude")||{path:c,category:$s,hash:null},f=await le(d,p,{expected:l});(f==="kept"||f==="partial")&&n.kept.push(c)}for(let c of[".opencode/agents",".opencode/plugins",".opencode"])try{await yv(Wt(e,c))}catch{}return n}var $s,Ep,wv,bp,_c,xp,vv,kv,Sv,Ev,_p,gi,Os,As=Z(()=>{Ee();U();fe();H();te();Be();Te();ai();$s="opencode-overlay",Ep="opencode-config",wv=Wt(O,"opencode","vesper-plugin.js"),bp=Object.freeze([Jt,Kr,Br]),_c=Object.freeze([".claude/rules/vesper-orchestrator.md",".claude/rules/vesper-orchestration.md",".claude/rules/vesper-context.md"]),xp="./.opencode/plugins/vesper.js",vv=Object.freeze(["default_agent","instructions","mcp","plugin","vesper"]),kv=Object.freeze(["plugin","files"]),Sv="plugin",Ev="https://opencode.ai/config.json";_p=(e,t)=>JSON.stringify(e)===JSON.stringify(t),gi=e=>!!e&&typeof e=="object"&&!Array.isArray(e),Os=e=>[...new Set((e||[]).filter(t=>typeof t=="string"&&t))].sort()});import{readFile as ie,readdir as Mp,rm as Sn,rmdir as Pc}from"node:fs/promises";import{join as R,dirname as js,basename as Tv}from"node:path";function Mr(e){return R(e,".claude")}function Fp(e){return R(e,".claude","vesper")}function Gp(e){return R(e,"CLAUDE.md")}function Ge(e){return R(e,Dp)}function Me(e){return R(e,".claude","settings.json")}function Rv(e,t){return t?e.replace(/^(name:\s*)([a-z0-9-]+)/m,(r,n,s)=>s.startsWith(t)?r:`${n}${t}${s}`):e}async function yi({workspaceRoot:e,namePrefix:t,version:r}={}){let n=Mr(e),s=[],o=`.claude/agents/${L}.md`,i=R(pr,"agents",`${L}.md`);await P(R(n,"agents"),{recursive:!0}),await A(R(e,o),await ie(i,"utf-8"),"utf-8"),s.push(F({path:o,host:"claude",category:"catalog-agent",hash:await ye(R(e,o))}));for(let d of Qt){let p=R(pr,"skills",d),f=`.claude/skills/${d}`;await os(p,R(e,f),{recursive:!0}),s.push(F({path:f,host:"claude",category:"catalog-skill",hash:null}))}let{pruned:a,kept:c}=await an(e,s,{categories:["catalog-agent","catalog-command","catalog-skill"]});if(r!==void 0){let d=await x(e);d.schemaVersion=ve,d.frameworkVersion=r,await T(e,d)}let l={agents:1,skills:Qt.length,commands:0};return{pluginDir:n,counts:l,pruned:a.map(d=>d.replace(/^\.claude\//,"")),keptEdited:c.map(d=>d.replace(/^\.claude\//,""))}}async function Ps(e,t){let r=s=>e==="skills"?R(s,"skills",t):R(s,e,`${t}.md`);if(await w(r(Fe)))return{path:r(Fe),pack:"core"};let n=[];try{n=(await Mp(R(Fe,"packs"),{withFileTypes:!0})).filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>s.name).sort()}catch{n=[]}for(let s of n){let o=R(Fe,"packs",s);if(await w(r(o)))return{path:r(o),pack:s}}return null}async function wi(e,t,{workspaceRoot:r,namePrefix:n=""}={}){let s=Mr(r),o=R(s,e);if(await P(o,{recursive:!0}),e==="skills"){let m=await Ps("skills",t);if(!m)throw new Error(`Skill "${t}" not found in assets/claude/skills/ or any assets/claude/packs/<pack>/skills/`);let h=m.path,g=R(o,t),y=await Mt(g,{sourceDir:h});if(y.status!=="absent"&&!(y.status==="classified"&&y.kept.length===0))throw Rp(`.claude/skills/${t}`,`vesper:${t}`);return await os(h,g,{recursive:!0}),await W(r,[F({path:`.claude/skills/${t}`,host:"claude",category:"added-asset",hash:null})]),{installedAs:t}}let i=".md",a=await Ps(e,t);if(!a)throw new Error(`${e.slice(0,-1)} "${t}" not found in assets/claude/${e}/ or any assets/claude/packs/<pack>/${e}/`);let c=a.path,l=await ie(c,"utf-8"),d=Rv(l,n),p=n&&!t.startsWith(n)?`${n}${t}${i}`:`${t}${i}`,f=null;try{f=await ie(R(o,p))}catch{f=null}if(f!==null&&!ee(f,d))throw Rp(`.claude/${e}/${p}`,`vesper:${t}`);return await A(R(o,p),d,"utf-8"),await W(r,[F({path:`.claude/${e}/${p}`,host:"claude",category:"added-asset",hash:await ye(R(o,p))})]),{installedAs:Tv(p,i)}}function Rp(e,t){let r=new Error(`${e} already exists and differs from Vesper's version (your edits, or a file of yours) \u2014 nothing was written or recorded. To keep yours: do nothing (it already takes precedence over \`${t}\`). To pin Vesper's version instead: move yours aside (e.g. \`mv ${e} ${e}.mine\`), then re-run the command.`);return r.name="AssetConflict",r.path=e,r}async function Vp(e){let t=Mr(e),r={};for(let n of Pv){let s=R(t,n);if(!await w(s)){r[n]=[];continue}let o=await Mp(s,{withFileTypes:!0});r[n]=n==="skills"?o.filter(i=>i.isDirectory()).map(i=>i.name).sort():o.filter(i=>i.isFile()&&i.name.endsWith(".md")).map(i=>i.name.replace(/\.md$/,"")).sort()}return r}async function vi({pluginName:e=jv,staleDir:t,dryRun:r=!1,workspaceRoot:n,backup:s}={}){return r?{removed:!1,...await xs({pluginName:e,staleDir:t,workspaceRoot:n})}:np({pluginName:e,staleDir:t,workspaceRoot:n,backup:s})}function Hp(e){let t="This is a machine-wide folder, removed as a side effect of running `vespercli init` in THIS project: every other pre-1.9 Vesper project on this machine loses its Vesper specialists until you run `vespercli init` in it (that migrates it to 2.0 \u2014 nothing else brings them back).",r=n=>n?.length?[`Kept ${n.length} file(s) there that no released Vesper build wrote (your edits or your own files): ${n.slice(0,10).join(", ")}${n.length>10?", \u2026":""}`]:[];return e.removed||e.partial?{level:e.partial?"warn":"success",lines:[`${e.removed?"Removed":"Removed the Vesper-written files of"} the pre-1.9 machine-wide Vesper Claude catalog at ${e.path}${e.backedUpTo?` (backed up first to ${e.backedUpTo})`:""}.`,...r(e.kept),t]}:e.reason==="no-backup"||e.reason==="nothing-proven"?{level:"warn",lines:[`Found the pre-1.9 machine-wide Vesper Claude catalog at ${e.path}, but ${e.reason==="no-backup"?"no backup could be made, so nothing was removed":"none of its files is byte-identical to a released Vesper build, so nothing was removed"}.`,"Review it yourself; `vespercli doctor` names it while Vesper-written files remain."]}:e.reason==="remove-failed"?{level:"warn",lines:[`Could not clean the stale machine-wide Vesper Claude catalog at ${e.path}${e.error?` (${e.error})`:""} \u2014 your install completed fine, this was only the cleanup step.`,"Re-run `vespercli init` to retry (it backs the folder up first and removes only files a released Vesper build wrote)."]}:null}function Nv(){return[Ic,"This project is managed by **Vesper**. Its orchestrator playbook, team roster, and slim","project whitepaper are always-on rules loaded automatically every session:","`.claude/rules/vesper-orchestrator.md`, `.claude/rules/vesper-orchestration.md`,","`.claude/rules/vesper-context.md`. On-demand deep context lives in `.claude/vesper/context/`.","This block is a human breadcrumb only (no `@import`) \u2014 it is regenerated by `vespercli`; do not hand-edit.",jc].join(`
|
|
85
|
-
`)}async function
|
|
83
|
+
Follow the always-on rules in \`${Oc.join("`, `")}\` exactly.`,""].join(`
|
|
84
|
+
`)}async function Pc(){return js(xv)}function yi(e){return Bt(e,Xt)}async function wi(e){let t;try{t=await js(yi(e),"utf-8")}catch{return{present:!1,malformed:!1,config:null}}try{let r=JSON.parse(t);return!r||typeof r!="object"||Array.isArray(r)?{present:!0,malformed:!0,config:null}:{present:!0,malformed:!1,config:r}}catch{return{present:!0,malformed:!0,config:null}}}async function vi(e,t){let r=yi(e);await P(Op(r),{recursive:!0}),await A(r,JSON.stringify(t,null," "),"utf-8")}async function jp(e){let t=await x(e),r=Array.isArray(t.mcp?.servers)?t.mcp.servers.filter(n=>typeof n=="string"&&n):[];return[...new Set([...me,...r])]}function Np(e,t){let r=ki(e.vesper)?e.vesper:{},n=Is(t===void 0?r.packs:t),s=_v.includes(r.agentsMode)?r.agentsMode:Cv,o={...r,packs:n,agentsMode:s};return Rp(e.vesper,o)?!1:(e.vesper=o,!0)}function Lp(e,t){let r=!1;ki(e.mcp)||(e.mcp={},r=!0);for(let n of t){let s=Ov(n);Rp(e.mcp[n],s)||(e.mcp[n]=s,r=!0)}return r}function $p(e,t,r){let n=!1;Array.isArray(e[t])||(e[t]=[],n=!0);for(let s of r)e[t].includes(s)||(e[t].push(s),n=!0);return n}function Iv(e,{servers:t,packs:r}){let n=!1;return e.default_agent!==L&&(e.default_agent=L,n=!0),$p(e,"instructions",Oc)&&(n=!0),Lp(e,t)&&(n=!0),$p(e,"plugin",[Ip])&&(n=!0),Np(e,r)&&(n=!0),n}function jv(e,{servers:t}){let r=!1;e.default_agent===L&&(delete e.default_agent,r=!0);let n=(s,o)=>{if(!Array.isArray(e[s]))return;let i=e[s].filter(a=>!o.includes(a));i.length!==e[s].length&&(i.length?e[s]=i:delete e[s],r=!0)};if(n("instructions",Oc),n("plugin",[Ip]),ki(e.mcp)){let s=!1;for(let o of t)o in e.mcp&&(delete e.mcp[o],s=!0);s&&(r=!0,Object.keys(e.mcp).length===0&&delete e.mcp)}return"vesper"in e&&(delete e.vesper,r=!0),r}async function Mp(e,t){await W(e,[Y({path:Xt,host:"claude",category:Tp,owns:{keys:[...Av],entries:Is(t)}})])}async function Rv(e){return(await ne(e)).find(t=>t&&t.path===Xt&&t.host==="claude"&&t.category===Tp)||null}async function Gp(e,{record:t=!0}={}){let r=yi(e),{present:n,malformed:s,config:o}=await wi(e);if(s)return{configured:!1,configPath:r,status:"skipped-malformed",servers:[]};let i=o||{$schema:$v},a=await jp(e),c=Iv(i,{servers:a});return(c||!n)&&await vi(e,i),t&&await Mp(e,a),{configured:!0,configPath:r,status:n?c?"updated":"unchanged":"created",servers:a}}async function fi(e,t){let{present:r,malformed:n,config:s}=await wi(e);if(!r)return{mirrored:!1,reason:"absent"};if(n)return{mirrored:!1,reason:"malformed"};let o=Np(s,t);o&&await vi(e,s);let i=s.vesper.agentsMode,a=!1;if(i==="files"){let c=await Promise.resolve().then(()=>($c(),Cp)).catch(()=>null);if(c&&typeof c.renderOpenCodeAgentFiles=="function")try{await c.renderOpenCodeAgentFiles(e,{packs:Is(t)}),a=!0}catch(l){u.dim(` OpenCode agent files not rendered (${l?.message||l}) \u2014 run \`vespercli opencode render-agents\`.`)}else u.dim(' OpenCode agentsMode "files": the agent-file renderer is not available in this build \u2014 run `vespercli opencode render-agents` once it ships.')}return{mirrored:!0,changed:o,agentsMode:i,rendered:a}}async function Ic(e){let{present:t,malformed:r,config:n}=await wi(e);if(!t)return{synced:!1,reason:"absent"};if(r)return{synced:!1,reason:"malformed"};let s=await jp(e),o=await Rv(e),i=new Set([...Array.isArray(o?.owns?.entries)?o.owns.entries:[],...me]),a=!1;if(ki(n.mcp))for(let c of i)!s.includes(c)&&c in n.mcp&&(delete n.mcp[c],a=!0);return Lp(n,s)&&(a=!0),a&&await vi(e,n),await Mp(e,s),{synced:!0,changed:a,servers:s}}async function Nv(e,t,r,n){let s=Bt(e,t),o=null;try{o=await js(s)}catch{o=null}if(o!==null&&ee(o,r))return"unchanged";if(o!==null){let i=n.find(a=>a&&a.path===t&&a.host==="claude")||{path:t,category:Ps,hash:null};if(!await ls(s,i))return"kept-edited"}return await P(Op(s),{recursive:!0}),await A(s,r),o===null?"created":"refreshed"}async function Fp(e){let t=await ne(e),r=[["agent",Br,await Tc()],["plugin",zr,await Pc()]],n={agent:"unchanged",plugin:"unchanged",keptEdited:[]},s=[];for(let[o,i,a]of r){let c=await Nv(e,i,a,t);if(n[o]=c,c==="kept-edited"){n.keptEdited.push(i);continue}s.push(G({path:i,host:"claude",category:Ps,hash:await ye(Bt(e,i))}))}return await cn(e,s,{categories:[Ps],prune:!1}),n}async function Dp(e){let t=[],r=[[Br,await Tc()],[zr,await Pc()]];for(let[n,s]of r){let o=null;try{o=await js(Bt(e,n))}catch{continue}ee(o,s)&&t.push(G({path:n,host:"claude",category:Ps,hash:await ye(Bt(e,n))}))}return t}async function Vp(e,{manifest:t=[],ownedServers:r=[]}={}){let n={kept:[],config:"absent"},{present:s,malformed:o,config:i}=await wi(e);if(s&&o&&(n.config="malformed"),s&&!o){let c=t.find(m=>m&&m.path===Xt&&m.host==="claude")||null,l=await x(e),d=Array.isArray(l.mcp?.servers)?l.mcp.servers:[],p=Is([...me,...Array.isArray(c?.owns?.entries)?c.owns.entries:[],...d,...r]);jv(i,{servers:p})?Object.keys(i).every(m=>m==="$schema")?(await Ev(yi(e),{force:!0}),n.config="removed"):(await vi(e,i),n.config="stripped"):n.config="unchanged"}let a=[[Br,[await Tc()]],[zr,[await Pc()]]];for(let[c,l]of a){let d=Bt(e,c);if(!await w(d))continue;let p=t.find(m=>m&&m.path===c&&m.host==="claude")||{path:c,category:Ps,hash:null},f=await le(d,p,{expected:l});(f==="kept"||f==="partial")&&n.kept.push(c)}for(let c of[".opencode/agents",".opencode/plugins",".opencode"])try{await bv(Bt(e,c))}catch{}return n}var Ps,Tp,xv,Pp,Oc,Ip,Av,_v,Cv,$v,Rp,ki,Is,$s=Z(()=>{xe();U();fe();H();te();Ye();Ie();di();Ps="opencode-overlay",Tp="opencode-config",xv=Bt(O,"opencode","vesper-plugin.js"),Pp=Object.freeze([Xt,Br,zr]),Oc=Object.freeze([".claude/rules/vesper-orchestrator.md",".claude/rules/vesper-orchestration.md",".claude/rules/vesper-context.md"]),Ip="./.opencode/plugins/vesper.js",Av=Object.freeze(["default_agent","instructions","mcp","plugin","vesper"]),_v=Object.freeze(["plugin","files"]),Cv="plugin",$v="https://opencode.ai/config.json";Rp=(e,t)=>JSON.stringify(e)===JSON.stringify(t),ki=e=>!!e&&typeof e=="object"&&!Array.isArray(e),Is=e=>[...new Set((e||[]).filter(t=>typeof t=="string"&&t))].sort()});import{readFile as ie,readdir as Kp,rm as En,rmdir as Rc}from"node:fs/promises";import{join as R,dirname as Ls,basename as Lv}from"node:path";function Gr(e){return R(e,".claude")}function Bp(e){return R(e,".claude","vesper")}function zp(e){return R(e,"CLAUDE.md")}function Ve(e){return R(e,Yp)}function Fe(e){return R(e,".claude","settings.json")}function Dv(e,t){return t?e.replace(/^(name:\s*)([a-z0-9-]+)/m,(r,n,s)=>s.startsWith(t)?r:`${n}${t}${s}`):e}async function Si({workspaceRoot:e,namePrefix:t,version:r}={}){let n=Gr(e),s=[],o=`.claude/agents/${L}.md`,i=R(hr,"agents",`${L}.md`);await P(R(n,"agents"),{recursive:!0}),await A(R(e,o),await ie(i,"utf-8"),"utf-8"),s.push(G({path:o,host:"claude",category:"catalog-agent",hash:await ye(R(e,o))}));for(let d of er){let p=R(hr,"skills",d),f=`.claude/skills/${d}`;await as(p,R(e,f),{recursive:!0}),s.push(G({path:f,host:"claude",category:"catalog-skill",hash:null}))}let{pruned:a,kept:c}=await cn(e,s,{categories:["catalog-agent","catalog-command","catalog-skill"]});if(r!==void 0){let d=await x(e);d.schemaVersion=ve,d.frameworkVersion=r,await T(e,d)}let l={agents:1,skills:er.length,commands:0};return{pluginDir:n,counts:l,pruned:a.map(d=>d.replace(/^\.claude\//,"")),keptEdited:c.map(d=>d.replace(/^\.claude\//,""))}}async function Rs(e,t){let r=s=>e==="skills"?R(s,"skills",t):R(s,e,`${t}.md`);if(await w(r(De)))return{path:r(De),pack:"core"};let n=[];try{n=(await Kp(R(De,"packs"),{withFileTypes:!0})).filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>s.name).sort()}catch{n=[]}for(let s of n){let o=R(De,"packs",s);if(await w(r(o)))return{path:r(o),pack:s}}return null}async function Ei(e,t,{workspaceRoot:r,namePrefix:n=""}={}){let s=Gr(r),o=R(s,e);if(await P(o,{recursive:!0}),e==="skills"){let m=await Rs("skills",t);if(!m)throw new Error(`Skill "${t}" not found in assets/claude/skills/ or any assets/claude/packs/<pack>/skills/`);let h=m.path,g=R(o,t),y=await Gt(g,{sourceDir:h});if(y.status!=="absent"&&!(y.status==="classified"&&y.kept.length===0))throw Hp(`.claude/skills/${t}`,`vesper:${t}`);return await as(h,g,{recursive:!0}),await W(r,[G({path:`.claude/skills/${t}`,host:"claude",category:"added-asset",hash:null})]),{installedAs:t}}let i=".md",a=await Rs(e,t);if(!a)throw new Error(`${e.slice(0,-1)} "${t}" not found in assets/claude/${e}/ or any assets/claude/packs/<pack>/${e}/`);let c=a.path,l=await ie(c,"utf-8"),d=Dv(l,n),p=n&&!t.startsWith(n)?`${n}${t}${i}`:`${t}${i}`,f=null;try{f=await ie(R(o,p))}catch{f=null}if(f!==null&&!ee(f,d))throw Hp(`.claude/${e}/${p}`,`vesper:${t}`);return await A(R(o,p),d,"utf-8"),await W(r,[G({path:`.claude/${e}/${p}`,host:"claude",category:"added-asset",hash:await ye(R(o,p))})]),{installedAs:Lv(p,i)}}function Hp(e,t){let r=new Error(`${e} already exists and differs from Vesper's version (your edits, or a file of yours) \u2014 nothing was written or recorded. To keep yours: do nothing (it already takes precedence over \`${t}\`). To pin Vesper's version instead: move yours aside (e.g. \`mv ${e} ${e}.mine\`), then re-run the command.`);return r.name="AssetConflict",r.path=e,r}async function Jp(e){let t=Gr(e),r={};for(let n of Mv){let s=R(t,n);if(!await w(s)){r[n]=[];continue}let o=await Kp(s,{withFileTypes:!0});r[n]=n==="skills"?o.filter(i=>i.isDirectory()).map(i=>i.name).sort():o.filter(i=>i.isFile()&&i.name.endsWith(".md")).map(i=>i.name.replace(/\.md$/,"")).sort()}return r}async function bi({pluginName:e=Fv,staleDir:t,dryRun:r=!1,workspaceRoot:n,backup:s}={}){return r?{removed:!1,...await Cs({pluginName:e,staleDir:t,workspaceRoot:n})}:dp({pluginName:e,staleDir:t,workspaceRoot:n,backup:s})}function qp(e){let t="This is a machine-wide folder, removed as a side effect of running `vespercli init` in THIS project: every other pre-1.9 Vesper project on this machine loses its Vesper specialists until you run `vespercli init` in it (that migrates it to 2.0 \u2014 nothing else brings them back).",r=n=>n?.length?[`Kept ${n.length} file(s) there that no released Vesper build wrote (your edits or your own files): ${n.slice(0,10).join(", ")}${n.length>10?", \u2026":""}`]:[];return e.removed||e.partial?{level:e.partial?"warn":"success",lines:[`${e.removed?"Removed":"Removed the Vesper-written files of"} the pre-1.9 machine-wide Vesper Claude catalog at ${e.path}${e.backedUpTo?` (backed up first to ${e.backedUpTo})`:""}.`,...r(e.kept),t]}:e.reason==="no-backup"||e.reason==="nothing-proven"?{level:"warn",lines:[`Found the pre-1.9 machine-wide Vesper Claude catalog at ${e.path}, but ${e.reason==="no-backup"?"no backup could be made, so nothing was removed":"none of its files is byte-identical to a released Vesper build, so nothing was removed"}.`,"Review it yourself; `vespercli doctor` names it while Vesper-written files remain."]}:e.reason==="remove-failed"?{level:"warn",lines:[`Could not clean the stale machine-wide Vesper Claude catalog at ${e.path}${e.error?` (${e.error})`:""} \u2014 your install completed fine, this was only the cleanup step.`,"Re-run `vespercli init` to retry (it backs the folder up first and removes only files a released Vesper build wrote)."]}:null}function Vv(){return[Nc,"This project is managed by **Vesper**. Its orchestrator playbook, team roster, and slim","project whitepaper are always-on rules loaded automatically every session:","`.claude/rules/vesper-orchestrator.md`, `.claude/rules/vesper-orchestration.md`,","`.claude/rules/vesper-context.md`. On-demand deep context lives in `.claude/vesper/context/`.","This block is a human breadcrumb only (no `@import`) \u2014 it is regenerated by `vespercli`; do not hand-edit.",Lc].join(`
|
|
85
|
+
`)}async function Hv(e){let t=zp(e),r=Vv(),n=new RegExp(`${Nc}[\\s\\S]*?${Lc}`);if(!await w(t))return await P(Ls(t),{recursive:!0}),await A(t,`${r}
|
|
86
86
|
`,"utf-8"),{created:!0,updated:!1};let s=await ie(t,"utf-8");if(n.test(s)){let i=s.replace(n,r);return i!==s?(await A(t,i,"utf-8"),{created:!1,updated:!0}):{created:!1,updated:!1}}let o=`${r}
|
|
87
87
|
|
|
88
|
-
${s}`;return await A(t,o,"utf-8"),{created:!1,updated:!0}}function
|
|
89
|
-
`);return t}async function
|
|
90
|
-
`),r=/^---\n[\s\S]*?\n---\n/.exec(t);return(r?t.slice(r[0].length):t).trim()}async function zv(e){let t={removed:[],kept:[]};for(let r of["orchestration","context"]){let n=`.claude/vesper/${r}.md`,s;try{s=await ie(R(e,n),"utf-8")}catch{continue}let o=null;try{o=await ie(R(e,".vesper","instructions",`vesper-${r}.instructions.md`),"utf-8")}catch{o=null}let i=Lp(s);o===null||i!==""&&Lp(o).includes(i)?(await Sn(R(e,n),{force:!0}),t.removed.push(n)):t.kept.push(n)}return t}async function bn(e,{purgeProjectAuthored:t=!1}={}){let r=Fp(e),n=".claude/vesper/orchestrator.md";await le(R(e,n),{path:n,category:"playbook"});let s=[];t&&(s.push(...(await zv(e)).kept),s.push(...(await Bv(e)).kept.map(y=>`.claude/vesper/context/${y}`)));try{await Pc(r)}catch{}let o=await x(e),i=new Set,a=Array.isArray(o.manifest)?o.manifest:[],c=new Set(a.filter(y=>y&&y.host!=="claude"&&y.category==="per-project-authored").map(y=>y.path));for(let y of a)Ko(y,{host:"claude",purgeProjectAuthored:t})&&(y.category==="per-project-authored"&&c.has(y.path)||i.add(y.path));for(let y of Array.isArray(o.claude?.catalogManifest)?o.claude.catalogManifest:[]){if(typeof y!="string"||y.includes(".."))continue;let[k,...v]=y.split("/");!Iv.includes(k)||v.length===0||i.add(`.claude/${y}`)}for(let y of i){let k=(o.manifest||[]).find(v=>v?.path===y)||{path:y,category:y.startsWith(".claude/skills/")?"catalog-skill":"catalog-agent"};await le(R(e,y),k,{purgeProjectAuthored:t})}let{kept:l}=await Yo(e,"claude");l.push(...(await hn(e,"claude")).kept);let d=await jp(e,{manifest:a}),p=Gp(e);if(await w(p)){let y=await ie(p,"utf-8"),k=Lc(Mv(y));k.trim()?await A(p,k,"utf-8"):await Sn(p,{force:!0})}await fr(e,!1);let f=Array.isArray(o.mcp?.servers)?o.mcp.servers:[];if(f.length&&await w(Ge(e)))try{let y=JSON.parse(await ie(Ge(e),"utf-8")),k=!1;for(let v of f)y?.mcpServers&&typeof y.mcpServers=="object"&&v in y.mcpServers&&(delete y.mcpServers[v],k=!0);k&&await Ei(e,y)}catch{}try{let y=JSON.parse(await ie(Ge(e),"utf-8"));y&&typeof y=="object"&&Object.keys(y).every(v=>v==="mcpServers")&&(!y.mcpServers||Object.keys(y.mcpServers).length===0)&&await Sn(Ge(e),{force:!0})}catch{}let m=Me(e);if(await w(m))try{let y=JSON.parse(await ie(m,"utf-8")),k=xi(y,{markers:[Is.legacy,Is.bootstrap]}),v=Xp(y),S=Np(y),C=Vv(y);(k||v||S||C)&&(Object.keys(y).length===0?await Sn(m,{force:!0}):await A(m,JSON.stringify(y,null," "),"utf-8"))}catch{}let h=En(e);if(await w(h))try{let y=JSON.parse(await ie(h,"utf-8"));Np(y)&&(Object.keys(y).length===0?await Sn(h,{force:!0}):await A(h,JSON.stringify(y,null," "),"utf-8"))}catch{}let g=await x(e);return delete g.claude,g.host==="claude"&&delete g.host,delete g.namePrefix,delete g.pluginPath,Array.isArray(g.manifest)&&(g.manifest=g.manifest.filter(y=>!(y&&y.host==="claude")||!t&&Re.has(y.category))),await T(e,g),{kept:l,knowledgeKept:s,overlayKept:d.kept}}var Fe,pr,Ce,Pv,Iv,jv,Dp,Ic,jc,Up,Yp,Is,qp,Wv,xe=Z(()=>{Ee();un();U();Be();dn();ut();Es();mc();H();te();fe();As();Fe=R(O,"claude"),pr=R(O,"claude-committed"),Ce="vesper-marketplace",Pv=["agents","skills"],Iv=["agents","commands","skills"],jv="vesper";Dp=".mcp.json";Ic="<!-- vesper:start -->",jc="<!-- vesper:end -->";Up=Object.freeze(["mcp__vesper-indexing__vesper_search","mcp__vesper-indexing__vesper_symbols","mcp__vesper-indexing__vesper_status","mcp__vesper-indexing__vesper_reindex","mcp__sequential-thinking__sequentialthinking","mcp__memory__create_entities","mcp__memory__create_relations","mcp__memory__add_observations","mcp__memory__delete_entities","mcp__memory__delete_observations","mcp__memory__delete_relations","mcp__memory__read_graph","mcp__memory__search_nodes","mcp__memory__open_nodes"]);Yp=`command -v vespercli >/dev/null 2>&1 && ${qr("claude")} || true`,Is=Object.freeze({legacy:Object.freeze([Ln,Mn]),bootstrap:Object.freeze([Fn]),guard:Object.freeze([Yp])});qp="command -v vespercli >/dev/null 2>&1 && vespercli log delegated --pipeline hook --note hook --stdin || true",Wv=Object.freeze({runLedger:Object.freeze([qp])})});import{Command as cx,Option as ft}from"commander";import{readFileSync as lx,existsSync as ux}from"node:fs";import{fileURLToPath as dx}from"node:url";import{dirname as Vl,join as zm}from"node:path";U();H();te();xe();import{resolve as AE,basename as Kh,relative as _E,sep as CE,isAbsolute as $E}from"node:path";import{spawn as OE}from"node:child_process";import{confirm as Kt,input as TE,number as PE,select as IE}from"@inquirer/prompts";U();Be();Es();H();te();fe();import{readFile as Fs,rm as Cf,rmdir as oS}from"node:fs/promises";import{join as Je}from"node:path";te();H();xe();be();import{readFile as Ms,readdir as wk}from"node:fs/promises";import{join as _e,isAbsolute as vk,relative as kk}from"node:path";import{readdir as Yv,readFile as Zp,rename as Jv,access as qv,constants as Xv}from"node:fs/promises";import{join as hr}from"node:path";import{execFile as Qv}from"node:child_process";var Mc=".vesper/.migration-backup";async function ef(e){try{return await qv(e,Xv.F_OK),!0}catch{return!1}}function Zv(e){return new Promise(t=>{try{Qv("git",["rev-parse","--verify","-q","HEAD"],{cwd:e,timeout:5e3,encoding:"utf-8",env:{...process.env,GIT_NO_LAZY_FETCH:"1",GIT_OPTIONAL_LOCKS:"0",GIT_TERMINAL_PROMPT:"0",GCM_INTERACTIVE:"never",SSH_ASKPASS_REQUIRE:"never",LC_ALL:"C"}},(n,s)=>t(n?null:String(s).trim()||null)).stdin?.end()}catch{t(null)}})}async function tf(e){try{return(await Yv(hr(e,Mc),{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>t.name).sort()}catch{return[]}}async function Ai(e,{head:t}={}){let r=await tf(e);if(r.length===0)return!1;let n=hr(e,Mc),s=t!==void 0?t:await Zv(e),o=r.at(-1);for(let i of[...r].reverse()){let a;try{a=await Zp(hr(n,i,"rollback.json"),"utf-8")}catch{continue}let c;try{c=JSON.parse(a)}catch{if(i!==o)continue;return!await ef(hr(n,i,"created.txt"))}if(!c||!Array.isArray(c.before)||s!==null&&c.head!==s)continue;return(typeof c.status=="string"?c.status:Array.isArray(c.created)?"finished":"started")==="started"}return!1}async function Fc(e){let t=await tf(e);if(!t.length)return null;let r=hr(e,Mc,t.at(-1)),n;try{n=await Zp(hr(r,"rollback.json"),"utf-8")}catch{return null}try{return JSON.parse(n),null}catch{}return await ef(hr(r,"created.txt"))?null:hr(r,"rollback.json")}async function rf(e,{now:t=new Date}={}){let r=await Fc(e);if(!r)return null;let n=`${r}.torn-${t.toISOString().replace(/[:.]/g,"-")}`;return await Jv(r,n),{from:r,to:n}}U();H();te();xe();fe();Be();be();import{readFile as cf,rm as ck,rmdir as lk}from"node:fs/promises";import{join as Uc}from"node:path";H();fe();Ee();mc();be();import{readFile as Dc,readdir as of}from"node:fs/promises";import{readdirSync as ek}from"node:fs";import{join as Ae,basename as tk}from"node:path";import{homedir as rk}from"node:os";var nk=Object.freeze(["agents","commands","skills"]),sk=Object.freeze(["claude","paths","catalogVersion","targets"]),Fr=".vesper/.migration-backup",rt="This is a pre-2.0 (1.x) Vesper workspace. Run `vespercli init` to migrate it in place \u2014 nothing of yours is deleted, and anything Vesper removes is backed up first.";async function $i(e){let t=[...new Set([await kt(e),Ae(e,".vesperrc"),Ae(e,".vesper","tracking.json")])],r=null,n=null;for(let c of t){let l;try{l=await Dc(c,"utf-8")}catch(d){if(d&&d.code==="ENOENT")continue;return _i({config:"corrupt",path:c})}try{r=JSON.parse(l),n=c}catch{return _i({config:"corrupt",path:c})}break}if(!r||typeof r!="object")return _i({config:"absent",path:null});let s=Number(r.schemaVersion)>=2?"v2":"v1",o=[];for(let c of Array.isArray(r.claude?.catalogManifest)?r.claude.catalogManifest:[]){if(typeof c!="string"||c.includes("..")||c.startsWith("/"))continue;let[l,...d]=c.split("/");!nk.includes(l)||d.length===0||o.push(`.claude/${c}`)}let i=c=>Array.isArray(c)?c.filter(l=>typeof l=="string"):[],a=r.claude?.namePrefix??r.namePrefix;return _i({config:s,path:n,catalogManifest:o,namePrefix:typeof a=="string"?a:"",injectedPaths:i(r.paths),readAccessPaths:i(r.readAccessPaths),mcpServers:i(r.mcp?.servers),vendored:r.vendored&&typeof r.vendored=="object"?JSON.parse(JSON.stringify(r.vendored)):void 0,hosts:s==="v1"?{claude:!!r.claude,copilot:i(r.paths).length>0}:{claude:!1,copilot:!1},staleKeys:s==="v2"?sk.filter(c=>c in r):[],recordedHost:s==="v2"?Bn({host:r.host}):null,version:s==="v1"&&[r.catalogVersion,r.claude?.catalogVersion,r.version].find(c=>typeof c=="string"&&/^1\.\d+\.\d+/.test(c))||null})}function _i(e){return Object.freeze({config:"absent",path:null,catalogManifest:[],namePrefix:"",injectedPaths:[],readAccessPaths:[],mcpServers:[],vendored:void 0,hosts:{claude:!1,copilot:!1},staleKeys:[],recordedHost:null,version:null,...e})}async function $e(e,{checkout:t}={}){let r=await $i(e),n;try{n=await K(e)}catch{n=void 0}let s=await fu(e,{vscodeSettings:n}),o={claude:s.hosts.claude||r.hosts.claude,copilot:s.hosts.copilot||r.hosts.copilot},i=[...s.matched];r.config==="v1"&&i.unshift(`${tk(r.path||".vesperrc")} (1.x record)`);let a=!1,c=!1,l=!1,d=null;try{let f=t??await B(e);d=f.source==="local"?null:f.host??f.candidate??null}catch{d=null}r.config==="corrupt"||(r.config==="v1"&&(r.hosts.claude||r.hosts.copilot||r.mcpServers.length>0||r.vendored!==void 0||s.primary)?a=!0:d?(s.primary||r.staleKeys.length)&&(l=!0,i.push(...r.staleKeys.map(f=>`.vesperrc key "${f}"`))):s.primary?a=!0:s.residue.length&&!d&&(c=!0,o.claude=!0,i.push(...s.residue)));let p=a||c?[]:[...s.residue];return{unmigrated:a,advisory:c,residue:l,needsMigration:a||c||l,corrupt:r.config==="corrupt",config:r.config,hosts:o,staleKeys:[...r.staleKeys],evidence:[...new Set(i)],leftovers:p,record:r}}var ok="<!-- vesper(?::[a-z0-9-]+)?:start -->[\\s\\S]*?<!-- vesper(?::[a-z0-9-]+)?:end -->",nf=e=>new RegExp(ok).test(e),ik=Object.freeze([Ln,Mn,Fn]);async function Gc(e){try{return await of(e,{withFileTypes:!0})}catch{return[]}}async function Ci(e){try{return await Dc(e)}catch{return null}}function sf(e){let t=new Set;for(let r of[Ae(O,"claude",e),Ae(O,"claude-committed",e)])try{for(let n of ek(r))t.add(n.replace(/\.md$/,""))}catch{}return t}function ak(e){let t=/^---\r?\n([\s\S]*?)\r?\n---/.exec(e);if(!t)return null;let r=/^name:\s*['"]?([A-Za-z0-9_.-]+)['"]?\s*$/m.exec(t[1]);return r?r[1]:null}async function Oi({homeDir:e=rk(),pluginName:t="vesper",workspaceRoot:r}={}){let n=[],s=(p,f,m,h,g={})=>n.push({path:Ae(e,p),rel:p,kind:f,tier:m,marker:h,...g}),o=sf("agents"),i=sf("skills"),a=`.claude/skills/${t}`,c=await xs({pluginName:t,staleDir:Ae(e,a),workspaceRoot:r});(c.reason==="match"||c.reason==="manifest-less-ours")&&c.proven.length&&s(a,"plugin",2,`${c.proven.length} file(s) byte-identical to a released Vesper 1.x build`,{proven:c.proven.length,kept:c.kept.length});for(let[p,f]of[[".claude/rules",m=>m.endsWith(".md")],[".copilot/instructions",()=>!0]])for(let m of await Gc(Ae(e,p))){if(!m.isFile()||!f(m.name))continue;let h=`${p}/${m.name}`,g=(await Ci(Ae(e,h)))?.toString("utf-8")??"";nf(g)?s(h,"file",3,"a Vesper guard block"):m.name.startsWith("vesper-")&&s(h,"file",3,"a vesper- file name")}for(let p of[".claude/agents",".copilot/agents"])for(let f of await Gc(Ae(e,p))){if(!f.isFile()||!f.name.endsWith(".md"))continue;let m=`${p}/${f.name}`,h=await Ci(Ae(e,m));if(!h)continue;let g=f.name.replace(/(\.agent)?\.md$/,"");(o.has(ak(h.toString("utf-8"))||g)||o.has(g)||f.name.startsWith("vesper-"))&&s(m,"file",3,"a Vesper agent name")}for(let p of[".claude/skills",".copilot/skills"])for(let f of await Gc(Ae(e,p)))f.isDirectory()&&(p===".claude/skills"&&f.name===t||(i.has(f.name)||f.name.startsWith("vesper-"))&&s(`${p}/${f.name}`,"dir",3,"a Vesper skill name"));let l=(await Ci(Ae(e,".claude","CLAUDE.md")))?.toString("utf-8");l&&nf(l)&&s(".claude/CLAUDE.md","region",3,"a Vesper guard block");let d=await Ci(Ae(e,".claude","settings.json"));if(d){let p=null;try{p=JSON.parse(d.toString("utf-8"))}catch{p=null}if(p&&typeof p=="object"){let f=[],m=p.hooks&&typeof p.hooks=="object"?p.hooks:{};for(let[h,g]of Object.entries(m))Array.isArray(g)&&g.some(y=>Array.isArray(y?.hooks)&&y.hooks.some(k=>typeof k?.command=="string"&&ik.includes(k.command.trim())))&&f.push(`hooks.${h}`);p.agent===L&&f.push("agent"),f.length&&s(".claude/settings.json","keys",3,`Vesper keys: ${f.join(", ")}`)}}return n.sort((p,f)=>p.rel.localeCompare(f.rel))}async function af(e){let t=Ae(e,Fr),r=[];try{r=(await of(t,{withFileTypes:!0})).filter(s=>s.isDirectory()).map(s=>s.name).sort()}catch{r=[]}let n=[];for(let s of r){let o;try{o=JSON.parse(await Dc(Ae(t,s,"kept.json"),"utf-8"))}catch{continue}if(Array.isArray(o))for(let i of o)i&&typeof i.rel=="string"&&typeof i.reason=="string"&&n.push({rel:i.rel,reason:i.reason,backup:Ae(t,s)})}return n}ot();var Ti="VESPER_HOST_MISMATCH",Wc="VESPER_PLUGIN_ABSENT",re="vespercli init",Ye=e=>`vespercli init --host ${e}`,Ns="opencode";function lf(e){return e===Ns?"claude":e}function uf(e){return z.includes(e)||e===Ns}function uk(e,t,{runningLabel:r}={}){return t==="copilot"&&e==="claude"?`This workspace is provisioned for Claude Code, and VS Code just opened it. If you use GitHub Copilot here, run \`${Ye("copilot")}\` (it removes the Claude Code setup). If you use Claude Code inside VS Code, ignore this message \u2014 nothing was changed.`:r===Ns&&t==="claude"?`This workspace is provisioned for "${e}" but is running under OpenCode, which uses the "claude" host. Fix: ${Ye("claude")}`:`This workspace is provisioned for "${e}" but is running under "${t}". Fix: ${Ye(t)}`}var Rs=".vesper/instructions/vesper-host-guard.instructions.md",Vc="guard-rule",dk=["---","applyTo: '**'",'description: "Vesper host guard \u2014 refuse work in this workspace while a host mismatch is active"',"---","","# Vesper host guard","","Before doing anything else in this workspace, check whether `.vesper/.host-guard/ACTIVE` exists.","",`If it does, treat this session as \`${Ti}\`: this workspace was provisioned for a`,"different AI host than the one you are running in. Refuse all provisioning and orchestration","work, print the `fix:` command the file contains (`vespercli init --host <running host>` to","re-provision this workspace for the host you are running in, or `vespercli reset --host <x>`","to remove one host's Vesper files), and take no other action.","","If the file does not exist, this rule imposes nothing \u2014 proceed normally.","","This file is written by Vesper (`vespercli`) and is constant; the sentinel it names is","gitignored and written/cleared by `vespercli guard`.",""].join(`
|
|
91
|
-
`);function Kc(e){return e==="claude"?"copilot":"claude"}async function df(e){let t=Me(e),r={},n=!0;try{r=JSON.parse(await cf(t,"utf-8")),n=!1}catch{r={}}(!r||typeof r!="object"||Array.isArray(r))&&(r={});let s=Nc(r);return(s||n)&&(await P(Uc(e,".claude"),{recursive:!0}),await A(t,JSON.stringify(r,null," "),"utf-8")),{changed:s,created:n}}function pk(){return{label:Jn.taskLabel,command:qr("copilot"),presentation:{reveal:"always",panel:"shared"}}}async function fk(e,t,{unattended:r=!1}={}){return An(t),t==="claude"?df(e):Xn(e,{createOnly:r})}async function pf(e,t){if(An(t),t==="claude"){let n=await df(e);return await W(e,[Y({path:".claude/settings.json",host:"shared",category:"guard-trigger",owns:{keys:["hooks.SessionStart"]}})]),n}let r=await ko(e,pk());return await W(e,[Y({path:".vscode/tasks.json",host:"shared",category:"guard-trigger",owns:{keys:[Jn.taskLabel]}})]),r}async function Pi(e,t,{unattended:r=!1}={}){return An(t),await fk(e,t,{unattended:r}),await pf(e,Kc(t)),{legacyGuardRule:await Gr(e)}}async function Hc(e,t){let r=await x(e),n=J(r),s=n.filter(o=>!t(o));return s.length===n.length?!1:(r.manifest=s,await T(e,r),!0)}async function Ls(e,t){An(t);let r=J(await x(e));if(t==="claude"){let i=Me(e);if(await w(i))try{let a=JSON.parse(await cf(i,"utf-8"));xi(a,{markers:[Is.guard]})&&(Object.keys(a).length===0?await ck(i,{force:!0}):await A(i,JSON.stringify(a,null," "),"utf-8"))}catch{}await Hc(e,a=>a.path===".claude/settings.json"&&a.category==="guard-trigger");return}let n=r.some(i=>i.path===".vscode/tasks.json"&&i.category==="guard-trigger"),s=r.some(i=>i.path===".vscode/tasks.json"&&i.host==="copilot"),{fileRemoved:o}=await qn(e,Jn.taskLabel,{removeFileIfEmpty:n&&!s});if(o)try{await lk(Uc(e,".vscode"))}catch{}await Hc(e,i=>i.path===".vscode/tasks.json"&&i.category==="guard-trigger")}async function Gr(e){let n=J(await x(e)).find(o=>o.path===Rs&&o.category===Vc)??{path:Rs,category:Vc,hash:null},s=await le(Uc(e,Rs),n,{expected:[dk]});return await Hc(e,o=>o.path===Rs&&o.category===Vc),s==="partial"?"kept":s}function xn(){return`Kept your edited ${Rs} \u2014 Vesper no longer uses this file (a host mismatch now warns instead of refusing work) and never deletes a copy that differs from what it wrote. Delete it by hand.`}function hk(e){return e?.ignoredFile&&e.ignoredEvidence&&e.ignoredEvidence!=="both"?`This repository gitignores ${e.ignoredFile}, so a checkout cannot confirm the ${e.ignoredEvidence} provisioning it carries \u2014 bootstrap wrote nothing; session start still provisions this worktree. To bootstrap on checkouts too, commit ${e.ignoredFile} (remove it from .gitignore).`:e?.candidate?`This checkout's committed files carry no ${e.candidate} provisioning \u2014 bootstrap wrote nothing. Session start (or \`vespercli init\`) provisions it.`:"Not a vesperized workspace \u2014 nothing to bootstrap. Run `vespercli init` to set up."}function mk(e,t){return e?.gitError==="dubious-ownership"?`git refuses this repository (dubious ownership), so Vesper cannot read its checkout and provisions nothing here. Fix: git config --global --add safe.directory ${t}`:"git could not read this repository, so Vesper provisions nothing here; run `git status` to see why."}async function Ii(e,{runningHost:t,runningLabel:r}={}){let n=t!==void 0,s={identity:n,network:n,runningHost:t,journal:null,fix:null,note:null,message:null},o=await Ft(e),i=await B(e,{requireCommitted:!n&&!o});if(o)return n&&t!==o.to?{...s,action:"refuse",reason:"switch-in-progress",host:o.to,checkout:i,journal:o,fix:re,message:`An interrupted host switch (${o.from} \u2192 ${o.to}) is pending in this workspace. Fix: ${re}`}:{...s,action:"none",reason:"switch-in-progress",host:null,checkout:i,journal:o,note:`An interrupted host switch (${o.from} \u2192 ${o.to}) is pending \u2014 run \`vespercli init\` to finish it.`};let a=async()=>{let l=null;try{l=await $e(e,{checkout:i})}catch{l=null}return l?.unmigrated?{...s,action:"none",reason:"legacy-unmigrated",host:null,checkout:i,note:`Bootstrap wrote nothing. ${rt}`}:await Ai(e)?{...s,action:"none",reason:"migration-in-progress",host:null,checkout:i,note:"A Vesper 1.x migration was interrupted in this workspace \u2014 run `vespercli init` to finish it. Nothing was provisioned."}:null},c=i.source==="local";if(c){let l=await a();if(l)return l}if(n&&i.host&&i.host!==t)return{...s,action:"refuse",reason:"host-mismatch",host:i.host,checkout:i,fix:Ye(t),message:uk(i.host,t,{runningLabel:r})};if(!c){let l=await a();if(l)return l}if(i.gitError)return{...s,action:"none",reason:i.gitError==="dubious-ownership"?"not-vesperized":"git-unreadable",host:null,checkout:i,note:mk(i,e)};if(i.ambiguous)return{...s,action:"none",reason:"host-ambiguous",host:null,checkout:i,note:n?Ze:null};if(!i.host){let l=!n&&i.candidate?"host-unconfirmed":"not-vesperized",d=n?await Or(e):null,p=d?`This worktree's local record names ${d}, but the checked-out commit carries no Vesper provisioning \u2014 nothing was provisioned. \`vespercli init --host ${t}\` provisions it.`:hk(i);return{...s,action:"none",reason:l,host:null,checkout:i,note:p}}return{...s,action:"bootstrap",reason:"healthy",host:i.host,checkout:i}}async function ff(e,t,{checkout:r}={}){if(An(t),r?.source==="local"){for(let n of[gk(t),".vesperrc"])if(!await yk(e,n))return{healed:!1,reason:"local-tier"}}return await pf(e,t),{healed:!0}}function gk(e){return An(e),e==="claude"?".claude/settings.json":".vscode/tasks.json"}async function yk(e,t){return await D(["check-ignore","-q","--",t],{cwd:e,timeout:5e3})!==null}function An(e){if(!z.includes(e))throw new Error(`host must be one of: ${z.join(", ")} (received "${e}")`)}fe();Ee();un();Ut();dn();ut();ot();U();Es();As();bs();import{readFile as zc,readdir as Sk}from"node:fs/promises";import{homedir as Ek}from"node:os";var $=Object.freeze({ERROR:"error",WARN:"warn",INFO:"info"}),Oe=Object.freeze({OK:0,ERROR:1,HOST_MISMATCH:2}),hf=new Set(Object.values($)),kf="host-mismatch",bk="check-failed",xk=new Set(["playbook","pointer","mcp-config","settings"]);var mf=Ho,Ak=e=>`vespercli reset --host ${e}`;function I({code:e,severity:t,message:r,fix:n,category:s,path:o}){if(!hf.has(t))throw new Error(`makeFinding: unknown severity "${t}" for code "${e}". Valid severities: ${[...hf].join(", ")}. An unbucketed finding is invisible to both the rendered report and the exit code.`);let i={code:e,severity:t,message:r,fix:n||re};return s!==void 0&&(i.category=s),o!==void 0&&(i.path=o),i}function Bc(e,t){if(!t)return t;let r=kk(e,t);return r.startsWith("..")?t:r}async function _k(e){let r=[await kt(e),_e(e,".vesperrc"),_e(e,".vesper","tracking.json")],n=new Set;for(let s of r){if(n.has(s))continue;n.add(s);let o;try{o=await Ms(s,"utf-8")}catch(i){if(i&&i.code==="ENOENT")continue;return{corrupt:!0,corruptPath:s}}try{return{tracking:JSON.parse(o),trackingPath:s}}catch{return{corrupt:!0,corruptPath:s}}}return{absent:!0}}async function gf(e,t){let r=!1;try{r=await w(e)}catch{r=!1}if(!r)return{path:e,exists:!1,servers:[]};try{let n=JSON.parse(await Ms(e,"utf-8"));return{path:e,exists:!0,servers:Object.keys(n[t]||{})}}catch{return{path:e,exists:!0,servers:[]}}}async function Ck(e,t,{visible:r}={}){let n={};for(let s of Object.keys(t)){n[s]=[];for(let o of t[s])try{await qt(e,o,{visible:r})&&n[s].push(o)}catch(i){if(!$k(i))throw i}}return n}function $k(e){return!!e&&typeof e.code=="string"&&["ENOENT","EACCES","EISDIR","ENOTDIR","EPERM","ELOOP","ENAMETOOLONG"].includes(e.code)}function Ok(e){return ya(e)}async function Tk(e,t,{homeDir:r=Ek(),checkout:n=null}={}){let s=await _k(e);if(s.corrupt)return{workspaceRoot:e,runningHost:t,corrupt:!0,corruptPath:s.corruptPath};let o=s.tracking||null,i=n;i||(i=await B(e,{withCommitted:!0}));let a=i.host,c=null;try{c=await Ft(e)}catch{c=null}let l=null,d=!1;try{l=await Fc(e)}catch{l=null}try{d=await Ai(e)}catch{d=!1}let p=await ud(e),f=[...p.missing,...p.modified,...p.clean],m=await Wo(e),h=Qs(),g=[];try{g=await ge(e)}catch{g=[]}let y=a?[a]:g,k={claude:await gf(Ge(e),"mcpServers"),copilot:await gf(Xe(e),"servers")},v=Zt(),S=i.ambiguous?"both":i.host,C=await Ck(e,v,{visible:i.visible}),N={};for(let[Ve,gr]of Object.entries(C))N[Ve]=gr.some(Ok);let E={};for(let Ve of z)E[Ve]=await Gn(e,Ve);let b=null;try{b=await $e(e,{checkout:i})}catch{b=null}let G=[];try{G=(await Oi({homeDir:r,workspaceRoot:e})).filter(Ve=>Ve.kind==="plugin")}catch{G=[]}let X=[];try{X=await af(e)}catch{X=[]}let De=await Or(e),Tn=!!De&&De!==a;{let Ve=i.source==="local"?null:a,gr=yr=>{if(!yr)return!1;if(z.includes(yr.host))return yr.host===Ve;let Ct=Pk(yr);return!Ct||Ct===Ve};p={...p,missing:p.missing.filter(gr),modified:p.modified.filter(gr),clean:p.clean.filter(gr),userLevelViolations:p.userLevelViolations}}let _t=[...p.missing,...p.modified,...p.clean],zt=!!a||f.length>0;return{workspaceRoot:e,runningHost:t,absent:!!s.absent,tracking:o,host:a,checkout:i,ledgerHostForReporting:De,verify:p,manifestEntries:_t,manifestAll:f,recordStale:Tn,journal:c,migrationTorn:l,migrationActive:d,frameworkVersion:m,packageVersion:h,installedTargets:y,mcpConfigs:k,detectedHost:S,fingerprintMatches:C,fingerprintSpecific:N,residue:E,legacy:b,userResidue:G,keptItems:X,initialised:zt}}function Pk(e){return e.category==="guard-rule"||e.category==="guard-trigger"&&e.path===".claude/settings.json"?"copilot":e.category==="guard-trigger"&&e.path===".vscode/tasks.json"?"claude":null}function Sf(e,t){return e.checkout?.host===t||!!e.fingerprintSpecific?.[t]}function Ik(e){let t=[],{verify:r}=e;for(let n of r.userLevelViolations)t.push(I({code:"user-level-violation",severity:$.ERROR,category:n.category,path:n.path,message:`Owned file "${n.path}" sits under a user-level scan path \u2014 it would silently activate in unrelated projects (isolation breach).`,fix:re}));for(let n of r.modified)(Gt[n.category]||{}).doctor==="server-drift"?t.push(I({code:"mcp-core-missing",severity:$.ERROR,category:n.category,path:n.path,message:`A required Vesper-core MCP server is missing from "${n.path}".`,fix:re})):t.push(I({code:"file-edited",severity:$.WARN,category:n.category,path:n.path,message:`"${n.path}" was edited since the last Vesper write in this worktree.`,fix:re}));for(let n of r.missing){let s=xk.has(n.category);t.push(I({code:"owned-file-missing",severity:s?$.ERROR:$.WARN,category:n.category,path:n.path,message:s?`Load-bearing owned file "${n.path}" is missing \u2014 framework cannot operate.`:`Owned file "${n.path}" is missing \u2014 \`vespercli init\` will re-provision it.`,fix:re}))}return t}async function ji(e,t={}){let r=new Set,n=t.installedTargets;if(!Array.isArray(n))try{let a=await sn(e);n=a?[a]:await ge(e)}catch{n=[]}if(n.includes("claude"))if(t.mcpConfigs?.claude)for(let a of t.mcpConfigs.claude.servers)r.add(a);else try{let a=await jk(e);for(let c of Object.keys(a.mcpServers||{}))r.add(c)}catch{}if(n.includes("copilot"))if(t.mcpConfigs?.copilot)for(let a of t.mcpConfigs.copilot.servers)r.add(a);else try{let a=await Qe(e);for(let c of Object.keys(a.servers||{}))r.add(c)}catch{}let s=[];if("tracking"in t)s=Array.isArray(t.tracking?.mcp?.servers)?t.tracking.mcp.servers:[];else try{let a=await x(e);s=Array.isArray(a.mcp?.servers)?a.mcp.servers:[]}catch{s=[]}let o=new Set(s);return{drifted:[...r].filter(a=>!me.includes(a)&&!o.has(a))}}async function jk(e){try{return JSON.parse(await Ms(Ge(e),"utf-8"))}catch{return{mcpServers:{}}}}async function Rk(e){let{drifted:t}=await ji(e.workspaceRoot,{tracking:e.tracking,mcpConfigs:e.mcpConfigs,installedTargets:e.installedTargets});return t.map(r=>I({code:"mcp-drift",severity:$.WARN,category:"mcp-config",message:`MCP server "${r}" is present in the live MCP config but not tracked in .vesperrc mcp.servers.`,fix:re}))}async function Nk(e){return!e.initialised||!e.host?[]:(e.manifestAll??e.manifestEntries).some(r=>r.category==="mcp-config")?[]:Lk(e)?[I({code:"mcp-config-unrecorded",severity:$.ERROR,category:"mcp-config",message:"A live MCP config exists but is not recorded in the owned-files manifest \u2014 Vesper cannot reconcile its managed servers.",fix:re})]:[]}function Lk(e){return!!e.mcpConfigs?.[e.host]?.exists}function Mk(e){if(e.absent||!e.tracking)return[];let t=e.tracking;return(t.host===void 0||z.includes(t.host))&&Array.isArray(t.manifest)&&t.schemaVersion===ve?[]:[I({code:"tracking-shape-invalid",severity:$.WARN,path:".vesperrc",message:".vesperrc parses but its shape is invalid (host/manifest/schemaVersion) \u2014 `vespercli init` repairs it.",fix:re})]}async function Fk(e){let t=[];if(e.detectedHost==="both"){let r=z.every(n=>Sf(e,n));t.push(I({code:"host-ambiguous",severity:r?$.ERROR:$.WARN,message:r?mf:`${mf} (Reported as a warning: at least one host matched only generic, non-Vesper-specific files, so this is probably not a real dual provisioning.)`,fix:"vespercli init --host <claude|copilot>"}))}if(e.host){let r=e.host==="claude"?"copilot":"claude";await Gk(e,r)&&t.push(I({code:"host-residue",severity:$.WARN,message:`This workspace is host "${e.host}" but still carries "${r}" artifacts (a leftover from a host switch).`,fix:Ak(r)}))}return t}async function Gk(e,t){if(e.checkout?.ignoredEvidence===t)return!0;let r=e.tracking||{};if(!(Number(r.schemaVersion)>=2)&&(t==="claude"&&r.claude||t==="copilot"&&Array.isArray(r.paths)&&r.paths.length>0))return!0;let n=[...e.residue?.[t]||[]];for(let a of e.manifestAll||[])a?.host!==t||a.owns||Re.has(a.category)||typeof a.path!="string"||a.path.includes("..")||vk(a.path)||await w(_e(e.workspaceRoot,a.path))&&n.push(a.path);if(!n.length)return!1;if(e.checkout?.visible===null||e.checkout?.visible===void 0)return!e.checkout?.gitError;let{runGit:s}=await Promise.resolve().then(()=>(ot(),ua)),{READ_ONLY_GIT_ENV:o}=await Promise.resolve().then(()=>(gt(),Ea)),i=await s(["--literal-pathspecs","ls-files","-z","--cached","--others","--exclude-standard","--",...n],{cwd:e.workspaceRoot,timeout:1e4,env:{...process.env,...o}});return!!i&&i.split("\0").some(Boolean)}function Dk(e){let t=[],r=e.checkout||{},n=e.ledgerHostForReporting??null;r.gitError==="dubious-ownership"?t.push(I({code:"git-dubious-ownership",severity:$.WARN,message:"git refuses this repository (dubious ownership), so Vesper cannot read its checkout and provisions nothing here.",fix:`git config --global --add safe.directory ${e.workspaceRoot}`})):r.gitError&&t.push(I({code:"git-unreadable",severity:$.INFO,message:"git could not read this repository, so Vesper provisions nothing here; run `git status` to see why.",fix:"git status"})),e.journal&&t.push(I({code:"host-switch-pending",severity:$.WARN,message:`An interrupted host switch (${e.journal.from} \u2192 ${e.journal.to}) is pending; automatic provisioning is suspended until \`vespercli init\` finishes it.`,fix:re}));let s=!r.host&&!r.ambiguous&&!r.gitError;if(n&&(r.host&&r.host!==n||s&&!e.journal&&!e.legacy?.needsMigration)&&t.push(I({code:"host-record-stale",severity:$.INFO,path:".vesperrc",message:`This worktree's local record describes a ${n} provisioning, but the checked-out commit is ${r.host??"not provisioned"}. The record is not used to decide the host.`,fix:Ye(r.host??n)})),r.source==="local"&&r.host&&t.push(I({code:"host-local-only",severity:$.INFO,path:r.ignoredFile??void 0,message:`Vesper's activation here lives in gitignored ${r.ignoredFile}; it follows this worktree across branches, not the commit. Commit ${r.ignoredFile} for per-commit behaviour.`,fix:Ye(r.host)})),!r.host&&r.ignoredEvidence){let o=r.ignoredEvidence==="both"?"claude|copilot":r.ignoredEvidence;t.push(I({code:"host-local-unconfirmed",severity:$.WARN,path:r.ignoredFile??void 0,message:`Vesper keys for ${o} are only in gitignored ${r.ignoredFile}, and this worktree's record does not confirm them \u2014 nothing is provisioned from them. Commit ${r.ignoredFile}, or run \`vespercli init --host ${r.ignoredEvidence==="both"?"<claude|copilot>":o}\`.`,fix:r.ignoredEvidence==="both"?"vespercli init --host <claude|copilot>":Ye(o)}))}return t}function Vk(e){let t=[];for(let r of z){let n=e.residue?.[r]||[];n.length&&((e.fingerprintMatches?.[r]||[]).length>0||e.host!==r&&t.push(I({code:"host-leftover-files",severity:$.WARN,message:`Leftover ${r} files that hold your edits: ${n.join(", ")} \u2014 delete them, or run \`${Ye(r)}\` to provision ${r} again. They do not mark this workspace as ${r}.`,fix:Ye(r)})))}return t}function yf(e){let t=z.filter(r=>e?.hosts?.[r]);return t.length===1?Ye(t[0]):"vespercli init --host claude (or --host copilot \u2014 Vesper 2.0 provisions exactly one host)"}function Hk(e){let t=[],r=e.legacy;r?.unmigrated?t.push(I({code:"legacy-workspace",severity:$.ERROR,message:`${rt} Evidence: ${r.evidence.join(", ")||"1.x record"}.`,fix:yf(r)})):(r?.advisory||r?.residue)&&t.push(I({code:"legacy-residue",severity:$.WARN,message:r.advisory?`Pre-2.0 Vesper leftovers and no 2.0 host (${r.evidence.join(", ")}) \u2014 \`vespercli init\` migrates them.`:`This 2.0 workspace still carries pre-2.0 Vesper state (${r.evidence.join(", ")}) \u2014 \`vespercli init\` finishes the migration.`,fix:r.residue&&e.host?Ye(e.host):yf(r)})),r&&!r.unmigrated&&!r.advisory&&r.leftovers.length&&t.push(I({code:"legacy-leftover-files",severity:$.WARN,message:`Leftover 1.x files that hold your edits: ${r.leftovers.join(", ")} \u2014 Vesper 2.0 never reads them. Delete them once you have kept what you need.`,fix:`rm ${r.leftovers.join(" ")}`}));for(let n of e.userResidue||[])t.push(I({code:"user-level-residue",severity:$.ERROR,path:n.path,message:`The pre-1.9 machine-wide Vesper catalog is still here (${n.marker}${n.kept?`; ${n.kept} other file(s) there are yours and stay`:""}) \u2014 every project on this machine loads it. \`vespercli init\` backs the folder up and removes only the files a released Vesper build wrote.`,fix:re}));return e.migrationTorn?t.push(I({code:"migration-record-unreadable",severity:$.WARN,path:Bc(e.workspaceRoot,e.migrationTorn),message:`The newest migration record (${Bc(e.workspaceRoot,e.migrationTorn)}) is unreadable, so automatic provisioning is suspended; \`vespercli init\` sets it aside and continues.`,fix:re})):e.migrationActive&&!t.length&&t.push(I({code:"migration-in-progress",severity:$.WARN,message:"A Vesper 1.x migration was interrupted in this workspace; automatic provisioning is suspended until `vespercli init` finishes it.",fix:re})),t}async function Uk(e){if(e.host!=="claude"||e.legacy?.needsMigration)return[];let t=await bt(),r=new Set((e.manifestEntries||[]).map(o=>o.path)),n=new Set;for(let o of e.keptItems||[])(o.reason==="edited-catalog"||o.reason==="edited-skill")&&n.add(o.rel);try{for(let o of await Sk(_e(e.workspaceRoot,".claude","agents"))){let i=`.claude/agents/${o}`;if(!o.endsWith(".md")||r.has(i)||!si("agents",o,""))continue;let a=null;try{a=await zc(_e(e.workspaceRoot,i))}catch{a=null}a&&!ni(a,`agents/${o}`)&&n.add(i)}}catch{}let s=[];for(let o of[...n].sort()){if(r.has(o)||!await w(_e(e.workspaceRoot,o)))continue;let i=/^\.claude\/(agents|skills)\/([^/]+?)(\.md)?$/.exec(o);if(!i)continue;let[,a,c]=i;if(!(a==="agents"?t.agents:t.skills).has(c)||a==="skills"&&!await w(_e(e.workspaceRoot,o,"SKILL.md")))continue;let l=a==="agents"?_e(O,"claude","agents",`${c}.md`):_e(O,"claude","skills",c);s.push(I({code:"kept-shadows-plugin",severity:$.WARN,path:o,message:`${o} is a 1.x copy kept because it holds your edits, and it shadows the plugin's \`vesper:${c}\` (Claude Code prefers the project-level one) \u2014 you keep getting the 1.x version.`,fix:`compare: ${a==="agents"?"diff":"diff -r"} "${_e(e.workspaceRoot,o)}" "${l}"; then either keep yours (it wins) or delete it (${a==="agents"?"rm":"rm -r"} ${o}) to use vesper:${c}`}))}return s}async function Wk(e){if(e.host!=="claude")return[];let t;try{t=await zc(_e(e.workspaceRoot,".claude","rules","vesper-orchestration.md"),"utf-8")}catch{return[]}let r=vd(t,(await bt()).agents);return r.length?[I({code:"roster-unqualified-agents",severity:$.WARN,path:".claude/rules/vesper-orchestration.md",message:`The Team Roster names ${r.length} specialist(s) without the plugin namespace (${r.slice(0,6).join(", ")}${r.length>6?", \u2026":""}) \u2014 2.0 serves them as \`vesper:<name>\`, so delegation to them does not match until the roster is revalidated.`,fix:"run `/revalidate-team` once in Claude Code (it rewrites the roster with vesper:<name> names)"})]:[]}async function Kk(e){if(!e.host)return[];let t=await cr(e.workspaceRoot,e.host);if(t===null)return[];let r=await lr(t),{enabled:n}=await Lr(e.workspaceRoot,e.host),s=[];for(let o of r.packs){if(n.includes(o))continue;let i=[...r.needed[o].agents,...r.needed[o].skills];s.push(I({code:"pack-not-enabled",severity:$.WARN,path:vn[e.host],message:`The Team Roster names ${i.length} asset(s) of the "${o}" pack (${Ne(o)}: ${i.slice(0,6).join(", ")}${i.length>6?", \u2026":""}), but that pack is not enabled for ${e.host} in this workspace \u2014 delegation to them does not resolve until it is.`,fix:ap}))}for(let o of n)r.packs.includes(o)||Pr(o)||o===Le||s.push(I({code:"pack-unused",severity:$.INFO,path:e.host==="claude"?".claude/settings.json":".vscode/settings.json",message:`The "${o}" pack (${Ne(o)}) is enabled for ${e.host}, but the Team Roster names none of its assets.`,fix:`vespercli packs disable ${o} (or keep it \u2014 an unused pack costs only load time)`}));return s}async function Bk(e){if(!e.runningHost)return[];if(e.journal)return[];if(e.checkout?.source==="local"&&e.legacy?.unmigrated)return[];if(e.checkout?.source==="local"&&e.migrationActive)return[];let t=[],r=e.checkout?.host??null;if(!r)return t.push(I({code:"host-unresolved",severity:$.INFO,message:"Could not resolve the provisioned host from disk (no recorded host and no Vesper-specific fingerprint) \u2014 the host-identity check has nothing to compare against.",fix:re})),t;if(r!==e.runningHost){let n=Sf(e,r);t.push(I({code:kf,severity:n?$.ERROR:$.WARN,message:n?`This workspace is provisioned for host "${r}" but is running under "${e.runningHost}".`:`This workspace looks like host "${r}" but is running under "${e.runningHost}". Reported as a warning: the only evidence is generic, non-Vesper-specific files, so this may not be a Vesper workspace at all.`,fix:Ye(e.runningHost)}))}return t}async function zk(e){if(e.host!=="claude")return[];let t;try{t=JSON.parse(await zc(En(e.workspaceRoot),"utf-8"))}catch{return[]}let r=t?.extraKnownMarketplaces?.[Ce];return r===void 0||zp(r)?[]:[I({code:"marketplace-entry-invalid",severity:$.WARN,path:".claude/settings.local.json",message:`The \`extraKnownMarketplaces.${Ce}\` entry is not in Claude Code's schema (\`source\` must be an object: {"source":"directory","path":\u2026}); Claude Code ignores it and the vesper plugin does not load.`,fix:"vespercli worktree bootstrap"})]}function Yk(e){if(!e.initialised)return[];let t=e.packageVersion;if(!t)return[];let r=e.frameworkVersion;return r?r!==t?[I({code:"framework-stale",severity:$.WARN,message:`Workspace provisioned with Vesper ${r}, running ${t}.`,fix:re})]:[]:[I({code:"ledger-unstamped",severity:$.INFO,message:"This worktree's ledger (`.vesperrc`) carries no framework version yet \u2014 `init` has not run in this worktree (bootstrap does not stamp one).",fix:re})]}async function Jk(e){return e.initialised?await w(_e(e.workspaceRoot,ue))?[]:e.manifestAll?.some(t=>t?.path===ue)?[]:[I({code:"gates-missing",severity:$.INFO,path:ue,message:"No gate policy (`.vesper/gates.json`) \u2014 `vespercli gate` exits 2 here until `init` seeds one.",fix:re})]:[]}async function qk(e){if(e.host!=="claude")return[];let t=new Set((e.manifestAll||[]).map(n=>n?.path)),r=[];for(let n of bp)t.has(n)||await w(_e(e.workspaceRoot,n))||r.push(n);return r.length?[I({code:"opencode-overlay-missing",severity:$.INFO,path:r[0],message:`OpenCode overlay incomplete \u2014 missing ${r.join(", ")}. \`vespercli init\` adds the missing file(s); nothing else changes (a 2.0.x Claude workspace gets the overlay this way).`,fix:re})]:[]}async function Xk(e){if(e.host!=="claude")return[];let t=_e(e.workspaceRoot,".claude","agents"),r=[];try{r=(await wk(t,{withFileTypes:!0})).filter(o=>o.isFile()&&o.name.endsWith(".md")).map(o=>o.name)}catch{return[]}let n=[];for(let s of r){let o=`.claude/agents/${s}`;try{let i=await Ms(_e(t,s),"utf-8"),a=Qk(i);(!a||!wf(a.name)||!wf(a.description))&&n.push(I({code:"agent-frontmatter-incomplete",severity:$.WARN,category:"catalog-agent",path:o,message:`Committed agent "${o}" is missing a non-empty name/description in its frontmatter.`,fix:re}))}catch{}}return n}function wf(e){return typeof e=="string"&&e.trim().length>0}function Qk(e){let t=/^---\r?\n([\s\S]*?)\r?\n---/.exec(e);if(!t)return null;let r={};for(let n of t[1].split(/\r?\n/)){let s=/^([A-Za-z0-9_-]+):\s*(.*)$/.exec(n);if(!s)continue;let o=s[2].trim();(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),r[s[1]]=o}return r}async function Zk(e){let t=[],r=e.checkout||{};if(!r.host||r.source==="local"||r.gitError)return t;let{resolveGitHooksDir:n,gitHooksSkipMessage:s,VESPER_MANAGED_GIT_HOOKS:o,isHookTrackedByGit:i,realOrNearestAncestor:a,resolveHookWriteTarget:c}=await Promise.resolve().then(()=>(H(),Ma)),{runGit:l}=await Promise.resolve().then(()=>(ot(),ua)),{classifyForeignHook:d,HOOK_GUARD_START:p,HOOK_GUARD_END:f}=await Promise.resolve().then(()=>(Wr(),Yl));if(await l(["config","--type=bool","--get","vesper.hooks"],{cwd:e.workspaceRoot,timeout:5e3})==="false")return t.push(I({code:"git-hooks-opted-out",severity:$.INFO,message:"Vesper's git hooks are turned off for this repository (git config vesper.hooks false): no guard runs on checkout and no commit hygiene on commit.",fix:"git config --unset vesper.hooks && vespercli worktree bootstrap"})),t;let m=await n(e.workspaceRoot);if(!m.dir)return m.reason==="not-a-repo"||t.push(I({code:"git-hooks-not-installable",severity:$.INFO,message:s({...m,hook:"hook"})??`Git hooks not installable (${m.reason}).`,fix:"see the message"})),t;if(!m.default&&await i(await a(m.dir),m,{dir:!0}))return t.push(I({code:"git-hooks-not-installable",severity:$.INFO,message:s({reason:"tracked-by-git",configured:m.dir}),fix:"see the message"})),t;for(let h of o){let g=_e(m.dir,h),y=await c(g),k=null;if(y.path)try{k=await Ms(y.path)}catch{k=null}let v=k?k.toString("latin1"):"",S=v.indexOf(p);if(S!==-1){let N=v.indexOf(f,S),E=v.slice(S,N===-1?void 0:N);E.includes("vesper.hooks")?h==="pre-commit"&&!E.includes("VESPER_NO_SWEEP")&&t.push(I({code:"git-hook-outdated",severity:$.INFO,path:g,message:`Vesper's pre-commit git hook block (${g}) predates VESPER_NO_SWEEP: an agent's commit still sweeps every dirty knowledge path into it.`,fix:"vespercli worktree bootstrap"})):t.push(I({code:"git-hook-outdated",severity:$.INFO,path:g,message:`Vesper's ${h} git hook block (${g}) predates the run-time opt-out check: \`git config vesper.hooks false\` would not stop it.`,fix:"vespercli worktree bootstrap"}));continue}let C=null;if(!y.path)C={reason:y.reason,configured:g};else if(k&&await i(await a(y.path),m))C={reason:"tracked-by-git",configured:y.path};else if(k){let N=d(k);N.ok||(C={reason:N.reason,interpreter:N.interpreter,line:N.line})}if(C){t.push(I({code:"git-hook-not-modifiable",severity:$.INFO,path:g,message:s({...C,hook:h,hooksDir:m.dir})??`Git hook ${h} cannot carry Vesper's block (${C.reason}).`,fix:"see the message"}));continue}t.push(I({code:"git-hook-missing",severity:$.WARN,path:g,message:`Vesper's ${h} git hook block is missing (${g}): ${h==="post-checkout"?"a branch switch or a new worktree does not run the host guard":"commits do not carry the project-knowledge files"}.`,fix:"vespercli worktree bootstrap"}))}return t}async function eS(e){if(!e.host)return[];if(!await fn(e.workspaceRoot,e.host))return[];let t=[],r=e.host==="claude"?".claude/settings.json":".vscode/settings.json";At()||t.push(I({code:"graphify-missing",severity:$.INFO,path:r,message:"The graphify pack is enabled but the `graphify` tool is not on PATH \u2014 the post-checkout refresh and `graphify update .` do nothing until it is installed (vesper-indexing remains the default codebase tool).",fix:Zo()}));let n=await Gd(e.workspaceRoot);if(!n.present)return t.push(I({code:"graphify-no-graph",severity:$.INFO,path:ze,message:`The graphify pack is enabled but ${ze} does not exist \u2014 the graphify MCP server has nothing to serve until the graph is built.`,fix:xt})),t;if(!n.commit)return t;let s=await D(["rev-parse","HEAD"],{cwd:e.workspaceRoot});return s&&(s.startsWith(n.commit)||n.commit.startsWith(s)||t.push(I({code:"graphify-stale",severity:$.WARN,path:ze,message:`${ze} was built from commit ${n.commit.slice(0,12)} (\`${n.key}\`) but HEAD is ${s.slice(0,12)} \u2014 impact and path answers may miss recent changes.`,fix:xt}))),t}var Ef=[{id:"manifest",title:"Owned-files manifest",run:e=>Ik(e)},{id:"mcp-drift",title:"MCP config drift",run:e=>Rk(e)},{id:"mcp-required",title:"MCP config recorded",run:e=>Nk(e)},{id:"tracking",title:"Tracking structure",run:e=>Mk(e)},{id:"host-conflict",title:"Host conflict",run:e=>Fk(e)},{id:"host-authority",title:"Host authority (checkout vs worktree record)",run:e=>Dk(e)},{id:"host-leftover",title:"Leftover host files",run:e=>Vk(e)},{id:"legacy",title:"Pre-2.0 (1.x) residue",run:e=>Hk(e)},{id:"legacy-kept-shadows",title:"Kept 1.x copies shadowing plugin specialists",run:e=>Uk(e)},{id:"roster-namespaces",title:"Team Roster delegation names",run:e=>Wk(e)},{id:"packs",title:"Packs the Team Roster needs",run:e=>Kk(e)},{id:"git-hooks",title:"Vesper git hooks",run:e=>Zk(e)},{id:"graphify",title:"graphify pack (opt-in)",run:e=>eS(e)},{id:"host-mismatch",title:"Host identity",run:e=>Bk(e),failureSeverity:e=>e.runningHost?$.ERROR:$.WARN},{id:"framework-version",title:"Framework version",run:e=>Yk(e)},{id:"marketplace-entry",title:"Marketplace entry shape",run:e=>zk(e)},{id:"agent-frontmatter",title:"Agent frontmatter",run:e=>Xk(e)},{id:"gates-config",title:"Gate policy",run:e=>Jk(e)},{id:"opencode-overlay",title:"OpenCode overlay",run:e=>qk(e)}];function vf(e){let t=e.filter(o=>o.severity===$.ERROR),r=e.filter(o=>o.severity===$.WARN),n=e.filter(o=>o.severity===$.INFO),s=t.some(o=>o.code===kf);return{findings:e,errors:t,warnings:r,infos:n,summary:{hasError:t.length>0,hostMismatch:s}}}async function _n(e,{runningHost:t,homeDir:r,checkout:n}={}){let s=await Tk(e,t,{homeDir:r,checkout:n});return s.corrupt?vf([I({code:"tracking-unparseable",severity:$.ERROR,path:Bc(e,s.corruptPath),message:"Malformed .tracking structure (.vesperrc is present but unparseable) \u2014 framework cannot operate.",fix:re})]):vf(await tS(s,Ef))}async function tS(e,t=Ef){let r=[];for(let n of t)try{let s=await n.run(e);Array.isArray(s)&&r.push(...s)}catch(s){let o=n.failureSeverity?n.failureSeverity(e):$.WARN;r.push(I({code:bk,severity:o,category:n.id,message:`Doctor check "${n.title}" (${n.id}) failed to run \u2014 its coverage is MISSING from this report, not clean: ${s?.message||s}`,fix:re}))}return r}function Ri(e){return e.summary.hostMismatch?Oe.HOST_MISMATCH:e.summary.hasError?Oe.ERROR:Oe.OK}xe();H();function Yc(e){return String(e??"").replace(/\r\n?/g,`
|
|
92
|
-
`)}function
|
|
93
|
-
`),n=r.findIndex(i=>new RegExp(`^${t}:`).test(i));if(n===-1)return null;let s=r[n].slice(t.length+1).trim();if(s&&![">","|",">-","|-"].includes(s))return/^'.*'$/.test(s)?s.slice(1,-1).replace(/''/g,"'"):/^".*"$/.test(s)?s.slice(1,-1).replace(/\\"/g,'"'):s;let o=[];for(let i=n+1;i<r.length;i++){if(!/^\s+\S/.test(r[i])){if(r[i].trim()==="")continue;break}o.push(r[i].trim())}return o.length?o.join(" "):null}function
|
|
94
|
-
`)}function
|
|
95
|
-
`).map(t=>t.trimStart().startsWith("- ")&&t.includes(
|
|
96
|
-
`)}function
|
|
97
|
-
`,r);n===-1&&(n=e.length);let s=`> **How the Vesper team resolves here:** on the Copilot host the specialist catalog is NOT a plugin and needs no workspace-trust dialog \u2014 the agents, skills, prompts and instructions are read straight from the installed \`@mthanh/vespercli\` package through the \`chat.*FilesLocations\` entries Vesper injects into \`.vscode/settings.json\`. Every package agent is a HIDDEN specialist (\`user-invocable: false\`); the only pickable Vesper agent is \`${L}\`, provisioned project-local at \`${
|
|
88
|
+
${s}`;return await A(t,o,"utf-8"),{created:!1,updated:!0}}function Uv(e){let t=new RegExp(`${Nc}[\\s\\S]*?${Lc}\\n*`);return e.replace(t,"")}function Wv(e){return R(e,".claude","rules")}async function xi(e){let t=Wv(e);await P(t,{recursive:!0});let r={orchestrator:"refreshed",orchestration:"skipped",context:"skipped"},n=[],s=".claude/rules/vesper-orchestrator.md";await A(R(e,s),await ie(R(De,"vesper-orchestrator.md"),"utf-8"),"utf-8"),n.push(G({path:s,host:"claude",category:"playbook",hash:await ye(R(e,s))}));let o=async(l,d,p)=>{await w(R(e,l))||(await A(R(e,l),await ie(R(De,d),"utf-8"),"utf-8"),r[p]="created"),n.push(G({path:l,host:"claude",category:"per-project-authored",hash:null}))};if(await o(".claude/rules/vesper-orchestration.md","orchestration.md.tpl","orchestration"),r.orchestration==="skipped"){let l=R(e,".claude/rules/vesper-orchestration.md"),d=await ie(l,"utf-8"),p=await _t(),f=new Set;for(let h of p.agents)await w(R(e,".claude","agents",`${h}.md`))&&f.add(h);let m=qo(d,p,{skip:f});m.qualified.length&&(await A(l,m.text,"utf-8"),r.orchestration=`namespaced ${m.qualified.length} specialist name(s) to their plugin (vesper:<name> / vesper-<pack>:<name>)`)}await o(".claude/rules/vesper-context.md","context.md.tpl","context");let i=await oi(e);r.gates=i.created?`created (checks: ${i.checks.join(", ")||"none"})`:"skipped",n.push(G({path:ue,host:"claude",category:"per-project-authored",hash:null}));let a=await Hv(e);r.claudeMd=a.created?"created":a.updated?"updated":"unchanged",n.push(Y({path:"CLAUDE.md",host:"claude",category:"pointer",owns:{region:"vesper"}})),await W(e,n);let c=await Fp(e);return r.opencodeAgent=c.agent,r.opencodePlugin=c.plugin,r.opencodeKept=c.keptEdited,r}async function Ai(e){let t=Ve(e);try{let r=await ie(t,"utf-8");return JSON.parse(r)}catch(r){return r.code==="ENOENT"?{mcpServers:{}}:{mcpServers:{}}}}async function _i(e,t){let r=Ve(e);await P(Ls(r),{recursive:!0}),await A(r,JSON.stringify(t,null," "),"utf-8")}function Kv(e){return{"vesper-indexing":{command:"node",args:[Be()],env:{VESPER_INDEX_ROOT:e}},"sequential-thinking":{command:"npx",args:["-y","@modelcontextprotocol/server-sequential-thinking"]},memory:{command:"npx",args:["-y","@modelcontextprotocol/server-memory"],env:{MEMORY_FILE_PATH:R(e,".vesper","memory.jsonl")}}}}async function mr(e,t=!0,{record:r=!0}={}){let n=await Ai(e);n.mcpServers||(n.mcpServers={});let s=Kv(e),o=Object.keys(s);if(t)for(let[i,a]of Object.entries(s))n.mcpServers[i]=a;else for(let i of o)delete n.mcpServers[i];return await _i(e,n),t&&r&&await W(e,[Y({path:Yp,host:"claude",category:"mcp-config",owns:{keys:o}})]),{configured:t,mcpPath:Ve(e),servers:t?o:[]}}function jc(e,t){return String(e).replace(/\$\{VESPER_INDEXING_PATH\}/g,Be()).replace(/\$\{workspaceFolder\}/g,t).replace(/\$\{env:([^}]+)\}/g,"$${$1}")}function Bv(e,{workspaceRoot:t}){let{type:r,...n}=structuredClone(e);if(typeof n.command=="string"&&(n.command=jc(n.command,t)),Array.isArray(n.args)&&(n.args=n.args.map(s=>jc(s,t))),n.env&&typeof n.env=="object")for(let[s,o]of Object.entries(n.env))n.env[s]=jc(o,t);return n}async function Sn(e,t){if(me.includes(t))return{added:!1,serverName:t,error:`${t} is a Vesper-managed core server \u2014 use "vespercli mcp enable --target claude" instead.`};let r=we[t];if(!r)return{added:!1,serverName:t,error:`Unknown MCP server: ${t}`};let n=await Ai(e);if(n.mcpServers||(n.mcpServers={}),n.mcpServers[t])return{added:!1,serverName:t,error:"Already configured"};n.mcpServers[t]=Bv(r.config,{workspaceRoot:e}),await _i(e,n);let s=await x(e);return s.mcp=s.mcp||{},s.mcp.servers=s.mcp.servers||[],s.mcp.servers.includes(t)||s.mcp.servers.push(t),s.mcp.updatedAt=new Date().toISOString(),await T(e,s),await Ic(e),{added:!0,serverName:t}}async function hi(e,t){if(me.includes(t))return{removed:!1,serverName:t,error:`${t} is a Vesper-managed core server \u2014 use "vespercli mcp disable --target claude" instead.`};let r=await Ai(e),n=!1;r.mcpServers&&r.mcpServers[t]&&(delete r.mcpServers[t],await _i(e,r),n=!0);let s=await x(e);return s.mcp?.servers&&(s.mcp.servers=s.mcp.servers.filter(o=>o!==t),s.mcp.updatedAt=new Date().toISOString(),await T(e,s)),await Ic(e),{removed:n,serverName:t}}async function Mc(e){let t=await Ai(e),r=Object.keys(t.mcpServers||{}),n=r.filter(s=>!we[s]);return{configured:r,custom:n}}function zv(e){let t=e?.permissions?.allow;if(!Array.isArray(t))return!1;let r=new Set(Xp),n=t.filter(s=>!r.has(s));return n.length===t.length?!1:(n.length?e.permissions.allow=n:delete e.permissions.allow,Object.keys(e.permissions).length===0&&delete e.permissions,!0)}function Qp(e){(!e.permissions||typeof e.permissions!="object")&&(e.permissions={}),Array.isArray(e.permissions.allow)||(e.permissions.allow=[]);let t=0;for(let r of Xp)e.permissions.allow.includes(r)||(e.permissions.allow.push(r),t+=1);return t}async function Zp(e){let t=Fe(e),r={},n=null;try{n=await ie(t,"utf-8")}catch{n=null}if(n!==null){try{r=JSON.parse(n)}catch{return{configured:0,settingsPath:t,skipped:"malformed"}}if(!r||typeof r!="object"||Array.isArray(r))return{configured:0,settingsPath:t,skipped:"malformed"}}let s=Qp(r);return(s>0||n===null)&&(await P(Ls(t),{recursive:!0}),await A(t,JSON.stringify(r,null," "),"utf-8")),{configured:s,settingsPath:t}}async function ef(e){let t=Fe(e),r={};try{r=JSON.parse(await ie(t,"utf-8"))}catch{r={}}let n=Qp(r);(!r.enabledPlugins||typeof r.enabledPlugins!="object")&&(r.enabledPlugins={}),r.enabledPlugins[wt]=!0,r.agent=L,Jv(r),Xv(r),await P(Ls(t),{recursive:!0}),await A(t,JSON.stringify(r,null," "),"utf-8");let s=(await ne(e)).find(a=>a&&a.path===".claude/settings.json"&&a.host==="claude"&&a.category==="settings"),o={keys:["permissions.allow","hooks.SessionStart","hooks.SubagentStart","agent","enabledPlugins"]};Array.isArray(s?.owns?.entries)&&s.owns.entries.length&&(o.entries=[...s.owns.entries]),await W(e,[Y({path:".claude/settings.json",host:"claude",category:"settings",owns:o})]),await Ci(e);let i=await Gp(e);return{configured:n,settingsPath:t,opencode:i}}function bn(e){return R(e,".claude","settings.local.json")}function Yv(){return{source:{source:"directory",path:De}}}function tf(e){return!!e&&typeof e=="object"&&!!e.source&&typeof e.source=="object"&&typeof e.source.source=="string"&&e.source.source.length>0}async function Ci(e,{record:t=!0}={}){let r=bn(e),n={};try{n=JSON.parse(await ie(r,"utf-8"))||{}}catch{n={}}return(!n.extraKnownMarketplaces||typeof n.extraKnownMarketplaces!="object")&&(n.extraKnownMarketplaces={}),n.extraKnownMarketplaces[Oe]=Yv(),await P(Ls(r),{recursive:!0}),await A(r,JSON.stringify(n,null," "),"utf-8"),t&&await W(e,[Y({path:".claude/settings.local.json",host:"claude",category:"settings",owns:{keys:["extraKnownMarketplaces"]}})]),{localPath:r}}function Up(e){let t=!1;if(e?.extraKnownMarketplaces&&Oe in e.extraKnownMarketplaces&&(delete e.extraKnownMarketplaces[Oe],Object.keys(e.extraKnownMarketplaces).length===0&&delete e.extraKnownMarketplaces,t=!0),e?.enabledPlugins&&wt in e.enabledPlugins&&(delete e.enabledPlugins[wt],Object.keys(e.enabledPlugins).length===0&&delete e.enabledPlugins,t=!0),e?.enabledPlugins&&typeof e.enabledPlugins=="object"){for(let r of Object.keys(e.enabledPlugins))Er(r)!==null&&(delete e.enabledPlugins[r],t=!0);Object.keys(e.enabledPlugins).length===0&&delete e.enabledPlugins}return e?.agent===L&&(delete e.agent,t=!0),t}function Gc(e,{command:t=rf,markers:r=Object.values(Ns)}={}){let n=JSON.stringify(e.hooks?.SessionStart??null);return $i(e,{markers:r}),e.hooks||(e.hooks={}),Array.isArray(e.hooks.SessionStart)||(e.hooks.SessionStart=[]),e.hooks.SessionStart.push({hooks:[{type:"command",command:t}]}),JSON.stringify(e.hooks.SessionStart)!==n}function Jv(e){Gc(e)}function $i(e,{markers:t}={}){if(!Array.isArray(t)||t.length===0)throw new Error("removeVesperSessionStartHook: an explicit `markers` list is required (see VESPER_HOOK_MARKERS)");return nf(e,"SessionStart",t)}function nf(e,t,r){if(!Array.isArray(e?.hooks?.[t]))return!1;let n=new Set(r.flat().filter(a=>typeof a=="string"&&a.trim()).map(a=>a.trim())),s=a=>typeof a?.command=="string"&&n.has(a.command.trim()),o=!1,i=[];for(let a of e.hooks[t]){if(!a||!Array.isArray(a.hooks)){i.push(a);continue}let c=a.hooks.filter(l=>!s(l));if(c.length===a.hooks.length){i.push(a);continue}o=!0,c.length>0&&i.push({...a,hooks:c})}return e.hooks[t]=i,e.hooks[t].length===0&&delete e.hooks[t],e.hooks&&Object.keys(e.hooks).length===0&&delete e.hooks,o}function Xv(e){let t=JSON.stringify(e.hooks?.SubagentStart??null);return of(e),e.hooks||(e.hooks={}),Array.isArray(e.hooks.SubagentStart)||(e.hooks.SubagentStart=[]),e.hooks.SubagentStart.push({hooks:[{type:"command",command:sf}]}),JSON.stringify(e.hooks.SubagentStart)!==t}function of(e,{markers:t=Object.values(qv)}={}){return nf(e,"SubagentStart",t)}async function af(e,t={}){let r=await x(e);return r.schemaVersion=ve,r.host="claude",t.namePrefix!==void 0&&(r.namePrefix=t.namePrefix),t.pluginPath!==void 0&&(r.pluginPath=t.pluginPath),t.version!==void 0&&(r.frameworkVersion=t.version),r.updatedAt=new Date().toISOString(),await T(e,r),r}function Fc(e){let t=String(e);for(let r of["adhd","ponytail"])t=t.replace(new RegExp(`\\n*<!-- vesper:${r}:start -->[\\s\\S]*?<!-- vesper:${r}:end -->\\n*`),`
|
|
89
|
+
`);return t}async function Qv(e){let t=R(Bp(e),"context"),r=R(e,".vesper","context"),n=await w(r),s={removed:[],kept:[]},o;try{o=await ut(t)}catch{return s}for(let i of o.files){let a=!n;if(n)try{a=ee(await ie(R(t,i)),await ie(R(r,i)))}catch{a=!1}a?(await En(R(t,i),{force:!0}),s.removed.push(i)):s.kept.push(i)}s.kept.push(...o.others);for(let i of o.dirs)try{await Rc(R(t,i))}catch{}try{await Rc(t)}catch{}return s}function Wp(e){let t=String(e).replace(/\r\n/g,`
|
|
90
|
+
`),r=/^---\n[\s\S]*?\n---\n/.exec(t);return(r?t.slice(r[0].length):t).trim()}async function Zv(e){let t={removed:[],kept:[]};for(let r of["orchestration","context"]){let n=`.claude/vesper/${r}.md`,s;try{s=await ie(R(e,n),"utf-8")}catch{continue}let o=null;try{o=await ie(R(e,".vesper","instructions",`vesper-${r}.instructions.md`),"utf-8")}catch{o=null}let i=Wp(s);o===null||i!==""&&Wp(o).includes(i)?(await En(R(e,n),{force:!0}),t.removed.push(n)):t.kept.push(n)}return t}async function xn(e,{purgeProjectAuthored:t=!1}={}){let r=Bp(e),n=".claude/vesper/orchestrator.md";await le(R(e,n),{path:n,category:"playbook"});let s=[];t&&(s.push(...(await Zv(e)).kept),s.push(...(await Qv(e)).kept.map(y=>`.claude/vesper/context/${y}`)));try{await Rc(r)}catch{}let o=await x(e),i=new Set,a=Array.isArray(o.manifest)?o.manifest:[],c=new Set(a.filter(y=>y&&y.host!=="claude"&&y.category==="per-project-authored").map(y=>y.path));for(let y of a)Yo(y,{host:"claude",purgeProjectAuthored:t})&&(y.category==="per-project-authored"&&c.has(y.path)||i.add(y.path));for(let y of Array.isArray(o.claude?.catalogManifest)?o.claude.catalogManifest:[]){if(typeof y!="string"||y.includes(".."))continue;let[k,...v]=y.split("/");!Gv.includes(k)||v.length===0||i.add(`.claude/${y}`)}for(let y of i){let k=(o.manifest||[]).find(v=>v?.path===y)||{path:y,category:y.startsWith(".claude/skills/")?"catalog-skill":"catalog-agent"};await le(R(e,y),k,{purgeProjectAuthored:t})}let{kept:l}=await Xo(e,"claude");l.push(...(await mn(e,"claude")).kept);let d=await Vp(e,{manifest:a}),p=zp(e);if(await w(p)){let y=await ie(p,"utf-8"),k=Fc(Uv(y));k.trim()?await A(p,k,"utf-8"):await En(p,{force:!0})}await mr(e,!1);let f=Array.isArray(o.mcp?.servers)?o.mcp.servers:[];if(f.length&&await w(Ve(e)))try{let y=JSON.parse(await ie(Ve(e),"utf-8")),k=!1;for(let v of f)y?.mcpServers&&typeof y.mcpServers=="object"&&v in y.mcpServers&&(delete y.mcpServers[v],k=!0);k&&await _i(e,y)}catch{}try{let y=JSON.parse(await ie(Ve(e),"utf-8"));y&&typeof y=="object"&&Object.keys(y).every(v=>v==="mcpServers")&&(!y.mcpServers||Object.keys(y.mcpServers).length===0)&&await En(Ve(e),{force:!0})}catch{}let m=Fe(e);if(await w(m))try{let y=JSON.parse(await ie(m,"utf-8")),k=$i(y,{markers:[Ns.legacy,Ns.bootstrap]}),v=of(y),S=Up(y),C=zv(y);(k||v||S||C)&&(Object.keys(y).length===0?await En(m,{force:!0}):await A(m,JSON.stringify(y,null," "),"utf-8"))}catch{}let h=bn(e);if(await w(h))try{let y=JSON.parse(await ie(h,"utf-8"));Up(y)&&(Object.keys(y).length===0?await En(h,{force:!0}):await A(h,JSON.stringify(y,null," "),"utf-8"))}catch{}let g=await x(e);return delete g.claude,g.host==="claude"&&delete g.host,delete g.namePrefix,delete g.pluginPath,Array.isArray(g.manifest)&&(g.manifest=g.manifest.filter(y=>!(y&&y.host==="claude")||!t&&Le.has(y.category))),await T(e,g),{kept:l,knowledgeKept:s,overlayKept:d.kept}}var De,hr,Oe,Mv,Gv,Fv,Yp,Nc,Lc,Xp,rf,Ns,sf,qv,_e=Z(()=>{xe();dn();U();Ye();pn();ft();As();wc();H();te();fe();$s();De=R(O,"claude"),hr=R(O,"claude-committed"),Oe="vesper-marketplace",Mv=["agents","skills"],Gv=["agents","commands","skills"],Fv="vesper";Yp=".mcp.json";Nc="<!-- vesper:start -->",Lc="<!-- vesper:end -->";Xp=Object.freeze(["mcp__vesper-indexing__vesper_search","mcp__vesper-indexing__vesper_symbols","mcp__vesper-indexing__vesper_status","mcp__vesper-indexing__vesper_reindex","mcp__sequential-thinking__sequentialthinking","mcp__memory__create_entities","mcp__memory__create_relations","mcp__memory__add_observations","mcp__memory__delete_entities","mcp__memory__delete_observations","mcp__memory__delete_relations","mcp__memory__read_graph","mcp__memory__search_nodes","mcp__memory__open_nodes"]);rf=`command -v vespercli >/dev/null 2>&1 && ${Xr("claude")} || true`,Ns=Object.freeze({legacy:Object.freeze([Gn,Fn]),bootstrap:Object.freeze([Dn]),guard:Object.freeze([rf])});sf="command -v vespercli >/dev/null 2>&1 && vespercli log delegated --pipeline hook --note hook --stdin || true",qv=Object.freeze({runLedger:Object.freeze([sf])})});import{Command as hx,Option as gt}from"commander";import{readFileSync as mx,existsSync as gx}from"node:fs";import{fileURLToPath as yx}from"node:url";import{dirname as Kl,join as tg}from"node:path";U();H();te();_e();import{resolve as PE,basename as Zh,relative as IE,sep as jE,isAbsolute as RE}from"node:path";import{spawn as NE}from"node:child_process";import{confirm as zt,input as LE,number as ME,select as GE}from"@inquirer/prompts";U();Ye();As();H();te();fe();import{readFile as Vs,rm as Nf,rmdir as dS}from"node:fs/promises";import{join as qe}from"node:path";te();H();_e();Ae();import{readFile as Ds,readdir as xk}from"node:fs/promises";import{join as $e,isAbsolute as Ak,relative as _k}from"node:path";import{readdir as ek,readFile as cf,rename as tk,access as rk,constants as nk}from"node:fs/promises";import{join as gr}from"node:path";import{execFile as sk}from"node:child_process";var Dc=".vesper/.migration-backup";async function lf(e){try{return await rk(e,nk.F_OK),!0}catch{return!1}}function ok(e){return new Promise(t=>{try{sk("git",["rev-parse","--verify","-q","HEAD"],{cwd:e,timeout:5e3,encoding:"utf-8",env:{...process.env,GIT_NO_LAZY_FETCH:"1",GIT_OPTIONAL_LOCKS:"0",GIT_TERMINAL_PROMPT:"0",GCM_INTERACTIVE:"never",SSH_ASKPASS_REQUIRE:"never",LC_ALL:"C"}},(n,s)=>t(n?null:String(s).trim()||null)).stdin?.end()}catch{t(null)}})}async function uf(e){try{return(await ek(gr(e,Dc),{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>t.name).sort()}catch{return[]}}async function Oi(e,{head:t}={}){let r=await uf(e);if(r.length===0)return!1;let n=gr(e,Dc),s=t!==void 0?t:await ok(e),o=r.at(-1);for(let i of[...r].reverse()){let a;try{a=await cf(gr(n,i,"rollback.json"),"utf-8")}catch{continue}let c;try{c=JSON.parse(a)}catch{if(i!==o)continue;return!await lf(gr(n,i,"created.txt"))}if(!c||!Array.isArray(c.before)||s!==null&&c.head!==s)continue;return(typeof c.status=="string"?c.status:Array.isArray(c.created)?"finished":"started")==="started"}return!1}async function Vc(e){let t=await uf(e);if(!t.length)return null;let r=gr(e,Dc,t.at(-1)),n;try{n=await cf(gr(r,"rollback.json"),"utf-8")}catch{return null}try{return JSON.parse(n),null}catch{}return await lf(gr(r,"created.txt"))?null:gr(r,"rollback.json")}async function df(e,{now:t=new Date}={}){let r=await Vc(e);if(!r)return null;let n=`${r}.torn-${t.toISOString().replace(/[:.]/g,"-")}`;return await tk(r,n),{from:r,to:n}}U();H();te();_e();fe();Ye();Ae();import{readFile as gf,rm as hk,rmdir as mk}from"node:fs/promises";import{join as Bc}from"node:path";H();fe();xe();wc();Ae();import{readFile as Uc,readdir as hf}from"node:fs/promises";import{readdirSync as ik}from"node:fs";import{join as Ce,basename as ak}from"node:path";import{homedir as ck}from"node:os";var lk=Object.freeze(["agents","commands","skills"]),uk=Object.freeze(["claude","paths","catalogVersion","targets"]),Fr=".vesper/.migration-backup",st="This is a pre-2.0 (1.x) Vesper workspace. Run `vespercli init` to migrate it in place \u2014 nothing of yours is deleted, and anything Vesper removes is backed up first.";async function Ii(e){let t=[...new Set([await bt(e),Ce(e,".vesperrc"),Ce(e,".vesper","tracking.json")])],r=null,n=null;for(let c of t){let l;try{l=await Uc(c,"utf-8")}catch(d){if(d&&d.code==="ENOENT")continue;return Ti({config:"corrupt",path:c})}try{r=JSON.parse(l),n=c}catch{return Ti({config:"corrupt",path:c})}break}if(!r||typeof r!="object")return Ti({config:"absent",path:null});let s=Number(r.schemaVersion)>=2?"v2":"v1",o=[];for(let c of Array.isArray(r.claude?.catalogManifest)?r.claude.catalogManifest:[]){if(typeof c!="string"||c.includes("..")||c.startsWith("/"))continue;let[l,...d]=c.split("/");!lk.includes(l)||d.length===0||o.push(`.claude/${c}`)}let i=c=>Array.isArray(c)?c.filter(l=>typeof l=="string"):[],a=r.claude?.namePrefix??r.namePrefix;return Ti({config:s,path:n,catalogManifest:o,namePrefix:typeof a=="string"?a:"",injectedPaths:i(r.paths),readAccessPaths:i(r.readAccessPaths),mcpServers:i(r.mcp?.servers),vendored:r.vendored&&typeof r.vendored=="object"?JSON.parse(JSON.stringify(r.vendored)):void 0,hosts:s==="v1"?{claude:!!r.claude,copilot:i(r.paths).length>0}:{claude:!1,copilot:!1},staleKeys:s==="v2"?uk.filter(c=>c in r):[],recordedHost:s==="v2"?Yn({host:r.host}):null,version:s==="v1"&&[r.catalogVersion,r.claude?.catalogVersion,r.version].find(c=>typeof c=="string"&&/^1\.\d+\.\d+/.test(c))||null})}function Ti(e){return Object.freeze({config:"absent",path:null,catalogManifest:[],namePrefix:"",injectedPaths:[],readAccessPaths:[],mcpServers:[],vendored:void 0,hosts:{claude:!1,copilot:!1},staleKeys:[],recordedHost:null,version:null,...e})}async function Te(e,{checkout:t}={}){let r=await Ii(e),n;try{n=await K(e)}catch{n=void 0}let s=await yu(e,{vscodeSettings:n}),o={claude:s.hosts.claude||r.hosts.claude,copilot:s.hosts.copilot||r.hosts.copilot},i=[...s.matched];r.config==="v1"&&i.unshift(`${ak(r.path||".vesperrc")} (1.x record)`);let a=!1,c=!1,l=!1,d=null;try{let f=t??await B(e);d=f.source==="local"?null:f.host??f.candidate??null}catch{d=null}r.config==="corrupt"||(r.config==="v1"&&(r.hosts.claude||r.hosts.copilot||r.mcpServers.length>0||r.vendored!==void 0||s.primary)?a=!0:d?(s.primary||r.staleKeys.length)&&(l=!0,i.push(...r.staleKeys.map(f=>`.vesperrc key "${f}"`))):s.primary?a=!0:s.residue.length&&!d&&(c=!0,o.claude=!0,i.push(...s.residue)));let p=a||c?[]:[...s.residue];return{unmigrated:a,advisory:c,residue:l,needsMigration:a||c||l,corrupt:r.config==="corrupt",config:r.config,hosts:o,staleKeys:[...r.staleKeys],evidence:[...new Set(i)],leftovers:p,record:r}}var dk="<!-- vesper(?::[a-z0-9-]+)?:start -->[\\s\\S]*?<!-- vesper(?::[a-z0-9-]+)?:end -->",pf=e=>new RegExp(dk).test(e),pk=Object.freeze([Gn,Fn,Dn]);async function Hc(e){try{return await hf(e,{withFileTypes:!0})}catch{return[]}}async function Pi(e){try{return await Uc(e)}catch{return null}}function ff(e){let t=new Set;for(let r of[Ce(O,"claude",e),Ce(O,"claude-committed",e)])try{for(let n of ik(r))t.add(n.replace(/\.md$/,""))}catch{}return t}function fk(e){let t=/^---\r?\n([\s\S]*?)\r?\n---/.exec(e);if(!t)return null;let r=/^name:\s*['"]?([A-Za-z0-9_.-]+)['"]?\s*$/m.exec(t[1]);return r?r[1]:null}async function ji({homeDir:e=ck(),pluginName:t="vesper",workspaceRoot:r}={}){let n=[],s=(p,f,m,h,g={})=>n.push({path:Ce(e,p),rel:p,kind:f,tier:m,marker:h,...g}),o=ff("agents"),i=ff("skills"),a=`.claude/skills/${t}`,c=await Cs({pluginName:t,staleDir:Ce(e,a),workspaceRoot:r});(c.reason==="match"||c.reason==="manifest-less-ours")&&c.proven.length&&s(a,"plugin",2,`${c.proven.length} file(s) byte-identical to a released Vesper 1.x build`,{proven:c.proven.length,kept:c.kept.length});for(let[p,f]of[[".claude/rules",m=>m.endsWith(".md")],[".copilot/instructions",()=>!0]])for(let m of await Hc(Ce(e,p))){if(!m.isFile()||!f(m.name))continue;let h=`${p}/${m.name}`,g=(await Pi(Ce(e,h)))?.toString("utf-8")??"";pf(g)?s(h,"file",3,"a Vesper guard block"):m.name.startsWith("vesper-")&&s(h,"file",3,"a vesper- file name")}for(let p of[".claude/agents",".copilot/agents"])for(let f of await Hc(Ce(e,p))){if(!f.isFile()||!f.name.endsWith(".md"))continue;let m=`${p}/${f.name}`,h=await Pi(Ce(e,m));if(!h)continue;let g=f.name.replace(/(\.agent)?\.md$/,"");(o.has(fk(h.toString("utf-8"))||g)||o.has(g)||f.name.startsWith("vesper-"))&&s(m,"file",3,"a Vesper agent name")}for(let p of[".claude/skills",".copilot/skills"])for(let f of await Hc(Ce(e,p)))f.isDirectory()&&(p===".claude/skills"&&f.name===t||(i.has(f.name)||f.name.startsWith("vesper-"))&&s(`${p}/${f.name}`,"dir",3,"a Vesper skill name"));let l=(await Pi(Ce(e,".claude","CLAUDE.md")))?.toString("utf-8");l&&pf(l)&&s(".claude/CLAUDE.md","region",3,"a Vesper guard block");let d=await Pi(Ce(e,".claude","settings.json"));if(d){let p=null;try{p=JSON.parse(d.toString("utf-8"))}catch{p=null}if(p&&typeof p=="object"){let f=[],m=p.hooks&&typeof p.hooks=="object"?p.hooks:{};for(let[h,g]of Object.entries(m))Array.isArray(g)&&g.some(y=>Array.isArray(y?.hooks)&&y.hooks.some(k=>typeof k?.command=="string"&&pk.includes(k.command.trim())))&&f.push(`hooks.${h}`);p.agent===L&&f.push("agent"),f.length&&s(".claude/settings.json","keys",3,`Vesper keys: ${f.join(", ")}`)}}return n.sort((p,f)=>p.rel.localeCompare(f.rel))}async function mf(e){let t=Ce(e,Fr),r=[];try{r=(await hf(t,{withFileTypes:!0})).filter(s=>s.isDirectory()).map(s=>s.name).sort()}catch{r=[]}let n=[];for(let s of r){let o;try{o=JSON.parse(await Uc(Ce(t,s,"kept.json"),"utf-8"))}catch{continue}if(Array.isArray(o))for(let i of o)i&&typeof i.rel=="string"&&typeof i.reason=="string"&&n.push({rel:i.rel,reason:i.reason,backup:Ce(t,s)})}return n}at();var Ri="VESPER_HOST_MISMATCH",zc="VESPER_PLUGIN_ABSENT",re="vespercli init",Je=e=>`vespercli init --host ${e}`,Gs="opencode";function yf(e){return e===Gs?"claude":e}function wf(e){return z.includes(e)||e===Gs}function gk(e,t,{runningLabel:r}={}){return t==="copilot"&&e==="claude"?`This workspace is provisioned for Claude Code, and VS Code just opened it. If you use GitHub Copilot here, run \`${Je("copilot")}\` (it removes the Claude Code setup). If you use Claude Code inside VS Code, ignore this message \u2014 nothing was changed.`:r===Gs&&t==="claude"?`This workspace is provisioned for "${e}" but is running under OpenCode, which uses the "claude" host. Fix: ${Je("claude")}`:`This workspace is provisioned for "${e}" but is running under "${t}". Fix: ${Je(t)}`}var Ms=".vesper/instructions/vesper-host-guard.instructions.md",Wc="guard-rule",yk=["---","applyTo: '**'",'description: "Vesper host guard \u2014 refuse work in this workspace while a host mismatch is active"',"---","","# Vesper host guard","","Before doing anything else in this workspace, check whether `.vesper/.host-guard/ACTIVE` exists.","",`If it does, treat this session as \`${Ri}\`: this workspace was provisioned for a`,"different AI host than the one you are running in. Refuse all provisioning and orchestration","work, print the `fix:` command the file contains (`vespercli init --host <running host>` to","re-provision this workspace for the host you are running in, or `vespercli reset --host <x>`","to remove one host's Vesper files), and take no other action.","","If the file does not exist, this rule imposes nothing \u2014 proceed normally.","","This file is written by Vesper (`vespercli`) and is constant; the sentinel it names is","gitignored and written/cleared by `vespercli guard`.",""].join(`
|
|
91
|
+
`);function Yc(e){return e==="claude"?"copilot":"claude"}async function vf(e){let t=Fe(e),r={},n=!0;try{r=JSON.parse(await gf(t,"utf-8")),n=!1}catch{r={}}(!r||typeof r!="object"||Array.isArray(r))&&(r={});let s=Gc(r);return(s||n)&&(await P(Bc(e,".claude"),{recursive:!0}),await A(t,JSON.stringify(r,null," "),"utf-8")),{changed:s,created:n}}function wk(){return{label:Xn.taskLabel,command:Xr("copilot"),presentation:{reveal:"always",panel:"shared"}}}async function vk(e,t,{unattended:r=!1}={}){return _n(t),t==="claude"?vf(e):Zn(e,{createOnly:r})}async function kf(e,t){if(_n(t),t==="claude"){let n=await vf(e);return await W(e,[Y({path:".claude/settings.json",host:"shared",category:"guard-trigger",owns:{keys:["hooks.SessionStart"]}})]),n}let r=await bo(e,wk());return await W(e,[Y({path:".vscode/tasks.json",host:"shared",category:"guard-trigger",owns:{keys:[Xn.taskLabel]}})]),r}async function Ni(e,t,{unattended:r=!1}={}){return _n(t),await vk(e,t,{unattended:r}),await kf(e,Yc(t)),{legacyGuardRule:await Dr(e)}}async function Kc(e,t){let r=await x(e),n=J(r),s=n.filter(o=>!t(o));return s.length===n.length?!1:(r.manifest=s,await T(e,r),!0)}async function Fs(e,t){_n(t);let r=J(await x(e));if(t==="claude"){let i=Fe(e);if(await w(i))try{let a=JSON.parse(await gf(i,"utf-8"));$i(a,{markers:[Ns.guard]})&&(Object.keys(a).length===0?await hk(i,{force:!0}):await A(i,JSON.stringify(a,null," "),"utf-8"))}catch{}await Kc(e,a=>a.path===".claude/settings.json"&&a.category==="guard-trigger");return}let n=r.some(i=>i.path===".vscode/tasks.json"&&i.category==="guard-trigger"),s=r.some(i=>i.path===".vscode/tasks.json"&&i.host==="copilot"),{fileRemoved:o}=await Qn(e,Xn.taskLabel,{removeFileIfEmpty:n&&!s});if(o)try{await mk(Bc(e,".vscode"))}catch{}await Kc(e,i=>i.path===".vscode/tasks.json"&&i.category==="guard-trigger")}async function Dr(e){let n=J(await x(e)).find(o=>o.path===Ms&&o.category===Wc)??{path:Ms,category:Wc,hash:null},s=await le(Bc(e,Ms),n,{expected:[yk]});return await Kc(e,o=>o.path===Ms&&o.category===Wc),s==="partial"?"kept":s}function An(){return`Kept your edited ${Ms} \u2014 Vesper no longer uses this file (a host mismatch now warns instead of refusing work) and never deletes a copy that differs from what it wrote. Delete it by hand.`}function kk(e){return e?.ignoredFile&&e.ignoredEvidence&&e.ignoredEvidence!=="both"?`This repository gitignores ${e.ignoredFile}, so a checkout cannot confirm the ${e.ignoredEvidence} provisioning it carries \u2014 bootstrap wrote nothing; session start still provisions this worktree. To bootstrap on checkouts too, commit ${e.ignoredFile} (remove it from .gitignore).`:e?.candidate?`This checkout's committed files carry no ${e.candidate} provisioning \u2014 bootstrap wrote nothing. Session start (or \`vespercli init\`) provisions it.`:"Not a vesperized workspace \u2014 nothing to bootstrap. Run `vespercli init` to set up."}function Sk(e,t){return e?.gitError==="dubious-ownership"?`git refuses this repository (dubious ownership), so Vesper cannot read its checkout and provisions nothing here. Fix: git config --global --add safe.directory ${t}`:"git could not read this repository, so Vesper provisions nothing here; run `git status` to see why."}async function Li(e,{runningHost:t,runningLabel:r}={}){let n=t!==void 0,s={identity:n,network:n,runningHost:t,journal:null,fix:null,note:null,message:null},o=await Ft(e),i=await B(e,{requireCommitted:!n&&!o});if(o)return n&&t!==o.to?{...s,action:"refuse",reason:"switch-in-progress",host:o.to,checkout:i,journal:o,fix:re,message:`An interrupted host switch (${o.from} \u2192 ${o.to}) is pending in this workspace. Fix: ${re}`}:{...s,action:"none",reason:"switch-in-progress",host:null,checkout:i,journal:o,note:`An interrupted host switch (${o.from} \u2192 ${o.to}) is pending \u2014 run \`vespercli init\` to finish it.`};let a=async()=>{let l=null;try{l=await Te(e,{checkout:i})}catch{l=null}return l?.unmigrated?{...s,action:"none",reason:"legacy-unmigrated",host:null,checkout:i,note:`Bootstrap wrote nothing. ${st}`}:await Oi(e)?{...s,action:"none",reason:"migration-in-progress",host:null,checkout:i,note:"A Vesper 1.x migration was interrupted in this workspace \u2014 run `vespercli init` to finish it. Nothing was provisioned."}:null},c=i.source==="local";if(c){let l=await a();if(l)return l}if(n&&i.host&&i.host!==t)return{...s,action:"refuse",reason:"host-mismatch",host:i.host,checkout:i,fix:Je(t),message:gk(i.host,t,{runningLabel:r})};if(!c){let l=await a();if(l)return l}if(i.gitError)return{...s,action:"none",reason:i.gitError==="dubious-ownership"?"not-vesperized":"git-unreadable",host:null,checkout:i,note:Sk(i,e)};if(i.ambiguous)return{...s,action:"none",reason:"host-ambiguous",host:null,checkout:i,note:n?et:null};if(!i.host){let l=!n&&i.candidate?"host-unconfirmed":"not-vesperized",d=n?await Pr(e):null,p=d?`This worktree's local record names ${d}, but the checked-out commit carries no Vesper provisioning \u2014 nothing was provisioned. \`vespercli init --host ${t}\` provisions it.`:kk(i);return{...s,action:"none",reason:l,host:null,checkout:i,note:p}}return{...s,action:"bootstrap",reason:"healthy",host:i.host,checkout:i}}async function Sf(e,t,{checkout:r}={}){if(_n(t),r?.source==="local"){for(let n of[Ek(t),".vesperrc"])if(!await bk(e,n))return{healed:!1,reason:"local-tier"}}return await kf(e,t),{healed:!0}}function Ek(e){return _n(e),e==="claude"?".claude/settings.json":".vscode/tasks.json"}async function bk(e,t){return await D(["check-ignore","-q","--",t],{cwd:e,timeout:5e3})!==null}function _n(e){if(!z.includes(e))throw new Error(`host must be one of: ${z.join(", ")} (received "${e}")`)}fe();xe();dn();Kt();pn();ft();at();U();As();$s();_s();import{readFile as qc,readdir as Ck}from"node:fs/promises";import{homedir as $k}from"node:os";var $=Object.freeze({ERROR:"error",WARN:"warn",INFO:"info"}),Pe=Object.freeze({OK:0,ERROR:1,HOST_MISMATCH:2}),Ef=new Set(Object.values($)),$f="host-mismatch",Ok="check-failed",Tk=new Set(["playbook","pointer","mcp-config","settings"]);var bf=Ko,Pk=e=>`vespercli reset --host ${e}`;function I({code:e,severity:t,message:r,fix:n,category:s,path:o}){if(!Ef.has(t))throw new Error(`makeFinding: unknown severity "${t}" for code "${e}". Valid severities: ${[...Ef].join(", ")}. An unbucketed finding is invisible to both the rendered report and the exit code.`);let i={code:e,severity:t,message:r,fix:n||re};return s!==void 0&&(i.category=s),o!==void 0&&(i.path=o),i}function Jc(e,t){if(!t)return t;let r=_k(e,t);return r.startsWith("..")?t:r}async function Ik(e){let r=[await bt(e),$e(e,".vesperrc"),$e(e,".vesper","tracking.json")],n=new Set;for(let s of r){if(n.has(s))continue;n.add(s);let o;try{o=await Ds(s,"utf-8")}catch(i){if(i&&i.code==="ENOENT")continue;return{corrupt:!0,corruptPath:s}}try{return{tracking:JSON.parse(o),trackingPath:s}}catch{return{corrupt:!0,corruptPath:s}}}return{absent:!0}}async function xf(e,t){let r=!1;try{r=await w(e)}catch{r=!1}if(!r)return{path:e,exists:!1,servers:[]};try{let n=JSON.parse(await Ds(e,"utf-8"));return{path:e,exists:!0,servers:Object.keys(n[t]||{})}}catch{return{path:e,exists:!0,servers:[]}}}async function jk(e,t,{visible:r}={}){let n={};for(let s of Object.keys(t)){n[s]=[];for(let o of t[s])try{await Qt(e,o,{visible:r})&&n[s].push(o)}catch(i){if(!Rk(i))throw i}}return n}function Rk(e){return!!e&&typeof e.code=="string"&&["ENOENT","EACCES","EISDIR","ENOTDIR","EPERM","ELOOP","ENAMETOOLONG"].includes(e.code)}function Nk(e){return ka(e)}async function Lk(e,t,{homeDir:r=$k(),checkout:n=null}={}){let s=await Ik(e);if(s.corrupt)return{workspaceRoot:e,runningHost:t,corrupt:!0,corruptPath:s.corruptPath};let o=s.tracking||null,i=n;i||(i=await B(e,{withCommitted:!0}));let a=i.host,c=null;try{c=await Ft(e)}catch{c=null}let l=null,d=!1;try{l=await Vc(e)}catch{l=null}try{d=await Oi(e)}catch{d=!1}let p=await hd(e),f=[...p.missing,...p.modified,...p.clean],m=await zo(e),h=to(),g=[];try{g=await ge(e)}catch{g=[]}let y=a?[a]:g,k={claude:await xf(Ve(e),"mcpServers"),copilot:await xf(Qe(e),"servers")},v=tr(),S=i.ambiguous?"both":i.host,C=await jk(e,v,{visible:i.visible}),N={};for(let[Ue,wr]of Object.entries(C))N[Ue]=wr.some(Nk);let E={};for(let Ue of z)E[Ue]=await Vn(e,Ue);let b=null;try{b=await Te(e,{checkout:i})}catch{b=null}let F=[];try{F=(await ji({homeDir:r,workspaceRoot:e})).filter(Ue=>Ue.kind==="plugin")}catch{F=[]}let X=[];try{X=await mf(e)}catch{X=[]}let He=await Pr(e),In=!!He&&He!==a;{let Ue=i.source==="local"?null:a,wr=vr=>{if(!vr)return!1;if(z.includes(vr.host))return vr.host===Ue;let $t=Mk(vr);return!$t||$t===Ue};p={...p,missing:p.missing.filter(wr),modified:p.modified.filter(wr),clean:p.clean.filter(wr),userLevelViolations:p.userLevelViolations}}let Ct=[...p.missing,...p.modified,...p.clean],Jt=!!a||f.length>0;return{workspaceRoot:e,runningHost:t,absent:!!s.absent,tracking:o,host:a,checkout:i,ledgerHostForReporting:He,verify:p,manifestEntries:Ct,manifestAll:f,recordStale:In,journal:c,migrationTorn:l,migrationActive:d,frameworkVersion:m,packageVersion:h,installedTargets:y,mcpConfigs:k,detectedHost:S,fingerprintMatches:C,fingerprintSpecific:N,residue:E,legacy:b,userResidue:F,keptItems:X,initialised:Jt}}function Mk(e){return e.category==="guard-rule"||e.category==="guard-trigger"&&e.path===".claude/settings.json"?"copilot":e.category==="guard-trigger"&&e.path===".vscode/tasks.json"?"claude":null}function Of(e,t){return e.checkout?.host===t||!!e.fingerprintSpecific?.[t]}function Gk(e){let t=[],{verify:r}=e;for(let n of r.userLevelViolations)t.push(I({code:"user-level-violation",severity:$.ERROR,category:n.category,path:n.path,message:`Owned file "${n.path}" sits under a user-level scan path \u2014 it would silently activate in unrelated projects (isolation breach).`,fix:re}));for(let n of r.modified)(Dt[n.category]||{}).doctor==="server-drift"?t.push(I({code:"mcp-core-missing",severity:$.ERROR,category:n.category,path:n.path,message:`A required Vesper-core MCP server is missing from "${n.path}".`,fix:re})):t.push(I({code:"file-edited",severity:$.WARN,category:n.category,path:n.path,message:`"${n.path}" was edited since the last Vesper write in this worktree.`,fix:re}));for(let n of r.missing){let s=Tk.has(n.category);t.push(I({code:"owned-file-missing",severity:s?$.ERROR:$.WARN,category:n.category,path:n.path,message:s?`Load-bearing owned file "${n.path}" is missing \u2014 framework cannot operate.`:`Owned file "${n.path}" is missing \u2014 \`vespercli init\` will re-provision it.`,fix:re}))}return t}async function Mi(e,t={}){let r=new Set,n=t.installedTargets;if(!Array.isArray(n))try{let a=await on(e);n=a?[a]:await ge(e)}catch{n=[]}if(n.includes("claude"))if(t.mcpConfigs?.claude)for(let a of t.mcpConfigs.claude.servers)r.add(a);else try{let a=await Fk(e);for(let c of Object.keys(a.mcpServers||{}))r.add(c)}catch{}if(n.includes("copilot"))if(t.mcpConfigs?.copilot)for(let a of t.mcpConfigs.copilot.servers)r.add(a);else try{let a=await Ze(e);for(let c of Object.keys(a.servers||{}))r.add(c)}catch{}let s=[];if("tracking"in t)s=Array.isArray(t.tracking?.mcp?.servers)?t.tracking.mcp.servers:[];else try{let a=await x(e);s=Array.isArray(a.mcp?.servers)?a.mcp.servers:[]}catch{s=[]}let o=new Set(s);return{drifted:[...r].filter(a=>!me.includes(a)&&!o.has(a))}}async function Fk(e){try{return JSON.parse(await Ds(Ve(e),"utf-8"))}catch{return{mcpServers:{}}}}async function Dk(e){let{drifted:t}=await Mi(e.workspaceRoot,{tracking:e.tracking,mcpConfigs:e.mcpConfigs,installedTargets:e.installedTargets});return t.map(r=>I({code:"mcp-drift",severity:$.WARN,category:"mcp-config",message:`MCP server "${r}" is present in the live MCP config but not tracked in .vesperrc mcp.servers.`,fix:re}))}async function Vk(e){return!e.initialised||!e.host?[]:(e.manifestAll??e.manifestEntries).some(r=>r.category==="mcp-config")?[]:Hk(e)?[I({code:"mcp-config-unrecorded",severity:$.ERROR,category:"mcp-config",message:"A live MCP config exists but is not recorded in the owned-files manifest \u2014 Vesper cannot reconcile its managed servers.",fix:re})]:[]}function Hk(e){return!!e.mcpConfigs?.[e.host]?.exists}function Uk(e){if(e.absent||!e.tracking)return[];let t=e.tracking;return(t.host===void 0||z.includes(t.host))&&Array.isArray(t.manifest)&&t.schemaVersion===ve?[]:[I({code:"tracking-shape-invalid",severity:$.WARN,path:".vesperrc",message:".vesperrc parses but its shape is invalid (host/manifest/schemaVersion) \u2014 `vespercli init` repairs it.",fix:re})]}async function Wk(e){let t=[];if(e.detectedHost==="both"){let r=z.every(n=>Of(e,n));t.push(I({code:"host-ambiguous",severity:r?$.ERROR:$.WARN,message:r?bf:`${bf} (Reported as a warning: at least one host matched only generic, non-Vesper-specific files, so this is probably not a real dual provisioning.)`,fix:"vespercli init --host <claude|copilot>"}))}if(e.host){let r=e.host==="claude"?"copilot":"claude";await Kk(e,r)&&t.push(I({code:"host-residue",severity:$.WARN,message:`This workspace is host "${e.host}" but still carries "${r}" artifacts (a leftover from a host switch).`,fix:Pk(r)}))}return t}async function Kk(e,t){if(e.checkout?.ignoredEvidence===t)return!0;let r=e.tracking||{};if(!(Number(r.schemaVersion)>=2)&&(t==="claude"&&r.claude||t==="copilot"&&Array.isArray(r.paths)&&r.paths.length>0))return!0;let n=[...e.residue?.[t]||[]];for(let a of e.manifestAll||[])a?.host!==t||a.owns||Le.has(a.category)||typeof a.path!="string"||a.path.includes("..")||Ak(a.path)||await w($e(e.workspaceRoot,a.path))&&n.push(a.path);if(!n.length)return!1;if(e.checkout?.visible===null||e.checkout?.visible===void 0)return!e.checkout?.gitError;let{runGit:s}=await Promise.resolve().then(()=>(at(),fa)),{READ_ONLY_GIT_ENV:o}=await Promise.resolve().then(()=>(vt(),Aa)),i=await s(["--literal-pathspecs","ls-files","-z","--cached","--others","--exclude-standard","--",...n],{cwd:e.workspaceRoot,timeout:1e4,env:{...process.env,...o}});return!!i&&i.split("\0").some(Boolean)}function Bk(e){let t=[],r=e.checkout||{},n=e.ledgerHostForReporting??null;r.gitError==="dubious-ownership"?t.push(I({code:"git-dubious-ownership",severity:$.WARN,message:"git refuses this repository (dubious ownership), so Vesper cannot read its checkout and provisions nothing here.",fix:`git config --global --add safe.directory ${e.workspaceRoot}`})):r.gitError&&t.push(I({code:"git-unreadable",severity:$.INFO,message:"git could not read this repository, so Vesper provisions nothing here; run `git status` to see why.",fix:"git status"})),e.journal&&t.push(I({code:"host-switch-pending",severity:$.WARN,message:`An interrupted host switch (${e.journal.from} \u2192 ${e.journal.to}) is pending; automatic provisioning is suspended until \`vespercli init\` finishes it.`,fix:re}));let s=!r.host&&!r.ambiguous&&!r.gitError;if(n&&(r.host&&r.host!==n||s&&!e.journal&&!e.legacy?.needsMigration)&&t.push(I({code:"host-record-stale",severity:$.INFO,path:".vesperrc",message:`This worktree's local record describes a ${n} provisioning, but the checked-out commit is ${r.host??"not provisioned"}. The record is not used to decide the host.`,fix:Je(r.host??n)})),r.source==="local"&&r.host&&t.push(I({code:"host-local-only",severity:$.INFO,path:r.ignoredFile??void 0,message:`Vesper's activation here lives in gitignored ${r.ignoredFile}; it follows this worktree across branches, not the commit. Commit ${r.ignoredFile} for per-commit behaviour.`,fix:Je(r.host)})),!r.host&&r.ignoredEvidence){let o=r.ignoredEvidence==="both"?"claude|copilot":r.ignoredEvidence;t.push(I({code:"host-local-unconfirmed",severity:$.WARN,path:r.ignoredFile??void 0,message:`Vesper keys for ${o} are only in gitignored ${r.ignoredFile}, and this worktree's record does not confirm them \u2014 nothing is provisioned from them. Commit ${r.ignoredFile}, or run \`vespercli init --host ${r.ignoredEvidence==="both"?"<claude|copilot>":o}\`.`,fix:r.ignoredEvidence==="both"?"vespercli init --host <claude|copilot>":Je(o)}))}return t}function zk(e){let t=[];for(let r of z){let n=e.residue?.[r]||[];n.length&&((e.fingerprintMatches?.[r]||[]).length>0||e.host!==r&&t.push(I({code:"host-leftover-files",severity:$.WARN,message:`Leftover ${r} files that hold your edits: ${n.join(", ")} \u2014 delete them, or run \`${Je(r)}\` to provision ${r} again. They do not mark this workspace as ${r}.`,fix:Je(r)})))}return t}function Af(e){let t=z.filter(r=>e?.hosts?.[r]);return t.length===1?Je(t[0]):"vespercli init --host claude (or --host copilot \u2014 Vesper 2.0 provisions exactly one host)"}function Yk(e){let t=[],r=e.legacy;r?.unmigrated?t.push(I({code:"legacy-workspace",severity:$.ERROR,message:`${st} Evidence: ${r.evidence.join(", ")||"1.x record"}.`,fix:Af(r)})):(r?.advisory||r?.residue)&&t.push(I({code:"legacy-residue",severity:$.WARN,message:r.advisory?`Pre-2.0 Vesper leftovers and no 2.0 host (${r.evidence.join(", ")}) \u2014 \`vespercli init\` migrates them.`:`This 2.0 workspace still carries pre-2.0 Vesper state (${r.evidence.join(", ")}) \u2014 \`vespercli init\` finishes the migration.`,fix:r.residue&&e.host?Je(e.host):Af(r)})),r&&!r.unmigrated&&!r.advisory&&r.leftovers.length&&t.push(I({code:"legacy-leftover-files",severity:$.WARN,message:`Leftover 1.x files that hold your edits: ${r.leftovers.join(", ")} \u2014 Vesper 2.0 never reads them. Delete them once you have kept what you need.`,fix:`rm ${r.leftovers.join(" ")}`}));for(let n of e.userResidue||[])t.push(I({code:"user-level-residue",severity:$.ERROR,path:n.path,message:`The pre-1.9 machine-wide Vesper catalog is still here (${n.marker}${n.kept?`; ${n.kept} other file(s) there are yours and stay`:""}) \u2014 every project on this machine loads it. \`vespercli init\` backs the folder up and removes only the files a released Vesper build wrote.`,fix:re}));return e.migrationTorn?t.push(I({code:"migration-record-unreadable",severity:$.WARN,path:Jc(e.workspaceRoot,e.migrationTorn),message:`The newest migration record (${Jc(e.workspaceRoot,e.migrationTorn)}) is unreadable, so automatic provisioning is suspended; \`vespercli init\` sets it aside and continues.`,fix:re})):e.migrationActive&&!t.length&&t.push(I({code:"migration-in-progress",severity:$.WARN,message:"A Vesper 1.x migration was interrupted in this workspace; automatic provisioning is suspended until `vespercli init` finishes it.",fix:re})),t}async function Jk(e){if(e.host!=="claude"||e.legacy?.needsMigration)return[];let t=await _t(),r=new Set((e.manifestEntries||[]).map(o=>o.path)),n=new Set;for(let o of e.keptItems||[])(o.reason==="edited-catalog"||o.reason==="edited-skill")&&n.add(o.rel);try{for(let o of await Ck($e(e.workspaceRoot,".claude","agents"))){let i=`.claude/agents/${o}`;if(!o.endsWith(".md")||r.has(i)||!ci("agents",o,""))continue;let a=null;try{a=await qc($e(e.workspaceRoot,i))}catch{a=null}a&&!ai(a,`agents/${o}`)&&n.add(i)}}catch{}let s=[];for(let o of[...n].sort()){if(r.has(o)||!await w($e(e.workspaceRoot,o)))continue;let i=/^\.claude\/(agents|skills)\/([^/]+?)(\.md)?$/.exec(o);if(!i)continue;let[,a,c]=i;if(!(a==="agents"?t.agents:t.skills).has(c)||a==="skills"&&!await w($e(e.workspaceRoot,o,"SKILL.md")))continue;let l=a==="agents"?$e(O,"claude","agents",`${c}.md`):$e(O,"claude","skills",c);s.push(I({code:"kept-shadows-plugin",severity:$.WARN,path:o,message:`${o} is a 1.x copy kept because it holds your edits, and it shadows the plugin's \`vesper:${c}\` (Claude Code prefers the project-level one) \u2014 you keep getting the 1.x version.`,fix:`compare: ${a==="agents"?"diff":"diff -r"} "${$e(e.workspaceRoot,o)}" "${l}"; then either keep yours (it wins) or delete it (${a==="agents"?"rm":"rm -r"} ${o}) to use vesper:${c}`}))}return s}async function qk(e){if(e.host!=="claude")return[];let t;try{t=await qc($e(e.workspaceRoot,".claude","rules","vesper-orchestration.md"),"utf-8")}catch{return[]}let r=bd(t,(await _t()).agents);return r.length?[I({code:"roster-unqualified-agents",severity:$.WARN,path:".claude/rules/vesper-orchestration.md",message:`The Team Roster names ${r.length} specialist(s) without the plugin namespace (${r.slice(0,6).join(", ")}${r.length>6?", \u2026":""}) \u2014 2.0 serves them as \`vesper:<name>\`, so delegation to them does not match until the roster is revalidated.`,fix:"run `/revalidate-team` once in Claude Code (it rewrites the roster with vesper:<name> names)"})]:[]}async function Xk(e){if(!e.host)return[];let t=await ur(e.workspaceRoot,e.host);if(t===null)return[];let r=await dr(t),{enabled:n}=await Mr(e.workspaceRoot,e.host),s=[];for(let o of r.packs){if(n.includes(o))continue;let i=[...r.needed[o].agents,...r.needed[o].skills];s.push(I({code:"pack-not-enabled",severity:$.WARN,path:kn[e.host],message:`The Team Roster names ${i.length} asset(s) of the "${o}" pack (${Me(o)}: ${i.slice(0,6).join(", ")}${i.length>6?", \u2026":""}), but that pack is not enabled for ${e.host} in this workspace \u2014 delegation to them does not resolve until it is.`,fix:mp}))}for(let o of n)r.packs.includes(o)||jr(o)||o===Ge||s.push(I({code:"pack-unused",severity:$.INFO,path:e.host==="claude"?".claude/settings.json":".vscode/settings.json",message:`The "${o}" pack (${Me(o)}) is enabled for ${e.host}, but the Team Roster names none of its assets.`,fix:`vespercli packs disable ${o} (or keep it \u2014 an unused pack costs only load time)`}));return s}async function Qk(e){if(!e.runningHost)return[];if(e.journal)return[];if(e.checkout?.source==="local"&&e.legacy?.unmigrated)return[];if(e.checkout?.source==="local"&&e.migrationActive)return[];let t=[],r=e.checkout?.host??null;if(!r)return t.push(I({code:"host-unresolved",severity:$.INFO,message:"Could not resolve the provisioned host from disk (no recorded host and no Vesper-specific fingerprint) \u2014 the host-identity check has nothing to compare against.",fix:re})),t;if(r!==e.runningHost){let n=Of(e,r);t.push(I({code:$f,severity:n?$.ERROR:$.WARN,message:n?`This workspace is provisioned for host "${r}" but is running under "${e.runningHost}".`:`This workspace looks like host "${r}" but is running under "${e.runningHost}". Reported as a warning: the only evidence is generic, non-Vesper-specific files, so this may not be a Vesper workspace at all.`,fix:Je(e.runningHost)}))}return t}async function Zk(e){if(e.host!=="claude")return[];let t;try{t=JSON.parse(await qc(bn(e.workspaceRoot),"utf-8"))}catch{return[]}let r=t?.extraKnownMarketplaces?.[Oe];return r===void 0||tf(r)?[]:[I({code:"marketplace-entry-invalid",severity:$.WARN,path:".claude/settings.local.json",message:`The \`extraKnownMarketplaces.${Oe}\` entry is not in Claude Code's schema (\`source\` must be an object: {"source":"directory","path":\u2026}); Claude Code ignores it and the vesper plugin does not load.`,fix:"vespercli worktree bootstrap"})]}function eS(e){if(!e.initialised)return[];let t=e.packageVersion;if(!t)return[];let r=e.frameworkVersion;return r?r!==t?[I({code:"framework-stale",severity:$.WARN,message:`Workspace provisioned with Vesper ${r}, running ${t}.`,fix:re})]:[]:[I({code:"ledger-unstamped",severity:$.INFO,message:"This worktree's ledger (`.vesperrc`) carries no framework version yet \u2014 `init` has not run in this worktree (bootstrap does not stamp one).",fix:re})]}async function tS(e){return e.initialised?await w($e(e.workspaceRoot,ue))?[]:e.manifestAll?.some(t=>t?.path===ue)?[]:[I({code:"gates-missing",severity:$.INFO,path:ue,message:"No gate policy (`.vesper/gates.json`) \u2014 `vespercli gate` exits 2 here until `init` seeds one.",fix:re})]:[]}async function rS(e){if(e.host!=="claude")return[];let t=new Set((e.manifestAll||[]).map(n=>n?.path)),r=[];for(let n of Pp)t.has(n)||await w($e(e.workspaceRoot,n))||r.push(n);return r.length?[I({code:"opencode-overlay-missing",severity:$.INFO,path:r[0],message:`OpenCode overlay incomplete \u2014 missing ${r.join(", ")}. \`vespercli init\` adds the missing file(s); nothing else changes (a 2.0.x Claude workspace gets the overlay this way).`,fix:re})]:[]}async function nS(e){if(e.host!=="claude")return[];let t=$e(e.workspaceRoot,".claude","agents"),r=[];try{r=(await xk(t,{withFileTypes:!0})).filter(o=>o.isFile()&&o.name.endsWith(".md")).map(o=>o.name)}catch{return[]}let n=[];for(let s of r){let o=`.claude/agents/${s}`;try{let i=await Ds($e(t,s),"utf-8"),a=sS(i);(!a||!_f(a.name)||!_f(a.description))&&n.push(I({code:"agent-frontmatter-incomplete",severity:$.WARN,category:"catalog-agent",path:o,message:`Committed agent "${o}" is missing a non-empty name/description in its frontmatter.`,fix:re}))}catch{}}return n}function _f(e){return typeof e=="string"&&e.trim().length>0}function sS(e){let t=/^---\r?\n([\s\S]*?)\r?\n---/.exec(e);if(!t)return null;let r={};for(let n of t[1].split(/\r?\n/)){let s=/^([A-Za-z0-9_-]+):\s*(.*)$/.exec(n);if(!s)continue;let o=s[2].trim();(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),r[s[1]]=o}return r}async function oS(e){let t=[],r=e.checkout||{};if(!r.host||r.source==="local"||r.gitError)return t;let{resolveGitHooksDir:n,gitHooksSkipMessage:s,VESPER_MANAGED_GIT_HOOKS:o,isHookTrackedByGit:i,realOrNearestAncestor:a,resolveHookWriteTarget:c}=await Promise.resolve().then(()=>(H(),Da)),{runGit:l}=await Promise.resolve().then(()=>(at(),fa)),{classifyForeignHook:d,HOOK_GUARD_START:p,HOOK_GUARD_END:f}=await Promise.resolve().then(()=>(Kr(),Ql));if(await l(["config","--type=bool","--get","vesper.hooks"],{cwd:e.workspaceRoot,timeout:5e3})==="false")return t.push(I({code:"git-hooks-opted-out",severity:$.INFO,message:"Vesper's git hooks are turned off for this repository (git config vesper.hooks false): no guard runs on checkout and no commit hygiene on commit.",fix:"git config --unset vesper.hooks && vespercli worktree bootstrap"})),t;let m=await n(e.workspaceRoot);if(!m.dir)return m.reason==="not-a-repo"||t.push(I({code:"git-hooks-not-installable",severity:$.INFO,message:s({...m,hook:"hook"})??`Git hooks not installable (${m.reason}).`,fix:"see the message"})),t;if(!m.default&&await i(await a(m.dir),m,{dir:!0}))return t.push(I({code:"git-hooks-not-installable",severity:$.INFO,message:s({reason:"tracked-by-git",configured:m.dir}),fix:"see the message"})),t;for(let h of o){let g=$e(m.dir,h),y=await c(g),k=null;if(y.path)try{k=await Ds(y.path)}catch{k=null}let v=k?k.toString("latin1"):"",S=v.indexOf(p);if(S!==-1){let N=v.indexOf(f,S),E=v.slice(S,N===-1?void 0:N);E.includes("vesper.hooks")?h==="pre-commit"&&!E.includes("VESPER_NO_SWEEP")&&t.push(I({code:"git-hook-outdated",severity:$.INFO,path:g,message:`Vesper's pre-commit git hook block (${g}) predates VESPER_NO_SWEEP: an agent's commit still sweeps every dirty knowledge path into it.`,fix:"vespercli worktree bootstrap"})):t.push(I({code:"git-hook-outdated",severity:$.INFO,path:g,message:`Vesper's ${h} git hook block (${g}) predates the run-time opt-out check: \`git config vesper.hooks false\` would not stop it.`,fix:"vespercli worktree bootstrap"}));continue}let C=null;if(!y.path)C={reason:y.reason,configured:g};else if(k&&await i(await a(y.path),m))C={reason:"tracked-by-git",configured:y.path};else if(k){let N=d(k);N.ok||(C={reason:N.reason,interpreter:N.interpreter,line:N.line})}if(C){t.push(I({code:"git-hook-not-modifiable",severity:$.INFO,path:g,message:s({...C,hook:h,hooksDir:m.dir})??`Git hook ${h} cannot carry Vesper's block (${C.reason}).`,fix:"see the message"}));continue}t.push(I({code:"git-hook-missing",severity:$.WARN,path:g,message:`Vesper's ${h} git hook block is missing (${g}): ${h==="post-checkout"?"a branch switch or a new worktree does not run the host guard":"commits do not carry the project-knowledge files"}.`,fix:"vespercli worktree bootstrap"}))}return t}async function iS(e){if(!e.host)return[];if(!await hn(e.workspaceRoot,e.host))return[];let t=[],r=e.host==="claude"?".claude/settings.json":".vscode/settings.json";rt()||t.push(I({code:"graphify-missing",severity:$.INFO,path:r,message:"The graphify pack is enabled but the `graphify` tool is not on PATH \u2014 the post-checkout refresh and `graphify update .` do nothing until it is installed (vesper-indexing remains the default codebase tool).",fix:xs()}));let n=await zd(e.workspaceRoot);if(!n.present)return t.push(I({code:"graphify-no-graph",severity:$.INFO,path:ke,message:`The graphify pack is enabled but ${ke} does not exist \u2014 the graphify MCP server has nothing to serve until the graph is built.`,fix:Se})),t;if(ri(e.workspaceRoot)||t.push(I({code:"graphify-no-interpreter",severity:$.INFO,path:Ut,message:`${ke} exists but ${Ut} is not recorded on this machine (it is gitignored) and no python3/python is on PATH \u2014 the graphify MCP server cannot start here yet.`,fix:Se})),!n.commit)return t;let s=await D(["rev-parse","HEAD"],{cwd:e.workspaceRoot});return s&&(s.startsWith(n.commit)||n.commit.startsWith(s)||t.push(I({code:"graphify-stale",severity:$.WARN,path:ke,message:`${ke} was built from commit ${n.commit.slice(0,12)} (\`${n.key}\`) but HEAD is ${s.slice(0,12)} \u2014 impact and path answers may miss recent changes.`,fix:Se}))),t}var Tf=[{id:"manifest",title:"Owned-files manifest",run:e=>Gk(e)},{id:"mcp-drift",title:"MCP config drift",run:e=>Dk(e)},{id:"mcp-required",title:"MCP config recorded",run:e=>Vk(e)},{id:"tracking",title:"Tracking structure",run:e=>Uk(e)},{id:"host-conflict",title:"Host conflict",run:e=>Wk(e)},{id:"host-authority",title:"Host authority (checkout vs worktree record)",run:e=>Bk(e)},{id:"host-leftover",title:"Leftover host files",run:e=>zk(e)},{id:"legacy",title:"Pre-2.0 (1.x) residue",run:e=>Yk(e)},{id:"legacy-kept-shadows",title:"Kept 1.x copies shadowing plugin specialists",run:e=>Jk(e)},{id:"roster-namespaces",title:"Team Roster delegation names",run:e=>qk(e)},{id:"packs",title:"Packs the Team Roster needs",run:e=>Xk(e)},{id:"git-hooks",title:"Vesper git hooks",run:e=>oS(e)},{id:"graphify",title:"graphify pack (opt-in)",run:e=>iS(e)},{id:"host-mismatch",title:"Host identity",run:e=>Qk(e),failureSeverity:e=>e.runningHost?$.ERROR:$.WARN},{id:"framework-version",title:"Framework version",run:e=>eS(e)},{id:"marketplace-entry",title:"Marketplace entry shape",run:e=>Zk(e)},{id:"agent-frontmatter",title:"Agent frontmatter",run:e=>nS(e)},{id:"gates-config",title:"Gate policy",run:e=>tS(e)},{id:"opencode-overlay",title:"OpenCode overlay",run:e=>rS(e)}];function Cf(e){let t=e.filter(o=>o.severity===$.ERROR),r=e.filter(o=>o.severity===$.WARN),n=e.filter(o=>o.severity===$.INFO),s=t.some(o=>o.code===$f);return{findings:e,errors:t,warnings:r,infos:n,summary:{hasError:t.length>0,hostMismatch:s}}}async function Cn(e,{runningHost:t,homeDir:r,checkout:n}={}){let s=await Lk(e,t,{homeDir:r,checkout:n});return s.corrupt?Cf([I({code:"tracking-unparseable",severity:$.ERROR,path:Jc(e,s.corruptPath),message:"Malformed .tracking structure (.vesperrc is present but unparseable) \u2014 framework cannot operate.",fix:re})]):Cf(await aS(s,Tf))}async function aS(e,t=Tf){let r=[];for(let n of t)try{let s=await n.run(e);Array.isArray(s)&&r.push(...s)}catch(s){let o=n.failureSeverity?n.failureSeverity(e):$.WARN;r.push(I({code:Ok,severity:o,category:n.id,message:`Doctor check "${n.title}" (${n.id}) failed to run \u2014 its coverage is MISSING from this report, not clean: ${s?.message||s}`,fix:re}))}return r}function Gi(e){return e.summary.hostMismatch?Pe.HOST_MISMATCH:e.summary.hasError?Pe.ERROR:Pe.OK}_e();H();function Xc(e){return String(e??"").replace(/\r\n?/g,`
|
|
92
|
+
`)}function ht(e){let t=Xc(e),r=/^---\n([\s\S]*?)\n---(?:\n|$)/.exec(t);return r?{frontmatter:r[1],body:t.slice(r[0].length)}:{frontmatter:null,body:t}}function Vr(e,t){if(!e)return null;let r=Xc(e).split(`
|
|
93
|
+
`),n=r.findIndex(i=>new RegExp(`^${t}:`).test(i));if(n===-1)return null;let s=r[n].slice(t.length+1).trim();if(s&&![">","|",">-","|-"].includes(s))return/^'.*'$/.test(s)?s.slice(1,-1).replace(/''/g,"'"):/^".*"$/.test(s)?s.slice(1,-1).replace(/\\"/g,'"'):s;let o=[];for(let i=n+1;i<r.length;i++){if(!/^\s+\S/.test(r[i])){if(r[i].trim()==="")continue;break}o.push(r[i].trim())}return o.length?o.join(" "):null}function Fi(e){return`'${String(e??"").replace(/[\u0000-\u001f]+/g," ").replace(/\s+/g," ").trim().replace(/'/g,"''")}'`}var If=Object.freeze(["vesper-orchestrator","vesper-orchestration","vesper-context"]);function cS(e){let t=e;for(let r of If){let n=r.replace(/^vesper-/,""),s=`.vesper/instructions/${r}.instructions.md`;t=t.replace(new RegExp(`\\.claude/rules/${r}\\.md`,"g"),s).replace(new RegExp(`\\.claude/vesper/${n}\\.md`,"g"),s)}return t.replace(/\.claude\/vesper\/\{orchestrator,orchestration,context\}\.md/g,".vesper/instructions/vesper-{orchestrator,orchestration,context}.instructions.md").replace(/\.claude\/rules\/vesper-\*\.md/g,".vesper/instructions/vesper-*.instructions.md").replace(/\.claude\/vesper\/\*\.md/g,".vesper/instructions/vesper-*.instructions.md").replace(/\.claude\/agents\/vesper-orchestrator\.md/g,".vesper/agents/vesper-orchestrator.agent.md")}function lS(e){return cS(e).replace(/\.claude\/rules\/([A-Za-z0-9_{}*-]+)\.md/g,".vesper/instructions/$1.instructions.md").replace(/\.claude\/agents/g,".vesper/agents").replace(/\.claude\/commands/g,".vesper/prompts").replace(/\.claude\/skills/g,".vesper/skills").replace(/\.claude\/rules/g,".vesper/instructions").replace(/\.claude\/vesper\/context/g,".vesper/context").replace(/\.claude\/vesper/g,".vesper").replace(/(?<!\.vscode\/)\.mcp\.json/g,".vscode/mcp.json").replace(/\bAskUserQuestion\b/g,"vscode/askQuestions").replace(/\bTodoWrite\b/g,"manage_todo_list").replace(/`run_in_background:\s*true`/g,"`isBackground: true`").replace(/run_in_background:\s*true/g,"isBackground: true")}function uS(e){let t=e;for(let r of If)t=t.replace(new RegExp(`\\.vesper/instructions/${r}\\.md`,"g"),`.vesper/instructions/${r}.instructions.md`);return t.replace(/\.vesper\/agents\/vesper-orchestrator\.md/g,".vesper/agents/vesper-orchestrator.agent.md")}var Pf=Object.freeze(["start","end","gitignore","hook"]);function jf(e){return e.replace(/`\/?vesper-<pack>:<name>`/g,"`<name>`").replace(/\bvesper-<pack>:<name>\b/g,"<name>").replace(/`\/?vesper-[a-z][a-z0-9-]*:([a-z][a-z0-9-]*)`/g,"`$1`").replace(/\bvesper-[a-z][a-z0-9-]*:([a-z][a-z0-9-]*)\b/g,"$1").replace(/`vesper:<name>`/g,"`<name>`").replace(/`\/vesper:<name>`/g,"`/<name>`").replace(/`vesper:\*`/g,"`<name>`").replace(/`vesper:([a-z][a-z0-9-]*)`/g,(t,r)=>Pf.includes(r)?t:`\`${r}\``).replace(/\bvesper:([a-z][a-z0-9-]*)\b/g,(t,r)=>Pf.includes(r)?t:r)}function Rf(e){return jf(uS(lS(Xc(e))))}var A$=Object.freeze({Read:"read/readFile",Bash:"execute/runInTerminal",Grep:"search/codebase",Glob:"search/fileSearch",TodoWrite:"todo",AskUserQuestion:"vscode/askQuestions",Agent:"agent/runSubagent"}),_$=Object.freeze(["read/readFile","search/codebase","search/fileSearch","edit/editFiles","edit/createFile","execute/runInTerminal","agent/runSubagent","todo","vscode/askQuestions","web","web/fetch"]),C$=Object.freeze({"claude-opus-5-5":"Claude Opus 5.5","claude-sonnet-5-5":"Claude Sonnet 5.5","claude-haiku-4-5-20251001":"Claude Haiku 4.5"});var $$=Object.freeze(["core","extended"]);var O$=Object.freeze(["copilot-apply-to","copilot-instructions-tier"]);var Qc=Object.freeze([{key:"orchestrator",source:"vesper-orchestrator.md",name:"vesper-orchestrator",seedOnce:!1},{key:"orchestration",source:"orchestration.md.tpl",name:"vesper-orchestration",seedOnce:!0},{key:"context",source:"context.md.tpl",name:"vesper-context",seedOnce:!0}]),Gf=".vesper/context";function Ff(e){return qe(e,".vesper","agents")}function pS(e){return qe(e,".vesper","instructions")}function Df(e){return qe(e,Gf)}var fS=".vscode/mcp.json",U$=Object.freeze([".github/",".claude/rules/",".claude/agents/",".claude/commands/",".claude/skills/"]);function Di(e){return Rf(e)}function Vf(e){return Fi(e).slice(1,-1)}var Lf="VESPER_HOST_MISMATCH";function hS(){return["## \u{1F3AF} Who this playbook binds (read first)","","This file is attached to **every** chat and agent context in this workspace","(`applyTo: '**'`), but it is the operating playbook of exactly **one** persona.","Establish which one you are before reading further:","",`- **You are \`${L}\`** \u2014 the single pickable Vesper agent`,` (\`${It}\`). Everything below binds you in full. The`," MANDATORY DELEGATION LAW, the Purpose Router and every Purpose Pipeline are yours.","- **You are anyone else** \u2014 a Vesper specialist you were delegated to"," (`code-reviewer`, `task-researcher`, `principal-software-engineer`, \u2026), a built-in"," mode (Agent / Ask / Edit), or a custom agent. Then the **MANDATORY DELEGATION LAW,"," the Purpose Router and the Purpose Pipelines below do NOT bind you.** You were"," delegated to precisely so that you would do the work directly: read, analyse, edit"," and run commands exactly as your own agent definition instructs. Never refuse a task"," by citing the delegation law, and never hand your task back to the orchestrator"," merely because this file is in your context.","","Sections that bind **every** agent regardless of persona: the workspace layout and","path conventions, the Tracking & History rules, and the Host-mismatch warning.","","---",""].join(`
|
|
94
|
+
`)}function mS(e,t,r){let n=t.trim().split(/\s+/).map(s=>s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("\\s+");return e.replace(new RegExp(n,"g"),r)}var gS=Object.freeze([["installed once, globally, as the Vesper plugin","shipped inside the installed `@mthanh/vespercli` package and activated by the `chat.*FilesLocations` settings Vesper injects"],["Degraded mode (plugin unavailable)","Degraded mode (specialists unresolvable)"],["(and any session where the plugin's workspace-trust dialog was declined) the marketplace plugin does **not** load, so those specialists are **absent**","(most often because `vespercli init` was never run here, the injected `chat.agentFilesLocations` entry was pruned, or the VS Code window has not been reloaded since init) the specialist agent files do **not** resolve, so those specialists are **absent**"],["in cloud/remote ALL skills are plugin-carried and therefore absent alongside the specialists","when the specialists do not resolve, ALL package-carried skills are absent alongside them"],["skills are installed in the shared Vesper plugin and auto-discovered by name","skills ship inside the installed Vesper package and are auto-discovered by name"],["never to the plugin/global install location","never to the package install location"],["(`.vesper/`, `.vesper/`, project source)","(`.vesper/`, project source)"],["(it verified the enabled plugin's cache resolves for this project)","(it verified the specialist agent files resolve for this project)"],["when it can confirm the plugin is not resolved","when it can confirm the specialists are not resolvable"],["the plugin is actually present (e.g. a flaked desktop hook)","the specialists are actually present (e.g. a flaked guard)"]]),yS="**Namespaced delegation names",wS=`- **Plain delegation names (correctness invariant, not style):** this host has no plugin namespace \u2014 every specialist is an ordinary agent file discovered by its bare name. Delegate to them by their **plain** name (e.g. \`code-reviewer\`, \`task-researcher\`, \`principal-software-engineer\`). The Team Roster's "Agent Name" column carries these plain names verbatim \u2014 use them exactly as written. The one project-local agent is \`${L}\` (this persona). The four maintenance prompts are invoked unqualified (\`/reinit\`, \`/compact-knowledge\`, \`/revalidate-knowledge\`, \`/revalidate-team\`).`;function vS(e){return e.split(`
|
|
95
|
+
`).map(t=>t.trimStart().startsWith("- ")&&t.includes(yS)?wS:t).join(`
|
|
96
|
+
`)}function kS(e){let t=gS.reduce((r,[n,s])=>mS(r,n,s),e);return vS(t)}function SS(e){let r=e.indexOf("> **First-run workspace trust & plugin resolution:**");if(r===-1)return e;let n=e.indexOf(`
|
|
97
|
+
`,r);n===-1&&(n=e.length);let s=`> **How the Vesper team resolves here:** on the Copilot host the specialist catalog is NOT a plugin and needs no workspace-trust dialog \u2014 the agents, skills, prompts and instructions are read straight from the installed \`@mthanh/vespercli\` package through the \`chat.*FilesLocations\` entries Vesper injects into \`.vscode/settings.json\`. Every package agent is a HIDDEN specialist (\`user-invocable: false\`); the only pickable Vesper agent is \`${L}\`, provisioned project-local at \`${It}\`. If the specialists do not resolve, the settings injection is missing or VS Code has not been reloaded \u2014 reload the window, then run \`vespercli doctor\`. The **Degraded mode** section below governs how you operate while they are unavailable.`;return e.slice(0,r)+s+e.slice(n)}function Hf(e){let{body:t}=ht(e);if(!t.includes(Lf))throw new Error(`renderCopilotPlaybook: the canonical playbook no longer contains the ${Lf} marker. The host-mismatch warning keys off it \u2014 restore the "Host-mismatch warning" section in assets/claude/vesper-orchestrator.md.`);let r=kS(Di(SS(t))),n=["---","applyTo: '**'",`description: 'Vesper orchestrator playbook \u2014 delegation law, purpose router, and pipelines. Binds the ${L} persona; see the scope block at the top.'`,"---",""].join(`
|
|
98
98
|
`),[s,...o]=r.split(`
|
|
99
99
|
`),i=o.join(`
|
|
100
100
|
`).replace(/^\n+/,"");return`${n}${s}
|
|
101
101
|
|
|
102
|
-
${
|
|
103
|
-
`)+
|
|
102
|
+
${hS()}${i}`}function Zc(e,t){let{frontmatter:r,body:n}=ht(e),s=Vr(r,"description")||t;return["---","applyTo: '**'",`description: '${Vf(s)}'`,"---",""].join(`
|
|
103
|
+
`)+Di(n).replace(/^\n+/,"")}var ES=Object.freeze([{token:".claude/settings.json",why:"Copilot has no `.claude/settings.json`"},{token:"marketplace",why:"the Copilot catalog is not a plugin marketplace"},{token:"vesper:<name>",why:"Copilot delegation names are plain (DEC-5)"},{token:"/vesper:",why:"Copilot prompts are invoked unqualified"},{token:"Claude Code project",why:"this artifact provisions a VS Code / Copilot project"}]);function bS(e,t){let r=ES.filter(({token:n})=>e.includes(n));if(r.length!==0)throw new Error(`Copilot render of ${t} still contains Claude-host-only text: `+r.map(({token:n,why:s})=>`"${n}" (${s})`).join(", ")+". The source in assets/claude-committed/agents/ was likely reworded, so a paragraph anchor in PERSONA_PARAGRAPH_REWRITES no longer matches \u2014 update the anchor/replacement pair rather than deleting this assertion.")}var xS=Object.freeze([{anchor:"committed main-thread persona",replace:e=>e.replace("committed main-thread persona","project-local orchestrator persona")},{anchor:"This agent file is intentionally thin",replace:()=>"This agent file is intentionally thin: it exists so that `"+L+"` is the ONE selectable Vesper agent in the VS Code chat agent picker. Every packaged specialist is emitted `user-invocable: false` and is therefore hidden from the picker while remaining delegable. All behavior lives in the always-on instructions above \u2014 follow them exactly. Do not restate or override them here."},{anchor:"Specialists are delegated to by",replace:()=>"Specialists are delegated to by their PLAIN names (e.g. `code-reviewer`, `task-researcher`) \u2014 this host has no plugin namespace, so the Team Roster carries plain names and you use them verbatim. The maintenance prompts are invoked unqualified (`/reinit`, `/compact-knowledge`, `/revalidate-knowledge`, `/revalidate-team`)."}]);function AS(e){return e.split(`
|
|
104
104
|
|
|
105
|
-
`).map(t=>{let r=
|
|
105
|
+
`).map(t=>{let r=xS.find(n=>t.includes(n.anchor));return r?r.replace(t):t}).join(`
|
|
106
106
|
|
|
107
|
-
`)}function
|
|
108
|
-
`)+
|
|
107
|
+
`)}function _S(e){let t=e.indexOf("This is a COMMITTED project agent"),r=(t===-1?e:e.slice(0,t)).trim();return`${Di(r).replace(/Claude Code project/g,"VS Code (GitHub Copilot) project")} The only user-selectable Vesper agent in this workspace; every packaged specialist is hidden and reached by delegation.`}function Uf(e){let{frontmatter:t,body:r}=ht(e),n=Vr(t,"description")||"Vesper super-orchestrator \u2014 routes every request to the specialist team.",o=["---",`description: '${Vf(_S(n))}'`,`name: ${L}`,"user-invocable: true","model: 'Claude Opus 5.5'","tools: ['read/readFile', 'search/listDirectory', 'search/fileSearch', 'agent/runSubagent', 'todo', 'vscode/askQuestions', 'vesper-indexing/*', 'memory/*']","agents: '*'","---",""].join(`
|
|
108
|
+
`)+AS(Di(r)).replace(/^\n+/,"");return bS(o,"the pickable orchestrator agent"),o}async function Mf(e,t){if(await w(e)){try{if(await Vs(e,"utf-8")===t)return"unchanged"}catch{}return await A(e,t,"utf-8"),"updated"}return await A(e,t,"utf-8"),"created"}async function Vi(e,{version:t}={}){await P(Ff(e),{recursive:!0}),await P(pS(e),{recursive:!0}),await P(Df(e),{recursive:!0});let r={},n=[],s=qe(hr,"agents",`${L}.md`);r.orchestratorAgent=await Mf(qe(e,It),Uf(await Vs(s,"utf-8"))),n.push(G({path:It,host:"copilot",category:"catalog-agent",hash:await ye(qe(e,It))}));for(let i of Qc){let a=je(i.name),c=qe(e,a),l=await Vs(qe(De,i.source),"utf-8");i.seedOnce?(r[i.key]="skipped",await w(c)||(await A(c,Zc(l,`Vesper ${i.name}`),"utf-8"),r[i.key]="created"),n.push(G({path:a,host:"copilot",category:"per-project-authored",hash:null}))):(r[i.key]=await Mf(c,Hf(l)),n.push(G({path:a,host:"copilot",category:"playbook",hash:await ye(c)})))}r.contextTier="ensured",n.push(G({path:Gf,host:"copilot",category:"per-project-authored",hash:null}));let o=await oi(e);if(r.gates=o.created?`created (checks: ${o.checks.join(", ")||"none"})`:"skipped",n.push(G({path:ue,host:"copilot",category:"per-project-authored",hash:null})),await W(e,n),t!==void 0){let i=await x(e);i.schemaVersion=ve,i.frameworkVersion=t,await T(e,i)}return r}async function el(e,{settingsEntries:t=[]}={}){let r=[],n=s=>qe(e,s);return await w(n(Zt))&&r.push(Y({path:Zt,host:"copilot",category:"settings",owns:{keys:[...Lt],entries:[...t]}})),await w(n(no))&&r.push(Y({path:no,host:"copilot",category:"bootstrap-task",owns:{keys:[so]}})),r.length>0&&await W(e,r),r}function Wf(){return _o()}async function Hi(e,t){let r=Co(t),{added:n}=await Zr(e,[r]),s=new Set([...await At(e),r.path]);return await el(e,{settingsEntries:[...s]}),{name:t,path:r.path,added:n.includes(r.path)}}async function Hs(e,t=!0,{record:r=!0}={}){let n=await _r(e,t,{record:r});return t&&r&&await W(e,[Y({path:fS,host:"copilot",category:"mcp-config",owns:{keys:[...me]}})]),{...n,mcpPath:Qe(e)}}async function Kf(e,{purgeProjectAuthored:t=!1}={}){let r=[],n=[],s=new Map(J(await x(e)).filter(l=>l.host==="copilot").map(l=>[l.path,l])),o=await CS(),i=[It,je(L)];for(let l of i){let d=await le(qe(e,l),s.get(l)||{path:l},{expected:o[l]===void 0?[]:[o[l]]});d==="removed"?r.push(l):d==="kept"&&n.push(l)}let a=J(await x(e)).some(l=>l.host!=="copilot"&&l.path===ue&&l.category==="per-project-authored"),c=t?[...Qc.filter(l=>l.seedOnce).map(l=>je(l.name)),...a?[]:[ue]]:[];for(let l of c){let d=qe(e,l);await w(d)&&(await Nf(d,{force:!0}),r.push(l))}try{await dS(Ff(e))}catch{}return t&&await Nf(Df(e),{recursive:!0,force:!0}),{removed:r,kept:n}}async function CS(){let e={};try{e[It]=Uf(await Vs(qe(hr,"agents",`${L}.md`),"utf-8"))}catch{}let t=Qc.find(r=>!r.seedOnce);try{e[je(t.name)]=Hf(await Vs(qe(De,t.source),"utf-8"))}catch{}return e}U();H();te();_e();import{resolve as On,basename as XS}from"node:path";import{confirm as pl}from"@inquirer/prompts";Ae();U();H();te();_e();fe();import{resolve as RS,join as Ee}from"node:path";import{rm as Us,rmdir as NS,readFile as sl,readdir as LS}from"node:fs/promises";Ye();Kt();pn();ft();$s();U();H();te();Ye();_s();fe();import{readFile as tl,rm as $S}from"node:fs/promises";import{join as Ui}from"node:path";Tr();_e();var Yf=Object.freeze(["i-have-adhd","ponytail"]),Bf=Object.freeze(["vendored-body","vendored-activation"]);function OS(){return $r.flatMap(e=>[`.claude/skills/${e}`,`.vesper/skills/${e}`])}function Jf(){return[...Yf.map(e=>`.claude/rules/${e}.md`),...$r.map(e=>je(e))]}function rl(){return[...OS(),...Jf()].sort()}function nl(e){if(!e||typeof e!="object")return!1;if(e.adhd?.installed===!0)return!0;let t=e.vendored;return!!t&&typeof t=="object"&&Object.values(t).some(r=>r&&r.installed===!0)}var qf=`# ADHD-friendly output (always on)
|
|
109
109
|
|
|
110
110
|
Shape every response so a reader with ADHD can act on it: lead with the next
|
|
111
111
|
concrete action (a command, path, or snippet \u2014 not preamble), keep it brief and
|
|
@@ -115,7 +115,7 @@ always win over brevity, and the harness/system prompt always outranks this rule
|
|
|
115
115
|
Follow the full \`i-have-adhd\` skill for the specifics
|
|
116
116
|
(\`.claude/skills/i-have-adhd/SKILL.md\`). It stays in effect for the whole
|
|
117
117
|
session until the reader says "stop adhd mode" or "normal mode".
|
|
118
|
-
`,
|
|
118
|
+
`,Xf=`# Ponytail: the laziest solution that works (always on)
|
|
119
119
|
|
|
120
120
|
Prefer the simplest, shortest, most minimal solution \u2014 but only after you
|
|
121
121
|
understand the problem and trace the flow. Climb the ladder, stop at the first
|
|
@@ -133,9 +133,9 @@ for \u2014 build it in full, no re-arguing. Intensity: \`/ponytail lite|full|ult
|
|
|
133
133
|
Follow the full \`ponytail\` skill for the specifics
|
|
134
134
|
(\`.claude/skills/ponytail/SKILL.md\`). It stays in effect for the
|
|
135
135
|
whole session until the user says "stop ponytail" or "normal mode".
|
|
136
|
-
`,
|
|
136
|
+
`,TS=Object.freeze({"i-have-adhd":"Install the third-party i-have-adhd output-style skill? (MIT, reviewed snapshot, added to this repo)",ponytail:"Install the third-party ponytail decision-ladder skill? (MIT, reviewed snapshot, rule-text only, added to this repo)"});function PS(e){let t=e==="i-have-adhd"?qf:Xf;return`${["---","applyTo: '**'",`description: '${TS[e].replace(/'/g,"''")}'`,"---",""].join(`
|
|
137
137
|
`)}
|
|
138
|
-
${t.split(`.claude/skills/${e}/`).join(`.vesper/skills/${e}/`)}`}function
|
|
138
|
+
${t.split(`.claude/skills/${e}/`).join(`.vesper/skills/${e}/`)}`}function zf(e,t){return`${["---","applyTo: '**'",`description: '${Fi(t||`Vendored skill "${e}", a reviewed snapshot pinned to an upstream commit and installed by Vesper.`)}'`,"---",""].join(`
|
|
139
139
|
`)}
|
|
140
140
|
# ${e} (vendored skill)
|
|
141
141
|
|
|
@@ -147,22 +147,22 @@ anything the skill covers, rather than working from memory.
|
|
|
147
147
|
Vesper places this skill but does not author it. A newer upstream arrives only with
|
|
148
148
|
a Vesper release that re-vendors it (a reviewed change); a file you edit is kept and
|
|
149
149
|
reported, never overwritten.
|
|
150
|
-
`}async function _S(e){let t=Cr(e);if(!t)return null;try{let{frontmatter:r}=dt(await Qc(Gi(t.dir,"SKILL.md"),"utf-8")),n=r?Dr(r,"description"):null;return n&&String(n).trim()||null}catch{return null}}async function CS(e){if(e===".claude/rules/i-have-adhd.md")return[Hf];if(e===".claude/rules/ponytail.md")return[Uf];for(let t of _r)if(e===Pe(t))return Df.includes(t)?[AS(t)]:[Gf(t,await _S(t)),Gf(t,null)];return[]}async function Wf(e,{backup:t}={}){let r={removed:[],kept:[],claudeMd:!1,stylesConsent:!1,rowsDropped:0},n=new Set,s=async h=>{typeof t!="function"||n.has(h)||(n.add(h),await t(h))},o=await x(e),i=J(o),a=h=>i.find(g=>g.path===h&&Ff.includes(g.category))||null;for(let h of _r){let g=Cr(h),y=g?await Go(g.dir):{};for(let k of[`.claude/skills/${h}`,`.vesper/skills/${h}`]){let v=Gi(e,k);if(!await w(v))continue;let S=a(k),C=S?.placedFiles??S?.syncedFiles,N=C&&typeof C=="object"&&Object.keys(C).length?{...C}:void 0,E={sourceFiles:y,...N?{sourceHashes:N}:{},sourceMatch:(X,De)=>fc(De,`${k}/${X}`),anchor:"SKILL.md"},b=await Mt(v,E);if(b.status!=="classified"||b.proven.length===0){(b.status==="anchor-unproven"||b.status==="classified"&&b.kept.length)&&r.kept.push({path:k,files:b.kept});continue}await s(k);let G=await is(v,E);G.status==="removed"?r.removed.push(k):G.status!=="absent"&&r.kept.push({path:k,files:G.kept})}}for(let h of Vf()){let g=Gi(e,h);if(!await w(g))continue;let y=null;try{y=await Qc(g)}catch{y=null}if(y&&fc(y,h)){await s(h),await ES(g,{force:!0}),r.removed.push(h);continue}let k=a(h)??{path:h,category:"vendored-activation",hash:null},v=await CS(h);if(!await as(g,k,{expected:v})){r.kept.push({path:h});continue}await s(h);let S=await le(g,k,{expected:v});S==="removed"?r.removed.push(h):S!=="absent"&&r.kept.push({path:h})}let c=Gi(e,"CLAUDE.md");if(await w(c)){let h=await Qc(c,"utf-8"),g=Lc(h);ee(g,h)||(await A(c,g,"utf-8"),r.claudeMd=!0)}let l=await x(e),d=new Set(Zc()),p=J(l),f=p.filter(h=>!(d.has(h.path)&&Ff.includes(h.category)));return r.rowsDropped=p.length-f.length,r.stylesConsent=el(l),(r.rowsDropped>0||l.vendored!==void 0||l.adhd!==void 0)&&(l.manifest=et(f),delete l.vendored,delete l.adhd,await T(e,l)),r}function Kf(e){let t=[];e.removed.length&&t.push(`Retired the third-party copies an older Vesper placed here (they are pack content now, served from the package): ${e.removed.join(", ")}`),e.claudeMd&&t.push("Removed the retired `vesper:adhd` / `vesper:ponytail` import blocks from CLAUDE.md."),e.stylesConsent&&t.push("Your recorded opt-in to the third-party styles now enables the `styles` pack (`.claude/rules/vesper-styles.md` / `.vesper/instructions/vesper-styles.instructions.md` point at it); `vespercli packs disable styles` turns it off.");let r=e.kept.map(s=>s.files?.length?`${s.path} (${s.files.join(", ")})`:s.path),n=r.length?`Kept \u2014 they hold your edits or your own files, so Vesper could not prove them its own: ${r.join("; ")}. The third-party skills are pack content now (nothing under .claude/skills or .vesper/skills is needed); delete these copies yourself if you do not need them.`:null;return{info:t,warn:n}}var rl=class extends Error{constructor(t){super(t),this.name="HostCleanRefused",this.code="HOST_CLEAN_REFUSED"}};async function nl(e,t){if(t==="copilot"&&!await id(e)&&await PS(e)!==0)throw new rl(`This workspace's Copilot ownership manifest has no granular-provenance record, so it may have been written by an older Vesper whose manifest can claim user files. Run \`${IS}\` to re-record it granularly, then retry.`)}async function PS(e){return J(await x(e)).filter(r=>r.host==="copilot"&&Gt[r.category]?.ownership==="whole-file").length}var IS="vespercli init --host copilot";async function Bf(e,{from:t,to:r,snapshot:n}){await P(ke(e,".vesper"),{recursive:!0});let s={from:t,to:r,snapshot:n,startedAt:new Date().toISOString()};await Ar(ke(e,ir),JSON.stringify(s,null,2))}async function sl(e){await Ds(ke(e,ir),{force:!0});let t=ir.split("/").pop();try{for(let r of await TS(ke(e,".vesper")))r.startsWith(`${t}.`)&&r.endsWith(".tmp")&&await Ds(ke(e,".vesper",r),{force:!0})}catch{}}async function ol(e){let t=await x(e),r=J(t);return{manifest:r,mcpServers:Array.isArray(t.mcp?.servers)?[...t.mcp.servers]:[],mcp:t.mcp?JSON.parse(JSON.stringify(t.mcp)):void 0,settingsEntries:await Et(e),addedAssets:r.filter(n=>n.category==="added-asset").map(n=>n.path),namePrefix:typeof t.namePrefix=="string"?t.namePrefix:"",packs:[...new Set([...await Ht(e,"claude"),...await Ht(e,"copilot"),...el(t)?["styles"]:[]])].sort()}}async function jS(e,t={}){let r=ke(e,".vscode"),n=async i=>{try{return Lt(await tl(i,"utf-8"))}catch{return}},s=ke(r,"settings.json");if((await q(e)).type!==he.WORKSPACE_FILE&&(t.paths?.length??0)+(t.settings?.length??0)>0){let i=await n(s);i&&typeof i=="object"&&Object.keys(i).length===0&&await Ds(s,{force:!0})}if((t.mcpServers?.length??0)>0){let i=Xe(e),a=await n(i);a&&typeof a=="object"&&Object.keys(a).every(l=>l==="servers")&&(!a.servers||Object.keys(a.servers).length===0)&&await Ds(i,{force:!0})}try{await OS(r)}catch{}}async function Vs(e,{purgeProjectAuthored:t=!1}={}){let r=await x(e),n=await Tr(e,"claude"),{removed:s}=await Zn(e);try{let i=await K(e);if(i[V]){let a=new Set(je),c=!1;for(let l of Object.keys(i[V]))a.has(l)||(delete i[V][l],c=!0);c&&await ce(e,i)}}catch{}await Yo(e,"copilot"),await hn(e,"copilot"),await Mf(e,{purgeProjectAuthored:t}),await qn(e,vo,{removeFileIfEmpty:!0}),await jS(e,s);let o=$S(e,".vesperrc");try{n?(r.paths=[],r.readAccessPaths=[],r.addedAt=null,r.workspaceType=null,r.settingsPath=null,r.host==="copilot"&&(r.host="claude"),Array.isArray(r.manifest)&&(r.manifest=r.manifest.filter(i=>!(i&&i.host==="copilot"))),await A(o,JSON.stringify(r,null,2),"utf-8")):await Ds(o,{force:!0})}catch{}}async function Di(e,t,r){let n=new Set(J(await x(e)).map(o=>`${o.host}\0${o.path}`)),s=[];for(let o of t||[])!o||o.host!==r||Gt[o.category]?.ownership!=="whole-file"||Re.has(o.category)||n.has(`${o.host}\0${o.path}`)||await w(ke(e,o.path))&&s.push(o.path);return[...new Set(s)].sort()}async function Cn(e,t,r,n){let o=(await Gn(e,r)).filter(a=>!(t||[]).some(c=>a===c||a.startsWith(`${c}/`))),i=[...new Set([...t||[],...o])].sort();return i.length?(n.warn(`Left in place \u2014 they hold your own files or edits (or were written by a different Vesper version), so Vesper could not prove them its own and no longer tracks them: ${i.join(", ")}. Delete them yourself if you do not need them.`),await Sr(e,r)?n.warn(`This workspace still carries ${r} provisioning markers and may still be detected as ${r}.`):n.warn(`These no longer mark this workspace as ${r}: a later \`vespercli worktree bootstrap\` will not re-provision ${r} because of them.`),i):[]}function RS(e,t,r){return r?t==="copilot"&&e.category==="guard-rule"?!0:e.category==="guard-trigger"?e.path===(t==="claude"?".claude/settings.json":".vscode/tasks.json"):!1:!1}async function Vi(e,t,{keepPaths:r=[],purgeProjectAuthored:n=!1,fullTeardown:s=!1}={}){if(!z.includes(t))throw new Error(`cleanHost: host must be one of ${z.join(", ")} (received "${t}")`);let o=!!n;await nl(e,t),await il(e,t);let i=await ol(e),{pruned:a}=await ld(e,r,{host:t,purgeProjectAuthored:o});t==="claude"?await bn(e,{purgeProjectAuthored:o}):await Vs(e,{purgeProjectAuthored:o}),s&&(await Ls(e,t),t==="copilot"&&await Gr(e));let c=await x(e);c.schemaVersion=ve,c.manifest=J(c).filter(d=>d.host!==t||!o&&Re.has(d.category));for(let d of i.manifest)if(!c.manifest.some(f=>f.path===d.path&&f.host===d.host))if(d.host==="shared"){if(RS(d,t,s))continue;c.manifest.push(d)}else d.host===t&&!o&&Re.has(d.category)&&await w(ke(e,d.path))&&c.manifest.push(d);c.manifest=et(c.manifest),i.mcp!==void 0?c.mcp=i.mcp:delete c.mcp,await T(e,c);let l=await Di(e,i.manifest,t);return{...i,pruned:a,retained:l}}async function il(e,t){if(t!=="claude")return[];if(!await Sr(e,"claude")&&!await no(e,"claude"))return[];let r=new Set(J(await x(e)).filter(a=>a.host==="claude").map(a=>a.path)),n=async(a,c)=>{try{let[l,d]=await Promise.all([tl(ke(e,a)),tl(c)]);return ee(l,d)}catch{return!1}},s=[],o=`.claude/agents/${L}.md`;!r.has(o)&&await n(o,ke(pr,"agents",`${L}.md`))&&s.push(F({path:o,host:"claude",category:"catalog-agent",hash:await ye(ke(e,o))}));for(let a of Qt){let c=`.claude/skills/${a}`;!r.has(c)&&await n(`${c}/SKILL.md`,ke(pr,"skills",a,"SKILL.md"))&&s.push(F({path:c,host:"claude",category:"catalog-skill",hash:null}))}let i=".claude/rules/vesper-orchestrator.md";!r.has(i)&&await n(i,ke(Fe,"vesper-orchestrator.md"))&&s.push(F({path:i,host:"claude",category:"playbook",hash:await ye(ke(e,i))}));for(let a of[".claude/rules/vesper-orchestration.md",".claude/rules/vesper-context.md"])!r.has(a)&&await w(ke(e,a))&&s.push(F({path:a,host:"claude",category:"per-project-authored",hash:null}));for(let a of await Cd(e,"claude"))r.has(a.path)||s.push(a);for(let a of await Ip(e))r.has(a.path)||s.push(a);return s.length&&await W(e,s),s.map(a=>a.path)}function NS(e){let t=/^\.claude\/agents\/([^/]+)\.md$/.exec(e);return t?{type:"agents",name:t[1]}:(t=/^\.claude\/commands\/([^/]+)\.md$/.exec(e),t?{type:"prompts",name:t[1]}:(t=/^\.claude\/skills\/([^/]+)$/.exec(e),t?{type:"skills",name:t[1]}:null))}function LS(e){let t=String(e).replace(/\\/g,"/"),r=/\/assets\/copilot\/instructions-extended\/([^/]+)\/?$/.exec(t);return r?{type:"instructions",name:r[1]}:(r=/\/assets\/(?:copilot\/)?(agents|prompts)\/([^/]+)\/?$/.exec(t),r?{type:r[1],name:r[2].replace(/\.(agent|prompt)\.md$/,"")}:null)}async function zf(e,t,r){let n={mcpServers:{added:[],skipped:[]},assets:{added:[],kept:[],skipped:[]},packs:{added:[],kept:[],skipped:[]}};for(let l of r.packs||[])try{let{enabled:d}=await ar(e,t,l);(d?n.packs.added:n.packs.kept).push(l)}catch{n.packs.skipped.push(l)}for(let l of r.mcpServers||[])if(!me.includes(l))try{((t==="claude"?await kn(e,l):await sr(e,l)).added?n.mcpServers.added:n.mcpServers.skipped).push(l)}catch{n.mcpServers.skipped.push(l)}let s=await on(e)||"",o=r.namePrefix??s,i=l=>o&&l.startsWith(o)?l.slice(o.length):l,a=[...(r.addedAssets||[]).map(NS).filter(Boolean).map(l=>({...l,name:i(l.name),source:"claude-record"})),...(r.settingsEntries||[]).map(LS).filter(Boolean).map(l=>({...l,source:"copilot-entry"}))],c=new Set;for(let{type:l,name:d,source:p}of a){let f=`${l}/${d}`;if(!c.has(f)){c.add(f);try{if(t==="copilot"){if(l==="instructions"){let{added:m}=await Fi(e,d);(m?n.assets.added:n.assets.kept).push(f);continue}n.assets.kept.push(f)}else if(p==="copilot-entry")n.assets.kept.push(f);else{let m=l==="prompts"?"commands":l,h=MS(m,d,s);if(await w(ke(e,h))){await W(e,[F({path:h,host:"claude",category:"added-asset",hash:null})]),n.assets.kept.push(f);continue}await wi(m,d,{workspaceRoot:e,namePrefix:s}),n.assets.added.push(f)}}catch{n.assets.skipped.push(f)}}}return n}function MS(e,t,r=""){if(e==="skills")return`.claude/skills/${t}`;let n=r&&!t.startsWith(r)?`${r}${t}`:t;return`.claude/${e}/${n}.md`}be();fe();Te();H();be();Wr();ut();gt();import{lstat as FS,readFile as Yf,realpath as GS,rm as Jf,stat as DS}from"node:fs/promises";import{join as qf,resolve as VS}from"node:path";function HS(e){return e.split(`
|
|
151
|
-
`).every(t=>{let r=t.trim();return r===""||r.startsWith("#")||/^exit\s+0\s*;?$/.test(r)})}async function Xf(e){try{return await GS(e)}catch{return VS(e)}}async function US(e){try{return(await DS(e)).isDirectory()}catch{return!1}}async function WS(e,t,{gitVersion:r,resolveHooksDir:n=nr}={}){let s={...Er(process.env),...jt},o=await Ro(e,{env:s,gitArgs:en,gitVersion:r});if(o===null)return[{worktree:"(unknown)",host:null,why:"git worktree list failed"}];let i=await it(t.dir),a=await Xf(t.top??e),c=[];for(let l of jo(o.out)){if(l.bare||!l.worktree||await Xf(l.worktree)===a)continue;if(l.prunable!==void 0){c.push({worktree:l.worktree,host:null,why:"prunable"});continue}if(l.locked!==void 0){c.push({worktree:l.worktree,host:null,why:"locked"});continue}if(!await US(l.worktree)){c.push({worktree:l.worktree,host:null,why:"missing"});continue}let p=await n(l.worktree,{env:s,gitArgs:en});if(!p.dir&&["machine-wide","not-a-directory","husky-v9"].includes(p.reason)||p.dir&&!p.default&&await it(p.dir)!==i)continue;if(!p.dir){c.push({worktree:l.worktree,host:null,why:`hooks path unknown (${p.reason})`});continue}let f;try{f=await B(l.worktree,{env:s,gitArgs:en})}catch{f={gitError:"unknown"}}if(f.gitError){c.push({worktree:l.worktree,host:null,why:`git error (${f.gitError})`});continue}(f.host||f.ambiguous)&&c.push({worktree:l.worktree,host:f.host??"both",why:"provisioned"})}return c}async function al(e,{gitVersion:t,resolveHooksDir:r}={}){let n=Object.fromEntries(at.map(c=>[c,null])),s=await nr(e);if(!s.dir)return{action:"none",hooks:n,reason:s.reason};let o=[];for(let c of at){let l=qf(s.dir,c);try{(await Yf(l)).toString("latin1").includes(st)&&o.push(l)}catch{}}if(!o.length)return{action:"none",hooks:n};let i=await B(e);if(i.host)return{action:"kept",hooks:n,paths:o,keptFor:[{worktree:e,host:i.host,why:"this checkout still carries Vesper provisioning"}]};let a=await WS(e,s,{gitVersion:t,...r?{resolveHooksDir:r}:{}});if(a.length)return{action:"kept",hooks:n,paths:o,keptFor:a};for(let c of at){let l=qf(s.dir,c),d=await tn(l);if(!d.path)continue;let p=await it(d.path);if(!wt(p,s.roots)||await tr(p,s))continue;let f;try{f=await Yf(d.path)}catch{continue}let m=f.toString("latin1");if(!m.includes(st))continue;let h=wr(Rd(m)??m);if(h!==null)if(HS(h)){await Jf(d.path,{force:!0});try{(await FS(l)).isSymbolicLink()&&l!==d.path&&await Jf(l,{force:!0})}catch{}n[c]="file"}else await yt(d.path,Buffer.from(h,"latin1")),n[c]="region"}return{action:Object.values(n).some(Boolean)?"removed":"none",hooks:n}}function cl(e){if(e.action==="removed")return`Removed Vesper's git hooks (${Object.entries(e.hooks).filter(([,t])=>t).map(([t])=>t).join(", ")}).`;if(e.action==="kept"){let t=e.keptFor.map(a=>`${a.worktree} (${a.host??`unknown: ${a.why}`})`).join(", "),r=e.paths?.length?` in ${e.paths.join(", ")}`:"",n=e.keptFor.filter(a=>a.why==="missing"||a.why==="prunable").map(a=>a.worktree),s=e.keptFor.filter(a=>a.why==="locked").map(a=>a.worktree),o=[n.length?` ${n.join(", ")} ${n.length>1?"are":"is"} gone: \`git worktree prune\` drops ${n.length>1?"those entries":"that entry"}, then reset again.`:"",s.length?` ${s.join(", ")} ${s.length>1?"are":"is"} locked: if ${s.length>1?"they are":"it is"} gone, \`git worktree unlock <path>\` and \`git worktree prune\`, then reset again.`:""].join(""),i=e.keptFor.every(a=>a.worktree===e.keptFor[0].worktree&&a.why==="this checkout still carries Vesper provisioning")?"this checkout still carries Vesper provisioning":`worktrees sharing these hooks may still use Vesper \u2014 ${t}`;return`Kept Vesper's git-hook block${r}: ${i}.${o} To remove it everywhere, reset those worktrees too, or run \`git config vesper.hooks false\` (the block then does nothing) and delete it from those files.`}return null}var Qf=".claude/rules/vesper-orchestrator.md";async function ul(e,t,{purge:r=!1}={}){if(await Tr(e,t)||await Sr(e,t)||await no(e,t))return!0;if(r){if((await ne(e)).some(s=>s.host===t&&Re.has(s.category)))return!0;if(t==="copilot"){for(let s of[".vesper/instructions/vesper-orchestration.instructions.md",".vesper/instructions/vesper-context.instructions.md",".vesper/context"])if(await w($n(e,s)))return!0}}return!1}async function Hi(e){try{let t=await al(e),r=cl(t);r&&(t.action==="kept"?u.warn:u.info)(r)}catch(t){u.warn(`Vesper's git-hook block was left in place (${t?.message??t}).`)}}async function eh(e,t){await Ls(e,t),await Ls(e,Kc(t)),await Gr(e)==="kept"&&u.warn(xn());try{let r=await al(e),n=cl(r);n&&(r.action==="kept"?u.warn:u.info)(n)}catch(r){u.warn(`Vesper's git-hook block was left in place (${r?.message??r}).`)}await Oa(e)}async function BS(e={}){let t=$n(e.path||process.cwd()),r=!!e.purgeKnowledge;if(!await ul(t,"claude",{purge:r})){u.warn("Claude Code target is not initialized in this workspace."),await Hi(t);return}if(!e.yes&&!await ll({message:r?"Remove the Claude Code target INCLUDING the Team Roster and project whitepaper? (this deletes accumulated project knowledge)":"Remove the Claude Code target from this project? (the Team Roster and project whitepaper are KEPT \u2014 pass --purge-knowledge to remove them too)",default:!1})){u.info("Reset cancelled.");return}await il(t,"claude");let n=await ne(t),s=await w($n(t,Qf)),{kept:o=[],knowledgeKept:i=[]}=await bn(t,{purgeProjectAuthored:r})||{};await eh(t,"claude");let a=await Di(t,n,"claude"),c=s&&!await w($n(t,Qf));console.log(),u.success("Claude Code target reset complete."),u.info(`Removed (manifest-scoped; only files Vesper could prove it wrote): recorded catalog entries, the pack pointer rules, ${c?"the orchestrator playbook, ":""}guard triggers, CLAUDE.md guard block, .mcp.json entry, the OpenCode overlay (opencode.json keys, .opencode/), .vesperrc.claude.`),o.length&&u.warn(`Kept \u2014 they hold your edits, so Vesper could not prove them its own: ${o.join(", ")}. Delete them yourself if you do not need them.`),u.info(r?"Removed (--purge-knowledge): the Team Roster, project whitepaper, on-demand context tier, and .vesper/gates.json.":"Kept: the Team Roster (.claude/rules/vesper-orchestration.md), project whitepaper (vesper-context.md), and on-demand context tier \u2014 they belong to this project."),r&&i.length&&u.warn(`Kept despite --purge-knowledge \u2014 their content exists nowhere else (no identical copy in the Copilot brain): ${i.join(", ")}.`),u.info("Left intact: agent-authored skills in .claude/skills/ (never Vesper-recorded)."),await Cn(t,a,"claude",u)}async function zS(e={}){let t=$n(e.path||process.cwd()),r=!!e.purgeKnowledge;if(!await ul(t,"copilot",{purge:r})){u.warn("Vesper is not initialized in this workspace."),await Hi(t);return}let n=await St(t),s=YS(n);if(!e.yes&&!await ll({message:r?`Remove all Vesper assets (${s.join(", ")}) INCLUDING the Team Roster and project whitepaper?`:`Remove all Vesper assets (${s.join(", ")})? (the Team Roster and project whitepaper are KEPT \u2014 pass --purge-knowledge to remove them too)`,default:!1})){u.info("Reset cancelled.");return}let o=await x(t),i=await q(t),a=await Tr(t,"claude"),c=await ne(t);await Vs(t,{purgeProjectAuthored:r}),await eh(t,"copilot");let l=await Di(t,c,"copilot");a&&u.info("Claude Code target detected \u2014 kept its record in .vesperrc"),console.log(),u.success("Vesper reset complete."),o.workspaceType===he.WORKSPACE_FILE||i.type===he.WORKSPACE_FILE?u.info(`Cleaned: ${KS(i.settingsPath)}`):u.info("Cleaned: .vscode/settings.json"),u.info(r?"Removed (--purge-knowledge): the Team Roster, project whitepaper, on-demand context tier, and .vesper/gates.json.":"Kept: the Team Roster and project whitepaper \u2014 they belong to this project."),u.info("Reload VS Code to apply changes"),await Cn(t,l,"copilot",u)}function YS(e){let t=new Set;for(let r of e)r.includes("/agents")&&t.add("Agents"),r.includes("/instructions")&&t.add("Instructions"),r.includes("/prompts")&&t.add("Prompts"),r.includes("/skills")&&t.add("Skills");return Array.from(t)}async function Zf(e,t,r){return t==="claude"?BS({...r,path:e}):zS({...r,path:e})}async function JS(e,t,r){let n=!!r.purgeKnowledge;if(!await ul(e,t,{purge:n})){u.info(`No ${t} artifacts found to clean \u2014 nothing to do.`);return}if(!r.yes&&!await ll({message:n?`Remove stray ${t} artifacts INCLUDING its Team Roster and project whitepaper? (the active host and all shared state are kept)`:`Remove stray ${t} artifacts from this workspace? (the active host and all shared state are kept)`,default:!1})){u.info("Reset cancelled.");return}let{retained:s}=await Vi(e,t,{fullTeardown:!1,purgeProjectAuthored:n});console.log(),u.success(`Foreign ${t} residue removed.`),await Cn(e,s,t,u),u.info(n?`Removed (--purge-knowledge): ${t}'s Team Roster, project whitepaper and on-demand context tier.`:`Kept: ${t}'s Team Roster + project whitepaper (pass --purge-knowledge to remove them).`),u.info("Kept: the active host, the cross-host guard trigger, and all shared state (.vesper/.tracking/, memory, history).")}async function th(e={}){try{let t=$n(e.path||process.cwd());await w(t)||(u.error(`Directory not found: ${u.formatPath(t)}`),process.exit(1));let r=e.host;if(!r&&e.target){let i=String(e.target).toLowerCase();z.includes(i)||(u.error(`Unknown target: ${e.target}. Valid: ${z.join(", ")}.`),process.exit(1)),u.warn("`--target` is deprecated; use `--host` instead. Mapping to `--host "+i+"`."),r=i}let n=await ge(t),o=await sn(t)??(n.length===1?n[0]:null);if(!r){if(n.length>1&&(u.error(Ho),process.exit(1)),!o){let i=await Or(t);if(i){u.warn(`Nothing is provisioned in this checkout; the local record names ${i} \u2014 \`vespercli reset --host ${i}\` removes that host's local files.`),await Hi(t);return}u.warn("Vesper is not initialized in this workspace."),await Hi(t);return}return await Zf(t,o,e)}return o&&o!==r?await JS(t,r,e):await Zf(t,r,e)}catch(t){if(t.name==="ExitPromptError"){console.log(),u.info("Reset cancelled.");return}t.name==="HostCleanRefused"&&(u.error(t.message),process.exit(1)),u.error(`Reset failed: ${t.message}`),process.exit(1)}}be();fe();U();import{lstat as Ui,readFile as Se,readdir as Bi,readlink as Hs,rmdir as oh}from"node:fs/promises";import{createHash as qS}from"node:crypto";import{basename as ih,dirname as dl,isAbsolute as Wi,join as _,relative as pl,sep as Us}from"node:path";import{homedir as Ws}from"node:os";te();be();Be();bs();$r();H();xe();fe();ot();un();var XS=Object.freeze([".vesper/.tracking",".vesper/history.md",".vesper/history-archive",".vesper/memory.jsonl",".vesper/index.db",".vesper/index.db-wal",".vesper/index.db-shm",".vesper/indexing-status.json",Fr]);function Ki(e){return XS.some(t=>e===t||e.startsWith(`${t}/`))}var ah=Object.freeze([".vesperrc",".vesper/tracking.json","CLAUDE.md",".claude/settings.json",".claude/settings.local.json",".mcp.json",".vscode/settings.json",".vscode/tasks.json",".vscode/mcp.json",".gitignore",".gitattributes"]),ch=Object.freeze([".claude",".vscode",".vesper",".github",".opencode"]);async function QS(e,t){let r,n;try{[r,n]=await Promise.all([Ui(e),Ui(t)])}catch{return!1}if(r.isSymbolicLink()||n.isSymbolicLink())return r.isSymbolicLink()&&n.isSymbolicLink()&&await Hs(e)===await Hs(t);if(r.isFile()&&n.isFile())return(await Se(e)).equals(await Se(t));if(!r.isDirectory()||!n.isDirectory())return!1;let[s,o]=await Promise.all([ct(e),ct(t)]),i=(a,c)=>a.length===c.length&&a.every((l,d)=>l===c[d]);if(!i(s.files,o.files)||!i(s.others,o.others)||!i([...s.dirs].sort(),[...o.dirs].sort()))return!1;for(let a of s.files)if(!(await Se(_(e,a))).equals(await Se(_(t,a))))return!1;for(let a of s.others)try{if(await Hs(_(e,a))!==await Hs(_(t,a)))return!1}catch{return!1}return!0}async function rh(e){let t=_(e,Fr);await P(t,{recursive:!0});let r=_(t,".gitignore"),n=null;try{n=await Se(r,"utf-8")}catch{n=null}n!==`*
|
|
150
|
+
`}async function IS(e){let t=Or(e);if(!t)return null;try{let{frontmatter:r}=ht(await tl(Ui(t.dir,"SKILL.md"),"utf-8")),n=r?Vr(r,"description"):null;return n&&String(n).trim()||null}catch{return null}}async function jS(e){if(e===".claude/rules/i-have-adhd.md")return[qf];if(e===".claude/rules/ponytail.md")return[Xf];for(let t of $r)if(e===je(t))return Yf.includes(t)?[PS(t)]:[zf(t,await IS(t)),zf(t,null)];return[]}async function Qf(e,{backup:t}={}){let r={removed:[],kept:[],claudeMd:!1,stylesConsent:!1,rowsDropped:0},n=new Set,s=async h=>{typeof t!="function"||n.has(h)||(n.add(h),await t(h))},o=await x(e),i=J(o),a=h=>i.find(g=>g.path===h&&Bf.includes(g.category))||null;for(let h of $r){let g=Or(h),y=g?await Ho(g.dir):{};for(let k of[`.claude/skills/${h}`,`.vesper/skills/${h}`]){let v=Ui(e,k);if(!await w(v))continue;let S=a(k),C=S?.placedFiles??S?.syncedFiles,N=C&&typeof C=="object"&&Object.keys(C).length?{...C}:void 0,E={sourceFiles:y,...N?{sourceHashes:N}:{},sourceMatch:(X,He)=>gc(He,`${k}/${X}`),anchor:"SKILL.md"},b=await Gt(v,E);if(b.status!=="classified"||b.proven.length===0){(b.status==="anchor-unproven"||b.status==="classified"&&b.kept.length)&&r.kept.push({path:k,files:b.kept});continue}await s(k);let F=await cs(v,E);F.status==="removed"?r.removed.push(k):F.status!=="absent"&&r.kept.push({path:k,files:F.kept})}}for(let h of Jf()){let g=Ui(e,h);if(!await w(g))continue;let y=null;try{y=await tl(g)}catch{y=null}if(y&&gc(y,h)){await s(h),await $S(g,{force:!0}),r.removed.push(h);continue}let k=a(h)??{path:h,category:"vendored-activation",hash:null},v=await jS(h);if(!await ls(g,k,{expected:v})){r.kept.push({path:h});continue}await s(h);let S=await le(g,k,{expected:v});S==="removed"?r.removed.push(h):S!=="absent"&&r.kept.push({path:h})}let c=Ui(e,"CLAUDE.md");if(await w(c)){let h=await tl(c,"utf-8"),g=Fc(h);ee(g,h)||(await A(c,g,"utf-8"),r.claudeMd=!0)}let l=await x(e),d=new Set(rl()),p=J(l),f=p.filter(h=>!(d.has(h.path)&&Bf.includes(h.category)));return r.rowsDropped=p.length-f.length,r.stylesConsent=nl(l),(r.rowsDropped>0||l.vendored!==void 0||l.adhd!==void 0)&&(l.manifest=tt(f),delete l.vendored,delete l.adhd,await T(e,l)),r}function Zf(e){let t=[];e.removed.length&&t.push(`Retired the third-party copies an older Vesper placed here (they are pack content now, served from the package): ${e.removed.join(", ")}`),e.claudeMd&&t.push("Removed the retired `vesper:adhd` / `vesper:ponytail` import blocks from CLAUDE.md."),e.stylesConsent&&t.push("Your recorded opt-in to the third-party styles now enables the `styles` pack (`.claude/rules/vesper-styles.md` / `.vesper/instructions/vesper-styles.instructions.md` point at it); `vespercli packs disable styles` turns it off.");let r=e.kept.map(s=>s.files?.length?`${s.path} (${s.files.join(", ")})`:s.path),n=r.length?`Kept \u2014 they hold your edits or your own files, so Vesper could not prove them its own: ${r.join("; ")}. The third-party skills are pack content now (nothing under .claude/skills or .vesper/skills is needed); delete these copies yourself if you do not need them.`:null;return{info:t,warn:n}}var ol=class extends Error{constructor(t){super(t),this.name="HostCleanRefused",this.code="HOST_CLEAN_REFUSED"}};async function il(e,t){if(t==="copilot"&&!await ud(e)&&await MS(e)!==0)throw new ol(`This workspace's Copilot ownership manifest has no granular-provenance record, so it may have been written by an older Vesper whose manifest can claim user files. Run \`${GS}\` to re-record it granularly, then retry.`)}async function MS(e){return J(await x(e)).filter(r=>r.host==="copilot"&&Dt[r.category]?.ownership==="whole-file").length}var GS="vespercli init --host copilot";async function eh(e,{from:t,to:r,snapshot:n}){await P(Ee(e,".vesper"),{recursive:!0});let s={from:t,to:r,snapshot:n,startedAt:new Date().toISOString()};await Cr(Ee(e,cr),JSON.stringify(s,null,2))}async function al(e){await Us(Ee(e,cr),{force:!0});let t=cr.split("/").pop();try{for(let r of await LS(Ee(e,".vesper")))r.startsWith(`${t}.`)&&r.endsWith(".tmp")&&await Us(Ee(e,".vesper",r),{force:!0})}catch{}}async function cl(e){let t=await x(e),r=J(t);return{manifest:r,mcpServers:Array.isArray(t.mcp?.servers)?[...t.mcp.servers]:[],mcp:t.mcp?JSON.parse(JSON.stringify(t.mcp)):void 0,settingsEntries:await At(e),addedAssets:r.filter(n=>n.category==="added-asset").map(n=>n.path),namePrefix:typeof t.namePrefix=="string"?t.namePrefix:"",packs:[...new Set([...await Wt(e,"claude"),...await Wt(e,"copilot"),...nl(t)?["styles"]:[]])].sort()}}async function FS(e,t={}){let r=Ee(e,".vscode"),n=async i=>{try{return Mt(await sl(i,"utf-8"))}catch{return}},s=Ee(r,"settings.json");if((await q(e)).type!==he.WORKSPACE_FILE&&(t.paths?.length??0)+(t.settings?.length??0)>0){let i=await n(s);i&&typeof i=="object"&&Object.keys(i).length===0&&await Us(s,{force:!0})}if((t.mcpServers?.length??0)>0){let i=Qe(e),a=await n(i);a&&typeof a=="object"&&Object.keys(a).every(l=>l==="servers")&&(!a.servers||Object.keys(a.servers).length===0)&&await Us(i,{force:!0})}try{await NS(r)}catch{}}async function Ws(e,{purgeProjectAuthored:t=!1}={}){let r=await x(e),n=await Ir(e,"claude"),{removed:s}=await ts(e);try{let i=await K(e);if(i[V]){let a=new Set(Ne),c=!1;for(let l of Object.keys(i[V]))a.has(l)||(delete i[V][l],c=!0);c&&await ce(e,i)}}catch{}await Xo(e,"copilot"),await mn(e,"copilot"),await Kf(e,{purgeProjectAuthored:t}),await Qn(e,Eo,{removeFileIfEmpty:!0}),await FS(e,s);let o=RS(e,".vesperrc");try{n?(r.paths=[],r.readAccessPaths=[],r.addedAt=null,r.workspaceType=null,r.settingsPath=null,r.host==="copilot"&&(r.host="claude"),Array.isArray(r.manifest)&&(r.manifest=r.manifest.filter(i=>!(i&&i.host==="copilot"))),await A(o,JSON.stringify(r,null,2),"utf-8")):await Us(o,{force:!0})}catch{}}async function Wi(e,t,r){let n=new Set(J(await x(e)).map(o=>`${o.host}\0${o.path}`)),s=[];for(let o of t||[])!o||o.host!==r||Dt[o.category]?.ownership!=="whole-file"||Le.has(o.category)||n.has(`${o.host}\0${o.path}`)||await w(Ee(e,o.path))&&s.push(o.path);return[...new Set(s)].sort()}async function $n(e,t,r,n){let o=(await Vn(e,r)).filter(a=>!(t||[]).some(c=>a===c||a.startsWith(`${c}/`))),i=[...new Set([...t||[],...o])].sort();return i.length?(n.warn(`Left in place \u2014 they hold your own files or edits (or were written by a different Vesper version), so Vesper could not prove them its own and no longer tracks them: ${i.join(", ")}. Delete them yourself if you do not need them.`),await br(e,r)?n.warn(`This workspace still carries ${r} provisioning markers and may still be detected as ${r}.`):n.warn(`These no longer mark this workspace as ${r}: a later \`vespercli worktree bootstrap\` will not re-provision ${r} because of them.`),i):[]}function DS(e,t,r){return r?t==="copilot"&&e.category==="guard-rule"?!0:e.category==="guard-trigger"?e.path===(t==="claude"?".claude/settings.json":".vscode/tasks.json"):!1:!1}async function Ki(e,t,{keepPaths:r=[],purgeProjectAuthored:n=!1,fullTeardown:s=!1}={}){if(!z.includes(t))throw new Error(`cleanHost: host must be one of ${z.join(", ")} (received "${t}")`);let o=!!n;await il(e,t),await ll(e,t);let i=await cl(e),{pruned:a}=await fd(e,r,{host:t,purgeProjectAuthored:o});t==="claude"?await xn(e,{purgeProjectAuthored:o}):await Ws(e,{purgeProjectAuthored:o}),s&&(await Fs(e,t),t==="copilot"&&await Dr(e));let c=await x(e);c.schemaVersion=ve,c.manifest=J(c).filter(d=>d.host!==t||!o&&Le.has(d.category));for(let d of i.manifest)if(!c.manifest.some(f=>f.path===d.path&&f.host===d.host))if(d.host==="shared"){if(DS(d,t,s))continue;c.manifest.push(d)}else d.host===t&&!o&&Le.has(d.category)&&await w(Ee(e,d.path))&&c.manifest.push(d);c.manifest=tt(c.manifest),i.mcp!==void 0?c.mcp=i.mcp:delete c.mcp,await T(e,c);let l=await Wi(e,i.manifest,t);return{...i,pruned:a,retained:l}}async function ll(e,t){if(t!=="claude")return[];if(!await br(e,"claude")&&!await io(e,"claude"))return[];let r=new Set(J(await x(e)).filter(a=>a.host==="claude").map(a=>a.path)),n=async(a,c)=>{try{let[l,d]=await Promise.all([sl(Ee(e,a)),sl(c)]);return ee(l,d)}catch{return!1}},s=[],o=`.claude/agents/${L}.md`;!r.has(o)&&await n(o,Ee(hr,"agents",`${L}.md`))&&s.push(G({path:o,host:"claude",category:"catalog-agent",hash:await ye(Ee(e,o))}));for(let a of er){let c=`.claude/skills/${a}`;!r.has(c)&&await n(`${c}/SKILL.md`,Ee(hr,"skills",a,"SKILL.md"))&&s.push(G({path:c,host:"claude",category:"catalog-skill",hash:null}))}let i=".claude/rules/vesper-orchestrator.md";!r.has(i)&&await n(i,Ee(De,"vesper-orchestrator.md"))&&s.push(G({path:i,host:"claude",category:"playbook",hash:await ye(Ee(e,i))}));for(let a of[".claude/rules/vesper-orchestration.md",".claude/rules/vesper-context.md"])!r.has(a)&&await w(Ee(e,a))&&s.push(G({path:a,host:"claude",category:"per-project-authored",hash:null}));for(let a of await Pd(e,"claude"))r.has(a.path)||s.push(a);for(let a of await Dp(e))r.has(a.path)||s.push(a);return s.length&&await W(e,s),s.map(a=>a.path)}function VS(e){let t=/^\.claude\/agents\/([^/]+)\.md$/.exec(e);return t?{type:"agents",name:t[1]}:(t=/^\.claude\/commands\/([^/]+)\.md$/.exec(e),t?{type:"prompts",name:t[1]}:(t=/^\.claude\/skills\/([^/]+)$/.exec(e),t?{type:"skills",name:t[1]}:null))}function HS(e){let t=String(e).replace(/\\/g,"/"),r=/\/assets\/copilot\/instructions-extended\/([^/]+)\/?$/.exec(t);return r?{type:"instructions",name:r[1]}:(r=/\/assets\/(?:copilot\/)?(agents|prompts)\/([^/]+)\/?$/.exec(t),r?{type:r[1],name:r[2].replace(/\.(agent|prompt)\.md$/,"")}:null)}async function th(e,t,r){let n={mcpServers:{added:[],skipped:[]},assets:{added:[],kept:[],skipped:[]},packs:{added:[],kept:[],skipped:[]}};for(let l of r.packs||[])try{let{enabled:d}=await lr(e,t,l);(d?n.packs.added:n.packs.kept).push(l)}catch{n.packs.skipped.push(l)}for(let l of r.mcpServers||[])if(!me.includes(l))try{((t==="claude"?await Sn(e,l):await ir(e,l)).added?n.mcpServers.added:n.mcpServers.skipped).push(l)}catch{n.mcpServers.skipped.push(l)}let s=await an(e)||"",o=r.namePrefix??s,i=l=>o&&l.startsWith(o)?l.slice(o.length):l,a=[...(r.addedAssets||[]).map(VS).filter(Boolean).map(l=>({...l,name:i(l.name),source:"claude-record"})),...(r.settingsEntries||[]).map(HS).filter(Boolean).map(l=>({...l,source:"copilot-entry"}))],c=new Set;for(let{type:l,name:d,source:p}of a){let f=`${l}/${d}`;if(!c.has(f)){c.add(f);try{if(t==="copilot"){if(l==="instructions"){let{added:m}=await Hi(e,d);(m?n.assets.added:n.assets.kept).push(f);continue}n.assets.kept.push(f)}else if(p==="copilot-entry")n.assets.kept.push(f);else{let m=l==="prompts"?"commands":l,h=US(m,d,s);if(await w(Ee(e,h))){await W(e,[G({path:h,host:"claude",category:"added-asset",hash:null})]),n.assets.kept.push(f);continue}await Ei(m,d,{workspaceRoot:e,namePrefix:s}),n.assets.added.push(f)}}catch{n.assets.skipped.push(f)}}}return n}function US(e,t,r=""){if(e==="skills")return`.claude/skills/${t}`;let n=r&&!t.startsWith(r)?`${r}${t}`:t;return`.claude/${e}/${n}.md`}Ae();fe();Ie();H();Ae();Kr();ft();vt();import{lstat as WS,readFile as rh,realpath as KS,rm as nh,stat as BS}from"node:fs/promises";import{join as sh,resolve as zS}from"node:path";function YS(e){return e.split(`
|
|
151
|
+
`).every(t=>{let r=t.trim();return r===""||r.startsWith("#")||/^exit\s+0\s*;?$/.test(r)})}async function oh(e){try{return await KS(e)}catch{return zS(e)}}async function JS(e){try{return(await BS(e)).isDirectory()}catch{return!1}}async function qS(e,t,{gitVersion:r,resolveHooksDir:n=or}={}){let s={...xr(process.env),...Rt},o=await Mo(e,{env:s,gitArgs:tn,gitVersion:r});if(o===null)return[{worktree:"(unknown)",host:null,why:"git worktree list failed"}];let i=await ct(t.dir),a=await oh(t.top??e),c=[];for(let l of Lo(o.out)){if(l.bare||!l.worktree||await oh(l.worktree)===a)continue;if(l.prunable!==void 0){c.push({worktree:l.worktree,host:null,why:"prunable"});continue}if(l.locked!==void 0){c.push({worktree:l.worktree,host:null,why:"locked"});continue}if(!await JS(l.worktree)){c.push({worktree:l.worktree,host:null,why:"missing"});continue}let p=await n(l.worktree,{env:s,gitArgs:tn});if(!p.dir&&["machine-wide","not-a-directory","husky-v9"].includes(p.reason)||p.dir&&!p.default&&await ct(p.dir)!==i)continue;if(!p.dir){c.push({worktree:l.worktree,host:null,why:`hooks path unknown (${p.reason})`});continue}let f;try{f=await B(l.worktree,{env:s,gitArgs:tn})}catch{f={gitError:"unknown"}}if(f.gitError){c.push({worktree:l.worktree,host:null,why:`git error (${f.gitError})`});continue}(f.host||f.ambiguous)&&c.push({worktree:l.worktree,host:f.host??"both",why:"provisioned"})}return c}async function ul(e,{gitVersion:t,resolveHooksDir:r}={}){let n=Object.fromEntries(lt.map(c=>[c,null])),s=await or(e);if(!s.dir)return{action:"none",hooks:n,reason:s.reason};let o=[];for(let c of lt){let l=sh(s.dir,c);try{(await rh(l)).toString("latin1").includes(it)&&o.push(l)}catch{}}if(!o.length)return{action:"none",hooks:n};let i=await B(e);if(i.host)return{action:"kept",hooks:n,paths:o,keptFor:[{worktree:e,host:i.host,why:"this checkout still carries Vesper provisioning"}]};let a=await qS(e,s,{gitVersion:t,...r?{resolveHooksDir:r}:{}});if(a.length)return{action:"kept",hooks:n,paths:o,keptFor:a};for(let c of lt){let l=sh(s.dir,c),d=await rn(l);if(!d.path)continue;let p=await ct(d.path);if(!St(p,s.roots)||await nr(p,s))continue;let f;try{f=await rh(d.path)}catch{continue}let m=f.toString("latin1");if(!m.includes(it))continue;let h=kr(Fd(m)??m);if(h!==null)if(YS(h)){await nh(d.path,{force:!0});try{(await WS(l)).isSymbolicLink()&&l!==d.path&&await nh(l,{force:!0})}catch{}n[c]="file"}else await kt(d.path,Buffer.from(h,"latin1")),n[c]="region"}return{action:Object.values(n).some(Boolean)?"removed":"none",hooks:n}}function dl(e){if(e.action==="removed")return`Removed Vesper's git hooks (${Object.entries(e.hooks).filter(([,t])=>t).map(([t])=>t).join(", ")}).`;if(e.action==="kept"){let t=e.keptFor.map(a=>`${a.worktree} (${a.host??`unknown: ${a.why}`})`).join(", "),r=e.paths?.length?` in ${e.paths.join(", ")}`:"",n=e.keptFor.filter(a=>a.why==="missing"||a.why==="prunable").map(a=>a.worktree),s=e.keptFor.filter(a=>a.why==="locked").map(a=>a.worktree),o=[n.length?` ${n.join(", ")} ${n.length>1?"are":"is"} gone: \`git worktree prune\` drops ${n.length>1?"those entries":"that entry"}, then reset again.`:"",s.length?` ${s.join(", ")} ${s.length>1?"are":"is"} locked: if ${s.length>1?"they are":"it is"} gone, \`git worktree unlock <path>\` and \`git worktree prune\`, then reset again.`:""].join(""),i=e.keptFor.every(a=>a.worktree===e.keptFor[0].worktree&&a.why==="this checkout still carries Vesper provisioning")?"this checkout still carries Vesper provisioning":`worktrees sharing these hooks may still use Vesper \u2014 ${t}`;return`Kept Vesper's git-hook block${r}: ${i}.${o} To remove it everywhere, reset those worktrees too, or run \`git config vesper.hooks false\` (the block then does nothing) and delete it from those files.`}return null}var ih=".claude/rules/vesper-orchestrator.md";async function fl(e,t,{purge:r=!1}={}){if(await Ir(e,t)||await br(e,t)||await io(e,t))return!0;if(r){if((await ne(e)).some(s=>s.host===t&&Le.has(s.category)))return!0;if(t==="copilot"){for(let s of[".vesper/instructions/vesper-orchestration.instructions.md",".vesper/instructions/vesper-context.instructions.md",".vesper/context"])if(await w(On(e,s)))return!0}}return!1}async function Bi(e){try{let t=await ul(e),r=dl(t);r&&(t.action==="kept"?u.warn:u.info)(r)}catch(t){u.warn(`Vesper's git-hook block was left in place (${t?.message??t}).`)}}async function ch(e,t){await Fs(e,t),await Fs(e,Yc(t)),await Dr(e)==="kept"&&u.warn(An());try{let r=await ul(e),n=dl(r);n&&(r.action==="kept"?u.warn:u.info)(n)}catch(r){u.warn(`Vesper's git-hook block was left in place (${r?.message??r}).`)}await Ia(e)}async function QS(e={}){let t=On(e.path||process.cwd()),r=!!e.purgeKnowledge;if(!await fl(t,"claude",{purge:r})){u.warn("Claude Code target is not initialized in this workspace."),await Bi(t);return}if(!e.yes&&!await pl({message:r?"Remove the Claude Code target INCLUDING the Team Roster and project whitepaper? (this deletes accumulated project knowledge)":"Remove the Claude Code target from this project? (the Team Roster and project whitepaper are KEPT \u2014 pass --purge-knowledge to remove them too)",default:!1})){u.info("Reset cancelled.");return}await ll(t,"claude");let n=await ne(t),s=await w(On(t,ih)),{kept:o=[],knowledgeKept:i=[]}=await xn(t,{purgeProjectAuthored:r})||{};await ch(t,"claude");let a=await Wi(t,n,"claude"),c=s&&!await w(On(t,ih));console.log(),u.success("Claude Code target reset complete."),u.info(`Removed (manifest-scoped; only files Vesper could prove it wrote): recorded catalog entries, the pack pointer rules, ${c?"the orchestrator playbook, ":""}guard triggers, CLAUDE.md guard block, .mcp.json entry, the OpenCode overlay (opencode.json keys, .opencode/), .vesperrc.claude.`),o.length&&u.warn(`Kept \u2014 they hold your edits, so Vesper could not prove them its own: ${o.join(", ")}. Delete them yourself if you do not need them.`),u.info(r?"Removed (--purge-knowledge): the Team Roster, project whitepaper, on-demand context tier, and .vesper/gates.json.":"Kept: the Team Roster (.claude/rules/vesper-orchestration.md), project whitepaper (vesper-context.md), and on-demand context tier \u2014 they belong to this project."),r&&i.length&&u.warn(`Kept despite --purge-knowledge \u2014 their content exists nowhere else (no identical copy in the Copilot brain): ${i.join(", ")}.`),u.info("Left intact: agent-authored skills in .claude/skills/ (never Vesper-recorded)."),await $n(t,a,"claude",u)}async function ZS(e={}){let t=On(e.path||process.cwd()),r=!!e.purgeKnowledge;if(!await fl(t,"copilot",{purge:r})){u.warn("Vesper is not initialized in this workspace."),await Bi(t);return}let n=await xt(t),s=eE(n);if(!e.yes&&!await pl({message:r?`Remove all Vesper assets (${s.join(", ")}) INCLUDING the Team Roster and project whitepaper?`:`Remove all Vesper assets (${s.join(", ")})? (the Team Roster and project whitepaper are KEPT \u2014 pass --purge-knowledge to remove them too)`,default:!1})){u.info("Reset cancelled.");return}let o=await x(t),i=await q(t),a=await Ir(t,"claude"),c=await ne(t);await Ws(t,{purgeProjectAuthored:r}),await ch(t,"copilot");let l=await Wi(t,c,"copilot");a&&u.info("Claude Code target detected \u2014 kept its record in .vesperrc"),console.log(),u.success("Vesper reset complete."),o.workspaceType===he.WORKSPACE_FILE||i.type===he.WORKSPACE_FILE?u.info(`Cleaned: ${XS(i.settingsPath)}`):u.info("Cleaned: .vscode/settings.json"),u.info(r?"Removed (--purge-knowledge): the Team Roster, project whitepaper, on-demand context tier, and .vesper/gates.json.":"Kept: the Team Roster and project whitepaper \u2014 they belong to this project."),u.info("Reload VS Code to apply changes"),await $n(t,l,"copilot",u)}function eE(e){let t=new Set;for(let r of e)r.includes("/agents")&&t.add("Agents"),r.includes("/instructions")&&t.add("Instructions"),r.includes("/prompts")&&t.add("Prompts"),r.includes("/skills")&&t.add("Skills");return Array.from(t)}async function ah(e,t,r){return t==="claude"?QS({...r,path:e}):ZS({...r,path:e})}async function tE(e,t,r){let n=!!r.purgeKnowledge;if(!await fl(e,t,{purge:n})){u.info(`No ${t} artifacts found to clean \u2014 nothing to do.`);return}if(!r.yes&&!await pl({message:n?`Remove stray ${t} artifacts INCLUDING its Team Roster and project whitepaper? (the active host and all shared state are kept)`:`Remove stray ${t} artifacts from this workspace? (the active host and all shared state are kept)`,default:!1})){u.info("Reset cancelled.");return}let{retained:s}=await Ki(e,t,{fullTeardown:!1,purgeProjectAuthored:n});console.log(),u.success(`Foreign ${t} residue removed.`),await $n(e,s,t,u),u.info(n?`Removed (--purge-knowledge): ${t}'s Team Roster, project whitepaper and on-demand context tier.`:`Kept: ${t}'s Team Roster + project whitepaper (pass --purge-knowledge to remove them).`),u.info("Kept: the active host, the cross-host guard trigger, and all shared state (.vesper/.tracking/, memory, history).")}async function lh(e={}){try{let t=On(e.path||process.cwd());await w(t)||(u.error(`Directory not found: ${u.formatPath(t)}`),process.exit(1));let r=e.host;if(!r&&e.target){let i=String(e.target).toLowerCase();z.includes(i)||(u.error(`Unknown target: ${e.target}. Valid: ${z.join(", ")}.`),process.exit(1)),u.warn("`--target` is deprecated; use `--host` instead. Mapping to `--host "+i+"`."),r=i}let n=await ge(t),o=await on(t)??(n.length===1?n[0]:null);if(!r){if(n.length>1&&(u.error(Ko),process.exit(1)),!o){let i=await Pr(t);if(i){u.warn(`Nothing is provisioned in this checkout; the local record names ${i} \u2014 \`vespercli reset --host ${i}\` removes that host's local files.`),await Bi(t);return}u.warn("Vesper is not initialized in this workspace."),await Bi(t);return}return await ah(t,o,e)}return o&&o!==r?await tE(t,r,e):await ah(t,r,e)}catch(t){if(t.name==="ExitPromptError"){console.log(),u.info("Reset cancelled.");return}t.name==="HostCleanRefused"&&(u.error(t.message),process.exit(1)),u.error(`Reset failed: ${t.message}`),process.exit(1)}}Ae();fe();U();import{lstat as zi,readFile as be,readdir as qi,readlink as Ks,rmdir as fh}from"node:fs/promises";import{createHash as rE}from"node:crypto";import{basename as hh,dirname as hl,isAbsolute as Yi,join as _,relative as ml,sep as Bs}from"node:path";import{homedir as zs}from"node:os";te();Ae();Ye();_s();Tr();H();_e();fe();at();dn();var nE=Object.freeze([".vesper/.tracking",".vesper/history.md",".vesper/history-archive",".vesper/memory.jsonl",".vesper/index.db",".vesper/index.db-wal",".vesper/index.db-shm",".vesper/indexing-status.json",Fr]);function Ji(e){return nE.some(t=>e===t||e.startsWith(`${t}/`))}var mh=Object.freeze([".vesperrc",".vesper/tracking.json","CLAUDE.md",".claude/settings.json",".claude/settings.local.json",".mcp.json",".vscode/settings.json",".vscode/tasks.json",".vscode/mcp.json",".gitignore",".gitattributes"]),gh=Object.freeze([".claude",".vscode",".vesper",".github",".opencode"]);async function sE(e,t){let r,n;try{[r,n]=await Promise.all([zi(e),zi(t)])}catch{return!1}if(r.isSymbolicLink()||n.isSymbolicLink())return r.isSymbolicLink()&&n.isSymbolicLink()&&await Ks(e)===await Ks(t);if(r.isFile()&&n.isFile())return(await be(e)).equals(await be(t));if(!r.isDirectory()||!n.isDirectory())return!1;let[s,o]=await Promise.all([ut(e),ut(t)]),i=(a,c)=>a.length===c.length&&a.every((l,d)=>l===c[d]);if(!i(s.files,o.files)||!i(s.others,o.others)||!i([...s.dirs].sort(),[...o.dirs].sort()))return!1;for(let a of s.files)if(!(await be(_(e,a))).equals(await be(_(t,a))))return!1;for(let a of s.others)try{if(await Ks(_(e,a))!==await Ks(_(t,a)))return!1}catch{return!1}return!0}async function uh(e){let t=_(e,Fr);await P(t,{recursive:!0});let r=_(t,".gitignore"),n=null;try{n=await be(r,"utf-8")}catch{n=null}n!==`*
|
|
152
152
|
`&&await A(r,`*
|
|
153
|
-
`,"utf-8")}async function
|
|
154
|
-
`,"utf-8"),m},async snapshot(c){return i.has(c)||(i.add(c),!await w(_(e,c)))?null:a("rewritten",c,_(e,c))},async writeSidecar(c,l){return await
|
|
153
|
+
`,"utf-8")}async function yh(e,t,r,n){if(!["project","home","rewritten","outside"].includes(t))throw new Error(`backupPath: sourceRoot must be 'project', 'home', 'rewritten' or 'outside' (got "${t}")`);let s=String(r||"").split(Bs).join("/");if(!s||Yi(s)||s.split("/").includes(".."))throw new Error(`backupPath: unsafe relative path "${r}"`);let o=_(e,t,s);if(await w(o))throw new Error(`backupPath: refusing to overwrite an existing backup at ${o}`);if(await P(hl(o),{recursive:!0}),await as(n,o,{recursive:!0,errorOnExist:!0,force:!1,verbatimSymlinks:!0,preserveTimestamps:!0}),!await sE(n,o))throw new Error(`backupPath: the backup of ${n} at ${o} is not byte-identical \u2014 nothing was removed`);return o}function gl(e,{now:t=new Date,homeDir:r=zs()}={}){let n=t.toISOString().replace(/[:.]/g,"-"),s=_(e,Fr,n),o=[],i=new Set,a=async(c,l,d)=>{await uh(e);let p=await yh(s,c,l,d);return o.push({sourceRoot:c,rel:l,original:d,backup:p}),p};return{dir:s,items:o,homeDir:r,project:c=>a("project",c,_(e,c)),home:c=>a("home",ml(r,c).split(Bs).join("/"),c),async nestedConfig(c){let l=ml(e,c).split(Bs).join("/");if(l&&!l.startsWith("..")&&!Yi(l))return a("project",l,c);let d=_(s,wh),p=[];try{p=JSON.parse(await be(d,"utf-8"))}catch{p=[]}let f=`${p.length}/${hh(c)}`,m=await a("outside",f,c);return p.push({original:c,backup:_("outside",f).split(Bs).join("/")}),await A(d,`${JSON.stringify(p,null,2)}
|
|
154
|
+
`,"utf-8"),m},async snapshot(c){return i.has(c)||(i.add(c),!await w(_(e,c)))?null:a("rewritten",c,_(e,c))},async writeSidecar(c,l){return await uh(e),await P(s,{recursive:!0}),await A(_(s,c),l,"utf-8"),_(s,c)},restoreCommands(){let c=new Set(o.map(d=>d.sourceRoot)),l=[];return c.has("project")&&l.push(`cp -R "${_(s,"project")}/." "${e}/"`),c.has("home")&&l.push(`cp -R "${_(s,"home")}/." "${r}/"`),l}}}var wh="outside.json";async function Xi(e){let t=_(e,Fr),r=[];try{r=(await qi(t,{withFileTypes:!0})).filter(s=>s.isDirectory()).map(s=>s.name).sort()}catch{r=[]}let n=[];for(let s of r){let o=_(t,s),i=async f=>{try{return JSON.parse(await be(_(o,f),"utf-8"))}catch{return null}},a=await i("kept.json"),c=await i("rollback.json"),l=await i(wh),d=!!c&&Array.isArray(c.before),p=d?typeof c.status=="string"?c.status:Array.isArray(c.created)?"finished":"started":null;n.push({dir:o,name:s,project:await w(_(o,"project")),home:await w(_(o,"home")),rewritten:await w(_(o,"rewritten")),kept:Array.isArray(a)?a.filter(f=>f&&typeof f.rel=="string"):[],created:Array.isArray(c?.created)?c.created.filter(f=>typeof f=="string"):[],trackedPaths:Array.isArray(c?.trackedPaths)?c.trackedPaths.filter(f=>typeof f=="string"):[],head:typeof c?.head=="string"?c.head:null,before:Array.isArray(c?.before)?c.before.filter(f=>typeof f=="string"):null,previousVersion:typeof c?.previousVersion=="string"?c.previousVersion:null,migration:d,status:p,chainRoot:typeof c?.chainRoot=="string"?c.chainRoot:s,preCreated:Array.isArray(c?.preCreated)?c.preCreated.filter(f=>typeof f=="string"):[],outside:Array.isArray(l)?l.filter(f=>f&&typeof f.original=="string"&&typeof f.backup=="string"):[],createdChecked:await w(_(o,wl))&&await w(_(o,vl)),guidancePrinted:d?typeof c.guidancePrinted=="boolean"?c.guidancePrinted:p==="finished":!1})}return n}async function vh(e,t=".md"){try{return(await qi(e,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(t)).map(r=>r.name).sort()}catch{return[]}}async function oE(e){try{return(await qi(e,{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>t.name).sort()}catch{return[]}}async function kh(e){try{return await be(e)}catch{return null}}var iE=Object.freeze({"edited-catalog":"a 1.x catalog file you edited (or a namesake you wrote) \u2014 it shadows its plugin twin `vesper:<name>` until you delete it","edited-skill":"a 1.x catalog skill holding your edits or your own files \u2014 only its untouched files are retired","edited-playbook":"the 1.x orchestrator playbook holds your edits (2.0 reads .claude/rules/vesper-orchestrator.md instead)","github-brain":"left in place: GitHub.com's Copilot coding agent and code review read it; its content was copied into the new brain","github-brain-kept":"left in place, untouched: GitHub.com's Copilot coding agent and code review read it (the new brain's whitepaper was taken from .claude/vesper/context.md instead)","github-brain-dest":"left in place, untouched: GitHub.com's Copilot coding agent and code review read it (the new brain already had its whitepaper)","github-own":"your own file (no Vesper content) \u2014 left untouched and nothing copied from it (GitHub Copilot reads it natively)","unmarked-knowledge":"no Vesper marker \u2014 not provably Vesper's; left in place","duplicate-knowledge":"not relocated: the same knowledge already moved into the new brain \u2014 review it and delete this copy yourself","plugin-folder":"kept in the old machine-wide plugin folder: no released Vesper build wrote these bytes",error:"left in place after an error"});async function Sh(e,t){let r=new Set(t.catalogManifest),n={record:[],keep:[]},s=new Set([...er,...$r]);for(let[o,i]of[["agents","catalog-agent"],["commands","catalog-command"]])for(let a of await vh(_(e,".claude",o))){if(o==="agents"&&a===`${L}.md`)continue;let c=`.claude/${o}/${a}`,l=await kh(_(e,c));if(!l)continue;let d=r.has(c)?1:2;ai(l,`${o}/${a}`,{namePrefix:t.namePrefix})?n.record.push({rel:c,kind:"file",tier:d,entry:G({path:c,host:"claude",category:i,hash:dt(l)})}):(r.has(c)||ci(o,a,t.namePrefix))&&n.keep.push({rel:c,reason:"edited-catalog"})}for(let o of await oE(_(e,".claude","skills"))){if(s.has(o))continue;let i=`.claude/skills/${o}`,a=ip(o);if(!a&&!r.has(i))continue;let c=a?await Gt(_(e,i),{sourceLfHashes:a}):{status:"none",proven:[]};if(c.status==="classified"&&c.proven.length){let l={};for(let d of c.proven)l[d]=dt(await be(_(e,i,d)));n.record.push({rel:i,kind:"dir",tier:r.has(i)?1:2,entry:{...G({path:i,host:"claude",category:"catalog-skill",hash:null}),fileHashes:l},userFiles:c.kept}),c.kept.length&&n.keep.push({rel:i,reason:"edited-skill",files:c.kept})}else n.keep.push({rel:i,reason:"edited-skill"})}return n}async function dh(e){let{frontmatter:t}=ht(await be(_(De,e),"utf-8"));return t===null?"":`---
|
|
155
155
|
${t}
|
|
156
156
|
---
|
|
157
157
|
|
|
158
|
-
`}function
|
|
158
|
+
`}function aE(e){let{frontmatter:t}=ht(e);return/Vesper orchestration/.test(Vr(t,"description")||"")}function cE(e){let t=e.split(`
|
|
159
159
|
`).slice(0,40).join(`
|
|
160
|
-
`);return/^#\s*Vesper\b/m.test(t)||t.includes(".vesper/")||t.includes(".claude/vesper/context")}async function
|
|
161
|
-
`).map(a=>a.trim()).filter(Boolean):[];for(let[i,a]of[[["diff","--name-only","--",...r],null],[["diff","--name-only","--cached","--",...r],s],[["ls-files","--others","--exclude-standard","--",...r],null]])for(let c of o(await D(["-c","core.quotepath=off",...i],{cwd:e})))n.add(c),a&&a.add(c);return{inGit:!0,dirty:[...n].sort(),staged:[...s].sort()}}function
|
|
160
|
+
`);return/^#\s*Vesper\b/m.test(t)||t.includes(".vesper/")||t.includes(".claude/vesper/context")}async function Eh(e){return await vh(e,".code-workspace")}async function bh(e,{record:t}={}){let r=t||await Ii(e),n=await Sh(e,r),s=new Set([...mh,...await Eh(e),...n.record.map(o=>o.rel),".claude/vesper/orchestrator.md",".claude/vesper/orchestration.md",".claude/vesper/context.md",".github/instructions/orchestration.instructions.md"]);for(let o of rl())s.add(o);return[...s].sort()}async function yl(e){let t=await D(["rev-parse","--git-path","hooks"],{cwd:e});if(!t)return null;let n=(Yi(t)?ml(e,t):t).split(Bs).join("/");return!n||n.startsWith("..")||Yi(n)?null:n}async function xh(e){return await D(["rev-parse","--is-inside-work-tree"],{cwd:e})==="true"}async function Ah(e,{record:t}={}){if(!await xh(e))return{inGit:!1,dirty:[],staged:[]};let r=await bh(e,{record:t}),n=new Set,s=new Set,o=i=>i?i.split(`
|
|
161
|
+
`).map(a=>a.trim()).filter(Boolean):[];for(let[i,a]of[[["diff","--name-only","--",...r],null],[["diff","--name-only","--cached","--",...r],s],[["ls-files","--others","--exclude-standard","--",...r],null]])for(let c of o(await D(["-c","core.quotepath=off",...i],{cwd:e})))n.add(c),a&&a.add(c);return{inGit:!0,dirty:[...n].sort(),staged:[...s].sort()}}function _h(e,{interrupted:t=null}={}){let r=e.slice(0,15).join(", ")+(e.length>15?`, \u2026 (${e.length} in total)`:""),n=t?` An interrupted migration of this commit left its own changes too (${t}) \u2014 those alone would not stop a re-run, but these paths hold changes it did not write.`:"";return`Not migrating: this pre-2.0 (1.x) Vesper workspace has uncommitted changes in paths the migration removes or rewrites (${r}).${n} Commit or stash them first (\`git add -A && git commit\`, or \`git stash -u\`), then re-run \`vespercli init\` \u2014 a clean start is what makes \`git restore\` a genuine undo of the migration.`}async function lE(e){let t=new Set,r=s=>Ji(s)||/^\.vesper\/index\.db/.test(s),n=await yl(e);for(let s of[...gh,...n?[n]:[]]){let o;try{o=await ut(_(e,s))}catch{continue}for(let i of[...o.files,...o.others]){let a=`${s}/${i}`;r(a)||t.add(a)}}try{for(let s of await qi(e,{withFileTypes:!0}))(s.isFile()||s.isSymbolicLink())&&t.add(s.name)}catch{}return t}var Ch="written.log",$h="no-hooks",wl="created.sha256",vl="remove-created.sh",uE=`#!/bin/sh
|
|
162
162
|
# Written by vespercli (1.x migration rollback). Run from the workspace root.
|
|
163
163
|
# Removes the files this migration created, ONLY while they still hold the bytes it wrote.
|
|
164
164
|
# A file changed since is KEPT and listed below: review it and delete it yourself.
|
|
165
|
-
list="$(dirname -- "$0")/${
|
|
165
|
+
list="$(dirname -- "$0")/${wl}"
|
|
166
166
|
kept=0
|
|
167
167
|
tab="$(printf ' ')"
|
|
168
168
|
while IFS="$tab" read -r want f; do
|
|
@@ -185,41 +185,41 @@ if [ "$kept" -gt 0 ]; then
|
|
|
185
185
|
echo "$kept file(s) this migration created were changed since and were NOT removed - review them and delete them yourself." >&2
|
|
186
186
|
fi
|
|
187
187
|
exit 0
|
|
188
|
-
`;async function
|
|
189
|
-
`))if(n)try{let s=JSON.parse(n);Array.isArray(s)&&typeof s[0]=="string"&&typeof s[1]=="string"&&r.push(s)}catch{}return r}async function
|
|
190
|
-
`)}async function
|
|
191
|
-
`).map(f=>f.trim()).filter(f=>f&&!
|
|
188
|
+
`;async function kl(e){let t="";try{t=await be(_(e,Ch),"utf-8")}catch{return[]}let r=[];for(let n of t.split(`
|
|
189
|
+
`))if(n)try{let s=JSON.parse(n);Array.isArray(s)&&typeof s[0]=="string"&&typeof s[1]=="string"&&r.push(s)}catch{}return r}async function dE(e,t){let r=[];for(let[n,s]of await kl(t)){if(r.push([n,s]),s!==is)continue;let o=null;try{o=await zi(_(e,n))}catch{o=null}if(!o?.isDirectory())continue;let i=null;try{i=await ut(_(e,n))}catch{i=null}for(let a of i?[...i.files,...i.others]:[])r.push([`${n}/${a}`,is])}return r}async function Oh(e){let t;try{t=await zi(e)}catch{return null}return t.isSymbolicLink()?`link:${await Ks(e)}`:t.isFile()?rE("sha256").update(await be(e)).digest("hex"):null}async function Sl(e,t){let r=_(e,"rollback.json"),n;try{n=JSON.parse(await be(r,"utf-8"))}catch{return}await Cr(r,`${JSON.stringify({...n,...t},null,2)}
|
|
190
|
+
`)}async function Qi(e){return await D(["rev-parse","HEAD"],{cwd:e})||null}async function pE(e){let t=(await Xi(e)).filter(s=>s.migration);if(!t.length)return null;let r=t[t.length-1],n=t.filter(s=>s.chainRoot===r.chainRoot);return{root:n[0],latest:r,members:n,status:r.status,guidancePrinted:r.guidancePrinted}}async function Th(e){let t=await pE(e);return t&&(t.status==="started"||t.status==="finished"&&!t.guidancePrinted)?t:null}async function Ph(e){for(let t of e.members)await Sl(t.dir,{status:"abandoned",guidancePrinted:!0});return e.members.map(t=>t.dir)}async function Ih(e,t,{dirty:r,staged:n=[]}){let s=new Map;for(let c of t.members)for(let[l,d]of await kl(c.dir))s.set(l,d);let o=new Set(t.root.trackedPaths),i=new Set(n),a=[];for(let c of r){if(i.has(c)){a.push(c);continue}let l=await Oh(_(e,c));l===null?o.has(c)||a.push(c):s.get(c)!==l&&a.push(c)}return a}async function El(e,t,{record:r,previousVersion:n=null,chain:s=null,preCreated:o=[]}={}){let i=await xh(e),a=null,c=[];if(i){a=await Qi(e);let d=await bh(e,{record:r}),p=a?await D(["-c","core.quotepath=off","ls-files","--",...d],{cwd:e}):null;c=p?p.split(`
|
|
191
|
+
`).map(f=>f.trim()).filter(f=>f&&!Ji(f)).sort():[]}let l={version:2,startedAt:new Date().toISOString(),head:a,trackedPaths:c,previousVersion:n||s?.root.previousVersion||null,before:[...await lE(e)].sort(),chainRoot:s?s.root.chainRoot:hh(t.dir),preCreated:[...new Set(o)].filter(d=>typeof d=="string"&&d).sort(),status:"started",created:null,guidancePrinted:!1};return c.length&&await t.writeSidecar("tracked-paths.txt",`${c.join(`
|
|
192
192
|
`)}
|
|
193
193
|
`),await t.writeSidecar("rollback.json",`${JSON.stringify(l,null,2)}
|
|
194
|
-
`),
|
|
194
|
+
`),Ha({root:e,log:_(t.dir,Ch),exclude:Ji}),l}function bl(){Ha(null)}async function xl(e,t){bl();let r=await Xi(e),n=r.find(v=>v.dir===t);if(!n?.migration)return null;let s=r.filter(v=>v.migration&&v.chainRoot===n.chainRoot&&v.name<=n.name),[o]=s,i=await yl(e),a=v=>!v.includes("/")||gh.some(S=>v.startsWith(`${S}/`))||i&&v.startsWith(`${i}/`),c=new Set(s.flatMap(v=>v.preCreated)),l=new Set(o.before.filter(v=>!c.has(v))),d=new Set(n.before.filter(v=>!c.has(v))),p=new Set,f=new Set,m=new Map;for(let v of s)for(let[S,C]of await dE(e,v.dir))p.add(S),m.set(S,C),v!==n&&f.add(S);let h=[],g=[];for(let v of[...p].sort()){if(!a(v)||Ji(v)||l.has(v)||d.has(v)&&!f.has(v))continue;let S=await Oh(_(e,v));if(S===null)continue;h.push(v);let C=m.get(v);g.push([C===is?S:C,v])}await A(_(n.dir,"created.txt"),h.length?`${h.join(`
|
|
195
195
|
`)}
|
|
196
|
-
`:"","utf-8"),await A(_(n.dir,
|
|
197
|
-
`).join(""),"utf-8"),await A(_(n.dir,
|
|
198
|
-
`)}async function
|
|
199
|
-
`;return await A(i,a,{encoding:"utf-8",flag:"a"}),{rel:`${
|
|
200
|
-
`))if(d.trim()!=="")try{let p=JSON.parse(d);if(!p||typeof p!="object"||Array.isArray(p)){i+=1;continue}o.push({...p,slug:
|
|
201
|
-
`).map(o=>o.trim()).find(o=>/^[0-9a-f]{40}\s+HEAD$/.test(o));return s?s.slice(0,40):null}async function ea({assetsDir:e,timeoutMs:t=Zi,env:r}={}){let n=[];for(let{pack:s,skill:o,record:i}of await Wu(e)){let a=typeof i?.upstream=="string"?i.upstream:null,c=typeof i?.sha=="string"?i.sha:null;if(!a||!c){n.push({skill:o,pack:s,upstream:a,pinned:c,remote:null,stale:null,status:"no-record"});continue}let l=await wE(a,{timeoutMs:t,env:r});if(!l){n.push({skill:o,pack:s,upstream:a,pinned:c,remote:null,stale:null,status:"unreachable"});continue}let d=l!==c;n.push({skill:o,pack:s,upstream:a,pinned:c,remote:l,stale:d,status:d?"stale":"current"})}return n}function Vh(e){return`\`${e.skill}\` has a newer upstream (${e.upstream} is at ${e.remote.slice(0,12)}, the package ships ${e.pinned.slice(0,12)}); the next Vesper release picks it up.`}Te();var Hh=["list","enable","disable","sync","upstream"];function SE(e,{log:t=console.log}={}){if(t(),t(ae.bold("Third-party pack skills \u2014 upstream check")),t(ae.dim("Pinned = the commit the shipped snapshot was taken at (UPSTREAM.json); remote = upstream HEAD now.")),t(),!e.length){t(ae.dim(" (this package ships no third-party skills)")),t();return}let r=Math.max(...e.map(s=>s.skill.length));for(let s of e){let o=s.status==="stale"?ae.yellow("newer upstream"):s.status==="current"?ae.green("current"):s.status==="unreachable"?ae.dim("unreachable"):ae.red("no record"),i=s.pinned?s.pinned.slice(0,12):"\u2014",a=s.remote?s.remote.slice(0,12):"\u2014";t(` ${s.skill.padEnd(r)} ${s.pack.padEnd(12)} pinned ${i} remote ${a} ${o}`)}t();let n=e.filter(s=>s.status==="stale");n.length&&t(ae.dim(`A newer upstream reaches projects with the next Vesper release (maintainers: npm run vendor:sync ${n.map(s=>s.skill).join(" ")}).`)),t()}function Vr(e,{log:t=u}={}){if(!e.rosterFound){t.info(`Packs: no Team Roster at ${e.rosterPath} yet \u2014 nothing to enable (run \`vespercli packs sync\` after the roster is written).`);return}e.enabled.length&&t.success(`Packs enabled for ${e.host}: ${e.enabled.map(Ne).join(", ")} (named by the Team Roster).`),e.already.length&&t.info(`Packs already enabled: ${e.already.map(Ne).join(", ")}.`),!e.enabled.length&&!e.already.length&&t.info("Packs: the Team Roster names core assets only \u2014 no pack needed."),e.unused.length&&t.info(`Packs enabled but unused by the Team Roster (kept; \`vespercli packs disable <pack>\` removes one): ${e.unused.join(", ")}.`),e.unknownAgents.length&&t.dim(` roster agents not in the catalog (project agents or typos): ${e.unknownAgents.join(", ")}`),e.unknownSkills.length&&t.dim(` roster skills not in the catalog (project skills or typos): ${e.unknownSkills.join(", ")}`)}function Cl(e){if(!e)return;let{gitignore:t,hook:r,mcp:n}=e;(t.status==="created"||t.status==="updated")&&u.info(" .gitignore block written: graphify-out/* ignored, graphify-out/graph.json committed"),t.status==="kept-edited"&&u.warn(Ss(t.path)),r.status==="created"&&u.info(` post-checkout hook block written (\`graphify update .\` after a branch checkout, no-op without the tool): ${r.path}`),r.status==="kept-edited"&&u.warn(Ss(r.path)),r.status==="skipped"&&u.info(` post-checkout hook block not written (${r.reason}) \u2014 run \`vespercli worktree bootstrap\` to install Vesper's hooks, then \`vespercli packs enable graphify\` again.`),n?.added?u.info(" MCP server registered: graphify (`vespercli mcp remove graphify` removes it)"):n?.error&&n.error!=="Already configured"&&u.warn(` MCP server not registered: ${n.error}`);for(let s of Nd())u.info(` ${s}`)}async function $l({interactive:e,plan:t,confirmImpl:r=kE,spawnImpl:n,env:s=process.env}){if(At(s))return{status:"present"};let o=t??mn({env:s});if(!e||!o.command)return{status:"skipped",plan:o};if(!await r({message:`Install graphifyy now? (${o.command})`,default:!0}))return{status:"declined",plan:o};u.info(`Running \`${o.command}\` \u2026`);let a=await Md(o,n?{spawn:n}:{});if(a.ok){let c=!!At(s);return u.success(`graphify installed${c?"":" (not on PATH in this shell yet \u2014 open a new shell, or add the installer's bin directory to PATH)"}. Run \`${xt}\` to build the graph.`),{status:"installed",plan:o,code:a.code}}return u.warn(`\`${o.command}\` failed${a.code!=null?` (exit ${a.code})`:a.error?` (${a.error})`:""} \u2014 nothing else changed. ${o.hint}`),{status:"failed",plan:o,code:a.code,error:a.error}}function EE(e){if(!e)return;let{gitignore:t,hook:r,mcp:n}=e;t.status==="removed"&&u.info(" .gitignore block removed"),t.status==="kept"&&u.warn(Ss(t.path)),r.status==="removed"&&u.info(` post-checkout hook block removed: ${r.path}`),r.status==="kept"&&u.warn(Ss(r.path)),n?.removed&&u.info(" MCP server removed: graphify"),u.info(" graphify-out/graph.json (if any) is yours to keep or delete; the tool itself is not touched.")}async function bE(e,t){let r=await B(e);(await $e(e,{checkout:r})).unmigrated&&(u.error(rt),process.exit(1));let n=r.host?[r.host]:await ge(e);!t.target&&n.length>1&&(u.error(Ze),process.exit(1));let s=t.target||r.host||null;return{host:s,provisioned:!!r.host&&r.host===s}}function Uh({host:e,provisioned:t},r){t||(e?u.error(`\`vespercli packs ${r}\` for ${e} needs a workspace provisioned for ${e} \u2014 nothing was written. Run \`vespercli init --host ${e}\` first.`):u.error(`\`vespercli packs ${r}\` needs a workspace provisioned for a host \u2014 nothing was written. Run \`vespercli init\` first.`),process.exit(1))}async function xE(e,{host:t}){let r=tt(),{enabled:n,unknown:s}=t?await Lr(e,t):{enabled:[],unknown:[]},o=t?await cr(e,t):null,i=o!==null?await lr(o):null;if(console.log(),console.log(ae.bold("Vesper packs")),console.log(ae.dim(t?`Host: ${t}${o===null?` (no Team Roster at ${vn[t]})`:""}`:"Host: not provisioned (catalog only)")),console.log(ae.dim("Core (vesper) is always enabled; a pack is enabled when the Team Roster names one of its assets (`vespercli packs sync`).")),console.log(),!r.length){console.log(ae.dim(" (this package ships no packs)")),console.log();return}for(let a of r){let{agents:c,skills:l}=lp(a),d=n.includes(a)?ae.green("enabled"):ae.dim("disabled"),p=i?.needed[a],f=p?` \u2014 roster needs it: ${[...p.agents,...p.skills].join(", ")}`:i?ae.dim(" \u2014 not named by the roster"):"";console.log(` ${ae.bold(a)} (${Ne(a)}) ${d}${f}`),console.log(ae.dim(` agents: ${c.join(", ")||"\u2014"}`)),console.log(ae.dim(` skills: ${l.join(", ")||"\u2014"}`)),Pr(a)&&console.log(ae.dim(" opt-in: enabling writes an always-on pointer rule that applies these styles (`vespercli packs enable styles`)")),a===Le&&console.log(ae.dim(` opt-in: graphify is an external tool (\`${Xo}\`); enabling adds the gitignore + post-checkout blocks and the graphify MCP server (\`vespercli packs enable graphify\`)`))}if(s.length&&(console.log(),u.warn(`Enabled pack keys this package does not ship: ${s.join(", ")} (an older/newer Vesper wrote them; \`vespercli packs disable <pack>\` cannot remove an unknown pack \u2014 edit the settings by hand).`)),i){let a=i.packs.filter(c=>!n.includes(c));console.log(),a.length?u.warn(`The Team Roster needs ${a.join(", ")} but they are not enabled \u2014 run \`vespercli packs sync\`.`):u.success("Every pack the Team Roster needs is enabled.")}console.log()}async function Wh(e="list",t,r={}){try{let n=vE(r.path||process.cwd());await w(n)||(u.error(`Directory not found: ${u.formatPath(n)}`),process.exit(1));let s=e||"list";Hh.includes(s)||(u.error(`Unknown packs subcommand: ${s}. Subcommands: ${Hh.join(", ")}`),process.exit(1));let o=await bE(n,r);if(s==="list")return await xE(n,o);if(s==="upstream"){SE(await ea());return}if(s==="sync"){Uh(o,"sync");let l=await ur(n,o.host);Vr(l);return}if(t||(u.error(`\`vespercli packs ${s}\` needs a pack name. Packs: ${tt().join(", ")||"none"}`),process.exit(1)),tt().includes(t)||(u.error(`Unknown pack "${t}". Packs: ${tt().join(", ")||"none"}`),process.exit(1)),Uh(o,s),s==="enable"){let{enabled:l,rule:d,graphify:p}=await ar(n,o.host,t);l?u.success(`Enabled the ${t} pack (${Ne(t)}) for ${o.host}.${o.host==="copilot"?" Reload VS Code to apply.":""}`):u.info(`The ${t} pack is already enabled for ${o.host}.`),(d?.status==="created"||d?.status==="updated")&&u.info(` always-on pointer rule written: ${d.path}`),d?.status==="kept-edited"&&u.warn(nc(d.path)),Cl(p),t===Le&&await $l({interactive:!!process.stdin.isTTY});return}let{disabled:i,rule:a,graphify:c}=await hp(n,o.host,t);if(a?.status==="removed"&&u.info(` always-on pointer rule removed: ${a.path}`),a?.status==="kept"&&u.warn(nc(a.path)),EE(c),i){u.success(`Disabled the ${t} pack (${Ne(t)}) for ${o.host}.`);let l=await cr(n,o.host);l!==null&&(await lr(l)).packs.includes(t)&&u.warn(`The Team Roster still names assets of the ${t} pack \u2014 \`vespercli doctor\` will report it; \`vespercli packs sync\` re-enables it.`)}else u.info(`The ${t} pack was not enabled for ${o.host}.`)}catch(n){u.error(`Packs failed: ${n.message}`),process.exit(1)}}ut();Te();var Ol=["copilot","claude"];function jE(e,t){return Xa(e)}async function RE(e,t,{settingsEntries:r,hooksDir:n=null,hookNames:s,version:o}={}){await cn(e,{frameworkVersion:o}),await sd(e,t);let i=await qa(e,t,{settingsEntries:r,hooksDir:n,hookNames:s});await W(e,jE(i,t)),await ad(e)}function Bh(e){return e==="claude"?"Claude Code + OpenCode":"GitHub Copilot"}async function zh(e,t,{thirdPartyBackup:r=null}={}){let n=await Wf(e,{backup:r||void 0}),{info:s,warn:o}=Kf(n);for(let i of s)u.info(i);if(o&&u.warn(o),n.stylesConsent)try{await ar(e,t,Hu)}catch(i){u.warn(`Could not enable the styles pack (${i?.message??i}); run \`vespercli packs enable styles\` by hand.`)}}async function NE(e,t,{legacyHint:r,checkout:n}={}){let s=await ge(t),o=n?n.host:await sn(t),i=o?[o]:s,a=()=>{u.error("Vesper 2.0 provisions exactly one host per workspace \u2014 pass a single `--host claude` or `--host copilot` (not `all` or a comma list)."),process.exit(1)},c=e.host;if(!c&&e.target&&(u.warn("`--target` is deprecated on `init`; use `--host` instead."),c=e.target),c){let h=String(c).toLowerCase();h==="all"&&a();let g=[...new Set(h.split(",").map(y=>y.trim()).filter(Boolean))];for(let y of g)Ol.includes(y)||(u.error(`Unknown host: ${y}. Valid hosts: copilot, claude`),process.exit(1));return g.length>1&&a(),{selected:g,installed:i}}let l=await Ft(t),d=l&&Ol.includes(l.to)?l.to:null,p=r?.needsMigration?Ol.filter(h=>r.hosts?.[h]):[],f=d??(p.length>1?null:o??p[0]??null);if(!process.stdin.isTTY){let h=s.length===1?s[0]:null;if(f&&(p.length===0||(o??h)===f))return{selected:[f],installed:i};u.error(p.length?`Non-interactive run on a pre-2.0 Vesper workspace (${p.join(" + ")}) without --host. Vesper 2.0 provisions exactly one host \u2014 re-run with --host claude or --host copilot to migrate.`:"Non-interactive run without --host, and this checkout carries no Vesper provisioning \u2014 specify the single platform, e.g. --host copilot or --host claude."),process.exit(1)}return{selected:[await IE({message:i.length?"Host for this workspace (Vesper provisions exactly one):":"Which AI host is this workspace for?",choices:[{name:"GitHub Copilot (VS Code)",value:"copilot"},{name:"Claude Code + OpenCode (Claude Code CLI / VS Code extension / JetBrains / desktop; OpenCode reads the same setup)",value:"claude"}],...f?{default:f}:{}})],installed:i}}function LE(e){if(!e)return;console.log();let t=e.level==="warn"?u.warn:u.success;for(let r of e.lines)t(r);console.log()}async function ME(e,t,{backup:r,workspaceRoot:n}={}){let s=await vi({staleDir:void 0,dryRun:!0,workspaceRoot:n});if(s.reason==="absent"||s.reason==="not-ours"||!s.proven?.length)return null;let o=t;if(t||(o=await Kt({message:`Clean the pre-1.9 MACHINE-WIDE Vesper Claude catalog at ${s.path}? ${s.proven.length} file(s) there are byte-identical to a released Vesper build and are removed (backed up first); ${s.kept.length?`${s.kept.length} other file(s) (your edits or your own files) are kept. `:""}Every other pre-1.9 Vesper project on this machine loses its specialists until you run \`vespercli init\` in it.`,default:!0})),!o)return u.info("Left the stale machine-wide Vesper Claude catalog in place (`vespercli doctor` names it)."),null;let i=await vi({backup:r,workspaceRoot:n});return LE(Hp(i)),i}async function FE(e,t={},r=!1){let n="";console.log(),u.header("Installing Vesper for Claude Code"),console.log();let{pluginDir:s,counts:o,pruned:i,keptEdited:a=[]}=await yi({workspaceRoot:e,namePrefix:n,version:t.version});u.success(`Committed fallback surface installed: ${s}`),u.info(` main-thread agent: ${o.agents} (vesper-orchestrator), maintenance skills: ${o.skills}`),u.info(" full specialist catalog served via the vesper marketplace plugin (see .claude/settings.json)"),i.length&&u.info(` pruned ${i.length} legacy project-committed asset(s): ${i.join(", ")}`),a.length&&u.warn(`Left in place \u2014 no longer shipped, but they hold your edits, so Vesper could not prove them its own and no longer tracks them: ${a.map(f=>`.claude/${f}`).join(", ")}. Delete them yourself if you do not need them.`);let c=await ki(e);u.success("Project files ready:"),u.info(` .claude/rules/vesper-orchestrator.md (${c.orchestrator})`),u.info(` .claude/rules/vesper-orchestration.md (${c.orchestration})`),u.info(` .claude/rules/vesper-context.md (${c.context})`),u.info(` .vesper/gates.json (${c.gates})`),u.info(` CLAUDE.md pointer (${c.claudeMd})`);let l=await fr(e,!0),d=await Bp(e);u.success(`MCP servers configured: .mcp.json (${l.servers.join(", ")})`);let p=d.opencode||{};u.success("OpenCode overlay ready (the same setup, read by OpenCode):"),u.info(` opencode.json (${p.status||"unchanged"}${p.status==="skipped-malformed"?" \u2014 the file does not parse as JSON; fix it and re-run":""})`),u.info(` .opencode/agents/vesper-orchestrator.md (${c.opencodeAgent})`),u.info(` .opencode/plugins/vesper.js (${c.opencodePlugin})`),c.opencodeKept?.length&&u.warn(`Left in place \u2014 they differ from what Vesper writes (your edits, or an older build's copy), so Vesper could not prove them its own and no longer tracks them: ${c.opencodeKept.join(", ")}. Delete them to get this version's copy on the next init.`),Vr(await ur(e,"claude")),await zh(e,"claude",t),await Qp(e,{pluginPath:Mr(e),namePrefix:n,mcpConfigPath:Ge(e),settingsPath:Me(e),installedAt:new Date().toISOString()})}async function GE(e,t,r,n={}){console.log(),u.header("Configuring GitHub Copilot"),console.log(),await Zr(e);let s=await Io(e);await $o(e,{maxRequests:r.maxRequests,omitBaseAgentInstructions:r.omitBaseAgentInstructions});let o=await Co(e,r.terminalEnableAutoApprove),i=!1;r.enableMcpServer&&(i=(await Gs(e,!0)).configured,await Lo(e)),await Xn(e);let a=await Mi(e,{version:n.version});return await Xc(e,{settingsEntries:await Et(e)}),Vr(await ur(e,"copilot")),await zh(e,"copilot",n),u.success("Core assets ensured: agents, prompts, instructions, skills"),u.success("Project brain ready:"),u.info(` .vesper/agents/vesper-orchestrator.agent.md (${a.orchestratorAgent}) \u2014 the one pickable agent`),u.info(` .vesper/instructions/vesper-orchestrator.instructions.md (${a.orchestrator})`),u.info(` .vesper/instructions/vesper-orchestration.instructions.md (${a.orchestration})`),u.info(` .vesper/instructions/vesper-context.instructions.md (${a.context})`),u.info(` .vesper/context/ (${a.contextTier}) \u2014 on-demand tier`),u.info(` .vesper/gates.json (${a.gates})`),u.info(`Max agent requests: ${r.maxRequests}`),o.configured>0?u.info(`Terminal auto-approval: ${o.configured} safe commands configured`):r.terminalEnableAutoApprove===!1&&u.info("Terminal auto-approval: disabled"),i&&(u.info("MCP servers: vesper-indexing, sequential-thinking, memory (.vscode/mcp.json)"),u.info("MCP tools auto-approval: vesper-indexing + context7 + sequential-thinking + memory")),s.workspaceType===he.WORKSPACE_FILE?u.info(`Settings added to: ${Kh(t.settingsPath)}`):u.info("Settings added to: .vscode/settings.json"),u.info("Tracking file: .vesperrc"),u.info("Worktree bootstrap task: .vscode/tasks.json (runs on folder open)"),{mcpConfigured:i}}async function DE(e,t,r=null){let n=await Qn(e);if(!n.found)return{migrated:!1,from:null,preCreated:[],backedUp:!1};let{paths:s}=n;console.log(),u.warn(`Found .vesperrc in nested folder${s.length>1?"s":""}:`);for(let{folderPath:c}of s)u.info(` \u2192 ${c}`);console.log();let o=s[0],i=!0;t||(i=await Kt({message:"Migrate .vesperrc to workspace level? (recommended for multi-root workspaces)",default:!0}));let a=[];if(i&&r)try{let c=await kt(e),l=_E(e,c).split(CE).join("/");l&&!l.startsWith("..")&&!$E(l)&&(await w(c)?await r.snapshot(l):(await r.snapshot(l),a=[l]));for(let{vesperrcPath:p}of s)await r.nestedConfig(p)}catch(c){return u.warn(`Not moving the nested .vesperrc: it could not be backed up first (${c?.message||c}). Nothing was changed.`),console.log(),{migrated:!1,from:null,preCreated:[],backedUp:!1}}if(i){let c=await Eo(e,o.vesperrcPath,o.tracking);if(c.success){if(u.success("Migrated .vesperrc to workspace level"),u.info(` From: ${o.vesperrcPath}`),u.info(` To: ${c.newPath}`),s.length>1){let{unlink:l}=await import("node:fs/promises");for(let d=1;d<s.length;d++)try{await l(s[d].vesperrcPath),u.info(` Removed: ${s[d].vesperrcPath}`)}catch{}}return console.log(),{migrated:!0,from:o.folderPath,preCreated:a,backedUp:!!r}}}else u.info("Migration skipped. .vesperrc will remain in nested folder."),console.log();return{migrated:!1,from:null,preCreated:[],backedUp:!!r&&i}}async function VE(e,t){let r=e;return t||(r=await TE({message:"Workspace root directory:",default:r})),AE(r)}async function HE(e,t,r){let n=[];for(let s of t){let o=Bh(s),i=r;if(r||(i=await Kt({message:`${o} is installed but was unchecked. Remove it from this project?`,default:!1})),!i){u.info(`Kept ${o}.`);continue}s==="claude"?await bn(e):await Vs(e),n.push(s),u.success(`Removed ${o} from this project.`)}return n}async function UE(e,t,r,n,{switchSnapshot:s=null}={}){if(await fn(e,t)||(s?.packs||[]).includes(Le))return!1;if(r.graphify)return!0;if(n||r.force||!process.stdin.isTTY)return!1;let i=mn(),a=At()?"graphify found on PATH":`external tool, not on PATH yet: ${i.command?`\`${i.command}\``:i.hint}`;return Kt({message:`Enable the graphify pack? (code knowledge graph for the research roles \u2014 ${a})`,default:!1})}async function WE(e,t,{interactive:r=!1}={}){try{let n=await ar(e,t,Le);u.success(`Enabled the graphify pack (vesper-graphify) for ${t}.`),Cl(n.graphify)}catch(n){u.warn(`Could not enable the graphify pack (${n?.message??n}); run \`vespercli packs enable graphify\` by hand.`);return}await $l({interactive:r})}async function KE(e){if(e)return{maxRequests:Ie.maxRequests,terminalEnableAutoApprove:Ie.terminalEnableAutoApprove,omitBaseAgentInstructions:Ie.omitBaseAgentInstructions,enableMcpServer:Ie.enableMcpServer};console.log(),u.info("Configure VS Code Chat settings:");let t=await PE({message:"Max agent requests per session (chat.agent.maxRequests):",default:Ie.maxRequests,min:1,max:1e3}),r=await Kt({message:"Controls whether terminal commands are automatically approved. Enable terminal auto-approval? (chat.tools.terminal.enableAutoApprove)",default:Ie.terminalEnableAutoApprove});r&&u.info("Terminal auto-approval enabled with safe command whitelist");let n=await Kt({message:"Omit base agent instructions for custom agents? (github.copilot.chat.omitBaseAgentInstructions)",default:Ie.omitBaseAgentInstructions}),s=await Kt({message:"Enable vesper-indexing MCP server for fast code search?",default:Ie.enableMcpServer});return{maxRequests:t||Ie.maxRequests,terminalEnableAutoApprove:r,omitBaseAgentInstructions:n,enableMcpServer:s}}async function ta(e,t=!1){let r=We().replace("index.js","cli-index.js");if(!await w(r))return{success:!1,error:"MCP server not built"};t&&(console.log(),u.info("Starting workspace indexing..."));let n=t?null:u.createSpinner("Indexing workspace...");return n&&n.start(),new Promise(s=>{let o=OE(process.execPath,["--disable-warning=ExperimentalWarning",r,e],{stdio:["ignore","pipe","pipe"],env:{...process.env}}),i="",a=0;o.stderr.on("data",c=>{let l=c.toString().trim(),d=l.match(/Indexed (\d+) files/);if(d&&(a=parseInt(d[1],10),n&&n.update(`Indexing workspace... ${a} files`)),t&&l)for(let p of l.split(`
|
|
202
|
-
`))p.trim()&&u.info(p.replace("[vesper-indexing] ",""))}),o.stdout.on("data",c=>{i+=c.toString()}),o.on("close",c=>{try{let l=JSON.parse(i.trim());l.success?n?n.succeed(`Workspace indexed: ${l.filesIndexed} files`):u.success(`Workspace indexed: ${l.filesIndexed} files`):n?n.fail(`Indexing failed: ${l.error}`):u.error(`Indexing failed: ${l.error}`),s(l)}catch{c===0?(n?n.succeed(`Workspace indexed: ${a} files`):u.success(`Workspace indexed: ${a} files`),s({success:!0,filesIndexed:a})):(n?n.fail("Indexing failed"):u.error("Indexing failed"),s({success:!1,error:"Unknown error"}))}}),o.on("error",c=>{n?n.fail(`Indexing failed: ${c.message}`):u.error(`Indexing failed: ${c.message}`),s({success:!1,error:c.message})})})}function BE({copilot:e,claude:t,indexingResult:r}){console.log(),u.success("Vesper is ready."),r?.success?u.info(`Code index built: ${r.filesIndexed} files.`):r?.error&&u.info("Code index will be built on first MCP server start."),console.log(),u.header("Next Steps"),console.log(),e&&(u.info("GitHub Copilot \u2014 reload VS Code to activate Vesper:"),u.info(' Cmd+Shift+P (macOS) / Ctrl+Shift+P (Windows/Linux) \u2192 "Developer: Reload Window"')),t&&(u.info("Claude Code \u2014 open a session in this workspace; the orchestrator"),u.info(" activates automatically via the always-on rules in .claude/rules/ plus the"),u.info(" default-agent key in .claude/settings.json (vesper-orchestrator)."),u.info(" Committed to the repo: the orchestrator agent, four maintenance skills, and"),u.info(" the three .claude/rules/vesper-*.md files. The full specialist catalog ships"),u.info(' as the "vesper" marketplace plugin \u2014 Claude Code shows a one-time'),u.info(" workspace-trust dialog to load it (decline it, or a cloud/headless session,"),u.info(" and Vesper runs in degraded mode on the committed fallback)."),u.info("OpenCode \u2014 open the same checkout: opencode.json makes vesper-orchestrator the"),u.info(" default agent, loads the three .claude/rules files as instructions, runs the MCP"),u.info(" servers through `vespercli mcp serve`, and .opencode/plugins/vesper.js registers"),u.info(" the specialists. Commit opencode.json and .opencode/ with the rest.")),console.log(),e&&u.vesperTip()}async function Yh(e={}){try{await zE(e)}finally{kl()}}async function zE(e){try{let t=e.yes||e.forceDefault,r=await VE(e.path||process.cwd(),t);await w(r)||(u.error(`Directory not found: ${u.formatPath(r)}`),process.exit(1));let n=await q(r),s=await B(r),o=await $e(r,{checkout:s}),i=n.type===he.WORKSPACE_FILE?await Qn(r):{found:!1,paths:[]},a=i.found&&i.paths.some(j=>!(Number(j?.tracking?.schemaVersion)>=2)),c=await rf(r);c&&u.warn(`An interrupted migration's record (${c.from}) was unreadable and was set aside as ${Kh(c.to)}; its backups are kept. If files look half-migrated, restore them from that folder.`);let l=await Eh(r),d=await Yi(r),p=null;if(o.needsMigration||a){let j=await yh(r,{record:o.record}),Q=l?.status==="started"&&l.latest.head===d&&l.root.head===d?l:null;if(j.dirty.length){let nt=Q?await xh(r,Q,j):j.dirty;nt.length&&(u.error(wh(nt,{interrupted:Q?Q.latest.dir:null})),process.exit(1)),u.warn(`Resuming an interrupted migration (its backups: ${Q.latest.dir}) \u2014 every uncommitted change is its own write.`)}p=Q}let f=fl(r),m={migrated:!1,preCreated:[],backedUp:!1};n.type===he.WORKSPACE_FILE&&(m=await DE(r,t,f),i.found&&(o=await $e(r,{checkout:s})));let{selected:h,installed:g}=await NE(e,r,{legacyHint:o,checkout:s}),y=h[0],k=y==="claude"?"copilot":"claude",v=o.needsMigration&&o.hosts[k]?k:null,S=null,C=s,N=async()=>!!y&&!!C.host&&C.host!==y&&(await Tr(r,C.host)||await Sr(r,C.host)),E=!!v||await N(),b=()=>v??C.host;await Ka(r)&&(u.warn(`An unreadable host-switch journal (${ir}) was found and removed: an earlier switch was interrupted before its record was saved. Check your added assets and MCP servers (\`vespercli list\`, \`vespercli mcp list\`) and re-add any that are missing.`),await sl(r));let G=await Ft(r),X=G?G.snapshot:null;if(G&&u.warn(E?`Resuming an interrupted host switch (${G.from} \u2192 ${G.to}, started ${G.startedAt}): completing it now \u2014 ${b()}'s remaining Vesper artifacts are cleaned, and the assets and MCP servers preserved when it started are restored onto ${y}.`:`Resuming an interrupted host switch (${G.from} \u2192 ${G.to}, started ${G.startedAt}): its preserved assets and MCP servers will be restored onto ${y}.`),E){let j=b(),Q=v?`the pre-2.0 (1.x) ${j} setup`:`${j}'s Vesper artifacts`;if(!t&&!process.stdin.isTTY&&(u.error(`This workspace is provisioned for "${j}"${v?" (pre-2.0)":""}; switching to "${y}" removes ${Q}. Re-run with --yes to confirm (non-interactive), or interactively.`),process.exit(1)),!t&&!await Kt({message:`Switch this workspace from ${j} to ${y}? This removes ${Q}. Your .vesper/.tracking/ (run ledger included) and memory.jsonl are untouched, and the Team Roster + project whitepaper are preserved.`,default:!1})){u.info("Initialization cancelled.");return}}let De=null;if(o.needsMigration){if(l?.status==="started"&&l!==p){let nt=await bh(l);u.warn(`An interrupted migration from another commit (${l.root.head?l.root.head.slice(0,12):"no git"}) cannot be resumed and was abandoned; its backups are kept \u2014 remove them when you no longer need them: ${nt.join(", ")}`)}let j=await vi({dryRun:!0,workspaceRoot:r});S=await vl(r,f,{record:o.record,previousVersion:await _h(r,o.record,j.version||null),chain:p,preCreated:m.preCreated});let Q=v??y;De=await $h(r,y,{legacy:o,recordHost:Q,frameworkVersion:e.version,log:u,backup:f}),C={host:Q,source:"migration"},E=!!v||E&&await N()}else l&&(u.warn(`Completing an interrupted 1.x migration (its backups: ${l.latest.dir}): its rollback record is finished and its backup and rollback guidance printed at the end of this run.`),l.latest.head===d?S=await vl(r,f,{record:o.record,chain:l}):l.status==="started"&&await Sl(r,l.latest.dir));if(E){await nl(r,C.host),G||(X=await ol(r),await Bf(r,{from:C.host,to:y,snapshot:X}));let{retained:j}=await Vi(r,C.host,{fullTeardown:!0});await Cn(r,j,C.host,u)}let Tn=E||De?[]:g.filter(j=>!h.includes(j));if(h.length===0&&Tn.length===0){u.info("No platforms selected. Nothing to do.");return}if(!t&&g.length===0&&h.length>0&&!await Kt({message:`Set up ${h.map(Bh).join(" + ")} in ${r}?`,default:!0})){u.info("Initialization cancelled.");return}Tn.length>0&&await HE(r,Tn,t);let _t=h.includes("copilot"),zt=h.includes("claude"),Ve=null;_t&&(Ve=await KE(t));let gr=await UE(r,y,e,t,{switchSnapshot:X}),yr={...e,thirdPartyBackup:De?j=>f.project(j):null};_t&&(await cd(r,"copilot"),await GE(r,n,Ve,yr)),zt&&await FE(r,yr,g.includes("claude"));let Ct=null;if((_t||zt)&&(Ct=await ME(g.includes(y),t,{backup:async j=>f.home(j),workspaceRoot:r}),Ct?.kept?.length&&(Ct.removed||Ct.partial)))try{await El(f,Ct.kept.map(j=>({rel:`~/.claude/skills/vesper/${j}`,reason:"plugin-folder"})))}catch{}if(_t||zt){let j=await Dh(r);j.archived&&u.success(`Archived .vesper/history.md \u2192 ${j.to} (${j.method==="git"?"git mv, staged":"moved"}). Vesper 2.0 keeps the run ledger under .vesper/.tracking/runs/ instead; the archive is read-only and reachable by /revalidate-knowledge.`)}let oa=null,Pn=[];if(_t||zt){await zn(r);let j=await Yn(r);if(j.length>0){let $t=j.map(Jm=>`'${Jm.replace(/'/g,"'\\''")}'`);u.warn(`Local-only file(s) are git-tracked despite .gitignore: ${$t.join(", ")}`),u.warn(`Untrack them yourself (Vesper won't touch your git index): git rm --cached -- ${$t.join(" ")}`)}let Q=await ts(r);Pn=at.filter($t=>Q[$t]&&!Q[$t].reason),oa=Pn.length&&Q[Pn[0]].hooksDir||null;for(let $t of es(Q))$t.startsWith("Git hooks not installed")?u.info($t):u.warn($t);oa&&(u.success("Local-only Vesper files gitignored (.vesperrc, .mcp.json, .vesper/index.db)"),Pn.includes("pre-commit")&&u.info("Commit-hygiene git hook installed (pre-commit): keeps team roster/context/tracking/memory in sync with every commit")),gr&&await WE(r,y,{interactive:!t&&!e.force&&!!process.stdin.isTTY});let nt=await rs(r);await ns(r),nt.skipped||u.info("Merge strategy configured (.gitattributes): memory.jsonl merges entity-aware across worktrees, recent-decisions.md unions")}if(h.length===1){let j=h[0],Q=j==="copilot"?await Et(r):void 0;await RE(r,j,{settingsEntries:Q,hooksDir:oa,hookNames:Pn,version:e.version}),X&&(await zf(r,j,X),await sl(r));let{legacyGuardRule:nt}=await Pi(r,j);nt==="kept"&&u.warn(xn())}if(De)try{let Q=(await _n(r)).findings.filter(nt=>nt.code.startsWith("legacy-"));Q.length&&u.warn(`The migration left ${Q.length} pre-2.0 item(s) \u2014 see \`vespercli doctor\`.`)}catch{}if(S)try{await Sl(r,f.dir)}catch(j){u.warn(`Could not finish the migration's rollback record (${j?.message||j}); the backups are under .vesper/.migration-backup/.`)}let Ym=_t&&Ve?.enableMcpServer||zt,Ul=null;Ym&&(Ul=await ta(r,!0));let In=[];if((S||Ct?.backedUpTo||m.backedUp)&&In.push(f.dir),l&&!o.needsMigration&&!S&&In.push(l.latest.dir),In.length)try{let j=await Ch(r,{runDirs:In});if(j.length){console.log();for(let Q of j)u.info(Q)}await Ah(r,In)}catch(j){u.warn(`Could not print the migration backup guidance (${j?.message||j}); the backups are under .vesper/.migration-backup/.`)}BE({copilot:_t,claude:zt,indexingResult:Ul})}catch(t){if(t.name==="ExitPromptError"){console.log(),u.info("Initialization cancelled.");return}t.name==="HostCleanRefused"&&(u.error(t.message),process.exit(1)),u.error(`Initialization failed: ${t.message}`),process.exit(1)}}U();H();te();be();Ee();xe();Ut();import{resolve as YE,join as Jh}from"node:path";import{checkbox as JE}from"@inquirer/prompts";Te();var qh=["agents","skills"];async function qE(e,t){let r=t?[t]:await ge(e);return r.length===0&&(u.warn('Vesper is not initialized in this workspace. Run "vespercli init" first.'),process.exit(0)),r.length>1&&(u.error(Ze),process.exit(1)),r[0]}async function Xh(e,t,r){r!==t&&(u.error(`\`vespercli add\` for ${t==="claude"?"Claude Code":"Copilot"} needs a workspace provisioned for ${t}${r?` (this one is provisioned for ${r})`:""} \u2014 nothing was written. Run \`vespercli init --host ${t}\` first.`),process.exit(1))}async function XE(e,t){return await Ps(e,t)!==null}async function QE(e,t,r){if(!t.type||!t.name){u.info("Every Vesper specialist and skill is served by the vesper plugin as `vesper:<name>` \u2014 there is nothing to add."),u.info("To pin a project-level copy anyway: vespercli add <agents|skills> <name> --override");return}if(t.type==="prompts"&&(u.error("Vesper 2.0 ships its maintenance workflows as skills (served by the plugin); slash commands are no longer provisioned."),process.exit(1)),qh.includes(t.type)||(u.error(`Unknown asset type for Claude Code: ${t.type}. Types: ${qh.join(", ")}`),process.exit(1)),await XE(t.type,t.name)||(u.error(`${t.type}/${t.name} is not in the Vesper catalog.`),process.exit(1)),!t.override){let n=await Ps(t.type,t.name),s=t.type==="agents"?await mp(t.name):`/${n.pack==="core"?"vesper":`vesper-${n.pack}`}:${t.name}`;u.info(`\`${t.name}\` is already available as \`${s}\` from the ${n.pack==="core"?"vesper plugin":`vesper-${n.pack} pack (enabled per project by \`vespercli packs sync\`)`} \u2014 nothing to add.`),u.info("A project-level copy would shadow the plugin's version. To pin one anyway (not recommended): add --override.");return}await Xh(e,"claude",r);try{let n=await wi(t.type,t.name,{workspaceRoot:e,namePrefix:await on(e)});u.success(`Pinned a project-level copy of ${t.type}/${t.name} as "${n.installedAs}" (recorded; \`vespercli reset --host claude\` removes it).`)}catch(n){u.error(n.message),process.exit(1)}}async function ZE(e,t,r){let n=await Lf(),s=new Set(await St(e)),o=c=>[...s].some(l=>l.replace(/\\/g,"/").endsWith(`/instructions-extended/${c}`));if(t.type&&t.type!=="instructions"){qe[t.type]||(u.error(`Unknown asset type: ${t.type}. Types: ${Object.keys(qe).join(", ")}`),process.exit(1));let c=ci(),l=[...new Set([...await Zs(t.type),...c[t.type]||[]])];t.name&&!l.includes(t.name)&&(u.error(`${t.type}/${t.name} is not in the Vesper catalog.`),process.exit(1));let d=t.name?c.assetPacks[t.type]?.[t.name]??"core":"core",p=d==="core"?`${Jh(Ot,qe[t.type].dir)} (the whole folder is injected)`:`${Jh(Ot,"packs",d,qe[t.type].dir)} (the ${d} pack's folder, injected when the pack is enabled \u2014 \`vespercli packs sync\`)`;u.info(`Copilot reads every Vesper ${t.type.replace(/s$/,"")} from ${p}${t.name?` \u2014 \`${t.name}\` is already available`:""}. Nothing to add.`);return}let i=[];if(t.name)n.includes(t.name)||(u.error(`Unknown opt-in instruction: ${t.name}. Available: ${n.join(", ")||"none"}`),process.exit(1)),i=[t.name];else{let c=n.filter(l=>!o(l));if(c.length===0){u.info("Every opt-in instruction is already added.");return}if(!process.stdin.isTTY){u.info(`Opt-in instructions you can add: ${c.join(", ")} \u2014 run \`vespercli add instructions <name>\`.`);return}if(i=await JE({message:"Select opt-in instructions to add:",choices:c.map(l=>({name:l,value:l}))}),i.length===0){u.info("Nothing selected.");return}}await Xh(e,"copilot",r);let a=[];for(let c of i)(await Fi(e,c)).added&&a.push(c);a.length?u.success(`Added opt-in instruction(s): ${a.join(", ")} \u2014 reload VS Code to apply.`):u.info("All selected instructions were already added.")}async function Qh(e={}){try{let t=YE(e.path||process.cwd());await w(t)||(u.error(`Directory not found: ${u.formatPath(t)}`),process.exit(1));let r=await B(t);return(await $e(t,{checkout:r})).unmigrated&&(u.error(rt),process.exit(1)),(e.target||await qE(t,r.host))==="claude"?await QE(t,e,r.host):await ZE(t,e,r.host)}catch(t){if(t.name==="ExitPromptError"){console.log(),u.info("Cancelled.");return}u.error(`Add failed: ${t.message}`),process.exit(1)}}U();Ee();H();import{resolve as em,join as eb}from"node:path";import{readdir as tm}from"node:fs/promises";te();be();xe();Ut();Te();import se from"picocolors";async function Zh(e={},t){let r=em(e.path||process.cwd());if(console.log(),console.log(se.bold("Claude Code target")),t!=="claude"){console.log(),u.warn('Not initialized for Claude Code. Run "vespercli init --host claude" first.'),console.log();return}let n=await od(r)||Mr(r);console.log(se.dim(`Project catalog: ${n}`));let s=await Wo(r),o=Qs();s&&o&&s!==o&&u.warn(`Catalog drift: installed catalog is v${s}, but Vesper is v${o}. Run \`vespercli update\` to refresh the committed orchestrator, maintenance skills and playbook.`);let i=await Vp(r);for(let[a,c]of Object.entries(i))console.log(),console.log(se.bold(a.charAt(0).toUpperCase()+a.slice(1))),c.length===0?console.log(se.dim(" (none installed)")):c.forEach(l=>console.log(` ${l}`));console.log(),console.log(se.dim("The full specialist catalog is served by the vesper plugin (vesper:<name>) and its packs (vesper-<pack>:<name>) \u2014 see `vespercli catalog`.")),await rm(r,"claude"),console.log(),console.log(se.bold("Project files")),console.log(" CLAUDE.md (pointer), .claude/rules/vesper-{orchestrator,orchestration,context}.md, .mcp.json, .claude/settings.json"),console.log()}async function rm(e,t){let r=tt();if(console.log(),console.log(se.bold("Packs")),!r.length){console.log(se.dim(" (this package ships no packs)"));return}let{enabled:n,unknown:s}=await Lr(e,t),o=await cr(e,t),i=o!==null?await lr(o):null;for(let a of r){let c=n.includes(a)?se.green("(enabled)"):se.dim("(disabled)"),l=i?.packs.includes(a)?n.includes(a)?se.dim("\u2014 roster needs it"):se.yellow("\u2014 roster needs it: run `vespercli packs sync`"):"";console.log(` ${a} ${c} ${l}`.trimEnd())}s.length&&console.log(se.yellow(` enabled but not shipped by this package: ${s.join(", ")}`)),console.log(se.dim(" `vespercli packs` for contents; `vespercli packs sync` enables what the Team Roster names."))}async function tb(e,t){try{let r=await tm(eb(e,".vesper",t),{withFileTypes:!0});return t==="skills"?r.filter(n=>n.isDirectory()&&!n.name.startsWith(".")).map(n=>n.name).sort():r.filter(n=>n.isFile()&&n.name.endsWith(".md")).map(n=>n.name.replace(/\.(agent|instructions|prompt)\.md$|\.md$/,"")).sort()}catch{return[]}}async function rb(){try{return(await tm(Kn,{withFileTypes:!0})).filter(e=>e.isFile()&&e.name.endsWith(".md")).map(e=>e.name.replace(/\.instructions\.md$|\.md$/,"")).sort()}catch{return[]}}async function nb(e,t){let n=(await St(e)).map(o=>/\/instructions-extended\/([^/]+)\/?$/.exec(String(o).replace(/\\/g,"/"))).filter(Boolean).map(o=>o[1]).sort(),s=t.type?[t.type]:Object.keys(qe);console.log(),console.log(se.bold("GitHub Copilot target")),console.log(se.dim(`Package catalog: ${Ot}`));for(let o of s){let i=o.charAt(0).toUpperCase()+o.slice(1),a=o==="instructions"?await rb():await Zs(o),c=await tb(e,o),l=o==="instructions"?n:[];if(console.log(),console.log(se.bold(i)),!a.length&&!c.length&&!l.length){console.log(se.dim(" (none)"));continue}a.forEach(d=>console.log(` ${d} ${se.dim("(package)")}`)),l.forEach(d=>console.log(` ${d} ${se.dim("(opt-in)")}`)),c.forEach(d=>console.log(` ${d} ${se.dim("(project)")}`))}await rm(e,"copilot"),console.log()}async function nm(e={}){try{let t=em(e.path||process.cwd());await w(t)||(u.error(`Directory not found: ${u.formatPath(t)}`),process.exit(1));let r=await B(t),n=r.host,s=n?[n]:await ge(t);if(e.target==="claude")return await Zh({...e,path:t},n);if(!e.target){if((await $e(t,{checkout:r})).unmigrated&&(u.error(rt),process.exit(1)),s.length===0){console.log(),u.warn('Vesper is not initialized. Run "vespercli init" first.'),console.log();return}if(s.length>1&&(u.error(Ze),process.exit(1)),s[0]==="claude")return await Zh({...e,path:t},n)}e.type&&!qe[e.type]&&(u.error(`Unknown asset type: ${e.type}`),u.info(`Valid types: ${Object.keys(qe).join(", ")}`),process.exit(1)),await nb(t,e)}catch(t){u.error(`List failed: ${t.message}`),process.exit(1)}}Ee();import{readFileSync as sb,existsSync as ob}from"node:fs";import{join as ib}from"node:path";var Tl=ib(O,"CATALOG.md");function ab(){return ob(Tl)?sb(Tl,"utf-8"):null}async function sm(){let e=ab();e===null&&(console.error(`Error loading catalog: ${Tl} not found in the installed package.`),process.exit(1)),console.log(e)}U();H();te();be();xe();import{resolve as dm,join as zs,dirname as am}from"node:path";import{stat as cb,readFile as pm}from"node:fs/promises";import{existsSync as lb}from"node:fs";import{spawn as ub}from"node:child_process";import"@inquirer/prompts";H();ut();var om=Object.freeze(Object.keys(we)),VP=Object.freeze(["vesper-indexing","sequential-thinking","memory"]);function Pl(e,{workspaceRoot:t,env:r,indexingPath:n}){return String(e).replace(/\$\{VESPER_INDEXING_PATH\}/g,n).replace(/\$\{workspaceFolder\}/g,t).replace(/\$\{env:([^}]+)\}/g,(s,o)=>r[o]??"")}function im(e,t,{env:r=process.env,indexingPath:n=We(),which:s}={}){let o=we[e];if(!o||!o.config)return null;if(e===Vt)return{command:Fd(String(t),{env:r||{},...s?{which:s}:{}}),args:["-m","graphify.serve",`${t}/${ze}`],env:{}};let{type:i,...a}=structuredClone(o.config),c={workspaceRoot:String(t),env:r||{},indexingPath:n},l={command:Pl(a.command,c),args:(Array.isArray(a.args)?a.args:[]).map(d=>Pl(d,c)),env:{}};for(let[d,p]of Object.entries(a.env||{})){let f=Pl(p,c);f!==""&&(l.env[d]=f)}return l}ut();Te();import pt from"picocolors";async function fm(e,t){if(!t.includes(Vt))return;let r=await w(zs(e,ze));console.log(),u.info(`graphify (opt-in pack): configured \u2014 tool on PATH: ${At()?"\u2713 yes":`\u2717 no (${Zo()})`}; ${ze}: ${r?"\u2713 exists":`\u2717 missing (run \`${xt}\`)`}`)}async function cm(e,t){if(console.log(),u.header("vesper-indexing MCP Server (Claude Code target)"),console.log(),t!=="claude"){u.info("Claude Code target is not initialized. Run `vesper init --target claude` first.");return}let r=Ge(e),n=!1;if(await w(r))try{n=!!JSON.parse(await pm(r,"utf-8")).mcpServers?.["vesper-indexing"]}catch{n=!1}u.info(`Configured: ${n?"\u2713 yes":"\u2717 no"} (${r})`),u.info(`Server built: ${wm(await ym())}`);let s=jl(e);u.info(`Index exists: ${await w(s)?"\u2713 yes":"\u2717 no"} (shared with the Copilot target if both are installed)`),await fm(e,(await Rc(e)).configured);try{let{drifted:o}=await ji(e);o.length&&(console.log(),u.warn(`MCP config drift: ${o.join(", ")} present in the live MCP config but not tracked in .vesperrc mcp.servers.`),u.warn("Run `/reinit` (or re-run workspace-learner) to resync tracking and the generated docs."))}catch{}}var hm=new Set(["enable","disable","sync","add","remove"]),db=hm,mm="Vesper regenerates them at every session start \u2014 `vespercli mcp disable` makes no lasting change.";function pb(e){return`\`vespercli mcp ${e}\` for Claude Code needs a workspace provisioned for Claude \u2014 nothing was written. Run \`vespercli init --host claude\` first.`}async function Il(e,t=!0){if(await fr(e,t),t){let r=await Kp(e);r.skipped==="malformed"&&u.warn(`${r.settingsPath} is not valid JSON \u2014 MCP tool permissions were not added (the file was left as found).`)}t?u.success("Claude Code target: vesper-indexing enabled in .mcp.json"):(u.success("MCP servers removed from .mcp.json until the next session start"),u.info(mm))}function jl(e){return zs(e,".vesper","index.db")}function fb(e){return zs(e,".vesper","indexing-status.json")}async function gm(e){let t=fb(e);try{let r=await pm(t,"utf-8");return JSON.parse(r)}catch{return null}}async function ym(){let e=We();if(!await w(e))return"missing";let t=am(am(e)),r=[zs(t,"node_modules","@modelcontextprotocol","sdk","package.json"),zs(t,"node_modules","zod","package.json")];for(let n of r)if(!await w(n))return"broken";return"ready"}function wm(e){switch(e){case"ready":return"\u2713 yes";case"broken":return"\u26A0 yes, but dependencies missing \u2014 run 'npm install' in src/mcp/vesper-indexing (or reinstall Vesper)";default:return"\u2717 no"}}async function hb(e){try{let t=await cb(e),r=t.size,n=`${r} bytes`;return r>1024*1024?n=`${(r/(1024*1024)).toFixed(2)} MB`:r>1024&&(n=`${(r/1024).toFixed(1)} KB`),{dbSize:n,lastModified:t.mtime.toISOString()}}catch{return null}}async function lm(e,t=!1){let r=await No(e),n=await ym(),s=jl(e),o=await w(s),i=await gm(e);if(console.log(),u.header("vesper-indexing MCP Server"),console.log(),u.info(`Configured: ${r?"\u2713 yes":"\u2717 no"}`),u.info(`Server built: ${wm(n)}`),u.info(`Index exists: ${o?"\u2713 yes":"\u2717 no"}`),await fm(e,await Mo(e)),i)if(console.log(),i.status==="indexing")if(t){await mb(e,i);return}else{let a=i.startedAt?Math.round((Date.now()-new Date(i.startedAt).getTime())/1e3):0;u.info(pt.yellow("\u27F3 Indexing in progress...")),u.info(` Files processed: ${pt.cyan(i.filesProcessed)}`),u.info(` Elapsed: ${pt.dim(`${a}s`)}`),console.log(),u.info("Use --watch to follow indexing progress until completion")}else i.status==="error"&&(u.error(`Indexing error: ${i.error}`),u.info(` Files processed before error: ${i.filesProcessed}`));if(!r){console.log(),u.info("Run `vespercli init` to configure the MCP server");return}if(n==="missing"){console.log(),u.warn("MCP server not built. Run: cd src/mcp/vesper-indexing && npm install && npm run build");return}if(n==="broken"){console.log(),u.warn("MCP server dependencies are missing/corrupt. Run: cd src/mcp/vesper-indexing && npm install (or reinstall Vesper)");return}if(o&&!i){let a=await hb(s);a&&(console.log(),u.info(`Index size: ${a.dbSize}`),u.info(`Last modified: ${a.lastModified}`)),u.vesperTip()}else!o&&!i&&(console.log(),u.info("Index not yet created. It will be built when VS Code loads the MCP server."),console.log())}async function mb(e,t){let r=u.createSpinner(`Indexing... ${t.filesProcessed} files processed`);r.start();let n=500,s=30*60*1e3,o=Date.now();return new Promise(i=>{let a=async()=>{let c=await gm(e);if(!c||c.status!=="indexing"){c?.status==="error"?r.fail(`Indexing failed: ${c.error}`):(r.succeed(`Indexing complete! ${c?.filesProcessed||"All"} files indexed`),u.info(`
|
|
203
|
-
\u2192 Reload VS Code to update MCP tools with the new index`),u.vesperTip()),i();return}let l=c.startedAt?Math.round((Date.now()-new Date(c.startedAt).getTime())/1e3):0;if(r.update(`Indexing... ${c.filesProcessed} files processed (${l}s)`),Date.now()-o>s){r.fail("Indexing watch timed out (30 minutes)"),i();return}setTimeout(a,n)};setTimeout(a,n)})}async function
|
|
196
|
+
`:"","utf-8"),await A(_(n.dir,wl),g.map(([v,S])=>`${v} ${S}
|
|
197
|
+
`).join(""),"utf-8"),await A(_(n.dir,vl),uE,"utf-8");let y=new Set;for(let v of s){if(v!==o){let S=null;try{S=await ut(_(v.dir,"rewritten"))}catch{S=null}for(let C of S?S.files:[])!l.has(C)||y.has(C)||await w(_(o.dir,"rewritten",C))||await yh(o.dir,"rewritten",C,_(v.dir,"rewritten",C))}for(let[S]of await kl(v.dir))y.add(S)}await P(_(n.dir,$h),{recursive:!0});let k=new Date().toISOString();for(let v of s)await Sl(v.dir,{status:"finished",finishedAt:k,...v.dir===n.dir?{created:h}:{}});return h}async function jh(e,t){for(let r of await Xi(e))r.migration&&t.includes(r.dir)&&await Sl(r.dir,{guidancePrinted:!0})}async function ph(e,{homeDir:t=zs()}={}){let r=new Set;for(let n of[...e?.injectedPaths||[],...e?.readAccessPaths||[]]){let s=/^(.*?)\/assets(?:\/|$)/.exec(String(n).split("\\").join("/"));!s||s[1].includes("${")||r.add(s[1].startsWith("~/")?_(t,s[1].slice(2)):s[1])}for(let n of r)try{let s=JSON.parse(await be(_(n,"package.json"),"utf-8"));if(["@mthanh/vespercli","vespercli"].includes(s?.name)&&/^1\.\d+\.\d+/.test(s?.version||""))return s.version}catch{}return null}async function Rh(e,t,r,{homeDir:n=zs()}={}){if(t?.version)return t.version;let s=await ph(t,{homeDir:n});if(s)return s;let o=[];try{let{readVSCodeSettings:a}=await Promise.resolve().then(()=>(H(),Da)),c=await a(e);for(let[l,d]of Object.entries(c||{}))!/^chat\..*Locations$/.test(l)||!d||o.push(...(Array.isArray(d)?d:Object.keys(d)).filter(p=>typeof p=="string"))}catch{o=[]}let i=await ph({injectedPaths:o},{homeDir:n});return i||t?.config==="v1"&&r||null}async function Nh(e,{runDirs:t=[],homeDir:r=zs()}={}){let n=await Xi(e),s=new Set(t),o=n.filter(E=>E.migration&&s.has(E.dir)),i=[];if(o.length){let E=o[o.length-1];i=n.filter(b=>b.migration&&b.chainRoot===E.chainRoot&&b.name<=E.name);for(let b of i)s.add(b.dir)}let a=n.filter(E=>s.has(E.dir)&&(E.project||E.home||E.rewritten||E.migration||E.outside.length));if(!a.length)return[];let c=n.filter(E=>!s.has(E.dir)),l=c.filter(E=>E.migration&&E.status==="abandoned"),d=E=>`"${E}"`,p=[];p.push(`Migration backups (${a.length}) \u2014 in ${_(e,Fr)}, gitignored; keep them until you are happy with 2.0${a.length>1?" (an interrupted run was completed: ALL its folders are listed, oldest first)":""}:`);for(let E of a)p.push(` ${E.dir}${E.home?" (holds home-directory files too)":""}${E.outside.length?" (holds files from outside the workspace too)":""}`);if(c.length&&p.push(` (${c.length} other folder(s) there belong to an earlier migration or cleanup \u2014 the commands below never use them)`),l.length){p.push(" Abandoned interrupted migration(s) \u2014 never resumed, kept in case they hold a file you need; remove them when you no longer do (rm -rf):");for(let E of l)p.push(` ${E.dir}`)}let f=E=>E.outside.map(b=>`cp -R -p ${d(_(E.dir,b.backup))} ${d(b.original)}`),m=[];for(let E of a)E.project&&m.push(`cp -R ${d(_(E.dir,"project"))}/. ${d(e)}/`),E.home&&m.push(`cp -R ${d(_(E.dir,"home"))}/. ${d(r)}/`),m.push(...f(E));if(m.length){p.push("Recover the files the migration REMOVED (copies them back; this alone is not a rollback):");for(let E of m)p.push(` ${E}`)}if(!i.length)return p;let h=i[0],g=i[i.length-1],y=g.created,k=i.map(E=>E.previousVersion).find(Boolean),v=h.head?await Qi(e):null;h.head&&v&&v!==h.head&&p.push(`Note: HEAD is now ${v.slice(0,12)}, not ${h.head.slice(0,12)} (the commit this migration started from). The rollback below still restores the migrated paths to ${h.head.slice(0,12)}'s committed layout \u2014 changes committed since to those paths are undone in the working tree (they stay in git history).`),p.push(`Roll back THIS migration to 1.x completely (back to its starting commit ${h.head?h.head.slice(0,12):"(no git)"}; run from the workspace root, in this order):`);let S=1;if(h.head){let E=h.head.slice(0,12);p.push(` ${S++}. [ "$(git rev-parse HEAD)" = "${h.head}" ] || echo "Warning: HEAD is no longer ${E}, the commit this migration started from - the restore below returns the migrated paths to ${E}'s layout; review git status/diff afterwards." >&2 (a check only: it changes nothing)`)}if(y.length&&g.createdChecked?p.push(` ${S++}. sh ${d(_(g.dir,vl))} (removes the ${y.length} file(s) this migration created, incl. its git hooks: ${y.slice(0,4).join(", ")}${y.length>4?", \u2026":""} \u2014 only while each still holds the bytes the migration wrote; a file changed since is kept and named)`):y.length&&p.push(` ${S++}. while IFS= read -r f; do rm -f -- "$f"; done < ${d(_(g.dir,"created.txt"))} (the ${y.length} file(s) this migration created, incl. its git hooks: ${y.slice(0,4).join(", ")}${y.length>4?", \u2026":""})`),h.rewritten&&p.push(` ${S++}. cp -R ${d(_(h.dir,"rewritten"))}/. ${d(e)}/ (every whole file init rewrote, incl. the gitignored .vesperrc / .mcp.json and the git hooks, as they were when this migration started)`),h.head&&h.trackedPaths.length){let E=_(h.dir,"tracked-paths.txt");p.push(` ${S++}. git -c core.hooksPath=${d(_(g.dir,$h))} restore --source=${h.head} --staged --worktree --pathspec-from-file=${d(E)} (the committed layout; hooks disabled for this one command; the migration refused to start on uncommitted changes, so this is exact)`)}let C=[];for(let E of i)E.project&&C.push(`cp -R ${d(_(E.dir,"project"))}/. ${d(e)}/`),E.home&&C.push(`cp -R ${d(_(E.dir,"home"))}/. ${d(r)}/`),C.push(...f(E));C.length&&p.push(` ${S++}. ${C.join(" && ")} (the removed files)`);let N=k&&/^1\.9\./.test(k)?`; ${k} was never published to npm \u2014 install it from the repository's ${k} commit, or pin 1.8.0`:"";return p.push(` ${S++}. npm install -g @mthanh/vespercli@${k||"<your previous 1.x version>"} (LAST: pin the previous CLI \u2014 any 2.x CLI migrates again${N})`),p}async function Lh(e,t,{legacy:r,recordHost:n,frameworkVersion:s,homeDir:o=zs(),now:i=new Date,log:a,backup:c}={}){let l=await Ii(e),d=a||{info(){},success(){},warn(){}},p=c||gl(e,{now:i,homeDir:o}),f={record:l,backupDir:null,relocated:[],recorded:[],removed:[],moved:[],kept:[],homeLookalikes:[],settings:null},m=(b,F,X={})=>f.kept.push({rel:b,reason:F,...X}),h=async(b,F)=>{try{return await F()}catch(X){m(b,"error",{detail:String(X?.message||X)});return}},g=await yl(e),y=g?["pre-commit","post-checkout"].map(b=>`${g}/${b}`):[];for(let b of[...mh,...await Eh(e),...y])await h(b,()=>p.snapshot(b));let k=l;if(l.config==="v2"&&l.recordedHost){let b=null;try{b=(await B(e)).host}catch{b=null}if(l.recordedHost!==b){let F=l.recordedHost;d.info(`This worktree's 2.0 record describes another branch (${F}); migrating this 1.x checkout from its files.`),k=Object.freeze({...l,catalogManifest:[],injectedPaths:[],readAccessPaths:[],mcpServers:[],vendored:void 0,hosts:{claude:!1,copilot:!1}}),await h(".vesperrc",async()=>{let X=await x(e);X.manifest=J(X).filter(He=>He.host!==F||Le.has(He.category)),delete X.host,await T(e,X)})}}let v=await Sh(e,k);await fE(e,t,{backup:p,result:f,safely:h,keep:m,catalog:v});let S=[];for(let b of v.record)await h(b.rel,async()=>(await p.project(b.rel),!0))&&(S.push(b.entry),f.recorded.push(b.rel));for(let b of v.keep)m(b.rel,b.reason,b.files?{files:b.files}:{});let C=".claude/vesper/orchestrator.md";await w(_(e,C))&&await h(C,async()=>{let b=await be(_(e,C));if(!op(b)){m(C,"edited-playbook");return}await p.project(C),await le(_(e,C),{path:C,category:"playbook",hash:dt(b)})==="removed"&&f.removed.push(C)});try{await fh(_(e,".claude","vesper"))}catch{}t==="copilot"&&(f.settings=await h(".vscode/settings.json",()=>en(e,{trackedPaths:k.injectedPaths,trackedReadAccess:k.readAccessPaths})));let N=await ji({homeDir:o}).catch(()=>[]);if(f.homeLookalikes=N.filter(b=>b.tier===3),(await x(e)).schemaVersion===ve){await ln(e,{frameworkVersion:s}),S.length&&await W(e,S);let b=await x(e);!b.host&&n&&(b.host=n,await T(e,b))}else await ln(e,{frameworkVersion:s,legacyEntries:S,host:n});return f.kept.length&&await h("kept.json",()=>Al(p,f.kept)),f.backup=p,f.backupDir=p.items.length?p.dir:null,mE(f,d),f}async function Al(e,t){e.keptRows??=[];for(let r of t)e.keptRows.push({rel:r.rel,reason:r.reason,...r.files?{files:r.files}:{},...r.detail?{detail:r.detail}:{}});return e.writeSidecar("kept.json",`${JSON.stringify(e.keptRows,null,2)}
|
|
198
|
+
`)}async function fE(e,t,{backup:r,result:n,safely:s,keep:o,catalog:i}){let a=null,c=new Set;if(t==="claude"){a=await _t();let d=new Set((i?.record||[]).map(p=>p.rel));for(let p of a.agents){let f=`.claude/agents/${p}.md`;!d.has(f)&&await w(_(e,f))&&c.add(p)}}let l=[{key:"orchestration",claudeDest:".claude/rules/vesper-orchestration.md",copilotDest:je("vesper-orchestration"),tpl:"orchestration.md.tpl",sources:[{rel:".claude/vesper/orchestration.md",vesper:()=>!0,move:!0},{rel:".github/instructions/orchestration.instructions.md",vesper:aE,move:!0,unmarked:"report"}]},{key:"context",claudeDest:".claude/rules/vesper-context.md",copilotDest:je("vesper-context"),tpl:"context.md.tpl",sources:[{rel:".claude/vesper/context.md",vesper:()=>!0,move:!0},{rel:".github/copilot-instructions.md",vesper:cE,move:!1,unmarked:"claude-only"}]}];for(let d of l){let p=t==="claude"?d.claudeDest:d.copilotDest,f=null;for(let m of d.sources){let h=_(e,m.rel),g=(await kh(h))?.toString("utf-8");if(g===void 0)continue;let y=m.vesper(g);if(!y&&m.unmarked==="report"){o(m.rel,"unmarked-knowledge");continue}if(!y&&m.unmarked==="claude-only"&&t!=="claude"){o(m.rel,"github-own");continue}if(f||await w(_(e,p))){let k="duplicate-knowledge";m.move||(k=y?f?"github-brain-kept":"github-brain-dest":"github-own"),o(m.rel,k);continue}await s(m.rel,async()=>{let{body:k}=ht(g),v=k.replace(/^\n+/,"");if(t==="claude"&&d.key==="orchestration"){let E=wd(v);n.rosterRetired=E.removed;let b=qo(E.text,a,{skip:c});v=b.text,n.rosterQualified=b.qualified}let S=t==="claude"?`${await dh(d.tpl)}${v}`:Zc(ht(g).frontmatter===null?`${await dh(d.tpl)}${k}`:g,`Vesper ${d.key}`),C=_(e,p);if(await P(hl(C),{recursive:!0}),await A(C,S,"utf-8"),await be(C,"utf-8")!==S)throw new Error(`could not verify ${p}`);if(f=m.rel,!m.move||!y){n.relocated.push({from:m.rel,to:p,copied:!0}),o(m.rel,m.move?"unmarked-knowledge":"github-brain");return}n.relocated.push({from:m.rel,to:p}),await r.project(m.rel),await le(h,{path:m.rel,category:"relocated-original"},{expected:[Buffer.from(g,"utf-8")]})==="removed"&&n.moved.push({from:m.rel,to:p})})}}for(let d of[".github/instructions",".github"])try{await fh(_(e,d))}catch{}if(t==="copilot"){let d=_(e,".claude","vesper","context"),p=[];try{p=(await ut(d)).files}catch{p=[]}for(let f of p){let m=_(e,".vesper","context",f);await w(m)||await s(`.claude/vesper/context/${f}`,async()=>{await P(hl(m),{recursive:!0}),await A(m,await be(_(d,f))),n.relocated.push({from:`.claude/vesper/context/${f}`,to:`.vesper/context/${f}`,copied:!0})})}}}function hE(e,{max:t=5}={}){let r=new Map;for(let s of e)r.has(s.reason)||r.set(s.reason,[]),r.get(s.reason).push(s.rel);let n=[];for(let[s,o]of r){let i=o.slice(0,t).join(", ")+(o.length>t?`, \u2026 +${o.length-t} more`:"");n.push(`Kept ${o.length} \u2014 ${iE[s]||s}: ${i}`)}return n}function mE(e,t){for(let{from:r,to:n,copied:s}of e.relocated)s&&t.info(`Copied ${r} \u2192 ${n}`);for(let{from:r,to:n}of e.moved)t.info(`Moved your ${r} \u2192 ${n} (your project knowledge; the original is backed up)`);if(e.relocated.some(r=>/vesper-orchestration\.md$/.test(r.to))){let r=e.rosterQualified?.length||0;for(let n of e.rosterRetired||[])t.info(`Removed retired roster row: ${n.role} (${n.agent}) \u2014 replaced by ${n.replacement}`);r?t.info(`Team roster relocated \u2014 ${r} specialist name(s) namespaced to \`vesper:<name>\` for the plugin.`):e.rosterQualified===void 0&&t.info("Team roster relocated \u2014 run `/revalidate-team` once: 2.0 delegates to the plugin's specialists by `vesper:<name>` (doctor reminds you until then).")}e.recorded.length&&t.info(`Retiring ${e.recorded.length} 1.x catalog item(s) byte-identical to a released 1.x build \u2014 the vesper plugin serves them now (backed up): ${e.recorded.slice(0,8).join(", ")}${e.recorded.length>8?", \u2026":""}`);for(let r of e.removed)t.info(`Removed ${r} (byte-identical to a released 1.x Vesper file; backed up)`);for(let r of e.settings?.removed||[])t.info(`Removed the 1.x settings location ${r} (2.0 injects each assets/copilot/<type> folder whole)`);for(let r of hE(e.kept))t.warn(r);if(e.homeLookalikes.length){let r=e.homeLookalikes.slice(0,5).map(n=>`~/${n.rel}`).join(", ")+(e.homeLookalikes.length>5?", \u2026":"");t.info(`FYI: ${e.homeLookalikes.length} Vesper-looking item(s) in your home directory (${r}). Vesper 1.x never wrote these locations, so they are yours \u2014 left untouched, and not mentioned again.`)}}U();import{join as Ol}from"node:path";U();at();vt();import{rename as gE}from"node:fs/promises";import{dirname as yE,join as Mh}from"node:path";async function Zi(e,t,r){let n=Mh(e,t),s=Mh(e,r);if(!await w(n))return{ok:!1,reason:"missing"};if(await w(s))return{ok:!1,reason:"exists"};await P(yE(s),{recursive:!0});let o={...process.env,...Rt};return await D(["rev-parse","--is-inside-work-tree"],{cwd:e,env:o})==="true"&&(await Pt(["--literal-pathspecs","ls-files","--error-unmatch","--",t],{cwd:e,env:o})).ok&&await D(["--literal-pathspecs","status","--porcelain","--",t],{cwd:e,env:o})===""&&(await Pt(["--literal-pathspecs","mv","--",t,r],{cwd:e,env:{...process.env,...Hn}})).ok?{ok:!0,method:"git"}:(await gE(n,s),{ok:!0,method:"rename"})}U();import{readdir as wE,readFile as vE}from"node:fs/promises";import{join as ea}from"node:path";var Cl=".vesper/.tracking/runs",Js=Object.freeze(["started","completed","note","delegated","returned"]),Gh=Object.freeze(["DONE","NEED_HELP","BLOCKED"]),kE="adhoc",ta=5,Tn=Object.freeze({OK:0,INVALID:2}),SE=Object.freeze(["ts","event","pipeline","step","agent","goal","author","status","note"]),EE=Object.freeze({started:["goal"],completed:["status"],note:[],delegated:["agent"],returned:["agent","status"]});function Fh(e){return String(e??"").toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/-{2,}/g,"-").replace(/^-|-$/g,"")||kE}function $l(e=new Date){return e.toISOString().slice(0,10).replace(/-/g,"")}function bE(e,t=new Date){return`${$l(t)}-${Fh(e)}.jsonl`}function Ys(e){return typeof e=="string"&&e.trim()!==""}function Dh(e={},{now:t=new Date}={}){let r=[],n=typeof e.event=="string"?e.event.trim():"";Js.includes(n)||r.push(`event must be one of ${Js.join("|")} (received "${n}")`),Ys(e.pipeline)||r.push("--pipeline is required");for(let o of EE[n]||[])Ys(e[o])||r.push(`--${o} is required for \`${n}\``);if(e.status!==void 0&&e.status!==null&&!Gh.includes(String(e.status))&&r.push(`--status must be one of ${Gh.join("|")} (received "${e.status}")`),r.length)return{ok:!1,errors:r};let s={ts:t.toISOString(),event:n};for(let o of SE.slice(2))s[o]=Ys(e[o])?e[o].trim():null;return Ys(e.session)&&(s.session=e.session.trim()),{ok:!0,row:s}}async function Vh(e,t,{slug:r,now:n=new Date}={}){let s=ea(e,Cl);await P(s,{recursive:!0});let o=bE(r,n),i=ea(s,o),a=`${JSON.stringify(t)}
|
|
199
|
+
`;return await A(i,a,{encoding:"utf-8",flag:"a"}),{rel:`${Cl}/${o}`,abs:i,line:a}}function _l(e){let t=/^\d{8}-(.+)\.jsonl$/.exec(e);return t?t[1]:null}async function Hh(e,{slug:t}={}){let r=ea(e,Cl);if(!await w(r))return{rows:[],files:[],malformed:0};let n=t?Fh(t):null,s=(await wE(r)).filter(c=>c.endsWith(".jsonl")&&_l(c)!==null&&(!n||_l(c)===n)).sort(),o=[],i=0,a=0;for(let c of s){let l=await vE(ea(r,c),"utf-8");for(let d of l.split(`
|
|
200
|
+
`))if(d.trim()!=="")try{let p=JSON.parse(d);if(!p||typeof p!="object"||Array.isArray(p)){i+=1;continue}o.push({...p,slug:_l(c),__order:a++})}catch{i+=1}}o.sort((c,l)=>{let d=typeof c.ts=="string"?c.ts:"",p=typeof l.ts=="string"?l.ts:"";return d<p?-1:d>p?1:c.__order-l.__order});for(let c of o)delete c.__order;return{rows:o,files:s,malformed:i}}function Uh(e,t=ta){let r=Number.isFinite(t)?Math.max(0,Math.floor(t)):ta;return r===0?[]:e.slice(-r)}function Wh(e){let t=[String(e.ts??"-"),String(e.event??"-").padEnd(9),String(e.pipeline??"-")];e.slug&&t.push(`[${e.slug}]`);for(let r of["step","agent","status","author","session"])e[r]!==null&&e[r]!==void 0&&e[r]!==""&&t.push(`${r}=${e[r]}`);return e.goal&&t.push(`goal="${e.goal}"`),e.note&&t.push(`\u2014 ${e.note}`),t.join(" ")}function Kh(e){let t;try{t=JSON.parse(String(e??""))}catch{return null}if(!t||typeof t!="object"||Array.isArray(t))return null;let r=n=>Ys(t[n])?t[n].trim():null;return{agent:r("agent_type"),agentId:r("agent_id"),session:r("session_id")}}var ra=".vesper/history.md",Bh=".vesper/history-archive";function zh(e=new Date,t=0){return`history-${$l(e)}${t>0?`-${t}`:""}.md`}async function Yh(e,{now:t=new Date}={}){if(!await w(Ol(e,ra)))return{archived:!1};let r=Ol(e,Bh);await P(r,{recursive:!0});let n=0,s=zh(t,n);for(;await w(Ol(r,s));)n+=1,s=zh(t,n);let o=`${Bh}/${s}`,i=await Zi(e,ra,o);if(!i.ok)throw new Error(`Could not archive ${ra}: ${i.reason}`);return{archived:!0,from:ra,to:o,method:i.method}}Kt();Tr();U();Ae();te();H();import{resolve as AE}from"node:path";import ae from"picocolors";Kt();pn();ft();import{confirm as _E}from"@inquirer/prompts";at();vt();Tr();var na=3e3;async function xE(e,{timeoutMs:t=na,env:r}={}){let n=await Pt(["ls-remote","--",e,"HEAD"],{timeout:t,env:Un(xr(r??process.env)),detached:!0});if(!n.ok)return null;let s=n.stdout.split(`
|
|
201
|
+
`).map(o=>o.trim()).find(o=>/^[0-9a-f]{40}\s+HEAD$/.test(o));return s?s.slice(0,40):null}async function sa({assetsDir:e,timeoutMs:t=na,env:r}={}){let n=[];for(let{pack:s,skill:o,record:i}of await Yu(e)){let a=typeof i?.upstream=="string"?i.upstream:null,c=typeof i?.sha=="string"?i.sha:null;if(!a||!c){n.push({skill:o,pack:s,upstream:a,pinned:c,remote:null,stale:null,status:"no-record"});continue}let l=await xE(a,{timeoutMs:t,env:r});if(!l){n.push({skill:o,pack:s,upstream:a,pinned:c,remote:null,stale:null,status:"unreachable"});continue}let d=l!==c;n.push({skill:o,pack:s,upstream:a,pinned:c,remote:l,stale:d,status:d?"stale":"current"})}return n}function Jh(e){return`\`${e.skill}\` has a newer upstream (${e.upstream} is at ${e.remote.slice(0,12)}, the package ships ${e.pinned.slice(0,12)}); the next Vesper release picks it up.`}Ie();var qh=["list","enable","disable","sync","upstream"];function CE(e,{log:t=console.log}={}){if(t(),t(ae.bold("Third-party pack skills \u2014 upstream check")),t(ae.dim("Pinned = the commit the shipped snapshot was taken at (UPSTREAM.json); remote = upstream HEAD now.")),t(),!e.length){t(ae.dim(" (this package ships no third-party skills)")),t();return}let r=Math.max(...e.map(s=>s.skill.length));for(let s of e){let o=s.status==="stale"?ae.yellow("newer upstream"):s.status==="current"?ae.green("current"):s.status==="unreachable"?ae.dim("unreachable"):ae.red("no record"),i=s.pinned?s.pinned.slice(0,12):"\u2014",a=s.remote?s.remote.slice(0,12):"\u2014";t(` ${s.skill.padEnd(r)} ${s.pack.padEnd(12)} pinned ${i} remote ${a} ${o}`)}t();let n=e.filter(s=>s.status==="stale");n.length&&t(ae.dim(`A newer upstream reaches projects with the next Vesper release (maintainers: npm run vendor:sync ${n.map(s=>s.skill).join(" ")}).`)),t()}function Hr(e,{log:t=u}={}){if(!e.rosterFound){t.info(`Packs: no Team Roster at ${e.rosterPath} yet \u2014 nothing to enable (run \`vespercli packs sync\` after the roster is written).`);return}e.enabled.length&&t.success(`Packs enabled for ${e.host}: ${e.enabled.map(Me).join(", ")} (named by the Team Roster).`),e.already.length&&t.info(`Packs already enabled: ${e.already.map(Me).join(", ")}.`),!e.enabled.length&&!e.already.length&&t.info("Packs: the Team Roster names core assets only \u2014 no pack needed."),e.unused.length&&t.info(`Packs enabled but unused by the Team Roster (kept; \`vespercli packs disable <pack>\` removes one): ${e.unused.join(", ")}.`),e.unknownAgents.length&&t.dim(` roster agents not in the catalog (project agents or typos): ${e.unknownAgents.join(", ")}`),e.unknownSkills.length&&t.dim(` roster skills not in the catalog (project skills or typos): ${e.unknownSkills.join(", ")}`)}function Tl(e){if(!e)return;let{gitignore:t,hook:r,mcp:n}=e;(t.status==="created"||t.status==="updated")&&u.info(" .gitignore block written: graphify-out/* ignored, graphify-out/graph.json committed"),t.status==="kept-edited"&&u.warn(bs(t.path)),r.status==="created"&&u.info(` post-checkout hook block written (\`graphify update .\` after a branch checkout, no-op without the tool): ${r.path}`),r.status==="kept-edited"&&u.warn(bs(r.path)),r.status==="skipped"&&u.info(` post-checkout hook block not written (${r.reason}) \u2014 run \`vespercli worktree bootstrap\` to install Vesper's hooks, then \`vespercli packs enable graphify\` again.`),n?.added?u.info(" MCP server registered: graphify (`vespercli mcp remove graphify` removes it)"):n?.error&&n.error!=="Already configured"&&u.warn(` MCP server not registered: ${n.error}`);for(let s of Dd())u.info(` ${s}`)}async function Pl({interactive:e,plan:t,confirmImpl:r=_E,spawnImpl:n,env:s=process.env}){if(rt(s))return{status:"present"};let o=t??gn({env:s});if(!e||!o.command)return{status:"skipped",plan:o};if(!await r({message:`Install graphifyy now? (${o.command})`,default:!0}))return{status:"declined",plan:o};u.info(`Running \`${o.command}\` \u2026`);let a=await Hd(o,n?{spawn:n}:{});if(a.ok){let c=!!rt(s);return u.success(`graphify installed${c?"":" (not on PATH in this shell yet \u2014 open a new shell, or add the installer's bin directory to PATH)"}. Run \`${Se}\` to build the graph.`),{status:"installed",plan:o,code:a.code}}return u.warn(`\`${o.command}\` failed${a.code!=null?` (exit ${a.code})`:a.error?` (${a.error})`:""} \u2014 nothing else changed. ${o.hint}`),{status:"failed",plan:o,code:a.code,error:a.error}}async function Il(e,{spawnImpl:t,env:r=process.env}={}){if(!rt(r))return{status:"no-binary"};if(Wd(e))return{status:"graph-exists"};u.info(`Building the code graph (${Se}) \u2014 first build takes about half a minute\u2026`);let n=await Ud(e,{env:r,...t?{spawn:t}:{}});return n.ok?(u.success(`Code graph built: ${ke} (commit it \u2014 the post-checkout hook keeps it fresh).`),{status:"built",code:n.code}):(u.warn(`\`${Se}\` failed${n.code!=null?` (exit ${n.code})`:n.error?` (${n.error})`:""} \u2014 the pack stays enabled; run \`${Se}\` by hand.`),{status:"failed",code:n.code,error:n.error})}function $E(e){if(!e)return;let{gitignore:t,hook:r,mcp:n}=e;t.status==="removed"&&u.info(" .gitignore block removed"),t.status==="kept"&&u.warn(bs(t.path)),r.status==="removed"&&u.info(` post-checkout hook block removed: ${r.path}`),r.status==="kept"&&u.warn(bs(r.path)),n?.removed&&u.info(" MCP server removed: graphify"),u.info(" graphify-out/graph.json (if any) is yours to keep or delete; the tool itself is not touched.")}async function OE(e,t){let r=await B(e);(await Te(e,{checkout:r})).unmigrated&&(u.error(st),process.exit(1));let n=r.host?[r.host]:await ge(e);!t.target&&n.length>1&&(u.error(et),process.exit(1));let s=t.target||r.host||null;return{host:s,provisioned:!!r.host&&r.host===s}}function Xh({host:e,provisioned:t},r){t||(e?u.error(`\`vespercli packs ${r}\` for ${e} needs a workspace provisioned for ${e} \u2014 nothing was written. Run \`vespercli init --host ${e}\` first.`):u.error(`\`vespercli packs ${r}\` needs a workspace provisioned for a host \u2014 nothing was written. Run \`vespercli init\` first.`),process.exit(1))}async function TE(e,{host:t}){let r=nt(),{enabled:n,unknown:s}=t?await Mr(e,t):{enabled:[],unknown:[]},o=t?await ur(e,t):null,i=o!==null?await dr(o):null;if(console.log(),console.log(ae.bold("Vesper packs")),console.log(ae.dim(t?`Host: ${t}${o===null?` (no Team Roster at ${kn[t]})`:""}`:"Host: not provisioned (catalog only)")),console.log(ae.dim("Core (vesper) is always enabled; a pack is enabled when the Team Roster names one of its assets (`vespercli packs sync`).")),console.log(),!r.length){console.log(ae.dim(" (this package ships no packs)")),console.log();return}for(let a of r){let{agents:c,skills:l}=yp(a),d=n.includes(a)?ae.green("enabled"):ae.dim("disabled"),p=i?.needed[a],f=p?` \u2014 roster needs it: ${[...p.agents,...p.skills].join(", ")}`:i?ae.dim(" \u2014 not named by the roster"):"";console.log(` ${ae.bold(a)} (${Me(a)}) ${d}${f}`),console.log(ae.dim(` agents: ${c.join(", ")||"\u2014"}`)),console.log(ae.dim(` skills: ${l.join(", ")||"\u2014"}`)),jr(a)&&console.log(ae.dim(" opt-in: enabling writes an always-on pointer rule that applies these styles (`vespercli packs enable styles`)")),a===Ge&&console.log(ae.dim(` opt-in: graphify is an external tool (\`${ei}\`); enabling adds the gitignore + post-checkout blocks and the graphify MCP server (\`vespercli packs enable graphify\`)`))}if(s.length&&(console.log(),u.warn(`Enabled pack keys this package does not ship: ${s.join(", ")} (an older/newer Vesper wrote them; \`vespercli packs disable <pack>\` cannot remove an unknown pack \u2014 edit the settings by hand).`)),i){let a=i.packs.filter(c=>!n.includes(c));console.log(),a.length?u.warn(`The Team Roster needs ${a.join(", ")} but they are not enabled \u2014 run \`vespercli packs sync\`.`):u.success("Every pack the Team Roster needs is enabled.")}console.log()}async function Qh(e="list",t,r={}){try{let n=AE(r.path||process.cwd());await w(n)||(u.error(`Directory not found: ${u.formatPath(n)}`),process.exit(1));let s=e||"list";qh.includes(s)||(u.error(`Unknown packs subcommand: ${s}. Subcommands: ${qh.join(", ")}`),process.exit(1));let o=await OE(n,r);if(s==="list")return await TE(n,o);if(s==="upstream"){CE(await sa());return}if(s==="sync"){Xh(o,"sync");let l=await pr(n,o.host);Hr(l);return}if(t||(u.error(`\`vespercli packs ${s}\` needs a pack name. Packs: ${nt().join(", ")||"none"}`),process.exit(1)),nt().includes(t)||(u.error(`Unknown pack "${t}". Packs: ${nt().join(", ")||"none"}`),process.exit(1)),Xh(o,s),s==="enable"){let{enabled:l,rule:d,graphify:p}=await lr(n,o.host,t);l?u.success(`Enabled the ${t} pack (${Me(t)}) for ${o.host}.${o.host==="copilot"?" Reload VS Code to apply.":""}`):u.info(`The ${t} pack is already enabled for ${o.host}.`),(d?.status==="created"||d?.status==="updated")&&u.info(` always-on pointer rule written: ${d.path}`),d?.status==="kept-edited"&&u.warn(ic(d.path)),Tl(p),t===Ge&&(await Pl({interactive:!!process.stdin.isTTY}),await Il(n));return}let{disabled:i,rule:a,graphify:c}=await Ep(n,o.host,t);if(a?.status==="removed"&&u.info(` always-on pointer rule removed: ${a.path}`),a?.status==="kept"&&u.warn(ic(a.path)),$E(c),i){u.success(`Disabled the ${t} pack (${Me(t)}) for ${o.host}.`);let l=await ur(n,o.host);l!==null&&(await dr(l)).packs.includes(t)&&u.warn(`The Team Roster still names assets of the ${t} pack \u2014 \`vespercli doctor\` will report it; \`vespercli packs sync\` re-enables it.`)}else u.info(`The ${t} pack was not enabled for ${o.host}.`)}catch(n){u.error(`Packs failed: ${n.message}`),process.exit(1)}}ft();Ie();var jl=["copilot","claude"];function FE(e,t){return ec(e)}async function DE(e,t,{settingsEntries:r,hooksDir:n=null,hookNames:s,version:o}={}){await ln(e,{frameworkVersion:o}),await cd(e,t);let i=await Za(e,t,{settingsEntries:r,hooksDir:n,hookNames:s});await W(e,FE(i,t)),await dd(e)}function em(e){return e==="claude"?"Claude Code + OpenCode":"GitHub Copilot"}async function tm(e,t,{thirdPartyBackup:r=null}={}){let n=await Qf(e,{backup:r||void 0}),{info:s,warn:o}=Zf(n);for(let i of s)u.info(i);if(o&&u.warn(o),n.stylesConsent)try{await lr(e,t,Bu)}catch(i){u.warn(`Could not enable the styles pack (${i?.message??i}); run \`vespercli packs enable styles\` by hand.`)}}async function VE(e,t,{legacyHint:r,checkout:n}={}){let s=await ge(t),o=n?n.host:await on(t),i=o?[o]:s,a=()=>{u.error("Vesper 2.0 provisions exactly one host per workspace \u2014 pass a single `--host claude` or `--host copilot` (not `all` or a comma list)."),process.exit(1)},c=e.host;if(!c&&e.target&&(u.warn("`--target` is deprecated on `init`; use `--host` instead."),c=e.target),c){let h=String(c).toLowerCase();h==="all"&&a();let g=[...new Set(h.split(",").map(y=>y.trim()).filter(Boolean))];for(let y of g)jl.includes(y)||(u.error(`Unknown host: ${y}. Valid hosts: copilot, claude`),process.exit(1));return g.length>1&&a(),{selected:g,installed:i}}let l=await Ft(t),d=l&&jl.includes(l.to)?l.to:null,p=r?.needsMigration?jl.filter(h=>r.hosts?.[h]):[],f=d??(p.length>1?null:o??p[0]??null);if(!process.stdin.isTTY){let h=s.length===1?s[0]:null;if(f&&(p.length===0||(o??h)===f))return{selected:[f],installed:i};u.error(p.length?`Non-interactive run on a pre-2.0 Vesper workspace (${p.join(" + ")}) without --host. Vesper 2.0 provisions exactly one host \u2014 re-run with --host claude or --host copilot to migrate.`:"Non-interactive run without --host, and this checkout carries no Vesper provisioning \u2014 specify the single platform, e.g. --host copilot or --host claude."),process.exit(1)}return{selected:[await GE({message:i.length?"Host for this workspace (Vesper provisions exactly one):":"Which AI host is this workspace for?",choices:[{name:"GitHub Copilot (VS Code)",value:"copilot"},{name:"Claude Code + OpenCode (Claude Code CLI / VS Code extension / JetBrains / desktop; OpenCode reads the same setup)",value:"claude"}],...f?{default:f}:{}})],installed:i}}function HE(e){if(!e)return;console.log();let t=e.level==="warn"?u.warn:u.success;for(let r of e.lines)t(r);console.log()}async function UE(e,t,{backup:r,workspaceRoot:n}={}){let s=await bi({staleDir:void 0,dryRun:!0,workspaceRoot:n});if(s.reason==="absent"||s.reason==="not-ours"||!s.proven?.length)return null;let o=t;if(t||(o=await zt({message:`Clean the pre-1.9 MACHINE-WIDE Vesper Claude catalog at ${s.path}? ${s.proven.length} file(s) there are byte-identical to a released Vesper build and are removed (backed up first); ${s.kept.length?`${s.kept.length} other file(s) (your edits or your own files) are kept. `:""}Every other pre-1.9 Vesper project on this machine loses its specialists until you run \`vespercli init\` in it.`,default:!0})),!o)return u.info("Left the stale machine-wide Vesper Claude catalog in place (`vespercli doctor` names it)."),null;let i=await bi({backup:r,workspaceRoot:n});return HE(qp(i)),i}async function WE(e,t={},r=!1){let n="";console.log(),u.header("Installing Vesper for Claude Code"),console.log();let{pluginDir:s,counts:o,pruned:i,keptEdited:a=[]}=await Si({workspaceRoot:e,namePrefix:n,version:t.version});u.success(`Committed fallback surface installed: ${s}`),u.info(` main-thread agent: ${o.agents} (vesper-orchestrator), maintenance skills: ${o.skills}`),u.info(" full specialist catalog served via the vesper marketplace plugin (see .claude/settings.json)"),i.length&&u.info(` pruned ${i.length} legacy project-committed asset(s): ${i.join(", ")}`),a.length&&u.warn(`Left in place \u2014 no longer shipped, but they hold your edits, so Vesper could not prove them its own and no longer tracks them: ${a.map(f=>`.claude/${f}`).join(", ")}. Delete them yourself if you do not need them.`);let c=await xi(e);u.success("Project files ready:"),u.info(` .claude/rules/vesper-orchestrator.md (${c.orchestrator})`),u.info(` .claude/rules/vesper-orchestration.md (${c.orchestration})`),u.info(` .claude/rules/vesper-context.md (${c.context})`),u.info(` .vesper/gates.json (${c.gates})`),u.info(` CLAUDE.md pointer (${c.claudeMd})`);let l=await mr(e,!0),d=await ef(e);u.success(`MCP servers configured: .mcp.json (${l.servers.join(", ")})`);let p=d.opencode||{};u.success("OpenCode overlay ready (the same setup, read by OpenCode):"),u.info(` opencode.json (${p.status||"unchanged"}${p.status==="skipped-malformed"?" \u2014 the file does not parse as JSON; fix it and re-run":""})`),u.info(` .opencode/agents/vesper-orchestrator.md (${c.opencodeAgent})`),u.info(` .opencode/plugins/vesper.js (${c.opencodePlugin})`),c.opencodeKept?.length&&u.warn(`Left in place \u2014 they differ from what Vesper writes (your edits, or an older build's copy), so Vesper could not prove them its own and no longer tracks them: ${c.opencodeKept.join(", ")}. Delete them to get this version's copy on the next init.`),Hr(await pr(e,"claude")),await tm(e,"claude",t),await af(e,{pluginPath:Gr(e),namePrefix:n,mcpConfigPath:Ve(e),settingsPath:Fe(e),installedAt:new Date().toISOString()})}async function KE(e,t,r,n={}){console.log(),u.header("Configuring GitHub Copilot"),console.log(),await en(e);let s=await No(e);await Po(e,{maxRequests:r.maxRequests,omitBaseAgentInstructions:r.omitBaseAgentInstructions});let o=await To(e,r.terminalEnableAutoApprove),i=!1;r.enableMcpServer&&(i=(await Hs(e,!0)).configured,await Fo(e)),await Zn(e);let a=await Vi(e,{version:n.version});return await el(e,{settingsEntries:await At(e)}),Hr(await pr(e,"copilot")),await tm(e,"copilot",n),u.success("Core assets ensured: agents, prompts, instructions, skills"),u.success("Project brain ready:"),u.info(` .vesper/agents/vesper-orchestrator.agent.md (${a.orchestratorAgent}) \u2014 the one pickable agent`),u.info(` .vesper/instructions/vesper-orchestrator.instructions.md (${a.orchestrator})`),u.info(` .vesper/instructions/vesper-orchestration.instructions.md (${a.orchestration})`),u.info(` .vesper/instructions/vesper-context.instructions.md (${a.context})`),u.info(` .vesper/context/ (${a.contextTier}) \u2014 on-demand tier`),u.info(` .vesper/gates.json (${a.gates})`),u.info(`Max agent requests: ${r.maxRequests}`),o.configured>0?u.info(`Terminal auto-approval: ${o.configured} safe commands configured`):r.terminalEnableAutoApprove===!1&&u.info("Terminal auto-approval: disabled"),i&&(u.info("MCP servers: vesper-indexing, sequential-thinking, memory (.vscode/mcp.json)"),u.info("MCP tools auto-approval: vesper-indexing + context7 + sequential-thinking + memory")),s.workspaceType===he.WORKSPACE_FILE?u.info(`Settings added to: ${Zh(t.settingsPath)}`):u.info("Settings added to: .vscode/settings.json"),u.info("Tracking file: .vesperrc"),u.info("Worktree bootstrap task: .vscode/tasks.json (runs on folder open)"),{mcpConfigured:i}}async function BE(e,t,r=null){let n=await es(e);if(!n.found)return{migrated:!1,from:null,preCreated:[],backedUp:!1};let{paths:s}=n;console.log(),u.warn(`Found .vesperrc in nested folder${s.length>1?"s":""}:`);for(let{folderPath:c}of s)u.info(` \u2192 ${c}`);console.log();let o=s[0],i=!0;t||(i=await zt({message:"Migrate .vesperrc to workspace level? (recommended for multi-root workspaces)",default:!0}));let a=[];if(i&&r)try{let c=await bt(e),l=IE(e,c).split(jE).join("/");l&&!l.startsWith("..")&&!RE(l)&&(await w(c)?await r.snapshot(l):(await r.snapshot(l),a=[l]));for(let{vesperrcPath:p}of s)await r.nestedConfig(p)}catch(c){return u.warn(`Not moving the nested .vesperrc: it could not be backed up first (${c?.message||c}). Nothing was changed.`),console.log(),{migrated:!1,from:null,preCreated:[],backedUp:!1}}if(i){let c=await Ao(e,o.vesperrcPath,o.tracking);if(c.success){if(u.success("Migrated .vesperrc to workspace level"),u.info(` From: ${o.vesperrcPath}`),u.info(` To: ${c.newPath}`),s.length>1){let{unlink:l}=await import("node:fs/promises");for(let d=1;d<s.length;d++)try{await l(s[d].vesperrcPath),u.info(` Removed: ${s[d].vesperrcPath}`)}catch{}}return console.log(),{migrated:!0,from:o.folderPath,preCreated:a,backedUp:!!r}}}else u.info("Migration skipped. .vesperrc will remain in nested folder."),console.log();return{migrated:!1,from:null,preCreated:[],backedUp:!!r&&i}}async function zE(e,t){let r=e;return t||(r=await LE({message:"Workspace root directory:",default:r})),PE(r)}async function YE(e,t,r){let n=[];for(let s of t){let o=em(s),i=r;if(r||(i=await zt({message:`${o} is installed but was unchecked. Remove it from this project?`,default:!1})),!i){u.info(`Kept ${o}.`);continue}s==="claude"?await xn(e):await Ws(e),n.push(s),u.success(`Removed ${o} from this project.`)}return n}async function JE(e,t,r,n,{switchSnapshot:s=null}={}){if(await hn(e,t)||(s?.packs||[]).includes(Ge))return!1;if(r.graphify)return!0;if(n||r.force||!process.stdin.isTTY)return!1;let i=gn(),a=rt()?"graphify found on PATH":`external tool, not on PATH yet: ${i.command?`\`${i.command}\``:i.hint}`;return zt({message:`Enable the graphify pack? (code knowledge graph for the research roles \u2014 ${a})`,default:!1})}async function qE(e,t,{interactive:r=!1}={}){try{let n=await lr(e,t,Ge);u.success(`Enabled the graphify pack (vesper-graphify) for ${t}.`),Tl(n.graphify)}catch(n){u.warn(`Could not enable the graphify pack (${n?.message??n}); run \`vespercli packs enable graphify\` by hand.`);return}await Pl({interactive:r}),await Il(e)}async function XE(e){if(e)return{maxRequests:Re.maxRequests,terminalEnableAutoApprove:Re.terminalEnableAutoApprove,omitBaseAgentInstructions:Re.omitBaseAgentInstructions,enableMcpServer:Re.enableMcpServer};console.log(),u.info("Configure VS Code Chat settings:");let t=await ME({message:"Max agent requests per session (chat.agent.maxRequests):",default:Re.maxRequests,min:1,max:1e3}),r=await zt({message:"Controls whether terminal commands are automatically approved. Enable terminal auto-approval? (chat.tools.terminal.enableAutoApprove)",default:Re.terminalEnableAutoApprove});r&&u.info("Terminal auto-approval enabled with safe command whitelist");let n=await zt({message:"Omit base agent instructions for custom agents? (github.copilot.chat.omitBaseAgentInstructions)",default:Re.omitBaseAgentInstructions}),s=await zt({message:"Enable vesper-indexing MCP server for fast code search?",default:Re.enableMcpServer});return{maxRequests:t||Re.maxRequests,terminalEnableAutoApprove:r,omitBaseAgentInstructions:n,enableMcpServer:s}}async function oa(e,t=!1){let r=Be().replace("index.js","cli-index.js");if(!await w(r))return{success:!1,error:"MCP server not built"};t&&(console.log(),u.info("Starting workspace indexing..."));let n=t?null:u.createSpinner("Indexing workspace...");return n&&n.start(),new Promise(s=>{let o=NE(process.execPath,["--disable-warning=ExperimentalWarning",r,e],{stdio:["ignore","pipe","pipe"],env:{...process.env}}),i="",a=0;o.stderr.on("data",c=>{let l=c.toString().trim(),d=l.match(/Indexed (\d+) files/);if(d&&(a=parseInt(d[1],10),n&&n.update(`Indexing workspace... ${a} files`)),t&&l)for(let p of l.split(`
|
|
202
|
+
`))p.trim()&&u.info(p.replace("[vesper-indexing] ",""))}),o.stdout.on("data",c=>{i+=c.toString()}),o.on("close",c=>{try{let l=JSON.parse(i.trim());l.success?n?n.succeed(`Workspace indexed: ${l.filesIndexed} files`):u.success(`Workspace indexed: ${l.filesIndexed} files`):n?n.fail(`Indexing failed: ${l.error}`):u.error(`Indexing failed: ${l.error}`),s(l)}catch{c===0?(n?n.succeed(`Workspace indexed: ${a} files`):u.success(`Workspace indexed: ${a} files`),s({success:!0,filesIndexed:a})):(n?n.fail("Indexing failed"):u.error("Indexing failed"),s({success:!1,error:"Unknown error"}))}}),o.on("error",c=>{n?n.fail(`Indexing failed: ${c.message}`):u.error(`Indexing failed: ${c.message}`),s({success:!1,error:c.message})})})}function QE({copilot:e,claude:t,indexingResult:r}){console.log(),u.success("Vesper is ready."),r?.success?u.info(`Code index built: ${r.filesIndexed} files.`):r?.error&&u.info("Code index will be built on first MCP server start."),console.log(),u.header("Next Steps"),console.log(),e&&(u.info("GitHub Copilot \u2014 reload VS Code to activate Vesper:"),u.info(' Cmd+Shift+P (macOS) / Ctrl+Shift+P (Windows/Linux) \u2192 "Developer: Reload Window"')),t&&(u.info("Claude Code \u2014 open a session in this workspace; the orchestrator"),u.info(" activates automatically via the always-on rules in .claude/rules/ plus the"),u.info(" default-agent key in .claude/settings.json (vesper-orchestrator)."),u.info(" Committed to the repo: the orchestrator agent, four maintenance skills, and"),u.info(" the three .claude/rules/vesper-*.md files. The full specialist catalog ships"),u.info(' as the "vesper" marketplace plugin \u2014 Claude Code shows a one-time'),u.info(" workspace-trust dialog to load it (decline it, or a cloud/headless session,"),u.info(" and Vesper runs in degraded mode on the committed fallback)."),u.info("OpenCode \u2014 open the same checkout: opencode.json makes vesper-orchestrator the"),u.info(" default agent, loads the three .claude/rules files as instructions, runs the MCP"),u.info(" servers through `vespercli mcp serve`, and .opencode/plugins/vesper.js registers"),u.info(" the specialists. Commit opencode.json and .opencode/ with the rest.")),console.log(),e&&u.vesperTip()}async function rm(e={}){try{await ZE(e)}finally{bl()}}async function ZE(e){try{let t=e.yes||e.forceDefault,r=await zE(e.path||process.cwd(),t);await w(r)||(u.error(`Directory not found: ${u.formatPath(r)}`),process.exit(1));let n=await q(r),s=await B(r),o=await Te(r,{checkout:s}),i=n.type===he.WORKSPACE_FILE?await es(r):{found:!1,paths:[]},a=i.found&&i.paths.some(j=>!(Number(j?.tracking?.schemaVersion)>=2)),c=await df(r);c&&u.warn(`An interrupted migration's record (${c.from}) was unreadable and was set aside as ${Zh(c.to)}; its backups are kept. If files look half-migrated, restore them from that folder.`);let l=await Th(r),d=await Qi(r),p=null;if(o.needsMigration||a){let j=await Ah(r,{record:o.record}),Q=l?.status==="started"&&l.latest.head===d&&l.root.head===d?l:null;if(j.dirty.length){let ot=Q?await Ih(r,Q,j):j.dirty;ot.length&&(u.error(_h(ot,{interrupted:Q?Q.latest.dir:null})),process.exit(1)),u.warn(`Resuming an interrupted migration (its backups: ${Q.latest.dir}) \u2014 every uncommitted change is its own write.`)}p=Q}let f=gl(r),m={migrated:!1,preCreated:[],backedUp:!1};n.type===he.WORKSPACE_FILE&&(m=await BE(r,t,f),i.found&&(o=await Te(r,{checkout:s})));let{selected:h,installed:g}=await VE(e,r,{legacyHint:o,checkout:s}),y=h[0],k=y==="claude"?"copilot":"claude",v=o.needsMigration&&o.hosts[k]?k:null,S=null,C=s,N=async()=>!!y&&!!C.host&&C.host!==y&&(await Ir(r,C.host)||await br(r,C.host)),E=!!v||await N(),b=()=>v??C.host;await Ya(r)&&(u.warn(`An unreadable host-switch journal (${cr}) was found and removed: an earlier switch was interrupted before its record was saved. Check your added assets and MCP servers (\`vespercli list\`, \`vespercli mcp list\`) and re-add any that are missing.`),await al(r));let F=await Ft(r),X=F?F.snapshot:null;if(F&&u.warn(E?`Resuming an interrupted host switch (${F.from} \u2192 ${F.to}, started ${F.startedAt}): completing it now \u2014 ${b()}'s remaining Vesper artifacts are cleaned, and the assets and MCP servers preserved when it started are restored onto ${y}.`:`Resuming an interrupted host switch (${F.from} \u2192 ${F.to}, started ${F.startedAt}): its preserved assets and MCP servers will be restored onto ${y}.`),E){let j=b(),Q=v?`the pre-2.0 (1.x) ${j} setup`:`${j}'s Vesper artifacts`;if(!t&&!process.stdin.isTTY&&(u.error(`This workspace is provisioned for "${j}"${v?" (pre-2.0)":""}; switching to "${y}" removes ${Q}. Re-run with --yes to confirm (non-interactive), or interactively.`),process.exit(1)),!t&&!await zt({message:`Switch this workspace from ${j} to ${y}? This removes ${Q}. Your .vesper/.tracking/ (run ledger included) and memory.jsonl are untouched, and the Team Roster + project whitepaper are preserved.`,default:!1})){u.info("Initialization cancelled.");return}}let He=null;if(o.needsMigration){if(l?.status==="started"&&l!==p){let ot=await Ph(l);u.warn(`An interrupted migration from another commit (${l.root.head?l.root.head.slice(0,12):"no git"}) cannot be resumed and was abandoned; its backups are kept \u2014 remove them when you no longer need them: ${ot.join(", ")}`)}let j=await bi({dryRun:!0,workspaceRoot:r});S=await El(r,f,{record:o.record,previousVersion:await Rh(r,o.record,j.version||null),chain:p,preCreated:m.preCreated});let Q=v??y;He=await Lh(r,y,{legacy:o,recordHost:Q,frameworkVersion:e.version,log:u,backup:f}),C={host:Q,source:"migration"},E=!!v||E&&await N()}else l&&(u.warn(`Completing an interrupted 1.x migration (its backups: ${l.latest.dir}): its rollback record is finished and its backup and rollback guidance printed at the end of this run.`),l.latest.head===d?S=await El(r,f,{record:o.record,chain:l}):l.status==="started"&&await xl(r,l.latest.dir));if(E){await il(r,C.host),F||(X=await cl(r),await eh(r,{from:C.host,to:y,snapshot:X}));let{retained:j}=await Ki(r,C.host,{fullTeardown:!0});await $n(r,j,C.host,u)}let In=E||He?[]:g.filter(j=>!h.includes(j));if(h.length===0&&In.length===0){u.info("No platforms selected. Nothing to do.");return}if(!t&&g.length===0&&h.length>0&&!await zt({message:`Set up ${h.map(em).join(" + ")} in ${r}?`,default:!0})){u.info("Initialization cancelled.");return}In.length>0&&await YE(r,In,t);let Ct=h.includes("copilot"),Jt=h.includes("claude"),Ue=null;Ct&&(Ue=await XE(t));let wr=await JE(r,y,e,t,{switchSnapshot:X}),vr={...e,thirdPartyBackup:He?j=>f.project(j):null};Ct&&(await pd(r,"copilot"),await KE(r,n,Ue,vr)),Jt&&await WE(r,vr,g.includes("claude"));let $t=null;if((Ct||Jt)&&($t=await UE(g.includes(y),t,{backup:async j=>f.home(j),workspaceRoot:r}),$t?.kept?.length&&($t.removed||$t.partial)))try{await Al(f,$t.kept.map(j=>({rel:`~/.claude/skills/vesper/${j}`,reason:"plugin-folder"})))}catch{}if(Ct||Jt){let j=await Yh(r);j.archived&&u.success(`Archived .vesper/history.md \u2192 ${j.to} (${j.method==="git"?"git mv, staged":"moved"}). Vesper 2.0 keeps the run ledger under .vesper/.tracking/runs/ instead; the archive is read-only and reachable by /revalidate-knowledge.`)}let ca=null,jn=[];if(Ct||Jt){await Jn(r);let j=await qn(r);if(j.length>0){let Ot=j.map(ng=>`'${ng.replace(/'/g,"'\\''")}'`);u.warn(`Local-only file(s) are git-tracked despite .gitignore: ${Ot.join(", ")}`),u.warn(`Untrack them yourself (Vesper won't touch your git index): git rm --cached -- ${Ot.join(" ")}`)}let Q=await ns(r);jn=lt.filter(Ot=>Q[Ot]&&!Q[Ot].reason),ca=jn.length&&Q[jn[0]].hooksDir||null;for(let Ot of rs(Q))Ot.startsWith("Git hooks not installed")?u.info(Ot):u.warn(Ot);ca&&(u.success("Local-only Vesper files gitignored (.vesperrc, .mcp.json, .vesper/index.db)"),jn.includes("pre-commit")&&u.info("Commit-hygiene git hook installed (pre-commit): keeps team roster/context/tracking/memory in sync with every commit")),wr&&await qE(r,y,{interactive:!t&&!e.force&&!!process.stdin.isTTY});let ot=await ss(r);await os(r),ot.skipped||u.info("Merge strategy configured (.gitattributes): memory.jsonl merges entity-aware across worktrees, recent-decisions.md unions")}if(h.length===1){let j=h[0],Q=j==="copilot"?await At(r):void 0;await DE(r,j,{settingsEntries:Q,hooksDir:ca,hookNames:jn,version:e.version}),X&&(await th(r,j,X),await al(r));let{legacyGuardRule:ot}=await Ni(r,j);ot==="kept"&&u.warn(An())}if(He)try{let Q=(await Cn(r)).findings.filter(ot=>ot.code.startsWith("legacy-"));Q.length&&u.warn(`The migration left ${Q.length} pre-2.0 item(s) \u2014 see \`vespercli doctor\`.`)}catch{}if(S)try{await xl(r,f.dir)}catch(j){u.warn(`Could not finish the migration's rollback record (${j?.message||j}); the backups are under .vesper/.migration-backup/.`)}let rg=Ct&&Ue?.enableMcpServer||Jt,zl=null;rg&&(zl=await oa(r,!0));let Rn=[];if((S||$t?.backedUpTo||m.backedUp)&&Rn.push(f.dir),l&&!o.needsMigration&&!S&&Rn.push(l.latest.dir),Rn.length)try{let j=await Nh(r,{runDirs:Rn});if(j.length){console.log();for(let Q of j)u.info(Q)}await jh(r,Rn)}catch(j){u.warn(`Could not print the migration backup guidance (${j?.message||j}); the backups are under .vesper/.migration-backup/.`)}QE({copilot:Ct,claude:Jt,indexingResult:zl})}catch(t){if(t.name==="ExitPromptError"){console.log(),u.info("Initialization cancelled.");return}t.name==="HostCleanRefused"&&(u.error(t.message),process.exit(1)),u.error(`Initialization failed: ${t.message}`),process.exit(1)}}U();H();te();Ae();xe();_e();Kt();import{resolve as eb,join as nm}from"node:path";import{checkbox as tb}from"@inquirer/prompts";Ie();var sm=["agents","skills"];async function rb(e,t){let r=t?[t]:await ge(e);return r.length===0&&(u.warn('Vesper is not initialized in this workspace. Run "vespercli init" first.'),process.exit(0)),r.length>1&&(u.error(et),process.exit(1)),r[0]}async function om(e,t,r){r!==t&&(u.error(`\`vespercli add\` for ${t==="claude"?"Claude Code":"Copilot"} needs a workspace provisioned for ${t}${r?` (this one is provisioned for ${r})`:""} \u2014 nothing was written. Run \`vespercli init --host ${t}\` first.`),process.exit(1))}async function nb(e,t){return await Rs(e,t)!==null}async function sb(e,t,r){if(!t.type||!t.name){u.info("Every Vesper specialist and skill is served by the vesper plugin as `vesper:<name>` \u2014 there is nothing to add."),u.info("To pin a project-level copy anyway: vespercli add <agents|skills> <name> --override");return}if(t.type==="prompts"&&(u.error("Vesper 2.0 ships its maintenance workflows as skills (served by the plugin); slash commands are no longer provisioned."),process.exit(1)),sm.includes(t.type)||(u.error(`Unknown asset type for Claude Code: ${t.type}. Types: ${sm.join(", ")}`),process.exit(1)),await nb(t.type,t.name)||(u.error(`${t.type}/${t.name} is not in the Vesper catalog.`),process.exit(1)),!t.override){let n=await Rs(t.type,t.name),s=t.type==="agents"?await bp(t.name):`/${n.pack==="core"?"vesper":`vesper-${n.pack}`}:${t.name}`;u.info(`\`${t.name}\` is already available as \`${s}\` from the ${n.pack==="core"?"vesper plugin":`vesper-${n.pack} pack (enabled per project by \`vespercli packs sync\`)`} \u2014 nothing to add.`),u.info("A project-level copy would shadow the plugin's version. To pin one anyway (not recommended): add --override.");return}await om(e,"claude",r);try{let n=await Ei(t.type,t.name,{workspaceRoot:e,namePrefix:await an(e)});u.success(`Pinned a project-level copy of ${t.type}/${t.name} as "${n.installedAs}" (recorded; \`vespercli reset --host claude\` removes it).`)}catch(n){u.error(n.message),process.exit(1)}}async function ob(e,t,r){let n=await Wf(),s=new Set(await xt(e)),o=c=>[...s].some(l=>l.replace(/\\/g,"/").endsWith(`/instructions-extended/${c}`));if(t.type&&t.type!=="instructions"){Xe[t.type]||(u.error(`Unknown asset type: ${t.type}. Types: ${Object.keys(Xe).join(", ")}`),process.exit(1));let c=pi(),l=[...new Set([...await ro(t.type),...c[t.type]||[]])];t.name&&!l.includes(t.name)&&(u.error(`${t.type}/${t.name} is not in the Vesper catalog.`),process.exit(1));let d=t.name?c.assetPacks[t.type]?.[t.name]??"core":"core",p=d==="core"?`${nm(Tt,Xe[t.type].dir)} (the whole folder is injected)`:`${nm(Tt,"packs",d,Xe[t.type].dir)} (the ${d} pack's folder, injected when the pack is enabled \u2014 \`vespercli packs sync\`)`;u.info(`Copilot reads every Vesper ${t.type.replace(/s$/,"")} from ${p}${t.name?` \u2014 \`${t.name}\` is already available`:""}. Nothing to add.`);return}let i=[];if(t.name)n.includes(t.name)||(u.error(`Unknown opt-in instruction: ${t.name}. Available: ${n.join(", ")||"none"}`),process.exit(1)),i=[t.name];else{let c=n.filter(l=>!o(l));if(c.length===0){u.info("Every opt-in instruction is already added.");return}if(!process.stdin.isTTY){u.info(`Opt-in instructions you can add: ${c.join(", ")} \u2014 run \`vespercli add instructions <name>\`.`);return}if(i=await tb({message:"Select opt-in instructions to add:",choices:c.map(l=>({name:l,value:l}))}),i.length===0){u.info("Nothing selected.");return}}await om(e,"copilot",r);let a=[];for(let c of i)(await Hi(e,c)).added&&a.push(c);a.length?u.success(`Added opt-in instruction(s): ${a.join(", ")} \u2014 reload VS Code to apply.`):u.info("All selected instructions were already added.")}async function im(e={}){try{let t=eb(e.path||process.cwd());await w(t)||(u.error(`Directory not found: ${u.formatPath(t)}`),process.exit(1));let r=await B(t);return(await Te(t,{checkout:r})).unmigrated&&(u.error(st),process.exit(1)),(e.target||await rb(t,r.host))==="claude"?await sb(t,e,r.host):await ob(t,e,r.host)}catch(t){if(t.name==="ExitPromptError"){console.log(),u.info("Cancelled.");return}u.error(`Add failed: ${t.message}`),process.exit(1)}}U();xe();H();import{resolve as cm,join as ib}from"node:path";import{readdir as lm}from"node:fs/promises";te();Ae();_e();Kt();Ie();import se from"picocolors";async function am(e={},t){let r=cm(e.path||process.cwd());if(console.log(),console.log(se.bold("Claude Code target")),t!=="claude"){console.log(),u.warn('Not initialized for Claude Code. Run "vespercli init --host claude" first.'),console.log();return}let n=await ld(r)||Gr(r);console.log(se.dim(`Project catalog: ${n}`));let s=await zo(r),o=to();s&&o&&s!==o&&u.warn(`Catalog drift: installed catalog is v${s}, but Vesper is v${o}. Run \`vespercli update\` to refresh the committed orchestrator, maintenance skills and playbook.`);let i=await Jp(r);for(let[a,c]of Object.entries(i))console.log(),console.log(se.bold(a.charAt(0).toUpperCase()+a.slice(1))),c.length===0?console.log(se.dim(" (none installed)")):c.forEach(l=>console.log(` ${l}`));console.log(),console.log(se.dim("The full specialist catalog is served by the vesper plugin (vesper:<name>) and its packs (vesper-<pack>:<name>) \u2014 see `vespercli catalog`.")),await um(r,"claude"),console.log(),console.log(se.bold("Project files")),console.log(" CLAUDE.md (pointer), .claude/rules/vesper-{orchestrator,orchestration,context}.md, .mcp.json, .claude/settings.json"),console.log()}async function um(e,t){let r=nt();if(console.log(),console.log(se.bold("Packs")),!r.length){console.log(se.dim(" (this package ships no packs)"));return}let{enabled:n,unknown:s}=await Mr(e,t),o=await ur(e,t),i=o!==null?await dr(o):null;for(let a of r){let c=n.includes(a)?se.green("(enabled)"):se.dim("(disabled)"),l=i?.packs.includes(a)?n.includes(a)?se.dim("\u2014 roster needs it"):se.yellow("\u2014 roster needs it: run `vespercli packs sync`"):"";console.log(` ${a} ${c} ${l}`.trimEnd())}s.length&&console.log(se.yellow(` enabled but not shipped by this package: ${s.join(", ")}`)),console.log(se.dim(" `vespercli packs` for contents; `vespercli packs sync` enables what the Team Roster names."))}async function ab(e,t){try{let r=await lm(ib(e,".vesper",t),{withFileTypes:!0});return t==="skills"?r.filter(n=>n.isDirectory()&&!n.name.startsWith(".")).map(n=>n.name).sort():r.filter(n=>n.isFile()&&n.name.endsWith(".md")).map(n=>n.name.replace(/\.(agent|instructions|prompt)\.md$|\.md$/,"")).sort()}catch{return[]}}async function cb(){try{return(await lm(zn,{withFileTypes:!0})).filter(e=>e.isFile()&&e.name.endsWith(".md")).map(e=>e.name.replace(/\.instructions\.md$|\.md$/,"")).sort()}catch{return[]}}async function lb(e,t){let n=(await xt(e)).map(o=>/\/instructions-extended\/([^/]+)\/?$/.exec(String(o).replace(/\\/g,"/"))).filter(Boolean).map(o=>o[1]).sort(),s=t.type?[t.type]:Object.keys(Xe);console.log(),console.log(se.bold("GitHub Copilot target")),console.log(se.dim(`Package catalog: ${Tt}`));for(let o of s){let i=o.charAt(0).toUpperCase()+o.slice(1),a=o==="instructions"?await cb():await ro(o),c=await ab(e,o),l=o==="instructions"?n:[];if(console.log(),console.log(se.bold(i)),!a.length&&!c.length&&!l.length){console.log(se.dim(" (none)"));continue}a.forEach(d=>console.log(` ${d} ${se.dim("(package)")}`)),l.forEach(d=>console.log(` ${d} ${se.dim("(opt-in)")}`)),c.forEach(d=>console.log(` ${d} ${se.dim("(project)")}`))}await um(e,"copilot"),console.log()}async function dm(e={}){try{let t=cm(e.path||process.cwd());await w(t)||(u.error(`Directory not found: ${u.formatPath(t)}`),process.exit(1));let r=await B(t),n=r.host,s=n?[n]:await ge(t);if(e.target==="claude")return await am({...e,path:t},n);if(!e.target){if((await Te(t,{checkout:r})).unmigrated&&(u.error(st),process.exit(1)),s.length===0){console.log(),u.warn('Vesper is not initialized. Run "vespercli init" first.'),console.log();return}if(s.length>1&&(u.error(et),process.exit(1)),s[0]==="claude")return await am({...e,path:t},n)}e.type&&!Xe[e.type]&&(u.error(`Unknown asset type: ${e.type}`),u.info(`Valid types: ${Object.keys(Xe).join(", ")}`),process.exit(1)),await lb(t,e)}catch(t){u.error(`List failed: ${t.message}`),process.exit(1)}}xe();import{readFileSync as ub,existsSync as db}from"node:fs";import{join as pb}from"node:path";var Rl=pb(O,"CATALOG.md");function fb(){return db(Rl)?ub(Rl,"utf-8"):null}async function pm(){let e=fb();e===null&&(console.error(`Error loading catalog: ${Rl} not found in the installed package.`),process.exit(1)),console.log(e)}U();H();te();Ae();_e();import{resolve as vm,join as qs,dirname as mm}from"node:path";import{stat as hb,readFile as km}from"node:fs/promises";import{existsSync as mb}from"node:fs";import{spawn as gb}from"node:child_process";import"@inquirer/prompts";H();ft();var fm=Object.freeze(Object.keys(we)),zP=Object.freeze(["vesper-indexing","sequential-thinking","memory"]);function Nl(e,{workspaceRoot:t,env:r,indexingPath:n}){return String(e).replace(/\$\{VESPER_INDEXING_PATH\}/g,n).replace(/\$\{workspaceFolder\}/g,t).replace(/\$\{env:([^}]+)\}/g,(s,o)=>r[o]??"")}function hm(e,t,{env:r=process.env,indexingPath:n=Be(),which:s}={}){let o=we[e];if(!o||!o.config)return null;if(e===pt)return{command:Kd(String(t),{env:r||{},...s?{which:s}:{}}),args:["-m","graphify.serve",`${t}/${ke}`],env:{}};let{type:i,...a}=structuredClone(o.config),c={workspaceRoot:String(t),env:r||{},indexingPath:n},l={command:Nl(a.command,c),args:(Array.isArray(a.args)?a.args:[]).map(d=>Nl(d,c)),env:{}};for(let[d,p]of Object.entries(a.env||{})){let f=Nl(p,c);f!==""&&(l.env[d]=f)}return l}ft();Ie();import mt from"picocolors";async function Sm(e,t){if(!t.includes(pt))return;let r=await w(qs(e,ke));console.log(),u.info(`graphify (opt-in pack): configured \u2014 tool on PATH: ${rt()?"\u2713 yes":`\u2717 no (${xs()})`}; ${ke}: ${r?"\u2713 exists":`\u2717 missing (run \`${Se}\`)`}`)}async function gm(e,t){if(console.log(),u.header("vesper-indexing MCP Server (Claude Code target)"),console.log(),t!=="claude"){u.info("Claude Code target is not initialized. Run `vesper init --target claude` first.");return}let r=Ve(e),n=!1;if(await w(r))try{n=!!JSON.parse(await km(r,"utf-8")).mcpServers?.["vesper-indexing"]}catch{n=!1}u.info(`Configured: ${n?"\u2713 yes":"\u2717 no"} (${r})`),u.info(`Server built: ${_m(await Am())}`);let s=Ml(e);u.info(`Index exists: ${await w(s)?"\u2713 yes":"\u2717 no"} (shared with the Copilot target if both are installed)`),await Sm(e,(await Mc(e)).configured);try{let{drifted:o}=await Mi(e);o.length&&(console.log(),u.warn(`MCP config drift: ${o.join(", ")} present in the live MCP config but not tracked in .vesperrc mcp.servers.`),u.warn("Run `/reinit` (or re-run workspace-learner) to resync tracking and the generated docs."))}catch{}}var Em=new Set(["enable","disable","sync","add","remove"]),yb=Em,bm="Vesper regenerates them at every session start \u2014 `vespercli mcp disable` makes no lasting change.";function wb(e){return`\`vespercli mcp ${e}\` for Claude Code needs a workspace provisioned for Claude \u2014 nothing was written. Run \`vespercli init --host claude\` first.`}async function Ll(e,t=!0){if(await mr(e,t),t){let r=await Zp(e);r.skipped==="malformed"&&u.warn(`${r.settingsPath} is not valid JSON \u2014 MCP tool permissions were not added (the file was left as found).`)}t?u.success("Claude Code target: vesper-indexing enabled in .mcp.json"):(u.success("MCP servers removed from .mcp.json until the next session start"),u.info(bm))}function Ml(e){return qs(e,".vesper","index.db")}function vb(e){return qs(e,".vesper","indexing-status.json")}async function xm(e){let t=vb(e);try{let r=await km(t,"utf-8");return JSON.parse(r)}catch{return null}}async function Am(){let e=Be();if(!await w(e))return"missing";let t=mm(mm(e)),r=[qs(t,"node_modules","@modelcontextprotocol","sdk","package.json"),qs(t,"node_modules","zod","package.json")];for(let n of r)if(!await w(n))return"broken";return"ready"}function _m(e){switch(e){case"ready":return"\u2713 yes";case"broken":return"\u26A0 yes, but dependencies missing \u2014 run 'npm install' in src/mcp/vesper-indexing (or reinstall Vesper)";default:return"\u2717 no"}}async function kb(e){try{let t=await hb(e),r=t.size,n=`${r} bytes`;return r>1024*1024?n=`${(r/(1024*1024)).toFixed(2)} MB`:r>1024&&(n=`${(r/1024).toFixed(1)} KB`),{dbSize:n,lastModified:t.mtime.toISOString()}}catch{return null}}async function ym(e,t=!1){let r=await Go(e),n=await Am(),s=Ml(e),o=await w(s),i=await xm(e);if(console.log(),u.header("vesper-indexing MCP Server"),console.log(),u.info(`Configured: ${r?"\u2713 yes":"\u2717 no"}`),u.info(`Server built: ${_m(n)}`),u.info(`Index exists: ${o?"\u2713 yes":"\u2717 no"}`),await Sm(e,await Do(e)),i)if(console.log(),i.status==="indexing")if(t){await Sb(e,i);return}else{let a=i.startedAt?Math.round((Date.now()-new Date(i.startedAt).getTime())/1e3):0;u.info(mt.yellow("\u27F3 Indexing in progress...")),u.info(` Files processed: ${mt.cyan(i.filesProcessed)}`),u.info(` Elapsed: ${mt.dim(`${a}s`)}`),console.log(),u.info("Use --watch to follow indexing progress until completion")}else i.status==="error"&&(u.error(`Indexing error: ${i.error}`),u.info(` Files processed before error: ${i.filesProcessed}`));if(!r){console.log(),u.info("Run `vespercli init` to configure the MCP server");return}if(n==="missing"){console.log(),u.warn("MCP server not built. Run: cd src/mcp/vesper-indexing && npm install && npm run build");return}if(n==="broken"){console.log(),u.warn("MCP server dependencies are missing/corrupt. Run: cd src/mcp/vesper-indexing && npm install (or reinstall Vesper)");return}if(o&&!i){let a=await kb(s);a&&(console.log(),u.info(`Index size: ${a.dbSize}`),u.info(`Last modified: ${a.lastModified}`)),u.vesperTip()}else!o&&!i&&(console.log(),u.info("Index not yet created. It will be built when VS Code loads the MCP server."),console.log())}async function Sb(e,t){let r=u.createSpinner(`Indexing... ${t.filesProcessed} files processed`);r.start();let n=500,s=30*60*1e3,o=Date.now();return new Promise(i=>{let a=async()=>{let c=await xm(e);if(!c||c.status!=="indexing"){c?.status==="error"?r.fail(`Indexing failed: ${c.error}`):(r.succeed(`Indexing complete! ${c?.filesProcessed||"All"} files indexed`),u.info(`
|
|
203
|
+
\u2192 Reload VS Code to update MCP tools with the new index`),u.vesperTip()),i();return}let l=c.startedAt?Math.round((Date.now()-new Date(c.startedAt).getTime())/1e3):0;if(r.update(`Indexing... ${c.filesProcessed} files processed (${l}s)`),Date.now()-o>s){r.fail("Indexing watch timed out (30 minutes)"),i();return}setTimeout(a,n)};setTimeout(a,n)})}async function wm(e,t=!1){let r=Ml(e);if(!await w(r))u.info("No index exists. It will be built when VS Code loads the MCP server.");else if(t){let{unlink:s}=await import("node:fs/promises");await s(r),u.success("Index cleared. Reload VS Code to rebuild.")}else u.info("Incremental reindex happens automatically when files change."),u.info("Use --full to clear and rebuild the entire index.")}async function Eb(e){let t=await _r(e,!0);t.configured&&(u.success("MCP server enabled"),u.info(`Config: ${t.mcpPath}`),u.info("Reload VS Code to start the server"))}async function bb(e){await _r(e,!1),u.success("MCP servers removed from .vscode/mcp.json until the next session start"),u.info(bm),u.info("Reload VS Code to apply changes")}async function Cm(e){let t=await xt(e),r=[];for(let n of t){let s=n.match(/agents\/([^/]+)\/?$/);s&&MCP_TOOLS_BY_AGENT[s[1]]&&r.push(s[1])}return r}async function xb(e){let t=await q(e),r=await x(e,t),n=await K(e,t),s=await Cm(e),o=n[V]||{},i=new Set(Ne),a=[],c=[],l=!1;n[V]||(n[V]={});for(let p of Ne)o[p]||(n[V][p]=!0,a.push(p),l=!0);for(let p of s){let f=MCP_TOOLS_BY_AGENT[p]||[];for(let m of f)o[m]||(n[V][m]=!0,a.push(m),l=!0)}let d=new Set;for(let p of s)for(let f of MCP_TOOLS_BY_AGENT[p]||[])d.add(f);for(let p of Object.keys(o)){if(i.has(p))continue;let f=!1;for(let[m,h]of Object.entries(MCP_TOOLS_BY_AGENT))if(h.includes(p)){f=!0;break}f&&!d.has(p)&&(delete n[V][p],c.push(p),l=!0)}if(r.mcp=r.mcp||{},r.mcp.syncedAt=new Date().toISOString(),r.mcp.approvedAgents=s,r.mcp.toolCount=Object.keys(n[V]).length,l&&await ce(e,n),await T(e,r),console.log(),u.header("MCP Tools Sync"),console.log(),a.length===0&&c.length===0)u.success("Already in sync");else{if(a.length>0){u.success(`Added ${a.length} tool(s)`);let p=a.filter(f=>i.has(f));p.length>0&&u.info(` Core: ${p.length} tools`);for(let f of s){let m=a.filter(h=>(MCP_TOOLS_BY_AGENT[f]||[]).includes(h));m.length>0&&u.info(` ${f}: ${m.length} tools`)}}c.length>0&&u.info(`Removed ${c.length} orphaned tool(s)`)}u.info(`
|
|
204
204
|
Total approved tools: ${r.mcp.toolCount}`),s.length>0&&u.info(`Agents with tools: ${s.join(", ")}`),l&&u.info(`
|
|
205
|
-
Reload VS Code to apply changes`)}async function
|
|
206
|
-
Reload VS Code to activate the MCP server`)}async function
|
|
207
|
-
Reload VS Code to deactivate the MCP server`)}async function
|
|
208
|
-
Reload the Claude Code session to activate the MCP server`)}async function
|
|
209
|
-
Reload the Claude Code session to deactivate the MCP server`)}async function Ab(e){let{configured:t,custom:r}=await Rc(e);console.log(),u.header("MCP Servers (Claude Code target)"),console.log(),u.info("Available servers:");for(let[n,s]of Object.entries(we)){let i=t.includes(n)?pt.green("\u2713"):pt.dim("\u25CB"),a=s.tools?.length||0;u.info(` ${i} ${n} (${a} tools)`)}if(r.length>0){console.log(),u.info("Custom servers:");for(let n of r)u.info(` ${pt.blue("\u25C6")} ${n}`)}console.log(),u.info(`Installed: ${t.length} server(s)`)}var ra=Object.freeze({START_FAILED:1,UNKNOWN:2});async function _b(e,t={}){let r=dm(t.path||process.cwd()),n=e?im(e,r):null;if(!n)return console.error(`Unknown MCP server "${e??""}". \`vespercli mcp serve <name>\` knows: ${om.join(", ")}.`),{exitCode:ra.UNKNOWN};if(e==="vesper-indexing"&&!lb(n.args[0]))return console.error(`vesper-indexing is not built (${n.args[0]} is missing) \u2014 reinstall @mthanh/vespercli or run \`npm run build:mcp\` in the package.`),{exitCode:ra.START_FAILED};let s=n.command==="node"?process.execPath:n.command;return new Promise(o=>{let i;try{i=ub(s,n.args,{stdio:"inherit",env:{...process.env,...n.env},shell:process.platform==="win32"&&s!==process.execPath})}catch(c){return console.error(`Could not start ${e}: ${c?.message||c}`),o({exitCode:ra.START_FAILED})}let a=c=>{try{i.kill(c)}catch{}};for(let c of["SIGINT","SIGTERM","SIGHUP"])process.on(c,a);i.on("error",c=>{console.error(`Could not start ${e}: ${c?.message||c}`),o({exitCode:ra.START_FAILED})}),i.on("exit",(c,l)=>o({exitCode:c??(l?1:0)}))})}async function Sm(e,t,r={}){let n=dm(r.path||process.cwd());if(await w(n)||(u.error(`Directory not found: ${n}`),process.exit(1)),e==="serve"){let{exitCode:l}=await _b(t,r);process.exitCode=l;return}let s=(await B(n)).host,o=s?[s]:await ge(n);!r.target&&o.length>1&&(u.error(Ze),process.exit(1)),!r.target&&o.length===0&&db.has(e)&&(u.error(`\`vespercli mcp ${e}\` needs an initialized workspace \u2014 nothing was written. Run \`vespercli init\` first.`),process.exit(1));let i=r.target?[r.target]:o.length?o:["copilot"],a=i.includes("copilot"),c=i.includes("claude");if(c&&!a)switch(hm.has(e)&&s!=="claude"&&(u.error(pb(e)),process.exit(1)),e){case"enable":return await Il(n,!0);case"disable":return await Il(n,!1);case"sync":return await Il(n,!0);case"add":return await bb(n,t);case"remove":return await xb(n,t);case"list":return await Ab(n);case"status":return await cm(n,s);case"reindex":return await um(n,r.full);default:return e&&u.warn(`'${e}' is not applicable to the Claude Code target \u2014 showing status instead.`),await cm(n,s)}switch(e){case"status":await lm(n,r.watch);break;case"add":await kb(n,t);break;case"remove":await Sb(n,t);break;case"list":await Eb(n);break;case"reindex":await um(n,r.full);break;case"enable":await gb(n);break;case"disable":await yb(n);break;case"sync":await wb(n);break;case"approve":await vb(n);break;default:await lm(n,r.watch)}}Te();H();import{resolve as Cb}from"node:path";async function bm(e,t,r,n={}){let s=Cb(n.path||process.cwd());if(!e){Em();return}switch(e){case"add":await $b(s,t,r);break;case"remove":await Ob(s,t,r);break;case"list":await Tb(s,t);break;default:u.error(`Unknown subcommand: ${e}`),Em()}}async function $b(e,t,r){if(!t){u.error("Setting key required"),u.info("Usage: vespercli settings add <setting-key> <value>");return}switch(t){case"github.copilot.chat.additionalReadAccessPaths":case"additionalReadAccessPaths":case"read-access":if(!r){u.error("Path value required"),u.info("Usage: vespercli settings add read-access <path>");return}let n=await Oo(e,r);u.success(`Added "${r}" to additional read access paths`),u.info(`Current paths: ${n.length>0?n.join(", "):"(none)"}`);break;default:u.error(`Unknown setting: ${t}`),u.info("Supported settings:"),u.info(" - read-access (github.copilot.chat.additionalReadAccessPaths)")}}async function Ob(e,t,r){if(!t){u.error("Setting key required"),u.info("Usage: vespercli settings remove <setting-key> <value>");return}switch(t){case"github.copilot.chat.additionalReadAccessPaths":case"additionalReadAccessPaths":case"read-access":if(!r){u.error("Path value required"),u.info("Usage: vespercli settings remove read-access <path>");return}let n=await To(e,r);u.success(`Removed "${r}" from additional read access paths`),u.info(`Current paths: ${n.length>0?n.join(", "):"(none)"}`);break;default:u.error(`Unknown setting: ${t}`),u.info("Supported settings:"),u.info(" - read-access (github.copilot.chat.additionalReadAccessPaths)")}}async function Tb(e,t){if(!t){u.info("Managed settings:"),u.info(" - read-access (github.copilot.chat.additionalReadAccessPaths)"),u.info(""),u.info("Use: vespercli settings list <setting-key>");return}switch(t){case"github.copilot.chat.additionalReadAccessPaths":case"additionalReadAccessPaths":case"read-access":let r=await Po(e);u.info(`${oe}:`),r.length===0?u.info(" (empty)"):r.forEach(n=>u.info(` - ${n}`));break;default:u.error(`Unknown setting: ${t}`),u.info("Supported settings:"),u.info(" - read-access (github.copilot.chat.additionalReadAccessPaths)")}}function Em(){u.info("Usage: vespercli settings <subcommand> [setting-key] [value]"),u.info(""),u.info("Subcommands:"),u.info(" add <setting-key> <value> Add a value to an array setting"),u.info(" remove <setting-key> <value> Remove a value from an array setting"),u.info(" list [setting-key] List current values"),u.info(""),u.info("Supported settings:"),u.info(" read-access github.copilot.chat.additionalReadAccessPaths"),u.info(""),u.info("Examples:"),u.info(" vespercli settings add read-access /path/to/external/repo"),u.info(" vespercli settings remove read-access /path/to/external/repo"),u.info(" vespercli settings list read-access")}U();H();te();be();xe();import{resolve as xm}from"node:path";Ut();Te();async function Pb(e={},t){let r=xm(e.path||process.cwd());if(t!=="claude"){u.warn('Claude Code target is not initialized. Run "vesper init --target claude" first.');return}console.log(),u.info("Refreshing Claude Code project catalog and orchestrator playbook...");let{pluginDir:n,counts:s,pruned:o}=await yi({workspaceRoot:r,namePrefix:await on(r),version:e.version});u.success(`Project catalog refreshed: ${n}`),u.info(` agents: ${s.agents}, commands: ${s.commands}, skills: ${s.skills}`),o.length&&u.info(` pruned ${o.length} asset(s) removed in this version: ${o.join(", ")}`);let i=await ki(r);u.success(`Orchestrator playbook refreshed (.claude/rules/vesper-orchestrator.md: ${i.orchestrator})`),u.info("Team roster (.claude/rules/vesper-orchestration.md) and project context (.claude/rules/vesper-context.md) are left alone \u2014 they belong to this project."),u.info(`OpenCode overlay: .opencode/agents/vesper-orchestrator.md (${i.opencodeAgent}), .opencode/plugins/vesper.js (${i.opencodePlugin})`),i.opencodeKept?.length&&u.warn(`Left in place \u2014 they differ from what Vesper writes (your edits, or an older build's copy): ${i.opencodeKept.join(", ")}. Delete them to get this version's copy.`),Vr(await ur(r,"claude"))}async function Ib({isTTY:e=!!process.stdout.isTTY,check:t=ea,timeoutMs:r=Zi}={}){if(!e)return[];let n=[];try{n=await t({timeoutMs:r})}catch{n=[]}let s=n.filter(o=>o.status==="stale").map(Vh);for(let o of s)u.info(o);return s}async function Am(e={}){try{let t=xm(e.path||process.cwd());await w(t)||(u.error(`Directory not found: ${u.formatPath(t)}`),process.exit(1));let r=await B(t);(await $e(t,{checkout:r})).unmigrated&&(u.error(rt),process.exit(1));let n=e.target?null:r.host,s=e.target?[e.target]:n?[n]:await ge(t);if(s.length===0){u.warn('Vesper is not initialized. Run "vespercli init" first.');return}if(!e.target&&s.length>1&&(u.error(Ze),process.exit(1)),s.includes("claude")&&await Pb({...e,path:t},r.host),s.includes("copilot")){console.log(),u.info("Copilot assets are linked from the package, not copied."),u.info("Update the vesper package to get the latest assets:"),u.dim(" npm update -g @mthanh/vespercli"),console.log();let o=await Mi(t),i=[[".vesper/agents/vesper-orchestrator.agent.md",o.orchestratorAgent],[".vesper/instructions/vesper-orchestrator.instructions.md",o.orchestrator]].filter(([,c])=>c==="created"||c==="updated");i.length?u.success(`Project brain refreshed: ${i.map(([c])=>c).join(", ")}`):u.info("Project brain already up to date."),Vr(await ur(t,"copilot"));let a=await Gr(t);a==="removed"&&u.info("Retired .vesper/instructions/vesper-host-guard.instructions.md (no longer used)."),a==="kept"&&u.warn(xn())}await Ib(e)}catch(t){u.error(`Update failed: ${t.message}`),process.exit(1)}}U();H();xe();te();import{resolve as jb,join as _m}from"node:path";ot();gt();ut();Te();async function Rb(e){await dd(e)}async function Nl(e,t,{quiet:r=!1}={}){if(t?.action!=="bootstrap"||!z.includes(t.host))throw new Error("runBootstrap requires a bootstrap decision");let n=t.host,s=t.network!==!1;if(t.checkout?.source==="local")return Nb(e,t,{quiet:r});let o=[],i=[],a=async(m,h)=>{try{return await h()}catch(g){i.push(m),u.warn(`Bootstrap step "${m}" failed (continuing): ${g?.message??g}`);return}},l={sshCommandConfigured:s?!!await D(["config","--get","core.sshCommand"],{cwd:e}):!1},d=s?Mb(e,l).catch(()=>({})):Promise.resolve({});await a("mcp",async()=>{n==="claude"?(await fr(e,!0),o.push(".mcp.json regenerated for this worktree"),await bi(e),o.push(".claude/settings.local.json marketplace source regenerated for this machine")):(await Gs(e,!0),o.push(".vscode/mcp.json regenerated for this worktree"))}),await a("index",async()=>{let m=_m(e,".vesper","index.db");if(!await w(m)){let h=await ta(e,!1);h.success&&o.push(`code index built (${h.filesIndexed} files)`)}}),await a("gitignore",()=>zn(e)),await a("tracked-local",async()=>{let m=await Yn(e);if(m.length>0){let h=m.map(g=>`'${g.replace(/'/g,"'\\''")}'`);u.warn(`Local-only file(s) git-tracked despite .gitignore: ${h.join(", ")} \u2014 untrack with: git rm --cached -- ${h.join(" ")}`)}});let p=await a("hooks",()=>ts(e));p&&o.push(...es(p)),await a("graphify",async()=>{await fn(e,n)&&await ks(e,n)}),await a("attributes",()=>rs(e)),await a("merge-driver",()=>ns(e)),o.push(p&&Na(p)?"gitignore + git hooks + merge strategy ensured":"gitignore + merge strategy ensured");let f=await a("fetch",()=>d)??{};if(f.action&&o.unshift(f.action),f.note&&!r&&u.info(f.note),await a("triggers",()=>Pi(e,n,{unattended:!0})),await a("ledger",()=>Rb(e)),o.push(`host guard triggers ensured (${n} + cross-host)`),i.length&&u.warn(`Worktree bootstrap finished with errors in: ${i.join(", ")}`),!r){u.success(i.length?"Worktree bootstrap finished (with errors)":"Worktree bootstrap complete");for(let m of o)u.info(` ${m}`)}return{host:n,failed:i}}async function Rl(e,t){return await D(["check-ignore","-q","--",t],{cwd:e,timeout:5e3})!==null}async function Nb(e,t,{quiet:r=!1}={}){let n=t.host,s=[],o=[],i=[],a=async(d,p)=>{try{return await p()}catch(f){o.push(d),u.warn(`Bootstrap step "${d}" failed (continuing): ${f?.message??f}`);return}},c=n==="claude"?[".mcp.json",".claude/settings.local.json"]:[".vscode/mcp.json"],l=await Rl(e,".vesperrc");if(l||i.push(".vesperrc (ledger not re-recorded)"),await a("mcp",async()=>{for(let d of c){if(!await Rl(e,d)){i.push(d);continue}d===".mcp.json"?(await fr(e,!0,{record:l}),s.push(".mcp.json regenerated")):d===".claude/settings.local.json"?(await bi(e,{record:l}),s.push(".claude/settings.local.json regenerated")):(await Gs(e,!0,{record:l}),s.push(".vscode/mcp.json regenerated"))}}),await a("index",async()=>{let d=".vesper/index.db";if(!await Rl(e,d)){i.push(d);return}if(!await w(_m(e,d))){let p=await ta(e,!1);p.success&&s.push(`code index built (${p.filesIndexed} files)`)}}),s.push(`local-only activation (${n}): tracked files, hooks and triggers left untouched`),o.length&&u.warn(`Worktree bootstrap finished with errors in: ${o.join(", ")}`),!r){u.success("Worktree bootstrap complete (local-only activation)");for(let d of s)u.info(` ${d}`);i.length&&u.info(` not written (git would track them here): ${i.join(", ")}`)}return{host:n,failed:o,localOnly:!0}}async function Lb(e,t,{runningHost:r}={}){if(!await w(e))return{skipped:"not-vesperized"};let n=await Ii(e,{runningHost:r});if(n.action==="bootstrap"){let{host:o,failed:i}=await Nl(e,n,{quiet:t});return i.length?{host:o,failed:i}:{host:o}}n.action==="refuse"?u.warn(n.reason==="host-mismatch"?`This workspace is provisioned for "${n.host}" but bootstrap was invoked as "${r}" \u2014 skipping all provisioning. Run \`vespercli init --host ${r}\` to switch, or \`vespercli reset --host ${r}\` to remove stray ${r} files.`:`Bootstrap wrote nothing. ${n.message}`):n.note&&(!t||n.reason==="legacy-unmigrated"||n.reason==="migration-in-progress")&&(n.reason==="legacy-unmigrated"||n.reason==="migration-in-progress"?u.warn(n.note):u.info(n.note));let s=n.host??n.checkout?.candidate??null;return{skipped:n.action==="refuse"?"host-mismatch":n.reason,...s?{host:s}:{}}}async function Mb(e,{sshCommandConfigured:t=!1}={}){let r=await D(["rev-parse","--abbrev-ref","origin/HEAD"],{cwd:e}),n=r===null?-1:r.indexOf("/");if(n===-1)return{note:"No base branch remote to refresh (origin/HEAD unset or no remote)."};let s=r.slice(0,n),o=r.slice(n+1),i=await Tt(["fetch",s,o],{cwd:e,timeout:15e3,env:Vn(process.env,{sshCommandConfigured:t}),detached:!0});return!i.ok&&ka.test(i.stderr)?(u.warn(Sa(`Fetching the latest ${s}/${o}`)),{}):i.ok?{action:`${s}/${o} fetched (latest base branch ref)`}:(u.warn(`Could not fetch the latest ${s}/${o} (offline, unreachable or timed out) \u2014 continuing with existing local refs.`),{})}async function Cm(e,t={}){let r=jb(t.path||process.cwd()),n=!!t.quiet;switch(e){case"bootstrap":case void 0:return Lb(r,n,{runningHost:t.runningHost});default:u.error(`Unknown subcommand: ${e}. Usage: vespercli worktree bootstrap`),process.exit(1)}}import{resolve as Fb}from"node:path";te();Te();async function $m(e={}){let t=Fb(e.path||process.cwd()),r=!!e.quiet,n=e.runningHost;if(n!==void 0&&!z.includes(n))return r||u.error(`--running-host must be one of: ${z.join(", ")} (received "${n}").`),{exitCode:Oe.ERROR,report:null};let s;try{s=await _n(t,{runningHost:n})}catch(i){return r||u.error(`doctor failed unexpectedly: ${i?.message||i}`),{exitCode:Oe.ERROR,report:null}}let o=Ri(s);return r||Gb(s),{exitCode:o,report:s}}function Gb(e){if(e.errors.length+e.warnings.length+e.infos.length===0){u.success("No issues found \u2014 this Vesper workspace is healthy.");return}Ll("Errors",e.errors,r=>u.error(r)),Ll("Warnings",e.warnings,r=>u.warn(r)),Ll("Info",e.infos,r=>u.info(r))}function Ll(e,t,r){if(t.length){console.log(),u.header(e);for(let n of t){let s=n.path?` (${n.path})`:"";r(`${n.message}${s}`),u.dim(` fix: ${n.fix}`)}}}import{resolve as zb}from"node:path";te();xe();import{readFile as Db,readdir as Vb,stat as jm}from"node:fs/promises";import{homedir as Ys}from"node:os";import{join as Bt,resolve as Rm,isAbsolute as Hb}from"node:path";var na=Object.freeze({NOT_ENABLED:"plugin-not-enabled",NOT_DECLARED:"marketplace-not-declared",SOURCE_MISSING:"marketplace-source-missing",INVALID_DECLARATION:"marketplace-declaration-invalid"});function Ml(e,t){return e.replace(/^~(?=$|[\\/])/,t)}function Nm({env:e=process.env,homeDir:t=Ys()}={}){let r=typeof e.CLAUDE_CONFIG_DIR=="string"?e.CLAUDE_CONFIG_DIR.trim():"";return r?Rm(Ml(r,t)):Bt(t,".claude")}function Om({env:e=process.env,homeDir:t=Ys()}={}){let r=typeof e.CLAUDE_CODE_PLUGIN_CACHE_DIR=="string"?e.CLAUDE_CODE_PLUGIN_CACHE_DIR.trim():"";return r?Rm(Ml(r,t)):Bt(Nm({env:e,homeDir:t}),"plugins")}function Ub(e=process.platform){return e==="darwin"?"/Library/Application Support/ClaudeCode":e==="win32"?"C:\\Program Files\\ClaudeCode":"/etc/claude-code"}async function Tm(e){try{let t=JSON.parse(await Db(e,"utf-8"));return t&&typeof t=="object"&&!Array.isArray(t)?t:null}catch{return null}}async function Pm(e){try{return await jm(e),!0}catch{return!1}}async function Wb(e){try{return(await jm(e)).isFile()}catch{return!1}}async function Kb(e,{env:t=process.env,homeDir:r=Ys(),platform:n=process.platform,managedDir:s}={}){let o=s??Ub(n),i=[{scope:"user",path:Bt(Nm({env:t,homeDir:r}),"settings.json")},{scope:"project",path:Me(e)},{scope:"local",path:En(e)},{scope:"managed",path:Bt(o,"managed-settings.json")}];try{let a=(await Vb(Bt(o,"managed-settings.d"))).filter(c=>c.endsWith(".json")).sort();for(let c of a)i.push({scope:"managed",path:Bt(o,"managed-settings.d",c)})}catch{}return i}function Im(e,t=Ys()){let r=s=>{if(typeof s!="string"||!s.trim())return null;let o=Ml(s.trim(),t);return Hb(o)?o:null};if(typeof e=="string")return r(e);if(!e||typeof e!="object")return null;let n=e.source;return typeof n=="string"?null:n&&typeof n=="object"?(n.source==="directory"||n.source==="file")&&typeof n.path=="string"?r(n.path):null:typeof e.installLocation=="string"?r(e.installLocation):null}async function Bb(e){return await Pm(e)?await Wb(e)?!0:Pm(Bt(e,".claude-plugin","marketplace.json")):!1}async function Lm(e,t={}){let r=t.env??process.env,n=t.homeDir??Ys(),s=await Kb(e,{...t,env:r,homeDir:n}),o,i=null,a,c=[],l=[];for(let m of s){let h=await Tm(m.path);if(!h)continue;let g=h.enabledPlugins;g&&typeof g=="object"&&typeof g[mt]=="boolean"&&(m.scope==="managed"?a!==!0&&(a=g[mt]):(o=g[mt],i=m.scope));let y=h.extraKnownMarketplaces;if(y&&typeof y=="object"&&y[Ce]!==void 0&&y[Ce]!==null){let k=y[Ce];if(k&&typeof k=="object"&&typeof k.source=="string"){l.push({scope:m.scope,path:m.path});continue}c.push({scope:m.scope,path:m.path,localPath:Im(k,n),exists:null})}}a!==void 0&&(o=a,i="managed");let d=await Tm(Bt(Om({env:r,homeDir:n}),"known_marketplaces.json"));if(d&&d[Ce]!==void 0&&d[Ce]!==null){let m=d[Ce],h=m&&typeof m=="object"&&m.source&&typeof m.source=="object"&&m.source.source!=="directory"&&m.source.source!=="file";c.push({scope:"known_marketplaces",path:Bt(Om({env:r,homeDir:n}),"known_marketplaces.json"),localPath:h?null:Im(m,n),exists:null})}let p=typeof r.CLAUDE_CODE_PLUGIN_SEED_DIR=="string"&&r.CLAUDE_CODE_PLUGIN_SEED_DIR.trim()!=="",f=[];if(o!==!0&&f.push(na.NOT_ENABLED),c.length===0&&!p)f.push(l.length?na.INVALID_DECLARATION:na.NOT_DECLARED);else if(c.length>0&&!p){let m=!1,h=!1;for(let g of c){if(g.localPath===null){m=!0;continue}g.exists=await Bb(g.localPath),g.exists&&(h=!0)}!m&&!h&&f.push(na.SOURCE_MISSING)}return{absent:f.length>0,missing:f,enabled:o,enabledBy:i,declarations:c,invalidDeclarations:l}}gt();ot();async function Yb(e,t){try{let{realpath:r}=await import("node:fs/promises"),{resolve:n}=await import("node:path"),s=await D(["rev-parse","--absolute-git-dir"],{cwd:t,env:Er(process.env),timeout:5e3});return s?await r(n(process.cwd(),e))===await r(s):!1}catch{return!1}}async function Mm(e){let t=process.stdout.write,r=[];process.stdout.write=(n,...s)=>{r.push(typeof n=="string"?n:String(n));let o=s.find(i=>typeof i=="function");return o&&o(),!0};try{return await e()}finally{process.stdout.write=t,r.length&&process.stderr.write(r.join(""))}}function Fm(e){process.stdout.write(`${e}
|
|
210
|
-
`)}async function
|
|
211
|
-
`),{exitCode:
|
|
212
|
-
`),await
|
|
213
|
-
`),!s.identity)return{exitCode:a.length?
|
|
214
|
-
`);return{exitCode:l,emitted:c,resolved:o,decision:s}}
|
|
215
|
-
`)}async function
|
|
205
|
+
Reload VS Code to apply changes`)}async function Ab(e){let t=await q(e),r=await x(e,t),s=(await K(e,t))[V]||{},o=Object.keys(s).length,i=await Cm(e);console.log(),u.header("MCP Tool Approval Status"),console.log();let a=Ne.filter(d=>s[d]);if(u.info(`Core tools: ${a.length}/${Ne.length} approved`),i.length>0){console.log(),u.info("Agent tools:");for(let d of i){let p=MCP_TOOLS_BY_AGENT[d]||[],f=p.filter(h=>s[h]),m=f.length===p.length?mt.green("\u2713"):mt.yellow("\u26A0");u.info(` ${m} ${d}: ${f.length}/${p.length} approved`)}}let c=[...Ne];for(let d of i)c.push(...MCP_TOOLS_BY_AGENT[d]||[]);let l=c.filter(d=>!s[d]);console.log(),u.info(`Total approved: ${o} tools`),l.length>0?(console.log(),u.warn(`${l.length} tools missing approval`),u.info("Run `vespercli mcp sync` to fix")):r.mcp?.syncedAt&&u.info(`Last synced: ${r.mcp.syncedAt}`)}function $m(){return Object.keys(we).filter(e=>!me.includes(e))}async function _b(e,t){t||(u.error("Server name required. Usage: vespercli mcp add <server>"),u.info(`Available servers: ${$m().join(", ")}`),process.exit(1)),console.log(),u.header("Add MCP Server"),console.log();let r=await ir(e,t);if(!r.added){r.error==="Already configured"?u.info(`MCP server '${t}' is already configured`):(u.error(r.error),process.exit(1));return}u.success(`Added MCP server: ${t}`),r.tools.length>0&&u.info(`Approved ${r.tools.length} tool(s) for auto-execution`),u.info(`
|
|
206
|
+
Reload VS Code to activate the MCP server`)}async function Cb(e,t){t||(u.error("Server name required. Usage: vespercli mcp remove <server>"),process.exit(1)),console.log(),u.header("Remove MCP Server"),console.log();let r=await nn(e,t);if(!r.removed){u.info(`MCP server '${t}' is not configured`);return}u.success(`Removed MCP server: ${t}`),r.tools.length>0&&u.info(`Removed ${r.tools.length} tool(s) from auto-approval`),u.info(`
|
|
207
|
+
Reload VS Code to deactivate the MCP server`)}async function $b(e){let t=await q(e),r=await x(e,t),n=await Ze(e);console.log(),u.header("MCP Servers"),console.log();let s=r.mcp?.servers||[],o=Object.keys(n.servers||{});u.info("Available servers:");for(let[a,c]of Object.entries(we)){let d=o.includes(a)?mt.green("\u2713"):mt.dim("\u25CB"),p=c.tools?.length||0;u.info(` ${d} ${a} (${p} tools)`)}let i=o.filter(a=>!we[a]);if(i.length>0){console.log(),u.info("Custom servers:");for(let a of i)u.info(` ${mt.blue("\u25C6")} ${a}`)}console.log(),u.info(`Installed: ${o.length} server(s)`)}async function Ob(e,t){t||(u.error("Server name required. Usage: vespercli mcp add <server> --target claude"),u.info(`Available servers: ${$m().join(", ")}`),process.exit(1));let r=await Sn(e,t);if(!r.added){r.error==="Already configured"?u.info(`MCP server '${t}' is already configured for the Claude Code target`):u.error(r.error);return}u.success(`Added MCP server: ${t} (Claude Code target)`),u.info(`
|
|
208
|
+
Reload the Claude Code session to activate the MCP server`)}async function Tb(e,t){t||(u.error("Server name required. Usage: vespercli mcp remove <server> --target claude"),process.exit(1));let r=await hi(e,t);if(r.error){u.error(r.error);return}if(!r.removed){u.info(`MCP server '${t}' is not configured for the Claude Code target`);return}u.success(`Removed MCP server: ${t} (Claude Code target)`),u.info(`
|
|
209
|
+
Reload the Claude Code session to deactivate the MCP server`)}async function Pb(e){let{configured:t,custom:r}=await Mc(e);console.log(),u.header("MCP Servers (Claude Code target)"),console.log(),u.info("Available servers:");for(let[n,s]of Object.entries(we)){let i=t.includes(n)?mt.green("\u2713"):mt.dim("\u25CB"),a=s.tools?.length||0;u.info(` ${i} ${n} (${a} tools)`)}if(r.length>0){console.log(),u.info("Custom servers:");for(let n of r)u.info(` ${mt.blue("\u25C6")} ${n}`)}console.log(),u.info(`Installed: ${t.length} server(s)`)}var Pn=Object.freeze({START_FAILED:1,UNKNOWN:2});async function Ib(e,t={}){let r=vm(t.path||process.cwd()),n=e?hm(e,r):null;if(!n)return console.error(`Unknown MCP server "${e??""}". \`vespercli mcp serve <name>\` knows: ${fm.join(", ")}.`),{exitCode:Pn.UNKNOWN};if(e==="vesper-indexing"&&!mb(n.args[0]))return console.error(`vesper-indexing is not built (${n.args[0]} is missing) \u2014 reinstall @mthanh/vespercli or run \`npm run build:mcp\` in the package.`),{exitCode:Pn.START_FAILED};if(e===pt&&!ri(r))return rt()?(console.error("graphify is installed but no interpreter has been recorded for this machine yet."),console.error(`Run \`${Se}\` once to build the graph and record a working interpreter (${Ut}).`)):(console.error(`graphify needs Python to serve its MCP tools, and none was found on PATH (no python3 / python, no recorded ${Ut}).`),console.error(`Install graphify for this machine: ${xs()}`)),console.error("This is the opt-in graphify pack; vesper-indexing remains the default codebase tool."),{exitCode:Pn.START_FAILED};if(e===pt&&!await Bd(n.command))return console.error(`graphify needs Python to serve its MCP tools. \`${n.command}\` is on PATH but cannot \`import graphify\` \u2014 it is likely installed into an isolated environment (uv tool / pipx), not this interpreter.`),console.error(`Run \`${Se}\` once on this machine so graphify records the interpreter that can actually import it (${Ut}).`),console.error("This is the opt-in graphify pack; vesper-indexing remains the default codebase tool."),{exitCode:Pn.START_FAILED};let s=n.command==="node"?process.execPath:n.command;return new Promise(o=>{let i;try{i=gb(s,n.args,{stdio:"inherit",env:{...process.env,...n.env},shell:process.platform==="win32"&&s!==process.execPath})}catch(c){return console.error(`Could not start ${e}: ${c?.message||c}`),o({exitCode:Pn.START_FAILED})}let a=c=>{try{i.kill(c)}catch{}};for(let c of["SIGINT","SIGTERM","SIGHUP"])process.on(c,a);i.on("error",c=>{console.error(`Could not start ${e}: ${c?.message||c}`),o({exitCode:Pn.START_FAILED})}),i.on("exit",(c,l)=>o({exitCode:c??(l?1:0)}))})}async function Om(e,t,r={}){let n=vm(r.path||process.cwd());if(await w(n)||(u.error(`Directory not found: ${n}`),process.exit(1)),e==="serve"){let{exitCode:l}=await Ib(t,r);process.exitCode=l;return}let s=(await B(n)).host,o=s?[s]:await ge(n);!r.target&&o.length>1&&(u.error(et),process.exit(1)),!r.target&&o.length===0&&yb.has(e)&&(u.error(`\`vespercli mcp ${e}\` needs an initialized workspace \u2014 nothing was written. Run \`vespercli init\` first.`),process.exit(1));let i=r.target?[r.target]:o.length?o:["copilot"],a=i.includes("copilot"),c=i.includes("claude");if(c&&!a)switch(Em.has(e)&&s!=="claude"&&(u.error(wb(e)),process.exit(1)),e){case"enable":return await Ll(n,!0);case"disable":return await Ll(n,!1);case"sync":return await Ll(n,!0);case"add":return await Ob(n,t);case"remove":return await Tb(n,t);case"list":return await Pb(n);case"status":return await gm(n,s);case"reindex":return await wm(n,r.full);default:return e&&u.warn(`'${e}' is not applicable to the Claude Code target \u2014 showing status instead.`),await gm(n,s)}switch(e){case"status":await ym(n,r.watch);break;case"add":await _b(n,t);break;case"remove":await Cb(n,t);break;case"list":await $b(n);break;case"reindex":await wm(n,r.full);break;case"enable":await Eb(n);break;case"disable":await bb(n);break;case"sync":await xb(n);break;case"approve":await Ab(n);break;default:await ym(n,r.watch)}}Ie();H();import{resolve as jb}from"node:path";async function Pm(e,t,r,n={}){let s=jb(n.path||process.cwd());if(!e){Tm();return}switch(e){case"add":await Rb(s,t,r);break;case"remove":await Nb(s,t,r);break;case"list":await Lb(s,t);break;default:u.error(`Unknown subcommand: ${e}`),Tm()}}async function Rb(e,t,r){if(!t){u.error("Setting key required"),u.info("Usage: vespercli settings add <setting-key> <value>");return}switch(t){case"github.copilot.chat.additionalReadAccessPaths":case"additionalReadAccessPaths":case"read-access":if(!r){u.error("Path value required"),u.info("Usage: vespercli settings add read-access <path>");return}let n=await Io(e,r);u.success(`Added "${r}" to additional read access paths`),u.info(`Current paths: ${n.length>0?n.join(", "):"(none)"}`);break;default:u.error(`Unknown setting: ${t}`),u.info("Supported settings:"),u.info(" - read-access (github.copilot.chat.additionalReadAccessPaths)")}}async function Nb(e,t,r){if(!t){u.error("Setting key required"),u.info("Usage: vespercli settings remove <setting-key> <value>");return}switch(t){case"github.copilot.chat.additionalReadAccessPaths":case"additionalReadAccessPaths":case"read-access":if(!r){u.error("Path value required"),u.info("Usage: vespercli settings remove read-access <path>");return}let n=await jo(e,r);u.success(`Removed "${r}" from additional read access paths`),u.info(`Current paths: ${n.length>0?n.join(", "):"(none)"}`);break;default:u.error(`Unknown setting: ${t}`),u.info("Supported settings:"),u.info(" - read-access (github.copilot.chat.additionalReadAccessPaths)")}}async function Lb(e,t){if(!t){u.info("Managed settings:"),u.info(" - read-access (github.copilot.chat.additionalReadAccessPaths)"),u.info(""),u.info("Use: vespercli settings list <setting-key>");return}switch(t){case"github.copilot.chat.additionalReadAccessPaths":case"additionalReadAccessPaths":case"read-access":let r=await Ro(e);u.info(`${oe}:`),r.length===0?u.info(" (empty)"):r.forEach(n=>u.info(` - ${n}`));break;default:u.error(`Unknown setting: ${t}`),u.info("Supported settings:"),u.info(" - read-access (github.copilot.chat.additionalReadAccessPaths)")}}function Tm(){u.info("Usage: vespercli settings <subcommand> [setting-key] [value]"),u.info(""),u.info("Subcommands:"),u.info(" add <setting-key> <value> Add a value to an array setting"),u.info(" remove <setting-key> <value> Remove a value from an array setting"),u.info(" list [setting-key] List current values"),u.info(""),u.info("Supported settings:"),u.info(" read-access github.copilot.chat.additionalReadAccessPaths"),u.info(""),u.info("Examples:"),u.info(" vespercli settings add read-access /path/to/external/repo"),u.info(" vespercli settings remove read-access /path/to/external/repo"),u.info(" vespercli settings list read-access")}U();H();te();Ae();_e();import{resolve as Im}from"node:path";Kt();Ie();async function Mb(e={},t){let r=Im(e.path||process.cwd());if(t!=="claude"){u.warn('Claude Code target is not initialized. Run "vesper init --target claude" first.');return}console.log(),u.info("Refreshing Claude Code project catalog and orchestrator playbook...");let{pluginDir:n,counts:s,pruned:o}=await Si({workspaceRoot:r,namePrefix:await an(r),version:e.version});u.success(`Project catalog refreshed: ${n}`),u.info(` agents: ${s.agents}, commands: ${s.commands}, skills: ${s.skills}`),o.length&&u.info(` pruned ${o.length} asset(s) removed in this version: ${o.join(", ")}`);let i=await xi(r);u.success(`Orchestrator playbook refreshed (.claude/rules/vesper-orchestrator.md: ${i.orchestrator})`),u.info("Team roster (.claude/rules/vesper-orchestration.md) and project context (.claude/rules/vesper-context.md) are left alone \u2014 they belong to this project."),u.info(`OpenCode overlay: .opencode/agents/vesper-orchestrator.md (${i.opencodeAgent}), .opencode/plugins/vesper.js (${i.opencodePlugin})`),i.opencodeKept?.length&&u.warn(`Left in place \u2014 they differ from what Vesper writes (your edits, or an older build's copy): ${i.opencodeKept.join(", ")}. Delete them to get this version's copy.`),Hr(await pr(r,"claude"))}async function Gb({isTTY:e=!!process.stdout.isTTY,check:t=sa,timeoutMs:r=na}={}){if(!e)return[];let n=[];try{n=await t({timeoutMs:r})}catch{n=[]}let s=n.filter(o=>o.status==="stale").map(Jh);for(let o of s)u.info(o);return s}async function jm(e={}){try{let t=Im(e.path||process.cwd());await w(t)||(u.error(`Directory not found: ${u.formatPath(t)}`),process.exit(1));let r=await B(t);(await Te(t,{checkout:r})).unmigrated&&(u.error(st),process.exit(1));let n=e.target?null:r.host,s=e.target?[e.target]:n?[n]:await ge(t);if(s.length===0){u.warn('Vesper is not initialized. Run "vespercli init" first.');return}if(!e.target&&s.length>1&&(u.error(et),process.exit(1)),s.includes("claude")&&await Mb({...e,path:t},r.host),s.includes("copilot")){console.log(),u.info("Copilot assets are linked from the package, not copied."),u.info("Update the vesper package to get the latest assets:"),u.dim(" npm update -g @mthanh/vespercli"),console.log();let o=await Vi(t),i=[[".vesper/agents/vesper-orchestrator.agent.md",o.orchestratorAgent],[".vesper/instructions/vesper-orchestrator.instructions.md",o.orchestrator]].filter(([,c])=>c==="created"||c==="updated");i.length?u.success(`Project brain refreshed: ${i.map(([c])=>c).join(", ")}`):u.info("Project brain already up to date."),Hr(await pr(t,"copilot"));let a=await Dr(t);a==="removed"&&u.info("Retired .vesper/instructions/vesper-host-guard.instructions.md (no longer used)."),a==="kept"&&u.warn(An())}await Gb(e)}catch(t){u.error(`Update failed: ${t.message}`),process.exit(1)}}U();H();_e();te();import{resolve as Fb,join as Rm}from"node:path";at();vt();ft();Ie();async function Db(e){await md(e)}async function Fl(e,t,{quiet:r=!1}={}){if(t?.action!=="bootstrap"||!z.includes(t.host))throw new Error("runBootstrap requires a bootstrap decision");let n=t.host,s=t.network!==!1;if(t.checkout?.source==="local")return Vb(e,t,{quiet:r});let o=[],i=[],a=async(m,h)=>{try{return await h()}catch(g){i.push(m),u.warn(`Bootstrap step "${m}" failed (continuing): ${g?.message??g}`);return}},l={sshCommandConfigured:s?!!await D(["config","--get","core.sshCommand"],{cwd:e}):!1},d=s?Ub(e,l).catch(()=>({})):Promise.resolve({});await a("mcp",async()=>{n==="claude"?(await mr(e,!0),o.push(".mcp.json regenerated for this worktree"),await Ci(e),o.push(".claude/settings.local.json marketplace source regenerated for this machine")):(await Hs(e,!0),o.push(".vscode/mcp.json regenerated for this worktree"))}),await a("index",async()=>{let m=Rm(e,".vesper","index.db");if(!await w(m)){let h=await oa(e,!1);h.success&&o.push(`code index built (${h.filesIndexed} files)`)}}),await a("gitignore",()=>Jn(e)),await a("tracked-local",async()=>{let m=await qn(e);if(m.length>0){let h=m.map(g=>`'${g.replace(/'/g,"'\\''")}'`);u.warn(`Local-only file(s) git-tracked despite .gitignore: ${h.join(", ")} \u2014 untrack with: git rm --cached -- ${h.join(" ")}`)}});let p=await a("hooks",()=>ns(e));p&&o.push(...rs(p)),await a("graphify",async()=>{await hn(e,n)&&await Es(e,n)}),await a("attributes",()=>ss(e)),await a("merge-driver",()=>os(e)),o.push(p&&Ga(p)?"gitignore + git hooks + merge strategy ensured":"gitignore + merge strategy ensured");let f=await a("fetch",()=>d)??{};if(f.action&&o.unshift(f.action),f.note&&!r&&u.info(f.note),await a("triggers",()=>Ni(e,n,{unattended:!0})),await a("ledger",()=>Db(e)),o.push(`host guard triggers ensured (${n} + cross-host)`),i.length&&u.warn(`Worktree bootstrap finished with errors in: ${i.join(", ")}`),!r){u.success(i.length?"Worktree bootstrap finished (with errors)":"Worktree bootstrap complete");for(let m of o)u.info(` ${m}`)}return{host:n,failed:i}}async function Gl(e,t){return await D(["check-ignore","-q","--",t],{cwd:e,timeout:5e3})!==null}async function Vb(e,t,{quiet:r=!1}={}){let n=t.host,s=[],o=[],i=[],a=async(d,p)=>{try{return await p()}catch(f){o.push(d),u.warn(`Bootstrap step "${d}" failed (continuing): ${f?.message??f}`);return}},c=n==="claude"?[".mcp.json",".claude/settings.local.json"]:[".vscode/mcp.json"],l=await Gl(e,".vesperrc");if(l||i.push(".vesperrc (ledger not re-recorded)"),await a("mcp",async()=>{for(let d of c){if(!await Gl(e,d)){i.push(d);continue}d===".mcp.json"?(await mr(e,!0,{record:l}),s.push(".mcp.json regenerated")):d===".claude/settings.local.json"?(await Ci(e,{record:l}),s.push(".claude/settings.local.json regenerated")):(await Hs(e,!0,{record:l}),s.push(".vscode/mcp.json regenerated"))}}),await a("index",async()=>{let d=".vesper/index.db";if(!await Gl(e,d)){i.push(d);return}if(!await w(Rm(e,d))){let p=await oa(e,!1);p.success&&s.push(`code index built (${p.filesIndexed} files)`)}}),s.push(`local-only activation (${n}): tracked files, hooks and triggers left untouched`),o.length&&u.warn(`Worktree bootstrap finished with errors in: ${o.join(", ")}`),!r){u.success("Worktree bootstrap complete (local-only activation)");for(let d of s)u.info(` ${d}`);i.length&&u.info(` not written (git would track them here): ${i.join(", ")}`)}return{host:n,failed:o,localOnly:!0}}async function Hb(e,t,{runningHost:r}={}){if(!await w(e))return{skipped:"not-vesperized"};let n=await Li(e,{runningHost:r});if(n.action==="bootstrap"){let{host:o,failed:i}=await Fl(e,n,{quiet:t});return i.length?{host:o,failed:i}:{host:o}}n.action==="refuse"?u.warn(n.reason==="host-mismatch"?`This workspace is provisioned for "${n.host}" but bootstrap was invoked as "${r}" \u2014 skipping all provisioning. Run \`vespercli init --host ${r}\` to switch, or \`vespercli reset --host ${r}\` to remove stray ${r} files.`:`Bootstrap wrote nothing. ${n.message}`):n.note&&(!t||n.reason==="legacy-unmigrated"||n.reason==="migration-in-progress")&&(n.reason==="legacy-unmigrated"||n.reason==="migration-in-progress"?u.warn(n.note):u.info(n.note));let s=n.host??n.checkout?.candidate??null;return{skipped:n.action==="refuse"?"host-mismatch":n.reason,...s?{host:s}:{}}}async function Ub(e,{sshCommandConfigured:t=!1}={}){let r=await D(["rev-parse","--abbrev-ref","origin/HEAD"],{cwd:e}),n=r===null?-1:r.indexOf("/");if(n===-1)return{note:"No base branch remote to refresh (origin/HEAD unset or no remote)."};let s=r.slice(0,n),o=r.slice(n+1),i=await Pt(["fetch",s,o],{cwd:e,timeout:15e3,env:Un(process.env,{sshCommandConfigured:t}),detached:!0});return!i.ok&&ba.test(i.stderr)?(u.warn(xa(`Fetching the latest ${s}/${o}`)),{}):i.ok?{action:`${s}/${o} fetched (latest base branch ref)`}:(u.warn(`Could not fetch the latest ${s}/${o} (offline, unreachable or timed out) \u2014 continuing with existing local refs.`),{})}async function Nm(e,t={}){let r=Fb(t.path||process.cwd()),n=!!t.quiet;switch(e){case"bootstrap":case void 0:return Hb(r,n,{runningHost:t.runningHost});default:u.error(`Unknown subcommand: ${e}. Usage: vespercli worktree bootstrap`),process.exit(1)}}import{resolve as Wb}from"node:path";te();Ie();async function Lm(e={}){let t=Wb(e.path||process.cwd()),r=!!e.quiet,n=e.runningHost;if(n!==void 0&&!z.includes(n))return r||u.error(`--running-host must be one of: ${z.join(", ")} (received "${n}").`),{exitCode:Pe.ERROR,report:null};let s;try{s=await Cn(t,{runningHost:n})}catch(i){return r||u.error(`doctor failed unexpectedly: ${i?.message||i}`),{exitCode:Pe.ERROR,report:null}}let o=Gi(s);return r||Kb(s),{exitCode:o,report:s}}function Kb(e){if(e.errors.length+e.warnings.length+e.infos.length===0){u.success("No issues found \u2014 this Vesper workspace is healthy.");return}Dl("Errors",e.errors,r=>u.error(r)),Dl("Warnings",e.warnings,r=>u.warn(r)),Dl("Info",e.infos,r=>u.info(r))}function Dl(e,t,r){if(t.length){console.log(),u.header(e);for(let n of t){let s=n.path?` (${n.path})`:"";r(`${n.message}${s}`),u.dim(` fix: ${n.fix}`)}}}import{resolve as Zb}from"node:path";te();_e();import{readFile as Bb,readdir as zb,stat as Vm}from"node:fs/promises";import{homedir as Xs}from"node:os";import{join as Yt,resolve as Hm,isAbsolute as Yb}from"node:path";var ia=Object.freeze({NOT_ENABLED:"plugin-not-enabled",NOT_DECLARED:"marketplace-not-declared",SOURCE_MISSING:"marketplace-source-missing",INVALID_DECLARATION:"marketplace-declaration-invalid"});function Vl(e,t){return e.replace(/^~(?=$|[\\/])/,t)}function Um({env:e=process.env,homeDir:t=Xs()}={}){let r=typeof e.CLAUDE_CONFIG_DIR=="string"?e.CLAUDE_CONFIG_DIR.trim():"";return r?Hm(Vl(r,t)):Yt(t,".claude")}function Mm({env:e=process.env,homeDir:t=Xs()}={}){let r=typeof e.CLAUDE_CODE_PLUGIN_CACHE_DIR=="string"?e.CLAUDE_CODE_PLUGIN_CACHE_DIR.trim():"";return r?Hm(Vl(r,t)):Yt(Um({env:e,homeDir:t}),"plugins")}function Jb(e=process.platform){return e==="darwin"?"/Library/Application Support/ClaudeCode":e==="win32"?"C:\\Program Files\\ClaudeCode":"/etc/claude-code"}async function Gm(e){try{let t=JSON.parse(await Bb(e,"utf-8"));return t&&typeof t=="object"&&!Array.isArray(t)?t:null}catch{return null}}async function Fm(e){try{return await Vm(e),!0}catch{return!1}}async function qb(e){try{return(await Vm(e)).isFile()}catch{return!1}}async function Xb(e,{env:t=process.env,homeDir:r=Xs(),platform:n=process.platform,managedDir:s}={}){let o=s??Jb(n),i=[{scope:"user",path:Yt(Um({env:t,homeDir:r}),"settings.json")},{scope:"project",path:Fe(e)},{scope:"local",path:bn(e)},{scope:"managed",path:Yt(o,"managed-settings.json")}];try{let a=(await zb(Yt(o,"managed-settings.d"))).filter(c=>c.endsWith(".json")).sort();for(let c of a)i.push({scope:"managed",path:Yt(o,"managed-settings.d",c)})}catch{}return i}function Dm(e,t=Xs()){let r=s=>{if(typeof s!="string"||!s.trim())return null;let o=Vl(s.trim(),t);return Yb(o)?o:null};if(typeof e=="string")return r(e);if(!e||typeof e!="object")return null;let n=e.source;return typeof n=="string"?null:n&&typeof n=="object"?(n.source==="directory"||n.source==="file")&&typeof n.path=="string"?r(n.path):null:typeof e.installLocation=="string"?r(e.installLocation):null}async function Qb(e){return await Fm(e)?await qb(e)?!0:Fm(Yt(e,".claude-plugin","marketplace.json")):!1}async function Wm(e,t={}){let r=t.env??process.env,n=t.homeDir??Xs(),s=await Xb(e,{...t,env:r,homeDir:n}),o,i=null,a,c=[],l=[];for(let m of s){let h=await Gm(m.path);if(!h)continue;let g=h.enabledPlugins;g&&typeof g=="object"&&typeof g[wt]=="boolean"&&(m.scope==="managed"?a!==!0&&(a=g[wt]):(o=g[wt],i=m.scope));let y=h.extraKnownMarketplaces;if(y&&typeof y=="object"&&y[Oe]!==void 0&&y[Oe]!==null){let k=y[Oe];if(k&&typeof k=="object"&&typeof k.source=="string"){l.push({scope:m.scope,path:m.path});continue}c.push({scope:m.scope,path:m.path,localPath:Dm(k,n),exists:null})}}a!==void 0&&(o=a,i="managed");let d=await Gm(Yt(Mm({env:r,homeDir:n}),"known_marketplaces.json"));if(d&&d[Oe]!==void 0&&d[Oe]!==null){let m=d[Oe],h=m&&typeof m=="object"&&m.source&&typeof m.source=="object"&&m.source.source!=="directory"&&m.source.source!=="file";c.push({scope:"known_marketplaces",path:Yt(Mm({env:r,homeDir:n}),"known_marketplaces.json"),localPath:h?null:Dm(m,n),exists:null})}let p=typeof r.CLAUDE_CODE_PLUGIN_SEED_DIR=="string"&&r.CLAUDE_CODE_PLUGIN_SEED_DIR.trim()!=="",f=[];if(o!==!0&&f.push(ia.NOT_ENABLED),c.length===0&&!p)f.push(l.length?ia.INVALID_DECLARATION:ia.NOT_DECLARED);else if(c.length>0&&!p){let m=!1,h=!1;for(let g of c){if(g.localPath===null){m=!0;continue}g.exists=await Qb(g.localPath),g.exists&&(h=!0)}!m&&!h&&f.push(ia.SOURCE_MISSING)}return{absent:f.length>0,missing:f,enabled:o,enabledBy:i,declarations:c,invalidDeclarations:l}}vt();at();async function ex(e,t){try{let{realpath:r}=await import("node:fs/promises"),{resolve:n}=await import("node:path"),s=await D(["rev-parse","--absolute-git-dir"],{cwd:t,env:xr(process.env),timeout:5e3});return s?await r(n(process.cwd(),e))===await r(s):!1}catch{return!1}}async function Km(e){let t=process.stdout.write,r=[];process.stdout.write=(n,...s)=>{r.push(typeof n=="string"?n:String(n));let o=s.find(i=>typeof i=="function");return o&&o(),!0};try{return await e()}finally{process.stdout.write=t,r.length&&process.stderr.write(r.join(""))}}function Bm(e){process.stdout.write(`${e}
|
|
210
|
+
`)}async function zm(e={}){let t=Zb(e.path||process.cwd()),r={};if(process.env.GIT_DIR&&await ex(process.env.GIT_DIR,t))for(let n of lo())n in process.env&&(r[n]=process.env[n],delete process.env[n]);try{return await tx(t,e)}finally{Object.assign(process.env,r)}}async function tx(e,t){let r=t.bootstrap!==!1;if(t.runningHost!==void 0&&!wf(t.runningHost))return process.stderr.write(`vespercli guard: --running-host must be one of: ${[...z,Gs].join(", ")} (received "${t.runningHost}")
|
|
211
|
+
`),{exitCode:Pe.ERROR,emitted:[],resolved:{host:null,source:null}};let n=yf(t.runningHost),s=await Li(e,{runningHost:n,runningLabel:t.runningHost}),o={host:s.checkout?.host??null,source:s.checkout?.source??null},i=null;if(s.identity)try{i=await Cn(e,{runningHost:n,checkout:s.checkout})}catch{i=null}if(s.action==="refuse")return Bm(Ri),process.stdout.write(`${s.message}
|
|
212
|
+
`),await Km(async()=>{if(s.reason!=="switch-in-progress")try{await Sf(e,n,{checkout:s.checkout})}catch{}}),{exitCode:Pe.HOST_MISMATCH,emitted:[Ri],resolved:o,decision:s};let a=[];if(await Km(async()=>{s.action==="bootstrap"&&r&&({failed:a}=await Fl(e,s,{quiet:!0}))}),s.action==="none"&&s.note&&(s.identity||process.stderr.isTTY)&&process.stderr.write(`${s.note}
|
|
213
|
+
`),!s.identity)return{exitCode:a.length?Pe.ERROR:Pe.OK,emitted:[],resolved:o,decision:s};let c=[];if(t.runningHost==="claude"&&o.host==="claude"){let d=null;try{d=await Wm(e)}catch{d=null}d?.absent&&(Bm(zc),c.push(zc))}let l=i?Gi(i):Pe.ERROR;if(a.length&&l===Pe.OK&&(l=Pe.ERROR),i&&l===Pe.ERROR)for(let d of i.errors)process.stderr.write(`vespercli guard: ${d.message} (fix: ${d.fix})
|
|
214
|
+
`);return{exitCode:l,emitted:c,resolved:o,decision:s}}As();U();import{resolve as rx,isAbsolute as nx,join as sx}from"node:path";async function Ym(e={}){let t=rx(e.path||process.cwd()),r=!!e.json,n=await Qd(t);if(!n.ok){let l=n.reason==="missing"?`No ${ue} in ${t} \u2014 run \`vespercli init\` to seed one.`:`${ue} is invalid: ${n.errors.join("; ")}`;return r?console.log(JSON.stringify({pass:!1,error:l,exitCode:Rr.NO_CONFIG})):console.error(l),{exitCode:Rr.NO_CONFIG,report:null}}let s=null;if(e.plan){let l=nx(e.plan)?e.plan:sx(t,e.plan);if(!await w(l)){let d=`--plan file not found: ${e.plan}`;return r?console.log(JSON.stringify({pass:!1,error:d,exitCode:Rr.NO_CONFIG})):console.error(d),{exitCode:Rr.NO_CONFIG,report:null}}s=(await Zd(l)).planned}let o=[];for(let l of n.config.checks)o.push(rp(l,t));let i=await np(t,e.base),a=i.skipped?null:i,c=ep({config:n.config,checks:o,diff:a,planned:s,diffSkipped:i.skipped||null});return console.log(r?JSON.stringify(c):tp(c)),{exitCode:c.pass?Rr.PASS:Rr.FAIL,report:c}}import{resolve as ox}from"node:path";async function ix(){if(process.stdin.isTTY)return"";let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf-8")}async function Jm(e,t={}){let r=ox(t.path||process.cwd()),n=!!t.json;if(e==="tail"){let a=t.lines===void 0?ta:Number(t.lines);if(!Number.isFinite(a)||a<0)return console.error(`-n must be a non-negative number (received "${t.lines}")`),{exitCode:Tn.INVALID};let{rows:c,malformed:l}=await Hh(r,{slug:t.slug}),d=Uh(c,a);if(n)for(let p of d)console.log(JSON.stringify(p));else if(d.length===0)console.log(t.slug?`No run ledger rows for slug "${t.slug}".`:"No run ledger rows yet.");else for(let p of d)console.log(Wh(p));return l>0&&!n&&console.error(`(${l} malformed line(s) skipped)`),{exitCode:Tn.OK}}if(!Js.includes(e))return console.error(`Unknown log event "${e}". Use one of: ${Js.join(", ")}, tail.`),{exitCode:Tn.INVALID};let s={event:e,pipeline:t.pipeline,step:t.step,agent:t.agent,goal:t.goal,author:t.author,status:t.status,note:t.note,session:t.session};if(t.stdin){let a=Kh(await ix());a&&(!s.agent&&a.agent&&(s.agent=a.agent),!s.session&&a.session&&(s.session=a.session))}let o=Dh(s);if(!o.ok){for(let a of o.errors)console.error(a);return{exitCode:Tn.INVALID}}let{rel:i}=await Vh(r,o.row,{slug:t.slug});return console.log(n?JSON.stringify({...o.row,file:i}):`logged ${e} \u2192 ${i}`),{exitCode:Tn.OK}}import{resolve as px}from"node:path";U();import{readdir as ax,readFile as cx}from"node:fs/promises";import{join as Hl}from"node:path";var Ul=".vesper/.tracking/stories",Ur=Object.freeze(["refining","backlog","inprogress","inreview","completed"]),yr=Object.freeze({OK:0,REFUSED:1,INVALID:2});function lx(e){return e.replace(/\.md$/i,"").replace(/^\d{8}-/,"").replace(/-story$/i,"")}function ux(e){let t=/^#\s+(.+?)\s*$/m.exec(String(e??""));return t?t[1]:null}async function Wl(e,{folder:t}={}){let r=t?[t]:Ur,n=[];for(let s of r){let o=Hl(e,Ul,s),i=[];try{i=await ax(o,{withFileTypes:!0})}catch{continue}for(let a of i.filter(c=>c.isFile()&&c.name.toLowerCase().endsWith(".md")).sort((c,l)=>c.name.localeCompare(l.name))){let c=`${Ul}/${s}/${a.name}`,l=null;try{l=ux(await cx(Hl(o,a.name),"utf-8"))}catch{l=null}n.push({slug:lx(a.name),folder:s,file:a.name,rel:c,title:l})}}return n}async function dx(e,t){let r=String(t??"").trim().toLowerCase();return r?(await Wl(e)).filter(n=>n.file.toLowerCase().includes(r)):[]}async function qm(e,t,r){if(!Ur.includes(r))return{ok:!1,reason:"invalid-folder"};let n=await dx(e,t);if(n.length===0)return{ok:!1,reason:"not-found",matches:n};if(n.length>1)return{ok:!1,reason:"ambiguous",matches:n};let[s]=n,o=`${Ul}/${r}/${s.file}`;if(s.folder===r)return{ok:!0,from:s.rel,to:o,method:"noop"};if(await w(Hl(e,o)))return{ok:!1,reason:"exists",matches:n};let i=await Zi(e,s.rel,o);return i.ok?{ok:!0,from:s.rel,to:o,method:i.method}:{ok:!1,reason:i.reason,matches:n}}function Xm(e){if(e.length===0)return"(no stories)";let t=Math.max(...e.map(r=>r.folder.length));return e.map(r=>`${r.folder.padEnd(t)} ${r.slug}${r.title?` \u2014 ${r.title}`:""}`).join(`
|
|
215
|
+
`)}async function Qm(e,t,r,n={}){let s=px(n.path||process.cwd()),o=!!n.json;if(e==="list"){if(n.folder&&!Ur.includes(n.folder))return console.error(`--folder must be one of ${Ur.join("|")} (received "${n.folder}")`),{exitCode:yr.INVALID};let i=await Wl(s,{folder:n.folder});return console.log(o?JSON.stringify(i):Xm(i)),{exitCode:yr.OK}}if(e==="move"){if(!t||!r)return console.error("Usage: vespercli story move <slug> <folder>"),{exitCode:yr.INVALID};if(!Ur.includes(r))return console.error(`Folder must be one of ${Ur.join("|")} (received "${r}")`),{exitCode:yr.INVALID};let i=await qm(s,t,r);if(!i.ok){let a=(i.matches||[]).map(l=>l.rel),c=i.reason==="not-found"?`No story matches "${t}" under .vesper/.tracking/stories/.`:i.reason==="ambiguous"?`"${t}" matches ${a.length} stories \u2014 be more specific:
|
|
216
216
|
${a.join(`
|
|
217
|
-
`)}`:i.reason==="exists"?`Refusing: a file with that name already exists in ${r}/.`:`Refusing: ${i.reason}.`;return o?console.log(JSON.stringify({ok:!1,reason:i.reason,matches:a})):console.error(c),{exitCode:
|
|
218
|
-
`);async function
|
|
217
|
+
`)}`:i.reason==="exists"?`Refusing: a file with that name already exists in ${r}/.`:`Refusing: ${i.reason}.`;return o?console.log(JSON.stringify({ok:!1,reason:i.reason,matches:a})):console.error(c),{exitCode:yr.REFUSED}}return console.log(o?JSON.stringify(i):i.method==="noop"?`Already in ${r}/: ${i.from}`:`Moved (${i.method}): ${i.from} \u2192 ${i.to}`),{exitCode:yr.OK}}return console.error(`Unknown story subcommand "${e}". Use: move <slug> <folder>, list [--folder <f>].`),{exitCode:yr.INVALID}}Ae();$c();di();Ie();import{resolve as fx}from"node:path";var aa=Object.freeze({OK:0,REFUSED:1,USAGE:2}),Zm=["Usage: vespercli opencode <subcommand> [--path <dir>]","","OpenCode is a companion of the Claude host: `vespercli init --host claude` writes the overlay",`(\`${Ts}\`, \`${Lr}/vesper-orchestrator.md\`, \`.opencode/plugins/vesper.js\`),`,"and the plugin registers every specialist from the installed package at runtime.","","Subcommands:",` render-agents Write \`${Lr}/<id>.md\` for every core + enabled-pack specialist`,' (the generated-files fallback \u2014 `vesper.agentsMode: "files"` in opencode.json),'," record them in the ledger and prune the recorded files whose agent is gone."," Idempotent. Packs: opencode.json `vesper.packs`, else the Claude host's enabled packs.","","Related:"," vespercli mcp serve <name> Run a catalog MCP server from the package (what opencode.json `mcp` points at)"," vespercli --print-assets-dir Print the package assets directory (what the plugin locates the catalog with)"].join(`
|
|
218
|
+
`);async function eg(e,t={}){let r=fx(t.path||process.cwd());if(!e||e==="help")return console.log(Zm),{exitCode:aa.OK};if(e!=="render-agents")return console.error(`Unknown opencode subcommand "${e}".
|
|
219
219
|
|
|
220
|
-
${
|
|
221
|
-
`),process.exit(0));de.command("init").description("Initialize vesper for exactly ONE host (GitHub Copilot, or Claude Code + OpenCode) in this workspace \u2014 prompts when omitted; switching hosts cleans the other host's artifacts after confirmation").option("-p, --path <path>","Workspace root directory",process.cwd()).option("-y, --yes","Skip follow-up prompts and the host-switch confirmation (not the host selection)").option("-f, --force","Force re-initialization (skips follow-up prompts)").option("--force-default","Use all default values for follow-up prompts (not the host selection)").option("--graphify","Enable the opt-in graphify pack (code knowledge graph for the research roles; external tool: `uv tool install graphifyy`) without asking \u2014 the default, and what -y/--force-default/--force/no TTY keep, is no pack").addOption(new
|
|
222
|
-
`),t)}de.command("add").description("Add an opt-in asset. Copilot: opt-in instructions (every agent, prompt and skill is already available). Claude Code: every specialist and skill is served by the vesper plugin \u2014 `--override` pins a project-level copy. Host auto-detected when omitted.").argument("[type]","Asset type (agents, prompts, instructions, skills)").argument("[name]","Asset name (specific asset to add)").option("--path <path>","Workspace root directory",process.cwd()).addOption(Js("Host to act on: claude or copilot (the checkout decides when omitted)")).addOption(qs()).option("--override","Claude Code only: pin a project-level copy of a plugin asset (recorded; reset removes it)").action((e,t,r)=>Qh({type:e,name:t,...Xs("add",r)}));de.command("reset").description("Remove a host's Vesper artifacts. `--host <x>` force-cleans host x (the active host = full teardown; the other host = foreign-residue clean, never an ambiguity error). Auto-detected from the workspace when omitted.").option("--path <path>","Workspace root directory",process.cwd()).option("-y, --yes","Skip confirmation prompts").addOption(new ft("--host <host>","Host whose artifacts to remove: claude or copilot").choices(["claude","copilot"])).option("--purge-knowledge","On a FULL teardown, also delete the Team Roster, project whitepaper and on-demand context tier (kept by default)").addOption(new ft("--target <target>","Deprecated alias of --host").hideHelp()).action(th);de.command("list").alias("ls").description("List enabled assets").argument("[type]","Filter by asset type (agents, prompts, instructions, skills)").option("--path <path>","Workspace root directory",process.cwd()).addOption(Js("Host to list: claude or copilot (the checkout decides when omitted)")).addOption(qs()).action((e,t)=>nm({type:e,...Xs("list",t)}));de.command("update").description("Refresh the checkout's host \u2014 the Claude Code committed fallback + orchestrator playbook, or the Copilot surface.").option("--path <path>","Workspace root directory",process.cwd()).addOption(Js("Host to refresh: claude or copilot (the checkout decides when omitted)")).addOption(qs()).action(e=>Am({...Xs("update",e),version:Hl.version}));de.command("packs").description("Manage the stack packs (vesper-<pack> plugins / Copilot pack folders) this project enables. `list` shows what the package ships, what is enabled here and what the Team Roster needs; `enable`/`disable <pack>` act on one pack (`styles` also writes/removes its always-on pointer rule); `sync` enables every pack the Team Roster names an asset of (never disables \u2014 it prints what it would); `upstream` compares each third-party pack skill with its upstream (network).").argument("[subcommand]","Subcommand: list (default), enable, disable, sync, upstream").argument("[pack]","Pack name for enable/disable (e.g. frontend, playwright, backend, styles)").option("--path <path>","Workspace root directory",process.cwd()).addOption(Js("Host to act on: claude or copilot (the checkout decides when omitted)")).addOption(qs()).action((e,t,r)=>Wh(e,t,Xs("packs",r)));de.command("opencode").description("OpenCode companion helpers. `render-agents` writes `.opencode/agents/<id>.md` for every core + enabled-pack specialist (the generated-files fallback of the OpenCode plugin), records them and prunes the gone ones. No subcommand prints the usage.").argument("[subcommand]","Subcommand: render-agents").option("--path <path>","Workspace root directory",process.cwd()).action(async(e,t)=>{let{exitCode:r}=await Bm(e,t);process.exit(r)});de.command("catalog").description("Show the Vesper catalog (agents, dependencies, requirements)").action(sm);de.command("mcp").description("Manage MCP servers and tool auto-approval. `serve <name>` runs a catalog MCP server (vesper-indexing, sequential-thinking, memory, \u2026) from the installed package with stdio inherited \u2014 what a committed `opencode.json` points at path-free (exit 2 on an unknown name).").argument("[subcommand]","Subcommand: status, add, remove, list, sync, approve, reindex, enable, disable, serve").argument("[argument]","Argument for subcommand (e.g., server name for add/remove/serve)").option("--path <path>","Workspace root directory",process.cwd()).option("--full","Full reindex (clears existing index)").option("-w, --watch","Watch indexing progress until completion").addOption(Js("Host whose MCP config to manage: claude or copilot (the checkout decides when omitted)")).addOption(qs()).action((e,t,r)=>Sm(e,t,Xs("mcp",r)));de.command("settings").description("Manage VS Code settings").argument("[subcommand]","Subcommand: add, remove, list").argument("[setting-key]","Setting key (e.g., read-access)").argument("[value]","Value to add/remove").option("--path <path>","Workspace root directory",process.cwd()).action((e,t,r,n)=>bm(e,t,r,n));de.command("doctor").description("Validate this workspace's Vesper install (read-only) \u2014 host identity, owned-files manifest, MCP config, tracking, framework version").option("--path <path>","Workspace root directory",process.cwd()).option("--quiet","Suppress all output; communicate only via exit code (guard mode)").addOption(new ft("--running-host <host>","The host currently running \u2014 enables the host-identity check").choices(["claude","copilot"])).action(async e=>{let{exitCode:t}=await $m(e);process.exit(t)});de.command("guard").description("Session-start host guard \u2014 verifies this workspace's provisioned host against the running one, emits VESPER_HOST_MISMATCH on stdout on a mismatch (no bootstrap), otherwise runs `worktree bootstrap`. With --running-host claude the healthy path also emits VESPER_PLUGIN_ABSENT when the Vesper plugin verifiably cannot load on this machine (not enabled, or no vesper-marketplace source declared); presence is never claimed. `--running-host opencode` is the Claude host's identity (a Claude workspace is healthy, a Copilot one a mismatch; the plugin token is never emitted for it). The installed triggers pass --running-host; omit it (git hooks, manual runs) for no identity claim: no mismatch check, no mismatch marker, and it acts only when the checked-out commit confirms the provisioned host. Exit code (0 ok / 1 degraded / 2 mismatch) is meaningful ONLY on direct invocation \u2014 the installed hook/task wrappers force exit 0 by design; the marker on stdout is the contract.").option("--path <path>","Workspace root directory",process.cwd()).addOption(new ft("--running-host <host>","The host currently running (claude|copilot|opencode \u2014 opencode stands for the claude host); omit for no identity claim").choices(["claude","copilot","opencode"])).option("--no-bootstrap","Do not invoke worktree bootstrap on the healthy path (testing)").action(async e=>{let{exitCode:t}=await Gm(e);process.exit(t)});de.command("gate").description("Run the project's committed gate policy (.vesper/gates.json): every configured check (`sh -c`, from the workspace root), plan conformance (--plan), the diff-size cap and the protected paths. Exit 0 pass, 1 fail, 2 no/invalid config. Read-only apart from what the checks themselves do.").option("--path <path>","Workspace root directory",process.cwd()).option("--plan <file>","A plan (or details) file: changed files it does not name fail the gate (.vesper/.tracking/ is always allowed)").option("--base <ref>","Diff the working tree against this ref instead of HEAD (untracked files always count)").option("--json","Print one JSON object on stdout and nothing else").action(async e=>{let{exitCode:t}=await Dm(e);process.exit(t)});de.command("log").description("Append one row to the run ledger (.vesper/.tracking/runs/YYYYMMDD-<slug>.jsonl) \u2014 `started|completed|note|delegated|returned` \u2014 or print its last rows with `tail`. The orchestrator calls it before and after each pipeline on both hosts; Claude Code's SubagentStart hook adds `delegated` rows as optional enrichment (`--stdin`). Exit 0; exit 2 on a missing or invalid required field.").argument("<event>","started | completed | note | delegated | returned | tail").option("--path <path>","Workspace root directory",process.cwd()).option("--pipeline <pipeline>","Pipeline name (required for every event but tail), e.g. implementation, refinement, testing").option("--step <step>","Pipeline step").option("--agent <agent>","Subagent name (required for delegated/returned)").option("--goal <goal>","What the run is for (required for started)").option("--author <author>","Who is orchestrating, e.g. the model/session identity").addOption(new ft("--status <status>","Handoff status (required for completed/returned)").choices(["DONE","NEED_HELP","BLOCKED"])).option("--slug <slug>","Story/task slug the row belongs to (default: adhoc); tail: only this slug").option("--note <text>","Free text").option("--session <id>","Session identifier (hooks pass session_id)").option("--stdin","Read a Claude Code hook's JSON from stdin: agent_type \u2192 --agent, session_id \u2192 --session (when the flags are absent)").option("-n, --lines <n>","tail: how many rows (default 5)").option("--json","Print the appended row (or each tailed row) as JSON and nothing else").action(async(e,t)=>{let{exitCode:r}=await Vm(e,t);process.exit(r)});de.command("story").description("Story folders under .vesper/.tracking/stories/ (folder = status). `move <slug> <folder>` finds the story by substring of its file name and refuses on 0 or >1 matches (git mv when tracked and clean, plain rename otherwise); `list [--folder <f>]` prints slug, folder and title. Exit 0; 1 refused; 2 usage.").argument("<subcommand>","move | list").argument("[slug]","move: the story slug (or any unique substring of its file name)").argument("[folder]","move: refining | backlog | inprogress | inreview | completed").option("--path <path>","Workspace root directory",process.cwd()).addOption(new ft("--folder <folder>","list: only this folder").choices(["refining","backlog","inprogress","inreview","completed"])).option("--json","Print JSON and nothing else").action(async(e,t,r,n)=>{let{exitCode:s}=await Wm(e,t,r,n);process.exit(s)});de.command("worktree").description("Bootstrap a git worktree with Vesper's local-only artifacts (host MCP config, code index, gitignore, git hooks). Gated on the provisioned host: with --running-host set and disagreeing, nothing is written; without it, nothing is written unless the checked-out commit confirms the provisioned host.").argument("[subcommand]","Subcommand: bootstrap (default)").option("--path <path>","Workspace root directory",process.cwd()).option("-q, --quiet","Suppress non-error output (used by hooks/tasks)").addOption(new ft("--running-host <host>","The host invoking bootstrap; a mismatch with the provisioned host skips all provisioning").choices(["claude","copilot"])).action(async(e,t)=>{(await Cm(e,t))?.failed?.length&&(process.exitCode=1)});de.addHelpText("after",`
|
|
220
|
+
${Zm}`),{exitCode:aa.USAGE};let{host:n}=await B(r);if(n!=="claude")return u.error("`vespercli opencode render-agents` needs a workspace provisioned for the Claude host (OpenCode is its companion) \u2014 nothing was written. Run `vespercli init --host claude` first."),{exitCode:aa.REFUSED};let s=await gi(r,{packs:t.packs}),o=s.packs.length?s.packs.join(", "):"none";return u.success(`OpenCode agents: ${s.agents.length} specialist file(s) under ${Lr}/ (core + packs: ${o}) \u2014 ${s.written.length} written, ${s.unchanged.length} unchanged.`),s.pruned.length&&u.info(`Pruned (agent gone): ${s.pruned.join(", ")}`),s.kept.length&&u.warn(`Kept (edited by hand, record dropped): ${s.kept.join(", ")}`),u.dim(' OpenCode reads these when opencode.json sets `vesper.agentsMode: "files"`; in the default plugin mode the plugin registers the same ids at runtime.'),{exitCode:aa.OK}}xe();var wx=yx(import.meta.url),vx=Kl(wx);function kx(e){let t=e;for(;t!==Kl(t);){let r=tg(t,"package.json");if(gx(r))return r;t=Kl(t)}return tg(e,"..","..","package.json")}var Sx=kx(vx),Bl=JSON.parse(mx(Sx,"utf-8")),de=new hx;de.name("vespercli").description("Vesper VS Code Agent Suite \u2014 provision an AI agent suite for Claude Code + OpenCode, or GitHub Copilot (one host per workspace)").version(Bl.version,"-v, --version","Output the current version").option("--print-assets-dir","Print the absolute path of the package's assets directory and exit");process.argv[2]==="--print-assets-dir"&&(process.stdout.write(`${O}
|
|
221
|
+
`),process.exit(0));de.command("init").description("Initialize vesper for exactly ONE host (GitHub Copilot, or Claude Code + OpenCode) in this workspace \u2014 prompts when omitted; switching hosts cleans the other host's artifacts after confirmation").option("-p, --path <path>","Workspace root directory",process.cwd()).option("-y, --yes","Skip follow-up prompts and the host-switch confirmation (not the host selection)").option("-f, --force","Force re-initialization (skips follow-up prompts)").option("--force-default","Use all default values for follow-up prompts (not the host selection)").option("--graphify","Enable the opt-in graphify pack (code knowledge graph for the research roles; external tool: `uv tool install graphifyy`) without asking \u2014 the default, and what -y/--force-default/--force/no TTY keep, is no pack").addOption(new gt("--host <host>","The single host to provision: claude (Claude Code + OpenCode \u2014 the OpenCode overlay is always written) or copilot. Interactive prompt if omitted (non-interactive runs reuse the recorded host).").choices(["claude","copilot"])).addOption(new gt("--target <target>","Deprecated alias of --host").hideHelp()).action(e=>rm({...e,version:Bl.version}));function Qs(e){return new gt("--host <host>",e).choices(["claude","copilot"])}var Zs=()=>new gt("--target <target>","Deprecated alias of --host").hideHelp();function eo(e,t){return t.host?{...t,target:t.host}:(t.target&&process.stderr.write(`\`--target\` is deprecated on \`${e}\`; use \`--host\` instead.
|
|
222
|
+
`),t)}de.command("add").description("Add an opt-in asset. Copilot: opt-in instructions (every agent, prompt and skill is already available). Claude Code: every specialist and skill is served by the vesper plugin \u2014 `--override` pins a project-level copy. Host auto-detected when omitted.").argument("[type]","Asset type (agents, prompts, instructions, skills)").argument("[name]","Asset name (specific asset to add)").option("--path <path>","Workspace root directory",process.cwd()).addOption(Qs("Host to act on: claude or copilot (the checkout decides when omitted)")).addOption(Zs()).option("--override","Claude Code only: pin a project-level copy of a plugin asset (recorded; reset removes it)").action((e,t,r)=>im({type:e,name:t,...eo("add",r)}));de.command("reset").description("Remove a host's Vesper artifacts. `--host <x>` force-cleans host x (the active host = full teardown; the other host = foreign-residue clean, never an ambiguity error). Auto-detected from the workspace when omitted.").option("--path <path>","Workspace root directory",process.cwd()).option("-y, --yes","Skip confirmation prompts").addOption(new gt("--host <host>","Host whose artifacts to remove: claude or copilot").choices(["claude","copilot"])).option("--purge-knowledge","On a FULL teardown, also delete the Team Roster, project whitepaper and on-demand context tier (kept by default)").addOption(new gt("--target <target>","Deprecated alias of --host").hideHelp()).action(lh);de.command("list").alias("ls").description("List enabled assets").argument("[type]","Filter by asset type (agents, prompts, instructions, skills)").option("--path <path>","Workspace root directory",process.cwd()).addOption(Qs("Host to list: claude or copilot (the checkout decides when omitted)")).addOption(Zs()).action((e,t)=>dm({type:e,...eo("list",t)}));de.command("update").description("Refresh the checkout's host \u2014 the Claude Code committed fallback + orchestrator playbook, or the Copilot surface.").option("--path <path>","Workspace root directory",process.cwd()).addOption(Qs("Host to refresh: claude or copilot (the checkout decides when omitted)")).addOption(Zs()).action(e=>jm({...eo("update",e),version:Bl.version}));de.command("packs").description("Manage the stack packs (vesper-<pack> plugins / Copilot pack folders) this project enables. `list` shows what the package ships, what is enabled here and what the Team Roster needs; `enable`/`disable <pack>` act on one pack (`styles` also writes/removes its always-on pointer rule); `sync` enables every pack the Team Roster names an asset of (never disables \u2014 it prints what it would); `upstream` compares each third-party pack skill with its upstream (network).").argument("[subcommand]","Subcommand: list (default), enable, disable, sync, upstream").argument("[pack]","Pack name for enable/disable (e.g. frontend, playwright, backend, styles)").option("--path <path>","Workspace root directory",process.cwd()).addOption(Qs("Host to act on: claude or copilot (the checkout decides when omitted)")).addOption(Zs()).action((e,t,r)=>Qh(e,t,eo("packs",r)));de.command("opencode").description("OpenCode companion helpers. `render-agents` writes `.opencode/agents/<id>.md` for every core + enabled-pack specialist (the generated-files fallback of the OpenCode plugin), records them and prunes the gone ones. No subcommand prints the usage.").argument("[subcommand]","Subcommand: render-agents").option("--path <path>","Workspace root directory",process.cwd()).action(async(e,t)=>{let{exitCode:r}=await eg(e,t);process.exit(r)});de.command("catalog").description("Show the Vesper catalog (agents, dependencies, requirements)").action(pm);de.command("mcp").description("Manage MCP servers and tool auto-approval. `serve <name>` runs a catalog MCP server (vesper-indexing, sequential-thinking, memory, \u2026) from the installed package with stdio inherited \u2014 what a committed `opencode.json` points at path-free (exit 2 on an unknown name).").argument("[subcommand]","Subcommand: status, add, remove, list, sync, approve, reindex, enable, disable, serve").argument("[argument]","Argument for subcommand (e.g., server name for add/remove/serve)").option("--path <path>","Workspace root directory",process.cwd()).option("--full","Full reindex (clears existing index)").option("-w, --watch","Watch indexing progress until completion").addOption(Qs("Host whose MCP config to manage: claude or copilot (the checkout decides when omitted)")).addOption(Zs()).action((e,t,r)=>Om(e,t,eo("mcp",r)));de.command("settings").description("Manage VS Code settings").argument("[subcommand]","Subcommand: add, remove, list").argument("[setting-key]","Setting key (e.g., read-access)").argument("[value]","Value to add/remove").option("--path <path>","Workspace root directory",process.cwd()).action((e,t,r,n)=>Pm(e,t,r,n));de.command("doctor").description("Validate this workspace's Vesper install (read-only) \u2014 host identity, owned-files manifest, MCP config, tracking, framework version").option("--path <path>","Workspace root directory",process.cwd()).option("--quiet","Suppress all output; communicate only via exit code (guard mode)").addOption(new gt("--running-host <host>","The host currently running \u2014 enables the host-identity check").choices(["claude","copilot"])).action(async e=>{let{exitCode:t}=await Lm(e);process.exit(t)});de.command("guard").description("Session-start host guard \u2014 verifies this workspace's provisioned host against the running one, emits VESPER_HOST_MISMATCH on stdout on a mismatch (no bootstrap), otherwise runs `worktree bootstrap`. With --running-host claude the healthy path also emits VESPER_PLUGIN_ABSENT when the Vesper plugin verifiably cannot load on this machine (not enabled, or no vesper-marketplace source declared); presence is never claimed. `--running-host opencode` is the Claude host's identity (a Claude workspace is healthy, a Copilot one a mismatch; the plugin token is never emitted for it). The installed triggers pass --running-host; omit it (git hooks, manual runs) for no identity claim: no mismatch check, no mismatch marker, and it acts only when the checked-out commit confirms the provisioned host. Exit code (0 ok / 1 degraded / 2 mismatch) is meaningful ONLY on direct invocation \u2014 the installed hook/task wrappers force exit 0 by design; the marker on stdout is the contract.").option("--path <path>","Workspace root directory",process.cwd()).addOption(new gt("--running-host <host>","The host currently running (claude|copilot|opencode \u2014 opencode stands for the claude host); omit for no identity claim").choices(["claude","copilot","opencode"])).option("--no-bootstrap","Do not invoke worktree bootstrap on the healthy path (testing)").action(async e=>{let{exitCode:t}=await zm(e);process.exit(t)});de.command("gate").description("Run the project's committed gate policy (.vesper/gates.json): every configured check (`sh -c`, from the workspace root), plan conformance (--plan), the diff-size cap and the protected paths. Exit 0 pass, 1 fail, 2 no/invalid config. Read-only apart from what the checks themselves do.").option("--path <path>","Workspace root directory",process.cwd()).option("--plan <file>","A plan (or details) file: changed files it does not name fail the gate (.vesper/.tracking/ is always allowed)").option("--base <ref>","Diff the working tree against this ref instead of HEAD (untracked files always count)").option("--json","Print one JSON object on stdout and nothing else").action(async e=>{let{exitCode:t}=await Ym(e);process.exit(t)});de.command("log").description("Append one row to the run ledger (.vesper/.tracking/runs/YYYYMMDD-<slug>.jsonl) \u2014 `started|completed|note|delegated|returned` \u2014 or print its last rows with `tail`. The orchestrator calls it before and after each pipeline on both hosts; Claude Code's SubagentStart hook adds `delegated` rows as optional enrichment (`--stdin`). Exit 0; exit 2 on a missing or invalid required field.").argument("<event>","started | completed | note | delegated | returned | tail").option("--path <path>","Workspace root directory",process.cwd()).option("--pipeline <pipeline>","Pipeline name (required for every event but tail), e.g. implementation, refinement, testing").option("--step <step>","Pipeline step").option("--agent <agent>","Subagent name (required for delegated/returned)").option("--goal <goal>","What the run is for (required for started)").option("--author <author>","Who is orchestrating, e.g. the model/session identity").addOption(new gt("--status <status>","Handoff status (required for completed/returned)").choices(["DONE","NEED_HELP","BLOCKED"])).option("--slug <slug>","Story/task slug the row belongs to (default: adhoc); tail: only this slug").option("--note <text>","Free text").option("--session <id>","Session identifier (hooks pass session_id)").option("--stdin","Read a Claude Code hook's JSON from stdin: agent_type \u2192 --agent, session_id \u2192 --session (when the flags are absent)").option("-n, --lines <n>","tail: how many rows (default 5)").option("--json","Print the appended row (or each tailed row) as JSON and nothing else").action(async(e,t)=>{let{exitCode:r}=await Jm(e,t);process.exit(r)});de.command("story").description("Story folders under .vesper/.tracking/stories/ (folder = status). `move <slug> <folder>` finds the story by substring of its file name and refuses on 0 or >1 matches (git mv when tracked and clean, plain rename otherwise); `list [--folder <f>]` prints slug, folder and title. Exit 0; 1 refused; 2 usage.").argument("<subcommand>","move | list").argument("[slug]","move: the story slug (or any unique substring of its file name)").argument("[folder]","move: refining | backlog | inprogress | inreview | completed").option("--path <path>","Workspace root directory",process.cwd()).addOption(new gt("--folder <folder>","list: only this folder").choices(["refining","backlog","inprogress","inreview","completed"])).option("--json","Print JSON and nothing else").action(async(e,t,r,n)=>{let{exitCode:s}=await Qm(e,t,r,n);process.exit(s)});de.command("worktree").description("Bootstrap a git worktree with Vesper's local-only artifacts (host MCP config, code index, gitignore, git hooks). Gated on the provisioned host: with --running-host set and disagreeing, nothing is written; without it, nothing is written unless the checked-out commit confirms the provisioned host.").argument("[subcommand]","Subcommand: bootstrap (default)").option("--path <path>","Workspace root directory",process.cwd()).option("-q, --quiet","Suppress non-error output (used by hooks/tasks)").addOption(new gt("--running-host <host>","The host invoking bootstrap; a mismatch with the provisioned host skips all provisioning").choices(["claude","copilot"])).action(async(e,t)=>{(await Nm(e,t))?.failed?.length&&(process.exitCode=1)});de.addHelpText("after",`
|
|
223
223
|
Examples:
|
|
224
224
|
$ vespercli init Pick the single host for this workspace, then initialize
|
|
225
225
|
$ vespercli init --host claude Provision the Claude Code + OpenCode host (CI-friendly)
|