@coreframe/dev 0.1.0 → 0.1.2

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.
@@ -1,6 +1,7 @@
1
- import{managedDevCodexHighArgs as e,managedDevCodexMaxArgs as t}from"./codex-model.js";import{access as n,copyFile as r,mkdir as i,mkdtemp as a,open as o,readFile as s,realpath as c,rm as l,unlink as u,writeFile as d}from"node:fs/promises";import f from"node:path";import p from"node:process";import m,{SubprocessError as h}from"nano-spawn";import{constants as g,watch as _}from"node:fs";import{createHash as v,randomBytes as y}from"node:crypto";import{pathToFileURL as b}from"node:url";import{stripVTControlCharacters as x}from"node:util";import{resolve as S}from"import-meta-resolve";const C=`refs/heads/main`,w=`refs/heads/dev`,ee=`refs/remotes/origin/main`,te=/^[a-z][a-z0-9-]*(?:\([^)]+\))?!?:\s+\S/i,T=`coreframe-managed-dev-codex-completion.json`,ne=`coreframe-managed-dev-setup-failure.json`;async function E(e=p.cwd()){let t=await se(e);return t.primary&&t.branch===`main`&&t.head===t.main}async function D(e=p.cwd()){try{let{commonDir:t,gitDir:n}=await O(e);return n===t}catch{return!1}}async function O(e){let t=await c(await Z(e,[`rev-parse`,`--show-toplevel`])),n=await c(e),r=f.resolve(n,await Z(e,[`rev-parse`,`--git-dir`])),i=f.resolve(n,await Z(e,[`rev-parse`,`--git-common-dir`]));return{commonDir:i,gitDir:r,primary:t===n&&r===i}}async function k({config:e,cwd:t=p.cwd(),env:n=p.env,localCheckInterval:r=1e3,onRestart:i=()=>void 0,onStatusChange:a=()=>void 0,remoteCheckInterval:o=6e4,runCheck:s=e=>me(t,n,e),watchState:c=ce}){let l=n,h={mode:`waiting`,warnings:[]},g=!1,_=!1,v=!1,b=!1,x,S,E,D,O,k,ie=[],A,j,M=Promise.resolve(),N=()=>{g||a(h)},F=async({fetch:e=!1}={})=>{if(!(!_||g||!S)){if(v){b=!0;return}try{let[n,r,i]=await Promise.all([Z(t,[`rev-parse`,`--abbrev-ref`,`HEAD`]),Z(t,[`rev-parse`,`HEAD`]),Z(t,[`rev-parse`,C])]);if(n!==`main`||r!==i){h={message:`Managed synchronization is paused until the primary checkout is back on local main.`,mode:`waiting`,warnings:[]};return}r!==x&&(x=r,A=void 0);let a=await P(t);if(a.tracked||a.untracked.length>0){h={...h,currentCommit:x,draft:a,message:void 0,mode:`managed`,proposal:B(a.fingerprint),target:void 0};return}if(e&&await Q(t,[`remote`,`get-url`,`origin`]))try{await X(t,[`fetch`,`origin`,`+refs/heads/main:${ee}`])}catch{}let o=await Q(t,[`rev-parse`,w]),s=await Q(t,[`rev-parse`,ee]),c=[...o?[{commit:o,source:`dev`}]:[],...s?[{commit:s,source:`upstream`}]:[]],l;for(let e of c)if(!await Ce(t,e.commit,x)){l=e;break}h={...h,currentCommit:x,draft:void 0,message:void 0,mode:`managed`,proposal:void 0,target:l===void 0?void 0:await be(t,l.commit,l.source)}}catch(e){h={...h,message:$(e),warnings:[$(e)]}}finally{N()}}},I=()=>{clearTimeout(k),k=setTimeout(()=>void F(),50),k.unref()},L=(e,t)=>{let n=async()=>{let n=[{command:`pnpm typecheck`,status:`running`},{command:`pnpm test`,status:`pending`}],r=()=>{h={...h,checks:{commit:e,commands:structuredClone(n),trigger:t}},N()};r();for(let[e,t]of[`typecheck`,`test`].entries()){e>0&&(n[e].status=`running`,r());try{await s(t),n[e].status=`passed`}catch(t){n[e].status=`failed`,n[e].failureId=y(12).toString(`hex`),n[e].output=he(t)}r()}};M=M.then(n,n)},pe=async()=>{if(_||g)return;let e=await se(t);if(!e.primary){h={message:`Managed development only runs from the primary checkout.`,mode:`unmanaged`,warnings:[]},N();return}if(e.branch!==`main`||e.head!==e.main){let t=`Managed development requires the primary checkout on local main; current branch is ${e.branch??`detached HEAD`}.`;console.warn(`Coreframe managed development disabled: ${t}`),h={message:t,mode:`unmanaged`,warnings:[]},N();return}E=f.join(e.commonDir,`coreframe-managed-dev.lock`),await xe(E),await Q(t,[`rev-parse`,`--verify`,w])||await X(t,[`branch`,`dev`,e.head]),S=e,x=e.head,_=!0,h={codexCompletion:await re(e.commonDir),currentCommit:e.head,mode:`managed`,setupFailure:await oe(e.commonDir,e.head),warnings:[]},N(),ie=await c(e,I),D=setInterval(()=>{h.draft&&F()},r),D.unref(),O=setInterval(()=>void F({fetch:!0}),o),O.unref(),await F(),F({fetch:!0})},R=async(e,{onCodexEvent:n=()=>void 0}={})=>{if(!_||h.mode!==`managed`)throw Error(`Managed development is not active.`);if(v)throw Error(`Another managed development action is already running.`);let r=[],i=[],a,o=e=>{e.phase===`start`?(i=e.commits,r.splice(0,r.length,e.message)):e.phase===`message`?r.push(e.message):e.phase===`complete`?a=e.finalMessage:e.phase===`progress`&&(i=e.commits),n(e)};v=!0,h={...h,busy:De(e),message:void 0};try{if(N(),e.type===`acknowledge-codex`)h.codexCompletion?.id===e.id&&await je();else if(e.type===`dismiss-check`)h.checks&&(h={...h,checks:{...h.checks,commands:h.checks.commands.map(t=>t.failureId===e.failureId?{...t,dismissed:!0}:t)}});else if(e.type===`reject`)h={...h,draft:void 0,proposal:void 0};else if(e.type===`prepare`){let n=z(e.target),r=await P(t);r.tracked||r.untracked.length>0?h={...h,draft:r,proposal:B(r.fingerprint)}:await H({onCodexEvent:o,source:n.source,target:e.target})}else if(e.type===`message`){let n=await V(e.fingerprint,e.untracked),r=B(n.fingerprint);if(r===void 0){try{if(j??=ue(`codex`,l),!await j)throw Error("Codex CLI is not installed or is unavailable on PATH. Install it with `npm install -g @openai/codex`, then restart the dev server.");r=await le(t,l,n.untracked)}catch(e){r=``,h={...h,warnings:[...h.warnings,`Codex could not generate a commit message: ${$(e)}`]}}A={fingerprint:n.fingerprint,message:r}}h={...h,draft:n,proposal:r}}else if(e.type===`commit`){let t=await _e(e);h={...h,currentCommit:t,draft:void 0,message:void 0,proposal:void 0,target:void 0},I()}else if(e.type===`retry-install`)await W();else if(e.type===`reset-database`)await G();else{let n=z(e.target),r=await P(t);if(r.tracked||r.untracked.length>0){if(!e.fingerprint||!e.untracked)throw Error(`Refresh requires the current working-tree confirmation.`);if(await V(e.fingerprint,e.untracked),!e.message||!te.test(Ee(e.message)))throw Error(`Enter a commit message with a valid Conventional Commits header.`)}await H({fingerprint:e.fingerprint,message:e.message,onCodexEvent:o,source:n.source,target:e.target,untracked:e.untracked})}}finally{v=!1,h={...h,busy:void 0},N(),b&&(b=!1,I())}return a&&await Ae(a,r,i),{status:h}},z=e=>{if(!h.target||h.target.commit!==e)throw Error(`The offered update changed. Review the latest target before refreshing.`);return h.target},B=e=>A?.fingerprint===e?A.message:void 0,V=async(e,n)=>{let r=await P(t);if(r.fingerprint!==e)throw A=void 0,Error(`Working-tree changes changed; generate a new commit message.`);if(!we(r.untracked,n))throw Error(`Include every untracked file or remove it before refreshing.`);return r},_e=async({fingerprint:e,message:n,untracked:r})=>{let i=await V(e,r);if(!n||!te.test(Ee(n)))throw Error(`Enter a commit message with a valid Conventional Commits header.`);await X(t,[`add`,`--update`]),i.untracked.length>0&&await X(t,[`add`,`--`,...r]),await X(t,[`commit`,`--message`,n],{env:{GIT_EDITOR:`true`}});let a=await Z(t,[`rev-parse`,`HEAD`]);return x=a,A=void 0,a},H=async({fingerprint:e,message:n,onCodexEvent:r=()=>void 0,source:i,target:a,untracked:o=[]})=>{z(a);let s=await Z(t,[`rev-parse`,`HEAD`]),c,u,d=await P(t);if(d.tracked||d.untracked.length>0){if(!e||d.fingerprint!==e||!we(d.untracked,o))throw Error(`Working-tree changes changed; review them before refreshing.`);await X(t,[`add`,`--update`]),o.length>0&&await X(t,[`add`,`--`,...o]),await X(t,[`commit`,`--message`,n],{env:{GIT_EDITOR:`true`}}),c=await Z(t,[`rev-parse`,`HEAD`]),x=c,u=`refs/coreframe/recovery/${Date.now()}-${c.slice(0,12)}`,await X(t,[`update-ref`,u,c])}let f=c??s,p;try{if(p=await de({cwd:t,env:l,localMain:f,onCodexEvent:r,source:i,target:a}),await Z(t,[`rev-parse`,`HEAD`])!==f)throw Error(`HEAD changed while the accepted update was being prepared.`);if(await Z(t,[`rev-parse`,C])!==f)throw Error(`Local main changed while the accepted update was being prepared.`);await fe(t,p,f),b=!0,x=p.commit,await X(t,[`reset`,`--hard`,p.commit]);let e=Te(await Z(t,[`diff`,`--name-only`,`-z`,s,p.commit]));A=void 0,u&&await X(t,[`update-ref`,`-d`,u]),h={...h,currentCommit:p.commit,draft:void 0,proposal:void 0,setupFailure:void 0,target:void 0},await U({installDependencies:ve(e),restartRequired:ye(e),trigger:`synchronization`})}catch(e){let t=u?` Recovery commit: ${u}.`:``;throw h={...h,currentCommit:x,message:`${$(e)}${t}`},e}},U=async({installDependencies:n,restartRequired:r,trigger:a})=>{let o=x;if(n)try{await q([`install`,`--frozen-lockfile`])}catch(e){await J({command:`pnpm install --frozen-lockfile`,commit:o,error:e,message:`The project was synchronized, but dependency installation failed. Fix the package or lockfile issue, then retry the install.`,restartRequired:r,stage:`dependencies`});return}try{await ge({config:e,cwd:t,env:l})}catch(e){await J({command:`pnpm db migrate`,commit:o,error:e,message:`The project was synchronized, but its database migration failed. The previous database was restored. Reset the database to recreate it, apply migrations, and rerun seed scripts.`,restartRequired:r,stage:`migration`});return}await Y(),L(o,a),r&&i()},W=async()=>{let e=K(`dependencies`);await Y(),await U({installDependencies:!0,restartRequired:e.restartRequired,trigger:`dependency-recovery`})},G=async()=>{let e=K(`migration`);try{await q([`db`,`setup`])}catch(t){await J({command:`pnpm db setup`,commit:e.commit,error:t,message:`The project remains synchronized, but the database reset failed. Review the diagnostics, fix the reported problem, and try the reset again.`,restartRequired:e.restartRequired,stage:`migration`});return}await Y(),L(e.commit,`database-recovery`),e.restartRequired&&i()},K=e=>{if(!h.setupFailure||h.setupFailure.stage!==e)throw Error(`There is no failed ${e} setup step to recover.`);return h.setupFailure},q=async e=>{await m(Oe(),e,{cwd:t,env:l})},J=async({command:e,commit:t,error:n,message:r,restartRequired:i,stage:a})=>{let o=he(n).slice(-1e5),s={command:e,commit:t,message:r,output:o,restartRequired:i,stage:a};h={...h,setupFailure:s,target:void 0},console.error(`Coreframe managed development setup failed (${e}): ${r}\n${o}`);let c=ke();c&&await d(c,`${JSON.stringify(s)}\n`,{mode:384}).catch(e=>{console.warn(`Could not persist the managed-development setup failure: ${$(e)}`)})},Y=async()=>{h={...h,setupFailure:void 0};let e=ke();e&&await u(e).catch(e=>{e instanceof Error&&`code`in e&&e.code===`ENOENT`||console.warn(`Could not clear the managed-development setup failure: ${$(e)}`)})},ke=()=>S?f.join(S.commonDir,ne):void 0,Ae=async(e,t,n)=>{let r={commits:n,finalMessage:e,id:y(16).toString(`hex`),messages:ae(t)};h={...h,codexCompletion:r},S&&await d(f.join(S.commonDir,T),`${JSON.stringify(r)}\n`,{mode:384}).catch(e=>{console.warn(`Could not persist the managed-development Codex result: ${$(e)}`)}),N()},je=async()=>{h={...h,codexCompletion:void 0},S&&await u(f.join(S.commonDir,T)).catch(e=>{if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e})};return{action:R,activate:pe,getStatus:()=>h,async close(){if(!g){g=!0,clearInterval(D),clearInterval(O),clearTimeout(k);for(let e of ie)e.close();await Se(E)}}}}async function re(e){let t=f.join(e,T);try{let e=JSON.parse(await s(t,`utf8`));if(ie(e))return e}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;console.warn(`Could not read the managed-development Codex result: ${$(e)}`)}await u(t).catch(()=>void 0)}function ie(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.finalMessage==`string`&&typeof t.id==`string`&&Array.isArray(t.messages)&&t.messages.every(j)&&(t.commits===void 0||Array.isArray(t.commits)&&t.commits.every(A))}function A(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.commit==`string`&&typeof t.shortCommit==`string`&&typeof t.subject==`string`}function j(e){if(!e||typeof e!=`object`)return!1;let t=e;return(t.kind===`agent`||t.kind===`thought`||t.kind===`user`)&&typeof t.text==`string`}function ae(e){let t=new Set(e.filter(e=>e.kind===`user`)),n=[...t].reduce((e,t)=>e+t.text.length,0),r=!1;for(let i of[...e].reverse())if(i.kind!==`user`){if(n+i.text.length>1e5&&r)break;t.add(i),r=!0,n+=i.text.length}return e.filter(e=>t.has(e))}async function oe(e,t){let n=f.join(e,ne);try{let e=JSON.parse(await s(n,`utf8`));if(M(e)&&e.commit===t)return e}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;console.warn(`Could not read the managed-development setup failure: ${$(e)}`)}await u(n).catch(()=>void 0)}function M(e){if(!e||typeof e!=`object`)return!1;let t=e;return(t.command===`pnpm db migrate`||t.command===`pnpm db setup`||t.command===`pnpm install --frozen-lockfile`)&&typeof t.commit==`string`&&typeof t.message==`string`&&typeof t.output==`string`&&typeof t.restartRequired==`boolean`&&(t.stage===`dependencies`||t.stage===`migration`)}async function se(e){let t=await O(e);return{branch:N(await Z(e,[`rev-parse`,`--abbrev-ref`,`HEAD`])),commonDir:t.commonDir,gitDir:t.gitDir,head:await Z(e,[`rev-parse`,`HEAD`]),main:await Z(e,[`rev-parse`,C]),primary:t.primary}}function N(e){return e===`HEAD`?void 0:e}async function ce(e,t){let n=[e.gitDir,f.join(e.commonDir,`refs`,`heads`)],r=[];for(let e of n)try{r.push(_(e,{persistent:!1},t))}catch{}return r}async function P(e){let[t,n,r]=await Promise.all([Z(e,[`status`,`--porcelain`,`--untracked-files=no`]),Z(e,[`diff`,`HEAD`,`--binary`]),Z(e,[`ls-files`,`--others`,`--exclude-standard`,`-z`])]),i=Te(r).sort(),a=v(`sha256`).update(n);for(let e of i)a.update(`\0`).update(e);return{fingerprint:a.digest(`hex`),tracked:t.length>0,untracked:i}}async function le(t,n,r){let i=[`Tracked changes:`,await Z(t,[`diff`,`HEAD`,`--binary`])];for(let e of r){let n=await s(f.join(t,e));i.push(`\nUntracked file: ${e}\n`,n.toString(`utf8`))}let{stdout:a}=await m(`codex`,[`exec`,...e,`--ephemeral`,`--ignore-user-config`,`--sandbox`,`read-only`,`--cd`,t,`Return only a concise Conventional Commits message for the supplied working-tree changes. Use a body only when it adds material context.`],{cwd:t,env:n,stderr:`ignore`,stdin:{string:i.join(`
2
- `)}});return a.trim().replace(/^```(?:text)?\s*|\s*```$/g,``)}async function ue(e,t){let r=t.PATH??t.Path??t.path??``,i=p.platform===`win32`?(t.PATHEXT??`.COM;.EXE;.BAT;.CMD`).split(`;`):[``];for(let t of r.split(f.delimiter))for(let r of i)try{return await n(f.join(t||`.`,`${e}${r}`),g.X_OK),!0}catch{}return!1}async function de({cwd:e,env:t,localMain:n,onCodexEvent:r,source:a,target:o}){if(a===`dev`&&await Ce(e,n,o))return{commit:o,devTarget:o};let s=f.resolve(e,await Z(e,[`rev-parse`,`--git-common-dir`])),c=f.join(s,`coreframe-managed-dev`);await i(c,{recursive:!0});let u=y(8).toString(`hex`),d=f.join(c,`integration-${u}`);try{if(await X(e,[`worktree`,`add`,`--detach`,d,n]),n!==o)if(a===`dev`)await F(d,t,[`merge`,`--no-edit`,`--no-ff`,`--allow-unrelated-histories`,`--message`,`Merge dev into main`,o],`merge`,r);else{let e=await Q(d,[`merge-base`,n,o]);await F(d,t,e?[`rebase`,`--onto`,o,e]:[`rebase`,`--root`,`--onto`,o],`rebase`,r,o)}return{commit:await Z(d,[`rev-parse`,`HEAD`]),devTarget:a===`dev`?o:void 0}}finally{await X(e,[`worktree`,`remove`,`--force`,d]).catch(()=>void 0),await l(d,{force:!0,recursive:!0})}}async function fe(e,t,n){let r=async r=>{let i=[`start`,`update ${C} ${t.commit} ${n}`];r&&t.devTarget&&i.push(t.devTarget===t.commit?`verify ${w} ${t.devTarget}`:`update ${w} ${t.commit} ${t.devTarget}`),i.push(`prepare`,`commit`),await m(`git`,[`update-ref`,`--stdin`],{cwd:e,stdin:{string:`${i.join(`
3
- `)}\n`}})};try{await r(!0)}catch(i){if(!t.devTarget)throw i;let a;try{a=await Promise.all([Z(e,[`rev-parse`,C]),Q(e,[`rev-parse`,w])])}catch{throw i}let[o,s]=a;if(o!==n||s===t.devTarget)throw i;await r(!1)}}async function F(e,t,n,r,i,a){try{await X(e,n,{env:{GIT_EDITOR:`true`}});return}catch(n){let o=await z(e);if(o.length===0)throw n;try{for(;o.length>0;){await I(e,t,r,o,a?await L(e,a):[],i),await X(e,[`diff`,`--check`]),await X(e,[`add`,`--all`]);let n=await z(e);if(n.length>0)throw Error(`Codex left unresolved paths: ${n.join(`, `)}`);try{await X(e,[r,`--continue`],{env:{GIT_EDITOR:`true`}})}catch(t){if(o=await z(e),o.length===0)throw t;i({commits:a?await L(e,a):[],phase:`progress`});continue}i({commits:a?await L(e,a):[],phase:`progress`}),o=await z(e)}return}catch(t){throw await X(e,[r,`--abort`]).catch(()=>void 0),Error(`Codex could not resolve ${r} conflicts: ${$(t)}`)}}}async function I(e,n,r,i,a,o){let s=`Resolve the current Git ${r} conflicts cleanly. Edit only files needed for the resolution, preserve intended behavior from both sides, and remove all conflict markers. Do not run pnpm test or any other test suite; managed development will run pnpm test after you finish and report any failures. You may run pnpm typecheck and pnpm format if useful. Do not stage files or run Git continuation commands. Conflicted paths: ${i.join(`, `)}`;o({commits:a,message:{kind:`user`,text:s},phase:`start`});let c=m(`codex`,[`exec`,...t,`--ephemeral`,`--ignore-user-config`,`--json`,`--sandbox`,`workspace-write`,`--cd`,e,s],{cwd:e,env:n,stdin:`ignore`}),l=``,u=[];try{await Promise.all([R(c.stdout,e=>{let t=pe(e);t&&(t.kind===`agent`&&(l=t.text),o({message:t,phase:`message`}))}),R(c.stderr,e=>u.push(e))])}catch(e){o({phase:`error`});let t=u.join(`
4
- `).trim();throw t?Error(`${$(e)}\n${t}`):e}o({finalMessage:l||`Codex resolved the conflicts.`,phase:`complete`})}async function L(e,t){let n=await Z(e,[`log`,`--reverse`,`--format=%H%x00%s`,`${t}..HEAD`]);return n?n.split(`
1
+ import{managedDevCodexHighArgs as e,managedDevCodexMaxArgs as t}from"./codex-model.js";import{access as n,copyFile as r,mkdir as i,mkdtemp as a,open as o,readFile as s,realpath as c,rm as l,unlink as u,writeFile as d}from"node:fs/promises";import f from"node:path";import p from"node:process";import m,{SubprocessError as h}from"nano-spawn";import{constants as g,watch as _}from"node:fs";import{createHash as v,randomBytes as y}from"node:crypto";import{pathToFileURL as b}from"node:url";import{stripVTControlCharacters as x}from"node:util";import{resolve as S}from"import-meta-resolve";const C=`refs/heads/main`,w=`refs/heads/dev`,ee=`refs/remotes/origin/main`,te=/^[a-z][a-z0-9-]*(?:\([^)]+\))?!?:\s+\S/i,T=`coreframe-managed-dev-codex-completion.json`,ne=`coreframe-managed-dev-setup-failure.json`;async function E(e=p.cwd()){let t=await se(e);return t.primary&&t.branch===`main`&&t.head===t.main}async function D(e=p.cwd()){try{let{commonDir:t,gitDir:n}=await O(e);return n===t}catch{return!1}}async function O(e){let t=await c(await Z(e,[`rev-parse`,`--show-toplevel`])),n=await c(e),r=f.resolve(n,await Z(e,[`rev-parse`,`--git-dir`])),i=f.resolve(n,await Z(e,[`rev-parse`,`--git-common-dir`]));return{commonDir:i,gitDir:r,primary:t===n&&r===i}}async function k({config:e,cwd:t=p.cwd(),env:n=p.env,localCheckInterval:r=1e3,onRestart:i=()=>void 0,onStatusChange:a=()=>void 0,remoteCheckInterval:o=6e4,runCheck:s=e=>me(t,n,e),watchState:c=ce}){let l=n,h={mode:`waiting`,warnings:[]},g=!1,_=!1,v=!1,b=!1,x,S,E,D,O,k,ie=[],A,j,M=Promise.resolve(),N=()=>{g||a(h)},F=async({fetch:e=!1}={})=>{if(!(!_||g||!S)){if(v){b=!0;return}try{let[n,r,i]=await Promise.all([Z(t,[`rev-parse`,`--abbrev-ref`,`HEAD`]),Z(t,[`rev-parse`,`HEAD`]),Z(t,[`rev-parse`,C])]);if(n!==`main`||r!==i){h={message:`Managed synchronization is paused until the primary checkout is back on local main.`,mode:`waiting`,warnings:[]};return}r!==x&&(x=r,A=void 0);let a=await P(t);if(a.tracked||a.untracked.length>0){h={...h,currentCommit:x,draft:a,message:void 0,mode:`managed`,proposal:B(a.fingerprint),target:void 0};return}if(e&&await Q(t,[`remote`,`get-url`,`origin`]))try{await X(t,[`fetch`,`origin`,`+refs/heads/main:${ee}`])}catch{}let o=await Q(t,[`rev-parse`,w]),s=await Q(t,[`rev-parse`,ee]),c=[...o?[{commit:o,source:`dev`}]:[],...s?[{commit:s,source:`upstream`}]:[]],l;for(let e of c)if(!await Ce(t,e.commit,x)){l=e;break}h={...h,currentCommit:x,draft:void 0,message:void 0,mode:`managed`,proposal:void 0,target:l===void 0?void 0:await be(t,x,l.commit,l.source)}}catch(e){h={...h,message:$(e),warnings:[$(e)]}}finally{N()}}},I=()=>{clearTimeout(k),k=setTimeout(()=>void F(),50),k.unref()},L=(e,t)=>{let n=async()=>{let n=[{command:`pnpm typecheck`,status:`running`},{command:`pnpm test`,status:`pending`}],r=()=>{h={...h,checks:{commit:e,commands:structuredClone(n),trigger:t}},N()};r();for(let[e,t]of[`typecheck`,`test`].entries()){e>0&&(n[e].status=`running`,r());try{await s(t),n[e].status=`passed`}catch(t){n[e].status=`failed`,n[e].failureId=y(12).toString(`hex`),n[e].output=he(t)}r()}};M=M.then(n,n)},pe=async()=>{if(_||g)return;let e=await se(t);if(!e.primary){h={message:`Managed development only runs from the primary checkout.`,mode:`unmanaged`,warnings:[]},N();return}if(e.branch!==`main`||e.head!==e.main){let t=`Managed development requires the primary checkout on local main; current branch is ${e.branch??`detached HEAD`}.`;console.warn(`Coreframe managed development disabled: ${t}`),h={message:t,mode:`unmanaged`,warnings:[]},N();return}E=f.join(e.commonDir,`coreframe-managed-dev.lock`),await xe(E),await Q(t,[`rev-parse`,`--verify`,w])||await X(t,[`branch`,`dev`,e.head]),S=e,x=e.head,_=!0,h={codexCompletion:await re(e.commonDir),currentCommit:e.head,mode:`managed`,setupFailure:await oe(e.commonDir,e.head),warnings:[]},N(),ie=await c(e,I),D=setInterval(()=>{h.draft&&F()},r),D.unref(),O=setInterval(()=>void F({fetch:!0}),o),O.unref(),await F(),F({fetch:!0})},R=async(e,{onCodexEvent:n=()=>void 0}={})=>{if(!_||h.mode!==`managed`)throw Error(`Managed development is not active.`);if(v)throw Error(`Another managed development action is already running.`);let r=[],i=[],a,o,s=e=>{e.phase===`start`?(i=e.commits,a=e.totalCommits,r.splice(0,r.length,e.message)):e.phase===`message`?r.push(e.message):e.phase===`complete`?o=e.finalMessage:e.phase===`progress`&&(i=e.commits,a=e.totalCommits??a),n(e)};v=!0,h={...h,busy:De(e),message:void 0};try{if(N(),e.type===`acknowledge-codex`)h.codexCompletion?.id===e.id&&await je();else if(e.type===`dismiss-check`)h.checks&&(h={...h,checks:{...h.checks,commands:h.checks.commands.map(t=>t.failureId===e.failureId?{...t,dismissed:!0}:t)}});else if(e.type===`reject`)h={...h,draft:void 0,proposal:void 0};else if(e.type===`prepare`){let n=z(e.target),r=await P(t);r.tracked||r.untracked.length>0?h={...h,draft:r,proposal:B(r.fingerprint)}:await H({onCodexEvent:s,source:n.source,target:e.target})}else if(e.type===`message`){let n=await V(e.fingerprint,e.untracked),r=B(n.fingerprint);if(r===void 0){try{if(j??=ue(`codex`,l),!await j)throw Error("Codex CLI is not installed or is unavailable on PATH. Install it with `npm install -g @openai/codex`, then restart the dev server.");r=await le(t,l,n.untracked)}catch(e){r=``,h={...h,warnings:[...h.warnings,`Codex could not generate a commit message: ${$(e)}`]}}A={fingerprint:n.fingerprint,message:r}}h={...h,draft:n,proposal:r}}else if(e.type===`commit`){let t=await _e(e);h={...h,currentCommit:t,draft:void 0,message:void 0,proposal:void 0,target:void 0},I()}else if(e.type===`retry-install`)await W();else if(e.type===`reset-database`)await G();else{let n=z(e.target),r=await P(t);if(r.tracked||r.untracked.length>0){if(!e.fingerprint||!e.untracked)throw Error(`Refresh requires the current working-tree confirmation.`);if(await V(e.fingerprint,e.untracked),!e.message||!te.test(Ee(e.message)))throw Error(`Enter a commit message with a valid Conventional Commits header.`)}await H({fingerprint:e.fingerprint,message:e.message,onCodexEvent:s,source:n.source,target:e.target,untracked:e.untracked})}}finally{v=!1,h={...h,busy:void 0},N(),b&&(b=!1,I())}return o&&await Ae(o,r,i,a),{status:h}},z=e=>{if(!h.target||h.target.commit!==e)throw Error(`The offered update changed. Review the latest target before refreshing.`);return h.target},B=e=>A?.fingerprint===e?A.message:void 0,V=async(e,n)=>{let r=await P(t);if(r.fingerprint!==e)throw A=void 0,Error(`Working-tree changes changed; generate a new commit message.`);if(!we(r.untracked,n))throw Error(`Include every untracked file or remove it before refreshing.`);return r},_e=async({fingerprint:e,message:n,untracked:r})=>{let i=await V(e,r);if(!n||!te.test(Ee(n)))throw Error(`Enter a commit message with a valid Conventional Commits header.`);await X(t,[`add`,`--update`]),i.untracked.length>0&&await X(t,[`add`,`--`,...r]),await X(t,[`commit`,`--message`,n],{env:{GIT_EDITOR:`true`}});let a=await Z(t,[`rev-parse`,`HEAD`]);return x=a,A=void 0,a},H=async({fingerprint:e,message:n,onCodexEvent:r=()=>void 0,source:i,target:a,untracked:o=[]})=>{z(a);let s=await Z(t,[`rev-parse`,`HEAD`]),c,u,d=await P(t);if(d.tracked||d.untracked.length>0){if(!e||d.fingerprint!==e||!we(d.untracked,o))throw Error(`Working-tree changes changed; review them before refreshing.`);await X(t,[`add`,`--update`]),o.length>0&&await X(t,[`add`,`--`,...o]),await X(t,[`commit`,`--message`,n],{env:{GIT_EDITOR:`true`}}),c=await Z(t,[`rev-parse`,`HEAD`]),x=c,u=`refs/coreframe/recovery/${Date.now()}-${c.slice(0,12)}`,await X(t,[`update-ref`,u,c])}let f=c??s,p;try{if(p=await de({cwd:t,env:l,localMain:f,onCodexEvent:r,source:i,target:a}),await Z(t,[`rev-parse`,`HEAD`])!==f)throw Error(`HEAD changed while the accepted update was being prepared.`);if(await Z(t,[`rev-parse`,C])!==f)throw Error(`Local main changed while the accepted update was being prepared.`);await fe(t,p,f),b=!0,x=p.commit,await X(t,[`reset`,`--hard`,p.commit]);let e=Te(await Z(t,[`diff`,`--name-only`,`-z`,s,p.commit]));A=void 0,u&&await X(t,[`update-ref`,`-d`,u]),h={...h,currentCommit:p.commit,draft:void 0,proposal:void 0,setupFailure:void 0,target:void 0},await U({installDependencies:ve(e),restartRequired:ye(e),trigger:`synchronization`})}catch(e){let t=u?` Recovery commit: ${u}.`:``;throw h={...h,currentCommit:x,message:`${$(e)}${t}`},e}},U=async({installDependencies:n,restartRequired:r,trigger:a})=>{let o=x;if(n)try{await q([`install`,`--frozen-lockfile`])}catch(e){await J({command:`pnpm install --frozen-lockfile`,commit:o,error:e,message:`The project was synchronized, but dependency installation failed. Fix the package or lockfile issue, then retry the install.`,restartRequired:r,stage:`dependencies`});return}try{await ge({config:e,cwd:t,env:l})}catch(e){await J({command:`pnpm db migrate`,commit:o,error:e,message:`The project was synchronized, but its database migration failed. The previous database was restored. Reset the database to recreate it, apply migrations, and rerun seed scripts.`,restartRequired:r,stage:`migration`});return}await Y(),L(o,a),r&&i()},W=async()=>{let e=K(`dependencies`);await Y(),await U({installDependencies:!0,restartRequired:e.restartRequired,trigger:`dependency-recovery`})},G=async()=>{let e=K(`migration`);try{await q([`db`,`setup`])}catch(t){await J({command:`pnpm db setup`,commit:e.commit,error:t,message:`The project remains synchronized, but the database reset failed. Review the diagnostics, fix the reported problem, and try the reset again.`,restartRequired:e.restartRequired,stage:`migration`});return}await Y(),L(e.commit,`database-recovery`),e.restartRequired&&i()},K=e=>{if(!h.setupFailure||h.setupFailure.stage!==e)throw Error(`There is no failed ${e} setup step to recover.`);return h.setupFailure},q=async e=>{await m(Oe(),e,{cwd:t,env:l})},J=async({command:e,commit:t,error:n,message:r,restartRequired:i,stage:a})=>{let o=he(n).slice(-1e5),s={command:e,commit:t,message:r,output:o,restartRequired:i,stage:a};h={...h,setupFailure:s,target:void 0},console.error(`Coreframe managed development setup failed (${e}): ${r}\n${o}`);let c=ke();c&&await d(c,`${JSON.stringify(s)}\n`,{mode:384}).catch(e=>{console.warn(`Could not persist the managed-development setup failure: ${$(e)}`)})},Y=async()=>{h={...h,setupFailure:void 0};let e=ke();e&&await u(e).catch(e=>{e instanceof Error&&`code`in e&&e.code===`ENOENT`||console.warn(`Could not clear the managed-development setup failure: ${$(e)}`)})},ke=()=>S?f.join(S.commonDir,ne):void 0,Ae=async(e,t,n,r)=>{let i={commits:n,finalMessage:e,id:y(16).toString(`hex`),messages:ae(t),...r===void 0?void 0:{totalCommits:r}};h={...h,codexCompletion:i},S&&await d(f.join(S.commonDir,T),`${JSON.stringify(i)}\n`,{mode:384}).catch(e=>{console.warn(`Could not persist the managed-development Codex result: ${$(e)}`)}),N()},je=async()=>{h={...h,codexCompletion:void 0},S&&await u(f.join(S.commonDir,T)).catch(e=>{if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e})};return{action:R,activate:pe,getStatus:()=>h,async close(){if(!g){g=!0,clearInterval(D),clearInterval(O),clearTimeout(k);for(let e of ie)e.close();await Se(E)}}}}async function re(e){let t=f.join(e,T);try{let e=JSON.parse(await s(t,`utf8`));if(ie(e))return e}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;console.warn(`Could not read the managed-development Codex result: ${$(e)}`)}await u(t).catch(()=>void 0)}function ie(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.finalMessage==`string`&&typeof t.id==`string`&&Array.isArray(t.messages)&&t.messages.every(j)&&(t.totalCommits===void 0||Number.isInteger(t.totalCommits)&&t.totalCommits>=0)&&(t.commits===void 0||Array.isArray(t.commits)&&t.commits.every(A))}function A(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.commit==`string`&&typeof t.shortCommit==`string`&&typeof t.subject==`string`}function j(e){if(!e||typeof e!=`object`)return!1;let t=e;return(t.kind===`agent`||t.kind===`thought`||t.kind===`user`)&&typeof t.text==`string`}function ae(e){let t=new Set(e.filter(e=>e.kind===`user`)),n=[...t].reduce((e,t)=>e+t.text.length,0),r=!1;for(let i of[...e].reverse())if(i.kind!==`user`){if(n+i.text.length>1e5&&r)break;t.add(i),r=!0,n+=i.text.length}return e.filter(e=>t.has(e))}async function oe(e,t){let n=f.join(e,ne);try{let e=JSON.parse(await s(n,`utf8`));if(M(e)&&e.commit===t)return e}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;console.warn(`Could not read the managed-development setup failure: ${$(e)}`)}await u(n).catch(()=>void 0)}function M(e){if(!e||typeof e!=`object`)return!1;let t=e;return(t.command===`pnpm db migrate`||t.command===`pnpm db setup`||t.command===`pnpm install --frozen-lockfile`)&&typeof t.commit==`string`&&typeof t.message==`string`&&typeof t.output==`string`&&typeof t.restartRequired==`boolean`&&(t.stage===`dependencies`||t.stage===`migration`)}async function se(e){let t=await O(e);return{branch:N(await Z(e,[`rev-parse`,`--abbrev-ref`,`HEAD`])),commonDir:t.commonDir,gitDir:t.gitDir,head:await Z(e,[`rev-parse`,`HEAD`]),main:await Z(e,[`rev-parse`,C]),primary:t.primary}}function N(e){return e===`HEAD`?void 0:e}async function ce(e,t){let n=[e.gitDir,f.join(e.commonDir,`refs`,`heads`)],r=[];for(let e of n)try{r.push(_(e,{persistent:!1},t))}catch{}return r}async function P(e){let[t,n,r]=await Promise.all([Z(e,[`status`,`--porcelain`,`--untracked-files=no`]),Z(e,[`diff`,`HEAD`,`--binary`]),Z(e,[`ls-files`,`--others`,`--exclude-standard`,`-z`])]),i=Te(r).sort(),a=v(`sha256`).update(n);for(let e of i)a.update(`\0`).update(e);return{fingerprint:a.digest(`hex`),tracked:t.length>0,untracked:i}}async function le(t,n,r){let i=[`Tracked changes:`,await Z(t,[`diff`,`HEAD`,`--binary`])];for(let e of r){let n=await s(f.join(t,e));i.push(`\nUntracked file: ${e}\n`,n.toString(`utf8`))}let{stdout:a}=await m(`codex`,[`exec`,...e,`--ephemeral`,`--ignore-user-config`,`--sandbox`,`read-only`,`--cd`,t,`Return only a concise Conventional Commits message for the supplied working-tree changes. Use a body only when it adds material context.`],{cwd:t,env:n,stderr:`ignore`,stdin:{string:i.join(`
2
+ `)}});return a.trim().replace(/^```(?:text)?\s*|\s*```$/g,``)}async function ue(e,t){let r=t.PATH??t.Path??t.path??``,i=p.platform===`win32`?(t.PATHEXT??`.COM;.EXE;.BAT;.CMD`).split(`;`):[``];for(let t of r.split(f.delimiter))for(let r of i)try{return await n(f.join(t||`.`,`${e}${r}`),g.X_OK),!0}catch{}return!1}async function de({cwd:e,env:t,localMain:n,onCodexEvent:r,source:a,target:o}){if(a===`dev`&&await Ce(e,n,o))return{commit:o,devTarget:o};let s=f.resolve(e,await Z(e,[`rev-parse`,`--git-common-dir`])),c=f.join(s,`coreframe-managed-dev`);await i(c,{recursive:!0});let u=y(8).toString(`hex`),d=f.join(c,`integration-${u}`);try{if(await X(e,[`worktree`,`add`,`--detach`,d,n]),n!==o)if(a===`dev`)await F(d,t,[`merge`,`--no-edit`,`--no-ff`,`--allow-unrelated-histories`,`--message`,`Merge dev into main`,o],`merge`,r);else{let e=await Q(d,[`merge-base`,n,o]),i=Number(await Z(d,[`rev-list`,`--count`,e?`${e}..HEAD`:`HEAD`]));await F(d,t,e?[`rebase`,`--onto`,o,e]:[`rebase`,`--root`,`--onto`,o],`rebase`,r,o,i)}return{commit:await Z(d,[`rev-parse`,`HEAD`]),devTarget:a===`dev`?o:void 0}}finally{await X(e,[`worktree`,`remove`,`--force`,d]).catch(()=>void 0),await l(d,{force:!0,recursive:!0})}}async function fe(e,t,n){let r=async r=>{let i=[`start`,`update ${C} ${t.commit} ${n}`];r&&t.devTarget&&i.push(t.devTarget===t.commit?`verify ${w} ${t.devTarget}`:`update ${w} ${t.commit} ${t.devTarget}`),i.push(`prepare`,`commit`),await m(`git`,[`update-ref`,`--stdin`],{cwd:e,stdin:{string:`${i.join(`
3
+ `)}\n`}})};try{await r(!0)}catch(i){if(!t.devTarget)throw i;let a;try{a=await Promise.all([Z(e,[`rev-parse`,C]),Q(e,[`rev-parse`,w])])}catch{throw i}let[o,s]=a;if(o!==n||s===t.devTarget)throw i;await r(!1)}}async function F(e,t,n,r,i,a,o=0){try{await X(e,n,{env:{GIT_EDITOR:`true`}});return}catch(n){let s=await z(e);if(s.length===0)throw n;try{for(;s.length>0;){await I(e,t,r,s,a?await L(e,a):[],o,i),await X(e,[`diff`,`--check`]),await X(e,[`add`,`--all`]);let n=await z(e);if(n.length>0)throw Error(`Codex left unresolved paths: ${n.join(`, `)}`);try{await X(e,[r,`--continue`],{env:{GIT_EDITOR:`true`}})}catch(t){if(s=await z(e),s.length===0)throw t;i({commits:a?await L(e,a):[],phase:`progress`,totalCommits:o});continue}i({commits:a?await L(e,a):[],phase:`progress`,totalCommits:o}),s=await z(e)}return}catch(t){throw await X(e,[r,`--abort`]).catch(()=>void 0),Error(`Codex could not resolve ${r} conflicts: ${$(t)}`)}}}async function I(e,n,r,i,a,o,s){let c=`Resolve the current Git ${r} conflicts cleanly. Edit only files needed for the resolution, preserve intended behavior from both sides, and remove all conflict markers. Do not run pnpm test or any other test suite; managed development will run pnpm test after you finish and report any failures. You may run pnpm typecheck and pnpm format if useful. Do not stage files or run Git continuation commands. Conflicted paths: ${i.join(`, `)}`;s({commits:a,message:{kind:`user`,text:c},phase:`start`,totalCommits:o});let l=m(`codex`,[`exec`,...t,`--ephemeral`,`--ignore-user-config`,`--json`,`--sandbox`,`workspace-write`,`--cd`,e,c],{cwd:e,env:n,stdin:`ignore`}),u=``,d=[];try{await Promise.all([R(l.stdout,e=>{let t=pe(e);t&&(t.kind===`agent`&&(u=t.text),s({message:t,phase:`message`}))}),R(l.stderr,e=>d.push(e))])}catch(e){s({phase:`error`});let t=d.join(`
4
+ `).trim();throw t?Error(`${$(e)}\n${t}`):e}s({finalMessage:u||`Codex resolved the conflicts.`,phase:`complete`})}async function L(e,t){let n=await Z(e,[`log`,`--reverse`,`--format=%H%x00%s`,`${t}..HEAD`]);return n?n.split(`
5
5
  `).map(e=>{let[t,n=``]=e.split(`\0`,2);return{commit:t,shortCommit:t.slice(0,12),subject:n}}):[]}function pe(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Codex emitted invalid JSONL output.`)}if(!t||typeof t!=`object`)return;let n=t.item;if(t.type!==`item.completed`||!n||typeof n!=`object`)return;let{text:r,type:i}=n;if(!(typeof r!=`string`||!r.trim())){if(i===`reasoning`)return{kind:`thought`,text:r};if(i===`agent_message`)return{kind:`agent`,text:r}}}async function R(e,t){for await(let n of e)t(n)}async function z(e){return Te(await Z(e,[`diff`,`--name-only`,`--diff-filter=U`,`-z`]))}async function me(e,t,n){await m(Oe(),[n],{cwd:e,env:t})}function he(e){let t=B(e);if(t){let e=x(t).trim();if(e)return e}return x($(e))}function B(e){if(typeof e!=`object`||!e)return;let t=e;if(typeof t.output==`string`&&t.output.trim())return t.output;let n=[t.stdout,t.stderr].filter(e=>typeof e==`string`&&e.length>0);return n.length>0?n.join(`
6
- `):void 0}async function ge({config:e,cwd:t,env:n}){if(!e.database)return;let r=await V({config:e,cwd:t,env:n});try{await m(Oe(),[`db`,`migrate`],{cwd:t,env:n})}catch(e){throw await r.restore(),e}await r.discard().catch(e=>{console.warn(`Could not remove the managed-development database snapshot: ${$(e)}`)}),await l(r.directory,{force:!0,recursive:!0})}async function V({config:e,cwd:t,env:n}){let o=f.join(t,`.coreframe`,`managed-dev-backups`);await i(o,{recursive:!0});let s=await a(f.join(o,`refresh-`));if(e.database?.dialect===`sqlite`){let e=[`turso.db`,`turso.db-wal`,`turso.db-shm`],n=new Set;for(let r of e)await _e(f.join(t,`.coreframe`,r),f.join(s,r))&&n.add(r);return{directory:s,async discard(){},async restore(){for(let i of e){let e=f.join(t,`.coreframe`,i);n.has(i)?await r(f.join(s,i),e):await l(e,{force:!0})}}}}if(!n.DATABASE_URL)throw Error(`DATABASE_URL is required to snapshot local PostgreSQL.`);let c=await H(t);if(c)return U({directory:s,connectionString:n.DATABASE_URL,postgres:c});let u=f.join(s,`database.dump`),d=J(n,n.DATABASE_URL);return await m(`pg_dump`,[`--format=custom`,`--file`,u],{cwd:t,env:d,stdin:`ignore`}),{directory:s,async discard(){},async restore(){await m(`pg_restore`,[`--clean`,`--if-exists`,`--no-owner`,`--dbname`,d.PGDATABASE,u],{cwd:t,env:d,stdin:`ignore`})}}}async function _e(e,t){try{return await r(e,t),!0}catch(e){if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e;return!1}}async function H(e){let t=JSON.parse(await s(f.join(e,`package.json`),`utf8`));if(!(!t.dependencies?.pg&&!t.devDependencies?.pg&&!t.optionalDependencies?.pg))try{return await import(S(`pg`,b(f.join(e,`package.json`)).href))}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ERR_MODULE_NOT_FOUND`)return;throw e}}async function U({directory:e,connectionString:t,postgres:n}){let r=new URL(t),i=decodeURIComponent(r.pathname.slice(1));if(!i)throw Error(`DATABASE_URL must name a PostgreSQL database to snapshot.`);let a=`coreframe_backup_${y(6).toString(`hex`)}`,o=`${a}_failed`,s=new URL(r);s.pathname=i===`postgres`?`/template1`:`/postgres`;let c=new n.Client({connectionString:s.href});await c.connect();try{await G(c,i,!1),await K(c,i),await c.query(`CREATE DATABASE ${q(a)} WITH TEMPLATE ${q(i)}`),await G(c,a,!0)}finally{await G(c,i,!0).catch(()=>void 0),await c.end()}return{directory:e,async discard(){await W(n,s.href,async e=>{await K(e,a),await e.query(`DROP DATABASE ${q(a)}`)})},async restore(){await W(n,s.href,async e=>{await G(e,i,!1),await K(e,i),await e.query(`ALTER DATABASE ${q(i)} RENAME TO ${q(o)}`);try{await e.query(`ALTER DATABASE ${q(a)} RENAME TO ${q(i)}`)}catch(t){throw await e.query(`ALTER DATABASE ${q(o)} RENAME TO ${q(i)}`).catch(()=>void 0),await G(e,i,!0).catch(()=>void 0),t}await K(e,o),await e.query(`DROP DATABASE ${q(o)}`)})}}}async function W(e,t,n){let r=new e.Client({connectionString:t});await r.connect();try{return await n(r)}finally{await r.end()}}async function G(e,t,n){await e.query(`ALTER DATABASE ${q(t)} ALLOW_CONNECTIONS ${n?`true`:`false`}`)}async function K(e,t){await e.query(`SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`,[t])}function q(e){return`"${e.replaceAll(`"`,`""`)}"`}function J(e,t){let n=new URL(t);return{...e,PGDATABASE:decodeURIComponent(n.pathname.slice(1)),PGHOST:n.hostname,PGPASSWORD:decodeURIComponent(n.password),PGPORT:n.port||`5432`,PGUSER:decodeURIComponent(n.username)}}function ve(e){return e.some(e=>f.basename(e)===`package.json`||f.basename(e).endsWith(`lock.yaml`)||f.basename(e)===`pnpm-workspace.yaml`)}function ye(e){return e.some(e=>ve([e])||/(^|\/)(vite|coreframe|tsconfig|drizzle)\.[^/]+$/.test(e)||/(^|\/)(drizzle|scripts|src\/api|tauri)(\/|$)/.test(e))}async function be(e,t,n){return{commit:t,shortCommit:t.slice(0,12),source:n,subject:await Z(e,[`show`,`-s`,`--format=%s`,t])}}async function xe(e){try{let t=await o(e,`wx`);await t.writeFile(`${p.pid}\n`),await t.close()}catch(t){if(!(t instanceof Error&&`code`in t&&t.code===`EEXIST`))throw t;let n=(await s(e,`utf8`).catch(()=>`unknown`)).trim(),r=Number(n);if(Number.isInteger(r)&&!Y(r)){await u(e).catch(()=>void 0),await xe(e);return}throw Error(`Managed development is already owned by PID ${n}.`)}}function Y(e){try{return p.kill(e,0),!0}catch(e){return!(e instanceof Error&&`code`in e&&e.code===`ESRCH`)}}async function Se(e){e&&(await s(e,`utf8`).catch(()=>void 0))?.trim()===String(p.pid)&&await u(e).catch(()=>void 0)}async function X(e,t,{env:n}={}){return m(`git`,t,{cwd:e,env:n,stdin:`ignore`})}async function Z(e,t){return(await X(e,t)).stdout.trim()}async function Q(e,t){try{return await Z(e,t)||void 0}catch(e){if(e instanceof h&&e.exitCode&&e.exitCode>0)return;throw e}}async function Ce(e,t,n){try{return await X(e,[`merge-base`,`--is-ancestor`,t,n]),!0}catch(e){if(e instanceof h&&e.exitCode===1)return!1;throw e}}function we(e,t){return e.length===t.length&&[...e].sort().every((e,n)=>e===[...t].sort()[n])}function Te(e){return e.split(`\0`).filter(Boolean)}function Ee(e){return e.split(/\r?\n/,1)[0]??``}function De(e){return e.type===`acknowledge-codex`?`Acknowledging Codex result`:e.type===`dismiss-check`?`Dismissing managed development check`:e.type===`message`?`Generating commit message`:e.type===`commit`?`Committing local changes`:e.type===`apply`?`Integrating accepted update`:e.type===`prepare`?`Reviewing working tree`:e.type===`retry-install`?`Retrying dependency installation`:e.type===`reset-database`?`Resetting local database`:`Aborting refresh`}function Oe(){return p.platform===`win32`?`pnpm.cmd`:`pnpm`}function $(e){return e instanceof Error?e.message:String(e)}export{E as isManagedDevCheckout,D as isPrimaryCheckout,k as startManagedDevSession};
6
+ `):void 0}async function ge({config:e,cwd:t,env:n}){if(!e.database)return;let r=await V({config:e,cwd:t,env:n});try{await m(Oe(),[`db`,`migrate`],{cwd:t,env:n})}catch(e){throw await r.restore(),e}await r.discard().catch(e=>{console.warn(`Could not remove the managed-development database snapshot: ${$(e)}`)}),await l(r.directory,{force:!0,recursive:!0})}async function V({config:e,cwd:t,env:n}){let o=f.join(t,`.coreframe`,`managed-dev-backups`);await i(o,{recursive:!0});let s=await a(f.join(o,`refresh-`));if(e.database?.dialect===`sqlite`){let e=[`turso.db`,`turso.db-wal`,`turso.db-shm`],n=new Set;for(let r of e)await _e(f.join(t,`.coreframe`,r),f.join(s,r))&&n.add(r);return{directory:s,async discard(){},async restore(){for(let i of e){let e=f.join(t,`.coreframe`,i);n.has(i)?await r(f.join(s,i),e):await l(e,{force:!0})}}}}if(!n.DATABASE_URL)throw Error(`DATABASE_URL is required to snapshot local PostgreSQL.`);let c=await H(t);if(c)return U({directory:s,connectionString:n.DATABASE_URL,postgres:c});let u=f.join(s,`database.dump`),d=J(n,n.DATABASE_URL);return await m(`pg_dump`,[`--format=custom`,`--file`,u],{cwd:t,env:d,stdin:`ignore`}),{directory:s,async discard(){},async restore(){await m(`pg_restore`,[`--clean`,`--if-exists`,`--no-owner`,`--dbname`,d.PGDATABASE,u],{cwd:t,env:d,stdin:`ignore`})}}}async function _e(e,t){try{return await r(e,t),!0}catch(e){if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e;return!1}}async function H(e){let t=JSON.parse(await s(f.join(e,`package.json`),`utf8`));if(!(!t.dependencies?.pg&&!t.devDependencies?.pg&&!t.optionalDependencies?.pg))try{return await import(S(`pg`,b(f.join(e,`package.json`)).href))}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ERR_MODULE_NOT_FOUND`)return;throw e}}async function U({directory:e,connectionString:t,postgres:n}){let r=new URL(t),i=decodeURIComponent(r.pathname.slice(1));if(!i)throw Error(`DATABASE_URL must name a PostgreSQL database to snapshot.`);let a=`coreframe_backup_${y(6).toString(`hex`)}`,o=`${a}_failed`,s=new URL(r);s.pathname=i===`postgres`?`/template1`:`/postgres`;let c=new n.Client({connectionString:s.href});await c.connect();try{await G(c,i,!1),await K(c,i),await c.query(`CREATE DATABASE ${q(a)} WITH TEMPLATE ${q(i)}`),await G(c,a,!0)}finally{await G(c,i,!0).catch(()=>void 0),await c.end()}return{directory:e,async discard(){await W(n,s.href,async e=>{await K(e,a),await e.query(`DROP DATABASE ${q(a)}`)})},async restore(){await W(n,s.href,async e=>{await G(e,i,!1),await K(e,i),await e.query(`ALTER DATABASE ${q(i)} RENAME TO ${q(o)}`);try{await e.query(`ALTER DATABASE ${q(a)} RENAME TO ${q(i)}`)}catch(t){throw await e.query(`ALTER DATABASE ${q(o)} RENAME TO ${q(i)}`).catch(()=>void 0),await G(e,i,!0).catch(()=>void 0),t}await K(e,o),await e.query(`DROP DATABASE ${q(o)}`)})}}}async function W(e,t,n){let r=new e.Client({connectionString:t});await r.connect();try{return await n(r)}finally{await r.end()}}async function G(e,t,n){await e.query(`ALTER DATABASE ${q(t)} ALLOW_CONNECTIONS ${n?`true`:`false`}`)}async function K(e,t){await e.query(`SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`,[t])}function q(e){return`"${e.replaceAll(`"`,`""`)}"`}function J(e,t){let n=new URL(t);return{...e,PGDATABASE:decodeURIComponent(n.pathname.slice(1)),PGHOST:n.hostname,PGPASSWORD:decodeURIComponent(n.password),PGPORT:n.port||`5432`,PGUSER:decodeURIComponent(n.username)}}function ve(e){return e.some(e=>f.basename(e)===`package.json`||f.basename(e).endsWith(`lock.yaml`)||f.basename(e)===`pnpm-workspace.yaml`)}function ye(e){return e.some(e=>ve([e])||/(^|\/)(vite|coreframe|tsconfig|drizzle)\.[^/]+$/.test(e)||/(^|\/)(drizzle|scripts|src\/api|tauri)(\/|$)/.test(e))}async function be(e,t,n,r){return{commit:n,commits:(await Z(e,[`log`,`--reverse`,`--format=%H%x00%s`,`${t}..${n}`])).split(`
7
+ `).filter(Boolean).map(e=>{let[t,n]=e.split(`\0`);return{commit:t,shortCommit:t.slice(0,12),subject:n}}),shortCommit:n.slice(0,12),source:r,subject:await Z(e,[`show`,`-s`,`--format=%s`,n])}}async function xe(e){try{let t=await o(e,`wx`);await t.writeFile(`${p.pid}\n`),await t.close()}catch(t){if(!(t instanceof Error&&`code`in t&&t.code===`EEXIST`))throw t;let n=(await s(e,`utf8`).catch(()=>`unknown`)).trim(),r=Number(n);if(Number.isInteger(r)&&!Y(r)){await u(e).catch(()=>void 0),await xe(e);return}throw Error(`Managed development is already owned by PID ${n}.`)}}function Y(e){try{return p.kill(e,0),!0}catch(e){return!(e instanceof Error&&`code`in e&&e.code===`ESRCH`)}}async function Se(e){e&&(await s(e,`utf8`).catch(()=>void 0))?.trim()===String(p.pid)&&await u(e).catch(()=>void 0)}async function X(e,t,{env:n}={}){return m(`git`,t,{cwd:e,env:n,stdin:`ignore`})}async function Z(e,t){return(await X(e,t)).stdout.trim()}async function Q(e,t){try{return await Z(e,t)||void 0}catch(e){if(e instanceof h&&e.exitCode&&e.exitCode>0)return;throw e}}async function Ce(e,t,n){try{return await X(e,[`merge-base`,`--is-ancestor`,t,n]),!0}catch(e){if(e instanceof h&&e.exitCode===1)return!1;throw e}}function we(e,t){return e.length===t.length&&[...e].sort().every((e,n)=>e===[...t].sort()[n])}function Te(e){return e.split(`\0`).filter(Boolean)}function Ee(e){return e.split(/\r?\n/,1)[0]??``}function De(e){return e.type===`acknowledge-codex`?`Acknowledging Codex result`:e.type===`dismiss-check`?`Dismissing managed development check`:e.type===`message`?`Generating commit message`:e.type===`commit`?`Committing local changes`:e.type===`apply`?`Integrating accepted update`:e.type===`prepare`?`Reviewing working tree`:e.type===`retry-install`?`Retrying dependency installation`:e.type===`reset-database`?`Resetting local database`:`Aborting refresh`}function Oe(){return p.platform===`win32`?`pnpm.cmd`:`pnpm`}function $(e){return e instanceof Error?e.message:String(e)}export{E as isManagedDevCheckout,D as isPrimaryCheckout,k as startManagedDevSession};
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@coreframe/dev",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
+ "description": "Development workflow utilities for Coreframe apps",
4
5
  "repository": {
5
6
  "type": "git",
6
7
  "url": "git+https://github.com/airlock-labs/coreframe.git",
@@ -39,10 +40,10 @@
39
40
  "dependencies": {
40
41
  "import-meta-resolve": "^4.2.0",
41
42
  "nano-spawn": "^2.1.0",
42
- "@coreframe/config": "^0.1.0",
43
- "@coreframe/db": "^0.1.0",
44
- "@coreframe/dev-contracts": "^0.1.0",
45
- "@coreframe/dev-supervisor": "^0.1.0"
43
+ "@coreframe/db": "^0.1.2",
44
+ "@coreframe/dev-contracts": "^0.1.1",
45
+ "@coreframe/config": "^0.1.2",
46
+ "@coreframe/dev-supervisor": "^0.1.2"
46
47
  },
47
48
  "devDependencies": {
48
49
  "@types/node": "^26.1.0",