skillcraft 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # temp
package/dist/index.js ADDED
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env node
2
+ import{Command as Zn}from"commander";var Ze={name:"skillcraft",version:"0.1.1",description:"Skillcraft CLI for git-native skill evidence and credential workflow",type:"module",bin:{skillcraft:"dist/index.js"},files:["dist/index.js","dist/index.js.map"],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 kr}from"child_process";import{promisify as vr}from"util";import Xe from"path";var Ye=vr(kr);async function y(e,t,r={}){try{let{stdout:n}=await Ye("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 q(e){try{return await y(["rev-parse","--git-dir"],e),!0}catch{return!1}}async function ee(e){return Xe.resolve(await y(["rev-parse","--show-toplevel"],e))}async function T(e,t="origin"){try{return await y(["config","--get",`remote.${t}.url`],e)||void 0}catch{return}}async function Qe(e,t="HEAD"){return y(["log","--format=%B","-n","1",t],e)}async function te(e){return(await y(["rev-parse","HEAD"],e)).trim()}async function M(e,t){try{return await y(["show-ref","--verify","--quiet",t],e),!0}catch{return!1}}async function et(e,t,r){try{let n=await y(["ls-tree","-r","--name-only",t,"--",...r?[r]:[]],e);return n?n.split(`
3
+ `).filter(Boolean):[]}catch{return[]}}async function tt(e,t,r){try{return await y(["show",`${t}:${r}`],e)}catch{return}}async function me(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(`
4
+ `),a=s.join(`
5
+ `).trimEnd();return{commit:i,message:a}}):[]}async function rt(e,t){let r={...process.env,SKILLCRAFT_HOOK_DISABLED:"1"},n=Xe.join(e,".git","SKILLCRAFT_COMMIT_MESSAGE"),{writeFile:o}=await import("fs/promises");return await o(n,`${t}
6
+ `,"utf8"),await Ye("git",["commit","--amend","--file",n,"--no-gpg-sign"],{cwd:e,encoding:"utf8",env:r}),te(e)}import no from"fs/promises";import k from"path";import xr from"os";function Pr(){return k.resolve(process.env.HOME||xr.homedir(),".skillcraft")}function E(){return Pr()}function $e(){return k.join(E(),"config.json")}function Ee(){return k.join(E(),"repos.json")}function Ie(){return k.join(E(),"credentials.json")}function nt(){return k.join(E(),"cache","credentials","index.json")}function Rr(e){return k.join(e,".skillcraft")}function I(e){return k.join(e,".git","skillcraft")}function A(e){return k.join(Rr(e),".skillcraft.json")}function B(e){return k.join(e,".git","hooks","post-commit")}function pe(e){return k.join(e,".git","hooks","pre-push")}function fe(e){return k.join(e,".git","hooks","post-push")}function L(e){return k.join(I(e),"pending.json")}function b(e){return k.join(I(e),"context.json")}function ge(e){return k.join(I(e),"agent.json")}function de(e){return k.join(e,".opencode","plugins","skillcraft.mjs")}function re(e){return k.join(I(e),"ai-model-context.json")}import le from"fs/promises";import br from"path";async function C(e){await le.mkdir(e,{recursive:!0})}async function Cr(e){return await le.readFile(e,"utf8")}async function J(e,t){await C(br.dirname(e)),await le.writeFile(e,t,"utf8")}async function $(e){try{return await le.access(e),!0}catch{return!1}}async function v(e){if(!await $(e))return null;let t=await Cr(e);return JSON.parse(t)}async function w(e,t){let r=JSON.stringify(t,null,2);await J(e,`${r}
7
+ `)}async function N(e){try{await le.rm(e,{force:!0})}catch{}}import ne from"fs/promises";function Ae(e){let t=process.argv[1]||"";return`#!/usr/bin/env sh
8
+ if [ -n "$SKILLCRAFT_HOOK_DISABLED" ]; then
9
+ exit 0
10
+ fi
11
+
12
+ run_skillcraft_hook() {
13
+ if command -v skillcraft >/dev/null 2>&1; then
14
+ skillcraft "$@"
15
+ return
16
+ fi
17
+
18
+ local cli=${JSON.stringify(t)}
19
+ if [ -n "$cli" ] && [ -f "$cli" ]; then
20
+ case "$cli" in
21
+ *.js|*.mjs)
22
+ node "$cli" "$@"
23
+ ;;
24
+ *)
25
+ "$cli" "$@"
26
+ ;;
27
+ esac
28
+ return
29
+ fi
30
+ }
31
+
32
+ ${e}
33
+ `}var Sr=Ae(`SKILLCRAFT_HOOK_DIR="$PWD"
34
+ run_skillcraft_hook _hook post-commit "$SKILLCRAFT_HOOK_DIR" || true`),$r=Ae(`SKILLCRAFT_HOOK_DIR="$PWD"
35
+ SKILLCRAFT_HOOK_REMOTE="$1"
36
+ run_skillcraft_hook _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`),Er=Ae(`SKILLCRAFT_HOOK_DIR="$PWD"
37
+ SKILLCRAFT_HOOK_REMOTE="$1"
38
+ run_skillcraft_hook _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`);async function ot(e){await J(B(e),`${Sr}
39
+ `),await ne.chmod(B(e),493),await J(fe(e),`${$r}
40
+ `),await ne.chmod(fe(e),493),await J(pe(e),`${Er}
41
+ `),await ne.chmod(pe(e),493)}async function it(e){await Promise.all([ne.rm(B(e),{force:!0}),ne.rm(fe(e),{force:!0}),ne.rm(pe(e),{force:!0})])}import{z as f}from"zod";var ho=f.literal(1),U="skillcraft/proofs/v1",st=f.object({skills:f.array(f.string()).default([])}),at=f.object({activeLoadouts:f.array(f.string()).default([])}),wo=f.object({provider:f.string().optional()}),yo=f.object({provider:f.string().optional(),name:f.string().optional()}),G=f.object({githubUser:f.string().optional(),provider:f.enum(["gh"]).default("gh"),version:f.number().int().default(1),proofRef:f.string().default(U)}),Ir=f.object({path:f.string(),remote:f.string().optional(),enabledAt:f.string().optional()}),ct=f.object({repos:f.array(Ir).default([])}),Ar=f.object({id:f.string(),trackedAt:f.string().optional()}),dt=f.object({credentials:f.array(Ar).default([])});async function j(){let e=await v($e()),t=G.safeParse(e??{});return t.success?t.data:G.parse({})}async function he(e){let t=await v(A(e)),r=G.safeParse(t??{});return r.success?r.data:G.parse({})}async function lt(e){await C(E()),await w($e(),e)}async function _(){let e=await v(Ee()),t=ct.safeParse(e??{});return t.success?t.data:{repos:[]}}async function we(e){await C(E()),await w(Ee(),e)}async function ut(e){let r=(await _()).repos.filter(n=>n.path!==e.path);r.push(e),await we({repos:r})}async function mt(e){let r=(await _()).repos.filter(n=>n.path!==e);await we({repos:r})}async function ye(){let e=await v(Ie()),t=dt.safeParse(e??{});return t.success?t.data:{credentials:[]}}async function pt(e){await C(E()),await w(Ie(),e)}async function ft(e){let t=await ye();return t.credentials.some(r=>r.id===e)?!1:(t.credentials.push({id:e,trackedAt:new Date().toISOString()}),t.credentials.sort(Lr),await pt(t),!0)}async function gt(e){let t=await ye(),r=t.credentials.length,n=t.credentials.filter(o=>o.id!==e);return n.length===r?!1:(await pt({credentials:n}),!0)}function Lr(e,t){return e.id.localeCompare(t.id)}async function ht(){let e=process.cwd();if(!await q(e))throw new Error("Current directory is not a git repository");let t=await ee(e);await Promise.all([N(A(t)),N(L(t)),N(b(t)),N(ge(t)),N(de(t)),N(re(t)),N(I(t))]),await it(t),await mt(t),process.stdout.write(`disabled skillcraft for ${t}
42
+ `)}import{createHash as Or}from"crypto";import ve from"path";import Tr from"os";import kt from"fs/promises";var jr=/^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*(?:@[^\s/]+)?$/,qr=/^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/,Nr=/^([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 wt(e){let t=D(e);if(t.id)return`${t.id}${t.version?`@${t.version}`:""}`}function Le(e){return jr.test(e)}function je(e){return!!D(e).id}function D(e){let t=e.trim(),r=Fr(t),n=r.id||"";if(_r(n)){let[c,g]=n.split("/");return{id:n,owner:c,slug:g,version:r.version}}let o=Nr.exec(n);if(!o)return{id:"",slug:"",version:r.version};let i=o[1],s=o[2],a=o[3];return a===void 0?{id:`${i}:${s}`,source:i,slug:s,version:r.version}:{id:`${i}:${s}/${a}`,source:i,owner:s,slug:a,version:r.version}}function _r(e){return qr.test(e)}function F(e,t){let r=e.trim();if(!r)throw new Error(`Expected ${t} to be provided`);return r}function Fr(e){let t=e.split("@"),r=t[0]||"",n=t.length>1?t.slice(1).join("@"):void 0;return{id:r,version:n}}function ke(e){let[t,r]=e.split("/");if(!t||!r)throw new Error(`Expected <owner>/<slug>, received ${e}`);return{owner:t,slug:r.trim()}}var qe="proofs";function vt(e){return(e?.trim()||U).replace(/^refs\/heads\//,"")}function xt(e){return`${qe}/${e}.json`}async function xe(e){let t=await he(e);return vt(t.proofRef)}async function Pt(e,t){let r=vt(t),n=`refs/heads/${r}`,o=`refs/remotes/origin/${r}`,i=[];return await M(e,n)&&i.push(r),await M(e,o)&&i.push(`origin/${r}`),i.length||i.push(r),i}async function Mr(e,t){let r=`refs/heads/${t}`;await M(e,r)||await y(["branch",t],e)}async function Dr(e,t,r){await zr(e,t);let n=await kt.mkdtemp(ve.join(Tr.tmpdir(),"skillcraft-proof-"));try{return await y(["worktree","add","--quiet",n,t],e),await r(n)}finally{await Rt(e,n)}}async function Rt(e,t){try{await y(["worktree","remove","--force",t],e)}catch{await kt.rm(t,{force:!0,recursive:!0})}}async function zr(e,t){let r=`refs/heads/${t}`;try{let o=(await y(["worktree","list","--porcelain"],e)).split(`
43
+ `),i,s,a=async()=>{!i||s!==r||await Rt(e,i)};for(let c of o){if(!c){i=void 0,s=void 0;continue}if(c.startsWith("worktree ")){await a(),i=c.slice(9),s=void 0;continue}c.startsWith("branch ")&&(s=c.slice(7))}await a()}catch{return}}async function Ne(e){let t=await xe(e),r=await Pt(e,t),n=new Set;for(let i of r){let s=await et(e,i,qe);for(let a of s)n.add(a)}let o=[];for(let i of n){if(!i.endsWith(".json"))continue;let s=ve.basename(i,".json"),a=await _e(e,s);a&&o.push(a)}return o}function Hr(e){let t=D(e);if(t.id&&je(t.id))return{id:t.id,version:t.version}}function Pe(e){let t=e.filter(Boolean).map(r=>D(r)).filter(r=>!!r.id).map(r=>`${r.id}${r.version?`@${r.version}`:""}`);return Array.from(new Set(t)).filter(je).sort()}function bt(e,t,r){let n={skills:e,loadouts:r,timestamp:t};return Or("sha256").update(JSON.stringify(n)).digest("hex").slice(0,8)}async function oe(e){let t=await v(L(e)),r=st.safeParse(t??{skills:[]});return r.success?Pe(r.data.skills):[]}async function Kr(e){let t=await v(b(e)),r=at.safeParse(t??{activeLoadouts:[]});return r.success?r.data.activeLoadouts:[]}async function Br(e){let t=await v(re(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:yt(n.provider)}:void 0,model:typeof o?.provider=="string"||typeof o?.name=="string"?{provider:typeof o.provider=="string"?yt(o.provider):void 0,name:typeof o.name=="string"?Jr(o.name):void 0}:void 0}}function yt(e){return e.trim().toLowerCase()}function Jr(e){return e.trim()}function Ur(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:Gr(t.agent),model:Wr(t.model)}}function Gr(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 Wr(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 _e(e,t){let r=await xe(e),n=xt(t),o=await Pt(e,r);for(let i of o){let s=await tt(e,i,n);if(!s)continue;let a;try{a=JSON.parse(s)}catch{continue}let c=Ur(a);if(c)return c}}async function Fe(e,t){let r=bt(t.skills.map(i=>i.id),t.timestamp,t.loadouts),n=await xe(e);await Mr(e,n);let o=xt(r);return await Dr(e,n,async i=>{await C(ve.join(i,qe)),await w(ve.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 Ct(e,t="origin"){let r=await xe(e);if(!(!await T(e,t)||!t))try{await y(["push",t,`${r}:${r}`],e,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}})}catch{return}}async function St(e,t){let r=await Ne(e);for(let n of r)if(n.commit===t)return bt(n.skills.map(o=>o.id),n.timestamp,n.loadouts)}async function $t(e,t,r=new Date().toISOString()){let n=await oe(e);if(!n.length)return;let o=await Kr(e),i=await Br(e),s={version:1,commit:t,skills:n.map(c=>Hr(c)).filter(c=>!!c),loadouts:o,timestamp:r,...i};return{proofId:await Fe(e,s),proof:s}}async function Vr(e){return e.replace(/\nSkillcraft-Ref: .*$/gm,"").trimEnd()}async function Et(e,t){let r=await Qe(e),n=await Vr(r);return n.includes("Skillcraft-Ref:")?n:`${n}
44
+
45
+ Skillcraft-Ref: ${t}
46
+ `}async function P(e){let t=A(e);if(!await $(t))return!1;let r=await v(t);return G.safeParse(r??{}).success}async function It(e){return $(I(e))}async function At(){let e=process.cwd(),t=await q(e);process.stdout.write(`git: ${t?"enabled":"not a repository"}
47
+ `);let r=await P(e);if(process.stdout.write(`skillcraft: ${r?"enabled":"disabled"}
48
+ `),!t||!r)return;let n=await oe(e);process.stdout.write(`pending skills: ${n.length}
49
+ `);let o=await $(b(e)),i=await $(B(e));process.stdout.write(`context file: ${o?"present":"missing"}
50
+ `),process.stdout.write(`post-commit hook: ${i?"installed":"missing"}
51
+ `);let s=await te(e),a=await St(e,s);process.stdout.write(`head: ${s}
52
+ `),process.stdout.write(`latest proof: ${a??"none"}
53
+ `);let g=(await me(e,20)).filter(p=>p.message.includes("Skillcraft-Ref:"));process.stdout.write(`recent commits with evidence: ${g.length}
54
+ `);let d=(await he(e)).proofRef?.replace(/^refs\/heads\//,"")||"skillcraft/proofs/v1",u=await M(e,`refs/heads/${d}`);process.stdout.write(`proof branch: ${u?"present":"missing"}
55
+ `),n.length>0&&process.stdout.write(`pending evidence queued: ${n.join(", ")}
56
+ `)}async function Lt(){let e=process.cwd(),t=[["node",!!process.version],["git",await q(e)],["skillcraft config",await $(A(e))],["plugin hook",await $(B(e))]];for(let[r,n]of t)process.stdout.write(`${r}: ${n?"ok":"missing"}
57
+ `);if(!process.env.GITHUB_TOKEN&&!await Zr("gh")){process.stdout.write(`gh: not installed
58
+ `);return}process.stdout.write(`gh: available
59
+ `)}async function Zr(e){try{let{execSync:t}=await import("child_process");return t(`command -v ${e}`),!0}catch{return!1}}import Xr from"path";async function jt(){let e=process.cwd();if(!await q(e))throw new Error("Current directory is not a git repository");let t=await ee(e),r=await j();if(!r.githubUser){let i=process.env.GITHUB_USER||process.env.USER||"developer";await lt({...r,githubUser:i})}await C(I(t)),await C(Xr.dirname(de(t))),await J(de(t),Yr()),await w(re(t),{agent:{provider:"opencode"},model:{}});let n=`refs/heads/${U}`;await M(t,n)||await y(["branch",U],t),await w(A(t),{version:1,proofRef:U}),await C(E()),await w(L(t),{skills:[]}),await w(b(t),{activeLoadouts:[]}),await w(ge(t),{version:1,providers:["opencode"],enabled:!0}),await ot(t);let o=await T(t);await ut({path:t,remote:o,enabledAt:new Date().toISOString()}),process.stdout.write(`enabled skillcraft for ${t}
60
+ `)}function Yr(){return`import fs from 'node:fs/promises'
61
+ import path from 'node:path'
62
+
63
+ function normalizeProvider(value) {
64
+ return typeof value === 'string' ? value.trim().toLowerCase() : ''
65
+ }
66
+
67
+ function normalizeModelName(value) {
68
+ return typeof value === 'string' ? value.trim() : ''
69
+ }
70
+
71
+ function extractModelInfo(payload) {
72
+ if (!payload || typeof payload !== 'object') {
73
+ return {}
74
+ }
75
+
76
+ const direct = {
77
+ modelProvider: normalizeProvider(payload.model_provider || payload.modelProvider || payload.model_provider_id),
78
+ modelName: normalizeModelName(payload.model_name || payload.modelName || payload.model),
79
+ agentProvider: normalizeProvider(payload.provider || payload.agent_provider || payload.agentProvider),
80
+ }
81
+
82
+ const msg = payload.message
83
+ const request = payload.request
84
+ const context = payload.context
85
+
86
+ const nestedMessage = msg && typeof msg === 'object' ? {
87
+ modelProvider: normalizeProvider(msg.model_provider || msg.modelProvider),
88
+ modelName: normalizeModelName(msg.model_name || msg.modelName || msg.model),
89
+ agentProvider: normalizeProvider(msg.provider || msg.agent_provider || msg.agentProvider),
90
+ } : {}
91
+
92
+ const nestedRequest = request && typeof request === 'object' ? {
93
+ modelProvider: normalizeProvider(request.model_provider || request.modelProvider),
94
+ modelName: normalizeModelName(request.model_name || request.modelName || request.model),
95
+ agentProvider: normalizeProvider(request.provider || request.agent_provider || request.agentProvider),
96
+ } : {}
97
+
98
+ const nestedContext = context && typeof context === 'object' ? {
99
+ modelProvider: normalizeProvider(context.model_provider || context.modelProvider),
100
+ modelName: normalizeModelName(context.model_name || context.modelName || context.model),
101
+ agentProvider: normalizeProvider(context.provider || context.agent_provider || context.agentProvider),
102
+ } : {}
103
+
104
+ const candidate = {
105
+ agentProvider: direct.agentProvider || nestedMessage.agentProvider || nestedRequest.agentProvider || nestedContext.agentProvider || 'opencode',
106
+ modelProvider: direct.modelProvider || nestedMessage.modelProvider || nestedRequest.modelProvider || nestedContext.modelProvider,
107
+ modelName: direct.modelName || nestedMessage.modelName || nestedRequest.modelName || nestedContext.modelName,
108
+ }
109
+
110
+ if (!candidate.modelProvider && !candidate.modelName && !candidate.agentProvider) {
111
+ return {}
112
+ }
113
+
114
+ return candidate
115
+ }
116
+
117
+ function resolveStateFile() {
118
+ return path.join(process.cwd(), '.git', 'skillcraft', 'ai-model-context.json')
119
+ }
120
+
121
+ async function updateState(update) {
122
+ const stateFile = resolveStateFile()
123
+ let current = {}
124
+
125
+ try {
126
+ const raw = await fs.readFile(stateFile, 'utf8')
127
+ const parsed = JSON.parse(raw)
128
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
129
+ current = parsed
130
+ }
131
+ } catch {
132
+ current = {}
133
+ }
134
+
135
+ const next = {
136
+ ...(current || {}),
137
+ ...(update || {}),
138
+ }
139
+
140
+ if (!next.agent || typeof next.agent !== 'object' || Array.isArray(next.agent)) {
141
+ next.agent = { provider: 'opencode' }
142
+ } else if (!next.agent.provider && update?.agent?.provider) {
143
+ next.agent = { ...next.agent }
144
+ }
145
+
146
+ if (update?.agent?.provider) {
147
+ next.agent.provider = update.agent.provider
148
+ }
149
+
150
+ if (update?.model) {
151
+ next.model = {
152
+ ...(next.model || {}),
153
+ ...(update.model || {}),
154
+ }
155
+ }
156
+
157
+ try {
158
+ await fs.mkdir(path.join(process.cwd(), '.git', 'skillcraft'), { recursive: true })
159
+ await fs.writeFile(stateFile, JSON.stringify(next, null, 2) + '
160
+ ', 'utf8')
161
+ } catch {
162
+ return
163
+ }
164
+ }
165
+
166
+ async function handlePayload(payload) {
167
+ if (!payload || typeof payload !== 'object') {
168
+ return
169
+ }
170
+
171
+ const extracted = extractModelInfo(payload)
172
+ if (!extracted || !extracted.agentProvider && !extracted.modelProvider && !extracted.modelName) {
173
+ return
174
+ }
175
+
176
+ const update = {
177
+ agent: {
178
+ provider: extracted.agentProvider || 'opencode',
179
+ },
180
+ model: {
181
+ ...(extracted.modelProvider ? { provider: extracted.modelProvider } : {}),
182
+ ...(extracted.modelName ? { name: extracted.modelName } : {}),
183
+ },
184
+ }
185
+
186
+ await updateState(update)
187
+ }
188
+
189
+ export default async function Skillcraft() {
190
+ const handler = async (event) => {
191
+ try {
192
+ await handlePayload(event)
193
+ } catch {
194
+ return
195
+ }
196
+ }
197
+
198
+ return {
199
+ 'chat.message': async (event) => {
200
+ try {
201
+ await handler(event)
202
+ } catch {
203
+ return
204
+ }
205
+ },
206
+ event: async (event) => {
207
+ try {
208
+ const payload = event?.type && typeof event.type === 'string' ? event : event?.payload
209
+ await handler(payload)
210
+ } catch {
211
+ return
212
+ }
213
+ },
214
+ }
215
+ }
216
+ `}async function qt(){let e=await _();if(!e.repos.length){process.stdout.write(`no repositories tracked
217
+ `);return}e.repos.forEach((t,r)=>{process.stdout.write(`${r+1}. ${t.path}`),t.remote&&process.stdout.write(` (${t.remote})`),process.stdout.write(`
218
+ `)})}async function Nt(){let e=await _(),t=[];for(let r of e.repos)await q(r.path)&&(await ee(r.path),t.push(r));await we({repos:t}),process.stdout.write(`pruned repo list: ${e.repos.length} -> ${t.length}
219
+ `)}async function ie(e){return Ne(e)}import Qr from"path";var en="https://skillcraft.gg/credentials/credentials/index.json",tn=360*60*1e3,Te=1,se=nt();function rn(){return process.env.SKILLCRAFT_CREDENTIAL_INDEX_URL?.trim()||en}async function _t(e){try{let t=await v(e);if(!t||!W(t))return null;let r=nn(t.cachedAt);if(r===void 0||r<=0||t.version!==Te||!("entries"in t))return null;let n=Re(t.entries);return{cachedAt:r,version:Te,entries:n}}catch{return null}}function nn(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 on(e){return Date.now()-e.cachedAt<tn}async function sn(e={}){let t=process.env.SKILLCRAFT_CREDENTIAL_INDEX_PATH?.trim();if(t)return Ft(t);let r=e.refresh?null:await _t(se);if(r&&on(r))return r.entries;try{let n=await an(rn());return await cn(n),n}catch(n){if(await $(se)){let o=await _t(se);return o?o.entries:Ft(se)}throw n instanceof Error?n:new Error("failed to load credential index")}}async function an(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 Re(r)}async function Ft(e){let t=await v(e);return t?W(t)&&Array.isArray(t.entries)?Re(t.entries):Re(t):[]}async function cn(e){await C(Qr.dirname(se));let t={cachedAt:Date.now(),version:Te,entries:e};await w(se,t)}function dn(e){let t=W(e)?e:{};if(t.mode!==void 0)throw new Error("requirements.mode is not supported. Use nested and/or expressions instead.");let r=ln(t);return{minCommits:Mt(t.min_commits??t.minCommits,0),minRepositories:Mt(t.min_repositories??t.minRepositories,0),tree:r}}function ln(e){if(Object.prototype.hasOwnProperty.call(e,"tree"))return De(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:Ot(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:Ot(e.or,"requirements.or")}}return{and:un(e)}}function Ot(e,t){if(!Array.isArray(e))throw new Error(`Expected array at ${t}`);return e.map((r,n)=>De(r,`${t}[${n}]`))}function Tt(e,t){if(e===void 0)return[];if(Array.isArray(e))return e.map(n=>{let o=S(n);if(o===void 0)throw new Error(`Expected text values for ${t}`);return o});let r=S(e);return r?[r]:[]}function un(e){let t=[],r=["and","or","min_commits","min_repositories","minRepositories","minCommits","tree","skill","loadout","agent","model"];for(let c of Tt(e.skill,"requirements.skill"))t.push({skill:c});for(let c of Tt(e.loadout,"requirements.loadout"))t.push({loadout:c});let n=Object.prototype.hasOwnProperty.call(e,"agent"),o=Dt(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=zt(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 a=Object.keys(e).filter(c=>!r.includes(c)&&!c.startsWith("$"));if(a.length)throw new Error(`Unexpected requirement fields: ${a.join(", ")}`);return t}function De(e,t){if(!W(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)=>De(i,`${t}.${n}[${s}]`))}}if(n==="skill"){let o=S(e[n]);if(!o)throw new Error(`Requirement node ${t} has empty skill`);return{skill:o}}if(n==="loadout"){let o=S(e[n]);if(!o)throw new Error(`Requirement node ${t} has empty loadout`);return{loadout:o}}if(n==="agent"){let o=Dt(e[n]);if(!o)throw new Error(`Requirement node ${t} has invalid agent requirement`);return o}if(n==="model"){let o=zt(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 Dt(e){if(!W(e))return;let t=S(e.provider);if(t)return{agent:{provider:t.toLowerCase()}}}function zt(e){if(!W(e))return;let t=S(e.provider),r=S(e.name);if(!(!t&&!r))return{model:{...t?{provider:t.toLowerCase()}:{},...r?{name:r}:{}}}}function Ht(e,t,r,n){let o=[],i=[],s=[],a=[],c=Array.from(new Set((t||[]).filter(Boolean))),g=Array.from(new Set((r||[]).filter(Boolean)));for(let p of e){let m=p.proof;for(let K of m.skills){let Q=ze(K.id);Q.id&&o.push({id:Q.id,version:Q.version})}for(let K of m.loadouts){let Q=S(K);Q&&i.push(Q)}m.agent?.provider&&typeof m.agent.provider=="string"&&s.push(m.agent.provider);let x=m.model?.provider,Y=m.model?.name;(typeof x=="string"||typeof Y=="string")&&a.push({provider:x,name:Y})}let l=Me(n.tree,{skills:o,loadouts:i,agents:s,models:a}),d=l.checks,u=[...mn(d)];return n.minCommits>c.length&&(u.push(`minimum required commits not met: have ${c.length}, need ${n.minCommits}`),l.passed=!1),n.minRepositories>g.length&&(u.push(`minimum required repositories not met: have ${g.length}, need ${n.minRepositories}`),l.passed=!1),{passed:l.passed,proofs:e,provenCommits:c,provenRepos:g,checks:d,reasons:u,noExplicitChecks:l.noExplicitChecks}}function Me(e,t){if("and"in e){let r=[],n=[],o=!0;for(let i of e.and){let s=Me(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=Me(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=ze(e.skill),n=pn(t.skills,r);return{passed:n,checks:[{type:"skill",requirement:e.skill,satisfied:n}],noExplicitChecks:!1}}if("loadout"in e){let r=gn(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=Oe(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=Oe(e.model.provider),n=Oe(e.model.name),o=t.models.some(s=>{let a=!r||s.provider===r,c=!n||s.name&&s.name===n;return a&&c}),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 mn(e){return e.filter(t=>!t.satisfied).map(t=>`${t.type} ${t.requirement} not met`)}function pn(e,t){return e.some(r=>fn(r.id,r.version,t))}function fn(e,t,r){return e!==r.id?!1:r.version?t===r.version:!0}function gn(e){return ze(e)}function ze(e){let t=S(e);if(!t)return{id:""};let r=t.split("@");return{id:r[0],version:r.length>1?r.slice(1).join("@"):void 0}}function Oe(e){return typeof e=="string"?e.trim().toLowerCase():""}function S(e){return typeof e!="string"?void 0:e.trim()||void 0}function Mt(e,t){return typeof e!="number"||!Number.isFinite(e)||e<0?t:Math.floor(e)}function W(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Re(e){if(!Array.isArray(e))return[];let t=[];for(let r of e){let n=hn(r);n&&t.push(n)}return t.sort((r,n)=>r.id.localeCompare(n.id))}function hn(e){if(!W(e))return;let t=S(e.id);if(t)try{return{id:t,name:S(e.name),description:S(e.description),requirements:dn(e.requirements)}}catch{return}}async function He(e={}){return sn(e)}function Kt(e){process.stdout.write(`${e.join(`
220
+ `)}
221
+ `)}async function wn(){let e=await _(),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 Ut(e={}){let t=await wn(),n=(await ye()).credentials;if(!n.length){if(e.outputMode==="json"){Jt(Bt({tracked:t,trackedCredentialsCount:0,proofFiles:0,provenCommits:0,provenRepositories:0,evaluated:[]}));return}process.stdout.write(`no credentials tracked
222
+ `);return}let o=Vt(await He({refresh:e.refreshIndex})),i=0,s=[],a=new Set,c=new Set;for(let m of t){let x=await ie(m);if(i+=x.length,!x.length)continue;let Y=await T(m)||m;a.add(Y);for(let K of x)K?.commit&&c.add(K.commit),s.push({proof:K})}let g=Array.from(c),l=Array.from(a),d=Bt({tracked:t,trackedCredentialsCount:n.length,proofFiles:i,provenCommits:g.length,provenRepositories:l.length,evaluated:[]}),u=[];for(let m of n){let x=o.get(m.id);if(!x){u.push(yn(m.id,s.length,g.length,l.length));continue}let Y=Ht(s,g,l,x.requirements);u.push(kn(m.id,x,Y,s.length,g.length,l.length))}if(d.credentials=u,e.outputMode==="json"){Jt(d);return}let p=[];p.push(`tracked credentials: ${n.length}`),p.push(`tracked repositories: ${t.length}`),p.push(`proof files: ${i}`),p.push(`proof commits: ${g.length}`),p.push(`proof repositories: ${l.length}`),p.push("");for(let m of u){if(p.push(`${m.credentialId}: ${m.status}`),p.push(` checks: ${m.passed?"passed":"blocked"}`),p.push(` proof scope: ${m.proofFiles} proofs, ${m.provenCommits}/${m.requiredMinCommits} commits, ${m.provenRepositories}/${m.requiredMinRepositories} repositories`),m.reasons.length){p.push(" reasons:");for(let x of m.reasons)p.push(` - ${x}`)}p.push("")}Kt(p)}async function Gt(e){let t=F(e,"credential id");if(!Vt(await He()).has(t))throw new Error(`credential not found in credential index: ${t}`);if(!await ft(t)){process.stdout.write(`credential already tracked: ${t}
223
+ `);return}process.stdout.write(`tracking credential: ${t}
224
+ `)}async function Wt(e){let t=F(e,"credential id");if(!await gt(t)){process.stdout.write(`credential not tracked: ${t}
225
+ `);return}process.stdout.write(`untracked credential: ${t}
226
+ `)}function Bt(e){return{trackedCredentials:e.trackedCredentialsCount,trackedRepositories:e.tracked.length,evidence:{proofFiles:e.proofFiles,provenCommits:e.provenCommits,provenRepositories:e.provenRepositories},credentials:e.evaluated}}function Jt(e){process.stdout.write(`${JSON.stringify(e)}
227
+ `)}function Vt(e){return new Map(e.map(t=>[t.id,t]))}function yn(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 kn(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 Z from"path";import O from"fs/promises";import z from"fs/promises";import Ke from"path";import{execFile as vn,execSync as xn}from"child_process";import{promisify as Pn}from"util";var Rn=Pn(vn);function bn(){try{return xn("which gh",{stdio:"ignore"}),!0}catch{return!1}}async function V(e){if(!bn())throw new Error("gh CLI is required for this workflow");return(await Rn("gh",e,{encoding:"utf8"})).stdout.trim()}async function Zt(e,t){await z.mkdir(t,{recursive:!0});let r=await z.readdir(e,{withFileTypes:!0});for(let n of r){if(n.name===".git")continue;let o=Ke.join(e,n.name),i=Ke.join(t,n.name);if(n.isDirectory()){await Zt(o,i);continue}if(n.isSymbolicLink()){let s=await z.readlink(o);await z.symlink(s,i);continue}n.isFile()&&await z.copyFile(o,i)}}var be=class{providerName(){return"gh"}async getUser(){let t=await V(["auth","status","--json","user"]);return JSON.parse(t).user?.login||""}async getIssueUrl(t,r){return`https://github.com/${t}/issues/${r}`}async createIssue(t,r,n){let i=(await V(["issue","create","-R",t,"--title",r,"--body",n,"--label","skillcraft-claim"])).match(/\b(\d+)$/);return i?Number(i[1]):0}async createPullRequest(t,r,n){let i=(await V(["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 a=(await V(["pr","create","--repo",t,"--head",`${r}:${n}`,"--base","main","--title",o,"--body",i])).match(/\b(\d+)$/);return a?Number(a[1]):0}async getIssueStatus(t,r){let n=await V(["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 listClaimIssues(t){let r=await V(["issue","list","--repo",t,"--label","skillcraft-claim","--state","all","--json","number,title,state","--limit","50"]);return JSON.parse(r)}async cloneRepo(t,r){let n=Ke.resolve(r);await V(["repo","clone",t,n])}async copyDirectory(t,r){await z.readdir(r).catch(()=>{})&&await z.rm(r,{recursive:!0,force:!0}),await z.mkdir(r,{recursive:!0}),await Zt(t,r)}};var Cn={gh:()=>new be};function H(e){return Cn[e]()}import{execFile as Sn}from"child_process";import{promisify as $n}from"util";import En from"ora";var In=$n(Sn);async function rr(e){let t=F(e,"skill id"),{owner:r,slug:n}=ke(t),o=process.cwd();if(!await P(o))throw new Error("Repository is not enabled");let i=await Promise.all([O.access(Z.join(o,"SKILL.md")).then(()=>!0).catch(()=>!1),O.access(Z.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 j(),a=H(s.provider??"gh");await a.getUser();let c="skillcraft-gg/skills",g=`skillcraft-skill-${r}-${n}`,l=Z.join(process.cwd(),".skillcraft-temp-skill-publish");try{await O.rm(l,{force:!0,recursive:!0}),await a.cloneRepo(c,l),await Ce(l,["checkout","-B",g]);let d=Z.join(l,"skills",r,n);await O.rm(d,{force:!0,recursive:!0}),await O.mkdir(Z.dirname(d),{recursive:!0}),await O.cp(o,d,{recursive:!0}),await Ce(l,["add",`skills/${r}/${n}`]),await Ce(l,["commit","-m",`Publish skill ${t}`]).catch(()=>{throw new Error("nothing to commit; skill may already be published")}),await Ce(l,["push","-u","origin",g]).catch(()=>{throw new Error("unable to push skill publish branch")}),await a.createPullRequest(c,g,`Publish skill: ${t}`).catch(()=>{process.stdout.write(`unable to create PR automatically. Please open one manually from your branch.
228
+ `)}),process.stdout.write(`published skill ${t} from ${c}
229
+ `)}finally{await O.rm(l,{force:!0,recursive:!0})}}async function nr(e){let t=process.cwd();if(!await P(t))throw new Error("Repository is not enabled");let r=F(e,"skill id"),n=D(r);if(!n.id)throw new Error("invalid skill id format");if(!(await On()).has(n.id))throw new Error(`skill ${n.id} is not listed in the search index`);let i=Pe([`${n.id}${n.version?`@${n.version}`:""}`]),s=await oe(t),a=Pe([...s,...i]);await w(L(t),{skills:a}),process.stdout.write(`queued skill: ${i[0]}
230
+ `)}async function An(){let e=process.cwd(),t=[["SKILL.md",await tr(Z.join(e,"SKILL.md"))],["skill.yaml",await tr(Z.join(e,"skill.yaml"))]];for(let[r,n]of t)process.stdout.write(`${r}: ${n?"ok":"missing"}
231
+ `)}async function or(){let e=process.cwd();if(!await P(e))throw new Error("Repository is not enabled");let[t,r]=await Promise.all([ie(e),oe(e)]),n=new Set;for(let i of t)for(let s of i.skills)n.add(s.id);for(let i of r)n.add(i);if(!n.size){process.stdout.write(`no skills detected
232
+ `);return}let o=Array.from(n).sort().join(`
233
+ `);process.stdout.write(`skills detected (${n.size}):
234
+ ${o}
235
+ `)}async function ir(e,t={}){let r=await Be(t.outputMode);if(!r.length){t.outputMode==="json"?process.stdout.write(`${JSON.stringify({query:e?.trim(),source:t.source?.trim(),limit:er(t.limit),count:0,results:[],message:"no skills indexed"})}
236
+ `):process.stdout.write(`no skills indexed
237
+ `);return}let n=e?.trim().toLowerCase(),o=t.source?.trim().toLowerCase(),i=er(t.limit),a=[...r.filter(d=>o&&Je(d.id)!==o?!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,u)=>{let p=(d.name||d.id).toLowerCase(),m=(u.name||u.id).toLowerCase();return p===m?d.id.localeCompare(u.id):p.localeCompare(m)}),c=a.slice(0,i);if(!c.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:i,count:0,results:[],message:d})}
238
+ `):process.stdout.write(`${d}
239
+ `);return}let g=n?`skills matching "${e?.trim()}"`:"skills index",l=c.map(d=>{let u=(d.runtime||[]).length?` [${d.runtime.join(", ")}]`:"",p=(d.tags||[]).length?` {${d.tags.join(", ")}}`:"",m=Hn(d.updatedAt),x=Dn(d);return`${d.id}${x?` \u2014 ${x}`:""}${u}${p}${m}`});if(t.outputMode==="json"){let d={query:e?.trim(),source:t.source?.trim(),limit:i,count:c.length,total:a.length,results:c.map(u=>({id:u.id,name:u.name,path:u.path,url:u.url,owner:u.owner,slug:u.slug,runtime:u.runtime,tags:u.tags}))};process.stdout.write(`${JSON.stringify(d)}
240
+ `);return}process.stdout.write(`${g} (${c.length}):
241
+ ${l.join(`
242
+ `)}
243
+ `)}async function sr(e,t={}){let r=F(e,"skill id"),n=D(r);if(!n.id)throw new Error("invalid skill id format");let i=(await Be(t.outputMode)).find(c=>c.id===n.id);if(!i)throw new Error(`skill ${n.id} is not listed in the search index`);let s=await jn(i);if(t.outputMode==="json"){let c={id:i.id,name:i.name,source:Je(i.id),owner:i.owner,slug:i.slug,path:i.path,url:i.url,runtime:i.runtime,tags:i.tags,updatedAt:i.updatedAt,manifest:s,version:n.version};process.stdout.write(`${JSON.stringify(c)}
244
+ `);return}let a=Ln(i,s);process.stdout.write(`${a}
245
+ `)}function Ln(e,t){let r=[];r.push(`skill: ${e.id}`),e.name&&r.push(`name: ${e.name}`);let n=Je(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(`
246
+ `)}async function jn(e){let t=qn(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(_n(i))return{url:t,error:"unable to parse manifest (not markdown)"};let s=Fn(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 qn(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 Nn(r)}function Nn(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 a=[o,i,"raw","refs","heads",...s];return`${t.protocol}//${t.host}/${a.join("/")}`}catch{return e}}function _n(e){let t=e.replace(/^\s+/,"").toLowerCase();return t.startsWith("<!doctype html")||t.startsWith("<html")}function Fn(e){let r=e.replace(/\r\n/g,`
247
+ `).split(`
248
+ `),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 a=r[s].trim();if(!a){if(i)break;continue}if(!o&&a.startsWith("#")){o=a.replace(/^#+\s*/,"").trim();continue}if(!i&&!a.startsWith(">")){i=a;break}}return{title:o,summary:i}}function Xt(e){return Array.isArray(e)}async function On(){let e=await Be();return new Set(e.map(t=>t.id))}async function Be(e=void 0){let t=process.env.SKILLCRAFT_SEARCH_INDEX_PATH?.trim(),r=t||process.env.SKILLCRAFT_SEARCH_INDEX_URL||"https://skillcraft.gg/skills/search/index.json",n=async()=>{if(t){let g=await O.readFile(t,"utf8"),l=JSON.parse(g);return Yt(Xt(l)?l:[])}let s=process.env.SKILLCRAFT_SEARCH_INDEX_URL||"https://skillcraft.gg/skills/search/index.json",a=await fetch(s,{headers:{"user-agent":"skillcraft-cli"}});if(!a.ok)throw new Error(`failed to download search index from ${s}`);let c=await a.json();return Yt(Xt(c)?c:[])};if(!Tn(e))return n();let o=t?`reading local index from ${r}`:`downloading index from ${r}`,i=En({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 Tn(e){return e!=="text"?!1:process.stdout.isTTY===!0||process.stderr.isTTY===!0}function Yt(e){return e.map(t=>Mn(t)).filter(t=>!!t)}function Mn(e){let t=ar(e.id),r=wt(t);if(r)return{id:r,name:ae(e.name),path:ae(e.path),url:ae(e.url),owner:ae(e.owner),slug:ae(e.slug),runtime:Qt(e.runtime),tags:Qt(e.tags),updatedAt:ae(e.updatedAt)}}function ar(e){return String(e||"").trim()}function ae(e){return ar(e)||void 0}function Qt(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 Je(e){let t=e.indexOf(":");if(t<1)return;let r=e.slice(0,t).trim();if(r)return r.toLowerCase()}function er(e){let t=e===void 0?20:Math.floor(e);return Number.isFinite(t)&&t>0?t:20}function Dn(e){let t=(e.name||"").trim();if(!t)return"";let r=zn(e);return r&&t.toLowerCase()===r.toLowerCase()?"":t}function zn(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 Hn(e){if(!e)return"";let t=new Date(e);return Number.isNaN(t.getTime())?"":` (updated ${t.toISOString().slice(0,10)})`}async function tr(e){try{return await O.access(e),!0}catch{return!1}}async function Ce(e,t){let{stdout:r}=await In("git",t,{cwd:e});return r.trim()}async function cr(){await An()}async function dr(){let e=process.cwd();if(!await P(e))throw new Error("Repository is not enabled");let r=(await me(e,200)).map(o=>o.message.match(/Skillcraft-Ref:\s*(\S+)/)?.[1]).filter(Boolean),n=0;for(let o of r){let i=await _e(e,o);if(!i){n+=1,process.stdout.write(`missing proof object: ${o}
249
+ `);continue}(!i.commit||!i.timestamp)&&(n+=1,process.stdout.write(`invalid proof object: ${o}
250
+ `))}if(n>0){process.stdout.write(`verify failed: ${n} missing/invalid proofs
251
+ `),process.exitCode=1;return}process.stdout.write(`verify passed: ${r.length} commit proofs resolved
252
+ `)}import{createHash as Kn}from"crypto";import Bn from"yaml";async function Ue(){let e=await j(),r=await H(e.provider??"gh").listClaimIssues("skillcraft-gg/credentials");if(!r.length){process.stdout.write(`no claim issues found
253
+ `);return}for(let n of r)process.stdout.write(`#${n.number} ${n.title} (${n.state})
254
+ `)}async function lr(e){let t=Number(e);if(!t)throw new Error("claim status requires issue number");let r=await j(),o=await H(r.provider??"gh").getIssueStatus("skillcraft-gg/credentials",t);process.stdout.write(`issue #${t}
255
+ `),process.stdout.write(`state: ${o.state}
256
+ `),process.stdout.write(`labels: ${o.labels.join(", ")||"none"}
257
+ `),process.stdout.write(`url: ${o.url}
258
+ `)}async function ur(e,t){let r=await Jn(e,{allRepos:t?.allRepos,repo:t?.repo}),n=Bn.stringify(r),o=await j(),s=await H(o.provider??"gh").createIssue("skillcraft-gg/credentials",`claim: ${e}`,n);process.stdout.write(`opened claim: #${s}
259
+ `),process.stdout.write(`payload:
260
+ ${n}
261
+ `)}async function Jn(e,t){let r=await Un(t),n=[];for(let a of r){let c=await ie(a),g=await T(a)||a,l=Array.from(new Set(c.map(d=>d?.commit).filter(Boolean)));n.push({repo:g,commits:l})}let o=process.env.GITHUB_USER||process.env.USER||"unknown",i=`${o}:${e}:${n.map(a=>`${a.repo}:${a.commits.length}`).join("|")}:${Date.now()}`,s=Kn("sha256").update(i).digest("hex").slice(0,8);return{claim_version:1,claimant:{github:o},credential:{id:e},sources:n,claim_id:`sha256:${s}`}}async function Un(e){let t=e.allRepos?(await _()).repos.map(o=>o.path):[process.cwd()],r=e.repo?e.repo:t,n=[];for(let o of r)await It(o)&&n.push(o);return n}import ue from"path";import X from"fs/promises";import{execFile as Gn}from"child_process";import{promisify as Wn}from"util";var Vn=Wn(Gn);async function mr(e){if(!Le(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(b(t)),n=Array.isArray(r?.activeLoadouts)?r.activeLoadouts.filter(Boolean):[];n.includes(e)||n.push(e),await w(b(t),{activeLoadouts:n}),process.stdout.write(`activated loadout: ${e}
262
+ `)}async function pr(){let e=process.cwd();if(!await P(e))throw new Error("Repository is not enabled");await w(b(e),{activeLoadouts:[]}),process.stdout.write(`cleared active loadouts
263
+ `)}async function fr(e){let t=F(e,"loadout id");if(!Le(t))throw new Error("loadout id must be <owner>/<slug>");let{owner:r,slug:n}=ke(t),o=process.cwd(),i=ue.join(o,"loadout.yaml");if(await X.access(i),!(await X.stat(i)).isFile())throw new Error("loadout.yaml not found in current directory");let a=await j(),c=H(a.provider??"gh"),g="skillcraft-gg/loadouts",l=ue.join(process.cwd(),".skillcraft-temp-loadout-share"),d=`skillcraft-loadout-${r}-${n}`;try{await X.rm(l,{force:!0,recursive:!0}),await c.cloneRepo(g,l),await Se(l,["checkout","-B",d]);let u=ue.join(l,"loadouts",r,n);await X.rm(u,{force:!0,recursive:!0}).catch(()=>{}),await X.mkdir(ue.dirname(u),{recursive:!0}),await X.copyFile(i,ue.join(u,"loadout.yaml")),await Se(l,["add",u]),await Se(l,["commit","-m",`Loadout: publish ${t}`]).catch(async()=>{throw new Error("nothing to commit; loadout may already be published")}),await Se(l,["push","-u","origin",d]).catch(()=>{throw new Error("unable to push loadout publish branch")}),await c.createPullRequest(g,d,`Loadout publish: ${t}`).catch(()=>{process.stdout.write(`unable to create PR automatically. Please open one manually from your branch.
264
+ `)}),process.stdout.write(`loadout publish workflow completed for ${t}
265
+ `)}finally{await X.rm(l,{force:!0,recursive:!0})}}async function Se(e,t){let{stdout:r}=await Vn("git",t,{cwd:e});return r.trim()}async function gr(e){if(!await P(e))return;let t=await te(e),r=new Date().toISOString(),n=await $t(e,t,r);if(!n)return;let o=await Et(e,n.proofId);await rt(e,o);let i=await te(e);i!==t&&await Fe(e,{...n.proof,commit:i}),await w(L(e),{skills:[]})}async function hr(e,t="origin"){await Ct(e,t)}var R=new Zn;R.name("skillcraft").description("Skillcraft CLI").version(Ze.version);R.option("--json","machine-readable JSON output");R.command("enable").description("Enable Skillcraft in the current repository").action(h(jt));R.command("disable").description("Disable Skillcraft in the current repository").action(h(ht));R.command("status").description("Show repository Skillcraft status").action(h(At));R.command("doctor").description("Check environment and integration readiness").action(h(Lt));var wr=R.command("repos").description("Manage tracked repositories");wr.command("list").description("List tracked repositories").action(h(qt));wr.command("prune").description("Remove unavailable repository entries").action(h(Nt));var Ge=R.command("progress").description("Show progress for tracked credentials");Ge.option("--refresh","refresh the local credential index cache before evaluating progress").action((e,t)=>{let r=t.parent?.opts()?.json?"json":"text";h(()=>Ut({outputMode:r,refreshIndex:e.refresh}))()});Ge.command("track <credential-id>").description("Track a credential for local progress evaluation").action(e=>h(()=>Gt(e))());Ge.command("untrack <credential-id>").description("Untrack a credential from local progress evaluation").action(e=>h(()=>Wt(e))());var ce=R.command("skills").description("Manage local skill publishing");ce.command("add <id>").description("Add a local or external skill from the registry index").action(e=>h(()=>nr(e))());ce.command("publish <owner-slug>").description("Publish a skill to the registry").action(e=>h(()=>rr(e))());ce.command("validate").description("Validate local skill layout").action(h(cr));ce.command("list").description("List detected skills in the current repository").action(h(or));ce.command("inspect <id>").description("Show detailed information for a registry skill").action((e,t,r)=>{let n=r.parent?.parent?.opts()?.json?"json":"text";h(()=>sr(e,{outputMode:n}))()});ce.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";h(()=>ir(e,{source:t.source,limit:t.limit,outputMode:n}))()});R.command("verify").description("Verify local Skillcraft proofs and trailers").action(h(dr));var We=R.command("claim").description("Claim a credential or inspect claim issues");We.argument("[credential]","credential identifier").option("--all-repos","include tracked repositories").option("--repo <path...>","explicit repositories to include").action((e,t)=>{if(!e){h(()=>Ue())();return}h(()=>ur(e,{allRepos:t.allRepos,repo:t.repo}))()});We.command("list").description("List claims in the credentials repository").action(h(Ue));We.command("status <issue>").description("Show claim issue status").action(e=>h(()=>lr(e))());var Ve=R.command("loadout").description("Manage active loadouts");Ve.command("use <id>").description("Activate a loadout in local context").action(e=>h(()=>mr(e))());Ve.command("clear").description("Clear active loadouts").action(h(pr));Ve.command("share <id>").description("Publish local loadout to registry").action(e=>h(()=>fr(e))());R.command("_hook <name> [repoPath] [remote]",{hidden:!0}).description("internal hook command").action((e,t,r)=>h(async()=>{e==="post-commit"&&await gr(t||process.cwd()),(e==="pre-push"||e==="post-push")&&await hr(t||process.cwd(),r||"origin")})());function h(e){return(...t)=>{Promise.resolve(e(...t)).catch(r=>{process.stderr.write(`${r instanceof Error?r.message:String(r)}
266
+ `),process.exitCode=1})}}R.parse(process.argv);
267
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../package.json","../src/core/git.ts","../src/core/paths.ts","../src/core/fs.ts","../src/core/hooks.ts","../src/core/types.ts","../src/core/config.ts","../src/commands/disable.ts","../src/core/proof.ts","../src/core/validation.ts","../src/core/state.ts","../src/commands/status.ts","../src/commands/enable.ts","../src/commands/repos.ts","../src/core/progress.ts","../src/core/credentials.ts","../src/lib/output.ts","../src/commands/progress.ts","../src/commands/skills.ts","../src/providers/github.ts","../src/providers/index.ts","../src/commands/verify.ts","../src/commands/claim.ts","../src/commands/loadout.ts","../src/commands/internalHook.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander'\nimport packageJson from '../package.json'\nimport { runDisable } from './commands/disable.js'\nimport { runDoctor, runStatus } from './commands/status.js'\nimport { runEnable } from './commands/enable.js'\nimport { runReposList, runReposPrune } from './commands/repos.js'\nimport { runProgress, runProgressTrack, runProgressUntrack } from './commands/progress.js'\nimport {\n runSkillsAdd,\n runSkillsInspect,\n runSkillsList,\n runSkillsPublish,\n runSkillsSearch,\n runSkillsValidateAndExit,\n} from './commands/skills.js'\nimport { runVerify } from './commands/verify.js'\nimport { runClaim, runClaimList, runClaimStatus } from './commands/claim.js'\nimport { runLoadoutUse, runLoadoutClear, runLoadoutShare } from './commands/loadout.js'\nimport { runHook } from './commands/internalHook.js'\nimport { runHookPush } from './commands/internalHook.js'\n\nconst program = new Command()\n\nprogram.name('skillcraft').description('Skillcraft CLI').version(packageJson.version)\nprogram.option('--json', 'machine-readable JSON output')\n\nprogram\n .command('enable')\n .description('Enable Skillcraft in the current repository')\n .action(withCommand(runEnable))\n\nprogram\n .command('disable')\n .description('Disable Skillcraft in the current repository')\n .action(withCommand(runDisable))\n\nprogram\n .command('status')\n .description('Show repository Skillcraft status')\n .action(withCommand(runStatus))\n\nprogram\n .command('doctor')\n .description('Check environment and integration readiness')\n .action(withCommand(runDoctor))\n\nconst reposCommand = program.command('repos').description('Manage tracked repositories')\nreposCommand.command('list').description('List tracked repositories').action(withCommand(runReposList))\nreposCommand.command('prune').description('Remove unavailable repository entries').action(withCommand(runReposPrune))\n\nconst progressCommand = program.command('progress').description('Show progress for tracked credentials')\nprogressCommand\n.option('--refresh', 'refresh the local credential index cache before evaluating progress')\n.action((options, command) => {\n const outputMode = command.parent?.opts()?.json ? 'json' : 'text'\n withCommand(() => runProgress({ outputMode, refreshIndex: options.refresh }))()\n})\n\nprogressCommand\n .command('track <credential-id>')\n .description('Track a credential for local progress evaluation')\n .action((credentialId: string) => withCommand(() => runProgressTrack(credentialId))())\n\nprogressCommand\n .command('untrack <credential-id>')\n .description('Untrack a credential from local progress evaluation')\n .action((credentialId: string) => withCommand(() => runProgressUntrack(credentialId))())\n\nconst skillsCommand = program.command('skills').description('Manage local skill publishing')\nskillsCommand\n .command('add <id>')\n .description('Add a local or external skill from the registry index')\n .action((id) => withCommand(() => runSkillsAdd(id))())\n\nskillsCommand\n .command('publish <owner-slug>')\n .description('Publish a skill to the registry')\n .action((ownerSlug) => withCommand(() => runSkillsPublish(ownerSlug))())\n\nskillsCommand\n .command('validate')\n .description('Validate local skill layout')\n .action(withCommand(runSkillsValidateAndExit))\n\nskillsCommand\n .command('list')\n .description('List detected skills in the current repository')\n .action(withCommand(runSkillsList))\n\nskillsCommand\n .command('inspect <id>')\n .description('Show detailed information for a registry skill')\n .action((id, _options, command) => {\n const outputMode = command.parent?.parent?.opts()?.json ? 'json' : 'text'\n withCommand(() => runSkillsInspect(id, { outputMode }))()\n })\n\nskillsCommand\n .command('search [query]')\n .description('Search the published skill index')\n .option('--source <source>', 'filter to a registry source')\n .option('--limit <n>', 'limit number of results', (value) => Number.parseInt(value, 10))\n .action((query, options, command) => {\n const outputMode = command.parent?.parent?.opts()?.json ? 'json' : 'text'\n withCommand(() => runSkillsSearch(query, { source: options.source, limit: options.limit, outputMode }))()\n })\n\nprogram\n .command('verify')\n .description('Verify local Skillcraft proofs and trailers')\n .action(withCommand(runVerify))\n\nconst claimCommand = program.command('claim').description('Claim a credential or inspect claim issues')\nclaimCommand\n .argument('[credential]', 'credential identifier')\n .option('--all-repos', 'include tracked repositories')\n .option('--repo <path...>', 'explicit repositories to include')\n .action((credential: string | undefined, options) => {\n if (!credential) {\n withCommand(() => runClaimList())()\n return\n }\n withCommand(() =>\n runClaim(credential, {\n allRepos: options.allRepos,\n repo: options.repo,\n }),\n )()\n })\n\nclaimCommand\n .command('list')\n .description('List claims in the credentials repository')\n .action(withCommand(runClaimList))\n\nclaimCommand\n .command('status <issue>')\n .description('Show claim issue status')\n .action((issue) => withCommand(() => runClaimStatus(issue))())\n\nconst loadoutCommand = program.command('loadout').description('Manage active loadouts')\nloadoutCommand\n .command('use <id>')\n .description('Activate a loadout in local context')\n .action((id) => withCommand(() => runLoadoutUse(id))())\n\nloadoutCommand\n .command('clear')\n .description('Clear active loadouts')\n .action(withCommand(runLoadoutClear))\n\nloadoutCommand\n .command('share <id>')\n .description('Publish local loadout to registry')\n .action((id) => withCommand(() => runLoadoutShare(id))())\n\nprogram\n .command('_hook <name> [repoPath] [remote]', { hidden: true })\n .description('internal hook command')\n .action((name, repoPath, remote) => withCommand(async () => {\n if (name === 'post-commit') {\n await runHook(repoPath || process.cwd())\n }\n if (name === 'pre-push' || name === 'post-push') {\n await runHookPush(repoPath || process.cwd(), remote || 'origin')\n }\n })())\n\nfunction withCommand<T extends (...args: readonly unknown[]) => Promise<void> | void>(fn: T): (...args: Parameters<T>) => void {\n return (...args: Parameters<T>) => {\n void Promise.resolve(fn(...args)).catch((error) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n process.exitCode = 1\n })\n }\n}\n\nprogram.parse(process.argv)\n","{\n \"name\": \"skillcraft\",\n \"version\": \"0.1.1\",\n \"description\": \"Skillcraft CLI for git-native skill evidence and credential workflow\",\n \"type\": \"module\",\n \"bin\": {\n \"skillcraft\": \"dist/index.js\"\n },\n \"files\": [\n \"dist/index.js\",\n \"dist/index.js.map\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"clean\": \"rm -rf dist\",\n \"test\": \"npm run build && node --test tests/*.test.mjs\",\n \"smoke\": \"npm test\",\n \"format\": \"printf ''\",\n \"start\": \"node dist/index.js\",\n \"check\": \"tsc --noEmit\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"dependencies\": {\n \"commander\": \"^13.1.0\",\n \"ora\": \"^8.2.0\",\n \"yaml\": \"^2.6.0\",\n \"zod\": \"^3.24.2\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.8.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.7.2\"\n }\n}\n","import { execFile as execFileCb } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport path from 'node:path'\n\nconst execFile = promisify(execFileCb)\n\ntype GitOptions = {\n env?: NodeJS.ProcessEnv\n}\n\nexport async function git(args: readonly string[], cwd: string, options: GitOptions = {}): Promise<string> {\n try {\n const { stdout } = await execFile('git', args, {\n cwd,\n encoding: 'utf8',\n maxBuffer: 10 * 1024 * 1024,\n env: options.env,\n })\n return stdout.trim()\n } catch (error) {\n const message = (error as { message?: string }).message ?? String(error)\n throw new Error(`git command failed in ${cwd}: ${message}`)\n }\n}\n\nexport async function isGitRepo(cwd: string): Promise<boolean> {\n try {\n await git(['rev-parse', '--git-dir'], cwd)\n return true\n } catch {\n return false\n }\n}\n\nexport async function gitRoot(cwd: string): Promise<string> {\n return path.resolve(await git(['rev-parse', '--show-toplevel'], cwd))\n}\n\nexport async function gitRemote(cwd: string, remote = 'origin'): Promise<string | undefined> {\n try {\n const value = await git(['config', '--get', `remote.${remote}.url`], cwd)\n return value || undefined\n } catch {\n return undefined\n }\n}\n\nexport async function gitCommitMessage(cwd: string, commit = 'HEAD'): Promise<string> {\n return git(['log', '--format=%B', '-n', '1', commit], cwd)\n}\n\nexport async function gitHeadCommit(cwd: string): Promise<string> {\n return (await git(['rev-parse', 'HEAD'], cwd)).trim()\n}\n\nexport async function gitHasRef(cwd: string, ref: string): Promise<boolean> {\n try {\n await git(['show-ref', '--verify', '--quiet', ref], cwd)\n return true\n } catch {\n return false\n }\n}\n\nexport async function gitLsTreeNames(cwd: string, ref: string, subPath?: string): Promise<string[]> {\n try {\n const raw = await git(['ls-tree', '-r', '--name-only', ref, '--', ...(subPath ? [subPath] : [])], cwd)\n return raw ? raw.split('\\n').filter(Boolean) : []\n } catch {\n return []\n }\n}\n\nexport async function gitShowText(cwd: string, ref: string, filePath: string): Promise<string | undefined> {\n try {\n return await git(['show', `${ref}:${filePath}`], cwd)\n } catch {\n return undefined\n }\n}\n\nexport async function gitLogWithMessages(cwd: string, maxCount?: number): Promise<Array<{ commit: string; message: string }>> {\n const n = maxCount ? String(maxCount) : '200'\n const raw = await git(['log', `--max-count=${n}`, '--pretty=%H%x00%B'], cwd)\n if (!raw) {\n return []\n }\n return raw\n .split('\\u0000')\n .filter(Boolean)\n .map((entry) => {\n const [commit, ...messageParts] = entry.split('\\n')\n const message = messageParts.join('\\n').trimEnd()\n return { commit, message }\n })\n}\n\nexport async function amendCommitMessage(cwd: string, message: string): Promise<string> {\n const env = { ...process.env, SKILLCRAFT_HOOK_DISABLED: '1' }\n const tempFile = path.join(cwd, '.git', 'SKILLCRAFT_COMMIT_MESSAGE')\n const { writeFile } = await import('node:fs/promises')\n await writeFile(tempFile, `${message}\\n`, 'utf8')\n await execFile('git', ['commit', '--amend', '--file', tempFile, '--no-gpg-sign'], {\n cwd,\n encoding: 'utf8',\n env,\n })\n return gitHeadCommit(cwd)\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport os from 'node:os'\n\nfunction defaultUserDir(): string {\n return path.resolve(process.env.HOME || os.homedir(), '.skillcraft')\n}\n\nexport function skillcraftGlobalDir(): string {\n return defaultUserDir()\n}\n\nexport function skillcraftConfigPath(): string {\n return path.join(skillcraftGlobalDir(), 'config.json')\n}\n\nexport function skillcraftReposPath(): string {\n return path.join(skillcraftGlobalDir(), 'repos.json')\n}\n\nexport function trackedCredentialsPath(): string {\n return path.join(skillcraftGlobalDir(), 'credentials.json')\n}\n\nexport function credentialIndexCachePath(): string {\n return path.join(skillcraftGlobalDir(), 'cache', 'credentials', 'index.json')\n}\n\nexport function localStateDir(repoPath: string): string {\n return path.join(repoPath, '.skillcraft')\n}\n\nexport function localGitDir(repoPath: string): string {\n return path.join(repoPath, '.git', 'skillcraft')\n}\n\nexport function localSkillcraftConfig(repoPath: string): string {\n return path.join(localStateDir(repoPath), '.skillcraft.json')\n}\n\nexport function localRepoHookPath(repoPath: string): string {\n return path.join(repoPath, '.git', 'hooks', 'post-commit')\n}\n\nexport function localRepoPrePushHookPath(repoPath: string): string {\n return path.join(repoPath, '.git', 'hooks', 'pre-push')\n}\n\nexport function localRepoPostPushHookPath(repoPath: string): string {\n return path.join(repoPath, '.git', 'hooks', 'post-push')\n}\n\nexport function pendingPath(repoPath: string): string {\n return path.join(localGitDir(repoPath), 'pending.json')\n}\n\nexport function contextPath(repoPath: string): string {\n return path.join(localGitDir(repoPath), 'context.json')\n}\n\nexport function pluginPath(repoPath: string): string {\n return path.join(localGitDir(repoPath), 'agent.json')\n}\n\nexport function managedPluginPath(repoPath: string): string {\n return path.join(repoPath, '.opencode', 'plugins', 'skillcraft.mjs')\n}\n\nexport function aiModelContextPath(repoPath: string): string {\n return path.join(localGitDir(repoPath), 'ai-model-context.json')\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath)\n return true\n } catch {\n return false\n }\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true })\n}\n\nexport async function readText(filePath: string): Promise<string> {\n const data = await fs.readFile(filePath, 'utf8')\n return data\n}\n\nexport async function writeText(filePath: string, content: string): Promise<void> {\n await ensureDir(path.dirname(filePath))\n await fs.writeFile(filePath, content, 'utf8')\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath)\n return true\n } catch {\n return false\n }\n}\n\nexport async function readJson<T>(filePath: string): Promise<T | null> {\n if (!(await fileExists(filePath))) {\n return null\n }\n const raw = await readText(filePath)\n return JSON.parse(raw) as T\n}\n\nexport async function writeJson(filePath: string, value: unknown): Promise<void> {\n const json = JSON.stringify(value, null, 2)\n await writeText(filePath, `${json}\\n`)\n}\n\nexport async function removeFile(filePath: string): Promise<void> {\n try {\n await fs.rm(filePath, { force: true })\n } catch {\n // best effort cleanup\n }\n}\n","import { writeText } from './fs.js'\nimport { localRepoHookPath, localRepoPrePushHookPath, localRepoPostPushHookPath } from './paths.js'\nimport fs from 'node:fs/promises'\n\nfunction buildHookScript(body: string): string {\n const rawCliPath = process.argv[1] || ''\n const cliPath = JSON.stringify(rawCliPath)\n return `#!/usr/bin/env sh\nif [ -n \"$SKILLCRAFT_HOOK_DISABLED\" ]; then\n exit 0\nfi\n\nrun_skillcraft_hook() {\n if command -v skillcraft >/dev/null 2>&1; then\n skillcraft \"$@\"\n return\n fi\n\n local cli=${cliPath}\n if [ -n \"$cli\" ] && [ -f \"$cli\" ]; then\n case \"$cli\" in\n *.js|*.mjs)\n node \"$cli\" \"$@\"\n ;;\n *)\n \"$cli\" \"$@\"\n ;;\n esac\n return\n fi\n}\n\n${body}\n`\n}\n\nconst postCommitScript = buildHookScript(`SKILLCRAFT_HOOK_DIR=\"$PWD\"\nrun_skillcraft_hook _hook post-commit \"$SKILLCRAFT_HOOK_DIR\" || true`)\n\nconst postPushScript = buildHookScript(`SKILLCRAFT_HOOK_DIR=\"$PWD\"\nSKILLCRAFT_HOOK_REMOTE=\"$1\"\nrun_skillcraft_hook _hook post-push \"$SKILLCRAFT_HOOK_DIR\" \"$SKILLCRAFT_HOOK_REMOTE\" || true`)\n\nconst prePushScript = buildHookScript(`SKILLCRAFT_HOOK_DIR=\"$PWD\"\nSKILLCRAFT_HOOK_REMOTE=\"$1\"\nrun_skillcraft_hook _hook post-push \"$SKILLCRAFT_HOOK_DIR\" \"$SKILLCRAFT_HOOK_REMOTE\" || true`)\n\nexport async function installPostCommitHook(repoPath: string): Promise<void> {\n await writeText(localRepoHookPath(repoPath), `${postCommitScript}\\n`)\n await fs.chmod(localRepoHookPath(repoPath), 0o755)\n\n await writeText(localRepoPostPushHookPath(repoPath), `${postPushScript}\\n`)\n await fs.chmod(localRepoPostPushHookPath(repoPath), 0o755)\n\n await writeText(localRepoPrePushHookPath(repoPath), `${prePushScript}\\n`)\n await fs.chmod(localRepoPrePushHookPath(repoPath), 0o755)\n}\n\nexport async function removePostCommitHook(repoPath: string): Promise<void> {\n await Promise.all([\n fs.rm(localRepoHookPath(repoPath), { force: true }),\n fs.rm(localRepoPostPushHookPath(repoPath), { force: true }),\n fs.rm(localRepoPrePushHookPath(repoPath), { force: true }),\n ])\n}\n","import { z } from 'zod'\n\nexport const ProofVersionSchema = z.literal(1)\n\nexport const DefaultProofRef = 'skillcraft/proofs/v1'\n\nexport const PendingSchema = z.object({\n skills: z.array(z.string()).default([]),\n})\n\nexport const ContextSchema = z.object({\n activeLoadouts: z.array(z.string()).default([]),\n})\n\nexport const ProofAgentSchema = z.object({\n provider: z.string().optional(),\n})\n\nexport const ProofModelSchema = z.object({\n provider: z.string().optional(),\n name: z.string().optional(),\n})\n\nexport const ConfigSchema = z.object({\n githubUser: z.string().optional(),\n provider: z.enum(['gh']).default('gh'),\n version: z.number().int().default(1),\n proofRef: z.string().default(DefaultProofRef),\n})\n\nexport const RepoEntrySchema = z.object({\n path: z.string(),\n remote: z.string().optional(),\n enabledAt: z.string().optional(),\n})\n\nexport const ReposFileSchema = z.object({\n repos: z.array(RepoEntrySchema).default([]),\n})\n\nexport const TrackedCredentialSchema = z.object({\n id: z.string(),\n trackedAt: z.string().optional(),\n})\n\nexport const TrackedCredentialsFileSchema = z.object({\n credentials: z.array(TrackedCredentialSchema).default([]),\n})\n\nexport type Proof = {\n version: number\n commit: string\n skills: Array<{ id: string; version?: string }>\n loadouts: string[]\n timestamp: string\n agent?: {\n provider?: string\n }\n model?: {\n provider?: string\n name?: string\n }\n}\n\nexport type RepoEntry = z.infer<typeof RepoEntrySchema>\nexport type ReposFile = z.infer<typeof ReposFileSchema>\nexport type TrackedCredentialEntry = z.infer<typeof TrackedCredentialSchema>\nexport type TrackedCredentialsFile = z.infer<typeof TrackedCredentialsFileSchema>\nexport type Config = z.infer<typeof ConfigSchema>\nexport type PendingFile = z.infer<typeof PendingSchema>\nexport type ContextFile = z.infer<typeof ContextSchema>\n\nexport type CliCommandResult = {\n ok: boolean\n message: string\n data?: unknown\n}\n","import { skillcraftGlobalDir, skillcraftConfigPath, skillcraftReposPath, trackedCredentialsPath, localSkillcraftConfig } from './paths.js'\nimport {\n ConfigSchema,\n ReposFileSchema,\n RepoEntry,\n TrackedCredentialsFileSchema,\n type Config,\n type ReposFile,\n type TrackedCredentialEntry,\n type TrackedCredentialsFile,\n} from './types.js'\nimport { ensureDir, readJson, writeJson } from './fs.js'\n\nexport async function loadGlobalConfig(): Promise<Config> {\n const raw = await readJson<unknown>(skillcraftConfigPath())\n const parsed = ConfigSchema.safeParse(raw ?? {})\n if (!parsed.success) {\n return ConfigSchema.parse({})\n }\n return parsed.data\n}\n\nexport async function loadLocalConfig(repoPath: string): Promise<Config> {\n const raw = await readJson<unknown>(localSkillcraftConfig(repoPath))\n const parsed = ConfigSchema.safeParse(raw ?? {})\n if (!parsed.success) {\n return ConfigSchema.parse({})\n }\n\n return parsed.data\n}\n\nexport async function saveGlobalConfig(config: Config): Promise<void> {\n await ensureDir(skillcraftGlobalDir())\n await writeJson(skillcraftConfigPath(), config)\n}\n\nexport async function loadRepos(): Promise<ReposFile> {\n const raw = await readJson<unknown>(skillcraftReposPath())\n const parsed = ReposFileSchema.safeParse(raw ?? {})\n if (!parsed.success) {\n return { repos: [] }\n }\n return parsed.data\n}\n\nexport async function saveRepos(file: ReposFile): Promise<void> {\n await ensureDir(skillcraftGlobalDir())\n await writeJson(skillcraftReposPath(), file)\n}\n\nexport async function addRepo(entry: RepoEntry): Promise<void> {\n const repos = await loadRepos()\n const next = repos.repos.filter((item) => item.path !== entry.path)\n next.push(entry)\n await saveRepos({ repos: next })\n}\n\nexport async function removeRepo(repoPath: string): Promise<void> {\n const repos = await loadRepos()\n const next = repos.repos.filter((item) => item.path !== repoPath)\n await saveRepos({ repos: next })\n}\n\nexport async function loadTrackedCredentials(): Promise<TrackedCredentialsFile> {\n const raw = await readJson<unknown>(trackedCredentialsPath())\n const parsed = TrackedCredentialsFileSchema.safeParse(raw ?? {})\n if (!parsed.success) {\n return { credentials: [] }\n }\n return parsed.data\n}\n\nexport async function saveTrackedCredentials(file: TrackedCredentialsFile): Promise<void> {\n await ensureDir(skillcraftGlobalDir())\n await writeJson(trackedCredentialsPath(), file)\n}\n\nexport async function addTrackedCredential(id: string): Promise<boolean> {\n const current = await loadTrackedCredentials()\n if (current.credentials.some((entry) => entry.id === id)) {\n return false\n }\n\n current.credentials.push({ id, trackedAt: new Date().toISOString() })\n current.credentials.sort(sortTrackedCredentialEntries)\n await saveTrackedCredentials(current)\n return true\n}\n\nexport async function removeTrackedCredential(id: string): Promise<boolean> {\n const current = await loadTrackedCredentials()\n const before = current.credentials.length\n const next = current.credentials.filter((entry) => entry.id !== id)\n if (next.length === before) {\n return false\n }\n await saveTrackedCredentials({ credentials: next })\n return true\n}\n\nexport function sortTrackedCredentialEntries(a: TrackedCredentialEntry, b: TrackedCredentialEntry): number {\n return a.id.localeCompare(b.id)\n}\n\nexport function reposByPath(repos: ReposFile, repoPath: string): RepoEntry | undefined {\n return repos.repos.find((r) => r.path === repoPath)\n}\n","import { isGitRepo, gitRoot } from '@/core/git'\nimport {\n localGitDir,\n localSkillcraftConfig,\n pendingPath,\n contextPath,\n pluginPath,\n managedPluginPath,\n aiModelContextPath,\n} from '@/core/paths'\nimport { removePostCommitHook } from '@/core/hooks'\nimport { removeFile } from '@/core/fs'\nimport { removeRepo } from '@/core/config'\n\nexport async function runDisable(): Promise<void> {\n const cwd = process.cwd()\n if (!(await isGitRepo(cwd))) {\n throw new Error('Current directory is not a git repository')\n }\n const root = await gitRoot(cwd)\n\n await Promise.all([\n removeFile(localSkillcraftConfig(root)),\n removeFile(pendingPath(root)),\n removeFile(contextPath(root)),\n removeFile(pluginPath(root)),\n removeFile(managedPluginPath(root)),\n removeFile(aiModelContextPath(root)),\n removeFile(localGitDir(root)),\n ])\n await removePostCommitHook(root)\n await removeRepo(root)\n process.stdout.write(`disabled skillcraft for ${root}\\n`)\n}\n","import { createHash } from 'node:crypto'\nimport path from 'node:path'\nimport os from 'node:os'\nimport fs from 'node:fs/promises'\nimport { ensureDir, readJson, writeJson } from './fs.js'\nimport { pendingPath, contextPath, aiModelContextPath } from './paths.js'\nimport { DefaultProofRef, PendingSchema, ContextSchema, type Proof } from './types.js'\nimport { git, gitCommitMessage, gitHasRef, gitLsTreeNames, gitRemote, gitShowText } from './git.js'\nimport { isValidSkillIdentifier, splitSkillIdentifier } from './validation.js'\nimport { loadLocalConfig } from './config.js'\n\nconst PROOFS_DIR = 'proofs'\n\nfunction normalizeProofBranch(proofRef?: string): string {\n const clean = proofRef?.trim() || DefaultProofRef\n return clean.replace(/^refs\\/heads\\//, '')\n}\n\nfunction proofPathForId(proofId: string): string {\n return `${PROOFS_DIR}/${proofId}.json`\n}\n\nasync function proofBranch(repoPath: string): Promise<string> {\n const config = await loadLocalConfig(repoPath)\n return normalizeProofBranch(config.proofRef)\n}\n\nasync function proofSearchRefs(repoPath: string, branch: string): Promise<string[]> {\n const normalized = normalizeProofBranch(branch)\n const localRef = `refs/heads/${normalized}`\n const remoteRef = `refs/remotes/origin/${normalized}`\n const refs = [] as string[]\n\n if (await gitHasRef(repoPath, localRef)) {\n refs.push(normalized)\n }\n if (await gitHasRef(repoPath, remoteRef)) {\n refs.push(`origin/${normalized}`)\n }\n\n if (!refs.length) {\n refs.push(normalized)\n }\n\n return refs\n}\n\nasync function ensureProofBranch(repoPath: string, branch: string): Promise<void> {\n const fullRef = `refs/heads/${branch}`\n if (await gitHasRef(repoPath, fullRef)) {\n return\n }\n\n await git(['branch', branch], repoPath)\n}\n\nasync function withProofWorktree<T>(repoPath: string, branch: string, action: (worktree: string) => Promise<T>): Promise<T> {\n await removeProofWorktrees(repoPath, branch)\n const worktree = await fs.mkdtemp(path.join(os.tmpdir(), 'skillcraft-proof-'))\n\n try {\n await git(['worktree', 'add', '--quiet', worktree, branch], repoPath)\n return await action(worktree)\n } finally {\n await removeProofWorktree(repoPath, worktree)\n }\n}\n\nasync function removeProofWorktree(repoPath: string, worktreePath: string): Promise<void> {\n try {\n await git(['worktree', 'remove', '--force', worktreePath], repoPath)\n } catch {\n await fs.rm(worktreePath, { force: true, recursive: true })\n }\n}\n\nasync function removeProofWorktrees(repoPath: string, branch: string): Promise<void> {\n const targetRef = `refs/heads/${branch}`\n\n try {\n const raw = await git(['worktree', 'list', '--porcelain'], repoPath)\n const lines = raw.split('\\n')\n let currentWorktree: string | undefined\n let currentBranch: string | undefined\n\n const maybeRemove = async () => {\n if (!currentWorktree || currentBranch !== targetRef) {\n return\n }\n await removeProofWorktree(repoPath, currentWorktree)\n }\n\n for (const line of lines) {\n if (!line) {\n currentWorktree = undefined\n currentBranch = undefined\n continue\n }\n\n if (line.startsWith('worktree ')) {\n await maybeRemove()\n currentWorktree = line.slice(9)\n currentBranch = undefined\n continue\n }\n\n if (line.startsWith('branch ')) {\n currentBranch = line.slice(7)\n }\n }\n\n await maybeRemove()\n } catch {\n return\n }\n}\n\nexport async function loadProofsFromRepo(repoPath: string): Promise<Proof[]> {\n const branch = await proofBranch(repoPath)\n const searchRefs = await proofSearchRefs(repoPath, branch)\n const files = new Set<string>()\n\n for (const proofRef of searchRefs) {\n const listed = await gitLsTreeNames(repoPath, proofRef, PROOFS_DIR)\n for (const file of listed) {\n files.add(file)\n }\n }\n\n const proofs: Proof[] = []\n\n for (const file of files) {\n if (!file.endsWith('.json')) {\n continue\n }\n\n const proofId = path.basename(file, '.json')\n const proof = await readProof(repoPath, proofId)\n if (proof) {\n proofs.push(proof)\n }\n }\n\n return proofs\n}\n\nfunction parseSkillFromRaw(value: string): { id: string; version?: string } | undefined {\n const parsed = splitSkillIdentifier(value)\n if (!parsed.id) {\n return undefined\n }\n\n if (!isValidSkillIdentifier(parsed.id)) {\n return undefined\n }\n\n return {\n id: parsed.id,\n version: parsed.version,\n }\n}\n\nexport function normalizeSkillIds(raw: string[]): string[] {\n const normalized = raw\n .filter(Boolean)\n .map((item) => splitSkillIdentifier(item))\n .filter((entry): entry is { id: string; version?: string; slug: string } => !!entry.id)\n .map((entry) => `${entry.id}${entry.version ? `@${entry.version}` : ''}`)\n\n return Array.from(new Set(normalized)).filter(isValidSkillIdentifier).sort()\n}\n\nexport function buildProofId(skills: string[], timestamp: string, loadouts: string[]): string {\n const normalized = {\n skills,\n loadouts,\n timestamp,\n }\n const digest = createHash('sha256').update(JSON.stringify(normalized)).digest('hex')\n return digest.slice(0, 8)\n}\n\nexport async function loadPending(repoPath: string): Promise<string[]> {\n const raw = await readJson<unknown>(pendingPath(repoPath))\n const parsed = PendingSchema.safeParse(raw ?? { skills: [] })\n return parsed.success ? normalizeSkillIds(parsed.data.skills) : []\n}\n\nexport async function loadContext(repoPath: string): Promise<string[]> {\n const raw = await readJson<unknown>(contextPath(repoPath))\n const parsed = ContextSchema.safeParse(raw ?? { activeLoadouts: [] })\n return parsed.success ? parsed.data.activeLoadouts : []\n}\n\nexport async function loadAiModelContext(repoPath: string): Promise<{ agent?: { provider?: string }; model?: { provider?: string; name?: string } }> {\n const raw = await readJson<unknown>(aiModelContextPath(repoPath))\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n return {}\n }\n\n const record = raw as Record<string, unknown>\n const agentValue = record.agent && typeof record.agent === 'object' && !Array.isArray(record.agent)\n ? (record.agent as Record<string, unknown>)\n : undefined\n\n const modelValue = record.model && typeof record.model === 'object' && !Array.isArray(record.model)\n ? (record.model as Record<string, unknown>)\n : undefined\n\n return {\n agent: typeof agentValue?.provider === 'string' ? { provider: normalizeLowerCase(agentValue.provider) } : undefined,\n model:\n typeof modelValue?.provider === 'string' || typeof modelValue?.name === 'string'\n ? {\n provider: typeof modelValue.provider === 'string' ? normalizeLowerCase(modelValue.provider) : undefined,\n name: typeof modelValue.name === 'string' ? normalizeModelName(modelValue.name) : undefined,\n }\n : undefined,\n }\n}\n\nfunction normalizeLowerCase(value: string): string {\n return value.trim().toLowerCase()\n}\n\nfunction normalizeModelName(value: string): string {\n return value.trim()\n}\n\nexport function parseProof(payload: unknown): Proof | undefined {\n if (!payload || typeof payload !== 'object') {\n return undefined\n }\n const record = payload as Record<string, unknown>\n if (typeof record.version !== 'number' || typeof record.commit !== 'string' || !Array.isArray(record.skills)) {\n return undefined\n }\n if (!record.timestamp || typeof record.timestamp !== 'string') {\n return undefined\n }\n const loadouts = Array.isArray(record.loadouts) ? record.loadouts.map(String) : []\n const skills = record.skills\n .map((entry) => {\n if (typeof entry === 'string') {\n return { id: entry }\n }\n if (entry && typeof entry === 'object' && 'id' in entry && typeof entry.id === 'string') {\n return { id: entry.id, version: typeof entry.version === 'string' ? entry.version : undefined }\n }\n return undefined\n })\n .filter((entry): entry is { id: string; version?: string } => !!entry)\n return {\n version: record.version,\n commit: record.commit,\n skills,\n loadouts,\n timestamp: record.timestamp,\n agent: parseAgentValue(record.agent),\n model: parseModelValue(record.model),\n }\n}\n\nfunction parseAgentValue(value: unknown): { provider?: string } | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined\n }\n\n const provider = (value as Record<string, unknown>).provider\n if (typeof provider !== 'string') {\n return undefined\n }\n\n const normalized = provider.trim().toLowerCase()\n return normalized ? { provider: normalized } : undefined\n}\n\nfunction parseModelValue(value: unknown): { provider?: string; name?: string } | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined\n }\n\n const raw = value as Record<string, unknown>\n const normalizedProvider = typeof raw.provider === 'string' ? raw.provider.trim().toLowerCase() : undefined\n const normalizedName = typeof raw.name === 'string' ? raw.name.trim() : undefined\n\n if (!normalizedProvider && !normalizedName) {\n return undefined\n }\n\n return {\n provider: normalizedProvider,\n name: normalizedName,\n }\n}\n\nexport async function readProof(repoPath: string, proofId: string): Promise<Proof | undefined> {\n const branch = await proofBranch(repoPath)\n const file = proofPathForId(proofId)\n const searchRefs = await proofSearchRefs(repoPath, branch)\n\n for (const proofRef of searchRefs) {\n const payload = await gitShowText(repoPath, proofRef, file)\n if (!payload) {\n continue\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(payload)\n } catch {\n continue\n }\n\n const proof = parseProof(parsed)\n if (proof) {\n return proof\n }\n }\n\n return undefined\n}\n\nexport async function writeProof(repoPath: string, proof: Proof): Promise<string> {\n const proofId = buildProofId(proof.skills.map((skill) => skill.id), proof.timestamp, proof.loadouts)\n const branch = await proofBranch(repoPath)\n await ensureProofBranch(repoPath, branch)\n\n const proofFile = proofPathForId(proofId)\n await withProofWorktree(repoPath, branch, async (worktree) => {\n await ensureDir(path.join(worktree, PROOFS_DIR))\n await writeJson(path.join(worktree, proofFile), proof)\n await git(['add', proofFile], worktree, { env: { ...process.env, SKILLCRAFT_HOOK_DISABLED: '1' } })\n\n const status = await git(\n ['status', '--porcelain', '--', proofFile],\n worktree,\n { env: { ...process.env, SKILLCRAFT_HOOK_DISABLED: '1' } },\n )\n if (!status) {\n return\n }\n\n await git(\n ['commit', '--no-gpg-sign', '-m', `add Skillcraft proof ${proofId}`],\n worktree,\n { env: { ...process.env, SKILLCRAFT_HOOK_DISABLED: '1' } },\n )\n })\n\n return proofId\n}\n\nexport async function pushProofBranch(repoPath: string, remoteName = 'origin'): Promise<void> {\n const branch = await proofBranch(repoPath)\n const remote = await gitRemote(repoPath, remoteName)\n if (!remote || !remoteName) {\n return\n }\n\n try {\n await git(['push', remoteName, `${branch}:${branch}`], repoPath, { env: { ...process.env, SKILLCRAFT_HOOK_DISABLED: '1' } })\n } catch {\n return\n }\n}\n\nexport async function currentProofIdForCommit(repoPath: string, commit: string): Promise<string | undefined> {\n const proofs = await loadProofsFromRepo(repoPath)\n\n for (const proof of proofs) {\n if (proof.commit === commit) {\n return buildProofId(\n proof.skills.map((skill) => skill.id),\n proof.timestamp,\n proof.loadouts,\n )\n }\n }\n return undefined\n}\n\nexport async function buildProofFromPending(\n repoPath: string,\n commit: string,\n timestamp: string = new Date().toISOString(),\n): Promise<{ proofId: string; proof: Proof } | undefined> {\n const pending = await loadPending(repoPath)\n if (!pending.length) {\n return undefined\n }\n const loadouts = await loadContext(repoPath)\n const aiModelContext = await loadAiModelContext(repoPath)\n\n const proof: Proof = {\n version: 1,\n commit,\n skills: pending\n .map((skill) => parseSkillFromRaw(skill))\n .filter((entry): entry is { id: string; version?: string } => !!entry),\n loadouts,\n timestamp,\n ...aiModelContext,\n }\n\n const proofId = await writeProof(repoPath, proof)\n return { proofId, proof }\n}\n\nexport async function stripDraftMessage(message: string): Promise<string> {\n return message\n .replace(/\\nSkillcraft-Ref: .*$/gm, '')\n .trimEnd()\n}\n\nexport async function buildCommitMessageWithProof(repoPath: string, proofId: string): Promise<string> {\n const existing = await gitCommitMessage(repoPath)\n const cleaned = await stripDraftMessage(existing)\n if (cleaned.includes('Skillcraft-Ref:')) {\n return cleaned\n }\n return `${cleaned}\\n\\nSkillcraft-Ref: ${proofId}\\n`\n}\n","const localIdentifierPattern = /^[a-zA-Z0-9][a-zA-Z0-9._-]*\\/[a-zA-Z0-9][a-zA-Z0-9._-]*(?:@[^\\s/]+)?$/\nconst localIdentifierPatternWithoutVersion = /^[a-zA-Z0-9][a-zA-Z0-9._-]*\\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/\nconst externalSourceIdWithoutVersion = /^([a-zA-Z0-9][a-zA-Z0-9._-]*):([a-zA-Z0-9][a-zA-Z0-9._-]*)(?:\\/([a-zA-Z0-9][a-zA-Z0-9._-]*))?$/\n\nexport type ParsedSkillId = {\n id: string\n owner?: string\n slug: string\n source?: string\n version?: string\n}\n\nexport function normalizeSkillId(value: string): string | undefined {\n const parsed = splitSkillIdentifier(value)\n if (!parsed.id) {\n return undefined\n }\n return `${parsed.id}${parsed.version ? `@${parsed.version}` : ''}`\n}\n\nexport function isValidIdentifier(value: string): boolean {\n return localIdentifierPattern.test(value)\n}\n\nexport function isValidSkillIdentifier(value: string): boolean {\n return !!splitSkillIdentifier(value).id\n}\n\nexport function splitSkillIdentifier(input: string): ParsedSkillId {\n const trimmed = input.trim()\n const parsed = splitIdentifierAndVersion(trimmed)\n const id = parsed.id || ''\n\n if (isLocalIdentifierWithoutVersion(id)) {\n const [owner, slug] = id.split('/')\n return {\n id,\n owner,\n slug,\n version: parsed.version,\n }\n }\n\n const match = externalSourceIdWithoutVersion.exec(id)\n if (!match) {\n return {\n id: '',\n slug: '',\n version: parsed.version,\n }\n }\n\n const source = match[1]\n const firstPart = match[2]\n const secondPart = match[3]\n\n if (secondPart === undefined) {\n return {\n id: `${source}:${firstPart}`,\n source,\n slug: firstPart,\n version: parsed.version,\n }\n }\n\n return {\n id: `${source}:${firstPart}/${secondPart}`,\n source,\n owner: firstPart,\n slug: secondPart,\n version: parsed.version,\n }\n}\n\nfunction isLocalIdentifierWithoutVersion(value: string): boolean {\n return localIdentifierPatternWithoutVersion.test(value)\n}\n\nexport function assertNonEmpty(value: string, field: string): string {\n const v = value.trim()\n if (!v) {\n throw new Error(`Expected ${field} to be provided`)\n }\n return v\n}\n\nexport function splitIdentifierAndVersion(value: string): { id: string; version?: string } {\n const parts = value.split('@')\n const id = parts[0] || ''\n const version = parts.length > 1 ? parts.slice(1).join('@') : undefined\n return {\n id,\n version,\n }\n}\n\nexport function splitArgPair(input: string): { owner: string; slug: string } {\n const [owner, slug] = input.split('/')\n if (!owner || !slug) {\n throw new Error(`Expected <owner>/<slug>, received ${input}`)\n }\n return { owner, slug: slug.trim() }\n}\n","import { fileExists, readJson } from './fs.js'\nimport { localSkillcraftConfig, localGitDir } from './paths.js'\nimport { ConfigSchema } from './types.js'\n\nexport async function isEnabled(repoPath: string): Promise<boolean> {\n const configPath = localSkillcraftConfig(repoPath)\n if (!(await fileExists(configPath))) {\n return false\n }\n const raw = await readJson<unknown>(configPath)\n const parsed = ConfigSchema.safeParse(raw ?? {})\n return parsed.success\n}\n\nexport async function hasSkillcraftDir(repoPath: string): Promise<boolean> {\n return fileExists(localGitDir(repoPath))\n}\n","import { isGitRepo, gitHeadCommit, gitLogWithMessages, gitHasRef } from '@/core/git'\nimport { loadPending, currentProofIdForCommit } from '@/core/proof'\nimport { localSkillcraftConfig, contextPath, localRepoHookPath } from '@/core/paths'\nimport { fileExists } from '@/core/fs'\nimport { isEnabled } from '@/core/state'\nimport { loadLocalConfig } from '@/core/config'\n\nexport async function runStatus(): Promise<void> {\n const cwd = process.cwd()\n const git = await isGitRepo(cwd)\n process.stdout.write(`git: ${git ? 'enabled' : 'not a repository'}\\n`)\n\n const enabled = await isEnabled(cwd)\n process.stdout.write(`skillcraft: ${enabled ? 'enabled' : 'disabled'}\\n`)\n\n if (!git || !enabled) {\n return\n }\n\n const pending = await loadPending(cwd)\n process.stdout.write(`pending skills: ${pending.length}\\n`)\n const contextExists = await fileExists(contextPath(cwd))\n const hasHook = await fileExists(localRepoHookPath(cwd))\n process.stdout.write(`context file: ${contextExists ? 'present' : 'missing'}\\n`)\n process.stdout.write(`post-commit hook: ${hasHook ? 'installed' : 'missing'}\\n`)\n\n const head = await gitHeadCommit(cwd)\n const proofId = await currentProofIdForCommit(cwd, head)\n process.stdout.write(`head: ${head}\\n`)\n process.stdout.write(`latest proof: ${proofId ?? 'none'}\\n`)\n\n const logs = await gitLogWithMessages(cwd, 20)\n const withSkillcraft = logs.filter((entry) => entry.message.includes('Skillcraft-Ref:'))\n process.stdout.write(`recent commits with evidence: ${withSkillcraft.length}\\n`)\n\n const config = await loadLocalConfig(cwd)\n const branch = config.proofRef?.replace(/^refs\\/heads\\//, '') || 'skillcraft/proofs/v1'\n const proofBranchExists = await gitHasRef(cwd, `refs/heads/${branch}`)\n process.stdout.write(`proof branch: ${proofBranchExists ? 'present' : 'missing'}\\n`)\n\n if (pending.length > 0) {\n process.stdout.write(`pending evidence queued: ${pending.join(', ')}\\n`)\n }\n}\n\nexport async function runDoctor(): Promise<void> {\n const cwd = process.cwd()\n const checks = [\n ['node', !!process.version],\n ['git', (await isGitRepo(cwd))],\n ['skillcraft config', await fileExists(localSkillcraftConfig(cwd))],\n ['plugin hook', await fileExists(localRepoHookPath(cwd))],\n ]\n\n for (const [name, ok] of checks) {\n process.stdout.write(`${name}: ${ok ? 'ok' : 'missing'}\\n`)\n }\n\n if (!process.env.GITHUB_TOKEN && !(await isToolAvailable('gh'))) {\n process.stdout.write('gh: not installed\\n')\n return\n }\n process.stdout.write('gh: available\\n')\n}\n\nasync function isToolAvailable(tool: string): Promise<boolean> {\n try {\n const { execSync } = await import('node:child_process')\n execSync(`command -v ${tool}`)\n return true\n } catch {\n return false\n }\n}\n","import { isGitRepo, gitRoot, gitRemote } from '@/core/git'\nimport path from 'node:path'\nimport {\n skillcraftGlobalDir,\n localGitDir,\n localSkillcraftConfig,\n pluginPath,\n managedPluginPath,\n aiModelContextPath,\n pendingPath,\n contextPath,\n} from '@/core/paths'\nimport { ensureDir, writeJson, writeText } from '@/core/fs'\nimport { addRepo, loadGlobalConfig, saveGlobalConfig } from '@/core/config'\nimport { installPostCommitHook } from '@/core/hooks'\nimport { DefaultProofRef } from '@/core/types'\nimport { git, gitHasRef } from '@/core/git'\n\nexport async function runEnable(): Promise<void> {\n const cwd = process.cwd()\n if (!(await isGitRepo(cwd))) {\n throw new Error('Current directory is not a git repository')\n }\n const root = await gitRoot(cwd)\n\n const config = await loadGlobalConfig()\n if (!config.githubUser) {\n const fallback = process.env.GITHUB_USER || process.env.USER || 'developer'\n await saveGlobalConfig({ ...config, githubUser: fallback })\n }\n\n await ensureDir(localGitDir(root))\n await ensureDir(path.dirname(managedPluginPath(root)))\n await writeText(managedPluginPath(root), getManagedPluginSource())\n await writeJson(aiModelContextPath(root), {\n agent: { provider: 'opencode' },\n model: {},\n })\n\n const branchRef = `refs/heads/${DefaultProofRef}`\n if (!(await gitHasRef(root, branchRef))) {\n await git(['branch', DefaultProofRef], root)\n }\n await writeJson(localSkillcraftConfig(root), {\n version: 1,\n proofRef: DefaultProofRef,\n })\n await ensureDir(skillcraftGlobalDir())\n await writeJson(pendingPath(root), { skills: [] })\n await writeJson(contextPath(root), { activeLoadouts: [] })\n await writeJson(pluginPath(root), {\n version: 1,\n providers: ['opencode'],\n enabled: true,\n })\n await installPostCommitHook(root)\n\n const remote = await gitRemote(root)\n await addRepo({ path: root, remote, enabledAt: new Date().toISOString() })\n process.stdout.write(`enabled skillcraft for ${root}\\n`)\n}\n\nfunction getManagedPluginSource(): string {\n return `import fs from 'node:fs/promises'\nimport path from 'node:path'\n\nfunction normalizeProvider(value) {\n return typeof value === 'string' ? value.trim().toLowerCase() : ''\n}\n\nfunction normalizeModelName(value) {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction extractModelInfo(payload) {\n if (!payload || typeof payload !== 'object') {\n return {}\n }\n\n const direct = {\n modelProvider: normalizeProvider(payload.model_provider || payload.modelProvider || payload.model_provider_id),\n modelName: normalizeModelName(payload.model_name || payload.modelName || payload.model),\n agentProvider: normalizeProvider(payload.provider || payload.agent_provider || payload.agentProvider),\n }\n\n const msg = payload.message\n const request = payload.request\n const context = payload.context\n\n const nestedMessage = msg && typeof msg === 'object' ? {\n modelProvider: normalizeProvider(msg.model_provider || msg.modelProvider),\n modelName: normalizeModelName(msg.model_name || msg.modelName || msg.model),\n agentProvider: normalizeProvider(msg.provider || msg.agent_provider || msg.agentProvider),\n } : {}\n\n const nestedRequest = request && typeof request === 'object' ? {\n modelProvider: normalizeProvider(request.model_provider || request.modelProvider),\n modelName: normalizeModelName(request.model_name || request.modelName || request.model),\n agentProvider: normalizeProvider(request.provider || request.agent_provider || request.agentProvider),\n } : {}\n\n const nestedContext = context && typeof context === 'object' ? {\n modelProvider: normalizeProvider(context.model_provider || context.modelProvider),\n modelName: normalizeModelName(context.model_name || context.modelName || context.model),\n agentProvider: normalizeProvider(context.provider || context.agent_provider || context.agentProvider),\n } : {}\n\n const candidate = {\n agentProvider: direct.agentProvider || nestedMessage.agentProvider || nestedRequest.agentProvider || nestedContext.agentProvider || 'opencode',\n modelProvider: direct.modelProvider || nestedMessage.modelProvider || nestedRequest.modelProvider || nestedContext.modelProvider,\n modelName: direct.modelName || nestedMessage.modelName || nestedRequest.modelName || nestedContext.modelName,\n }\n\n if (!candidate.modelProvider && !candidate.modelName && !candidate.agentProvider) {\n return {}\n }\n\n return candidate\n}\n\nfunction resolveStateFile() {\n return path.join(process.cwd(), '.git', 'skillcraft', 'ai-model-context.json')\n}\n\nasync function updateState(update) {\n const stateFile = resolveStateFile()\n let current = {}\n\n try {\n const raw = await fs.readFile(stateFile, 'utf8')\n const parsed = JSON.parse(raw)\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n current = parsed\n }\n } catch {\n current = {}\n }\n\n const next = {\n ...(current || {}),\n ...(update || {}),\n }\n\n if (!next.agent || typeof next.agent !== 'object' || Array.isArray(next.agent)) {\n next.agent = { provider: 'opencode' }\n } else if (!next.agent.provider && update?.agent?.provider) {\n next.agent = { ...next.agent }\n }\n\n if (update?.agent?.provider) {\n next.agent.provider = update.agent.provider\n }\n\n if (update?.model) {\n next.model = {\n ...(next.model || {}),\n ...(update.model || {}),\n }\n }\n\n try {\n await fs.mkdir(path.join(process.cwd(), '.git', 'skillcraft'), { recursive: true })\n await fs.writeFile(stateFile, JSON.stringify(next, null, 2) + '\\n', 'utf8')\n } catch {\n return\n }\n}\n\nasync function handlePayload(payload) {\n if (!payload || typeof payload !== 'object') {\n return\n }\n\n const extracted = extractModelInfo(payload)\n if (!extracted || !extracted.agentProvider && !extracted.modelProvider && !extracted.modelName) {\n return\n }\n\n const update = {\n agent: {\n provider: extracted.agentProvider || 'opencode',\n },\n model: {\n ...(extracted.modelProvider ? { provider: extracted.modelProvider } : {}),\n ...(extracted.modelName ? { name: extracted.modelName } : {}),\n },\n }\n\n await updateState(update)\n}\n\nexport default async function Skillcraft() {\n const handler = async (event) => {\n try {\n await handlePayload(event)\n } catch {\n return\n }\n }\n\n return {\n 'chat.message': async (event) => {\n try {\n await handler(event)\n } catch {\n return\n }\n },\n event: async (event) => {\n try {\n const payload = event?.type && typeof event.type === 'string' ? event : event?.payload\n await handler(payload)\n } catch {\n return\n }\n },\n }\n}\n`\n}\n","import { loadRepos, saveRepos } from '@/core/config'\nimport { isGitRepo, gitRoot } from '@/core/git'\n\nexport async function runReposList(): Promise<void> {\n const data = await loadRepos()\n if (!data.repos.length) {\n process.stdout.write('no repositories tracked\\n')\n return\n }\n data.repos.forEach((entry, index) => {\n process.stdout.write(`${index + 1}. ${entry.path}`)\n if (entry.remote) {\n process.stdout.write(` (${entry.remote})`)\n }\n process.stdout.write('\\n')\n })\n}\n\nexport async function runReposPrune(): Promise<void> {\n const data = await loadRepos()\n const next = [] as typeof data.repos\n for (const item of data.repos) {\n if (await isGitRepo(item.path)) {\n await gitRoot(item.path)\n next.push(item)\n }\n }\n await saveRepos({ repos: next })\n process.stdout.write(`pruned repo list: ${data.repos.length} -> ${next.length}\\n`)\n}\n","import { loadProofsFromRepo } from './proof.js'\nimport type { Proof } from './types.js'\n\nexport async function loadProofFromRepo(repoPath: string): Promise<Proof[]> {\n return loadProofsFromRepo(repoPath)\n}\n","import path from 'node:path'\nimport { ensureDir, fileExists, readJson, writeJson } from './fs.js'\nimport { credentialIndexCachePath } from './paths.js'\nimport type { Proof } from './types.js'\n\nexport type NormalizedRequirements = {\n minCommits: number\n minRepositories: number\n tree: RequirementNode\n}\n\nexport type RequirementNode =\n | { and: RequirementNode[] }\n | { or: RequirementNode[] }\n | { skill: string }\n | { loadout: string }\n | { agent: { provider: string } }\n | { model: { provider?: string; name?: string } }\n\nexport type CredentialIndexEntry = {\n id: string\n name?: string\n description?: string\n requirements: NormalizedRequirements\n}\n\nexport type RequirementCheck = {\n type: 'skill' | 'loadout' | 'agent' | 'model'\n requirement: string\n satisfied: boolean\n}\n\nexport type EvaluationProof = {\n proof: Proof\n}\n\nexport type CredentialRequirementResult = {\n passed: boolean\n proofs: EvaluationProof[]\n provenCommits: string[]\n provenRepos: string[]\n checks: RequirementCheck[]\n reasons: string[]\n noExplicitChecks: boolean\n}\n\ntype RawRequirementNode = Record<string, unknown>\n\nconst DEFAULT_CREDENTIAL_INDEX_URL = 'https://skillcraft.gg/credentials/credentials/index.json'\nconst CREDENTIAL_INDEX_CACHE_REFRESH_MS = 6 * 60 * 60 * 1000\nconst CREDENTIAL_INDEX_CACHE_VERSION = 1\n\nconst CREDENTIAL_INDEX_CACHE_PATH = credentialIndexCachePath()\n\ntype CachedCredentialIndexFile = {\n cachedAt: number\n version: number\n entries: CredentialIndexEntry[]\n}\n\ntype CredentialIndexLoadOptions = {\n refresh?: boolean\n}\n\nfunction getCredentialIndexUrl(): string {\n return process.env.SKILLCRAFT_CREDENTIAL_INDEX_URL?.trim() || DEFAULT_CREDENTIAL_INDEX_URL\n}\n\nasync function readCredentialIndexCache(cachePath: string): Promise<CachedCredentialIndexFile | null> {\n try {\n const raw = await readJson<unknown>(cachePath)\n if (!raw || !isObject(raw)) {\n return null\n }\n\n const cachedAt = parseInteger(raw.cachedAt)\n if (cachedAt === undefined || cachedAt <= 0) {\n return null\n }\n\n if (raw.version !== CREDENTIAL_INDEX_CACHE_VERSION) {\n return null\n }\n\n if (!('entries' in raw)) {\n return null\n }\n\n const entries = normalizeCredentialIndexEntries(raw.entries)\n return {\n cachedAt,\n version: CREDENTIAL_INDEX_CACHE_VERSION,\n entries,\n }\n } catch {\n return null\n }\n}\n\nfunction parseInteger(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value\n }\n if (typeof value === 'string' && value.trim()) {\n const parsed = Number.parseInt(value, 10)\n if (Number.isFinite(parsed)) {\n return parsed\n }\n }\n return undefined\n}\n\nfunction isCredentialIndexCacheFresh(cache: CachedCredentialIndexFile): boolean {\n const ageMs = Date.now() - cache.cachedAt\n return ageMs < CREDENTIAL_INDEX_CACHE_REFRESH_MS\n}\n\nexport async function loadCredentialIndex(options: CredentialIndexLoadOptions = {}): Promise<CredentialIndexEntry[]> {\n const explicitPath = process.env.SKILLCRAFT_CREDENTIAL_INDEX_PATH?.trim()\n if (explicitPath) {\n return loadIndexFromPath(explicitPath)\n }\n\n const cached = !options.refresh ? await readCredentialIndexCache(CREDENTIAL_INDEX_CACHE_PATH) : null\n if (cached && isCredentialIndexCacheFresh(cached)) {\n return cached.entries\n }\n\n try {\n const entries = await loadIndexFromRemote(getCredentialIndexUrl())\n await writeCredentialIndexCache(entries)\n return entries\n } catch (error) {\n if (await fileExists(CREDENTIAL_INDEX_CACHE_PATH)) {\n const cached = await readCredentialIndexCache(CREDENTIAL_INDEX_CACHE_PATH)\n if (cached) {\n return cached.entries\n }\n return loadIndexFromPath(CREDENTIAL_INDEX_CACHE_PATH)\n }\n if (error instanceof Error) {\n throw error\n }\n throw new Error('failed to load credential index')\n }\n}\n\nasync function loadIndexFromRemote(url: string): Promise<CredentialIndexEntry[]> {\n const response = await fetch(url, {\n headers: {\n 'user-agent': 'skillcraft-cli',\n },\n })\n\n if (!response.ok) {\n throw new Error(`failed to download credential index from ${url}`)\n }\n\n const raw = await response.json()\n const entries = normalizeCredentialIndexEntries(raw)\n return entries\n}\n\nasync function loadIndexFromPath(filePath: string): Promise<CredentialIndexEntry[]> {\n const raw = await readJson<unknown>(filePath)\n if (!raw) {\n return []\n }\n\n if (isObject(raw) && Array.isArray((raw as { entries?: unknown }).entries)) {\n return normalizeCredentialIndexEntries((raw as { entries: unknown }).entries)\n }\n\n return normalizeCredentialIndexEntries(raw)\n}\n\nasync function writeCredentialIndexCache(entries: CredentialIndexEntry[]): Promise<void> {\n await ensureDir(path.dirname(CREDENTIAL_INDEX_CACHE_PATH))\n const payload = {\n cachedAt: Date.now(),\n version: CREDENTIAL_INDEX_CACHE_VERSION,\n entries,\n }\n await writeJson(CREDENTIAL_INDEX_CACHE_PATH, payload)\n}\n\nexport function normalizeRequirements(value: unknown): NormalizedRequirements {\n const requirements = isObject(value) ? value : {}\n\n if (requirements.mode !== undefined) {\n throw new Error('requirements.mode is not supported. Use nested and/or expressions instead.')\n }\n\n const requirementTree = normalizeRequirementRoot(requirements)\n\n return {\n minCommits: normalizeNonNegativeInteger(requirements.min_commits ?? requirements.minCommits, 0),\n minRepositories: normalizeNonNegativeInteger(requirements.min_repositories ?? requirements.minRepositories, 0),\n tree: requirementTree,\n }\n}\n\nfunction normalizeRequirementRoot(value: RawRequirementNode): RequirementNode {\n if (Object.prototype.hasOwnProperty.call(value, 'tree')) {\n return parseRequirementNode(value.tree, 'requirements.tree')\n }\n\n const hasExplicitAnd = Object.prototype.hasOwnProperty.call(value, 'and')\n const hasExplicitOr = Object.prototype.hasOwnProperty.call(value, 'or')\n\n if (hasExplicitAnd && hasExplicitOr) {\n throw new Error('requirements cannot include both and and or at the same level')\n }\n\n if (hasExplicitAnd) {\n const unexpected = Object.keys(value).filter((key) =>\n !['and', 'min_commits', 'min_repositories', 'minRepositories', 'minCommits', 'tree'].includes(key),\n )\n if (unexpected.length) {\n throw new Error(`Unexpected requirement fields: ${unexpected.join(', ')}`)\n }\n\n return {\n and: normalizeRequirementList((value as RawRequirementNode).and, 'requirements.and'),\n }\n }\n\n if (hasExplicitOr) {\n const unexpected = Object.keys(value).filter((key) =>\n !['or', 'min_commits', 'min_repositories', 'minRepositories', 'minCommits', 'tree'].includes(key),\n )\n if (unexpected.length) {\n throw new Error(`Unexpected requirement fields: ${unexpected.join(', ')}`)\n }\n\n return {\n or: normalizeRequirementList((value as RawRequirementNode).or, 'requirements.or'),\n }\n }\n\n return { and: buildImplicitAndFromShortcuts(value) }\n}\n\nfunction normalizeRequirementList(value: unknown, location: string): RequirementNode[] {\n if (!Array.isArray(value)) {\n throw new Error(`Expected array at ${location}`)\n }\n\n return value.map((entry, index) => parseRequirementNode(entry, `${location}[${index}]`))\n}\n\nfunction normalizeShortHandList(values: unknown, location: string): string[] {\n if (values === undefined) {\n return []\n }\n\n if (Array.isArray(values)) {\n return values.map((entry) => {\n const text = parseScalarText(entry)\n if (text === undefined) {\n throw new Error(`Expected text values for ${location}`)\n }\n return text\n })\n }\n\n const text = parseScalarText(values)\n if (!text) {\n return []\n }\n\n return [text]\n}\n\nfunction buildImplicitAndFromShortcuts(requirements: RawRequirementNode): RequirementNode[] {\n const normalized: RequirementNode[] = []\n const known = ['and', 'or', 'min_commits', 'min_repositories', 'minRepositories', 'minCommits', 'tree', 'skill', 'loadout', 'agent', 'model']\n\n for (const skill of normalizeShortHandList(requirements.skill, 'requirements.skill')) {\n normalized.push({ skill })\n }\n\n for (const loadout of normalizeShortHandList(requirements.loadout, 'requirements.loadout')) {\n normalized.push({ loadout })\n }\n\n const hasAgent = Object.prototype.hasOwnProperty.call(requirements, 'agent')\n const agent = normalizeAgentRequirement(requirements.agent)\n if (agent) {\n normalized.push(agent)\n } else if (hasAgent) {\n throw new Error('requirements.agent must be an object with a provider')\n }\n\n const hasModel = Object.prototype.hasOwnProperty.call(requirements, 'model')\n const model = normalizeModelRequirement(requirements.model)\n if (model) {\n normalized.push(model)\n } else if (hasModel) {\n throw new Error('requirements.model must be an object with optional provider and/or name')\n }\n\n const nested = Object.keys(requirements).filter((key) => !known.includes(key) && !key.startsWith('$'))\n if (nested.length) {\n throw new Error(`Unexpected requirement fields: ${nested.join(', ')}`)\n }\n\n return normalized\n}\n\nfunction parseRequirementNode(value: unknown, location: string): RequirementNode {\n if (!isObject(value)) {\n throw new Error(`Invalid requirement node at ${location}`)\n }\n\n const keys = Object.keys(value)\n if (!keys.length) {\n throw new Error(`Empty requirement node at ${location}`)\n }\n\n if (keys.length > 1) {\n throw new Error(`Requirement node has multiple keys at ${location}`)\n }\n\n const [key] = keys\n\n if (key === 'and' || key === 'or') {\n const valueForKey = (value as RawRequirementNode)[key]\n if (!Array.isArray(valueForKey)) {\n throw new Error(`Requirement node ${location} expected array for ${key}`)\n }\n\n return {\n [key]: valueForKey.map((entry, childIndex) => parseRequirementNode(entry, `${location}.${key}[${childIndex}]`)),\n } as RequirementNode\n }\n\n if (key === 'skill') {\n const text = parseScalarText((value as RawRequirementNode)[key])\n if (!text) {\n throw new Error(`Requirement node ${location} has empty skill`)\n }\n return { skill: text }\n }\n\n if (key === 'loadout') {\n const text = parseScalarText((value as RawRequirementNode)[key])\n if (!text) {\n throw new Error(`Requirement node ${location} has empty loadout`)\n }\n return { loadout: text }\n }\n\n if (key === 'agent') {\n const node = normalizeAgentRequirement((value as RawRequirementNode)[key])\n if (!node) {\n throw new Error(`Requirement node ${location} has invalid agent requirement`)\n }\n return node\n }\n\n if (key === 'model') {\n const node = normalizeModelRequirement((value as RawRequirementNode)[key])\n if (!node) {\n throw new Error(`Requirement node ${location} has invalid model requirement`)\n }\n return node\n }\n\n throw new Error(`Unexpected requirement key ${key} at ${location}`)\n}\n\nfunction normalizeAgentRequirement(value: unknown): { agent: { provider: string } } | undefined {\n if (!isObject(value)) {\n return undefined\n }\n\n const provider = parseScalarText(value.provider)\n if (!provider) {\n return undefined\n }\n\n return {\n agent: {\n provider: provider.toLowerCase(),\n },\n }\n}\n\nfunction normalizeModelRequirement(value: unknown): { model: { provider?: string; name?: string } } | undefined {\n if (!isObject(value)) {\n return undefined\n }\n\n const provider = parseScalarText(value.provider)\n const name = parseScalarText(value.name)\n\n if (!provider && !name) {\n return undefined\n }\n\n return {\n model: {\n ...(provider ? { provider: provider.toLowerCase() } : {}),\n ...(name ? { name } : {}),\n },\n }\n}\n\nexport function evaluateRequirements(\n proofs: EvaluationProof[],\n provenCommits: string[],\n provenRepos: string[],\n requirements: NormalizedRequirements,\n): CredentialRequirementResult {\n const proofSkills = [] as Array<{ id: string; version?: string }>\n const proofLoadouts = [] as string[]\n const proofAgents = [] as string[]\n const proofModels = [] as Array<{ provider?: string; name?: string }>\n\n const dedupedCommits = Array.from(new Set((provenCommits || []).filter(Boolean)))\n const dedupedRepos = Array.from(new Set((provenRepos || []).filter(Boolean)))\n\n for (const proofEntry of proofs) {\n const proof = proofEntry.proof\n for (const skill of proof.skills) {\n const parsed = parseIdentifierWithVersion(skill.id)\n if (parsed.id) {\n proofSkills.push({ id: parsed.id, version: parsed.version })\n }\n }\n\n for (const loadout of proof.loadouts) {\n const normalized = parseScalarText(loadout)\n if (normalized) {\n proofLoadouts.push(normalized)\n }\n }\n\n if (proof.agent?.provider && typeof proof.agent.provider === 'string') {\n proofAgents.push(proof.agent.provider)\n }\n\n const modelProvider = proof.model?.provider\n const modelName = proof.model?.name\n if (typeof modelProvider === 'string' || typeof modelName === 'string') {\n proofModels.push({ provider: modelProvider, name: modelName })\n }\n }\n\n const requirementResult = evaluateRequirementTree(requirements.tree, {\n skills: proofSkills,\n loadouts: proofLoadouts,\n agents: proofAgents,\n models: proofModels,\n })\n\n const checks = requirementResult.checks\n const resultReasons = [...failedRequirementReasons(checks)]\n\n if (requirements.minCommits > dedupedCommits.length) {\n resultReasons.push(`minimum required commits not met: have ${dedupedCommits.length}, need ${requirements.minCommits}`)\n requirementResult.passed = false\n }\n\n if (requirements.minRepositories > dedupedRepos.length) {\n resultReasons.push(`minimum required repositories not met: have ${dedupedRepos.length}, need ${requirements.minRepositories}`)\n requirementResult.passed = false\n }\n\n return {\n passed: requirementResult.passed,\n proofs,\n provenCommits: dedupedCommits,\n provenRepos: dedupedRepos,\n checks,\n reasons: resultReasons,\n noExplicitChecks: requirementResult.noExplicitChecks,\n }\n}\n\nfunction evaluateRequirementTree(\n node: RequirementNode,\n context: { skills: Array<{ id: string; version?: string }>; loadouts: string[]; agents: string[]; models: Array<{ provider?: string; name?: string }> },\n): { passed: boolean; checks: RequirementCheck[]; noExplicitChecks: boolean } {\n if ('and' in node) {\n const checks: RequirementCheck[] = []\n const childResults = [] as { passed: boolean; checks: RequirementCheck[]; noExplicitChecks: boolean }[]\n let noExplicitChecks = true\n\n for (const child of node.and) {\n const childResult = evaluateRequirementTree(child, context)\n checks.push(...childResult.checks)\n childResults.push(childResult)\n if (!childResult.noExplicitChecks) {\n noExplicitChecks = false\n }\n }\n\n return {\n passed: childResults.every((entry) => entry.passed),\n checks,\n noExplicitChecks,\n }\n }\n\n if ('or' in node) {\n const checks: RequirementCheck[] = []\n const childResults = [] as { passed: boolean; checks: RequirementCheck[]; noExplicitChecks: boolean }[]\n let noExplicitChecks = true\n\n for (const child of node.or) {\n const childResult = evaluateRequirementTree(child, context)\n checks.push(...childResult.checks)\n childResults.push(childResult)\n if (!childResult.noExplicitChecks) {\n noExplicitChecks = false\n }\n }\n\n return {\n passed: childResults.some((entry) => entry.passed),\n checks,\n noExplicitChecks,\n }\n }\n\n if ('skill' in node) {\n const parsed = parseIdentifierWithVersion(node.skill)\n const satisfied = proofSkillsMatch(context.skills, parsed)\n return {\n passed: satisfied,\n checks: [{ type: 'skill', requirement: node.skill, satisfied }],\n noExplicitChecks: false,\n }\n }\n\n if ('loadout' in node) {\n const parsed = parseTextRequirement(node.loadout)\n const satisfied = context.loadouts.includes(node.loadout) || (parsed && parsed.id !== '' && context.loadouts.includes(parsed.id))\n\n return {\n passed: satisfied,\n checks: [{ type: 'loadout', requirement: node.loadout, satisfied }],\n noExplicitChecks: false,\n }\n }\n\n if ('agent' in node) {\n const expectedProvider = normalizeRequirementText(node.agent.provider)\n const satisfied = context.agents.some((provider) => provider === expectedProvider)\n return {\n passed: satisfied,\n checks: [{ type: 'agent', requirement: `provider=${expectedProvider}`, satisfied }],\n noExplicitChecks: false,\n }\n }\n\n if ('model' in node) {\n const expectedProvider = normalizeRequirementText(node.model.provider)\n const expectedName = normalizeRequirementText(node.model.name)\n const satisfied = context.models.some((candidate) => {\n const hasProvider = !expectedProvider || candidate.provider === expectedProvider\n const hasName = !expectedName || (candidate.name && candidate.name === expectedName)\n return hasProvider && hasName\n })\n\n const parts = [] as string[]\n if (expectedProvider) {\n parts.push(`provider=${expectedProvider}`)\n }\n if (expectedName) {\n parts.push(`name=${expectedName}`)\n }\n\n return {\n passed: satisfied,\n checks: [{ type: 'model', requirement: parts.join(',') || 'model', satisfied }],\n noExplicitChecks: false,\n }\n }\n\n throw new Error('Unknown requirement node encountered during evaluation')\n}\n\nfunction failedRequirementReasons(checks: RequirementCheck[]): string[] {\n return checks.filter((entry) => !entry.satisfied).map((entry) => `${entry.type} ${entry.requirement} not met`)\n}\n\nfunction proofSkillsMatch(proofSkills: Array<{ id: string; version?: string }>, parsed: { id: string; version?: string }): boolean {\n return proofSkills.some((skill) => matchesId(skill.id, skill.version, parsed))\n}\n\nfunction matchesId(actualId: string, actualVersion: string | undefined, expected: { id: string; version?: string }): boolean {\n if (actualId !== expected.id) {\n return false\n }\n\n if (!expected.version) {\n return true\n }\n\n return actualVersion === expected.version\n}\n\nfunction parseTextRequirement(value: unknown): { id: string; version?: string } {\n return parseIdentifierWithVersion(value)\n}\n\nfunction parseIdentifierWithVersion(value: unknown): { id: string; version?: string } {\n const trimmed = parseScalarText(value)\n if (!trimmed) {\n return { id: '' }\n }\n\n const parts = trimmed.split('@')\n return {\n id: parts[0],\n version: parts.length > 1 ? parts.slice(1).join('@') : undefined,\n }\n}\n\nfunction normalizeRequirementText(value: unknown): string {\n return typeof value === 'string' ? value.trim().toLowerCase() : ''\n}\n\nfunction parseScalarText(value: unknown): string | undefined {\n if (typeof value !== 'string') {\n return undefined\n }\n const text = value.trim()\n return text || undefined\n}\n\nfunction normalizeNonNegativeInteger(value: unknown, fallback: number): number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {\n return fallback\n }\n\n return Math.floor(value)\n}\n\nfunction isObject(value: unknown): value is RawRequirementNode {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction normalizeCredentialIndexEntries(entries: unknown): CredentialIndexEntry[] {\n if (!Array.isArray(entries)) {\n return []\n }\n\n const normalized = [] as CredentialIndexEntry[]\n for (const entry of entries) {\n const normalizedEntry = normalizeCredentialIndexEntry(entry)\n if (normalizedEntry) {\n normalized.push(normalizedEntry)\n }\n }\n\n return normalized.sort((left, right) => left.id.localeCompare(right.id))\n}\n\nfunction normalizeCredentialIndexEntry(raw: unknown): CredentialIndexEntry | undefined {\n if (!isObject(raw)) {\n return undefined\n }\n\n const id = parseScalarText(raw.id)\n if (!id) {\n return undefined\n }\n\n try {\n return {\n id,\n name: parseScalarText(raw.name),\n description: parseScalarText(raw.description),\n requirements: normalizeRequirements(raw.requirements),\n }\n } catch {\n return undefined\n }\n}\n\nexport async function getCredentialIndexEntries(options: CredentialIndexLoadOptions = {}): Promise<CredentialIndexEntry[]> {\n return loadCredentialIndex(options)\n}\n","import { Command } from 'commander'\n\ntype OutputMode = 'text' | 'json'\n\nexport function getOutputMode(program: Command): OutputMode {\n const raw = program.opts<{ json?: boolean }>().json\n return raw ? 'json' : 'text'\n}\n\nexport function printResult<T>(mode: OutputMode, label: string, data: T): void {\n if (mode === 'json') {\n process.stdout.write(`${JSON.stringify({ label, data })}\\n`)\n return\n }\n process.stdout.write(`${label}: ${JSON.stringify(data)}\\n`)\n}\n\nexport function printLines(lines: string[]): void {\n process.stdout.write(`${lines.join('\\n')}\\n`)\n}\n\nexport function printError(message: string): void {\n process.stderr.write(`${message}\\n`)\n}\n","import { isEnabled } from '@/core/state'\nimport { gitRemote } from '@/core/git'\nimport { loadProofFromRepo } from '@/core/progress'\nimport { addTrackedCredential, loadRepos, loadTrackedCredentials, removeTrackedCredential } from '@/core/config'\nimport { assertNonEmpty } from '@/core/validation'\nimport { evaluateRequirements, getCredentialIndexEntries, type CredentialIndexEntry, type CredentialRequirementResult, type RequirementCheck } from '@/core/credentials'\nimport { printLines } from '@/lib/output'\n\ntype ProgressOutputMode = {\n outputMode?: 'text' | 'json'\n refreshIndex?: boolean\n}\n\ntype EvaluatedCredentialResult = {\n credentialId: string\n name?: string\n description?: string\n passed: boolean\n status: 'eligible' | 'blocked'\n reasons: string[]\n checks: RequirementCheck[]\n requiredMinCommits: number\n requiredMinRepositories: number\n provenCommits: number\n provenRepositories: number\n proofFiles: number\n}\n\ntype ProgressPayload = {\n trackedCredentials: number\n trackedRepositories: number\n evidence: {\n proofFiles: number\n provenCommits: number\n provenRepositories: number\n }\n credentials: EvaluatedCredentialResult[]\n}\n\ntype ProofEntry = {\n proof: {\n commit: string\n loadouts: string[]\n skills: Array<{ id: string; version?: string }>\n agent?: { provider?: string }\n model?: { provider?: string; name?: string }\n version: number\n timestamp: string\n }\n}\n\nasync function resolveTrackedRepos(): Promise<string[]> {\n const data = await loadRepos()\n const repoPaths = new Set<string>()\n const repos: string[] = []\n\n for (const entry of data.repos) {\n if (repoPaths.has(entry.path)) {\n continue\n }\n repoPaths.add(entry.path)\n\n if (await isEnabled(entry.path)) {\n repos.push(entry.path)\n }\n }\n\n return repos\n}\n\nexport async function runProgress(options: ProgressOutputMode = {}): Promise<void> {\n const tracked = await resolveTrackedRepos()\n const trackedCredentials = await loadTrackedCredentials()\n\n const trackedCredList = trackedCredentials.credentials\n if (!trackedCredList.length) {\n if (options.outputMode === 'json') {\n printJsonResult(\n buildPayload({\n tracked,\n trackedCredentialsCount: 0,\n proofFiles: 0,\n provenCommits: 0,\n provenRepositories: 0,\n evaluated: [],\n }),\n )\n return\n }\n process.stdout.write('no credentials tracked\\n')\n return\n }\n\n const indexById = mapCredentials(await getCredentialIndexEntries({ refresh: options.refreshIndex }))\n\n let proofFiles = 0\n const proofs: ProofEntry[] = []\n const provenRepos = new Set<string>()\n const provenCommits = new Set<string>()\n\n for (const repoPath of tracked) {\n const proofsInRepo = await loadProofFromRepo(repoPath)\n proofFiles += proofsInRepo.length\n\n if (!proofsInRepo.length) {\n continue\n }\n\n const remote = (await gitRemote(repoPath)) || repoPath\n provenRepos.add(remote)\n\n for (const proof of proofsInRepo) {\n if (proof?.commit) {\n provenCommits.add(proof.commit)\n }\n proofs.push({ proof })\n }\n }\n\n const provenCommitList = Array.from(provenCommits)\n const provenRepoList = Array.from(provenRepos)\n\n const payload = buildPayload({\n tracked,\n trackedCredentialsCount: trackedCredList.length,\n proofFiles,\n provenCommits: provenCommitList.length,\n provenRepositories: provenRepoList.length,\n evaluated: [],\n })\n\n const evaluated = [] as EvaluatedCredentialResult[]\n for (const entry of trackedCredList) {\n const definition = indexById.get(entry.id)\n if (!definition) {\n evaluated.push(makeMissingDefinitionResult(entry.id, proofs.length, provenCommitList.length, provenRepoList.length))\n continue\n }\n\n const result = evaluateRequirements(proofs, provenCommitList, provenRepoList, definition.requirements)\n evaluated.push(formatResult(entry.id, definition, result, proofs.length, provenCommitList.length, provenRepoList.length))\n }\n\n payload.credentials = evaluated\n\n if (options.outputMode === 'json') {\n printJsonResult(payload)\n return\n }\n\n const lines = [] as string[]\n lines.push(`tracked credentials: ${trackedCredList.length}`)\n lines.push(`tracked repositories: ${tracked.length}`)\n lines.push(`proof files: ${proofFiles}`)\n lines.push(`proof commits: ${provenCommitList.length}`)\n lines.push(`proof repositories: ${provenRepoList.length}`)\n lines.push('')\n\n for (const entry of evaluated) {\n lines.push(`${entry.credentialId}: ${entry.status}`)\n lines.push(` checks: ${entry.passed ? 'passed' : 'blocked'}`)\n lines.push(` proof scope: ${entry.proofFiles} proofs, ${entry.provenCommits}/${entry.requiredMinCommits} commits, ${entry.provenRepositories}/${entry.requiredMinRepositories} repositories`)\n if (entry.reasons.length) {\n lines.push(' reasons:')\n for (const reason of entry.reasons) {\n lines.push(` - ${reason}`)\n }\n }\n lines.push('')\n }\n\n printLines(lines)\n}\n\nexport async function runProgressTrack(rawId: string): Promise<void> {\n const id = assertNonEmpty(rawId, 'credential id')\n const indexById = mapCredentials(await getCredentialIndexEntries())\n if (!indexById.has(id)) {\n throw new Error(`credential not found in credential index: ${id}`)\n }\n\n const added = await addTrackedCredential(id)\n if (!added) {\n process.stdout.write(`credential already tracked: ${id}\\n`)\n return\n }\n process.stdout.write(`tracking credential: ${id}\\n`)\n}\n\nexport async function runProgressUntrack(rawId: string): Promise<void> {\n const id = assertNonEmpty(rawId, 'credential id')\n const removed = await removeTrackedCredential(id)\n if (!removed) {\n process.stdout.write(`credential not tracked: ${id}\\n`)\n return\n }\n process.stdout.write(`untracked credential: ${id}\\n`)\n}\n\nfunction buildPayload(params: {\n tracked: string[]\n trackedCredentialsCount: number\n proofFiles: number\n provenCommits: number\n provenRepositories: number\n evaluated: EvaluatedCredentialResult[]\n}): ProgressPayload {\n return {\n trackedCredentials: params.trackedCredentialsCount,\n trackedRepositories: params.tracked.length,\n evidence: {\n proofFiles: params.proofFiles,\n provenCommits: params.provenCommits,\n provenRepositories: params.provenRepositories,\n },\n credentials: params.evaluated,\n }\n}\n\nfunction printJsonResult(payload: ProgressPayload) {\n process.stdout.write(`${JSON.stringify(payload)}\\n`)\n}\n\nfunction mapCredentials(index: CredentialIndexEntry[]): Map<string, CredentialIndexEntry> {\n return new Map(index.map((entry) => [entry.id, entry]))\n}\n\nfunction makeMissingDefinitionResult(\n credentialId: string,\n proofFiles: number,\n provenCommits: number,\n provenRepositories: number,\n): EvaluatedCredentialResult {\n return {\n credentialId,\n passed: false,\n status: 'blocked',\n reasons: ['credential definition is not available'],\n checks: [],\n requiredMinCommits: 0,\n requiredMinRepositories: 0,\n provenCommits,\n provenRepositories,\n proofFiles,\n }\n}\n\nfunction formatResult(\n credentialId: string,\n definition: CredentialIndexEntry,\n result: CredentialRequirementResult,\n proofFiles: number,\n provenCommits: number,\n provenRepositories: number,\n): EvaluatedCredentialResult {\n return {\n credentialId,\n name: definition.name,\n description: definition.description,\n passed: result.passed,\n status: result.passed ? 'eligible' : 'blocked',\n reasons: result.reasons,\n checks: result.checks,\n requiredMinCommits: definition.requirements.minCommits,\n requiredMinRepositories: definition.requirements.minRepositories,\n provenCommits,\n provenRepositories,\n proofFiles,\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs/promises'\nimport { getProvider } from '@/providers'\nimport { loadGlobalConfig } from '@/core/config'\nimport { assertNonEmpty, splitArgPair, splitSkillIdentifier, normalizeSkillId } from '@/core/validation'\nimport { isEnabled } from '@/core/state'\nimport { loadProofFromRepo } from '@/core/progress'\nimport { loadPending, normalizeSkillIds } from '@/core/proof'\nimport { pendingPath } from '@/core/paths'\nimport { writeJson } from '@/core/fs'\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport ora from 'ora'\n\nconst execPromise = promisify(execFile)\n\ntype SearchIndexEntry = {\n id: string\n name?: string\n path?: string\n url?: string\n owner?: string\n slug?: string\n runtime?: string[]\n tags?: string[]\n updatedAt?: string\n}\n\ntype SearchIndexOptions = {\n source?: string\n limit?: number\n outputMode?: 'text' | 'json'\n}\n\ntype SearchResult = {\n id: string\n name?: string\n path?: string\n url?: string\n owner?: string\n slug?: string\n runtime?: string[]\n tags?: string[]\n}\n\ntype SkillInspectOptions = {\n outputMode?: 'text' | 'json'\n}\n\ntype SkillManifestDetails = {\n url: string\n title?: string\n summary?: string\n error?: string\n}\n\nexport async function runSkillsPublish(slug: string): Promise<void> {\n const ref = assertNonEmpty(slug, 'skill id')\n const { owner, slug: slugPart } = splitArgPair(ref)\n const cwd = process.cwd()\n if (!(await isEnabled(cwd))) {\n throw new Error('Repository is not enabled')\n }\n\n const files = await Promise.all([\n fs.access(path.join(cwd, 'SKILL.md')).then(() => true).catch(() => false),\n fs.access(path.join(cwd, 'skill.yaml')).then(() => true).catch(() => false),\n ])\n if (!files[0] || !files[1]) {\n throw new Error('SKILL.md and skill.yaml are required for publishing')\n }\n\n const config = await loadGlobalConfig()\n const provider = getProvider(config.provider ?? 'gh')\n await provider.getUser()\n\n const destination = 'skillcraft-gg/skills'\n const branch = `skillcraft-skill-${owner}-${slugPart}`\n const temp = path.join(process.cwd(), '.skillcraft-temp-skill-publish')\n\n try {\n await fs.rm(temp, { force: true, recursive: true })\n await provider.cloneRepo(destination, temp)\n await runGit(temp, ['checkout', '-B', branch])\n\n const target = path.join(temp, 'skills', owner, slugPart)\n await fs.rm(target, { force: true, recursive: true })\n await fs.mkdir(path.dirname(target), { recursive: true })\n await fs.cp(cwd, target, { recursive: true })\n\n await runGit(temp, ['add', `skills/${owner}/${slugPart}`])\n await runGit(temp, ['commit', '-m', `Publish skill ${ref}`]).catch(() => {\n throw new Error('nothing to commit; skill may already be published')\n })\n await runGit(temp, ['push', '-u', 'origin', branch]).catch(() => {\n throw new Error('unable to push skill publish branch')\n })\n await provider.createPullRequest(destination, branch, `Publish skill: ${ref}`).catch(() => {\n process.stdout.write('unable to create PR automatically. Please open one manually from your branch.\\n')\n })\n\n process.stdout.write(`published skill ${ref} from ${destination}\\n`)\n } finally {\n await fs.rm(temp, { force: true, recursive: true })\n }\n}\n\nexport async function runSkillsAdd(rawId: string): Promise<void> {\n const cwd = process.cwd()\n if (!(await isEnabled(cwd))) {\n throw new Error('Repository is not enabled')\n }\n\n const cleanInput = assertNonEmpty(rawId, 'skill id')\n const parsed = splitSkillIdentifier(cleanInput)\n if (!parsed.id) {\n throw new Error('invalid skill id format')\n }\n\n const index = await loadSearchIndex()\n if (!index.has(parsed.id)) {\n throw new Error(`skill ${parsed.id} is not listed in the search index`)\n }\n\n const normalized = normalizeSkillIds([`${parsed.id}${parsed.version ? `@${parsed.version}` : ''}`])\n const existing = await loadPending(cwd)\n const next = normalizeSkillIds([...existing, ...normalized])\n\n await writeJson(pendingPath(cwd), { skills: next })\n process.stdout.write(`queued skill: ${normalized[0]}\\n`)\n}\n\nexport async function runSkillsValidate(): Promise<void> {\n const cwd = process.cwd()\n const checks = [\n ['SKILL.md', await exists(path.join(cwd, 'SKILL.md'))],\n ['skill.yaml', await exists(path.join(cwd, 'skill.yaml'))],\n ]\n for (const [name, ok] of checks) {\n process.stdout.write(`${name}: ${ok ? 'ok' : 'missing'}\\n`)\n }\n}\n\nexport async function runSkillsList(): Promise<void> {\n const cwd = process.cwd()\n if (!(await isEnabled(cwd))) {\n throw new Error('Repository is not enabled')\n }\n\n const [proofs, pending] = await Promise.all([loadProofFromRepo(cwd), loadPending(cwd)])\n const skills = new Set<string>()\n for (const proof of proofs) {\n for (const item of proof.skills) {\n skills.add(item.id)\n }\n }\n for (const skill of pending) {\n skills.add(skill)\n }\n\n if (!skills.size) {\n process.stdout.write('no skills detected\\n')\n return\n }\n\n const list = Array.from(skills).sort().join('\\n')\n process.stdout.write(`skills detected (${skills.size}):\\n${list}\\n`)\n}\n\nexport async function runSkillsSearch(rawQuery?: string, options: SearchIndexOptions = {}): Promise<void> {\n const entries = await loadSearchIndexEntries(options.outputMode)\n if (!entries.length) {\n if (options.outputMode === 'json') {\n process.stdout.write(`${JSON.stringify({\n query: rawQuery?.trim(),\n source: options.source?.trim(),\n limit: getSearchLimit(options.limit),\n count: 0,\n results: [],\n message: 'no skills indexed',\n })}\\n`)\n } else {\n process.stdout.write('no skills indexed\\n')\n }\n return\n }\n\n const query = rawQuery?.trim().toLowerCase()\n const sourceFilter = options.source?.trim().toLowerCase()\n const limit = getSearchLimit(options.limit)\n\n const filtered = entries.filter((entry) => {\n if (sourceFilter) {\n const source = getSkillSource(entry.id)\n if (source !== sourceFilter) {\n return false\n }\n }\n\n if (!query) {\n return true\n }\n\n const fields = [\n entry.id,\n entry.name,\n entry.owner,\n entry.slug,\n entry.path,\n entry.url,\n ...(entry.runtime || []),\n ...(entry.tags || []),\n ].filter((value): value is string => !!value).map((value) => value.toLowerCase())\n\n return fields.some((value) => value.includes(query))\n })\n\n const sorted = [...filtered].sort((left, right) => {\n const leftName = (left.name || left.id).toLowerCase()\n const rightName = (right.name || right.id).toLowerCase()\n if (leftName === rightName) {\n return left.id.localeCompare(right.id)\n }\n return leftName.localeCompare(rightName)\n })\n\n const shown = sorted.slice(0, limit)\n if (!shown.length) {\n const message = query ? `no skills match \"${rawQuery?.trim()}\"` : 'no skills match current filters'\n if (options.outputMode === 'json') {\n process.stdout.write(`${JSON.stringify({\n query: rawQuery?.trim(),\n source: options.source?.trim(),\n limit,\n count: 0,\n results: [],\n message,\n })}\\n`)\n } else {\n process.stdout.write(`${message}\\n`)\n }\n return\n }\n\n const title = query ? `skills matching \"${rawQuery?.trim()}\"` : 'skills index'\n const lines = shown.map((entry) => {\n const runtime = (entry.runtime || []).length ? ` [${entry.runtime!.join(', ')}]` : ''\n const tags = (entry.tags || []).length ? ` {${entry.tags!.join(', ')}}` : ''\n const updatedLabel = formatUpdatedAt(entry.updatedAt)\n const name = formatSearchResultName(entry)\n return `${entry.id}${name ? ` — ${name}` : ''}${runtime}${tags}${updatedLabel}`\n })\n\n if (options.outputMode === 'json') {\n const payload = {\n query: rawQuery?.trim(),\n source: options.source?.trim(),\n limit,\n count: shown.length,\n total: sorted.length,\n results: shown.map((entry) => {\n const row: SearchResult = {\n id: entry.id,\n name: entry.name,\n path: entry.path,\n url: entry.url,\n owner: entry.owner,\n slug: entry.slug,\n runtime: entry.runtime,\n tags: entry.tags,\n }\n return row\n }),\n }\n process.stdout.write(`${JSON.stringify(payload)}\\n`)\n return\n }\n\n process.stdout.write(`${title} (${shown.length}):\\n${lines.join('\\n')}\\n`)\n}\n\nexport async function runSkillsInspect(rawId: string, options: SkillInspectOptions = {}): Promise<void> {\n const cleanId = assertNonEmpty(rawId, 'skill id')\n const parsed = splitSkillIdentifier(cleanId)\n if (!parsed.id) {\n throw new Error('invalid skill id format')\n }\n\n const entries = await loadSearchIndexEntries(options.outputMode)\n const match = entries.find((entry) => entry.id === parsed.id)\n if (!match) {\n throw new Error(`skill ${parsed.id} is not listed in the search index`)\n }\n\n const manifest = await loadSkillManifest(match)\n if (options.outputMode === 'json') {\n const payload = {\n id: match.id,\n name: match.name,\n source: getSkillSource(match.id),\n owner: match.owner,\n slug: match.slug,\n path: match.path,\n url: match.url,\n runtime: match.runtime,\n tags: match.tags,\n updatedAt: match.updatedAt,\n manifest,\n version: parsed.version,\n }\n process.stdout.write(`${JSON.stringify(payload)}\\n`)\n return\n }\n\n const lines = formatInspectOutput(match, manifest)\n process.stdout.write(`${lines}\\n`)\n}\n\nfunction formatInspectOutput(entry: SearchIndexEntry, manifest?: SkillManifestDetails): string {\n const lines: string[] = []\n lines.push(`skill: ${entry.id}`)\n\n if (entry.name) {\n lines.push(`name: ${entry.name}`)\n }\n\n const source = getSkillSource(entry.id)\n if (source) {\n lines.push(`source: ${source}`)\n }\n\n if (entry.owner) {\n lines.push(`owner: ${entry.owner}`)\n }\n\n if (entry.slug) {\n lines.push(`slug: ${entry.slug}`)\n }\n\n if (entry.runtime && entry.runtime.length) {\n lines.push(`runtime: ${entry.runtime.join(', ')}`)\n }\n\n if (entry.tags && entry.tags.length) {\n lines.push(`tags: ${entry.tags.join(', ')}`)\n }\n\n if (entry.updatedAt) {\n lines.push(`updated: ${entry.updatedAt}`)\n }\n\n if (entry.path) {\n lines.push(`path: ${entry.path}`)\n }\n\n if (entry.url) {\n lines.push(`url: ${entry.url}`)\n }\n\n if (manifest) {\n lines.push(`manifest: ${manifest.url}`)\n if (manifest.title) {\n lines.push(`manifest title: ${manifest.title}`)\n }\n if (manifest.summary) {\n lines.push(`manifest summary: ${manifest.summary}`)\n }\n if (manifest.error) {\n lines.push(`manifest fetch: ${manifest.error}`)\n }\n }\n\n return lines.join('\\n')\n}\n\nasync function loadSkillManifest(entry: SearchIndexEntry): Promise<SkillManifestDetails | undefined> {\n const manifestUrl = buildSkillManifestUrl(entry.url)\n if (!manifestUrl) {\n return undefined\n }\n\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(manifestUrl, {\n headers: {\n 'user-agent': 'skillcraft-cli',\n },\n signal: controller.signal,\n })\n\n if (!response.ok) {\n return {\n url: manifestUrl,\n error: `unable to fetch manifest (${response.status})`,\n }\n }\n\n const text = await response.text()\n if (isHtmlDocument(text)) {\n return {\n url: manifestUrl,\n error: 'unable to parse manifest (not markdown)',\n }\n }\n const parsed = parseSkillManifest(text)\n return {\n url: manifestUrl,\n title: parsed.title,\n summary: parsed.summary,\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n return {\n url: manifestUrl,\n error: 'manifest fetch timed out',\n }\n }\n\n return {\n url: manifestUrl,\n error: error instanceof Error ? error.message : 'failed to fetch manifest',\n }\n } finally {\n clearTimeout(timeout)\n }\n}\n\nfunction buildSkillManifestUrl(rawUrl?: string): string | undefined {\n if (!rawUrl) {\n return undefined\n }\n\n const url = rawUrl.trim()\n if (!url) {\n return undefined\n }\n\n const manifestUrl = url.endsWith('/SKILL.md') ? url : url.endsWith('/') ? `${url}SKILL.md` : `${url}/SKILL.md`\n return toRawManifestUrl(manifestUrl)\n}\n\nfunction toRawManifestUrl(rawUrl: string): string {\n try {\n const parsed = new URL(rawUrl)\n if (parsed.hostname !== 'github.com') {\n return rawUrl\n }\n\n const parts = parsed.pathname.split('/').filter(Boolean)\n const blobIndex = parts.indexOf('blob')\n if (blobIndex !== 2 || parts.length < blobIndex + 2) {\n return rawUrl\n }\n\n const owner = parts[0]\n const repo = parts[1]\n const remainingPath = parts.slice(blobIndex + 1)\n if (!owner || !repo || !remainingPath.length) {\n return rawUrl\n }\n\n const rawParts = [owner, repo, 'raw', 'refs', 'heads', ...remainingPath]\n return `${parsed.protocol}//${parsed.host}/${rawParts.join('/')}`\n } catch {\n return rawUrl\n }\n}\n\nfunction isHtmlDocument(input: string): boolean {\n const text = input.replace(/^\\s+/, '').toLowerCase()\n return text.startsWith('<!doctype html') || text.startsWith('<html')\n}\n\nfunction parseSkillManifest(input: string): { title?: string; summary?: string } {\n const normalized = input.replace(/\\r\\n/g, '\\n')\n const lines = normalized.split('\\n')\n let index = 0\n\n if ((lines[0] || '').trim() === '---') {\n index = 1\n while (index < lines.length && lines[index].trim() !== '---') {\n index += 1\n }\n if (index < lines.length && lines[index].trim() === '---') {\n index += 1\n }\n }\n\n let title: string | undefined\n let summary: string | undefined\n\n for (let i = index; i < lines.length; i += 1) {\n const line = lines[i].trim()\n if (!line) {\n if (summary) {\n break\n }\n continue\n }\n\n if (!title && line.startsWith('#')) {\n title = line.replace(/^#+\\s*/, '').trim()\n continue\n }\n\n if (!summary && !line.startsWith('>')) {\n summary = line\n break\n }\n }\n\n return {\n title,\n summary,\n }\n}\n\nfunction isJson(value: unknown): value is SearchIndexEntry[] {\n return Array.isArray(value)\n}\n\nasync function loadSearchIndex(): Promise<Set<string>> {\n const entries = await loadSearchIndexEntries()\n return new Set(entries.map((entry) => entry.id))\n}\n\nasync function loadSearchIndexEntries(outputMode: SearchIndexOptions['outputMode'] = undefined): Promise<SearchIndexEntry[]> {\n const explicitPath = process.env.SKILLCRAFT_SEARCH_INDEX_PATH?.trim()\n const source = explicitPath || process.env.SKILLCRAFT_SEARCH_INDEX_URL || 'https://skillcraft.gg/skills/search/index.json'\n const loadEntries = async () => {\n if (explicitPath) {\n const raw = await fs.readFile(explicitPath, 'utf8')\n const parsed = JSON.parse(raw)\n return normalizeSearchIndexEntries(isJson(parsed) ? parsed : [])\n }\n\n const url = process.env.SKILLCRAFT_SEARCH_INDEX_URL || 'https://skillcraft.gg/skills/search/index.json'\n const response = await fetch(url, {\n headers: {\n 'user-agent': 'skillcraft-cli',\n },\n })\n if (!response.ok) {\n throw new Error(`failed to download search index from ${url}`)\n }\n\n const parsed = await response.json()\n return normalizeSearchIndexEntries(isJson(parsed) ? parsed : [])\n }\n\n if (!shouldShowSearchSpinner(outputMode)) {\n return loadEntries()\n }\n\n const action = explicitPath ? `reading local index from ${source}` : `downloading index from ${source}`\n const spinner = ora({\n text: `Loading ${action}...`,\n }).start()\n\n try {\n const entries = await loadEntries()\n spinner.succeed(`loaded ${entries.length} indexed entries`)\n return entries\n } catch (error) {\n spinner.fail('failed to load search index')\n throw error\n }\n}\n\nfunction shouldShowSearchSpinner(outputMode: SearchIndexOptions['outputMode']): boolean {\n if (outputMode !== 'text') {\n return false\n }\n\n return process.stdout.isTTY === true || process.stderr.isTTY === true\n}\n\nfunction normalizeSearchIndexEntries(entries: SearchIndexEntry[]): SearchIndexEntry[] {\n return entries\n .map((entry) => normalizeSearchIndexEntry(entry))\n .filter((entry): entry is SearchIndexEntry => !!entry)\n}\n\nfunction normalizeSearchIndexEntry(raw: SearchIndexEntry): SearchIndexEntry | undefined {\n const rawId = normalizeString(raw.id)\n const id = normalizeSkillId(rawId)\n if (!id) {\n return undefined\n }\n\n return {\n id,\n name: normalizeText(raw.name),\n path: normalizeText(raw.path),\n url: normalizeText(raw.url),\n owner: normalizeText(raw.owner),\n slug: normalizeText(raw.slug),\n runtime: normalizeStringArray(raw.runtime),\n tags: normalizeStringArray(raw.tags),\n updatedAt: normalizeText(raw.updatedAt),\n }\n}\n\nfunction normalizeString(value: unknown): string {\n return String(value || '').trim()\n}\n\nfunction normalizeText(value: unknown): string | undefined {\n const text = normalizeString(value)\n return text || undefined\n}\n\nfunction normalizeStringArray(value: unknown): string[] {\n if (value === undefined) {\n return []\n }\n\n if (typeof value === 'string') {\n return value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean)\n }\n\n if (!Array.isArray(value)) {\n return []\n }\n\n const normalized: string[] = []\n for (const item of value) {\n if (typeof item !== 'string') {\n continue\n }\n const text = item.trim()\n if (text) {\n normalized.push(text)\n }\n }\n return normalized\n}\n\nfunction getSkillSource(id: string): string | undefined {\n const separatorIndex = id.indexOf(':')\n if (separatorIndex < 1) {\n return undefined\n }\n\n const source = id.slice(0, separatorIndex).trim()\n if (!source) {\n return undefined\n }\n\n return source.toLowerCase()\n}\n\nfunction getSearchLimit(raw: number | undefined): number {\n const requestedLimit = raw === undefined ? 20 : Math.floor(raw)\n return Number.isFinite(requestedLimit) && requestedLimit > 0 ? requestedLimit : 20\n}\n\nfunction formatSearchResultName(entry: SearchIndexEntry): string {\n const name = (entry.name || '').trim()\n if (!name) {\n return ''\n }\n\n const slug = deriveSearchResultSlug(entry)\n if (!slug) {\n return name\n }\n\n if (name.toLowerCase() === slug.toLowerCase()) {\n return ''\n }\n\n return name\n}\n\nfunction deriveSearchResultSlug(entry: SearchIndexEntry): string {\n if (entry.slug && entry.slug.trim()) {\n return entry.slug.trim()\n }\n\n const id = entry.id.trim()\n const separator = id.indexOf(':')\n const suffix = separator >= 0 ? id.slice(separator + 1) : id\n const parts = suffix.split('/').filter(Boolean)\n\n return parts.length ? parts[parts.length - 1] : suffix\n}\n\nfunction formatUpdatedAt(value?: string): string {\n if (!value) {\n return ''\n }\n\n const updatedAt = new Date(value)\n if (Number.isNaN(updatedAt.getTime())) {\n return ''\n }\n\n return ` (updated ${updatedAt.toISOString().slice(0, 10)})`\n}\n\nasync function exists(pathToCheck: string): Promise<boolean> {\n try {\n await fs.access(pathToCheck)\n return true\n } catch {\n return false\n }\n}\n\nasync function runGit(cwd: string, args: string[]): Promise<string> {\n const { stdout } = await execPromise('git', args, { cwd })\n return stdout.trim()\n}\n\nexport async function runSkillsValidateAndExit(): Promise<void> {\n await runSkillsValidate()\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { execFile, execSync } from 'node:child_process'\nimport { promisify } from 'node:util'\n\nconst exec = promisify(execFile)\n\nexport type ClaimInputs = {\n credential: string\n claimant: string\n sources: Array<{ repo: string; commits: string[] }>\n claimId: string\n}\n\nexport type PublishInputs = {\n targetRepo: string\n sourceDir: string\n destinationPath: string\n branch: string\n commitMessage: string\n}\n\nexport interface ForgeProvider {\n providerName(): string\n getUser(): Promise<string>\n getIssueUrl(repo: string, number: number): Promise<string>\n createIssue(repo: string, title: string, body: string): Promise<number>\n createPullRequest(repo: string, branch: string, title: string): Promise<number>\n openPullRequestForBranch(\n targetRepo: string,\n sourceRepo: string,\n sourceBranch: string,\n title: string,\n body: string,\n ): Promise<number>\n getIssueStatus(repo: string, issueNumber: number): Promise<{ state: string; labels: string[]; url: string }>\n listClaimIssues(repo: string): Promise<Array<{ number: number; title: string; state: string }>>\n cloneRepo(fullName: string, destination: string): Promise<void>\n copyDirectory(source: string, destination: string): Promise<void>\n}\n\nfunction hasGh(): boolean {\n try {\n execSync('which gh', { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n}\n\nasync function runGh(args: readonly string[]): Promise<string> {\n if (!hasGh()) {\n throw new Error('gh CLI is required for this workflow')\n }\n const result = await exec('gh', args, { encoding: 'utf8' })\n return result.stdout.trim()\n}\n\nasync function copyDirRecursively(source: string, target: string): Promise<void> {\n await fs.mkdir(target, { recursive: true })\n const entries = await fs.readdir(source, { withFileTypes: true })\n for (const entry of entries) {\n if (entry.name === '.git') {\n continue\n }\n const from = path.join(source, entry.name)\n const to = path.join(target, entry.name)\n if (entry.isDirectory()) {\n await copyDirRecursively(from, to)\n continue\n }\n if (entry.isSymbolicLink()) {\n const link = await fs.readlink(from)\n await fs.symlink(link, to)\n continue\n }\n if (entry.isFile()) {\n await fs.copyFile(from, to)\n }\n }\n}\n\nexport class GitHubProvider implements ForgeProvider {\n providerName(): string {\n return 'gh'\n }\n\n async getUser(): Promise<string> {\n const json = await runGh(['auth', 'status', '--json', 'user'])\n const parsed = JSON.parse(json) as { user?: { login?: string } }\n return parsed.user?.login || ''\n }\n\n async getIssueUrl(repo: string, number: number): Promise<string> {\n return `https://github.com/${repo}/issues/${number}`\n }\n\n async createIssue(repo: string, title: string, body: string): Promise<number> {\n const raw = await runGh([\n 'issue',\n 'create',\n '-R',\n repo,\n '--title',\n title,\n '--body',\n body,\n '--label',\n 'skillcraft-claim',\n ])\n const match = raw.match(/\\b(\\d+)$/)\n if (!match) {\n return 0\n }\n return Number(match[1])\n }\n\n async createPullRequest(targetRepo: string, branch: string, title: string): Promise<number> {\n const raw = await runGh([\n 'pr',\n 'create',\n '--repo',\n targetRepo,\n '--head',\n branch,\n '--base',\n 'main',\n '--title',\n title,\n '--body',\n `Generated by skillcraft for ${title}`,\n '--fill-first',\n ])\n const match = raw.match(/\\b(\\d+)$/)\n if (!match) {\n return 0\n }\n return Number(match[1])\n }\n\n async openPullRequestForBranch(\n targetRepo: string,\n sourceRepo: string,\n sourceBranch: string,\n title: string,\n body: string,\n ): Promise<number> {\n const raw = await runGh([\n 'pr',\n 'create',\n '--repo',\n targetRepo,\n '--head',\n `${sourceRepo}:${sourceBranch}`,\n '--base',\n 'main',\n '--title',\n title,\n '--body',\n body,\n ])\n const match = raw.match(/\\b(\\d+)$/)\n if (!match) {\n return 0\n }\n return Number(match[1])\n }\n\n async getIssueStatus(repo: string, issueNumber: number): Promise<{ state: string; labels: string[]; url: string }> {\n const raw = await runGh(['issue', 'view', String(issueNumber), '--repo', repo, '--json', 'state,labels,url'])\n const parsed = JSON.parse(raw) as { state: string; labels: Array<{ name: string }>; url: string }\n return {\n state: parsed.state,\n labels: parsed.labels?.map((label) => label.name) ?? [],\n url: parsed.url,\n }\n }\n\n async listClaimIssues(repo: string): Promise<Array<{ number: number; title: string; state: string }>> {\n const raw = await runGh([\n 'issue',\n 'list',\n '--repo',\n repo,\n '--label',\n 'skillcraft-claim',\n '--state',\n 'all',\n '--json',\n 'number,title,state',\n '--limit',\n '50',\n ])\n const parsed = JSON.parse(raw) as Array<{ number: number; title: string; state: string }>\n return parsed\n }\n\n async cloneRepo(fullName: string, destination: string): Promise<void> {\n const temp = path.resolve(destination)\n await runGh(['repo', 'clone', fullName, temp])\n }\n\n async copyDirectory(source: string, destination: string): Promise<void> {\n const info = await fs.readdir(destination).catch(() => undefined)\n if (info) {\n await fs.rm(destination, { recursive: true, force: true })\n }\n await fs.mkdir(destination, { recursive: true })\n await copyDirRecursively(source, destination)\n }\n}\n","import { GitHubProvider } from './github.js'\n\nexport type ProviderName = 'gh'\n\nexport const providers = {\n gh: () => new GitHubProvider(),\n}\n\nexport function getProvider(name: 'gh'): GitHubProvider {\n return providers[name]()\n}\n","import { isEnabled } from '@/core/state'\nimport { gitLogWithMessages } from '@/core/git'\nimport { readProof } from '@/core/proof'\n\nexport async function runVerify(): Promise<void> {\n const repoPath = process.cwd()\n if (!(await isEnabled(repoPath))) {\n throw new Error('Repository is not enabled')\n }\n\n const messages = await gitLogWithMessages(repoPath, 200)\n const referenced = messages\n .map((entry: { message: string }) => {\n const match = entry.message.match(/Skillcraft-Ref:\\s*(\\S+)/)\n return match?.[1]\n })\n .filter(Boolean) as string[]\n\n let missing = 0\n for (const id of referenced) {\n const proof = await readProof(repoPath, id)\n if (!proof) {\n missing += 1\n process.stdout.write(`missing proof object: ${id}\\n`)\n continue\n }\n if (!proof.commit || !proof.timestamp) {\n missing += 1\n process.stdout.write(`invalid proof object: ${id}\\n`)\n }\n }\n\n if (missing > 0) {\n process.stdout.write(`verify failed: ${missing} missing/invalid proofs\\n`)\n process.exitCode = 1\n return\n }\n\n process.stdout.write(`verify passed: ${referenced.length} commit proofs resolved\\n`)\n}\n","import { createHash } from 'node:crypto'\nimport yaml from 'yaml'\nimport { loadRepos } from '@/core/config'\nimport { hasSkillcraftDir } from '@/core/state'\nimport { loadProofFromRepo } from '@/core/progress'\nimport { getProvider } from '@/providers'\nimport { loadGlobalConfig } from '@/core/config'\nimport { gitRemote } from '@/core/git'\n\nexport async function runClaimList(): Promise<void> {\n const config = await loadGlobalConfig()\n const provider = getProvider(config.provider ?? 'gh')\n const issues = await provider.listClaimIssues('skillcraft-gg/credentials')\n if (!issues.length) {\n process.stdout.write('no claim issues found\\n')\n return\n }\n for (const issue of issues) {\n process.stdout.write(`#${issue.number} ${issue.title} (${issue.state})\\n`)\n }\n}\n\nexport async function runClaimStatus(reference: string): Promise<void> {\n const issue = Number(reference)\n if (!issue) {\n throw new Error('claim status requires issue number')\n }\n const config = await loadGlobalConfig()\n const provider = getProvider(config.provider ?? 'gh')\n const status = await provider.getIssueStatus('skillcraft-gg/credentials', issue)\n process.stdout.write(`issue #${issue}\\n`)\n process.stdout.write(`state: ${status.state}\\n`)\n process.stdout.write(`labels: ${status.labels.join(', ') || 'none'}\\n`)\n process.stdout.write(`url: ${status.url}\\n`)\n}\n\nexport async function runClaim(credential: string, opts: { allRepos?: boolean; repo?: string[] }): Promise<void> {\n const payload = await makeClaimPayload(credential, {\n allRepos: opts?.allRepos,\n repo: opts?.repo,\n })\n const yamlPayload = yaml.stringify(payload)\n const config = await loadGlobalConfig()\n const provider = getProvider(config.provider ?? 'gh')\n const issue = await provider.createIssue('skillcraft-gg/credentials', `claim: ${credential}`, yamlPayload)\n process.stdout.write(`opened claim: #${issue}\\n`)\n process.stdout.write(`payload:\\n${yamlPayload}\\n`)\n}\n\nasync function makeClaimPayload(\n credential: string,\n options: { allRepos?: boolean; repo?: string[] },\n): Promise<{\n claim_version: number\n claimant: { github: string }\n credential: { id: string }\n sources: Array<{ repo: string; commits: string[] }>\n claim_id: string\n}> {\n const repos = await resolveClaimRepos(options)\n const sources = [] as Array<{ repo: string; commits: string[] }>\n for (const repoPath of repos) {\n const proofs = await loadProofFromRepo(repoPath)\n const remote = (await gitRemote(repoPath)) || repoPath\n\n const commitIds = Array.from(new Set(proofs.map((proof) => proof?.commit).filter(Boolean) as string[]))\n sources.push({\n repo: remote,\n commits: commitIds,\n })\n }\n\n const username = process.env.GITHUB_USER || process.env.USER || 'unknown'\n const claimSeed = `${username}:${credential}:${sources.map((s) => `${s.repo}:${s.commits.length}`).join('|')}:${Date.now()}`\n const claimId = createHash('sha256').update(claimSeed).digest('hex').slice(0, 8)\n\n return {\n claim_version: 1,\n claimant: {\n github: username,\n },\n credential: {\n id: credential,\n },\n sources,\n claim_id: `sha256:${claimId}`,\n }\n}\n\nasync function resolveClaimRepos(options: { allRepos?: boolean; repo?: string[] }): Promise<string[]> {\n const repoList = options.allRepos ? (await loadRepos()).repos.map((entry) => entry.path) : [process.cwd()]\n const selected = options.repo ? options.repo : repoList\n const valid = [] as string[]\n for (const repoPath of selected) {\n if (!(await hasSkillcraftDir(repoPath))) {\n continue\n }\n valid.push(repoPath)\n }\n return valid\n}\n","import path from 'node:path'\nimport fs from 'node:fs/promises'\nimport { isEnabled } from '@/core/state'\nimport { contextPath } from '@/core/paths'\nimport { readJson, writeJson } from '@/core/fs'\nimport { isValidIdentifier } from '@/core/validation'\nimport { assertNonEmpty } from '@/core/validation'\nimport { getProvider } from '@/providers'\nimport { loadGlobalConfig } from '@/core/config'\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { splitArgPair } from '@/core/validation'\n\nconst execPromise = promisify(execFile)\n\nexport async function runLoadoutUse(id: string): Promise<void> {\n if (!isValidIdentifier(id)) {\n throw new Error('loadout id must be <owner>/<slug>')\n }\n const cwd = process.cwd()\n if (!(await isEnabled(cwd))) {\n throw new Error('Repository is not enabled')\n }\n\n const current = (await readJson(contextPath(cwd))) as { activeLoadouts?: string[] } | null\n const active = Array.isArray(current?.activeLoadouts) ? current!.activeLoadouts.filter(Boolean) : []\n if (!active.includes(id)) {\n active.push(id)\n }\n await writeJson(contextPath(cwd), { activeLoadouts: active })\n process.stdout.write(`activated loadout: ${id}\\n`)\n}\n\nexport async function runLoadoutClear(): Promise<void> {\n const cwd = process.cwd()\n if (!(await isEnabled(cwd))) {\n throw new Error('Repository is not enabled')\n }\n await writeJson(contextPath(cwd), { activeLoadouts: [] })\n process.stdout.write('cleared active loadouts\\n')\n}\n\nexport async function runLoadoutShare(id: string): Promise<void> {\n const cleanId = assertNonEmpty(id, 'loadout id')\n if (!isValidIdentifier(cleanId)) {\n throw new Error('loadout id must be <owner>/<slug>')\n }\n const { owner, slug: slugPart } = splitArgPair(cleanId)\n\n const cwd = process.cwd()\n const loadoutFile = path.join(cwd, 'loadout.yaml')\n await fs.access(loadoutFile)\n const stat = await fs.stat(loadoutFile)\n if (!stat.isFile()) {\n throw new Error('loadout.yaml not found in current directory')\n }\n\n const config = await loadGlobalConfig()\n const provider = getProvider(config.provider ?? 'gh')\n const remote = `skillcraft-gg/loadouts`\n const temp = path.join(process.cwd(), '.skillcraft-temp-loadout-share')\n const branch = `skillcraft-loadout-${owner}-${slugPart}`\n\n try {\n await fs.rm(temp, { force: true, recursive: true })\n await provider.cloneRepo(remote, temp)\n await runGit(temp, ['checkout', '-B', branch])\n\n const targetDir = path.join(temp, 'loadouts', owner, slugPart)\n await fs.rm(targetDir, { force: true, recursive: true }).catch(() => undefined)\n await fs.mkdir(path.dirname(targetDir), { recursive: true })\n await fs.copyFile(loadoutFile, path.join(targetDir, 'loadout.yaml'))\n\n await runGit(temp, ['add', targetDir])\n await runGit(temp, ['commit', '-m', `Loadout: publish ${cleanId}`]).catch(async () => {\n throw new Error('nothing to commit; loadout may already be published')\n })\n await runGit(temp, ['push', '-u', 'origin', branch]).catch(() => {\n throw new Error('unable to push loadout publish branch')\n })\n await provider.createPullRequest(\n remote,\n branch,\n `Loadout publish: ${cleanId}`,\n ).catch(() => {\n process.stdout.write('unable to create PR automatically. Please open one manually from your branch.\\n')\n })\n process.stdout.write(`loadout publish workflow completed for ${cleanId}\\n`)\n } finally {\n await fs.rm(temp, { force: true, recursive: true })\n }\n}\n\nasync function runGit(cwd: string, args: string[]): Promise<string> {\n const { stdout } = await execPromise('git', args, { cwd })\n return stdout.trim()\n}\n","import { buildProofFromPending, buildCommitMessageWithProof, pushProofBranch } from '@/core/proof'\nimport { isEnabled } from '@/core/state'\nimport { removeFile, writeJson } from '@/core/fs'\nimport { pendingPath, contextPath } from '@/core/paths'\nimport { amendCommitMessage, gitHeadCommit } from '@/core/git'\nimport { writeProof } from '@/core/proof'\n\nexport async function runHook(repoPath: string): Promise<void> {\n if (!(await isEnabled(repoPath))) {\n return\n }\n\n const commit = await gitHeadCommit(repoPath)\n const timestamp = new Date().toISOString()\n\n const result = await buildProofFromPending(repoPath, commit, timestamp)\n if (!result) {\n return\n }\n\n const message = await buildCommitMessageWithProof(repoPath, result.proofId)\n await amendCommitMessage(repoPath, message)\n\n const amendedCommit = await gitHeadCommit(repoPath)\n if (amendedCommit !== commit) {\n await writeProof(repoPath, {\n ...result.proof,\n commit: amendedCommit,\n })\n }\n\n await writeJson(pendingPath(repoPath), { skills: [] })\n}\n\nexport async function runHookPush(repoPath: string, remote = 'origin'): Promise<void> {\n await pushProofBranch(repoPath, remote)\n}\n\nexport async function runHookClear(repoPath: string): Promise<void> {\n await Promise.all([removeFile(pendingPath(repoPath)), removeFile(contextPath(repoPath)),])\n process.stdout.write(`cleared hook state in ${repoPath}\\n`)\n}\n"],"mappings":"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","names":["Command","package_default","execFileCb","promisify","path","execFile","git","args","cwd","options","stdout","error","message","isGitRepo","gitRoot","gitRemote","remote","gitCommitMessage","commit","gitHeadCommit","gitHasRef","ref","gitLsTreeNames","subPath","raw","gitShowText","filePath","gitLogWithMessages","maxCount","n","entry","messageParts","amendCommitMessage","env","tempFile","writeFile","fs","path","os","defaultUserDir","skillcraftGlobalDir","skillcraftConfigPath","skillcraftReposPath","trackedCredentialsPath","credentialIndexCachePath","localStateDir","repoPath","localGitDir","localSkillcraftConfig","localRepoHookPath","localRepoPrePushHookPath","localRepoPostPushHookPath","pendingPath","contextPath","pluginPath","managedPluginPath","aiModelContextPath","fs","path","ensureDir","dirPath","readText","filePath","writeText","content","fileExists","readJson","raw","writeJson","value","json","removeFile","fs","buildHookScript","body","rawCliPath","postCommitScript","postPushScript","prePushScript","installPostCommitHook","repoPath","writeText","localRepoHookPath","localRepoPostPushHookPath","localRepoPrePushHookPath","removePostCommitHook","z","ProofVersionSchema","DefaultProofRef","PendingSchema","ContextSchema","ProofAgentSchema","ProofModelSchema","ConfigSchema","RepoEntrySchema","ReposFileSchema","TrackedCredentialSchema","TrackedCredentialsFileSchema","loadGlobalConfig","raw","readJson","skillcraftConfigPath","parsed","ConfigSchema","loadLocalConfig","repoPath","localSkillcraftConfig","saveGlobalConfig","config","ensureDir","skillcraftGlobalDir","writeJson","loadRepos","skillcraftReposPath","ReposFileSchema","saveRepos","file","addRepo","entry","next","item","removeRepo","loadTrackedCredentials","trackedCredentialsPath","TrackedCredentialsFileSchema","saveTrackedCredentials","addTrackedCredential","id","current","sortTrackedCredentialEntries","removeTrackedCredential","before","a","b","runDisable","cwd","isGitRepo","root","gitRoot","removeFile","localSkillcraftConfig","pendingPath","contextPath","pluginPath","managedPluginPath","aiModelContextPath","localGitDir","removePostCommitHook","removeRepo","createHash","path","os","fs","localIdentifierPattern","localIdentifierPatternWithoutVersion","externalSourceIdWithoutVersion","normalizeSkillId","value","parsed","splitSkillIdentifier","isValidIdentifier","isValidSkillIdentifier","input","trimmed","splitIdentifierAndVersion","id","isLocalIdentifierWithoutVersion","owner","slug","match","source","firstPart","secondPart","assertNonEmpty","field","v","parts","version","splitArgPair","PROOFS_DIR","normalizeProofBranch","proofRef","DefaultProofRef","proofPathForId","proofId","proofBranch","repoPath","config","loadLocalConfig","proofSearchRefs","branch","normalized","localRef","remoteRef","refs","gitHasRef","ensureProofBranch","fullRef","git","withProofWorktree","action","removeProofWorktrees","worktree","fs","path","os","removeProofWorktree","worktreePath","targetRef","lines","currentWorktree","currentBranch","maybeRemove","line","loadProofsFromRepo","searchRefs","files","listed","gitLsTreeNames","file","proofs","proof","readProof","parseSkillFromRaw","value","parsed","splitSkillIdentifier","isValidSkillIdentifier","normalizeSkillIds","raw","item","entry","buildProofId","skills","timestamp","loadouts","createHash","loadPending","readJson","pendingPath","PendingSchema","loadContext","contextPath","ContextSchema","loadAiModelContext","aiModelContextPath","record","agentValue","modelValue","normalizeLowerCase","normalizeModelName","parseProof","payload","parseAgentValue","parseModelValue","provider","normalizedProvider","normalizedName","gitShowText","writeProof","skill","proofFile","ensureDir","writeJson","pushProofBranch","remoteName","gitRemote","currentProofIdForCommit","commit","buildProofFromPending","pending","aiModelContext","stripDraftMessage","message","buildCommitMessageWithProof","existing","gitCommitMessage","cleaned","isEnabled","repoPath","configPath","localSkillcraftConfig","fileExists","raw","readJson","ConfigSchema","hasSkillcraftDir","localGitDir","runStatus","cwd","git","isGitRepo","enabled","isEnabled","pending","loadPending","contextExists","fileExists","contextPath","hasHook","localRepoHookPath","head","gitHeadCommit","proofId","currentProofIdForCommit","withSkillcraft","gitLogWithMessages","entry","branch","loadLocalConfig","proofBranchExists","gitHasRef","runDoctor","checks","localSkillcraftConfig","name","ok","isToolAvailable","tool","execSync","path","runEnable","cwd","isGitRepo","root","gitRoot","config","loadGlobalConfig","fallback","saveGlobalConfig","ensureDir","localGitDir","path","managedPluginPath","writeText","getManagedPluginSource","writeJson","aiModelContextPath","branchRef","DefaultProofRef","gitHasRef","git","localSkillcraftConfig","skillcraftGlobalDir","pendingPath","contextPath","pluginPath","installPostCommitHook","remote","gitRemote","addRepo","runReposList","data","loadRepos","entry","index","runReposPrune","next","item","isGitRepo","gitRoot","saveRepos","loadProofFromRepo","repoPath","loadProofsFromRepo","path","DEFAULT_CREDENTIAL_INDEX_URL","CREDENTIAL_INDEX_CACHE_REFRESH_MS","CREDENTIAL_INDEX_CACHE_VERSION","CREDENTIAL_INDEX_CACHE_PATH","credentialIndexCachePath","getCredentialIndexUrl","readCredentialIndexCache","cachePath","raw","readJson","isObject","cachedAt","parseInteger","entries","normalizeCredentialIndexEntries","value","parsed","isCredentialIndexCacheFresh","cache","loadCredentialIndex","options","explicitPath","loadIndexFromPath","cached","loadIndexFromRemote","writeCredentialIndexCache","error","fileExists","url","response","filePath","ensureDir","path","payload","writeJson","normalizeRequirements","requirements","requirementTree","normalizeRequirementRoot","normalizeNonNegativeInteger","parseRequirementNode","hasExplicitAnd","hasExplicitOr","unexpected","key","normalizeRequirementList","buildImplicitAndFromShortcuts","location","entry","index","normalizeShortHandList","values","text","parseScalarText","normalized","known","skill","loadout","hasAgent","agent","normalizeAgentRequirement","hasModel","model","normalizeModelRequirement","nested","keys","valueForKey","childIndex","node","provider","name","evaluateRequirements","proofs","provenCommits","provenRepos","proofSkills","proofLoadouts","proofAgents","proofModels","dedupedCommits","dedupedRepos","proofEntry","proof","parseIdentifierWithVersion","modelProvider","modelName","requirementResult","evaluateRequirementTree","checks","resultReasons","failedRequirementReasons","context","childResults","noExplicitChecks","child","childResult","satisfied","proofSkillsMatch","parseTextRequirement","expectedProvider","normalizeRequirementText","expectedName","candidate","hasProvider","hasName","parts","matchesId","actualId","actualVersion","expected","trimmed","fallback","normalizedEntry","normalizeCredentialIndexEntry","left","right","id","getCredentialIndexEntries","printLines","lines","resolveTrackedRepos","data","loadRepos","repoPaths","repos","entry","isEnabled","runProgress","options","tracked","trackedCredList","loadTrackedCredentials","printJsonResult","buildPayload","indexById","mapCredentials","getCredentialIndexEntries","proofFiles","proofs","provenRepos","provenCommits","repoPath","proofsInRepo","loadProofFromRepo","remote","gitRemote","proof","provenCommitList","provenRepoList","payload","evaluated","definition","makeMissingDefinitionResult","result","evaluateRequirements","formatResult","lines","reason","printLines","runProgressTrack","rawId","id","assertNonEmpty","addTrackedCredential","runProgressUntrack","removeTrackedCredential","params","index","credentialId","provenRepositories","path","fs","fs","path","execFile","execSync","promisify","exec","hasGh","runGh","args","copyDirRecursively","source","target","entries","entry","from","to","link","GitHubProvider","json","repo","number","title","body","match","targetRepo","branch","sourceRepo","sourceBranch","issueNumber","raw","parsed","label","fullName","destination","temp","providers","GitHubProvider","getProvider","name","execFile","promisify","ora","execPromise","runSkillsPublish","slug","ref","assertNonEmpty","owner","slugPart","splitArgPair","cwd","isEnabled","files","fs","path","config","loadGlobalConfig","provider","getProvider","destination","branch","temp","runGit","target","runSkillsAdd","rawId","cleanInput","parsed","splitSkillIdentifier","loadSearchIndex","normalized","normalizeSkillIds","existing","loadPending","next","writeJson","pendingPath","runSkillsValidate","checks","exists","name","ok","runSkillsList","proofs","pending","loadProofFromRepo","skills","proof","item","skill","list","runSkillsSearch","rawQuery","options","entries","loadSearchIndexEntries","getSearchLimit","query","sourceFilter","limit","sorted","entry","getSkillSource","value","left","right","leftName","rightName","shown","message","title","lines","runtime","tags","updatedLabel","formatUpdatedAt","formatSearchResultName","payload","runSkillsInspect","cleanId","match","manifest","loadSkillManifest","formatInspectOutput","source","manifestUrl","buildSkillManifestUrl","controller","timeout","response","text","isHtmlDocument","parseSkillManifest","error","rawUrl","url","toRawManifestUrl","parts","blobIndex","repo","remainingPath","rawParts","input","index","summary","i","line","isJson","outputMode","explicitPath","loadEntries","raw","normalizeSearchIndexEntries","shouldShowSearchSpinner","action","spinner","normalizeSearchIndexEntry","normalizeString","id","normalizeSkillId","normalizeText","normalizeStringArray","separatorIndex","requestedLimit","deriveSearchResultSlug","separator","suffix","updatedAt","pathToCheck","args","stdout","runSkillsValidateAndExit","runVerify","repoPath","isEnabled","referenced","gitLogWithMessages","entry","missing","id","proof","readProof","createHash","yaml","runClaimList","config","loadGlobalConfig","issues","getProvider","issue","runClaimStatus","reference","status","runClaim","credential","opts","payload","makeClaimPayload","yamlPayload","yaml","options","repos","resolveClaimRepos","sources","repoPath","proofs","loadProofFromRepo","remote","gitRemote","commitIds","proof","username","claimSeed","s","claimId","createHash","repoList","loadRepos","entry","selected","valid","hasSkillcraftDir","path","fs","execFile","promisify","execPromise","promisify","execFile","runLoadoutUse","id","isValidIdentifier","cwd","isEnabled","current","readJson","contextPath","active","writeJson","runLoadoutClear","runLoadoutShare","cleanId","assertNonEmpty","owner","slugPart","splitArgPair","loadoutFile","path","fs","config","loadGlobalConfig","provider","getProvider","remote","temp","branch","runGit","targetDir","args","stdout","runHook","repoPath","isEnabled","commit","gitHeadCommit","timestamp","result","buildProofFromPending","message","buildCommitMessageWithProof","amendCommitMessage","amendedCommit","writeProof","writeJson","pendingPath","runHookPush","remote","pushProofBranch","program","Command","package_default","withCommand","runEnable","runDisable","runStatus","runDoctor","reposCommand","runReposList","runReposPrune","progressCommand","options","command","outputMode","runProgress","credentialId","runProgressTrack","runProgressUntrack","skillsCommand","id","runSkillsAdd","ownerSlug","runSkillsPublish","runSkillsValidateAndExit","runSkillsList","_options","runSkillsInspect","value","query","runSkillsSearch","runVerify","claimCommand","credential","runClaimList","runClaim","issue","runClaimStatus","loadoutCommand","runLoadoutUse","runLoadoutClear","runLoadoutShare","name","repoPath","remote","runHook","runHookPush","fn","args","error"]}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "skillcraft",
3
+ "version": "0.1.1",
4
+ "description": "Skillcraft CLI for git-native skill evidence and credential workflow",
5
+ "type": "module",
6
+ "bin": {
7
+ "skillcraft": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist/index.js",
11
+ "dist/index.js.map"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsup",
15
+ "clean": "rm -rf dist",
16
+ "test": "npm run build && node --test tests/*.test.mjs",
17
+ "smoke": "npm test",
18
+ "format": "printf ''",
19
+ "start": "node dist/index.js",
20
+ "check": "tsc --noEmit",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "dependencies": {
27
+ "commander": "^13.1.0",
28
+ "ora": "^8.2.0",
29
+ "yaml": "^2.6.0",
30
+ "zod": "^3.24.2"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^24.8.0",
34
+ "tsup": "^8.5.0",
35
+ "typescript": "^5.7.2"
36
+ }
37
+ }