skillcraft 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,48 +1,35 @@
1
1
  #!/usr/bin/env node
2
- import{Command as ki}from"commander";var nt={name:"skillcraft",version:"0.1.8",description:"Turn your work into verifiable AI credentials. Capture what you build, share your progress, and earn verifiable credentials that prove measurable real-world AI engineering work.",keywords:["skillcraft","cli","ai","evidence","credentials","skills","loadout","git","verification","developer-tools"],repository:{type:"git",url:"git+https://github.com/skillcraft-gg/skillcraft.git"},homepage:"https://skillcraft.gg",bugs:{url:"https://github.com/skillcraft-gg/skillcraft/issues"},type:"module",bin:{skillcraft:"dist/index.js"},files:["dist/index.js","dist/index.js.map","README.md","LICENSE"],scripts:{build:"tsup",clean:"rm -rf dist",test:"npm run build && node --test tests/*.test.mjs",smoke:"npm test",format:"printf ''",start:"node dist/index.js",check:"tsc --noEmit",prepublishOnly:"npm run build"},publishConfig:{access:"public"},dependencies:{commander:"^13.1.0",ora:"^8.2.0",yaml:"^2.6.0",zod:"^3.24.2"},devDependencies:{"@types/node":"^24.8.0",tsup:"^8.5.0",typescript:"^5.7.2"}};import{execFile as Ar}from"child_process";import{promisify as Lr}from"util";import it from"path";var ot=Lr(Ar);async function h(e,t,r={}){try{let{stdout:n}=await ot("git",e,{cwd:t,encoding:"utf8",maxBuffer:10485760,env:r.env});return n.trim()}catch(n){let i=n.message??String(n);throw new Error(`git command failed in ${t}: ${i}`)}}async function O(e){try{return await h(["rev-parse","--git-dir"],e),!0}catch{return!1}}async function ee(e){return it.resolve(await h(["rev-parse","--show-toplevel"],e))}async function z(e,t="origin"){try{return await h(["config","--get",`remote.${t}.url`],e)||void 0}catch{return}}async function st(e,t="HEAD"){return h(["log","--format=%B","-n","1",t],e)}async function te(e){return(await h(["rev-parse","HEAD"],e)).trim()}async function M(e,t){try{return await h(["show-ref","--verify","--quiet",t],e),!0}catch{return!1}}async function at(e,t,r="HEAD"){try{return await h(["merge-base","--is-ancestor",t,r],e),!0}catch{return!1}}async function ct(e,t,r){try{let n=await h(["ls-tree","-r","--name-only",t,"--",...r?[r]:[]],e);return n?n.split(`
3
- `).filter(Boolean):[]}catch{return[]}}async function dt(e,t,r){try{return await h(["show",`${t}:${r}`],e)}catch{return}}async function fe(e,t){let r=t?String(t):"200",n=await h(["log",`--max-count=${r}`,"--pretty=%H%x00%B"],e);return n?n.split("\0").filter(Boolean).map(i=>{let[o,...s]=i.split(`
4
- `),c=s.join(`
5
- `).trimEnd();return{commit:o,message:c}}):[]}async function lt(e,t){let r={...process.env,SKILLCRAFT_HOOK_DISABLED:"1"},n=it.join(e,".git","SKILLCRAFT_COMMIT_MESSAGE"),{writeFile:i}=await import("fs/promises");return await i(n,`${t}
6
- `,"utf8"),await ot("git",["commit","--amend","--file",n,"--no-gpg-sign"],{cwd:e,encoding:"utf8",env:r}),te(e)}import Si from"fs/promises";import k from"path";import jr from"os";function qr(){return k.resolve(process.env.HOME||jr.homedir(),".skillcraft")}function I(){return qr()}function Ae(){return k.join(I(),"config.json")}function Le(){return k.join(I(),"repos.json")}function je(){return k.join(I(),"credentials.json")}function ut(){return k.join(I(),"cache","credentials","index.json")}function Nr(e){return k.join(e,".skillcraft")}function A(e){return k.join(e,".git","skillcraft")}function D(e){return k.join(Nr(e),".skillcraft.json")}function re(e){return k.join(e,".git","hooks","post-commit")}function ge(e){return k.join(e,".git","hooks","pre-push")}function he(e){return k.join(e,".git","hooks","post-push")}function L(e){return k.join(A(e),"pending.json")}function R(e){return k.join(A(e),"context.json")}function we(e){return k.join(A(e),"agent.json")}function le(e){return k.join(e,".opencode","plugins","skillcraft.mjs")}function ne(e){return k.join(A(e),"ai-model-context.json")}import ue from"fs/promises";import Fr from"path";async function C(e){await ue.mkdir(e,{recursive:!0})}async function Tr(e){return await ue.readFile(e,"utf8")}async function W(e,t){await C(Fr.dirname(e)),await ue.writeFile(e,t,"utf8")}async function q(e){try{return await ue.access(e),!0}catch{return!1}}async function v(e){if(!await q(e))return null;let t=await Tr(e);return JSON.parse(t)}async function y(e,t){let r=JSON.stringify(t,null,2);await W(e,`${r}
7
- `)}async function N(e){try{await ue.rm(e,{force:!0})}catch{}}import ie from"fs/promises";function qe(e){let t=process.argv[1]||"skillcraft";return`#!/usr/bin/env sh
8
- if [ -n "$SKILLCRAFT_HOOK_DISABLED" ]; then
9
- exit 0
10
- fi
2
+ import{Command as rs}from"commander";var jt={name:"skillcraft",version:"0.1.9",description:"Turn your work into verifiable AI credentials. Capture what you build, share your progress, and earn verifiable credentials that prove your AI coding skills.",keywords:["skillcraft","cli","ai","evidence","credentials","skills","loadout","git","verification","developer-tools"],repository:{type:"git",url:"git+https://github.com/skillcraft-gg/skillcraft.git"},homepage:"https://skillcraft.gg",bugs:{url:"https://github.com/skillcraft-gg/skillcraft/issues"},type:"module",bin:{skillcraft:"dist/index.js"},files:["dist/index.js","dist/index.js.map","README.md","LICENSE"],scripts:{build:"tsup",clean:"rm -rf dist",test:"npm run build && node --test tests/*.test.mjs",smoke:"npm test",format:"printf ''",start:"node dist/index.js",check:"tsc --noEmit",prepublishOnly:"npm run build"},publishConfig:{access:"public"},dependencies:{commander:"^13.1.0",ora:"^8.2.0",yaml:"^2.6.0",zod:"^3.24.2"},devDependencies:{"@types/node":"^24.8.0",tsup:"^8.5.0",typescript:"^5.7.2"}};import is from"fs/promises";import x from"path";import En from"os";function jn(){return x.resolve(process.env.HOME||En.homedir(),".skillcraft")}function T(){return jn()}function Be(){return x.join(T(),"config.json")}function Je(){return x.join(T(),"repos.json")}function We(){return x.join(T(),"credentials.json")}function Lt(){return x.join(T(),"cache","credentials","index.json")}function Ln(e){return x.join(e,".skillcraft")}function q(e){return x.join(e,".git","skillcraft")}function W(e){return x.join(Ln(e),".skillcraft.json")}function N(e){return x.join(q(e),"pending.json")}function I(e){return x.join(q(e),"context.json")}function ge(e){return x.join(q(e),"agent.json")}function Se(e){return x.join(e,".opencode","plugins","skillcraft.mjs")}function Ge(e){return x.join(e,".codex","config.toml")}function Ve(e){return x.join(e,".codex","hooks.json")}function Ze(e){return x.join(e,".agents","plugins","marketplace.json")}function Ce(e){return x.join(e,"plugins","skillcraft-codex")}function _t(e){return x.join(Ce(e),".codex-plugin","plugin.json")}function Nt(e){return x.join(Ce(e),"skills","skillcraft","SKILL.md")}function Re(e){return x.join(e,".agents","skills")}function Xe(e){return x.join(Re(e),".skillcraft-index.json")}function H(e){return x.join(q(e),"ai-model-context.json")}import{z as m}from"zod";var ds=m.literal(1),Q="skillcraft/proofs/v1",Tt=m.object({skills:m.array(m.string()).default([])}),qt=m.object({activeLoadouts:m.array(m.string()).default([])}),us=m.object({provider:m.string().optional()}),ms=m.object({provider:m.string().optional(),name:m.string().optional()}),_n=m.enum(["opencode","codex"]),Ft=m.object({version:m.number().int().default(1),providers:m.array(_n).default([]),enabled:m.boolean().default(!0)}),Nn=m.object({type:m.enum(["github-directory","local-directory"]),repo:m.string().optional(),ref:m.string().optional(),path:m.string()}),Tn=m.object({id:m.string(),name:m.string(),path:m.string(),install:Nn,installedAt:m.string()}),Ot=m.object({version:m.number().int().default(1),skills:m.array(Tn).default([])}),ee=m.object({githubUser:m.string().optional(),provider:m.enum(["gh"]).default("gh"),version:m.number().int().default(1),proofRef:m.string().default(Q)}),qn=m.object({path:m.string(),remote:m.string().optional(),enabledAt:m.string().optional()}),Mt=m.object({repos:m.array(qn).default([])}),Fn=m.object({id:m.string(),trackedAt:m.string().optional()}),zt=m.object({credentials:m.array(Fn).default([])});import se from"fs/promises";import On from"path";async function v(e){await se.mkdir(e,{recursive:!0})}async function te(e){return await se.readFile(e,"utf8")}async function U(e,t){await v(On.dirname(e)),await se.writeFile(e,t,"utf8")}async function S(e){try{return await se.access(e),!0}catch{return!1}}async function w(e){if(!await S(e))return null;let t=await te(e);return JSON.parse(t)}async function h(e,t){let r=JSON.stringify(t,null,2);await U(e,`${r}
3
+ `)}async function j(e){try{await se.rm(e,{force:!0})}catch{}}async function Ae(e){try{await se.rm(e,{force:!0,recursive:!0})}catch{}}async function F(){let e=await w(Be()),t=ee.safeParse(e??{});return t.success?t.data:ee.parse({})}async function Ie(e){let t=await w(W(e)),r=ee.safeParse(t??{});return r.success?r.data:ee.parse({})}async function Dt(e){await v(T()),await h(Be(),e)}async function K(){let e=await w(Je()),t=Mt.safeParse(e??{});return t.success?t.data:{repos:[]}}async function $e(e){await v(T()),await h(Je(),e)}async function Ht(e){let r=(await K()).repos.filter(n=>n.path!==e.path);r.push(e),await $e({repos:r})}async function Ut(e){let r=(await K()).repos.filter(n=>n.path!==e);await $e({repos:r})}async function Ee(){let e=await w(We()),t=zt.safeParse(e??{});return t.success?t.data:{credentials:[]}}async function Kt(e){await v(T()),await h(We(),e)}async function Bt(e){let t=await Ee();return t.credentials.some(r=>r.id===e)?!1:(t.credentials.push({id:e,trackedAt:new Date().toISOString()}),t.credentials.sort(Mn),await Kt(t),!0)}async function Jt(e){let t=await Ee(),r=t.credentials.length,n=t.credentials.filter(o=>o.id!==e);return n.length===r?!1:(await Kt({credentials:n}),!0)}function Mn(e,t){return e.id.localeCompare(t.id)}import{execSync as Qn}from"child_process";import eo from"path";import Wn from"fs/promises";import Xt from"path";import Bn from"path";var zn=/^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*(?:@[^\s/]+)?$/,Dn=/^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/,Hn=/^([a-zA-Z0-9][a-zA-Z0-9._-]*):([a-zA-Z0-9][a-zA-Z0-9._-]*)(?:\/([a-zA-Z0-9][a-zA-Z0-9._-]*))?$/;function ae(e){let t=G(e);if(t.id)return`${t.id}${t.version?`@${t.version}`:""}`}function Ye(e){return zn.test(e)}function Qe(e){return!!G(e).id}function G(e){let t=e.trim(),r=Kn(t),n=r.id||"";if(Un(n)){let[a,d]=n.split("/");return{id:n,owner:a,slug:d,version:r.version}}let o=Hn.exec(n);if(!o)return{id:"",slug:"",version:r.version};let i=o[1],s=o[2],c=o[3];return c===void 0?{id:`${i}:${s}`,source:i,slug:s,version:r.version}:{id:`${i}:${s}/${c}`,source:i,owner:s,slug:c,version:r.version}}function Un(e){return Dn.test(e)}function O(e,t){let r=e.trim();if(!r)throw new Error(`Expected ${t} to be provided`);return r}function Kn(e){let t=e.split("@"),r=t[0]||"",n=t.length>1?t.slice(1).join("@"):void 0;return{id:r,version:n}}function je(e){let[t,r]=e.split("/");if(!t||!r)throw new Error(`Expected <owner>/<slug>, received ${e}`);return{owner:t,slug:r.trim()}}async function he(e){let t=await w(Xe(e)),r=Ot.safeParse(t??{version:1,skills:[]});return r.success?r.data.skills:[]}async function Jn(e,t){let r=[...t].sort((n,o)=>n.id.localeCompare(o.id));await h(Xe(e),{version:1,skills:r})}async function Wt(e,t){let n=(await he(e)).filter(o=>o.id!==t.id&&o.name!==t.name);n.push(t),await Jn(e,n)}async function Le(e,t){let r=ae(t);if(!r)throw new Error(`invalid skill id format: ${t}`);let n=await w(N(e)),o=n&&typeof n=="object"&&!Array.isArray(n)&&Array.isArray(n.skills)?n.skills:[],i=Array.from(new Set(o.map(s=>typeof s=="string"?ae(s):void 0).filter(s=>!!s).concat(r))).sort();await h(N(e),{skills:i})}function Gt(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"skillcraft-skill"}function Vt(e){return{id:e.id,name:e.name,path:Bn.posix.join(".agents","skills",e.name),install:e.install,installedAt:e.installedAt}}async function Yt(e,t){let r=await he(e);if(!r.length)return;let n=Gn(t);if(!n.hook_event_name)return;let o=new Set;if(n.hook_event_name==="Stop")for(let i of await Vn(e,r,n.transcript_path,n.turn_id))o.add(i);for(let i of o)await Le(e,i)}function Gn(e){if(!e||typeof e!="object"||Array.isArray(e))return{};let t=e,r=t.tool_input;return{hook_event_name:B(t.hook_event_name),turn_id:B(t.turn_id),cwd:B(t.cwd),transcript_path:B(t.transcript_path),tool_input:r&&typeof r=="object"&&!Array.isArray(r)?{command:B(r.command)}:void 0}}async function Vn(e,t,r,n){if(!r||!n)return[];let o=await Wn.readFile(r,"utf8").catch(()=>"");if(!o.trim())return[];let i=new Map,s=new Map;for(let d of t)s.set(d.name,d.id),i.set(Zt(Xt.join(e,d.path,"SKILL.md")),d.id);let c=new Set,a;for(let d of o.split(/\r?\n/)){if(!d.trim())continue;let l;try{l=JSON.parse(d)}catch{continue}if(!l||typeof l!="object"||Array.isArray(l))continue;let u=l;if(u.type==="turn_context"){a=Zn(u.payload);continue}if(!(u.type!=="response_item"||a!==n))for(let p of Xn(u.payload)){let f=(p.path?i.get(Zt(p.path)):void 0)||(p.name?s.get(p.name):void 0);f&&c.add(f)}}return Array.from(c).sort()}function Zn(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return B(e.turn_id)}function Xn(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e;if(t.type!=="message"||B(t.role)!=="user"||!Array.isArray(t.content))return[];let r=[];for(let n of t.content){if(!n||typeof n!="object"||Array.isArray(n))continue;let o=B(n.text);if(!o)continue;let i=o.matchAll(/<skill>\s*<name>([^<]+)<\/name>\s*<path>([^<]+)<\/path>[\s\S]*?<\/skill>/g);for(let s of i)r.push({name:Yn(s[1]||""),path:B(s[2])})}return r}function Yn(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function Zt(e){return Xt.resolve(e)}function B(e){return(typeof e=="string"?e.trim():"")||void 0}var it=["codex","opencode"],rt="# skillcraft:begin codex",nt="# skillcraft:end codex",Qt="skillcraft _agent-hook codex",Ms=[...it];function we(e){let t=e.trim().toLowerCase();return it.find(r=>r===t)}function ye(e){let t=e.flatMap(r=>r.split(",")).map(r=>we(r)).filter(r=>!!r);return Array.from(new Set(t)).sort()}function Ne(e){return e.flatMap(t=>t.split(",")).map(t=>t.trim()).filter(Boolean).filter(t=>!we(t))}async function ce(e){let t=await w(ge(e)),r=Ft.safeParse(t??{});if(r.success)return r.data.providers;if(!t||typeof t!="object"||Array.isArray(t))return[];let n=t;return Array.isArray(n.providers)?n.providers.map(o=>typeof o=="string"?we(o):void 0).filter(o=>!!o):[]}async function Te(e,t){let r=Array.from(new Set(t)).sort();await h(ge(e),{version:1,providers:r,enabled:r.length>0})}async function qe(){return it.filter(e=>to(e))}async function er(e,t){if(t==="opencode"){await v(eo.dirname(Se(e))),await U(Se(e),po());return}await ro(e)}async function tr(e,t){if(t==="opencode"){await j(Se(e));return}await no(e)}async function rr(e,t){let r=await w(H(e));if(r&&typeof r=="object"&&!Array.isArray(r)){let n=r,o=n.agent&&typeof n.agent=="object"&&!Array.isArray(n.agent)?n.agent.provider:void 0;if(typeof o=="string"&&o.trim())return;await ot(e,{agent:{provider:t}});return}await h(H(e),{agent:{provider:t},model:{}})}async function ot(e,t){let r=await w(H(e)),n=r&&typeof r=="object"&&!Array.isArray(r)?r:{},o=n.agent&&typeof n.agent=="object"&&!Array.isArray(n.agent)?n.agent:{},i=n.model&&typeof n.model=="object"&&!Array.isArray(n.model)?n.model:{},s={...n,agent:{...o,...t.agent?.provider?{provider:t.agent.provider.trim().toLowerCase()}:{}},model:{...i,...t.model?.provider?{provider:t.model.provider.trim().toLowerCase()}:{},...t.model?.name?{name:t.model.name.trim()}:{}}};await h(H(e),s)}async function nr(e,t){if(!t||typeof t!="object"||Array.isArray(t)){await ot(e,{agent:{provider:"codex"}});return}let r=t,n=typeof r.model=="string"?r.model.trim():"",o=typeof r.model_provider=="string"?r.model_provider.trim().toLowerCase():typeof r.modelProvider=="string"?r.modelProvider.trim().toLowerCase():"";await ot(e,{agent:{provider:"codex"},model:{...o?{provider:o}:{},...n?{name:n}:{}}}),await Yt(e,t)}function to(e){try{return Qn(`command -v ${e}`,{stdio:"ignore"}),!0}catch{return!1}}async function ro(e){await Promise.all([lo(e),ao(e),io(e),oo(e)])}async function no(e){await Promise.all([uo(e),co(e),so(e),Ae(Ce(e))])}async function oo(e){await h(_t(e),{name:"skillcraft-codex",version:"0.1.0",description:"Repo-local Skillcraft workflow support for Codex CLI.",skills:"./skills/",interface:{displayName:"Skillcraft",shortDescription:"Skillcraft-aware repository guidance for Codex.",longDescription:"Adds Skillcraft repository guidance and pairs with repo-local hooks to record model provenance.",developerName:"Skillcraft",category:"Developer Tools",capabilities:["Read","Write"],defaultPrompt:["Use Skillcraft guidance while working in this repository."],brandColor:"#0f766e"}}),await U(Nt(e),`---
4
+ name: skillcraft
5
+ description: Use when working in a Skillcraft-enabled repository so Codex preserves normal git history and evidence-friendly commit workflows.
6
+ ---
11
7
 
12
- SKILLCRAFT_HOOK_DIR="$PWD"
13
- SKILLCRAFT_HOOK_DIR="$(git -C "$SKILLCRAFT_HOOK_DIR" rev-parse --show-toplevel 2>/dev/null || printf "%s" "$SKILLCRAFT_HOOK_DIR")"
14
- SKILLCRAFT_CLI=${JSON.stringify(t)}
15
- unset GIT_INDEX_FILE
8
+ When Skillcraft is enabled in this repository:
16
9
 
17
- ${e}
18
- `}var _r=qe('"$SKILLCRAFT_CLI" _hook post-commit "$SKILLCRAFT_HOOK_DIR" || true'),Or=qe(`SKILLCRAFT_HOOK_REMOTE="$1"
19
- "$SKILLCRAFT_CLI" _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`),zr=qe(`SKILLCRAFT_HOOK_REMOTE="$1"
20
- "$SKILLCRAFT_CLI" _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`);async function mt(e){await W(re(e),`${_r}
21
- `),await ie.chmod(re(e),493),await W(he(e),`${Or}
22
- `),await ie.chmod(he(e),493),await W(ge(e),`${zr}
23
- `),await ie.chmod(ge(e),493)}async function pt(e){await Promise.all([ie.rm(re(e),{force:!0}),ie.rm(he(e),{force:!0}),ie.rm(ge(e),{force:!0})])}import{z as g}from"zod";var Oi=g.literal(1),J="skillcraft/proofs/v1",ft=g.object({skills:g.array(g.string()).default([])}),gt=g.object({activeLoadouts:g.array(g.string()).default([])}),zi=g.object({provider:g.string().optional()}),Mi=g.object({provider:g.string().optional(),name:g.string().optional()}),G=g.object({githubUser:g.string().optional(),provider:g.enum(["gh"]).default("gh"),version:g.number().int().default(1),proofRef:g.string().default(J)}),Mr=g.object({path:g.string(),remote:g.string().optional(),enabledAt:g.string().optional()}),ht=g.object({repos:g.array(Mr).default([])}),Dr=g.object({id:g.string(),trackedAt:g.string().optional()}),wt=g.object({credentials:g.array(Dr).default([])});async function j(){let e=await v(Ae()),t=G.safeParse(e??{});return t.success?t.data:G.parse({})}async function ye(e){let t=await v(D(e)),r=G.safeParse(t??{});return r.success?r.data:G.parse({})}async function yt(e){await C(I()),await y(Ae(),e)}async function F(){let e=await v(Le()),t=ht.safeParse(e??{});return t.success?t.data:{repos:[]}}async function ke(e){await C(I()),await y(Le(),e)}async function kt(e){let r=(await F()).repos.filter(n=>n.path!==e.path);r.push(e),await ke({repos:r})}async function vt(e){let r=(await F()).repos.filter(n=>n.path!==e);await ke({repos:r})}async function ve(){let e=await v(je()),t=wt.safeParse(e??{});return t.success?t.data:{credentials:[]}}async function xt(e){await C(I()),await y(je(),e)}async function Pt(e){let t=await ve();return t.credentials.some(r=>r.id===e)?!1:(t.credentials.push({id:e,trackedAt:new Date().toISOString()}),t.credentials.sort(Hr),await xt(t),!0)}async function bt(e){let t=await ve(),r=t.credentials.length,n=t.credentials.filter(i=>i.id!==e);return n.length===r?!1:(await xt({credentials:n}),!0)}function Hr(e,t){return e.id.localeCompare(t.id)}async function Rt(){let e=process.cwd();if(!await O(e))throw new Error("Current directory is not a git repository");let t=await ee(e);await Promise.all([N(D(t)),N(L(t)),N(R(t)),N(we(t)),N(le(t)),N(ne(t)),N(A(t))]),await pt(t),await vt(t),process.stdout.write(`disabled skillcraft for ${t}
24
- `)}import{createHash as Gr}from"crypto";import Pe from"path";import Vr from"os";import $t from"fs/promises";var Kr=/^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*(?:@[^\s/]+)?$/,Ur=/^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/,Br=/^([a-zA-Z0-9][a-zA-Z0-9._-]*):([a-zA-Z0-9][a-zA-Z0-9._-]*)(?:\/([a-zA-Z0-9][a-zA-Z0-9._-]*))?$/;function Ct(e){let t=H(e);if(t.id)return`${t.id}${t.version?`@${t.version}`:""}`}function Ne(e){return Kr.test(e)}function Fe(e){return!!H(e).id}function H(e){let t=e.trim(),r=Jr(t),n=r.id||"";if(Wr(n)){let[a,u]=n.split("/");return{id:n,owner:a,slug:u,version:r.version}}let i=Br.exec(n);if(!i)return{id:"",slug:"",version:r.version};let o=i[1],s=i[2],c=i[3];return c===void 0?{id:`${o}:${s}`,source:o,slug:s,version:r.version}:{id:`${o}:${s}/${c}`,source:o,owner:s,slug:c,version:r.version}}function Wr(e){return Ur.test(e)}function T(e,t){let r=e.trim();if(!r)throw new Error(`Expected ${t} to be provided`);return r}function Jr(e){let t=e.split("@"),r=t[0]||"",n=t.length>1?t.slice(1).join("@"):void 0;return{id:r,version:n}}function xe(e){let[t,r]=e.split("/");if(!t||!r)throw new Error(`Expected <owner>/<slug>, received ${e}`);return{owner:t,slug:r.trim()}}var Te="proofs";function Et(e){return(e?.trim()||J).replace(/^refs\/heads\//,"")}function It(e){return`${Te}/${e}.json`}async function be(e){let t=await ye(e);return Et(t.proofRef)}async function At(e,t){let r=Et(t),n=`refs/heads/${r}`,i=`refs/remotes/origin/${r}`,o=[];return await M(e,n)&&o.push(r),await M(e,i)&&o.push(`origin/${r}`),o.length||o.push(r),o}async function Zr(e,t){let r=`refs/heads/${t}`;await M(e,r)||await h(["branch",t],e)}async function Xr(e,t,r){await Yr(e,t);let n=await $t.mkdtemp(Pe.join(Vr.tmpdir(),"skillcraft-proof-"));try{return await h(["worktree","add","--quiet",n,t],e),await r(n)}finally{await Lt(e,n)}}async function Lt(e,t){try{await h(["worktree","remove","--force",t],e)}catch{await $t.rm(t,{force:!0,recursive:!0})}}async function Yr(e,t){let r=`refs/heads/${t}`;try{let i=(await h(["worktree","list","--porcelain"],e)).split(`
25
- `),o,s,c=async()=>{!o||s!==r||await Lt(e,o)};for(let a of i){if(!a){o=void 0,s=void 0;continue}if(a.startsWith("worktree ")){await c(),o=a.slice(9),s=void 0;continue}a.startsWith("branch ")&&(s=a.slice(7))}await c()}catch{return}}async function _e(e){let t=await be(e),r=await At(e,t),n=new Set;for(let o of r){let s=await ct(e,o,Te);for(let c of s)n.add(c)}let i=[];for(let o of n){if(!o.endsWith(".json"))continue;let s=Pe.basename(o,".json"),c=await Oe(e,s);c&&i.push(c)}return i}function Qr(e){let t=H(e);if(t.id&&Fe(t.id))return{id:t.id,version:t.version}}function Re(e){let t=e.filter(Boolean).map(r=>H(r)).filter(r=>!!r.id).map(r=>`${r.id}${r.version?`@${r.version}`:""}`);return Array.from(new Set(t)).filter(Fe).sort()}function jt(e,t,r){let n={skills:e,loadouts:r,timestamp:t};return Gr("sha256").update(JSON.stringify(n)).digest("hex").slice(0,8)}async function oe(e){let t=await v(L(e)),r=ft.safeParse(t??{skills:[]});return r.success?Re(r.data.skills):[]}async function en(e){let t=await v(R(e)),r=gt.safeParse(t??{activeLoadouts:[]});return r.success?r.data.activeLoadouts:[]}async function tn(e){let t=await v(ne(e));if(!t||typeof t!="object"||Array.isArray(t))return{};let r=t,n=r.agent&&typeof r.agent=="object"&&!Array.isArray(r.agent)?r.agent:void 0,i=r.model&&typeof r.model=="object"&&!Array.isArray(r.model)?r.model:void 0;return{agent:typeof n?.provider=="string"?{provider:St(n.provider)}:void 0,model:typeof i?.provider=="string"||typeof i?.name=="string"?{provider:typeof i.provider=="string"?St(i.provider):void 0,name:typeof i.name=="string"?rn(i.name):void 0}:void 0}}function St(e){return e.trim().toLowerCase()}function rn(e){return e.trim()}function nn(e){if(!e||typeof e!="object")return;let t=e;if(typeof t.version!="number"||typeof t.commit!="string"||!Array.isArray(t.skills)||!t.timestamp||typeof t.timestamp!="string")return;let r=Array.isArray(t.loadouts)?t.loadouts.map(String):[],n=t.skills.map(i=>{if(typeof i=="string")return{id:i};if(i&&typeof i=="object"&&"id"in i&&typeof i.id=="string")return{id:i.id,version:typeof i.version=="string"?i.version:void 0}}).filter(i=>!!i);return{version:t.version,commit:t.commit,skills:n,loadouts:r,timestamp:t.timestamp,agent:on(t.agent),model:sn(t.model)}}function on(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e.provider;if(typeof t!="string")return;let r=t.trim().toLowerCase();return r?{provider:r}:void 0}function sn(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,r=typeof t.provider=="string"?t.provider.trim().toLowerCase():void 0,n=typeof t.name=="string"?t.name.trim():void 0;if(!(!r&&!n))return{provider:r,name:n}}async function Oe(e,t){let r=await be(e),n=It(t),i=await At(e,r);for(let o of i){let s=await dt(e,o,n);if(!s)continue;let c;try{c=JSON.parse(s)}catch{continue}let a=nn(c);if(a)return a}}async function ze(e,t){let r=jt(t.skills.map(o=>o.id),t.timestamp,t.loadouts),n=await be(e);await Zr(e,n);let i=It(r);return await Xr(e,n,async o=>{await C(Pe.join(o,Te)),await y(Pe.join(o,i),t),await h(["add",i],o,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}}),await h(["status","--porcelain","--",i],o,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}})&&await h(["commit","--no-gpg-sign","-m",`add Skillcraft proof ${r}`],o,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}})}),r}async function qt(e,t="origin"){let r=await be(e);if(!(!await z(e,t)||!t))try{await h(["push",t,`${r}:${r}`],e,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}})}catch{return}}async function Nt(e,t){let r=await _e(e);for(let n of r)if(n.commit===t)return jt(n.skills.map(i=>i.id),n.timestamp,n.loadouts)}async function Ft(e,t,r=new Date().toISOString()){let n=await oe(e),i=await en(e),o=await tn(e),s=n.map(u=>Qr(u)).filter(u=>!!u),c={version:1,commit:t,skills:s,loadouts:i,timestamp:r,...o};return{proofId:await ze(e,c),proof:c}}async function an(e){return e.replace(/\nSkillcraft-Ref: .*$/gm,"").trimEnd()}async function Tt(e,t){let r=await st(e),n=await an(r);return n.includes("Skillcraft-Ref:")?n:`${n}
10
+ - Preserve normal git history unless the user explicitly asks for destructive history changes.
11
+ - Prefer regular commits over rebases, squashes, or amends once Skillcraft evidence has been recorded.
12
+ - Keep work in this repository so repo-local Skillcraft hooks can capture model provenance.
13
+ - Let Skillcraft post-commit hooks attach proof references after meaningful commits.
14
+ `)}async function io(e){let t=Ze(e),r=await w(t);if(r&&(typeof r!="object"||Array.isArray(r)))throw new Error(`Invalid marketplace file: ${t}`);let n=r??{},o=Array.isArray(n.plugins)?[...n.plugins]:[],i={name:"skillcraft-codex",source:{source:"local",path:"./plugins/skillcraft-codex"},policy:{installation:"AVAILABLE",authentication:"ON_INSTALL"},category:"Developer Tools",interface:{displayName:"Skillcraft"}},s=o.filter(c=>c&&typeof c=="object"&&c.name!==i.name);s.push(i),await h(t,{name:n.name||"skillcraft-local",interface:n.interface||{displayName:"Skillcraft Local Plugins"},plugins:s})}async function so(e){let t=Ze(e),r=await w(t);if(!r)return;if(typeof r!="object"||Array.isArray(r))throw new Error(`Invalid marketplace file: ${t}`);let n=r,o=Array.isArray(n.plugins)?n.plugins.filter(i=>!(i&&typeof i=="object"&&i.name==="skillcraft-codex")):[];if(!o.length){await j(t);return}await h(t,{...n,plugins:o})}async function ao(e){let t=Ve(e),r=await w(t);if(r&&(typeof r!="object"||Array.isArray(r)))throw new Error(`Invalid hooks file: ${t}`);let n=r??{},o=n.hooks&&typeof n.hooks=="object"&&!Array.isArray(n.hooks)?{...n.hooks}:{};o.SessionStart=tt(o.SessionStart,{matcher:"startup|resume",hooks:[et("Updating Skillcraft session context")]}),o.UserPromptSubmit=tt(o.UserPromptSubmit,{hooks:[et("Updating Skillcraft prompt context")]}),o.Stop=tt(o.Stop,{hooks:[et("Recording Skillcraft turn evidence")]}),await h(t,{hooks:o})}async function co(e){let t=Ve(e),r=await w(t);if(!r)return;if(typeof r!="object"||Array.isArray(r))throw new Error(`Invalid hooks file: ${t}`);let n=r,o=n.hooks&&typeof n.hooks=="object"&&!Array.isArray(n.hooks)?{...n.hooks}:{};for(let i of Object.keys(o)){let c=(Array.isArray(o[i])?o[i]:[]).map(a=>{let d=Array.isArray(a.hooks)?a.hooks.filter(l=>l.command!==Qt):[];return d.length?{...a,hooks:d}:void 0}).filter(a=>!!a);c.length?o[i]=c:delete o[i]}if(!Object.keys(o).length){await j(t);return}await h(t,{hooks:o})}async function lo(e){let t=Ge(e),r=await te(t).catch(()=>""),n=mo(r);n!==r&&await U(t,n)}async function uo(e){let t=Ge(e);if(!await S(t))return;let r=await te(t),n=or(r);if(!n.trim()){await j(t);return}n!==r&&await U(t,n)}function et(e){return{type:"command",command:Qt,statusMessage:e,timeout:30}}function tt(e,t){let r=Array.isArray(e)?[...e]:[],n=r.findIndex(s=>(s.matcher||"")===(t.matcher||""));if(n===-1)return r.push(t),r;let o=r[n],i=Array.isArray(o.hooks)?[...o.hooks]:[];for(let s of t.hooks)i.some(c=>c.command===s.command)||i.push(s);return r[n]={...o,matcher:t.matcher??o.matcher,hooks:i},r}function mo(e){let t=or(e);if(/^\s*features\.codex_hooks\s*=\s*false\s*$/m.test(t))return t.replace(/^\s*features\.codex_hooks\s*=\s*false\s*$/m,"features.codex_hooks = true");if(/^\s*features\.codex_hooks\s*=\s*true\s*$/m.test(t))return t;let r=t.split(/\r?\n/),n=!1;for(let c=0;c<r.length;c+=1){let a=r[c];if(/^\s*\[.*\]\s*$/.test(a)){n=a.trim()==="[features]";continue}if(n&&/^\s*codex_hooks\s*=\s*false\s*$/.test(a))return r[c]="codex_hooks = true",_e(r.join(`
15
+ `));if(n&&/^\s*codex_hooks\s*=\s*true\s*$/.test(a))return _e(r.join(`
16
+ `))}let o=r.findIndex(c=>c.trim()==="[features]"),i=[rt,"codex_hooks = true",nt];return o!==-1?(r.splice(o+1,0,...i),_e(r.join(`
17
+ `))):`${t.trim()?`${t.trimEnd()}
26
18
 
27
- Skillcraft-Ref: ${t}
28
- `}async function P(e){let t=D(e);if(!await q(t))return!1;let r=await v(t);return G.safeParse(r??{}).success}async function _t(e){return q(A(e))}import U from"fs/promises";import Me from"path";import{execFile as cn,execSync as dn}from"child_process";import{promisify as ln}from"util";var un=ln(cn);function mn(){try{return dn("which gh",{stdio:"ignore"}),!0}catch{return!1}}async function K(e){if(!mn())throw new Error("gh CLI is required for this workflow");return(await un("gh",e,{encoding:"utf8"})).stdout.trim()}async function Ot(e,t){await U.mkdir(t,{recursive:!0});let r=await U.readdir(e,{withFileTypes:!0});for(let n of r){if(n.name===".git")continue;let i=Me.join(e,n.name),o=Me.join(t,n.name);if(n.isDirectory()){await Ot(i,o);continue}if(n.isSymbolicLink()){let s=await U.readlink(i);await U.symlink(s,o);continue}n.isFile()&&await U.copyFile(i,o)}}var Ce=class{providerName(){return"gh"}async getUser(){return await K(["api","user","--jq",".login"])}async getIssueUrl(t,r){return`https://github.com/${t}/issues/${r}`}async createIssue(t,r,n){let o=(await K(["issue","create","-R",t,"--title",r,"--body",n])).match(/\b(\d+)$/);return o?Number(o[1]):0}async createPullRequest(t,r,n){let o=(await K(["pr","create","--repo",t,"--head",r,"--base","main","--title",n,"--body",`Generated by skillcraft for ${n}`,"--fill-first"])).match(/\b(\d+)$/);return o?Number(o[1]):0}async openPullRequestForBranch(t,r,n,i,o){let c=(await K(["pr","create","--repo",t,"--head",`${r}:${n}`,"--base","main","--title",i,"--body",o])).match(/\b(\d+)$/);return c?Number(c[1]):0}async getIssueStatus(t,r){let n=await K(["issue","view",String(r),"--repo",t,"--json","state,labels,url"]),i=JSON.parse(n);return{state:i.state,labels:i.labels?.map(o=>o.name)??[],url:i.url}}async listClaimProcessingRuns(t,r){let n=await K(["run","list","--repo",t,"--workflow","Process credential claims","--json","name,status,conclusion,url,createdAt,workflowName"]),i=JSON.parse(n),o=`#${r}`,s=i.filter(a=>{let u=a.name||"",l=a.workflowName||"";return u.includes(o)||l.includes(o)}),c=s.length>0?s:i.filter(a=>a.status&&["in_progress","queued","waiting","action_required","canceling"].includes(a.status));return c.length?c.filter(a=>a.url).map(a=>({status:a.status||"unknown",conclusion:a.conclusion??void 0,url:a.url,name:a.name,createdAt:a.createdAt,workflowName:a.workflowName})):[]}async listClaimIssues(t){let r=await K(["issue","list","--repo",t,"--state","all","--json","number,title,state,body,labels,url","--limit","100"]);return JSON.parse(r).filter(i=>pn(i.title)||fn(i.labels,"skillcraft-claim"))}async cloneRepo(t,r){let n=Me.resolve(r);await K(["repo","clone",t,n])}async copyDirectory(t,r){await U.readdir(r).catch(()=>{})&&await U.rm(r,{recursive:!0,force:!0}),await U.mkdir(r,{recursive:!0}),await Ot(t,r)}};function De(e){return String(e||"").trim().toLowerCase()}function pn(e){return De(e).startsWith("claim:")}function fn(e,t){let r=De(t);return(e||[]).some(n=>De(n?.name)===r)}var gn={gh:()=>new Ce};function $(e){return gn[e]()}async function zt(){let e=process.cwd(),t=await O(e);process.stdout.write(`git: ${t?"enabled":"not a repository"}
29
- `);let r=await P(e);if(process.stdout.write(`skillcraft: ${r?"enabled":"disabled"}
30
- `),!t||!r)return;let n=await oe(e);process.stdout.write(`pending skills: ${n.length}
31
- `);let i=await q(R(e)),o=await q(re(e));process.stdout.write(`context file: ${i?"present":"missing"}
32
- `),process.stdout.write(`post-commit hook: ${o?"installed":"missing"}
33
- `);let s=await te(e),c=await Nt(e,s);process.stdout.write(`head: ${s}
34
- `),process.stdout.write(`latest proof: ${c??"none"}
35
- `);let u=(await fe(e,20)).filter(p=>p.message.includes("Skillcraft-Ref:"));process.stdout.write(`recent commits with evidence: ${u.length}
36
- `);let d=(await ye(e)).proofRef?.replace(/^refs\/heads\//,"")||"skillcraft/proofs/v1",m=await M(e,`refs/heads/${d}`);process.stdout.write(`proof branch: ${m?"present":"missing"}
37
- `),n.length>0&&process.stdout.write(`pending evidence queued: ${n.join(", ")}
38
- `)}async function Mt(){let e=await Promise.all([me("node"),me("npm"),me("git"),me("gh"),me("opencode")]);for(let[n,i]of e)process.stdout.write(`${n}: ${i?"ok":"missing"}
39
- `);if(!(e.find(([n])=>n==="gh")?.[1]??!1)){process.stdout.write(`gh auth: missing
40
- `),process.stdout.write(`github user: unknown
41
- `);return}let r=await $("gh").getUser().catch(()=>"");process.stdout.write(`gh auth: ${r?"ok":"missing"}
42
- `),process.stdout.write(`github user: ${r||"unknown"}
43
- `)}async function me(e){return[e,await hn(e)]}async function hn(e){try{let{execSync:t}=await import("child_process");return t(`command -v ${e}`,{stdio:"ignore"}),!0}catch{return!1}}import wn from"path";async function Dt(){let e=process.cwd();if(!await O(e))throw new Error("Current directory is not a git repository");let t=await ee(e),r=await j();if(!r.githubUser){let s=await $(r.provider??"gh").getUser().catch(()=>process.env.GITHUB_USER||process.env.USER||"developer");await yt({...r,githubUser:s})}await C(A(t)),await C(wn.dirname(le(t))),await W(le(t),yn()),await y(ne(t),{agent:{provider:"opencode"},model:{}});let n=`refs/heads/${J}`;await M(t,n)||await h(["branch",J],t),await y(D(t),{version:1,proofRef:J}),await C(I()),await y(L(t),{skills:[]}),await y(R(t),{activeLoadouts:[]}),await y(we(t),{version:1,providers:["opencode"],enabled:!0}),await mt(t);let i=await z(t);await kt({path:t,remote:i,enabledAt:new Date().toISOString()}),process.stdout.write(`enabled skillcraft for ${t}
44
- `)}function yn(){return`import fs from 'node:fs/promises'
19
+ `:""}${rt}
20
+ [features]
21
+ codex_hooks = true
22
+ ${nt}
23
+ `}function or(e){let t=rt.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=nt.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=new RegExp(`\\n?${t}[\\s\\S]*?${r}\\n?`,"g");return _e(e.replace(n,`
24
+ `).replace(/\n{3,}/g,`
25
+
26
+ `).trimEnd())}function _e(e){return e?`${e.replace(/\n+$/g,"")}
27
+ `:""}function po(){return`import fs from 'node:fs/promises'
45
28
  import path from 'node:path'
29
+ import { execFile } from 'node:child_process'
30
+ import { promisify } from 'node:util'
31
+
32
+ const exec = promisify(execFile)
46
33
 
47
34
  function normalizeProvider(value) {
48
35
  return typeof value === 'string' ? value.trim().toLowerCase() : ''
@@ -52,6 +39,12 @@ function normalizeModelName(value) {
52
39
  return typeof value === 'string' ? value.trim() : ''
53
40
  }
54
41
 
42
+ function normalizeSkillName(value) {
43
+ return typeof value === 'string'
44
+ ? value.trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-+|-+$/g, '')
45
+ : ''
46
+ }
47
+
55
48
  function extractModelInfo(payload) {
56
49
  if (!payload || typeof payload !== 'object') {
57
50
  return {}
@@ -98,12 +91,16 @@ function extractModelInfo(payload) {
98
91
  return candidate
99
92
  }
100
93
 
101
- function resolveStateFile() {
102
- return path.join(process.cwd(), '.git', 'skillcraft', 'ai-model-context.json')
94
+ function resolveStateFile(root) {
95
+ return path.join(root, '.git', 'skillcraft', 'ai-model-context.json')
103
96
  }
104
97
 
105
- async function updateState(update) {
106
- const stateFile = resolveStateFile()
98
+ function resolveInstalledSkillsIndex(root) {
99
+ return path.join(root, '.agents', 'skills', '.skillcraft-index.json')
100
+ }
101
+
102
+ async function updateState(root, update) {
103
+ const stateFile = resolveStateFile(root)
107
104
  let current = {}
108
105
 
109
106
  try {
@@ -139,7 +136,7 @@ async function updateState(update) {
139
136
  }
140
137
 
141
138
  try {
142
- await fs.mkdir(path.join(process.cwd(), '.git', 'skillcraft'), { recursive: true })
139
+ await fs.mkdir(path.join(root, '.git', 'skillcraft'), { recursive: true })
143
140
  await fs.writeFile(stateFile, JSON.stringify(next, null, 2) + '
144
141
  ', 'utf8')
145
142
  } catch {
@@ -147,7 +144,63 @@ async function updateState(update) {
147
144
  }
148
145
  }
149
146
 
150
- async function handlePayload(payload) {
147
+ async function loadInstalledSkillId(root, skillName) {
148
+ const normalized = normalizeSkillName(skillName)
149
+ if (!normalized) {
150
+ return undefined
151
+ }
152
+
153
+ try {
154
+ const raw = await fs.readFile(resolveInstalledSkillsIndex(root), 'utf8')
155
+ const parsed = JSON.parse(raw)
156
+ const skills = Array.isArray(parsed?.skills) ? parsed.skills : []
157
+ const match = skills.find((entry) => entry && typeof entry === 'object' && entry.name === normalized && typeof entry.id === 'string')
158
+ return match?.id
159
+ } catch {
160
+ return undefined
161
+ }
162
+ }
163
+
164
+ function extractSkillName(args) {
165
+ if (!args) {
166
+ return ''
167
+ }
168
+ if (typeof args === 'string') {
169
+ return args.trim()
170
+ }
171
+ if (typeof args !== 'object') {
172
+ return ''
173
+ }
174
+
175
+ const direct = [args.name, args.skill, args.id]
176
+ for (const value of direct) {
177
+ if (typeof value === 'string' && value.trim()) {
178
+ return value.trim()
179
+ }
180
+ }
181
+
182
+ for (const value of Object.values(args)) {
183
+ if (typeof value === 'string' && value.trim()) {
184
+ return value.trim()
185
+ }
186
+ }
187
+
188
+ return ''
189
+ }
190
+
191
+ async function markSkillUsed(root, skillId) {
192
+ if (!skillId) {
193
+ return
194
+ }
195
+
196
+ try {
197
+ await exec('skillcraft', ['_skill-used', skillId, root], { cwd: root })
198
+ } catch {
199
+ return
200
+ }
201
+ }
202
+
203
+ async function handlePayload(root, payload) {
151
204
  if (!payload || typeof payload !== 'object') {
152
205
  return
153
206
  }
@@ -167,13 +220,14 @@ async function handlePayload(payload) {
167
220
  },
168
221
  }
169
222
 
170
- await updateState(update)
223
+ await updateState(root, update)
171
224
  }
172
225
 
173
- export default async function Skillcraft() {
226
+ export default async function Skillcraft(context) {
227
+ const repoRoot = context?.worktree || context?.directory || process.cwd()
174
228
  const handler = async (event) => {
175
229
  try {
176
- await handlePayload(event)
230
+ await handlePayload(repoRoot, event)
177
231
  } catch {
178
232
  return
179
233
  }
@@ -187,6 +241,18 @@ export default async function Skillcraft() {
187
241
  return
188
242
  }
189
243
  },
244
+ 'tool.execute.after': async (input) => {
245
+ try {
246
+ if (input?.tool !== 'skill') {
247
+ return
248
+ }
249
+ const skillName = extractSkillName(input?.args)
250
+ const skillId = await loadInstalledSkillId(repoRoot, skillName)
251
+ await markSkillUsed(repoRoot, skillId)
252
+ } catch {
253
+ return
254
+ }
255
+ },
190
256
  event: async (event) => {
191
257
  try {
192
258
  const payload = event?.type && typeof event.type === 'string' ? event : event?.payload
@@ -197,70 +263,130 @@ export default async function Skillcraft() {
197
263
  },
198
264
  }
199
265
  }
200
- `}async function Ht(){let e=await F();if(!e.repos.length){process.stdout.write(`no repositories tracked
266
+ `}import{execFile as fo,spawn as go}from"child_process";import{promisify as ho}from"util";import ir from"path";var sr=ho(fo);async function y(e,t,r={}){try{let{stdout:n}=await sr("git",e,{cwd:t,encoding:"utf8",maxBuffer:10485760,env:r.env});return n.trim()}catch(n){let o=n.message??String(n);throw new Error(`git command failed in ${t}: ${o}`)}}async function wo(e,t,r,n={}){return await new Promise((o,i)=>{let s=go("git",e,{cwd:t,env:n.env,stdio:["pipe","pipe","pipe"]}),c="",a="";s.stdout.setEncoding("utf8"),s.stdout.on("data",d=>{c+=d}),s.stderr.setEncoding("utf8"),s.stderr.on("data",d=>{a+=d}),s.on("error",d=>{i(new Error(`git command failed in ${t}: ${d.message}`))}),s.on("close",d=>{if(d===0){o(c.trim());return}let l=a.trim()||c.trim()||`process exited with code ${d??"unknown"}`;i(new Error(`git command failed in ${t}: ${l}`))}),s.stdin.end(r)})}async function M(e){try{return await y(["rev-parse","--git-dir"],e),!0}catch{return!1}}async function z(e){return ir.resolve(await y(["rev-parse","--show-toplevel"],e))}async function V(e,t="origin"){try{return await y(["config","--get",`remote.${t}.url`],e)||void 0}catch{return}}async function ar(e){return y(["rev-parse","--git-path","hooks"],e)}async function cr(e,t="HEAD"){return y(["log","--format=%B","-n","1",t],e)}async function le(e){return(await y(["rev-parse","HEAD"],e)).trim()}async function J(e,t){try{return await y(["show-ref","--verify","--quiet",t],e),!0}catch{return!1}}async function Fe(e,t,r){let n=`refs/heads/${t}`;if(await J(e,n))return;let o=await wo(["hash-object","-t","tree","--stdin"],e,""),i=await y(["commit-tree",o,"-m",r],e);await y(["update-ref",n,i],e)}async function lr(e,t,r="HEAD"){try{return await y(["merge-base","--is-ancestor",t,r],e),!0}catch{return!1}}async function dr(e,t,r){try{let n=await y(["ls-tree","-r","--name-only",t,"--",...r?[r]:[]],e);return n?n.split(`
267
+ `).filter(Boolean):[]}catch{return[]}}async function ur(e,t,r){try{return await y(["show",`${t}:${r}`],e)}catch{return}}async function Oe(e,t){let r=t?String(t):"200",n=await y(["log",`--max-count=${r}`,"--pretty=%H%x00%B"],e);return n?n.split("\0").filter(Boolean).map(o=>{let[i,...s]=o.split(`
268
+ `),c=s.join(`
269
+ `).trimEnd();return{commit:i,message:c}}):[]}async function mr(e,t){let r={...process.env,SKILLCRAFT_HOOK_DISABLED:"1"},n=ir.join(e,".git","SKILLCRAFT_COMMIT_MESSAGE"),{writeFile:o}=await import("fs/promises");return await o(n,`${t}
270
+ `,"utf8"),await sr("git",["commit","--amend","--file",n,"--no-gpg-sign"],{cwd:e,encoding:"utf8",env:r}),le(e)}import de from"fs/promises";import $ from"path";var pr="# skillcraft-managed-hook";function ct(e,t){let r=process.argv[1]||"skillcraft",n=JSON.stringify(r),o=e?JSON.stringify(e):void 0,i=o?`if [ -x ${o} ]; then
271
+ ${o} "$@"
272
+ SKILLCRAFT_PREVIOUS_HOOK_EXIT=$?
273
+ if [ "$SKILLCRAFT_PREVIOUS_HOOK_EXIT" -ne 0 ]; then
274
+ exit "$SKILLCRAFT_PREVIOUS_HOOK_EXIT"
275
+ fi
276
+ fi
277
+
278
+ `:"";return`#!/usr/bin/env sh
279
+ ${pr}
280
+ if [ -n "$SKILLCRAFT_HOOK_DISABLED" ]; then
281
+ exit 0
282
+ fi
283
+
284
+ ${i}SKILLCRAFT_HOOK_DIR="$PWD"
285
+ SKILLCRAFT_HOOK_DIR="$(git -C "$SKILLCRAFT_HOOK_DIR" rev-parse --show-toplevel 2>/dev/null || printf "%s" "$SKILLCRAFT_HOOK_DIR")"
286
+ SKILLCRAFT_CLI=${n}
287
+ unset GIT_INDEX_FILE
288
+
289
+ ${t}
290
+ `}var yo=e=>ct(e,'"$SKILLCRAFT_CLI" _hook post-commit "$SKILLCRAFT_HOOK_DIR" || true'),ko=e=>ct(e,`SKILLCRAFT_HOOK_REMOTE="$1"
291
+ "$SKILLCRAFT_CLI" _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`),xo=e=>ct(e,`SKILLCRAFT_HOOK_REMOTE="$1"
292
+ "$SKILLCRAFT_CLI" _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`);async function fr(e){let t=await lt(e);await v(t),await st($.join(t,"post-commit"),yo),await st($.join(t,"post-push"),ko),await st($.join(t,"pre-push"),xo)}async function gr(e){let t=await lt(e).catch(()=>{});!t||t==="/dev/null"||await Promise.all([at($.join(t,"post-commit")),at($.join(t,"post-push")),at($.join(t,"pre-push"))])}async function hr(e){let t=await lt(e).catch(()=>{});if(!t||t==="/dev/null")return!1;let r=$.join(t,"post-commit");return await S(r)?yr(await te(r).catch(()=>"")):!1}async function lt(e){let t=await ar(e);if(t==="/dev/null")throw new Error("Git hooks are disabled for this repository (`core.hooksPath=/dev/null`). Re-enable hooks or unset `core.hooksPath` before running `skillcraft enable`.");let r=$.isAbsolute(t)?$.normalize(t):$.resolve(e,t),n=$.join(e,".git","hooks");if(r===n||vo(r,e))return r;throw new Error(`Git hooks path points outside this repository: ${r}. Skillcraft currently supports the default hooks directory or repo-local hooks paths such as .husky.`)}async function st(e,t){let r=await wr(e);if(r.exists&&r.isManaged){await U(e,`${t(r.backupExists?r.backupPath:void 0)}
293
+ `),await de.chmod(e,493);return}let n;r.exists&&(n=r.backupPath,await S(n)?await de.rm(e,{force:!0}):await de.rename(e,n)),await U(e,`${t(n)}
294
+ `),await de.chmod(e,493)}async function at(e){let t=await wr(e);if(!(!t.exists||!t.isManaged)){if(t.backupExists){await de.rename(t.backupPath,e);return}await de.rm(e,{force:!0})}}async function wr(e){let t=`${e}.skillcraft.orig`;if(!await S(e))return{hookPath:e,backupPath:t,exists:!1,isManaged:!1,backupExists:await S(t)};let n=await te(e).catch(()=>"");return{hookPath:e,backupPath:t,exists:!0,isManaged:yr(n),backupExists:await S(t)}}function yr(e){return e.includes(pr)||e.includes("SKILLCRAFT_CLI=")&&(e.includes("_hook post-commit")||e.includes("_hook post-push"))}function vo(e,t){let r=$.relative(t,e);return r===""||!r.startsWith("..")&&!$.isAbsolute(r)}async function kr(e={}){let t=process.cwd();if(!await M(t))throw new Error("Current directory is not a git repository");let r=await z(t),n=await ce(r),o=bo(e.agents||[],n);for(let s of o)await tr(r,s);let i=n.filter(s=>!o.includes(s));if(i.length){await Te(r,i),process.stdout.write(`disabled skillcraft agents for ${r} (remaining: ${i.join(", ")})
295
+ `);return}await Po(r),process.stdout.write(`disabled skillcraft for ${r}
296
+ `)}function bo(e,t){let r=Ne(e);if(r.length)throw new Error(`Unsupported agent value: ${r.join(", ")}`);if(!t.length)return[];let n=ye(e);if(!n.length)return t;let o=n.filter(i=>t.includes(i));if(!o.length)throw new Error(`None of the requested agents are enabled in this repository: ${n.join(", ")}`);return o}async function Po(e){await Promise.all([j(W(e)),j(N(e)),j(I(e)),j(ge(e)),j(H(e)),Ae(q(e))]),await gr(e),await Ut(e)}import{createHash as So}from"crypto";import Me from"path";import Co from"os";import vr from"fs/promises";var dt="proofs";function br(e){return(e?.trim()||Q).replace(/^refs\/heads\//,"")}function Pr(e){return`${dt}/${e}.json`}async function ze(e){let t=await Ie(e);return br(t.proofRef)}async function Sr(e,t){let r=br(t),n=`refs/heads/${r}`,o=`refs/remotes/origin/${r}`,i=[];return await J(e,n)&&i.push(r),await J(e,o)&&i.push(`origin/${r}`),i.length||i.push(r),i}async function Ro(e,t){let r=`refs/heads/${t}`;await J(e,r)||await Fe(e,t,"Initialize Skillcraft proofs branch")}async function Ao(e,t,r){await Io(e,t);let n=await vr.mkdtemp(Me.join(Co.tmpdir(),"skillcraft-proof-"));try{return await y(["worktree","add","--quiet",n,t],e),await r(n)}finally{await Cr(e,n)}}async function Cr(e,t){try{await y(["worktree","remove","--force",t],e)}catch{await vr.rm(t,{force:!0,recursive:!0})}}async function Io(e,t){let r=`refs/heads/${t}`;try{let o=(await y(["worktree","list","--porcelain"],e)).split(`
297
+ `),i,s,c=async()=>{!i||s!==r||await Cr(e,i)};for(let a of o){if(!a){i=void 0,s=void 0;continue}if(a.startsWith("worktree ")){await c(),i=a.slice(9),s=void 0;continue}a.startsWith("branch ")&&(s=a.slice(7))}await c()}catch{return}}async function ut(e){let t=await ze(e),r=await Sr(e,t),n=new Set;for(let i of r){let s=await dr(e,i,dt);for(let c of s)n.add(c)}let o=[];for(let i of n){if(!i.endsWith(".json"))continue;let s=Me.basename(i,".json"),c=await mt(e,s);c&&o.push(c)}return o}function $o(e){let t=G(e);if(t.id&&Qe(t.id))return{id:t.id,version:t.version}}function Eo(e){let t=e.filter(Boolean).map(r=>G(r)).filter(r=>!!r.id).map(r=>`${r.id}${r.version?`@${r.version}`:""}`);return Array.from(new Set(t)).filter(Qe).sort()}function Rr(e,t,r){let n={skills:e,loadouts:r,timestamp:t};return So("sha256").update(JSON.stringify(n)).digest("hex").slice(0,8)}async function ke(e){let t=await w(N(e)),r=Tt.safeParse(t??{skills:[]});return r.success?Eo(r.data.skills):[]}async function jo(e){let t=await w(I(e)),r=qt.safeParse(t??{activeLoadouts:[]});return r.success?r.data.activeLoadouts:[]}async function Lo(e){let t=await w(H(e));if(!t||typeof t!="object"||Array.isArray(t))return{};let r=t,n=r.agent&&typeof r.agent=="object"&&!Array.isArray(r.agent)?r.agent:void 0,o=r.model&&typeof r.model=="object"&&!Array.isArray(r.model)?r.model:void 0;return{agent:typeof n?.provider=="string"?{provider:xr(n.provider)}:void 0,model:typeof o?.provider=="string"||typeof o?.name=="string"?{provider:typeof o.provider=="string"?xr(o.provider):void 0,name:typeof o.name=="string"?_o(o.name):void 0}:void 0}}function xr(e){return e.trim().toLowerCase()}function _o(e){return e.trim()}function No(e){if(!e||typeof e!="object")return;let t=e;if(typeof t.version!="number"||typeof t.commit!="string"||!Array.isArray(t.skills)||!t.timestamp||typeof t.timestamp!="string")return;let r=Array.isArray(t.loadouts)?t.loadouts.map(String):[],n=t.skills.map(o=>{if(typeof o=="string")return{id:o};if(o&&typeof o=="object"&&"id"in o&&typeof o.id=="string")return{id:o.id,version:typeof o.version=="string"?o.version:void 0}}).filter(o=>!!o);return{version:t.version,commit:t.commit,skills:n,loadouts:r,timestamp:t.timestamp,agent:To(t.agent),model:qo(t.model)}}function To(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e.provider;if(typeof t!="string")return;let r=t.trim().toLowerCase();return r?{provider:r}:void 0}function qo(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,r=typeof t.provider=="string"?t.provider.trim().toLowerCase():void 0,n=typeof t.name=="string"?t.name.trim():void 0;if(!(!r&&!n))return{provider:r,name:n}}async function mt(e,t){let r=await ze(e),n=Pr(t),o=await Sr(e,r);for(let i of o){let s=await ur(e,i,n);if(!s)continue;let c;try{c=JSON.parse(s)}catch{continue}let a=No(c);if(a)return a}}async function pt(e,t){let r=Rr(t.skills.map(i=>i.id),t.timestamp,t.loadouts),n=await ze(e);await Ro(e,n);let o=Pr(r);return await Ao(e,n,async i=>{await v(Me.join(i,dt)),await h(Me.join(i,o),t),await y(["add",o],i,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}}),await y(["status","--porcelain","--",o],i,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}})&&await y(["commit","--no-gpg-sign","-m",`add Skillcraft proof ${r}`],i,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}})}),r}async function Ar(e,t="origin"){let r=await ze(e);if(!(!await V(e,t)||!t))try{await y(["push",t,`${r}:${r}`],e,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}})}catch{return}}async function Ir(e,t){let r=await ut(e);for(let n of r)if(n.commit===t)return Rr(n.skills.map(o=>o.id),n.timestamp,n.loadouts)}async function $r(e,t,r=new Date().toISOString()){let n=await ke(e),o=await jo(e),i=await Lo(e),s=n.map(d=>$o(d)).filter(d=>!!d),c={version:1,commit:t,skills:s,loadouts:o,timestamp:r,...i};return{proofId:await pt(e,c),proof:c}}async function Fo(e){return e.replace(/\nSkillcraft-Ref: .*$/gm,"").trimEnd()}async function Er(e,t){let r=await cr(e),n=await Fo(r);return n.includes("Skillcraft-Ref:")?n:`${n}
298
+
299
+ Skillcraft-Ref: ${t}
300
+ `}async function R(e){let t=W(e);if(!await S(t))return!1;let r=await w(t);return ee.safeParse(r??{}).success}async function jr(e){return S(q(e))}import X from"fs/promises";import ft from"path";import{execFile as Oo,execSync as Mo}from"child_process";import{promisify as zo}from"util";var Do=zo(Oo);function Ho(){try{return Mo("which gh",{stdio:"ignore"}),!0}catch{return!1}}async function Z(e){if(!Ho())throw new Error("gh CLI is required for this workflow");return(await Do("gh",e,{encoding:"utf8"})).stdout.trim()}async function Lr(e,t){await X.mkdir(t,{recursive:!0});let r=await X.readdir(e,{withFileTypes:!0});for(let n of r){if(n.name===".git")continue;let o=ft.join(e,n.name),i=ft.join(t,n.name);if(n.isDirectory()){await Lr(o,i);continue}if(n.isSymbolicLink()){let s=await X.readlink(o);await X.symlink(s,i);continue}n.isFile()&&await X.copyFile(o,i)}}var De=class{providerName(){return"gh"}async getUser(){return await Z(["api","user","--jq",".login"])}async getIssueUrl(t,r){return`https://github.com/${t}/issues/${r}`}async createIssue(t,r,n){let i=(await Z(["issue","create","-R",t,"--title",r,"--body",n])).match(/\b(\d+)$/);return i?Number(i[1]):0}async createPullRequest(t,r,n){let i=(await Z(["pr","create","--repo",t,"--head",r,"--base","main","--title",n,"--body",`Generated by skillcraft for ${n}`,"--fill-first"])).match(/\b(\d+)$/);return i?Number(i[1]):0}async openPullRequestForBranch(t,r,n,o,i){let c=(await Z(["pr","create","--repo",t,"--head",`${r}:${n}`,"--base","main","--title",o,"--body",i])).match(/\b(\d+)$/);return c?Number(c[1]):0}async getIssueStatus(t,r){let n=await Z(["issue","view",String(r),"--repo",t,"--json","state,labels,url"]),o=JSON.parse(n);return{state:o.state,labels:o.labels?.map(i=>i.name)??[],url:o.url}}async listClaimProcessingRuns(t,r){let n=await Z(["run","list","--repo",t,"--workflow","Process credential claims","--json","name,status,conclusion,url,createdAt,workflowName"]),o=JSON.parse(n),i=`#${r}`,s=o.filter(a=>{let d=a.name||"",l=a.workflowName||"";return d.includes(i)||l.includes(i)}),c=s.length>0?s:o.filter(a=>a.status&&["in_progress","queued","waiting","action_required","canceling"].includes(a.status));return c.length?c.filter(a=>a.url).map(a=>({status:a.status||"unknown",conclusion:a.conclusion??void 0,url:a.url,name:a.name,createdAt:a.createdAt,workflowName:a.workflowName})):[]}async listClaimIssues(t){let r=await Z(["issue","list","--repo",t,"--state","all","--json","number,title,state,body,labels,url","--limit","100"]);return JSON.parse(r).filter(o=>Uo(o.title)||Ko(o.labels,"skillcraft-claim"))}async cloneRepo(t,r){let n=ft.resolve(r);await Z(["repo","clone",t,n])}async copyDirectory(t,r){await X.readdir(r).catch(()=>{})&&await X.rm(r,{recursive:!0,force:!0}),await X.mkdir(r,{recursive:!0}),await Lr(t,r)}};function gt(e){return String(e||"").trim().toLowerCase()}function Uo(e){return gt(e).startsWith("claim:")}function Ko(e,t){let r=gt(t);return(e||[]).some(n=>gt(n?.name)===r)}var Bo={gh:()=>new De};function L(e){return Bo[e]()}async function _r(){let e=process.cwd(),t=await M(e);process.stdout.write(`git: ${t?"enabled":"not a repository"}
301
+ `);let r=t?await z(e):e,n=await R(r);if(process.stdout.write(`skillcraft: ${n?"enabled":"disabled"}
302
+ `),!t||!n)return;let o=await ke(r),i=await ce(r);process.stdout.write(`pending skills: ${o.length}
303
+ `),process.stdout.write(`agents: ${i.length?i.join(", "):"none"}
304
+ `);let s=await S(I(r)),c=await hr(r);process.stdout.write(`context file: ${s?"present":"missing"}
305
+ `),process.stdout.write(`post-commit hook: ${c?"installed":"missing"}
306
+ `);let a=await le(r),d=await Ir(r,a);process.stdout.write(`head: ${a}
307
+ `),process.stdout.write(`latest proof: ${d??"none"}
308
+ `);let u=(await Oe(r,20)).filter(P=>P.message.includes("Skillcraft-Ref:"));process.stdout.write(`recent commits with evidence: ${u.length}
309
+ `);let f=(await Ie(r)).proofRef?.replace(/^refs\/heads\//,"")||"skillcraft/proofs/v1",g=await J(r,`refs/heads/${f}`);process.stdout.write(`proof branch: ${g?"present":"missing"}
310
+ `),o.length>0&&process.stdout.write(`pending evidence queued: ${o.join(", ")}
311
+ `)}async function Nr(){let e=await Promise.all([ue("node"),ue("npm"),ue("git"),ue("gh"),ue("codex"),ue("opencode")]);for(let[o,i]of e)process.stdout.write(`${o}: ${i?"ok":"missing"}
312
+ `);let t=await qe();if(process.stdout.write(`detected agents: ${t.length?t.join(", "):"none"}
313
+ `),!(e.find(([o])=>o==="gh")?.[1]??!1)){process.stdout.write(`gh auth: missing
314
+ `),process.stdout.write(`github user: unknown
315
+ `);return}let n=await L("gh").getUser().catch(()=>"");process.stdout.write(`gh auth: ${n?"ok":"missing"}
316
+ `),process.stdout.write(`github user: ${n||"unknown"}
317
+ `)}async function ue(e){return[e,await Jo(e)]}async function Jo(e){try{let{execSync:t}=await import("child_process");return t(`command -v ${e}`,{stdio:"ignore"}),!0}catch{return!1}}import{createInterface as Wo}from"readline/promises";import{stdin as Tr,stdout as xe}from"process";async function qr(e={}){let t=process.cwd();if(!await M(t))throw new Error("Current directory is not a git repository");let r=await z(t),n=await Go(e.agents||[]),o=await F();if(!o.githubUser){let l=await L(o.provider??"gh").getUser().catch(()=>process.env.GITHUB_USER||process.env.USER||"developer");await Dt({...o,githubUser:l})}await v(q(r));let i=`refs/heads/${Q}`;await J(r,i)||await Fe(r,Q,"Initialize Skillcraft proofs branch"),await h(W(r),{version:1,proofRef:Q}),await v(T()),await h(N(r),{skills:[]}),await h(I(r),{activeLoadouts:[]});let s=await ce(r),c=Fr([...s,...n]);for(let d of n)await er(r,d);await rr(r,c[0]||"opencode"),await Te(r,c),await fr(r);let a=await V(r);await Ht({path:r,remote:a,enabledAt:new Date().toISOString()}),process.stdout.write(`enabled skillcraft for ${r} (agents: ${c.join(", ")})
318
+ `)}async function Go(e){let t=Ne(e);if(t.length)throw new Error(`Unsupported agent value: ${t.join(", ")}`);let r=ye(e);if(r.length)return r;let n=await qe();if(!n.length)throw new Error("No supported AI coding agents detected. Install opencode or codex, or pass --agent explicitly.");if(n.length===1)return n;if(!Tr.isTTY||!xe.isTTY)throw new Error("Multiple supported agents detected (codex, opencode). Re-run with --agent codex, --agent opencode, or both.");return Vo(n)}async function Vo(e){let t=Wo({input:Tr,output:xe});try{xe.write(`Multiple supported agents detected: ${e.join(", ")}
319
+ `),xe.write(`Select one or more agents to enable (comma-separated, e.g. 1,2):
320
+ `),e.forEach((o,i)=>{xe.write(`${i+1}. ${o}
321
+ `)});let r=await t.question("Agents: "),n=Fr(r.split(",").map(o=>{let i=o.trim(),s=Number.parseInt(i,10);return Number.isFinite(s)&&s>=1&&s<=e.length?e[s-1]:ye([i])[0]}).filter(o=>!!o));if(!n.length)throw new Error("No valid agent selection provided.");return n}finally{t.close()}}function Fr(e){return Array.from(new Set(e)).sort()}async function Or(){let e=await K();if(!e.repos.length){process.stdout.write(`no repositories tracked
201
322
  `);return}e.repos.forEach((t,r)=>{process.stdout.write(`${r+1}. ${t.path}`),t.remote&&process.stdout.write(` (${t.remote})`),process.stdout.write(`
202
- `)})}async function Kt(){let e=await F(),t=[];for(let r of e.repos)await O(r.path)&&(await ee(r.path),t.push(r));await ke({repos:t}),process.stdout.write(`pruned repo list: ${e.repos.length} -> ${t.length}
203
- `)}async function se(e){return _e(e)}import kn from"path";var vn="https://skillcraft.gg/credential-ledger/credentials/index.json",xn=360*60*1e3,Ke=1,ae=ut();function Pn(){return process.env.SKILLCRAFT_CREDENTIAL_INDEX_URL?.trim()||vn}async function Ut(e){try{let t=await v(e);if(!t||!V(t))return null;let r=bn(t.cachedAt);if(r===void 0||r<=0||t.version!==Ke||!("entries"in t))return null;let n=Se(t.entries);return{cachedAt:r,version:Ke,entries:n}}catch{return null}}function bn(e){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"&&e.trim()){let t=Number.parseInt(e,10);if(Number.isFinite(t))return t}}function Rn(e){return Date.now()-e.cachedAt<xn}async function Cn(e={}){let t=process.env.SKILLCRAFT_CREDENTIAL_INDEX_PATH?.trim();if(t)return Bt(t);let r=e.refresh?null:await Ut(ae);if(r&&Rn(r))return r.entries;try{let n=await Sn(Pn());return await $n(n),n}catch(n){if(await q(ae)){let i=await Ut(ae);return i?i.entries:Bt(ae)}throw n instanceof Error?n:new Error("failed to load credential index")}}async function Sn(e){let t=await fetch(e,{headers:{"user-agent":"skillcraft-cli"}});if(!t.ok)throw new Error(`failed to download credential index from ${e}`);let r=await t.json();return Se(r)}async function Bt(e){let t=await v(e);return t?V(t)&&Array.isArray(t.entries)?Se(t.entries):Se(t):[]}async function $n(e){await C(kn.dirname(ae));let t={cachedAt:Date.now(),version:Ke,entries:e};await y(ae,t)}function En(e){let t=V(e)?e:{};if(t.mode!==void 0)throw new Error("requirements.mode is not supported. Use nested and/or expressions instead.");let r=In(t);return{minCommits:Gt(t.min_commits??t.minCommits,0),minRepositories:Gt(t.min_repositories??t.minRepositories,0),tree:r}}function In(e){if(Object.prototype.hasOwnProperty.call(e,"tree"))return Be(e.tree,"requirements.tree");let t=Object.prototype.hasOwnProperty.call(e,"and"),r=Object.prototype.hasOwnProperty.call(e,"or");if(t&&r)throw new Error("requirements cannot include both and and or at the same level");if(t){let n=Object.keys(e).filter(i=>!["and","min_commits","min_repositories","minRepositories","minCommits","tree"].includes(i));if(n.length)throw new Error(`Unexpected requirement fields: ${n.join(", ")}`);return{and:Wt(e.and,"requirements.and")}}if(r){let n=Object.keys(e).filter(i=>!["or","min_commits","min_repositories","minRepositories","minCommits","tree"].includes(i));if(n.length)throw new Error(`Unexpected requirement fields: ${n.join(", ")}`);return{or:Wt(e.or,"requirements.or")}}return{and:An(e)}}function Wt(e,t){if(!Array.isArray(e))throw new Error(`Expected array at ${t}`);return e.map((r,n)=>Be(r,`${t}[${n}]`))}function Jt(e,t){if(e===void 0)return[];if(Array.isArray(e))return e.map(n=>{let i=E(n);if(i===void 0)throw new Error(`Expected text values for ${t}`);return i});let r=E(e);return r?[r]:[]}function An(e){let t=[],r=["and","or","min_commits","min_repositories","minRepositories","minCommits","tree","skill","loadout","agent","model"];for(let a of Jt(e.skill,"requirements.skill"))t.push({skill:a});for(let a of Jt(e.loadout,"requirements.loadout"))t.push({loadout:a});let n=Object.prototype.hasOwnProperty.call(e,"agent"),i=Vt(e.agent);if(i)t.push(i);else if(n)throw new Error("requirements.agent must be an object with a provider");let o=Object.prototype.hasOwnProperty.call(e,"model"),s=Zt(e.model);if(s)t.push(s);else if(o)throw new Error("requirements.model must be an object with optional provider and/or name");let c=Object.keys(e).filter(a=>!r.includes(a)&&!a.startsWith("$"));if(c.length)throw new Error(`Unexpected requirement fields: ${c.join(", ")}`);return t}function Be(e,t){if(!V(e))throw new Error(`Invalid requirement node at ${t}`);let r=Object.keys(e);if(!r.length)throw new Error(`Empty requirement node at ${t}`);if(r.length>1)throw new Error(`Requirement node has multiple keys at ${t}`);let[n]=r;if(n==="and"||n==="or"){let i=e[n];if(!Array.isArray(i))throw new Error(`Requirement node ${t} expected array for ${n}`);return{[n]:i.map((o,s)=>Be(o,`${t}.${n}[${s}]`))}}if(n==="skill"){let i=E(e[n]);if(!i)throw new Error(`Requirement node ${t} has empty skill`);return{skill:i}}if(n==="loadout"){let i=E(e[n]);if(!i)throw new Error(`Requirement node ${t} has empty loadout`);return{loadout:i}}if(n==="agent"){let i=Vt(e[n]);if(!i)throw new Error(`Requirement node ${t} has invalid agent requirement`);return i}if(n==="model"){let i=Zt(e[n]);if(!i)throw new Error(`Requirement node ${t} has invalid model requirement`);return i}throw new Error(`Unexpected requirement key ${n} at ${t}`)}function Vt(e){if(!V(e))return;let t=E(e.provider);if(t)return{agent:{provider:t.toLowerCase()}}}function Zt(e){if(!V(e))return;let t=E(e.provider),r=E(e.name);if(!(!t&&!r))return{model:{...t?{provider:t.toLowerCase()}:{},...r?{name:r}:{}}}}function Xt(e,t,r,n){let i=[],o=[],s=[],c=[],a=Array.from(new Set((t||[]).filter(Boolean))),u=Array.from(new Set((r||[]).filter(Boolean)));for(let p of e){let f=p.proof;for(let B of f.skills){let Q=We(B.id);Q.id&&i.push({id:Q.id,version:Q.version})}for(let B of f.loadouts){let Q=E(B);Q&&o.push(Q)}f.agent?.provider&&typeof f.agent.provider=="string"&&s.push(f.agent.provider);let x=f.model?.provider,Y=f.model?.name;(typeof x=="string"||typeof Y=="string")&&c.push({provider:x,name:Y})}let l=Ue(n.tree,{skills:i,loadouts:o,agents:s,models:c}),d=l.checks,m=[...Ln(d)];return n.minCommits>a.length&&(m.push(`minimum required commits not met: have ${a.length}, need ${n.minCommits}`),l.passed=!1),n.minRepositories>u.length&&(m.push(`minimum required repositories not met: have ${u.length}, need ${n.minRepositories}`),l.passed=!1),{passed:l.passed,proofs:e,provenCommits:a,provenRepos:u,checks:d,reasons:m,noExplicitChecks:l.noExplicitChecks}}function Ue(e,t){if("and"in e){let r=[],n=[],i=!0;for(let o of e.and){let s=Ue(o,t);r.push(...s.checks),n.push(s),s.noExplicitChecks||(i=!1)}return{passed:n.every(o=>o.passed),checks:r,noExplicitChecks:i}}if("or"in e){let r=[],n=[],i=!0;for(let o of e.or){let s=Ue(o,t);r.push(...s.checks),n.push(s),s.noExplicitChecks||(i=!1)}return{passed:n.some(o=>o.passed),checks:r,noExplicitChecks:i}}if("skill"in e){let r=We(e.skill),n=jn(t.skills,r);return{passed:n,checks:[{type:"skill",requirement:e.skill,satisfied:n}],noExplicitChecks:!1}}if("loadout"in e){let r=Nn(e.loadout),n=t.loadouts.includes(e.loadout)||r&&r.id!==""&&t.loadouts.includes(r.id);return{passed:n,checks:[{type:"loadout",requirement:e.loadout,satisfied:n}],noExplicitChecks:!1}}if("agent"in e){let r=He(e.agent.provider),n=t.agents.some(i=>i===r);return{passed:n,checks:[{type:"agent",requirement:`provider=${r}`,satisfied:n}],noExplicitChecks:!1}}if("model"in e){let r=He(e.model.provider),n=He(e.model.name),i=t.models.some(s=>{let c=!r||s.provider===r,a=!n||s.name&&s.name===n;return c&&a}),o=[];return r&&o.push(`provider=${r}`),n&&o.push(`name=${n}`),{passed:i,checks:[{type:"model",requirement:o.join(",")||"model",satisfied:i}],noExplicitChecks:!1}}throw new Error("Unknown requirement node encountered during evaluation")}function Ln(e){return e.filter(t=>!t.satisfied).map(t=>`${t.type} ${t.requirement} not met`)}function jn(e,t){return e.some(r=>qn(r.id,r.version,t))}function qn(e,t,r){return e!==r.id?!1:r.version?t===r.version:!0}function Nn(e){return We(e)}function We(e){let t=E(e);if(!t)return{id:""};let r=t.split("@");return{id:r[0],version:r.length>1?r.slice(1).join("@"):void 0}}function He(e){return typeof e=="string"?e.trim().toLowerCase():""}function E(e){return typeof e!="string"?void 0:e.trim()||void 0}function Gt(e,t){return typeof e!="number"||!Number.isFinite(e)||e<0?t:Math.floor(e)}function V(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Se(e){if(!Array.isArray(e))return[];let t=[];for(let r of e){let n=Fn(r);n&&t.push(n)}return t.sort((r,n)=>r.id.localeCompare(n.id))}function Fn(e){if(!V(e))return;let t=E(e.id);if(t)try{return{id:t,name:E(e.name),description:E(e.description),requirements:En(e.requirements)}}catch{return}}async function Je(e={}){return Cn(e)}function Yt(e){process.stdout.write(`${e.join(`
323
+ `)})}async function Mr(){let e=await K(),t=[];for(let r of e.repos)await M(r.path)&&(await z(r.path),t.push(r));await $e({repos:t}),process.stdout.write(`pruned repo list: ${e.repos.length} -> ${t.length}
324
+ `)}async function me(e){return ut(e)}import Zo from"path";var Xo="https://skillcraft.gg/credential-ledger/credentials/index.json",Yo=360*60*1e3,wt=1,pe=Lt();function Qo(){return process.env.SKILLCRAFT_CREDENTIAL_INDEX_URL?.trim()||Xo}async function zr(e){try{let t=await w(e);if(!t||!re(t))return null;let r=ei(t.cachedAt);if(r===void 0||r<=0||t.version!==wt||!("entries"in t))return null;let n=He(t.entries);return{cachedAt:r,version:wt,entries:n}}catch{return null}}function ei(e){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"&&e.trim()){let t=Number.parseInt(e,10);if(Number.isFinite(t))return t}}function ti(e){return Date.now()-e.cachedAt<Yo}async function ri(e={}){let t=process.env.SKILLCRAFT_CREDENTIAL_INDEX_PATH?.trim();if(t)return Dr(t);let r=e.refresh?null:await zr(pe);if(r&&ti(r))return r.entries;try{let n=await ni(Qo());return await oi(n),n}catch(n){if(await S(pe)){let o=await zr(pe);return o?o.entries:Dr(pe)}throw n instanceof Error?n:new Error("failed to load credential index")}}async function ni(e){let t=await fetch(e,{headers:{"user-agent":"skillcraft-cli"}});if(!t.ok)throw new Error(`failed to download credential index from ${e}`);let r=await t.json();return He(r)}async function Dr(e){let t=await w(e);return t?re(t)&&Array.isArray(t.entries)?He(t.entries):He(t):[]}async function oi(e){await v(Zo.dirname(pe));let t={cachedAt:Date.now(),version:wt,entries:e};await h(pe,t)}function ii(e){let t=re(e)?e:{};if(t.mode!==void 0)throw new Error("requirements.mode is not supported. Use nested and/or expressions instead.");let r=si(t);return{minCommits:Kr(t.min_commits??t.minCommits,0),minRepositories:Kr(t.min_repositories??t.minRepositories,0),tree:r}}function si(e){if(Object.prototype.hasOwnProperty.call(e,"tree"))return kt(e.tree,"requirements.tree");let t=Object.prototype.hasOwnProperty.call(e,"and"),r=Object.prototype.hasOwnProperty.call(e,"or");if(t&&r)throw new Error("requirements cannot include both and and or at the same level");if(t){let n=Object.keys(e).filter(o=>!["and","min_commits","min_repositories","minRepositories","minCommits","tree"].includes(o));if(n.length)throw new Error(`Unexpected requirement fields: ${n.join(", ")}`);return{and:Hr(e.and,"requirements.and")}}if(r){let n=Object.keys(e).filter(o=>!["or","min_commits","min_repositories","minRepositories","minCommits","tree"].includes(o));if(n.length)throw new Error(`Unexpected requirement fields: ${n.join(", ")}`);return{or:Hr(e.or,"requirements.or")}}return{and:ai(e)}}function Hr(e,t){if(!Array.isArray(e))throw new Error(`Expected array at ${t}`);return e.map((r,n)=>kt(r,`${t}[${n}]`))}function Ur(e,t){if(e===void 0)return[];if(Array.isArray(e))return e.map(n=>{let o=_(n);if(o===void 0)throw new Error(`Expected text values for ${t}`);return o});let r=_(e);return r?[r]:[]}function ai(e){let t=[],r=["and","or","min_commits","min_repositories","minRepositories","minCommits","tree","skill","loadout","agent","model"];for(let a of Ur(e.skill,"requirements.skill"))t.push({skill:a});for(let a of Ur(e.loadout,"requirements.loadout"))t.push({loadout:a});let n=Object.prototype.hasOwnProperty.call(e,"agent"),o=Br(e.agent);if(o)t.push(o);else if(n)throw new Error("requirements.agent must be an object with a provider");let i=Object.prototype.hasOwnProperty.call(e,"model"),s=Jr(e.model);if(s)t.push(s);else if(i)throw new Error("requirements.model must be an object with optional provider and/or name");let c=Object.keys(e).filter(a=>!r.includes(a)&&!a.startsWith("$"));if(c.length)throw new Error(`Unexpected requirement fields: ${c.join(", ")}`);return t}function kt(e,t){if(!re(e))throw new Error(`Invalid requirement node at ${t}`);let r=Object.keys(e);if(!r.length)throw new Error(`Empty requirement node at ${t}`);if(r.length>1)throw new Error(`Requirement node has multiple keys at ${t}`);let[n]=r;if(n==="and"||n==="or"){let o=e[n];if(!Array.isArray(o))throw new Error(`Requirement node ${t} expected array for ${n}`);return{[n]:o.map((i,s)=>kt(i,`${t}.${n}[${s}]`))}}if(n==="skill"){let o=_(e[n]);if(!o)throw new Error(`Requirement node ${t} has empty skill`);return{skill:o}}if(n==="loadout"){let o=_(e[n]);if(!o)throw new Error(`Requirement node ${t} has empty loadout`);return{loadout:o}}if(n==="agent"){let o=Br(e[n]);if(!o)throw new Error(`Requirement node ${t} has invalid agent requirement`);return o}if(n==="model"){let o=Jr(e[n]);if(!o)throw new Error(`Requirement node ${t} has invalid model requirement`);return o}throw new Error(`Unexpected requirement key ${n} at ${t}`)}function Br(e){if(!re(e))return;let t=_(e.provider);if(t)return{agent:{provider:t.toLowerCase()}}}function Jr(e){if(!re(e))return;let t=_(e.provider),r=_(e.name);if(!(!t&&!r))return{model:{...t?{provider:t.toLowerCase()}:{},...r?{name:r}:{}}}}function Wr(e,t,r,n){let o=[],i=[],s=[],c=[],a=Array.from(new Set((t||[]).filter(Boolean))),d=Array.from(new Set((r||[]).filter(Boolean)));for(let f of e){let g=f.proof;for(let Y of g.skills){let ie=xt(Y.id);ie.id&&o.push({id:ie.id,version:ie.version})}for(let Y of g.loadouts){let ie=_(Y);ie&&i.push(ie)}g.agent?.provider&&typeof g.agent.provider=="string"&&s.push(g.agent.provider);let P=g.model?.provider,oe=g.model?.name;(typeof P=="string"||typeof oe=="string")&&c.push({provider:P,name:oe})}let l=yt(n.tree,{skills:o,loadouts:i,agents:s,models:c}),u=l.checks,p=[...ci(u)];return n.minCommits>a.length&&(p.push(`minimum required commits not met: have ${a.length}, need ${n.minCommits}`),l.passed=!1),n.minRepositories>d.length&&(p.push(`minimum required repositories not met: have ${d.length}, need ${n.minRepositories}`),l.passed=!1),{passed:l.passed,proofs:e,provenCommits:a,provenRepos:d,checks:u,reasons:p,noExplicitChecks:l.noExplicitChecks}}function yt(e,t){if("and"in e){let r=[],n=[],o=!0;for(let i of e.and){let s=yt(i,t);r.push(...s.checks),n.push(s),s.noExplicitChecks||(o=!1)}return{passed:n.every(i=>i.passed),checks:r,noExplicitChecks:o}}if("or"in e){let r=[],n=[],o=!0;for(let i of e.or){let s=yt(i,t);r.push(...s.checks),n.push(s),s.noExplicitChecks||(o=!1)}return{passed:n.some(i=>i.passed),checks:r,noExplicitChecks:o}}if("skill"in e){let r=xt(e.skill),n=li(t.skills,r);return{passed:n,checks:[{type:"skill",requirement:e.skill,satisfied:n}],noExplicitChecks:!1}}if("loadout"in e){let r=ui(e.loadout),n=t.loadouts.includes(e.loadout)||r&&r.id!==""&&t.loadouts.includes(r.id);return{passed:n,checks:[{type:"loadout",requirement:e.loadout,satisfied:n}],noExplicitChecks:!1}}if("agent"in e){let r=ht(e.agent.provider),n=t.agents.some(o=>o===r);return{passed:n,checks:[{type:"agent",requirement:`provider=${r}`,satisfied:n}],noExplicitChecks:!1}}if("model"in e){let r=ht(e.model.provider),n=ht(e.model.name),o=t.models.some(s=>{let c=!r||s.provider===r,a=!n||s.name&&s.name===n;return c&&a}),i=[];return r&&i.push(`provider=${r}`),n&&i.push(`name=${n}`),{passed:o,checks:[{type:"model",requirement:i.join(",")||"model",satisfied:o}],noExplicitChecks:!1}}throw new Error("Unknown requirement node encountered during evaluation")}function ci(e){return e.filter(t=>!t.satisfied).map(t=>`${t.type} ${t.requirement} not met`)}function li(e,t){return e.some(r=>di(r.id,r.version,t))}function di(e,t,r){return e!==r.id?!1:r.version?t===r.version:!0}function ui(e){return xt(e)}function xt(e){let t=_(e);if(!t)return{id:""};let r=t.split("@");return{id:r[0],version:r.length>1?r.slice(1).join("@"):void 0}}function ht(e){return typeof e=="string"?e.trim().toLowerCase():""}function _(e){return typeof e!="string"?void 0:e.trim()||void 0}function Kr(e,t){return typeof e!="number"||!Number.isFinite(e)||e<0?t:Math.floor(e)}function re(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function He(e){if(!Array.isArray(e))return[];let t=[];for(let r of e){let n=mi(r);n&&t.push(n)}return t.sort((r,n)=>r.id.localeCompare(n.id))}function mi(e){if(!re(e))return;let t=_(e.id);if(t)try{return{id:t,name:_(e.name),description:_(e.description),requirements:ii(e.requirements)}}catch{return}}async function vt(e={}){return ri(e)}function Gr(e){process.stdout.write(`${e.join(`
204
325
  `)}
205
- `)}async function Tn(){let e=await F(),t=new Set,r=[];for(let n of e.repos)t.has(n.path)||(t.add(n.path),await P(n.path)&&r.push(n.path));return r}async function tr(e={}){let t=await Tn(),n=(await ve()).credentials;if(!n.length){if(e.outputMode==="json"){er(Qt({tracked:t,trackedCredentialsCount:0,proofFiles:0,provenCommits:0,provenRepositories:0,evaluated:[]}));return}process.stdout.write(`no credentials tracked
206
- `);return}let i=ir(await Je({refresh:e.refreshIndex})),o=0,s=[],c=new Set,a=new Set;for(let f of t){let x=await se(f);if(o+=x.length,!x.length)continue;let Y=await z(f)||f;c.add(Y);for(let B of x)B?.commit&&a.add(B.commit),s.push({proof:B})}let u=Array.from(a),l=Array.from(c),d=Qt({tracked:t,trackedCredentialsCount:n.length,proofFiles:o,provenCommits:u.length,provenRepositories:l.length,evaluated:[]}),m=[];for(let f of n){let x=i.get(f.id);if(!x){m.push(_n(f.id,s.length,u.length,l.length));continue}let Y=Xt(s,u,l,x.requirements);m.push(On(f.id,x,Y,s.length,u.length,l.length))}if(d.credentials=m,e.outputMode==="json"){er(d);return}let p=[];p.push(`tracked credentials: ${n.length}`),p.push(`tracked repositories: ${t.length}`),p.push(`proof files: ${o}`),p.push(`proof commits: ${u.length}`),p.push(`proof repositories: ${l.length}`),p.push("");for(let f of m){if(p.push(`${f.credentialId}: ${f.status}`),p.push(` checks: ${f.passed?"passed":"blocked"}`),p.push(` proof scope: ${f.proofFiles} proofs, ${f.provenCommits}/${f.requiredMinCommits} commits, ${f.provenRepositories}/${f.requiredMinRepositories} repositories`),f.reasons.length){p.push(" reasons:");for(let x of f.reasons)p.push(` - ${x}`)}p.push("")}Yt(p)}async function rr(e){let t=T(e,"credential id");if(!ir(await Je()).has(t))throw new Error(`credential not found in credential index: ${t}`);if(!await Pt(t)){process.stdout.write(`credential already tracked: ${t}
326
+ `)}async function pi(){let e=await K(),t=new Set,r=[];for(let n of e.repos)t.has(n.path)||(t.add(n.path),await R(n.path)&&r.push(n.path));return r}async function Xr(e={}){let t=await pi(),n=(await Ee()).credentials;if(!n.length){if(e.outputMode==="json"){Zr(Vr({tracked:t,trackedCredentialsCount:0,proofFiles:0,provenCommits:0,provenRepositories:0,evaluated:[]}));return}process.stdout.write(`no credentials tracked
327
+ `);return}let o=en(await vt({refresh:e.refreshIndex})),i=0,s=[],c=new Set,a=new Set;for(let g of t){let P=await me(g);if(i+=P.length,!P.length)continue;let oe=await V(g)||g;c.add(oe);for(let Y of P)Y?.commit&&a.add(Y.commit),s.push({proof:Y})}let d=Array.from(a),l=Array.from(c),u=Vr({tracked:t,trackedCredentialsCount:n.length,proofFiles:i,provenCommits:d.length,provenRepositories:l.length,evaluated:[]}),p=[];for(let g of n){let P=o.get(g.id);if(!P){p.push(fi(g.id,s.length,d.length,l.length));continue}let oe=Wr(s,d,l,P.requirements);p.push(gi(g.id,P,oe,s.length,d.length,l.length))}if(u.credentials=p,e.outputMode==="json"){Zr(u);return}let f=[];f.push(`tracked credentials: ${n.length}`),f.push(`tracked repositories: ${t.length}`),f.push(`proof files: ${i}`),f.push(`proof commits: ${d.length}`),f.push(`proof repositories: ${l.length}`),f.push("");for(let g of p){if(f.push(`${g.credentialId}: ${g.status}`),f.push(` checks: ${g.passed?"passed":"blocked"}`),f.push(` proof scope: ${g.proofFiles} proofs, ${g.provenCommits}/${g.requiredMinCommits} commits, ${g.provenRepositories}/${g.requiredMinRepositories} repositories`),g.reasons.length){f.push(" reasons:");for(let P of g.reasons)f.push(` - ${P}`)}f.push("")}Gr(f)}async function Yr(e){let t=O(e,"credential id");if(!en(await vt()).has(t))throw new Error(`credential not found in credential index: ${t}`);if(!await Bt(t)){process.stdout.write(`credential already tracked: ${t}
207
328
  `);return}process.stdout.write(`tracking credential: ${t}
208
- `)}async function nr(e){let t=T(e,"credential id");if(!await bt(t)){process.stdout.write(`credential not tracked: ${t}
329
+ `)}async function Qr(e){let t=O(e,"credential id");if(!await Jt(t)){process.stdout.write(`credential not tracked: ${t}
209
330
  `);return}process.stdout.write(`untracked credential: ${t}
210
- `)}function Qt(e){return{trackedCredentials:e.trackedCredentialsCount,trackedRepositories:e.tracked.length,evidence:{proofFiles:e.proofFiles,provenCommits:e.provenCommits,provenRepositories:e.provenRepositories},credentials:e.evaluated}}function er(e){process.stdout.write(`${JSON.stringify(e)}
211
- `)}function ir(e){return new Map(e.map(t=>[t.id,t]))}function _n(e,t,r,n){return{credentialId:e,passed:!1,status:"blocked",reasons:["credential definition is not available"],checks:[],requiredMinCommits:0,requiredMinRepositories:0,provenCommits:r,provenRepositories:n,proofFiles:t}}function On(e,t,r,n,i,o){return{credentialId:e,name:t.name,description:t.description,passed:r.passed,status:r.passed?"eligible":"blocked",reasons:r.reasons,checks:r.checks,requiredMinCommits:t.requirements.minCommits,requiredMinRepositories:t.requirements.minRepositories,provenCommits:i,provenRepositories:o,proofFiles:n}}import Z from"path";import _ from"fs/promises";import{execFile as zn}from"child_process";import{promisify as Mn}from"util";import Dn from"ora";var Hn=Mn(zn);async function lr(e){let t=T(e,"skill id"),{owner:r,slug:n}=xe(t),i=process.cwd();if(!await P(i))throw new Error("Repository is not enabled");let o=await Promise.all([_.access(Z.join(i,"SKILL.md")).then(()=>!0).catch(()=>!1),_.access(Z.join(i,"skill.yaml")).then(()=>!0).catch(()=>!1)]);if(!o[0]||!o[1])throw new Error("SKILL.md and skill.yaml are required for publishing");let s=await j(),c=$(s.provider??"gh");await c.getUser();let a="skillcraft-gg/skills-registry",u=`skillcraft-skill-${r}-${n}`,l=Z.join(process.cwd(),".skillcraft-temp-skill-publish");try{await _.rm(l,{force:!0,recursive:!0}),await c.cloneRepo(a,l),await $e(l,["checkout","-B",u]);let d=Z.join(l,"skills",r,n);await _.rm(d,{force:!0,recursive:!0}),await _.mkdir(Z.dirname(d),{recursive:!0}),await _.cp(i,d,{recursive:!0}),await $e(l,["add",`skills/${r}/${n}`]),await $e(l,["commit","-m",`Publish skill ${t}`]).catch(()=>{throw new Error("nothing to commit; skill may already be published")}),await $e(l,["push","-u","origin",u]).catch(()=>{throw new Error("unable to push skill publish branch")}),await c.createPullRequest(a,u,`Publish skill: ${t}`).catch(()=>{process.stdout.write(`unable to create PR automatically. Please open one manually from your branch.
331
+ `)}function Vr(e){return{trackedCredentials:e.trackedCredentialsCount,trackedRepositories:e.tracked.length,evidence:{proofFiles:e.proofFiles,provenCommits:e.provenCommits,provenRepositories:e.provenRepositories},credentials:e.evaluated}}function Zr(e){process.stdout.write(`${JSON.stringify(e)}
332
+ `)}function en(e){return new Map(e.map(t=>[t.id,t]))}function fi(e,t,r,n){return{credentialId:e,passed:!1,status:"blocked",reasons:["credential definition is not available"],checks:[],requiredMinCommits:0,requiredMinRepositories:0,provenCommits:r,provenRepositories:n,proofFiles:t}}function gi(e,t,r,n,o,i){return{credentialId:e,name:t.name,description:t.description,passed:r.passed,status:r.passed?"eligible":"blocked",reasons:r.reasons,checks:r.checks,requiredMinCommits:t.requirements.minCommits,requiredMinRepositories:t.requirements.minRepositories,provenCommits:o,provenRepositories:i,proofFiles:n}}import b from"path";import A from"fs/promises";import hi from"os";import{execFile as wi}from"child_process";import{promisify as yi}from"util";import ki from"ora";var xi=yi(wi);async function sn(e){let t=O(e,"skill id"),{owner:r,slug:n}=je(t),o=process.cwd();if(!await R(o))throw new Error("Repository is not enabled");let i=await Promise.all([A.access(b.join(o,"SKILL.md")).then(()=>!0).catch(()=>!1),A.access(b.join(o,"skill.yaml")).then(()=>!0).catch(()=>!1)]);if(!i[0]||!i[1])throw new Error("SKILL.md and skill.yaml are required for publishing");let s=await F(),c=L(s.provider??"gh");await c.getUser();let a="skillcraft-gg/skills-registry",d=`skillcraft-skill-${r}-${n}`,l=b.join(process.cwd(),".skillcraft-temp-skill-publish");try{await A.rm(l,{force:!0,recursive:!0}),await c.cloneRepo(a,l),await ve(l,["checkout","-B",d]);let u=b.join(l,"skills",r,n);await A.rm(u,{force:!0,recursive:!0}),await A.mkdir(b.dirname(u),{recursive:!0}),await A.cp(o,u,{recursive:!0}),await ve(l,["add",`skills/${r}/${n}`]),await ve(l,["commit","-m",`Publish skill ${t}`]).catch(()=>{throw new Error("nothing to commit; skill may already be published")}),await ve(l,["push","-u","origin",d]).catch(()=>{throw new Error("unable to push skill publish branch")}),await c.createPullRequest(a,d,`Publish skill: ${t}`).catch(()=>{process.stdout.write(`unable to create PR automatically. Please open one manually from your branch.
212
333
  `)}),process.stdout.write(`published skill ${t} from ${a}
213
- `)}finally{await _.rm(l,{force:!0,recursive:!0})}}async function ur(e){let t=process.cwd();if(!await P(t))throw new Error("Repository is not enabled");let r=T(e,"skill id"),n=H(r);if(!n.id)throw new Error("invalid skill id format");if(!(await Zn()).has(n.id))throw new Error(`skill ${n.id} is not listed in the search index`);let o=Re([`${n.id}${n.version?`@${n.version}`:""}`]),s=await oe(t),c=Re([...s,...o]);await y(L(t),{skills:c}),process.stdout.write(`queued skill: ${o[0]}
214
- `)}async function Kn(){let e=process.cwd(),t=[["SKILL.md",await dr(Z.join(e,"SKILL.md"))],["skill.yaml",await dr(Z.join(e,"skill.yaml"))]];for(let[r,n]of t)process.stdout.write(`${r}: ${n?"ok":"missing"}
215
- `)}async function mr(){let e=process.cwd();if(!await P(e))throw new Error("Repository is not enabled");let[t,r]=await Promise.all([se(e),oe(e)]),n=new Set;for(let o of t)for(let s of o.skills)n.add(s.id);for(let o of r)n.add(o);if(!n.size){process.stdout.write(`no skills detected
216
- `);return}let i=Array.from(n).sort().join(`
217
- `);process.stdout.write(`skills detected (${n.size}):
334
+ `)}finally{await A.rm(l,{force:!0,recursive:!0})}}async function an(e){let t=process.cwd();if(!await R(t))throw new Error("Repository is not enabled");let r=O(e,"skill id"),n=G(r);if(!n.id)throw new Error("invalid skill id format");if(n.version)throw new Error("skill versions are not supported for installation yet");let i=(await bt("text")).find(l=>l.id===n.id);if(!i)throw new Error(`skill ${n.id} is not listed in the search index`);let s=un(i),c=Gt(i.id),a=b.join(Re(t),c);if(await be(a))throw new Error(`skill ${i.id} is already installed at ${b.posix.join(".agents","skills",c)}`);let d=await A.mkdtemp(b.join(hi.tmpdir(),"skillcraft-skill-"));try{let l=await Ii(i,d);await v(Re(t)),await A.cp(l,a,{recursive:!0}),await Ei(b.join(a,"SKILL.md"),c),await Wt(t,Vt({id:i.id,name:c,install:s,installedAt:new Date().toISOString()}))}finally{await A.rm(d,{force:!0,recursive:!0})}process.stdout.write(`installed skill: ${i.id} -> ${b.posix.join(".agents","skills",c)}
335
+ `)}async function vi(){let e=process.cwd(),t=[["SKILL.md",await be(b.join(e,"SKILL.md"))],["skill.yaml",await be(b.join(e,"skill.yaml"))]];for(let[r,n]of t)process.stdout.write(`${r}: ${n?"ok":"missing"}
336
+ `)}async function cn(){let e=process.cwd();if(!await R(e))throw new Error("Repository is not enabled");let[t,r,n]=await Promise.all([me(e),ke(e),he(e)]),o=new Set;for(let s of t)for(let c of s.skills)o.add(c.id);for(let s of r)o.add(s);for(let s of n)o.add(s.id);if(!o.size){process.stdout.write(`no skills detected
337
+ `);return}let i=Array.from(o).sort().join(`
338
+ `);process.stdout.write(`skills detected (${o.size}):
218
339
  ${i}
219
- `)}async function pr(e,t={}){let r=await Ge(t.outputMode);if(!r.length){t.outputMode==="json"?process.stdout.write(`${JSON.stringify({query:e?.trim(),source:t.source?.trim(),limit:cr(t.limit),count:0,results:[],message:"no skills indexed"})}
340
+ `)}async function ln(e,t={}){let r=await bt(t.outputMode);if(!r.length){t.outputMode==="json"?process.stdout.write(`${JSON.stringify({query:e?.trim(),source:t.source?.trim(),limit:on(t.limit),count:0,results:[],message:"no skills indexed"})}
220
341
  `):process.stdout.write(`no skills indexed
221
- `);return}let n=e?.trim().toLowerCase(),i=t.source?.trim().toLowerCase(),o=cr(t.limit),c=[...r.filter(d=>i&&Ve(d.id)!==i?!1:n?[d.id,d.name,d.owner,d.slug,d.path,d.url,...d.runtime||[],...d.tags||[]].filter(p=>!!p).map(p=>p.toLowerCase()).some(p=>p.includes(n)):!0)].sort((d,m)=>{let p=(d.name||d.id).toLowerCase(),f=(m.name||m.id).toLowerCase();return p===f?d.id.localeCompare(m.id):p.localeCompare(f)}),a=c.slice(0,o);if(!a.length){let d=n?`no skills match "${e?.trim()}"`:"no skills match current filters";t.outputMode==="json"?process.stdout.write(`${JSON.stringify({query:e?.trim(),source:t.source?.trim(),limit:o,count:0,results:[],message:d})}
222
- `):process.stdout.write(`${d}
223
- `);return}let u=n?`skills matching "${e?.trim()}"`:"skills index",l=a.map(d=>{let m=(d.runtime||[]).length?` [${d.runtime.join(", ")}]`:"",p=(d.tags||[]).length?` {${d.tags.join(", ")}}`:"",f=ti(d.updatedAt),x=Qn(d);return`${d.id}${x?` \u2014 ${x}`:""}${m}${p}${f}`});if(t.outputMode==="json"){let d={query:e?.trim(),source:t.source?.trim(),limit:o,count:a.length,total:c.length,results:a.map(m=>({id:m.id,name:m.name,path:m.path,url:m.url,owner:m.owner,slug:m.slug,runtime:m.runtime,tags:m.tags}))};process.stdout.write(`${JSON.stringify(d)}
224
- `);return}process.stdout.write(`${u} (${a.length}):
342
+ `);return}let n=e?.trim().toLowerCase(),o=t.source?.trim().toLowerCase(),i=on(t.limit),c=[...r.filter(u=>o&&Pt(u.id)!==o?!1:n?[u.id,u.name,u.owner,u.slug,u.path,u.url,...u.runtime||[],...u.tags||[]].filter(f=>!!f).map(f=>f.toLowerCase()).some(f=>f.includes(n)):!0)].sort((u,p)=>{let f=(u.name||u.id).toLowerCase(),g=(p.name||p.id).toLowerCase();return f===g?u.id.localeCompare(p.id):f.localeCompare(g)}),a=c.slice(0,i);if(!a.length){let u=n?`no skills match "${e?.trim()}"`:"no skills match current filters";t.outputMode==="json"?process.stdout.write(`${JSON.stringify({query:e?.trim(),source:t.source?.trim(),limit:i,count:0,results:[],message:u})}
343
+ `):process.stdout.write(`${u}
344
+ `);return}let d=n?`skills matching "${e?.trim()}"`:"skills index",l=a.map(u=>{let p=(u.runtime||[]).length?` [${u.runtime.join(", ")}]`:"",f=(u.tags||[]).length?` {${u.tags.join(", ")}}`:"",g=qi(u.updatedAt),P=Ni(u);return`${u.id}${P?` \u2014 ${P}`:""}${p}${f}${g}`});if(t.outputMode==="json"){let u={query:e?.trim(),source:t.source?.trim(),limit:i,count:a.length,total:c.length,results:a.map(p=>({id:p.id,name:p.name,path:p.path,url:p.url,owner:p.owner,slug:p.slug,runtime:p.runtime,tags:p.tags}))};process.stdout.write(`${JSON.stringify(u)}
345
+ `);return}process.stdout.write(`${d} (${a.length}):
225
346
  ${l.join(`
226
347
  `)}
227
- `)}async function fr(e,t={}){let r=T(e,"skill id"),n=H(r);if(!n.id)throw new Error("invalid skill id format");let o=(await Ge(t.outputMode)).find(a=>a.id===n.id);if(!o)throw new Error(`skill ${n.id} is not listed in the search index`);let s=await Bn(o);if(t.outputMode==="json"){let a={id:o.id,name:o.name,source:Ve(o.id),owner:o.owner,slug:o.slug,path:o.path,url:o.url,runtime:o.runtime,tags:o.tags,updatedAt:o.updatedAt,manifest:s,version:n.version};process.stdout.write(`${JSON.stringify(a)}
228
- `);return}let c=Un(o,s);process.stdout.write(`${c}
229
- `)}function Un(e,t){let r=[];r.push(`skill: ${e.id}`),e.name&&r.push(`name: ${e.name}`);let n=Ve(e.id);return n&&r.push(`source: ${n}`),e.owner&&r.push(`owner: ${e.owner}`),e.slug&&r.push(`slug: ${e.slug}`),e.runtime&&e.runtime.length&&r.push(`runtime: ${e.runtime.join(", ")}`),e.tags&&e.tags.length&&r.push(`tags: ${e.tags.join(", ")}`),e.updatedAt&&r.push(`updated: ${e.updatedAt}`),e.path&&r.push(`path: ${e.path}`),e.url&&r.push(`url: ${e.url}`),t&&(r.push(`manifest: ${t.url}`),t.title&&r.push(`manifest title: ${t.title}`),t.summary&&r.push(`manifest summary: ${t.summary}`),t.error&&r.push(`manifest fetch: ${t.error}`)),r.join(`
230
- `)}async function Bn(e){let t=Wn(e.url);if(!t)return;let r=new AbortController,n=setTimeout(()=>{r.abort()},5e3);try{let i=await fetch(t,{headers:{"user-agent":"skillcraft-cli"},signal:r.signal});if(!i.ok)return{url:t,error:`unable to fetch manifest (${i.status})`};let o=await i.text();if(Gn(o))return{url:t,error:"unable to parse manifest (not markdown)"};let s=Vn(o);return{url:t,title:s.title,summary:s.summary}}catch(i){return i instanceof Error&&i.name==="AbortError"?{url:t,error:"manifest fetch timed out"}:{url:t,error:i instanceof Error?i.message:"failed to fetch manifest"}}finally{clearTimeout(n)}}function Wn(e){if(!e)return;let t=e.trim();if(!t)return;let r=t.endsWith("/SKILL.md")?t:t.endsWith("/")?`${t}SKILL.md`:`${t}/SKILL.md`;return Jn(r)}function Jn(e){try{let t=new URL(e);if(t.hostname!=="github.com")return e;let r=t.pathname.split("/").filter(Boolean),n=r.indexOf("blob");if(n!==2||r.length<n+2)return e;let i=r[0],o=r[1],s=r.slice(n+1);if(!i||!o||!s.length)return e;let c=[i,o,"raw","refs","heads",...s];return`${t.protocol}//${t.host}/${c.join("/")}`}catch{return e}}function Gn(e){let t=e.replace(/^\s+/,"").toLowerCase();return t.startsWith("<!doctype html")||t.startsWith("<html")}function Vn(e){let r=e.replace(/\r\n/g,`
348
+ `)}async function dn(e,t={}){let r=O(e,"skill id"),n=G(r);if(!n.id)throw new Error("invalid skill id format");let i=(await bt(t.outputMode)).find(a=>a.id===n.id);if(!i)throw new Error(`skill ${n.id} is not listed in the search index`);let s=await Pi(i);if(t.outputMode==="json"){let a={id:i.id,name:i.name,source:Pt(i.id),owner:i.owner,slug:i.slug,path:i.path,url:i.url,runtime:i.runtime,tags:i.tags,install:i.install,updatedAt:i.updatedAt,manifest:s,version:n.version};process.stdout.write(`${JSON.stringify(a)}
349
+ `);return}let c=bi(i,s);process.stdout.write(`${c}
350
+ `)}function bi(e,t){let r=[];r.push(`skill: ${e.id}`),e.name&&r.push(`name: ${e.name}`);let n=Pt(e.id);return n&&r.push(`source: ${n}`),e.owner&&r.push(`owner: ${e.owner}`),e.slug&&r.push(`slug: ${e.slug}`),e.runtime&&e.runtime.length&&r.push(`runtime: ${e.runtime.join(", ")}`),e.tags&&e.tags.length&&r.push(`tags: ${e.tags.join(", ")}`),e.updatedAt&&r.push(`updated: ${e.updatedAt}`),e.path&&r.push(`path: ${e.path}`),e.url&&r.push(`url: ${e.url}`),e.install?.type&&r.push(`install type: ${e.install.type}`),e.install?.repo&&r.push(`install repo: ${e.install.repo}`),e.install?.path&&r.push(`install path: ${e.install.path}`),t&&(r.push(`manifest: ${t.url}`),t.title&&r.push(`manifest title: ${t.title}`),t.summary&&r.push(`manifest summary: ${t.summary}`),t.error&&r.push(`manifest fetch: ${t.error}`)),r.join(`
351
+ `)}async function Pi(e){let t=Si(e.url);if(!t)return;let r=new AbortController,n=setTimeout(()=>{r.abort()},5e3);try{let o=await fetch(t,{headers:{"user-agent":"skillcraft-cli"},signal:r.signal});if(!o.ok)return{url:t,error:`unable to fetch manifest (${o.status})`};let i=await o.text();if(Ri(i))return{url:t,error:"unable to parse manifest (not markdown)"};let s=Ai(i);return{url:t,title:s.title,summary:s.summary}}catch(o){return o instanceof Error&&o.name==="AbortError"?{url:t,error:"manifest fetch timed out"}:{url:t,error:o instanceof Error?o.message:"failed to fetch manifest"}}finally{clearTimeout(n)}}function Si(e){if(!e)return;let t=e.trim();if(!t)return;let r=t.endsWith("/SKILL.md")?t:t.endsWith("/")?`${t}SKILL.md`:`${t}/SKILL.md`;return Ci(r)}function Ci(e){try{let t=new URL(e);if(t.hostname!=="github.com")return e;let r=t.pathname.split("/").filter(Boolean),n=r.indexOf("blob");if(n!==2||r.length<n+2)return e;let o=r[0],i=r[1],s=r.slice(n+1);if(!o||!i||!s.length)return e;let c=[o,i,"raw","refs","heads",...s];return`${t.protocol}//${t.host}/${c.join("/")}`}catch{return e}}function Ri(e){let t=e.replace(/^\s+/,"").toLowerCase();return t.startsWith("<!doctype html")||t.startsWith("<html")}function Ai(e){let r=e.replace(/\r\n/g,`
352
+ `).split(`
353
+ `),n=0;if((r[0]||"").trim()==="---"){for(n=1;n<r.length&&r[n].trim()!=="---";)n+=1;n<r.length&&r[n].trim()==="---"&&(n+=1)}let o,i;for(let s=n;s<r.length;s+=1){let c=r[s].trim();if(!c){if(i)break;continue}if(!o&&c.startsWith("#")){o=c.replace(/^#+\s*/,"").trim();continue}if(!i&&!c.startsWith(">")){i=c;break}}return{title:o,summary:i}}function un(e){let t=e.install;if(!t?.type||!t.path)throw new Error(`skill ${e.id} does not include install metadata in the search index`);if(t.type==="github-directory"&&(!t.repo||!t.ref))throw new Error(`skill ${e.id} has incomplete github install metadata`);return{type:t.type,...t.repo?{repo:t.repo}:{},...t.ref?{ref:t.ref}:{},path:t.path}}async function Ii(e,t){let r=un(e);if(r.type==="local-directory"){let i=$i(r.path);if(!await be(i))throw new Error(`local skill source does not exist: ${i}`);return i}let n=b.join(t,"source");await ve(t,["clone","--depth","1","--branch",r.ref,`https://github.com/${r.repo}.git`,n]);let o=b.join(n,r.path);if(!await be(o))throw new Error(`skill source path does not exist in ${r.repo}@${r.ref}: ${r.path}`);return o}function $i(e){if(b.isAbsolute(e))return e;let t=process.env.SKILLCRAFT_SEARCH_INDEX_PATH?.trim();return t?b.resolve(b.dirname(t),e):b.resolve(e)}async function Ei(e,t){let o=(await A.readFile(e,"utf8").catch(()=>{throw new Error(`installed skill is missing SKILL.md: ${e}`)})).replace(/\r\n/g,`
231
354
  `).split(`
232
- `),n=0;if((r[0]||"").trim()==="---"){for(n=1;n<r.length&&r[n].trim()!=="---";)n+=1;n<r.length&&r[n].trim()==="---"&&(n+=1)}let i,o;for(let s=n;s<r.length;s+=1){let c=r[s].trim();if(!c){if(o)break;continue}if(!i&&c.startsWith("#")){i=c.replace(/^#+\s*/,"").trim();continue}if(!o&&!c.startsWith(">")){o=c;break}}return{title:i,summary:o}}function or(e){return Array.isArray(e)}async function Zn(){let e=await Ge();return new Set(e.map(t=>t.id))}async function Ge(e=void 0){let t=process.env.SKILLCRAFT_SEARCH_INDEX_PATH?.trim(),r=t||process.env.SKILLCRAFT_SEARCH_INDEX_URL||"https://skillcraft.gg/skills-registry/search/index.json",n=async()=>{if(t){let u=await _.readFile(t,"utf8"),l=JSON.parse(u);return sr(or(l)?l:[])}let s=process.env.SKILLCRAFT_SEARCH_INDEX_URL||"https://skillcraft.gg/skills-registry/search/index.json",c=await fetch(s,{headers:{"user-agent":"skillcraft-cli"}});if(!c.ok)throw new Error(`failed to download search index from ${s}`);let a=await c.json();return sr(or(a)?a:[])};if(!Xn(e))return n();let i=t?`reading local index from ${r}`:`downloading index from ${r}`,o=Dn({text:`Loading ${i}...`}).start();try{let s=await n();return o.succeed(`loaded ${s.length} indexed entries`),s}catch(s){throw o.fail("failed to load search index"),s}}function Xn(e){return e!=="text"?!1:process.stdout.isTTY===!0||process.stderr.isTTY===!0}function sr(e){return e.map(t=>Yn(t)).filter(t=>!!t)}function Yn(e){let t=gr(e.id),r=Ct(t);if(r)return{id:r,name:ce(e.name),path:ce(e.path),url:ce(e.url),owner:ce(e.owner),slug:ce(e.slug),runtime:ar(e.runtime),tags:ar(e.tags),updatedAt:ce(e.updatedAt)}}function gr(e){return String(e||"").trim()}function ce(e){return gr(e)||void 0}function ar(e){if(e===void 0)return[];if(typeof e=="string")return e.split(",").map(r=>r.trim()).filter(Boolean);if(!Array.isArray(e))return[];let t=[];for(let r of e){if(typeof r!="string")continue;let n=r.trim();n&&t.push(n)}return t}function Ve(e){let t=e.indexOf(":");if(t<1)return;let r=e.slice(0,t).trim();if(r)return r.toLowerCase()}function cr(e){let t=e===void 0?20:Math.floor(e);return Number.isFinite(t)&&t>0?t:20}function Qn(e){let t=(e.name||"").trim();if(!t)return"";let r=ei(e);return r&&t.toLowerCase()===r.toLowerCase()?"":t}function ei(e){if(e.slug&&e.slug.trim())return e.slug.trim();let t=e.id.trim(),r=t.indexOf(":"),n=r>=0?t.slice(r+1):t,i=n.split("/").filter(Boolean);return i.length?i[i.length-1]:n}function ti(e){if(!e)return"";let t=new Date(e);return Number.isNaN(t.getTime())?"":` (updated ${t.toISOString().slice(0,10)})`}async function dr(e){try{return await _.access(e),!0}catch{return!1}}async function $e(e,t){let{stdout:r}=await Hn("git",t,{cwd:e});return r.trim()}async function hr(){await Kn()}import{mkdtemp as ri,rm as ni}from"fs/promises";import ii from"os";import oi from"path";function si(e){let t=e.trim();if(t&&!(/^[a-zA-Z]:[\\/]/.test(t)||t.startsWith("/")||t.startsWith("./")||t.startsWith("../"))&&(/^[a-z][a-z0-9+.-]*:/.test(t)||t.startsWith("git@")||t.startsWith("ssh://")||t.startsWith("http://")||t.startsWith("https://")||t.startsWith("file://")))return t}async function wr(e){try{return(await h(["config","--get-regexp","^remote..*.url$"],e)).split(`
233
- `).map(r=>r.trim()).filter(Boolean).map(r=>{let n=r.indexOf(" ");if(n===-1)return;let i=r.slice(0,n),o=r.slice(n+1).trim(),s=i.slice(7,-4);if(!(!o||!s))return{name:s,url:o}}).filter(r=>!!r)}catch{return[]}}async function yr(e){return Ze(e,{normalize:!0})}async function Ze(e,t={}){let r=t.normalize??!0,n=[];for(let i of e){let o=r?si(i.repo):i.repo;if(!o){for(let a of i.commits)n.push({repo:i.repo,commit:a});continue}let s=Array.from(new Set(i.commits.map(a=>a.trim()).filter(Boolean)));if(!s.length)continue;let c=await ai(o,s);for(let a of c)n.push({repo:o,commit:a})}return n}async function ai(e,t){let r=Array.from(new Set(t.map(i=>i.trim()).filter(Boolean)));if(!r.length)return[];let n=await ri(oi.join(ii.tmpdir(),"skillcraft-remote-check-"));try{try{await h(["clone","--quiet","--no-checkout",e,n],process.cwd())}catch{return r}let i=[];for(let o of r)await ci(n,o)||i.push(o);return i}finally{await ni(n,{recursive:!0,force:!0})}}async function ci(e,t){try{await h(["cat-file","-e",`${t}^{commit}`],e)}catch{return!1}try{return!!await h(["branch","-r","--contains",t],e)}catch{return!1}}async function kr(){let e=process.cwd();if(!await P(e))throw new Error("Repository is not enabled");let r=(await fe(e,200)).map(l=>l.message.match(/Skillcraft-Ref:\s*(\S+)/)?.[1]).filter(Boolean),n=0,i=[];for(let l of r){let d=await Oe(e,l);if(!d){n+=1,process.stdout.write(`missing proof object: ${l}
234
- `);continue}if(!d.commit||!d.timestamp){n+=1,process.stdout.write(`invalid proof object: ${l}
235
- `);continue}i.push(d.commit)}if(n>0){process.stdout.write(`verify failed: ${n} missing/invalid proofs
355
+ `);if((o[0]||"").trim()!=="---")throw new Error(`skill manifest is missing YAML frontmatter: ${e}`);let i=-1;for(let d=1;d<o.length;d+=1)if(o[d].trim()==="---"){i=d;break}if(i===-1)throw new Error(`skill manifest frontmatter is not closed: ${e}`);let s=!1,c=o.slice(1,i).map(d=>/^\s*name\s*:/.test(d)?(s=!0,`name: ${t}`):d);s||c.unshift(`name: ${t}`);let a=["---",...c,"---",...o.slice(i+1)].join(`
356
+ `);await A.writeFile(e,a.endsWith(`
357
+ `)?a:`${a}
358
+ `,"utf8")}function tn(e){return Array.isArray(e)}async function bt(e=void 0){let t=process.env.SKILLCRAFT_SEARCH_INDEX_PATH?.trim(),r=t||process.env.SKILLCRAFT_SEARCH_INDEX_URL||"https://skillcraft.gg/skills-registry/search/index.json",n=async()=>{if(t){let d=await A.readFile(t,"utf8"),l=JSON.parse(d);return rn(tn(l)?l:[])}let s=process.env.SKILLCRAFT_SEARCH_INDEX_URL||"https://skillcraft.gg/skills-registry/search/index.json",c=await fetch(s,{headers:{"user-agent":"skillcraft-cli"}});if(!c.ok)throw new Error(`failed to download search index from ${s}`);let a=await c.json();return rn(tn(a)?a:[])};if(!ji(e))return n();let o=t?`reading local index from ${r}`:`downloading index from ${r}`,i=ki({text:`Loading ${o}...`}).start();try{let s=await n();return i.succeed(`loaded ${s.length} indexed entries`),s}catch(s){throw i.fail("failed to load search index"),s}}function ji(e){return e!=="text"?!1:process.stdout.isTTY===!0||process.stderr.isTTY===!0}function rn(e){return e.map(t=>Li(t)).filter(t=>!!t)}function Li(e){let t=mn(e.id),r=ae(t);if(r)return{id:r,name:D(e.name),path:D(e.path),url:D(e.url),owner:D(e.owner),slug:D(e.slug),runtime:nn(e.runtime),tags:nn(e.tags),install:_i(e.install),updatedAt:D(e.updatedAt)}}function _i(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,r=D(t.type),n=D(t.path);if(!(!r||!n)&&!(r!=="github-directory"&&r!=="local-directory"))return{type:r,repo:D(t.repo),ref:D(t.ref),path:n}}function mn(e){return String(e||"").trim()}function D(e){return mn(e)||void 0}function nn(e){if(e===void 0)return[];if(typeof e=="string")return e.split(",").map(r=>r.trim()).filter(Boolean);if(!Array.isArray(e))return[];let t=[];for(let r of e){if(typeof r!="string")continue;let n=r.trim();n&&t.push(n)}return t}function Pt(e){let t=e.indexOf(":");if(t<1)return;let r=e.slice(0,t).trim();if(r)return r.toLowerCase()}function on(e){let t=e===void 0?20:Math.floor(e);return Number.isFinite(t)&&t>0?t:20}function Ni(e){let t=(e.name||"").trim();if(!t)return"";let r=Ti(e);return r&&t.toLowerCase()===r.toLowerCase()?"":t}function Ti(e){if(e.slug&&e.slug.trim())return e.slug.trim();let t=e.id.trim(),r=t.indexOf(":"),n=r>=0?t.slice(r+1):t,o=n.split("/").filter(Boolean);return o.length?o[o.length-1]:n}function qi(e){if(!e)return"";let t=new Date(e);return Number.isNaN(t.getTime())?"":` (updated ${t.toISOString().slice(0,10)})`}async function be(e){try{return await A.access(e),!0}catch{return!1}}async function pn(e,t=process.cwd()){let r=ae(O(e,"skill id"));if(!r)throw new Error("invalid skill id format");await Le(t,r)}async function ve(e,t){let{stdout:r}=await xi("git",t,{cwd:e});return r.trim()}async function fn(){await vi()}import{mkdtemp as Fi,rm as Oi}from"fs/promises";import Mi from"os";import zi from"path";function Di(e){let t=e.trim();if(t&&!(/^[a-zA-Z]:[\\/]/.test(t)||t.startsWith("/")||t.startsWith("./")||t.startsWith("../"))&&(/^[a-z][a-z0-9+.-]*:/.test(t)||t.startsWith("git@")||t.startsWith("ssh://")||t.startsWith("http://")||t.startsWith("https://")||t.startsWith("file://")))return t}async function gn(e){try{return(await y(["config","--get-regexp","^remote..*.url$"],e)).split(`
359
+ `).map(r=>r.trim()).filter(Boolean).map(r=>{let n=r.indexOf(" ");if(n===-1)return;let o=r.slice(0,n),i=r.slice(n+1).trim(),s=o.slice(7,-4);if(!(!i||!s))return{name:s,url:i}}).filter(r=>!!r)}catch{return[]}}async function hn(e){return St(e,{normalize:!0})}async function St(e,t={}){let r=t.normalize??!0,n=[];for(let o of e){let i=r?Di(o.repo):o.repo;if(!i){for(let a of o.commits)n.push({repo:o.repo,commit:a});continue}let s=Array.from(new Set(o.commits.map(a=>a.trim()).filter(Boolean)));if(!s.length)continue;let c=await Hi(i,s);for(let a of c)n.push({repo:i,commit:a})}return n}async function Hi(e,t){let r=Array.from(new Set(t.map(o=>o.trim()).filter(Boolean)));if(!r.length)return[];let n=await Fi(zi.join(Mi.tmpdir(),"skillcraft-remote-check-"));try{try{await y(["clone","--quiet","--no-checkout",e,n],process.cwd())}catch{return r}let o=[];for(let i of r)await Ui(n,i)||o.push(i);return o}finally{await Oi(n,{recursive:!0,force:!0})}}async function Ui(e,t){try{await y(["cat-file","-e",`${t}^{commit}`],e)}catch{return!1}try{return!!await y(["branch","-r","--contains",t],e)}catch{return!1}}async function wn(){let e=process.cwd();if(!await R(e))throw new Error("Repository is not enabled");let r=(await Oe(e,200)).map(l=>l.message.match(/Skillcraft-Ref:\s*(\S+)/)?.[1]).filter(Boolean),n=0,o=[];for(let l of r){let u=await mt(e,l);if(!u){n+=1,process.stdout.write(`missing proof object: ${l}
360
+ `);continue}if(!u.commit||!u.timestamp){n+=1,process.stdout.write(`invalid proof object: ${l}
361
+ `);continue}o.push(u.commit)}if(n>0){process.stdout.write(`verify failed: ${n} missing/invalid proofs
236
362
  `),process.exitCode=1;return}process.stdout.write(`verify passed: ${r.length} commit proofs resolved
237
- `);let o=await wr(e);if(!o.length){process.stdout.write(`\u26A0\uFE0F Warning: no git remotes configured for repository
238
- `);return}let s=o.map(l=>({repo:l.url,commits:i})),c=await Ze(s,{normalize:!1}),a=new Map;for(let{repo:l,commit:d}of c){let m=a.get(l);m?m.push(d):a.set(l,[d])}let u=l=>{let d=a.get(l);return d?Array.from(new Set(d)):[]};for(let l of o){let d=u(l.url);d.length>0?process.stdout.write(`\u26A0\uFE0F Warning: proof commits not pushed to ${l.url}: ${d.join(", ")}
363
+ `);let i=await gn(e);if(!i.length){process.stdout.write(`\u26A0\uFE0F Warning: no git remotes configured for repository
364
+ `);return}let s=i.map(l=>({repo:l.url,commits:o})),c=await St(s,{normalize:!1}),a=new Map;for(let{repo:l,commit:u}of c){let p=a.get(l);p?p.push(u):a.set(l,[u])}let d=l=>{let u=a.get(l);return u?Array.from(new Set(u)):[]};for(let l of i){let u=d(l.url);u.length>0?process.stdout.write(`\u26A0\uFE0F Warning: proof commits not pushed to ${l.url}: ${u.join(", ")}
239
365
  `):process.stdout.write(`remote status: ${l.url} (all referenced proof commits present)
240
- `)}}import{createHash as di}from"crypto";import vr from"yaml";async function Xe(){let e=await j(),t=$(e.provider??"gh"),r=await Ye(t,e.githubUser),i=(await t.listClaimIssues("skillcraft-gg/credential-ledger")).filter(o=>{let s=Ee(o.body);return s?.claimant===S(r)&&!!s?.credential});if(!i.length){process.stdout.write(`no claims found for ${r||"user"}
241
- `);return}for(let o of i)process.stdout.write(`#${o.number} ${o.title} (${Qe(o.labels?.map(s=>s?.name)||[])})
242
- `)}async function xr(e){let t=S(e);if(!t)throw new Error("claim status requires a credential identifier");let r=await j(),n=$(r.provider??"gh"),i=await Ye(n,r.githubUser),o=await li(n,t,i);if(!o)throw new Error(`No claim found for credential ${t} for user ${i||"unknown"}. Run "skillcraft claim" to see your claims.`);let s=await n.getIssueStatus("skillcraft-gg/credential-ledger",o),c=await n.listClaimProcessingRuns("skillcraft-gg/credential-ledger",o);if(process.stdout.write(`issue #${o}
243
- `),process.stdout.write(`state: ${Qe(s.labels)}
366
+ `)}}import{createHash as Ki}from"crypto";import yn from"yaml";async function Ct(){let e=await F(),t=L(e.provider??"gh"),r=await Rt(t,e.githubUser),o=(await t.listClaimIssues("skillcraft-gg/credential-ledger")).filter(i=>{let s=Ue(i.body);return s?.claimant===E(r)&&!!s?.credential});if(!o.length){process.stdout.write(`no claims found for ${r||"user"}
367
+ `);return}for(let i of o)process.stdout.write(`#${i.number} ${i.title} (${At(i.labels?.map(s=>s?.name)||[])})
368
+ `)}async function kn(e){let t=E(e);if(!t)throw new Error("claim status requires a credential identifier");let r=await F(),n=L(r.provider??"gh"),o=await Rt(n,r.githubUser),i=await Bi(n,t,o);if(!i)throw new Error(`No claim found for credential ${t} for user ${o||"unknown"}. Run "skillcraft claim" to see your claims.`);let s=await n.getIssueStatus("skillcraft-gg/credential-ledger",i),c=await n.listClaimProcessingRuns("skillcraft-gg/credential-ledger",i);if(process.stdout.write(`issue #${i}
369
+ `),process.stdout.write(`state: ${At(s.labels)}
244
370
  `),process.stdout.write(`labels: ${s.labels.join(", ")||"none"}
245
371
  `),process.stdout.write(`url: ${s.url}
246
372
  `),!c.length){process.stdout.write(`processing actions: none found
247
- `);return}let a=c[0],u=a.conclusion?` (${a.conclusion})`:"";process.stdout.write(`processing actions: ${a.status}${u}
373
+ `);return}let a=c[0],d=a.conclusion?` (${a.conclusion})`:"";process.stdout.write(`processing actions: ${a.status}${d}
248
374
  `),process.stdout.write(`latest run: ${a.url}
249
375
  `),c.length>1&&process.stdout.write(`previous attempts: ${c.length-1}
250
- `)}async function li(e,t,r){let n=await e.listClaimIssues("skillcraft-gg/credential-ledger"),i=S(t),o=S(r);return n.map(c=>{let a=Ee(c.body);if(!(!a||a.claimant!==o||a.credential!==i))return c.number}).filter(c=>!!c).sort((c,a)=>a-c)[0]}async function ui(e,t,r){let n=await e.listClaimIssues("skillcraft-gg/credential-ledger"),i=S(t),o=S(r);return n.filter(c=>{if(S(c.state)!=="open")return!1;let a=Ee(c.body);return!!a&&a.claimant===o&&a.credential===i}).sort((c,a)=>c.number-a.number)[0]}async function Pr(e,t){let r=await j(),n=$(r.provider??"gh"),i=await Ye(n,r.githubUser),o=await fi(e,{allRepos:t?.allRepos,repo:t?.repo},i),s=S(e),c=S(i),a=await yr(o.sources);if(a.length>0){process.stdout.write(`\u26A0\uFE0F Warning: some claim commits may not be pushed yet. Please push recent commits before re-submitting the claim.
251
- `);for(let d of a)process.stdout.write(`- ${d.commit} in ${d.repo}
252
- `);process.exitCode=1;return}if(s&&c){let d=await ui(n,s,c);if(d){let m=d.url||await n.getIssueUrl("skillcraft-gg/credential-ledger",d.number);process.stdout.write(`claim already submitted
253
- `),process.stdout.write(`issue: #${d.number}
254
- `),process.stdout.write(`state: ${Qe(d.labels?.map(p=>p?.name)||[])}
255
- `),process.stdout.write(`url: ${m}
256
- `);return}await mi(n,s,c)}let u=vr.stringify(o),l=await n.createIssue("skillcraft-gg/credential-ledger",`claim: ${e}`,u);process.stdout.write(`opened claim: #${l}
376
+ `)}async function Bi(e,t,r){let n=await e.listClaimIssues("skillcraft-gg/credential-ledger"),o=E(t),i=E(r);return n.map(c=>{let a=Ue(c.body);if(!(!a||a.claimant!==i||a.credential!==o))return c.number}).filter(c=>!!c).sort((c,a)=>a-c)[0]}async function Ji(e,t,r){let n=await e.listClaimIssues("skillcraft-gg/credential-ledger"),o=E(t),i=E(r);return n.filter(c=>{if(E(c.state)!=="open")return!1;let a=Ue(c.body);return!!a&&a.claimant===i&&a.credential===o}).sort((c,a)=>c.number-a.number)[0]}async function xn(e,t){let r=await F(),n=L(r.provider??"gh"),o=await Rt(n,r.githubUser),i=await Vi(e,{allRepos:t?.allRepos,repo:t?.repo},o),s=E(e),c=E(o),a=await hn(i.sources);if(a.length>0){process.stdout.write(`\u26A0\uFE0F Warning: some claim commits may not be pushed yet. Please push recent commits before re-submitting the claim.
377
+ `);for(let u of a)process.stdout.write(`- ${u.commit} in ${u.repo}
378
+ `);process.exitCode=1;return}if(s&&c){let u=await Ji(n,s,c);if(u){let p=u.url||await n.getIssueUrl("skillcraft-gg/credential-ledger",u.number);process.stdout.write(`claim already submitted
379
+ `),process.stdout.write(`issue: #${u.number}
380
+ `),process.stdout.write(`state: ${At(u.labels?.map(f=>f?.name)||[])}
381
+ `),process.stdout.write(`url: ${p}
382
+ `);return}await Wi(n,s,c)}let d=yn.stringify(i),l=await n.createIssue("skillcraft-gg/credential-ledger",`claim: ${e}`,d);process.stdout.write(`opened claim: #${l}
257
383
  `),process.stdout.write(`payload:
258
- ${u}
259
- `)}async function Ye(e,t){let r=process.env.GITHUB_USER||process.env.USER||"";try{let n=await e.getUser();if(n)return n}catch{}return t||r||"unknown"}function S(e){return(e||"").trim().toLowerCase()}async function mi(e,t,r){let i=(await e.listClaimIssues("skillcraft-gg/credential-ledger")).find(s=>{if(!pi(s,"skillcraft-issued"))return!1;let c=Ee(s.body);return c?c.credential===t&&c.claimant===r:!1});if(!i)return;let o=i.url?` (${i.url})`:"";throw new Error(`You already have an issued claim for ${t}. Existing issue: #${i.number}${o}`)}function Ee(e){if(e)try{let t=String(e).replace(/\\n/g,`
260
- `),r=vr.parse(t);if(!r||typeof r!="object")return;let n=r.credential&&typeof r.credential=="string"?r.credential:r.credential?.id,i=r.claimant?.github,o=S(n),s=S(i);return!o||!s?void 0:{credential:o,claimant:s}}catch{return}}function pi(e,t){let r=t.toLowerCase();return(e.labels||[]).some(n=>S(n?.name)===r)}function Qe(e){let t=new Set((e||[]).map(r=>S(r)));return t.has("skillcraft-issued")?"issued":t.has("skillcraft-rejected")?"rejected":t.has("skillcraft-verified")?"verified":t.has("skillcraft-processing")?"processing":"pending"}async function fi(e,t,r="unknown"){let n=await gi(t),i=[];for(let a of n){let u=await se(a),l=await z(a)||a,d=await Promise.all(u.map(async p=>await at(a,p.commit)?p:void 0)),m=Array.from(new Set(d.map(p=>p?.commit).filter(Boolean)));i.push({repo:l,commits:m})}let o=r,s=`${o}:${e}:${i.map(a=>`${a.repo}:${a.commits.length}`).join("|")}:${Date.now()}`,c=di("sha256").update(s).digest("hex").slice(0,8);return{claim_version:1,claimant:{github:o},credential:{id:e},sources:i,claim_id:`sha256:${c}`}}async function gi(e){let t=e.allRepos?(await F()).repos.map(i=>i.path):[process.cwd()],r=e.repo?e.repo:t,n=[];for(let i of r)await _t(i)&&n.push(i);return n}import pe from"path";import X from"fs/promises";import{execFile as hi}from"child_process";import{promisify as wi}from"util";var yi=wi(hi);async function br(e){if(!Ne(e))throw new Error("loadout id must be <owner>/<slug>");let t=process.cwd();if(!await P(t))throw new Error("Repository is not enabled");let r=await v(R(t)),n=Array.isArray(r?.activeLoadouts)?r.activeLoadouts.filter(Boolean):[];n.includes(e)||n.push(e),await y(R(t),{activeLoadouts:n}),process.stdout.write(`activated loadout: ${e}
261
- `)}async function Rr(){let e=process.cwd();if(!await P(e))throw new Error("Repository is not enabled");await y(R(e),{activeLoadouts:[]}),process.stdout.write(`cleared active loadouts
262
- `)}async function Cr(e){let t=T(e,"loadout id");if(!Ne(t))throw new Error("loadout id must be <owner>/<slug>");let{owner:r,slug:n}=xe(t),i=process.cwd(),o=pe.join(i,"loadout.yaml");if(await X.access(o),!(await X.stat(o)).isFile())throw new Error("loadout.yaml not found in current directory");let c=await j(),a=$(c.provider??"gh"),u="skillcraft-gg/loadouts",l=pe.join(process.cwd(),".skillcraft-temp-loadout-share"),d=`skillcraft-loadout-${r}-${n}`;try{await X.rm(l,{force:!0,recursive:!0}),await a.cloneRepo(u,l),await Ie(l,["checkout","-B",d]);let m=pe.join(l,"loadouts",r,n);await X.rm(m,{force:!0,recursive:!0}).catch(()=>{}),await X.mkdir(pe.dirname(m),{recursive:!0}),await X.copyFile(o,pe.join(m,"loadout.yaml")),await Ie(l,["add",m]),await Ie(l,["commit","-m",`Loadout: publish ${t}`]).catch(async()=>{throw new Error("nothing to commit; loadout may already be published")}),await Ie(l,["push","-u","origin",d]).catch(()=>{throw new Error("unable to push loadout publish branch")}),await a.createPullRequest(u,d,`Loadout publish: ${t}`).catch(()=>{process.stdout.write(`unable to create PR automatically. Please open one manually from your branch.
384
+ ${d}
385
+ `)}async function Rt(e,t){let r=process.env.GITHUB_USER||process.env.USER||"";try{let n=await e.getUser();if(n)return n}catch{}return t||r||"unknown"}function E(e){return(e||"").trim().toLowerCase()}async function Wi(e,t,r){let o=(await e.listClaimIssues("skillcraft-gg/credential-ledger")).find(s=>{if(!Gi(s,"skillcraft-issued"))return!1;let c=Ue(s.body);return c?c.credential===t&&c.claimant===r:!1});if(!o)return;let i=o.url?` (${o.url})`:"";throw new Error(`You already have an issued claim for ${t}. Existing issue: #${o.number}${i}`)}function Ue(e){if(e)try{let t=String(e).replace(/\\n/g,`
386
+ `),r=yn.parse(t);if(!r||typeof r!="object")return;let n=r.credential&&typeof r.credential=="string"?r.credential:r.credential?.id,o=r.claimant?.github,i=E(n),s=E(o);return!i||!s?void 0:{credential:i,claimant:s}}catch{return}}function Gi(e,t){let r=t.toLowerCase();return(e.labels||[]).some(n=>E(n?.name)===r)}function At(e){let t=new Set((e||[]).map(r=>E(r)));return t.has("skillcraft-issued")?"issued":t.has("skillcraft-rejected")?"rejected":t.has("skillcraft-verified")?"verified":t.has("skillcraft-processing")?"processing":"pending"}async function Vi(e,t,r="unknown"){let n=await Zi(t),o=[];for(let a of n){let d=await me(a),l=await V(a)||a,u=await Promise.all(d.map(async f=>await lr(a,f.commit)?f:void 0)),p=Array.from(new Set(u.map(f=>f?.commit).filter(Boolean)));o.push({repo:l,commits:p})}let i=r,s=`${i}:${e}:${o.map(a=>`${a.repo}:${a.commits.length}`).join("|")}:${Date.now()}`,c=Ki("sha256").update(s).digest("hex").slice(0,8);return{claim_version:1,claimant:{github:i},credential:{id:e},sources:o,claim_id:`sha256:${c}`}}async function Zi(e){let t=e.allRepos?(await K()).repos.map(o=>o.path):[process.cwd()],r=e.repo?e.repo:t,n=[];for(let o of r)await jr(o)&&n.push(o);return n}import Pe from"path";import ne from"fs/promises";import{execFile as Xi}from"child_process";import{promisify as Yi}from"util";var Qi=Yi(Xi);async function vn(e){if(!Ye(e))throw new Error("loadout id must be <owner>/<slug>");let t=process.cwd();if(!await R(t))throw new Error("Repository is not enabled");let r=await w(I(t)),n=Array.isArray(r?.activeLoadouts)?r.activeLoadouts.filter(Boolean):[];n.includes(e)||n.push(e),await h(I(t),{activeLoadouts:n}),process.stdout.write(`activated loadout: ${e}
387
+ `)}async function bn(){let e=process.cwd();if(!await R(e))throw new Error("Repository is not enabled");await h(I(e),{activeLoadouts:[]}),process.stdout.write(`cleared active loadouts
388
+ `)}async function Pn(e){let t=O(e,"loadout id");if(!Ye(t))throw new Error("loadout id must be <owner>/<slug>");let{owner:r,slug:n}=je(t),o=process.cwd(),i=Pe.join(o,"loadout.yaml");if(await ne.access(i),!(await ne.stat(i)).isFile())throw new Error("loadout.yaml not found in current directory");let c=await F(),a=L(c.provider??"gh"),d="skillcraft-gg/loadouts",l=Pe.join(process.cwd(),".skillcraft-temp-loadout-share"),u=`skillcraft-loadout-${r}-${n}`;try{await ne.rm(l,{force:!0,recursive:!0}),await a.cloneRepo(d,l),await Ke(l,["checkout","-B",u]);let p=Pe.join(l,"loadouts",r,n);await ne.rm(p,{force:!0,recursive:!0}).catch(()=>{}),await ne.mkdir(Pe.dirname(p),{recursive:!0}),await ne.copyFile(i,Pe.join(p,"loadout.yaml")),await Ke(l,["add",p]),await Ke(l,["commit","-m",`Loadout: publish ${t}`]).catch(async()=>{throw new Error("nothing to commit; loadout may already be published")}),await Ke(l,["push","-u","origin",u]).catch(()=>{throw new Error("unable to push loadout publish branch")}),await a.createPullRequest(d,u,`Loadout publish: ${t}`).catch(()=>{process.stdout.write(`unable to create PR automatically. Please open one manually from your branch.
263
389
  `)}),process.stdout.write(`loadout publish workflow completed for ${t}
264
- `)}finally{await X.rm(l,{force:!0,recursive:!0})}}async function Ie(e,t){let{stdout:r}=await yi("git",t,{cwd:e});return r.trim()}async function Sr(e){if(!await P(e))return;let t=await te(e),r=new Date().toISOString(),n=await Ft(e,t,r);if(!n)return;let i=await Tt(e,n.proofId);await lt(e,i);let o=await te(e);o!==t&&await ze(e,{...n.proof,commit:o}),await y(L(e),{skills:[]})}async function $r(e,t="origin"){await qt(e,t)}var b=new ki;b.name("skillcraft").description("Skillcraft CLI").version(nt.version);b.option("--json","machine-readable JSON output");b.command("enable").description("Enable Skillcraft in the current repository").action(w(Dt));b.command("disable").description("Disable Skillcraft in the current repository").action(w(Rt));b.command("status").description("Show repository Skillcraft status").action(w(zt));b.command("doctor").description("Check environment and integration readiness").action(w(Mt));var Er=b.command("repos").description("Manage tracked repositories");Er.command("list").description("List tracked repositories").action(w(Ht));Er.command("prune").description("Remove unavailable repository entries").action(w(Kt));var et=b.command("progress").description("Show progress for tracked credentials");et.option("--refresh","refresh the local credential index cache before evaluating progress").action((e,t)=>{let r=t.parent?.opts()?.json?"json":"text";w(()=>tr({outputMode:r,refreshIndex:e.refresh}))()});et.command("track <credential-id>").description("Track a credential for local progress evaluation").action(e=>w(()=>rr(e))());et.command("untrack <credential-id>").description("Untrack a credential from local progress evaluation").action(e=>w(()=>nr(e))());var de=b.command("skills").description("Manage local skill publishing");de.command("add <id>").description("Add a local or external skill from the registry index").action(e=>w(()=>ur(e))());de.command("publish <owner-slug>").description("Publish a skill to the registry").action(e=>w(()=>lr(e))());de.command("validate").description("Validate local skill layout").action(w(hr));de.command("list").description("List detected skills in the current repository").action(w(mr));de.command("inspect <id>").description("Show detailed information for a registry skill").action((e,t,r)=>{let n=r.parent?.parent?.opts()?.json?"json":"text";w(()=>fr(e,{outputMode:n}))()});de.command("search [query]").description("Search the published skill index").option("--source <source>","filter to a registry source").option("--limit <n>","limit number of results",e=>Number.parseInt(e,10)).action((e,t,r)=>{let n=r.parent?.parent?.opts()?.json?"json":"text";w(()=>pr(e,{source:t.source,limit:t.limit,outputMode:n}))()});b.command("verify").description("Verify local Skillcraft proofs and trailers").action(w(kr));var tt=b.command("claim").description("Claim a credential or inspect your claims");tt.argument("[credential]","credential identifier").option("--all-repos","include tracked repositories").option("--repo <path...>","explicit repositories to include").action((e,t)=>{if(!e){w(()=>Xe())();return}w(()=>Pr(e,{allRepos:t.allRepos,repo:t.repo}))()});tt.command("list").description("List your claims in the credentials repository").action(w(Xe));tt.command("status <credential>").description("Show claim status by credential identifier").action(e=>w(()=>xr(e))());var rt=b.command("loadout").description("Manage active loadouts");rt.command("use <id>").description("Activate a loadout in local context").action(e=>w(()=>br(e))());rt.command("clear").description("Clear active loadouts").action(w(Rr));rt.command("share <id>").description("Publish local loadout to registry").action(e=>w(()=>Cr(e))());b.command("_hook <name> [repoPath] [remote]",{hidden:!0}).description("internal hook command").action((e,t,r)=>w(async()=>{e==="post-commit"&&await Sr(t||process.cwd()),(e==="pre-push"||e==="post-push")&&await $r(t||process.cwd(),r||"origin")})());function w(e){return(...t)=>{Promise.resolve(e(...t)).catch(r=>{process.stderr.write(`${r instanceof Error?r.message:String(r)}
265
- `),process.exitCode=1})}}b.parse(process.argv);
390
+ `)}finally{await ne.rm(l,{force:!0,recursive:!0})}}async function Ke(e,t){let{stdout:r}=await Qi("git",t,{cwd:e});return r.trim()}async function Sn(e){if(!await R(e))return;let t=await le(e),r=new Date().toISOString(),n=await $r(e,t,r);if(!n)return;let o=await Er(e,n.proofId);await mr(e,o);let i=await le(e);i!==t&&await pt(e,{...n.proof,commit:i}),await h(N(e),{skills:[]})}async function Cn(e,t="origin"){await Ar(e,t)}async function Rn(e,t){let r=we(e);if(!r)throw new Error(`Unsupported agent hook: ${e}`);let n=await es(),o=n&&typeof n=="object"&&!Array.isArray(n)&&typeof n.cwd=="string"?String(n.cwd):void 0,i=await ts(o||t||process.cwd());r==="codex"&&await nr(i,n)}async function es(){let e=[];for await(let r of process.stdin)e.push(Buffer.isBuffer(r)?r:Buffer.from(String(r)));let t=Buffer.concat(e).toString("utf8").trim();return t?JSON.parse(t):{}}async function ts(e){return await M(e)?z(e):e}var C=new rs;C.name("skillcraft").description("Skillcraft CLI").version(jt.version);C.option("--json","machine-readable JSON output");C.command("enable").description("Enable Skillcraft in the current repository").option("--agent <name>","enable a specific agent integration (repeatable or comma-separated)",In,[]).action(e=>k(()=>qr({agents:e.agent}))());C.command("disable").description("Disable Skillcraft in the current repository").option("--agent <name>","disable a specific agent integration (repeatable or comma-separated)",In,[]).action(e=>k(()=>kr({agents:e.agent}))());C.command("status").description("Show repository Skillcraft status").action(k(_r));C.command("doctor").description("Check environment and integration readiness").action(k(Nr));var An=C.command("repos").description("Manage tracked repositories");An.command("list").description("List tracked repositories").action(k(Or));An.command("prune").description("Remove unavailable repository entries").action(k(Mr));var It=C.command("progress").description("Show progress for tracked credentials");It.option("--refresh","refresh the local credential index cache before evaluating progress").action((e,t)=>{let r=t.parent?.opts()?.json?"json":"text";k(()=>Xr({outputMode:r,refreshIndex:e.refresh}))()});It.command("track <credential-id>").description("Track a credential for local progress evaluation").action(e=>k(()=>Yr(e))());It.command("untrack <credential-id>").description("Untrack a credential from local progress evaluation").action(e=>k(()=>Qr(e))());var fe=C.command("skills").description("Manage local skill publishing");fe.command("add <id>").description("Add a local or external skill from the registry index").action(e=>k(()=>an(e))());fe.command("publish <owner-slug>").description("Publish a skill to the registry").action(e=>k(()=>sn(e))());fe.command("validate").description("Validate local skill layout").action(k(fn));fe.command("list").description("List detected skills in the current repository").action(k(cn));fe.command("inspect <id>").description("Show detailed information for a registry skill").action((e,t,r)=>{let n=r.parent?.parent?.opts()?.json?"json":"text";k(()=>dn(e,{outputMode:n}))()});fe.command("search [query]").description("Search the published skill index").option("--source <source>","filter to a registry source").option("--limit <n>","limit number of results",e=>Number.parseInt(e,10)).action((e,t,r)=>{let n=r.parent?.parent?.opts()?.json?"json":"text";k(()=>ln(e,{source:t.source,limit:t.limit,outputMode:n}))()});C.command("verify").description("Verify local Skillcraft proofs and trailers").action(k(wn));var $t=C.command("claim").description("Claim a credential or inspect your claims");$t.argument("[credential]","credential identifier").option("--all-repos","include tracked repositories").option("--repo <path...>","explicit repositories to include").action((e,t)=>{if(!e){k(()=>Ct())();return}k(()=>xn(e,{allRepos:t.allRepos,repo:t.repo}))()});$t.command("list").description("List your claims in the credentials repository").action(k(Ct));$t.command("status <credential>").description("Show claim status by credential identifier").action(e=>k(()=>kn(e))());var Et=C.command("loadout").description("Manage active loadouts");Et.command("use <id>").description("Activate a loadout in local context").action(e=>k(()=>vn(e))());Et.command("clear").description("Clear active loadouts").action(k(bn));Et.command("share <id>").description("Publish local loadout to registry").action(e=>k(()=>Pn(e))());C.command("_hook <name> [repoPath] [remote]",{hidden:!0}).description("internal hook command").action((e,t,r)=>k(async()=>{e==="post-commit"&&await Sn(t||process.cwd()),(e==="pre-push"||e==="post-push")&&await Cn(t||process.cwd(),r||"origin")})());C.command("_agent-hook <agent> [repoPath]",{hidden:!0}).description("internal agent hook command").action((e,t)=>k(()=>Rn(e,t||process.cwd()))());C.command("_skill-used <id> [repoPath]",{hidden:!0}).description("internal skill evidence command").action((e,t)=>k(()=>pn(e,t||process.cwd()))());function k(e){return(...t)=>{Promise.resolve(e(...t)).catch(r=>{process.stderr.write(`${r instanceof Error?r.message:String(r)}
391
+ `),process.exitCode=1})}}function In(e,t){return[...t,e]}C.parse(process.argv);
266
392
  //# sourceMappingURL=index.js.map