@tech-leads-club/harness-toolkit 0.10.3 → 0.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/obs-cli.mjs CHANGED
@@ -117,9 +117,9 @@ ${" ".repeat(4)}${Z.dim(F.bar)} ${Y.detail}`:K});return[Z.heading(`LAST ${$.leng
117
117
  `))return null;let Z=$.indexOf(`
118
118
  `),J=$.slice(Z+1),Q=/^---\s*$/m.exec(J);if(!Q)return null;return{block:J.slice(0,Q.index),bodyAt:Z+1+Q.index+Q[0].length}}function m2($){let Z=$.trim();if(Z.length>=2){let J=Z[0],Q=Z[Z.length-1];if(J==='"'&&Q==='"'||J==="'"&&Q==="'")return Z.slice(1,-1)}return Z}function g2($){return $.replace(/\\(["'\\])/g,"$1")}function V4($){let Z=$.trim();if(Z.startsWith("[")&&Z.endsWith("]")){let J=Z.slice(1,-1).trim();if(J==="")return[];return J.split(",").map((Q)=>g2(m2(Q)))}return g2(m2(Z))}function u2($){let Z=G4($);if(Z===null)return{doc:null,error:"missing --- frontmatter block"};let J={},Q=null;for(let q of Z.block.split(`
119
119
  `)){let X=q.trim();if(X===""||X.startsWith("#"))continue;if(X.startsWith("- ")){if(Q===null)return{doc:null,error:`list item with no key above it: "${X}"`};let G=J[Q],V=g2(m2(X.slice(2)));J[Q]=Array.isArray(G)?[...G,V]:[V];continue}let z=X.indexOf(":");if(z===-1)return{doc:null,error:`unparseable frontmatter line: "${X}"`};let Y=X.slice(0,z).trim();if(Y==="")return{doc:null,error:`frontmatter line has an empty key: "${X}"`};let W=X.slice(z+1);if(W.trim()===""){J[Y]=[],Q=Y;continue}J[Y]=V4(W),Q=null}return{doc:{fields:J,body:$.slice(Z.bodyAt).trim()},error:null}}function q8($,Z){let{doc:J}=u2($),Q=J?.fields[Z];if(typeof Q!=="string"||Q.trim()==="")return;return Q.trim()}function X1($){if($===void 0)return[];return(Array.isArray($)?$:[$]).filter((Z)=>Z!=="")}function W1($){return X8($,"docs","decisions")}function h2($,Z){let J=X8(W1($),Z);if(!Y1(J))return null;let Q;try{Q=H4(J,"utf8")}catch{return null}let q=q8(Q,"title");if(q===void 0)return null;let X=(Z.split(/[\\/]/).pop()??Z).replace(/\.md$/,"").toUpperCase(),z=q8(Q,"migration"),Y=q8(Q,"timestamp");return{id:X,title:q,path:`/decisions/${Z.split(/[\\/]/).join("/")}`,...z===void 0?{}:{migration:z},...Y===void 0?{}:{timestamp:Y}}}function G1($,Z){return Z.filter((J)=>/(?:^|[\\/])ad-\d+\.md$/.test(J)).map((J)=>h2($,J)).filter((J)=>J!==null).sort((J,Q)=>J.id.localeCompare(Q.id))}var U4="archived";function V1($){let Z=W1($),J=[];for(let Q of["",U4]){let q=Q===""?Z:X8(Z,Q);if(!Y1(q))continue;try{for(let X of B4(q))if(/^ad-\d+\.md$/.test(X))J.push(Q===""?X:X8(Q,X))}catch{}}return J}function p2($){return $.filter((Z)=>Z.migration!==void 0)}function z1($){return $.id}function B1($){if($.length===0)return"";let Z=p2($),J=[`Harness updated. ${$.length} decision(s) landed; doctor runs below and reports what applies here.`];if(Z.length>0){J.push("",`Needs a change doctor cannot detect for you (${Z.length}):`);for(let q of Z)J.push(` ${q.migration} (${z1(q)})`)}let Q=$.filter((q)=>q.migration===void 0);if(Q.length>0)J.push("",`Also landed: ${Q.map(z1).join(", ")} — docs/decisions/index.md`);else J.push("","Full reasoning: docs/decisions/index.md");return J.join(`
120
- `)}import{existsSync as K4,readFileSync as M4}from"node:fs";import{join as F4}from"node:path";function H1($){return F4(H($),"release-seen.json")}function U1($){let Z=H1($);if(!K4(Z))return null;try{let J=JSON.parse(M4(Z,"utf8"));return typeof J?.revision==="string"&&J.revision!==""?J:null}catch{return null}}async function K1($,Z){await J$(H1($),{revision:Z,updatedAt:new Date().toISOString()})}var C4={"pr-open":[{prefix:["gh","pr","create"],excludeIfAny:["--draft","-d"]},{prefix:["gh","pr","ready"]}],commit:[{prefix:["git","commit"]}],push:[{prefix:["git","push"]}]};function M1($){return S($).map((Z)=>Z.words.map((J)=>J.text)).filter((Z)=>Z.length>0)}function O4($,Z){return Z.every((J,Q)=>$[Q]===J)}function I4($,Z){if(!O4($,Z.prefix))return!1;return!Z.excludeIfAny?.some((J)=>$.includes(J))}function c2($,Z){let J=Z.trim().split(/\s+/);if(J.length===0)return!1;return $.some((Q,q)=>J.every((X,z)=>$[q+z]===X))}function d2($,Z){switch($.kind){case"stop":return Z.event==="stop";case"tool":return Z.toolName===$.name;case"pr-open":case"commit":case"push":{if(Z.command===void 0)return!1;let J=C4[$.kind];return M1(Z.command).some((Q)=>J.some((q)=>I4(Q,q)))}default:{if(Z.command===void 0)return!1;return M1(Z.command).some((J)=>c2(J,$.pattern))}}}function z8($,Z){return $.filter((J)=>J.enabled&&d2(J.on,Z))}function _4($,Z){if($===Z)return!0;if($.startsWith("*"))return Z.endsWith($.slice(1));if($.endsWith("/"))return Z.startsWith($);return!1}function F1($,Z){if($.kind!==Z.kind)return!1;switch($.kind){case"command":return c2(Z.value.split(/\s+/),$.value);case"file":return _4($.value,Z.value);default:return Z.value===$.value}}function N4($,Z,J){if($.since==="session")return Z.sessionKey===J.sessionKey;return J.sha!==null&&Z.sha===J.sha}function P4($,Z,J){return Z.some((Q)=>F1($,Q)&&N4($,Q,J))}function j4($,Z){if($.since==="session")return"ran, but in a different session";return Z.sha===null?"ran, but this project is not a git checkout, so since HEAD can never be satisfied":"ran, but at a different commit"}function C1($,Z,J){return $.require.filter((Q)=>!P4(Q,Z,J)).map((Q)=>({proof:Q,reason:Z.some((q)=>F1(Q,q))?j4(Q,J):null}))}function O1($){let{proof:Z,reason:J}=$,Q=`${Z.kind}(${Z.value}) since ${Z.since==="head"?"HEAD":"session"}`;return J===null?Q:`${Q} (${J})`}function Y8($,Z){return $.some((J)=>J.require.some((Q)=>Q.kind===Z))}function I1($,Z){let J=new Set(Z.map((Q)=>Q.kind));return $.map((Q)=>({rule:Q.name,kinds:[...new Set(Q.require.map((q)=>q.kind))].filter((q)=>!J.has(q))})).filter((Q)=>Q.kinds.length>0)}function l2($,Z){return $==="ask"&&Z!=="paired"?"deny":$}function L4($,Z){let J=`rule ${$.name} (${$.tier}): missing ${Z.join(", ")}`;return $.body.trim()===""?J:`${J}
120
+ `)}import{existsSync as K4,readFileSync as M4}from"node:fs";import{join as F4}from"node:path";function H1($){return F4(H($),"release-seen.json")}function U1($){let Z=H1($);if(!K4(Z))return null;try{let J=JSON.parse(M4(Z,"utf8"));return typeof J?.revision==="string"&&J.revision!==""?J:null}catch{return null}}async function K1($,Z){await J$(H1($),{revision:Z,updatedAt:new Date().toISOString()})}var C4={"pr-open":[{prefix:["gh","pr","create"],excludeIfAny:["--draft","-d"]},{prefix:["gh","pr","ready"]}],commit:[{prefix:["git","commit"]}],push:[{prefix:["git","push"]}]};function M1($){return S($).map((Z)=>Z.words.map((J)=>J.text)).filter((Z)=>Z.length>0)}function O4($,Z){return Z.every((J,Q)=>$[Q]===J)}function I4($,Z){if(!O4($,Z.prefix))return!1;return!Z.excludeIfAny?.some((J)=>$.includes(J))}function c2($,Z){let J=Z.trim().split(/\s+/);if(J.length===0)return!1;return $.some((Q,q)=>J.every((X,z)=>$[q+z]===X))}function d2($,Z){switch($.kind){case"stop":return Z.event==="stop";case"tool":return Z.toolName===$.name;case"pr-open":case"commit":case"push":{if(Z.command===void 0)return!1;let J=C4[$.kind];return M1(Z.command).some((Q)=>J.some((q)=>I4(Q,q)))}default:{if(Z.command===void 0)return!1;return M1(Z.command).some((J)=>c2(J,$.pattern))}}}function z8($,Z){return $.filter((J)=>J.enabled&&d2(J.on,Z))}function _4($,Z){if($===Z)return!0;if($.startsWith("*"))return Z.endsWith($.slice(1));if($.endsWith("/"))return Z.startsWith($);return!1}function F1($,Z){if($.kind!==Z.kind)return!1;switch($.kind){case"command":return c2(Z.value.split(/\s+/),$.value);case"file":return _4($.value,Z.value);default:return Z.value===$.value}}function N4($,Z,J){if($.since==="session")return Z.sessionKey===J.sessionKey;return J.sha!==null&&Z.sha===J.sha}function P4($,Z,J){return Z.some((Q)=>F1($,Q)&&N4($,Q,J))}function j4($,Z){if($.since==="session")return"ran, but in a different session";return Z.sha===null?"ran, but this project is not a git checkout, so since HEAD can never be satisfied":"ran, but at a different commit"}function C1($,Z,J){return $.require.filter((Q)=>!P4(Q,Z,J)).map((Q)=>({proof:Q,reason:Z.some((q)=>F1(Q,q))?j4(Q,J):null}))}function O1($){let{proof:Z,reason:J}=$,Q=`${Z.kind}(${Z.value}) since ${Z.since==="head"?"HEAD":"session"}`;return J===null?Q:`${Q} (${J})`}function Y8($,Z){return $.some((J)=>J.require.some((Q)=>Q.kind===Z))}function I1($,Z){let J=new Set(Z.map((Q)=>Q.kind));return $.map((Q)=>({rule:Q.name,kinds:[...new Set(Q.require.map((q)=>q.kind))].filter((q)=>!J.has(q))})).filter((Q)=>Q.kinds.length>0)}function l2($,Z){return $==="ask"&&Z!=="paired"?"deny":$}function L4($,Z,J,Q){let q=`rule ${$.name} (${$.tier}): missing ${Z.join(", ")} — checked ${J} at ${Q??"no HEAD"}`;return $.body.trim()===""?q:`${q}
121
121
 
122
- ${$.body.trim()}`}function W8($,Z,J){let Q=[];for(let q of $){let X=C1(q,Z,J);if(X.length===0)continue;let z=X.map(O1);Q.push({rule:q,verdict:l2(q.otherwise,J.mode),missing:z,message:L4(q,z)})}return Q}var _1={warn:0,"follow-up":1,ask:2,deny:3};function G8($){return $.reduce((Z,J)=>Z===null||_1[J.verdict]>_1[Z.verdict]?J:Z,null)}function V8($){let Z=`rule:${$.rule.name}`;if($.verdict==="deny")return{kind:"deny",reason:$.message,rule:Z};if($.verdict==="ask")return{kind:"ask",reason:$.message,userNote:$.message,rule:Z};return{kind:"abstain"}}function B8($){switch($.verdict){case"deny":case"ask":return{kind:"continue",text:`BLOCKED: ${$.message}`};case"follow-up":return{kind:"continue",text:`NEED: ${$.message}`};case"warn":return{kind:"context",text:`ADVISORY: ${$.message}`}}}function i2($){if($.event==="subagent.stop"){let Z=$.spawnSubagentType??$.spawnAgentLabel;return Z===void 0?null:{kind:"subagent",value:Z}}if($.event==="tool.after"||$.event==="shell.after")return $.command===void 0?null:{kind:"command",value:$.command};if($.event==="edit.after")return $.filePath===void 0?null:{kind:"file",value:$.filePath};return null}function H8($,Z){let J=i2($);return J===null?null:{...J,sha:Z.sha,sessionKey:Z.sessionKey,at:Z.at}}function U8($,Z){return{kind:"gate",value:$,sha:Z.sha,sessionKey:Z.sessionKey,at:Z.at}}function n2($){if($.event!=="tool.after"||!T4.has($.toolName??""))return null;let{spawnAgentLabel:Z,spawnSubagentType:J}=$;return Z===void 0||J===void 0||Z===J?null:{label:Z,type:J}}var T4=new Set(["Task","Agent"]);function N1($,Z){if($.event!=="subagent.stop"||$.spawnSubagentType!==void 0)return $;let J=$.spawnAgentLabel;if(J===void 0)return $;let Q=Z().filter((X)=>X.label===J),q=Q[Q.length-1];return q===void 0?$:{...$,spawnSubagentType:q.type}}var P1=new Set(["deny","ask","follow-up","warn"]),j1=new Set(["subagent","command","gate","file"]);var A4=new Set(["pr-open","commit","push","stop"]);function D4($){let Z=$.trim();if(A4.has(Z))return{kind:Z};let J=/^(tool|command)\(([^)]*)\)$/.exec(Z),Q=J?.[1],q=J?.[2]?.trim();if(Q===void 0||q===void 0||q==="")return`unknown trigger "${Z}" — use one of pr-open, commit, push, stop, tool(<name>), command(<pattern>)`;return Q==="tool"?{kind:"tool",name:q}:{kind:"command",pattern:q}}function R4($){let[Z,...J]=$.trim().split(/\s+since\s+/i),Q=/^([a-z]+)\(([^)]*)\)$/.exec((Z??"").trim()),q=Q?.[1],X=Q?.[2]?.trim();if(q===void 0||!j1.has(q)||X===void 0||X==="")return`unknown proof "${$.trim()}" — use subagent(<type>), command(<pattern>), gate(<name>) or file(<glob>)`;let z=(J[0]??"head").trim().toLowerCase();if(z!=="head"&&z!=="session")return`unknown window "since ${z}" in "${$.trim()}" — use since HEAD or since session`;return{kind:q,value:X,since:z}}function E4($){let Z=(V)=>({error:{name:$.name,tier:$.tier,error:V}}),{doc:J,error:Q}=u2($.text);if(J===null)return Z(Q??"unreadable");let q=J.fields.enabled,X=q===void 0?!0:String(q).trim()!=="false",z=J.fields.on;if(typeof z!=="string"||z.trim()==="")return Z("no `on:` trigger");let Y=D4(z);if(typeof Y==="string")return Z(Y);let W=J.fields.otherwise;if(typeof W!=="string"||!P1.has(W.trim()))return Z("`otherwise:` must be one of deny, ask, follow-up, warn");let G=[];for(let V of X1(J.fields.require)){let B=R4(V);if(typeof B==="string")return Z(B);G.push(B)}if(G.length===0&&X)return Z("no `require:` proof, so nothing could ever satisfy this rule");return{rule:{name:$.name,tier:$.tier,enabled:X,on:Y,require:G,otherwise:W.trim(),body:J.body}}}function K8($){let Z=new Map,J=[];for(let q of["global","project"])for(let X of $.filter((z)=>z.tier===q)){let z=E4(X);if("error"in z){J.push(z.error);continue}Z.set(z.rule.name,z.rule)}let Q=[...Z.values()];return{rules:Q.filter((q)=>q.enabled),disabled:Q.filter((q)=>!q.enabled),errors:J}}import{existsSync as k4,readdirSync as x4,readFileSync as S4}from"node:fs";import{basename as f4,join as F$}from"node:path";var T1=500;function A1($){return F$(H($),"rule-observations.jsonl")}function a2($){return F$(H($),"..","rules")}function r2(){return F$(P$(),"rules")}function L1($,Z){if(!k4($))return[];return x4($,{withFileTypes:!0}).filter((J)=>J.isFile()&&J.name.endsWith(".md")).map((J)=>{let Q=F$($,J.name);return{name:f4(J.name,".md"),tier:Z,text:S4(Q,"utf8")}})}function M8($){return[...L1(r2(),"global"),...L1(a2($),"project")]}function D1($){return F$(H($),"rule-spawn-links.jsonl")}function R1($,Z){try{_(D1($),Z)}catch{}}function E1($){try{return T(D1($),T1)}catch{return[]}}function C$($,Z){try{_(A1($),Z)}catch{}}function F8($){try{return T(A1($),T1)}catch{return[]}}function O$($,Z){if(!Z.enabled)return{rules:[],disabled:[],errors:[]};return K8(M8($))}function x1($,Z,J){let Q=O$($,Z).rules;if(n2(J)!==null)return Y8(Q,"subagent");let q=i2(J);return q!==null&&Y8(Q,q.kind)}function S1($,Z,J,Q){if(!Z.enabled)return;let q=n2(J);if(q!==null){R1($,{...q,at:Q.at});return}let X=H8(N1(J,()=>E1($)),Q);if(X!==null)C$($,X)}function f1($,Z){return Y8(O$($,Z).rules,"gate")}function b1($,Z,J,Q){if(!Z.enabled)return;C$($,U8(J,Q))}var k1={decision:{kind:"abstain"},outcomes:[],errors:[]};function w1($,Z,J,Q){return v1($,Z,J,Q,V8)}function y1($,Z,J){return v1($,Z,{event:"stop"},J,B8)}function v1($,Z,J,Q,q){let X=O$($,Z);if(X.rules.length===0&&X.errors.length===0)return k1;let z=z8(X.rules,J);if(z.length===0)return{...k1,errors:X.errors};let Y=W8(z,F8($),Q),W=G8(Y);return{decision:W===null?{kind:"abstain"}:q(W),outcomes:Y,errors:X.errors}}import{existsSync as b4,mkdirSync as w4,readFileSync as y4,writeFileSync as v4}from"node:fs";import{join as m4}from"node:path";function m1($){return m4(H($),"shell-stall.json")}function g1($){let Z=m1($);if(!b4(Z))return{};try{return JSON.parse(y4(Z,"utf8"))}catch{return{}}}function u1($,Z){try{w4(H($),{recursive:!0}),v4(m1($),`${JSON.stringify(Z,null,2)}
122
+ ${$.body.trim()}`}function W8($,Z,J){let Q=[];for(let q of $){let X=C1(q,Z,J);if(X.length===0)continue;let z=X.map(O1);Q.push({rule:q,verdict:l2(q.otherwise,J.mode),missing:z,message:L4(q,z,J.shaRoot,J.sha)})}return Q}var _1={warn:0,"follow-up":1,ask:2,deny:3};function G8($){return $.reduce((Z,J)=>Z===null||_1[J.verdict]>_1[Z.verdict]?J:Z,null)}function V8($){let Z=`rule:${$.rule.name}`;if($.verdict==="deny")return{kind:"deny",reason:$.message,rule:Z};if($.verdict==="ask")return{kind:"ask",reason:$.message,userNote:$.message,rule:Z};return{kind:"abstain"}}function B8($){switch($.verdict){case"deny":case"ask":return{kind:"continue",text:`BLOCKED: ${$.message}`};case"follow-up":return{kind:"continue",text:`NEED: ${$.message}`};case"warn":return{kind:"context",text:`ADVISORY: ${$.message}`}}}function i2($){if($.event==="subagent.stop"){let Z=$.spawnSubagentType??$.spawnAgentLabel;return Z===void 0?null:{kind:"subagent",value:Z}}if($.event==="tool.after"||$.event==="shell.after")return $.command===void 0?null:{kind:"command",value:$.command};if($.event==="edit.after")return $.filePath===void 0?null:{kind:"file",value:$.filePath};return null}function H8($,Z){let J=i2($);return J===null?null:{...J,sha:Z.sha,sessionKey:Z.sessionKey,at:Z.at}}function U8($,Z){return{kind:"gate",value:$,sha:Z.sha,sessionKey:Z.sessionKey,at:Z.at}}function n2($){if($.event!=="tool.after"||!T4.has($.toolName??""))return null;let{spawnAgentLabel:Z,spawnSubagentType:J}=$;return Z===void 0||J===void 0||Z===J?null:{label:Z,type:J}}var T4=new Set(["Task","Agent"]);function N1($,Z){if($.event!=="subagent.stop"||$.spawnSubagentType!==void 0)return $;let J=$.spawnAgentLabel;if(J===void 0)return $;let Q=Z().filter((X)=>X.label===J),q=Q[Q.length-1];return q===void 0?$:{...$,spawnSubagentType:q.type}}var P1=new Set(["deny","ask","follow-up","warn"]),j1=new Set(["subagent","command","gate","file"]);var A4=new Set(["pr-open","commit","push","stop"]);function D4($){let Z=$.trim();if(A4.has(Z))return{kind:Z};let J=/^(tool|command)\(([^)]*)\)$/.exec(Z),Q=J?.[1],q=J?.[2]?.trim();if(Q===void 0||q===void 0||q==="")return`unknown trigger "${Z}" — use one of pr-open, commit, push, stop, tool(<name>), command(<pattern>)`;return Q==="tool"?{kind:"tool",name:q}:{kind:"command",pattern:q}}function R4($){let[Z,...J]=$.trim().split(/\s+since\s+/i),Q=/^([a-z]+)\(([^)]*)\)$/.exec((Z??"").trim()),q=Q?.[1],X=Q?.[2]?.trim();if(q===void 0||!j1.has(q)||X===void 0||X==="")return`unknown proof "${$.trim()}" — use subagent(<type>), command(<pattern>), gate(<name>) or file(<glob>)`;let z=(J[0]??"head").trim().toLowerCase();if(z!=="head"&&z!=="session")return`unknown window "since ${z}" in "${$.trim()}" — use since HEAD or since session`;return{kind:q,value:X,since:z}}function E4($){let Z=(V)=>({error:{name:$.name,tier:$.tier,error:V}}),{doc:J,error:Q}=u2($.text);if(J===null)return Z(Q??"unreadable");let q=J.fields.enabled,X=q===void 0?!0:String(q).trim()!=="false",z=J.fields.on;if(typeof z!=="string"||z.trim()==="")return Z("no `on:` trigger");let Y=D4(z);if(typeof Y==="string")return Z(Y);let W=J.fields.otherwise;if(typeof W!=="string"||!P1.has(W.trim()))return Z("`otherwise:` must be one of deny, ask, follow-up, warn");let G=[];for(let V of X1(J.fields.require)){let B=R4(V);if(typeof B==="string")return Z(B);G.push(B)}if(G.length===0&&X)return Z("no `require:` proof, so nothing could ever satisfy this rule");return{rule:{name:$.name,tier:$.tier,enabled:X,on:Y,require:G,otherwise:W.trim(),body:J.body}}}function K8($){let Z=new Map,J=[];for(let q of["global","project"])for(let X of $.filter((z)=>z.tier===q)){let z=E4(X);if("error"in z){J.push(z.error);continue}Z.set(z.rule.name,z.rule)}let Q=[...Z.values()];return{rules:Q.filter((q)=>q.enabled),disabled:Q.filter((q)=>!q.enabled),errors:J}}import{existsSync as k4,readdirSync as x4,readFileSync as S4}from"node:fs";import{basename as f4,join as F$}from"node:path";var T1=500;function A1($){return F$(H($),"rule-observations.jsonl")}function a2($){return F$(H($),"..","rules")}function r2(){return F$(P$(),"rules")}function L1($,Z){if(!k4($))return[];return x4($,{withFileTypes:!0}).filter((J)=>J.isFile()&&J.name.endsWith(".md")).map((J)=>{let Q=F$($,J.name);return{name:f4(J.name,".md"),tier:Z,text:S4(Q,"utf8")}})}function M8($){return[...L1(r2(),"global"),...L1(a2($),"project")]}function D1($){return F$(H($),"rule-spawn-links.jsonl")}function R1($,Z){try{_(D1($),Z)}catch{}}function E1($){try{return T(D1($),T1)}catch{return[]}}function C$($,Z){try{_(A1($),Z)}catch{}}function F8($){try{return T(A1($),T1)}catch{return[]}}function O$($,Z){if(!Z.enabled)return{rules:[],disabled:[],errors:[]};return K8(M8($))}function x1($,Z,J){let Q=O$($,Z).rules;if(n2(J)!==null)return Y8(Q,"subagent");let q=i2(J);return q!==null&&Y8(Q,q.kind)}function S1($,Z,J,Q){if(!Z.enabled)return;let q=n2(J);if(q!==null){R1($,{...q,at:Q.at});return}let X=H8(N1(J,()=>E1($)),Q);if(X!==null)C$($,X)}function f1($,Z){return Y8(O$($,Z).rules,"gate")}function b1($,Z,J,Q){if(!Z.enabled)return;C$($,U8(J,Q))}var k1={decision:{kind:"abstain"},outcomes:[],errors:[]};function w1($,Z,J,Q){return v1($,Z,J,Q,V8)}function y1($,Z,J){return v1($,Z,{event:"stop"},J,B8)}function v1($,Z,J,Q,q){let X=O$($,Z);if(X.rules.length===0&&X.errors.length===0)return k1;let z=z8(X.rules,J);if(z.length===0)return{...k1,errors:X.errors};let Y=W8(z,F8($),Q),W=G8(Y);return{decision:W===null?{kind:"abstain"}:q(W),outcomes:Y,errors:X.errors}}import{existsSync as b4,mkdirSync as w4,readFileSync as y4,writeFileSync as v4}from"node:fs";import{join as m4}from"node:path";function m1($){return m4(H($),"shell-stall.json")}function g1($){let Z=m1($);if(!b4(Z))return{};try{return JSON.parse(y4(Z,"utf8"))}catch{return{}}}function u1($,Z){try{w4(H($),{recursive:!0}),v4(m1($),`${JSON.stringify(Z,null,2)}
123
123
  `,"utf8")}catch{}}function g4($){return $.trim().replace(/\s+/g," ").slice(0,300)}function h1($,Z,J){let Q=g4(J);if(!Q)return 0;let q=g1($),X=q[Z]??{hits:0},z=X.lastCommand===Q?{lastCommand:Q,hits:X.hits+1}:{lastCommand:Q,hits:1};return q[Z]=z,u1($,q),z.hits}function p1($,Z){let J=g1($);J[Z]={hits:0},u1($,J)}var u4=new Set(["command","doas","env","nice","nohup","sudo","time","xargs"]),h4=new Set(["halt","poweroff","reboot","shutdown"]),p4=new Set(["curl","ftp","gh","nc","ncat","rsync","scp","sftp","ssh","telnet","wget"]),c4=new Set(["cp","mv","rm","rmdir","tee","truncate"]),d4=new Set(["chmod","chown"]),l4=/^\/dev\/(sd|nvme|vd|hd|disk)/;function i4($){let Z=0;while(Z<$.length){let J=$[Z];if(!J)break;if(u4.has(J.text)||J.text.startsWith("-")||J.text.includes("=")){Z+=1;continue}let Q=J.text.split("/").pop()??J.text,X=$.slice(Z+1).map((z)=>z.text);if(h4.has(Q)||Q==="mkfs"||Q.startsWith("mkfs."))return"destructive";if(Q==="dd"&&X.some((z)=>z.startsWith("of=")&&l4.test(z.slice(3))))return"destructive";if(Q==="diskutil"&&X.some((z)=>z.startsWith("erase")||z.startsWith("partition")))return"destructive";if(Q==="rm"&&X.some((z)=>z==="/"||z==="/*"||z.startsWith("../../")))return"destructive";if(p4.has(Q))return"network";if((Q==="git"||Q==="docker")&&X.includes("push"))return"network";if(c4.has(Q)||Q==="sed"&&X.includes("-i"))return"write";if(d4.has(Q))return"privilege";if(X.includes(">"))return"write";return X.includes(">>")?"write-preserving":"read"}return"read"}var c1=["read","write-preserving","write","privilege","network","destructive"];function l1($){let Z="read";for(let J of S($)){let Q=i4(J.words);if(c1.indexOf(Q)>c1.indexOf(Z))Z=Q}return Z}function n4($){return l1($)==="destructive"}function a4($,Z){return[`BLOCKED: shell stall — the same command was attempted ${Z} times.`,`TRIED: \`${$.slice(0,160)}\``,"NEED: change approach. Do not repeat this command. Diagnose why it failed, use a different tool/path, or escalate with BLOCKED/TRIED/NEED."].join(`
124
124
  `)}var r4=new Set(["write","privilege","network"]),s2={catastrophic:"shell-catastrophic",posture:"shell-posture-paired",stall:"shell-stall"},s4={network:"reaches the network, so it leaves this machine and cannot be pulled back",privilege:"changes who can reach a path, and that will not appear in any diff",write:"can overwrite or remove a path that already exists"};function d1($){return s4[$]??"changes something outside this turn"}function o4($,Z){if(Z!=="paired")return null;let J=l1($);if(!r4.has(J))return null;return{kind:"ask",reason:`Posture paired: this command ${d1(J)}, and the operator asked to see these before they run. Wait for their answer — the posture is theirs to change, not yours.`,userNote:`Paired posture: this ${J} command ${d1(J)}. Approve it, or leave the posture with \`tlc harness mode solo\`.`,rule:s2.posture}}function i1($){let Z=$.command;if(!Z)return{kind:"allow"};if($.catastrophicAsk&&n4(Z))return{kind:"ask",reason:"The command was flagged as potentially catastrophic. Prefer scoped paths inside the repo or reversible operations.",userNote:"This shell command can destroy data outside the workspace. Approve only if you intend it.",rule:s2.catastrophic};let J=o4(Z,$.mode);if(J)return J;if($.stallDetection){let Q=h1($.projectDir,$.sessionKey,Z);if(Q>=$.stallRepeatThreshold)return{kind:"deny",reason:a4(Z,Q),userNote:`Harness blocked a repeated shell command (${Q}x).`,rule:s2.stall}}return{kind:"allow"}}function t4($){return[$.command??"",...$.args??[]].join(" ")}function o2($,Z){for(let J of Object.values($.hooks??{}))for(let Q of J)for(let q of Q.hooks??[]){let X=t4(q);if(X.includes("tlc-exec")&&new RegExp(`(^|\\s)${Z}(\\s|$)`).test(X))return!0}return!1}function n1($,Z){if($===null)return{run:!0,reason:"no user-level settings — this shim is the only hook for this event"};return o2($,Z)?{run:!1,reason:`a user-level hook already runs ${Z} — standing down to avoid a second run`}:{run:!0,reason:`no user-level hook runs ${Z}`}}function a1($,Z,J){let Q=`${$}/skills/harness-init`;return Z.filter((q)=>J(q)).map((q)=>({providerDir:q,source:Q,target:`${q}/skills/harness-init`}))}function r1($,Z,J){let Q=J.linkTarget($);if(Q===null)return{state:"absent",target:$};if(!J.exists(Q))return{state:"dangling",target:$,resolved:Q};let X=(J.realpath??((z)=>z))(Z).replace(/\/+$/,"");return Q===X||Q.startsWith(`${X}/`)?{state:"ok",target:$,resolved:Q}:{state:"outside-runtime",target:$,resolved:Q}}function s1($){switch($.state){case"ok":return`linked → ${$.resolved}`;case"dangling":return`points at ${$.resolved}, which does not exist — re-run \`tlc harness install\``;case"outside-runtime":return`points at ${$.resolved}, outside the runtime — it will break when that path goes`;default:return"not linked — the provider cannot see the init skill"}}import{existsSync as e4,mkdirSync as $z,readFileSync as Zz,writeFileSync as Jz}from"node:fs";import{join as Qz}from"node:path";var o1=200,qz=8;function t1($){return Qz(H($),"fingerprint-resolutions.json")}function e1($){let Z=t1($);if(!e4(Z))return{};try{let J=JSON.parse(Zz(Z,"utf8"));return J&&typeof J==="object"?J:{}}catch{return{}}}function Xz($){let Z=Object.entries($);if(Z.length<=o1)return $;let J=Z.sort((Q,q)=>q[1].at.localeCompare(Q[1].at)).slice(0,o1);return Object.fromEntries(J)}function $7($,Z,J){let Q=e1($);Q[Z]={...J,files:J.files.slice(0,qz)};let q=Xz(Q);try{$z(H($),{recursive:!0}),Jz(t1($),`${JSON.stringify(q,null,2)}
125
125
  `,"utf8")}catch{}return q}function Z7($,Z){return e1($)[Z]??null}function J7($){return`History: this same ${$.gate} failure was resolved once before, after changes to ${$.files.join(", ")}. That is a record of what happened, not a list to edit — confirm it against this failure before acting on it.`}import{createHash as zz}from"node:crypto";function Q7($){let Z=$.output.replace(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/g,"<ts>").replace(/\b\d{5,}\b/g,"<n>").slice(0,1500),J=JSON.stringify({files:[...$.files].sort(),gate:$.gate,exitCode:$.exitCode,output:Z});return zz("sha256").update(J).digest("hex").slice(0,16)}import{existsSync as Yz,mkdirSync as Wz,readFileSync as Gz,writeFileSync as Vz}from"node:fs";import{join as Bz}from"node:path";function q7($){return Bz(H($),"fingerprint.json")}function t2($){let Z=q7($);if(!Yz(Z))return{};try{return JSON.parse(Gz(Z,"utf8"))}catch{return{}}}function X7($,Z){try{Wz(H($),{recursive:!0}),Vz(q7($),`${JSON.stringify(Z,null,2)}