@code-partner/codepipe 0.13.1-dev.257.g5884e02 → 0.13.1-dev.266.g24c82f1

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.
Files changed (2) hide show
  1. package/dist/index.js +6 -6
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
- var lb=Object.defineProperty;var x=(t,e)=>()=>(t&&(e=t(t=0)),e);var ze=(t,e)=>{for(var r in e)lb(t,r,{get:e[r],enumerable:!0})};var Ve,mt,zs=x(()=>{"use strict";Ve="0.13.1-dev.257.g5884e02",mt="https://hub.dev.codepipe.dev"});function Vn(t){return typeof t!="number"||!Number.isFinite(t)?!1:t>=xu&&t<=ht}var ht,xu,Su=x(()=>{"use strict";zs();ht=4,xu=4});var Eu=x(()=>{"use strict";zs()});function Xn(t=6){return`# CodePipe Context Repo format version.
2
+ var lb=Object.defineProperty;var x=(t,e)=>()=>(t&&(e=t(t=0)),e);var ze=(t,e)=>{for(var r in e)lb(t,r,{get:e[r],enumerable:!0})};var Ve,mt,zs=x(()=>{"use strict";Ve="0.13.1-dev.266.g24c82f1",mt="https://hub.dev.codepipe.dev"});function Vn(t){return typeof t!="number"||!Number.isFinite(t)?!1:t>=xu&&t<=ht}var ht,xu,Su=x(()=>{"use strict";zs();ht=4,xu=4});var Eu=x(()=>{"use strict";zs()});function Xn(t=6){return`# CodePipe Context Repo format version.
3
3
  # Bumped by the scaffold / the format-migration PR \u2014 do not edit by hand.
4
4
  template_version: ${t}
5
5
  `}function Xs(t){if(!t)return 0;let e=/^\s*template_version:\s*(\d+)\s*$/m.exec(t),r=e?parseInt(e[1]??"",10):NaN;return Number.isFinite(r)&&r>=0?r:0}function Js(t,e=Vs){let r=[];for(let n of e)if(!(n.version<=t))for(let o of n.addedPaths)r.includes(o)||r.push(o);return r}function Zs(t,e=Vs){return e.filter(r=>r.version>t)}var Tu,gt,Kr,Vs,Ru=x(()=>{"use strict";Tu=6,gt=".codepipe-context.yaml",Kr=".devpipe-context.yaml",Vs=[{version:1,summary:"ADR section: adr/ scaffold (README, template, derived INDEX) + the format-version stamp itself",addedPaths:["adr/README.md","adr/0000-template.md","adr/INDEX.md",gt]},{version:2,summary:"Rename the format-version stamp .devpipe-context.yaml \u2192 .codepipe-context.yaml (drop the devpipe-brand leftover)",addedPaths:[gt]},{version:3,summary:"Custom project actions (the RUN tab): actions/ scaffold with the format README",addedPaths:["actions/README.md"]},{version:4,summary:"Project map: model/ scaffold with the format README (facts/ vs derived/ layout)",addedPaths:["model/README.md"]},{version:5,summary:"Roles: roles/ scaffold with the format README (override a bundled critic by name, or add your own)",addedPaths:["roles/README.md"]},{version:6,summary:"Skills: skills/ scaffold with the format README (procedures the agent invokes instead of improvising)",addedPaths:["skills/README.md"]}]});function Zn(t){return`model/facts/identity/${t}.yaml`}function gr(t){return`model/facts/events/${t}.yaml`}function ta(t){return`model/facts/annotations/${t}.md`}function ra(t){return`model/derived/correlates/${t}.yaml`}function na(t){return`model/derived/touched/${t}.yaml`}function Iu(t){return t===""?"root":t.replace(/\//g,"-")}function oa(t,e){return`model/derived/structure/${t}/${Iu(e)}.yaml`}function ei(t){return typeof t=="string"&&Pu.test(t)}function re(t){if(typeof t!="string")return null;let e=t.indexOf(":");if(e<=0)return null;let r=t.indexOf(":",e+1);if(r<0)return null;let n=t.slice(0,e);if(!Cu.includes(n))return null;let o=t.slice(e+1,r),i=t.slice(r+1);return o===""&&!mb.includes(n)||i===""?null:{level:n,repo:o,path:i}}function xe(t){return`task::${t}`}function ye(t,e,r){return`${t}:${e}:${r}`}function Qn(t){let e=[];return vt(t)?(ri(t.modelFormatVersion)||e.push("modelFormatVersion: missing or not a positive integer"),typeof t.repo!="string"&&e.push("repo: missing (empty string = cross-repo)"),typeof t.builtFromCommit!="string"&&e.push("builtFromCommit: missing"),Array.isArray(t.edges)?t.edges.forEach((r,n)=>{if(!vt(r)){e.push(`edges[${n}]: not an object`);return}ia.includes(r.kind)||e.push(`edges[${n}].kind: unknown "${String(r.kind)}"`),re(r.from)||e.push(`edges[${n}].from: malformed nodeKey`),re(r.to)||e.push(`edges[${n}].to: malformed nodeKey`),r.weight!==void 0&&!(typeof r.weight=="number"&&Number.isFinite(r.weight))&&e.push(`edges[${n}].weight: not a finite number`)}):e.push("edges: not an array"),e.length?{ok:!1,errors:e}:{ok:!0,value:t}):{ok:!1,errors:["edge sheet: not an object"]}}function Au(t){return{...t,edges:Hr(t.edges,e=>`${e.kind} ${e.from} ${e.to}`)}}function yr(t){return kr(Au(t))}function vt(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function ri(t){return typeof t=="number"&&Number.isInteger(t)&&t>0}function yt(t){return typeof t=="string"&&t.length>0}function gb(t){return t.modelFormatVersion!==2}function jt(t){let e=[];if(!vt(t))return{ok:!1,errors:["shard: not an object"]};ri(t.modelFormatVersion)||e.push("modelFormatVersion: missing or not a positive integer"),yt(t.repo)||e.push("repo: missing or empty"),yt(t.builtFromCommit)||e.push("builtFromCommit: missing or empty");let r=typeof t.repo=="string"?t.repo:"",n=new Set;return Array.isArray(t.nodes)?t.nodes.forEach((o,i)=>{if(!vt(o)){e.push(`nodes[${i}]: not an object`);return}let s=re(o.key);if(!s){e.push(`nodes[${i}].key: malformed nodeKey (${JSON.stringify(o.key??null)})`);return}o.level!==s.level&&e.push(`nodes[${i}]: level "${String(o.level)}" does not match key prefix "${s.level}"`),r&&s.repo!==r&&e.push(`nodes[${i}].key: repo "${s.repo}" mixed into shard of repo "${r}"`);let a=o.key;n.has(a)&&e.push(`nodes[${i}].key: duplicate "${a}"`),n.add(a),o.entityId!==void 0&&!ei(o.entityId)&&e.push(`nodes[${i}].entityId: malformed (${JSON.stringify(o.entityId)})`)}):e.push("nodes: not an array"),Array.isArray(t.edges)?t.edges.forEach((o,i)=>{if(!vt(o)){e.push(`edges[${i}]: not an object`);return}ia.includes(o.kind)||e.push(`edges[${i}].kind: unknown "${String(o.kind)}"`),(!yt(o.to)||!re(o.to))&&e.push(`edges[${i}].to: malformed nodeKey`),(!yt(o.from)||!n.has(o.from))&&e.push(`edges[${i}].from: "${String(o.from)}" is not a node of this shard`),o.weight!==void 0&&!(typeof o.weight=="number"&&Number.isFinite(o.weight))&&e.push(`edges[${i}].weight: not a finite number`)}):e.push("edges: not an array"),e.length?{ok:!1,errors:e}:{ok:!0,value:t}}function eo(t){let e=[];if(!vt(t))return{ok:!1,errors:["identity: not an object"]};if(ri(t.modelFormatVersion)||e.push("modelFormatVersion: missing or not a positive integer"),yt(t.repo)||e.push("repo: missing or empty"),t.builtFromCommit!==void 0&&!yt(t.builtFromCommit)&&e.push("builtFromCommit: not a non-empty string"),!Array.isArray(t.entities))e.push("entities: not an array");else{let r=new Set;t.entities.forEach((n,o)=>{if(!vt(n)){e.push(`entities[${o}]: not an object`);return}ei(n.entityId)?r.has(n.entityId)?e.push(`entities[${o}].entityId: duplicate "${n.entityId}"`):r.add(n.entityId):e.push(`entities[${o}].entityId: malformed (${JSON.stringify(n.entityId??null)})`),re(n.currentKey)||e.push(`entities[${o}].currentKey: malformed nodeKey`),n.status!=="active"&&n.status!=="orphaned"&&e.push(`entities[${o}].status: expected active|orphaned`),yt(n.firstSeen)||e.push(`entities[${o}].firstSeen: missing`),yt(n.lastSeen)||e.push(`entities[${o}].lastSeen: missing`),n.aliases!==void 0&&(Array.isArray(n.aliases)?n.aliases.forEach((i,s)=>{(!vt(i)||!re(i.key)||!yt(i.until))&&e.push(`entities[${o}].aliases[${s}]: malformed`)}):e.push(`entities[${o}].aliases: not an array`))})}return e.length?{ok:!1,errors:e}:{ok:!0,value:t}}function Nt(t){let e=[];return vt(t)?(ri(t.modelFormatVersion)||e.push("modelFormatVersion: missing or not a positive integer"),yt(t.taskKey)||e.push("taskKey: missing or empty"),t.origin!=="bootstrap"&&t.origin!=="pipeline"&&e.push("origin: expected bootstrap|pipeline"),t.date!==void 0&&!(typeof t.date=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(t.date))&&e.push("date: expected YYYY-MM-DD"),(!Array.isArray(t.commits)||t.commits.some(r=>!yt(r)))&&e.push("commits: not an array of non-empty strings"),Array.isArray(t.files)?t.files.forEach((r,n)=>{if(!vt(r)||!re(r.key)){e.push(`files[${n}].key: malformed nodeKey`);return}r.entityId!==void 0&&!ei(r.entityId)&&e.push(`files[${n}].entityId: malformed`),r.churn!==void 0&&!(typeof r.churn=="number"&&r.churn>=0)&&e.push(`files[${n}].churn: not a non-negative number`)}):e.push("files: not an array"),e.length?{ok:!1,errors:e}:{ok:!0,value:t}):{ok:!1,errors:["event: not an object"]}}function Hr(t,e){return[...t].sort((r,n)=>e(r)<e(n)?-1:e(r)>e(n)?1:0)}function _u(t){return{...t,nodes:Hr(t.nodes,e=>e.key),edges:Hr(t.edges,e=>`${e.kind}\0${e.from}\0${e.to}`)}}function ju(t){return{...t,entities:Hr(t.entities,e=>e.entityId).map(e=>e.aliases?{...e,aliases:Hr(e.aliases,r=>`${r.key}\0${r.until}`)}:e)}}function Nu(t){let e=t.links?{...t.links,...t.links.adr?{adr:[...t.links.adr].sort()}:{},...t.links.tasks?{tasks:[...t.links.tasks].sort()}:{}}:void 0;return{...t,commits:[...t.commits].sort(),files:Hr(t.files,r=>r.key),...e?{links:e}:{}}}function Jn(t){return yb.test(t)?t:JSON.stringify(t)}function Ou(t){if(t===null)return"null";if(typeof t=="boolean")return t?"true":"false";if(typeof t=="number"){if(!Number.isFinite(t))throw new Error(`model yaml: non-finite number ${t}`);return JSON.stringify(t)}if(typeof t=="string")return JSON.stringify(t);throw new Error(`model yaml: unsupported scalar ${typeof t}`)}function Lu(t){return t===null||["boolean","number","string"].includes(typeof t)}function Qs(t){return Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[r])=>e<r?-1:e>r?1:0)}function Mu(t,e,r){if(Array.isArray(t)){for(let n of t)if(Lu(n))r.push(`${e}- ${Ou(n)}`);else{if(Array.isArray(n))throw new Error("model yaml: nested arrays are not part of the model schema");{let o=Qs(n);if(o.length===0){r.push(`${e}- {}`);continue}o.forEach(([i,s],a)=>{let c=a===0?`${e}- `:`${e} `;ea(i,s,c,`${e} `,r)})}}return}for(let[n,o]of Qs(t))ea(n,o,e,e,r)}function ea(t,e,r,n,o){if(Lu(e))o.push(`${r}${Jn(t)}: ${Ou(e)}`);else if(Array.isArray(e))e.length===0?o.push(`${r}${Jn(t)}: []`):(o.push(`${r}${Jn(t)}:`),Mu(e,`${n} `,o));else{let i=Qs(e);if(i.length===0)o.push(`${r}${Jn(t)}: {}`);else{o.push(`${r}${Jn(t)}:`);for(let[s,a]of i)ea(s,a,`${n} `,`${n} `,o)}}}function kr(t){let e=[];return Mu(t,"",e),e.join(`
6
6
  `)+`
7
- `}function ua(t){return kr(_u(t))}function da(t){return kr(ju(t))}function Wr(t){return kr(Nu(t))}var Oe,ub,db,pb,fb,Qo,hr,Cu,ia,Pu,mb,nt,sa,aa,ca,ti,hb,la,wr,yb,pa=x(()=>{"use strict";Oe=2,ub="model",db="model/README.md",pb="model/facts",fb="model/derived",Qo="model/derived/INDEX.yaml",hr="model/derived/relates.yaml";Cu=["system","container","component","code","task","adr"],ia=["contains","touched_by","correlates","relates","references","depends_on"],Pu=/^e_[0-9a-f]{8}$/;mb=["system","task","adr"];nt={windowCommits:1e3,commitFileCap:30,supportMin:5,jaccardMinPct:25,halfLifeDays:270,topK:8};sa=2,aa=5,ca=50,ti=2e3,hb=5e4,la={touched_by:.8,references:.7,relates:.6,correlates:.4,contains:.3,depends_on:.5},wr={budgetTokens:4e3,activationCutoff:.05,topKPerNode:8,nodeCap:200};yb=/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/});function wb(t){return t==="DONE"}function kb(t){return t==="AWAITING_EXTERNAL_FIX"?!1:fa.indexOf(t)>=fa.indexOf("IMPLEMENTING")}var fa,Du=x(()=>{"use strict";fa=["BACKLOG","QUEUED","INTAKE","AWAITING_APPROVAL","ANALYZING","ESTIMATING","AWAITING_ANSWER","REVIEW","READY","IMPLEMENTING","BUILD","CODE_REVIEW","TESTING","AWAITING_EXTERNAL_FIX","READY_TO_APPLY","APPLYING","AWAITING_CLUSTER","TRACKING","NEEDS_MANUAL","DONE"]});function $b(t){for(let e of ma)if(e.phases.includes(t))return e.id;return null}function vb(t){for(let e of Uu)if(e.phases.includes(t))return e.id;return null}var ma,bb,Uu,Bu=x(()=>{"use strict";ma=[{id:"intake",label:"Intake",phases:["INTAKE"]},{id:"analysis",label:"Analysis",phases:["ANALYZING","ESTIMATING"]},{id:"ready",label:"Ready",phases:["READY"]},{id:"implementation",label:"Implementation",phases:["IMPLEMENTING","BUILD"]},{id:"delivery",label:"Delivery",phases:["READY_TO_APPLY","APPLYING","AWAITING_CLUSTER"]}],bb=ma.flatMap(t=>t.phases),Uu=[{id:"review",label:"Review / tracking",phases:["CODE_REVIEW","TESTING","TRACKING"]},{id:"attention",label:"Need your attention",phases:["NEEDS_MANUAL","AWAITING_APPROVAL","AWAITING_EXTERNAL_FIX","AWAITING_ANSWER","REVIEW"]},{id:"backlog",label:"Backlog / queue",phases:["BACKLOG","QUEUED"]}]});function xb(t){return Fu.includes(t)?"planning":"implementation"}function Ht(){return{inputTokens:0,outputTokens:0,cacheReadInputTokens:0,cacheCreationInputTokens:0,totalCostUsd:0,model:"",numTurns:0,durationMs:0}}var ha,Fu,Sb,ga=x(()=>{"use strict";ha=["estimate","analyze","implement","resolve-conflict","rework","draft","build","code-review","index","backfill","analysis","chat","observer","council","testing"],Fu=["draft","analysis","chat","observer","council"];Sb=1});function Gu(t,e){return e.toLowerCase().includes(t.toLowerCase())}function ka(t){let e=t.filter(o=>o&&typeof o.id=="string"&&o.id.trim().length>0);if(e.length===0||Yu.every(o=>e.some(i=>Gu(o,i.id))))return null;let n=[...e].sort((o,i)=>{let s=o.createdAt??"",a=i.createdAt??"";return s!==a?s<a?1:-1:o.id<i.id?1:-1});for(let o of qu){let i=n.find(s=>Gu(o,s.id));if(i)return i.id}return n[0].id}function qr(){return{default:null,roles:{}}}function Eb(t,e){let r=t?.roles?.[e];return typeof r=="string"&&r.trim().length>0?r.trim():t?.default&&t.default.trim().length>0?t.default.trim():ro[e]??Wu}function Tb(t){let e=t?.provider;return typeof e=="string"&&e.trim().length>0?e.trim():Xe}function Rb(t){let e=qr();if(!t||typeof t!="object")return e;let r=t.llm;if(!r||typeof r!="object")return e;let n=r.provider;typeof n=="string"&&n.trim().length>0&&(e.provider=n.trim());let o=r.models;if(!o||typeof o!="object")return e;for(let[i,s]of Object.entries(o))typeof s!="string"||s.trim().length===0||(i==="default"?e.default=s.trim():e.roles[i]=s.trim());return e}function Ib(t){let e=typeof t.provider=="string"&&t.provider.trim().length>0&&t.provider.trim()!==Xe;if(t.default===null&&Object.keys(t.roles).length===0&&!e)return null;let{provider:r,...n}=t;return JSON.stringify(e?{provider:r.trim(),...n}:n)}function Cb(t){if(!t)return qr();try{let e=JSON.parse(t);if(!e||typeof e!="object")return qr();let r=e,n=qr();typeof r.provider=="string"&&r.provider.trim().length>0&&(n.provider=r.provider.trim()),typeof r.default=="string"&&(n.default=r.default);let o=r.roles;if(o&&typeof o=="object")for(let[i,s]of Object.entries(o))typeof s=="string"&&(n.roles[i]=s);return n}catch{return qr()}}var Xe,ya,Pe,to,ni,oi,Ku,Hu,wa,ro,Wu,qu,Yu,ba=x(()=>{"use strict";ga();Xe="claude",ya=[Xe],Pe="opus",to="sonnet",ni="haiku",oi=[Pe,to,ni],Ku="build-discovery",Hu=[Ku],wa=[...ha,...Hu],ro={analyze:Pe,implement:Pe,"resolve-conflict":Pe,rework:Pe,estimate:to,build:ni,"build-discovery":Pe,"code-review":Pe,draft:to,index:Pe,backfill:Pe,analysis:Pe,chat:Pe,observer:Pe,council:Pe,testing:Pe},Wu=Pe,qu=[Pe,to,ni],Yu=Array.from(new Set(Object.values(ro)))});function Ot(t){return Pb.has(t)?!0:Ab.some(e=>t.startsWith(e))}function ii(t,e){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e} must be a mapping`);return t}function br(t,e){if(t!=null){if(typeof t!="string")throw new Error(`${e} must be a string`);return t}}function va(t,e){if(t!=null){if(typeof t!="number"||!Number.isFinite(t))throw new Error(`${e} must be a number`);return t}}function Sa(t,e){let r=ii(e,"action definition"),n=t.replace(/\.(yml|yaml)$/i,""),o=br(r.id,"id")??n;if(!$a.test(o))throw new Error(`id must match ${$a} (got "${o}")`);if(o!==n)throw new Error(`id "${o}" must match the file name ("${n}")`);let i=br(r.title,"title")?.trim()||o,s;if(r.env!==void 0&&r.env!==null){let p=ii(r.env,"env");s={};for(let[d,m]of Object.entries(p)){if(!Je.test(d))throw new Error(`env name "${d}" must match ${Je}`);if(typeof m!="string"&&typeof m!="number"&&typeof m!="boolean")throw new Error(`env.${d} must be a scalar`);s[d]=String(m)}}let a,c=r.params;if(c!=null){if(!Array.isArray(c))throw new Error("params must be a list");if(c.length>zu)throw new Error(`too many params (max ${zu})`);let p=new Set;a=c.map((d,m)=>_b(d,m,p))}let l=r.steps;if(!Array.isArray(l)||l.length===0)throw new Error("steps must be a non-empty list");if(l.length>Vu)throw new Error(`too many steps (max ${Vu})`);let u=l.map((p,d)=>{let m=ii(p,`steps[${d}]`),f=br(m.run,`steps[${d}].run`);if(!f||f.trim().length===0)throw new Error(`steps[${d}].run is required`);let g=br(m.name,`steps[${d}].name`),k=va(m.timeout_sec,`steps[${d}].timeout_sec`);if(k!==void 0&&(!Number.isInteger(k)||k<=0))throw new Error(`steps[${d}].timeout_sec must be a positive integer`);return{run:f,...g?{name:g}:{},...k!==void 0?{timeout_sec:k}:{}}});return{id:o,title:i,...s?{env:s}:{},...a?{params:a}:{},steps:u}}function _b(t,e,r){let n=ii(t,`params[${e}]`),o=br(n.name,`params[${e}].name`);if(!o||!Je.test(o))throw new Error(`params[${e}].name must match ${Je}`);if(r.has(o))throw new Error(`duplicate param "${o}"`);r.add(o);let i=n.type;if(i!=="string"&&i!=="enum"&&i!=="number"&&i!=="boolean")throw new Error(`params[${e}].type must be string | enum | number | boolean`);let s;if(i==="enum"){let m=n.enum;if(!Array.isArray(m)||m.length===0||!m.every(f=>typeof f=="string"))throw new Error(`params[${e}].enum must be a non-empty string list`);s=m}let a=br(n.label,`params[${e}].label`),c=br(n.help,`params[${e}].help`),l=n.required===!0,u=va(n.min,`params[${e}].min`),p=va(n.max,`params[${e}].max`),d=n.default;if(d!=null&&typeof d!="string"&&typeof d!="number"&&typeof d!="boolean")throw new Error(`params[${e}].default must be a scalar`);return{name:o,type:i,...a?{label:a}:{},...c?{help:c}:{},...l?{required:!0}:{},...s?{enum:s}:{},...u!==void 0?{min:u}:{},...p!==void 0?{max:p}:{},...d!=null?{default:d}:{}}}function Ea(t,e){let r=t.params??[],n=new Map(r.map(i=>[i.name,i]));for(let i of Object.keys(e))if(!n.has(i))return{ok:!1,error:`unknown param: ${i}`};let o={};for(let i of r){let s=e[i.name];if(s==null||typeof s=="string"&&s.trim()==="")if(i.default!==void 0)s=i.default;else{if(i.required)return{ok:!1,error:`${i.name} is required`};continue}switch(i.type){case"string":{if(typeof s!="string")return{ok:!1,error:`${i.name} must be a string`};o[i.name]=s;break}case"enum":{if(typeof s!="string"||!(i.enum??[]).includes(s))return{ok:!1,error:`${i.name} must be one of: ${(i.enum??[]).join(", ")}`};o[i.name]=s;break}case"number":{let a=typeof s=="number"?s:typeof s=="string"?Number(s):NaN;if(!Number.isFinite(a))return{ok:!1,error:`${i.name} must be a number`};if(i.min!==void 0&&a<i.min)return{ok:!1,error:`${i.name} must be \u2265 ${i.min}`};if(i.max!==void 0&&a>i.max)return{ok:!1,error:`${i.name} must be \u2264 ${i.max}`};o[i.name]=a;break}case"boolean":{let a=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:null;if(a===null)return{ok:!1,error:`${i.name} must be a boolean`};o[i.name]=a;break}}}return{ok:!0,values:o}}var Je,Pb,Ab,xa,$a,zu,Vu,Ta=x(()=>{"use strict";Je=/^[A-Z][A-Z0-9_]*$/,Pb=new Set(["GH_TOKEN","GITHUB_TOKEN","GITLAB_TOKEN"]),Ab=["BITBUCKET_","YOUTRACK_","CLAUDE_","INPUT_"];xa=600,$a=/^[a-z0-9-]+$/,zu=32,Vu=64});function Xu(){return{primary:$e,context:$e,tasks:$e,docs:$e,code_comments:$e,chat:$e,code_review:$e}}function Ju(t){return!t||t.trim().length===0||t.trim().toLowerCase()===$e}function jb(t){if(typeof t!="string")return $e;let e=t.trim().replace(/\s+/g," ");return e.length===0||e.length>40||e.toLowerCase()===$e?$e:e}function Nb(t){let e=Xu();if(!t||typeof t!="object")return e;let r=t.language;if(!r||typeof r!="object"||Array.isArray(r))return e;let n=r;for(let o of no)e[o]=jb(n[o]);return e}function Ob(t){return no.every(e=>Ju(t[e]))}var $e,no,Yr,oo,Ra=x(()=>{"use strict";$e="auto",no=["primary","context","tasks","docs","code_comments","chat","code_review"],Yr=["English","Russian","German","Spanish","French","Portuguese","Italian","Chinese","Japanese","Korean"],oo=40});function Aa(t=Zu){let e=[];for(let r of t)e.push(...r.fields),r.groups&&e.push(...Aa(r.groups));return e}function Qu(t,e){let r=JSON.stringify(e);return Aa().find(n=>n.file===t&&JSON.stringify(n.path)===r)}function _a(t){let e=Qu(t.file,t.path);if(!e)return{ok:!1,error:`unknown setting path: ${t.file}:${t.path.join(".")}`};let r=t.value,n=e.type==="model"||e.type==="enum"||e.type==="string";if(r===null||n&&typeof r=="string"&&r.trim().length===0)return e.nullable?{ok:!0,field:e,value:null}:{ok:!1,error:`${e.id} cannot be cleared`};switch(e.type){case"model":case"string":{if(typeof r!="string")return{ok:!1,error:`${e.id} must be a string`};let i=r.trim();return e.type==="string"&&e.mustContain&&!i.includes(e.mustContain)?{ok:!1,error:`${e.id} must contain "${e.mustContain}"`}:e.maxLength!==void 0&&i.length>e.maxLength?{ok:!1,error:`${e.id} must be \u2264 ${e.maxLength} chars`}:{ok:!0,field:e,value:i}}case"enum":{if(typeof r!="string")return{ok:!1,error:`${e.id} must be a string`};let i=r.trim();return e.suggestions?.includes(i)?{ok:!0,field:e,value:i}:{ok:!1,error:`${e.id} must be one of: ${(e.suggestions??[]).join(", ")}`}}case"number":return typeof r!="number"||!Number.isFinite(r)?{ok:!1,error:`${e.id} must be a number`}:!e.float&&!Number.isInteger(r)?{ok:!1,error:`${e.id} must be an integer`}:e.min!==void 0&&r<e.min?{ok:!1,error:`${e.id} must be \u2265 ${e.min}`}:e.max!==void 0&&r>e.max?{ok:!1,error:`${e.id} must be \u2264 ${e.max}`}:{ok:!0,field:e,value:r};case"boolean":return typeof r!="boolean"?{ok:!1,error:`${e.id} must be a boolean`}:{ok:!0,field:e,value:r};case"string_list":{if(!Array.isArray(r))return{ok:!1,error:`${e.id} must be a list`};let i=r.map(s=>typeof s=="string"?s.trim():"").filter(s=>s.length>0);return i.length===0?e.nullable?{ok:!0,field:e,value:null}:{ok:!1,error:`${e.id} must be a non-empty list`}:{ok:!0,field:e,value:i}}case"string_map":{if(typeof r!="object"||r===null||Array.isArray(r))return{ok:!1,error:`${e.id} must be a name\u2192value map`};let i=Object.entries(r);if(i.length===0)return e.nullable?{ok:!0,field:e,value:null}:{ok:!1,error:`${e.id} must be a non-empty map`};if(i.length>Ia)return{ok:!1,error:`${e.id} must have \u2264 ${Ia} entries`};let s={};for(let[a,c]of i){if(!Je.test(a))return{ok:!1,error:`${e.id}: name "${a}" must match ${Je}`};if(Ot(a))return{ok:!1,error:`${e.id}: name "${a}" is reserved`};if(typeof c!="string")return{ok:!1,error:`${e.id}: value of "${a}" must be a string`};if(c.length>Ca)return{ok:!1,error:`${e.id}: value of "${a}" must be \u2264 ${Ca} chars`};s[a]=c}return{ok:!0,field:e,value:s}}}}var Lb,Mb,Ia,Ca,Pa,Zu,ed=x(()=>{"use strict";Ta();ba();pa();Ra();Lb={primary:"Primary language",context:"Context documents",tasks:"Tracker issues",docs:"Repo documentation",code_comments:"Code comments",chat:"Agent chat",code_review:"Code review comments"},Mb={primary:"The project's main language (agent status notes ride it). Empty \u21D2 auto.",context:"Knowledge, ADRs and task artifacts in the Context Repo. Empty \u21D2 auto.",tasks:"Issue titles/bodies the agent drafts. Empty \u21D2 auto.",docs:"Documentation changes in the project repos. Empty \u21D2 auto.",code_comments:"New code comments the agent writes. Empty \u21D2 auto.",chat:"The interactive task-drafting chat. Empty/auto \u21D2 mirror the user's messages.",code_review:"Review findings and PR comments. Empty \u21D2 follows the tracker-issues language."},Ia=64,Ca=2e3,Pa=2e3,Zu=[{id:"branch",label:"Branch",help:"Task-branch naming.",fields:[{id:"branch.pattern",file:"project.yaml",path:["branch","pattern"],type:"string",label:"Task-branch pattern",nullable:!0,mustContain:"<TASK_ID>",help:"Template for the per-task branch name. Must contain the <TASK_ID> placeholder. Empty \u21D2 default codepipe/<TASK_ID>."}]},{id:"llm",label:"LLM",fields:[{id:"llm.provider",file:"regimen.yaml",path:["llm","provider"],type:"enum",label:"Provider",nullable:!1,suggestions:[...ya],help:"LLM backend for this project. Currently only claude is available."}],groups:[{id:"llm.models",label:"Models by role",help:"Model per pipeline stage. Empty \u21D2 the role's recommended default applies.",fields:[{id:"llm.models.default",file:"regimen.yaml",path:["llm","models","default"],type:"model",label:"default (catch-all)",nullable:!0,suggestions:[...oi],help:"Overrides the recommended defaults for every role not listed below."},...wa.map(t=>({id:`llm.models.${t}`,file:"regimen.yaml",path:["llm","models",t],type:"model",label:t,nullable:!0,suggestions:[...oi],help:`recommended: ${ro[t]}`}))]}]},{id:"apply.style",label:"Commits & PRs",help:"Instructions for the AI agent on how to write commit messages and PR descriptions. Empty \u21D2 built-in templates.",fields:[{id:"apply.commit_style",file:"project.yaml",path:["apply","commit_style"],type:"string",label:"Commit message style",nullable:!0,multiline:!0,maxLength:Pa,help:'e.g. "English, imperative mood, first line \u2264 72 chars, start with the issue key". Empty \u21D2 "<KEY>: <task title>".'},{id:"apply.pr_style",file:"project.yaml",path:["apply","pr_style"],type:"string",label:"PR description style",nullable:!0,multiline:!0,maxLength:Pa,help:`e.g. "implementation details, bullet list of what was done, in the tracker's language". Empty \u21D2 the default PR body.`}]},{id:"apply.delivery",label:"Delivery & merge",help:"How a finished change reaches the repository: with or without a pull request, and who merges it.",fields:[{id:"apply.pull_request",file:"project.yaml",path:["apply","pull_request"],type:"boolean",label:"Open a pull request",nullable:!1,help:"On (default): the task branch is pushed and a pull request is opened \u2014 the change is reviewable in the git host and keeps a history of review comments. Off: no PR at all; the branch is merged into the default branch directly, and the agent's review remarks live only in the dashboard and the Context Repo."},{id:"apply.done",file:"project.yaml",path:["apply","done"],type:"enum",label:"Task is done when",nullable:!1,suggestions:["merge","branch"],help:"merge (default): the task is finished only once its change lands in the default branch. branch: the task ends at the pushed branch (plus the PR, if enabled) and nothing is merged for you."},{id:"apply.auto_merge",file:"project.yaml",path:["apply","auto_merge"],type:"enum",label:"Auto-merge pull requests",nullable:!1,suggestions:["off","on_ci_green"],help:"Applies to the pull-request path only. off (default): the merge waits for you (Approve on the task card). on_ci_green: as soon as the PR is open, conflict-free and its CI is green, CodePipe merges it \u2014 changes reach the default branch with no further review from you. Requires full automation; branch protection on the host still applies (a refused merge parks the task). Without pull requests, full automation merges the branch itself and this switch does not apply."}]},{id:"variables",label:"Variables",help:"Non-secret env vars for custom actions (RUN tab). Secrets go via the sealed Secrets form on the Tokens section instead.",fields:[{id:"variables",file:"project.yaml",path:["variables"],type:"string_map",label:"Variables",nullable:!0,help:"NAME=value pairs, one per line. Names are env-style (A-Z, 0-9, _); reserved credential names are refused."}]},{id:"testing",label:"Testing",help:"An optional phase after code review: writes the test plan you run in the morning and reports what it could verify.",fields:[{id:"testing.enabled",file:"regimen.yaml",path:["testing","enabled"],type:"boolean",nullable:!1,label:"Run the testing phase",help:"Off by default. When on, a task passing code review goes through a test pass before the PR: it derives TESTPLAN.md from the plan's requirements and reports per requirement what it could verify. A requirement it finds broken sends the change back for a fix (bounded below)."},{id:"testing.max_iterations",file:"regimen.yaml",path:["testing","max_iterations"],type:"number",nullable:!0,min:1,max:10,label:"Fix rounds before stopping",help:"How many times a failed test pass may send the change back before the task waits for you. Empty \u21D2 2."}]},{id:"skills",label:"Skills",help:"Reusable procedures the agent can invoke instead of improvising. Only their names and one-line descriptions sit in the prompt; the steps load when a skill is used.",fields:[{id:"skills.from_bundled",file:"regimen.yaml",path:["skills","from_bundled"],type:"boolean",nullable:!1,label:"Use the skills shipped with CodePipe",help:"On by default. General procedures maintained with the product."},{id:"skills.from_context_repo",file:"regimen.yaml",path:["skills","from_context_repo"],type:"boolean",nullable:!1,label:"Use this project's skills",help:"On by default. Skills the team writes in the context repository under `skills/<name>/SKILL.md`. These override a bundled skill of the same name."},{id:"skills.from_project_repo",file:"regimen.yaml",path:["skills","from_project_repo"],type:"boolean",nullable:!1,label:"Use the code repository's skills",help:"On by default. `.claude/skills/` inside the project repositories \u2014 the skills your developers already use locally. These win over both other sources."}]},{id:"gates",label:"Gates",help:"Approval gate before the pipeline starts (on by default; orthogonal to automation).",fields:[{id:"gates.require_approval",file:"regimen.yaml",path:["gates","require_approval"],type:"boolean",label:"Require approval before start",nullable:!1,help:"When on (default), a task taken from Develop waits in the QUEUE for a single Confirm before the pipeline starts \u2014 the Confirm pulls in dependency closure and topologically orders the queue. Off \u21D2 conveyor: the task starts the pipeline immediately."}]},{id:"automation",label:"Automation",help:"How far the pipeline advances the G1\u2013G4 gates without a manual Run/Approve. Independent of the approval gate above.",fields:[{id:"automation.level",file:"regimen.yaml",path:["automation","level"],type:"enum",label:"Automation level",nullable:!1,suggestions:["assisted","full"],help:"assisted \u21D2 manual Run/Approve at each of G1\u2013G4; full \u21D2 gates auto-pass."}]},{id:"language",label:"Language",help:"Languages the agent writes in, per area. Empty \u21D2 auto: mirror the language of the user's material.",fields:no.map(t=>({id:`language.${t}`,file:"project.yaml",path:["language",t],type:"string",label:Lb[t],nullable:!0,maxLength:40,suggestions:t==="chat"?[$e,...Yr]:[...Yr],help:Mb[t]}))},{id:"context.model",label:"Project map",help:"Parameters of the project map (built from git history by the CLI). Empty fields keep the defaults.",fields:[{id:"context.model.enabled",file:"regimen.yaml",path:["context","model","enabled"],type:"boolean",label:"Enable in the pipeline",nullable:!1,help:"When on, agents are asked to record intent annotations and (once available) receive an assembled context pack. Off \u21D2 the pipeline ignores the map entirely."},{id:"context.model.prompt.pack",file:"regimen.yaml",path:["context","model","prompt","pack"],type:"boolean",nullable:!1,label:"Give agents the context pack",help:"On by default. The assembled pack costs up to ~4000 tokens on every task of the analyze / estimate / implement / rework roles. Turning it off keeps the map building and stops the spend \u2014 the way to see what the pack is actually worth on this project."},{id:"context.model.prompt.annotations",file:"regimen.yaml",path:["context","model","prompt","annotations"],type:"boolean",nullable:!1,label:"Ask agents for intent annotations",help:"On by default. Adds the annotations block to the implement and rework prompts \u2014 the layer that records WHY the code is shaped this way. Cheap, and worth accumulating even while the pack is off."},{id:"context.index.hub",file:"regimen.yaml",path:["context","index","hub"],type:"enum",label:"Search index on the server",nullable:!0,suggestions:["off","metadata"],help:"off (default): search runs on your machine, nothing is uploaded. metadata: paths, labels and task texts (never code) are mirrored to the server so search and structure stay available while your machine is offline. Switching back to off deletes the mirrored rows."},{id:"context.model.issue_key_pattern",file:"regimen.yaml",path:["context","model","issue_key_pattern"],type:"string",label:"Issue-key pattern (regex)",nullable:!0,maxLength:200,help:"Regex that finds tracker issue keys in commit subjects when mining task events from history. Empty \u21D2 derived from the tracker project key (e.g. DEV-\\d+)."},{id:"context.model.cochange.window_commits",file:"regimen.yaml",path:["context","model","cochange","window_commits"],type:"number",label:"History window (commits)",nullable:!0,min:50,max:5e4,help:`How many commits back from the build commit are mined. Default ${nt.windowCommits}.`},{id:"context.model.cochange.commit_file_cap",file:"regimen.yaml",path:["context","model","cochange","commit_file_cap"],type:"number",label:"Commit size cap (files)",nullable:!0,min:2,max:500,help:`Commits touching more files are ignored as noise. Default ${nt.commitFileCap}.`},{id:"context.model.cochange.support_min",file:"regimen.yaml",path:["context","model","cochange","support_min"],type:"number",label:"Minimum co-occurrences",nullable:!0,min:1,max:100,help:`A pair of files must change together at least this many times. Default ${nt.supportMin}.`},{id:"context.model.cochange.jaccard_min_pct",file:"regimen.yaml",path:["context","model","cochange","jaccard_min_pct"],type:"number",label:"Minimum Jaccard (%)",nullable:!0,min:0,max:100,help:`Overlap threshold: |A\u2229B| / |A\u222AB| of the files' commit sets, in percent. Default ${nt.jaccardMinPct}.`},{id:"context.model.cochange.half_life_days",file:"regimen.yaml",path:["context","model","cochange","half_life_days"],type:"number",label:"Time-decay half-life (days)",nullable:!0,min:1,max:3650,help:`A commit this old counts half as much. Default ${nt.halfLifeDays} (~9 months).`},{id:"context.model.cochange.top_k",file:"regimen.yaml",path:["context","model","cochange","top_k"],type:"number",label:"Edges per file (top-k)",nullable:!0,min:1,max:64,help:`Only the k strongest co-change edges of a file survive \u2014 bounds graph density whatever the thresholds. Default ${nt.topK}.`}]},{id:"rate_limit",label:"Rate limit",help:"Automatic project pause as the LLM usage window fills up.",fields:[{id:"rate_limit.auto_pause.enabled",file:"project.yaml",path:["rate_limit","auto_pause","enabled"],type:"boolean",nullable:!1,label:"Pause the project near the limit",help:"On (default): when window utilization reaches the threshold, the project is paused (same pause as the manual one) and you get an email \u2014 the remaining window stays available for your own work. Off: agents keep working until the provider actually runs out."},{id:"rate_limit.auto_pause.threshold",file:"project.yaml",path:["rate_limit","auto_pause","threshold"],type:"number",float:!0,nullable:!0,min:.05,max:1,label:"Pause threshold (share of the window)",help:"Fraction of the usage window at which the pause fires; the rest (1 \u2212 threshold) is your manual-work reserve. Empty \u21D2 0.75."}]},{id:"context.job_logs",label:"Job transcripts",help:"Whether the raw agent transcript of each job is kept in the Context Repo.",fields:[{id:"context.job_logs.enabled",file:"regimen.yaml",path:["context","job_logs","enabled"],type:"boolean",label:"Keep transcripts in the Context Repo",nullable:!1,help:"Off (default): the transcript is discarded after the run \u2014 nothing lands in the Context Repo. On: each job's raw transcript is committed as tasks/<KEY>/logs/job-<id>.jsonl for post-mortem debugging."}]}]});function td(t){if(t==null)return[];if(!Array.isArray(t))return null;let e=[];for(let r of t){if(typeof r!="string"||r.trim().length===0)return null;e.push(r.trim())}return e}function Na(t){let{name:e,body:r,origin:n}=t;if(!ja.test(e))return{ok:!1,error:`role name must match ${ja} (got "${e}")`};if(r.trim().length===0)return{ok:!1,error:"role body is empty \u2014 the body IS the role's prompt"};let o=t.frontmatter;if(o==null||typeof o!="object"||Array.isArray(o))return{ok:!1,error:"missing or malformed frontmatter block"};let i=o,s=i.description;if(typeof s!="string"||s.trim().length===0)return{ok:!1,error:"description is required (one line: what this role looks for)"};if(s.length>300)return{ok:!1,error:"description must be \u2264 300 characters"};let a=td(i.refs);if(a===null)return{ok:!1,error:"refs must be a list of non-empty paths"};if(a.length>10)return{ok:!1,error:"refs must list at most 10 files \u2014 a role is a narrow view"};for(let d of a)if(d.startsWith("/")||d.includes(".."))return{ok:!1,error:`ref "${d}" must be a path inside the Context Repo`};let c=td(i.scenarios);if(c===null)return{ok:!1,error:"scenarios must be a list"};let l=[];for(let d of c){if(!si.includes(d))return{ok:!1,error:`unknown scenario "${d}" \u2014 one of: ${si.join(", ")}`};l.includes(d)||l.push(d)}if(l.length===0)return{ok:!1,error:`scenarios must name at least one of: ${si.join(", ")}`};let u=i.model;if(u!==void 0&&(typeof u!="string"||u.trim().length===0))return{ok:!1,error:"model must be a non-empty string when set"};let p=i.enabled;return p!==void 0&&typeof p!="boolean"?{ok:!1,error:"enabled must be true or false"}:{ok:!0,role:{name:e,description:s.trim(),...typeof u=="string"?{model:u.trim()}:{},refs:a,scenarios:l,enabled:p!==!1,body:r.trim(),origin:n}}}function Oa(t,e){let r=new Map;for(let n of t)r.set(n.name,n);for(let n of e)r.set(n.name,n);return[...r.values()].sort((n,o)=>n.name<o.name?-1:n.name>o.name?1:0)}function La(t,e){return t.filter(r=>r.enabled&&r.scenarios.includes(e))}var si,ja,CA,PA,rd=x(()=>{"use strict";si=["plan_review","code_review","council"],ja=/^[a-z][a-z0-9-]{1,39}$/,CA=10,PA=300});function Ma(t){return nd.includes(t)}function Da(t){return`prompts/${t}.md`}var nd,od=x(()=>{"use strict";nd=["analysis","analyze","backfill","build","chat","code-review","code-review-external","code-review-fix","council","draft","estimate","implement","index","observer","resolve-conflict","review-comment","rework","testing"]});function Ba(t){if(!Ua.test(t.name))return{ok:!1,error:`skill directory name must match ${Ua}`};if(t.body.trim().length===0)return{ok:!1,error:"SKILL.md has no body \u2014 the body IS the procedure"};let e=t.frontmatter;if(!e||typeof e!="object"||Array.isArray(e))return{ok:!1,error:"SKILL.md has no frontmatter block"};let r=e.description;return typeof r!="string"||r.trim().length===0?{ok:!1,error:"description is required \u2014 it is what decides when the skill fires"}:r.length>300?{ok:!1,error:"description must be \u2264 300 characters"}:{ok:!0,skill:{name:t.name,description:r.trim()}}}function Fa(t,e,r){let n=new Map;for(let o of[...t,...e,...r])n.set(o.name,o);return[...n.values()].sort((o,i)=>o.name<i.name?-1:o.name>i.name?1:0)}function sd(t){let e=t.trim(),r=e.lastIndexOf("@"),n=r===-1?e:e.slice(0,r),o=r===-1?"":e.slice(r+1).trim();if(!Db.test(n))return{ok:!1,error:`"${t}": expected <owner>/<repo>[@<40-hex sha>]`};let i=id.find(s=>s.repo.toLowerCase()===n.toLowerCase());return o&&!Ub.test(o)?{ok:!1,error:`"${t}": pin to a full 40-character commit sha \u2014 a branch or tag can change under you`}:!i&&!o?{ok:!1,error:`"${t}": a third-party marketplace must be pinned to a commit (<owner>/<repo>@<sha>). Its skills run beside your code with the agent's token.`}:{ok:!0,source:{repo:n,sha:o,name:i?.name??n.replace("/","-").toLowerCase(),official:!!i}}}function Bb(t){let e=[],r=[],n=new Set;for(let o of t){if(!o.trim())continue;let i=sd(o);if(!i.ok){r.push(i.error);continue}n.has(i.source.name)||(n.add(i.source.name),e.push(i.source))}return{sources:e,errors:r}}function Gb(t,e){let r=new Set(e.map(i=>i.name)),n={},o=[];for(let i of t){let s=i.trim();if(s){if(!Fb.test(s)||!r.has(s.slice(s.indexOf("@")+1))){o.push(s);continue}n[s]=!0}}return{enabled:n,unknown:o}}var Ua,jA,id,Db,Ub,Fb,ad=x(()=>{"use strict";Ua=/^[a-z][a-z0-9-]{1,39}$/,jA=300;id=[{repo:"anthropics/skills",name:"anthropic-agent-skills"},{repo:"anthropics/claude-plugins-official",name:"claude-plugins-official"}],Db=/^[A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*$/,Ub=/^[0-9a-f]{40}$/;Fb=/^[A-Za-z0-9][\w.-]*@[A-Za-z0-9][\w.-]*$/});function cd(t,e){if(t==null)return[];if(!Array.isArray(t)||t.length>e)return null;let r=[];for(let n of t){if(typeof n!="string"||n.trim().length===0)return null;r.push(n.trim())}return r}function Kb(t,e){if(!t||typeof t!="object"||Array.isArray(t))return{ok:!1,error:"queue plan must be a JSON object"};let r=new Set(e),n=t,o=cd(n.order,e.length);if(o===null)return{ok:!1,error:"order must be a list of task keys"};for(let f of o)if(!r.has(f))return{ok:!1,error:`order names ${f}, which is not in this batch`};if(new Set(o).size!==o.length)return{ok:!1,error:"order repeats a task key"};let i=e.filter(f=>!o.includes(f));if(o.length>0&&i.length>0)return{ok:!1,error:`order omits ${i.join(", ")}`};let s=n.tasks,a=[];if(s!=null){if(!Array.isArray(s))return{ok:!1,error:"tasks must be a list"};for(let f of s){if(!f||typeof f!="object")return{ok:!1,error:"each task entry must be an object"};let g=f,k=typeof g.taskKey=="string"?g.taskKey.trim():"";if(!r.has(k))return{ok:!1,error:`tasks names ${k||"(empty)"}, which is not in this batch`};let h=cd(g.after,e.length);if(h===null)return{ok:!1,error:`${k}: after must be a list of task keys`};for(let $ of h){if(!r.has($))return{ok:!1,error:`${k}: after names ${$}, not in this batch`};if($===k)return{ok:!1,error:`${k}: cannot come after itself`}}let w=typeof g.decisions=="string"?g.decisions.trim():"";a.push({taskKey:k,decisions:w.slice(0,4e3),after:h})}}let c=[],l=n.conflicts;if(Array.isArray(l))for(let f of l){if(!f||typeof f!="object")continue;let g=f,k=typeof g.taskKey=="string"?g.taskKey.trim():"",h=typeof g.adr=="string"?g.adr.trim():"",w=typeof g.detail=="string"?g.detail.trim():"";!r.has(k)||!w||c.push({taskKey:k,adr:h,detail:w.slice(0,4e3)})}let u=[],p=n.related;if(Array.isArray(p))for(let f of p){if(!f||typeof f!="object")continue;let g=f,k=typeof g.taskKey=="string"?g.taskKey.trim():"",h=typeof g.detail=="string"?g.detail.trim():"";!k||!h||u.push({taskKey:k,detail:h.slice(0,4e3)})}let d=typeof n.summary=="string"?n.summary.trim().slice(0,4e3):"",m=n.deferBehind===!0;return{ok:!0,plan:{order:o,tasks:a,conflicts:c,related:u,summary:d,deferBehind:m}}}var OA,LA,ld=x(()=>{"use strict";OA=4e3,LA=4e3});function Hb(t,e){if(!t||typeof t!="object"||Array.isArray(t))return{ok:!1,error:"council verdict must be a JSON object"};let r=t,n=r.unresolved===!0,o=typeof r.fork=="string"?r.fork.trim().slice(0,4e3):"";if(n)return o?{ok:!0,verdict:{answers:[],unresolved:!0,fork:o}}:{ok:!1,error:"an unresolved verdict must describe the fork"};let i=r.answers;if(!Array.isArray(i))return{ok:!1,error:"answers must be a list"};if(i.length!==e.length)return{ok:!1,error:`expected ${e.length} answer(s), got ${i.length}`};let s=[];for(let[a,c]of i.entries()){if(!c||typeof c!="object")return{ok:!1,error:`answer ${a+1} must be an object`};let l=c,u=typeof l.answer=="string"?l.answer.trim():"";if(!u)return{ok:!1,error:`answer ${a+1} is empty`};s.push({question:typeof l.question=="string"?l.question.trim():e[a],answer:u.slice(0,4e3),rationale:typeof l.rationale=="string"?l.rationale.trim().slice(0,4e3):""})}return{ok:!0,verdict:{answers:s,unresolved:!1,fork:""}}}var DA,ud=x(()=>{"use strict";DA=4e3});function Yb(t){let e=t.replace(/^#+\s*/,"").trim();for(let r of Wb)if(r.re.test(e))return{kind:r.kind,letter:r.letter};return null}function Ga(t){let e=[],r=new Map,n="",o=null,i=null;for(let a of t.split(`
7
+ `}function ua(t){return kr(_u(t))}function da(t){return kr(ju(t))}function Wr(t){return kr(Nu(t))}var Oe,ub,db,pb,fb,Qo,hr,Cu,ia,Pu,mb,nt,sa,aa,ca,ti,hb,la,wr,yb,pa=x(()=>{"use strict";Oe=2,ub="model",db="model/README.md",pb="model/facts",fb="model/derived",Qo="model/derived/INDEX.yaml",hr="model/derived/relates.yaml";Cu=["system","container","component","code","task","adr"],ia=["contains","touched_by","correlates","relates","references","depends_on"],Pu=/^e_[0-9a-f]{8}$/;mb=["system","task","adr"];nt={windowCommits:1e3,commitFileCap:30,supportMin:5,jaccardMinPct:25,halfLifeDays:270,topK:8};sa=2,aa=5,ca=50,ti=2e3,hb=5e4,la={touched_by:.8,references:.7,relates:.6,correlates:.4,contains:.3,depends_on:.5},wr={budgetTokens:4e3,activationCutoff:.05,topKPerNode:8,nodeCap:200};yb=/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/});function wb(t){return t==="DONE"}function kb(t){return t==="AWAITING_EXTERNAL_FIX"?!1:fa.indexOf(t)>=fa.indexOf("IMPLEMENTING")}var fa,Du=x(()=>{"use strict";fa=["BACKLOG","QUEUED","INTAKE","AWAITING_APPROVAL","ANALYZING","ESTIMATING","AWAITING_ANSWER","REVIEW","READY","IMPLEMENTING","BUILD","CODE_REVIEW","TESTING","AWAITING_EXTERNAL_FIX","READY_TO_APPLY","APPLYING","AWAITING_CLUSTER","TRACKING","NEEDS_MANUAL","DONE"]});function $b(t){for(let e of ma)if(e.phases.includes(t))return e.id;return null}function vb(t){for(let e of Uu)if(e.phases.includes(t))return e.id;return null}var ma,bb,Uu,Bu=x(()=>{"use strict";ma=[{id:"intake",label:"Intake",phases:["INTAKE"]},{id:"analysis",label:"Analysis",phases:["ANALYZING","ESTIMATING"]},{id:"ready",label:"Ready",phases:["READY"]},{id:"implementation",label:"Implementation",phases:["IMPLEMENTING","BUILD"]},{id:"delivery",label:"Delivery",phases:["READY_TO_APPLY","APPLYING","AWAITING_CLUSTER"]}],bb=ma.flatMap(t=>t.phases),Uu=[{id:"review",label:"Review / tracking",phases:["CODE_REVIEW","TESTING","TRACKING"]},{id:"attention",label:"Need your attention",phases:["NEEDS_MANUAL","AWAITING_APPROVAL","AWAITING_EXTERNAL_FIX","AWAITING_ANSWER","REVIEW"]},{id:"backlog",label:"Backlog / queue",phases:["BACKLOG","QUEUED"]}]});function xb(t){return Fu.includes(t)?"planning":"implementation"}function Ht(){return{inputTokens:0,outputTokens:0,cacheReadInputTokens:0,cacheCreationInputTokens:0,totalCostUsd:0,model:"",numTurns:0,durationMs:0}}var ha,Fu,Sb,ga=x(()=>{"use strict";ha=["estimate","analyze","implement","resolve-conflict","rework","draft","build","code-review","index","backfill","analysis","chat","observer","council","testing"],Fu=["draft","analysis","chat","observer","council"];Sb=1});function Gu(t,e){return e.toLowerCase().includes(t.toLowerCase())}function ka(t){let e=t.filter(o=>o&&typeof o.id=="string"&&o.id.trim().length>0);if(e.length===0||Yu.every(o=>e.some(i=>Gu(o,i.id))))return null;let n=[...e].sort((o,i)=>{let s=o.createdAt??"",a=i.createdAt??"";return s!==a?s<a?1:-1:o.id<i.id?1:-1});for(let o of qu){let i=n.find(s=>Gu(o,s.id));if(i)return i.id}return n[0].id}function qr(){return{default:null,roles:{}}}function Eb(t,e){let r=t?.roles?.[e];return typeof r=="string"&&r.trim().length>0?r.trim():t?.default&&t.default.trim().length>0?t.default.trim():ro[e]??Wu}function Tb(t){let e=t?.provider;return typeof e=="string"&&e.trim().length>0?e.trim():Xe}function Rb(t){let e=qr();if(!t||typeof t!="object")return e;let r=t.llm;if(!r||typeof r!="object")return e;let n=r.provider;typeof n=="string"&&n.trim().length>0&&(e.provider=n.trim());let o=r.models;if(!o||typeof o!="object")return e;for(let[i,s]of Object.entries(o))typeof s!="string"||s.trim().length===0||(i==="default"?e.default=s.trim():e.roles[i]=s.trim());return e}function Ib(t){let e=typeof t.provider=="string"&&t.provider.trim().length>0&&t.provider.trim()!==Xe;if(t.default===null&&Object.keys(t.roles).length===0&&!e)return null;let{provider:r,...n}=t;return JSON.stringify(e?{provider:r.trim(),...n}:n)}function Cb(t){if(!t)return qr();try{let e=JSON.parse(t);if(!e||typeof e!="object")return qr();let r=e,n=qr();typeof r.provider=="string"&&r.provider.trim().length>0&&(n.provider=r.provider.trim()),typeof r.default=="string"&&(n.default=r.default);let o=r.roles;if(o&&typeof o=="object")for(let[i,s]of Object.entries(o))typeof s=="string"&&(n.roles[i]=s);return n}catch{return qr()}}var Xe,ya,Pe,to,ni,oi,Ku,Hu,wa,ro,Wu,qu,Yu,ba=x(()=>{"use strict";ga();Xe="claude",ya=[Xe],Pe="opus",to="sonnet",ni="haiku",oi=[Pe,to,ni],Ku="build-discovery",Hu=[Ku],wa=[...ha,...Hu],ro={analyze:Pe,implement:Pe,"resolve-conflict":Pe,rework:Pe,estimate:to,build:ni,"build-discovery":Pe,"code-review":Pe,draft:to,index:Pe,backfill:Pe,analysis:Pe,chat:Pe,observer:Pe,council:Pe,testing:Pe},Wu=Pe,qu=[Pe,to,ni],Yu=Array.from(new Set(Object.values(ro)))});function Ot(t){return Pb.has(t)?!0:Ab.some(e=>t.startsWith(e))}function ii(t,e){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e} must be a mapping`);return t}function br(t,e){if(t!=null){if(typeof t!="string")throw new Error(`${e} must be a string`);return t}}function va(t,e){if(t!=null){if(typeof t!="number"||!Number.isFinite(t))throw new Error(`${e} must be a number`);return t}}function Sa(t,e){let r=ii(e,"action definition"),n=t.replace(/\.(yml|yaml)$/i,""),o=br(r.id,"id")??n;if(!$a.test(o))throw new Error(`id must match ${$a} (got "${o}")`);if(o!==n)throw new Error(`id "${o}" must match the file name ("${n}")`);let i=br(r.title,"title")?.trim()||o,s;if(r.env!==void 0&&r.env!==null){let p=ii(r.env,"env");s={};for(let[d,m]of Object.entries(p)){if(!Je.test(d))throw new Error(`env name "${d}" must match ${Je}`);if(typeof m!="string"&&typeof m!="number"&&typeof m!="boolean")throw new Error(`env.${d} must be a scalar`);s[d]=String(m)}}let a,c=r.params;if(c!=null){if(!Array.isArray(c))throw new Error("params must be a list");if(c.length>zu)throw new Error(`too many params (max ${zu})`);let p=new Set;a=c.map((d,m)=>_b(d,m,p))}let l=r.steps;if(!Array.isArray(l)||l.length===0)throw new Error("steps must be a non-empty list");if(l.length>Vu)throw new Error(`too many steps (max ${Vu})`);let u=l.map((p,d)=>{let m=ii(p,`steps[${d}]`),f=br(m.run,`steps[${d}].run`);if(!f||f.trim().length===0)throw new Error(`steps[${d}].run is required`);let g=br(m.name,`steps[${d}].name`),k=va(m.timeout_sec,`steps[${d}].timeout_sec`);if(k!==void 0&&(!Number.isInteger(k)||k<=0))throw new Error(`steps[${d}].timeout_sec must be a positive integer`);return{run:f,...g?{name:g}:{},...k!==void 0?{timeout_sec:k}:{}}});return{id:o,title:i,...s?{env:s}:{},...a?{params:a}:{},steps:u}}function _b(t,e,r){let n=ii(t,`params[${e}]`),o=br(n.name,`params[${e}].name`);if(!o||!Je.test(o))throw new Error(`params[${e}].name must match ${Je}`);if(r.has(o))throw new Error(`duplicate param "${o}"`);r.add(o);let i=n.type;if(i!=="string"&&i!=="enum"&&i!=="number"&&i!=="boolean")throw new Error(`params[${e}].type must be string | enum | number | boolean`);let s;if(i==="enum"){let m=n.enum;if(!Array.isArray(m)||m.length===0||!m.every(f=>typeof f=="string"))throw new Error(`params[${e}].enum must be a non-empty string list`);s=m}let a=br(n.label,`params[${e}].label`),c=br(n.help,`params[${e}].help`),l=n.required===!0,u=va(n.min,`params[${e}].min`),p=va(n.max,`params[${e}].max`),d=n.default;if(d!=null&&typeof d!="string"&&typeof d!="number"&&typeof d!="boolean")throw new Error(`params[${e}].default must be a scalar`);return{name:o,type:i,...a?{label:a}:{},...c?{help:c}:{},...l?{required:!0}:{},...s?{enum:s}:{},...u!==void 0?{min:u}:{},...p!==void 0?{max:p}:{},...d!=null?{default:d}:{}}}function Ea(t,e){let r=t.params??[],n=new Map(r.map(i=>[i.name,i]));for(let i of Object.keys(e))if(!n.has(i))return{ok:!1,error:`unknown param: ${i}`};let o={};for(let i of r){let s=e[i.name];if(s==null||typeof s=="string"&&s.trim()==="")if(i.default!==void 0)s=i.default;else{if(i.required)return{ok:!1,error:`${i.name} is required`};continue}switch(i.type){case"string":{if(typeof s!="string")return{ok:!1,error:`${i.name} must be a string`};o[i.name]=s;break}case"enum":{if(typeof s!="string"||!(i.enum??[]).includes(s))return{ok:!1,error:`${i.name} must be one of: ${(i.enum??[]).join(", ")}`};o[i.name]=s;break}case"number":{let a=typeof s=="number"?s:typeof s=="string"?Number(s):NaN;if(!Number.isFinite(a))return{ok:!1,error:`${i.name} must be a number`};if(i.min!==void 0&&a<i.min)return{ok:!1,error:`${i.name} must be \u2265 ${i.min}`};if(i.max!==void 0&&a>i.max)return{ok:!1,error:`${i.name} must be \u2264 ${i.max}`};o[i.name]=a;break}case"boolean":{let a=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:null;if(a===null)return{ok:!1,error:`${i.name} must be a boolean`};o[i.name]=a;break}}}return{ok:!0,values:o}}var Je,Pb,Ab,xa,$a,zu,Vu,Ta=x(()=>{"use strict";Je=/^[A-Z][A-Z0-9_]*$/,Pb=new Set(["GH_TOKEN","GITHUB_TOKEN","GITLAB_TOKEN"]),Ab=["BITBUCKET_","YOUTRACK_","CLAUDE_","INPUT_"];xa=600,$a=/^[a-z0-9-]+$/,zu=32,Vu=64});function Xu(){return{primary:$e,context:$e,tasks:$e,docs:$e,code_comments:$e,chat:$e,code_review:$e}}function Ju(t){return!t||t.trim().length===0||t.trim().toLowerCase()===$e}function jb(t){if(typeof t!="string")return $e;let e=t.trim().replace(/\s+/g," ");return e.length===0||e.length>40||e.toLowerCase()===$e?$e:e}function Nb(t){let e=Xu();if(!t||typeof t!="object")return e;let r=t.language;if(!r||typeof r!="object"||Array.isArray(r))return e;let n=r;for(let o of no)e[o]=jb(n[o]);return e}function Ob(t){return no.every(e=>Ju(t[e]))}var $e,no,Yr,oo,Ra=x(()=>{"use strict";$e="auto",no=["primary","context","tasks","docs","code_comments","chat","code_review"],Yr=["English","Russian","German","Spanish","French","Portuguese","Italian","Chinese","Japanese","Korean"],oo=40});function Aa(t=Zu){let e=[];for(let r of t)e.push(...r.fields),r.groups&&e.push(...Aa(r.groups));return e}function Qu(t,e){let r=JSON.stringify(e);return Aa().find(n=>n.file===t&&JSON.stringify(n.path)===r)}function _a(t){let e=Qu(t.file,t.path);if(!e)return{ok:!1,error:`unknown setting path: ${t.file}:${t.path.join(".")}`};let r=t.value,n=e.type==="model"||e.type==="enum"||e.type==="string";if(r===null||n&&typeof r=="string"&&r.trim().length===0)return e.nullable?{ok:!0,field:e,value:null}:{ok:!1,error:`${e.id} cannot be cleared`};switch(e.type){case"model":case"string":{if(typeof r!="string")return{ok:!1,error:`${e.id} must be a string`};let i=r.trim();return e.type==="string"&&e.mustContain&&!i.includes(e.mustContain)?{ok:!1,error:`${e.id} must contain "${e.mustContain}"`}:e.maxLength!==void 0&&i.length>e.maxLength?{ok:!1,error:`${e.id} must be \u2264 ${e.maxLength} chars`}:{ok:!0,field:e,value:i}}case"enum":{if(typeof r!="string")return{ok:!1,error:`${e.id} must be a string`};let i=r.trim();return e.suggestions?.includes(i)?{ok:!0,field:e,value:i}:{ok:!1,error:`${e.id} must be one of: ${(e.suggestions??[]).join(", ")}`}}case"number":return typeof r!="number"||!Number.isFinite(r)?{ok:!1,error:`${e.id} must be a number`}:!e.float&&!Number.isInteger(r)?{ok:!1,error:`${e.id} must be an integer`}:e.min!==void 0&&r<e.min?{ok:!1,error:`${e.id} must be \u2265 ${e.min}`}:e.max!==void 0&&r>e.max?{ok:!1,error:`${e.id} must be \u2264 ${e.max}`}:{ok:!0,field:e,value:r};case"boolean":return typeof r!="boolean"?{ok:!1,error:`${e.id} must be a boolean`}:{ok:!0,field:e,value:r};case"string_list":{if(!Array.isArray(r))return{ok:!1,error:`${e.id} must be a list`};let i=r.map(s=>typeof s=="string"?s.trim():"").filter(s=>s.length>0);return i.length===0?e.nullable?{ok:!0,field:e,value:null}:{ok:!1,error:`${e.id} must be a non-empty list`}:{ok:!0,field:e,value:i}}case"string_map":{if(typeof r!="object"||r===null||Array.isArray(r))return{ok:!1,error:`${e.id} must be a name\u2192value map`};let i=Object.entries(r);if(i.length===0)return e.nullable?{ok:!0,field:e,value:null}:{ok:!1,error:`${e.id} must be a non-empty map`};if(i.length>Ia)return{ok:!1,error:`${e.id} must have \u2264 ${Ia} entries`};let s={};for(let[a,c]of i){if(!Je.test(a))return{ok:!1,error:`${e.id}: name "${a}" must match ${Je}`};if(Ot(a))return{ok:!1,error:`${e.id}: name "${a}" is reserved`};if(typeof c!="string")return{ok:!1,error:`${e.id}: value of "${a}" must be a string`};if(c.length>Ca)return{ok:!1,error:`${e.id}: value of "${a}" must be \u2264 ${Ca} chars`};s[a]=c}return{ok:!0,field:e,value:s}}}}var Lb,Mb,Ia,Ca,Pa,Zu,ed=x(()=>{"use strict";Ta();ba();pa();Ra();Lb={primary:"Primary language",context:"Context documents",tasks:"Tracker issues",docs:"Repo documentation",code_comments:"Code comments",chat:"Agent chat",code_review:"Code review comments"},Mb={primary:"The project's main language (agent status notes ride it). Empty \u21D2 auto.",context:"Knowledge, ADRs and task artifacts in the Context Repo. Empty \u21D2 auto.",tasks:"Issue titles/bodies the agent drafts. Empty \u21D2 auto.",docs:"Documentation changes in the project repos. Empty \u21D2 auto.",code_comments:"New code comments the agent writes. Empty \u21D2 auto.",chat:"The interactive task-drafting chat. Empty/auto \u21D2 mirror the user's messages.",code_review:"Review findings and PR comments. Empty \u21D2 follows the tracker-issues language."},Ia=64,Ca=2e3,Pa=2e3,Zu=[{id:"branch",label:"Branch",help:"Task-branch naming.",fields:[{id:"branch.pattern",file:"project.yaml",path:["branch","pattern"],type:"string",label:"Task-branch pattern",nullable:!0,mustContain:"<TASK_ID>",help:"Template for the per-task branch name. Must contain the <TASK_ID> placeholder. Empty \u21D2 default codepipe/<TASK_ID>."}]},{id:"llm",label:"LLM",fields:[{id:"llm.provider",file:"regimen.yaml",path:["llm","provider"],type:"enum",label:"Provider",nullable:!1,suggestions:[...ya],help:"LLM backend for this project. Currently only claude is available."}],groups:[{id:"llm.models",label:"Models by role",help:"Model per pipeline stage. Empty \u21D2 the role's recommended default applies.",fields:[{id:"llm.models.default",file:"regimen.yaml",path:["llm","models","default"],type:"model",label:"default (catch-all)",nullable:!0,suggestions:[...oi],help:"Overrides the recommended defaults for every role not listed below."},...wa.map(t=>({id:`llm.models.${t}`,file:"regimen.yaml",path:["llm","models",t],type:"model",label:t,nullable:!0,suggestions:[...oi],help:`recommended: ${ro[t]}`}))]}]},{id:"apply.style",label:"Commits & PRs",help:"Instructions for the AI agent on how to write commit messages and PR descriptions. Empty \u21D2 built-in templates.",fields:[{id:"apply.commit_style",file:"project.yaml",path:["apply","commit_style"],type:"string",label:"Commit message style",nullable:!0,multiline:!0,maxLength:Pa,help:'e.g. "English, imperative mood, first line \u2264 72 chars, start with the issue key". Empty \u21D2 "<KEY>: <task title>".'},{id:"apply.pr_style",file:"project.yaml",path:["apply","pr_style"],type:"string",label:"PR description style",nullable:!0,multiline:!0,maxLength:Pa,help:`e.g. "implementation details, bullet list of what was done, in the tracker's language". Empty \u21D2 the default PR body.`}]},{id:"apply.delivery",label:"Delivery & merge",help:"How a finished change reaches the repository: with or without a pull request, and who merges it.",fields:[{id:"apply.pull_request",file:"project.yaml",path:["apply","pull_request"],type:"boolean",label:"Open a pull request",nullable:!1,help:"On (default): the task branch is pushed and a pull request is opened \u2014 the change is reviewable in the git host and keeps a history of review comments. Off: no PR at all; the branch is merged into the default branch directly, and the agent's review remarks live only in the dashboard and the Context Repo."},{id:"apply.done",file:"project.yaml",path:["apply","done"],type:"enum",label:"Task is done when",nullable:!1,suggestions:["merge","branch"],help:"merge (default): the task is finished only once its change lands in the default branch. branch: the task ends at the pushed branch (plus the PR, if enabled) and nothing is merged for you."},{id:"apply.auto_merge",file:"project.yaml",path:["apply","auto_merge"],type:"enum",label:"Auto-merge pull requests",nullable:!1,suggestions:["off","on_ci_green"],help:"Applies to the pull-request path only. off (default): the merge waits for you (Approve on the task card). on_ci_green: as soon as the PR is open, conflict-free and its CI is green, CodePipe merges it \u2014 changes reach the default branch with no further review from you. Requires full automation; branch protection on the host still applies (a refused merge parks the task). Without pull requests, full automation merges the branch itself and this switch does not apply."}]},{id:"variables",label:"Variables",help:"Non-secret env vars for custom actions (RUN tab). Secrets go via the sealed Secrets form on the Tokens section instead.",fields:[{id:"variables",file:"project.yaml",path:["variables"],type:"string_map",label:"Variables",nullable:!0,help:"NAME=value pairs, one per line. Names are env-style (A-Z, 0-9, _); reserved credential names are refused."}]},{id:"testing",label:"Testing",help:"An optional phase after code review: writes the test plan you run in the morning and reports what it could verify.",fields:[{id:"testing.enabled",file:"regimen.yaml",path:["testing","enabled"],type:"boolean",nullable:!1,label:"Run the testing phase",help:"Off by default. When on, a task passing code review goes through a test pass before the PR: it derives TESTPLAN.md from the plan's requirements and reports per requirement what it could verify. A requirement it finds broken sends the change back for a fix (bounded below)."},{id:"testing.max_iterations",file:"regimen.yaml",path:["testing","max_iterations"],type:"number",nullable:!0,min:1,max:10,label:"Fix rounds before stopping",help:"How many times a failed test pass may send the change back before the task waits for you. Empty \u21D2 2."}]},{id:"code_review",label:"Code review",help:"The review of a developer's branch, triggered by moving the tracker issue into the review column.",fields:[{id:"code_review.external.verification",file:"regimen.yaml",path:["code_review","external","verification"],type:"boolean",nullable:!1,label:"Verification round (second reviewer)",help:"Off by default. When on, the first review verdict is checked by a second independent pass that confirms, refutes or re-grades the findings before anything reaches the card or the PR. Roughly doubles the review cost."}]},{id:"skills",label:"Skills",help:"Reusable procedures the agent can invoke instead of improvising. Only their names and one-line descriptions sit in the prompt; the steps load when a skill is used.",fields:[{id:"skills.from_bundled",file:"regimen.yaml",path:["skills","from_bundled"],type:"boolean",nullable:!1,label:"Use the skills shipped with CodePipe",help:"On by default. General procedures maintained with the product."},{id:"skills.from_context_repo",file:"regimen.yaml",path:["skills","from_context_repo"],type:"boolean",nullable:!1,label:"Use this project's skills",help:"On by default. Skills the team writes in the context repository under `skills/<name>/SKILL.md`. These override a bundled skill of the same name."},{id:"skills.from_project_repo",file:"regimen.yaml",path:["skills","from_project_repo"],type:"boolean",nullable:!1,label:"Use the code repository's skills",help:"On by default. `.claude/skills/` inside the project repositories \u2014 the skills your developers already use locally. These win over both other sources."}]},{id:"gates",label:"Gates",help:"Approval gate before the pipeline starts (on by default; orthogonal to automation).",fields:[{id:"gates.require_approval",file:"regimen.yaml",path:["gates","require_approval"],type:"boolean",label:"Require approval before start",nullable:!1,help:"When on (default), a task taken from Develop waits in the QUEUE for a single Confirm before the pipeline starts \u2014 the Confirm pulls in dependency closure and topologically orders the queue. Off \u21D2 conveyor: the task starts the pipeline immediately."}]},{id:"automation",label:"Automation",help:"How far the pipeline advances the G1\u2013G4 gates without a manual Run/Approve. Independent of the approval gate above.",fields:[{id:"automation.level",file:"regimen.yaml",path:["automation","level"],type:"enum",label:"Automation level",nullable:!1,suggestions:["assisted","full"],help:"assisted \u21D2 manual Run/Approve at each of G1\u2013G4; full \u21D2 gates auto-pass."}]},{id:"language",label:"Language",help:"Languages the agent writes in, per area. Empty \u21D2 auto: mirror the language of the user's material.",fields:no.map(t=>({id:`language.${t}`,file:"project.yaml",path:["language",t],type:"string",label:Lb[t],nullable:!0,maxLength:40,suggestions:t==="chat"?[$e,...Yr]:[...Yr],help:Mb[t]}))},{id:"context.model",label:"Project map",help:"Parameters of the project map (built from git history by the CLI). Empty fields keep the defaults.",fields:[{id:"context.model.enabled",file:"regimen.yaml",path:["context","model","enabled"],type:"boolean",label:"Enable in the pipeline",nullable:!1,help:"When on, agents are asked to record intent annotations and (once available) receive an assembled context pack. Off \u21D2 the pipeline ignores the map entirely."},{id:"context.model.prompt.pack",file:"regimen.yaml",path:["context","model","prompt","pack"],type:"boolean",nullable:!1,label:"Give agents the context pack",help:"On by default. The assembled pack costs up to ~4000 tokens on every task of the analyze / estimate / implement / rework roles. Turning it off keeps the map building and stops the spend \u2014 the way to see what the pack is actually worth on this project."},{id:"context.model.prompt.annotations",file:"regimen.yaml",path:["context","model","prompt","annotations"],type:"boolean",nullable:!1,label:"Ask agents for intent annotations",help:"On by default. Adds the annotations block to the implement and rework prompts \u2014 the layer that records WHY the code is shaped this way. Cheap, and worth accumulating even while the pack is off."},{id:"context.index.hub",file:"regimen.yaml",path:["context","index","hub"],type:"enum",label:"Search index on the server",nullable:!0,suggestions:["off","metadata"],help:"off (default): search runs on your machine, nothing is uploaded. metadata: paths, labels and task texts (never code) are mirrored to the server so search and structure stay available while your machine is offline. Switching back to off deletes the mirrored rows."},{id:"context.model.issue_key_pattern",file:"regimen.yaml",path:["context","model","issue_key_pattern"],type:"string",label:"Issue-key pattern (regex)",nullable:!0,maxLength:200,help:"Regex that finds tracker issue keys in commit subjects when mining task events from history. Empty \u21D2 derived from the tracker project key (e.g. DEV-\\d+)."},{id:"context.model.cochange.window_commits",file:"regimen.yaml",path:["context","model","cochange","window_commits"],type:"number",label:"History window (commits)",nullable:!0,min:50,max:5e4,help:`How many commits back from the build commit are mined. Default ${nt.windowCommits}.`},{id:"context.model.cochange.commit_file_cap",file:"regimen.yaml",path:["context","model","cochange","commit_file_cap"],type:"number",label:"Commit size cap (files)",nullable:!0,min:2,max:500,help:`Commits touching more files are ignored as noise. Default ${nt.commitFileCap}.`},{id:"context.model.cochange.support_min",file:"regimen.yaml",path:["context","model","cochange","support_min"],type:"number",label:"Minimum co-occurrences",nullable:!0,min:1,max:100,help:`A pair of files must change together at least this many times. Default ${nt.supportMin}.`},{id:"context.model.cochange.jaccard_min_pct",file:"regimen.yaml",path:["context","model","cochange","jaccard_min_pct"],type:"number",label:"Minimum Jaccard (%)",nullable:!0,min:0,max:100,help:`Overlap threshold: |A\u2229B| / |A\u222AB| of the files' commit sets, in percent. Default ${nt.jaccardMinPct}.`},{id:"context.model.cochange.half_life_days",file:"regimen.yaml",path:["context","model","cochange","half_life_days"],type:"number",label:"Time-decay half-life (days)",nullable:!0,min:1,max:3650,help:`A commit this old counts half as much. Default ${nt.halfLifeDays} (~9 months).`},{id:"context.model.cochange.top_k",file:"regimen.yaml",path:["context","model","cochange","top_k"],type:"number",label:"Edges per file (top-k)",nullable:!0,min:1,max:64,help:`Only the k strongest co-change edges of a file survive \u2014 bounds graph density whatever the thresholds. Default ${nt.topK}.`}]},{id:"rate_limit",label:"Rate limit",help:"Automatic project pause as the LLM usage window fills up.",fields:[{id:"rate_limit.auto_pause.enabled",file:"project.yaml",path:["rate_limit","auto_pause","enabled"],type:"boolean",nullable:!1,label:"Pause the project near the limit",help:"On (default): when window utilization reaches the threshold, the project is paused (same pause as the manual one) and you get an email \u2014 the remaining window stays available for your own work. Off: agents keep working until the provider actually runs out."},{id:"rate_limit.auto_pause.threshold",file:"project.yaml",path:["rate_limit","auto_pause","threshold"],type:"number",float:!0,nullable:!0,min:.05,max:1,label:"Pause threshold (share of the window)",help:"Fraction of the usage window at which the pause fires; the rest (1 \u2212 threshold) is your manual-work reserve. Empty \u21D2 0.75."}]},{id:"context.job_logs",label:"Job transcripts",help:"Whether the raw agent transcript of each job is kept in the Context Repo.",fields:[{id:"context.job_logs.enabled",file:"regimen.yaml",path:["context","job_logs","enabled"],type:"boolean",label:"Keep transcripts in the Context Repo",nullable:!1,help:"Off (default): the transcript is discarded after the run \u2014 nothing lands in the Context Repo. On: each job's raw transcript is committed as tasks/<KEY>/logs/job-<id>.jsonl for post-mortem debugging."}]}]});function td(t){if(t==null)return[];if(!Array.isArray(t))return null;let e=[];for(let r of t){if(typeof r!="string"||r.trim().length===0)return null;e.push(r.trim())}return e}function Na(t){let{name:e,body:r,origin:n}=t;if(!ja.test(e))return{ok:!1,error:`role name must match ${ja} (got "${e}")`};if(r.trim().length===0)return{ok:!1,error:"role body is empty \u2014 the body IS the role's prompt"};let o=t.frontmatter;if(o==null||typeof o!="object"||Array.isArray(o))return{ok:!1,error:"missing or malformed frontmatter block"};let i=o,s=i.description;if(typeof s!="string"||s.trim().length===0)return{ok:!1,error:"description is required (one line: what this role looks for)"};if(s.length>300)return{ok:!1,error:"description must be \u2264 300 characters"};let a=td(i.refs);if(a===null)return{ok:!1,error:"refs must be a list of non-empty paths"};if(a.length>10)return{ok:!1,error:"refs must list at most 10 files \u2014 a role is a narrow view"};for(let d of a)if(d.startsWith("/")||d.includes(".."))return{ok:!1,error:`ref "${d}" must be a path inside the Context Repo`};let c=td(i.scenarios);if(c===null)return{ok:!1,error:"scenarios must be a list"};let l=[];for(let d of c){if(!si.includes(d))return{ok:!1,error:`unknown scenario "${d}" \u2014 one of: ${si.join(", ")}`};l.includes(d)||l.push(d)}if(l.length===0)return{ok:!1,error:`scenarios must name at least one of: ${si.join(", ")}`};let u=i.model;if(u!==void 0&&(typeof u!="string"||u.trim().length===0))return{ok:!1,error:"model must be a non-empty string when set"};let p=i.enabled;return p!==void 0&&typeof p!="boolean"?{ok:!1,error:"enabled must be true or false"}:{ok:!0,role:{name:e,description:s.trim(),...typeof u=="string"?{model:u.trim()}:{},refs:a,scenarios:l,enabled:p!==!1,body:r.trim(),origin:n}}}function Oa(t,e){let r=new Map;for(let n of t)r.set(n.name,n);for(let n of e)r.set(n.name,n);return[...r.values()].sort((n,o)=>n.name<o.name?-1:n.name>o.name?1:0)}function La(t,e){return t.filter(r=>r.enabled&&r.scenarios.includes(e))}var si,ja,CA,PA,rd=x(()=>{"use strict";si=["plan_review","code_review","council"],ja=/^[a-z][a-z0-9-]{1,39}$/,CA=10,PA=300});function Ma(t){return nd.includes(t)}function Da(t){return`prompts/${t}.md`}var nd,od=x(()=>{"use strict";nd=["analysis","analyze","backfill","build","chat","code-review","code-review-external","code-review-fix","code-review-verify","council","draft","estimate","implement","index","observer","resolve-conflict","review-comment","rework","testing"]});function Ba(t){if(!Ua.test(t.name))return{ok:!1,error:`skill directory name must match ${Ua}`};if(t.body.trim().length===0)return{ok:!1,error:"SKILL.md has no body \u2014 the body IS the procedure"};let e=t.frontmatter;if(!e||typeof e!="object"||Array.isArray(e))return{ok:!1,error:"SKILL.md has no frontmatter block"};let r=e.description;return typeof r!="string"||r.trim().length===0?{ok:!1,error:"description is required \u2014 it is what decides when the skill fires"}:r.length>300?{ok:!1,error:"description must be \u2264 300 characters"}:{ok:!0,skill:{name:t.name,description:r.trim()}}}function Fa(t,e,r){let n=new Map;for(let o of[...t,...e,...r])n.set(o.name,o);return[...n.values()].sort((o,i)=>o.name<i.name?-1:o.name>i.name?1:0)}function sd(t){let e=t.trim(),r=e.lastIndexOf("@"),n=r===-1?e:e.slice(0,r),o=r===-1?"":e.slice(r+1).trim();if(!Db.test(n))return{ok:!1,error:`"${t}": expected <owner>/<repo>[@<40-hex sha>]`};let i=id.find(s=>s.repo.toLowerCase()===n.toLowerCase());return o&&!Ub.test(o)?{ok:!1,error:`"${t}": pin to a full 40-character commit sha \u2014 a branch or tag can change under you`}:!i&&!o?{ok:!1,error:`"${t}": a third-party marketplace must be pinned to a commit (<owner>/<repo>@<sha>). Its skills run beside your code with the agent's token.`}:{ok:!0,source:{repo:n,sha:o,name:i?.name??n.replace("/","-").toLowerCase(),official:!!i}}}function Bb(t){let e=[],r=[],n=new Set;for(let o of t){if(!o.trim())continue;let i=sd(o);if(!i.ok){r.push(i.error);continue}n.has(i.source.name)||(n.add(i.source.name),e.push(i.source))}return{sources:e,errors:r}}function Gb(t,e){let r=new Set(e.map(i=>i.name)),n={},o=[];for(let i of t){let s=i.trim();if(s){if(!Fb.test(s)||!r.has(s.slice(s.indexOf("@")+1))){o.push(s);continue}n[s]=!0}}return{enabled:n,unknown:o}}var Ua,jA,id,Db,Ub,Fb,ad=x(()=>{"use strict";Ua=/^[a-z][a-z0-9-]{1,39}$/,jA=300;id=[{repo:"anthropics/skills",name:"anthropic-agent-skills"},{repo:"anthropics/claude-plugins-official",name:"claude-plugins-official"}],Db=/^[A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*$/,Ub=/^[0-9a-f]{40}$/;Fb=/^[A-Za-z0-9][\w.-]*@[A-Za-z0-9][\w.-]*$/});function cd(t,e){if(t==null)return[];if(!Array.isArray(t)||t.length>e)return null;let r=[];for(let n of t){if(typeof n!="string"||n.trim().length===0)return null;r.push(n.trim())}return r}function Kb(t,e){if(!t||typeof t!="object"||Array.isArray(t))return{ok:!1,error:"queue plan must be a JSON object"};let r=new Set(e),n=t,o=cd(n.order,e.length);if(o===null)return{ok:!1,error:"order must be a list of task keys"};for(let f of o)if(!r.has(f))return{ok:!1,error:`order names ${f}, which is not in this batch`};if(new Set(o).size!==o.length)return{ok:!1,error:"order repeats a task key"};let i=e.filter(f=>!o.includes(f));if(o.length>0&&i.length>0)return{ok:!1,error:`order omits ${i.join(", ")}`};let s=n.tasks,a=[];if(s!=null){if(!Array.isArray(s))return{ok:!1,error:"tasks must be a list"};for(let f of s){if(!f||typeof f!="object")return{ok:!1,error:"each task entry must be an object"};let g=f,k=typeof g.taskKey=="string"?g.taskKey.trim():"";if(!r.has(k))return{ok:!1,error:`tasks names ${k||"(empty)"}, which is not in this batch`};let h=cd(g.after,e.length);if(h===null)return{ok:!1,error:`${k}: after must be a list of task keys`};for(let $ of h){if(!r.has($))return{ok:!1,error:`${k}: after names ${$}, not in this batch`};if($===k)return{ok:!1,error:`${k}: cannot come after itself`}}let w=typeof g.decisions=="string"?g.decisions.trim():"";a.push({taskKey:k,decisions:w.slice(0,4e3),after:h})}}let c=[],l=n.conflicts;if(Array.isArray(l))for(let f of l){if(!f||typeof f!="object")continue;let g=f,k=typeof g.taskKey=="string"?g.taskKey.trim():"",h=typeof g.adr=="string"?g.adr.trim():"",w=typeof g.detail=="string"?g.detail.trim():"";!r.has(k)||!w||c.push({taskKey:k,adr:h,detail:w.slice(0,4e3)})}let u=[],p=n.related;if(Array.isArray(p))for(let f of p){if(!f||typeof f!="object")continue;let g=f,k=typeof g.taskKey=="string"?g.taskKey.trim():"",h=typeof g.detail=="string"?g.detail.trim():"";!k||!h||u.push({taskKey:k,detail:h.slice(0,4e3)})}let d=typeof n.summary=="string"?n.summary.trim().slice(0,4e3):"",m=n.deferBehind===!0;return{ok:!0,plan:{order:o,tasks:a,conflicts:c,related:u,summary:d,deferBehind:m}}}var OA,LA,ld=x(()=>{"use strict";OA=4e3,LA=4e3});function Hb(t,e){if(!t||typeof t!="object"||Array.isArray(t))return{ok:!1,error:"council verdict must be a JSON object"};let r=t,n=r.unresolved===!0,o=typeof r.fork=="string"?r.fork.trim().slice(0,4e3):"";if(n)return o?{ok:!0,verdict:{answers:[],unresolved:!0,fork:o}}:{ok:!1,error:"an unresolved verdict must describe the fork"};let i=r.answers;if(!Array.isArray(i))return{ok:!1,error:"answers must be a list"};if(i.length!==e.length)return{ok:!1,error:`expected ${e.length} answer(s), got ${i.length}`};let s=[];for(let[a,c]of i.entries()){if(!c||typeof c!="object")return{ok:!1,error:`answer ${a+1} must be an object`};let l=c,u=typeof l.answer=="string"?l.answer.trim():"";if(!u)return{ok:!1,error:`answer ${a+1} is empty`};s.push({question:typeof l.question=="string"?l.question.trim():e[a],answer:u.slice(0,4e3),rationale:typeof l.rationale=="string"?l.rationale.trim().slice(0,4e3):""})}return{ok:!0,verdict:{answers:s,unresolved:!1,fork:""}}}var DA,ud=x(()=>{"use strict";DA=4e3});function Yb(t){let e=t.replace(/^#+\s*/,"").trim();for(let r of Wb)if(r.re.test(e))return{kind:r.kind,letter:r.letter};return null}function Ga(t){let e=[],r=new Map,n="",o=null,i=null;for(let a of t.split(`
8
8
  `)){let c=/^#{1,6}\s+(.*)$/.exec(a);if(c){n=c[1].trim(),o=Yb(n),i=null;continue}let l=qb.exec(a);if(l&&o){let u=l[1];r.set(u,(r.get(u)??0)+1),i={id:u,kind:o.kind,text:l[2].trim(),section:n},e.push(i);continue}if(i&&a.trim()&&!/^#{1,6}\s/.test(a)&&!/^\s*[-*]\s/.test(a)){i.text=`${i.text}
9
9
  ${a.trim()}`.trim();continue}a.trim()||(i=null)}let s=[...r.entries()].filter(([,a])=>a>1).map(([a])=>a);return{items:e,structured:e.length>=2&&s.length===0,duplicateIds:s}}function zb(t){let e={decision:"D",change:"C",assumption:"A",out_of_scope:"O",test:"T",procedure:"P"};return t.items.filter(r=>!r.id.startsWith(e[r.kind]))}function Vb(t,e){let r=new Map(t.items.map(s=>[s.id,s])),n=e.filter(s=>!s.approved),o=e.filter(s=>s.approved).map(s=>s.id);if(n.length===0)return"";let i=["Rejected plan items:",""];for(let s of n){let a=r.get(s.id),c=a?`${s.id} \u2014 ${a.text.split(`
10
10
  `)[0]}`:s.id;i.push(`- **${c}**`),s.remark?.trim()&&i.push(` ${s.remark.trim()}`)}return o.length>0&&i.push("",`Approved and settled: ${o.join(", ")}. Do not revisit these unless a`,"rejected item forces it \u2014 and say so explicitly if it does."),i.join(`
11
11
  `)}function Ka(t){let e=new Set;for(let r of t.items)if(r.kind==="procedure")for(let n of r.text.matchAll(Xb))e.add(n[1]);return[...e]}var Wb,qb,Xb,dd=x(()=>{"use strict";Wb=[{re:/^decisions?$/i,kind:"decision",letter:"D"},{re:/^changes?$/i,kind:"change",letter:"C"},{re:/^assumptions?$/i,kind:"assumption",letter:"A"},{re:/^out of scope$/i,kind:"out_of_scope",letter:"O"},{re:/^test strategy$/i,kind:"test",letter:"T"},{re:/^procedures?$/i,kind:"procedure",letter:"P"}],qb=/^\s*[-*]\s+(?:\*\*)?\[([A-Z][0-9]+)\](?:\*\*)?\s*(.*)$/;Xb=/`([a-z][a-z0-9-]{1,39})`/g});function Qb(t){let e=[],r=null;for(let o of t.split(`
12
12
  `)){let i=Zb.exec(o);if(i){r={id:i[1],status:i[2].toLowerCase(),text:i[3].trim()},e.push(r);continue}if(/^#{1,6}\s/.test(o)||/^\s*[-*]\s/.test(o)||!o.trim()){r=null;continue}r&&(r.text=`${r.text}
13
- ${o.trim()}`.trim())}let n={};for(let o of e)n[o.id]=o;return{items:e,byId:n}}function e$(t,e){let r=new Set(t);return{unreported:t.filter(n=>!(n in e.byId)),unknown:e.items.filter(n=>!r.has(n.id)).map(n=>n.id),notDone:e.items.filter(n=>n.status!=="done")}}var Jb,Zb,pd=x(()=>{"use strict";Jb=["done","deviated","partial","dropped"],Zb=/^\s*[-*]\s+(?:\*\*)?\[([A-Z][0-9]+)\](?:\*\*)?\s*[—:-]?\s*(done|deviated|partial|dropped)\b\s*[—:-]?\s*(.*)$/i});var fd=x(()=>{"use strict"});var md=x(()=>{"use strict"});var hd=x(()=>{"use strict"});function Ha(t){return`codepipe-host-${t}`}function t$(t){let e=t.filter(r=>r!=="self-hosted");return`runs-on: [self-hosted${e.length?", "+e.join(", "):""}]`}var gd=x(()=>{"use strict"});function r$(t,e){return(t&&t.includes("<TASK_ID>")?t:yd).replace(/<TASK_ID>/g,e.toLowerCase())}function n$(t,e){if(t)return`${t.replace(/\/+$/,"")}/issue/${encodeURIComponent(e)}`}function io(t){return!(!t||t.length>250||!/^[A-Za-z0-9._/-]+$/.test(t)||/^[-/.]/.test(t)||/[/.]$/.test(t)||t.endsWith(".lock")||t.includes("..")||t.includes("//")||t.includes("/."))}function Wa(t){if(!t||typeof t!="object")return null;let e=t,r=typeof e.owner=="string"?e.owner.trim():"",n=typeof e.repo=="string"?e.repo.trim():typeof e.repoName=="string"?e.repoName.trim():"",o=typeof e.host=="string"?e.host.trim():"";return!r||!n||o!=="github"&&o!=="gitlab"&&o!=="bitbucket"?null:{host:o,owner:r,repoName:n}}function qa(t){if(!t.mirror)return t;let{mirror:e,...r}=t;return{...r,host:e.host,owner:e.owner,repoName:e.repoName}}function xt(t){return`${t}${wd}`}var yd,Wt,wd,kd=x(()=>{"use strict";yd="codepipe/<TASK_ID>";Wt=/^[a-z][a-z0-9-]{1,30}$/,wd="-codepipe-ctx"});function o$(t,e){return`${t}:${e}`}var bd=x(()=>{"use strict"});function $d(t){let e=(t??"").trim();return/^pr_closed_without_merge\b/.test(e)?"blocked":/^(merge_failed|close_failed)\b/.test(e)||/^chain_base_changed\b/.test(e)?"conflict":/^(build_failed|ci_failed)\b/.test(e)?"loop_exhausted":"error"}function i$(t){for(let e=t.length-1;e>=0;e--){let r=t[e];if(r.to==="NEEDS_MANUAL")return r}return null}function s$(t,e){if(t==="AWAITING_ANSWER")return{kind:"question"};if(t==="NEEDS_MANUAL"){let n=i$(e)?.reason,o={kind:$d(n)};return n&&(o.reason=n),o}}var vd=x(()=>{"use strict"});function $r(t){for(let e of xd){let r=t.match(e.pattern);if(r)return{name:e.name,args:(r[1]??"").trim()}}return null}var xd,Sd=x(()=>{"use strict";xd=[{name:"rework",pattern:/^@(?:codepipe|devpipe)\s+rework:\s*(.+)$/im,description:"Send the task back to ANALYZING with a new instruction.",hasArg:!0},{name:"approve",pattern:/^@(?:codepipe|devpipe)\s+approve\s*$/im,description:"Merge every PR for this task (TRACKING only)."},{name:"reject",pattern:/^@(?:codepipe|devpipe)\s+reject(?::\s*(.+))?\s*$/im,description:"Abandon this task: close any open PR(s) and move it to DONE (reason rejected_and_closed). Valid from any non-terminal phase; from early phases it just skips the task.",hasArg:!0},{name:"merge",pattern:/^@(?:codepipe|devpipe)\s+merge\s*$/im,description:"Merge the task branch into the default branch without a PR (direct apply path, apply.pull_request=false; TRACKING only)."},{name:"rebase",pattern:/^@(?:codepipe|devpipe)\s+rebase\s*$/im,description:"Re-apply the patch on top of the latest base branch and force-push. Use after a PR merge conflict or APPLYING failure."},{name:"update",pattern:/^@(?:codepipe|devpipe)\s+update(?::\s*(.+))?\s*$/im,description:"Update a conflicting PR: resolve conflicts against the current base branch (TRACKING only). Optional `: <instruction>` is forwarded to the agent.",hasArg:!0},{name:"apply",pattern:/^@(?:codepipe|devpipe)\s+apply:\s*(local|auto)\s*$/im,description:"Override apply mode for this task: local (you apply by hand) or auto.",hasArg:!0},{name:"fix",pattern:/^@(?:codepipe|devpipe)\s+fix\s*$/im,description:"Fix the external review remarks on the developer's branch (waiting-for-fix state only)."}]});var Ed=x(()=>{"use strict"});function Td(t){let e=Math.max(1,Math.round(t));if(e<60)return`${e}s`;let r=Math.round(e/60);if(r<60)return`${r}m`;let n=Math.round(r/60);return n<24?`${n}h`:`${Math.round(n/24)}d`}function a$(t,e=Date.now()){return`${Td((e-t)/1e3)} ago`}function c$(t){let e=Math.floor(t/86400),r=Math.floor(t%86400/3600),n=Math.floor(t%3600/60);return e>0?`${e}d ${r}h`:r>0?`${r}h ${n}m`:`${n}m`}var Rd=x(()=>{"use strict"});var Id=x(()=>{"use strict"});function Cd(t){return t.toUpperCase().replace(/[^A-Z0-9]/g,"").replace(/^[^A-Z]+/,"").slice(0,10)}function za(t){let e=t.split(/[^A-Za-z0-9]+/).filter(Boolean),r=Cd(e.length>=2?e.map(o=>o[0]).join(""):(e[0]??"").slice(0,4));if(vr.test(r))return r;let n=Cd(t);return vr.test(n)?n:ai}function Va(t,e){let r=new Set([...e].map(n=>n.toUpperCase()));if(!r.has(t.toUpperCase()))return t;for(let n=1;n<1e4;n++){let o=String(n),i=t.slice(0,10-o.length)+o;if(!r.has(i.toUpperCase()))return i}return t}function Vr(t){return`tasks/${t}/issue.yaml`}var Ya,so,ai,vr,ci,l$,ao,zr,Pd=x(()=>{"use strict";Ya=["bug","feature","epic"],so="feature",ai="TASK",vr=/^[A-Z][A-Z0-9]{1,9}$/;ci={backlog:"Backlog",source:["To Do"],inProgress:"In Progress",review:"Review",done:["Done"],rejected:["Rejected"],statusColumns:["Backlog","To Do","In Progress","Review","Done","Rejected"]},l$=ci.backlog,ao="tracker/config.yaml",zr="tracker/counter"});function co(t){let e=t.split(`
13
+ ${o.trim()}`.trim())}let n={};for(let o of e)n[o.id]=o;return{items:e,byId:n}}function e$(t,e){let r=new Set(t);return{unreported:t.filter(n=>!(n in e.byId)),unknown:e.items.filter(n=>!r.has(n.id)).map(n=>n.id),notDone:e.items.filter(n=>n.status!=="done")}}var Jb,Zb,pd=x(()=>{"use strict";Jb=["done","deviated","partial","dropped"],Zb=/^\s*[-*]\s+(?:\*\*)?\[([A-Z][0-9]+)\](?:\*\*)?\s*[—:-]?\s*(done|deviated|partial|dropped)\b\s*[—:-]?\s*(.*)$/i});var fd=x(()=>{"use strict"});var md=x(()=>{"use strict"});var hd=x(()=>{"use strict"});function Ha(t){return`codepipe-host-${t}`}function t$(t){let e=t.filter(r=>r!=="self-hosted");return`runs-on: [self-hosted${e.length?", "+e.join(", "):""}]`}var gd=x(()=>{"use strict"});function r$(t,e){return(t&&t.includes("<TASK_ID>")?t:yd).replace(/<TASK_ID>/g,e.toLowerCase())}function n$(t,e){if(t)return`${t.replace(/\/+$/,"")}/issue/${encodeURIComponent(e)}`}function io(t){return!(!t||t.length>250||!/^[A-Za-z0-9._/-]+$/.test(t)||/^[-/.]/.test(t)||/[/.]$/.test(t)||t.endsWith(".lock")||t.includes("..")||t.includes("//")||t.includes("/."))}function Wa(t){if(!t||typeof t!="object")return null;let e=t,r=typeof e.owner=="string"?e.owner.trim():"",n=typeof e.repo=="string"?e.repo.trim():typeof e.repoName=="string"?e.repoName.trim():"",o=typeof e.host=="string"?e.host.trim():"";return!r||!n||o!=="github"&&o!=="gitlab"&&o!=="bitbucket"?null:{host:o,owner:r,repoName:n}}function qa(t){if(!t.mirror)return t;let{mirror:e,...r}=t;return{...r,host:e.host,owner:e.owner,repoName:e.repoName}}function xt(t){return`${t}${wd}`}var yd,Wt,wd,kd=x(()=>{"use strict";yd="codepipe/<TASK_ID>";Wt=/^[a-z][a-z0-9-]{1,30}$/,wd="-codepipe-ctx"});function o$(t,e){return`${t}:${e}`}var bd=x(()=>{"use strict"});function $d(t){let e=(t??"").trim();return/^pr_closed_without_merge\b/.test(e)?"blocked":/^(merge_failed|close_failed)\b/.test(e)||/^chain_base_changed\b/.test(e)||/^write action apply_delivery failed: .*hit conflicts/.test(e)?"conflict":/^(build_failed|ci_failed)\b/.test(e)?"loop_exhausted":"error"}function i$(t){for(let e=t.length-1;e>=0;e--){let r=t[e];if(r.to==="NEEDS_MANUAL")return r}return null}function s$(t,e){if(t==="AWAITING_ANSWER")return{kind:"question"};if(t==="NEEDS_MANUAL"){let n=i$(e)?.reason,o={kind:$d(n)};return n&&(o.reason=n),o}}var vd=x(()=>{"use strict"});function $r(t){for(let e of xd){let r=t.match(e.pattern);if(r)return{name:e.name,args:(r[1]??"").trim()}}return null}var xd,Sd=x(()=>{"use strict";xd=[{name:"rework",pattern:/^@(?:codepipe|devpipe)\s+rework:\s*(.+)$/im,description:"Send the task back to ANALYZING with a new instruction.",hasArg:!0},{name:"approve",pattern:/^@(?:codepipe|devpipe)\s+approve\s*$/im,description:"Merge every PR for this task (TRACKING only)."},{name:"reject",pattern:/^@(?:codepipe|devpipe)\s+reject(?::\s*(.+))?\s*$/im,description:"Abandon this task: close any open PR(s) and move it to DONE (reason rejected_and_closed). Valid from any non-terminal phase; from early phases it just skips the task.",hasArg:!0},{name:"merge",pattern:/^@(?:codepipe|devpipe)\s+merge\s*$/im,description:"Merge the task branch into the default branch without a PR (direct apply path, apply.pull_request=false; TRACKING only)."},{name:"rebase",pattern:/^@(?:codepipe|devpipe)\s+rebase\s*$/im,description:"Re-apply the patch on top of the latest base branch and force-push. Use after a PR merge conflict or APPLYING failure."},{name:"update",pattern:/^@(?:codepipe|devpipe)\s+update(?::\s*(.+))?\s*$/im,description:"Update a conflicting PR: resolve conflicts against the current base branch (TRACKING only). Optional `: <instruction>` is forwarded to the agent.",hasArg:!0},{name:"apply",pattern:/^@(?:codepipe|devpipe)\s+apply:\s*(local|auto)\s*$/im,description:"Override apply mode for this task: local (you apply by hand) or auto.",hasArg:!0},{name:"fix",pattern:/^@(?:codepipe|devpipe)\s+fix\s*$/im,description:"Fix the external review remarks on the developer's branch (waiting-for-fix state only)."}]});var Ed=x(()=>{"use strict"});function Td(t){let e=Math.max(1,Math.round(t));if(e<60)return`${e}s`;let r=Math.round(e/60);if(r<60)return`${r}m`;let n=Math.round(r/60);return n<24?`${n}h`:`${Math.round(n/24)}d`}function a$(t,e=Date.now()){return`${Td((e-t)/1e3)} ago`}function c$(t){let e=Math.floor(t/86400),r=Math.floor(t%86400/3600),n=Math.floor(t%3600/60);return e>0?`${e}d ${r}h`:r>0?`${r}h ${n}m`:`${n}m`}var Rd=x(()=>{"use strict"});var Id=x(()=>{"use strict"});function Cd(t){return t.toUpperCase().replace(/[^A-Z0-9]/g,"").replace(/^[^A-Z]+/,"").slice(0,10)}function za(t){let e=t.split(/[^A-Za-z0-9]+/).filter(Boolean),r=Cd(e.length>=2?e.map(o=>o[0]).join(""):(e[0]??"").slice(0,4));if(vr.test(r))return r;let n=Cd(t);return vr.test(n)?n:ai}function Va(t,e){let r=new Set([...e].map(n=>n.toUpperCase()));if(!r.has(t.toUpperCase()))return t;for(let n=1;n<1e4;n++){let o=String(n),i=t.slice(0,10-o.length)+o;if(!r.has(i.toUpperCase()))return i}return t}function Vr(t){return`tasks/${t}/issue.yaml`}var Ya,so,ai,vr,ci,l$,ao,zr,Pd=x(()=>{"use strict";Ya=["bug","feature","epic"],so="feature",ai="TASK",vr=/^[A-Z][A-Z0-9]{1,9}$/;ci={backlog:"Backlog",source:["To Do"],inProgress:"In Progress",review:"Review",done:["Done"],rejected:["Rejected"],statusColumns:["Backlog","To Do","In Progress","Review","Done","Rejected"]},l$=ci.backlog,ao="tracker/config.yaml",zr="tracker/counter"});function co(t){let e=t.split(`
14
14
  `),r=e.indexOf("---");if(r<0)return;let n=e.slice(r+1),o=n.lastIndexOf("## Attachments");o>=0&&n.slice(o+1).every(c=>c.trim()===""||/^- \[[^\]]*\]\(attachments\/[^)]*\)$/.test(c.trim()))&&(n=n.slice(0,o));let i=n.join(`
15
15
  `).trim();if(!(!i||i==="_(no description)_"))return i}function u$(t){return`{{ancestorExcerpt:${t}}}`}var li,Ad=x(()=>{"use strict";li=/\{\{ancestorExcerpt:([^}]+)\}\}/g});var d$,_d=x(()=>{"use strict";d$="youtrack"});function xr(t){let e=t.match(/^git@([^:/]+):/);if(e)return e[1]??null;let r=t.match(/^ssh:\/\/(?:[^@/]+@)?([^/:]+)/);if(r)return r[1]??null;let n=t.match(/^https?:\/\/(?:[^@/]+@)?([^/:]+)/);return n?n[1]??null:null}function lo(t){switch(t){case Xr.gitlab:return"oauth2";case Xr.bitbucket:return"x-token-auth";default:return"x-access-token"}}var Xr,Lt,jd=x(()=>{"use strict";Xr={github:"github.com",gitlab:"gitlab.com",bitbucket:"bitbucket.org"};Lt="x-bitbucket-api-token-auth"});var Nd=x(()=>{"use strict"});var Od=x(()=>{"use strict";_d();jd();Nd()});var Ld={};ze(Ld,{ACTION_ID_RE:()=>$a,ACTION_STEP_DEFAULT_TIMEOUT_SEC:()=>xa,ALL_JOB_ROLES:()=>ha,ALL_MODEL_ROLE_KEYS:()=>wa,ANALYSIS_MAX_DRAFTS:()=>Xa,ANCESTOR_EXCERPT_RE:()=>li,ANCESTOR_EXCERPT_TOKEN:()=>u$,ANNOTATION_MAX_PER_TASK:()=>aa,BACKFILL_MAX_DRAFTS:()=>p$,BITBUCKET_API_TOKEN_GIT_USER:()=>Lt,BUILD_DISCOVERY:()=>Ku,COCHANGE_DEFAULTS:()=>nt,CODEPIPE_COMMANDS:()=>xd,COMMIT_STYLE_MAX_LENGTH:()=>Pa,CONTEXT_PACK_DECAY:()=>la,CONTEXT_PACK_DEFAULTS:()=>wr,CONTEXT_REPO_SUFFIX:()=>wd,CONTEXT_STAMP_FILE:()=>gt,CONTEXT_TEMPLATE_CHANGELOG:()=>Vs,CONTEXT_TEMPLATE_VERSION:()=>Tu,COUNCIL_MAX_ANSWER:()=>DA,DEFAULT_BRANCH_PATTERN:()=>yd,DEFAULT_HUB_URL:()=>mt,DEFAULT_INTERNAL_ISSUE_TYPE:()=>so,DEFAULT_INTERNAL_TRACKER_PREFIX:()=>ai,DEFAULT_LLM_PROVIDER:()=>Xe,DEFAULT_REGIMEN_ALIASES:()=>Yu,DEFAULT_TRACKER_PROVIDER:()=>d$,ENV_NAME_RE:()=>Je,FALLBACK_MODEL:()=>Wu,GIT_HOST_DOMAINS:()=>Xr,INTERNAL_ISSUE_TYPES:()=>Ya,INTERNAL_TRACKER_CONFIG_PATH:()=>ao,INTERNAL_TRACKER_COUNTER_PATH:()=>zr,INTERNAL_TRACKER_DEFAULT_STATUS:()=>l$,INTERNAL_TRACKER_PREFIX_RE:()=>vr,INTERNAL_TRACKER_STATUSES:()=>ci,LANE_PHASES:()=>bb,LANE_SEGMENTS:()=>ma,LANGUAGE_AUTO:()=>$e,LANGUAGE_SUGGESTIONS:()=>Yr,LANGUAGE_VALUE_MAX_LENGTH:()=>oo,LEGACY_CONTEXT_STAMP_FILE:()=>Kr,LLM_PROVIDER_SUGGESTIONS:()=>ya,MIN_SUPPORTED_PROTOCOL:()=>xu,MODEL_ALIAS_SUGGESTIONS:()=>oi,MODEL_DERIVED_DIR:()=>fb,MODEL_DERIVED_INDEX_PATH:()=>Qo,MODEL_DIR:()=>ub,MODEL_EDGE_KINDS:()=>ia,MODEL_ENTITY_ID_RE:()=>Pu,MODEL_FACTS_DIR:()=>pb,MODEL_FAMILY_PREFERENCE:()=>qu,MODEL_HAIKU:()=>ni,MODEL_LEVELS:()=>Cu,MODEL_OPUS:()=>Pe,MODEL_README_PATH:()=>db,MODEL_RELATES_PATH:()=>hr,MODEL_SEARCH_MAX_LIMIT:()=>ca,MODEL_SEARCH_MAX_ROWS:()=>hb,MODEL_SEARCH_ROW_TEXT_MAX:()=>ti,MODEL_SONNET:()=>to,MODEL_SUB_ROLES:()=>Hu,OBSERVER_MAX_DECISION:()=>OA,OBSERVER_MAX_SUMMARY:()=>LA,OFFICIAL_MARKETPLACES:()=>id,PHASES:()=>fa,PIPELINE_COLUMNS:()=>Uu,PLANNING_LANE_MAX_JOBS:()=>Sb,PLANNING_ROLES:()=>Fu,PLATFORM_VERSION:()=>Ve,PROJECT_ID_RE:()=>Wt,PROJECT_LANGUAGE_SECTIONS:()=>no,PROJECT_MODEL_FORMAT_VERSION:()=>Oe,PROJECT_SETTINGS_MANIFEST:()=>Zu,PROMPT_ROLES:()=>nd,PROTOCOL_VERSION:()=>ht,RECOMMENDED_ROLE_MODELS:()=>ro,RELATES_MIN_OVERLAP:()=>sa,ROLE_MAX_DESCRIPTION:()=>PA,ROLE_MAX_REFS:()=>CA,ROLE_NAME_RE:()=>ja,ROLE_SCENARIOS:()=>si,SKILL_MAX_DESCRIPTION:()=>jA,SKILL_NAME_RE:()=>Ua,SOLUTION_STATUSES:()=>Jb,STRING_MAP_MAX_ENTRIES:()=>Ia,STRING_MAP_MAX_VALUE_LENGTH:()=>Ca,additionsSince:()=>Js,ago:()=>a$,attentionFor:()=>s$,autoLanguageConfig:()=>Xu,autoModelDefault:()=>ka,canonicalizeModelEdgeSheet:()=>Au,canonicalizeModelIdentityTable:()=>ju,canonicalizeModelShard:()=>_u,canonicalizeModelTaskEvent:()=>Nu,changesSince:()=>Zs,classifyAttentionReason:()=>$d,compilePlanRework:()=>Vb,contextRepoName:()=>xt,deserializeModelConfig:()=>Cb,emptyModelConfig:()=>qr,enabledPluginsSetting:()=>Gb,extractLanguageConfig:()=>Nb,extractTaskMdBody:()=>co,findSettingField:()=>Qu,firstFreeInternalTrackerPrefix:()=>Va,flattenSettingFields:()=>Aa,fmtDuration:()=>Td,fmtUptime:()=>c$,ghRunnerHostLabel:()=>Ha,ghRunnerRunsOnSnippet:()=>t$,gitCloneUrlDomain:()=>xr,httpsTokenUser:()=>lo,internalIssueYamlPath:()=>Vr,isAllAutoLanguage:()=>Ob,isAutoLanguage:()=>Ju,isBodyEditFrozen:()=>kb,isModelEntityId:()=>ei,isPromptRole:()=>Ma,isProtocolCompatible:()=>Vn,isReservedEnvName:()=>Ot,isTerminalPhase:()=>wb,isValidBranchName:()=>io,jobLane:()=>xb,laneSegmentForPhase:()=>$b,makeTaskId:()=>o$,mergeRoles:()=>Oa,mergeSkills:()=>Fa,mismatchedIds:()=>zb,modelAnnotationPath:()=>ta,modelComponentSlug:()=>Iu,modelCorrelatesPath:()=>ra,modelEventPath:()=>gr,modelIdentityPath:()=>Zn,modelNodeKey:()=>ye,modelShardNeedsRebuild:()=>gb,modelStructureShardPath:()=>oa,modelTaskNodeKey:()=>xe,modelTouchedPath:()=>na,parseActionDefinition:()=>Sa,parseCodepipeCommand:()=>$r,parseContextStamp:()=>Xs,parseMarketplaceSource:()=>sd,parseMarketplaces:()=>Bb,parseModelConfig:()=>Rb,parseModelNodeKey:()=>re,parsePlanItems:()=>Ga,parseRepoMirror:()=>Wa,parseSolutionItems:()=>Qb,pipelineColumnForPhase:()=>vb,pipelineRepoSpec:()=>qa,prescribedSkills:()=>Ka,promptOverridePath:()=>Da,renderContextStamp:()=>Xn,resolveBranchName:()=>r$,resolveModelForRole:()=>Eb,resolveProvider:()=>Tb,rolesForScenario:()=>La,serializeModelConfig:()=>Ib,serializeModelEdgeSheet:()=>yr,serializeModelIdentityTable:()=>da,serializeModelShard:()=>ua,serializeModelTaskEvent:()=>Wr,serializeModelYaml:()=>kr,solutionCoverage:()=>e$,suggestInternalTrackerPrefix:()=>za,validateActionInput:()=>Ea,validateCouncilVerdict:()=>Hb,validateModelEdgeSheet:()=>Qn,validateModelIdentityTable:()=>eo,validateModelShard:()=>jt,validateModelTaskEvent:()=>Nt,validateObserverPlan:()=>Kb,validateRoleDefinition:()=>Na,validateSettingEdit:()=>_a,validateSkill:()=>Ba,youtrackIssueUrl:()=>n$,zeroUsage:()=>Ht});var Xa,p$,B=x(()=>{"use strict";Su();Eu();Ru();pa();Du();Bu();ga();ba();ed();Ra();Ta();rd();od();ad();ld();ud();dd();pd();fd();md();hd();gd();kd();bd();vd();Sd();Ed();Rd();Id();Pd();Ad();Od();Xa=20,p$=15});function X(t){return process.env[`CODEPIPE_${t}`]??process.env[`DEVPIPE_${t}`]}var Fe=x(()=>{"use strict"});import{existsSync as f$,readFileSync as m$,readdirSync as h$}from"node:fs";import{dirname as g$,join as Ja}from"node:path";import{parse as y$}from"yaml";function w$(t=process.cwd()){let e=t;for(;;){if(f$(Ja(e,ot,"project.yaml")))return e;let r=g$(e);if(r===e)return null;e=r}}function k$(t){return Ja(t,ot)}function Ae(t=process.cwd()){let e=w$(t);if(!e)return null;let r=k$(e),n=b$(m$(Ja(r,"project.yaml"),"utf-8"));return{root:e,contextDir:r,spec:n}}function Md(t,e,r){return h$(t).filter(o=>o!==".DS_Store").length===0?!0:e?r.some(o=>o.host===e.host&&o.owner===e.owner&&o.repoName===e.repoName):!1}function Jr(t,e=process.cwd()){try{let r=Ae(e);return r&&r.spec.projectId===t?r:null}catch{return null}}function b$(t){let e=y$(t);if(!e||typeof e!="object")throw new Error("project.yaml is empty or malformed");let r=String(e.id??""),n=String(e.name??r),o=Array.isArray(e.repos)?e.repos:[],i=[];for(let s of o){if(!s||typeof s!="object")continue;let a=s,c=String(a.repo??a.repoName??""),l=String(a.name??c);if(!l||!c)continue;let u=a.host,p=u==="bitbucket"?"bitbucket":u==="gitlab"?"gitlab":"github",d=Wa(a.mirror);i.push({name:l,host:p,owner:String(a.owner??""),repoName:c,defaultBranch:String(a.default_branch??a.defaultBranch??"main"),mountAs:String(a.mount_as??a.mountAs??l),...d?{mirror:d}:{}})}return{projectId:r,name:n,repos:i}}function ui(t){return t.host==="github"?`git@github.com:${t.owner}/${t.repoName}.git`:t.host==="gitlab"?`git@gitlab.com:${t.owner}/${t.repoName}.git`:`git@bitbucket.org:${t.owner}/${t.repoName}.git`}var ot,it=x(()=>{"use strict";B();ot=".codepipe"});import{homedir as Dd}from"node:os";import{mkdirSync as $$,readFileSync as v$,writeFileSync as x$,existsSync as Za}from"node:fs";import{dirname as Bd,join as di,resolve as S$}from"node:path";import{fileURLToPath as E$}from"node:url";function Fd(t){let e=di(Ud,".env");if(Za(e)&&process.loadEnvFile(e),t){let r=di(Ud,"profiles",t,".env");Za(r)&&process.loadEnvFile(r)}}function Zr(t){let e=X("CONFIG");return e||(t?di(Dd(),".codepipe","profiles",t,"config.json"):di(Dd(),".codepipe","config.json"))}function wt(t){let e=Zr(t);if(!Za(e))return null;let r=v$(e,"utf-8");return JSON.parse(r)}function Mt(t,e){let r=Zr(e);$$(Bd(r),{recursive:!0}),x$(r,JSON.stringify(t,null,2)+`
16
16
  `,{mode:384})}function Qr(t){if(t)return{cfg:st(t),profile:t};let e;try{e=Ae()?.spec.projectId||void 0}catch{}if(e){let r=wt(e);if(r)return console.log(`[profile] ${e} \u2014 resolved from this folder's workspace`),{cfg:r,profile:e};console.error(`this folder is the workspace of project '${e}', but that CLI profile is not initialised on this machine \u2014 run \`codepipe init\` here (or pass --profile).`),process.exit(1)}return{cfg:st(void 0),profile:void 0}}function st(t){let e=wt(t);if(!e){let r=t?`codepipe init --profile ${t} --hub <url> --token <token> --project ${t}`:"codepipe init --hub <url> --token <token> --project <id>";console.error(t?`CLI profile '${t}' is not initialised. run \`${r}\` first.`:`CLI is not initialised. run \`${r}\` first.`),process.exit(1)}return e.projectId||(console.error(`config at ${Zr(t)} is missing 'projectId'. re-run init with --force.`),process.exit(1)),e}var Ud,Ge=x(()=>{"use strict";Fe();it();Ud=S$(Bd(E$(import.meta.url)),"..")});import{homedir as Gd}from"node:os";import{existsSync as Kd,mkdirSync as Hd,readFileSync as Wd,writeFileSync as qd}from"node:fs";import{dirname as Yd,join as zd}from"node:path";function Vd(t,e,r){let n=q(t);if(!n)throw new Error("no secrets file for this project on the CLI");n.secrets={...n.secrets??{},[e]:r},ae(n)}function Xd(t,e){let r=q(t);return!r?.secrets||!(e in r.secrets)?!1:(delete r.secrets[e],ae(r),!0)}function Jd(t){return Object.keys(q(t)?.secrets??{}).sort()}function pi(t,e,r){let n=q(t);if(!n)return"mismatch";let o=n.sandboxPins??{},i=o[e];return i&&i===r?"ok":i&&i!==r?"mismatch":(o[e]=r,n.sandboxPins=o,ae(n),"pinned")}function Zd(t,e){let r=q(t);return r?.sandboxPins?.[e]?(delete r.sandboxPins[e],ae(r),!0):!1}function St(t){return zd(Gd(),".codepipe","secrets",`${t}.json`)}function q(t){let e=St(t);return Kd(e)?JSON.parse(Wd(e,"utf-8")):null}function ae(t){let e=St(t.projectId);Hd(Yd(e),{recursive:!0}),qd(e,JSON.stringify(t,null,2)+`
@@ -812,7 +812,7 @@ Produced by the interactive chat (mock runner).
812
812
  ${s.join("").trim()||"(no stderr)"}`))})})}function Ne(t,e,r){return new Promise((n,o)=>{let i=ty("git",e,{cwd:t,stdio:["ignore","pipe","pipe"],env:r??{...process.env}}),s=[],a=[];i.stdout.setEncoding("utf-8"),i.stderr.setEncoding("utf-8"),i.stdout.on("data",c=>s.push(c)),i.stderr.on("data",c=>a.push(c)),i.on("error",o),i.on("close",c=>{if(c===0)return n(s.join(""));o(new Error(`git ${e[0]} failed (exit ${c}):
813
813
  ${a.join("").trim()||"(no stderr)"}`))})})}function dy(t,e){ys(t)&&Nl(t,{recursive:!0,force:!0}),Uo(In(t),{recursive:!0}),KT(e,t,"dir")}async function py(t,e,r){await de(t,["worktree","prune"]).catch(()=>{}),Uo(In(r),{recursive:!0}),await de(t,["worktree","add","--detach",r,`origin/${e}`])}async function qT(t,e,r){Uo(In(r),{recursive:!0}),await de(In(r),["clone","--quiet","--no-checkout",t,r]),await de(r,["checkout","--force","--detach",e])}async function fy(t,e,r,n="worktree",o,i){return r.length===0?[]:ny(e,async()=>{let s=[];for(let a of r){let c=cr(ry(i),e,a.name);console.log(`[git] code: ensure ${a.cloneUrl} @ ${a.ref} \u2192 ${c}`);let l;try{l=await oy(c,a.cloneUrl,a.ref,a.defaultBranch,o)}catch(d){throw new Error(`failed to materialize project repo "${a.name}" (${a.cloneUrl}): `+(d instanceof Error?d.message:String(d)))}let u=(await Ne(c,["rev-parse","HEAD"])).trim(),p=cr(t,"code",a.name);n==="direct"?(dy(p,c),console.log(`[git] code: linked ${p} \u2192 ${c} @ ${u.slice(0,10)}`)):n==="clone"?(await qT(c,u,p),console.log(`[git] code: clone ${p} \u2190 ${c} @ ${u.slice(0,10)}`)):(await py(c,l,p),console.log(`[git] code: worktree ${p} \u2190 ${c} @ ${u.slice(0,10)}`)),s.push({name:a.name,workspacePath:p,cachePath:c,ref:l,baseSha:u})}return s})}async function my(t,e,r,n="worktree",o,i){if(!r||!r.cloneUrl)return null;let s=r;return ny(e,async()=>{let a=cr(ry(i),e,"_context");console.log(`[git] context: ensure ${s.cloneUrl} @ ${s.ref} \u2192 ${a}`);try{await oy(a,s.cloneUrl,s.ref,void 0,o)}catch(u){throw new Error(`failed to materialize context repo (${s.cloneUrl}): `+(u instanceof Error?u.message:String(u)))}let c=cr(t,"context");n==="direct"?(dy(c,a),console.log(`[git] context: linked ${c} \u2192 ${a}`)):(await py(a,s.ref,c),console.log(`[git] context: worktree ${c} \u2190 ${a}`));let l=(await Ne(a,["rev-parse","HEAD"])).trim();return{workspacePath:c,cachePath:a,baseSha:l}})}async function hy(t,e=[]){let r=t.workspacePath,n=["knowledge",...e];await de(r,["add","-A",...n]).catch(()=>{});let o;try{o=await Ne(r,["diff","--cached","--name-only","--diff-filter=d",t.baseSha,"--",...n])}catch{return[]}let i=o.split(`
814
814
  `).map(a=>a.trim()).filter(a=>a.length>0),s=[];for(let a of i)try{let c=GT(cr(r,a)).toString("base64");s.push({path:a,contentBase64:c})}catch{}return s}var Rn,Cn,Pn,gy=x(()=>{"use strict";B();Rn=new Map;Cn="CodePipe Agent",Pn="codepipe@codepartner.ee"});import{existsSync as YT,readFileSync as zT}from"node:fs";import{join as VT}from"node:path";import{parse as XT}from"yaml";function yy(t){if(!t)return!1;let e=VT(t,Ll);if(!YT(e))return!1;try{let r=XT(zT(e,"utf-8"));if(!r||typeof r!="object")return!1;let n=r.steps;return!Array.isArray(n)||n.length===0?!1:n.some(o=>o!=null&&typeof o=="object"&&typeof o.run=="string"&&o.run.trim().length>0)}catch{return!1}}var Ll,wy=x(()=>{"use strict";Ll="knowledge/build.yaml"});import{readFileSync as JT}from"node:fs";import{join as ZT}from"node:path";function ky(t){let e=ZT(t,Bo),r;try{r=JT(e,"utf-8")}catch{throw new lr(`BUILD produced no ${Bo} verdict \u2014 inconclusive run`)}let n;try{n=JSON.parse(r)}catch(u){throw new lr(`${Bo} is not valid JSON: ${u instanceof Error?u.message:String(u)}`)}if(!n||typeof n!="object")throw new lr(`${Bo} must be a JSON object`);let o=n;if(typeof o.ok!="boolean")throw new lr(`${Bo}: "ok" must be a boolean`);let i=o.ok,a=(Array.isArray(o.steps)?o.steps:[]).flatMap(u=>{if(!u||typeof u!="object")return[];let p=u,d=typeof p.name=="string"?p.name:null,m=typeof p.exitCode=="number"?p.exitCode:null;if(d===null||m===null)return[];let f={name:d,exitCode:m};return typeof p.durationMs=="number"&&(f.durationMs=p.durationMs),[f]}),c=typeof o.logTail=="string"?QT(o.logTail):"",l={ok:i,steps:a,logTail:c};if(typeof o.failedStep=="string"&&o.failedStep)l.failedStep=o.failedStep;else if(!i){let u=a.find(p=>p.exitCode!==0);u&&(l.failedStep=u.name)}return l}function QT(t){let e=Buffer.from(t,"utf-8");return e.length<=Ml?t:`\u2026 [${e.length-Ml} bytes elided] \u2026
815
- `+e.subarray(e.length-Ml).toString("utf-8")}var Ml,lr,Bo,by=x(()=>{"use strict";Ml=8*1024,lr=class extends Error{},Bo="meta/build-result.json"});import{readFileSync as eR}from"node:fs";import{join as tR}from"node:path";function $y(t){let e=tR(t,An),r;try{r=eR(e,"utf-8")}catch{throw new Gt(`code review produced no ${An} verdict \u2014 inconclusive run`)}let n;try{n=JSON.parse(r)}catch(l){throw new Gt(`${An} is not valid JSON: ${l instanceof Error?l.message:String(l)}`)}if(!n||typeof n!="object")throw new Gt(`${An} must be a JSON object`);let o=n;if(typeof o.approved!="boolean")throw new Gt(`${An}: "approved" must be a boolean`);let i=o.approved,s=typeof o.remarks=="string"?Nr(o.remarks,rR):"";if(!i&&s.trim().length===0)throw new Gt(`${An}: "approved" is false but "remarks" is empty \u2014 nothing to rework on`);let a=typeof o.summary=="string"?Nr(o.summary,nR):"",c=iR(o.findings);return{approved:i,remarks:s,summary:a,...c.length>0?{findings:c}:{}}}function iR(t){if(!Array.isArray(t))return[];let e=[];for(let r of t.slice(0,oR)){if(!r||typeof r!="object")continue;let n=r,o=typeof n.title=="string"?Nr(n.title,512).trim():"",i=typeof n.problem=="string"?Nr(n.problem,Dl).trim():"";if(!o||!i)continue;let s=typeof n.line=="number"&&Number.isInteger(n.line)&&n.line>0?n.line:void 0;e.push({severity:n.severity==="blocker"?"blocker":"other",title:o,problem:i,...typeof n.repo=="string"&&n.repo?{repo:n.repo}:{},...typeof n.file=="string"&&n.file?{file:Nr(n.file,1024)}:{},...s!==void 0?{line:s}:{},...typeof n.scenario=="string"&&n.scenario.trim()?{scenario:Nr(n.scenario,Dl)}:{},...typeof n.suggestion=="string"&&n.suggestion.trim()?{suggestion:Nr(n.suggestion,Dl)}:{}})}return e}function Nr(t,e){let r=Buffer.from(t,"utf-8");return r.length<=e?t:r.subarray(0,e).toString("utf-8")+`
815
+ `+e.subarray(e.length-Ml).toString("utf-8")}var Ml,lr,Bo,by=x(()=>{"use strict";Ml=8*1024,lr=class extends Error{},Bo="meta/build-result.json"});import{readFileSync as eR}from"node:fs";import{join as tR}from"node:path";function $y(t){let e=tR(t,An),r;try{r=eR(e,"utf-8")}catch{throw new Gt(`code review produced no ${An} verdict \u2014 inconclusive run`)}let n;try{n=JSON.parse(r)}catch(l){throw new Gt(`${An} is not valid JSON: ${l instanceof Error?l.message:String(l)}`)}if(!n||typeof n!="object")throw new Gt(`${An} must be a JSON object`);let o=n;if(typeof o.approved!="boolean")throw new Gt(`${An}: "approved" must be a boolean`);let i=o.approved,s=typeof o.remarks=="string"?Nr(o.remarks,rR):"";if(!i&&s.trim().length===0)throw new Gt(`${An}: "approved" is false but "remarks" is empty \u2014 nothing to rework on`);let a=typeof o.summary=="string"?Nr(o.summary,nR):"",c=iR(o.findings);return{approved:i,remarks:s,summary:a,...c.length>0?{findings:c}:{}}}function iR(t){if(!Array.isArray(t))return[];let e=[];for(let r of t.slice(0,oR)){if(!r||typeof r!="object")continue;let n=r,o=typeof n.title=="string"?Nr(n.title,512).trim():"",i=typeof n.problem=="string"?Nr(n.problem,Dl).trim():"";if(!o||!i)continue;let s=typeof n.line=="number"&&Number.isInteger(n.line)&&n.line>0?n.line:void 0;e.push({severity:n.severity==="blocker"||n.severity==="major"||n.severity==="minor"?n.severity:"other",title:o,problem:i,...typeof n.repo=="string"&&n.repo?{repo:n.repo}:{},...typeof n.file=="string"&&n.file?{file:Nr(n.file,1024)}:{},...s!==void 0?{line:s}:{},...typeof n.scenario=="string"&&n.scenario.trim()?{scenario:Nr(n.scenario,Dl)}:{},...typeof n.suggestion=="string"&&n.suggestion.trim()?{suggestion:Nr(n.suggestion,Dl)}:{}})}return e}function Nr(t,e){let r=Buffer.from(t,"utf-8");return r.length<=e?t:r.subarray(0,e).toString("utf-8")+`
816
816
  \u2026 [${r.length-e} bytes elided]`}var rR,nR,Gt,An,Dl,oR,vy=x(()=>{"use strict";rR=16*1024,nR=4*1024,Gt=class extends Error{},An="meta/review-result.json";Dl=8*1024,oR=50});import{readFileSync as sR,statSync as aR}from"node:fs";import{join as xy}from"node:path";function mR(t){return t.startsWith("meta/")||fR.has(t)}function hR(t,e,r,n){return`[codepipe] artifact omitted from upload: ${t} was ${e} bytes, exceeds the SANDBOX upload budget (per-artifact ${r} / total ${n}). The delivered code (git) and the build/review verdict are unaffected \u2014 only this display/durability copy was dropped.`}function gR(t){return`[codepipe] artifact unreadable at upload time: ${t} could not be read from the workspace \u2014 content omitted.`}function Sy(t,e,r){let n=r?.maxBytes??cR,o=r?.totalBytes??lR,i=r?.maxCount??uR,s=e.map((f,g)=>{let k=null;try{k=aR(xy(t,f)).size}catch{}return{path:f,index:g,size:k}}),a=[...s].sort((f,g)=>{let k=h=>mR(h.path)?0:1;return k(f)!==k(g)?k(f)-k(g):(f.size??0)-(g.size??0)}),c=a.slice(0,i),l=a.slice(i).sort((f,g)=>f.index-g.index).map(f=>f.path),u=new Array(s.length),p=[],d=0;for(let f of c){let g=null;if(f.size!==null&&f.size<=n&&d+f.size<=o)try{g=sR(xy(t,f.path))}catch{}if(g!==null){d+=g.length,u[f.index]={path:f.path,contentBase64:g.toString("base64")};continue}let k=f.size===null?gR(f.path):hR(f.path,f.size,n,o),h=Buffer.from(k,"utf-8");d+=h.length,u[f.index]={path:f.path,contentBase64:h.toString("base64")},p.push({path:f.path,bytes:f.size??0})}let m=u.filter(f=>f!==void 0);if(l.length>0){let f=l.slice(0,pR),g=`# Artifacts omitted from upload
817
817
 
818
818
  ${l.length} file(s) exceeded the SANDBOX artifact count budget (${i}) and were dropped from the listing. The delivered code (git) and the build/review verdicts are unaffected. Usually this means a job left a stray tree in the workspace \u2014 throwaway copies belong in the workspace's \`scratch/\` directory, which is never uploaded.
@@ -871,7 +871,7 @@ ${n}`}function jI(t,e,r,n){let o=La(e,r);if(o.length===0)return{roles:[],files:[
871
871
 
872
872
  \u2026 [${s} bytes elided \u2014 log capped at ${Ts} bytes for upload] \u2026
873
873
 
874
- ${i}`}function qI(){let t=[],e=!1,r=null,n=i=>{if(r){let s=r;r=null,s({value:i,done:!1})}else t.push(i)},o=()=>{if(r){let i=r;r=null,i({value:void 0,done:!0})}};return{push(i){e||n(i)},finalize(){e||(n({kind:"finalize"}),e=!0)},close(){e=!0,t.length=0,o()},iterable:{[Symbol.asyncIterator](){return{next(){return t.length>0?Promise.resolve({value:t.shift(),done:!1}):e?Promise.resolve({value:void 0,done:!0}):new Promise(i=>{r=i})}}}}}}async function Go(t={}){let e=Le(t.profile);e||(console.error("sandbox not registered. run `codepipe worker register` first."),process.exit(1));let r=e.sealPrivateKey,n=e.sandboxId,o=e.llm,i=kg(t.profile,e.sandboxId,!!X("SANDBOX_CONFIG")),s=It(GI(),".codepipe","logs"),a=mi("SANDBOX_LOG",i,s);if(a.enabled){let A=new rn(a);hi(A),console.log(`[log] file logging \u2192 ${A.path} (rotate at ${a.maxBytes}B, keep ${a.maxFiles})`)}console.log(`codepipe-sandbox v${Ve} (protocol ${ht})`),console.log(`starting sandbox ${e.sandboxId} (${e.name}) \u2192 ${e.hubUrl}`);let c=jg(e.llm);console.log(`llm backend: ${c?c.name():"(none \u2014 will not claim agent jobs)"}`);let l=Dg();console.log(`llm retry: maxAttempts=${l.maxAttempts} backoff=${l.baseDelayMs}\u2013${l.maxDelayMs}ms budget=${l.totalBudgetMs}ms`);let u=new $n(e.hubUrl,e.token),p=!1,d=new AbortController,m=new Map,f=null,g=null,k=!1,h=()=>{let A=u.openControlSocket();return f=A,A.on("open",()=>{console.log("[ws] connected");let y={type:"sandbox_hello",platformVersion:Ve,protocolVersion:ht};A.send(JSON.stringify(y))}),A.on("message",y=>{let U=y.toString("utf-8"),j=null;try{let H=JSON.parse(U);H&&typeof H=="object"&&(j=H)}catch{}if(j&&j.type==="hello"){let H=j;g=Vn(H.protocolVersion);let J=g?"compatible":"INCOMPATIBLE";console.log(`[ws] hub v${H.platformVersion} (protocol ${H.protocolVersion}) \u2014 ${J}`),g&&(k=!1);return}if(j&&j.type==="pause_job"){let H=typeof j.jobId=="string"?j.jobId:"",J=H?m.get(H):void 0;J?(console.warn(`[ws] pause_job ${H} \u2014 aborting agent`),J.paused=!0,J.abort.abort()):console.log(`[ws] pause_job ${H} \u2014 not a running job, ignoring`),H&&A.send(JSON.stringify({type:"job_paused",jobId:H}));return}if(j&&(j.type==="chat_user_message"||j.type==="chat_finalize")){let H=typeof j.jobId=="string"?j.jobId:"",J=H?m.get(H):void 0;if(J?.chatInbox)if(j.type==="chat_user_message"){let oe=typeof j.text=="string"?j.text:"";oe.trim()&&J.chatInbox.push({kind:"user",text:oe})}else J.chatInbox.finalize();else console.log(`[ws] ${String(j.type)} ${H} \u2014 not a live chat job, ignoring`);return}console.log(`[ws] ${U}`)}),A.on("close",(y,U)=>{console.log(`[ws] closed code=${y} reason=${U?.toString()||""}`),f===A&&(f=null),!p&&setTimeout(h,2e3)}),A.on("error",y=>console.warn(`[ws] error: ${y.message}`)),A},w=h(),$=async A=>{for(;!p;){if(g===!1){k||(console.error(`[claim] HUB protocol incompatible with this SANDBOX (v${Ve}, protocol ${ht}) \u2014 not claiming jobs until versions align.`),k=!0),await new Promise(y=>setTimeout(y,5e3));continue}try{let y=await u.claim(d.signal,A);if(y.status===204)continue;if(y.status===401){console.error("[claim] 401 unauthorized \u2014 the HUB does not know this worker registration. It was removed; re-register with `codepipe up --reregister` (or `codepipe worker register --force`). exiting."),process.exitCode=1,p=!0;break}if(!y.ok){console.warn(`[claim:${A}] ${y.status} \u2014 backoff 5s`),await new Promise(j=>setTimeout(j,5e3));continue}let U=await y.json();await S(u,U)}catch(y){if(d.signal.aborted)break;let U=y instanceof Error?y.message:String(y);console.warn(`[claim:${A}] error: ${U} \u2014 backoff 5s`),await new Promise(j=>setTimeout(j,5e3))}}};async function S(A,y){let U={abort:new AbortController,paused:!1};y.role==="chat"&&(U.chatInbox=qI()),m.set(y.jobId,U);let j=!1,H=null,J=null,oe=Number(process.env.SANDBOX_HEARTBEAT_INTERVAL_MS??3e4),At=async()=>{try{await A.heartbeat(y.jobId)==="claim_lost"&&(j=!0,console.warn(`[job] ${y.jobId} claim lost \u2014 HUB sweeper took it`))}catch(N){let pe=N instanceof Error?N.message:String(N);console.warn(`[job] ${y.jobId} heartbeat error: ${pe}`)}};At();let pt=setInterval(()=>{At()},oe),Ue=new Date().toISOString();console.log(`[job] ${y.jobId} claimed \u2014 role=${y.role} task=${y.taskId} phase=${y.phase}`),console.log(`[job] ${y.jobId} prompt (${y.prompt.length} chars):`),console.log(v(y.prompt," \u2502 "));let L=[],F=null,M=400,Y=25,W=500,E=()=>{if(F&&(clearTimeout(F),F=null),L.length===0)return;let N=L.splice(0,L.length),pe=f;if(!pe||pe.readyState!==pe.OPEN)return;let Te={type:"agent_activity",jobId:y.jobId,taskId:y.taskId,projectId:y.projectId,role:y.role,phase:y.phase,events:N};try{pe.send(JSON.stringify(Te))}catch{}},I=N=>{L.push(N),L.length>W&&L.shift(),L.length>=Y?E():F||(F=setTimeout(E,M))},Q=y.role==="analysis"&&y.taskId.startsWith("draft::")?y.taskId.slice(7):null,ie=new Set,P=null;try{if(!c){j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:"sandbox has no LLM backend configured"},startedAt:Ue,finishedAt:new Date().toISOString()});return}if(!Ng(o,y.provider??null)){j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:`llm provider mismatch: worker backend "${o}" does not serve provider "${y.provider??"claude"}"`},startedAt:Ue,finishedAt:new Date().toISOString()});return}let N=Iy(y.jobId);console.log(`[job] ${y.jobId} workspace=${N.dir}`);let pe=T(y,r);H=pe.gitCreds,J=pe.contextGitCreds;let Te=H?.env,ft=pe.claudeOauthToken?{CLAUDE_CODE_OAUTH_TOKEN:pe.claudeOauthToken}:void 0,fe=[],ne=null,Gs=null;try{let O=y.role==="build"?"clone":"worktree";fe=await fy(N.dir,y.projectId,y.projectRepos,O,Te,n);let D=await my(N.dir,y.projectId,y.contextRepo,"worktree",Te,n);Gs=D,ne=D?.workspacePath??null}catch(O){let D=O instanceof Error?O.message:String(O);console.warn(`[job] ${y.jobId} materialize failed: ${D}`),j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:`materialize failed: ${D}`},startedAt:Ue,finishedAt:new Date().toISOString()}),N.dispose();return}let Hn=y.model;y.role==="build"&&y.modelDiscovery&&!yy(ne)&&(Hn=y.modelDiscovery,console.log(`[job] ${y.jobId} BUILD discovery (no steps in ${Ll}) \u2014 model=${Hn}`));let hu=async()=>{if(!y.deliveries||y.deliveries.length===0)return[];let O=y.contextRepo?.cloneUrl;if(!O||!Te)throw new Error(O?"no git credentials in bundle":"no contextRepo cloneUrl in job spec");let D=[];for(let ee of y.deliveries){let Z=fe.find(le=>le.name===ee.name);if(Z){if(y.role==="implement"&&ee.baseSha&&ee.baseSha!==Z.baseSha){let le=await uy(Z,ee.deliveryRef,ee.deliverySha,ee.baseSha,O,Te);console.log(`[job] ${y.jobId} ${Z.name}: base moved ${ee.baseSha.slice(0,10)} \u2192 ${Z.baseSha.slice(0,10)} \u2014 re-applied delivery ${ee.deliverySha.slice(0,10)} (${le.length} conflicted file(s))`),le.length>0&&D.push(`- **${Z.name}**:`,...le.map(tt=>` - \`${tt}\``));continue}await ly(Z,ee.deliveryRef,ee.deliverySha,O,Te),console.log(`[job] ${y.jobId} ${Z.name}: checked out delivery ${ee.deliverySha.slice(0,10)} for ${y.role}`)}}return D},Ks=[];if(y.role==="build"||y.role==="implement"||y.role==="code-review")try{Ks=await hu()}catch(O){let D=O instanceof Error?O.message:String(O);console.warn(`[job] ${y.jobId} delivery checkout failed: ${D}`),j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:`delivery checkout failed: ${D}`},startedAt:Ue,finishedAt:new Date().toISOString()}),N.dispose();return}let Hs=y.role==="resolve-conflict"?y.metadata?.taskBranchByRepo??{}:{},gu="";if(y.role==="resolve-conflict"){if(!fe.some(O=>Hs[O.name])){let O="resolve-conflict job carries no task branch to merge for any repo \u2014 nothing to resolve. The task branch could not be identified on the hub (the apply step may have failed before recording it); make sure the task branch exists upstream, then retry the update.";console.warn(`[job] ${y.jobId} ${O}`),j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:O},startedAt:Ue,finishedAt:new Date().toISOString()}),N.dispose();return}try{let O=[];for(let D of fe){let ee=Hs[D.name];if(!ee)continue;let Z=await Ol(D,ee,Te);console.log(`[job] ${y.jobId} ${D.name}: merged ${ee} into ${D.ref} \u2014 ${Z.length} conflicted file(s)`),Z.length>0?O.push(`- **${D.name}**:`,...Z.map(le=>` - \`${le}\``)):O.push(`- **${D.name}**: merged cleanly (no markers \u2014 verify it still builds)`)}gu=`
874
+ ${i}`}function qI(){let t=[],e=!1,r=null,n=i=>{if(r){let s=r;r=null,s({value:i,done:!1})}else t.push(i)},o=()=>{if(r){let i=r;r=null,i({value:void 0,done:!0})}};return{push(i){e||n(i)},finalize(){e||(n({kind:"finalize"}),e=!0)},close(){e=!0,t.length=0,o()},iterable:{[Symbol.asyncIterator](){return{next(){return t.length>0?Promise.resolve({value:t.shift(),done:!1}):e?Promise.resolve({value:void 0,done:!0}):new Promise(i=>{r=i})}}}}}}async function Go(t={}){let e=Le(t.profile);e||(console.error("sandbox not registered. run `codepipe worker register` first."),process.exit(1));let r=e.sealPrivateKey,n=e.sandboxId,o=e.llm,i=kg(t.profile,e.sandboxId,!!X("SANDBOX_CONFIG")),s=It(GI(),".codepipe","logs"),a=mi("SANDBOX_LOG",i,s);if(a.enabled){let A=new rn(a);hi(A),console.log(`[log] file logging \u2192 ${A.path} (rotate at ${a.maxBytes}B, keep ${a.maxFiles})`)}console.log(`codepipe-sandbox v${Ve} (protocol ${ht})`),console.log(`starting sandbox ${e.sandboxId} (${e.name}) \u2192 ${e.hubUrl}`);let c=jg(e.llm);console.log(`llm backend: ${c?c.name():"(none \u2014 will not claim agent jobs)"}`);let l=Dg();console.log(`llm retry: maxAttempts=${l.maxAttempts} backoff=${l.baseDelayMs}\u2013${l.maxDelayMs}ms budget=${l.totalBudgetMs}ms`);let u=new $n(e.hubUrl,e.token),p=!1,d=new AbortController,m=new Map,f=null,g=null,k=!1,h=()=>{let A=u.openControlSocket();return f=A,A.on("open",()=>{console.log("[ws] connected");let y={type:"sandbox_hello",platformVersion:Ve,protocolVersion:ht};A.send(JSON.stringify(y))}),A.on("message",y=>{let U=y.toString("utf-8"),j=null;try{let H=JSON.parse(U);H&&typeof H=="object"&&(j=H)}catch{}if(j&&j.type==="hello"){let H=j;g=Vn(H.protocolVersion);let J=g?"compatible":"INCOMPATIBLE";console.log(`[ws] hub v${H.platformVersion} (protocol ${H.protocolVersion}) \u2014 ${J}`),g&&(k=!1);return}if(j&&j.type==="pause_job"){let H=typeof j.jobId=="string"?j.jobId:"",J=H?m.get(H):void 0;J?(console.warn(`[ws] pause_job ${H} \u2014 aborting agent`),J.paused=!0,J.abort.abort()):console.log(`[ws] pause_job ${H} \u2014 not a running job, ignoring`),H&&A.send(JSON.stringify({type:"job_paused",jobId:H}));return}if(j&&(j.type==="chat_user_message"||j.type==="chat_finalize")){let H=typeof j.jobId=="string"?j.jobId:"",J=H?m.get(H):void 0;if(J?.chatInbox)if(j.type==="chat_user_message"){let oe=typeof j.text=="string"?j.text:"";oe.trim()&&J.chatInbox.push({kind:"user",text:oe})}else J.chatInbox.finalize();else console.log(`[ws] ${String(j.type)} ${H} \u2014 not a live chat job, ignoring`);return}console.log(`[ws] ${U}`)}),A.on("close",(y,U)=>{console.log(`[ws] closed code=${y} reason=${U?.toString()||""}`),f===A&&(f=null),!p&&setTimeout(h,2e3)}),A.on("error",y=>console.warn(`[ws] error: ${y.message}`)),A},w=h(),$=async A=>{for(;!p;){if(g===!1){k||(console.error(`[claim] HUB protocol incompatible with this SANDBOX (v${Ve}, protocol ${ht}) \u2014 not claiming jobs until versions align.`),k=!0),await new Promise(y=>setTimeout(y,5e3));continue}try{let y=await u.claim(d.signal,A);if(y.status===204)continue;if(y.status===401){console.error("[claim] 401 unauthorized \u2014 the HUB does not know this worker registration. It was removed; re-register with `codepipe up --reregister` (or `codepipe worker register --force`). exiting."),process.exitCode=1,p=!0;break}if(!y.ok){console.warn(`[claim:${A}] ${y.status} \u2014 backoff 5s`),await new Promise(j=>setTimeout(j,5e3));continue}let U=await y.json();await S(u,U)}catch(y){if(d.signal.aborted)break;let U=y instanceof Error?y.message:String(y);console.warn(`[claim:${A}] error: ${U} \u2014 backoff 5s`),await new Promise(j=>setTimeout(j,5e3))}}};async function S(A,y){let U={abort:new AbortController,paused:!1};y.role==="chat"&&(U.chatInbox=qI()),m.set(y.jobId,U);let j=!1,H=null,J=null,oe=Number(process.env.SANDBOX_HEARTBEAT_INTERVAL_MS??3e4),At=async()=>{try{await A.heartbeat(y.jobId)==="claim_lost"&&(j=!0,console.warn(`[job] ${y.jobId} claim lost \u2014 HUB sweeper took it`))}catch(N){let pe=N instanceof Error?N.message:String(N);console.warn(`[job] ${y.jobId} heartbeat error: ${pe}`)}};At();let pt=setInterval(()=>{At()},oe),Ue=new Date().toISOString();console.log(`[job] ${y.jobId} claimed \u2014 role=${y.role} task=${y.taskId} phase=${y.phase}`),console.log(`[job] ${y.jobId} prompt (${y.prompt.length} chars):`),console.log(v(y.prompt," \u2502 "));let L=[],F=null,M=400,Y=25,W=500,E=()=>{if(F&&(clearTimeout(F),F=null),L.length===0)return;let N=L.splice(0,L.length),pe=f;if(!pe||pe.readyState!==pe.OPEN)return;let Te={type:"agent_activity",jobId:y.jobId,taskId:y.taskId,projectId:y.projectId,role:y.role,phase:y.phase,events:N};try{pe.send(JSON.stringify(Te))}catch{}},I=N=>{L.push(N),L.length>W&&L.shift(),L.length>=Y?E():F||(F=setTimeout(E,M))},Q=y.role==="analysis"&&y.taskId.startsWith("draft::")?y.taskId.slice(7):null,ie=new Set,P=null;try{if(!c){j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:"sandbox has no LLM backend configured"},startedAt:Ue,finishedAt:new Date().toISOString()});return}if(!Ng(o,y.provider??null)){j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:`llm provider mismatch: worker backend "${o}" does not serve provider "${y.provider??"claude"}"`},startedAt:Ue,finishedAt:new Date().toISOString()});return}let N=Iy(y.jobId);console.log(`[job] ${y.jobId} workspace=${N.dir}`);let pe=T(y,r);H=pe.gitCreds,J=pe.contextGitCreds;let Te=H?.env,ft=pe.claudeOauthToken?{CLAUDE_CODE_OAUTH_TOKEN:pe.claudeOauthToken}:void 0,fe=[],ne=null,Gs=null;try{let O=y.role==="build"?"clone":"worktree";fe=await fy(N.dir,y.projectId,y.projectRepos,O,Te,n);let D=await my(N.dir,y.projectId,y.contextRepo,"worktree",Te,n);Gs=D,ne=D?.workspacePath??null}catch(O){let D=O instanceof Error?O.message:String(O);console.warn(`[job] ${y.jobId} materialize failed: ${D}`),j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:`materialize failed: ${D}`},startedAt:Ue,finishedAt:new Date().toISOString()}),N.dispose();return}let Hn=y.model;y.role==="build"&&y.modelDiscovery&&!yy(ne)&&(Hn=y.modelDiscovery,console.log(`[job] ${y.jobId} BUILD discovery (no steps in ${Ll}) \u2014 model=${Hn}`));let hu=async()=>{if(!y.deliveries||y.deliveries.length===0)return[];let O=y.contextRepo?.cloneUrl;if(!O||!Te)throw new Error(O?"no git credentials in bundle":"no contextRepo cloneUrl in job spec");let D=[];for(let ee of y.deliveries){let Z=fe.find(le=>le.name===ee.name);if(Z){if(y.role==="implement"&&ee.baseSha&&ee.baseSha!==Z.baseSha){let le=await uy(Z,ee.deliveryRef,ee.deliverySha,ee.baseSha,O,Te);console.log(`[job] ${y.jobId} ${Z.name}: base moved ${ee.baseSha.slice(0,10)} \u2192 ${Z.baseSha.slice(0,10)} \u2014 re-applied delivery ${ee.deliverySha.slice(0,10)} (${le.length} conflicted file(s))`),le.length>0&&D.push(`- **${Z.name}**:`,...le.map(tt=>` - \`${tt}\``));continue}await ly(Z,ee.deliveryRef,ee.deliverySha,O,Te),console.log(`[job] ${y.jobId} ${Z.name}: checked out delivery ${ee.deliverySha.slice(0,10)} for ${y.role}`)}}return D},Ks=[];if(y.role==="build"||y.role==="implement"||y.role==="code-review")try{Ks=await hu()}catch(O){let D=O instanceof Error?O.message:String(O);console.warn(`[job] ${y.jobId} delivery checkout failed: ${D}`),j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:`delivery checkout failed: ${D}`},startedAt:Ue,finishedAt:new Date().toISOString()}),N.dispose();return}let Hs=y.role==="resolve-conflict"?y.metadata?.mergeBranchByRepo??y.metadata?.taskBranchByRepo??{}:{},gu="";if(y.role==="resolve-conflict"){if(!fe.some(O=>Hs[O.name])){let O="resolve-conflict job carries no branch to merge for any repo \u2014 nothing to resolve. The task branch could not be identified on the hub (the apply step may have failed before recording it); make sure the task branch exists upstream, then retry the update.";console.warn(`[job] ${y.jobId} ${O}`),j||await A.submitResult({jobId:y.jobId,status:"failed",artifacts:[],error:{message:O},startedAt:Ue,finishedAt:new Date().toISOString()}),N.dispose();return}try{let O=[];for(let D of fe){let ee=Hs[D.name];if(!ee)continue;let Z=await Ol(D,ee,Te);console.log(`[job] ${y.jobId} ${D.name}: merged ${ee} into ${D.ref} \u2014 ${Z.length} conflicted file(s)`),Z.length>0?O.push(`- **${D.name}**:`,...Z.map(le=>` - \`${le}\``)):O.push(`- **${D.name}**: merged cleanly (no markers \u2014 verify it still builds)`)}gu=`
875
875
 
876
876
  ## Conflicts to resolve
877
877
 
@@ -972,7 +972,7 @@ Append-only. Keyed by entityId \u2014 never by path; entries survive renames.
972
972
  `)[0]:String(a)}) \u2014 posting as a plain comment`)}return await s.addPRComment(i,e.prNumber,`\u{1F4CD} \`${e.path}:${e.line}\`
973
973
 
974
974
  ${e.body}`),ue({prNumber:e.prNumber,inline:!1,host:s.name})}case"tracker_status":{let i=Rt({contextDir:t.contextDir});return i.ok?t.trackerIssueId?(await i.provider.updateStatus(t.trackerIssueId,e.newStatus),ue({issueId:t.trackerIssueId,newStatus:e.newStatus})):V("no tracker_issue_id provided"):V(i.error)}case"tracker_comment":{let i=Rt({contextDir:t.contextDir});if(!i.ok)return V(i.error);if(!t.trackerIssueId)return V("no tracker_issue_id provided");let s=await i.provider.addComment(t.trackerIssueId,e.body,e.author);return ue({issueId:t.trackerIssueId,commentId:s.id})}case"create_tracker_issue":{let i=Rt({contextDir:t.contextDir});if(!i.ok)return V(i.error);if(!e.projectKey)return V("no projectKey in create_tracker_issue action");let{id:s,key:a}=await i.provider.createIssue({projectKey:e.projectKey,title:e.title,body:e.body,targetStatus:e.targetStatus});return ue({issueKey:a,issueId:s})}case"apply_tracker_links":{let i=Rt({contextDir:t.contextDir});if(!i.ok)return V(i.error);let s=0;for(let a of e.links)try{await i.provider.applyLink(a.sourceIssueKey,a.rel,a.targetIssueKey),s++}catch(c){return V(`${c instanceof Error?c.message:String(c)} (applied ${s}/${e.links.length})`)}return ue({applied:s})}case"set_project_setting":{if(!t.contextDir)return V("no context repo clone on this CLI");let i=await Qf(t.contextDir,e.edits);return ue({files:i.files})}case"set_prompt_override":{if(!t.contextDir)return V("no context repo clone on this CLI");if(!Ma(e.role))return V(`unknown prompt operation: ${e.role}`);let i=Da(e.role);return await Ie(t.contextDir,[e.content===null?{path:i,content:"",deleted:!0}:{path:i,content:e.content}],e.commitMessage),t.requestConfigReport?.(),ue({path:i,reset:e.content===null})}case"tracker_edit":{let i=Rt({contextDir:t.contextDir});if(!i.ok)return V(i.error);if(!t.contextDir)return V("no context repo clone on this CLI");await i.provider.editIssue(e.issueKey,{...e.title!==void 0?{title:e.title}:{},...e.body!==void 0?{body:e.body}:{}});let s=await i.provider.getIssue(e.issueKey);return s&&await Xi(t.contextDir,e.projectId,[{issue:s,comments:[],attachments:[]}]),ue({issueKey:e.issueKey})}case"set_youtrack_config":{if(!t.contextDir)return V("no context repo clone on this CLI");let i=await am(t.contextDir,e);return ue({files:i.files})}case"set_repo_default_branch":{if(!t.contextDir)return V("no context repo clone on this CLI");let i=await im(t.contextDir,e);return ue({repoName:i.repoName,defaultBranch:i.defaultBranch})}case"sync_config":return t.requestConfigReport?(t.requestConfigReport(),ue({reported:!0})):V("no context repo clone on this CLI");case"refresh_context_status":{if(!t.refreshContextStatus)return V("no context repo clone on this CLI");let i=await t.refreshContextStatus();return ue({outdated:i.outdated,templateVersion:i.templateVersion})}case"run_action":{if(!t.contextDir)return V("no project workspace on this CLI");if(!r)return V("no repo spec");if(!t.onRunActivity)return V("no run-activity stream on this CLI");let i=t.onRunActivity,{defs:s,errors:a}=vi(t.contextDir),c=s.find(m=>m.id===e.actionId);if(!c){let m=a.find(f=>f.file===`actions/${e.actionId}.yml`);return V(m?`action "${e.actionId}" failed to parse: ${m.error}`:`unknown action "${e.actionId}"`)}let l=Ea(c,e.input);if(!l.ok)return V(l.error);let u=Jp(t.contextDir),p=q(e.projectId),d={};return p?.github?.token&&(d.GH_TOKEN=p.github.token),p?.gitlab?.token&&(d.GITLAB_TOKEN=p.gitlab.token),p?.bitbucket&&(d.BITBUCKET_EMAIL=p.bitbucket.email,d.BITBUCKET_API_TOKEN=p.bitbucket.apiToken),p?.youtrack&&(d.YOUTRACK_URL=p.youtrack.url,d.YOUTRACK_TOKEN=p.youtrack.token),Ao(`${e.projectId}/${r.name}`,async()=>{await nr(e.projectId,r,{baseDir:t.baseDir,cloneUrlOverride:t.cloneUrlOverride});let m=_e(e.projectId,r.name,t.baseDir),f=await Vf({cwd:m,def:c,input:l.values,variables:u,secrets:p?.secrets??{},credEnv:d,onEvent:g=>i(e.runId,g)});return ue({runId:e.runId,status:f.status,exitCode:f.exitCode,...f.failedStep?{failedStep:f.failedStep}:{}})})}case"read_context_file":{if(!t.contextDir)return V("no context repo clone on this CLI");let i=Zf(t.contextDir,e.path);return ue({path:e.path,...i})}case"search_model":{if(!t.contextDir)return V("no context repo clone on this CLI");let{searchModelIndex:i}=await Promise.resolve().then(()=>(Io(),Ro)),s=await i(t.contextDir,e.q,e.limit);return ue({hits:s})}case"model_drift":return V("model_drift requires a local workspace (handled by the daemon)");case"model_bootstrap":return V("model_bootstrap requires a local workspace (handled by the daemon)");default:return V(`unsupported action type: ${e.type}`)}}catch(i){return V(i instanceof Error?i.message:String(i))}}function ue(t){return{status:"done",result:t}}function V(t){return{status:"failed",error:t}}ut();ol();je();me();import{existsSync as xh,readFileSync as Sh}from"node:fs";import{join as Eh}from"node:path";async function Th(t,e,r,n){let o=i=>({type:"move_to_farm_result",requestId:e.requestId,projectId:t.projectId,ok:!1,error:i});try{if(e.projectId!==t.projectId)return o(`project mismatch: this daemon serves ${t.projectId}, not ${e.projectId}`);let i=Ke(e.farmPublicKey);if(i!==e.fingerprint)return o("farm key fingerprint does not match the confirmed one \u2014 refusing to seal (possible relay tampering)");Qi(e.farmId,e.farmPublicKey);let s=q(t.projectId);if(!s)return o("no secrets stored for this project on this CLI \u2014 cannot build the farm bundle");let a=await se(t.hubUrl,t.cliToken,t.projectId),c;if(r){let d=Eh(r,"project.yaml"),m=Eh(r,"regimen.yaml");xh(d)&&xh(m)?c={projectYaml:Sh(d,"utf-8"),regimenYaml:Sh(m,"utf-8")}:n.warn("[farm-move] local project.yaml/regimen.yaml not found \u2014 the farm will seed defaults")}let l={projectId:t.projectId,config:{hubUrl:t.hubUrl,cliToken:t.cliToken,projectId:t.projectId},secrets:{...s.github?{github:s.github}:{},...s.bitbucket?{bitbucket:s.bitbucket}:{},...s.gitlab?{gitlab:s.gitlab}:{},...s.youtrack?{youtrack:s.youtrack}:{},...s.claude?{claude:s.claude}:{},...s.contextWrite?{contextWrite:s.contextWrite}:{},...s.contextSsh?{contextSsh:s.contextSsh}:{}},...a.contextRepo?{contextRepo:a.contextRepo}:{},...c?{projectConfig:c}:{}},u=Bt(e.farmPublicKey,JSON.stringify(l));Zi(e.farmId,i),n.info(`[farm-move] bundle sealed for farm ${e.farmName} (${i}) \u2014 handing off`);let p=await ts(t.hubUrl,t.cliToken,e.farmId,{projectId:t.projectId,sealedBundle:u});return p.ok?{type:"move_to_farm_result",requestId:e.requestId,projectId:t.projectId,ok:!0,...p.daemonStatus?{daemonStatus:p.daemonStatus}:{}}:o(p.error??"farm provisioning failed")}catch(i){return o(i instanceof Error?i.message:String(i))}}B();ut();Fe();ut();import{homedir as nE}from"node:os";import{existsSync as oE,mkdirSync as iE,readFileSync as sE,writeFileSync as aE}from"node:fs";import{dirname as cE,join as lE}from"node:path";function al(){return X("RUNNER_PINS")??lE(nE(),".codepipe","runner-pins.json")}function Rh(){let t=al();if(!oE(t))return{};try{return JSON.parse(sE(t,"utf-8"))}catch{return{}}}function uE(t){let e=al();iE(cE(e),{recursive:!0}),aE(e,JSON.stringify(t,null,2)+`
975
- `,{mode:384})}function dE(t){return Rh()[t]}function cl(t,e){let r=Rh();r[t]=e,uE(r)}function Ih(t,e){let r=Ke(e),n=dE(t);if(n&&n!==r)throw new Error(`runner host ${t} key fingerprint changed (pinned ${n}, now ${r}) \u2014 refusing to seal. If the runner host was re-registered intentionally, remove its entry from ${al()}.`);return r}je();me();var Ph=t=>({Authorization:`Bearer ${t}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28","User-Agent":"codepipe-cli"});async function Ch(t,e,r,n){let o=await fetch(`https://api.github.com/repos/${e}/${r}/actions/runners/${n}`,{method:"POST",headers:Ph(t)});if(!o.ok)throw new Error(`github ${n} for ${e}/${r}: HTTP ${o.status}`);let i=await o.json();if(!i.token)throw new Error(`github ${n} for ${e}/${r}: no token in response`);return i.token}var pE={async repoHasAdmin(t,e,r){let n=await fetch(`https://api.github.com/repos/${e}/${r}`,{headers:Ph(t)});if(!n.ok)throw new Error(`github GET /repos/${e}/${r}: HTTP ${n.status}`);return(await n.json()).permissions?.admin===!0},mintRegistrationToken:(t,e,r)=>Ch(t,e,r,"registration-token"),mintRemoveToken:(t,e,r)=>Ch(t,e,r,"remove-token")},Ah={api:pE,fetchProject:se,provisionOnRunner:dh,teardownOnRunner:ph};async function _h(t,e,r){if(e.projectId!==t.projectId)throw new Error(`project mismatch: this daemon serves ${t.projectId}, not ${e.projectId}`);if(Ke(e.runnerPublicKey)!==e.fingerprint)throw new Error("runner host key fingerprint does not match the confirmed one \u2014 refusing to seal (possible relay tampering)");Ih(e.runnerId,e.runnerPublicKey);let i=q(t.projectId)?.github?.token;if(!i)throw new Error("no GitHub token stored for this project on this CLI");let a=((await r.fetchProject(t.hubUrl,t.cliToken,t.projectId)).repos??[]).find(c=>c.host==="github"&&c.owner===e.owner&&c.repoName===e.repo);if(!a)throw new Error(`${e.owner}/${e.repo} is not a GitHub repository of this project`);return{githubToken:i,repo:a}}async function jh(t,e,r,n=Ah){let o=i=>({type:"gh_runner_setup_result",requestId:e.requestId,projectId:t.projectId,ok:!1,error:i});try{let{githubToken:i,repo:s}=await _h(t,e,n);if(!await n.api.repoHasAdmin(i,s.owner,s.repoName))return o(`the GitHub token lacks admin access on ${s.owner}/${s.repoName} \u2014 replace it (project page \u2192 Tokens \u2192 Replace) with a token that has admin rights on this repository`);let a={projectId:t.projectId,runners:[{owner:s.owner,repo:s.repoName,regToken:await n.api.mintRegistrationToken(i,s.owner,s.repoName)}],labels:[Ha(e.runnerId)]},c=Bt(e.runnerPublicKey,JSON.stringify(a));cl(e.runnerId,e.fingerprint),r.info(`[ghr] registration token for ${s.owner}/${s.repoName} sealed for runner host ${e.runnerName} \u2014 handing off`);let l=await n.provisionOnRunner(t.hubUrl,t.cliToken,e.runnerId,{projectId:t.projectId,sealedBundle:c});return{type:"gh_runner_setup_result",requestId:e.requestId,projectId:t.projectId,ok:l.ok,...l.runners?{runners:l.runners}:{},...l.error?{error:l.error}:{}}}catch(i){return o(i instanceof Error?i.message:String(i))}}async function Nh(t,e,r,n=Ah){let o=i=>({type:"gh_runner_teardown_result",requestId:e.requestId,projectId:t.projectId,ok:!1,error:i});try{let{githubToken:i,repo:s}=await _h(t,e,n),a={owner:s.owner,repo:s.repoName};try{a.removeToken=await n.api.mintRemoveToken(i,s.owner,s.repoName)}catch(p){r.warn(`[ghr] remove-token for ${s.owner}/${s.repoName} failed (${p instanceof Error?p.message:p}) \u2014 the runner host will force-remove`)}let c={projectId:t.projectId,runners:[a]},l=Bt(e.runnerPublicKey,JSON.stringify(c));cl(e.runnerId,e.fingerprint),r.info(`[ghr] removal bundle for ${s.owner}/${s.repoName} sealed for runner host ${e.runnerName} \u2014 handing off`);let u=await n.teardownOnRunner(t.hubUrl,t.cliToken,e.runnerId,{projectId:t.projectId,sealedBundle:l,owner:s.owner,repo:s.repoName});return{type:"gh_runner_teardown_result",requestId:e.requestId,projectId:t.projectId,ok:u.ok,...u.error?{error:u.error}:{}}}catch(i){return o(i instanceof Error?i.message:String(i))}}je();B();ut();me();var Oh=16*1024;function fE(t){return Je.test(t)?Ot(t)?`secret name "${t}" is reserved`:null:`secret name must match ${Je}`}function Lh(t,e,r,n){let o=fE(e);if(o)return{ok:!1,detail:o};let i;try{let s=JSON.parse(fn(n,r).toString("utf-8"));if(typeof s.value!="string"||s.value.length===0)return{ok:!1,detail:"payload has no value"};i=s.value}catch(s){return{ok:!1,detail:`cannot open the sealed secret (${s instanceof Error?s.message:String(s)}) \u2014 wrong channel key?`}}if(i.length>Oh)return{ok:!1,detail:`secret value too large (max ${Oh} chars)`};try{return Vd(t,e,i),{ok:!0}}catch(s){return{ok:!1,detail:s instanceof Error?s.message:String(s)}}}function Mh(t,e){try{return Xd(t,e)?{ok:!0}:{ok:!0,detail:"no such secret (already absent)"}}catch(r){return{ok:!1,detail:r instanceof Error?r.message:String(r)}}}on();me();Vt();var ns=class{constructor(e,r,n){this.intervalMs=e;this.send=r;this.log=n}targets=new Map;lastSig=new Map;timer=null;running=!1;setTargets(e){this.targets.clear(),this.lastSig.clear();for(let r of e)this.targets.set(r.taskId,r);this.log.info(`[track] targets updated: ${this.targets.size} task(s)`)}start(){if(this.timer)return;this.log.info(`[track] poller started (interval=${this.intervalMs}ms)`);let e=()=>{this.tick().catch(r=>this.log.warn(`[track] tick crashed: ${r instanceof Error?r.message:String(r)}`))};e(),this.timer=setInterval(e,this.intervalMs)}stop(){this.timer&&(clearInterval(this.timer),this.timer=null,this.log.info("[track] poller stopped"))}async tickOnce(){await this.tick()}async tick(){if(!this.running){this.running=!0;try{for(let[e,r]of this.targets)await this.processTask(e,r)}finally{this.running=!1}}}async processTask(e,r){let n=[],o=e.split(":",2)[0]??"";for(let a of r.prs){let{spec:c,host:l}=po(o,a.repoSpec);try{let u=await l.getPullRequest(c,a.number);n.push({number:a.number,url:a.url,state:u.state,merged:u.merged,ci:u.ci,mergeable:u.mergeable})}catch(u){if(u instanceof Sr){this.log.warn(`[track] task=${e} pr=${a.url} not found \u2014 skipping tick for this task`);return}this.log.warn(`[track] task=${e} pr=${a.url} fetch failed: ${u instanceof Error?u.message:String(u)}`);return}}let i=n.map(a=>`${a.number}:${a.state}:${a.merged?1:0}:${a.ci}:${a.mergeable}`).join("|");if(this.lastSig.get(e)===i)return;for(let a=0;a<n.length;a++){let c=n[a];if(c.ci!=="failed")continue;let{spec:l,host:u}=po(o,r.prs[a].repoSpec);if(u.getCiFailureLog)try{let p=await u.getCiFailureLog(l,c.number);p&&(c.ciFailureLog=p)}catch(p){this.log.warn(`[track] task=${e} pr=${c.url} ci-log fetch failed: ${p instanceof Error?p.message:String(p)}`)}}this.send({type:"pr_state_observed",taskId:e,prs:n}),this.lastSig.set(e,i);let s=mE(n);this.log.info(`[track] task=${e} snapshot signalled${s?` \u2192 ${s}`:""} (${n.length} PR(s))`)}};function mE(t){return t.length===0?null:t.some(e=>e.state==="closed"&&!e.merged)?"needs_manual":t.every(e=>e.merged)?"done":null}B();var os=class t{constructor(e,r,n,o={contextDir:null}){this.intervalMs=e;this.send=r;this.log=n;this.options=o}request=null;timer=null;running=!1;warnedMissingCfg=!1;shippedAttachments=new Set;abandonedTicks=0;static MAX_ABANDONED_TICKS=3;setRequest(e){let r=this.request?.projectId;this.request=e,this.log.info(`[yt-sync] request updated: project=${e.projectKey} columns=[${e.sourceColumns.join(",")}] sinceMs=${e.sinceMs} offBoard=${e.offBoardIssueIds.length}`),this.timer||this.start(),r&&r!==e.projectId&&this.log.info(`[yt-sync] project switch ${r} \u2192 ${e.projectId}`)}start(){if(this.timer)return;this.log.info(`[yt-sync] poller started (interval=${this.intervalMs}ms)`);let e=()=>{this.tick().catch(r=>this.log.warn(`[yt-sync] tick crashed: ${r instanceof Error?r.message:String(r)}`))};e(),this.timer=setInterval(e,this.intervalMs)}stop(){this.timer&&(clearInterval(this.timer),this.timer=null,this.log.info("[yt-sync] poller stopped"))}async tickOnce(){await this.tick()}async forceSync(){if(!this.request){this.log.info("[yt-sync] force requested but no sync_request yet \u2014 ignored");return}this.log.info("[yt-sync] force sync requested (manual)"),await this.tick()}async tick(){if(this.running||!this.request)return;let r=(this.options.resolveProvider??(()=>Rt({contextDir:this.options.contextDir})))();if(!r.ok){this.warnedMissingCfg||(this.warnedMissingCfg=!0,this.log.warn(`[yt-sync] tracker provider unavailable (${r.error}) \u2014 poller idle.`));return}this.warnedMissingCfg=!1,this.running=!0;try{await this.pollOnce(this.request,r.provider)}finally{this.running=!1}}async pollOnce(e,r){let n=Date.now(),o;try{let $=e.stageField?{stageField:e.stageField}:{},S=e.requireAssignee&&e.assignee?{assignee:e.assignee}:e.requireAssignee&&!e.assignee?{requireAnyAssignee:!0}:{},v=(e.backlogScope??"personal")==="shared"&&!!e.requireAssignee&&!!e.backlogColumn;if(r.kind==="internal")o=await r.listIssues({projectKey:e.projectKey});else if(v){let b=[...new Set([...e.sourceColumns,...e.rejectColumns??[],...e.doneColumns??[],...e.reviewColumns??[]])],[R,_]=await Promise.all([b.length>0?r.listIssues({projectKey:e.projectKey,columns:b,...$,...S}):Promise.resolve([]),r.listIssues({projectKey:e.projectKey,columns:[e.backlogColumn],...$})]),G=new Map;for(let z of[...R,..._])G.set(z.id,z);o=[...G.values()]}else{let b=[...new Set([...e.sourceColumns,...e.rejectColumns??[],...e.doneColumns??[],...e.reviewColumns??[],...e.backlogColumn?[e.backlogColumn]:[]])];o=await r.listIssues({projectKey:e.projectKey,columns:b,...$,...S})}}catch($){let S=$ instanceof Error?$.message:String($);S.includes("stage_field")?this.log.warn(`[yt-sync] CONFIGURATION ERROR \u2014 ${S}`):this.log.warn(`[yt-sync] listIssues failed: ${S}`);return}let i=new Map,s=new Set,a=new Set(e.doneColumns??[]);for(let $ of o){if(s.add($.id),a.has($.status))continue;let S=await Bh(r,$.id,e.sinceMs,this.log);S&&i.set($.id,S)}let c=[];for(let $ of e.offBoardIssueIds){if(s.has($))continue;let S=await Bh(r,$,e.sinceMs,this.log);if(S&&S.length>0&&i.set($,S),e.requireAssignee||S&&S.length>0){let T=await Uh(r,$,e.stageField,this.log);if(T)c.push(T);else if(S&&S.length>0){this.abandonTick("off-board issue fetch failed with new comments");return}}}let l=o.filter($=>!a.has($.status)),{attachmentsByIssue:u,attachmentKeys:p}=await this.collectAttachments(l,i,r);if(!this.options.contextDir){this.abandonTick("no Context Repo clone (headless / clone failed) \u2014 cannot deliver task content");return}let d=[...l,...c].map($=>({issue:$,comments:i.get($.id)??[],attachments:u.get($.id)??[]}));d.push(...await th(this.options.contextDir,d,$=>Uh(r,$,e.stageField,this.log)));try{await Xi(this.options.contextDir,e.projectId,d),this.abandonedTicks=0;for(let $ of p)this.shippedAttachments.add($)}catch($){let S=$ instanceof Error?$.message:String($);this.abandonTick(`context task sync failed: ${S}`);return}let m=this.options.isSelfComment??(()=>!1),f=[],g=[];for(let[$,S]of i){let T=S.filter(b=>!m(b.id));if(T.length===0)continue;f.push({issueId:$,comments:T.map(hE)});let v=T.flatMap(b=>{let R=$r(b.body);return R?[{commentId:b.id,author:b.author,name:R.name,args:R.args,createdAt:b.createdAt}]:[]});v.length>0&&g.push({issueId:$,commands:v})}let k={type:"youtrack_observation",projectId:e.projectId,issues:o.map(Dh),commentsBatch:f,...g.length>0?{commandsBatch:g}:{},...e.requireAssignee&&c.length>0?{offBoardIssues:c.map(Dh)}:{},observedAtMs:n};this.send(k);let h=f.reduce(($,S)=>$+S.comments.length,0),w=g.reduce(($,S)=>$+S.commands.length,0);this.log.info(`[yt-sync] observation sent: issues=${o.length} comments=${h} commands=${w} (sinceMs=${e.sinceMs})`)}abandonTick(e){this.abandonedTicks++,this.abandonedTicks<=t.MAX_ABANDONED_TICKS?this.log.warn(`[yt-sync] ${e} \u2014 tick abandoned (${this.abandonedTicks}/${t.MAX_ABANDONED_TICKS}), will retry`):this.log.warn(`[yt-sync] ERROR: ${e} \u2014 still failing after ${this.abandonedTicks} ticks; the project is STALLED until the Context Repo clone is restored`)}async collectAttachments(e,r,n){let o=new Map,i=[];for(let s of e){let a=[...s.attachments??[]];for(let u of r.get(s.id)??[])a.push(...u.attachments??[]);if(a.length===0)continue;let c=[],l=new Set;for(let u of a){let p=`${s.id}:${u.id}`;if(this.shippedAttachments.has(p))continue;let d;try{d=await n.downloadAttachment(u.url)}catch(f){this.log.warn(`[yt-sync] attachment ${u.name} (${s.id}) download failed: ${f instanceof Error?f.message:String(f)}`);continue}let m=gE(u.name);l.has(m)&&(m=`${u.id}-${m}`),l.add(m),c.push({name:m,contentBase64:d.toString("base64")}),i.push(p)}c.length>0&&o.set(s.id,c)}return{attachmentsByIssue:o,attachmentKeys:i}}};function Dh(t){let{description:e,...r}=t;return r}function hE(t){let{body:e,...r}=t;return r}function gE(t){let r=(t.split(/[\\/]/).pop()??t).replace(/[^A-Za-z0-9._-]/g,"_").replace(/^\.+/,"");return r.length>0?r.slice(0,120):"attachment"}async function Uh(t,e,r,n){try{return await t.getIssue(e,r)}catch(o){return n.warn(`[yt-sync] getIssue ${e} failed: ${o instanceof Error?o.message:String(o)}`),null}}async function Bh(t,e,r,n){try{return await t.listComments(e,r)}catch(o){return n.warn(`[yt-sync] listComments ${e} failed: ${o instanceof Error?o.message:String(o)}`),null}}async function OE(t,e){let r=t.repos.filter(i=>i.mirror);if(r.length===0)return[];let{mirrorLag:n}=await Promise.resolve().then(()=>(dl(),ul)),o=[];for(let i of r){let s=i.mountAs==="."?t.root:Ar(t.root,i.mountAs);try{o.push({repo:i.name,behind:await n(i,s)})}catch(a){e.warn(`[mirror] lag for ${i.name} unknown: ${a instanceof Error?a.message:String(a)}`),o.push({repo:i.name,behind:null})}}return o}var vl="npm i -g @code-partner/codepipe@latest";function ls(t,e={}){let r=e.log??{info:h=>console.log(h),warn:h=>console.warn(h)};r.info(`codepipe-cli v${Ve} (protocol ${ht})`);let n=h=>e.onEvent?.(h),o=e.workspace;o?.contextDir&&ef(o.contextDir,r);let i=()=>{if(o?.contextDir)try{ln(o.contextDir,o.root,r)}catch(h){r.warn(`[skills] materialize failed (non-fatal): ${h instanceof Error?h.message:String(h)}`)}};i();let s=rg("CLI_TRACKING_POLL_INTERVAL_SEC"),a=rg("CLI_YOUTRACK_POLL_INTERVAL_SEC"),c=(()=>{let h=parseInt(process.env.CLI_READINESS_INTERVAL_SEC??"600",10);return Number.isFinite(h)&&h>0?h*1e3:6e5})(),l=!1,u=!1,p=!1,d=new Set,m=!1,f=new Set,g=k();function k(){let h=es(t.hubUrl,t.cliToken),w=null,$=new ns(s,L=>{h.readyState===h.OPEN&&h.send(JSON.stringify(L))},r),S=new os(a,L=>{h.readyState===h.OPEN&&h.send(JSON.stringify(L))},r,{contextDir:o?.contextDir??null,isSelfComment:L=>f.has(L)}),T=null,v=async()=>{try{let L={trackerProvider:rl(o?.contextDir??null)};try{let E=await se(t.hubUrl,t.cliToken,t.projectId);L={...L,repos:E.repos,contextRepo:E.contextRepo}}catch(E){r.warn(`[readiness] could not fetch project summary for push checks: ${E instanceof Error?E.message:String(E)}`)}let F=await Up(t.projectId,L),M=o?await OE(o,r):[];if(i(),h.readyState!==h.OPEN)return;let Y={type:"cli_readiness",projectId:t.projectId,ready:F.ready,checks:F.checks,creds:F.creds,secretNames:Jd(t.projectId),...o?{mirrors:M}:{},checkedAt:F.checkedAt};if(h.send(JSON.stringify(Y)),F.ready)r.info("[readiness] ready");else{let E=F.checks.filter(I=>!I.ok).map(I=>`${I.name}(${I.detail??""})`);r.warn(`[readiness] NOT ready \u2014 ${E.join(", ")}`)}let W=Wp(F.creds,p);if(W==="open"){p=!0;let E=qp(t.hubUrl,t.projectId);r.info(`[agent-auth] Claude token invalid (401) \u2014 opening the dashboard to re-authorize: ${E}`),Rr(E)}else W==="rearm"&&(p=!1)}catch(L){r.warn(`[readiness] check failed: ${L instanceof Error?L.message:String(L)}`)}},b=()=>{v(),T=setInterval(()=>void v(),c),typeof T.unref=="function"&&T.unref()},R=()=>{T&&(clearInterval(T),T=null)},_=150,G=new Map,z=L=>{let F=G.get(L);if(!F||(F.timer&&clearTimeout(F.timer),G.delete(L),F.events.length===0||h.readyState!==h.OPEN))return;let M={type:"run_activity",projectId:t.projectId,runId:L,events:F.events};h.send(JSON.stringify(M))},A=(L,F)=>{let M=G.get(L);if(M||(M={events:[],timer:null},G.set(L,M)),M.events.push(F),F.kind==="result"){z(L);return}M.timer||(M.timer=setTimeout(()=>z(L),_),M.timer.unref?.())},y=o?.contextDir?new xi(o.contextDir,t.projectId,L=>{h.readyState===h.OPEN&&h.send(JSON.stringify(L))},r):null,U=async()=>{let L=o?.contextDir;if(!L)throw new Error("no context repo clone on this CLI");let F;try{F=(await se(t.hubUrl,t.cliToken,t.projectId)).contextRepo}catch{}let M=await Tf(L,t.projectId,F,r);return h.readyState===h.OPEN&&h.send(JSON.stringify(M)),M},j=null,H=async()=>{let L=o?.contextDir;if(L)try{let{readContextIndexHub:F,collectSearchRows:M}=await Promise.resolve().then(()=>(Io(),Ro));if(F(L)!=="metadata")return;let Y=M(L);h.readyState===h.OPEN&&(h.send(JSON.stringify({type:"model_index",projectId:t.projectId,rows:Y})),r.info(`[model] tier-2 index snapshot pushed (${Y.length} rows)`))}catch(F){r.warn(`[model] tier-2 index push failed (non-fatal): ${F instanceof Error?F.message:String(F)}`)}},J=()=>{j&&clearTimeout(j),j=setTimeout(()=>void H(),5e3)},oe=null,At=async L=>{if(o?.contextDir)try{let{rebuildWorkspaceModelIfStale:F}=await Promise.resolve().then(()=>(Oo(),cs));(await F({root:o.root,contextDir:o.contextDir,repos:o.repos},{fetch:L,onLog:Y=>r.info(Y)})).rebuilt.length>0&&J()}catch(F){r.warn(`[model] release-path rebuild failed (non-fatal): ${F instanceof Error?F.message:String(F)}`)}},pt=L=>{oe&&clearTimeout(oe),oe=setTimeout(()=>void At(L),6e4)},Ue=setInterval(()=>void At(!0),6*36e5);return h.on("open",()=>{r.info("[ws] connected"),n({kind:"connected"});let L=ip(t.projectId),F=X("ORIGIN")==="farm"?"farm":"local",M=X("FARM_ID"),Y=t.accountEmail??L.email,W;try{let I=Wf(t.projectId);I&&(W=I.publicKey,r.info(`[cred-channel] key fingerprint: ${I.fingerprint}`))}catch(I){r.warn(`[cred-channel] key setup failed (token replacement via dashboard unavailable): ${I instanceof Error?I.message:String(I)}`)}let E={type:"register",projectId:t.projectId,platformVersion:Ve,protocolVersion:ht,accountId:L.accountId,accountLabel:L.label,origin:F,inFlightActionIds:[...d],...Y?{accountEmail:Y}:{},...F==="farm"&&M?{farmId:M}:{},...W?{sealPublicKey:W}:{}};h.send(JSON.stringify(E))}),h.on("message",async L=>{let F=L.toString("utf-8");if(F==="pong"||F==="ping")return;let M;try{M=JSON.parse(F)}catch{return}if(!M||typeof M!="object")return;let Y=M.type;if(Y==="registered"){let E=M;if(E.ok){if(r.info(`[ws] registered for project ${E.projectId}`),n({kind:"registered",projectId:E.projectId??t.projectId}),$.start(),y?.start(),b(),xl(t,o,r),o?.contextDir){try{let I=Ci(o.contextDir,t.projectId);h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.outdated&&(r.warn(`[ctx] context format outdated: v${I.templateVersion} \u2192 v${I.currentVersion}`+(I.missingPaths.length>0?` (missing: ${I.missingPaths.join(", ")})`:"")),u||(u=!0,U().catch(()=>{})))}catch(I){r.warn(`[ctx] context-format detect failed (non-fatal): ${I instanceof Error?I.message:String(I)}`)}H(),pt(!0)}}else r.warn(`[ws] register rejected: ${E.reason??"unknown"}`),n({kind:"register_rejected",reason:E.reason??"unknown"}),l=!0,h.close();return}if(Y==="hello"){let E=M;w=Vn(E.protocolVersion);let I=w?"compatible":"INCOMPATIBLE";r.info(`[ws] hub v${E.platformVersion} (protocol ${E.protocolVersion}) \u2014 ${I}`),w||(r.warn(`[ws] HUB protocol incompatible with this CLI (v${Ve}, protocol ${ht}) \u2014 WriteActions will be refused until versions align.`),r.warn(`[ws] update the CLI: ${vl}`),n({kind:"incompatible",hubVersion:typeof E.platformVersion=="string"?E.platformVersion:null,hubProtocol:typeof E.protocolVersion=="number"?E.protocolVersion:null,updateCommand:vl}));return}if(Y==="tracking_targets"){$.setTargets(M.targets);return}if(Y==="youtrack_sync_request"){S.setRequest(M);return}if(Y==="youtrack_force_sync"){S.forceSync();return}if(Y==="sync_local"){await DE(M,o,h,r);return}if(Y==="provision_repo"){let E=M;r.info(`[repo] provision_repo: ${E.repo.name} (${E.repo.host}:${E.repo.owner}/${E.repo.repoName})`),await LE(t,o,E.repo,r),await xl(t,o,r);return}if(Y==="remove_repo"){let E=M;r.info(`[repo] remove_repo: ${E.repoName}${E.purge?" (purge)":""}`),await xl(t,o,r),E.purge&&ME(t,o,E.repoName,r);return}if(Y==="context_write"){await UE(M,o,h,r),i();return}if(Y==="adr_promote"){await BE(M,o,h,r),i();return}if(Y==="cred_update"){let E=M,I=q(t.projectId),Q=I?.sealKey?await qf(t.projectId,E.kind,E.sealed,I.sealKey.privateKey):{ok:!1,detail:"no cred-channel key on this CLI (restart the daemon)"},ie={type:"cred_update_result",updateId:E.updateId,projectId:t.projectId,ok:Q.ok,...Q.detail?{detail:Q.detail}:{}};h.readyState===h.OPEN&&h.send(JSON.stringify(ie)),Q.ok?(r.info(`[cred] ${E.kind} replaced${Q.detail?` \u2014 ${Q.detail}`:""}`),v()):r.warn(`[cred] ${E.kind} replacement rejected: ${Q.detail??"unknown"}`);return}if(Y==="readiness_check"){r.info("[readiness] on-demand check requested"),v();return}if(Y==="agent_login_start"){Hp(t,h,M,r,v);return}if(Y==="move_to_farm"){let E=M;r.info(`[farm-move] request to move ${t.projectId} onto farm ${E.farmName} (${E.farmId})`);let I=await Th(t,E,o?.contextDir,r);h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.ok?r.info(`[farm-move] done \u2014 farm daemon ${I.daemonStatus??"started"}; expecting takeover`):r.warn(`[farm-move] failed: ${I.error??"unknown error"}`);return}if(Y==="gh_runner_setup"){let E=M;r.info(`[ghr] runner setup for ${t.projectId} on runner host ${E.runnerName} (${E.runnerId})`);let I=await jh(t,E,r);h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.ok?r.info(`[ghr] runners connected on ${E.runnerName}`):r.warn(`[ghr] setup failed: ${I.error??"see per-repo statuses"}`);return}if(Y==="gh_runner_teardown"){let E=M;r.info(`[ghr] runner teardown for ${t.projectId} on runner host ${E.runnerName} (${E.runnerId})`);let I=await Nh(t,E,r);h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.ok?r.info(`[ghr] runners disconnected from ${E.runnerName}`):r.warn(`[ghr] teardown failed: ${I.error??"unknown error"}`);return}if(Y==="tracker_fields_request"){let E=M,I={type:"tracker_fields_result",requestId:E.requestId,projectId:t.projectId,ok:!1},Q=Rt({contextDir:o?.contextDir??null});if(!Q.ok)I.error=Q.error;else try{I.fields=await Q.provider.fetchStateFields(E.projectKey),I.ok=!0}catch(ie){I.error=ie instanceof Error?ie.message:String(ie)}h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.ok||r.warn(`[yt-fields] listing failed: ${I.error??"unknown"}`);return}if(Y==="project_secret_update"||Y==="project_secret_delete"){let E=M,I;if(E.type==="project_secret_update"){let ie=q(t.projectId);I=ie?.sealKey?Lh(t.projectId,E.name,E.sealed,ie.sealKey.privateKey):{ok:!1,detail:"no cred-channel key on this CLI (restart the daemon)"}}else I=Mh(t.projectId,E.name);let Q={type:"project_secret_update_result",updateId:E.updateId,projectId:t.projectId,ok:I.ok,...I.detail?{detail:I.detail}:{}};h.readyState===h.OPEN&&h.send(JSON.stringify(Q)),I.ok?(r.info(`[secret] ${E.name} ${E.type==="project_secret_update"?"saved":"deleted"}`+(I.detail?` \u2014 ${I.detail}`:"")),v()):r.warn(`[secret] ${E.name} rejected: ${I.detail??"unknown"}`);return}if(Y==="sandbox_keys"){let E=q(t.projectId);if(!E){r.warn(`[cred] sandbox_keys received but no secrets for ${t.projectId} \u2014 cannot seal`);return}let I=en(t.projectId),Q=Ff(M,E,I,r);for(let ie of Q)h.readyState===h.OPEN&&h.send(JSON.stringify(ie));return}if(Y!=="dispatch_action")return;let W=M;if(w===!1){let E=`refused: HUB protocol incompatible with CLI v${Ve} (protocol ${ht})`;h.send(JSON.stringify({type:"action_result",actionId:W.actionId,status:"failed",error:E})),r.warn(`[exec] ${W.actionId} (${W.action.type}) \u2192 REFUSED: ${E}`),r.warn(`[exec] update the CLI to clear this: ${vl}`),n({kind:"action",actionId:W.actionId,actionType:W.action.type,ok:!1,error:E});return}if(W.action.type==="model_drift"){d.add(W.actionId);try{let E,I=o?.repos.find(Q=>Q.name===W.action.repoName);if(!o?.contextDir||!I)E={status:"failed",error:"no local workspace/repo clone on this CLI"};else try{let{computeDriftReport:Q}=await Promise.resolve().then(()=>(tg(),eg)),ie=I.mountAs==="."?o.root:Ar(o.root,I.mountAs);E={status:"done",result:{report:await Q(ie,o.contextDir,I.name)}}}catch(Q){E={status:"failed",error:Q instanceof Error?Q.message:String(Q)}}h.send(JSON.stringify({type:"action_result",actionId:W.actionId,...E}))}finally{d.delete(W.actionId)}return}if(W.action.type==="model_bootstrap"){d.add(W.actionId);try{let E;if(!o?.contextDir)E={status:"failed",error:"no Context Repo clone on this CLI"};else if(m)E={status:"failed",error:"model bootstrap is already running"};else{m=!0;try{let I=await se(t.hubUrl,t.cliToken,t.projectId),{bootstrapDaemonModel:Q}=await Promise.resolve().then(()=>(Oo(),cs)),ie=await Q(t.projectId,{root:o.root,contextDir:o.contextDir},I.repos,P=>r.info(`[model] ${P}`));r.info(`[model] bootstrap done: ${ie.repos} repos, ${ie.events} task events`),J(),E={status:"done",result:{repos:ie.repos,events:ie.events}}}catch(I){E={status:"failed",error:I instanceof Error?I.message:String(I)},r.warn(`[model] bootstrap failed: ${E.error}`)}finally{m=!1}}h.readyState===h.OPEN&&h.send(JSON.stringify({type:"action_result",actionId:W.actionId,...E}))}finally{d.delete(W.actionId)}return}d.add(W.actionId);try{let E=await ch({action:W.action,repo:W.repo,trackerIssueId:W.trackerIssueId,contextDir:o?.contextDir,requestConfigReport:y?()=>y.reportNow():void 0,refreshContextStatus:o?.contextDir?U:void 0,onRunActivity:A}).catch(ie=>({status:"failed",error:ie instanceof Error?ie.message:String(ie)}));W.action.type==="tracker_comment"&&E.status==="done"&&"result"in E&&typeof E.result?.commentId=="string"&&f.add(E.result.commentId),h.send(JSON.stringify({type:"action_result",actionId:W.actionId,...E}));let I=E.status!=="failed",Q=!I&&"error"in E?E.error:void 0;I?r.info(`[exec] ${W.actionId} (${W.action.type}) \u2192 done`):r.warn(`[exec] ${W.actionId} (${W.action.type}) \u2192 FAILED: ${Q??"?"}`),n({kind:"action",actionId:W.actionId,actionType:W.action.type,ok:I,...Q?{error:Q}:{}}),I&&["apply_delivery","context_write","create_pr"].includes(W.action.type)&&J(),I&&["merge_pr","merge_branch"].includes(W.action.type)&&pt(!0)}finally{d.delete(W.actionId)}}),h.on("close",(L,F)=>{let M=F?.toString("utf-8")??"";if(r.info(`[ws] closed code=${L}${M?` reason=${M}`:""}`),$.stop(),S.stop(),y?.stop(),R(),clearInterval(Ue),oe&&clearTimeout(oe),j&&clearTimeout(j),M==="replaced"){l=!0,r.warn(`[ws] project ${t.projectId} was taken over by another CLI (HUB closed us as "replaced") \u2014 standing down, not reconnecting. Run exactly ONE CLI per project.`),n({kind:"replaced"});return}n({kind:"disconnected",code:L}),!l&&setTimeout(()=>{g=k()},2e3)}),h.on("error",L=>r.warn(`[ws] error: ${L.message}`)),h}return{stop(){l=!0,g.close()}}}async function xl(t,e,r){try{let n=await se(t.hubUrl,t.cliToken,t.projectId),{updated:o,errors:i}=bo(t.projectId,n.repos,e?.contextDir);for(let s of o)r.info(`[repo] restaged repo set in ${s}`);for(let s of i)r.warn(`[repo] could not restage ${s.path}: ${s.error}`)}catch(n){r.warn(`[repo] repo-set reconcile skipped: ${n instanceof Error?n.message:String(n)}`)}}async function LE(t,e,r,n){let o=r.mountAs??r.name;if(o==="."){n.info(`[repo] ${r.name} mounts in place (mount_as: .) \u2014 nothing to clone`);return}let i=e?Ar(e.root,o):_e(t.projectId,r.name);if(ng(Ar(i,".git"))){n.info(`[repo] ${r.name} already present at ${i}`);return}try{await NE().clone(e?ji(r):Nc(r),i),n.info(`[repo] cloned ${r.name} \u2192 ${i}`)}catch(s){n.warn(`[repo] clone of ${r.name} failed (will retry lazily): ${s instanceof Error?s.message.trim():String(s)}`)}}function ME(t,e,r,n){let o=e?.repos.find(s=>s.name===r)?.mountAs??r,i=e?Ar(e.root,o):_e(t.projectId,r);if(e&&i===e.root){n.warn(`[repo] ${r} maps to the workspace root \u2014 skipping purge`);return}if(!ng(Ar(i,".git"))){n.info(`[repo] no local clone to purge for ${r} (${i})`);return}try{jE(i,{recursive:!0,force:!0}),n.info(`[repo] purged local clone ${i}`)}catch(s){n.warn(`[repo] purge of ${i} failed: ${s instanceof Error?s.message:String(s)}`)}}async function DE(t,e,r,n){if(!e){n.info(`[sync] sync_local for ${t.taskId} \u2014 no workspace (headless), skipped`);return}for(let o of t.repos){let i=e.repos.find(l=>l.name===o.repoName),s=Ar(e.root,i?.mountAs??o.repoName),a=i?.defaultBranch??o.defaultBranch,c=await Yp(s,a).catch(l=>({status:"warn",reason:l instanceof Error?l.message:String(l)}));c.status==="updated"?n.info(`[sync] ${o.repoName}: fast-forwarded ${a} \u2192 origin`):c.status==="skipped"?n.info(`[sync] ${o.repoName}: not cloned in workspace \u2014 skipped`):(n.warn(`[sync] ${o.repoName}: ${c.reason??"sync skipped"}`),r.readyState===r.OPEN&&r.send(JSON.stringify({type:"local_sync_warning",taskId:t.taskId,repoName:o.repoName,reason:c.reason??"sync skipped"})))}}async function UE(t,e,r,n){let o=(i,s)=>{if(r.readyState!==r.OPEN)return;let a={type:"context_write_result",id:t.id,status:i};s&&(a.error=s),r.send(JSON.stringify(a))};if(!e?.contextDir){n.warn(`[ctx] context_write ${t.id} \u2014 no .codepipe clone (headless), reporting failed`),o("failed","no context repo clone on this CLI");return}try{await Ie(e.contextDir,t.files,t.message),n.info(`[ctx] context_write ${t.id}: committed ${t.files.length} file(s)`),o("done")}catch(i){let s=i instanceof Error?i.message:String(i);n.warn(`[ctx] context_write ${t.id} failed: ${s}`),o("failed",s)}}async function BE(t,e,r,n){let o=(i,s)=>{if(r.readyState!==r.OPEN)return;let a={type:"context_write_result",id:t.id,status:i};s&&(a.error=s),r.send(JSON.stringify(a))};if(!e?.contextDir){n.warn(`[adr] adr_promote ${t.id} \u2014 no .codepipe clone (headless), reporting failed`),o("failed","no context repo clone on this CLI");return}try{let i=t.source??"task",s=await cf(e.contextDir,t.taskKey,t.slugs,void 0,i);if(n.info(`[adr] adr_promote ${t.id}: promoted ${s.promoted.length}, skipped ${s.skipped.length}`+(s.promoted.length>0?` (${s.promoted.join(", ")})`:"")),s.missing.length>0){let a=l=>i==="staging"?`adr/DRAFT-${l}.md`:`tasks/${t.taskKey}/adr/DRAFT-${l}.md`,c=`draft file(s) missing in clone: ${s.missing.map(a).join(", ")}`;n.warn(`[adr] adr_promote ${t.id}: ${c}`),o("failed",c);return}o("done")}catch(i){let s=i instanceof Error?i.message:String(i);n.warn(`[adr] adr_promote ${t.id} failed: ${s}`),o("failed",s)}}function rg(t){let e=parseInt(process.env[t]??"60",10);return Number.isFinite(e)&&e>0?e*1e3:6e4}je();me();Ut();El();it();Oi();async function hg(t={profile:void 0}){let{cfg:e,profile:r}=Qr(t.profile),n=q(e.projectId);n&&uo(n),vo(n?.github?.token??process.env.GH_TOKEN)&&console.log("[git] github.com over token-HTTPS (insteadOf) \u2014 farm transport"),xo(n?.gitlab?.token??process.env.GITLAB_TOKEN)&&console.log("[git] gitlab.com over token-HTTPS (insteadOf) \u2014 farm transport"),So(n?.bitbucket?.apiToken||process.env.BITBUCKET_API_TOKEN)&&console.log("[git] bitbucket.org over token-HTTPS (insteadOf) \u2014 farm transport");let o=Lo(Tl(),".codepipe","logs"),i=r?`cli-daemon-${r}`:"cli-daemon",s=mi("CLI_LOG",i,o);if(s.enabled){let d=new rn(s);hi(d),console.log(`[log] file logging \u2192 ${d.path} (rotate at ${s.maxBytes}B, keep ${s.maxFiles})`)}console.log(`codepipe daemon \u2192 ${e.hubUrl} (project=${e.projectId})`);let a=null,c=Jr(e.projectId);if(c&&(a={root:c.root,contextDir:c.contextDir,repos:c.spec.repos},console.log(`[ctx] workspace found at ${c.root} \u2014 using its Context Repo clone`)),!a){let d=Lo(Tl(),".codepipe",r?Lo("profiles",r,"context"):"context");if(await sl(e.hubUrl,e.cliToken,e.projectId,{phase:"context_cloning"}).catch(()=>{}),a=await fg(()=>ds({cfg:e,secrets:n,contextDir:d,log:{info:m=>console.log(m),warn:m=>console.warn(m)}}),{log:{warn:m=>console.warn(m)}}),a||await sl(e.hubUrl,e.cliToken,e.projectId,{phase:"context_cloning",error:"could not clone the Context Repo \u2014 check the context credentials (the daemon continues without config reporting)"}).catch(()=>{}),a?.contextDir){let m=Lo(Tl(),".codepipe",r?Lo("profiles",r,"context-config"):"context-config");Si(a.contextDir,m,{info:f=>console.log(f),warn:f=>console.warn(f)})}}let l=ls(e,{...a?{workspace:a}:{},onEvent:d=>{d.kind==="replaced"&&(console.error(`[daemon] project ${e.projectId} is now served by another CLI \u2014 exiting. Run exactly one CLI per project.`),process.exit(0))}}),u=!1;function p(d){u||(u=!0,console.log(`
975
+ `,{mode:384})}function dE(t){return Rh()[t]}function cl(t,e){let r=Rh();r[t]=e,uE(r)}function Ih(t,e){let r=Ke(e),n=dE(t);if(n&&n!==r)throw new Error(`runner host ${t} key fingerprint changed (pinned ${n}, now ${r}) \u2014 refusing to seal. If the runner host was re-registered intentionally, remove its entry from ${al()}.`);return r}je();me();var Ph=t=>({Authorization:`Bearer ${t}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28","User-Agent":"codepipe-cli"});async function Ch(t,e,r,n){let o=await fetch(`https://api.github.com/repos/${e}/${r}/actions/runners/${n}`,{method:"POST",headers:Ph(t)});if(!o.ok)throw new Error(`github ${n} for ${e}/${r}: HTTP ${o.status}`);let i=await o.json();if(!i.token)throw new Error(`github ${n} for ${e}/${r}: no token in response`);return i.token}var pE={async repoHasAdmin(t,e,r){let n=await fetch(`https://api.github.com/repos/${e}/${r}`,{headers:Ph(t)});if(!n.ok)throw new Error(`github GET /repos/${e}/${r}: HTTP ${n.status}`);return(await n.json()).permissions?.admin===!0},mintRegistrationToken:(t,e,r)=>Ch(t,e,r,"registration-token"),mintRemoveToken:(t,e,r)=>Ch(t,e,r,"remove-token")},Ah={api:pE,fetchProject:se,provisionOnRunner:dh,teardownOnRunner:ph};async function _h(t,e,r){if(e.projectId!==t.projectId)throw new Error(`project mismatch: this daemon serves ${t.projectId}, not ${e.projectId}`);if(Ke(e.runnerPublicKey)!==e.fingerprint)throw new Error("runner host key fingerprint does not match the confirmed one \u2014 refusing to seal (possible relay tampering)");Ih(e.runnerId,e.runnerPublicKey);let i=q(t.projectId)?.github?.token;if(!i)throw new Error("no GitHub token stored for this project on this CLI");let a=((await r.fetchProject(t.hubUrl,t.cliToken,t.projectId)).repos??[]).find(c=>c.host==="github"&&c.owner===e.owner&&c.repoName===e.repo);if(!a)throw new Error(`${e.owner}/${e.repo} is not a GitHub repository of this project`);return{githubToken:i,repo:a}}async function jh(t,e,r,n=Ah){let o=i=>({type:"gh_runner_setup_result",requestId:e.requestId,projectId:t.projectId,ok:!1,error:i});try{let{githubToken:i,repo:s}=await _h(t,e,n);if(!await n.api.repoHasAdmin(i,s.owner,s.repoName))return o(`the GitHub token lacks admin access on ${s.owner}/${s.repoName} \u2014 replace it (project page \u2192 Tokens \u2192 Replace) with a token that has admin rights on this repository`);let a={projectId:t.projectId,runners:[{owner:s.owner,repo:s.repoName,regToken:await n.api.mintRegistrationToken(i,s.owner,s.repoName)}],labels:[Ha(e.runnerId)]},c=Bt(e.runnerPublicKey,JSON.stringify(a));cl(e.runnerId,e.fingerprint),r.info(`[ghr] registration token for ${s.owner}/${s.repoName} sealed for runner host ${e.runnerName} \u2014 handing off`);let l=await n.provisionOnRunner(t.hubUrl,t.cliToken,e.runnerId,{projectId:t.projectId,sealedBundle:c});return{type:"gh_runner_setup_result",requestId:e.requestId,projectId:t.projectId,ok:l.ok,...l.runners?{runners:l.runners}:{},...l.error?{error:l.error}:{}}}catch(i){return o(i instanceof Error?i.message:String(i))}}async function Nh(t,e,r,n=Ah){let o=i=>({type:"gh_runner_teardown_result",requestId:e.requestId,projectId:t.projectId,ok:!1,error:i});try{let{githubToken:i,repo:s}=await _h(t,e,n),a={owner:s.owner,repo:s.repoName};try{a.removeToken=await n.api.mintRemoveToken(i,s.owner,s.repoName)}catch(p){r.warn(`[ghr] remove-token for ${s.owner}/${s.repoName} failed (${p instanceof Error?p.message:p}) \u2014 the runner host will force-remove`)}let c={projectId:t.projectId,runners:[a]},l=Bt(e.runnerPublicKey,JSON.stringify(c));cl(e.runnerId,e.fingerprint),r.info(`[ghr] removal bundle for ${s.owner}/${s.repoName} sealed for runner host ${e.runnerName} \u2014 handing off`);let u=await n.teardownOnRunner(t.hubUrl,t.cliToken,e.runnerId,{projectId:t.projectId,sealedBundle:l,owner:s.owner,repo:s.repoName});return{type:"gh_runner_teardown_result",requestId:e.requestId,projectId:t.projectId,ok:u.ok,...u.error?{error:u.error}:{}}}catch(i){return o(i instanceof Error?i.message:String(i))}}je();B();ut();me();var Oh=16*1024;function fE(t){return Je.test(t)?Ot(t)?`secret name "${t}" is reserved`:null:`secret name must match ${Je}`}function Lh(t,e,r,n){let o=fE(e);if(o)return{ok:!1,detail:o};let i;try{let s=JSON.parse(fn(n,r).toString("utf-8"));if(typeof s.value!="string"||s.value.length===0)return{ok:!1,detail:"payload has no value"};i=s.value}catch(s){return{ok:!1,detail:`cannot open the sealed secret (${s instanceof Error?s.message:String(s)}) \u2014 wrong channel key?`}}if(i.length>Oh)return{ok:!1,detail:`secret value too large (max ${Oh} chars)`};try{return Vd(t,e,i),{ok:!0}}catch(s){return{ok:!1,detail:s instanceof Error?s.message:String(s)}}}function Mh(t,e){try{return Xd(t,e)?{ok:!0}:{ok:!0,detail:"no such secret (already absent)"}}catch(r){return{ok:!1,detail:r instanceof Error?r.message:String(r)}}}on();me();Vt();var ns=class{constructor(e,r,n){this.intervalMs=e;this.send=r;this.log=n}targets=new Map;lastSig=new Map;timer=null;running=!1;setTargets(e){this.targets.clear(),this.lastSig.clear();for(let r of e)this.targets.set(r.taskId,r);this.log.info(`[track] targets updated: ${this.targets.size} task(s)`)}start(){if(this.timer)return;this.log.info(`[track] poller started (interval=${this.intervalMs}ms)`);let e=()=>{this.tick().catch(r=>this.log.warn(`[track] tick crashed: ${r instanceof Error?r.message:String(r)}`))};e(),this.timer=setInterval(e,this.intervalMs)}stop(){this.timer&&(clearInterval(this.timer),this.timer=null,this.log.info("[track] poller stopped"))}async tickOnce(){await this.tick()}async tick(){if(!this.running){this.running=!0;try{for(let[e,r]of this.targets)await this.processTask(e,r)}finally{this.running=!1}}}async processTask(e,r){let n=[],o=e.split(":",2)[0]??"";for(let a of r.prs){let{spec:c,host:l}=po(o,a.repoSpec);try{let u=await l.getPullRequest(c,a.number);n.push({number:a.number,url:a.url,state:u.state,merged:u.merged,ci:u.ci,mergeable:u.mergeable})}catch(u){if(u instanceof Sr){this.log.warn(`[track] task=${e} pr=${a.url} not found \u2014 skipping tick for this task`);return}this.log.warn(`[track] task=${e} pr=${a.url} fetch failed: ${u instanceof Error?u.message:String(u)}`);return}}let i=n.map(a=>`${a.number}:${a.state}:${a.merged?1:0}:${a.ci}:${a.mergeable}`).join("|");if(this.lastSig.get(e)===i)return;for(let a=0;a<n.length;a++){let c=n[a];if(c.ci!=="failed")continue;let{spec:l,host:u}=po(o,r.prs[a].repoSpec);if(u.getCiFailureLog)try{let p=await u.getCiFailureLog(l,c.number);p&&(c.ciFailureLog=p)}catch(p){this.log.warn(`[track] task=${e} pr=${c.url} ci-log fetch failed: ${p instanceof Error?p.message:String(p)}`)}}this.send({type:"pr_state_observed",taskId:e,prs:n}),this.lastSig.set(e,i);let s=mE(n);this.log.info(`[track] task=${e} snapshot signalled${s?` \u2192 ${s}`:""} (${n.length} PR(s))`)}};function mE(t){return t.length===0?null:t.some(e=>e.state==="closed"&&!e.merged)?"needs_manual":t.every(e=>e.merged)?"done":null}B();var os=class t{constructor(e,r,n,o={contextDir:null}){this.intervalMs=e;this.send=r;this.log=n;this.options=o}request=null;timer=null;running=!1;warnedMissingCfg=!1;shippedAttachments=new Set;abandonedTicks=0;static MAX_ABANDONED_TICKS=3;setRequest(e){let r=this.request?.projectId;this.request=e,this.log.info(`[yt-sync] request updated: project=${e.projectKey} columns=[${e.sourceColumns.join(",")}] sinceMs=${e.sinceMs} offBoard=${e.offBoardIssueIds.length}`),this.timer||this.start(),r&&r!==e.projectId&&this.log.info(`[yt-sync] project switch ${r} \u2192 ${e.projectId}`)}start(){if(this.timer)return;this.log.info(`[yt-sync] poller started (interval=${this.intervalMs}ms)`);let e=()=>{this.tick().catch(r=>this.log.warn(`[yt-sync] tick crashed: ${r instanceof Error?r.message:String(r)}`))};e(),this.timer=setInterval(e,this.intervalMs)}stop(){this.timer&&(clearInterval(this.timer),this.timer=null,this.log.info("[yt-sync] poller stopped"))}async tickOnce(){await this.tick()}async forceSync(){if(!this.request){this.log.info("[yt-sync] force requested but no sync_request yet \u2014 ignored");return}this.log.info("[yt-sync] force sync requested (manual)"),await this.tick()}async tick(){if(this.running||!this.request)return;let r=(this.options.resolveProvider??(()=>Rt({contextDir:this.options.contextDir})))();if(!r.ok){this.warnedMissingCfg||(this.warnedMissingCfg=!0,this.log.warn(`[yt-sync] tracker provider unavailable (${r.error}) \u2014 poller idle.`));return}this.warnedMissingCfg=!1,this.running=!0;try{await this.pollOnce(this.request,r.provider)}finally{this.running=!1}}async pollOnce(e,r){let n=Date.now(),o;try{let $=e.stageField?{stageField:e.stageField}:{},S=e.requireAssignee&&e.assignee?{assignee:e.assignee}:e.requireAssignee&&!e.assignee?{requireAnyAssignee:!0}:{},v=(e.backlogScope??"personal")==="shared"&&!!e.requireAssignee&&!!e.backlogColumn;if(r.kind==="internal")o=await r.listIssues({projectKey:e.projectKey});else if(v){let b=[...new Set([...e.sourceColumns,...e.rejectColumns??[],...e.doneColumns??[],...e.reviewColumns??[]])],[R,_]=await Promise.all([b.length>0?r.listIssues({projectKey:e.projectKey,columns:b,...$,...S}):Promise.resolve([]),r.listIssues({projectKey:e.projectKey,columns:[e.backlogColumn],...$})]),G=new Map;for(let z of[...R,..._])G.set(z.id,z);o=[...G.values()]}else{let b=[...new Set([...e.sourceColumns,...e.rejectColumns??[],...e.doneColumns??[],...e.reviewColumns??[],...e.backlogColumn?[e.backlogColumn]:[]])];o=await r.listIssues({projectKey:e.projectKey,columns:b,...$,...S})}}catch($){let S=$ instanceof Error?$.message:String($);S.includes("stage_field")?this.log.warn(`[yt-sync] CONFIGURATION ERROR \u2014 ${S}`):this.log.warn(`[yt-sync] listIssues failed: ${S}`);return}let i=new Map,s=new Set,a=new Set(e.doneColumns??[]);for(let $ of o){if(s.add($.id),a.has($.status))continue;let S=await Bh(r,$.id,e.sinceMs,this.log);S&&i.set($.id,S)}let c=[];for(let $ of e.offBoardIssueIds){if(s.has($))continue;let S=await Bh(r,$,e.sinceMs,this.log);if(S&&S.length>0&&i.set($,S),e.requireAssignee||S&&S.length>0){let T=await Uh(r,$,e.stageField,this.log);if(T)c.push(T);else if(S&&S.length>0){this.abandonTick("off-board issue fetch failed with new comments");return}}}let l=o.filter($=>!a.has($.status)),{attachmentsByIssue:u,attachmentKeys:p}=await this.collectAttachments(l,i,r);if(!this.options.contextDir){this.abandonTick("no Context Repo clone (headless / clone failed) \u2014 cannot deliver task content");return}let d=[...l,...c].map($=>({issue:$,comments:i.get($.id)??[],attachments:u.get($.id)??[]}));d.push(...await th(this.options.contextDir,d,$=>Uh(r,$,e.stageField,this.log)));try{await Xi(this.options.contextDir,e.projectId,d),this.abandonedTicks=0;for(let $ of p)this.shippedAttachments.add($)}catch($){let S=$ instanceof Error?$.message:String($);this.abandonTick(`context task sync failed: ${S}`);return}let m=this.options.isSelfComment??(()=>!1),f=[],g=[];for(let[$,S]of i){let T=S.filter(b=>!m(b.id));if(T.length===0)continue;f.push({issueId:$,comments:T.map(hE)});let v=T.flatMap(b=>{let R=$r(b.body);return R?[{commentId:b.id,author:b.author,name:R.name,args:R.args,createdAt:b.createdAt}]:[]});v.length>0&&g.push({issueId:$,commands:v})}let k={type:"youtrack_observation",projectId:e.projectId,issues:o.map(Dh),commentsBatch:f,...g.length>0?{commandsBatch:g}:{},...c.length>0?{offBoardIssues:c.map(Dh)}:{},observedAtMs:n};this.send(k);let h=f.reduce(($,S)=>$+S.comments.length,0),w=g.reduce(($,S)=>$+S.commands.length,0);this.log.info(`[yt-sync] observation sent: issues=${o.length} comments=${h} commands=${w} (sinceMs=${e.sinceMs})`)}abandonTick(e){this.abandonedTicks++,this.abandonedTicks<=t.MAX_ABANDONED_TICKS?this.log.warn(`[yt-sync] ${e} \u2014 tick abandoned (${this.abandonedTicks}/${t.MAX_ABANDONED_TICKS}), will retry`):this.log.warn(`[yt-sync] ERROR: ${e} \u2014 still failing after ${this.abandonedTicks} ticks; the project is STALLED until the Context Repo clone is restored`)}async collectAttachments(e,r,n){let o=new Map,i=[];for(let s of e){let a=[...s.attachments??[]];for(let u of r.get(s.id)??[])a.push(...u.attachments??[]);if(a.length===0)continue;let c=[],l=new Set;for(let u of a){let p=`${s.id}:${u.id}`;if(this.shippedAttachments.has(p))continue;let d;try{d=await n.downloadAttachment(u.url)}catch(f){this.log.warn(`[yt-sync] attachment ${u.name} (${s.id}) download failed: ${f instanceof Error?f.message:String(f)}`);continue}let m=gE(u.name);l.has(m)&&(m=`${u.id}-${m}`),l.add(m),c.push({name:m,contentBase64:d.toString("base64")}),i.push(p)}c.length>0&&o.set(s.id,c)}return{attachmentsByIssue:o,attachmentKeys:i}}};function Dh(t){let{description:e,...r}=t;return r}function hE(t){let{body:e,...r}=t;return r}function gE(t){let r=(t.split(/[\\/]/).pop()??t).replace(/[^A-Za-z0-9._-]/g,"_").replace(/^\.+/,"");return r.length>0?r.slice(0,120):"attachment"}async function Uh(t,e,r,n){try{return await t.getIssue(e,r)}catch(o){return n.warn(`[yt-sync] getIssue ${e} failed: ${o instanceof Error?o.message:String(o)}`),null}}async function Bh(t,e,r,n){try{return await t.listComments(e,r)}catch(o){return n.warn(`[yt-sync] listComments ${e} failed: ${o instanceof Error?o.message:String(o)}`),null}}async function OE(t,e){let r=t.repos.filter(i=>i.mirror);if(r.length===0)return[];let{mirrorLag:n}=await Promise.resolve().then(()=>(dl(),ul)),o=[];for(let i of r){let s=i.mountAs==="."?t.root:Ar(t.root,i.mountAs);try{o.push({repo:i.name,behind:await n(i,s)})}catch(a){e.warn(`[mirror] lag for ${i.name} unknown: ${a instanceof Error?a.message:String(a)}`),o.push({repo:i.name,behind:null})}}return o}var vl="npm i -g @code-partner/codepipe@latest";function ls(t,e={}){let r=e.log??{info:h=>console.log(h),warn:h=>console.warn(h)};r.info(`codepipe-cli v${Ve} (protocol ${ht})`);let n=h=>e.onEvent?.(h),o=e.workspace;o?.contextDir&&ef(o.contextDir,r);let i=()=>{if(o?.contextDir)try{ln(o.contextDir,o.root,r)}catch(h){r.warn(`[skills] materialize failed (non-fatal): ${h instanceof Error?h.message:String(h)}`)}};i();let s=rg("CLI_TRACKING_POLL_INTERVAL_SEC"),a=rg("CLI_YOUTRACK_POLL_INTERVAL_SEC"),c=(()=>{let h=parseInt(process.env.CLI_READINESS_INTERVAL_SEC??"600",10);return Number.isFinite(h)&&h>0?h*1e3:6e5})(),l=!1,u=!1,p=!1,d=new Set,m=!1,f=new Set,g=k();function k(){let h=es(t.hubUrl,t.cliToken),w=null,$=new ns(s,L=>{h.readyState===h.OPEN&&h.send(JSON.stringify(L))},r),S=new os(a,L=>{h.readyState===h.OPEN&&h.send(JSON.stringify(L))},r,{contextDir:o?.contextDir??null,isSelfComment:L=>f.has(L)}),T=null,v=async()=>{try{let L={trackerProvider:rl(o?.contextDir??null)};try{let E=await se(t.hubUrl,t.cliToken,t.projectId);L={...L,repos:E.repos,contextRepo:E.contextRepo}}catch(E){r.warn(`[readiness] could not fetch project summary for push checks: ${E instanceof Error?E.message:String(E)}`)}let F=await Up(t.projectId,L),M=o?await OE(o,r):[];if(i(),h.readyState!==h.OPEN)return;let Y={type:"cli_readiness",projectId:t.projectId,ready:F.ready,checks:F.checks,creds:F.creds,secretNames:Jd(t.projectId),...o?{mirrors:M}:{},checkedAt:F.checkedAt};if(h.send(JSON.stringify(Y)),F.ready)r.info("[readiness] ready");else{let E=F.checks.filter(I=>!I.ok).map(I=>`${I.name}(${I.detail??""})`);r.warn(`[readiness] NOT ready \u2014 ${E.join(", ")}`)}let W=Wp(F.creds,p);if(W==="open"){p=!0;let E=qp(t.hubUrl,t.projectId);r.info(`[agent-auth] Claude token invalid (401) \u2014 opening the dashboard to re-authorize: ${E}`),Rr(E)}else W==="rearm"&&(p=!1)}catch(L){r.warn(`[readiness] check failed: ${L instanceof Error?L.message:String(L)}`)}},b=()=>{v(),T=setInterval(()=>void v(),c),typeof T.unref=="function"&&T.unref()},R=()=>{T&&(clearInterval(T),T=null)},_=150,G=new Map,z=L=>{let F=G.get(L);if(!F||(F.timer&&clearTimeout(F.timer),G.delete(L),F.events.length===0||h.readyState!==h.OPEN))return;let M={type:"run_activity",projectId:t.projectId,runId:L,events:F.events};h.send(JSON.stringify(M))},A=(L,F)=>{let M=G.get(L);if(M||(M={events:[],timer:null},G.set(L,M)),M.events.push(F),F.kind==="result"){z(L);return}M.timer||(M.timer=setTimeout(()=>z(L),_),M.timer.unref?.())},y=o?.contextDir?new xi(o.contextDir,t.projectId,L=>{h.readyState===h.OPEN&&h.send(JSON.stringify(L))},r):null,U=async()=>{let L=o?.contextDir;if(!L)throw new Error("no context repo clone on this CLI");let F;try{F=(await se(t.hubUrl,t.cliToken,t.projectId)).contextRepo}catch{}let M=await Tf(L,t.projectId,F,r);return h.readyState===h.OPEN&&h.send(JSON.stringify(M)),M},j=null,H=async()=>{let L=o?.contextDir;if(L)try{let{readContextIndexHub:F,collectSearchRows:M}=await Promise.resolve().then(()=>(Io(),Ro));if(F(L)!=="metadata")return;let Y=M(L);h.readyState===h.OPEN&&(h.send(JSON.stringify({type:"model_index",projectId:t.projectId,rows:Y})),r.info(`[model] tier-2 index snapshot pushed (${Y.length} rows)`))}catch(F){r.warn(`[model] tier-2 index push failed (non-fatal): ${F instanceof Error?F.message:String(F)}`)}},J=()=>{j&&clearTimeout(j),j=setTimeout(()=>void H(),5e3)},oe=null,At=async L=>{if(o?.contextDir)try{let{rebuildWorkspaceModelIfStale:F}=await Promise.resolve().then(()=>(Oo(),cs));(await F({root:o.root,contextDir:o.contextDir,repos:o.repos},{fetch:L,onLog:Y=>r.info(Y)})).rebuilt.length>0&&J()}catch(F){r.warn(`[model] release-path rebuild failed (non-fatal): ${F instanceof Error?F.message:String(F)}`)}},pt=L=>{oe&&clearTimeout(oe),oe=setTimeout(()=>void At(L),6e4)},Ue=setInterval(()=>void At(!0),6*36e5);return h.on("open",()=>{r.info("[ws] connected"),n({kind:"connected"});let L=ip(t.projectId),F=X("ORIGIN")==="farm"?"farm":"local",M=X("FARM_ID"),Y=t.accountEmail??L.email,W;try{let I=Wf(t.projectId);I&&(W=I.publicKey,r.info(`[cred-channel] key fingerprint: ${I.fingerprint}`))}catch(I){r.warn(`[cred-channel] key setup failed (token replacement via dashboard unavailable): ${I instanceof Error?I.message:String(I)}`)}let E={type:"register",projectId:t.projectId,platformVersion:Ve,protocolVersion:ht,accountId:L.accountId,accountLabel:L.label,origin:F,inFlightActionIds:[...d],...Y?{accountEmail:Y}:{},...F==="farm"&&M?{farmId:M}:{},...W?{sealPublicKey:W}:{}};h.send(JSON.stringify(E))}),h.on("message",async L=>{let F=L.toString("utf-8");if(F==="pong"||F==="ping")return;let M;try{M=JSON.parse(F)}catch{return}if(!M||typeof M!="object")return;let Y=M.type;if(Y==="registered"){let E=M;if(E.ok){if(r.info(`[ws] registered for project ${E.projectId}`),n({kind:"registered",projectId:E.projectId??t.projectId}),$.start(),y?.start(),b(),xl(t,o,r),o?.contextDir){try{let I=Ci(o.contextDir,t.projectId);h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.outdated&&(r.warn(`[ctx] context format outdated: v${I.templateVersion} \u2192 v${I.currentVersion}`+(I.missingPaths.length>0?` (missing: ${I.missingPaths.join(", ")})`:"")),u||(u=!0,U().catch(()=>{})))}catch(I){r.warn(`[ctx] context-format detect failed (non-fatal): ${I instanceof Error?I.message:String(I)}`)}H(),pt(!0)}}else r.warn(`[ws] register rejected: ${E.reason??"unknown"}`),n({kind:"register_rejected",reason:E.reason??"unknown"}),l=!0,h.close();return}if(Y==="hello"){let E=M;w=Vn(E.protocolVersion);let I=w?"compatible":"INCOMPATIBLE";r.info(`[ws] hub v${E.platformVersion} (protocol ${E.protocolVersion}) \u2014 ${I}`),w||(r.warn(`[ws] HUB protocol incompatible with this CLI (v${Ve}, protocol ${ht}) \u2014 WriteActions will be refused until versions align.`),r.warn(`[ws] update the CLI: ${vl}`),n({kind:"incompatible",hubVersion:typeof E.platformVersion=="string"?E.platformVersion:null,hubProtocol:typeof E.protocolVersion=="number"?E.protocolVersion:null,updateCommand:vl}));return}if(Y==="tracking_targets"){$.setTargets(M.targets);return}if(Y==="youtrack_sync_request"){S.setRequest(M);return}if(Y==="youtrack_force_sync"){S.forceSync();return}if(Y==="sync_local"){await DE(M,o,h,r);return}if(Y==="provision_repo"){let E=M;r.info(`[repo] provision_repo: ${E.repo.name} (${E.repo.host}:${E.repo.owner}/${E.repo.repoName})`),await LE(t,o,E.repo,r),await xl(t,o,r);return}if(Y==="remove_repo"){let E=M;r.info(`[repo] remove_repo: ${E.repoName}${E.purge?" (purge)":""}`),await xl(t,o,r),E.purge&&ME(t,o,E.repoName,r);return}if(Y==="context_write"){await UE(M,o,h,r),i();return}if(Y==="adr_promote"){await BE(M,o,h,r),i();return}if(Y==="cred_update"){let E=M,I=q(t.projectId),Q=I?.sealKey?await qf(t.projectId,E.kind,E.sealed,I.sealKey.privateKey):{ok:!1,detail:"no cred-channel key on this CLI (restart the daemon)"},ie={type:"cred_update_result",updateId:E.updateId,projectId:t.projectId,ok:Q.ok,...Q.detail?{detail:Q.detail}:{}};h.readyState===h.OPEN&&h.send(JSON.stringify(ie)),Q.ok?(r.info(`[cred] ${E.kind} replaced${Q.detail?` \u2014 ${Q.detail}`:""}`),v()):r.warn(`[cred] ${E.kind} replacement rejected: ${Q.detail??"unknown"}`);return}if(Y==="readiness_check"){r.info("[readiness] on-demand check requested"),v();return}if(Y==="agent_login_start"){Hp(t,h,M,r,v);return}if(Y==="move_to_farm"){let E=M;r.info(`[farm-move] request to move ${t.projectId} onto farm ${E.farmName} (${E.farmId})`);let I=await Th(t,E,o?.contextDir,r);h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.ok?r.info(`[farm-move] done \u2014 farm daemon ${I.daemonStatus??"started"}; expecting takeover`):r.warn(`[farm-move] failed: ${I.error??"unknown error"}`);return}if(Y==="gh_runner_setup"){let E=M;r.info(`[ghr] runner setup for ${t.projectId} on runner host ${E.runnerName} (${E.runnerId})`);let I=await jh(t,E,r);h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.ok?r.info(`[ghr] runners connected on ${E.runnerName}`):r.warn(`[ghr] setup failed: ${I.error??"see per-repo statuses"}`);return}if(Y==="gh_runner_teardown"){let E=M;r.info(`[ghr] runner teardown for ${t.projectId} on runner host ${E.runnerName} (${E.runnerId})`);let I=await Nh(t,E,r);h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.ok?r.info(`[ghr] runners disconnected from ${E.runnerName}`):r.warn(`[ghr] teardown failed: ${I.error??"unknown error"}`);return}if(Y==="tracker_fields_request"){let E=M,I={type:"tracker_fields_result",requestId:E.requestId,projectId:t.projectId,ok:!1},Q=Rt({contextDir:o?.contextDir??null});if(!Q.ok)I.error=Q.error;else try{I.fields=await Q.provider.fetchStateFields(E.projectKey),I.ok=!0}catch(ie){I.error=ie instanceof Error?ie.message:String(ie)}h.readyState===h.OPEN&&h.send(JSON.stringify(I)),I.ok||r.warn(`[yt-fields] listing failed: ${I.error??"unknown"}`);return}if(Y==="project_secret_update"||Y==="project_secret_delete"){let E=M,I;if(E.type==="project_secret_update"){let ie=q(t.projectId);I=ie?.sealKey?Lh(t.projectId,E.name,E.sealed,ie.sealKey.privateKey):{ok:!1,detail:"no cred-channel key on this CLI (restart the daemon)"}}else I=Mh(t.projectId,E.name);let Q={type:"project_secret_update_result",updateId:E.updateId,projectId:t.projectId,ok:I.ok,...I.detail?{detail:I.detail}:{}};h.readyState===h.OPEN&&h.send(JSON.stringify(Q)),I.ok?(r.info(`[secret] ${E.name} ${E.type==="project_secret_update"?"saved":"deleted"}`+(I.detail?` \u2014 ${I.detail}`:"")),v()):r.warn(`[secret] ${E.name} rejected: ${I.detail??"unknown"}`);return}if(Y==="sandbox_keys"){let E=q(t.projectId);if(!E){r.warn(`[cred] sandbox_keys received but no secrets for ${t.projectId} \u2014 cannot seal`);return}let I=en(t.projectId),Q=Ff(M,E,I,r);for(let ie of Q)h.readyState===h.OPEN&&h.send(JSON.stringify(ie));return}if(Y!=="dispatch_action")return;let W=M;if(w===!1){let E=`refused: HUB protocol incompatible with CLI v${Ve} (protocol ${ht})`;h.send(JSON.stringify({type:"action_result",actionId:W.actionId,status:"failed",error:E})),r.warn(`[exec] ${W.actionId} (${W.action.type}) \u2192 REFUSED: ${E}`),r.warn(`[exec] update the CLI to clear this: ${vl}`),n({kind:"action",actionId:W.actionId,actionType:W.action.type,ok:!1,error:E});return}if(W.action.type==="model_drift"){d.add(W.actionId);try{let E,I=o?.repos.find(Q=>Q.name===W.action.repoName);if(!o?.contextDir||!I)E={status:"failed",error:"no local workspace/repo clone on this CLI"};else try{let{computeDriftReport:Q}=await Promise.resolve().then(()=>(tg(),eg)),ie=I.mountAs==="."?o.root:Ar(o.root,I.mountAs);E={status:"done",result:{report:await Q(ie,o.contextDir,I.name)}}}catch(Q){E={status:"failed",error:Q instanceof Error?Q.message:String(Q)}}h.send(JSON.stringify({type:"action_result",actionId:W.actionId,...E}))}finally{d.delete(W.actionId)}return}if(W.action.type==="model_bootstrap"){d.add(W.actionId);try{let E;if(!o?.contextDir)E={status:"failed",error:"no Context Repo clone on this CLI"};else if(m)E={status:"failed",error:"model bootstrap is already running"};else{m=!0;try{let I=await se(t.hubUrl,t.cliToken,t.projectId),{bootstrapDaemonModel:Q}=await Promise.resolve().then(()=>(Oo(),cs)),ie=await Q(t.projectId,{root:o.root,contextDir:o.contextDir},I.repos,P=>r.info(`[model] ${P}`));r.info(`[model] bootstrap done: ${ie.repos} repos, ${ie.events} task events`),J(),E={status:"done",result:{repos:ie.repos,events:ie.events}}}catch(I){E={status:"failed",error:I instanceof Error?I.message:String(I)},r.warn(`[model] bootstrap failed: ${E.error}`)}finally{m=!1}}h.readyState===h.OPEN&&h.send(JSON.stringify({type:"action_result",actionId:W.actionId,...E}))}finally{d.delete(W.actionId)}return}d.add(W.actionId);try{let E=await ch({action:W.action,repo:W.repo,trackerIssueId:W.trackerIssueId,contextDir:o?.contextDir,requestConfigReport:y?()=>y.reportNow():void 0,refreshContextStatus:o?.contextDir?U:void 0,onRunActivity:A}).catch(ie=>({status:"failed",error:ie instanceof Error?ie.message:String(ie)}));W.action.type==="tracker_comment"&&E.status==="done"&&"result"in E&&typeof E.result?.commentId=="string"&&f.add(E.result.commentId),h.send(JSON.stringify({type:"action_result",actionId:W.actionId,...E}));let I=E.status!=="failed",Q=!I&&"error"in E?E.error:void 0;I?r.info(`[exec] ${W.actionId} (${W.action.type}) \u2192 done`):r.warn(`[exec] ${W.actionId} (${W.action.type}) \u2192 FAILED: ${Q??"?"}`),n({kind:"action",actionId:W.actionId,actionType:W.action.type,ok:I,...Q?{error:Q}:{}}),I&&["apply_delivery","context_write","create_pr"].includes(W.action.type)&&J(),I&&["merge_pr","merge_branch"].includes(W.action.type)&&pt(!0)}finally{d.delete(W.actionId)}}),h.on("close",(L,F)=>{let M=F?.toString("utf-8")??"";if(r.info(`[ws] closed code=${L}${M?` reason=${M}`:""}`),$.stop(),S.stop(),y?.stop(),R(),clearInterval(Ue),oe&&clearTimeout(oe),j&&clearTimeout(j),M==="replaced"){l=!0,r.warn(`[ws] project ${t.projectId} was taken over by another CLI (HUB closed us as "replaced") \u2014 standing down, not reconnecting. Run exactly ONE CLI per project.`),n({kind:"replaced"});return}n({kind:"disconnected",code:L}),!l&&setTimeout(()=>{g=k()},2e3)}),h.on("error",L=>r.warn(`[ws] error: ${L.message}`)),h}return{stop(){l=!0,g.close()}}}async function xl(t,e,r){try{let n=await se(t.hubUrl,t.cliToken,t.projectId),{updated:o,errors:i}=bo(t.projectId,n.repos,e?.contextDir);for(let s of o)r.info(`[repo] restaged repo set in ${s}`);for(let s of i)r.warn(`[repo] could not restage ${s.path}: ${s.error}`)}catch(n){r.warn(`[repo] repo-set reconcile skipped: ${n instanceof Error?n.message:String(n)}`)}}async function LE(t,e,r,n){let o=r.mountAs??r.name;if(o==="."){n.info(`[repo] ${r.name} mounts in place (mount_as: .) \u2014 nothing to clone`);return}let i=e?Ar(e.root,o):_e(t.projectId,r.name);if(ng(Ar(i,".git"))){n.info(`[repo] ${r.name} already present at ${i}`);return}try{await NE().clone(e?ji(r):Nc(r),i),n.info(`[repo] cloned ${r.name} \u2192 ${i}`)}catch(s){n.warn(`[repo] clone of ${r.name} failed (will retry lazily): ${s instanceof Error?s.message.trim():String(s)}`)}}function ME(t,e,r,n){let o=e?.repos.find(s=>s.name===r)?.mountAs??r,i=e?Ar(e.root,o):_e(t.projectId,r);if(e&&i===e.root){n.warn(`[repo] ${r} maps to the workspace root \u2014 skipping purge`);return}if(!ng(Ar(i,".git"))){n.info(`[repo] no local clone to purge for ${r} (${i})`);return}try{jE(i,{recursive:!0,force:!0}),n.info(`[repo] purged local clone ${i}`)}catch(s){n.warn(`[repo] purge of ${i} failed: ${s instanceof Error?s.message:String(s)}`)}}async function DE(t,e,r,n){if(!e){n.info(`[sync] sync_local for ${t.taskId} \u2014 no workspace (headless), skipped`);return}for(let o of t.repos){let i=e.repos.find(l=>l.name===o.repoName),s=Ar(e.root,i?.mountAs??o.repoName),a=i?.defaultBranch??o.defaultBranch,c=await Yp(s,a).catch(l=>({status:"warn",reason:l instanceof Error?l.message:String(l)}));c.status==="updated"?n.info(`[sync] ${o.repoName}: fast-forwarded ${a} \u2192 origin`):c.status==="skipped"?n.info(`[sync] ${o.repoName}: not cloned in workspace \u2014 skipped`):(n.warn(`[sync] ${o.repoName}: ${c.reason??"sync skipped"}`),r.readyState===r.OPEN&&r.send(JSON.stringify({type:"local_sync_warning",taskId:t.taskId,repoName:o.repoName,reason:c.reason??"sync skipped"})))}}async function UE(t,e,r,n){let o=(i,s)=>{if(r.readyState!==r.OPEN)return;let a={type:"context_write_result",id:t.id,status:i};s&&(a.error=s),r.send(JSON.stringify(a))};if(!e?.contextDir){n.warn(`[ctx] context_write ${t.id} \u2014 no .codepipe clone (headless), reporting failed`),o("failed","no context repo clone on this CLI");return}try{await Ie(e.contextDir,t.files,t.message),n.info(`[ctx] context_write ${t.id}: committed ${t.files.length} file(s)`),o("done")}catch(i){let s=i instanceof Error?i.message:String(i);n.warn(`[ctx] context_write ${t.id} failed: ${s}`),o("failed",s)}}async function BE(t,e,r,n){let o=(i,s)=>{if(r.readyState!==r.OPEN)return;let a={type:"context_write_result",id:t.id,status:i};s&&(a.error=s),r.send(JSON.stringify(a))};if(!e?.contextDir){n.warn(`[adr] adr_promote ${t.id} \u2014 no .codepipe clone (headless), reporting failed`),o("failed","no context repo clone on this CLI");return}try{let i=t.source??"task",s=await cf(e.contextDir,t.taskKey,t.slugs,void 0,i);if(n.info(`[adr] adr_promote ${t.id}: promoted ${s.promoted.length}, skipped ${s.skipped.length}`+(s.promoted.length>0?` (${s.promoted.join(", ")})`:"")),s.missing.length>0){let a=l=>i==="staging"?`adr/DRAFT-${l}.md`:`tasks/${t.taskKey}/adr/DRAFT-${l}.md`,c=`draft file(s) missing in clone: ${s.missing.map(a).join(", ")}`;n.warn(`[adr] adr_promote ${t.id}: ${c}`),o("failed",c);return}o("done")}catch(i){let s=i instanceof Error?i.message:String(i);n.warn(`[adr] adr_promote ${t.id} failed: ${s}`),o("failed",s)}}function rg(t){let e=parseInt(process.env[t]??"60",10);return Number.isFinite(e)&&e>0?e*1e3:6e4}je();me();Ut();El();it();Oi();async function hg(t={profile:void 0}){let{cfg:e,profile:r}=Qr(t.profile),n=q(e.projectId);n&&uo(n),vo(n?.github?.token??process.env.GH_TOKEN)&&console.log("[git] github.com over token-HTTPS (insteadOf) \u2014 farm transport"),xo(n?.gitlab?.token??process.env.GITLAB_TOKEN)&&console.log("[git] gitlab.com over token-HTTPS (insteadOf) \u2014 farm transport"),So(n?.bitbucket?.apiToken||process.env.BITBUCKET_API_TOKEN)&&console.log("[git] bitbucket.org over token-HTTPS (insteadOf) \u2014 farm transport");let o=Lo(Tl(),".codepipe","logs"),i=r?`cli-daemon-${r}`:"cli-daemon",s=mi("CLI_LOG",i,o);if(s.enabled){let d=new rn(s);hi(d),console.log(`[log] file logging \u2192 ${d.path} (rotate at ${s.maxBytes}B, keep ${s.maxFiles})`)}console.log(`codepipe daemon \u2192 ${e.hubUrl} (project=${e.projectId})`);let a=null,c=Jr(e.projectId);if(c&&(a={root:c.root,contextDir:c.contextDir,repos:c.spec.repos},console.log(`[ctx] workspace found at ${c.root} \u2014 using its Context Repo clone`)),!a){let d=Lo(Tl(),".codepipe",r?Lo("profiles",r,"context"):"context");if(await sl(e.hubUrl,e.cliToken,e.projectId,{phase:"context_cloning"}).catch(()=>{}),a=await fg(()=>ds({cfg:e,secrets:n,contextDir:d,log:{info:m=>console.log(m),warn:m=>console.warn(m)}}),{log:{warn:m=>console.warn(m)}}),a||await sl(e.hubUrl,e.cliToken,e.projectId,{phase:"context_cloning",error:"could not clone the Context Repo \u2014 check the context credentials (the daemon continues without config reporting)"}).catch(()=>{}),a?.contextDir){let m=Lo(Tl(),".codepipe",r?Lo("profiles",r,"context-config"):"context-config");Si(a.contextDir,m,{info:f=>console.log(f),warn:f=>console.warn(f)})}}let l=ls(e,{...a?{workspace:a}:{},onEvent:d=>{d.kind==="replaced"&&(console.error(`[daemon] project ${e.projectId} is now served by another CLI \u2014 exiting. Run exactly one CLI per project.`),process.exit(0))}}),u=!1;function p(d){u||(u=!0,console.log(`
976
976
  [${d}] shutting down`),l.stop(),setTimeout(()=>process.exit(0),200))}process.on("SIGINT",()=>p("SIGINT")),process.on("SIGTERM",()=>p("SIGTERM")),await new Promise(()=>{})}jn();Ge();je();async function kw(t={profile:void 0}){let e=st(t.profile);console.log(`connecting to ${e.hubUrl} (project=${e.projectId}) \u2026`);let r=es(e.hubUrl,e.cliToken),n=await new Promise(i=>{let s=[],a=!1,c=setTimeout(()=>{s.push("timeout"),r.close(),i({ok:!1,events:s})},5e3);r.on("open",()=>{s.push("open");let l={type:"register",projectId:e.projectId};r.send(JSON.stringify(l))}),r.on("message",l=>{let u=l.toString("utf-8");if(s.push(`msg:${u}`),u!=="pong")try{let p=JSON.parse(u);p.type==="registered"?(a=!!p.ok,clearTimeout(c),r.send("ping")):p.type}catch{}}),r.on("error",l=>s.push(`error:${l.message}`)),r.on("close",(l,u)=>{s.push(`close:${l}:${u?.toString()||""}`),clearTimeout(c),i({ok:a,events:s})}),setTimeout(()=>r.close(),1500)});for(let i of n.events)console.log(` ${i}`);n.ok||(console.error("hello failed"),process.exit(1)),console.log("ok \u2014 HUB reachable, CLI auth + project binding works.");try{let i=await se(e.hubUrl,e.cliToken,e.projectId);if(i.duplicateIntake){let s=i.duplicateIntake;console.warn(`warning: project \xAB${s.withProjectId}\xBB watches the same YouTrack columns (${s.columns.join(", ")}) and at least one of the two has no assignee filter \u2014 both will grab the same issues. Enable require_assignee + assignee on both.`)}}catch{}let o=Le(t.profile);o?o.hubUrl===e.hubUrl.replace(/\/$/,"")?console.log(`worker: registered as ${o.sandboxId} (${o.name}), llm=${o.llm??"none"} \u2014 live state on the dashboard`):console.log(`worker: registered against a different HUB (${o.hubUrl})`):console.log("worker: not registered (run `codepipe up` or `codepipe worker register`)")}qo();import{readFileSync as tP}from"node:fs";B();Ge();Ut();Ko();Ir();Vt();Tr();je();me();function ve(t){throw new Error(t)}function Ce(t,e){return(typeof t!="string"||t.trim().length===0)&&ve(`config: '${e}' must be a non-empty string`),t.trim()}function Vo(t,e){if(t==null)return;typeof t!="string"&&ve(`config: '${e}' must be a string`);let r=t.trim();return r.length>0?r:void 0}function rP(t){(!t||typeof t!="object")&&ve("config: expected a JSON object");let e=t,r=Ce(e.hubUrl,"hubUrl").replace(/\/$/,"");r.startsWith("http")||ve("config: 'hubUrl' must start with http(s)://");let n=Ce(e.cliToken,"cliToken"),o=e.project;(!o||typeof o!="object")&&ve("config: 'project' is required");let i=o,s=Ce(i.id,"project.id");Wt.test(s)||ve("config: 'project.id' must match /^[a-z][a-z0-9-]{1,30}$/");let a=Ce(i.name,"project.name"),c=Ce(i.automationLevel,"project.automationLevel");c!=="assisted"&&c!=="full"&&ve("config: 'project.automationLevel' must be 'assisted' or 'full'");let l=i.repos;Array.isArray(l)||ve("config: 'project.repos' must be an array");let u=l.map((w,$)=>{(!w||typeof w!="object")&&ve(`config: project.repos[${$}] must be an object`);let S=w,T=Ce(S.host,`project.repos[${$}].host`);T!=="github"&&T!=="bitbucket"&&T!=="gitlab"&&ve(`config: project.repos[${$}].host must be 'github', 'bitbucket' or 'gitlab'`);let v={name:Ce(S.name,`project.repos[${$}].name`),host:T,owner:Ce(S.owner,`project.repos[${$}].owner`),repoName:Ce(S.repoName,`project.repos[${$}].repoName`)},b=Vo(S.defaultBranch,`project.repos[${$}].defaultBranch`);b&&(v.defaultBranch=b);let R=Vo(S.mountAs,`project.repos[${$}].mountAs`);return R&&(v.mountAs=R),v}),p=i.contextRepo;(!p||typeof p!="object")&&ve("config: 'project.contextRepo' is required");let d=p,m=Vo(d.host,"project.contextRepo.host")??"github";m!=="github"&&m!=="bitbucket"&&m!=="gitlab"&&ve("config: 'project.contextRepo.host' must be 'github', 'bitbucket' or 'gitlab'");let f={host:m,owner:Ce(d.owner,"project.contextRepo.owner"),name:Vo(d.name,"project.contextRepo.name")??xt(s)},g={hubUrl:r,cliToken:n,project:{id:s,name:a,automationLevel:c,repos:u,contextRepo:f}},k=Vo(i.youtrackProjectKey,"project.youtrackProjectKey");if(k&&(g.project.youtrackProjectKey=k),i.index!==void 0&&(typeof i.index!="boolean"&&ve("config: 'project.index' must be a boolean"),g.project.index=i.index),i.youtrackWrites!==void 0&&(typeof i.youtrackWrites!="boolean"&&ve("config: 'project.youtrackWrites' must be a boolean"),g.project.youtrackWrites=i.youtrackWrites),i.llmProvider!==void 0){let w=Ce(i.llmProvider,"project.llmProvider");w==="codex"&&ve(`config: 'project.llmProvider' "codex" is not yet supported (coming soon); use "claude".`),w!=="claude"&&ve("config: 'project.llmProvider' must be 'claude'"),g.project.llmProvider=w}let h=e.secrets;if(h!==void 0){(typeof h!="object"||h===null)&&ve("config: 'secrets' must be an object");let w=h,$={};if(w.github){let S=w.github;$.github={token:Ce(S.token,"secrets.github.token")}}if(w.bitbucket){let S=w.bitbucket;$.bitbucket={email:Ce(S.email,"secrets.bitbucket.email"),apiToken:Ce(S.apiToken,"secrets.bitbucket.apiToken")}}if(w.gitlab){let S=w.gitlab;$.gitlab={token:Ce(S.token,"secrets.gitlab.token")}}if(w.youtrack){let S=w.youtrack;$.youtrack={url:Ce(S.url,"secrets.youtrack.url").replace(/\/$/,""),token:Ce(S.token,"secrets.youtrack.token")}}if(w.contextWrite){let S=w.contextWrite;$.contextWrite={token:Ce(S.token,"secrets.contextWrite.token")}}g.secrets=$}return g}async function nP(){let t=[];for await(let e of process.stdin)t.push(e);return Buffer.concat(t).toString("utf-8")}async function oP(t){let e=t.secrets;if(e){if(e.github){let r=t.project.contextRepo,n=await qt(e.github.token,r.host==="github"?{owner:r.owner}:void 0);console.log(` GitHub OK \u2014 ${n}`)}if(e.bitbucket){let r=t.project.repos.find(i=>i.host==="bitbucket"),n=r?.owner??(t.project.contextRepo.host==="bitbucket"?t.project.contextRepo.owner:void 0),o=await Yt(e.bitbucket.email,e.bitbucket.apiToken,n);if(r){let i=await ki(e.bitbucket.email,e.bitbucket.apiToken,r.owner,r.repoName);if(i)throw new Error(`Bitbucket: ${i}`)}console.log(` Bitbucket OK \u2014 ${o}`)}if(e.gitlab){let r=await zt(e.gitlab.token);console.log(` GitLab OK \u2014 ${r}`)}if(e.youtrack){let r=await Jt({baseUrl:e.youtrack.url,token:e.youtrack.token});console.log(` YouTrack OK \u2014 ${r}`)}}}async function Sk(t){let e=!t.configPath||t.configPath==="-"?await nP():tP(t.configPath,"utf-8"),r;try{r=JSON.parse(e)}catch(d){ve(`config: invalid JSON \u2014 ${d instanceof Error?d.message:String(d)}`)}let n=rP(r),{hubUrl:o,cliToken:i,project:s}=n;console.log(`codepipe init --headless \u2192 ${o} (project=${s.id})`),t.skipVerify||(console.log("verifying credentials\u2026"),await oP(n));let a={projectId:s.id,name:s.name,automationLevel:s.automationLevel,repos:s.repos};s.youtrackProjectKey&&(a.youtrackProjectKey=s.youtrackProjectKey),console.log(`provisioning Context Repo ${s.contextRepo.owner}/${s.contextRepo.name} (${s.contextRepo.host})\u2026`);let c=n.secrets?.github?.token??process.env.GH_TOKEN??process.env.GITHUB_TOKEN,l;try{l=await Nn(a,s.contextRepo,{githubToken:c,gitlabToken:n.secrets?.gitlab?.token??process.env.GITLAB_TOKEN,bitbucket:n.secrets?.bitbucket??tn(),youtrackWrites:s.youtrackWrites??!0,trackerUrl:n.secrets?.youtrack?.url,log:{info:d=>console.log(` ${d}`),warn:d=>console.warn(` ${d}`)}})}catch(d){ve(`Context Repo provisioning failed: ${d instanceof Error?d.message:String(d)}`)}a.contextRepo=l,console.log(`Context Repo ready: ${l.owner}/${l.name}@${l.branch}`),console.log(`registering project on ${o}\u2026`);let u;try{u=await or(o,i,a)}catch(d){if(d instanceof K&&d.status===409)console.log(`project ${s.id} already exists on HUB \u2014 reusing it`),u=await se(o,i,s.id);else if(d instanceof K)ve(`HUB \u2192 ${d.status} ${d.message}`);else throw d}console.log(`project ${u.projectId} ready (${u.provisioningStatus})`);let p={hubUrl:o,cliToken:i,projectId:s.id,...n.secrets??{}};if(ae(p),Mt({hubUrl:o,cliToken:i,projectId:s.id},s.id),console.log(`config + secrets written (profile ${s.id}) \u2192 ${St(s.id)}`),Qt(s.id,Tt(a,s.youtrackWrites??!0,n.secrets?.youtrack?.url,void 0,s.llmProvider??Xe),{info:d=>console.log(d),warn:d=>console.warn(d)}),s.index)try{let{jobId:d}=await No(o,i,s.id,{reindex:!1});console.log(`index job enqueued (job ${d}); runs once a SANDBOX claims it.`)}catch(d){console.warn(`could not enqueue index job: ${d instanceof Error?d.message:String(d)} (registration succeeded; retry later).`)}console.log(`done. start the daemon: codepipe --profile ${s.id} daemon`)}Ge();me();import{cancel as Ek,intro as Tk,isCancel as Rk,log as nu,outro as iP,password as Ik}from"@clack/prompts";async function sP(){let t=[];for await(let e of process.stdin)t.push(e);return Buffer.concat(t).toString("utf-8").trim()}async function Ck(t){let e=t.token?.trim()??"";if(!e&&t.stdin&&(e=await sP(),e||(console.error("login: no token on stdin"),process.exit(1))),t.shared){if(!e){Tk("codepipe login --shared \u2014 set the farm/machine-wide Claude OAuth token"),nu.message("Run `claude setup-token` and paste the token below (input hidden).");let i=await Ik({message:"Claude OAuth token"});Rk(i)&&(Ek("aborted"),process.exit(1)),e=i.trim()}e||(console.error("login: no token provided"),process.exit(1)),Qd({claude:{oauthToken:e}}),console.log(`Claude OAuth token saved to ${fi()} (shared). `),console.log("Every project without its own token will use it on the next job.");return}let r=st(t.profile);if(!e){Tk(`codepipe login \u2014 set the Claude OAuth token for project ${r.projectId}`),nu.message("Run `claude setup-token` and paste the token below (input hidden).");let i=await Ik({message:"Claude OAuth token"});Rk(i)&&(Ek("aborted"),process.exit(1)),e=i.trim()}e||(console.error("login: no token provided"),process.exit(1));let o=q(r.projectId)??{hubUrl:r.hubUrl,cliToken:r.cliToken,projectId:r.projectId};o.claude={oauthToken:e},ae(o),t.stdin?console.log(`Claude OAuth token saved for project ${r.projectId}.`):(nu.success("Claude OAuth token saved."),iP("It will be sealed into job bundles when a SANDBOX (re)connects."))}Oo();B();Ge();Ut();Ko();Ir();Rs();je();me();import{cancel as aP,confirm as cP,intro as lP,isCancel as Pk,log as Me,outro as uP,select as Ak,text as pr}from"@clack/prompts";function _k(t){aP(t),process.exit(1)}function Un(t){return Pk(t)&&_k("aborted"),t}function Xo(t){return Pk(t)&&_k("aborted"),typeof t=="string"?t:""}async function dP(t,e){let r=Un(await Ak({message:"Context Repo host",options:[{value:"github",label:"github"},{value:"gitlab",label:"gitlab"},{value:"bitbucket",label:"bitbucket"}],initialValue:e[0]?.host??"github"})),n=e.find(s=>s.host===r)?.owner??e[0]?.owner??"",o=Xo(await pr({message:"Context Repo owner (org / group / workspace / user)",placeholder:n||"your-org",initialValue:n,validate:s=>s.trim().length>0?void 0:"required"})).trim(),i=Xo(await pr({message:"Context Repo name",placeholder:xt(t),initialValue:xt(t),validate:s=>s.trim().length>0?void 0:"required"})).trim();return{host:r,owner:o,name:i}}async function jk(t={profile:void 0}){let e=st(t.profile);lP(`codepipe project add \u2192 ${e.hubUrl}`);let r=Un(await pr({message:"project_id (lowercase letters, digits, dashes; starts with a letter)",placeholder:"cp",validate:d=>Wt.test(d.trim())?void 0:"must match /^[a-z][a-z0-9-]{1,30}$/"})).trim(),n=Un(await pr({message:"project name (human-readable)",placeholder:"CodePartner",validate:d=>d.trim().length>0?void 0:"required"})).trim(),o=Un(await Ak({message:"automation level",options:[{value:"assisted",label:"assisted \u2014 every gate via manual Run on the dashboard"},{value:"full",label:"full \u2014 gates auto-approve, runs end-to-end"}],initialValue:"assisted"})),i=Un(await pr({message:"YouTrack project key (optional)",placeholder:"DEV"})).trim(),s=Un(await cP({message:"Allow CodePipe to write to YouTrack? (status changes, PR comments, dashboard mirror)",initialValue:!0})),a=[];for(;;){let d=Xo(await pr({message:a.length===0?"project repo clone URL \u2014 blank if none":"next repo clone URL \u2014 blank to finish",placeholder:"git@bitbucket.org:acme/api.git",validate:h=>!h||!h.trim()||qe(h)?void 0:"use git@host:owner/repo.git or https://host/owner/repo (github.com / gitlab.com / bitbucket.org)"})).trim();if(!d)break;let m=qe(d);Me.message(`${m.host}: ${m.owner}/${m.repoName}`);let f=Xo(await pr({message:"repo logical name (used inside Context Repo paths)",placeholder:m.repoName,initialValue:m.repoName,validate:h=>h.trim().length>0?void 0:"required"})).trim(),g=Xo(await pr({message:"default branch (optional)",placeholder:"main"})).trim(),k={name:f,host:m.host,owner:m.owner,repoName:m.repoName};g&&(k.defaultBranch=g),a.push(k)}let c={projectId:r,name:n,automationLevel:o,repos:a};i&&(c.youtrackProjectKey=i);let l=await dP(r,a),u=q(e.projectId);Me.info(`provisioning Context Repo ${l.owner}/${l.name} (${l.host})\u2026`);let p;try{p=await Nn(c,l,{githubToken:u?.github?.token??process.env.GH_TOKEN??process.env.GITHUB_TOKEN,gitlabToken:u?.gitlab?.token??process.env.GITLAB_TOKEN,bitbucket:u?.bitbucket??tn(),youtrackWrites:s,trackerUrl:u?.youtrack?.url,log:{info:d=>Me.message(d),warn:d=>Me.warn(d)}})}catch(d){Me.error(`Context Repo provisioning failed: ${d instanceof Error?d.message:String(d)}`),process.exit(1)}c.contextRepo=p,Me.info(`submitting \u2192 ${e.hubUrl}/projects`);try{let d=await or(e.hubUrl,e.cliToken,c);Me.success(`project "${d.projectId}" \u2014 ${d.provisioningStatus}`),Qt(r,Tt(c,s,u?.youtrack?.url),{info:m=>Me.message(m),warn:m=>Me.warn(m)}),d.contextRepo&&(Me.message(` context repo: ${d.contextRepo.owner}/${d.contextRepo.name} (${d.contextRepo.cloneUrl})`),Me.message(` branch: ${d.contextRepo.branch}`)),d.provisioningError&&Me.error(` error: ${d.provisioningError}`),uP("done")}catch(d){d instanceof K?(Me.error(`HUB \u2192 ${d.status} ${d.message}`),d.payload&&typeof d.payload=="object"&&Me.message(JSON.stringify(d.payload,null,2))):Me.error(d instanceof Error?d.message:String(d)),process.exit(1)}}jn();Ge();je();me();it();qo();import{existsSync as pP,rmSync as fP}from"node:fs";import{confirm as mP,intro as hP,isCancel as gP,log as fr,outro as yP,spinner as wP}from"@clack/prompts";function Pt(t){fr.error(t),process.exit(1)}var Nk=t=>t.trim().replace(/\/+$/,"");async function Ok(t){hP("codepipe project move \u2014 repoint a project at another HUB");let e=t.fromProfile??t.cliProfile??Ae()?.spec.projectId??void 0;e||Pt("no source project \u2014 pass --from-profile <id> (or run inside a project's workspace folder).");let r=wt(e);r||Pt(`source profile '${e}' is not initialised on this machine (~/.codepipe/profiles/${e}/config.json is missing).`);let n=Nk(r.hubUrl),o=r.projectId,i=Nk(t.hub);i.startsWith("http")||Pt("--hub must be an http(s):// URL");let s=t.toProfile??e,a=t.project??o,c=s===e;c&&a===o&&i===n&&Pt(`profile '${e}' is already on ${n} \u2014 nothing to move.`);let l;{let h=wP();h.start(`reading project ${o} from ${n}\u2026`);try{l=await se(n,r.cliToken,o),h.stop(`read project ${o} (${l.name})`)}catch(w){throw h.stop("could not read the source project",1),w instanceof K&&Pt(`source HUB ${n} \u2192 ${w.status} ${w.message}. The source HUB must be reachable with a valid token to move a project.`),w}}l.contextRepo||Pt(`project ${o} has no Context Repo recorded on the source HUB \u2014 cannot re-register it elsewhere.`);let u=q(o),p=(t.account??r.accountEmail??await Mn()).trim().toLowerCase();if(fr.message(`move project '${o}'
977
977
  from : ${n} (profile ${e})
978
978
  to : ${i} (profile ${s}, project ${a}, account ${p})
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-partner/codepipe",
3
- "version": "0.13.1-dev.257.g5884e02",
3
+ "version": "0.13.1-dev.266.g24c82f1",
4
4
  "description": "CodePipe turns tasks into reviewed pull requests: an AI agent analyzes, implements, and opens a PR under your control.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -29,8 +29,8 @@
29
29
  "@types/ws": "^8.5.13",
30
30
  "esbuild": "^0.21.5",
31
31
  "vitest": "2.1.9",
32
- "@codepipe/shared": "0.0.0",
33
- "@codepipe/sandbox": "0.1.0"
32
+ "@codepipe/sandbox": "0.1.0",
33
+ "@codepipe/shared": "0.0.0"
34
34
  },
35
35
  "scripts": {
36
36
  "build": "tsc -p tsconfig.json && chmod +x dist/index.js",