gestalt-mobile 0.41.1 → 0.41.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.
@@ -20,7 +20,7 @@ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=
20
20
  destinations.</p></div> <!> <button id="browse-files" type="button">Browse files</button></section> <form class="clone-form svelte-pudr3t"><div class="clone-controls svelte-pudr3t"><div class="clone-field clone-destination svelte-pudr3t"><span class="field-label svelte-pudr3t">Destination</span> <output aria-live="polite" class="svelte-pudr3t"> </output></div> <div class="clone-field svelte-pudr3t"><label for="git-clone-address">Git address</label> <input id="git-clone-address" name="address" required="" autocomplete="url" inputmode="url" enterkeyhint="done" placeholder="https://example.com/owner/repository.git" aria-describedby="clone-help"/></div> <button type="submit" class="svelte-pudr3t"> </button></div> <p id="clone-help" class="svelte-pudr3t">The repository is cloned inside the selected workspace.</p> <!></form> <section class="repository-details svelte-pudr3t" aria-labelledby="repository-details-title"><h3 id="repository-details-title" class="svelte-pudr3t">Repository details</h3> <!> <!></section></section>`);function Lu(e,t){Qe(t,!0);let n=I(``),r=P(()=>t.selectedWorkspace&&!t.selectedWorkspace.isGitRepository?t.selectedWorkspace:null);function i(e){e.preventDefault(),!(!G(n).trim()||t.cloning)&&t.onclone(G(n).trim())}var a=Iu(),o=V(z(a),2),s=V(z(o),2);{let e=P(()=>t.selectedWorkspace?.id??null);bu(s,{get roots(){return t.workspaceTree},get expandedIds(){return t.expandedIds},get selectedId(){return G(e)},label:`Git repository and clone destination`,get onexpandedchange(){return t.onexpandedchange},get onselect(){return t.onselect}})}var c=V(s,2);N(o);var l=V(o,2),u=z(l),d=z(u),f=V(z(d),2),p=z(f,!0);N(f),N(d);var m=V(d,2),h=V(z(m),2);Di(h),N(m);var g=V(m,2),_=z(g,!0);N(g),N(u);var v=V(u,4),y=e=>{var n=Tu(),r=z(n,!0);N(n),H(()=>Y(r,t.cloneStatus)),J(e,n)};X(v,e=>{t.cloneStatus&&e(y)}),N(l);var b=V(l,2),x=V(z(b),2),S=e=>{var n=Hr(),r=B(n),i=e=>{var n=Hr(),r=B(n),i=e=>{var n=Au(),r=B(n),i=z(r),a=V(z(i),2);Z(a,20,()=>t.summary.branches??[],e=>e,(e,t)=>{var n=Eu(),r=z(n,!0);N(n);var i={};H(()=>{Y(r,t),i!==(i=t)&&(n.value=(n.__value=t)??``)}),J(e,n)}),N(a);var o;bi(a);var s=V(a,2),c=z(s);N(s);var l=V(s,2),u=z(l);N(l);var d=V(l,2),f=z(d),p=z(f,!0);N(f),N(d);var m=V(d,2),h=z(m);N(m),N(i);var g=V(i,2),_=z(g),v=V(_,2),y=V(z(v));N(v),N(g),N(r);var b=V(r,2),x=e=>{var n=Du(),r=z(n),i=z(r);N(r);var a=V(r,2),o=V(a,2);N(n),H(()=>Y(i,`Push HEAD to ${t.summary.upstream??``}?`)),K(`click`,a,function(...e){t.onpush?.apply(this,e)}),K(`click`,o,function(...e){t.oncancelpush?.apply(this,e)}),J(e,n)};X(b,e=>{t.confirmingPush&&e(x)});var S=V(b,2),C=e=>{var n=ku(),r=V(z(n),2);Z(r,21,()=>t.summary.commits,e=>e.hash,(e,t)=>{var n=Ou(),r=z(n),i=z(r),a=z(i,!0);N(i);var o=V(i),s=z(o,!0);N(o),N(r);var c=V(r,2),l=z(c),u=z(l,!0);N(l);var d=V(l),f=z(d,!0);N(d),N(c),N(n),H(e=>{Q(i,`title`,G(t).hash),Y(a,G(t).shortHash),Y(s,G(t).subject),Y(u,G(t).author),Q(d,`datetime`,G(t).authoredAt),Q(d,`title`,G(t).authoredAt),Y(f,e)},[()=>wu(G(t).authoredAt)]),J(e,n)}),N(r),N(n),J(e,n)};X(S,e=>{t.summary.commits.length&&e(C)}),H(e=>{a.disabled=t.refreshing||t.checkingOut||!t.summary.branches?.length,o!==(o=t.summary.branch??``)&&(a.value=(a.__value=t.summary.branch??``)??``,yi(a,t.summary.branch??``)),Y(c,`Upstream: ${t.summary.upstream??`none`??``}`),Y(u,`Ahead ${t.summary.ahead??``}; behind ${t.summary.behind??``}.`),Q(f,`datetime`,t.summary.fetchedAt??void 0),Y(p,e),Y(h,`Changes: ${t.summary.dirty.staged??``} staged, ${t.summary.dirty.unstaged??``} unstaged, ${t.summary.dirty.untracked??``} untracked.`),_.disabled=t.refreshing||t.checkingOut||!t.summary.upstream||t.summary.ahead<1||t.summary.behind>0,v.disabled=t.refreshing||t.checkingOut,Y(y,` ${t.refreshing?`Pulling…`:`Pull`}`)},[()=>Cu(t.summary.fetchedAt)]),K(`change`,a,e=>t.oncheckout(e.currentTarget.value)),K(`click`,_,function(...e){t.onopenpushconfirmation?.apply(this,e)}),K(`click`,v,function(...e){t.onpull?.apply(this,e)}),J(e,n)},a=e=>{J(e,ju())};X(r,e=>{t.summary.available?e(i):e(a,-1)}),J(e,n)},a=e=>{J(e,Mu())};X(r,e=>{t.summary?e(i):t.error||e(a,1)}),J(e,n)},C=e=>{var n=Nu(),r=B(n),i=z(r),a=z(i,!0);N(i),He(),N(r),He(2),H(()=>Y(a,t.selectedWorkspace.name)),J(e,n)},w=e=>{var t=Pu();He(2),J(e,t)};X(x,e=>{t.selectedWorkspace?.isGitRepository?e(S):t.selectedWorkspace?e(C,1):e(w,-1)});var T=V(x,2),E=e=>{var n=Fu(),r=z(n,!0);N(n),H(()=>Y(r,t.error)),J(e,n)};X(T,e=>{t.error&&e(E)}),N(b),N(a),H(()=>{c.disabled=!t.selectedWorkspace,Y(p,G(r)?`~/${G(r).relativePath}`:`Select a non-repository folder`),g.disabled=t.cloning,Y(_,t.cloning?`Cloning…`:`Clone`)}),K(`click`,c,e=>t.onbrowsefiles(e.currentTarget)),Nr(`submit`,l,i),Ni(h,()=>G(n),e=>L(n,e)),J(e,a),$e()}Pr([`click`,`change`]);var Ru=class{transport;isRepository;onChange;errorMessage;#e={workspaceId:null,summary:null,loading:!1,refreshing:!1,checkingOut:!1,error:null};#t=0;#n=null;#r=!1;constructor(e,t,n,r){this.transport=e,this.isRepository=t,this.onChange=n,this.errorMessage=r}get state(){return this.#e}select(e){this.#a();let t=e,n=!!(t&&this.isRepository(t));this.#s({workspaceId:t,summary:null,loading:n,refreshing:!1,checkingOut:!1,error:null}),n&&this.refresh()}async refresh(){let e=this.#e.workspaceId;if(!e||!this.isRepository(e))return;let t=this.#i(),n=this.#t;this.#s({...this.#e,loading:!0,error:null});try{let r=await this.transport.getSummary(e,t.signal);this.#o(n,e,t)&&this.#s({...this.#e,summary:r,loading:!1})}catch(r){this.#o(n,e,t)&&!t.signal.aborted&&this.#s({...this.#e,summary:null,loading:!1,error:this.errorMessage(r,`GIT_SUMMARY_FAILED`)})}}async pull(e){let t=this.#e.workspaceId;if(!t||this.#e.refreshing)return;let n=this.#i(),r=this.#t;this.#s({...this.#e,refreshing:!0,error:null});try{await this.transport.pull(t,e,n.signal),this.#o(r,t,n)&&(this.#s({...this.#e,refreshing:!1}),await this.refresh())}catch(e){this.#o(r,t,n)&&!n.signal.aborted&&this.#s({...this.#e,refreshing:!1,error:this.errorMessage(e,`GIT_PULL_FAILED`)})}}async checkout(e){let t=this.#e.workspaceId;if(!t||this.#e.checkingOut||e===this.#e.summary?.branch)return;let n=this.#i(),r=this.#t;this.#s({...this.#e,checkingOut:!0,error:null});try{await this.transport.checkout(t,e,n.signal),this.#o(r,t,n)&&(this.#s({...this.#e,checkingOut:!1}),await this.refresh())}catch(e){this.#o(r,t,n)&&!n.signal.aborted&&this.#s({...this.#e,checkingOut:!1,error:this.errorMessage(e,`GIT_CHECKOUT_FAILED`)})}}dispose(){this.#r=!0,this.#a()}#i(){return this.#a(),this.#n=new AbortController,++this.#t,this.#n}#a(){this.#n?.abort(),this.#n=null,++this.#t}#o(e,t,n){return!this.#r&&e===this.#t&&this.#e.workspaceId===t&&this.#n===n}#s(e){this.#r||(this.#e=e,this.onChange(e))}};function zu(e,t,n,r,i){let a=new Set(Bu(e).filter(e=>e.isGitRepository).map(e=>e.id)),o=fu(t,n),s=o?Bu(o.children).filter(e=>e.isGitRepository&&!a.has(e.id)):[],c=Vu(r),l=s.find(e=>e.name===c)??(s.length===1?s[0]:void 0),u=l?.id??o?.id??null,d=new Set(i);return u&&du(t,u).forEach(e=>d.add(e)),!l&&o&&d.add(o.id),{selectedId:u,expandedIds:d}}function Bu(e){let t=[],n=e=>{t.push(e),e.children.forEach(n)};return e.forEach(n),t}function Vu(e){return(e.trim().replace(/[?#].*$/,``).replace(/\/+$/,``).split(/[/:]/).at(-1)??``).replace(/\.git$/i,``)}function Hu(e){if(typeof e!=`object`||!e)return null;let t=e.permissions;if(typeof t!=`object`||!t)return null;let n=t;return{permissions:{...n.network===null||n.network===void 0?{}:{network:n.network},...n.fileSystem===null||n.fileSystem===void 0?{}:{fileSystem:n.fileSystem}},scope:`turn`}}function Uu(e){return{answers:Object.fromEntries(e.filter(e=>e.answer.trim()).map(e=>[e.id,{answers:[e.answer]}]))}}function Wu(e){return[`Submitted quiz answers:`,...e.map(e=>`- ${e.header} — ${e.question}\n ${e.answer.trim().replaceAll(`
21
21
  `,`
22
22
  `)}`)].join(`
23
- `)}function Gu(e=fetch){async function t(e){let t=await e.json().catch(()=>null),n=typeof t?.code==`string`&&/^[A-Z0-9_]+$/.test(t.code)?t.code:void 0,r=n?.startsWith(`AUTOPILOT_`)&&e.status===409?`Relay request failed (${e.status}).`:typeof t?.detail==`string`&&t.detail.length<=600?t.detail:typeof t?.title==`string`?t.title:`Relay request failed (${e.status}).`;return Object.assign(Error(r),{...n?{code:n}:{},...typeof t?.replaceAllowed==`boolean`?{replaceAllowed:t.replaceAllowed}:{},status:e.status})}async function n(n,r,i={},a){let o=await e(n,{method:`POST`,headers:{"content-type":`application/json`,...i},body:JSON.stringify(r),signal:a});if(!o.ok)throw await t(o);return o.json()}async function r(n,r,i={}){let a=await e(n,{method:`PUT`,headers:{"content-type":`application/json`,...i},body:JSON.stringify(r)});if(!a.ok)throw await t(a);return a.json()}async function i(n,r,i,a){let o=await e(n,{method:`PUT`,headers:{"content-type":`application/octet-stream`,"idempotency-key":i},body:r,signal:a});if(!o.ok)throw await t(o);return o.json()}async function a(n,r,i){let a=await e(n,{method:`DELETE`,headers:{"content-type":`application/json`,"idempotency-key":i},body:JSON.stringify(r)});if(!a.ok)throw await t(a);return a.json()}async function o(n){let r=await e(n,{method:`DELETE`});if(!r.ok)throw await t(r)}async function s(n,r){let i=await e(n,r?{signal:r}:void 0);if(!i.ok)throw await t(i);return i.json()}async function c(n,r){let i=await e(n,{signal:r});if(i.status===204)return null;if(!i.ok)throw await t(i);return i.json()}return{quit:()=>n(`/api/maintenance/quit`,{}),listSessions:e=>s(`/api/sessions`,e),listWorkspaceDirectory:(e,t={},n)=>{let r=new URLSearchParams;t.directory!==void 0&&r.set(`directory`,t.directory),t.cursor!==void 0&&r.set(`cursor`,t.cursor),t.limit!==void 0&&r.set(`limit`,String(t.limit));let i=r.size===0?``:`?${r}`;return s(`/api/workspaces/${encodeURIComponent(e)}/files${i}`,n)},copyWorkspaceEntry:(e,t,r)=>n(`/api/workspaces/${encodeURIComponent(e)}/files/copy`,t,{"idempotency-key":r}),moveWorkspaceEntry:(e,t,r)=>n(`/api/workspaces/${encodeURIComponent(e)}/files/move`,t,{"idempotency-key":r}),uploadWorkspaceFile:(e,t,n,r)=>{let a=new URLSearchParams({directory:t.directory,filename:t.filename,conflict:t.conflict});return i(`/api/workspaces/${encodeURIComponent(e)}/files/upload?${a}`,t.file,n,r)},deleteWorkspaceEntry:(e,t,n)=>a(`/api/workspaces/${encodeURIComponent(e)}/files`,{path:t,recursive:!0},n),getSession:e=>s(`/api/sessions/${encodeURIComponent(e)}`),refreshActivity:e=>n(`/api/sessions/${encodeURIComponent(e)}/activity/refresh`,{}),setAutopilot:(e,t,n)=>r(`/api/sessions/${encodeURIComponent(e)}/autopilot`,{enabled:t},n?{"idempotency-key":n}:{}),resolveAttention:(e,t,r)=>n(`/api/sessions/${encodeURIComponent(e)}/attention/${encodeURIComponent(t)}/resolve`,r),listRecentSessions:()=>s(`/api/sessions/recent-threads`),openRecentSession:(e,t,r=`codex`)=>n(`/api/sessions/recent-threads/open`,{threadId:e,cwd:t,provider:r}),listSessionModels:e=>n(`/api/session-models/${encodeURIComponent(e)}`,{}),startSession:(e,t={},r)=>n(`/api/sessions`,{workspaceId:e,profile:`default`,provider:`codex`,...t},r?{"idempotency-key":r}:{}),startTurn:(e,t,r)=>n(`/api/sessions/${encodeURIComponent(e)}/turns`,{text:t},r?{"idempotency-key":r}:{}),selectModel:(e,t)=>n(`/api/sessions/${encodeURIComponent(e)}/model`,{model:t}),interruptTurn:(e,t)=>n(`/api/sessions/${encodeURIComponent(e)}/turns/${encodeURIComponent(t)}/interrupt`,{}),queueTurnInput:(e,t,r,i)=>n(`/api/sessions/${encodeURIComponent(e)}/turns/${encodeURIComponent(t)}/queue`,{text:r},i?{"idempotency-key":i}:{}),restoreSession:e=>n(`/api/sessions/${encodeURIComponent(e)}/restore`,{}),releaseSession:e=>n(`/api/sessions/${encodeURIComponent(e)}/release`,{}),forgetSession:n=>e(`/api/sessions/${encodeURIComponent(n)}`,{method:`DELETE`}).then(async e=>{if(!e.ok)throw await t(e)}),getHistory:e=>s(`/api/sessions/${encodeURIComponent(e)}/history`),getPlan:(e,t)=>c(`/api/sessions/${encodeURIComponent(e)}/plan`,t),closePlan:e=>o(`/api/sessions/${encodeURIComponent(e)}/plan`),listWorkspacePlans:(e,t)=>s(`/api/workspaces/${encodeURIComponent(e)}/plans`,t),getWorkspacePlan:(e,t,n)=>s(`/api/workspaces/${encodeURIComponent(e)}/plans/${encodeURIComponent(t)}`,n),openSessionPlan:(e,t)=>r(`/api/sessions/${encodeURIComponent(e)}/plan`,{planName:t}),getGitSummary:(e,t)=>s(`/api/git/repositories/${encodeURIComponent(e)}`,t),cloneGitRepository:(e,t)=>n(`/api/git/clone`,{workspaceId:e,address:t}),refreshGit:(e,t)=>n(`/api/git/repositories/${encodeURIComponent(e)}/refresh`,{},t?{"idempotency-key":t}:{}),pullGit:(e,t,r)=>n(`/api/git/repositories/${encodeURIComponent(e)}/pull`,{},t?{"idempotency-key":t}:{},r),checkoutGitBranch:(e,t,r)=>n(`/api/git/repositories/${encodeURIComponent(e)}/checkout`,{branch:t},{},r),pushGit:(e,t)=>n(`/api/git/repositories/${encodeURIComponent(e)}/push`,{},t?{"idempotency-key":t}:{}),listAvailableSkills:(e,t,n=!1,r)=>s(`/api/skills?${new URLSearchParams({workspaceId:e,profile:t,...n?{refresh:`true`}:{}}).toString()}`,r),listSkillProfiles:e=>s(`/api/skill-profiles`,e),replaceSkillProfile:(e,t)=>r(`/api/skill-profiles/${encodeURIComponent(e)}`,t),deleteSkillProfile:e=>o(`/api/skill-profiles/${encodeURIComponent(e)}`),respondInteraction:(e,t,r,i)=>n(`/api/sessions/${encodeURIComponent(e)}/interactions/${encodeURIComponent(t)}`,r,i?{"idempotency-key":i}:{})}}var Ku=[`authoring-start`,`work-start`,`checkpoint`,`update`,`supervision-start`,`resync`];function qu(e){return typeof e==`string`&&Ku.includes(e)}function Ju(e){if(!e||typeof e!=`object`)return!1;let t=e;return Yu(t.plan)&&(t.reason===null||qu(t.reason))}function Yu(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.title==`string`&&Array.isArray(t.steps)&&typeof t.totalSteps==`number`&&typeof t.doneSteps==`number`&&typeof t.allDone==`boolean`&&typeof t.currentStepId==`string`}function Xu(e){return e instanceof Error?e.message:`Could not load the plan.`}function Zu(e){return{...e,...e.skills?{skills:[...e.skills]}:{},description:{...e.description},children:e.children.map(Zu)}}function Qu(e){return{...e,steps:e.steps.map(Zu)}}function $u(e,t){return e.kind===`unavailable`&&e.sessionId===t}function ed(e,t){let n=null,r={kind:`unavailable`,sessionId:null},i=0,a=0,o=null,s=0,c=e=>{++a,r=e,t(e)},l=(t,r)=>{o?.abort(),o=new AbortController;let a=++i,l=s;r||c({kind:`loading`,sessionId:t}),e.getPlan(t,o.signal).then(e=>{a!==i||n!==t||s===l&&c(e?{kind:`ready`,sessionId:t,plan:Qu(e)}:{kind:`unavailable`,sessionId:t})}).catch(e=>{o?.signal.aborted||a!==i||n!==t||c({kind:`error`,sessionId:t,error:Xu(e),...r?{plan:r}:{}})})};return{select(e){if(o?.abort(),n=e,s=0,!e){++i,c({kind:`unavailable`,sessionId:null});return}l(e,void 0)},refresh(e){if(n!==e)return;let t=r.kind===`ready`||r.kind===`closing`||r.kind===`error`?r.plan:void 0;l(e,t)},applyEvent(e,t){if(!(n!==e||t.sequence<=s)){if(t.type===`plan.updated`&&(Yu(t.payload)||Ju(t.payload))){let n=Ju(t.payload)?t.payload.plan:t.payload;s=t.sequence,c({kind:`ready`,sessionId:e,plan:Qu(n)})}t.type===`plan.closed`&&(s=t.sequence,c({kind:`unavailable`,sessionId:e}))}},async close(){if(r.kind!==`ready`&&r.kind!==`error`||!r.plan?.allDone)return null;let{sessionId:t,plan:i}=r;c({kind:`closing`,sessionId:t,plan:i});let o=a;try{return await e.closePlan(t),n===t?a===o?(c({kind:`unavailable`,sessionId:t}),`chat`):$u(r,t)?`chat`:null:null}catch(e){return n===t?a===o?(c({kind:`error`,sessionId:t,plan:i,error:Xu(e)}),null):$u(r,t)?`chat`:null:null}},dispose(){o?.abort(),o=null,n=null,++i,c({kind:`unavailable`,sessionId:null})}}}function td(e){if(!e)return null;let t=nd(e.steps,e.currentStepId)?.measurement?.weeklyRemainingCurrent;return typeof t==`number`&&Number.isFinite(t)&&t>=0&&t<=100?Math.round(t):null}function nd(e,t){for(let n of e){if(n.id===t)return n;let e=nd(n.children,t);if(e)return e}}function rd(e,t){return t===void 0?`L${e}`:`L${e}.${t}`}function id(e){let t=e.steps.filter(e=>e.reviewStatus===`REVIEWED`).length,n=e.steps.length,r=ad(e),i=e.steps.find(e=>e.state===`DONE`&&e.reviewStatus===`UNREVIEWED`);return i?{phase:`awaiting review`,label:`Awaiting ${rd(e.steps.indexOf(i)+1)} review`,current:r,reviewedL1s:t,totalL1s:n}:n>0&&t===n?{phase:`terminal review`,label:`Terminal review`,current:r,reviewedL1s:t,totalL1s:n}:t>0&&!r?{phase:`milestone reported`,label:`Preparing milestone summary`,current:r,reviewedL1s:t,totalL1s:n}:r?{phase:`implementing`,label:`Implementing ${r.position} ${r.title}`,current:r,reviewedL1s:t,totalL1s:n}:{phase:e.allDone?`terminal review`:`implementing`,label:e.allDone?`Terminal review`:`Implementing`,current:r,reviewedL1s:t,totalL1s:n}}function ad(e){for(let[t,n]of e.steps.entries()){if(n.id===e.currentStepId)return{id:n.id,position:rd(t+1),title:n.title,state:n.state};let r=n.children.findIndex(t=>t.id===e.currentStepId);if(r>=0){let e=n.children[r];return{id:e.id,position:rd(t+1,r+1),title:e.title,state:e.state}}}}var od=q(`<span class="wip-effort svelte-hmxg46"> </span>`),sd=q(`<li class="svelte-hmxg46"><span class="wip-position svelte-hmxg46" aria-hidden="true"> </span> <span class="wip-title svelte-hmxg46"> </span> <!></li>`),cd=q(`<ol class="wip-steps svelte-hmxg46" aria-label="Work in progress plan steps"></ol>`),ld=q(`<li class="svelte-hmxg46"><span aria-hidden="true" class="position svelte-hmxg46"> </span> <span aria-hidden="true" class="state"> </span></li>`),ud=q(`<ol class="step-markers svelte-hmxg46" aria-label="Plan step progress"></ol>`),dd=q(`<div><div class="progress-heading svelte-hmxg46"><span> </span> <span> </span></div> <progress class="svelte-hmxg46"> </progress> <span class="review-status"> </span> <!></div>`);function fd(e,t){Qe(t,!0);let n=$(t,`compact`,3,!1),r=$(t,`label`,3,`Plan progress`),i=P(()=>t.plan.steps.flatMap((e,t)=>[{id:e.id,position:rd(t+1),state:e.state,level:e.level,title:e.title,...e.description.effort?{effort:e.description.effort}:{}},...e.children.map((e,n)=>({id:e.id,position:rd(t+1,n+1),state:e.state,level:e.level,title:e.title}))])),a=P(()=>G(i).filter(e=>e.state===`WIP`)),o=P(()=>id(t.plan)),s=P(()=>Math.max(t.plan.totalSteps,1));var c=dd(),l=z(c),u=z(l),d=z(u);N(u);var f=V(u,2),p=z(f);N(f),N(l);var m=V(l,2),h=z(m);N(m);var g=V(m,2),_=z(g,!0);N(g);var v=V(g,2),y=e=>{var n=cd();Z(n,21,()=>G(a),e=>e.id,(e,n)=>{var r=sd(),i=z(r),a=z(i);N(i);var o=V(i,2),s=z(o,!0);N(o);var c=V(o,2),l=e=>{var t=od(),r=z(t);N(t),H(()=>Y(r,`Effort: ${G(n).effort??``}`)),J(e,t)};X(c,e=>{G(n).level===1&&G(n).effort&&e(l)}),N(r),H(()=>{Q(r,`aria-current`,G(n).id===t.plan.currentStepId?`step`:void 0),Q(r,`aria-label`,`${G(n).position}: ${G(n).title}, WIP${G(n).level===1&&G(n).effort?`, effort ${G(n).effort}`:``}`),Y(a,`${G(n).position??``} · WIP`),Y(s,G(n).title)}),J(e,r)}),N(n),J(e,n)},b=e=>{var n=ud();Z(n,21,()=>G(i),e=>e.id,(e,n)=>{var r=ld(),i=z(r),a=z(i,!0);N(i);var o=V(i,2),s=z(o,!0);N(o),N(r),H(()=>{Q(r,`data-state`,G(n).state),Q(r,`aria-current`,G(n).id===t.plan.currentStepId?`step`:void 0),Q(r,`aria-label`,`${G(n).position}: ${G(n).state}`),Y(a,G(n).position),Y(s,G(n).state)}),J(e,r)}),N(n),J(e,n)};X(v,e=>{n()&&G(a).length?e(y):!n()&&G(i).length&&e(b,1)}),N(c),H(()=>{gi(c,1,ui([`plan-progress`,{compact:n()}]),`svelte-hmxg46`),Y(d,`${t.plan.doneSteps??``} / ${t.plan.totalSteps??``} work items done`),Y(p,`· ${G(o).reviewedL1s??``} / ${G(o).totalL1s??``} reviewed`),Q(m,`aria-label`,r()),Oi(m,t.plan.doneSteps),Q(m,`max`,G(s)),Y(h,`${t.plan.doneSteps??``} of ${t.plan.totalSteps??``} work items done`),Q(g,`data-phase`,G(o).phase),Y(_,G(o).label)}),J(e,c),$e()}var pd=q(`<section aria-labelledby="plan-title" class="svelte-3rmyvg"><h2 id="plan-title" class="svelte-3rmyvg">Plan</h2> <p class="svelte-3rmyvg">Loading plan…</p></section>`),md=q(`<section aria-labelledby="plan-title" class="svelte-3rmyvg"><h2 id="plan-title" class="svelte-3rmyvg">Plan</h2> <p class="svelte-3rmyvg">No retained plan for this session.</p></section>`),hd=q(`<section aria-labelledby="plan-title" class="svelte-3rmyvg"><h2 id="plan-title" class="svelte-3rmyvg">Plan</h2> <p class="svelte-3rmyvg"> </p></section>`),gd=q(`<p class="svelte-3rmyvg"> </p>`),_d=q(`<div class="svelte-3rmyvg"><dt class="svelte-3rmyvg">Subtitle</dt> <dd class="svelte-3rmyvg"> </dd></div>`),vd=q(`<div class="svelte-3rmyvg"><dt class="svelte-3rmyvg">Date</dt> <dd class="svelte-3rmyvg"> </dd></div>`),yd=q(`<div class="svelte-3rmyvg"><dt class="svelte-3rmyvg">Keywords</dt> <dd class="svelte-3rmyvg"> </dd></div>`),bd=q(`<dl class="metadata svelte-3rmyvg"><!> <!> <!></dl>`),xd=q(`<p class="svelte-3rmyvg">No plan steps have been retained yet.</p>`),Sd=q(`<p class="svelte-3rmyvg"><strong class="svelte-3rmyvg"> </strong> </p>`),Cd=q(`<p class="svelte-3rmyvg"><strong class="svelte-3rmyvg">Skills:</strong> </p>`),wd=q(`<li class="svelte-3rmyvg"><details class="svelte-3rmyvg"><summary class="svelte-3rmyvg"><strong class="svelte-3rmyvg"><span class="position svelte-3rmyvg"> </span> </strong> <span class="svelte-3rmyvg"> </span> <span class="svelte-3rmyvg"> </span></summary> <!> <!></details></li>`),Td=q(`<ol class="svelte-3rmyvg"></ol>`),Ed=q(`<li class="svelte-3rmyvg"><details class="svelte-3rmyvg"><summary class="svelte-3rmyvg"><strong class="svelte-3rmyvg"><span class="position svelte-3rmyvg"> </span> </strong> <span class="svelte-3rmyvg"> </span> <span class="svelte-3rmyvg"> </span> <span class="measurement svelte-3rmyvg"> </span></summary> <!> <!> <!></details></li>`),Dd=q(`<ol class="plan-steps svelte-3rmyvg"></ol>`),Od=q(`<section class="plan svelte-3rmyvg" aria-labelledby="plan-title"><header class="svelte-3rmyvg"><div class="svelte-3rmyvg"><h2 id="plan-title" class="svelte-3rmyvg"> </h2></div> <button class="close svelte-3rmyvg" aria-label="Close plan and return to list">×</button></header> <!> <p class="svelte-3rmyvg"> </p> <!> <!> <!></section>`),kd=q(`<p class="visually-hidden svelte-3rmyvg" aria-live="polite" aria-atomic="true"> </p> <!>`,1);function Ad(e,t){Qe(t,!0);let n={effort:`Effort`,goal:`Goal`,notes:`Notes`,why:`Why`,change:`Change`,tests:`Tests`,doneWhen:`Done when`},r=I(R(new Set)),i=R({}),a=null,o=0,s=P(()=>t.state.kind===`ready`||t.state.kind===`closing`||t.state.kind===`error`?t.state.plan:void 0),c=P(()=>G(s)?p(G(s).steps,G(s).currentStepId):void 0),l=P(()=>G(s)?m(G(s).steps,G(s).currentStepId):void 0),u=P(()=>G(s)?id(G(s)):void 0),d=P(()=>G(s)?h(G(s).steps,G(s).currentStepId):new Set),f=P(()=>t.state.kind===`loading`?`Loading plan.`:t.state.kind===`unavailable`?`No retained plan for this session.`:t.state.kind===`error`&&!G(s)?t.state.error:t.state.kind===`closing`?`Closing completed plan.`:G(s)?G(c)?`${G(u)?.label??`Current step: ${G(l)} ${G(c).title}`}. ${G(s).doneSteps} of ${G(s).totalSteps} work items done.${t.state.kind===`error`?` ${t.state.error}`:``}`:`${G(u)?.label??`Plan progress`}. ${G(s).doneSteps} of ${G(s).totalSteps} work items done.${t.state.kind===`error`?` ${t.state.error}`:``}`:``);Mn(()=>{let e=G(s)?.currentStepId||null;if(!e||a===e)return;a=e;let t=++o;Cr().then(()=>{t!==o||G(s)?.currentStepId!==e||i[e]?.scrollIntoView({behavior:`auto`,block:`nearest`,inline:`nearest`})})});function p(e,t){for(let n of e){if(n.id===t)return n;let e=p(n.children,t);if(e)return e}}function m(e,t){for(let[n,r]of e.entries()){if(r.id===t)return rd(n+1);let e=r.children.findIndex(e=>e.id===t);if(e>=0)return rd(n+1,e+1)}}function h(e,t,n=[]){for(let r of e){if(r.id===t)return new Set([...n,r.id]);let e=h(r.children,t,[...n,r.id]);if(e.size)return e}return new Set}function g(e){return G(r).has(e)||G(d).has(e)}function _(e,t){L(r,t?new Set([...G(r),e]):new Set([...G(r)].filter(t=>t!==e)),!0)}function v(e){return e.description.goal??e.description.why??e.title}function y(e){let t=e.measurement;if(!t)return`Measurements unavailable`;let n=[];return t.elapsedSeconds!==void 0&&n.push(`${Math.floor(t.elapsedSeconds/60)}m ${t.elapsedSeconds%60}s elapsed`),t.weeklyPercentUsed!==void 0&&n.push(`${t.weeklyPercentUsed}% observed account-wide usage`),t.tokensUsed!==void 0&&n.push(`${t.tokensUsed.toLocaleString()} tokens used`),n.join(` · `)||`Measurements unavailable`}function b(e){return Object.keys(n).flatMap(t=>{let r=e.description[t];return r?[[n[t],r]]:[]})}var x=kd(),S=B(x),w=z(S,!0);N(S);var T=V(S,2),E=e=>{J(e,pd())},D=e=>{J(e,md())},ee=e=>{var n=hd(),r=V(z(n),2),i=z(r,!0);N(r),N(n),H(()=>Y(i,t.state.error)),J(e,n)},te=e=>{var n=Od(),r=z(n),a=z(r),o=z(a),d=z(o,!0);N(o),N(a);var f=V(a,2);N(r);var p=V(r,2);fd(p,{get plan(){return G(s)}});var m=V(p,2),h=z(m);N(m);var x=V(m,2),S=e=>{var n=gd(),r=z(n,!0);N(n),H(()=>Y(r,t.state.error)),J(e,n)};X(x,e=>{t.state.kind===`error`&&e(S)});var w=V(x,2),T=e=>{var t=bd(),n=z(t),r=e=>{var t=_d(),n=V(z(t),2),r=z(n,!0);N(n),N(t),H(()=>Y(r,G(s).subtitle)),J(e,t)};X(n,e=>{G(s).subtitle&&e(r)});var i=V(n,2),a=e=>{var t=vd(),n=V(z(t),2),r=z(n,!0);N(n),N(t),H(()=>Y(r,G(s).date)),J(e,t)};X(i,e=>{G(s).date&&e(a)});var o=V(i,2),c=e=>{var t=yd(),n=V(z(t),2),r=z(n,!0);N(n),N(t),H(()=>Y(r,G(s).keywords)),J(e,t)};X(o,e=>{G(s).keywords&&e(c)}),N(t),J(e,t)};X(w,e=>{(G(s).subtitle||G(s).date||G(s).keywords)&&e(T)});var E=V(w,2),D=e=>{J(e,xd())},ee=e=>{var t=Dd();Z(t,23,()=>G(s).steps,e=>e.id,(e,t,n)=>{var r=Ed(),a=z(r),o=z(a),s=z(o),c=z(s),l=z(c,!0);N(c);var u=V(c);N(s);var d=V(s,2),f=z(d);N(d);var p=V(d,2),m=z(p,!0);N(p);var h=V(p,2),x=z(h,!0);N(h),N(o);var S=V(o,2);Z(S,17,()=>b(G(t)),([e,t])=>e,(e,t)=>{var n=P(()=>C(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Sd(),o=z(a),s=z(o);N(o);var c=V(o);N(a),H(()=>{Y(s,`${r()??``}:`),Y(c,` ${i()??``}`)}),J(e,a)});var w=V(S,2),T=e=>{var n=Cd(),r=V(z(n));N(n),H(e=>Y(r,` ${e??``}`),[()=>G(t).skills.join(`, `)]),J(e,n)};X(w,e=>{G(t).skills?.length&&e(T)});var E=V(w,2),D=e=>{var r=Td();Z(r,23,()=>G(t).children,e=>e.id,(e,t,r)=>{var a=wd(),o=z(a),s=z(o),c=z(s),l=z(c),u=z(l,!0);N(l);var d=V(l);N(c);var f=V(c,2),p=z(f);N(f);var m=V(f,2),h=z(m,!0);N(m),N(s);var y=V(s,2);Z(y,17,()=>b(G(t)),([e,t])=>e,(e,t)=>{var n=P(()=>C(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Sd(),o=z(a),s=z(o);N(o);var c=V(o);N(a),H(()=>{Y(s,`${r()??``}:`),Y(c,` ${i()??``}`)}),J(e,a)});var x=V(y,2),S=e=>{var n=Cd(),r=V(z(n));N(n),H(e=>Y(r,` ${e??``}`),[()=>G(t).skills.join(`, `)]),J(e,n)};X(x,e=>{G(t).skills?.length&&e(S)}),N(o),Li(o,(e,t)=>i[t.id]=e,e=>i?.[e.id],()=>[G(t)]),N(a),H((e,n,r)=>{Q(o,`data-step-id`,G(t).id),o.open=e,Y(u,n),Y(d,` ${G(t).title??``}`),Y(p,`${G(t).state??``} · Priority ${G(t).priority??``}${G(t).reviewStatus?` · ${G(t).reviewStatus}`:``}`),Y(h,r)},[()=>g(G(t).id),()=>rd(G(n)+1,G(r)+1),()=>v(G(t))]),Nr(`toggle`,o,e=>_(G(t).id,e.currentTarget.open)),J(e,a)}),N(r),J(e,r)};X(E,e=>{G(t).children.length&&e(D)}),N(a),Li(a,(e,t)=>i[t.id]=e,e=>i?.[e.id],()=>[G(t)]),N(r),H((e,n,r,i)=>{Q(a,`data-step-id`,G(t).id),a.open=e,Y(l,n),Y(u,` ${G(t).title??``}`),Y(f,`${G(t).state??``} · Priority ${G(t).priority??``}${G(t).reviewStatus?` · ${G(t).reviewStatus}`:``}`),Y(m,r),Y(x,i)},[()=>g(G(t).id),()=>rd(G(n)+1),()=>v(G(t)),()=>y(G(t))]),Nr(`toggle`,a,e=>_(G(t).id,e.currentTarget.open)),J(e,r)}),N(t),J(e,t)};X(E,e=>{G(s).steps.length===0?e(D):e(ee,-1)}),N(n),H(()=>{Y(d,G(s).title),Y(h,`${G(u)?.label??``}. Current: ${G(c)?`${G(l)} ${G(c).title} (${G(c).state})`:`No current step`}`)}),K(`click`,f,function(...e){t.onclose?.apply(this,e)}),J(e,n)};X(T,e=>{t.state.kind===`loading`?e(E):t.state.kind===`unavailable`?e(D,1):t.state.kind===`error`&&!G(s)?e(ee,2):G(s)&&e(te,3)}),H(()=>Y(w,G(f))),J(e,x),$e()}Pr([`click`]);var jd=/^(\*+)\s+(?:(TODO|WIP|DONE)\s+)?(?:\[#([ABC])\]\s+)?(.+)$/,Md=/^#\+([A-Z][A-Z0-9_-]*):\s*(.*)$/i,Nd=/^:([A-Z][A-Z0-9_]*):\s*(.*)$/,Pd=/^-\s+([^:]+?)\s+::\s*(.*)$/;function Fd(e){let t=[],n=[],r=[],i=e.replace(/\r\n?/g,`
23
+ `)}function Gu(e=fetch){async function t(e){let t=await e.json().catch(()=>null),n=typeof t?.code==`string`&&/^[A-Z0-9_]+$/.test(t.code)?t.code:void 0,r=n?.startsWith(`AUTOPILOT_`)&&e.status===409?`Relay request failed (${e.status}).`:typeof t?.detail==`string`&&t.detail.length<=600?t.detail:typeof t?.title==`string`?t.title:`Relay request failed (${e.status}).`;return Object.assign(Error(r),{...n?{code:n}:{},...typeof t?.replaceAllowed==`boolean`?{replaceAllowed:t.replaceAllowed}:{},status:e.status})}async function n(n,r,i={},a){let o=await e(n,{method:`POST`,headers:{"content-type":`application/json`,...i},body:JSON.stringify(r),signal:a});if(!o.ok)throw await t(o);return o.json()}async function r(n,r,i={}){let a=await e(n,{method:`PUT`,headers:{"content-type":`application/json`,...i},body:JSON.stringify(r)});if(!a.ok)throw await t(a);return a.json()}async function i(n,r,i,a){let o=await e(n,{method:`PUT`,headers:{"content-type":`application/octet-stream`,"idempotency-key":i},body:r,signal:a});if(!o.ok)throw await t(o);return o.json()}async function a(n,r,i){let a=await e(n,{method:`DELETE`,headers:{"content-type":`application/json`,"idempotency-key":i},body:JSON.stringify(r)});if(!a.ok)throw await t(a);return a.json()}async function o(n){let r=await e(n,{method:`DELETE`});if(!r.ok)throw await t(r)}async function s(n,r){let i=await e(n,r?{signal:r}:void 0);if(!i.ok)throw await t(i);return i.json()}async function c(n,r){let i=await e(n,{signal:r});if(i.status===204)return null;if(!i.ok)throw await t(i);return i.json()}return{quit:()=>n(`/api/maintenance/quit`,{}),listSessions:e=>s(`/api/sessions`,e),listWorkspaceDirectory:(e,t={},n)=>{let r=new URLSearchParams;t.directory!==void 0&&r.set(`directory`,t.directory),t.cursor!==void 0&&r.set(`cursor`,t.cursor),t.limit!==void 0&&r.set(`limit`,String(t.limit));let i=r.size===0?``:`?${r}`;return s(`/api/workspaces/${encodeURIComponent(e)}/files${i}`,n)},copyWorkspaceEntry:(e,t,r)=>n(`/api/workspaces/${encodeURIComponent(e)}/files/copy`,t,{"idempotency-key":r}),moveWorkspaceEntry:(e,t,r)=>n(`/api/workspaces/${encodeURIComponent(e)}/files/move`,t,{"idempotency-key":r}),uploadWorkspaceFile:(e,t,n,r)=>{let a=new URLSearchParams({directory:t.directory,filename:t.filename,conflict:t.conflict});return i(`/api/workspaces/${encodeURIComponent(e)}/files/upload?${a}`,t.file,n,r)},deleteWorkspaceEntry:(e,t,n)=>a(`/api/workspaces/${encodeURIComponent(e)}/files`,{path:t,recursive:!0},n),getSession:e=>s(`/api/sessions/${encodeURIComponent(e)}`),refreshActivity:e=>n(`/api/sessions/${encodeURIComponent(e)}/activity/refresh`,{}),setAutopilot:(e,t,n)=>r(`/api/sessions/${encodeURIComponent(e)}/autopilot`,{enabled:t},n?{"idempotency-key":n}:{}),resolveAttention:(e,t,r)=>n(`/api/sessions/${encodeURIComponent(e)}/attention/${encodeURIComponent(t)}/resolve`,r),listRecentSessions:()=>s(`/api/sessions/recent-threads`),openRecentSession:(e,t,r=`codex`)=>n(`/api/sessions/recent-threads/open`,{threadId:e,cwd:t,provider:r}),listSessionModels:e=>n(`/api/session-models/${encodeURIComponent(e)}`,{}),startSession:(e,t={},r)=>n(`/api/sessions`,{workspaceId:e,profile:`default`,provider:`codex`,...t},r?{"idempotency-key":r}:{}),startTurn:(e,t,r)=>n(`/api/sessions/${encodeURIComponent(e)}/turns`,{text:t},r?{"idempotency-key":r}:{}),selectModel:(e,t)=>n(`/api/sessions/${encodeURIComponent(e)}/model`,{model:t}),interruptTurn:(e,t)=>n(`/api/sessions/${encodeURIComponent(e)}/turns/${encodeURIComponent(t)}/interrupt`,{}),queueTurnInput:(e,t,r,i)=>n(`/api/sessions/${encodeURIComponent(e)}/turns/${encodeURIComponent(t)}/queue`,{text:r},i?{"idempotency-key":i}:{}),restoreSession:e=>n(`/api/sessions/${encodeURIComponent(e)}/restore`,{}),releaseSession:e=>n(`/api/sessions/${encodeURIComponent(e)}/release`,{}),forgetSession:n=>e(`/api/sessions/${encodeURIComponent(n)}`,{method:`DELETE`}).then(async e=>{if(!e.ok)throw await t(e)}),getHistory:e=>s(`/api/sessions/${encodeURIComponent(e)}/history`),getPlan:(e,t)=>c(`/api/sessions/${encodeURIComponent(e)}/plan`,t),closePlan:e=>o(`/api/sessions/${encodeURIComponent(e)}/plan`),listWorkspacePlans:(e,t)=>s(`/api/workspaces/${encodeURIComponent(e)}/plans`,t),getWorkspacePlan:(e,t,n)=>s(`/api/workspaces/${encodeURIComponent(e)}/plans/${encodeURIComponent(t)}`,n),openSessionPlan:(e,t)=>r(`/api/sessions/${encodeURIComponent(e)}/plan`,{planName:t}),getGitSummary:(e,t)=>s(`/api/git/repositories/${encodeURIComponent(e)}`,t),cloneGitRepository:(e,t)=>n(`/api/git/clone`,{workspaceId:e,address:t}),refreshGit:(e,t)=>n(`/api/git/repositories/${encodeURIComponent(e)}/refresh`,{},t?{"idempotency-key":t}:{}),pullGit:(e,t,r)=>n(`/api/git/repositories/${encodeURIComponent(e)}/pull`,{},t?{"idempotency-key":t}:{},r),checkoutGitBranch:(e,t,r)=>n(`/api/git/repositories/${encodeURIComponent(e)}/checkout`,{branch:t},{},r),pushGit:(e,t)=>n(`/api/git/repositories/${encodeURIComponent(e)}/push`,{},t?{"idempotency-key":t}:{}),listAvailableSkills:(e,t,n=!1,r)=>s(`/api/skills?${new URLSearchParams({workspaceId:e,profile:t,...n?{refresh:`true`}:{}}).toString()}`,r),listSkillProfiles:e=>s(`/api/skill-profiles`,e),replaceSkillProfile:(e,t)=>r(`/api/skill-profiles/${encodeURIComponent(e)}`,t),deleteSkillProfile:e=>o(`/api/skill-profiles/${encodeURIComponent(e)}`),respondInteraction:(e,t,r,i)=>n(`/api/sessions/${encodeURIComponent(e)}/interactions/${encodeURIComponent(t)}`,r,i?{"idempotency-key":i}:{})}}var Ku=[`authoring-start`,`work-start`,`checkpoint`,`update`,`supervision-start`,`resync`];function qu(e){return typeof e==`string`&&(Ku.includes(e)||/^review:[A-Za-z0-9._-]{1,128}:REVIEWED$/.test(e))}function Ju(e){if(!e||typeof e!=`object`)return!1;let t=e;return Yu(t.plan)&&(t.reason===null||qu(t.reason))}function Yu(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.title==`string`&&Array.isArray(t.steps)&&typeof t.totalSteps==`number`&&typeof t.doneSteps==`number`&&typeof t.allDone==`boolean`&&typeof t.currentStepId==`string`}function Xu(e){return e instanceof Error?e.message:`Could not load the plan.`}function Zu(e){return{...e,...e.skills?{skills:[...e.skills]}:{},description:{...e.description},children:e.children.map(Zu)}}function Qu(e){return{...e,steps:e.steps.map(Zu)}}function $u(e,t){return e.kind===`unavailable`&&e.sessionId===t}function ed(e,t){let n=null,r={kind:`unavailable`,sessionId:null},i=0,a=0,o=null,s=0,c=e=>{++a,r=e,t(e)},l=(t,r)=>{o?.abort(),o=new AbortController;let a=++i,l=s;r||c({kind:`loading`,sessionId:t}),e.getPlan(t,o.signal).then(e=>{a!==i||n!==t||s===l&&c(e?{kind:`ready`,sessionId:t,plan:Qu(e)}:{kind:`unavailable`,sessionId:t})}).catch(e=>{o?.signal.aborted||a!==i||n!==t||c({kind:`error`,sessionId:t,error:Xu(e),...r?{plan:r}:{}})})};return{select(e){if(o?.abort(),n=e,s=0,!e){++i,c({kind:`unavailable`,sessionId:null});return}l(e,void 0)},refresh(e){if(n!==e)return;let t=r.kind===`ready`||r.kind===`closing`||r.kind===`error`?r.plan:void 0;l(e,t)},applyEvent(e,t){if(!(n!==e||t.sequence<=s)){if(t.type===`plan.updated`&&(Yu(t.payload)||Ju(t.payload))){let n=Ju(t.payload)?t.payload.plan:t.payload;s=t.sequence,c({kind:`ready`,sessionId:e,plan:Qu(n)})}t.type===`plan.closed`&&(s=t.sequence,c({kind:`unavailable`,sessionId:e}))}},async close(){if(r.kind!==`ready`&&r.kind!==`error`||!r.plan?.allDone)return null;let{sessionId:t,plan:i}=r;c({kind:`closing`,sessionId:t,plan:i});let o=a;try{return await e.closePlan(t),n===t?a===o?(c({kind:`unavailable`,sessionId:t}),`chat`):$u(r,t)?`chat`:null:null}catch(e){return n===t?a===o?(c({kind:`error`,sessionId:t,plan:i,error:Xu(e)}),null):$u(r,t)?`chat`:null:null}},dispose(){o?.abort(),o=null,n=null,++i,c({kind:`unavailable`,sessionId:null})}}}function td(e){if(!e)return null;let t=nd(e.steps,e.currentStepId)?.measurement?.weeklyRemainingCurrent;return typeof t==`number`&&Number.isFinite(t)&&t>=0&&t<=100?Math.round(t):null}function nd(e,t){for(let n of e){if(n.id===t)return n;let e=nd(n.children,t);if(e)return e}}function rd(e,t){return t===void 0?`L${e}`:`L${e}.${t}`}function id(e){let t=e.steps.filter(e=>e.reviewStatus===`REVIEWED`).length,n=e.steps.length,r=ad(e),i=e.steps.find(e=>e.state===`DONE`&&e.reviewStatus===`UNREVIEWED`);return i?{phase:`awaiting review`,label:`Awaiting ${rd(e.steps.indexOf(i)+1)} review`,current:r,reviewedL1s:t,totalL1s:n}:n>0&&t===n?{phase:`terminal review`,label:`Terminal review`,current:r,reviewedL1s:t,totalL1s:n}:t>0&&!r?{phase:`milestone reported`,label:`Preparing milestone summary`,current:r,reviewedL1s:t,totalL1s:n}:r?{phase:`implementing`,label:`Implementing ${r.position} ${r.title}`,current:r,reviewedL1s:t,totalL1s:n}:{phase:e.allDone?`terminal review`:`implementing`,label:e.allDone?`Terminal review`:`Implementing`,current:r,reviewedL1s:t,totalL1s:n}}function ad(e){for(let[t,n]of e.steps.entries()){if(n.id===e.currentStepId)return{id:n.id,position:rd(t+1),title:n.title,state:n.state};let r=n.children.findIndex(t=>t.id===e.currentStepId);if(r>=0){let e=n.children[r];return{id:e.id,position:rd(t+1,r+1),title:e.title,state:e.state}}}}var od=q(`<span class="wip-effort svelte-hmxg46"> </span>`),sd=q(`<li class="svelte-hmxg46"><span class="wip-position svelte-hmxg46" aria-hidden="true"> </span> <span class="wip-title svelte-hmxg46"> </span> <!></li>`),cd=q(`<ol class="wip-steps svelte-hmxg46" aria-label="Work in progress plan steps"></ol>`),ld=q(`<li class="svelte-hmxg46"><span aria-hidden="true" class="position svelte-hmxg46"> </span> <span aria-hidden="true" class="state"> </span></li>`),ud=q(`<ol class="step-markers svelte-hmxg46" aria-label="Plan step progress"></ol>`),dd=q(`<div><div class="progress-heading svelte-hmxg46"><span> </span> <span> </span></div> <progress class="svelte-hmxg46"> </progress> <span class="review-status"> </span> <!></div>`);function fd(e,t){Qe(t,!0);let n=$(t,`compact`,3,!1),r=$(t,`label`,3,`Plan progress`),i=P(()=>t.plan.steps.flatMap((e,t)=>[{id:e.id,position:rd(t+1),state:e.state,level:e.level,title:e.title,...e.description.effort?{effort:e.description.effort}:{}},...e.children.map((e,n)=>({id:e.id,position:rd(t+1,n+1),state:e.state,level:e.level,title:e.title}))])),a=P(()=>G(i).filter(e=>e.state===`WIP`)),o=P(()=>id(t.plan)),s=P(()=>Math.max(t.plan.totalSteps,1));var c=dd(),l=z(c),u=z(l),d=z(u);N(u);var f=V(u,2),p=z(f);N(f),N(l);var m=V(l,2),h=z(m);N(m);var g=V(m,2),_=z(g,!0);N(g);var v=V(g,2),y=e=>{var n=cd();Z(n,21,()=>G(a),e=>e.id,(e,n)=>{var r=sd(),i=z(r),a=z(i);N(i);var o=V(i,2),s=z(o,!0);N(o);var c=V(o,2),l=e=>{var t=od(),r=z(t);N(t),H(()=>Y(r,`Effort: ${G(n).effort??``}`)),J(e,t)};X(c,e=>{G(n).level===1&&G(n).effort&&e(l)}),N(r),H(()=>{Q(r,`aria-current`,G(n).id===t.plan.currentStepId?`step`:void 0),Q(r,`aria-label`,`${G(n).position}: ${G(n).title}, WIP${G(n).level===1&&G(n).effort?`, effort ${G(n).effort}`:``}`),Y(a,`${G(n).position??``} · WIP`),Y(s,G(n).title)}),J(e,r)}),N(n),J(e,n)},b=e=>{var n=ud();Z(n,21,()=>G(i),e=>e.id,(e,n)=>{var r=ld(),i=z(r),a=z(i,!0);N(i);var o=V(i,2),s=z(o,!0);N(o),N(r),H(()=>{Q(r,`data-state`,G(n).state),Q(r,`aria-current`,G(n).id===t.plan.currentStepId?`step`:void 0),Q(r,`aria-label`,`${G(n).position}: ${G(n).state}`),Y(a,G(n).position),Y(s,G(n).state)}),J(e,r)}),N(n),J(e,n)};X(v,e=>{n()&&G(a).length?e(y):!n()&&G(i).length&&e(b,1)}),N(c),H(()=>{gi(c,1,ui([`plan-progress`,{compact:n()}]),`svelte-hmxg46`),Y(d,`${t.plan.doneSteps??``} / ${t.plan.totalSteps??``} work items done`),Y(p,`· ${G(o).reviewedL1s??``} / ${G(o).totalL1s??``} reviewed`),Q(m,`aria-label`,r()),Oi(m,t.plan.doneSteps),Q(m,`max`,G(s)),Y(h,`${t.plan.doneSteps??``} of ${t.plan.totalSteps??``} work items done`),Q(g,`data-phase`,G(o).phase),Y(_,G(o).label)}),J(e,c),$e()}var pd=q(`<section aria-labelledby="plan-title" class="svelte-3rmyvg"><h2 id="plan-title" class="svelte-3rmyvg">Plan</h2> <p class="svelte-3rmyvg">Loading plan…</p></section>`),md=q(`<section aria-labelledby="plan-title" class="svelte-3rmyvg"><h2 id="plan-title" class="svelte-3rmyvg">Plan</h2> <p class="svelte-3rmyvg">No retained plan for this session.</p></section>`),hd=q(`<section aria-labelledby="plan-title" class="svelte-3rmyvg"><h2 id="plan-title" class="svelte-3rmyvg">Plan</h2> <p class="svelte-3rmyvg"> </p></section>`),gd=q(`<p class="svelte-3rmyvg"> </p>`),_d=q(`<div class="svelte-3rmyvg"><dt class="svelte-3rmyvg">Subtitle</dt> <dd class="svelte-3rmyvg"> </dd></div>`),vd=q(`<div class="svelte-3rmyvg"><dt class="svelte-3rmyvg">Date</dt> <dd class="svelte-3rmyvg"> </dd></div>`),yd=q(`<div class="svelte-3rmyvg"><dt class="svelte-3rmyvg">Keywords</dt> <dd class="svelte-3rmyvg"> </dd></div>`),bd=q(`<dl class="metadata svelte-3rmyvg"><!> <!> <!></dl>`),xd=q(`<p class="svelte-3rmyvg">No plan steps have been retained yet.</p>`),Sd=q(`<p class="svelte-3rmyvg"><strong class="svelte-3rmyvg"> </strong> </p>`),Cd=q(`<p class="svelte-3rmyvg"><strong class="svelte-3rmyvg">Skills:</strong> </p>`),wd=q(`<li class="svelte-3rmyvg"><details class="svelte-3rmyvg"><summary class="svelte-3rmyvg"><strong class="svelte-3rmyvg"><span class="position svelte-3rmyvg"> </span> </strong> <span class="svelte-3rmyvg"> </span> <span class="svelte-3rmyvg"> </span></summary> <!> <!></details></li>`),Td=q(`<ol class="svelte-3rmyvg"></ol>`),Ed=q(`<li class="svelte-3rmyvg"><details class="svelte-3rmyvg"><summary class="svelte-3rmyvg"><strong class="svelte-3rmyvg"><span class="position svelte-3rmyvg"> </span> </strong> <span class="svelte-3rmyvg"> </span> <span class="svelte-3rmyvg"> </span> <span class="measurement svelte-3rmyvg"> </span></summary> <!> <!> <!></details></li>`),Dd=q(`<ol class="plan-steps svelte-3rmyvg"></ol>`),Od=q(`<section class="plan svelte-3rmyvg" aria-labelledby="plan-title"><header class="svelte-3rmyvg"><div class="svelte-3rmyvg"><h2 id="plan-title" class="svelte-3rmyvg"> </h2></div> <button class="close svelte-3rmyvg" aria-label="Close plan and return to list">×</button></header> <!> <p class="svelte-3rmyvg"> </p> <!> <!> <!></section>`),kd=q(`<p class="visually-hidden svelte-3rmyvg" aria-live="polite" aria-atomic="true"> </p> <!>`,1);function Ad(e,t){Qe(t,!0);let n={effort:`Effort`,goal:`Goal`,notes:`Notes`,why:`Why`,change:`Change`,tests:`Tests`,doneWhen:`Done when`},r=I(R(new Set)),i=R({}),a=null,o=0,s=P(()=>t.state.kind===`ready`||t.state.kind===`closing`||t.state.kind===`error`?t.state.plan:void 0),c=P(()=>G(s)?p(G(s).steps,G(s).currentStepId):void 0),l=P(()=>G(s)?m(G(s).steps,G(s).currentStepId):void 0),u=P(()=>G(s)?id(G(s)):void 0),d=P(()=>G(s)?h(G(s).steps,G(s).currentStepId):new Set),f=P(()=>t.state.kind===`loading`?`Loading plan.`:t.state.kind===`unavailable`?`No retained plan for this session.`:t.state.kind===`error`&&!G(s)?t.state.error:t.state.kind===`closing`?`Closing completed plan.`:G(s)?G(c)?`${G(u)?.label??`Current step: ${G(l)} ${G(c).title}`}. ${G(s).doneSteps} of ${G(s).totalSteps} work items done.${t.state.kind===`error`?` ${t.state.error}`:``}`:`${G(u)?.label??`Plan progress`}. ${G(s).doneSteps} of ${G(s).totalSteps} work items done.${t.state.kind===`error`?` ${t.state.error}`:``}`:``);Mn(()=>{let e=G(s)?.currentStepId||null;if(!e||a===e)return;a=e;let t=++o;Cr().then(()=>{t!==o||G(s)?.currentStepId!==e||i[e]?.scrollIntoView({behavior:`auto`,block:`nearest`,inline:`nearest`})})});function p(e,t){for(let n of e){if(n.id===t)return n;let e=p(n.children,t);if(e)return e}}function m(e,t){for(let[n,r]of e.entries()){if(r.id===t)return rd(n+1);let e=r.children.findIndex(e=>e.id===t);if(e>=0)return rd(n+1,e+1)}}function h(e,t,n=[]){for(let r of e){if(r.id===t)return new Set([...n,r.id]);let e=h(r.children,t,[...n,r.id]);if(e.size)return e}return new Set}function g(e){return G(r).has(e)||G(d).has(e)}function _(e,t){L(r,t?new Set([...G(r),e]):new Set([...G(r)].filter(t=>t!==e)),!0)}function v(e){return e.description.goal??e.description.why??e.title}function y(e){let t=e.measurement;if(!t)return`Measurements unavailable`;let n=[];return t.elapsedSeconds!==void 0&&n.push(`${Math.floor(t.elapsedSeconds/60)}m ${t.elapsedSeconds%60}s elapsed`),t.weeklyPercentUsed!==void 0&&n.push(`${t.weeklyPercentUsed}% observed account-wide usage`),t.tokensUsed!==void 0&&n.push(`${t.tokensUsed.toLocaleString()} tokens used`),n.join(` · `)||`Measurements unavailable`}function b(e){return Object.keys(n).flatMap(t=>{let r=e.description[t];return r?[[n[t],r]]:[]})}var x=kd(),S=B(x),w=z(S,!0);N(S);var T=V(S,2),E=e=>{J(e,pd())},D=e=>{J(e,md())},ee=e=>{var n=hd(),r=V(z(n),2),i=z(r,!0);N(r),N(n),H(()=>Y(i,t.state.error)),J(e,n)},te=e=>{var n=Od(),r=z(n),a=z(r),o=z(a),d=z(o,!0);N(o),N(a);var f=V(a,2);N(r);var p=V(r,2);fd(p,{get plan(){return G(s)}});var m=V(p,2),h=z(m);N(m);var x=V(m,2),S=e=>{var n=gd(),r=z(n,!0);N(n),H(()=>Y(r,t.state.error)),J(e,n)};X(x,e=>{t.state.kind===`error`&&e(S)});var w=V(x,2),T=e=>{var t=bd(),n=z(t),r=e=>{var t=_d(),n=V(z(t),2),r=z(n,!0);N(n),N(t),H(()=>Y(r,G(s).subtitle)),J(e,t)};X(n,e=>{G(s).subtitle&&e(r)});var i=V(n,2),a=e=>{var t=vd(),n=V(z(t),2),r=z(n,!0);N(n),N(t),H(()=>Y(r,G(s).date)),J(e,t)};X(i,e=>{G(s).date&&e(a)});var o=V(i,2),c=e=>{var t=yd(),n=V(z(t),2),r=z(n,!0);N(n),N(t),H(()=>Y(r,G(s).keywords)),J(e,t)};X(o,e=>{G(s).keywords&&e(c)}),N(t),J(e,t)};X(w,e=>{(G(s).subtitle||G(s).date||G(s).keywords)&&e(T)});var E=V(w,2),D=e=>{J(e,xd())},ee=e=>{var t=Dd();Z(t,23,()=>G(s).steps,e=>e.id,(e,t,n)=>{var r=Ed(),a=z(r),o=z(a),s=z(o),c=z(s),l=z(c,!0);N(c);var u=V(c);N(s);var d=V(s,2),f=z(d);N(d);var p=V(d,2),m=z(p,!0);N(p);var h=V(p,2),x=z(h,!0);N(h),N(o);var S=V(o,2);Z(S,17,()=>b(G(t)),([e,t])=>e,(e,t)=>{var n=P(()=>C(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Sd(),o=z(a),s=z(o);N(o);var c=V(o);N(a),H(()=>{Y(s,`${r()??``}:`),Y(c,` ${i()??``}`)}),J(e,a)});var w=V(S,2),T=e=>{var n=Cd(),r=V(z(n));N(n),H(e=>Y(r,` ${e??``}`),[()=>G(t).skills.join(`, `)]),J(e,n)};X(w,e=>{G(t).skills?.length&&e(T)});var E=V(w,2),D=e=>{var r=Td();Z(r,23,()=>G(t).children,e=>e.id,(e,t,r)=>{var a=wd(),o=z(a),s=z(o),c=z(s),l=z(c),u=z(l,!0);N(l);var d=V(l);N(c);var f=V(c,2),p=z(f);N(f);var m=V(f,2),h=z(m,!0);N(m),N(s);var y=V(s,2);Z(y,17,()=>b(G(t)),([e,t])=>e,(e,t)=>{var n=P(()=>C(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Sd(),o=z(a),s=z(o);N(o);var c=V(o);N(a),H(()=>{Y(s,`${r()??``}:`),Y(c,` ${i()??``}`)}),J(e,a)});var x=V(y,2),S=e=>{var n=Cd(),r=V(z(n));N(n),H(e=>Y(r,` ${e??``}`),[()=>G(t).skills.join(`, `)]),J(e,n)};X(x,e=>{G(t).skills?.length&&e(S)}),N(o),Li(o,(e,t)=>i[t.id]=e,e=>i?.[e.id],()=>[G(t)]),N(a),H((e,n,r)=>{Q(o,`data-step-id`,G(t).id),o.open=e,Y(u,n),Y(d,` ${G(t).title??``}`),Y(p,`${G(t).state??``} · Priority ${G(t).priority??``}${G(t).reviewStatus?` · ${G(t).reviewStatus}`:``}`),Y(h,r)},[()=>g(G(t).id),()=>rd(G(n)+1,G(r)+1),()=>v(G(t))]),Nr(`toggle`,o,e=>_(G(t).id,e.currentTarget.open)),J(e,a)}),N(r),J(e,r)};X(E,e=>{G(t).children.length&&e(D)}),N(a),Li(a,(e,t)=>i[t.id]=e,e=>i?.[e.id],()=>[G(t)]),N(r),H((e,n,r,i)=>{Q(a,`data-step-id`,G(t).id),a.open=e,Y(l,n),Y(u,` ${G(t).title??``}`),Y(f,`${G(t).state??``} · Priority ${G(t).priority??``}${G(t).reviewStatus?` · ${G(t).reviewStatus}`:``}`),Y(m,r),Y(x,i)},[()=>g(G(t).id),()=>rd(G(n)+1),()=>v(G(t)),()=>y(G(t))]),Nr(`toggle`,a,e=>_(G(t).id,e.currentTarget.open)),J(e,r)}),N(t),J(e,t)};X(E,e=>{G(s).steps.length===0?e(D):e(ee,-1)}),N(n),H(()=>{Y(d,G(s).title),Y(h,`${G(u)?.label??``}. Current: ${G(c)?`${G(l)} ${G(c).title} (${G(c).state})`:`No current step`}`)}),K(`click`,f,function(...e){t.onclose?.apply(this,e)}),J(e,n)};X(T,e=>{t.state.kind===`loading`?e(E):t.state.kind===`unavailable`?e(D,1):t.state.kind===`error`&&!G(s)?e(ee,2):G(s)&&e(te,3)}),H(()=>Y(w,G(f))),J(e,x),$e()}Pr([`click`]);var jd=/^(\*+)\s+(?:(TODO|WIP|DONE)\s+)?(?:\[#([ABC])\]\s+)?(.+)$/,Md=/^#\+([A-Z][A-Z0-9_-]*):\s*(.*)$/i,Nd=/^:([A-Z][A-Z0-9_]*):\s*(.*)$/,Pd=/^-\s+([^:]+?)\s+::\s*(.*)$/;function Fd(e){let t=[],n=[],r=[],i=e.replace(/\r\n?/g,`
24
24
  `).split(`
25
25
  `),a=null,o=!1,s=()=>{a&&r.push({...a,properties:[...a.properties],descriptions:[...a.descriptions],body:Id(a.body)})};for(let e of i){let r=jd.exec(e);if(r){s(),a={level:r[1].length,title:r[4].trim(),...r[2]?{state:r[2]}:{},...r[3]?{priority:r[3]}:{},properties:[],descriptions:[],body:[]},o=!1;continue}if(!a){let r=Md.exec(e);r?t.push([r[1].toUpperCase(),r[2].trim()]):n.push(e);continue}if(e===`:PROPERTIES:`){o=!0;continue}if(o&&e===`:END:`){o=!1;continue}if(o){let t=Nd.exec(e);t&&a.properties.push([t[1],t[2].trim()]);continue}let i=Pd.exec(e);i?a.descriptions.push([i[1].trim(),i[2].trim()]):a.body.push(e)}return s(),{metadata:t,preamble:Id(n),sections:r}}function Id(e){let t=[...e];for(;t[0]?.trim()===``;)t.shift();for(;t.at(-1)?.trim()===``;)t.pop();return t}var Ld=q(`<div class="svelte-h7gaqo"><dt class="svelte-h7gaqo"> </dt> <dd class="svelte-h7gaqo"> </dd></div>`),Rd=q(`<dl class="metadata svelte-h7gaqo"></dl>`),zd=q(`<p class="svelte-h7gaqo"> </p>`),Bd=q(`<p class="svelte-h7gaqo">This Org document has no headings.</p>`),Vd=q(`<h3 class="svelte-h7gaqo"> </h3>`),Hd=q(`<h4 class="svelte-h7gaqo"> </h4>`),Ud=q(`<span> </span>`),Wd=q(`<span class="priority svelte-h7gaqo"> </span>`),Gd=q(`<dl class="descriptions svelte-h7gaqo"></dl>`),Kd=q(`<p> </p>`),qd=q(`<details class="properties svelte-h7gaqo"><summary class="svelte-h7gaqo">Properties</summary> <dl class="svelte-h7gaqo"></dl></details>`),Jd=q(`<section class="org-section svelte-h7gaqo"><div class="section-heading svelte-h7gaqo"><!> <!> <!></div> <!> <!> <!></section>`),Yd=q(`<div class="sections svelte-h7gaqo"></div>`),Xd=q(`<article class="org-document svelte-h7gaqo" aria-labelledby="org-document-title"><header class="svelte-h7gaqo"><div><h2 id="org-document-title" class="svelte-h7gaqo"> </h2> <code class="svelte-h7gaqo"> </code></div> <button class="close svelte-h7gaqo" type="button" aria-label="Close plan and return to list">×</button></header> <!> <!> <!></article>`);function Zd(e,t){Qe(t,!0);let n=P(()=>Fd(t.preview.source)),r=P(()=>G(n).metadata.filter(([e])=>e!==`TITLE`));var i=Xd(),a=z(i),o=z(a),s=z(o),c=z(s,!0);N(s);var l=V(s,2),u=z(l,!0);N(l),N(o);var d=V(o,2);N(a);var f=V(a,2),p=e=>{var t=Rd();Z(t,21,()=>G(r),([e,t])=>`${e}:${t}`,(e,t)=>{var n=P(()=>C(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Ld(),o=z(a),s=z(o,!0);N(o);var c=V(o,2),l=z(c,!0);N(c),N(a),H(()=>{Y(s,r()),Y(l,i()||`—`)}),J(e,a)}),N(t),J(e,t)};X(f,e=>{G(r).length&&e(p)});var m=V(f,2);Z(m,19,()=>G(n).preamble,(e,t)=>`preamble:${t}:${e}`,(e,t)=>{var n=Hr(),r=B(n),i=e=>{var n=zd(),r=z(n,!0);N(n),H(()=>Y(r,G(t))),J(e,n)},a=P(()=>G(t).trim());X(r,e=>{G(a)&&e(i)}),J(e,n)});var h=V(m,2),g=e=>{J(e,Bd())},_=e=>{var t=Yd();Z(t,23,()=>G(n).sections,(e,t)=>`${t}:${e.level}:${e.title}`,(e,t)=>{var n=Jd();let r;var i=z(n),a=z(i),o=e=>{var n=Vd(),r=z(n,!0);N(n),H(()=>Y(r,G(t).title)),J(e,n)},s=e=>{var n=Hd(),r=z(n,!0);N(n),H(()=>Y(r,G(t).title)),J(e,n)};X(a,e=>{G(t).level===1?e(o):e(s,-1)});var c=V(a,2),l=e=>{var n=Ud(),r=z(n,!0);N(n),H(e=>{gi(n,1,e,`svelte-h7gaqo`),Y(r,G(t).state)},[()=>`state state-${G(t).state.toLowerCase()}`]),J(e,n)};X(c,e=>{G(t).state&&e(l)});var u=V(c,2),d=e=>{var n=Wd(),r=z(n);N(n),H(()=>Y(r,`Priority ${G(t).priority??``}`)),J(e,n)};X(u,e=>{G(t).priority&&e(d)}),N(i);var f=V(i,2),p=e=>{var n=Gd();Z(n,21,()=>G(t).descriptions,([e,t])=>`${e}:${t}`,(e,t)=>{var n=P(()=>C(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Ld(),o=z(a),s=z(o,!0);N(o);var c=V(o,2),l=z(c,!0);N(c),N(a),H(()=>{Y(s,r()),Y(l,i()||`—`)}),J(e,a)}),N(n),J(e,n)};X(f,e=>{G(t).descriptions.length&&e(p)});var m=V(f,2);Z(m,19,()=>G(t).body,(e,t)=>`${t}:${e}`,(e,t)=>{var n=Hr(),r=B(n),i=e=>{var n=Kd();let r;var i=z(n,!0);N(n),H(e=>{r=gi(n,1,`svelte-h7gaqo`,null,r,e),Y(i,G(t))},[()=>({"list-item":G(t).trimStart().startsWith(`- `)})]),J(e,n)},a=P(()=>G(t).trim());X(r,e=>{G(a)&&e(i)}),J(e,n)});var h=V(m,2),g=e=>{var n=qd(),r=V(z(n),2);Z(r,21,()=>G(t).properties,([e,t])=>`${e}:${t}`,(e,t)=>{var n=P(()=>C(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Ld(),o=z(a),s=z(o,!0);N(o);var c=V(o,2),l=z(c,!0);N(c),N(a),H(()=>{Y(s,r()),Y(l,i()||`—`)}),J(e,a)}),N(r),N(n),J(e,n)};X(h,e=>{G(t).properties.length&&e(g)}),N(n),H(e=>r=vi(n,``,r,e),[()=>({"--org-depth":Math.max(0,G(t).level-1)})]),J(e,n)}),N(t),J(e,t)};X(h,e=>{G(n).sections.length===0?e(g):e(_,-1)}),N(i),H(()=>{Y(c,t.preview.title),Y(u,t.preview.planName)}),K(`click`,d,function(...e){t.onclose?.apply(this,e)}),J(e,i),$e()}Pr([`click`]);var Qd=q(`<span> </span>`),$d=q(`<span> </span> <!>`,1),ef=q(`<span>Org document</span>`),tf=q(`<li><button class="svelte-x2ko9l"><strong> </strong> <code class="svelte-x2ko9l"> </code> <!></button></li>`),nf=q(`<p>Select a workspace to browse its local plans.</p>`),rf=q(`<p>Loading workspace plans…</p>`),af=q(`<p> </p>`),of=q(`<p>No Org files were found below this workspace.</p>`),sf=q(`<ul aria-label="Unfinished plans" class="svelte-x2ko9l"></ul>`),cf=q(`<section class="completed svelte-x2ko9l" aria-labelledby="completed-plans-title"><h3 id="completed-plans-title" class="svelte-x2ko9l">Completed</h3> <ul class="svelte-x2ko9l"></ul></section>`),lf=q(`<p class="scope svelte-x2ko9l">Org files below the selected workspace.</p> <!> <!>`,1),uf=q(`<section class="plans svelte-x2ko9l" aria-labelledby="plans-title"><h2 id="plans-title" tabindex="-1" class="svelte-x2ko9l">Plans</h2> <!></section>`);function df(e,t){Qe(t,!0);let n=(e,t=b)=>{var n=tf(),r=z(n),a=z(r),o=z(a,!0);N(a);var s=V(a,2),c=z(s,!0);N(s);var l=V(s,2),u=e=>{var n=$d(),r=B(n),i=z(r);N(r);var a=V(r,2),o=e=>{var n=Qd(),r=z(n,!0);N(n),H(()=>Y(r,t().subtitle)),J(e,n)};X(a,e=>{t().subtitle&&e(o)}),H(()=>Y(i,`${t().doneSteps??``} / ${t().totalSteps??``} complete`)),J(e,n)},f=e=>{J(e,ef())};X(l,e=>{t().previewAvailable===!1?e(f,-1):e(u)}),N(r),Li(r,e=>i[t().planName]=e,()=>i?.[t().planName]),N(n),H(()=>{Y(o,t().title),Y(c,t().planName)}),K(`click`,r,()=>d(t().planName)),J(e,n)},r=I(null),i=R({}),a=I(null),o=!1,s=!1,c=P(()=>t.catalog.kind===`ready`?t.catalog.entries.filter(e=>e.allDone!==!0):[]),l=P(()=>t.catalog.kind===`ready`?t.catalog.entries.filter(e=>e.allDone===!0):[]);function u(){t.onclose()}function d(e){L(a,e,!0),t.onopen(e)}Mn(()=>{if(t.state){o=!0;return}if(o&&(o=!1,s=!0),!s)return;let e=t.catalog.kind,n=G(a);queueMicrotask(()=>{let t=n?i[n]:void 0;t?.isConnected?(t.focus(),s=!1):e!==`loading`&&(G(r)?.focus(),s=!1)})});var f=Hr(),p=B(f),m=e=>{Zd(e,{get preview(){return t.state},onclose:u})},h=e=>{Ad(e,{get state(){return t.state},onclose:u})},g=e=>{var i=uf(),a=z(i);Li(a,e=>L(r,e),()=>G(r));var o=V(a,2),s=e=>{J(e,nf())},u=e=>{J(e,rf())},d=e=>{var n=af(),r=z(n,!0);N(n),H(()=>Y(r,t.catalog.error)),J(e,n)},f=e=>{J(e,of())},p=e=>{var t=lf(),r=V(B(t),2),i=e=>{var t=sf();Z(t,21,()=>G(c),e=>e.planName,(e,t)=>{n(e,()=>G(t))}),N(t),J(e,t)};X(r,e=>{G(c).length>0&&e(i)});var a=V(r,2),o=e=>{var t=cf(),r=V(z(t),2);Z(r,21,()=>G(l),e=>e.planName,(e,t)=>{n(e,()=>G(t))}),N(r),N(t),J(e,t)};X(a,e=>{G(l).length>0&&e(o)}),J(e,t)};X(o,e=>{t.catalog.kind===`no-workspace`?e(s):t.catalog.kind===`loading`?e(u,1):t.catalog.kind===`error`?e(d,2):t.catalog.entries.length===0?e(f,3):e(p,-1)}),N(i),J(e,i)};X(p,e=>{t.state?.kind===`org-source`?e(m):t.state?e(h,1):e(g,-1)}),J(e,f),$e()}Pr([`click`]);var ff=`settings`,pf=`drafts`,mf=`cursors`,hf=`selected-session`,gf={text:``,revision:0},_f=e=>{if(!e||typeof e!=`object`)return!1;let t=e,n=t.pending;return typeof t.text==`string`&&Number.isSafeInteger(t.revision)&&t.revision>=0&&(n===void 0||Array.isArray(n)&&n.every(e=>!!e&&typeof e.operationId==`string`&&typeof e.text==`string`&&Number.isSafeInteger(e.revision)&&e.revision>=0&&(e.kind===`send`||e.kind===`queue`||e.kind===`interrupt-send`)))};function vf(e=globalThis.indexedDB){if(!e)return yf;let t=Rc(e),n=new Map,r=new Map,i=async(e,i)=>{let a=r.get(e);if(a&&a.revision>i.revision)return;r.set(e,i);let o=(n.get(e)??Promise.resolve()).catch(()=>void 0).then(async()=>{if(r.get(e)===i)try{await Bc(await t,pf,e,i)}catch{}});n.set(e,o),await o};return{async readSelectedSession(){try{return await zc(await t,ff,hf)??null}catch{return null}},async saveSelectedSession(e){try{let n=await t;e?await Bc(n,ff,hf,e):await Vc(n,ff,hf)}catch{}},async readDraft(e){return(await this.readDraftEnvelope(e)).text},async saveDraft(e,t){let n=await this.readDraftEnvelope(e);await i(e,{text:t,revision:n.revision+1})},async readDraftEnvelope(e){try{let n=await zc(await t,pf,e),i=_f(n)?n:typeof n==`string`?{text:n,revision:0}:gf,a=r.get(e);return a&&a.revision>=i.revision?a:(r.set(e,i),i)}catch{return r.get(e)??gf}},saveDraftEnvelope:i,replaceDraftText:async(e,t,n)=>{let a=r.get(e);await i(e,{text:t,revision:n,pending:a?.pending})},addPendingDraftOperation:async(e,t)=>{let n=r.get(e)??gf;await i(e,{...n,pending:[...(n.pending??[]).filter(e=>e.operationId!==t.operationId),t].slice(-8)})},consumeAcceptedDraft:async(e,i,a)=>{let o=n.get(e)??Promise.resolve(),s=null,c=o.catch(()=>void 0).then(async()=>{let n=r.get(e);if(!n)try{let r=await zc(await t,pf,e);n=_f(r)?r:typeof r==`string`?{text:r,revision:0}:gf}catch{n=gf}if(!(n.revision!==i||!n.pending?.some(e=>e.operationId===a))){s={text:``,revision:n.revision+1,pending:n.pending.filter(e=>e.operationId!==a)},r.set(e,s);try{await Bc(await t,pf,e,s)}catch{r.get(e)===s&&r.set(e,n),s=null}}});return n.set(e,c),await c,s},async readCursor(e){try{let n=await zc(await t,mf,e);return typeof n==`number`&&Number.isSafeInteger(n)&&n>=0?n:0}catch{return 0}},async saveCursor(e,n){try{await Bc(await t,mf,e,n)}catch{}}}}var yf={readSelectedSession:async()=>null,saveSelectedSession:async()=>{},readDraft:async()=>``,saveDraft:async()=>{},readDraftEnvelope:async()=>gf,saveDraftEnvelope:async()=>{},replaceDraftText:async()=>{},addPendingDraftOperation:async()=>{},consumeAcceptedDraft:async()=>null,readCursor:async()=>0,saveCursor:async()=>{}};function bf(e,t=Date.now()){if(e===null)return`Unknown activity time`;let n=Math.max(0,t-e),r=Math.floor(n/(3600*1e3));if(r<1)return`Less than an hour ago`;if(r<24)return`${r} hour${r===1?``:`s`} ago`;let i=Math.floor(r/24);return`${i} day${i===1?``:`s`} ago`}function xf(e){let t=e.updatedAt?Date.parse(e.updatedAt):NaN;return{threadId:e.threadId??null,workspacePath:e.workspacePath??`Workspace unavailable`,updatedAt:Number.isFinite(t)?t:null}}function Sf(e,t){if(!t?.threadId||!t.workspacePath||!t.resumeCommand||e.some(e=>e.id===t.threadId&&(e.provider??`codex`)===(t.provider??`codex`)))return e;let n=t.updatedAt?Date.parse(t.updatedAt)/1e3:NaN,r={id:t.threadId,cwd:t.workspacePath,recencyAt:Number.isFinite(n)?n:null,resumeCommand:t.resumeCommand,...t.provider===void 0?{}:{provider:t.provider},...t.model===void 0?{}:{model:t.model},...t.effectiveSkillSelection?.selectedProfileName===void 0?{}:{skillProfile:t.effectiveSkillSelection.selectedProfileName},...t.lastOrgPlan===void 0?{}:{orgPlanFilename:t.lastOrgPlan.filename}};return[...e,r].sort((e,t)=>(t.recencyAt??-1/0)-(e.recencyAt??-1/0))}function Cf(e){let t=/^\/home\/[^/]+/.exec(e)?.[0];if(!t)return e;let n=e.slice(t.length);return n?`~${n}`:`~/`}function wf(e,t){let n=Date.parse(e);if(!Number.isFinite(n))return`Updated recently`;let r=Math.max(0,Math.floor((t-n)/1e3));return r<5?`Updated just now`:r<60?`Updated ${r}s ago`:`Updated ${Math.floor(r/60)}m ago`}var Tf=q(`<time class="svelte-2szxr9"> </time>`),Ef=q(`<span role="status"><span aria-hidden="true" class="dot svelte-2szxr9"></span> <span class="svelte-2szxr9"> </span> <!></span>`);function Df(e,t){Qe(t,!0);let n=$(t,`connected`,3,!0),r=P(()=>n()?t.autopilot?.state??`unknown`:`disconnected`),i=P(()=>!!t.autopilot?.health?.healthy),a=I(R(Date.now())),o=I(R(typeof document>`u`||document.visibilityState!==`hidden`)),s=P(()=>G(r)===`disconnected`?`Autopilot disconnected`:G(r)===`attentionRequired`?`Autopilot needs attention`:G(r)===`safetyPaused`?`Autopilot safety paused`:G(i)?`Autopilot continuation active`:`Autopilot continuation inactive`);function c(){L(o,document.visibilityState!==`hidden`),G(o)&&L(a,Date.now(),!0)}Mn(()=>{if(!G(i)||!G(o))return;let e=window.setInterval(()=>L(a,Date.now(),!0),1e3);return()=>window.clearInterval(e)});var l=Ef();Nr(`visibilitychange`,un,c);let u;var d=V(z(l),2),f=z(d,!0);N(d);var p=V(d,2),m=e=>{var n=Tf(),r=z(n,!0);N(n),H(e=>{Q(n,`datetime`,t.autopilot.updatedAt),Y(r,e)},[()=>wf(t.autopilot.updatedAt,G(a))]),J(e,n)};X(p,e=>{t.autopilot&&G(i)&&e(m)}),N(l),H(()=>{u=gi(l,1,`liveness svelte-2szxr9`,null,u,{active:G(i)}),Q(l,`data-state`,G(r)),Q(l,`aria-label`,G(s)),Y(f,G(s))}),J(e,l),$e()}var Of=q(`<details class="session-verdict svelte-hxb22h"><summary class="svelte-hxb22h"><span aria-hidden="true"></span> </summary> <p class="svelte-hxb22h"> </p></details>`),kf=q(`<time class="svelte-hxb22h"> </time>`),Af=q(`<div class="svelte-hxb22h"> </div>`),jf=q(`<span class="profile-badge svelte-hxb22h"> </span>`),Mf=q(`<span class="profile-badge svelte-hxb22h">Kimi</span>`),Nf=q(`<span class="org-plan-metadata svelte-hxb22h"><span class="org-plan-title svelte-hxb22h"> </span> <span class="org-plan-filename svelte-hxb22h"> </span></span>`),Pf=q(`<div class="session-plan-progress svelte-hxb22h"><!></div>`),Ff=q(`<li><div class="session-actions svelte-hxb22h" aria-label="Session actions"><!> <!> <!> <!> <!> <!></div> <div class="session-details svelte-hxb22h"><div class="session-summary svelte-hxb22h"><!> <!> <div class="workspace-path svelte-hxb22h"> </div> <!> <!> <!> <!> <!> <!></div> <!> <!></div></li>`),If=q(`<section aria-labelledby="open-sessions-title" class="svelte-hxb22h"><h3 id="open-sessions-title" class="svelte-hxb22h">Open sessions</h3> <ul class="session-list svelte-hxb22h" aria-label="Open sessions"></ul></section>`),Lf=q(`<li class="managed-session svelte-hxb22h"><div class="session-actions svelte-hxb22h"><!> <!> <!></div> <div class="session-details svelte-hxb22h"><!> <div class="workspace-path svelte-hxb22h"> </div> <!> <!> <!> <!></div></li>`),Rf=q(`<ul class="session-list svelte-hxb22h" aria-label="Saved sessions"></ul>`),zf=q(`<p class="svelte-hxb22h">No saved sessions yet.</p>`),Bf=q(`<label for="sandbox" class="svelte-hxb22h">Sandbox</label> <label for="approval-policy" class="svelte-hxb22h">Approval policy</label>`,1),Vf=q(`<option class="svelte-hxb22h"> </option>`),Hf=q(`<select id="sandbox" class="svelte-hxb22h"><option class="svelte-hxb22h">workspace-git (Git writable)</option><option class="svelte-hxb22h">workspace-write</option><option class="svelte-hxb22h">read-only</option><option class="svelte-hxb22h">danger-full-access</option></select> <select id="approval-policy" aria-describedby="approval-policy-help" class="svelte-hxb22h"><option class="svelte-hxb22h">Ask on all commands</option><option class="svelte-hxb22h">Ask out of workspace</option><option class="svelte-hxb22h">Approve everything</option></select>`,1),Uf=q(`<p id="approval-policy-help" class="svelte-hxb22h"> </p>`),Wf=q(`<p class="skills-profile-error svelte-hxb22h" role="alert"> </p>`),Gf=q(`<option class="svelte-hxb22h">Loading models…</option>`),Kf=q(`<option class="svelte-hxb22h">Choose automatically</option>`),qf=q(`<p id="provider-availability" class="provider-availability svelte-hxb22h">Kimi is unavailable because its CLI was not found when the relay started.</p>`),Jf=q(`<li class="recent-session svelte-hxb22h"><div class="session-details svelte-hxb22h"><!> <div class="workspace-path svelte-hxb22h"> </div> <!> <!> <!> <!></div> <div class="session-actions svelte-hxb22h"><!> <!></div></li>`),Yf=q(`<ul class="session-list recent-session-list svelte-hxb22h" aria-label="Recent sessions"></ul>`),Xf=q(`<p class="svelte-hxb22h">No other recent sessions found.</p>`),Zf=q(`<section aria-labelledby="sessions-title" class="svelte-hxb22h"><h2 id="sessions-title" class="visually-hidden svelte-hxb22h">Sessions</h2> <!> <!> <form class="svelte-hxb22h"><section class="session-base svelte-hxb22h" aria-labelledby="session-base-title"><div class="session-base-heading svelte-hxb22h"><h3 id="session-base-title" class="svelte-hxb22h">Session base</h3> <p class="svelte-hxb22h"> </p></div> <!></section> <section class="session-settings svelte-hxb22h" aria-label="New session settings"><div class="session-setting-labels svelte-hxb22h"><label for="skills-profile" class="svelte-hxb22h">Skills profile</label> <!></div> <div class="session-setting-controls svelte-hxb22h"><select id="skills-profile" class="svelte-hxb22h"><option class="svelte-hxb22h">Default</option><!></select> <!></div> <!> <!> <div class="session-secondary-actions svelte-hxb22h"><!> <div class="model-control svelte-hxb22h"><label for="session-provider" class="svelte-hxb22h">Provider</label> <select id="session-provider" class="svelte-hxb22h"><option class="svelte-hxb22h">Codex</option><option class="svelte-hxb22h"> </option></select></div> <div class="model-control svelte-hxb22h"><label for="model" class="svelte-hxb22h"> </label> <select id="model" class="svelte-hxb22h"><!><!></select></div> <!></div> <!></section></form> <section aria-labelledby="recent-sessions-title" class="svelte-hxb22h"><h3 id="recent-sessions-title" class="svelte-hxb22h">Recent sessions</h3> <!></section></section>`);function Qf(e,t){Qe(t,!0);let n=$(t,`activitySnapshots`,19,()=>new Map),r=$(t,`autopilotSnapshots`,19,()=>new Map),i=$(t,`autopilotPending`,19,()=>new Set),a=$(t,`autopilotAttention`,19,()=>new Map),o=$(t,`models`,19,()=>[]),s=$(t,`selectedModel`,3,``),c=$(t,`provider`,3,`codex`),l=$(t,`kimiAvailable`,3,!1),u=$(t,`modelsLoading`,3,!1),d=$(t,`onmodelchange`,3,()=>{}),f=$(t,`onproviderchange`,3,()=>{}),p=$(t,`onautopilottoggle`,3,()=>{}),m=$(t,`onactivityopen`,3,()=>{}),h=$(t,`onautopilotresolve`,3,()=>{}),g=P(()=>t.sessions.filter(e=>e.state===`ready`||e.state===`turnActive`)),_=P(()=>t.sessions.filter(e=>e.state!==`ready`&&e.state!==`turnActive`)),v=P(()=>t.recentSessions.filter(e=>!G(g).some(t=>t.threadId===e.id&&(t.provider??`codex`)===(e.provider??`codex`)))),y=P(()=>fu(t.workspaceTree,t.workspaceId)),b=P(()=>c()===`kimi`?`Kimi`:`Codex`);var x=Zf(),S=V(z(x),2),C=e=>{var s=If(),c=V(z(s),2);Z(c,21,()=>G(g),e=>e.id,(e,s)=>{let c=P(()=>xf(G(s))),l=P(()=>Vl(G(s).sessionStatus)?G(s).sessionStatus:null);var u=Ff();let d;var f=z(u),g=z(f);{let e=P(()=>G(s).id===t.selectedSessionId?`page`:void 0);Ta(g,{compact:!0,full:!0,get current(){return G(e)},onclick:()=>t.onselectopen(G(s).id),children:(e,t)=>{He(),J(e,Vr(`Open`))},$$slots:{default:!0}})}var _=V(g,2),v=e=>{Ta(e,{compact:!0,full:!0,onclick:()=>t.oncopyresume(G(s).resumeCommand),children:(e,t)=>{He(),J(e,Vr(`Copy`))},$$slots:{default:!0}})};X(_,e=>{G(s).resumeCommand&&G(s).provider!==`kimi`&&e(v)});var y=V(_,2),b=e=>{{let t=P(()=>r().get(G(s).id)??G(s).autopilot??null),n=P(()=>`session-autopilot-${G(s).id}`),a=P(()=>i().has(G(s).id));no(e,{compact:!0,indicatorOnly:!0,get autopilot(){return G(t)},get controlId(){return G(n)},get pending(){return G(a)},ontoggle:e=>p()(G(s).id,e)})}};X(y,e=>{G(s).provider!==`kimi`&&e(b)});var x=V(y,2);{let e=P(()=>n().get(G(s).id)??G(s).agentActivity??null),t=P(()=>G(s).model??o()?.[0]);La(x,{compact:!0,get activity(){return G(e)},popupAlign:`start`,get rootModel(){return G(t)},get plan(){return G(s).plan},onopen:()=>m()(G(s).id)})}var S=V(x,2);Ta(S,{compact:!0,full:!0,onclick:()=>t.onclose(G(s).id),children:(e,t)=>{He(),J(e,Vr(`Close`))},$$slots:{default:!0}});var C=V(S,2),w=e=>{{let t=P(()=>r().get(G(s).id)??G(s).autopilot??null),i=P(()=>(n().get(G(s).id)??G(s).agentActivity)?.root.state!==`disconnected`);Df(e,{get autopilot(){return G(t)},get connected(){return G(i)}})}};X(C,e=>{G(s).provider!==`kimi`&&e(w)}),N(f);var T=V(f,2),E=z(T),D=z(E),ee=e=>{var t=Of(),n=z(t),r=z(n);let i;var a=V(r);N(n);var o=V(n,2),s=z(o);N(o),N(t),H(()=>{Q(t,`data-state`,G(l).state),Q(t,`aria-label`,`${G(l).state===`working`?`Working`:`Idle`}: ${G(l).reason}`),Q(n,`aria-label`,`${G(l).state===`working`?`Working`:`Idle`}: ${G(l).reason}`),i=gi(r,1,`verdict-dot svelte-hxb22h`,null,i,{live:G(l).state===`working`&&G(l).confidence===`fresh`}),Y(a,` ${G(l).state===`working`?`Working`:`Idle`}`),Y(s,`${G(l).reason??``}. ${G(l).nextExpectedAction??``}
26
26
  Evidence confidence: ${G(l).confidence??``}.`)}),J(e,t)};X(D,e=>{G(l)&&e(ee)});var te=V(D,2),ne=e=>{var t=kf(),n=z(t,!0);N(t),H((e,r)=>{Q(t,`datetime`,e),Y(n,r)},[()=>new Date(G(c).updatedAt).toISOString(),()=>bf(G(c).updatedAt)]),J(e,t)},re=e=>{var t=Af(),n=z(t,!0);N(t),H(e=>Y(n,e),[()=>bf(null)]),J(e,t)};X(te,e=>{G(c).updatedAt===null?e(re,-1):e(ne)});var ie=V(te,2),O=z(ie,!0);N(ie);var k=V(ie,2),ae=e=>{var t=jf(),n=z(t);N(t),H(()=>Y(n,`Model: ${G(s).model??``}`)),J(e,t)};X(k,e=>{G(s).model&&e(ae)});var A=V(k,2),oe=e=>{J(e,Mf())};X(A,e=>{G(s).provider===`kimi`&&e(oe)});var se=V(A,2),ce=e=>{var t=jf(),n=z(t);N(t),H(()=>Y(n,`Branch: ${G(s).branch??``}`)),J(e,t)};X(se,e=>{G(s).branch&&e(ce)});var le=V(se,2),ue=e=>{var t=jf(),n=z(t);N(t),H(()=>Y(n,`Skills profile: ${G(s).effectiveSkillSelection.selectedProfileName??``}`)),J(e,t)};X(le,e=>{G(s).effectiveSkillSelection?.selectedProfileName&&e(ue)});var de=V(le,2),fe=e=>{var t=Nf(),n=z(t),r=z(n,!0);N(n);var i=V(n,2),a=z(i,!0);N(i),N(t),H(()=>{Y(r,G(s).lastOrgPlan.title),Y(a,G(s).lastOrgPlan.filename)}),J(e,t)};X(de,e=>{G(s).lastOrgPlan&&e(fe)});var pe=V(de,2),me=e=>{var t=Pf(),n=z(t);{let e=P(()=>`Plan progress for ${G(s).plan.title}`);fd(n,{compact:!0,get plan(){return G(s).plan},get label(){return G(e)}})}N(t),J(e,t)};X(pe,e=>{G(s).plan&&e(me)}),N(E);var he=V(E,2);{let e=P(()=>a().get(G(s).id)??null),t=P(()=>`session-attention-${G(s).id}`),n=P(()=>i().has(G(s).id));io(he,{get attention(){return G(e)},get controlId(){return G(t)},get pending(){return G(n)},onresolve:(e,t)=>h()(G(s).id,e,t)})}var ge=V(he,2);{let e=P(()=>r().get(G(s).id)??G(s).autopilot??null),t=P(()=>a().get(G(s).id)??null),n=P(()=>`session-autopilot-safety-${G(s).id}`),o=P(()=>i().has(G(s).id));oo(ge,{get autopilot(){return G(e)},get attention(){return G(t)},get controlId(){return G(n)},get pending(){return G(o)},onrecover:()=>p()(G(s).id,!0),ondisable:()=>p()(G(s).id,!1)})}N(T),N(u),H(e=>{d=gi(u,1,`managed-session open-session svelte-hxb22h`,null,d,{"current-session":G(s).id===t.selectedSessionId}),Y(O,e)},[()=>Cf(G(c).workspacePath)]),J(e,u)}),N(c),N(s),J(e,s)};X(S,e=>{G(g).length&&e(C)});var w=V(S,2),T=e=>{var n=Rf();Z(n,21,()=>G(_),e=>e.id,(e,n)=>{let r=P(()=>xf(G(n)));var i=Lf(),a=z(i),o=z(a);{let e=P(()=>t.openingSessionId===G(n).id);Ta(o,{compact:!0,full:!0,get disabled(){return G(e)},onclick:()=>t.onopen(G(n).id),children:(e,r)=>{He();var i=Vr();H(()=>Y(i,t.openingSessionId===G(n).id?`Opening…`:`Open`)),J(e,i)},$$slots:{default:!0}})}var s=V(o,2),c=e=>{Ta(e,{compact:!0,full:!0,onclick:()=>t.oncopyresume(G(n).resumeCommand),children:(e,t)=>{He(),J(e,Vr(`Copy`))},$$slots:{default:!0}})};X(s,e=>{G(n).resumeCommand&&G(n).provider!==`kimi`&&e(c)}),Ta(V(s,2),{compact:!0,full:!0,onclick:()=>t.onforget(G(n).id),children:(e,t)=>{He(),J(e,Vr(`Forget`))},$$slots:{default:!0}}),N(a);var l=V(a,2),u=z(l),d=e=>{var t=kf(),n=z(t,!0);N(t),H((e,r)=>{Q(t,`datetime`,e),Y(n,r)},[()=>new Date(G(r).updatedAt).toISOString(),()=>bf(G(r).updatedAt)]),J(e,t)},f=e=>{var t=Af(),n=z(t,!0);N(t),H(e=>Y(n,e),[()=>bf(null)]),J(e,t)};X(u,e=>{G(r).updatedAt===null?e(f,-1):e(d)});var p=V(u,2),m=z(p,!0);N(p);var h=V(p,2),g=e=>{var t=jf(),r=z(t);N(t),H(()=>Y(r,`Model: ${G(n).model??``}`)),J(e,t)};X(h,e=>{G(n).model&&e(g)});var _=V(h,2),v=e=>{J(e,Mf())};X(_,e=>{G(n).provider===`kimi`&&e(v)});var y=V(_,2),b=e=>{var t=jf(),r=z(t);N(t),H(()=>Y(r,`Branch: ${G(n).branch??``}`)),J(e,t)};X(y,e=>{G(n).branch&&e(b)});var x=V(y,2),S=e=>{var t=jf(),r=z(t);N(t),H(()=>Y(r,`Skills profile: ${G(n).effectiveSkillSelection.selectedProfileName??``}`)),J(e,t)};X(x,e=>{G(n).effectiveSkillSelection?.selectedProfileName&&e(S)}),N(l),N(i),H(e=>Y(m,e),[()=>Cf(G(r).workspacePath)]),J(e,i)}),N(n),J(e,n)},E=e=>{J(e,zf())};X(w,e=>{G(_).length?e(T):G(g).length||e(E,1)});var D=V(w,2),ee=z(D),te=z(ee),ne=V(z(te),2),re=z(ne);N(ne),N(te);var ie=V(te,2);{let e=P(()=>G(y)?.id??null);bu(ie,{get roots(){return t.workspaceTree},get expandedIds(){return t.expandedIds},get selectedId(){return G(e)},get isSelectable(){return su.sessionBase},label:`Session base`,get onexpandedchange(){return t.onexpandedchange},onselect:e=>t.onworkspacechange(e.id)})}N(ee);var O=V(ee,2),k=z(O);let ae;var A=V(z(k),2),oe=e=>{var t=Bf();He(2),J(e,t)};X(A,e=>{c()!==`kimi`&&e(oe)}),N(k);var se=V(k,2);let ce;var le=z(se),ue=z(le);ue.value=ue.__value=``,Z(V(ue),17,()=>t.skillProfiles,e=>e.name,(e,t)=>{var n=Vf(),r=z(n,!0);N(n);var i={};H(()=>{Y(r,G(t).name),i!==(i=G(t).name)&&(n.value=(n.__value=G(t).name)??``)}),J(e,n)}),N(le);var de;bi(le);var fe=V(le,2),pe=e=>{var n=Hf(),r=B(n),i=z(r);i.value=i.__value=`workspace-git`;var a=V(i);a.value=a.__value=`workspace-write`;var o=V(a);o.value=o.__value=`read-only`;var s=V(o);s.value=s.__value=`danger-full-access`,N(r);var c;bi(r);var l=V(r,2),u=z(l);u.value=u.__value=`untrusted`;var d=V(u);d.value=d.__value=`on-request`;var f=V(d);f.value=f.__value=`never`,N(l);var p;bi(l),H(()=>{c!==(c=t.sandbox)&&(r.value=(r.__value=t.sandbox)??``,yi(r,t.sandbox)),p!==(p=t.approvalPolicy)&&(l.value=(l.__value=t.approvalPolicy)??``,yi(l,t.approvalPolicy))}),K(`change`,r,e=>t.onsandboxchange(e.currentTarget.value)),K(`change`,l,e=>t.onapprovalpolicychange(e.currentTarget.value)),J(e,n)};X(fe,e=>{c()!==`kimi`&&e(pe)}),N(se);var me=V(se,2),he=e=>{var t=Uf(),n=z(t);N(t),H(()=>Y(n,`This controls when ${G(b)??``} asks; it does not expand the sandbox's technical permissions.`)),J(e,t)};X(me,e=>{c()!==`kimi`&&e(he)});var ge=V(me,2),_e=e=>{var n=Wf(),r=z(n,!0);N(n),H(()=>Y(r,t.skillProfileError)),J(e,n)};X(ge,e=>{t.skillProfileError&&e(_e)});var ve=V(ge,2),ye=z(ve);Ta(ye,{id:`manage-skill-profiles`,onclick:e=>t.onmanageprofiles(e.currentTarget),children:(e,t)=>{He(),J(e,Vr(`Manage skill profiles`))},$$slots:{default:!0}});var be=V(ye,2),xe=V(z(be),2),Se=z(xe);Se.value=Se.__value=`codex`;var Ce=V(Se),we=z(Ce);N(Ce),Ce.value=Ce.__value=`kimi`,N(xe);var Te;bi(xe),N(be);var Ee=V(be,2),De=z(Ee),Oe=z(De);N(De);var ke=V(De,2),Ae=z(ke),je=e=>{var t=Gf();t.value=t.__value=``,J(e,t)},Me=e=>{var t=Kf();t.value=t.__value=``,J(e,t)};X(Ae,e=>{u()?e(je):o().length===0&&e(Me,1)}),Z(V(Ae),16,o,e=>e,(e,t)=>{var n=Vf(),r=z(n,!0);N(n);var i={};H(()=>{Y(r,t),i!==(i=t)&&(n.value=(n.__value=t)??``)}),J(e,n)}),N(ke);var Ne;bi(ke),N(Ee);var Pe=V(Ee,2);{let e=P(()=>!G(y)||t.startingSession||u()||o().length>0&&!s());Ta(Pe,{class:`new-session-button`,type:`submit`,primary:!0,get disabled(){return G(e)},children:(e,n)=>{He();var r=Vr();H(()=>Y(r,t.startingSession?`Creating…`:`Create session`)),J(e,r)},$$slots:{default:!0}})}N(ve);var Fe=V(ve,2),Ie=e=>{J(e,qf())};X(Fe,e=>{l()||e(Ie)}),N(O),N(D);var Le=V(D,2),Re=V(z(Le),2),j=e=>{var n=Yf();Z(n,21,()=>G(v),e=>(e.provider??`codex`)+`:`+e.id,(e,n)=>{var r=Jf(),i=z(r),a=z(i),o=e=>{var t=kf(),r=z(t,!0);N(t),H((e,n)=>{Q(t,`datetime`,e),Y(r,n)},[()=>new Date(G(n).recencyAt*1e3).toISOString(),()=>bf(G(n).recencyAt*1e3)]),J(e,t)},s=e=>{var t=Af(),n=z(t,!0);N(t),H(e=>Y(n,e),[()=>bf(null)]),J(e,t)};X(a,e=>{G(n).recencyAt===null?e(s,-1):e(o)});var c=V(a,2),l=z(c,!0);N(c);var u=V(c,2),d=e=>{var t=jf(),r=z(t);N(t),H(()=>Y(r,`Model: ${G(n).model??``}`)),J(e,t)};X(u,e=>{G(n).model&&e(d)});var f=V(u,2),p=e=>{J(e,Mf())};X(f,e=>{G(n).provider===`kimi`&&e(p)});var m=V(f,2),h=e=>{var t=jf(),r=z(t);N(t),H(()=>Y(r,`Skills profile: ${G(n).skillProfile??``}`)),J(e,t)};X(m,e=>{G(n).skillProfile&&e(h)});var g=V(m,2),_=e=>{var t=jf(),r=z(t);N(t),H(()=>Y(r,`Org plan: ${G(n).orgPlanFilename??``}`)),J(e,t)};X(g,e=>{G(n).orgPlanFilename&&e(_)}),N(i);var v=V(i,2),y=z(v);Ta(y,{onclick:()=>t.onopenrecent(G(n)),children:(e,t)=>{He(),J(e,Vr(`Open`))},$$slots:{default:!0}});var b=V(y,2),x=e=>{Ta(e,{onclick:()=>t.oncopyresume(G(n).resumeCommand),children:(e,t)=>{He(),J(e,Vr(`Copy`))},$$slots:{default:!0}})};X(b,e=>{G(n).resumeCommand&&e(x)}),N(v),N(r),H(e=>Y(l,e),[()=>Cf(G(n).cwd)]),J(e,r)}),N(n),J(e,n)},ze=e=>{J(e,Xf())};X(Re,e=>{G(v).length?e(j):e(ze,-1)}),N(Le),N(x),H(()=>{Y(re,`Select the folder or repository ${G(b)??``} should use as its working directory.`),ae=vi(k,``,ae,{"grid-template-columns":c()===`kimi`?`minmax(0, 1fr)`:`repeat(3, minmax(0, 1fr))`}),ce=vi(se,``,ce,{"grid-template-columns":c()===`kimi`?`minmax(0, 1fr)`:`repeat(3, minmax(0, 1fr))`}),de!==(de=t.selectedSkillProfile)&&(le.value=(le.__value=t.selectedSkillProfile)??``,yi(le,t.selectedSkillProfile)),Q(xe,`aria-describedby`,l()?void 0:`provider-availability`),Ce.disabled=!l(),Y(we,`Kimi${l()?``:` (unavailable)`}`),Te!==(Te=c())&&(xe.value=(xe.__value=c())??``,yi(xe,c())),Y(Oe,`${G(b)??``} model`),ke.disabled=u()||o().length===0,Ne!==(Ne=s())&&(ke.value=(ke.__value=s())??``,yi(ke,s()))}),Nr(`submit`,D,e=>{e.preventDefault(),t.onstart()}),K(`change`,le,e=>t.onskillprofilechange(e.currentTarget.value)),K(`change`,xe,e=>f()(e.currentTarget.value)),K(`change`,ke,e=>d()(e.currentTarget.value)),J(e,x),$e()}Pr([`change`]);function $f(e){let t={};return e.workspaceId||(t.workspaceId=`Choose a workspace.`),e.profile||(t.profile=`Choose a profile.`),e.profile&&e.profileState&&e.profileState!==`ok`&&(t.profile=`Sign in to this profile before starting Codex.`),t}var ep=class{transport;key;onChange;#e={starting:!1,error:null};#t=0;#n=!1;#r=null;constructor(e,t,n){this.transport=e,this.key=t,this.onChange=n}get state(){return this.#e}async start(e,t){if(this.#n||this.#e.starting||!e)return null;let n=++this.#t;this.#a({starting:!0,error:null});let r=this.#r??=this.key();try{let i=await this.transport.start(e,t,r);return this.#i(n)&&(this.#r=null),this.#i(n)?i:null}catch(e){return this.#i(n)&&this.#a({starting:!1,error:e instanceof Error?e.message:`Could not start session.`}),null}finally{this.#i(n)&&this.#a({...this.#e,starting:!1})}}dispose(){this.#n=!0,++this.#t}#i(e){return!this.#n&&e===this.#t}#a(e){this.#n||(this.#e=e,this.onChange(e))}};function tp({chatEnabled:e}){return[`sessions`,`git`,...e?[`chat`]:[],`plan`]}function np(e,t,n={chatEnabled:!0}){let r=tp(n);return r[(r.indexOf(e)+t+r.length)%r.length]}var rp=q(`<nav class="bottom-navigation" aria-label="Primary"><button>Sessions</button> <button>Git</button> <button>Chat</button> <button>Plan</button></nav>`);function ip(e,t){Qe(t,!0);let n=$(t,`focusTab`,3,null),r=R({});Mn(()=>{n()&&r[n()]?.focus()});function i(e){let n=e.key===`ArrowRight`?1:e.key===`ArrowLeft`?-1:null;if(n===null)return;e.preventDefault();let i=np(t.activeTab,n,{chatEnabled:t.chatEnabled});t.onselect(i),r[i]?.focus()}var a=rp(),o=z(a);Li(o,e=>r.sessions=e,()=>r?.sessions);var s=V(o,2);Li(s,e=>r.git=e,()=>r?.git);var c=V(s,2);Li(c,e=>r.chat=e,()=>r?.chat);var l=V(c,2);Li(l,e=>r.plan=e,()=>r?.plan),N(a),H(()=>{Q(o,`aria-pressed`,t.activeTab===`sessions`),Q(s,`aria-pressed`,t.activeTab===`git`),Q(c,`aria-pressed`,t.activeTab===`chat`),c.disabled=!t.chatEnabled,Q(l,`aria-pressed`,t.activeTab===`plan`)}),K(`keydown`,o,i),K(`click`,o,()=>t.onselect(`sessions`)),K(`keydown`,s,i),K(`click`,s,()=>t.onselect(`git`)),K(`keydown`,c,i),K(`click`,c,()=>t.onselect(`chat`)),K(`keydown`,l,i),K(`click`,l,()=>t.onselect(`plan`)),J(e,a),$e()}Pr([`keydown`,`click`]);var ap=q(`<option> </option>`),op=q(`<p id="skills-status" aria-live="polite">Loading skills…</p>`),sp=q(`<p id="skills-status">No skills were discovered for this workspace and Codex profile.</p>`),cp=q(`<p id="skills-status" class="notice svelte-dg6sjj" role="status"> </p>`),lp=q(`<p id="skills-status" class="error svelte-dg6sjj" role="alert"> </p>`),up=q(`<p id="skills-status" class="error svelte-dg6sjj" role="alert" tabindex="-1"> </p>`),dp=q(`<p id="skills-status" role="status">Profile saved.</p>`),fp=q(`<p id="skills-status" role="status">Profile deleted.</p>`),pp=q(`<li class="svelte-dg6sjj"><div class="svelte-dg6sjj"><strong> </strong> <span class="missing-state svelte-dg6sjj">Missing · disabled</span> <span class="path svelte-dg6sjj"> </span></div> <button type="button" class="remove-missing svelte-dg6sjj">Remove</button></li>`),mp=q(`<section class="missing-skills svelte-dg6sjj" aria-labelledby="missing-skills-title"><h3 id="missing-skills-title" class="svelte-dg6sjj">Missing skills</h3> <p class="svelte-dg6sjj">These saved paths no longer exist. They are disabled for new sessions until restored or
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
16
16
  <link rel="icon" href="/icons/gestalt-mobile-192.png" />
17
17
  <link rel="apple-touch-icon" href="/icons/gestalt-mobile-180.png" />
18
18
  <title>Gestalt Mobile</title>
19
- <script type="module" crossorigin src="/assets/index-G2PznC5F.js"></script>
19
+ <script type="module" crossorigin src="/assets/index-9uZwieND.js"></script>
20
20
  <link rel="stylesheet" crossorigin href="/assets/index-D57mr3B1.css">
21
21
  </head>
22
22
  <body>
@@ -19,7 +19,7 @@ import { authorizationSessionId, authorizedDeviceId, localOwnerId, webAuthnCrede
19
19
  import { deviceNickname } from './features/auth/domain/device-nickname.js';
20
20
  import { workspaceId } from './platform/catalog/workspace-id.js';
21
21
  import { planStatusDirectoryPath, planStatusFilePath, } from './platform/plans/filesystem-plan-status-source.js';
22
- import { toOrgPlanAttentionToolResponse } from '../shared/contracts/org-plan-attention.js';
22
+ import { toOrgPlanAttentionAcknowledgement, toOrgPlanAttentionToolResponse, } from '../shared/contracts/org-plan-attention.js';
23
23
  import { toOrgPlanCheckpointToolResponse } from '../shared/contracts/org-plan-checkpoint.js';
24
24
  import { applyProjectionEvent, createChatProjection, } from '../client/features/chat/chat-projection.js';
25
25
  function fakeAppServer(calls) {
@@ -153,6 +153,25 @@ const autopilotPlanText = (childState = 'TODO') => `#+TITLE: Autopilot fixture
153
153
  const completedAutopilotPlanText = () => autopilotPlanText('DONE')
154
154
  .replace('* WIP [#A] Parent', '* DONE [#A] Parent')
155
155
  .replace(':REVIEW_STATUS: UNREVIEWED', ':REVIEW_STATUS: REVIEWED');
156
+ const acceptedL1WithNextTodoPlanText = () => `${completedAutopilotPlanText()}
157
+ * TODO [#B] Next parent
158
+ :PROPERTIES:
159
+ :ID: next-parent
160
+ :SKILLS: $gestalt:org-plan
161
+ :REVIEW_STATUS: UNREVIEWED
162
+ :END:
163
+ - Effort :: Small
164
+ - Goal :: Continue on the next root turn.
165
+ - Notes :: Must remain pending at the accepted-L1 boundary.
166
+ ** TODO [#B] Next child
167
+ :PROPERTIES:
168
+ :ID: next-child
169
+ :END:
170
+ - Why :: Verify boundary separation.
171
+ - Change :: Start only after durable handoff.
172
+ - Tests :: Exercise the next continuation.
173
+ - Done when :: The next L1 starts exactly once.
174
+ `;
156
175
  async function installAutopilotPlan(app, sessionId, workspacePath, name, childState = 'TODO', reason = 'supervision-start') {
157
176
  const planPath = join(workspacePath, `${name}.org`);
158
177
  await writeFile(planPath, autopilotPlanText(childState));
@@ -958,6 +977,83 @@ describe('production composition', () => {
958
977
  expect(checkpoint.count).toBe(1);
959
978
  await fixture.app.close();
960
979
  });
980
+ it('records and idempotently replays accepted L1 after REVIEWED advances to the next TODO L1', async () => {
981
+ const timers = [];
982
+ const fixture = await createProductionAutopilotFixture({
983
+ autopilotSchedule: (callback) => {
984
+ const timer = { callback, cancelled: false, fired: false };
985
+ timers.push(timer);
986
+ return () => {
987
+ timer.cancelled = true;
988
+ };
989
+ },
990
+ });
991
+ const initial = timers.find((timer) => !timer.cancelled && !timer.fired);
992
+ initial.fired = true;
993
+ initial.callback();
994
+ await vi.waitFor(() => expect(fixture.handles.flatMap((candidate) => candidate.requests.filter((request) => request.method === 'turn/start'))).toHaveLength(1));
995
+ const handle = fixture.handles.find((candidate) => candidate.request);
996
+ const session = (await fixture.app.inject(`/api/sessions/${fixture.sessionId}`)).json();
997
+ const threadId = session.threadId;
998
+ const turnId = session.activeTurnId;
999
+ await writeFile(join(fixture.workspacePath, 'autopilot.org'), acceptedL1WithNextTodoPlanText());
1000
+ await expect
1001
+ .poll(async () => (await fixture.app.inject(`/api/sessions/${fixture.sessionId}/plan`)).json()
1002
+ .currentStepId)
1003
+ .toBe('next-parent');
1004
+ handle.deferResponseSettlement = true;
1005
+ const checkpointCall = (id) => ({
1006
+ id,
1007
+ method: 'item/tool/call',
1008
+ params: {
1009
+ threadId,
1010
+ turnId,
1011
+ tool: 'gestalt_org_plan_checkpoint',
1012
+ arguments: { kind: 'l1Accepted' },
1013
+ },
1014
+ });
1015
+ const startsBefore = fixture.handles
1016
+ .flatMap((candidate) => candidate.requests)
1017
+ .filter((request) => request.method === 'turn/start').length;
1018
+ const first = handle.request(checkpointCall(813));
1019
+ await vi.waitFor(() => expect(handle.pendingResponses.has(813)).toBe(true));
1020
+ handle.responseSettled({ id: 813, outcome: 'resultWritten' });
1021
+ await expect(first).resolves.toEqual(toOrgPlanCheckpointToolResponse('recorded'));
1022
+ const replay = handle.request(checkpointCall(814));
1023
+ await vi.waitFor(() => expect(handle.pendingResponses.has(814)).toBe(true));
1024
+ handle.responseSettled({ id: 814, outcome: 'resultWritten' });
1025
+ await expect(replay).resolves.toEqual(toOrgPlanCheckpointToolResponse('alreadyRecorded'));
1026
+ const database = new DatabaseSync(join(fixture.dataDir, 'relay.sqlite'));
1027
+ const acceptedEvents = database
1028
+ .prepare("SELECT count(*) AS count FROM session_events WHERE session_id = ? AND type = 'org-plan.milestone-checkpointed'")
1029
+ .get(fixture.sessionId);
1030
+ const pendingInteractions = database
1031
+ .prepare('SELECT count(*) AS count FROM pending_interactions WHERE session_id = ? AND resolved_at IS NULL')
1032
+ .get(fixture.sessionId);
1033
+ database.close();
1034
+ expect(acceptedEvents.count).toBe(1);
1035
+ expect(pendingInteractions.count).toBe(0);
1036
+ expect(fixture.handles
1037
+ .flatMap((candidate) => candidate.requests)
1038
+ .filter((request) => request.method === 'turn/start')).toHaveLength(startsBefore);
1039
+ handle.notify({ method: 'turn/completed', params: { threadId, turn: { id: turnId } } });
1040
+ await expect
1041
+ .poll(async () => (await fixture.app.inject(`/api/sessions/${fixture.sessionId}`)).json().activeTurnId)
1042
+ .toBeNull();
1043
+ const startedTurns = () => fixture.handles
1044
+ .flatMap((candidate) => candidate.requests)
1045
+ .filter((request) => request.method === 'turn/start').length;
1046
+ for (let attempts = 0; attempts < 3 && startedTurns() === startsBefore; attempts += 1) {
1047
+ await vi.waitFor(() => expect(timers.find((timer) => !timer.cancelled && !timer.fired)).toBeDefined());
1048
+ const continuation = timers.find((timer) => !timer.cancelled && !timer.fired);
1049
+ continuation.fired = true;
1050
+ continuation.callback();
1051
+ await vi.waitFor(() => expect(startedTurns() > startsBefore ||
1052
+ timers.some((timer) => !timer.cancelled && !timer.fired)).toBe(true));
1053
+ }
1054
+ await vi.waitFor(() => expect(startedTurns()).toBe(startsBefore + 1));
1055
+ await fixture.app.close();
1056
+ });
961
1057
  it('returns a typed failed checkpoint result when persistence never occurs', async () => {
962
1058
  let coordinator;
963
1059
  const timers = [];
@@ -980,7 +1076,13 @@ describe('production composition', () => {
980
1076
  const { handle, response, startsBefore, writersBefore } = await holdCheckpointRequest(fixture, timers, 995, false);
981
1077
  await vi.waitFor(() => expect(handle.pendingResponses.has(995)).toBe(true));
982
1078
  handle.responseSettled({ id: 995, outcome: 'resultWritten' });
983
- await expect(response).resolves.toEqual(toOrgPlanCheckpointToolResponse('failed'));
1079
+ const failure = (await response);
1080
+ expect(failure.success).toBe(false);
1081
+ expect(JSON.parse(failure.contentItems[0].text)).toMatchObject({
1082
+ status: 'failed',
1083
+ reasonCode: 'checkpointPersistenceFailed',
1084
+ correlationId: expect.any(String),
1085
+ });
984
1086
  expect(coordinator.checkpointAccepted).not.toBe(original);
985
1087
  expect(fixture.handles).toHaveLength(writersBefore);
986
1088
  expect(fixture.handles
@@ -1340,7 +1442,13 @@ describe('production composition', () => {
1340
1442
  const planIdentity = createHash('sha256')
1341
1443
  .update(join(fixture.workspacePath, 'autopilot.org'))
1342
1444
  .digest('hex');
1343
- await expect(handle.request(l2CheckpointCall(812, threadId, active.active_turn_id, planIdentity))).resolves.toEqual(toOrgPlanCheckpointToolResponse('failed'));
1445
+ const rejected = (await handle.request(l2CheckpointCall(812, threadId, active.active_turn_id, planIdentity)));
1446
+ expect(rejected.success).toBe(false);
1447
+ expect(JSON.parse(rejected.contentItems[0].text)).toMatchObject({
1448
+ status: 'failed',
1449
+ reasonCode: 'rootNotOwner',
1450
+ correlationId: expect.any(String),
1451
+ });
1344
1452
  expect(timers).toHaveLength(timersAfterFinal);
1345
1453
  expect(fixture.handles
1346
1454
  .flatMap((candidate) => candidate.requests)
@@ -1356,6 +1464,7 @@ describe('production composition', () => {
1356
1464
  payload: { enabled: true },
1357
1465
  })).statusCode).toBe(200);
1358
1466
  const attention = handle.request(attentionCall(810));
1467
+ await expect(attention).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
1359
1468
  await vi.waitFor(async () => expect((await fixture.app.inject(`/api/sessions/${fixture.sessionId}`)).json()).toMatchObject({
1360
1469
  autopilot: { state: 'attentionRequired', enabled: false, reason: 'attentionRequired' },
1361
1470
  }));
@@ -1365,7 +1474,6 @@ describe('production composition', () => {
1365
1474
  url: `/api/sessions/${fixture.sessionId}/attention/810/resolve`,
1366
1475
  payload: { operationKey: 'resume-attention', action: 'resume' },
1367
1476
  })).statusCode).toBe(202);
1368
- await expect(attention).resolves.toEqual(toOrgPlanAttentionToolResponse({ action: 'resume' }));
1369
1477
  await new Promise((resolve) => setTimeout(resolve, 25));
1370
1478
  expect((await fixture.app.inject(`/api/sessions/${fixture.sessionId}`)).json()).toMatchObject({
1371
1479
  autopilot: { state: 'attentionRequired', enabled: false },
@@ -1959,6 +2067,56 @@ describe('production composition', () => {
1959
2067
  });
1960
2068
  });
1961
2069
  describeCompositionConcern('attention', () => {
2070
+ it('bounds a wedged attention acknowledgement writer without losing durable attention', async () => {
2071
+ const fixture = await createProductionAutopilotFixture({
2072
+ attentionAcknowledgementDeadlineMs: 100,
2073
+ });
2074
+ const handle = fixture.handles.find((candidate) => candidate.request);
2075
+ handle.deferResponseSettlement = true;
2076
+ const response = handle.request(attentionCall(699));
2077
+ const rejected = expect(response).rejects.toThrow('CODEX_SERVER_REQUEST_CANCELLED');
2078
+ await vi.waitFor(() => expect(handle.pendingResponses.has(699)).toBe(true));
2079
+ await rejected;
2080
+ expect((await fixture.app.inject(`/api/sessions/${fixture.sessionId}/attention`)).json()).toMatchObject({ requestId: '699', attention: { reason: 'hardBlock' } });
2081
+ await fixture.app.close();
2082
+ });
2083
+ it('returns a bounded failure when durable attention persistence fails', async () => {
2084
+ const root = await mkdtemp(join(tmpdir(), 'gestalt-mobile-root-'));
2085
+ const dataDir = await mkdtemp(join(tmpdir(), 'gestalt-mobile-state-'));
2086
+ ownTemporaryPaths(root, dataDir);
2087
+ await mkdir(join(root, 'workspace'));
2088
+ const handles = [];
2089
+ const app = await composeAuthorizedApp({
2090
+ root,
2091
+ dataDir,
2092
+ relyingParty,
2093
+ installedCodexVersion: 'codex-cli 0.144.3',
2094
+ startAppServers: true,
2095
+ launchAppServer: liveAppServer(handles),
2096
+ profiles: {
2097
+ list: async () => [],
2098
+ require: async () => ({
2099
+ name: 'default',
2100
+ state: 'ok',
2101
+ status: 'ready',
2102
+ }),
2103
+ },
2104
+ });
2105
+ await createComposedSession(app);
2106
+ const handle = await vi.waitFor(() => {
2107
+ const candidate = handles.find((item) => item.request);
2108
+ expect(candidate).toBeDefined();
2109
+ return candidate;
2110
+ });
2111
+ const database = new DatabaseSync(join(dataDir, 'relay.sqlite'));
2112
+ database.exec(`CREATE TRIGGER reject_attention_insert
2113
+ BEFORE INSERT ON pending_interactions
2114
+ WHEN NEW.kind = 'orgPlanAttention'
2115
+ BEGIN SELECT RAISE(ABORT, 'injected attention persistence failure'); END`);
2116
+ database.close();
2117
+ await expect(handle.request(attentionCall(700))).resolves.toEqual(toOrgPlanAttentionAcknowledgement({ accepted: false, reason: 'persistenceFailed' }));
2118
+ await app.close();
2119
+ });
1962
2120
  it('publishes isolated typed required, resolved, and failed attention transitions through the feature-only seam', async () => {
1963
2121
  const root = await mkdtemp(join(tmpdir(), 'gestalt-mobile-root-'));
1964
2122
  const dataDir = await mkdtemp(join(tmpdir(), 'gestalt-mobile-state-'));
@@ -2004,6 +2162,7 @@ describe('production composition', () => {
2004
2162
  const unsubscribeA = transitions.subscribe(sessionA, (event) => receivedA.push(event));
2005
2163
  const unsubscribeB = transitions.subscribe(sessionB, (event) => receivedB.push(event));
2006
2164
  const resolving = handleA.request(attentionCall(701));
2165
+ await expect(resolving).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2007
2166
  await vi.waitFor(() => expect(receivedA).toEqual([
2008
2167
  expect.objectContaining({ kind: 'required', requestId: '701' }),
2009
2168
  ]));
@@ -2013,12 +2172,12 @@ describe('production composition', () => {
2013
2172
  url: `/api/sessions/${sessionA}/attention/701/resolve`,
2014
2173
  payload: { operationKey: 'resolve-a', action: 'resume' },
2015
2174
  })).statusCode).toBe(202);
2016
- await expect(resolving).resolves.toEqual(toOrgPlanAttentionToolResponse({ action: 'resume' }));
2017
2175
  await vi.waitFor(() => expect(receivedA).toEqual([
2018
2176
  expect.objectContaining({ kind: 'required', requestId: '701' }),
2019
2177
  expect.objectContaining({ kind: 'resolved', requestId: '701' }),
2020
2178
  ]));
2021
2179
  const failing = handleB.request(attentionCall(702, 'permissionRequired'));
2180
+ await expect(failing).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2022
2181
  await vi.waitFor(() => expect(receivedB).toEqual([
2023
2182
  expect.objectContaining({ kind: 'required', requestId: '702' }),
2024
2183
  ]));
@@ -2026,13 +2185,10 @@ describe('production composition', () => {
2026
2185
  method: 'serverRequest/resolved',
2027
2186
  params: { threadId: 'thread-ignored', requestId: 702 },
2028
2187
  });
2029
- await expect(failing).rejects.toMatchObject({ message: 'CODEX_SERVER_REQUEST_CLEARED' });
2030
- await vi.waitFor(() => expect(receivedB).toEqual([
2031
- expect.objectContaining({ kind: 'required', requestId: '702' }),
2032
- expect.objectContaining({ kind: 'failed', requestId: '702' }),
2033
- ]));
2188
+ expect(receivedB).toEqual([expect.objectContaining({ kind: 'required', requestId: '702' })]);
2034
2189
  unsubscribeA();
2035
2190
  const afterUnsubscribe = handleA.request(attentionCall(703));
2191
+ await expect(afterUnsubscribe).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2036
2192
  await vi.waitFor(async () => expect((await app.inject(`/api/sessions/${sessionA}/attention`)).json()).toMatchObject({
2037
2193
  requestId: '703',
2038
2194
  }));
@@ -2041,9 +2197,6 @@ describe('production composition', () => {
2041
2197
  method: 'serverRequest/resolved',
2042
2198
  params: { threadId: 'thread-ignored', requestId: 703 },
2043
2199
  });
2044
- await expect(afterUnsubscribe).rejects.toMatchObject({
2045
- message: 'CODEX_SERVER_REQUEST_CLEARED',
2046
- });
2047
2200
  expect(receivedA).toHaveLength(2);
2048
2201
  unsubscribeB();
2049
2202
  await app.close();
@@ -2074,6 +2227,7 @@ describe('production composition', () => {
2074
2227
  await vi.waitFor(() => expect(handles.find((handle) => handle.request)?.request).toBeDefined());
2075
2228
  const handle = handles.find((candidate) => candidate.calls.includes('thread/start'));
2076
2229
  const attentionFirst = handle.request(attentionCall(711, 'permissionRequired'));
2230
+ await expect(attentionFirst).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2077
2231
  const inputFirst = handle.request({
2078
2232
  id: 712,
2079
2233
  method: 'item/tool/requestUserInput',
@@ -2096,11 +2250,11 @@ describe('production composition', () => {
2096
2250
  url: `/api/sessions/${sessionId}/attention/711/resolve`,
2097
2251
  payload: { operationKey: 'attention-first', action: 'resume' },
2098
2252
  });
2099
- await expect(attentionFirst).resolves.toEqual(toOrgPlanAttentionToolResponse({ action: 'resume' }));
2100
2253
  await vi.waitFor(async () => expect((await app.inject(`/api/sessions/${sessionId}`)).json()).toMatchObject({
2101
2254
  agentActivity: { root: { state: 'working' } },
2102
2255
  }));
2103
2256
  const attentionSecond = handle.request(attentionCall(713));
2257
+ await expect(attentionSecond).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2104
2258
  const inputSecond = handle.request({
2105
2259
  id: 714,
2106
2260
  method: 'item/tool/requestUserInput',
@@ -2111,7 +2265,6 @@ describe('production composition', () => {
2111
2265
  url: `/api/sessions/${sessionId}/attention/713/resolve`,
2112
2266
  payload: { operationKey: 'attention-second', action: 'resume' },
2113
2267
  });
2114
- await expect(attentionSecond).resolves.toEqual(toOrgPlanAttentionToolResponse({ action: 'resume' }));
2115
2268
  await vi.waitFor(async () => expect((await app.inject(`/api/sessions/${sessionId}`)).json()).toMatchObject({
2116
2269
  agentActivity: { root: { state: 'awaitingHuman', reason: 'pendingInteraction' } },
2117
2270
  }));
@@ -2150,10 +2303,8 @@ describe('production composition', () => {
2150
2303
  const handle = handles.find((candidate) => candidate.calls.includes('thread/start'));
2151
2304
  const active = handle.request(attentionCall(801));
2152
2305
  const terminal = handle.request(attentionCall(802));
2153
- const terminalResponse = toOrgPlanAttentionToolResponse({
2154
- action: 'resume',
2155
- guidance: 'Sensitive terminal guidance.',
2156
- });
2306
+ await expect(active).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2307
+ await expect(terminal).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2157
2308
  const accepted = await first.inject({
2158
2309
  method: 'POST',
2159
2310
  url: `/api/sessions/${sessionId}/attention/802/resolve`,
@@ -2164,9 +2315,7 @@ describe('production composition', () => {
2164
2315
  },
2165
2316
  });
2166
2317
  const resolvedAt = accepted.json().resolvedAt;
2167
- await expect(terminal).resolves.toEqual(terminalResponse);
2168
2318
  await first.close();
2169
- await expect(active).rejects.toMatchObject({ message: 'CODEX_SERVER_REQUEST_CANCELLED' });
2170
2319
  const reopened = await composeAuthorizedApp({
2171
2320
  root,
2172
2321
  dataDir,
@@ -2205,7 +2354,7 @@ describe('production composition', () => {
2205
2354
  })).json()).toEqual({ code: 'ATTENTION_OPERATION_STALE' });
2206
2355
  await reopened.close();
2207
2356
  });
2208
- it('reports supported offline writers separately from legacy sessions without the attention capability', async () => {
2357
+ it('resolves acknowledged attention offline while retaining legacy writer diagnostics', async () => {
2209
2358
  const root = await mkdtemp(join(tmpdir(), 'gestalt-mobile-root-'));
2210
2359
  const dataDir = await mkdtemp(join(tmpdir(), 'gestalt-mobile-state-'));
2211
2360
  ownTemporaryPaths(root, dataDir);
@@ -2230,18 +2379,17 @@ describe('production composition', () => {
2230
2379
  const started = handles.filter((handle) => handle.calls.includes('thread/start'));
2231
2380
  const supportedRequest = started[0].request(attentionCall(901));
2232
2381
  const legacyRequest = started[1].request(attentionCall(902));
2382
+ await expect(supportedRequest).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2383
+ await expect(legacyRequest).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
2233
2384
  await vi.waitFor(async () => expect((await first.inject(`/api/sessions/${legacySession}/attention`)).statusCode).toBe(200));
2234
2385
  await first.close();
2235
- await expect(supportedRequest).rejects.toMatchObject({
2236
- message: 'CODEX_SERVER_REQUEST_CANCELLED',
2237
- });
2238
- await expect(legacyRequest).rejects.toMatchObject({
2239
- message: 'CODEX_SERVER_REQUEST_CANCELLED',
2240
- });
2241
2386
  const database = new DatabaseSync(join(dataDir, 'relay.sqlite'));
2242
2387
  database
2243
2388
  .prepare('UPDATE relay_sessions SET attention_tool_capability = NULL WHERE id = ?')
2244
2389
  .run(legacySession);
2390
+ database
2391
+ .prepare("UPDATE pending_interactions SET resolution_state = 'active' WHERE session_id = ? AND request_id = '902'")
2392
+ .run(legacySession);
2245
2393
  database.close();
2246
2394
  const offline = await composeAuthorizedApp({
2247
2395
  root,
@@ -2254,7 +2402,7 @@ describe('production composition', () => {
2254
2402
  method: 'POST',
2255
2403
  url: `/api/sessions/${supportedSession}/attention/901/resolve`,
2256
2404
  payload: { operationKey: 'offline-supported', action: 'resume' },
2257
- })).json()).toEqual({ code: 'ATTENTION_WRITER_UNAVAILABLE' });
2405
+ })).statusCode).toBe(202);
2258
2406
  expect((await offline.inject({
2259
2407
  method: 'POST',
2260
2408
  url: `/api/sessions/${legacySession}/attention/902/resolve`,
@@ -3703,6 +3851,7 @@ describe('production composition', () => {
3703
3851
  },
3704
3852
  },
3705
3853
  });
3854
+ await expect(attention).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
3706
3855
  await vi.waitFor(async () => {
3707
3856
  expect((await app.inject(`/api/sessions/${sessionId}`)).json()).toMatchObject({
3708
3857
  pendingInteractions: [
@@ -3747,7 +3896,6 @@ describe('production composition', () => {
3747
3896
  guidance: 'The release permission is now granted.',
3748
3897
  },
3749
3898
  })).toMatchObject({ statusCode: 202 });
3750
- expect(await attention).toEqual(attentionResponse);
3751
3899
  expect((await app.inject({
3752
3900
  method: 'POST',
3753
3901
  url: `/api/sessions/${sessionId}/attention/8/resolve`,
@@ -3773,8 +3921,8 @@ describe('production composition', () => {
3773
3921
  }),
3774
3922
  ]));
3775
3923
  expect(JSON.stringify(attentionHistory)).not.toContain('The release permission is now granted.');
3776
- // A server-cleared attention request is a durable failed audit and must
3777
- // re-project the root rather than leaving the GUI awaiting a vanished alert.
3924
+ // Clearing the already-acknowledged dynamic request must not erase the
3925
+ // durable attention record or wedge the caller.
3778
3926
  const clearedAttention = handle.request({
3779
3927
  id: 9,
3780
3928
  method: 'item/tool/call',
@@ -3788,6 +3936,7 @@ describe('production composition', () => {
3788
3936
  },
3789
3937
  },
3790
3938
  });
3939
+ await expect(clearedAttention).resolves.toEqual(toOrgPlanAttentionAcknowledgement());
3791
3940
  await vi.waitFor(async () => expect((await app.inject(`/api/sessions/${sessionId}`)).json()).toMatchObject({
3792
3941
  agentActivity: { root: { state: 'awaitingHuman' } },
3793
3942
  }));
@@ -3795,14 +3944,11 @@ describe('production composition', () => {
3795
3944
  method: 'serverRequest/resolved',
3796
3945
  params: { threadId: 'thread-1', requestId: 9 },
3797
3946
  });
3798
- await expect(clearedAttention).rejects.toMatchObject({
3799
- message: 'CODEX_SERVER_REQUEST_CLEARED',
3800
- });
3801
3947
  await vi.waitFor(async () => expect((await app.inject(`/api/sessions/${sessionId}`)).json()).toMatchObject({
3802
- agentActivity: { root: { state: 'working' } },
3948
+ agentActivity: { root: { state: 'awaitingHuman' } },
3803
3949
  }));
3804
3950
  expect((await app.inject(`/api/sessions/${sessionId}/history`)).json().interactions).toEqual(expect.arrayContaining([
3805
- expect.objectContaining({ requestId: '9', kind: 'orgPlanAttention', outcome: 'failed' }),
3951
+ expect.objectContaining({ requestId: '9', kind: 'orgPlanAttention', resolvedAt: null }),
3806
3952
  ]));
3807
3953
  const quiz = handle.request({
3808
3954
  id: 71,
@@ -7,6 +7,7 @@ import { createHash, randomBytes, randomUUID } from 'node:crypto';
7
7
  import { existsSync } from 'node:fs';
8
8
  import { homedir } from 'node:os';
9
9
  import { basename, dirname, join, resolve } from 'node:path';
10
+ import { debuglog } from 'node:util';
10
11
  import { buildApp } from './app.js';
11
12
  import { FilesystemWorkspaceCatalog } from './platform/catalog/filesystem-workspace-catalog.js';
12
13
  import { FilesystemWorkspaceFiles } from './platform/filesystem/filesystem-workspace-files.js';
@@ -48,7 +49,7 @@ import { toAgentActivityDto } from './features/agent-activity/activity-dto.js';
48
49
  import { decodeAgentActivityFacts } from './platform/codex/activity-facts.js';
49
50
  import { completedCommandId, compactOrgPlanCheckpointKind, isAgentCapacityRecoveryCall, isAutopilotWaitLeaseCall, resolvedServerRequestId, toPendingInteraction, } from './platform/codex/server-request.js';
50
51
  import { parseOrgPlanCheckpoint, toOrgPlanCheckpointToolResponse, } from '../shared/contracts/org-plan-checkpoint.js';
51
- import { resolveOrgPlanCheckpointSignal, validOrgPlanCheckpoint, } from './features/org-plan-checkpoint/application/validate.js';
52
+ import { hasActiveL1Writer, resolveOrgPlanCheckpointSignal, validateOrgPlanCheckpoint, } from './features/org-plan-checkpoint/application/validate.js';
52
53
  import { isValidInteractionResponse, isValidQuizInteractionResponse, } from './features/sessions/interaction/response-validator.js';
53
54
  import { promoteRecentThread } from './features/sessions/promote-recent-thread/use-case.js';
54
55
  import { FilesystemSkillProfileStore } from './platform/skills/filesystem-skill-profile-store.js';
@@ -65,11 +66,13 @@ import { AutopilotCoordinator } from './features/autopilot/application/service.j
65
66
  import { deriveSessionStatus } from './features/sessions/session-status.js';
66
67
  import { AUTOPILOT_CONTINUATION_PROMPT, AUTOPILOT_EXECUTOR_CONTINUATION_PROMPT, autopilotExecutorLaunchPrompt, defaultAutopilotPolicy, } from './features/autopilot/application/policy.js';
67
68
  import { createRelyingPartyConfig } from './config.js';
68
- import { parseOrgPlanAttention } from '../shared/contracts/org-plan-attention.js';
69
+ import { parseOrgPlanAttention, toOrgPlanAttentionAcknowledgement, } from '../shared/contracts/org-plan-attention.js';
69
70
  import { autopilotWaitLeaseToolResponse, } from '../shared/contracts/autopilot-wait-lease.js';
70
71
  import { agentCapacityRecoveryToolResponse } from '../shared/contracts/agent-capacity-recovery.js';
71
72
  import { pwaIconUrl } from './features/pwa/register-routes.js';
72
73
  const generatedProtocolVersion = 'codex-cli 0.144.3';
74
+ const checkpointDiagnostic = debuglog('gestalt-mobile:checkpoint');
75
+ const attentionDiagnostic = debuglog('gestalt-mobile:attention');
73
76
  export async function composeRelayApp(options) {
74
77
  const passkeyAuthEnabled = options.passkeyAuthEnabled ?? true;
75
78
  const relyingParty = createRelyingPartyConfig(options.relyingParty.publicOrigin);
@@ -104,6 +107,7 @@ export async function composeRelayApp(options) {
104
107
  const autopilotStore = new SqliteAutopilotStore(database);
105
108
  const attentionResolutionOperations = new Map();
106
109
  const checkpointHandoffTimers = new Map();
110
+ const attentionAcknowledgementTimers = new Map();
107
111
  const checkpointHandoffRecoveries = new Set();
108
112
  const supervisedPlans = new SupervisedPlanRegistry();
109
113
  const planStatusSource = new FilesystemPlanStatusSource(join(dirname(databasePath), 'plans'));
@@ -471,6 +475,9 @@ export async function composeRelayApp(options) {
471
475
  // request: the client can deliver them as a follow-up prompt instead.
472
476
  if (interaction.kind === 'quiz')
473
477
  continue;
478
+ if (interaction.kind === 'orgPlanAttention' &&
479
+ interactions.resolutionState(sessionId, interaction.requestId) === 'acknowledged')
480
+ continue;
474
481
  if (interactions.resolve(sessionId, interaction.requestId, occurredAt, outcome))
475
482
  publishInteractionResolved(sessionId, interaction.requestId, occurredAt, outcome);
476
483
  }
@@ -551,6 +558,36 @@ export async function composeRelayApp(options) {
551
558
  handle.unref?.();
552
559
  checkpointHandoffTimers.set(key, { handle, token });
553
560
  };
561
+ const cancelAttentionAcknowledgementTimer = (sessionId, requestId) => {
562
+ const key = checkpointTimerKey(sessionId, requestId);
563
+ const timer = attentionAcknowledgementTimers.get(key);
564
+ if (!timer)
565
+ return;
566
+ clearTimeout(timer.handle);
567
+ attentionAcknowledgementTimers.delete(key);
568
+ };
569
+ const armAttentionAcknowledgementDeadline = (sessionId, requestId) => {
570
+ cancelAttentionAcknowledgementTimer(sessionId, requestId);
571
+ const key = checkpointTimerKey(sessionId, requestId);
572
+ const token = Symbol(key);
573
+ const handle = setTimeout(() => {
574
+ if (attentionAcknowledgementTimers.get(key)?.token !== token)
575
+ return;
576
+ attentionAcknowledgementTimers.delete(key);
577
+ const ownedRuntime = runtime;
578
+ const session = sessions.find(sessionId);
579
+ if (!ownedRuntime || !session || !ownedRuntime.abandonServerRequest(sessionId, requestId))
580
+ return;
581
+ void ownedRuntime
582
+ .recycle(session, new Date().toISOString())
583
+ .then((recovered) => saveSession(recovered))
584
+ .catch(() => {
585
+ // The durable attention survives; normal session recovery can reacquire the writer.
586
+ });
587
+ }, options.attentionAcknowledgementDeadlineMs ?? 5_000);
588
+ handle.unref?.();
589
+ attentionAcknowledgementTimers.set(key, { handle, token });
590
+ };
554
591
  const failPendingCheckpointHandoffs = (sessionId, recoverBoundary) => {
555
592
  for (const interaction of interactions.list(sessionId)) {
556
593
  if (interaction.kind !== 'orgPlanCheckpoint')
@@ -568,28 +605,38 @@ export async function composeRelayApp(options) {
568
605
  * enters the durable store, requests human attention, and notifies autopilot.
569
606
  * Both the codex JSON-RPC handler and the kimi polling handler land here.
570
607
  */
571
- const acceptPendingInteraction = (sessionId, rawInteraction, session) => {
608
+ const acceptPendingInteraction = (sessionId, rawInteraction, session, acknowledgeAttention = false) => {
572
609
  const interaction = {
573
610
  ...rawInteraction,
574
611
  turnId: session.activeTurnId,
575
612
  requestedAt: new Date().toISOString(),
576
613
  };
577
- interactions.add(sessionId, interaction);
578
- activity.observe({
579
- sessionId,
580
- occurredAt: interaction.requestedAt,
581
- kind: 'interactionPending',
582
- ...(interaction.kind === 'orgPlanAttention'
583
- ? { attentionReason: interaction.payload.reason }
584
- : {}),
585
- });
586
- autopilot.semanticEvent(sessionId, 'interactionChanged');
587
- const updated = RelaySession.rehydrate(session).requestInteraction(interaction, new Date().toISOString()).snapshot;
588
- sessions.save(updated);
589
- events.publish(journal.append(sessionId, 'interaction.requested', interaction, updated.updatedAt));
590
- if (interaction.kind === 'orgPlanAttention')
591
- events.publish(journal.append(sessionId, 'org-plan.attention-required', interaction, updated.updatedAt));
592
- autopilot.evaluate(sessionId);
614
+ interactions.add(sessionId, interaction, acknowledgeAttention && interaction.kind === 'orgPlanAttention' ? 'acknowledged' : 'active');
615
+ try {
616
+ activity.observe({
617
+ sessionId,
618
+ occurredAt: interaction.requestedAt,
619
+ kind: 'interactionPending',
620
+ ...(interaction.kind === 'orgPlanAttention'
621
+ ? { attentionReason: interaction.payload.reason }
622
+ : {}),
623
+ });
624
+ autopilot.semanticEvent(sessionId, 'interactionChanged');
625
+ const updated = RelaySession.rehydrate(session).requestInteraction(interaction, new Date().toISOString()).snapshot;
626
+ sessions.save(updated);
627
+ events.publish(journal.append(sessionId, 'interaction.requested', interaction, updated.updatedAt));
628
+ if (interaction.kind === 'orgPlanAttention')
629
+ events.publish(journal.append(sessionId, 'org-plan.attention-required', interaction, updated.updatedAt));
630
+ autopilot.evaluate(sessionId);
631
+ }
632
+ catch (error) {
633
+ if (!acknowledgeAttention || interaction.kind !== 'orgPlanAttention')
634
+ throw error;
635
+ attentionDiagnostic('%o', {
636
+ requestId: interaction.requestId,
637
+ reasonCode: 'postPersistenceProjectionFailed',
638
+ });
639
+ }
593
640
  return true;
594
641
  };
595
642
  const acceptPlanUpdate = (sessionId, update) => {
@@ -625,7 +672,9 @@ export async function composeRelayApp(options) {
625
672
  if (resolvedRequestId) {
626
673
  const interaction = interactions.find(sessionId, resolvedRequestId);
627
674
  const outcome = interaction?.kind === 'orgPlanAttention' ? 'failed' : 'dismissed';
628
- if (interaction?.kind !== 'quiz' &&
675
+ if (!(interaction?.kind === 'orgPlanAttention' &&
676
+ interactions.resolutionState(sessionId, resolvedRequestId) === 'acknowledged') &&
677
+ interaction?.kind !== 'quiz' &&
629
678
  interactions.resolve(sessionId, resolvedRequestId, occurredAt, outcome)) {
630
679
  if (outcome === 'failed')
631
680
  publishAttentionSettlement(sessionId, resolvedRequestId, occurredAt, outcome);
@@ -683,7 +732,7 @@ export async function composeRelayApp(options) {
683
732
  const retained = supervisedPlans.find(sessionId);
684
733
  const identity = supervisedPlans.identity(sessionId);
685
734
  const checkpoint = retained && identity
686
- ? resolveOrgPlanCheckpointSignal(compactCheckpointKind, retained, identity)
735
+ ? resolveOrgPlanCheckpointSignal(compactCheckpointKind, retained, identity, supervisedPlans.publicationReason(sessionId))
687
736
  : null;
688
737
  if (checkpoint)
689
738
  rawInteraction = {
@@ -741,23 +790,38 @@ export async function composeRelayApp(options) {
741
790
  !identity ||
742
791
  checkpoint.planIdentity !== identity ||
743
792
  !rootOwned)
744
- return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanCheckpointToolResponse('failed')) === true);
745
- const valid = validOrgPlanCheckpoint({
793
+ return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, checkpointFailureResponse(!checkpoint
794
+ ? compactCheckpointKind === 'l1Accepted'
795
+ ? 'acceptedL1NotResolved'
796
+ : 'checkpointPayloadInvalid'
797
+ : !retained
798
+ ? 'planProjectionUnavailable'
799
+ : !identity || checkpoint.planIdentity !== identity
800
+ ? 'planIdentityMismatch'
801
+ : 'rootNotOwner')) === true);
802
+ const validation = validateOrgPlanCheckpoint({
746
803
  checkpoint,
747
804
  plan: retained,
748
805
  planIdentity: identity,
749
806
  rootOwned,
750
807
  hasActiveL1Writer: (position) => hasActiveL1Writer(activity.snapshot(sessionId, new Date().toISOString()), position),
751
808
  });
752
- if (!valid || !session.activeTurnId)
753
- return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanCheckpointToolResponse('failed')) === true);
809
+ if (!validation.valid || !session.activeTurnId)
810
+ return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, checkpointFailureResponse(validation.valid ? 'rootTurnNotActive' : validation.reasonCode, {
811
+ ...(!validation.valid && validation.expected
812
+ ? { expected: validation.expected }
813
+ : {}),
814
+ ...(!validation.valid && validation.observed
815
+ ? { observed: validation.observed }
816
+ : {}),
817
+ })) === true);
754
818
  let recordStatus = 'failed';
755
819
  try {
756
820
  recordStatus = autopilot.checkpointAccepted(sessionId, checkpoint, session.activeTurnId, new Date().toISOString());
757
821
  }
758
822
  catch {
759
823
  if (!autopilot.checkpointHandoffFailed(sessionId, session.activeTurnId))
760
- return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanCheckpointToolResponse('failed')) === true);
824
+ return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, checkpointFailureResponse('checkpointPersistenceFailed')) === true);
761
825
  const interaction = {
762
826
  ...rawInteraction,
763
827
  turnId: session.activeTurnId,
@@ -768,7 +832,7 @@ export async function composeRelayApp(options) {
768
832
  return true;
769
833
  }
770
834
  if (recordStatus === 'failed')
771
- return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanCheckpointToolResponse('failed')) === true);
835
+ return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, checkpointFailureResponse('checkpointStateConflict')) === true);
772
836
  if (recordStatus === 'alreadyRecorded')
773
837
  return (runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanCheckpointToolResponse('alreadyRecorded')) === true);
774
838
  const interaction = {
@@ -788,6 +852,24 @@ export async function composeRelayApp(options) {
788
852
  // is cancelled solely by the JSON-RPC write-settlement callback.
789
853
  return true;
790
854
  }
855
+ if (rawInteraction.kind === 'orgPlanAttention') {
856
+ try {
857
+ acceptPendingInteraction(sessionId, rawInteraction, session, true);
858
+ const acknowledged = runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanAttentionAcknowledgement()) === true;
859
+ if (acknowledged)
860
+ armAttentionAcknowledgementDeadline(sessionId, rawInteraction.requestId);
861
+ return acknowledged;
862
+ }
863
+ catch {
864
+ const rejected = runtime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanAttentionAcknowledgement({
865
+ accepted: false,
866
+ reason: 'persistenceFailed',
867
+ })) === true;
868
+ if (rejected)
869
+ armAttentionAcknowledgementDeadline(sessionId, rawInteraction.requestId);
870
+ return rejected;
871
+ }
872
+ }
791
873
  return acceptPendingInteraction(sessionId, rawInteraction, session);
792
874
  }, (sessionId) => {
793
875
  activity.disconnected(sessionId, new Date().toISOString());
@@ -827,7 +909,18 @@ export async function composeRelayApp(options) {
827
909
  const handleKimiServerRequest = (sessionId, request) => {
828
910
  const rawInteraction = toPendingInteraction(request);
829
911
  const session = withPendingInteractions(sessions.find(sessionId));
830
- return Boolean(rawInteraction && session && acceptPendingInteraction(sessionId, rawInteraction, session));
912
+ if (!rawInteraction || !session)
913
+ return false;
914
+ if (rawInteraction.kind !== 'orgPlanAttention')
915
+ return acceptPendingInteraction(sessionId, rawInteraction, session);
916
+ try {
917
+ acceptPendingInteraction(sessionId, rawInteraction, session, true);
918
+ void kimiRuntime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanAttentionAcknowledgement());
919
+ }
920
+ catch {
921
+ void kimiRuntime?.resolveServerRequest(sessionId, rawInteraction.requestId, toOrgPlanAttentionAcknowledgement({ accepted: false, reason: 'persistenceFailed' }));
922
+ }
923
+ return true;
831
924
  };
832
925
  kimiRuntime = kimiManager
833
926
  ? new KimiSessionRuntime({
@@ -850,6 +943,10 @@ export async function composeRelayApp(options) {
850
943
  })
851
944
  : null;
852
945
  runtime?.onServerResponseSettled((sessionId, requestId, outcome) => {
946
+ if (attentionAcknowledgementTimers.has(checkpointTimerKey(sessionId, requestId))) {
947
+ cancelAttentionAcknowledgementTimer(sessionId, requestId);
948
+ return;
949
+ }
853
950
  const interaction = interactions.find(sessionId, requestId);
854
951
  if (interaction?.kind !== 'orgPlanCheckpoint')
855
952
  return;
@@ -1347,6 +1444,18 @@ export async function composeRelayApp(options) {
1347
1444
  return { kind: 'staleOperation' };
1348
1445
  if (claim === 'missing')
1349
1446
  return { kind: 'noActive' };
1447
+ const acknowledged = interactions.resolutionState(sessionId, requestId) === 'acknowledged';
1448
+ if (acknowledged) {
1449
+ if (!interactions.beginDelivery(sessionId, requestId, operationKey))
1450
+ return { kind: 'staleOperation' };
1451
+ const resolvedAt = new Date().toISOString();
1452
+ if (!interactions.settleOperation(sessionId, requestId, operationKey, resolvedAt, 'answered'))
1453
+ return { kind: 'staleOperation' };
1454
+ const accepted = { kind: 'accepted', resolvedAt };
1455
+ idempotency.put(scope, operationKey, 202, JSON.stringify({ kind: 'replayed', resolvedAt }));
1456
+ publishAttentionSettlement(sessionId, requestId, resolvedAt, 'answered');
1457
+ return accepted;
1458
+ }
1350
1459
  // A durable capability belongs to the session/thread, not the
1351
1460
  // relay process. A supported stopped writer is retryable;
1352
1461
  // missing capability identifies a pre-rollout legacy thread.
@@ -1468,6 +1577,14 @@ export async function composeRelayApp(options) {
1468
1577
  checkpointHandoffTimers.delete(key);
1469
1578
  }
1470
1579
  }
1580
+ for (const key of [...attentionAcknowledgementTimers.keys()]) {
1581
+ if (key.startsWith(`${session.id}:`)) {
1582
+ const timer = attentionAcknowledgementTimers.get(key);
1583
+ if (timer)
1584
+ clearTimeout(timer.handle);
1585
+ attentionAcknowledgementTimers.delete(key);
1586
+ }
1587
+ }
1471
1588
  // Relay shutdown only releases this process's writer. A typed attention
1472
1589
  // request remains a durable human-visible blocker for the next relay
1473
1590
  // instance; only an app-server-cleared request is a failed audit outcome.
@@ -1497,7 +1614,8 @@ function resolveStateDatabasePath(root, stateHome) {
1497
1614
  const legacyPath = legacyRelayStatePath(root, stateHome);
1498
1615
  return existsSync(legacyPath) ? legacyPath : currentPath;
1499
1616
  }
1500
- function hasActiveL1Writer(snapshot, position) {
1501
- return snapshot.subagents.some((child) => child.canonicalPosition === position &&
1502
- ['working', 'awaitingAgent', 'awaitingHuman'].includes(child.state));
1617
+ function checkpointFailureResponse(reasonCode, details = {}) {
1618
+ const correlationId = randomUUID();
1619
+ checkpointDiagnostic('%o', { correlationId, reasonCode, ...details });
1620
+ return toOrgPlanCheckpointToolResponse('failed', { reasonCode, correlationId, ...details });
1503
1621
  }
@@ -201,7 +201,10 @@ function childOutcome(status, action, previous) {
201
201
  function childState(status, action, previous = 'working') {
202
202
  if (status === 'error' || status === 'failed' || status === 'systemError' || status === 'errored')
203
203
  return 'blocked';
204
- if (status === 'completed' || status === 'idle' || action === 'close_agent')
204
+ if (status === 'completed' ||
205
+ status === 'idle' ||
206
+ status === 'interrupted' ||
207
+ action === 'close_agent')
205
208
  return 'idle';
206
209
  // `wait` belongs to the caller/root; it does not rewrite the child which may
207
210
  // still be working. A child can explicitly report its own waiting status.
@@ -229,7 +232,10 @@ function childReason(status, action) {
229
232
  return 'processExited';
230
233
  if (action === 'wait')
231
234
  return 'collaborationWait';
232
- if (status === 'completed' || status === 'idle' || action === 'close_agent')
235
+ if (status === 'completed' ||
236
+ status === 'idle' ||
237
+ status === 'interrupted' ||
238
+ action === 'close_agent')
233
239
  return 'turnCompleted';
234
240
  return 'turnActive';
235
241
  }
@@ -3,8 +3,13 @@
3
3
  * Designed by Denis Roio <jaromil@dyne.org>
4
4
  * SPDX-License-Identifier: AGPL-3.0-or-later
5
5
  */
6
+ /** Terminal roster entries remain visible and are not active implementation writers. */
7
+ export function hasActiveL1Writer(snapshot, position) {
8
+ return snapshot.subagents.some((child) => child.canonicalPosition === position &&
9
+ ['working', 'awaitingAgent', 'awaitingHuman'].includes(child.state));
10
+ }
6
11
  /** Expands a host-owned compact boundary signal from authoritative plan state. */
7
- export function resolveOrgPlanCheckpointSignal(kind, plan, planIdentity) {
12
+ export function resolveOrgPlanCheckpointSignal(kind, plan, planIdentity, publicationReason = null) {
8
13
  if (kind === 'terminalReviewAccepted')
9
14
  return {
10
15
  version: 1,
@@ -12,8 +17,16 @@ export function resolveOrgPlanCheckpointSignal(kind, plan, planIdentity) {
12
17
  planIdentity,
13
18
  verdict: 'ACCEPT',
14
19
  };
15
- const selected = plan.steps.find((step) => step.id === plan.currentStepId) ??
16
- [...plan.steps].reverse().find((step) => step.state === 'DONE' || step.state === 'WIP');
20
+ const reviewedId = publicationReason?.match(/^review:([^:]{1,128}):REVIEWED$/)?.[1];
21
+ const selected = kind === 'l1Accepted'
22
+ ? ((reviewedId
23
+ ? plan.steps.find((step) => step.id === reviewedId && step.state === 'DONE' && step.reviewStatus === 'REVIEWED')
24
+ : undefined) ??
25
+ [...plan.steps]
26
+ .reverse()
27
+ .find((step) => step.state === 'DONE' && step.reviewStatus === 'REVIEWED'))
28
+ : (plan.steps.find((step) => step.id === plan.currentStepId) ??
29
+ [...plan.steps].reverse().find((step) => step.state === 'DONE' || step.state === 'WIP'));
17
30
  if (!selected)
18
31
  return null;
19
32
  const l1Position = `L${plan.steps.indexOf(selected) + 1}`;
@@ -44,25 +57,80 @@ export function resolveOrgPlanCheckpointSignal(kind, plan, planIdentity) {
44
57
  };
45
58
  }
46
59
  export function validOrgPlanCheckpoint(input) {
60
+ return validateOrgPlanCheckpoint(input).valid;
61
+ }
62
+ export function validateOrgPlanCheckpoint(input) {
47
63
  const { checkpoint, plan, planIdentity, rootOwned } = input;
48
- if (!rootOwned || checkpoint.planIdentity !== planIdentity)
49
- return false;
64
+ if (!rootOwned)
65
+ return { valid: false, reasonCode: 'rootNotOwner' };
66
+ if (checkpoint.planIdentity !== planIdentity)
67
+ return { valid: false, reasonCode: 'planIdentityMismatch' };
50
68
  if (checkpoint.kind === 'terminalReviewAccepted')
51
- return plan.steps.every((step) => step.state === 'DONE' && step.reviewStatus === 'REVIEWED');
69
+ return plan.steps.every((step) => step.state === 'DONE' && step.reviewStatus === 'REVIEWED')
70
+ ? { valid: true }
71
+ : { valid: false, reasonCode: 'terminalReviewIncomplete' };
52
72
  const l1 = plan.steps.find((step) => step.id === checkpoint.l1Id);
53
73
  if (!l1)
54
- return false;
74
+ return { valid: false, reasonCode: 'l1NotFound' };
55
75
  const position = `L${plan.steps.indexOf(l1) + 1}`;
56
76
  if (checkpoint.kind === 'l2Completed') {
57
77
  const l2 = l1.children.find((step) => step.id === checkpoint.l2Id);
58
78
  if (!l2)
59
- return false;
60
- return (checkpoint.position === `${position}.${l1.children.indexOf(l2) + 1}` &&
61
- l2.state === 'DONE' &&
62
- l1.reviewStatus === 'UNREVIEWED');
79
+ return { valid: false, reasonCode: 'l2NotFound' };
80
+ const expectedPosition = `${position}.${l1.children.indexOf(l2) + 1}`;
81
+ if (checkpoint.position !== expectedPosition)
82
+ return {
83
+ valid: false,
84
+ reasonCode: 'checkpointPositionMismatch',
85
+ expected: { position: expectedPosition },
86
+ observed: { position: checkpoint.position },
87
+ };
88
+ if (l2.state !== 'DONE')
89
+ return {
90
+ valid: false,
91
+ reasonCode: 'l2NotDone',
92
+ expected: { l2State: 'DONE' },
93
+ observed: { l2State: l2.state },
94
+ };
95
+ return l1.reviewStatus === 'UNREVIEWED'
96
+ ? { valid: true }
97
+ : { valid: false, reasonCode: 'l1AlreadyReviewed' };
63
98
  }
64
- return (checkpoint.position === position &&
65
- l1.state === 'DONE' &&
66
- l1.reviewStatus === 'REVIEWED' &&
67
- !input.hasActiveL1Writer(position));
99
+ if (checkpoint.position !== position)
100
+ return {
101
+ valid: false,
102
+ reasonCode: 'checkpointPositionMismatch',
103
+ expected: { position },
104
+ observed: { position: checkpoint.position },
105
+ };
106
+ if (l1.state !== 'DONE')
107
+ return {
108
+ valid: false,
109
+ reasonCode: 'l1NotDone',
110
+ expected: { l1State: 'DONE' },
111
+ observed: { l1State: l1.state },
112
+ };
113
+ if (l1.reviewStatus !== 'REVIEWED')
114
+ return {
115
+ valid: false,
116
+ reasonCode: 'l1NotReviewed',
117
+ expected: { reviewStatus: 'REVIEWED' },
118
+ observed: { reviewStatus: l1.reviewStatus ?? null },
119
+ };
120
+ const incompleteChild = l1.children.find((child) => child.state !== 'DONE');
121
+ if (incompleteChild)
122
+ return {
123
+ valid: false,
124
+ reasonCode: 'l1ChildrenIncomplete',
125
+ expected: { childrenDone: true },
126
+ observed: { childrenDone: false, childState: incompleteChild.state },
127
+ };
128
+ if (input.hasActiveL1Writer(position))
129
+ return {
130
+ valid: false,
131
+ reasonCode: 'executorStillActive',
132
+ expected: { executorTerminal: true },
133
+ observed: { executorTerminal: false },
134
+ };
135
+ return { valid: true };
68
136
  }
@@ -8,7 +8,11 @@ export class SupervisedPlanRegistry {
8
8
  plans = new Map();
9
9
  accept(sessionId, update) {
10
10
  if (update.kind === 'updated')
11
- this.plans.set(sessionId, { plan: update.plan, identity: update.identity });
11
+ this.plans.set(sessionId, {
12
+ plan: update.plan,
13
+ identity: update.identity,
14
+ publicationReason: update.reason,
15
+ });
12
16
  }
13
17
  find(sessionId) {
14
18
  return this.plans.get(sessionId)?.plan ?? null;
@@ -16,6 +20,9 @@ export class SupervisedPlanRegistry {
16
20
  identity(sessionId) {
17
21
  return this.plans.get(sessionId)?.identity ?? null;
18
22
  }
23
+ publicationReason(sessionId) {
24
+ return this.plans.get(sessionId)?.publicationReason ?? null;
25
+ }
19
26
  clear(sessionId) {
20
27
  this.plans.delete(sessionId);
21
28
  }
@@ -17,16 +17,22 @@ export class SqlitePendingInteractionStore {
17
17
  constructor(db) {
18
18
  this.db = db;
19
19
  }
20
- add(sessionId, interaction) {
20
+ add(sessionId, interaction, initialResolutionState = 'active') {
21
21
  this.db
22
- .prepare(`INSERT INTO pending_interactions (session_id,request_id,kind,payload_json,turn_id,requested_at)
23
- VALUES (?,?,?,?,?,?)
22
+ .prepare(`INSERT INTO pending_interactions (session_id,request_id,kind,payload_json,turn_id,requested_at,resolution_state)
23
+ VALUES (?,?,?,?,?,?,?)
24
24
  ON CONFLICT(session_id,request_id) DO UPDATE SET
25
25
  kind = excluded.kind, payload_json = excluded.payload_json, turn_id = excluded.turn_id,
26
26
  requested_at = excluded.requested_at, resolved_at = NULL, outcome = NULL, operation_key = NULL,
27
- resolution_state = 'active'
27
+ resolution_state = excluded.resolution_state
28
28
  WHERE pending_interactions.kind != 'orgPlanAttention'`)
29
- .run(sessionId, interaction.requestId, interaction.kind, JSON.stringify(interaction.payload), interaction.turnId ?? null, interaction.requestedAt ?? null);
29
+ .run(sessionId, interaction.requestId, interaction.kind, JSON.stringify(interaction.payload), interaction.turnId ?? null, interaction.requestedAt ?? null, initialResolutionState);
30
+ }
31
+ resolutionState(sessionId, requestId) {
32
+ const row = this.db
33
+ .prepare('SELECT resolution_state FROM pending_interactions WHERE session_id = ? AND request_id = ? AND resolved_at IS NULL')
34
+ .get(sessionId, requestId);
35
+ return row?.resolution_state ?? null;
30
36
  }
31
37
  resolve(sessionId, requestId, resolvedAt, outcome = 'answered') {
32
38
  return (this.db
@@ -56,7 +62,7 @@ export class SqlitePendingInteractionStore {
56
62
  /** Persist the in-flight delivery boundary before the app-server is notified. */
57
63
  beginDelivery(sessionId, requestId, operationKey) {
58
64
  return (this.db
59
- .prepare("UPDATE pending_interactions SET resolution_state = 'delivering' WHERE session_id = ? AND request_id = ? AND operation_key = ? AND resolved_at IS NULL AND resolution_state IN ('active','delivering')")
65
+ .prepare("UPDATE pending_interactions SET resolution_state = 'delivering' WHERE session_id = ? AND request_id = ? AND operation_key = ? AND resolved_at IS NULL AND resolution_state IN ('active','acknowledged','delivering')")
60
66
  .run(sessionId, requestId, operationKey).changes === 1);
61
67
  }
62
68
  /** A local writer outage is retryable only by the already-claimed key. */
@@ -93,13 +93,20 @@ export function parseOrgPlanAttentionResponse(value) {
93
93
  ...(typeof value.guidance === 'string' ? { guidance: value.guidance } : {}),
94
94
  };
95
95
  }
96
- /** The only result accepted by the held app-server dynamic-tool request. */
96
+ /** Legacy human resolution payload used only for pre-acknowledgement held requests. */
97
97
  export function toOrgPlanAttentionToolResponse(response) {
98
98
  return {
99
99
  success: true,
100
100
  contentItems: [{ type: 'inputText', text: JSON.stringify(response) }],
101
101
  };
102
102
  }
103
+ /** Immediate persist-first acknowledgement returned to the dynamic-tool caller. */
104
+ export function toOrgPlanAttentionAcknowledgement(acknowledgement = { accepted: true }) {
105
+ return {
106
+ success: acknowledgement.accepted,
107
+ contentItems: [{ type: 'inputText', text: JSON.stringify(acknowledgement) }],
108
+ };
109
+ }
103
110
  export function isOrgPlanAttentionToolResponse(value) {
104
111
  if (!isRecord(value) || value.success !== true || !Array.isArray(value.contentItems))
105
112
  return false;
@@ -176,7 +176,7 @@ export function parseOrgPlanCheckpoint(value) {
176
176
  };
177
177
  }
178
178
  /** Acknowledgement deliberately contains no plan path, findings, or model text. */
179
- export function toOrgPlanCheckpointToolResponse(status) {
179
+ export function toOrgPlanCheckpointToolResponse(status, failure) {
180
180
  const result = status === 'recorded'
181
181
  ? {
182
182
  status,
@@ -193,7 +193,11 @@ export function toOrgPlanCheckpointToolResponse(status) {
193
193
  }
194
194
  : {
195
195
  status,
196
+ reasonCode: failure?.reasonCode ?? 'checkpointPersistenceFailed',
196
197
  durable: false,
198
+ ...(failure?.expected ? { expected: failure.expected } : {}),
199
+ ...(failure?.observed ? { observed: failure.observed } : {}),
200
+ ...(failure?.correlationId ? { correlationId: failure.correlationId } : {}),
197
201
  next: 'reconcileCheckpointState',
198
202
  allowBoundaryFinal: false,
199
203
  };
@@ -13,5 +13,7 @@ export const planSignalReasons = [
13
13
  'resync',
14
14
  ];
15
15
  export function isPlanSignalReason(value) {
16
- return typeof value === 'string' && planSignalReasons.includes(value);
16
+ return (typeof value === 'string' &&
17
+ (planSignalReasons.includes(value) ||
18
+ /^review:[A-Za-z0-9._-]{1,128}:REVIEWED$/.test(value)));
17
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gestalt-mobile",
3
- "version": "0.41.1",
3
+ "version": "0.41.2",
4
4
  "description": "Mobile-first web relay for durable Codex development sessions",
5
5
  "keywords": [
6
6
  "codex",