infra-kit 0.1.121 → 0.1.123
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/.omc/state/agent-replay-6be1264f-8069-4412-8119-86118ed1943e.jsonl +3 -0
- package/.omc/state/sessions/6be1264f-8069-4412-8119-86118ed1943e/last-tool-error-state.json +7 -0
- package/.omc/state/sessions/6be1264f-8069-4412-8119-86118ed1943e/mission-state.json +53 -0
- package/.omc/state/sessions/6be1264f-8069-4412-8119-86118ed1943e/pre-tool-advisory-throttle.json +22 -0
- package/.omc/state/sessions/6be1264f-8069-4412-8119-86118ed1943e/skill-active-state.json +15 -0
- package/.omc/state/sessions/6be1264f-8069-4412-8119-86118ed1943e/subagent-tracking-state.json +17 -0
- package/.turbo/turbo-test.log +53 -53
- package/dist/boot-SGM5RVLJ.js +2 -0
- package/dist/boot-SGM5RVLJ.js.map +7 -0
- package/dist/{chunk-PWOX6B3T.js → chunk-YMXDO43V.js} +2 -2
- package/dist/chunk-YMXDO43V.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/mcp.js +1 -1
- package/package.json +2 -2
- package/src/commands/.omc/state/sessions/f09f401f-56c6-42cd-97be-c742c1956468/pre-tool-advisory-throttle.json +14 -0
- package/src/lib/vendor/.omc/state/sessions/f09f401f-56c6-42cd-97be-c742c1956468/pre-tool-advisory-throttle.json +10 -0
- package/src/tui/__tests__/boot.test.tsx +61 -0
- package/src/tui/boot.tsx +15 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/.eslintcache +0 -1
- package/dist/boot-K4QUAFSP.js +0 -2
- package/dist/boot-K4QUAFSP.js.map +0 -7
- package/dist/chunk-PWOX6B3T.js.map +0 -7
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{A as de,B as me,C as le,D as pe,E as fe,F as ue,G as ge,H as ve,I as ye,J as he,K as we,L as ke,M as Ce,N as Ae,O as xe,P as _,Q as Ee,R as Se,S as Re,T as Le,U as be,W as j,a as U,d as a,e as B,f as T,g as z,h as Y,i as h,j as u,k as D,l as q,m as Q,n as I,o as X,p as Z,q as ee,r as oe,s as te,t as re,u as ne,v as ie,w as C,x as ae,y as se,z as ce}from"./chunk-
|
|
1
|
+
import{A as de,B as me,C as le,D as pe,E as fe,F as ue,G as ge,H as ve,I as ye,J as he,K as we,L as ke,M as Ce,N as Ae,O as xe,P as _,Q as Ee,R as Se,S as Re,T as Le,U as be,W as j,a as U,d as a,e as B,f as T,g as z,h as Y,i as h,j as u,k as D,l as q,m as Q,n as I,o as X,p as Z,q as ee,r as oe,s as te,t as re,u as ne,v as ie,w as C,x as ae,y as se,z as ce}from"./chunk-YMXDO43V.js";import{e as $}from"./chunk-WA4BQRDC.js";import vo,{Separator as x}from"@inquirer/select";import{Command as yo}from"commander";import w from"node:process";import N from"node:fs/promises";import Xe from"node:path";import je from"node:process";import{$ as Ze}from"zx";var O=async()=>{let e=await T(),o=await Promise.all([{label:"project (committed)",path:e.main},{label:"user global",path:e.userGlobal},{label:"user project",path:e.userProject}].map(async r=>({...r,exists:await h(r.path)})));a.info(`Project name: ${e.projectName}
|
|
2
2
|
`),a.info(`Config merge chain (later overrides earlier):
|
|
3
3
|
`);for(let r of o){let c=r.exists?" [\u2713]":" [ ]";a.info(`${c} ${r.label.padEnd(22)} ${u(r.path)}`)}let t={projectName:e.projectName,layers:o.map(r=>({label:r.label,path:r.path,exists:r.exists}))};return{content:[{type:"text",text:JSON.stringify(t,null,2)}],structuredContent:t}},M=async()=>{let e=await T(),o=je.env.EDITOR||je.env.VISUAL||"vi";if(await N.mkdir(Xe.dirname(e.userProject),{recursive:!0}),!await h(e.userProject)){let r=eo(e.userProject);await N.writeFile(e.userProject,`{}
|
|
4
4
|
`,"utf-8"),await N.writeFile(r,oo(e.projectName),"utf-8"),a.info(`Created ${u(e.userProject)} \u2014 see ${u(r)} for the annotated reference.`)}a.info(`Opening ${u(e.userProject)} in ${o}`),await Ze({stdio:"inherit"})`${o} ${e.userProject}`,Y();let t={path:e.userProject,editor:o};return{content:[{type:"text",text:JSON.stringify(t,null,2)}],structuredContent:t}},eo=e=>e.replace(/\.json$/,".example.jsonc"),oo=e=>`// infra-kit user override for ${e} \u2014 ~/.infra-kit/projects/${e}/infra-kit.json
|
|
@@ -16,5 +16,5 @@ import{A as de,B as me,C as le,D as pe,E as fe,F as ue,G as ge,H as ve,I as ye,J
|
|
|
16
16
|
}
|
|
17
17
|
`;import f from"node:fs";import A from"node:path";import E from"node:process";var to="autoload-warn.flag",F="autoload-fail.flag",ro=3e4,Pe=async(e=!0)=>{let o;try{o=await z()}catch{return null}let t=o.envAutoLoad;return t?o.environments.includes(t.config)?{trigger:t.trigger,config:t.config,project:o.envManagement.config.name}:(e&&De(`infra-kit: envAutoLoad.config "${t.config}" is not one of environments [${o.environments.join(", ")}] \u2014 env auto-load disabled.`),null):null},Te=e=>{let{trigger:o,expectedTrigger:t,targetConfig:r,targetProject:c,env:s}=e;return o!==t||!s.session||s.cleared||s.currentConfig&&!s.autoLoadedMarker||s.autoLoadedMarker&&s.currentConfig===r&&s.currentProject===c?"skip":"load"},S=async({expectedTrigger:e})=>{let o=e==="cli-invocation";try{let t=await Pe(o);if(!t||Te({trigger:t.trigger,expectedTrigger:e,targetConfig:t.config,targetProject:t.project,env:no()})==="skip"||io()||ao())return null;let c=await ae({config:t.config,autoLoaded:!0});return co(),c.filePath}catch(t){let r=t.message;return so(),o?De(`infra-kit: env auto-load failed \u2014 ${r} (will retry later)`):a.debug(`env auto-load skipped: ${r}`),null}},no=()=>({session:E.env[oe],cleared:E.env[ie],currentConfig:E.env[te],currentProject:E.env[re],autoLoadedMarker:E.env[ne]}),io=()=>{try{let e=C(),o=A.join(e,ee);if(!f.existsSync(o))return!1;let t=A.join(e,Z);return f.existsSync(t)?f.statSync(o).mtimeMs>=f.statSync(t).mtimeMs:!0}catch{return!1}},ao=()=>{try{let e=A.join(C(),F);return f.existsSync(e)?Date.now()-f.statSync(e).mtimeMs<ro:!1}catch{return!1}},so=()=>{try{let e=C();f.mkdirSync(e,{recursive:!0,mode:448}),f.writeFileSync(A.join(e,F),"",{mode:384})}catch{}},co=()=>{try{f.rmSync(A.join(C(),F),{force:!0})}catch{}},De=e=>{try{let o=C(),t=A.join(o,to);if(f.existsSync(t))return;f.mkdirSync(o,{recursive:!0,mode:448}),f.writeFileSync(t,"",{mode:384})}catch{}a.warn(e)};var V=async()=>{await S({expectedTrigger:"shell-startup"})};import G from"node:fs/promises";import J from"node:path";import Ie from"node:process";import{pathToFileURL as mo}from"node:url";var $e="~/projects",W=async(e={})=>{if(e.init){await po(e.cwd);return}await lo()},lo=async()=>{let e=D(),o=await h(e);if(a.info(`Factory config: ${u(e)} ${o?"[\u2713]":"[ ]"}`),!o){a.info("\nNot found \u2014 run `infra-kit vendor-config --init` to scaffold it."),Ie.exitCode=1;return}let{workspaceDir:t,targets:r}=await Q(),c=q(t),s=await h(c);a.info(`workspaceDir: ${t} (resolved: ${c}) ${s?"[\u2713 exists]":"[ ] not found"}`),a.info("Targets:");let l=s;for(let d of r){let g=J.join(c,d),p=await h(g);p||(l=!1);let v=p?"[\u2713]":"[ ]",y=p?"":" (not found \u2014 clone or remove)";a.info(` ${v} ${d} ${u(g)}${y}`)}l||(Ie.exitCode=1)},po=async e=>{let o=D();if(await h(o)){a.info(`Factory config already exists at ${u(o)} \u2014 leaving it untouched.`);return}let t=e??await U(),r=await fo(t);await G.mkdir(J.dirname(o),{recursive:!0}),await G.writeFile(o,uo(r),"utf-8"),a.info(`\u2713 Created ${u(o)}`),r.length>0&&a.info(` Seeded ${r.length} target(s) from the source ${$}.`),a.info(` Edit \`workspaceDir\` (placeholder: ${$e}) to point at where your repos live.`),r.length===0&&a.info(" Add at least one repo name to `targets` before running vendor sync/manifest/diff.")},fo=async e=>{try{let o=J.join(e,$),t=await G.stat(o),s=(await import(`${mo(o).href}?mtime=${Number(t.mtimeMs)}`)).default,l=typeof s=="function"?await s():s;if(l&&typeof l=="object"&&"targets"in l){let d=l.targets;if(Array.isArray(d)&&d.every(g=>typeof g=="string"))return d}}catch{}return[]},uo=e=>`${JSON.stringify({workspaceDir:$e,targets:e},null,2)}
|
|
18
18
|
`;import go from"node:process";var R={enabled:!1},i=(e,o=t=>{go.stdout.write(t)})=>(R.enabled&&e&&e.structuredContent!=null&&o(`${JSON.stringify(e.structuredContent,null,2)}
|
|
19
|
-
`),e),P=e=>{e.options.some(t=>t.long==="--json")||e.option("--json","Output the structured result as JSON on stdout (human logs stay on stderr)"),e.commands.forEach(P)};var K=(e,o=" ")=>{let t=e.reduce((r,[c])=>Math.max(r,c.length),0);return e.map(([r,c])=>`${r.padEnd(t)}${o}${c}`)};var n=new yo,ho=(e,o)=>[...o,e],H=e=>typeof e=="string"?e.split(",").filter(Boolean):void 0,_e=(e,o)=>{if(!(typeof e>"u")){if(e===!0)return"workspace";if(e===!1)return"none";if(typeof e=="string"&&_.includes(e))return e;throw new Error(`Invalid ${o} value "${String(e)}". Expected one of: ${_.join(", ")}.`)}},Ne=async e=>{try{e?await n.parseAsync(e):await n.parseAsync()}catch(o){let t=o instanceof Error?o.message:String(o);a.error(t),w.exit(1)}},Oe={value:!1},m=(e,o)=>e.hook("preAction",()=>{Oe.value||a.warn(`"${e.name()}" is a deprecated alias; use "${o}" instead.`)}),Me=e=>e.description("Merge dev branch into every release branch").option("-a, --all","Select all active release branches").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await le({all:o.all,confirmedCommand:o.yes}))}),Fe=e=>e.description("List all release branches").action(async()=>{i(await ge())}),Ve=e=>e.description("Create one or more release branches (each entry can mix regular/hotfix and its own description)").option("-r, --release <spec>",'Release spec "<version|next|name>[:type[:description]]" (repeatable). The token is a semver ("1.2.5"), the literal "next", or a kebab-case name ("checkout-redesign"). Type is regular|hotfix (default regular). Examples: "1.2.5", "1.2.5:hotfix", "next:regular:Holiday backend", "checkout-redesign:regular:Q3 redesign".',ho,[]).option("-y, --yes","Skip confirmation prompt").action(async o=>{let r=o.release.map(ve),c=r.length>0?r:void 0;i(await ye({releases:c,confirmedCommand:o.yes}))}),Ge=e=>e.description("Edit a release's description in Jira and in the matching GitHub PR body").option("-v, --version <version>","Release version (e.g. 1.2.5) or release name (e.g. checkout-redesign)").option("-d, --description <description>",'New description (use "" to clear)').option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await he({version:o.version,description:o.description,confirmedCommand:o.yes}))}),Je=e=>e.description("Deploy any release branch to any environment").option("-v, --version <version>",'Version (e.g. 1.2.5) or release name (e.g. checkout-redesign) to deploy; "dev" deploys from the dev branch').option("-e, --env <env>","Specify the environment to deploy to, e.g. dev").option("--skip-terraform","Skip terraform deployment step").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await fe({version:o.version,env:o.env,skipTerraform:o.skipTerraform,confirmedCommand:o.yes}))}),We=e=>e.description("Deploy selected services from release branch to any environment").option("-v, --version <version>",'Version (e.g. 1.2.5) or release name (e.g. checkout-redesign) to deploy; "dev" deploys from the dev branch').option("-e, --env <env>","Specify the environment to deploy to, e.g. dev").option("-s, --services <services...>","Specify services to deploy, e.g. client-be client-fe").option("--skip-terraform","Skip terraform deployment step").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await ue({version:o.version,env:o.env,services:o.services,skipTerraform:o.skipTerraform,confirmedCommand:o.yes}))}),Ke=e=>e.description("Release a new version to production").option("-v, --version <version>","Version (e.g. 1.2.5) or release name (e.g. checkout-redesign) to deliver").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await pe({version:o.version,confirmedCommand:o.yes}))}),He=e=>e.description("Remove release worktrees whose PRs are no longer open").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await be({confirmedCommand:o.yes}))}),Ue=e=>e.description("Add git worktrees for release branches").option("-y, --yes","Skip confirmation prompt").option("-a, --all","Select all active release branches").option("-v, --versions <versions>","Specify versions by comma, e.g. 1.2.5, 1.2.6").option("-i, --ide [mode]","Editor mode for created worktrees: workspace (default) | none").option("--no-ide","Skip the editor (alias for --ide none)").option("-c, --cursor [mode]","Deprecated alias for --ide").option("--no-cursor","Deprecated alias for --no-ide").option("-g, --github-desktop","Open created worktrees in GitHub Desktop").option("--no-github-desktop","Skip GitHub Desktop prompt").option("-m, --cmux","Open created worktrees in cmux (3-pane layout)").option("--no-cmux","Skip cmux prompt").action(async o=>{let t=_e(o.ide,"--ide")??_e(o.cursor,"--cursor");i(await Ee({confirmedCommand:o.yes,all:o.all,versions:o.versions,ide:t,githubDesktop:o.githubDesktop,cmux:o.cmux}))}),Be=e=>e.description("List all git worktrees with detailed information").action(async()=>{i(await Se())}),ze=e=>e.description("Remove git worktrees for release branches").option("-y, --yes","Skip confirmation prompt").option("-a, --all","Select all active release branches").option("-v, --versions <versions>","Specify versions by comma, e.g. 1.2.5, 1.2.6").action(async o=>{i(await Le({confirmedCommand:o.yes,all:o.all,versions:o.versions}))}),Ye=e=>e.description("Close all cmux/editor worktree windows, then reopen the current release worktrees (also cold-start restore)").action(async()=>{i(await Re())}),qe=e=>e.description("Show the machine-local factory config (~/.infra-kit/vendor.json) or scaffold it with --init").option("--init","Scaffold ~/.infra-kit/vendor.json (skips if it already exists)").action(async o=>{i(await W({init:o.init}))}),k=n.command("release").description("Release management commands");Me(k.command("merge-dev"));Fe(k.command("list"));Ve(k.command("create"));Ge(k.command("desc-edit"));Je(k.command("deploy-all"));We(k.command("deploy-selected"));Ke(k.command("deliver"));var L=n.command("worktrees").description("Git worktree management commands");Ue(L.command("add"));Be(L.command("list"));ze(L.command("remove"));He(L.command("sync"));Ye(L.command("reload"));m(Me(n.command("merge-dev")),"release merge-dev");m(Fe(n.command("release-list")),"release list");m(Ve(n.command("release-create")),"release create");m(Ge(n.command("release-desc-edit")),"release desc-edit");m(Je(n.command("release-deploy-all")),"release deploy-all");m(We(n.command("release-deploy-selected")),"release deploy-selected");m(Ke(n.command("release-deliver")),"release deliver");m(Ue(n.command("worktrees-add")),"worktrees add");m(Be(n.command("worktrees-list")),"worktrees list");m(ze(n.command("worktrees-remove")),"worktrees remove");m(He(n.command("worktrees-sync")),"worktrees sync");m(Ye(n.command("worktrees-reload")),"worktrees reload");var Qe=n.command("config").description("Manage infra-kit configuration files");Qe.command("path").description("Show the resolved config merge chain and file paths").action(async()=>{i(await O())});Qe.command("edit").description("Open the user-scope per-project override file in $EDITOR").action(async()=>{i(await M())});n.command("audit").description("Audit against infra-kit.config.ts rules (--all for every package, --root for the monorepo root)").option("-a, --all","Audit every non-vendor workspace package").option("-r, --root","Audit the monorepo root (turbo pipeline + root commands)").action(async e=>{let o=await B({all:e.all,root:e.root});i(o),o.structuredContent.allPassed||(w.exitCode=1)});var b=n.command("vendor").description("Verify and sync the mirrored vendor/ tree");b.command("check").description("Verify vendor/ matches vendor/.sync-manifest.json (self-contained; for any consumer repo)").action(async()=>{let e=await we();i(e),e.structuredContent.ok||(w.exitCode=1)});b.command("sync").description("Copy vendored files from the source repo into each target and regenerate manifests").option("-y, --yes","Skip confirmation prompt").option("-r, --repos <repos>","Restrict to comma-separated target repo names").action(async e=>{i(await Ae({confirmedCommand:e.yes,repos:H(e.repos)}))});b.command("manifest").description("Regenerate each target vendor/.sync-manifest.json + README from current content (no copy)").option("-r, --repos <repos>","Restrict to comma-separated target repo names").action(async e=>{i(await Ce({confirmedCommand:!0,repos:H(e.repos)}))});b.command("diff").description("Source-aware drift check (rsync dry-run) of each target vendored subtree vs the source").option("-r, --repos <repos>","Restrict to comma-separated target repo names").action(async e=>{let o=await ke({repos:H(e.repos)});i(o),o.structuredContent.ok||(w.exitCode=1)});qe(b.command("config"));m(qe(n.command("vendor-config")),"vendor config");n.command("doctor").description("Check installation and authentication status of gh and doppler CLIs").action(async()=>{i(await X())});n.command("version").description("Print the installed infra-kit CLI version").action(async()=>{i(await xe())});n.command("env-status").description("Show which env is loaded in this session (local introspection; no Doppler call)").action(async()=>{i(await me())});n.command("env-list").description("List available Doppler configs for the detected project").action(async()=>{i(await de())});n.command("init").description("Inject shell integration into .zshrc and sync repo agent-instruction files").action(async()=>{i(await I())});n.command("env-load").description("Load Doppler env vars for a config. Source the returned file path to apply.").option("-c, --config <config>","Environment config name to load (e.g. dev, arthur)").action(async e=>{i(await se({config:e.config}))});n.command("env-clear").description("Clear loaded env vars. Source the returned file path to apply.").action(async()=>{i(await ce())});n.command("env-autoload",{hidden:!0}).description("Internal: prime env for the shell-startup auto-load trigger").action(async()=>{await V()});n.commands.forEach(P);var wo=e=>e.startsWith("env-")||e==="init"||e==="doctor"||e==="version";n.hook("preAction",async(e,o)=>{R.enabled=!!o.optsWithGlobals().json,R.enabled&&(a.level="warn"),wo(o.name())||await S({expectedTrigger:"cli-invocation"})});if(w.argv.length<=2){let e=j("release"),o=j("worktrees"),t=j("environment"),r=new Map(n.commands.map(d=>[d.name(),d])),s=[{label:"Release Management",names:e},{label:"Worktrees",names:o},{label:"Environment",names:t}].flatMap(({label:d,names:g})=>g.filter(p=>r.has(p)).map(p=>({name:p,description:r.get(p).description(),group:d}))),l;if(w.stdout.isTTY&&w.stdin.isTTY){let{runCommandPalette:d}=await import("./boot-K4QUAFSP.js");l=await d(s)}else{let d=K(s.map(v=>[v.name,v.description])),g=new Map;s.forEach((v,y)=>{g.set(v.name,d[y]??v.name)});let p=v=>v.filter(y=>r.has(y)).map(y=>({name:g.get(y)??y,value:y}));l=await vo({message:"Select a command to run",choices:[new x(" "),new x("\u2014 Release Management \u2014"),...p(e),new x(" "),new x("\u2014 Worktrees \u2014"),...p(o),new x(" "),new x("\u2014 Environment \u2014"),...p(t)]},{output:w.stderr})}l&&(Oe.value=!0,await Ne(["node","infra-kit",l]))}else await Ne();
|
|
19
|
+
`),e),P=e=>{e.options.some(t=>t.long==="--json")||e.option("--json","Output the structured result as JSON on stdout (human logs stay on stderr)"),e.commands.forEach(P)};var K=(e,o=" ")=>{let t=e.reduce((r,[c])=>Math.max(r,c.length),0);return e.map(([r,c])=>`${r.padEnd(t)}${o}${c}`)};var n=new yo,ho=(e,o)=>[...o,e],H=e=>typeof e=="string"?e.split(",").filter(Boolean):void 0,_e=(e,o)=>{if(!(typeof e>"u")){if(e===!0)return"workspace";if(e===!1)return"none";if(typeof e=="string"&&_.includes(e))return e;throw new Error(`Invalid ${o} value "${String(e)}". Expected one of: ${_.join(", ")}.`)}},Ne=async e=>{try{e?await n.parseAsync(e):await n.parseAsync()}catch(o){let t=o instanceof Error?o.message:String(o);a.error(t),w.exit(1)}},Oe={value:!1},m=(e,o)=>e.hook("preAction",()=>{Oe.value||a.warn(`"${e.name()}" is a deprecated alias; use "${o}" instead.`)}),Me=e=>e.description("Merge dev branch into every release branch").option("-a, --all","Select all active release branches").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await le({all:o.all,confirmedCommand:o.yes}))}),Fe=e=>e.description("List all release branches").action(async()=>{i(await ge())}),Ve=e=>e.description("Create one or more release branches (each entry can mix regular/hotfix and its own description)").option("-r, --release <spec>",'Release spec "<version|next|name>[:type[:description]]" (repeatable). The token is a semver ("1.2.5"), the literal "next", or a kebab-case name ("checkout-redesign"). Type is regular|hotfix (default regular). Examples: "1.2.5", "1.2.5:hotfix", "next:regular:Holiday backend", "checkout-redesign:regular:Q3 redesign".',ho,[]).option("-y, --yes","Skip confirmation prompt").action(async o=>{let r=o.release.map(ve),c=r.length>0?r:void 0;i(await ye({releases:c,confirmedCommand:o.yes}))}),Ge=e=>e.description("Edit a release's description in Jira and in the matching GitHub PR body").option("-v, --version <version>","Release version (e.g. 1.2.5) or release name (e.g. checkout-redesign)").option("-d, --description <description>",'New description (use "" to clear)').option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await he({version:o.version,description:o.description,confirmedCommand:o.yes}))}),Je=e=>e.description("Deploy any release branch to any environment").option("-v, --version <version>",'Version (e.g. 1.2.5) or release name (e.g. checkout-redesign) to deploy; "dev" deploys from the dev branch').option("-e, --env <env>","Specify the environment to deploy to, e.g. dev").option("--skip-terraform","Skip terraform deployment step").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await fe({version:o.version,env:o.env,skipTerraform:o.skipTerraform,confirmedCommand:o.yes}))}),We=e=>e.description("Deploy selected services from release branch to any environment").option("-v, --version <version>",'Version (e.g. 1.2.5) or release name (e.g. checkout-redesign) to deploy; "dev" deploys from the dev branch').option("-e, --env <env>","Specify the environment to deploy to, e.g. dev").option("-s, --services <services...>","Specify services to deploy, e.g. client-be client-fe").option("--skip-terraform","Skip terraform deployment step").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await ue({version:o.version,env:o.env,services:o.services,skipTerraform:o.skipTerraform,confirmedCommand:o.yes}))}),Ke=e=>e.description("Release a new version to production").option("-v, --version <version>","Version (e.g. 1.2.5) or release name (e.g. checkout-redesign) to deliver").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await pe({version:o.version,confirmedCommand:o.yes}))}),He=e=>e.description("Remove release worktrees whose PRs are no longer open").option("-y, --yes","Skip confirmation prompt").action(async o=>{i(await be({confirmedCommand:o.yes}))}),Ue=e=>e.description("Add git worktrees for release branches").option("-y, --yes","Skip confirmation prompt").option("-a, --all","Select all active release branches").option("-v, --versions <versions>","Specify versions by comma, e.g. 1.2.5, 1.2.6").option("-i, --ide [mode]","Editor mode for created worktrees: workspace (default) | none").option("--no-ide","Skip the editor (alias for --ide none)").option("-c, --cursor [mode]","Deprecated alias for --ide").option("--no-cursor","Deprecated alias for --no-ide").option("-g, --github-desktop","Open created worktrees in GitHub Desktop").option("--no-github-desktop","Skip GitHub Desktop prompt").option("-m, --cmux","Open created worktrees in cmux (3-pane layout)").option("--no-cmux","Skip cmux prompt").action(async o=>{let t=_e(o.ide,"--ide")??_e(o.cursor,"--cursor");i(await Ee({confirmedCommand:o.yes,all:o.all,versions:o.versions,ide:t,githubDesktop:o.githubDesktop,cmux:o.cmux}))}),Be=e=>e.description("List all git worktrees with detailed information").action(async()=>{i(await Se())}),ze=e=>e.description("Remove git worktrees for release branches").option("-y, --yes","Skip confirmation prompt").option("-a, --all","Select all active release branches").option("-v, --versions <versions>","Specify versions by comma, e.g. 1.2.5, 1.2.6").action(async o=>{i(await Le({confirmedCommand:o.yes,all:o.all,versions:o.versions}))}),Ye=e=>e.description("Close all cmux/editor worktree windows, then reopen the current release worktrees (also cold-start restore)").action(async()=>{i(await Re())}),qe=e=>e.description("Show the machine-local factory config (~/.infra-kit/vendor.json) or scaffold it with --init").option("--init","Scaffold ~/.infra-kit/vendor.json (skips if it already exists)").action(async o=>{i(await W({init:o.init}))}),k=n.command("release").description("Release management commands");Me(k.command("merge-dev"));Fe(k.command("list"));Ve(k.command("create"));Ge(k.command("desc-edit"));Je(k.command("deploy-all"));We(k.command("deploy-selected"));Ke(k.command("deliver"));var L=n.command("worktrees").description("Git worktree management commands");Ue(L.command("add"));Be(L.command("list"));ze(L.command("remove"));He(L.command("sync"));Ye(L.command("reload"));m(Me(n.command("merge-dev")),"release merge-dev");m(Fe(n.command("release-list")),"release list");m(Ve(n.command("release-create")),"release create");m(Ge(n.command("release-desc-edit")),"release desc-edit");m(Je(n.command("release-deploy-all")),"release deploy-all");m(We(n.command("release-deploy-selected")),"release deploy-selected");m(Ke(n.command("release-deliver")),"release deliver");m(Ue(n.command("worktrees-add")),"worktrees add");m(Be(n.command("worktrees-list")),"worktrees list");m(ze(n.command("worktrees-remove")),"worktrees remove");m(He(n.command("worktrees-sync")),"worktrees sync");m(Ye(n.command("worktrees-reload")),"worktrees reload");var Qe=n.command("config").description("Manage infra-kit configuration files");Qe.command("path").description("Show the resolved config merge chain and file paths").action(async()=>{i(await O())});Qe.command("edit").description("Open the user-scope per-project override file in $EDITOR").action(async()=>{i(await M())});n.command("audit").description("Audit against infra-kit.config.ts rules (--all for every package, --root for the monorepo root)").option("-a, --all","Audit every non-vendor workspace package").option("-r, --root","Audit the monorepo root (turbo pipeline + root commands)").action(async e=>{let o=await B({all:e.all,root:e.root});i(o),o.structuredContent.allPassed||(w.exitCode=1)});var b=n.command("vendor").description("Verify and sync the mirrored vendor/ tree");b.command("check").description("Verify vendor/ matches vendor/.sync-manifest.json (self-contained; for any consumer repo)").action(async()=>{let e=await we();i(e),e.structuredContent.ok||(w.exitCode=1)});b.command("sync").description("Copy vendored files from the source repo into each target and regenerate manifests").option("-y, --yes","Skip confirmation prompt").option("-r, --repos <repos>","Restrict to comma-separated target repo names").action(async e=>{i(await Ae({confirmedCommand:e.yes,repos:H(e.repos)}))});b.command("manifest").description("Regenerate each target vendor/.sync-manifest.json + README from current content (no copy)").option("-r, --repos <repos>","Restrict to comma-separated target repo names").action(async e=>{i(await Ce({confirmedCommand:!0,repos:H(e.repos)}))});b.command("diff").description("Source-aware drift check (rsync dry-run) of each target vendored subtree vs the source").option("-r, --repos <repos>","Restrict to comma-separated target repo names").action(async e=>{let o=await ke({repos:H(e.repos)});i(o),o.structuredContent.ok||(w.exitCode=1)});qe(b.command("config"));m(qe(n.command("vendor-config")),"vendor config");n.command("doctor").description("Check installation and authentication status of gh and doppler CLIs").action(async()=>{i(await X())});n.command("version").description("Print the installed infra-kit CLI version").action(async()=>{i(await xe())});n.command("env-status").description("Show which env is loaded in this session (local introspection; no Doppler call)").action(async()=>{i(await me())});n.command("env-list").description("List available Doppler configs for the detected project").action(async()=>{i(await de())});n.command("init").description("Inject shell integration into .zshrc and sync repo agent-instruction files").action(async()=>{i(await I())});n.command("env-load").description("Load Doppler env vars for a config. Source the returned file path to apply.").option("-c, --config <config>","Environment config name to load (e.g. dev, arthur)").action(async e=>{i(await se({config:e.config}))});n.command("env-clear").description("Clear loaded env vars. Source the returned file path to apply.").action(async()=>{i(await ce())});n.command("env-autoload",{hidden:!0}).description("Internal: prime env for the shell-startup auto-load trigger").action(async()=>{await V()});n.commands.forEach(P);var wo=e=>e.startsWith("env-")||e==="init"||e==="doctor"||e==="version";n.hook("preAction",async(e,o)=>{R.enabled=!!o.optsWithGlobals().json,R.enabled&&(a.level="warn"),wo(o.name())||await S({expectedTrigger:"cli-invocation"})});if(w.argv.length<=2){let e=j("release"),o=j("worktrees"),t=j("environment"),r=new Map(n.commands.map(d=>[d.name(),d])),s=[{label:"Release Management",names:e},{label:"Worktrees",names:o},{label:"Environment",names:t}].flatMap(({label:d,names:g})=>g.filter(p=>r.has(p)).map(p=>({name:p,description:r.get(p).description(),group:d}))),l;if(w.stdout.isTTY&&w.stdin.isTTY){let{runCommandPalette:d}=await import("./boot-SGM5RVLJ.js");l=await d(s)}else{let d=K(s.map(v=>[v.name,v.description])),g=new Map;s.forEach((v,y)=>{g.set(v.name,d[y]??v.name)});let p=v=>v.filter(y=>r.has(y)).map(y=>({name:g.get(y)??y,value:y}));l=await vo({message:"Select a command to run",choices:[new x(" "),new x("\u2014 Release Management \u2014"),...p(e),new x(" "),new x("\u2014 Worktrees \u2014"),...p(o),new x(" "),new x("\u2014 Environment \u2014"),...p(t)]},{output:w.stderr})}l&&(Oe.value=!0,await Ne(["node","infra-kit",l]))}else await Ne();
|
|
20
20
|
//# sourceMappingURL=cli.js.map
|
package/dist/mcp.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{V as m,b as s,c as p,d as c}from"./chunk-
|
|
1
|
+
import{V as m,b as s,c as p,d as c}from"./chunk-YMXDO43V.js";import"./chunk-WA4BQRDC.js";import{StdioServerTransport as g}from"@modelcontextprotocol/sdk/server/stdio.js";import h from"node:process";import o from"node:process";var l=r=>{o.on("SIGINT",()=>{r.info({msg:"Received SIGINT. Shutting down..."}),o.exit(0)}),o.on("SIGTERM",()=>{r.info({msg:"Received SIGTERM. Shutting down..."}),o.exit(0)}),o.on("uncaughtException",e=>{r.fatal({err:e,msg:"Uncaught Exception"}),r.error(`Uncaught Exception! Check ${s}. Shutting down...`),r.flush(),o.exit(1)}),o.on("unhandledRejection",(e,n)=>{r.fatal({reason:e,promise:n,msg:"Unhandled Rejection"}),r.error(`Unhandled Rejection! Check ${s}. Shutting down...`),r.flush(),o.exit(1)})};import{McpServer as x}from"@modelcontextprotocol/sdk/server/mcp.js";var d=async r=>{};var u=async r=>{};var a=r=>async e=>{let{toolName:n,handler:S}=r;c.info({msg:`Tool execution started: ${n}`,params:e});try{let i=await S({...e,confirmedCommand:!0});return c.info({msg:`Tool execution successful: ${n}`}),i}catch(i){throw c.error({err:i,params:e,msg:`Tool execution failed: ${n}`}),i}};var f=async r=>{for(let e of m())r.registerTool(e.name,{description:e.description,inputSchema:e.inputSchema,outputSchema:e.outputSchema},a({toolName:e.name,handler:e.handler}))};async function v(){let r=new x({name:"infra-kit",version:"1.0.0"},{capabilities:{resources:{},tools:{},prompts:{}}});return await d(r),await u(r),await f(r),r}var t=p(),T=async()=>{let r;try{r=await v(),t.info("MCP Server instance created")}catch(e){t.error({err:e,msg:"Failed to create MCP server"}),t.error("Fatal error during server creation."),h.exit(1)}try{let e=new g;await r.connect(e),t.info({msg:"Server connected to transport. Ready."})}catch(e){t.error({err:e,msg:"Failed to initialize server"}),t.error("Fatal error during server transport init."),h.exit(1)}};l(t);T();
|
|
2
2
|
//# sourceMappingURL=mcp.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "infra-kit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.123",
|
|
5
5
|
"description": "infra-kit",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"ink": "^7.1.0",
|
|
46
46
|
"pino": "^10.3.1",
|
|
47
47
|
"pino-pretty": "^13.1.3",
|
|
48
|
-
"react": "
|
|
48
|
+
"react": "19.2.7",
|
|
49
49
|
"yaml": "^2.9.0",
|
|
50
50
|
"zod": "^4.4.3",
|
|
51
51
|
"zx": "^8.8.5"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"entries": {
|
|
4
|
+
"79a93d4a2f8f50b95f852280616242fee1855dc99a3c75211917f55e72e95fae": {
|
|
5
|
+
"last_emitted_at_ms": 1782811819739,
|
|
6
|
+
"message": "Use parallel execution for independent tasks. Use run_in_background for long operations (npm install, builds, tests)."
|
|
7
|
+
},
|
|
8
|
+
"466399dafa2d20f60587180bad0a07358eb7f2bce724df0ff682f038ad33f5ad": {
|
|
9
|
+
"last_emitted_at_ms": 1782811804270,
|
|
10
|
+
"message": "Read multiple files in parallel when possible for faster analysis."
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"updated_at": "2026-06-30T09:30:19.739Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"entries": {
|
|
4
|
+
"79a93d4a2f8f50b95f852280616242fee1855dc99a3c75211917f55e72e95fae": {
|
|
5
|
+
"last_emitted_at_ms": 1782811823537,
|
|
6
|
+
"message": "Use parallel execution for independent tasks. Use run_in_background for long operations (npm install, builds, tests)."
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
"updated_at": "2026-06-30T09:30:23.537Z"
|
|
10
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ReactElement } from 'react'
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import type { PaletteItem } from '../types'
|
|
5
|
+
|
|
6
|
+
// Ink `unref()`s process.stdin when it tears down raw mode on exit and never
|
|
7
|
+
// restores it. Without a re-ref, the Inquirer prompt the selected command opens
|
|
8
|
+
// reads from an unref'd stdin that no longer keeps the event loop alive: once the
|
|
9
|
+
// command's subprocesses settle, the loop drains mid-prompt and Node aborts
|
|
10
|
+
// entry/cli.ts's top-level await with "Detected unsettled top-level await"
|
|
11
|
+
// (exit 13). runCommandPalette must re-ref stdin once the palette exits.
|
|
12
|
+
|
|
13
|
+
// Control `waitUntilExit` so the test drives the palette teardown deterministically,
|
|
14
|
+
// and capture the rendered element so a test can fire its onSelect/onCancel props.
|
|
15
|
+
const waitUntilExit = vi.fn<() => Promise<void>>()
|
|
16
|
+
let rendered: ReactElement | undefined
|
|
17
|
+
|
|
18
|
+
vi.mock('ink', () => {
|
|
19
|
+
return {
|
|
20
|
+
render: (element: ReactElement) => {
|
|
21
|
+
rendered = element
|
|
22
|
+
|
|
23
|
+
return { waitUntilExit }
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const { runCommandPalette } = await import('../boot')
|
|
29
|
+
|
|
30
|
+
const items: PaletteItem[] = [{ name: 'worktrees-remove', description: 'remove', group: 'Worktrees' }]
|
|
31
|
+
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
vi.restoreAllMocks()
|
|
34
|
+
waitUntilExit.mockReset()
|
|
35
|
+
rendered = undefined
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('runCommandPalette stdin lifecycle', () => {
|
|
39
|
+
it('re-refs process.stdin and returns the picked command after the palette exits', async () => {
|
|
40
|
+
const refSpy = vi.spyOn(process.stdin, 'ref').mockReturnValue(process.stdin)
|
|
41
|
+
|
|
42
|
+
waitUntilExit.mockResolvedValue(undefined)
|
|
43
|
+
|
|
44
|
+
const pending = runCommandPalette(items)
|
|
45
|
+
|
|
46
|
+
// render runs synchronously; mimic Ink firing onSelect before it exits.
|
|
47
|
+
;(rendered?.props as { onSelect: (name: string) => void }).onSelect('worktrees-remove')
|
|
48
|
+
|
|
49
|
+
expect(await pending).toBe('worktrees-remove')
|
|
50
|
+
expect(refSpy).toHaveBeenCalledTimes(1)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('re-refs process.stdin even when the palette teardown rejects (cancel path)', async () => {
|
|
54
|
+
const refSpy = vi.spyOn(process.stdin, 'ref').mockReturnValue(process.stdin)
|
|
55
|
+
|
|
56
|
+
waitUntilExit.mockRejectedValue(new Error('forced close'))
|
|
57
|
+
|
|
58
|
+
expect(await runCommandPalette(items)).toBeNull()
|
|
59
|
+
expect(refSpy).toHaveBeenCalledTimes(1)
|
|
60
|
+
})
|
|
61
|
+
})
|
package/src/tui/boot.tsx
CHANGED
|
@@ -34,11 +34,26 @@ export const runCommandPalette = async (items: PaletteItem[]): Promise<string |
|
|
|
34
34
|
{ stdout: process.stderr as unknown as NodeJS.WriteStream },
|
|
35
35
|
)
|
|
36
36
|
|
|
37
|
+
// Ink `unref()`s process.stdin when it tears down raw mode on exit. That ref
|
|
38
|
+
// is process-wide and never restored, so the next consumer of stdin — the
|
|
39
|
+
// Inquirer prompt the selected command opens (e.g. the worktrees-remove
|
|
40
|
+
// checkbox) — reads from an unref'd handle that no longer keeps the event
|
|
41
|
+
// loop alive. Once the command's git/gh subprocesses settle, the loop drains
|
|
42
|
+
// mid-prompt, Node flags entry/cli.ts's top-level await as unsettled, and the
|
|
43
|
+
// process exits with code 13 (the prompt dies on arrival). Re-ref stdin so it
|
|
44
|
+
// holds the loop while a prompt is reading; an idle ref'd stdin does not block
|
|
45
|
+
// exit, so non-interactive follow-up commands still terminate normally.
|
|
46
|
+
const restoreStdinRef = () => {
|
|
47
|
+
process.stdin.ref()
|
|
48
|
+
}
|
|
49
|
+
|
|
37
50
|
waitUntilExit()
|
|
38
51
|
.then(() => {
|
|
52
|
+
restoreStdinRef()
|
|
39
53
|
resolve(selected)
|
|
40
54
|
})
|
|
41
55
|
.catch(() => {
|
|
56
|
+
restoreStdinRef()
|
|
42
57
|
resolve(null)
|
|
43
58
|
})
|
|
44
59
|
})
|