@code-partner/codepipe 0.14.1-dev.284.gfeac74d2 → 0.14.1-dev.285.g30f288c9
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 Rb=Object.defineProperty;var x=(t,e)=>()=>(t&&(e=t(t=0)),e);var Ge=(t,e)=>{for(var r in e)Rb(t,r,{get:e[r],enumerable:!0})};var Xe,mt,ta=x(()=>{"use strict";Xe="0.14.1-dev.
|
|
2
|
+
var Rb=Object.defineProperty;var x=(t,e)=>()=>(t&&(e=t(t=0)),e);var Ge=(t,e)=>{for(var r in e)Rb(t,r,{get:e[r],enumerable:!0})};var Xe,mt,ta=x(()=>{"use strict";Xe="0.14.1-dev.285.g30f288c9",mt="https://hub.dev.codepipe.dev"});function Jn(t){return typeof t!="number"||!Number.isFinite(t)?!1:t>=Cu&&t<=ht}var ht,Cu,Au=x(()=>{"use strict";ta();ht=4,Cu=4});var Pu=x(()=>{"use strict";ta()});function Zn(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 na(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 oa(t,e=ra){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 ia(t,e=ra){return e.filter(r=>r.version>t)}var _u,gt,zr,ra,ju=x(()=>{"use strict";_u=6,gt=".codepipe-context.yaml",zr=".devpipe-context.yaml",ra=[{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 eo(t){return`model/facts/identity/${t}.yaml`}function kr(t){return`model/facts/events/${t}.yaml`}function ca(t){return`model/facts/annotations/${t}.md`}function la(t){return`model/derived/correlates/${t}.yaml`}function ua(t){return`model/derived/touched/${t}.yaml`}function Nu(t){return t===""?"root":t.replace(/\//g,"-")}function da(t,e){return`model/derived/structure/${t}/${Nu(e)}.yaml`}function ti(t){return typeof t=="string"&&Lu.test(t)}function te(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(!Ou.includes(n))return null;let o=t.slice(e+1,r),i=t.slice(r+1);return o===""&&!_b.includes(n)||i===""?null:{level:n,repo:o,path:i}}function Se(t){return`task::${t}`}function ge(t,e,r){return`${t}:${e}:${r}`}function to(t){let e=[];return St(t)?(ni(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(!St(r)){e.push(`edges[${n}]: not an object`);return}pa.includes(r.kind)||e.push(`edges[${n}].kind: unknown "${String(r.kind)}"`),te(r.from)||e.push(`edges[${n}].from: malformed nodeKey`),te(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 Mu(t){return{...t,edges:Vr(t.edges,e=>`${e.kind} ${e.from} ${e.to}`)}}function br(t){return $r(Mu(t))}function St(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function ni(t){return typeof t=="number"&&Number.isInteger(t)&&t>0}function yt(t){return typeof t=="string"&&t.length>0}function Nb(t){return t.modelFormatVersion!==2}function Ot(t){let e=[];if(!St(t))return{ok:!1,errors:["shard: not an object"]};ni(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(!St(o)){e.push(`nodes[${i}]: not an object`);return}let s=te(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&&!ti(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(!St(o)){e.push(`edges[${i}]: not an object`);return}pa.includes(o.kind)||e.push(`edges[${i}].kind: unknown "${String(o.kind)}"`),(!yt(o.to)||!te(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 ro(t){let e=[];if(!St(t))return{ok:!1,errors:["identity: not an object"]};if(ni(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(!St(n)){e.push(`entities[${o}]: not an object`);return}ti(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)})`),te(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)=>{(!St(i)||!te(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 Lt(t){let e=[];return St(t)?(ni(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(!St(r)||!te(r.key)){e.push(`files[${n}].key: malformed nodeKey`);return}r.entityId!==void 0&&!ti(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 Vr(t,e){return[...t].sort((r,n)=>e(r)<e(n)?-1:e(r)>e(n)?1:0)}function Du(t){return{...t,nodes:Vr(t.nodes,e=>e.key),edges:Vr(t.edges,e=>`${e.kind}\0${e.from}\0${e.to}`)}}function Uu(t){return{...t,entities:Vr(t.entities,e=>e.entityId).map(e=>e.aliases?{...e,aliases:Vr(e.aliases,r=>`${r.key}\0${r.until}`)}:e)}}function Bu(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:Vr(t.files,r=>r.key),...e?{links:e}:{}}}function Qn(t){return Ob.test(t)?t:JSON.stringify(t)}function Fu(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 Gu(t){return t===null||["boolean","number","string"].includes(typeof t)}function sa(t){return Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[r])=>e<r?-1:e>r?1:0)}function Ku(t,e,r){if(Array.isArray(t)){for(let n of t)if(Gu(n))r.push(`${e}- ${Fu(n)}`);else{if(Array.isArray(n))throw new Error("model yaml: nested arrays are not part of the model schema");{let o=sa(n);if(o.length===0){r.push(`${e}- {}`);continue}o.forEach(([i,s],a)=>{let c=a===0?`${e}- `:`${e} `;aa(i,s,c,`${e} `,r)})}}return}for(let[n,o]of sa(t))aa(n,o,e,e,r)}function aa(t,e,r,n,o){if(Gu(e))o.push(`${r}${Qn(t)}: ${Fu(e)}`);else if(Array.isArray(e))e.length===0?o.push(`${r}${Qn(t)}: []`):(o.push(`${r}${Qn(t)}:`),Ku(e,`${n} `,o));else{let i=sa(e);if(i.length===0)o.push(`${r}${Qn(t)}: {}`);else{o.push(`${r}${Qn(t)}:`);for(let[s,a]of i)aa(s,a,`${n} `,`${n} `,o)}}}function $r(t){let e=[];return Ku(t,"",e),e.join(`
|
|
@@ -1013,7 +1013,7 @@ Append-only. Keyed by entityId \u2014 never by path; entries survive renames.
|
|
|
1013
1013
|
${e.body}`),de({prNumber:e.prNumber,inline:!1,host:s.name})}case"tracker_status":{let i=Ct({contextDir:t.contextDir});return i.ok?t.trackerIssueId?(await i.provider.updateStatus(t.trackerIssueId,e.newStatus),de({issueId:t.trackerIssueId,newStatus:e.newStatus})):Z("no tracker_issue_id provided"):Z(i.error)}case"tracker_comment":{let i=Ct({contextDir:t.contextDir});if(!i.ok)return Z(i.error);if(!t.trackerIssueId)return Z("no tracker_issue_id provided");let s=await i.provider.addComment(t.trackerIssueId,e.body,e.author);return de({issueId:t.trackerIssueId,commentId:s.id})}case"create_tracker_issue":{let i=Ct({contextDir:t.contextDir});if(!i.ok)return Z(i.error);if(!e.projectKey)return Z("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 de({issueKey:a,issueId:s})}case"apply_tracker_links":{let i=Ct({contextDir:t.contextDir});if(!i.ok)return Z(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 Z(`${c instanceof Error?c.message:String(c)} (applied ${s}/${e.links.length})`)}return de({applied:s})}case"set_project_setting":{if(!t.contextDir)return Z("no context repo clone on this CLI");let i=await am(t.contextDir,e.edits);return de({files:i.files})}case"set_prompt_override":{if(!t.contextDir)return Z("no context repo clone on this CLI");if(!Ha(e.role))return Z(`unknown prompt operation: ${e.role}`);let i=Wa(e.role);return await Re(t.contextDir,[e.content===null?{path:i,content:"",deleted:!0}:{path:i,content:e.content}],e.commitMessage),t.requestConfigReport?.(),de({path:i,reset:e.content===null})}case"tracker_edit":{let i=Ct({contextDir:t.contextDir});if(!i.ok)return Z(i.error);if(!t.contextDir)return Z("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:[]}]),de({issueKey:e.issueKey})}case"set_youtrack_config":{if(!t.contextDir)return Z("no context repo clone on this CLI");let i=await hm(t.contextDir,e);return de({files:i.files})}case"set_repo_default_branch":{if(!t.contextDir)return Z("no context repo clone on this CLI");let i=await fm(t.contextDir,e);return de({repoName:i.repoName,defaultBranch:i.defaultBranch})}case"sync_config":return t.requestConfigReport?(t.requestConfigReport(),de({reported:!0})):Z("no context repo clone on this CLI");case"refresh_context_status":{if(!t.refreshContextStatus)return Z("no context repo clone on this CLI");let i=await t.refreshContextStatus();return de({outdated:i.outdated,templateVersion:i.templateVersion})}case"run_action":{if(!t.contextDir)return Z("no project workspace on this CLI");if(!r)return Z("no repo spec");if(!t.onRunActivity)return Z("no run-activity stream on this CLI");let i=t.onRunActivity,{defs:s,errors:a}=$i(t.contextDir),c=s.find(m=>m.id===e.actionId);if(!c){let m=a.find(f=>f.file===`actions/${e.actionId}.yml`);return Z(m?`action "${e.actionId}" failed to parse: ${m.error}`:`unknown action "${e.actionId}"`)}let l=_a(c,e.input);if(!l.ok)return Z(l.error);let u=sf(t.contextDir),p=Y(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),_o(`${e.projectId}/${r.name}`,async()=>{await or(e.projectId,r,{baseDir:t.baseDir,cloneUrlOverride:t.cloneUrlOverride});let m=_e(e.projectId,r.name,t.baseDir),f=await nm({cwd:m,def:c,input:l.values,variables:u,secrets:p?.secrets??{},credEnv:d,onEvent:g=>i(e.runId,g)});return de({runId:e.runId,status:f.status,exitCode:f.exitCode,...f.failedStep?{failedStep:f.failedStep}:{}})})}case"read_context_file":{if(!t.contextDir)return Z("no context repo clone on this CLI");let i=sm(t.contextDir,e.path);return de({path:e.path,...i})}case"search_model":{if(!t.contextDir)return Z("no context repo clone on this CLI");let{searchModelIndex:i}=await Promise.resolve().then(()=>(Co(),Io)),s=await i(t.contextDir,e.q,e.limit);return de({hits:s})}case"model_drift":return Z("model_drift requires a local workspace (handled by the daemon)");case"model_bootstrap":return Z("model_bootstrap requires a local workspace (handled by the daemon)");default:return Z(`unsupported action type: ${e.type}`)}}catch(i){return Z(i instanceof Error?i.message:String(i))}}function de(t){return{status:"done",result:t}}function Z(t){return{status:"failed",error:t}}dt();pl();je();pe();import{existsSync as jh,readFileSync as Nh}from"node:fs";import{join as Oh}from"node:path";async function Lh(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=We(e.farmPublicKey);if(i!==e.fingerprint)return o("farm key fingerprint does not match the confirmed one \u2014 refusing to seal (possible relay tampering)");ts(e.farmId,e.farmPublicKey);let s=Y(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=Oh(r,"project.yaml"),m=Oh(r,"regimen.yaml");jh(d)&&jh(m)?c={projectYaml:Nh(d,"utf-8"),regimenYaml:Nh(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=Gt(e.farmPublicKey,JSON.stringify(l));es(e.farmId,i),n.info(`[farm-move] bundle sealed for farm ${e.farmName} (${i}) \u2014 handing off`);let p=await ns(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))}}F();dt();Ke();dt();import{homedir as SE}from"node:os";import{existsSync as EE,mkdirSync as TE,readFileSync as RE,writeFileSync as IE}from"node:fs";import{dirname as CE,join as AE}from"node:path";function hl(){return Q("RUNNER_PINS")??AE(SE(),".codepipe","runner-pins.json")}function Mh(){let t=hl();if(!EE(t))return{};try{return JSON.parse(RE(t,"utf-8"))}catch{return{}}}function PE(t){let e=hl();TE(CE(e),{recursive:!0}),IE(e,JSON.stringify(t,null,2)+`
|
|
1014
1014
|
`,{mode:384})}function _E(t){return Mh()[t]}function gl(t,e){let r=Mh();r[t]=e,PE(r)}function Dh(t,e){let r=We(e),n=_E(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 ${hl()}.`);return r}je();pe();var Bh=t=>({Authorization:`Bearer ${t}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28","User-Agent":"codepipe-cli"});async function Uh(t,e,r,n){let o=await fetch(`https://api.github.com/repos/${e}/${r}/actions/runners/${n}`,{method:"POST",headers:Bh(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 jE={async repoHasAdmin(t,e,r){let n=await fetch(`https://api.github.com/repos/${e}/${r}`,{headers:Bh(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)=>Uh(t,e,r,"registration-token"),mintRemoveToken:(t,e,r)=>Uh(t,e,r,"remove-token")},Fh={api:jE,fetchProject:se,provisionOnRunner:$h,teardownOnRunner:xh};async function Gh(t,e,r){if(e.projectId!==t.projectId)throw new Error(`project mismatch: this daemon serves ${t.projectId}, not ${e.projectId}`);if(We(e.runnerPublicKey)!==e.fingerprint)throw new Error("runner host key fingerprint does not match the confirmed one \u2014 refusing to seal (possible relay tampering)");Dh(e.runnerId,e.runnerPublicKey);let i=Y(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 Kh(t,e,r,n=Fh){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 Gh(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:[Ja(e.runnerId)]},c=Gt(e.runnerPublicKey,JSON.stringify(a));gl(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 Hh(t,e,r,n=Fh){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 Gh(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=Gt(e.runnerPublicKey,JSON.stringify(c));gl(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();F();import{existsSync as NE}from"node:fs";import{join as Wh}from"node:path";import{simpleGit as Yh}from"simple-git";async function yl(t,e,r,n,o){for(let i of r.repos){let s=e.find(u=>u.name===i.repoName);if(!s)continue;let a=`${r.taskKey}:${s.name}:${i.branchName}`;if(!so(i.branchName)){n.has(a)||(n.add(a),o.warn(`[pull] ${r.taskKey} ${s.mountAs}: refusing suspicious branch name`));continue}let c=Wh(t,s.mountAs);if(!NE(Wh(c,".git")))continue;let l=Yh(c);try{let u=await ME(l,i.branchName);await l.fetch(await OE(l,s),`refs/heads/${i.branchName}`);let p=(await l.revparse(["FETCH_HEAD"])).trim();if(u===p)continue;if(await LE(l,c,i.branchName)){n.has(a)||(n.add(a),o.info(`[pull] ${r.taskKey} \u2192 ${s.mountAs}: ${i.branchName} is checked out here \u2014 fetched ${p.slice(0,10)}; merge or pull it in that checkout yourself`));continue}await l.raw(["branch","-f",i.branchName,p]),o.info(`[pull] ${r.taskKey} \u2192 ${s.mountAs}: ${i.branchName} ${p.slice(0,10)} (checkout untouched)`)}catch(u){if(n.has(a))continue;n.add(a),o.warn(`[pull] ${r.taskKey} ${s.mountAs}: ${i.branchName} unavailable \u2014 `+(u instanceof Error?u.message.split(`
|
|
1015
1015
|
`)[0]:String(u)))}}}async function OE(t,e){if(e.mirror)return qh(e.mirror);try{if((await t.getRemotes(!0)).find(n=>n.name==="origin")?.refs?.fetch)return"origin"}catch{}return e.host&&e.owner&&e.repoName?qh({host:e.host,owner:e.owner,repoName:e.repoName}):"origin"}function qh(t){return t.host==="github"?`git@github.com:${t.owner}/${t.repoName}.git`:t.host==="gitlab"?`git@gitlab.com:${t.owner}/${t.repoName}.git`:`git@bitbucket.org:${t.owner}/${t.repoName}.git`}async function LE(t,e,r){try{return(await t.raw(["worktree","list","--porcelain"])).split(`
|
|
1016
|
-
`).some(o=>o.trim()===`branch refs/heads/${r}`)}catch{try{return(await Yh(e).revparse(["--abbrev-ref","HEAD"])).trim()===r}catch{return!1}}}async function ME(t,e){try{return(await t.revparse([e])).trim()}catch{return null}}var ss=class{constructor(e,r,n,o){this.intervalMs=e;this.fetchDeliverables=r;this.workspace=n;this.log=o}timer=null;running=!1;caughtUp=!1;warned=new Set;start(){if(this.timer)return;this.log.info(`[pull] local delivery started (interval=${this.intervalMs}ms)`);let e=()=>void this.runOnce();e(),this.timer=setInterval(e,this.intervalMs)}stop(){this.timer&&(clearInterval(this.timer),this.timer=null,this.log.info("[pull] local delivery stopped"))}poke(){this.runOnce()}async runOnce(){if(!this.running){this.running=!0;try{let e=await this.fetchDeliverables(),r=this.caughtUp?e.filter(n=>n.phase==="TRACKING"||n.phase==="AWAITING_CLUSTER"):e;for(let n of r)await yl(this.workspace.root,this.workspace.repos,n,this.warned,this.log);this.caughtUp=!0}catch(e){this.log.warn(`[pull] pass failed: ${e instanceof Error?e.message:String(e)}`)}finally{this.running=!1}}}};F();dt();pe();var zh=16*1024;function DE(t){return Ze.test(t)?Mt(t)?`secret name "${t}" is reserved`:null:`secret name must match ${Ze}`}function Vh(t,e,r,n){let o=DE(e);if(o)return{ok:!1,detail:o};let i;try{let s=JSON.parse(kn(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>zh)return{ok:!1,detail:`secret value too large (max ${zh} chars)`};try{return np(t,e,i),{ok:!0}}catch(s){return{ok:!1,detail:s instanceof Error?s.message:String(s)}}}function Xh(t,e){try{return op(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)}}}dn();pe();Jt();var as=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}=fo(o,a.repoSpec);try{let u=await l.getPullRequest(c,a.number);n.push({number:a.number,repoName:a.repoSpec.name,url:a.url,state:u.state,merged:u.merged,ci:u.ci,mergeable:u.mergeable})}catch(u){if(u instanceof Rr){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.repoName??""}#${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}=fo(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=UE(n);this.log.info(`[track] task=${e} snapshot signalled${s?` \u2192 ${s}`:""} (${n.length} PR(s))`)}};function UE(t){return t.length===0?null:t.some(e=>e.state==="closed"&&!e.merged)?"needs_manual":t.every(e=>e.merged)?"done":null}F();var cs=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??(()=>Ct({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 v=e.stageField?{stageField:e.stageField}:{},S=e.requireAssignee&&e.assignee?{assignee:e.assignee}:e.requireAssignee&&!e.assignee?{requireAnyAssignee:!0}:{},$=(e.backlogScope??"personal")==="shared"&&!!e.requireAssignee&&!!e.backlogColumn;if(r.kind==="internal")o=await r.listIssues({projectKey:e.projectKey});else if($){let b=[...new Set([...e.sourceColumns,...e.rejectColumns??[],...e.doneColumns??[],...e.reviewColumns??[]])],[I,N]=await Promise.all([b.length>0?r.listIssues({projectKey:e.projectKey,columns:b,...v,...S}):Promise.resolve([]),r.listIssues({projectKey:e.projectKey,columns:[e.backlogColumn],...v})]),H=new Map;for(let z of[...I,...N])H.set(z.id,z);o=[...H.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,...v,...S})}}catch(v){let S=v instanceof Error?v.message:String(v);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 v of o){if(s.add(v.id),a.has(v.status))continue;let S=await Qh(r,v.id,e.sinceMs,this.log);S&&i.set(v.id,S)}let c=[];for(let v of e.offBoardIssueIds){if(s.has(v))continue;let S=await Qh(r,v,e.sinceMs,this.log);if(S&&S.length>0&&i.set(v,S),e.requireAssignee||S&&S.length>0){let R=await Zh(r,v,e.stageField,this.log);if(R)c.push(R);else if(S&&S.length>0){this.abandonTick("off-board issue fetch failed with new comments");return}}}let l=o.filter(v=>!a.has(v.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(v=>({issue:v,comments:i.get(v.id)??[],attachments:u.get(v.id)??[]}));d.push(...await lh(this.options.contextDir,d,v=>Zh(r,v,e.stageField,this.log)));try{await Xi(this.options.contextDir,e.projectId,d),this.abandonedTicks=0;for(let v of p)this.shippedAttachments.add(v)}catch(v){let S=v instanceof Error?v.message:String(v);this.abandonTick(`context task sync failed: ${S}`);return}let m=this.options.isSelfComment??(()=>!1),f=[],g=[];for(let[v,S]of i){let R=S.filter(b=>!m(b.id));if(R.length===0)continue;f.push({issueId:v,comments:R.map(BE)});let $=R.flatMap(b=>{let I=Sr(b.body);return I?[{commentId:b.id,author:b.author,name:I.name,args:I.args,createdAt:b.createdAt}]:[]});$.length>0&&g.push({issueId:v,commands:$})}let k={type:"youtrack_observation",projectId:e.projectId,issues:o.map(Jh),commentsBatch:f,...g.length>0?{commandsBatch:g}:{},...c.length>0?{offBoardIssues:c.map(Jh)}:{},observedAtMs:n};this.send(k);let h=f.reduce((v,S)=>v+S.comments.length,0),w=g.reduce((v,S)=>v+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=FE(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 Jh(t){let{description:e,...r}=t;return r}function BE(t){let{body:e,...r}=t;return r}function FE(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 Zh(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 Qh(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 oT(t,e){let r=t.repos.filter(i=>i.mirror);if(r.length===0)return[];let{mirrorLag:n}=await Promise.resolve().then(()=>(Zi(),Ji)),o=[];for(let i of r){let s=i.mountAs==="."?t.root:Or(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 Rl="npm i -g @code-partner/codepipe@latest";function ms(t,e={}){let r=e.log??{info:h=>console.log(h),warn:h=>console.warn(h)};r.info(`codepipe-cli v${Xe} (protocol ${ht})`);let n=h=>e.onEvent?.(h),o=e.workspace;o?.contextDir&&lf(o.contextDir,r);let i=()=>{if(o?.contextDir)try{hn(o.contextDir,o.root,r)}catch(h){r.warn(`[skills] materialize failed (non-fatal): ${h instanceof Error?h.message:String(h)}`)}};i();let s=Cl("CLI_TRACKING_POLL_INTERVAL_SEC"),a=Cl("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=rs(t.hubUrl,t.cliToken),w=null,v=new as(s,M=>{h.readyState===h.OPEN&&h.send(JSON.stringify(M))},r),S=o&&o.repos.length>0?new ss(Cl("CLI_LOCAL_PULL_INTERVAL_SEC"),()=>is(t.hubUrl,t.cliToken,t.projectId),{root:o.root,repos:o.repos},r):null,R=new cs(a,M=>{h.readyState===h.OPEN&&h.send(JSON.stringify(M))},r,{contextDir:o?.contextDir??null,isSelfComment:M=>f.has(M)}),$=null,b=async()=>{try{let M={trackerProvider:ll(o?.contextDir??null)};try{let E=await se(t.hubUrl,t.cliToken,t.projectId);M={...M,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 B=await Yp(t.projectId,M),D=o?await oT(o,r):[];if(i(),h.readyState!==h.OPEN)return;let X={type:"cli_readiness",projectId:t.projectId,ready:B.ready,checks:B.checks,creds:B.creds,secretNames:ip(t.projectId),...o?{mirrors:D}:{},checkedAt:B.checkedAt};if(h.send(JSON.stringify(X)),B.ready)r.info("[readiness] ready");else{let E=B.checks.filter(C=>!C.ok).map(C=>`${C.name}(${C.detail??""})`);r.warn(`[readiness] NOT ready \u2014 ${E.join(", ")}`)}let G=Qp(B.creds,p);if(G==="open"){p=!0;let E=ef(t.hubUrl,t.projectId);r.info(`[agent-auth] Claude token invalid (401) \u2014 opening the dashboard to re-authorize: ${E}`),Ar(E)}else G==="rearm"&&(p=!1)}catch(M){r.warn(`[readiness] check failed: ${M instanceof Error?M.message:String(M)}`)}},I=()=>{b(),$=setInterval(()=>void b(),c),typeof $.unref=="function"&&$.unref()},N=()=>{$&&(clearInterval($),$=null)},H=150,z=new Map,_=M=>{let B=z.get(M);if(!B||(B.timer&&clearTimeout(B.timer),z.delete(M),B.events.length===0||h.readyState!==h.OPEN))return;let D={type:"run_activity",projectId:t.projectId,runId:M,events:B.events};h.send(JSON.stringify(D))},y=(M,B)=>{let D=z.get(M);if(D||(D={events:[],timer:null},z.set(M,D)),D.events.push(B),B.kind==="result"){_(M);return}D.timer||(D.timer=setTimeout(()=>_(M),H),D.timer.unref?.())},U=o?.contextDir?new xi(o.contextDir,t.projectId,M=>{h.readyState===h.OPEN&&h.send(JSON.stringify(M))},r):null,O=async()=>{let M=o?.contextDir;if(!M)throw new Error("no context repo clone on this CLI");let B;try{B=(await se(t.hubUrl,t.cliToken,t.projectId)).contextRepo}catch{}let D=await Nf(M,t.projectId,B,r);return h.readyState===h.OPEN&&h.send(JSON.stringify(D)),D},K=null,ee=async()=>{let M=o?.contextDir;if(M)try{let{readContextIndexHub:B,collectSearchRows:D}=await Promise.resolve().then(()=>(Co(),Io));if(B(M)!=="metadata")return;let X=D(M);h.readyState===h.OPEN&&(h.send(JSON.stringify({type:"model_index",projectId:t.projectId,rows:X})),r.info(`[model] tier-2 index snapshot pushed (${X.length} rows)`))}catch(B){r.warn(`[model] tier-2 index push failed (non-fatal): ${B instanceof Error?B.message:String(B)}`)}},le=()=>{K&&clearTimeout(K),K=setTimeout(()=>void ee(),5e3)},Nt=async()=>{if(!o?.contextDir)throw new Error("no Context Repo clone on this CLI");if(m)throw new Error("model bootstrap is already running");m=!0;try{let M=await se(t.hubUrl,t.cliToken,t.projectId),{bootstrapDaemonModel:B}=await Promise.resolve().then(()=>(Lo(),fs)),D=await B(t.projectId,{root:o.root,contextDir:o.contextDir},M.repos,X=>r.info(`[model] ${X}`));return r.info(`[model] bootstrap done: ${D.repos} repos, ${D.events} task events`),le(),D}finally{m=!1}},Ue=null,Ne=async M=>{if(o?.contextDir)try{let B=await Promise.resolve().then(()=>(Lo(),fs)),D={root:o.root,contextDir:o.contextDir,repos:o.repos};if(B.shouldAutoBootstrapModel(o.contextDir)){await B.syncWorkspaceMirrors(D,G=>r.info(G));try{await Nt()}catch(G){r.warn(`[model] auto-bootstrap failed (non-fatal): ${G instanceof Error?G.message:String(G)}`)}return}(await B.rebuildWorkspaceModelIfStale(D,{fetch:M,onLog:G=>r.info(G)})).rebuilt.length>0&&le()}catch(B){r.warn(`[model] release-path rebuild failed (non-fatal): ${B instanceof Error?B.message:String(B)}`)}},Pe=M=>{Ue&&clearTimeout(Ue),Ue=setTimeout(()=>void Ne(M),6e4)},Be=setInterval(()=>void Ne(!0),6*36e5);return h.on("open",()=>{r.info("[ws] connected"),n({kind:"connected"});let M=fp(t.projectId),B=Q("ORIGIN")==="farm"?"farm":"local",D=Q("FARM_ID"),X=t.accountEmail??M.email,G;try{let C=Qf(t.projectId);C&&(G=C.publicKey,r.info(`[cred-channel] key fingerprint: ${C.fingerprint}`))}catch(C){r.warn(`[cred-channel] key setup failed (token replacement via dashboard unavailable): ${C instanceof Error?C.message:String(C)}`)}let E={type:"register",projectId:t.projectId,platformVersion:Xe,protocolVersion:ht,accountId:M.accountId,accountLabel:M.label,origin:B,inFlightActionIds:[...d],...X?{accountEmail:X}:{},...B==="farm"&&D?{farmId:D}:{},...G?{sealPublicKey:G}:{}};h.send(JSON.stringify(E))}),h.on("message",async M=>{let B=M.toString("utf-8");if(B==="pong"||B==="ping")return;let D;try{D=JSON.parse(B)}catch{return}if(!D||typeof D!="object")return;let X=D.type;if(X==="registered"){let E=D;if(E.ok){if(r.info(`[ws] registered for project ${E.projectId}`),n({kind:"registered",projectId:E.projectId??t.projectId}),v.start(),S?.start(),U?.start(),I(),Il(t,o,r),o?.contextDir){try{let C=Ci(o.contextDir,t.projectId);h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.outdated&&(r.warn(`[ctx] context format outdated: v${C.templateVersion} \u2192 v${C.currentVersion}`+(C.missingPaths.length>0?` (missing: ${C.missingPaths.join(", ")})`:"")),u||(u=!0,O().catch(()=>{})))}catch(C){r.warn(`[ctx] context-format detect failed (non-fatal): ${C instanceof Error?C.message:String(C)}`)}ee(),Pe(!0)}}else r.warn(`[ws] register rejected: ${E.reason??"unknown"}`),n({kind:"register_rejected",reason:E.reason??"unknown"}),l=!0,h.close();return}if(X==="hello"){let E=D;w=Jn(E.protocolVersion);let C=w?"compatible":"INCOMPATIBLE";r.info(`[ws] hub v${E.platformVersion} (protocol ${E.protocolVersion}) \u2014 ${C}`),w||(r.warn(`[ws] HUB protocol incompatible with this CLI (v${Xe}, protocol ${ht}) \u2014 WriteActions will be refused until versions align.`),r.warn(`[ws] update the CLI: ${Rl}`),n({kind:"incompatible",hubVersion:typeof E.platformVersion=="string"?E.platformVersion:null,hubProtocol:typeof E.protocolVersion=="number"?E.protocolVersion:null,updateCommand:Rl}));return}if(X==="tracking_targets"){v.setTargets(D.targets),S?.poke();return}if(X==="youtrack_sync_request"){R.setRequest(D);return}if(X==="youtrack_force_sync"){R.forceSync();return}if(X==="sync_local"){await aT(D,o,h,r);return}if(X==="provision_repo"){let E=D;r.info(`[repo] provision_repo: ${E.repo.name} (${E.repo.host}:${E.repo.owner}/${E.repo.repoName})`),await iT(t,o,E.repo,r),await Il(t,o,r);return}if(X==="remove_repo"){let E=D;r.info(`[repo] remove_repo: ${E.repoName}${E.purge?" (purge)":""}`),await Il(t,o,r),E.purge&&sT(t,o,E.repoName,r);return}if(X==="context_write"){await cT(D,o,h,r),i();return}if(X==="adr_promote"){await lT(D,o,h,r),i();return}if(X==="cred_update"){let E=D,C=Y(t.projectId),T=C?.sealKey?await em(t.projectId,E.kind,E.sealed,C.sealKey.privateKey):{ok:!1,detail:"no cred-channel key on this CLI (restart the daemon)"},P={type:"cred_update_result",updateId:E.updateId,projectId:t.projectId,ok:T.ok,...T.detail?{detail:T.detail}:{}};h.readyState===h.OPEN&&h.send(JSON.stringify(P)),T.ok?(r.info(`[cred] ${E.kind} replaced${T.detail?` \u2014 ${T.detail}`:""}`),b()):r.warn(`[cred] ${E.kind} replacement rejected: ${T.detail??"unknown"}`);return}if(X==="readiness_check"){r.info("[readiness] on-demand check requested"),b();return}if(X==="agent_login_start"){Zp(t,h,D,r,b);return}if(X==="move_to_farm"){let E=D;r.info(`[farm-move] request to move ${t.projectId} onto farm ${E.farmName} (${E.farmId})`);let C=await Lh(t,E,o?.contextDir,r);h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.ok?r.info(`[farm-move] done \u2014 farm daemon ${C.daemonStatus??"started"}; expecting takeover`):r.warn(`[farm-move] failed: ${C.error??"unknown error"}`);return}if(X==="gh_runner_setup"){let E=D;r.info(`[ghr] runner setup for ${t.projectId} on runner host ${E.runnerName} (${E.runnerId})`);let C=await Kh(t,E,r);h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.ok?r.info(`[ghr] runners connected on ${E.runnerName}`):r.warn(`[ghr] setup failed: ${C.error??"see per-repo statuses"}`);return}if(X==="gh_runner_teardown"){let E=D;r.info(`[ghr] runner teardown for ${t.projectId} on runner host ${E.runnerName} (${E.runnerId})`);let C=await Hh(t,E,r);h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.ok?r.info(`[ghr] runners disconnected from ${E.runnerName}`):r.warn(`[ghr] teardown failed: ${C.error??"unknown error"}`);return}if(X==="tracker_fields_request"){let E=D,C={type:"tracker_fields_result",requestId:E.requestId,projectId:t.projectId,ok:!1},T=Ct({contextDir:o?.contextDir??null});if(!T.ok)C.error=T.error;else try{C.fields=await T.provider.fetchStateFields(E.projectKey),C.ok=!0}catch(P){C.error=P instanceof Error?P.message:String(P)}h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.ok||r.warn(`[yt-fields] listing failed: ${C.error??"unknown"}`);return}if(X==="project_secret_update"||X==="project_secret_delete"){let E=D,C;if(E.type==="project_secret_update"){let P=Y(t.projectId);C=P?.sealKey?Vh(t.projectId,E.name,E.sealed,P.sealKey.privateKey):{ok:!1,detail:"no cred-channel key on this CLI (restart the daemon)"}}else C=Xh(t.projectId,E.name);let T={type:"project_secret_update_result",updateId:E.updateId,projectId:t.projectId,ok:C.ok,...C.detail?{detail:C.detail}:{}};h.readyState===h.OPEN&&h.send(JSON.stringify(T)),C.ok?(r.info(`[secret] ${E.name} ${E.type==="project_secret_update"?"saved":"deleted"}`+(C.detail?` \u2014 ${C.detail}`:"")),b()):r.warn(`[secret] ${E.name} rejected: ${C.detail??"unknown"}`);return}if(X==="sandbox_keys"){let E=Y(t.projectId);if(!E){r.warn(`[cred] sandbox_keys received but no secrets for ${t.projectId} \u2014 cannot seal`);return}let C=an(t.projectId),T=Vf(D,E,C,r);for(let P of T)h.readyState===h.OPEN&&h.send(JSON.stringify(P));return}if(X!=="dispatch_action")return;let G=D;if(w===!1){let E=`refused: HUB protocol incompatible with CLI v${Xe} (protocol ${ht})`;h.send(JSON.stringify({type:"action_result",actionId:G.actionId,status:"failed",error:E})),r.warn(`[exec] ${G.actionId} (${G.action.type}) \u2192 REFUSED: ${E}`),r.warn(`[exec] update the CLI to clear this: ${Rl}`),n({kind:"action",actionId:G.actionId,actionType:G.action.type,ok:!1,error:E});return}if(G.action.type==="model_drift"){d.add(G.actionId);try{let E,C=o?.repos.find(T=>T.name===G.action.repoName);if(!o?.contextDir||!C)E={status:"failed",error:"no local workspace/repo clone on this CLI"};else try{let{computeDriftReport:T}=await Promise.resolve().then(()=>(fg(),pg)),P=C.mountAs==="."?o.root:Or(o.root,C.mountAs);E={status:"done",result:{report:await T(P,o.contextDir,C.name)}}}catch(T){E={status:"failed",error:T instanceof Error?T.message:String(T)}}h.send(JSON.stringify({type:"action_result",actionId:G.actionId,...E}))}finally{d.delete(G.actionId)}return}if(G.action.type==="model_bootstrap"){d.add(G.actionId);try{let E;try{let C=await Nt();E={status:"done",result:{repos:C.repos,events:C.events}}}catch(C){E={status:"failed",error:C instanceof Error?C.message:String(C)},r.warn(`[model] bootstrap failed: ${E.error}`)}h.readyState===h.OPEN&&h.send(JSON.stringify({type:"action_result",actionId:G.actionId,...E}))}finally{d.delete(G.actionId)}return}d.add(G.actionId);try{let E=await kh({action:G.action,repo:G.repo,trackerIssueId:G.trackerIssueId,contextDir:o?.contextDir,requestConfigReport:U?()=>U.reportNow():void 0,refreshContextStatus:o?.contextDir?O:void 0,onRunActivity:y}).catch(P=>({status:"failed",error:P instanceof Error?P.message:String(P)}));G.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:G.actionId,...E}));let C=E.status!=="failed",T=!C&&"error"in E?E.error:void 0;C?r.info(`[exec] ${G.actionId} (${G.action.type}) \u2192 done`):r.warn(`[exec] ${G.actionId} (${G.action.type}) \u2192 FAILED: ${T??"?"}`),n({kind:"action",actionId:G.actionId,actionType:G.action.type,ok:C,...T?{error:T}:{}}),C&&["apply_delivery","context_write","create_pr"].includes(G.action.type)&&le(),C&&["merge_pr","merge_branch"].includes(G.action.type)&&Pe(!0)}finally{d.delete(G.actionId)}}),h.on("close",(M,B)=>{let D=B?.toString("utf-8")??"";if(r.info(`[ws] closed code=${M}${D?` reason=${D}`:""}`),v.stop(),S?.stop(),R.stop(),U?.stop(),N(),clearInterval(Be),Ue&&clearTimeout(Ue),K&&clearTimeout(K),D==="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:M}),!l&&setTimeout(()=>{g=k()},2e3)}),h.on("error",M=>r.warn(`[ws] error: ${M.message}`)),h}return{stop(){l=!0,g.close()}}}async function Il(t,e,r){try{let n=await se(t.hubUrl,t.cliToken,t.projectId),{updated:o,errors:i}=vo(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 iT(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?Or(e.root,o):_e(t.projectId,r.name);if(mg(Or(i,".git"))){n.info(`[repo] ${r.name} already present at ${i}`);return}try{await nT().clone(e?ji(r):Fc(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 sT(t,e,r,n){let o=e?.repos.find(s=>s.name===r)?.mountAs??r,i=e?Or(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(!mg(Or(i,".git"))){n.info(`[repo] no local clone to purge for ${r} (${i})`);return}try{rT(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 aT(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=Or(e.root,i?.mountAs??o.repoName),a=i?.defaultBranch??o.defaultBranch,c=await tf(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 cT(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 Re(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 lT(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 gf(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 Cl(t){let e=parseInt(process.env[t]??"60",10);return Number.isFinite(e)&&e>0?e*1e3:6e4}je();pe();Ft();Pl();wt();Oi();async function Tg(t={profile:void 0}){let{cfg:e,profile:r}=sn(t.profile),n=Y(e.projectId);n&&po(n),xo(n?.github?.token??process.env.GH_TOKEN)&&console.log("[git] github.com over token-HTTPS (insteadOf) \u2014 farm transport"),So(n?.gitlab?.token??process.env.GITLAB_TOKEN)&&console.log("[git] gitlab.com over token-HTTPS (insteadOf) \u2014 farm transport"),Eo(n?.bitbucket?.apiToken||process.env.BITBUCKET_API_TOKEN)&&console.log("[git] bitbucket.org over token-HTTPS (insteadOf) \u2014 farm transport");let o=Mo(_l(),".codepipe","logs"),i=r?`cli-daemon-${r}`:"cli-daemon",s=mi("CLI_LOG",i,o);if(s.enabled){let d=new ln(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=nn(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=Mo(_l(),".codepipe",r?Mo("profiles",r,"context"):"context");if(await ml(e.hubUrl,e.cliToken,e.projectId,{phase:"context_cloning"}).catch(()=>{}),a=await Sg(()=>gs({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 ml(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=Mo(_l(),".codepipe",r?Mo("profiles",r,"context-config"):"context-config");Si(a.contextDir,m,{info:f=>console.log(f),warn:f=>console.warn(f)})}}let l=ms(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(`
|
|
1016
|
+
`).some(o=>o.trim()===`branch refs/heads/${r}`)}catch{try{return(await Yh(e).revparse(["--abbrev-ref","HEAD"])).trim()===r}catch{return!1}}}async function ME(t,e){try{return(await t.revparse([e])).trim()}catch{return null}}var ss=class{constructor(e,r,n,o){this.intervalMs=e;this.fetchDeliverables=r;this.workspace=n;this.log=o}timer=null;running=!1;caughtUp=!1;warned=new Set;start(){if(this.timer)return;this.log.info(`[pull] local delivery started (interval=${this.intervalMs}ms)`);let e=()=>void this.runOnce();e(),this.timer=setInterval(e,this.intervalMs)}stop(){this.timer&&(clearInterval(this.timer),this.timer=null,this.log.info("[pull] local delivery stopped"))}poke(){this.runOnce()}async runOnce(){if(!this.running){this.running=!0;try{let e=await this.fetchDeliverables(),r=this.caughtUp?e.filter(n=>n.phase==="TRACKING"||n.phase==="AWAITING_CLUSTER"):e;for(let n of r)await yl(this.workspace.root,this.workspace.repos,n,this.warned,this.log);this.caughtUp=!0}catch(e){this.log.warn(`[pull] pass failed: ${e instanceof Error?e.message:String(e)}`)}finally{this.running=!1}}}};F();dt();pe();var zh=16*1024;function DE(t){return Ze.test(t)?Mt(t)?`secret name "${t}" is reserved`:null:`secret name must match ${Ze}`}function Vh(t,e,r,n){let o=DE(e);if(o)return{ok:!1,detail:o};let i;try{let s=JSON.parse(kn(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>zh)return{ok:!1,detail:`secret value too large (max ${zh} chars)`};try{return np(t,e,i),{ok:!0}}catch(s){return{ok:!1,detail:s instanceof Error?s.message:String(s)}}}function Xh(t,e){try{return op(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)}}}dn();pe();Jt();var as=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}=fo(o,a.repoSpec);try{let u=await l.getPullRequest(c,a.number);n.push({number:a.number,repoName:a.repoSpec.name,url:a.url,state:u.state,merged:u.merged,ci:u.ci,mergeable:u.mergeable})}catch(u){if(u instanceof Rr){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.repoName??""}#${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}=fo(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=UE(n);this.log.info(`[track] task=${e} snapshot signalled${s?` \u2192 ${s}`:""} (${n.length} PR(s))`)}};function UE(t){return t.length===0?null:t.some(e=>e.state==="closed"&&!e.merged)?"needs_manual":t.every(e=>e.merged)?"done":null}F();var cs=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??(()=>Ct({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 v=e.stageField?{stageField:e.stageField}:{},S=e.requireAssignee&&e.assignee?{assignee:e.assignee}:e.requireAssignee&&!e.assignee?{requireAnyAssignee:!0}:{},$=(e.backlogScope??"personal")==="shared"&&!!e.requireAssignee&&!!e.backlogColumn;if(r.kind==="internal")o=await r.listIssues({projectKey:e.projectKey});else if($){let b=[...new Set([...e.sourceColumns,...e.rejectColumns??[],...e.doneColumns??[],...e.reviewColumns??[]])],[I,N]=await Promise.all([b.length>0?r.listIssues({projectKey:e.projectKey,columns:b,...v,...S}):Promise.resolve([]),r.listIssues({projectKey:e.projectKey,columns:[e.backlogColumn],...v})]),H=new Map;for(let z of[...I,...N])H.set(z.id,z);o=[...H.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,...v,...S})}}catch(v){let S=v instanceof Error?v.message:String(v);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 v of o){if(s.add(v.id),a.has(v.status))continue;let S=await Qh(r,v.id,e.sinceMs,this.log);S&&i.set(v.id,S)}let c=[];for(let v of e.offBoardIssueIds){if(s.has(v))continue;let S=await Qh(r,v,e.sinceMs,this.log);S&&S.length>0&&i.set(v,S);let R=await Zh(r,v,e.stageField,this.log);if(R)c.push(R);else if(S&&S.length>0){this.abandonTick("off-board issue fetch failed with new comments");return}}let l=o.filter(v=>!a.has(v.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(v=>({issue:v,comments:i.get(v.id)??[],attachments:u.get(v.id)??[]}));d.push(...await lh(this.options.contextDir,d,v=>Zh(r,v,e.stageField,this.log)));try{await Xi(this.options.contextDir,e.projectId,d),this.abandonedTicks=0;for(let v of p)this.shippedAttachments.add(v)}catch(v){let S=v instanceof Error?v.message:String(v);this.abandonTick(`context task sync failed: ${S}`);return}let m=this.options.isSelfComment??(()=>!1),f=[],g=[];for(let[v,S]of i){let R=S.filter(b=>!m(b.id));if(R.length===0)continue;f.push({issueId:v,comments:R.map(BE)});let $=R.flatMap(b=>{let I=Sr(b.body);return I?[{commentId:b.id,author:b.author,name:I.name,args:I.args,createdAt:b.createdAt}]:[]});$.length>0&&g.push({issueId:v,commands:$})}let k={type:"youtrack_observation",projectId:e.projectId,issues:o.map(Jh),commentsBatch:f,...g.length>0?{commandsBatch:g}:{},...c.length>0?{offBoardIssues:c.map(Jh)}:{},observedAtMs:n};this.send(k);let h=f.reduce((v,S)=>v+S.comments.length,0),w=g.reduce((v,S)=>v+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=FE(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 Jh(t){let{description:e,...r}=t;return r}function BE(t){let{body:e,...r}=t;return r}function FE(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 Zh(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 Qh(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 oT(t,e){let r=t.repos.filter(i=>i.mirror);if(r.length===0)return[];let{mirrorLag:n}=await Promise.resolve().then(()=>(Zi(),Ji)),o=[];for(let i of r){let s=i.mountAs==="."?t.root:Or(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 Rl="npm i -g @code-partner/codepipe@latest";function ms(t,e={}){let r=e.log??{info:h=>console.log(h),warn:h=>console.warn(h)};r.info(`codepipe-cli v${Xe} (protocol ${ht})`);let n=h=>e.onEvent?.(h),o=e.workspace;o?.contextDir&&lf(o.contextDir,r);let i=()=>{if(o?.contextDir)try{hn(o.contextDir,o.root,r)}catch(h){r.warn(`[skills] materialize failed (non-fatal): ${h instanceof Error?h.message:String(h)}`)}};i();let s=Cl("CLI_TRACKING_POLL_INTERVAL_SEC"),a=Cl("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=rs(t.hubUrl,t.cliToken),w=null,v=new as(s,M=>{h.readyState===h.OPEN&&h.send(JSON.stringify(M))},r),S=o&&o.repos.length>0?new ss(Cl("CLI_LOCAL_PULL_INTERVAL_SEC"),()=>is(t.hubUrl,t.cliToken,t.projectId),{root:o.root,repos:o.repos},r):null,R=new cs(a,M=>{h.readyState===h.OPEN&&h.send(JSON.stringify(M))},r,{contextDir:o?.contextDir??null,isSelfComment:M=>f.has(M)}),$=null,b=async()=>{try{let M={trackerProvider:ll(o?.contextDir??null)};try{let E=await se(t.hubUrl,t.cliToken,t.projectId);M={...M,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 B=await Yp(t.projectId,M),D=o?await oT(o,r):[];if(i(),h.readyState!==h.OPEN)return;let X={type:"cli_readiness",projectId:t.projectId,ready:B.ready,checks:B.checks,creds:B.creds,secretNames:ip(t.projectId),...o?{mirrors:D}:{},checkedAt:B.checkedAt};if(h.send(JSON.stringify(X)),B.ready)r.info("[readiness] ready");else{let E=B.checks.filter(C=>!C.ok).map(C=>`${C.name}(${C.detail??""})`);r.warn(`[readiness] NOT ready \u2014 ${E.join(", ")}`)}let G=Qp(B.creds,p);if(G==="open"){p=!0;let E=ef(t.hubUrl,t.projectId);r.info(`[agent-auth] Claude token invalid (401) \u2014 opening the dashboard to re-authorize: ${E}`),Ar(E)}else G==="rearm"&&(p=!1)}catch(M){r.warn(`[readiness] check failed: ${M instanceof Error?M.message:String(M)}`)}},I=()=>{b(),$=setInterval(()=>void b(),c),typeof $.unref=="function"&&$.unref()},N=()=>{$&&(clearInterval($),$=null)},H=150,z=new Map,_=M=>{let B=z.get(M);if(!B||(B.timer&&clearTimeout(B.timer),z.delete(M),B.events.length===0||h.readyState!==h.OPEN))return;let D={type:"run_activity",projectId:t.projectId,runId:M,events:B.events};h.send(JSON.stringify(D))},y=(M,B)=>{let D=z.get(M);if(D||(D={events:[],timer:null},z.set(M,D)),D.events.push(B),B.kind==="result"){_(M);return}D.timer||(D.timer=setTimeout(()=>_(M),H),D.timer.unref?.())},U=o?.contextDir?new xi(o.contextDir,t.projectId,M=>{h.readyState===h.OPEN&&h.send(JSON.stringify(M))},r):null,O=async()=>{let M=o?.contextDir;if(!M)throw new Error("no context repo clone on this CLI");let B;try{B=(await se(t.hubUrl,t.cliToken,t.projectId)).contextRepo}catch{}let D=await Nf(M,t.projectId,B,r);return h.readyState===h.OPEN&&h.send(JSON.stringify(D)),D},K=null,ee=async()=>{let M=o?.contextDir;if(M)try{let{readContextIndexHub:B,collectSearchRows:D}=await Promise.resolve().then(()=>(Co(),Io));if(B(M)!=="metadata")return;let X=D(M);h.readyState===h.OPEN&&(h.send(JSON.stringify({type:"model_index",projectId:t.projectId,rows:X})),r.info(`[model] tier-2 index snapshot pushed (${X.length} rows)`))}catch(B){r.warn(`[model] tier-2 index push failed (non-fatal): ${B instanceof Error?B.message:String(B)}`)}},le=()=>{K&&clearTimeout(K),K=setTimeout(()=>void ee(),5e3)},Nt=async()=>{if(!o?.contextDir)throw new Error("no Context Repo clone on this CLI");if(m)throw new Error("model bootstrap is already running");m=!0;try{let M=await se(t.hubUrl,t.cliToken,t.projectId),{bootstrapDaemonModel:B}=await Promise.resolve().then(()=>(Lo(),fs)),D=await B(t.projectId,{root:o.root,contextDir:o.contextDir},M.repos,X=>r.info(`[model] ${X}`));return r.info(`[model] bootstrap done: ${D.repos} repos, ${D.events} task events`),le(),D}finally{m=!1}},Ue=null,Ne=async M=>{if(o?.contextDir)try{let B=await Promise.resolve().then(()=>(Lo(),fs)),D={root:o.root,contextDir:o.contextDir,repos:o.repos};if(B.shouldAutoBootstrapModel(o.contextDir)){await B.syncWorkspaceMirrors(D,G=>r.info(G));try{await Nt()}catch(G){r.warn(`[model] auto-bootstrap failed (non-fatal): ${G instanceof Error?G.message:String(G)}`)}return}(await B.rebuildWorkspaceModelIfStale(D,{fetch:M,onLog:G=>r.info(G)})).rebuilt.length>0&&le()}catch(B){r.warn(`[model] release-path rebuild failed (non-fatal): ${B instanceof Error?B.message:String(B)}`)}},Pe=M=>{Ue&&clearTimeout(Ue),Ue=setTimeout(()=>void Ne(M),6e4)},Be=setInterval(()=>void Ne(!0),6*36e5);return h.on("open",()=>{r.info("[ws] connected"),n({kind:"connected"});let M=fp(t.projectId),B=Q("ORIGIN")==="farm"?"farm":"local",D=Q("FARM_ID"),X=t.accountEmail??M.email,G;try{let C=Qf(t.projectId);C&&(G=C.publicKey,r.info(`[cred-channel] key fingerprint: ${C.fingerprint}`))}catch(C){r.warn(`[cred-channel] key setup failed (token replacement via dashboard unavailable): ${C instanceof Error?C.message:String(C)}`)}let E={type:"register",projectId:t.projectId,platformVersion:Xe,protocolVersion:ht,accountId:M.accountId,accountLabel:M.label,origin:B,inFlightActionIds:[...d],...X?{accountEmail:X}:{},...B==="farm"&&D?{farmId:D}:{},...G?{sealPublicKey:G}:{}};h.send(JSON.stringify(E))}),h.on("message",async M=>{let B=M.toString("utf-8");if(B==="pong"||B==="ping")return;let D;try{D=JSON.parse(B)}catch{return}if(!D||typeof D!="object")return;let X=D.type;if(X==="registered"){let E=D;if(E.ok){if(r.info(`[ws] registered for project ${E.projectId}`),n({kind:"registered",projectId:E.projectId??t.projectId}),v.start(),S?.start(),U?.start(),I(),Il(t,o,r),o?.contextDir){try{let C=Ci(o.contextDir,t.projectId);h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.outdated&&(r.warn(`[ctx] context format outdated: v${C.templateVersion} \u2192 v${C.currentVersion}`+(C.missingPaths.length>0?` (missing: ${C.missingPaths.join(", ")})`:"")),u||(u=!0,O().catch(()=>{})))}catch(C){r.warn(`[ctx] context-format detect failed (non-fatal): ${C instanceof Error?C.message:String(C)}`)}ee(),Pe(!0)}}else r.warn(`[ws] register rejected: ${E.reason??"unknown"}`),n({kind:"register_rejected",reason:E.reason??"unknown"}),l=!0,h.close();return}if(X==="hello"){let E=D;w=Jn(E.protocolVersion);let C=w?"compatible":"INCOMPATIBLE";r.info(`[ws] hub v${E.platformVersion} (protocol ${E.protocolVersion}) \u2014 ${C}`),w||(r.warn(`[ws] HUB protocol incompatible with this CLI (v${Xe}, protocol ${ht}) \u2014 WriteActions will be refused until versions align.`),r.warn(`[ws] update the CLI: ${Rl}`),n({kind:"incompatible",hubVersion:typeof E.platformVersion=="string"?E.platformVersion:null,hubProtocol:typeof E.protocolVersion=="number"?E.protocolVersion:null,updateCommand:Rl}));return}if(X==="tracking_targets"){v.setTargets(D.targets),S?.poke();return}if(X==="youtrack_sync_request"){R.setRequest(D);return}if(X==="youtrack_force_sync"){R.forceSync();return}if(X==="sync_local"){await aT(D,o,h,r);return}if(X==="provision_repo"){let E=D;r.info(`[repo] provision_repo: ${E.repo.name} (${E.repo.host}:${E.repo.owner}/${E.repo.repoName})`),await iT(t,o,E.repo,r),await Il(t,o,r);return}if(X==="remove_repo"){let E=D;r.info(`[repo] remove_repo: ${E.repoName}${E.purge?" (purge)":""}`),await Il(t,o,r),E.purge&&sT(t,o,E.repoName,r);return}if(X==="context_write"){await cT(D,o,h,r),i();return}if(X==="adr_promote"){await lT(D,o,h,r),i();return}if(X==="cred_update"){let E=D,C=Y(t.projectId),T=C?.sealKey?await em(t.projectId,E.kind,E.sealed,C.sealKey.privateKey):{ok:!1,detail:"no cred-channel key on this CLI (restart the daemon)"},P={type:"cred_update_result",updateId:E.updateId,projectId:t.projectId,ok:T.ok,...T.detail?{detail:T.detail}:{}};h.readyState===h.OPEN&&h.send(JSON.stringify(P)),T.ok?(r.info(`[cred] ${E.kind} replaced${T.detail?` \u2014 ${T.detail}`:""}`),b()):r.warn(`[cred] ${E.kind} replacement rejected: ${T.detail??"unknown"}`);return}if(X==="readiness_check"){r.info("[readiness] on-demand check requested"),b();return}if(X==="agent_login_start"){Zp(t,h,D,r,b);return}if(X==="move_to_farm"){let E=D;r.info(`[farm-move] request to move ${t.projectId} onto farm ${E.farmName} (${E.farmId})`);let C=await Lh(t,E,o?.contextDir,r);h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.ok?r.info(`[farm-move] done \u2014 farm daemon ${C.daemonStatus??"started"}; expecting takeover`):r.warn(`[farm-move] failed: ${C.error??"unknown error"}`);return}if(X==="gh_runner_setup"){let E=D;r.info(`[ghr] runner setup for ${t.projectId} on runner host ${E.runnerName} (${E.runnerId})`);let C=await Kh(t,E,r);h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.ok?r.info(`[ghr] runners connected on ${E.runnerName}`):r.warn(`[ghr] setup failed: ${C.error??"see per-repo statuses"}`);return}if(X==="gh_runner_teardown"){let E=D;r.info(`[ghr] runner teardown for ${t.projectId} on runner host ${E.runnerName} (${E.runnerId})`);let C=await Hh(t,E,r);h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.ok?r.info(`[ghr] runners disconnected from ${E.runnerName}`):r.warn(`[ghr] teardown failed: ${C.error??"unknown error"}`);return}if(X==="tracker_fields_request"){let E=D,C={type:"tracker_fields_result",requestId:E.requestId,projectId:t.projectId,ok:!1},T=Ct({contextDir:o?.contextDir??null});if(!T.ok)C.error=T.error;else try{C.fields=await T.provider.fetchStateFields(E.projectKey),C.ok=!0}catch(P){C.error=P instanceof Error?P.message:String(P)}h.readyState===h.OPEN&&h.send(JSON.stringify(C)),C.ok||r.warn(`[yt-fields] listing failed: ${C.error??"unknown"}`);return}if(X==="project_secret_update"||X==="project_secret_delete"){let E=D,C;if(E.type==="project_secret_update"){let P=Y(t.projectId);C=P?.sealKey?Vh(t.projectId,E.name,E.sealed,P.sealKey.privateKey):{ok:!1,detail:"no cred-channel key on this CLI (restart the daemon)"}}else C=Xh(t.projectId,E.name);let T={type:"project_secret_update_result",updateId:E.updateId,projectId:t.projectId,ok:C.ok,...C.detail?{detail:C.detail}:{}};h.readyState===h.OPEN&&h.send(JSON.stringify(T)),C.ok?(r.info(`[secret] ${E.name} ${E.type==="project_secret_update"?"saved":"deleted"}`+(C.detail?` \u2014 ${C.detail}`:"")),b()):r.warn(`[secret] ${E.name} rejected: ${C.detail??"unknown"}`);return}if(X==="sandbox_keys"){let E=Y(t.projectId);if(!E){r.warn(`[cred] sandbox_keys received but no secrets for ${t.projectId} \u2014 cannot seal`);return}let C=an(t.projectId),T=Vf(D,E,C,r);for(let P of T)h.readyState===h.OPEN&&h.send(JSON.stringify(P));return}if(X!=="dispatch_action")return;let G=D;if(w===!1){let E=`refused: HUB protocol incompatible with CLI v${Xe} (protocol ${ht})`;h.send(JSON.stringify({type:"action_result",actionId:G.actionId,status:"failed",error:E})),r.warn(`[exec] ${G.actionId} (${G.action.type}) \u2192 REFUSED: ${E}`),r.warn(`[exec] update the CLI to clear this: ${Rl}`),n({kind:"action",actionId:G.actionId,actionType:G.action.type,ok:!1,error:E});return}if(G.action.type==="model_drift"){d.add(G.actionId);try{let E,C=o?.repos.find(T=>T.name===G.action.repoName);if(!o?.contextDir||!C)E={status:"failed",error:"no local workspace/repo clone on this CLI"};else try{let{computeDriftReport:T}=await Promise.resolve().then(()=>(fg(),pg)),P=C.mountAs==="."?o.root:Or(o.root,C.mountAs);E={status:"done",result:{report:await T(P,o.contextDir,C.name)}}}catch(T){E={status:"failed",error:T instanceof Error?T.message:String(T)}}h.send(JSON.stringify({type:"action_result",actionId:G.actionId,...E}))}finally{d.delete(G.actionId)}return}if(G.action.type==="model_bootstrap"){d.add(G.actionId);try{let E;try{let C=await Nt();E={status:"done",result:{repos:C.repos,events:C.events}}}catch(C){E={status:"failed",error:C instanceof Error?C.message:String(C)},r.warn(`[model] bootstrap failed: ${E.error}`)}h.readyState===h.OPEN&&h.send(JSON.stringify({type:"action_result",actionId:G.actionId,...E}))}finally{d.delete(G.actionId)}return}d.add(G.actionId);try{let E=await kh({action:G.action,repo:G.repo,trackerIssueId:G.trackerIssueId,contextDir:o?.contextDir,requestConfigReport:U?()=>U.reportNow():void 0,refreshContextStatus:o?.contextDir?O:void 0,onRunActivity:y}).catch(P=>({status:"failed",error:P instanceof Error?P.message:String(P)}));G.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:G.actionId,...E}));let C=E.status!=="failed",T=!C&&"error"in E?E.error:void 0;C?r.info(`[exec] ${G.actionId} (${G.action.type}) \u2192 done`):r.warn(`[exec] ${G.actionId} (${G.action.type}) \u2192 FAILED: ${T??"?"}`),n({kind:"action",actionId:G.actionId,actionType:G.action.type,ok:C,...T?{error:T}:{}}),C&&["apply_delivery","context_write","create_pr"].includes(G.action.type)&&le(),C&&["merge_pr","merge_branch"].includes(G.action.type)&&Pe(!0)}finally{d.delete(G.actionId)}}),h.on("close",(M,B)=>{let D=B?.toString("utf-8")??"";if(r.info(`[ws] closed code=${M}${D?` reason=${D}`:""}`),v.stop(),S?.stop(),R.stop(),U?.stop(),N(),clearInterval(Be),Ue&&clearTimeout(Ue),K&&clearTimeout(K),D==="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:M}),!l&&setTimeout(()=>{g=k()},2e3)}),h.on("error",M=>r.warn(`[ws] error: ${M.message}`)),h}return{stop(){l=!0,g.close()}}}async function Il(t,e,r){try{let n=await se(t.hubUrl,t.cliToken,t.projectId),{updated:o,errors:i}=vo(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 iT(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?Or(e.root,o):_e(t.projectId,r.name);if(mg(Or(i,".git"))){n.info(`[repo] ${r.name} already present at ${i}`);return}try{await nT().clone(e?ji(r):Fc(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 sT(t,e,r,n){let o=e?.repos.find(s=>s.name===r)?.mountAs??r,i=e?Or(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(!mg(Or(i,".git"))){n.info(`[repo] no local clone to purge for ${r} (${i})`);return}try{rT(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 aT(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=Or(e.root,i?.mountAs??o.repoName),a=i?.defaultBranch??o.defaultBranch,c=await tf(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 cT(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 Re(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 lT(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 gf(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 Cl(t){let e=parseInt(process.env[t]??"60",10);return Number.isFinite(e)&&e>0?e*1e3:6e4}je();pe();Ft();Pl();wt();Oi();async function Tg(t={profile:void 0}){let{cfg:e,profile:r}=sn(t.profile),n=Y(e.projectId);n&&po(n),xo(n?.github?.token??process.env.GH_TOKEN)&&console.log("[git] github.com over token-HTTPS (insteadOf) \u2014 farm transport"),So(n?.gitlab?.token??process.env.GITLAB_TOKEN)&&console.log("[git] gitlab.com over token-HTTPS (insteadOf) \u2014 farm transport"),Eo(n?.bitbucket?.apiToken||process.env.BITBUCKET_API_TOKEN)&&console.log("[git] bitbucket.org over token-HTTPS (insteadOf) \u2014 farm transport");let o=Mo(_l(),".codepipe","logs"),i=r?`cli-daemon-${r}`:"cli-daemon",s=mi("CLI_LOG",i,o);if(s.enabled){let d=new ln(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=nn(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=Mo(_l(),".codepipe",r?Mo("profiles",r,"context"):"context");if(await ml(e.hubUrl,e.cliToken,e.projectId,{phase:"context_cloning"}).catch(()=>{}),a=await Sg(()=>gs({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 ml(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=Mo(_l(),".codepipe",r?Mo("profiles",r,"context-config"):"context-config");Si(a.contextDir,m,{info:f=>console.log(f),warn:f=>console.warn(f)})}}let l=ms(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(`
|
|
1017
1017
|
[${d}] shutting down`),l.stop(),setTimeout(()=>process.exit(0),200))}process.on("SIGINT",()=>p("SIGINT")),process.on("SIGTERM",()=>p("SIGTERM")),await new Promise(()=>{})}Ln();He();je();async function Mw(t={profile:void 0}){let e=st(t.profile);console.log(`connecting to ${e.hubUrl} (project=${e.projectId}) \u2026`);let r=rs(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`)")}Yo();import{readFileSync as EA}from"node:fs";F();He();Ft();Ho();Pr();Jt();Cr();je();pe();function xe(t){throw new Error(t)}function Ie(t,e){return(typeof t!="string"||t.trim().length===0)&&xe(`config: '${e}' must be a non-empty string`),t.trim()}function Xo(t,e){if(t==null)return;typeof t!="string"&&xe(`config: '${e}' must be a string`);let r=t.trim();return r.length>0?r:void 0}function TA(t){(!t||typeof t!="object")&&xe("config: expected a JSON object");let e=t,r=Ie(e.hubUrl,"hubUrl").replace(/\/$/,"");r.startsWith("http")||xe("config: 'hubUrl' must start with http(s)://");let n=Ie(e.cliToken,"cliToken"),o=e.project;(!o||typeof o!="object")&&xe("config: 'project' is required");let i=o,s=Ie(i.id,"project.id");Yt.test(s)||xe("config: 'project.id' must match /^[a-z][a-z0-9-]{1,30}$/");let a=Ie(i.name,"project.name"),c=Ie(i.automationLevel,"project.automationLevel");c!=="assisted"&&c!=="full"&&xe("config: 'project.automationLevel' must be 'assisted' or 'full'");let l=i.repos;Array.isArray(l)||xe("config: 'project.repos' must be an array");let u=l.map((w,v)=>{(!w||typeof w!="object")&&xe(`config: project.repos[${v}] must be an object`);let S=w,R=Ie(S.host,`project.repos[${v}].host`);R!=="github"&&R!=="bitbucket"&&R!=="gitlab"&&xe(`config: project.repos[${v}].host must be 'github', 'bitbucket' or 'gitlab'`);let $={name:Ie(S.name,`project.repos[${v}].name`),host:R,owner:Ie(S.owner,`project.repos[${v}].owner`),repoName:Ie(S.repoName,`project.repos[${v}].repoName`)},b=Xo(S.defaultBranch,`project.repos[${v}].defaultBranch`);b&&($.defaultBranch=b);let I=Xo(S.mountAs,`project.repos[${v}].mountAs`);return I&&($.mountAs=I),$}),p=i.contextRepo;(!p||typeof p!="object")&&xe("config: 'project.contextRepo' is required");let d=p,m=Xo(d.host,"project.contextRepo.host")??"github";m!=="github"&&m!=="bitbucket"&&m!=="gitlab"&&xe("config: 'project.contextRepo.host' must be 'github', 'bitbucket' or 'gitlab'");let f={host:m,owner:Ie(d.owner,"project.contextRepo.owner"),name:Xo(d.name,"project.contextRepo.name")??Et(s)},g={hubUrl:r,cliToken:n,project:{id:s,name:a,automationLevel:c,repos:u,contextRepo:f}},k=Xo(i.youtrackProjectKey,"project.youtrackProjectKey");if(k&&(g.project.youtrackProjectKey=k),i.index!==void 0&&(typeof i.index!="boolean"&&xe("config: 'project.index' must be a boolean"),g.project.index=i.index),i.youtrackWrites!==void 0&&(typeof i.youtrackWrites!="boolean"&&xe("config: 'project.youtrackWrites' must be a boolean"),g.project.youtrackWrites=i.youtrackWrites),i.llmProvider!==void 0){let w=Ie(i.llmProvider,"project.llmProvider");w==="codex"&&xe(`config: 'project.llmProvider' "codex" is not yet supported (coming soon); use "claude".`),w!=="claude"&&xe("config: 'project.llmProvider' must be 'claude'"),g.project.llmProvider=w}let h=e.secrets;if(h!==void 0){(typeof h!="object"||h===null)&&xe("config: 'secrets' must be an object");let w=h,v={};if(w.github){let S=w.github;v.github={token:Ie(S.token,"secrets.github.token")}}if(w.bitbucket){let S=w.bitbucket;v.bitbucket={email:Ie(S.email,"secrets.bitbucket.email"),apiToken:Ie(S.apiToken,"secrets.bitbucket.apiToken")}}if(w.gitlab){let S=w.gitlab;v.gitlab={token:Ie(S.token,"secrets.gitlab.token")}}if(w.youtrack){let S=w.youtrack;v.youtrack={url:Ie(S.url,"secrets.youtrack.url").replace(/\/$/,""),token:Ie(S.token,"secrets.youtrack.token")}}if(w.contextWrite){let S=w.contextWrite;v.contextWrite={token:Ie(S.token,"secrets.contextWrite.token")}}g.secrets=v}return g}async function RA(){let t=[];for await(let e of process.stdin)t.push(e);return Buffer.concat(t).toString("utf-8")}async function IA(t){let e=t.secrets;if(e){if(e.github){let r=t.project.contextRepo,n=await zt(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 Vt(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 Xt(e.gitlab.token);console.log(` GitLab OK \u2014 ${r}`)}if(e.youtrack){let r=await Qt({baseUrl:e.youtrack.url,token:e.youtrack.token});console.log(` YouTrack OK \u2014 ${r}`)}}}async function Gk(t){let e=!t.configPath||t.configPath==="-"?await RA():EA(t.configPath,"utf-8"),r;try{r=JSON.parse(e)}catch(d){xe(`config: invalid JSON \u2014 ${d instanceof Error?d.message:String(d)}`)}let n=TA(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 IA(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 Mn(a,s.contextRepo,{githubToken:c,gitlabToken:n.secrets?.gitlab?.token??process.env.GITLAB_TOKEN,bitbucket:n.secrets?.bitbucket??cn(),youtrackWrites:s.youtrackWrites??!0,trackerUrl:n.secrets?.youtrack?.url,log:{info:d=>console.log(` ${d}`),warn:d=>console.warn(` ${d}`)}})}catch(d){xe(`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 ir(o,i,a)}catch(d){if(d instanceof W&&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 W)xe(`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),Ut({hubUrl:o,cliToken:i,projectId:s.id},s.id),console.log(`config + secrets written (profile ${s.id}) \u2192 ${Tt(s.id)}`),tr(s.id,It(a,s.youtrackWrites??!0,n.secrets?.youtrack?.url,void 0,s.llmProvider??Je),{info:d=>console.log(d),warn:d=>console.warn(d)}),s.index)try{let{jobId:d}=await Oo(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`)}He();pe();import{cancel as Kk,intro as Hk,isCancel as Wk,log as pu,outro as CA,password as qk}from"@clack/prompts";async function AA(){let t=[];for await(let e of process.stdin)t.push(e);return Buffer.concat(t).toString("utf-8").trim()}async function Yk(t){let e=t.token?.trim()??"";if(!e&&t.stdin&&(e=await AA(),e||(console.error("login: no token on stdin"),process.exit(1))),t.shared){if(!e){Hk("codepipe login --shared \u2014 set the farm/machine-wide Claude OAuth token"),pu.message("Run `claude setup-token` and paste the token below (input hidden).");let i=await qk({message:"Claude OAuth token"});Wk(i)&&(Kk("aborted"),process.exit(1)),e=i.trim()}e||(console.error("login: no token provided"),process.exit(1)),ap({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){Hk(`codepipe login \u2014 set the Claude OAuth token for project ${r.projectId}`),pu.message("Run `claude setup-token` and paste the token below (input hidden).");let i=await qk({message:"Claude OAuth token"});Wk(i)&&(Kk("aborted"),process.exit(1)),e=i.trim()}e||(console.error("login: no token provided"),process.exit(1));let o=Y(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}.`):(pu.success("Claude OAuth token saved."),CA("It will be sealed into job bundles when a SANDBOX (re)connects."))}Lo();F();He();Ft();Ho();Pr();js();je();pe();import{cancel as PA,confirm as _A,intro as jA,isCancel as zk,log as Me,outro as NA,select as Vk,text as hr}from"@clack/prompts";function Xk(t){PA(t),process.exit(1)}function Gn(t){return zk(t)&&Xk("aborted"),t}function Jo(t){return zk(t)&&Xk("aborted"),typeof t=="string"?t:""}async function OA(t,e){let r=Gn(await Vk({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=Jo(await hr({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=Jo(await hr({message:"Context Repo name",placeholder:Et(t),initialValue:Et(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);jA(`codepipe project add \u2192 ${e.hubUrl}`);let r=Gn(await hr({message:"project_id (lowercase letters, digits, dashes; starts with a letter)",placeholder:"cp",validate:d=>Yt.test(d.trim())?void 0:"must match /^[a-z][a-z0-9-]{1,30}$/"})).trim(),n=Gn(await hr({message:"project name (human-readable)",placeholder:"CodePartner",validate:d=>d.trim().length>0?void 0:"required"})).trim(),o=Gn(await Vk({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=Gn(await hr({message:"YouTrack project key (optional)",placeholder:"DEV"})).trim(),s=Gn(await _A({message:"Allow CodePipe to write to YouTrack? (status changes, PR comments, dashboard mirror)",initialValue:!0})),a=[];for(;;){let d=Jo(await hr({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()||ze(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=ze(d);Me.message(`${m.host}: ${m.owner}/${m.repoName}`);let f=Jo(await hr({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=Jo(await hr({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 OA(r,a),u=Y(e.projectId);Me.info(`provisioning Context Repo ${l.owner}/${l.name} (${l.host})\u2026`);let p;try{p=await Mn(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??cn(),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 ir(e.hubUrl,e.cliToken,c);Me.success(`project "${d.projectId}" \u2014 ${d.provisioningStatus}`),tr(r,It(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}`),NA("done")}catch(d){d instanceof W?(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)}}Ln();He();je();pe();wt();Yo();import{existsSync as LA,rmSync as MA}from"node:fs";import{confirm as DA,intro as UA,isCancel as BA,log as gr,outro as FA,spinner as GA}from"@clack/prompts";function jt(t){gr.error(t),process.exit(1)}var Zk=t=>t.trim().replace(/\/+$/,"");async function Qk(t){UA("codepipe project move \u2014 repoint a project at another HUB");let e=t.fromProfile??t.cliProfile??Ae()?.spec.projectId??void 0;e||jt("no source project \u2014 pass --from-profile <id> (or run inside a project's workspace folder).");let r=kt(e);r||jt(`source profile '${e}' is not initialised on this machine (~/.codepipe/profiles/${e}/config.json is missing).`);let n=Zk(r.hubUrl),o=r.projectId,i=Zk(t.hub);i.startsWith("http")||jt("--hub must be an http(s):// URL");let s=t.toProfile??e,a=t.project??o,c=s===e;c&&a===o&&i===n&&jt(`profile '${e}' is already on ${n} \u2014 nothing to move.`);let l;{let h=GA();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 W&&jt(`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||jt(`project ${o} has no Context Repo recorded on the source HUB \u2014 cannot re-register it elsewhere.`);let u=Y(o),p=(t.account??r.accountEmail??await Bn()).trim().toLowerCase();if(gr.message(`move project '${o}'
|
|
1018
1018
|
from : ${n} (profile ${e})
|
|
1019
1019
|
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.14.1-dev.
|
|
3
|
+
"version": "0.14.1-dev.285.g30f288c9",
|
|
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",
|