@brainervirus/workit-claude-code 8.5.0 → 8.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "workit",
3
3
  "displayName": "Workit",
4
- "version": "8.5.0",
4
+ "version": "8.5.2",
5
5
  "description": "Workflow rails for agentic coding: task context on every session, branch policy on shell commands, and the workit method skills",
6
6
  "author": {
7
7
  "name": "BrainerVirus"
@@ -162,7 +162,7 @@ ${r.addendum}`:""}
162
162
  `),m=h.findIndex((w)=>w.trim()===f),v=(m<0?h:h.slice(0,m+1)).join(`
163
163
  `).length+1;p+=v}}else if(/\s/.test(d))u();else if(d==="("||d===")"){if(d==="("&&s&&o.endsWith("$"))o=o.slice(0,-1),s=o!=="";l(),r.push({words:[],redirects:[],group:d==="("?"open":"close"})}else if(";&|".includes(d)){if(d==="&"&&e[p+1]===">")continue;l()}else if(d===">"){if(s&&/^\d$/.test(o))o="",s=!1;else u();if(e[p+1]===">")p++;if(e[p+1]==="&")p++,o="&",s=!0;i="redirect"}else if(d==="<"&&t==="posix")if(u(),e[p+1]==="<"){if(p++,e[p+1]==="<")p++;i="heredoc"}else i="input";else o+=d,s=!0}return l(),r};var Ac={kind:"none"},c$=process.platform==="darwin"||process.platform==="win32",Bg=(e)=>{let t="";for(let r=Ze.resolve(e);;r=Ze.dirname(r))try{return Ze.join(a$(r),t)}catch{if(Ze.dirname(r)===r)return Ze.resolve(e);t=t?Ze.join(Ze.basename(r),t):Ze.basename(r)}},u$=(e,t,r,n)=>{let o=(c)=>c$?c.toLowerCase():c,s=Ze.relative(o(Bg(t)),o(Bg(Ze.resolve(e,r))));if(s.startsWith("..")||Ze.isAbsolute(s))return!0;let i=s.split(Ze.sep).join("/"),a=i.split("/");return/\.mdx?$/i.test(i)||a[0]==="docs"||a.includes("plans")||[...n].some((c)=>o(c)===i)},l$=new Set(["sudo","command","env","nohup","time","exec","xargs"]),zn=(e)=>e.filter((t)=>!t.startsWith("-")),d$=(e)=>{let t=e;while(t.length&&(l$.has(t[0])||/^\w+=/.test(t[0])))t=t.slice(1);let[r,...n]=t,o=(r?.split(/[\\/]/).at(-1)??"").toLowerCase();if(!o||o==="workit"||o==="npx"&&n.some((s)=>/workit/.test(s)))return[];switch(o){case"touch":case"mkdir":case"rm":case"rmdir":case"tee":case"mv":case"truncate":return zn(n);case"cp":case"ln":case"install":{let s=n.indexOf("-t");if(s>=0)return n[s+1]?[n[s+1]]:null;let i=zn(n).at(-1);return i?[i]:null}case"dd":return n.filter((s)=>s.startsWith("of=")).map((s)=>s.slice(3));case"sed":case"perl":{if(!n.some((a)=>/^-[a-zA-Z]*i|^--in-place/.test(a)))return[];let s=n.some((a)=>a==="-e"||a==="-f"),i=[];for(let a=0;a<n.length;a++)if(n[a]==="-e"||n[a]==="-f")a++;else if(!n[a].startsWith("-"))i.push(n[a]);return s?i:i.slice(1)}case"patch":return null;case"set-content":case"add-content":case"out-file":case"new-item":case"ni":case"remove-item":case"del":case"copy-item":case"move-item":{let s=n.findIndex((c)=>/^-(?:path|filepath|literalpath|destination)$/i.test(c));if(s>=0)return n[s+1]?[n[s+1]]:null;let i=zn(n);if(o==="move-item")return i.length?i:null;let a=o==="copy-item"?i.at(-1):i[0];return a?[a]:null}case"git":{let s=zn(n)[0];if(s==="apply")return null;if(s==="restore"||s==="mv"||s==="rm")return zn(n).slice(1);if(s==="checkout"&&n.includes("--"))return n.slice(n.indexOf("--")+1);return[]}default:return[]}},zc=(e)=>{let t=[],r=!1;for(let n of hr(e)){t.push(...n.redirects.filter((s)=>!/^\/dev\/(?:null|stdout|stderr|tty)$/.test(s)));let o=d$(n.words);if(o===null)r=!0;else t.push(...o)}if(!r&&t.length===0)return{writes:!1,targets:null};return{writes:!0,targets:r?null:t}},Nn=new Map,Mg=(e,t)=>[...t].map((r)=>ar(Ze.resolve(e,r))??"-").join("\x00"),p$=(e)=>{let t=new Ar(e),r=t.listTaskIndex();if(!r.ok)return null;let n=t.currentKey();if(!n.ok)return null;let o=r.data.filter((f)=>f.key===n.data.key&&f.status!=="closed").toSorted((f,h)=>h.updatedAt.localeCompare(f.updatedAt))[0];if(!o)return{blockers:[],root:t.root,plans:new Set};let s=us(t.root),i=`${o.id}\x00${o.revision}\x00${s.ok&&ar(s.value)||"-"}`,a=Nn.get(t.root);if(a&&a.key===i&&a.planKey===Mg(t.root,a.plans))return a;let c=t.readTask(o.id);if(!c.ok)return null;let u=t.readWorkspace(),l=new Set((In(c.data)?.refs??[]).flatMap((f)=>f.kind==="file"?[f.path]:[])),d={blockers:jm(c.data,t.root).filter((f)=>{let h=c.data.policy?.requirements.find((m)=>m.ruleId===f.ruleId&&m.before==="write");return!(h?.acceptanceAllowed&&u.ok&&u.data&&ds(c.data,u.data,h,t.root).length>0)}),root:t.root,plans:l,key:i,planKey:Mg(t.root,l)};if(Nn.set(t.root,d),Nn.size>32)Nn.delete(Nn.keys().next().value);return d};function xs(e,t){try{let r=p$(e);if(!r||r.blockers.length===0)return Ac;if(t?.length&&t.every((o)=>u$(e,r.root,o,r.plans)))return Ac;return{kind:"deny",reason:`workit before-write gate: ${r.blockers.map((o)=>`${o.ruleId}: ${o.reason}`).join("; ")}. Markdown, docs/, plans/ and files outside the checkout stay writable.`,unblock:r.blockers[0].reason}}catch{return Ac}}import{spawnSync as f$}from"node:child_process";import{createHash as Ug}from"node:crypto";import wt from"node:fs";import Kg from"node:os";import at from"node:path";var Nc={kind:"none"},h$=new Set(["sh","bash","zsh","dash","ksh"]),m$=new Set(["sudo","command","env","nohup","time","exec","nice","&"]),g$=/^-[a-zA-Z]*c[a-zA-Z]*$/,k$=new Set(["cd","chdir","set-location","sl"]),y$=new Set(["pushd","push-location"]),v$=new Set(["popd","pop-location"]),w$=new Set(["-c","--git-dir","--work-tree","--namespace","--exec-path","--config-env","--super-prefix"]),b$=(e)=>at.isAbsolute(e)||/^[A-Za-z]:[\\/]/.test(e)||e.startsWith("\\\\"),Ss=(e,t)=>{if(e===void 0||/[$`*?]/.test(t)||t==="-")return;let r=t==="~"||t.startsWith("~/")?at.join(Kg.homedir(),t.slice(1)):t;return e===null||b$(r)?r:at.join(e,r)},Hg=(e)=>{let t=e.slice(1),r=t.findIndex((n)=>/^-(?:literal)?path$/i.test(n));if(r>=0)return t[r+1]??null;return t.find((n)=>n==="-"||!n.startsWith("-"))??null},_$=(e)=>{let t=e;for(;;){let r=t[0];if(r===void 0)return t;if(/^\w+=/.test(r))t=t.slice(1);else if(m$.has(r)){t=t.slice(1);while(t[0]?.startsWith("-"))t=t.slice(t[0]==="-u"?2:1)}else if(r==="timeout"){t=t.slice(1);while(t[0]?.startsWith("-"))t=t.slice(1);t=t.slice(1)}else return t}},x$=(e)=>(e?.split(/[\\/]/).at(-1)??"").toLowerCase().replace(/\.exe$/,"");function Jg(e,t="posix",r=0){let n=[],o=null,s=[],i=[];for(let a of hr(e,t)){if(a.group==="open"){s.push({dir:o,stack:[...i]});continue}if(a.group==="close"){let d=s.pop();if(d)({dir:o,stack:i}=d);continue}let c=_$(a.words),u=x$(c[0]);if(k$.has(u)){let d=Hg(c);o=d===null?Kg.homedir():Ss(o,d);continue}if(y$.has(u)){let d=Hg(c);i.push(o),o=d===null||d==="-"?void 0:Ss(o,d);continue}if(v$.has(u)){o=i.length?i.pop():void 0;continue}if(h$.has(u)&&r<3){let d=c.findIndex((h,m)=>m>0&&g$.test(h)),f=d>0?c[d+1]:void 0;if(f)for(let h of Jg(f,"posix",r+1))n.push({...h,dir:h.dir===null?o:h.dir===void 0?void 0:Ss(o,h.dir)});continue}if(u==="gh"||u==="glab"){n.push({tool:u,dir:o,args:c.slice(1)});continue}if(u!=="git")continue;let l=o,p=1;for(;p<c.length;p++){let d=c[p];if(d==="-C")l=c[p+1]?Ss(l,c[++p]):l;else if(w$.has(d))p++;else if(!d.startsWith("-"))break}n.push({tool:"git",dir:l,args:c.slice(p)})}return n}var S$=new Set(["-o","--push-option","--receive-pack","--exec","--repo"]),$$=(e)=>{let t=!1,r=!1,n=!1,o=null,s=[];for(let c=1;c<e.length;c++){let u=e[c];if(u==="--"){s.push(...e.slice(c+1));break}if(u==="--dry-run"||/^-[a-zA-Z]*n[a-zA-Z]*$/.test(u))return null;if(u==="--repo")o=e[++c]??null;else if(u.startsWith("--repo="))o=u.slice(7);else if(S$.has(u))c++;else if(u==="--force"||/^-[a-zA-Z]*f[a-zA-Z]*$/.test(u))t=!0;else if(u.startsWith("--force-with-lease")||u==="--force-if-includes")r=!0;else if(["--all","--mirror","--branches","--tags"].includes(u))n=!0;else if(!u.startsWith("-"))s.push(u)}let i=o===null?s.slice(1):s;o??=s[0]??null;let a=[];for(let c of i){if(c.startsWith("+"))t=!0;let u=c.replace(/^\+/,""),l=u.indexOf(":"),p=l>=0?u.slice(l+1):u;if(!p)continue;if(p==="HEAD")a.push(null);else if(p.startsWith("refs/heads/"))a.push(p.slice(11));else if(!p.startsWith("refs/"))a.push(p)}if(i.length===0&&!n)a.push(null);return{kind:"push",targets:a,blindForce:t&&!r,remote:o}},R$={git:new Set(["-m","--message","-F","--file","-C","-c","--reuse-message","--reedit-message","--author","--date","--trailer","-t","--template","--cleanup","--fixup","--squash","-o","--push-option","--repo","--receive-pack","--exec"]),gh:new Set(["-b","--body","-F","--body-file","-t","--title","--subject","-A","--author-email"].concat(["-B","--base","-H","--head","-l","--label","-a","--assignee"]).concat(["-r","--reviewer","-m","--milestone","-p","--project","-T","--template"]).concat(["--match-head-commit","-R","--repo"])),glab:new Set(["-m","--message","--squash-message","--sha","-t","--title","-d","--description"].concat(["-b","--target-branch","-s","--source-branch","-l","--label"]).concat(["-a","--assignee","--reviewer","-R","--repo"]))},I$=(e)=>{let{tool:t,args:r}=e;if(r[0]==="help"||t!=="git"&&r[1]==="help")return!0;let n=R$[t];for(let o=0;o<r.length;o++){let s=r[o];if(s==="--")return!1;if(s==="--help"||s==="-h")return!0;if(n.has(s))o++}return!1};function T$(e){let t=e.args;if(I$(e))return null;let[r,n]=t;if(e.tool==="git"){if(r==="commit")return t.includes("--dry-run")?null:{kind:"commit",amend:t.includes("--amend")};if(r==="push")return $$(t);return null}let o=e.tool;if(r!==(o==="gh"?"pr":"mr"))return null;if(n==="merge")return{kind:"merge",forge:o};if(n==="create")return{kind:"pr-create",forge:o};if(["view","checks","status","ci","list"].includes(n??""))return{kind:"pr-read",forge:o};return null}var Lc=(e)=>{let t=Ae(e);if(t instanceof Error||!t.shared)return null;return{location:t,dir:e,branch:Zn(e,t).branch}},Gg=(e)=>{if(wt.existsSync(e.location.dir))return!0;try{return _n(e.location.top??e.dir)!==null}catch{return!1}},O$=(e,t)=>{try{let r=Wg(e);return r.protected.has(t.toLowerCase())||r.defaultTargetBranch.toLowerCase()===t.toLowerCase()}catch{return!1}},C$=(e,t)=>{if(t===null)return!0;try{let r=No(e.dir,e.branch);return r===null||r===t}catch{return!1}},P$=(e)=>{let t=e.location.git;if(!t||t.reftable)return null;try{let r=wt.readFileSync(at.join(t.gitDir,"HEAD"),"utf8").trim();if(/^[0-9a-f]{40,64}$/.test(r))return r;let n=/^ref: (refs\/.+)$/.exec(r)?.[1];if(!n)return null;let o=at.dirname(e.location.dir);try{return wt.readFileSync(at.join(o,n),"utf8").trim()||null}catch{}let s=wt.readFileSync(at.join(o,"packed-refs"),"utf8");return new RegExp(`^([0-9a-f]{40,64}) ${n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}$`,"m").exec(s)?.[1]??null}catch{return null}},_e=(e)=>`\`${e}\``,Vg=(e,t)=>{if(e.kind==="merge")return`workit: raw ${_e(e.forge==="gh"?"gh pr merge":"glab mr merge")} bypasses the merge grant and the verdict gate. Run ${_e("workit pr merge")} instead (it checks both; ${_e("workit help pr")}).`;return`workit: raw ${_e("git push")}${e.kind==="push"&&e.blindForce?" --force":""} onto ${t}, a protected branch or the default target, bypasses workit's protected-branch check. Push your feature branch with ${_e("workit git push")} (${_e("workit git push --force-with-lease")} to rewrite it) and land it with ${_e("workit pr merge")}.`},E$=(e,t,r)=>{switch(e.kind){case"commit":{let n=t==="cursor"&&r?`WORKIT_SESSION_ID=${r} `:"";return e.amend?`workit: raw ${_e("git commit --amend")} is recorded for this session; for new commits prefer ${_e(`${n}workit git commit -m '<msg>'`)} (adds the Workit-Session trailer and checks branch and commit policy).`:`workit: prefer ${_e(`${n}workit git commit -m '<msg>' [--all | -- <paths>]`)}: it adds the Workit-Session trailer and checks branch and commit policy.`}case"push":return e.blindForce?`workit: ${_e("git push --force")} overwrites without a lease; use ${_e("workit git push --force-with-lease")}.`:`workit: prefer ${_e("workit git push")}: it refuses protected branches and verifies the remote tip.`;case"pr-create":return`workit: prefer ${_e("workit pr create --fill")} (or --title/--body): it records the PR the merge gate checks.`;case"pr-read":return`workit: ${_e("workit pr status")} shows the PR, its checks and the verdict state; ${_e("workit ci wait")} waits for checks.`;case"merge":return null}},$s=(e,t,r)=>{let n=[],o=new Map;for(let s of Jg(t,r)){if(s.dir===void 0)continue;let i=T$(s);if(!i)continue;let a=at.resolve(e,s.dir??".");if(!o.has(a)){let u=Lc(a);o.set(a,u&&Gg(u)?u:null)}let c=o.get(a);if(c)n.push({action:i,repo:c})}return n},Rs=(e)=>{let t=Lc(e);return t!==null&&Gg(t)},Xg=(e,t,r)=>Yg(t)&&$s(e,t,r).some(({action:n})=>n.kind!=="commit"&&n.kind!=="pr-read"),Yg=(e)=>/\b(?:git|gh|glab)\b/i.test(e),Dc=(e)=>(e.event.kind==="shell.pre"||e.event.kind==="shell.post"?e.event.dialect:void 0)??"posix";function Is(e,t){try{if(!Yg(t))return Nc;let r=[];for(let{action:n,repo:o}of $s(e.cwd,t,Dc(e))){if(n.kind==="merge")return qg(Vg(n,null));if(n.kind==="push")for(let i of n.targets){let a=i??o.branch;if(a&&O$(o.dir,a)&&C$(o,n.remote))return qg(Vg(n,a))}let s=E$(n,e.host,e.session.id);if(s&&!r.includes(s))r.push(s)}return r.length?{kind:"context",text:r.join(`
164
164
  `)}:Nc}catch{return Nc}}var qg=(e)=>({kind:"deny",reason:e,unblock:null}),jc="next",A$=3600,Fc=(e,t,r)=>at.join(e.location.dir,"hooks",`commit-${Ug("sha256").update(`${t}\x00${r}`).digest("hex").slice(0,32)}.json`),Ts=(e,t)=>e??`cmd:${Ug("sha256").update(t).digest("hex")}`;function Wc(e,t,r){try{if(!e.session.id||!/\bcommit\b/.test(t))return;let n=Math.floor(Date.now()/1000);for(let{action:o,repo:s}of $s(e.cwd,t,Dc(e))){if(o.kind!=="commit")continue;let i=Fc(s,e.session.id,r);wt.mkdirSync(at.dirname(i),{recursive:!0}),wt.writeFileSync(i,`${JSON.stringify({head:P$(s),at:n})}
165
- `)}}catch{}}var z$=(e)=>{let t=f$("git",["log","-1","--format=%H%x1f%ct%x1f%s%x1f%(trailers:key=Workit-Session,valueonly,separator=%x2c)"],{cwd:e,encoding:"utf8",timeout:5000,windowsHide:!0,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_OPTIONAL_LOCKS:"0",LC_ALL:"C"}}),[r,n,o="",s=""]=(t.status===0?t.stdout.trim():"").split("\x1F");return r&&/^[0-9a-f]{40,64}$/.test(r)?{sha:r,committed:Number(n),subject:o,trailer:s.trim()||null}:null},Qg=(e,t,r)=>{let n;try{n=JSON.parse(wt.readFileSync(r,"utf8"))}catch{return}wt.rmSync(r,{force:!0});let o=e.session.id,s=Date.now()/1000;if(typeof n.at!=="number"||s-n.at>A$)return;if(!o||!t.branch)return;let i=z$(t.dir);if(!i||i.sha===n.head||i.committed<n.at)return;if(i.trailer&&i.trailer!==o)return;let a=Lr(t.dir);if(!a.ok)return;if(a.value.rows.some((u)=>u.type==="commit.recorded"&&(u.sha===i.sha||u.head===i.sha)))return;ls(t.dir,{type:"commit.recorded",actor:{host:e.host,session:o,agentId:e.session.agentId},branch:t.branch,head:i.sha,sha:i.sha,session:o,agentId:e.session.agentId,subject:i.subject.slice(0,200),files:[],fileCount:null,via:"raw_shell"})};function Zc(e,t,r){try{if(!e.session.id||!/\bcommit\b/.test(t))return;for(let{action:n,repo:o}of $s(e.cwd,t,Dc(e)))if(n.kind==="commit")Qg(e,o,Fc(o,e.session.id,r))}catch{}}function ek(e){try{if(!e.session.id)return;let t=Lc(e.cwd);if(!t)return;let r=Fc(t,e.session.id,jc);if(wt.existsSync(r))Qg(e,t,r)}catch{}}import{createHash as N$}from"node:crypto";import Bc from"node:fs";import ok from"node:path";var tk=["workit-shape","workit-implement","workit-review","workit-debug","workit-ship","workit-continue","workit-bdd","workit-test-audit","workit-deslop","workit-fanout","workit-verify-app","workit-retro","workit-architecture"],rk={"wk-shape":"workit-shape","wk-implement":"workit-implement","wk-review":"workit-review","wk-debug":"workit-debug","wk-ship":"workit-ship","wk-continue":"workit-continue","wk-bdd":"workit-bdd","wk-test-audit":"workit-test-audit","wk-deslop":"workit-deslop","wk-fanout":"workit-fanout","wk-verify-app":"workit-verify-app","wk-retro":"workit-retro","wk-architecture":"workit-architecture"};var nk=(e,t)=>{switch(e){case"claude-code":return`call the Skill tool with \`workit:${t.replace(/^workit-/,"")}\``;case"opencode":return`call the skill tool with \`${t}\``;default:return`read the \`${t}\` skill's SKILL.md and follow it`}};var L$=new Set(["workit-retro","workit-architecture"]),D$={claude_code:"claude-code",opencode:"opencode",codex_cli:"codex",codex_desktop:"codex",cursor:"cursor",pi:"pi"},j$=[["workit-debug",/\b(flaky|regression|(?:is|are|got|looks) broken|debug (?:this|it|the|why)|fix (?:the|this|a) bug)\b/i],["workit-continue",/\b(pick up where|where (?:were|did) we|resume (?:the|this|my|our|work|where)|hand ?off)\b/i],["workit-review",/\b(blast radius|code review|review (?:the|this|my|PR|pr|#\d+|branch|diff|changes))\b/i],["workit-ship",/\b(ship (?:it|this|the)|babysit|open (?:a|the) (?:PR|pr|MR|mr)|merge (?:the|this|my) (?:PR|pr|MR|mr|branch)|(?:get|until|make) CI (?:is )?green)\b/i],["workit-bdd",/\b(BDD|TDD|acceptance criteria|Given\/When\/Then)(?![\w/])/],["workit-test-audit",/\b(test audit|audit the tests|tautolog\w*|weak tests)\b/i],["workit-deslop",/\b(deslop|slop|dead code)\b/i],["workit-fanout",/\b(fan(?: |-)?out|parallelize|parallel agents|swarm)\b/i],["workit-verify-app",/\b(verify the app|smoke test|prove it works)\b/i],["workit-retro",/\b(retro|retrospective)\b(?!\.\w)/i],["workit-architecture",/\b(deepen (?:the )?modules|architecture (?:review|pass|audit))\b/i],["workit-shape",/\b(brainstorm\w*|grill me|should we|let'?s plan|plan (?:out|how|the|a|for)|(?:write|draft) (?:a|the) spec)\b/i],["workit-implement",/\b(implement (?:the|this|a|it)|add (?:a|the) feature|build (?:a|an|the) (?:new )?(?:feature|command|verb|page|endpoint|component|cli|tool))\b/i]],F$=(e)=>{let t=e.trim().replace(/^\//,"").toLowerCase(),r=rk[t];if(r)return r;let n=t.replace(/^workit:/,"workit-");return tk.includes(n)?n:null},W$=(e)=>{let t=e.replace(/```[\s\S]*?```/g," ").slice(0,4000);for(let[r,n]of j$){let o=n.exec(t);if(o)return{skill:r,trigger:o[1]??o[0]}}return null},sk=(e,t)=>{let r=Ae(e.cwd);if(r instanceof Error||!r.shared)return null;let n=N$("sha256").update(`${e.host}\x00${t}`).digest("hex").slice(0,32);return ok.join(r.dir,"hooks",`skills-${n}.json`)},ik=(e)=>{try{let t=JSON.parse(Bc.readFileSync(e,"utf8"));return{nudged:t.nudged??[],loaded:t.loaded??[]}}catch{return{nudged:[],loaded:[]}}},ak=(e,t)=>{try{Bc.mkdirSync(ok.dirname(e),{recursive:!0}),Bc.writeFileSync(e,JSON.stringify(t))}catch{}},ck=(e,t)=>{let r=Lr(e),n=new Set;if(!r.ok)return n;for(let o of r.value.rows)if(o.type==="skill.loaded"&&o.actor.session===t&&typeof o.skill==="string")n.add(o.skill);return n},Z$=/(?:^|[\\/])(workit-[a-z-]+)[\\/]SKILL\.md$/,uk=(e)=>Z$.exec(e)?.[1]??null,B$=new Set(["cat","sed","head","tail","less","more","bat","nl","get-content","gc","type"]),lk=(e,t="posix")=>{for(let{words:r}of hr(e,t)){if(!B$.has((r[0]?.split(/[\\/]/).at(-1)??"").toLowerCase()))continue;for(let n of r.slice(1)){let o=uk(n);if(o)return o}}return null};function Ln(e,t,r){try{let n=F$(t),o=e.session.id;if(!n||!o)return;if(!Rs(e.cwd))return;let s=sk(e,o);if(!s)return;let i=ik(s);if(i.loaded.includes(n))return;if(ak(s,{...i,loaded:[...i.loaded,n]}),ck(e.cwd,o).has(n))return;ls(e.cwd,{type:"skill.loaded",actor:{host:e.host,session:o,agentId:e.session.agentId},skill:n,via:r})}catch{}}var dk=(e,t,r,n)=>{let o=sk(e,t);if(!o)return null;let s=ik(o);if(s.nudged.includes(r)||s.loaded.includes(r))return null;if(ck(e.cwd,t).has(r))return null;return ak(o,{...s,nudged:[...s.nudged,r]}),n},pk=(e,t,r)=>L$.has(t)?`Workit: ${r} looks like ${t} work, which the user starts; offer it (/${t.replace(/^workit-/,"wk-")}) rather than loading it.`:`Workit: ${r} looks like ${t} work; if it is, ${nk(D$[e.host],t)} first.`,M$=(e)=>/^\s*\/(?:skill:)?([\w:-]+)/.exec(e)?.[1]??/^\s*<skill name="([\w:-]+)"/.exec(e)?.[1]??/^\s*Load the (workit-[a-z-]+) skill with the skill tool\b/.exec(e)?.[1]??null;function Mc(e,t){try{let r=e.session.id;if(!t||!r||e.session.agentId)return null;let n=M$(t);if(n)return Ln(e,n,"slash"),null;let o=W$(t);if(!o||!Rs(e.cwd))return null;return dk(e,r,o.skill,pk(e,o.skill,`this request ("${o.trigger}")`))}catch{return null}}var H$=/^(?:pr (?:create|merge)|ci wait|git push)\b/,V$=new Set(["sh","bash","zsh","dash","ksh"]),q$=new Set(["npx","bunx","pnpx","-y","--yes","pnpm","dlx","exec","env","sudo","command"]),fk=(e,t,r=0)=>hr(e,t).some(({words:n})=>{let o=n.findIndex((a)=>!/^\w+=/.test(a)&&!q$.has(a));if(o>=0&&/(?:^|[\\/])workit(?:\.exe)?$|^@brainervirus\/workit-cli$/.test(n[o])){let a=n.slice(o+1);if(a.some((c)=>c==="--help"||c==="-h"||c==="--dry-run"))return!1;return H$.test(a.join(" "))}let i=V$.has(n[o]?.split(/[\\/]/).at(-1)??"")&&n[o+1]==="-c"?n[o+2]:void 0;return r<3&&i!==void 0&&fk(i,"posix",r+1)}),U$=(e,t,r="posix")=>Xg(e,t,r)||fk(t,r)&&Rs(e);function hk(e,t){try{let r=e.session.id;if(!r||e.session.agentId)return null;let n=e.event.kind==="shell.pre"?e.event.dialect??"posix":"posix";if(!U$(e.cwd,t,n))return null;return dk(e,r,"workit-ship",pk(e,"workit-ship","this delivery step"))}catch{return null}}var Hc=(e,t)=>{if(!t)return e;if(e.kind==="none")return{kind:"context",text:t};if(e.kind==="context")return{kind:"context",text:`${e.text}
165
+ `)}}catch{}}var z$=(e)=>{let t=f$("git",["log","-1","--format=%H%x1f%ct%x1f%s%x1f%(trailers:key=Workit-Session,valueonly,separator=%x2c)"],{cwd:e,encoding:"utf8",timeout:5000,windowsHide:!0,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_OPTIONAL_LOCKS:"0",LC_ALL:"C"}}),[r,n,o="",s=""]=(t.status===0?t.stdout.trim():"").split("\x1F");return r&&/^[0-9a-f]{40,64}$/.test(r)?{sha:r,committed:Number(n),subject:o,trailer:s.trim()||null}:null},Qg=(e,t,r)=>{let n;try{n=JSON.parse(wt.readFileSync(r,"utf8"))}catch{return}wt.rmSync(r,{force:!0});let o=e.session.id,s=Date.now()/1000;if(typeof n.at!=="number"||s-n.at>A$)return;if(!o||!t.branch)return;let i=z$(t.dir);if(!i||i.sha===n.head||i.committed<n.at)return;if(i.trailer&&i.trailer!==o)return;let a=Lr(t.dir);if(!a.ok)return;if(a.value.rows.some((u)=>u.type==="commit.recorded"&&(u.sha===i.sha||u.head===i.sha)))return;ls(t.dir,{type:"commit.recorded",actor:{host:e.host,session:o,agentId:e.session.agentId},branch:t.branch,head:i.sha,sha:i.sha,session:o,agentId:e.session.agentId,subject:i.subject.slice(0,200),files:[],fileCount:null,via:"raw_shell"})};function Zc(e,t,r){try{if(!e.session.id||!/\bcommit\b/.test(t))return;for(let{action:n,repo:o}of $s(e.cwd,t,Dc(e)))if(n.kind==="commit")Qg(e,o,Fc(o,e.session.id,r))}catch{}}function ek(e){try{if(!e.session.id)return;let t=Lc(e.cwd);if(!t)return;let r=Fc(t,e.session.id,jc);if(wt.existsSync(r))Qg(e,t,r)}catch{}}import{createHash as N$}from"node:crypto";import Bc from"node:fs";import ok from"node:path";var tk=["workit-shape","workit-implement","workit-review","workit-debug","workit-ship","workit-continue","workit-bdd","workit-test-audit","workit-deslop","workit-fanout","workit-verify-app","workit-retro","workit-architecture"],rk={"wk-shape":"workit-shape","wk-implement":"workit-implement","wk-review":"workit-review","wk-debug":"workit-debug","wk-ship":"workit-ship","wk-continue":"workit-continue","wk-bdd":"workit-bdd","wk-test-audit":"workit-test-audit","wk-deslop":"workit-deslop","wk-fanout":"workit-fanout","wk-verify-app":"workit-verify-app","wk-retro":"workit-retro","wk-architecture":"workit-architecture"};var nk=(e,t)=>{switch(e){case"claude-code":return`call the Skill tool with \`workit:${t.replace(/^workit-/,"")}\``;case"opencode":return`call the skill tool with \`${t}\``;default:return`read the \`${t}\` skill's SKILL.md and follow it`}};var L$=new Set(["workit-retro","workit-architecture"]),D$={claude_code:"claude-code",opencode:"opencode",codex_cli:"codex",codex_desktop:"codex",cursor:"cursor",pi:"pi"},j$=[["workit-debug",/\b(flaky|regressed|(?:is|introduced) a regression|regression (?:in|after|since|from)|(?:is|are|got|looks) broken|debug (?:this|it|the|why)|fix (?:the|this|a) bug)\b/i],["workit-continue",/\b(pick up where|where (?:were|did) we|resume (?:the|this|my|our|work|where)|hand ?off)\b/i],["workit-review",/\b(blast radius|code review|review (?:the|this|my|PR|pr|#\d+|branch|diff|changes))\b/i],["workit-ship",/\b(ship (?:it|this|the)|babysit|open (?:a|the) (?:PR|pr|MR|mr)(?=\s*$|\s+(?:for|to|on|with|and|against|into|from|after|once)\b|[.!,;])|merge (?:the|this|my) (?:PR|pr|MR|mr|branch)|(?:get|until|make) CI (?:is )?green)\b/i],["workit-bdd",/\b(BDD|TDD|acceptance criteria|Given\/When\/Then)(?![\w/])/],["workit-test-audit",/\b(test audit|audit the tests|tautolog\w*|weak tests)\b/i],["workit-deslop",/\b(deslop|slop|dead code)\b/i],["workit-fanout",/\b(fan(?: |-)?out|parallelize|parallel agents|agent swarm|swarm of agents)\b/i],["workit-verify-app",/\b(verify the app|smoke test|prove it works)\b/i],["workit-retro",/\b((?:a|the) retro(?![-\w]|\.\w)|retrospective)/i],["workit-architecture",/\b(deepen (?:the )?modules|architecture (?:review|pass|audit))\b/i],["workit-shape",/\b(brainstorm\w*|grill me|should we|let'?s plan|plan (?:out|how|the|a|for)|(?:write|draft) (?:a|the) spec)\b/i],["workit-implement",/\b(implement (?:the|this|a|it)|add (?:a|the) feature|build (?:a|an|the) (?:new )?(?:feature|command|verb|page|endpoint|component|cli|tool))\b/i]],F$=(e)=>{let t=e.trim().replace(/^\//,"").toLowerCase(),r=rk[t];if(r)return r;let n=t.replace(/^workit:/,"workit-");return tk.includes(n)?n:null},W$=(e)=>{let t=e.replace(/```[\s\S]*?```/g," ").slice(0,4000);for(let[r,n]of j$){let o=n.exec(t);if(o)return{skill:r,trigger:o[1]??o[0]}}return null},sk=(e,t)=>{let r=Ae(e.cwd);if(r instanceof Error||!r.shared)return null;let n=N$("sha256").update(`${e.host}\x00${t}`).digest("hex").slice(0,32);return ok.join(r.dir,"hooks",`skills-${n}.json`)},ik=(e)=>{try{let t=JSON.parse(Bc.readFileSync(e,"utf8"));return{nudged:t.nudged??[],loaded:t.loaded??[]}}catch{return{nudged:[],loaded:[]}}},ak=(e,t)=>{try{Bc.mkdirSync(ok.dirname(e),{recursive:!0}),Bc.writeFileSync(e,JSON.stringify(t))}catch{}},ck=(e,t)=>{let r=Lr(e),n=new Set;if(!r.ok)return n;for(let o of r.value.rows)if(o.type==="skill.loaded"&&o.actor.session===t&&typeof o.skill==="string")n.add(o.skill);return n},Z$=/(?:^|[\\/])(workit-[a-z-]+)[\\/]SKILL\.md$/,uk=(e)=>Z$.exec(e)?.[1]??null,B$=new Set(["cat","sed","head","tail","less","more","bat","nl","get-content","gc","type"]),lk=(e,t="posix")=>{for(let{words:r}of hr(e,t)){if(!B$.has((r[0]?.split(/[\\/]/).at(-1)??"").toLowerCase()))continue;if(r.some((n)=>/^(?:-i(?:\.\w+)?|--in-place(?:=.*)?)$/.test(n)))continue;for(let n of r.slice(1)){let o=uk(n);if(o)return o}}return null};function Ln(e,t,r){try{let n=F$(t),o=e.session.id;if(!n||!o)return;if(!Rs(e.cwd))return;let s=sk(e,o);if(!s)return;let i=ik(s);if(i.loaded.includes(n))return;if(ak(s,{...i,loaded:[...i.loaded,n]}),ck(e.cwd,o).has(n))return;ls(e.cwd,{type:"skill.loaded",actor:{host:e.host,session:o,agentId:e.session.agentId},skill:n,via:r})}catch{}}var dk=(e,t,r,n)=>{let o=sk(e,t);if(!o)return null;let s=ik(o);if(s.nudged.includes(r)||s.loaded.includes(r))return null;if(ck(e.cwd,t).has(r))return null;return ak(o,{...s,nudged:[...s.nudged,r]}),n},pk=(e,t,r)=>L$.has(t)?`Workit: ${r} looks like ${t} work, which the user starts; offer it (/${t.replace(/^workit-/,"wk-")}) rather than loading it.`:`Workit: ${r} looks like ${t} work; if it is, ${nk(D$[e.host],t)} first.`,M$=(e)=>/^\s*\/(?:skill:)?([\w:-]+)/.exec(e)?.[1]??/^\s*<skill name="([\w:-]+)"/.exec(e)?.[1]??/^\s*Load the (workit-[a-z-]+) skill with the skill tool\b/.exec(e)?.[1]??null;function Mc(e,t){try{let r=e.session.id;if(!t||!r||e.session.agentId)return null;let n=M$(t);if(n)return Ln(e,n,"slash"),null;let o=W$(t);if(!o||!Rs(e.cwd))return null;return dk(e,r,o.skill,pk(e,o.skill,`this request ("${o.trigger}")`))}catch{return null}}var H$=/^(?:pr (?:create|merge)|ci wait|git push)\b/,V$=new Set(["sh","bash","zsh","dash","ksh"]),q$=new Set(["npx","bunx","pnpx","-y","--yes","pnpm","dlx","exec","env","sudo","command"]),fk=(e,t,r=0)=>hr(e,t).some(({words:n})=>{let o=n.findIndex((a)=>!/^\w+=/.test(a)&&!q$.has(a));if(o>=0&&/(?:^|[\\/])workit(?:\.exe)?$|^@brainervirus\/workit-cli$/.test(n[o])){let a=n.slice(o+1);if(a.some((c)=>c==="--help"||c==="-h"||c==="--dry-run"))return!1;return H$.test(a.join(" "))}let i=V$.has(n[o]?.split(/[\\/]/).at(-1)??"")&&n[o+1]==="-c"?n[o+2]:void 0;return r<3&&i!==void 0&&fk(i,"posix",r+1)}),U$=(e,t,r="posix")=>Xg(e,t,r)||fk(t,r)&&Rs(e);function hk(e,t){try{let r=e.session.id;if(!r||e.session.agentId)return null;let n=e.event.kind==="shell.pre"?e.event.dialect??"posix":"posix";if(!U$(e.cwd,t,n))return null;return dk(e,r,"workit-ship",pk(e,"workit-ship","this delivery step"))}catch{return null}}var Hc=(e,t)=>{if(!t)return e;if(e.kind==="none")return{kind:"context",text:t};if(e.kind==="context")return{kind:"context",text:`${e.text}
166
166
  ${t}`};return e};import{existsSync as K$,realpathSync as J$,statSync as G$}from"node:fs";import X$ from"node:path";var bt=(e)=>e!==null&&typeof e==="object"&&!Array.isArray(e),Be=(e)=>typeof e==="string"&&e.trim()!=="",Ee=(e)=>typeof e==="string"?e:null,Os=(e)=>{if(!Be(e)||!X$.isAbsolute(e)||!K$(e))return null;try{return G$(e).isDirectory()?J$(e):null}catch{return null}},Y$=new Set(["sh","bash","zsh","dash","pwsh","powershell","cmd"]),Q$=/^(?:-\w*c|-command|\/c)$/i,eR=(e)=>/^[\w@%+=:,./-]+$/.test(e)?e:JSON.stringify(e),Vc=(e)=>{if(Be(e))return e;if(!Array.isArray(e)||e.length===0)return null;let t=e;if(!t.every((o)=>typeof o==="string"))return null;let r=t[0].split(/[\\/]/).at(-1)?.replace(/\.exe$/i,"").toLowerCase()??"";if(Y$.has(r))for(let o=1;o<t.length-1;o++){if(Q$.test(t[o]))return Be(t[o+1])?t[o+1]:null;if(!/^[-/]/.test(t[o]))break}let n=t.map(eR).join(" ");return Be(n)?n:null},tR=new Set(["write","edit","multiedit","notebookedit","applypatch","patch","delete","remove","rename","mkdir","mv","cp","touch","strreplace","searchreplace","editfile","writefile"]),Dn=(e)=>typeof e==="string"&&tR.has(e.toLowerCase().replace(/[_-]/g,"")),rR=["file_path","filePath","notebook_path","path","target_file","file"],nR=/^[ \t]*\*\*\* (?:(?:Add|Update|Delete) File|Move to): (.+)$/gm,mk=(e)=>{if(!bt(e))return[];let t=rR.map((r)=>e[r]).filter(Be);for(let r of Object.values(e))if(typeof r==="string")for(let n of r.matchAll(nR))t.push(n[1].trim());return[...new Set(t)]},Cs=(e)=>{let t=mk(e);return t.length>0?t:null};var _t=(e)=>e==="native"||e==="partial",Xe={kind:"none"},gk=(e)=>e.context.turnResend==="on-change"&&_t(e.context.perTurn),kk=new Set,yk={implementer:"implementer",verifier:"judge",reviewer:"judge"},oR=(e,t)=>{let r=e.subagents.agentPrefix,n=t.startsWith(r)?t.slice(r.length):"";return Object.hasOwn(yk,n)?yk[n]:null},sR=(e,t)=>[e,t].filter((r)=>Boolean(r)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g,"-").slice(0,128),iR=(e,t,r)=>{let n=oR(t,r.agentType),o=`${t.label} subagent ${r.agentId} (${r.agentType})`;if(n==="implementer"){let a=t.subagents.worktreeIsolation==="native"?"working in its own git worktree: it may edit and commit there":"as an implementer: it edits and commits only in its own git worktree (the lead makes one with `workit fanout worktree create <slice>`), never in the lead's checkout";return`Workit observed ${o} ${a}, within its brief's scope. Before the first commit, switch to a policy-compliant branch with \`workit git branch <branch> --base <base>\` (e.g. feature/<slug>); branch policy hooks still deny protected or non-compliant branches. Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`}let s=`Workit observed ${o} as read-only/agent-guided.`;if(n!=="judge"||!r.agentId)return s;let i=sR(e,r.agentId);return`${s} Its own Workit session is ${i}: record verdicts with \`workit ledger verdict <result> --session ${i} ...\` so the ledger tells it apart from the author.`};function vk(e,t){let{descriptor:r}=t,n=e.event;switch(n.kind){case"session.start":{if(!_t(r.context.sessionStart))return Xe;let o=e.session.id?`${e.host}\x00${e.session.id}`:null,s=n.source==="startup"&&(o===null||!kk.has(o));if(s&&o!==null)kk.add(o);let i=_t(r.events["write.pre"].support)?null:`Workit cannot gate file writes on ${r.label} (no pre-write hook): before-write requirements (an open product choice, a missing plan) are advisory here, so settle them before editing.`,a=[t.addendum,i].filter(Boolean).join(`
167
167
  `)||null,c=Cc(e,r,{offer:s,addendum:a});if(gk(r))Dg(e,r);return{kind:"context",text:c}}case"context.turn":{if(!_t(r.context.perTurn))return Xe;let o=_s(e,r),s=gk(r)?Lg(e,o):o;return Hc(s?{kind:"context",text:s}:Xe,Mc(e,n.prompt))}case"shell.pre":{let o=lk(n.command,n.dialect);if(o)Ln(e,o,"read");let s=_t(r.shellPolicy.deny),i=s?Ec(e.cwd,n.command):Xe;if(i.kind!=="none")return i;let a=_t(r.events["shell.post"].support);if(!a)ek(e);let c=s?Is(e,n.command):Xe;if(c.kind==="deny")return c;let u=_t(r.events["write.pre"].support)?zc(n.command):{writes:!1,targets:null},l=u.writes?xs(e.cwd,u.targets):Xe;if(l.kind==="deny")return l;return Wc(e,n.command,a?Ts(n.toolUseId,n.command):jc),Hc(c,hk(e,n.command))}case"shell.post":if(_t(r.events["shell.post"].support))Zc(e,n.command,Ts(n.toolUseId,n.command));return Xe;case"write.pre":return _t(r.events["write.pre"].support)?xs(e.cwd,n.paths):Xe;case"subagent.start":return{kind:"context",text:iR(e.session.id??null,r,n)};case"compact.pre":return{kind:"notice",userMessage:"Workit context may be stale after compaction; re-run inspection or resume before acting."};case"tool.pre":if(n.skill)Ln(e,n.skill,"tool");return Xe;case"subagent.stop":case"prompt.submit":case"stop":return Xe}}var qc=(e,t,r)=>{if(t==="shell.pre"||t==="tool.pre"||t==="write.pre")return e.shellPolicy.failClosed?{kind:"deny",reason:r,unblock:null}:Xe;if(t==="session.start"||t==="subagent.start")return{kind:"context",text:`[workit diagnostic: ${r}]`};return Xe},jn=(e,t,r=process.env)=>{let n=e.parse(t,r);if(!n.ok)return{...e.render(qc(e.descriptor,n.event,n.error),n.native),error:n.error};let o={...e.descriptor,host:n.input.host};try{let s=vk(n.input,{descriptor:o,addendum:e.addendum?.(n.input)??null});return{...e.render(s,n.native),error:null}}catch(s){let i=`hook failure: ${String(s)}`;return{...e.render(qc(o,n.input.event.kind,i),n.native),error:i}}};var Sk={host:"claude_code",label:"Claude Code",verifiedAgainst:"claude 2.1.288 (hook zod schemas in the binary)",docs:["https://code.claude.com/docs/en/hooks"],transport:"hook-process",events:{"session.start":{support:"native",native:"SessionStart"},"context.turn":{support:"native",native:"UserPromptSubmit"},"shell.pre":{support:"native",native:"PreToolUse"},"tool.pre":{support:"native",native:"PreToolUse"},"write.pre":{support:"native",native:"PreToolUse"},"shell.post":{support:"native",native:"PostToolUse"},"subagent.start":{support:"native",native:"SubagentStart"},"prompt.submit":{support:"native",native:"UserPromptSubmit"},"subagent.stop":{support:"none",native:null},"compact.pre":{support:"none",native:null},stop:{support:"none",native:null}},shellPolicy:{deny:"native",channel:"permissionDecision",failClosed:!1},context:{sessionStart:"native",perTurn:"native",afterCompact:"native",task:"session-bound",turnResend:"every-turn"},subagents:{identity:"native",parentBinding:"partial",blockStart:"none",worktreeIsolation:"native",maxConcurrency:"undocumented",agentPrefix:"workit:"},provenance:{sessionId:"native",agentIdOnTool:"native",postToolObserve:"native"},interaction:{questions:"undocumented",writeBoundary:"partial"},stopControl:"native",shellAvailable:"native",perEventCost:"low",capabilities:[{name:"known_product_writes",surface:"PreToolUse",refs:["PreToolUse"],requires:[],assurance:"unavailable",reason:"file writes are host-policy; Claude Code permissions govern them"},{name:"native_subagents",surface:"SubagentStart",refs:["SubagentStart"],requires:["event:subagent.start"],observed:["subagent.start"],assurance:"agent_guided",reason:"Claude Code reports stable agent identities, but SubagentStart cannot block or bind",unavailableReason:"Claude Code SubagentStart is unavailable"},{name:"fresh-context-review",surface:"SubagentStart",refs:["SubagentStart"],requires:["event:subagent.start"],observed:["subagent.start"],assurance:"agent_guided",reason:"independent review runs as a fresh subagent; evidence evaluation enforces reviewer exclusivity",unavailableReason:"Claude Code SubagentStart is unavailable for independent review"},{name:"arbitrary_shell_write",surface:"unobservable_shell",refs:["PreToolUse"],requires:[],assurance:"unavailable",reason:"Only literal Bash commands are interceptable; arbitrary shell writes are not provable"},{name:"compact_context",surface:"SessionStart",refs:["SessionStart"],requires:["context.afterCompact"],observed:["session.start"],assurance:"agent_guided",reason:"SessionStart source=compact is the single restore path"}]},wk={SessionStart:"session.start",UserPromptSubmit:"context.turn",PreToolUse:"shell.pre",PostToolUse:"shell.post",SubagentStart:"subagent.start",SubagentStop:"subagent.stop",PreCompact:"compact.pre",Stop:"stop"},aR=new Set(["startup","resume","clear","compact","fork"]),bk=new Set(["Bash","PowerShell"]),_k=(e)=>e.tool_name==="PowerShell"?"powershell":"posix",xk=(e)=>bt(e.tool_input)?Vc(e.tool_input.command):null,cR=(e,t)=>{let r=Ee(t.tool_use_id);switch(e){case"SessionStart":return aR.has(t.source)?{ok:!0,event:{kind:"session.start",source:t.source}}:{ok:!1,error:"SessionStart source is required"};case"UserPromptSubmit":return{ok:!0,event:{kind:"context.turn",prompt:Ee(t.prompt)}};case"PreToolUse":{if(!Be(t.tool_name))return{ok:!1,error:"tool_name is required"};if(Dn(t.tool_name))return{ok:!0,event:{kind:"write.pre",tool:t.tool_name,paths:Cs(t.tool_input),toolUseId:r}};if(t.tool_name==="Skill")return{ok:!0,event:{kind:"tool.pre",tool:t.tool_name,toolUseId:r,skill:bt(t.tool_input)?Ee(t.tool_input.skill):null}};if(!bk.has(t.tool_name))return{ok:!0,event:{kind:"tool.pre",tool:t.tool_name,toolUseId:r}};let n=xk(t);return n?{ok:!0,event:{kind:"shell.pre",command:n,toolUseId:r,dialect:_k(t)}}:{ok:!1,error:`tool_input.command is required for ${t.tool_name}`}}case"PostToolUse":{let n=xk(t);if(!bk.has(String(t.tool_name))||!n)return{ok:!1,error:"only shell PostToolUse is mapped"};let o=bt(t.tool_response)?t.tool_response:{};return{ok:!0,event:{kind:"shell.post",command:n,stdout:Ee(o.stdout)??"",exitCode:typeof o.exit_code==="number"?o.exit_code:null,toolUseId:r,dialect:_k(t)}}}case"SubagentStart":return Be(t.agent_id)&&Be(t.agent_type)?{ok:!0,event:{kind:"subagent.start",agentId:t.agent_id,agentType:t.agent_type,task:null}}:{ok:!1,error:"agent_id and agent_type are required"};case"SubagentStop":return{ok:!0,event:{kind:"subagent.stop",agentId:Ee(t.agent_id),agentType:Ee(t.agent_type),lastMessage:Ee(t.last_assistant_message),stopHookActive:t.stop_hook_active===!0}};case"PreCompact":return{ok:!0,event:{kind:"compact.pre",trigger:t.trigger==="manual"?"manual":"auto"}};case"Stop":return{ok:!0,event:{kind:"stop",lastMessage:Ee(t.last_assistant_message),stopHookActive:t.stop_hook_active===!0}}}},uR=new Set(["SessionStart","UserPromptSubmit","SubagentStart","PreToolUse","PostToolUse"]),lR=(e,t)=>{if(e.kind==="deny"&&t==="PreToolUse")return{json:{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:e.reason}},exitCode:0};if(e.kind==="context"&&t!==null&&uR.has(t))return{json:{hookSpecificOutput:{hookEventName:t,additionalContext:e.text}},exitCode:0};if(e.kind==="notice")return{json:{systemMessage:e.userMessage},exitCode:0};if(e.kind==="continue"&&(t==="Stop"||t==="SubagentStop"))return{json:{decision:"block",reason:e.reason},exitCode:0};return{json:{},exitCode:0}},Ps={descriptor:Sk,parse(e){let t=bt(e)&&Object.hasOwn(wk,String(e.hook_event_name))?e.hook_event_name:null,r=(s)=>({ok:!1,error:s,native:t,event:t?wk[t]:null});if(!bt(e)||!t)return r("hook_event_name is required");if(!Be(e.session_id))return r("session_id is required");let n=Os(e.cwd);if(!n)return r("cwd must be an existing absolute directory");let o=cR(t,e);if(!o.ok)return r(o.error);return{ok:!0,native:t,input:{host:"claude_code",cwd:n,session:{id:e.session_id,agentId:Ee(e.agent_id),agentType:Ee(e.agent_type),parentId:Be(e.agent_id)?e.session_id:null},permissionMode:Ee(e.permission_mode),transcriptPath:Ee(e.transcript_path),event:o.event}}},render:lR};var vR="Claude Code: the workit-<name> skills are this plugin's /workit:<name> skills (workit-shape is /workit:shape). Run workit verbs with the `workit` CLI on the Bash tool (`workit --help`); run `workit ci wait` in the background. Agents: `implementer` builds one brief in an isolated worktree and never records a verdict; `verifier` and `reviewer` are read-only non-authors that record `workit ledger verdict` with the `--session` the SubagentStart hook names for them (subagents share this session's WORKIT_SESSION_ID).",Ik={...Ps,addendum:()=>vR},Uc=(e)=>e!==null&&typeof e==="object"&&!Array.isArray(e),Fn=(e)=>typeof e==="string"&&e.trim()!==""?e:null,wR=(e)=>$k("sha256").update(e).digest("hex").slice(0,32),bR=(e,t)=>{let r=Fn(e.CLAUDE_PLUGIN_DATA);return r?Es.join(r,"ctx",`${wR(t)}.json`):null},_R=(e)=>`'${e.replaceAll("'","'\\''")}'`,xR=(e,t)=>{let r=Fn(e.CLAUDE_ENV_FILE);if(!r)return;try{fR(r,`export WORKIT_HOST=claude_code
168
168
  export WORKIT_SESSION_ID=${_R(t)}
package/dist/workit.js CHANGED
@@ -65,7 +65,7 @@ var package_default;
65
65
  var init_package = __esm(() => {
66
66
  package_default = {
67
67
  name: "@brainervirus/workit-cli",
68
- version: "8.5.0",
68
+ version: "8.5.2",
69
69
  private: false,
70
70
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
71
71
  keywords: [
@@ -103,9 +103,9 @@ var init_package = __esm(() => {
103
103
  },
104
104
  dependencies: {
105
105
  "@babel/parser": "7.29.9",
106
- "@brainervirus/workit-core": "^8.5.0",
107
- "@brainervirus/workit-cursor": "^8.5.0",
108
- "@brainervirus/workit-opencode": "^8.5.0",
106
+ "@brainervirus/workit-core": "^8.5.2",
107
+ "@brainervirus/workit-cursor": "^8.5.2",
108
+ "@brainervirus/workit-opencode": "^8.5.2",
109
109
  "@inkjs/ui": "2.0.0",
110
110
  ink: "7.1.1",
111
111
  react: "19.2.8"
@@ -76197,20 +76197,30 @@ async function status(argv, io) {
76197
76197
  return forgeFail(io, report);
76198
76198
  const doc = report.data.doc;
76199
76199
  const hint = nextHint(doc.next, doc.number);
76200
- return emit(io, ok({ ...doc, nextHint: hint, verdict: verdictBlock(io.cwd, doc.head.branch) }), (data) => {
76200
+ return emit(io, ok({ ...doc, nextHint: hint, verdict: verdictBlock(io.cwd, doc.head.branch, doc) }), (data) => {
76201
76201
  const lines = renderStatus(data);
76202
- lines.splice(lines.length - 1, 0, data.verdict ? `verdict: ${data.verdict.accepted ? `accepted (${data.verdict.basis})` : data.verdict.review === "self-reviewed" ? "self-reviewed (author's own verdict; not independent)" : `not accepted (${data.verdict.reasons.join(", ") || data.verdict.basis})`}` : "verdict: unknown (ledger unreadable)");
76202
+ lines.splice(lines.length - 1, 0, data.verdict?.merge ? `verdict: ${mergedVerdictLine(data.verdict.merge)}` : data.verdict ? `verdict: ${data.verdict.accepted ? `accepted (${data.verdict.basis})` : data.verdict.review === "self-reviewed" ? "self-reviewed (author's own verdict; not independent)" : `not accepted (${data.verdict.reasons.join(", ") || data.verdict.basis})`}` : "verdict: unknown (ledger unreadable)");
76203
76203
  if (data.nextHint)
76204
76204
  lines.splice(lines.length - 1, 0, `do: ${data.nextHint}`);
76205
76205
  return lines;
76206
76206
  });
76207
76207
  }
76208
- function verdictBlock(cwd, branch) {
76208
+ function verdictBlock(cwd, branch, doc) {
76209
76209
  const ledger = readLedger(cwd);
76210
76210
  if (!ledger.ok)
76211
76211
  return null;
76212
76212
  const check = checkVerdicts(cwd, branch, ledger.value.rows);
76213
+ let landed = null;
76214
+ if (doc.state === "merged") {
76215
+ const row = ledger.value.rows.findLast((candidate) => candidate.type === "pr.merged" && candidate.observer === "workit_cli" && candidate.pr === doc.number && candidate.base === doc.base);
76216
+ landed = row ? {
76217
+ head: typeof row.head === "string" ? row.head : null,
76218
+ verdictId: typeof row.verdictId === "string" ? row.verdictId : null,
76219
+ unverified: row.unverified !== undefined && row.unverified !== null
76220
+ } : "untracked";
76221
+ }
76213
76222
  return {
76223
+ merge: landed,
76214
76224
  accepted: check.accepted.accepted,
76215
76225
  review: check.review,
76216
76226
  basis: check.current.basis,
@@ -76496,7 +76506,7 @@ async function run10(argv, io) {
76496
76506
  return reply(rest, io);
76497
76507
  return usage3(io, sub && !sub.startsWith("-") ? `unknown pr subcommand "${sub}"` : "missing pr subcommand", USAGE4);
76498
76508
  }
76499
- var STATUS_USAGE = "workit pr status [--pr <n> | --branch <b>] [--log-lines 60] [--json]", CREATE_USAGE = "workit pr create [--base <b> | --track <t>] (--title <t> [--body <text> | --body-file <f|->] | --fill) [--label <l>]… [--reviewer <login>]… [--draft] [--json]", MERGE_USAGE = "workit pr merge [--pr <n>] [--method squash|merge|rebase] [--delete-branch] [--unverified --reason <why>] [--json]", READY_USAGE = "workit pr ready [--pr <n>] [--undo] [--json]", EDIT_USAGE = "workit pr edit [--pr <n>] [--title <t>] [--body-file <f|->] [--add-label <l>]… [--remove-label <l>]… [--add-reviewer <login>]… [--base <b>] [--json]", THREADS_USAGE = "workit pr threads [--pr <n>] [--json]", REPLY_USAGE = "workit pr reply [--pr <n>] --thread <id> [--body-file <f|->] [--resolve] [--json]", USAGE4 = "workit pr status|create|merge|ready|edit|threads|reply ... (workit help pr)", prLabel = (kind, number) => `${kind === "github" ? "PR #" : "MR !"}${number}`, METHODS2;
76509
+ var STATUS_USAGE = "workit pr status [--pr <n> | --branch <b>] [--log-lines 60] [--json]", CREATE_USAGE = "workit pr create [--base <b> | --track <t>] (--title <t> [--body <text> | --body-file <f|->] | --fill) [--label <l>]… [--reviewer <login>]… [--draft] [--json]", MERGE_USAGE = "workit pr merge [--pr <n>] [--method squash|merge|rebase] [--delete-branch] [--unverified --reason <why>] [--json]", READY_USAGE = "workit pr ready [--pr <n>] [--undo] [--json]", EDIT_USAGE = "workit pr edit [--pr <n>] [--title <t>] [--body-file <f|->] [--add-label <l>]… [--remove-label <l>]… [--add-reviewer <login>]… [--base <b>] [--json]", THREADS_USAGE = "workit pr threads [--pr <n>] [--json]", REPLY_USAGE = "workit pr reply [--pr <n>] --thread <id> [--body-file <f|->] [--resolve] [--json]", USAGE4 = "workit pr status|create|merge|ready|edit|threads|reply ... (workit help pr)", prLabel = (kind, number) => `${kind === "github" ? "PR #" : "MR !"}${number}`, mergedVerdictLine = (landed) => landed === "untracked" ? "merged outside workit (no merge record)" : landed.unverified ? `merged unverified at ${(landed.head ?? "?").slice(0, 12)} (recorded bypass)` : `merged with accepted verdict ${landed.verdictId ?? "?"} at ${(landed.head ?? "?").slice(0, 12)}`, METHODS2;
76500
76510
  var init_pr = __esm(() => {
76501
76511
  init_pr_body();
76502
76512
  init_pr_edit();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-claude-code",
3
- "version": "8.5.0",
3
+ "version": "8.5.2",
4
4
  "private": false,
5
5
  "description": "Workit Claude Code plugin — session and per-turn task context, branch policy on git shell commands, workit method skills, and verifier/reviewer/implementer agents",
6
6
  "keywords": [
@@ -39,8 +39,8 @@
39
39
  "build": "bun scripts/build.ts"
40
40
  },
41
41
  "devDependencies": {
42
- "@brainervirus/workit-cli": "^8.5.0",
43
- "@brainervirus/workit-core": "^8.5.0"
42
+ "@brainervirus/workit-cli": "^8.5.2",
43
+ "@brainervirus/workit-core": "^8.5.2"
44
44
  },
45
45
  "engines": {
46
46
  "node": ">=24"