@code-partner/codepipe 0.13.1-dev.265.g11b4c39 → 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.
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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.
|
|
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(`
|
|
@@ -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.
|
|
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",
|