alchemylab 3.0.0 → 3.0.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.
@@ -3637,22 +3637,22 @@ const de=async(e,r)=>(await Promise.resolve().then(()=>t(79414))).actionServerFe
3637
3637
  if(G){const e="string"==typeof W?.sitting?.head?W.sitting.head:""
3638
3638
  let t=e?null:X
3639
3639
  if(e)try{const r=await fetch(`${(0,f.getActionServerBaseUrl)()}/api/request-diff-stats?requestId=${encodeURIComponent(s)}&since=${encodeURIComponent(e)}`,{signal:AbortSignal.timeout(5e3)}),n=r.ok?await r.json():null
3640
- n?.data&&(t={files:Array.isArray(n.data.files)?n.data.files.filter(e=>"string"==typeof e):[],additions:n.data.additions,deletions:n.data.deletions})}catch(e){P.debug("the change's own diff could not be read; it is recorded without its files",{requestId:s,error:(0,h.getErrorMessage)(e)})}le={...O?{account:O}:{},files:t?.files??[],..."number"==typeof t?.additions?{additions:t.additions}:{},..."number"==typeof t?.deletions?{deletions:t.deletions}:{}},ce=await(0,x.lookNow)(s,ae,de).catch(()=>{})}const ue=async e=>{const t=await C.proxyPost(`/api/projects/${E.projectId}/requests/${s}/validate-completion`,(0,w.validateCompletionBody)("tool",{sessionId:K,skipTestsReason:D,skipTests:F,headSha:J,...le?{change:le}:{},...e?{look:e}:{},...void 0!==oe?{authoredSinceReview:oe}:{},...ie?{reviewDelta:ie}:{},...se?{intentMoves:se}:{},...X?.files?{files:X.files}:{}}))
3640
+ n?.data&&(t={files:Array.isArray(n.data.files)?n.data.files.filter(e=>"string"==typeof e):[],additions:n.data.additions,deletions:n.data.deletions})}catch(e){P.debug("the change's own diff could not be read; it is recorded without its files",{requestId:s,error:(0,h.getErrorMessage)(e)})}le={...O?{account:O}:{},files:t?.files??[],..."number"==typeof t?.additions?{additions:t.additions}:{},..."number"==typeof t?.deletions?{deletions:t.deletions}:{}},ce=await(0,x.lookNow)(s,ae,de).catch(()=>{})}const ue=G&&("settle"===(0,v.kindProfile)(re??W?.type).finalize||!!X&&0===X.filesChanged&&0===X.additions&&0===X.deletions),he=async e=>{const t=await C.proxyPost(`/api/projects/${E.projectId}/requests/${s}/validate-completion`,(0,w.validateCompletionBody)("tool",{sessionId:K,skipTestsReason:D,skipTests:F,headSha:J,...ue?{diffNone:!0}:{},...le?{change:le}:{},...e?{look:e}:{},...void 0!==oe?{authoredSinceReview:oe}:{},...ie?{reviewDelta:ie}:{},...se?{intentMoves:se}:{},...X?.files?{files:X.files}:{}}))
3641
3641
  return t?.data||t}
3642
- let he=null
3643
- try{if(te=await ue(ce),te.canComplete&&"sitting-look"===te.plan?.action){const e=await(0,x.settleLook)(s,ae,de)
3644
- he=e.served,te=await ue(e.look)}}catch(e){const t=(0,h.getErrorMessage)(e)
3642
+ let pe=null
3643
+ try{if(te=await he(ce),te.canComplete&&"sitting-look"===te.plan?.action){const e=await(0,x.settleLook)(s,ae,de)
3644
+ pe=e.served,te=await he(e.look)}}catch(e){const t=(0,h.getErrorMessage)(e)
3645
3645
  return P.error("Server validation failed",{requestId:s,error:t}),A({success:!1,error:"validation_request_failed"}),{content:[{type:"text",text:`Failed to validate completion: ${t}`}],isError:!0}}if(!te.canComplete){let e=`Cannot complete request ${s}: ${te.reason}\n`
3646
3646
  if(te.blockedByTasks&&te.blockedByTasks.length>0&&(e+="\n**Tasks that must be completed or canceled first:**\n",te.blockedByTasks.forEach((t,r)=>{e+=`${r+1}. **${t.taskId}** - ${t.title} (Status: ${t.status})\n`})),te.lifoViolation&&(e+="\n**Requests that must be re-completed first (LIFO order):**\n",te.lifoViolation.blockingRequests.forEach((t,r)=>{e+=`${r+1}. **${t.requestId}** - ${t.title} (Status: ${t.status})\n`})),ne.length>0)try{const t=await C.getRequestClient().getRequest(s)
3647
3647
  e+=`\n${function(e,t){const r=(Array.isArray(e)?e:[]).map((e,t)=>({c:e,i:t})).filter(({c:e})=>e?.id&&t.includes(String(e.id))).map(({c:e,i:t})=>{const r=Array.isArray(e.verify)?e.verify.filter(e=>"string"==typeof e):[],o=(0,n.latestRow)(e,["verify","check"]),s=o?"met"===o.verdict?"passed":"unmet"===o.verdict?"failed":o.verdict:"not run yet"
3648
3648
  return`- [${(0,n.criterionShortKey)(String(e.id),t)}] ${r.length?`check now: ${r.map(e=>`\`${e.slice(0,120)}\``).join("; ")} (newest result: ${s})`:"no check of its own"}`})
3649
- return 0===r.length?"":`Recorded all the same, as the request reads now: your account on these criteria, and their checks as they stand:\n${r.join("\n")}\nOnly the completion was refused; say so if you tell the user.`}(t?.acceptanceCriteria,ne)}`}catch{}return A({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}if("sitting-held"===te.plan?.action)return P.info("completion held: the round stays open while the user is on its page",{requestId:s,until:te.plan.detail,look:ce,preview:he}),await(0,k.reopenOneTask)(C.getTaskClient(),s).then(()=>(0,I.clearActiveTaskCache)(),e=>P.warn("the round's one task could not be opened again; its worker opens one for its next edit",{requestId:s,error:(0,h.getErrorMessage)(e)})),A({success:!0}),{content:[{type:"text",text:[`The change is recorded on ${s}, and the round stays open: the user is on its page and may ask for more. Nothing is checked or completed yet. That happens once, for everything this round changed, when they go quiet, leave the page or press Complete, and you are told then.`,"Between changes they look at what this round made: a preview of your working copy when it serves a page, and the pictures and documents it changed, as committed. What they see must be current, so after every change run the build or the script that makes it.","When they ask for another change on this round, make it and call complete with `change`: one line saying what that change did. That records it under their words and loads what they are looking at again. Do not call merge. End your turn with that one line."].join("\n")}]}
3649
+ return 0===r.length?"":`Recorded all the same, as the request reads now: your account on these criteria, and their checks as they stand:\n${r.join("\n")}\nOnly the completion was refused; say so if you tell the user.`}(t?.acceptanceCriteria,ne)}`}catch{}return A({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}if("sitting-held"===te.plan?.action)return P.info("completion held: the round stays open while the user is on its page",{requestId:s,until:te.plan.detail,look:ce,preview:pe}),await(0,k.reopenOneTask)(C.getTaskClient(),s).then(()=>(0,I.clearActiveTaskCache)(),e=>P.warn("the round's one task could not be opened again; its worker opens one for its next edit",{requestId:s,error:(0,h.getErrorMessage)(e)})),A({success:!0}),{content:[{type:"text",text:[`The change is recorded on ${s}, and the round stays open: the user is on its page and may ask for more. Nothing is checked or completed yet. That happens once, for everything this round changed, when they go quiet, leave the page or press Complete, and you are told then.`,"Between changes they look at what this round made: a preview of your working copy when it serves a page, and the pictures and documents it changed, as committed. What they see must be current, so after every change run the build or the script that makes it.","When they ask for another change on this round, make it and call complete with `change`: one line saying what that change did. That records it under their words and loads what they are looking at again. Do not call merge. End your turn with that one line."].join("\n")}]}
3650
3650
  if(G&&!i)try{const e=await C.proxyGet(`/api/projects/${E.projectId}/requests/${encodeURIComponent(s)}/rounds`)
3651
3651
  V=function(e,t){const r=[]
3652
3652
  for(const t of Array.isArray(e)?e:[]){const e="string"==typeof t?.changed?t.changed.trim():""
3653
3653
  e&&!r.includes(e)&&r.push(e)}const n=(t??"").replace(/\s+/g," ").trim()
3654
- return n&&!r.includes(n)&&r.push(n),r.join("\n")}(((e?.data??e)?.rounds??[]).find(e=>e?.id===s)?.changes,O)||V}catch(e){P.debug("the round's changes could not be read for its summary; this change's line stands for it",{requestId:s,error:(0,h.getErrorMessage)(e)})}const pe=(0,x.showGiven)(U),fe=te.plan
3655
- await async function(e,t,r,n){try{const o=await e.getRequestClient().getRequest(t),s=function(e,t){return(Array.isArray(e)?e:[]).flatMap(e=>{if(!e?.id||!(0,$.hasBaseline)(e)||e.retired||e.standing&&e.waived)return[]
3654
+ return n&&!r.includes(n)&&r.push(n),r.join("\n")}(((e?.data??e)?.rounds??[]).find(e=>e?.id===s)?.changes,O)||V}catch(e){P.debug("the round's changes could not be read for its summary; this change's line stands for it",{requestId:s,error:(0,h.getErrorMessage)(e)})}const fe=(0,x.showGiven)(U),me=te.plan,ge="answer"===me?.action
3655
+ ge||await async function(e,t,r,n){try{const o=await e.getRequestClient().getRequest(t),s=function(e,t){return(Array.isArray(e)?e:[]).flatMap(e=>{if(!e?.id||!(0,$.hasBaseline)(e)||e.retired||e.standing&&e.waived)return[]
3656
3656
  const r="string"==typeof e.command?e.command.trim():""
3657
3657
  if(!r)return[]
3658
3658
  const n=Array.isArray(e.ledger)?e.ledger:[]
@@ -3660,35 +3660,36 @@ return t&&n.some(e=>"verify"===e?.source&&"string"==typeof e?.instrument&&e.inst
3660
3660
  if(0===s.length)return
3661
3661
  const i=await fetch(`${(0,f.getActionServerBaseUrl)()}/api/baseline-measure`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({requestId:t,baselines:s}),signal:AbortSignal.timeout(2e4)})
3662
3662
  n.info("baseline measurement started beside the sign-off check; the merge waits for it",{requestId:t,baselines:s.length,ok:i.ok})}catch(e){n.debug("baseline measurement could not start; the card says it was not measured",{requestId:t,error:(0,h.getErrorMessage)(e)})}}(C,s,J,P)
3663
- const me=fe&&pe.artifact?await C.getRequestClient().getRequest(s).then(e=>String(e?.title??"")).catch(()=>""):"",ge=fe?await(0,x.startShowing)({projectId:E.projectId,post:(e,t)=>C.proxyPost(e,t),log:P,sessionExternalId:K??void 0,assetThere:e=>(0,x.assetIsThere)(E.basePath,e),resultsOf:e=>C.proxyGet(`/api/projects/${E.projectId}/results?requestId=${encodeURIComponent(e)}`).then(e=>Array.isArray(e?.data)?e.data:Array.isArray(e)?e:[])},s,pe,me).catch(()=>""):""
3664
- if(ge&&P.info("showing started",{requestId:s,said:ge}),"review-submit"===fe?.action&&J&&X&&(X.reviewAcceptedSha=J),fe?.reviewChange&&ie&&X&&(X.afterReview={...ie,outcome:fe.reviewChange},"restarted"===fe.reviewChange&&(X.sinceReview=ie)),!fe)return A({success:!1,error:"plan_missing"}),{content:[{type:"text",text:`Server validation returned no completion plan for ${s} -- the remote is likely mid-deploy. Retry complete.`}],isError:!0}
3665
- const ye="testing"===fe.action||"human-review"===fe.action||"merge-cleared"===fe.action
3666
- if(ye&&te.testsSkipped&&(D||F&&F.length>0))try{const e=C.getToolRecordClient()
3667
- e&&await e.createToolRecord({projectId:E.projectId,requestId:s,type:"tests-skipped",metadata:{...D?{reason:D}:{},...F&&F.length>0?{skipTests:F}:{},testGate:te.gates.test,timestamp:(new Date).toISOString()}})}catch(e){P.warn("Failed to persist tests-skipped tool_record",{error:(0,h.getErrorMessage)(e)})}if(ye&&M&&M.length>0&&K){const e=C.getSessionMessageClient()
3663
+ const ye=me&&fe.artifact?await C.getRequestClient().getRequest(s).then(e=>String(e?.title??"")).catch(()=>""):"",we=me&&!ge?await(0,x.startShowing)({projectId:E.projectId,post:(e,t)=>C.proxyPost(e,t),log:P,sessionExternalId:K??void 0,assetThere:e=>(0,x.assetIsThere)(E.basePath,e),resultsOf:e=>C.proxyGet(`/api/projects/${E.projectId}/results?requestId=${encodeURIComponent(e)}`).then(e=>Array.isArray(e?.data)?e.data:Array.isArray(e)?e:[])},s,fe,ye).catch(()=>""):""
3664
+ if(we&&P.info("showing started",{requestId:s,said:we}),"review-submit"===me?.action&&J&&X&&(X.reviewAcceptedSha=J),me?.reviewChange&&ie&&X&&(X.afterReview={...ie,outcome:me.reviewChange},"restarted"===me.reviewChange&&(X.sinceReview=ie)),!me)return A({success:!1,error:"plan_missing"}),{content:[{type:"text",text:`Server validation returned no completion plan for ${s} -- the remote is likely mid-deploy. Retry complete.`}],isError:!0}
3665
+ const be="testing"===me.action||"human-review"===me.action||"merge-cleared"===me.action
3666
+ if(be&&te.testsSkipped&&(D||F&&F.length>0))try{const e=C.getToolRecordClient()
3667
+ e&&await e.createToolRecord({projectId:E.projectId,requestId:s,type:"tests-skipped",metadata:{...D?{reason:D}:{},...F&&F.length>0?{skipTests:F}:{},testGate:te.gates.test,timestamp:(new Date).toISOString()}})}catch(e){P.warn("Failed to persist tests-skipped tool_record",{error:(0,h.getErrorMessage)(e)})}if(be&&M&&M.length>0&&K){const e=C.getSessionMessageClient()
3668
3668
  if(e){let t=new Set
3669
3669
  try{const e=await C.proxyGet(`/api/projects/${E.projectId}/session-messages`,{requestId:s,messageType:"report",limit:200}),r=Array.isArray(e)?e:e?.data??[]
3670
3670
  t=new Set(r.filter(e=>(e?.content?.requestId??e?.content?.anchor?.id)===s).map(e=>String(e?.content?.summary??"")))}catch{}for(const r of M.slice(0,5)){const n=r.length>140?`${r.slice(0,137)}\u2026`:r
3671
3671
  if(!t.has(n))try{await e.createReport({fromSessionId:K,status:"success",summary:n,...r.length>140?{details:r}:{},attention:"fyi",requestId:s})}catch(e){P.warn("worthKnowing note failed (completion continues)",{error:(0,h.getErrorMessage)(e)})}}P.info("worthKnowing notes processed",{count:Math.min(M.length,5),requestId:s})}}if(B&&B.length>0&&K)for(const e of B.slice(0,2))try{const t=Array.isArray(e.files)&&e.files.length>0
3672
- await C.proxyPost(`/api/projects/${E.projectId}/guidance/propose`,{body:e.body,scope:t?"files":"project",...t?{pathAnchors:e.files}:{},...e.evidence?{evidence:e.evidence}:{},...e.userSaid?{userSaid:e.userSaid}:{},requestId:s,sessionExternalId:K}),P.info("guidance proposed at completion",{requestId:s})}catch(e){P.info("guidance at completion not proposed (completion continues)",{requestId:s,reason:(0,h.getErrorMessage)(e)})}const we=C.getRequestClient()
3673
- for(const t of fe.patches)try{const r=await we.updateRequest(s,{...t,completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3674
- e.refsSeen&&r?.namedRefs&&(e.refsSeen.namedRefs=r.namedRefs)}catch(e){return A({success:!1,error:"plan_patch_failed"}),{content:[{type:"text",text:`Failed to apply completion transition (${Object.keys(t).join(", ")}): ${(0,h.getErrorMessage)(e)}`}],isError:!0}}if(A({success:!0}),"review-escalated"===fe.action)return{content:[{type:"text",text:`Request ${s}: review stopped the work and it went to the user (out of review tries, or completed again unchanged). No further action from you; a human finalizes or sends back must_fix items.`}]}
3675
- if("review-start"===fe.action)return{content:[{type:"text",text:`Request ${s}: review started. Read-only reviewers are reading your diff. STOP here and wait: do NOT poll, sleep, or call tools to pass the time; each reviewer's report is delivered to you automatically and wakes you, so just end your turn between reports. When their reports arrive (a detailed handoff follows with the specifics), act on the findings, finish your tasks, and call complete again. If no reviewer finds anything, you are told the review was clean and the request went on with this completion: then do not complete again. After review passes, the server runs any remaining gates and messages you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that and don't merge until it tells you to.`}]}
3676
- if("review-submit"===fe.action)return{content:[{type:"text",text:`Request ${s}: review submitted. The server is evaluating it and will message you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that before acting. If a criterion is still unmet, the criteria reviewer takes another pass and reports back; address any must_fix and call complete again.`}]}
3677
- if("signoff-park"===fe.action)return{content:[{type:"text",text:`Request ${s}: review is complete. This request now awaits the user's sign-off in the UI -- stop here and do NOT call merge.`}]}
3678
- if("promise-hold"===fe.action){const e=fe.detail?` (${fe.detail})`:""
3679
- return{content:[{type:"text",text:`Request ${s}: your change touches the test behind a promise an earlier request made${e}. Only the user changes a promise's test: on the promise card they accept your test, send the work back to put the test back, or retire the promise. Stop here and end your turn; do not call complete or merge again. You are told their answer.`}]}}if("merge-cleared-after-review"===fe.action)return{content:[{type:"text",text:`Request ${s}: review is complete and all gates are clear. Call merge to finalize (do not call complete again).`}]}
3680
- if("testing"===fe.action){const e="human"===fe.testResolver?"A notification has been created asking the user to choose how to handle testing (auto-test, interactive-test, or skip). Stop here; you will receive a report when testing finishes.":"Tests are running automatically in the background. Stop here; each active test process will run and post its own report back to you."
3681
- return{content:[{type:"text",text:`Request ${s}: tests are now running. ${e}\n\n## When reports arrive\nEach test process reports separately: an individual passed report does NOT mean you are cleared.\n- When every process has passed, the server advances the remaining gates automatically: agent review may start (reviewers report their findings to you), the request may wait for sign-off from the user, or the request merges. With your account of every criterion on the record (criteriaComments in this call), the server merges it and tells you so; you call nothing. Only if you are told explicitly that you are "cleared to merge" do you call \`merge\`, with evidence for the criteria you had not accounted for.\n- **Failed**: fix the issues and call \`complete\` again.\n\nDo NOT call merge, finalize, or any other tool before that explicit instruction: stop here and wait.`}]}}if("delivery-review"===fe.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3682
- return{content:[{type:"text",text:`Request ${s} is handed to the DELIVERY review, which is the last gate on this project and resolves the sign-off.${e}\n\nStop here and do NOT call merge: the review finalizes the request, or comes back to you with what it found. End your turn with one short line; your completion summary is what the user reads, so do not write it out again.`}]}}if("human-review"===fe.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3683
- return{content:[{type:"text",text:`Request ${s} submitted for human review.${e}\n\nReview is human-only for this project: the user approves the merge in the UI. Do NOT call merge yourself.`}]}}let be,ve
3684
- try{be=await we.getRequest(s)}catch(e){ve=e}const ke=(0,v.kindProfile)(re??be?.type)
3685
- if("settle"===ke.finalize)return{content:[{type:"text",text:`Request ${s} is complete. A ${ke.label.toLowerCase()} request has no branch, so nothing merges: it closes on its own record now. Stop here and do not call merge.`}]}
3686
- if(void 0!==ve)return{content:[{type:"text",text:`Request ${s} is cleared to merge, but fetching its criteria failed: ${(0,h.getErrorMessage)(ve)}. Call merge with verification evidence for each acceptance criterion.`}]}
3687
- const Ie=be?.acceptanceCriteria||[]
3688
- if(!1===te?.gates?.review?.enabled&&(0,S.checksOff)(te)&&!1===te?.gates?.signoff?.enabled&&"merge"===ke.finalize&&(0===Ie.length||Array.isArray(N)&&N.length>0)){P.info("gates off and account recorded: merging in the same call",{requestId:s})
3672
+ await C.proxyPost(`/api/projects/${E.projectId}/guidance/propose`,{body:e.body,scope:t?"files":"project",...t?{pathAnchors:e.files}:{},...e.evidence?{evidence:e.evidence}:{},...e.userSaid?{userSaid:e.userSaid}:{},requestId:s,sessionExternalId:K}),P.info("guidance proposed at completion",{requestId:s})}catch(e){P.info("guidance at completion not proposed (completion continues)",{requestId:s,reason:(0,h.getErrorMessage)(e)})}const ve=C.getRequestClient()
3673
+ if("answer"===me.action){try{const t=await ve.updateRequest(s,{completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3674
+ e.refsSeen&&t?.namedRefs&&(e.refsSeen.namedRefs=t.namedRefs),await C.proxyPost(`/api/projects/${E.projectId}/requests/${s}/finalize-completion`,{summary:V,acceptanceEvidence:[{evidence:"This changed nothing: its branch holds no change and no record writes into the project."}],mergeResult:{mergeCommitHash:"unknown",cleanedUp:!1,method:"answer-only",diffStats:{additions:0,deletions:0,filesChanged:0}}})}catch(e){return A({success:!1,error:"answer_finish_failed"}),{content:[{type:"text",text:`Your reply on ${s} could not be recorded: ${(0,h.getErrorMessage)(e)}. Call complete again.`}],isError:!0}}return A({success:!0}),{content:[{type:"text",text:`Your summary is the reply to the user on ${s}, and it is with them now. Nothing in the project changed, so nothing is checked and nothing waits for a sign-off: it is finished. Stop here.`}]}}for(const t of me.patches)try{const r=await ve.updateRequest(s,{...t,completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3675
+ e.refsSeen&&r?.namedRefs&&(e.refsSeen.namedRefs=r.namedRefs)}catch(e){return A({success:!1,error:"plan_patch_failed"}),{content:[{type:"text",text:`Failed to apply completion transition (${Object.keys(t).join(", ")}): ${(0,h.getErrorMessage)(e)}`}],isError:!0}}if(A({success:!0}),"review-escalated"===me.action)return{content:[{type:"text",text:`Request ${s}: review stopped the work and it went to the user (out of review tries, or completed again unchanged). No further action from you; a human finalizes or sends back must_fix items.`}]}
3676
+ if("review-start"===me.action)return{content:[{type:"text",text:`Request ${s}: review started. Read-only reviewers are reading your diff. STOP here and wait: do NOT poll, sleep, or call tools to pass the time; each reviewer's report is delivered to you automatically and wakes you, so just end your turn between reports. When their reports arrive (a detailed handoff follows with the specifics), act on the findings, finish your tasks, and call complete again. If no reviewer finds anything, you are told the review was clean and the request went on with this completion: then do not complete again. After review passes, the server runs any remaining gates and messages you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that and don't merge until it tells you to.`}]}
3677
+ if("review-submit"===me.action)return{content:[{type:"text",text:`Request ${s}: review submitted. The server is evaluating it and will message you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that before acting. If a criterion is still unmet, the criteria reviewer takes another pass and reports back; address any must_fix and call complete again.`}]}
3678
+ if("signoff-park"===me.action)return{content:[{type:"text",text:`Request ${s}: review is complete. This request now awaits the user's sign-off in the UI -- stop here and do NOT call merge.`}]}
3679
+ if("promise-hold"===me.action){const e=me.detail?` (${me.detail})`:""
3680
+ return{content:[{type:"text",text:`Request ${s}: your change touches the test behind a promise an earlier request made${e}. Only the user changes a promise's test: on the promise card they accept your test, send the work back to put the test back, or retire the promise. Stop here and end your turn; do not call complete or merge again. You are told their answer.`}]}}if("merge-cleared-after-review"===me.action)return{content:[{type:"text",text:`Request ${s}: review is complete and all gates are clear. Call merge to finalize (do not call complete again).`}]}
3681
+ if("testing"===me.action){const e="human"===me.testResolver?"A notification has been created asking the user to choose how to handle testing (auto-test, interactive-test, or skip). Stop here; you will receive a report when testing finishes.":"Tests are running automatically in the background. Stop here; each active test process will run and post its own report back to you."
3682
+ return{content:[{type:"text",text:`Request ${s}: tests are now running. ${e}\n\n## When reports arrive\nEach test process reports separately: an individual passed report does NOT mean you are cleared.\n- When every process has passed, the server advances the remaining gates automatically: agent review may start (reviewers report their findings to you), the request may wait for sign-off from the user, or the request merges. With your account of every criterion on the record (criteriaComments in this call), the server merges it and tells you so; you call nothing. Only if you are told explicitly that you are "cleared to merge" do you call \`merge\`, with evidence for the criteria you had not accounted for.\n- **Failed**: fix the issues and call \`complete\` again.\n\nDo NOT call merge, finalize, or any other tool before that explicit instruction: stop here and wait.`}]}}if("delivery-review"===me.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3683
+ return{content:[{type:"text",text:`Request ${s} is handed to the DELIVERY review, which is the last gate on this project and resolves the sign-off.${e}\n\nStop here and do NOT call merge: the review finalizes the request, or comes back to you with what it found. End your turn with one short line; your completion summary is what the user reads, so do not write it out again.`}]}}if("human-review"===me.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3684
+ return{content:[{type:"text",text:`Request ${s} submitted for human review.${e}\n\nReview is human-only for this project: the user approves the merge in the UI. Do NOT call merge yourself.`}]}}let ke,Ie
3685
+ try{ke=await ve.getRequest(s)}catch(e){Ie=e}const $e=(0,v.kindProfile)(re??ke?.type)
3686
+ if("settle"===$e.finalize)return{content:[{type:"text",text:`Request ${s} is complete. A ${$e.label.toLowerCase()} request has no branch, so nothing merges: it closes on its own record now. Stop here and do not call merge.`}]}
3687
+ if(void 0!==Ie)return{content:[{type:"text",text:`Request ${s} is cleared to merge, but fetching its criteria failed: ${(0,h.getErrorMessage)(Ie)}. Call merge with verification evidence for each acceptance criterion.`}]}
3688
+ const xe=ke?.acceptanceCriteria||[]
3689
+ if(!1===te?.gates?.review?.enabled&&(0,S.checksOff)(te)&&!1===te?.gates?.signoff?.enabled&&"merge"===$e.finalize&&(0===xe.length||Array.isArray(N)&&N.length>0)){P.info("gates off and account recorded: merging in the same call",{requestId:s})
3689
3690
  const e=await(0,u.handleMergeRequest)({requestId:s,verifications:[]},E,C,q,T,j)
3690
- return e?.isError?e:{...e,content:[{type:"text",text:`Request ${s}: nothing gates this project (review, tests and sign-off are off) and your account per criterion is on the record, so it merged in this call.\n\n${e.content?.[0]?.text??""}`},...e.content?.slice(1)??[]]}}const $e=fe.skippedReason?`\n\n_Skipped re-running tests: ${fe.skippedReason}._\n`:"",xe=fe.noTestsAutoMerge?"\n\n_No test processes are configured for this project, so the test gate has nothing to run; this completion merges without tests._\n":""
3691
- return 0===Ie.length?{content:[{type:"text",text:`Request ${s} is ready. ${$e}${xe}No acceptance criteria defined: call merge directly.`}]}:{content:[{type:"text",text:`Request ${s}: all gates are clear.${$e}${xe}\n\n## Next Step: Verify & Merge\n\n${(0,p.formatVerifyInstructions)(Ie)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(t){let r="An unexpected error occurred",n=""
3691
+ return e?.isError?e:{...e,content:[{type:"text",text:`Request ${s}: nothing gates this project (review, tests and sign-off are off) and your account per criterion is on the record, so it merged in this call.\n\n${e.content?.[0]?.text??""}`},...e.content?.slice(1)??[]]}}const Se=me.skippedReason?`\n\n_Skipped re-running tests: ${me.skippedReason}._\n`:"",_e=me.noTestsAutoMerge?"\n\n_No test processes are configured for this project, so the test gate has nothing to run; this completion merges without tests._\n":""
3692
+ return 0===xe.length?{content:[{type:"text",text:`Request ${s} is ready. ${Se}${_e}No acceptance criteria defined: call merge directly.`}]}:{content:[{type:"text",text:`Request ${s}: all gates are clear.${Se}${_e}\n\n## Next Step: Verify & Merge\n\n${(0,p.formatVerifyInstructions)(xe)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(t){let r="An unexpected error occurred",n=""
3692
3693
  t instanceof s.ZodError?(r="Validation error",n=t.errors.map(e=>`${e.path.join(".")}: ${e.message}`).join(", ")):t instanceof Error?(r=t.message,n=t.stack||""):n=String(t),P.error("Complete request failed",{error:r,details:n})
3693
3694
  try{await(0,i.createFailureToolRecord)("complete-request",t,{error:r,details:n,requestId:e?.requestId},C.getToolRecordClient(),P,T,{requestId:e?.requestId,projectId:E.projectId,note:"Failed to complete request"})}catch{}return T.startTimer("tool_execution_time")({success:!1,error:t instanceof Error?t.name:"unknown"}),{content:[{type:"text",text:`Error: ${r}`}],isError:!0}}}
3694
3695
  const n=t(65454),o=t(59860),s=t(11569),i=t(18616),a=t(35510),c=t(82860),l=t(95122),d=t(7161),u=t(34306),h=t(58824),p=t(65454),f=t(79414),m=t(67071),g=t(92456),y=t(80331),w=t(63580),b=t(52232),v=t(87780),k=t(45391),I=t(43451),$=t(70715),x=t(42692),S=t(64721),_=new Set},32283(e,exports,t){exports.def=void 0
@@ -8337,7 +8338,8 @@ if(t.status===a.PollingStatus.POLLING)return null
8337
8338
  const r=this.authFlow.getPollingUrl(e),n=await fetch(r)
8338
8339
  if(n.ok){const e=await n.json()
8339
8340
  if(e.authenticated&&e.token){const t=this.authFlow.parseTokenResponse(e)
8340
- if(t)return await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),t}}return null}catch(e){return this.logger.error("Error checking authentication status",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,null}}async validateTokenWithRemoteServer(){this.logger.debug("Validating stored token with remote server")
8341
+ if(t)return await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),t}}return null}catch(e){return this.logger.error("Error checking authentication status",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,null}}async signInRefused(){try{const e=await this.getToken()
8342
+ return!!e&&401===(await fetch(`${this.remoteServerUrl}/api/auth/validate`,{method:"GET",headers:{Authorization:`Bearer ${e.token}`},signal:AbortSignal.timeout(1e4)})).status}catch{return!1}}forgetCachedSignIn(){this.invalidateCache()}async validateTokenWithRemoteServer(){this.logger.debug("Validating stored token with remote server")
8341
8343
  try{const e=await this.getToken()
8342
8344
  if(!e)return this.logger.debug("No token available for validation"),!1
8343
8345
  const t=`${this.remoteServerUrl}/auth/validate`
package/dist/index.js CHANGED
@@ -3693,22 +3693,22 @@ const de=async(e,r)=>(await Promise.resolve().then(()=>t(79414))).actionServerFe
3693
3693
  if(G){const e="string"==typeof W?.sitting?.head?W.sitting.head:""
3694
3694
  let t=e?null:X
3695
3695
  if(e)try{const r=await fetch(`${(0,f.getActionServerBaseUrl)()}/api/request-diff-stats?requestId=${encodeURIComponent(s)}&since=${encodeURIComponent(e)}`,{signal:AbortSignal.timeout(5e3)}),n=r.ok?await r.json():null
3696
- n?.data&&(t={files:Array.isArray(n.data.files)?n.data.files.filter(e=>"string"==typeof e):[],additions:n.data.additions,deletions:n.data.deletions})}catch(e){P.debug("the change's own diff could not be read; it is recorded without its files",{requestId:s,error:(0,h.getErrorMessage)(e)})}le={...O?{account:O}:{},files:t?.files??[],..."number"==typeof t?.additions?{additions:t.additions}:{},..."number"==typeof t?.deletions?{deletions:t.deletions}:{}},ce=await(0,x.lookNow)(s,ae,de).catch(()=>{})}const ue=async e=>{const t=await C.proxyPost(`/api/projects/${_.projectId}/requests/${s}/validate-completion`,(0,w.validateCompletionBody)("tool",{sessionId:K,skipTestsReason:D,skipTests:F,headSha:J,...le?{change:le}:{},...e?{look:e}:{},...void 0!==oe?{authoredSinceReview:oe}:{},...ie?{reviewDelta:ie}:{},...se?{intentMoves:se}:{},...X?.files?{files:X.files}:{}}))
3696
+ n?.data&&(t={files:Array.isArray(n.data.files)?n.data.files.filter(e=>"string"==typeof e):[],additions:n.data.additions,deletions:n.data.deletions})}catch(e){P.debug("the change's own diff could not be read; it is recorded without its files",{requestId:s,error:(0,h.getErrorMessage)(e)})}le={...O?{account:O}:{},files:t?.files??[],..."number"==typeof t?.additions?{additions:t.additions}:{},..."number"==typeof t?.deletions?{deletions:t.deletions}:{}},ce=await(0,x.lookNow)(s,ae,de).catch(()=>{})}const ue=G&&("settle"===(0,v.kindProfile)(re??W?.type).finalize||!!X&&0===X.filesChanged&&0===X.additions&&0===X.deletions),he=async e=>{const t=await C.proxyPost(`/api/projects/${_.projectId}/requests/${s}/validate-completion`,(0,w.validateCompletionBody)("tool",{sessionId:K,skipTestsReason:D,skipTests:F,headSha:J,...ue?{diffNone:!0}:{},...le?{change:le}:{},...e?{look:e}:{},...void 0!==oe?{authoredSinceReview:oe}:{},...ie?{reviewDelta:ie}:{},...se?{intentMoves:se}:{},...X?.files?{files:X.files}:{}}))
3697
3697
  return t?.data||t}
3698
- let he=null
3699
- try{if(te=await ue(ce),te.canComplete&&"sitting-look"===te.plan?.action){const e=await(0,x.settleLook)(s,ae,de)
3700
- he=e.served,te=await ue(e.look)}}catch(e){const t=(0,h.getErrorMessage)(e)
3698
+ let pe=null
3699
+ try{if(te=await he(ce),te.canComplete&&"sitting-look"===te.plan?.action){const e=await(0,x.settleLook)(s,ae,de)
3700
+ pe=e.served,te=await he(e.look)}}catch(e){const t=(0,h.getErrorMessage)(e)
3701
3701
  return P.error("Server validation failed",{requestId:s,error:t}),A({success:!1,error:"validation_request_failed"}),{content:[{type:"text",text:`Failed to validate completion: ${t}`}],isError:!0}}if(!te.canComplete){let e=`Cannot complete request ${s}: ${te.reason}\n`
3702
3702
  if(te.blockedByTasks&&te.blockedByTasks.length>0&&(e+="\n**Tasks that must be completed or canceled first:**\n",te.blockedByTasks.forEach((t,r)=>{e+=`${r+1}. **${t.taskId}** - ${t.title} (Status: ${t.status})\n`})),te.lifoViolation&&(e+="\n**Requests that must be re-completed first (LIFO order):**\n",te.lifoViolation.blockingRequests.forEach((t,r)=>{e+=`${r+1}. **${t.requestId}** - ${t.title} (Status: ${t.status})\n`})),ne.length>0)try{const t=await C.getRequestClient().getRequest(s)
3703
3703
  e+=`\n${function(e,t){const r=(Array.isArray(e)?e:[]).map((e,t)=>({c:e,i:t})).filter(({c:e})=>e?.id&&t.includes(String(e.id))).map(({c:e,i:t})=>{const r=Array.isArray(e.verify)?e.verify.filter(e=>"string"==typeof e):[],o=(0,n.latestRow)(e,["verify","check"]),s=o?"met"===o.verdict?"passed":"unmet"===o.verdict?"failed":o.verdict:"not run yet"
3704
3704
  return`- [${(0,n.criterionShortKey)(String(e.id),t)}] ${r.length?`check now: ${r.map(e=>`\`${e.slice(0,120)}\``).join("; ")} (newest result: ${s})`:"no check of its own"}`})
3705
- return 0===r.length?"":`Recorded all the same, as the request reads now: your account on these criteria, and their checks as they stand:\n${r.join("\n")}\nOnly the completion was refused; say so if you tell the user.`}(t?.acceptanceCriteria,ne)}`}catch{}return A({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}if("sitting-held"===te.plan?.action)return P.info("completion held: the round stays open while the user is on its page",{requestId:s,until:te.plan.detail,look:ce,preview:he}),await(0,k.reopenOneTask)(C.getTaskClient(),s).then(()=>(0,I.clearActiveTaskCache)(),e=>P.warn("the round's one task could not be opened again; its worker opens one for its next edit",{requestId:s,error:(0,h.getErrorMessage)(e)})),A({success:!0}),{content:[{type:"text",text:[`The change is recorded on ${s}, and the round stays open: the user is on its page and may ask for more. Nothing is checked or completed yet. That happens once, for everything this round changed, when they go quiet, leave the page or press Complete, and you are told then.`,"Between changes they look at what this round made: a preview of your working copy when it serves a page, and the pictures and documents it changed, as committed. What they see must be current, so after every change run the build or the script that makes it.","When they ask for another change on this round, make it and call complete with `change`: one line saying what that change did. That records it under their words and loads what they are looking at again. Do not call merge. End your turn with that one line."].join("\n")}]}
3705
+ return 0===r.length?"":`Recorded all the same, as the request reads now: your account on these criteria, and their checks as they stand:\n${r.join("\n")}\nOnly the completion was refused; say so if you tell the user.`}(t?.acceptanceCriteria,ne)}`}catch{}return A({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}if("sitting-held"===te.plan?.action)return P.info("completion held: the round stays open while the user is on its page",{requestId:s,until:te.plan.detail,look:ce,preview:pe}),await(0,k.reopenOneTask)(C.getTaskClient(),s).then(()=>(0,I.clearActiveTaskCache)(),e=>P.warn("the round's one task could not be opened again; its worker opens one for its next edit",{requestId:s,error:(0,h.getErrorMessage)(e)})),A({success:!0}),{content:[{type:"text",text:[`The change is recorded on ${s}, and the round stays open: the user is on its page and may ask for more. Nothing is checked or completed yet. That happens once, for everything this round changed, when they go quiet, leave the page or press Complete, and you are told then.`,"Between changes they look at what this round made: a preview of your working copy when it serves a page, and the pictures and documents it changed, as committed. What they see must be current, so after every change run the build or the script that makes it.","When they ask for another change on this round, make it and call complete with `change`: one line saying what that change did. That records it under their words and loads what they are looking at again. Do not call merge. End your turn with that one line."].join("\n")}]}
3706
3706
  if(G&&!i)try{const e=await C.proxyGet(`/api/projects/${_.projectId}/requests/${encodeURIComponent(s)}/rounds`)
3707
3707
  V=function(e,t){const r=[]
3708
3708
  for(const t of Array.isArray(e)?e:[]){const e="string"==typeof t?.changed?t.changed.trim():""
3709
3709
  e&&!r.includes(e)&&r.push(e)}const n=(t??"").replace(/\s+/g," ").trim()
3710
- return n&&!r.includes(n)&&r.push(n),r.join("\n")}(((e?.data??e)?.rounds??[]).find(e=>e?.id===s)?.changes,O)||V}catch(e){P.debug("the round's changes could not be read for its summary; this change's line stands for it",{requestId:s,error:(0,h.getErrorMessage)(e)})}const pe=(0,x.showGiven)(U),fe=te.plan
3711
- await async function(e,t,r,n){try{const o=await e.getRequestClient().getRequest(t),s=function(e,t){return(Array.isArray(e)?e:[]).flatMap(e=>{if(!e?.id||!(0,$.hasBaseline)(e)||e.retired||e.standing&&e.waived)return[]
3710
+ return n&&!r.includes(n)&&r.push(n),r.join("\n")}(((e?.data??e)?.rounds??[]).find(e=>e?.id===s)?.changes,O)||V}catch(e){P.debug("the round's changes could not be read for its summary; this change's line stands for it",{requestId:s,error:(0,h.getErrorMessage)(e)})}const fe=(0,x.showGiven)(U),me=te.plan,ge="answer"===me?.action
3711
+ ge||await async function(e,t,r,n){try{const o=await e.getRequestClient().getRequest(t),s=function(e,t){return(Array.isArray(e)?e:[]).flatMap(e=>{if(!e?.id||!(0,$.hasBaseline)(e)||e.retired||e.standing&&e.waived)return[]
3712
3712
  const r="string"==typeof e.command?e.command.trim():""
3713
3713
  if(!r)return[]
3714
3714
  const n=Array.isArray(e.ledger)?e.ledger:[]
@@ -3716,35 +3716,36 @@ return t&&n.some(e=>"verify"===e?.source&&"string"==typeof e?.instrument&&e.inst
3716
3716
  if(0===s.length)return
3717
3717
  const i=await fetch(`${(0,f.getActionServerBaseUrl)()}/api/baseline-measure`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({requestId:t,baselines:s}),signal:AbortSignal.timeout(2e4)})
3718
3718
  n.info("baseline measurement started beside the sign-off check; the merge waits for it",{requestId:t,baselines:s.length,ok:i.ok})}catch(e){n.debug("baseline measurement could not start; the card says it was not measured",{requestId:t,error:(0,h.getErrorMessage)(e)})}}(C,s,J,P)
3719
- const me=fe&&pe.artifact?await C.getRequestClient().getRequest(s).then(e=>String(e?.title??"")).catch(()=>""):"",ge=fe?await(0,x.startShowing)({projectId:_.projectId,post:(e,t)=>C.proxyPost(e,t),log:P,sessionExternalId:K??void 0,assetThere:e=>(0,x.assetIsThere)(_.basePath,e),resultsOf:e=>C.proxyGet(`/api/projects/${_.projectId}/results?requestId=${encodeURIComponent(e)}`).then(e=>Array.isArray(e?.data)?e.data:Array.isArray(e)?e:[])},s,pe,me).catch(()=>""):""
3720
- if(ge&&P.info("showing started",{requestId:s,said:ge}),"review-submit"===fe?.action&&J&&X&&(X.reviewAcceptedSha=J),fe?.reviewChange&&ie&&X&&(X.afterReview={...ie,outcome:fe.reviewChange},"restarted"===fe.reviewChange&&(X.sinceReview=ie)),!fe)return A({success:!1,error:"plan_missing"}),{content:[{type:"text",text:`Server validation returned no completion plan for ${s} -- the remote is likely mid-deploy. Retry complete.`}],isError:!0}
3721
- const ye="testing"===fe.action||"human-review"===fe.action||"merge-cleared"===fe.action
3722
- if(ye&&te.testsSkipped&&(D||F&&F.length>0))try{const e=C.getToolRecordClient()
3723
- e&&await e.createToolRecord({projectId:_.projectId,requestId:s,type:"tests-skipped",metadata:{...D?{reason:D}:{},...F&&F.length>0?{skipTests:F}:{},testGate:te.gates.test,timestamp:(new Date).toISOString()}})}catch(e){P.warn("Failed to persist tests-skipped tool_record",{error:(0,h.getErrorMessage)(e)})}if(ye&&M&&M.length>0&&K){const e=C.getSessionMessageClient()
3719
+ const ye=me&&fe.artifact?await C.getRequestClient().getRequest(s).then(e=>String(e?.title??"")).catch(()=>""):"",we=me&&!ge?await(0,x.startShowing)({projectId:_.projectId,post:(e,t)=>C.proxyPost(e,t),log:P,sessionExternalId:K??void 0,assetThere:e=>(0,x.assetIsThere)(_.basePath,e),resultsOf:e=>C.proxyGet(`/api/projects/${_.projectId}/results?requestId=${encodeURIComponent(e)}`).then(e=>Array.isArray(e?.data)?e.data:Array.isArray(e)?e:[])},s,fe,ye).catch(()=>""):""
3720
+ if(we&&P.info("showing started",{requestId:s,said:we}),"review-submit"===me?.action&&J&&X&&(X.reviewAcceptedSha=J),me?.reviewChange&&ie&&X&&(X.afterReview={...ie,outcome:me.reviewChange},"restarted"===me.reviewChange&&(X.sinceReview=ie)),!me)return A({success:!1,error:"plan_missing"}),{content:[{type:"text",text:`Server validation returned no completion plan for ${s} -- the remote is likely mid-deploy. Retry complete.`}],isError:!0}
3721
+ const be="testing"===me.action||"human-review"===me.action||"merge-cleared"===me.action
3722
+ if(be&&te.testsSkipped&&(D||F&&F.length>0))try{const e=C.getToolRecordClient()
3723
+ e&&await e.createToolRecord({projectId:_.projectId,requestId:s,type:"tests-skipped",metadata:{...D?{reason:D}:{},...F&&F.length>0?{skipTests:F}:{},testGate:te.gates.test,timestamp:(new Date).toISOString()}})}catch(e){P.warn("Failed to persist tests-skipped tool_record",{error:(0,h.getErrorMessage)(e)})}if(be&&M&&M.length>0&&K){const e=C.getSessionMessageClient()
3724
3724
  if(e){let t=new Set
3725
3725
  try{const e=await C.proxyGet(`/api/projects/${_.projectId}/session-messages`,{requestId:s,messageType:"report",limit:200}),r=Array.isArray(e)?e:e?.data??[]
3726
3726
  t=new Set(r.filter(e=>(e?.content?.requestId??e?.content?.anchor?.id)===s).map(e=>String(e?.content?.summary??"")))}catch{}for(const r of M.slice(0,5)){const n=r.length>140?`${r.slice(0,137)}\u2026`:r
3727
3727
  if(!t.has(n))try{await e.createReport({fromSessionId:K,status:"success",summary:n,...r.length>140?{details:r}:{},attention:"fyi",requestId:s})}catch(e){P.warn("worthKnowing note failed (completion continues)",{error:(0,h.getErrorMessage)(e)})}}P.info("worthKnowing notes processed",{count:Math.min(M.length,5),requestId:s})}}if(L&&L.length>0&&K)for(const e of L.slice(0,2))try{const t=Array.isArray(e.files)&&e.files.length>0
3728
- await C.proxyPost(`/api/projects/${_.projectId}/guidance/propose`,{body:e.body,scope:t?"files":"project",...t?{pathAnchors:e.files}:{},...e.evidence?{evidence:e.evidence}:{},...e.userSaid?{userSaid:e.userSaid}:{},requestId:s,sessionExternalId:K}),P.info("guidance proposed at completion",{requestId:s})}catch(e){P.info("guidance at completion not proposed (completion continues)",{requestId:s,reason:(0,h.getErrorMessage)(e)})}const we=C.getRequestClient()
3729
- for(const t of fe.patches)try{const r=await we.updateRequest(s,{...t,completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3730
- e.refsSeen&&r?.namedRefs&&(e.refsSeen.namedRefs=r.namedRefs)}catch(e){return A({success:!1,error:"plan_patch_failed"}),{content:[{type:"text",text:`Failed to apply completion transition (${Object.keys(t).join(", ")}): ${(0,h.getErrorMessage)(e)}`}],isError:!0}}if(A({success:!0}),"review-escalated"===fe.action)return{content:[{type:"text",text:`Request ${s}: review stopped the work and it went to the user (out of review tries, or completed again unchanged). No further action from you; a human finalizes or sends back must_fix items.`}]}
3731
- if("review-start"===fe.action)return{content:[{type:"text",text:`Request ${s}: review started. Read-only reviewers are reading your diff. STOP here and wait: do NOT poll, sleep, or call tools to pass the time; each reviewer's report is delivered to you automatically and wakes you, so just end your turn between reports. When their reports arrive (a detailed handoff follows with the specifics), act on the findings, finish your tasks, and call complete again. If no reviewer finds anything, you are told the review was clean and the request went on with this completion: then do not complete again. After review passes, the server runs any remaining gates and messages you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that and don't merge until it tells you to.`}]}
3732
- if("review-submit"===fe.action)return{content:[{type:"text",text:`Request ${s}: review submitted. The server is evaluating it and will message you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that before acting. If a criterion is still unmet, the criteria reviewer takes another pass and reports back; address any must_fix and call complete again.`}]}
3733
- if("signoff-park"===fe.action)return{content:[{type:"text",text:`Request ${s}: review is complete. This request now awaits the user's sign-off in the UI -- stop here and do NOT call merge.`}]}
3734
- if("promise-hold"===fe.action){const e=fe.detail?` (${fe.detail})`:""
3735
- return{content:[{type:"text",text:`Request ${s}: your change touches the test behind a promise an earlier request made${e}. Only the user changes a promise's test: on the promise card they accept your test, send the work back to put the test back, or retire the promise. Stop here and end your turn; do not call complete or merge again. You are told their answer.`}]}}if("merge-cleared-after-review"===fe.action)return{content:[{type:"text",text:`Request ${s}: review is complete and all gates are clear. Call merge to finalize (do not call complete again).`}]}
3736
- if("testing"===fe.action){const e="human"===fe.testResolver?"A notification has been created asking the user to choose how to handle testing (auto-test, interactive-test, or skip). Stop here; you will receive a report when testing finishes.":"Tests are running automatically in the background. Stop here; each active test process will run and post its own report back to you."
3737
- return{content:[{type:"text",text:`Request ${s}: tests are now running. ${e}\n\n## When reports arrive\nEach test process reports separately: an individual passed report does NOT mean you are cleared.\n- When every process has passed, the server advances the remaining gates automatically: agent review may start (reviewers report their findings to you), the request may wait for sign-off from the user, or the request merges. With your account of every criterion on the record (criteriaComments in this call), the server merges it and tells you so; you call nothing. Only if you are told explicitly that you are "cleared to merge" do you call \`merge\`, with evidence for the criteria you had not accounted for.\n- **Failed**: fix the issues and call \`complete\` again.\n\nDo NOT call merge, finalize, or any other tool before that explicit instruction: stop here and wait.`}]}}if("delivery-review"===fe.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3738
- return{content:[{type:"text",text:`Request ${s} is handed to the DELIVERY review, which is the last gate on this project and resolves the sign-off.${e}\n\nStop here and do NOT call merge: the review finalizes the request, or comes back to you with what it found. End your turn with one short line; your completion summary is what the user reads, so do not write it out again.`}]}}if("human-review"===fe.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3739
- return{content:[{type:"text",text:`Request ${s} submitted for human review.${e}\n\nReview is human-only for this project: the user approves the merge in the UI. Do NOT call merge yourself.`}]}}let be,ve
3740
- try{be=await we.getRequest(s)}catch(e){ve=e}const ke=(0,v.kindProfile)(re??be?.type)
3741
- if("settle"===ke.finalize)return{content:[{type:"text",text:`Request ${s} is complete. A ${ke.label.toLowerCase()} request has no branch, so nothing merges: it closes on its own record now. Stop here and do not call merge.`}]}
3742
- if(void 0!==ve)return{content:[{type:"text",text:`Request ${s} is cleared to merge, but fetching its criteria failed: ${(0,h.getErrorMessage)(ve)}. Call merge with verification evidence for each acceptance criterion.`}]}
3743
- const Ie=be?.acceptanceCriteria||[]
3744
- if(!1===te?.gates?.review?.enabled&&(0,S.checksOff)(te)&&!1===te?.gates?.signoff?.enabled&&"merge"===ke.finalize&&(0===Ie.length||Array.isArray(N)&&N.length>0)){P.info("gates off and account recorded: merging in the same call",{requestId:s})
3728
+ await C.proxyPost(`/api/projects/${_.projectId}/guidance/propose`,{body:e.body,scope:t?"files":"project",...t?{pathAnchors:e.files}:{},...e.evidence?{evidence:e.evidence}:{},...e.userSaid?{userSaid:e.userSaid}:{},requestId:s,sessionExternalId:K}),P.info("guidance proposed at completion",{requestId:s})}catch(e){P.info("guidance at completion not proposed (completion continues)",{requestId:s,reason:(0,h.getErrorMessage)(e)})}const ve=C.getRequestClient()
3729
+ if("answer"===me.action){try{const t=await ve.updateRequest(s,{completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3730
+ e.refsSeen&&t?.namedRefs&&(e.refsSeen.namedRefs=t.namedRefs),await C.proxyPost(`/api/projects/${_.projectId}/requests/${s}/finalize-completion`,{summary:V,acceptanceEvidence:[{evidence:"This changed nothing: its branch holds no change and no record writes into the project."}],mergeResult:{mergeCommitHash:"unknown",cleanedUp:!1,method:"answer-only",diffStats:{additions:0,deletions:0,filesChanged:0}}})}catch(e){return A({success:!1,error:"answer_finish_failed"}),{content:[{type:"text",text:`Your reply on ${s} could not be recorded: ${(0,h.getErrorMessage)(e)}. Call complete again.`}],isError:!0}}return A({success:!0}),{content:[{type:"text",text:`Your summary is the reply to the user on ${s}, and it is with them now. Nothing in the project changed, so nothing is checked and nothing waits for a sign-off: it is finished. Stop here.`}]}}for(const t of me.patches)try{const r=await ve.updateRequest(s,{...t,completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3731
+ e.refsSeen&&r?.namedRefs&&(e.refsSeen.namedRefs=r.namedRefs)}catch(e){return A({success:!1,error:"plan_patch_failed"}),{content:[{type:"text",text:`Failed to apply completion transition (${Object.keys(t).join(", ")}): ${(0,h.getErrorMessage)(e)}`}],isError:!0}}if(A({success:!0}),"review-escalated"===me.action)return{content:[{type:"text",text:`Request ${s}: review stopped the work and it went to the user (out of review tries, or completed again unchanged). No further action from you; a human finalizes or sends back must_fix items.`}]}
3732
+ if("review-start"===me.action)return{content:[{type:"text",text:`Request ${s}: review started. Read-only reviewers are reading your diff. STOP here and wait: do NOT poll, sleep, or call tools to pass the time; each reviewer's report is delivered to you automatically and wakes you, so just end your turn between reports. When their reports arrive (a detailed handoff follows with the specifics), act on the findings, finish your tasks, and call complete again. If no reviewer finds anything, you are told the review was clean and the request went on with this completion: then do not complete again. After review passes, the server runs any remaining gates and messages you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that and don't merge until it tells you to.`}]}
3733
+ if("review-submit"===me.action)return{content:[{type:"text",text:`Request ${s}: review submitted. The server is evaluating it and will message you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that before acting. If a criterion is still unmet, the criteria reviewer takes another pass and reports back; address any must_fix and call complete again.`}]}
3734
+ if("signoff-park"===me.action)return{content:[{type:"text",text:`Request ${s}: review is complete. This request now awaits the user's sign-off in the UI -- stop here and do NOT call merge.`}]}
3735
+ if("promise-hold"===me.action){const e=me.detail?` (${me.detail})`:""
3736
+ return{content:[{type:"text",text:`Request ${s}: your change touches the test behind a promise an earlier request made${e}. Only the user changes a promise's test: on the promise card they accept your test, send the work back to put the test back, or retire the promise. Stop here and end your turn; do not call complete or merge again. You are told their answer.`}]}}if("merge-cleared-after-review"===me.action)return{content:[{type:"text",text:`Request ${s}: review is complete and all gates are clear. Call merge to finalize (do not call complete again).`}]}
3737
+ if("testing"===me.action){const e="human"===me.testResolver?"A notification has been created asking the user to choose how to handle testing (auto-test, interactive-test, or skip). Stop here; you will receive a report when testing finishes.":"Tests are running automatically in the background. Stop here; each active test process will run and post its own report back to you."
3738
+ return{content:[{type:"text",text:`Request ${s}: tests are now running. ${e}\n\n## When reports arrive\nEach test process reports separately: an individual passed report does NOT mean you are cleared.\n- When every process has passed, the server advances the remaining gates automatically: agent review may start (reviewers report their findings to you), the request may wait for sign-off from the user, or the request merges. With your account of every criterion on the record (criteriaComments in this call), the server merges it and tells you so; you call nothing. Only if you are told explicitly that you are "cleared to merge" do you call \`merge\`, with evidence for the criteria you had not accounted for.\n- **Failed**: fix the issues and call \`complete\` again.\n\nDo NOT call merge, finalize, or any other tool before that explicit instruction: stop here and wait.`}]}}if("delivery-review"===me.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3739
+ return{content:[{type:"text",text:`Request ${s} is handed to the DELIVERY review, which is the last gate on this project and resolves the sign-off.${e}\n\nStop here and do NOT call merge: the review finalizes the request, or comes back to you with what it found. End your turn with one short line; your completion summary is what the user reads, so do not write it out again.`}]}}if("human-review"===me.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3740
+ return{content:[{type:"text",text:`Request ${s} submitted for human review.${e}\n\nReview is human-only for this project: the user approves the merge in the UI. Do NOT call merge yourself.`}]}}let ke,Ie
3741
+ try{ke=await ve.getRequest(s)}catch(e){Ie=e}const $e=(0,v.kindProfile)(re??ke?.type)
3742
+ if("settle"===$e.finalize)return{content:[{type:"text",text:`Request ${s} is complete. A ${$e.label.toLowerCase()} request has no branch, so nothing merges: it closes on its own record now. Stop here and do not call merge.`}]}
3743
+ if(void 0!==Ie)return{content:[{type:"text",text:`Request ${s} is cleared to merge, but fetching its criteria failed: ${(0,h.getErrorMessage)(Ie)}. Call merge with verification evidence for each acceptance criterion.`}]}
3744
+ const xe=ke?.acceptanceCriteria||[]
3745
+ if(!1===te?.gates?.review?.enabled&&(0,S.checksOff)(te)&&!1===te?.gates?.signoff?.enabled&&"merge"===$e.finalize&&(0===xe.length||Array.isArray(N)&&N.length>0)){P.info("gates off and account recorded: merging in the same call",{requestId:s})
3745
3746
  const e=await(0,u.handleMergeRequest)({requestId:s,verifications:[]},_,C,T,q,R)
3746
- return e?.isError?e:{...e,content:[{type:"text",text:`Request ${s}: nothing gates this project (review, tests and sign-off are off) and your account per criterion is on the record, so it merged in this call.\n\n${e.content?.[0]?.text??""}`},...e.content?.slice(1)??[]]}}const $e=fe.skippedReason?`\n\n_Skipped re-running tests: ${fe.skippedReason}._\n`:"",xe=fe.noTestsAutoMerge?"\n\n_No test processes are configured for this project, so the test gate has nothing to run; this completion merges without tests._\n":""
3747
- return 0===Ie.length?{content:[{type:"text",text:`Request ${s} is ready. ${$e}${xe}No acceptance criteria defined: call merge directly.`}]}:{content:[{type:"text",text:`Request ${s}: all gates are clear.${$e}${xe}\n\n## Next Step: Verify & Merge\n\n${(0,p.formatVerifyInstructions)(Ie)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(t){let r="An unexpected error occurred",n=""
3747
+ return e?.isError?e:{...e,content:[{type:"text",text:`Request ${s}: nothing gates this project (review, tests and sign-off are off) and your account per criterion is on the record, so it merged in this call.\n\n${e.content?.[0]?.text??""}`},...e.content?.slice(1)??[]]}}const Se=me.skippedReason?`\n\n_Skipped re-running tests: ${me.skippedReason}._\n`:"",Ee=me.noTestsAutoMerge?"\n\n_No test processes are configured for this project, so the test gate has nothing to run; this completion merges without tests._\n":""
3748
+ return 0===xe.length?{content:[{type:"text",text:`Request ${s} is ready. ${Se}${Ee}No acceptance criteria defined: call merge directly.`}]}:{content:[{type:"text",text:`Request ${s}: all gates are clear.${Se}${Ee}\n\n## Next Step: Verify & Merge\n\n${(0,p.formatVerifyInstructions)(xe)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(t){let r="An unexpected error occurred",n=""
3748
3749
  t instanceof s.ZodError?(r="Validation error",n=t.errors.map(e=>`${e.path.join(".")}: ${e.message}`).join(", ")):t instanceof Error?(r=t.message,n=t.stack||""):n=String(t),P.error("Complete request failed",{error:r,details:n})
3749
3750
  try{await(0,i.createFailureToolRecord)("complete-request",t,{error:r,details:n,requestId:e?.requestId},C.getToolRecordClient(),P,q,{requestId:e?.requestId,projectId:_.projectId,note:"Failed to complete request"})}catch{}return q.startTimer("tool_execution_time")({success:!1,error:t instanceof Error?t.name:"unknown"}),{content:[{type:"text",text:`Error: ${r}`}],isError:!0}}}
3750
3751
  const n=t(65454),o=t(59860),s=t(11569),i=t(18616),a=t(35510),c=t(82860),l=t(95122),d=t(7161),u=t(34306),h=t(58824),p=t(65454),f=t(79414),m=t(67071),g=t(92456),y=t(80331),w=t(63580),b=t(52232),v=t(87780),k=t(45391),I=t(43451),$=t(70715),x=t(42692),S=t(64721),E=new Set},32283(e,exports,t){exports.def=void 0
@@ -8433,7 +8434,8 @@ if(t.status===a.PollingStatus.POLLING)return null
8433
8434
  const r=this.authFlow.getPollingUrl(e),n=await fetch(r)
8434
8435
  if(n.ok){const e=await n.json()
8435
8436
  if(e.authenticated&&e.token){const t=this.authFlow.parseTokenResponse(e)
8436
- if(t)return await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),t}}return null}catch(e){return this.logger.error("Error checking authentication status",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,null}}async validateTokenWithRemoteServer(){this.logger.debug("Validating stored token with remote server")
8437
+ if(t)return await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),t}}return null}catch(e){return this.logger.error("Error checking authentication status",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,null}}async signInRefused(){try{const e=await this.getToken()
8438
+ return!!e&&401===(await fetch(`${this.remoteServerUrl}/api/auth/validate`,{method:"GET",headers:{Authorization:`Bearer ${e.token}`},signal:AbortSignal.timeout(1e4)})).status}catch{return!1}}forgetCachedSignIn(){this.invalidateCache()}async validateTokenWithRemoteServer(){this.logger.debug("Validating stored token with remote server")
8437
8439
  try{const e=await this.getToken()
8438
8440
  if(!e)return this.logger.debug("No token available for validation"),!1
8439
8441
  const t=`${this.remoteServerUrl}/auth/validate`
@@ -3529,22 +3529,22 @@ const de=async(e,r)=>(await Promise.resolve().then(()=>t(79414))).actionServerFe
3529
3529
  if(G){const e="string"==typeof W?.sitting?.head?W.sitting.head:""
3530
3530
  let t=e?null:X
3531
3531
  if(e)try{const r=await fetch(`${(0,f.getActionServerBaseUrl)()}/api/request-diff-stats?requestId=${encodeURIComponent(s)}&since=${encodeURIComponent(e)}`,{signal:AbortSignal.timeout(5e3)}),n=r.ok?await r.json():null
3532
- n?.data&&(t={files:Array.isArray(n.data.files)?n.data.files.filter(e=>"string"==typeof e):[],additions:n.data.additions,deletions:n.data.deletions})}catch(e){P.debug("the change's own diff could not be read; it is recorded without its files",{requestId:s,error:(0,h.getErrorMessage)(e)})}le={...O?{account:O}:{},files:t?.files??[],..."number"==typeof t?.additions?{additions:t.additions}:{},..."number"==typeof t?.deletions?{deletions:t.deletions}:{}},ce=await(0,x.lookNow)(s,ae,de).catch(()=>{})}const ue=async e=>{const t=await C.proxyPost(`/api/projects/${E.projectId}/requests/${s}/validate-completion`,(0,w.validateCompletionBody)("tool",{sessionId:K,skipTestsReason:D,skipTests:F,headSha:J,...le?{change:le}:{},...e?{look:e}:{},...void 0!==oe?{authoredSinceReview:oe}:{},...ie?{reviewDelta:ie}:{},...se?{intentMoves:se}:{},...X?.files?{files:X.files}:{}}))
3532
+ n?.data&&(t={files:Array.isArray(n.data.files)?n.data.files.filter(e=>"string"==typeof e):[],additions:n.data.additions,deletions:n.data.deletions})}catch(e){P.debug("the change's own diff could not be read; it is recorded without its files",{requestId:s,error:(0,h.getErrorMessage)(e)})}le={...O?{account:O}:{},files:t?.files??[],..."number"==typeof t?.additions?{additions:t.additions}:{},..."number"==typeof t?.deletions?{deletions:t.deletions}:{}},ce=await(0,x.lookNow)(s,ae,de).catch(()=>{})}const ue=G&&("settle"===(0,v.kindProfile)(re??W?.type).finalize||!!X&&0===X.filesChanged&&0===X.additions&&0===X.deletions),he=async e=>{const t=await C.proxyPost(`/api/projects/${E.projectId}/requests/${s}/validate-completion`,(0,w.validateCompletionBody)("tool",{sessionId:K,skipTestsReason:D,skipTests:F,headSha:J,...ue?{diffNone:!0}:{},...le?{change:le}:{},...e?{look:e}:{},...void 0!==oe?{authoredSinceReview:oe}:{},...ie?{reviewDelta:ie}:{},...se?{intentMoves:se}:{},...X?.files?{files:X.files}:{}}))
3533
3533
  return t?.data||t}
3534
- let he=null
3535
- try{if(te=await ue(ce),te.canComplete&&"sitting-look"===te.plan?.action){const e=await(0,x.settleLook)(s,ae,de)
3536
- he=e.served,te=await ue(e.look)}}catch(e){const t=(0,h.getErrorMessage)(e)
3534
+ let pe=null
3535
+ try{if(te=await he(ce),te.canComplete&&"sitting-look"===te.plan?.action){const e=await(0,x.settleLook)(s,ae,de)
3536
+ pe=e.served,te=await he(e.look)}}catch(e){const t=(0,h.getErrorMessage)(e)
3537
3537
  return P.error("Server validation failed",{requestId:s,error:t}),j({success:!1,error:"validation_request_failed"}),{content:[{type:"text",text:`Failed to validate completion: ${t}`}],isError:!0}}if(!te.canComplete){let e=`Cannot complete request ${s}: ${te.reason}\n`
3538
3538
  if(te.blockedByTasks&&te.blockedByTasks.length>0&&(e+="\n**Tasks that must be completed or canceled first:**\n",te.blockedByTasks.forEach((t,r)=>{e+=`${r+1}. **${t.taskId}** - ${t.title} (Status: ${t.status})\n`})),te.lifoViolation&&(e+="\n**Requests that must be re-completed first (LIFO order):**\n",te.lifoViolation.blockingRequests.forEach((t,r)=>{e+=`${r+1}. **${t.requestId}** - ${t.title} (Status: ${t.status})\n`})),ne.length>0)try{const t=await C.getRequestClient().getRequest(s)
3539
3539
  e+=`\n${function(e,t){const r=(Array.isArray(e)?e:[]).map((e,t)=>({c:e,i:t})).filter(({c:e})=>e?.id&&t.includes(String(e.id))).map(({c:e,i:t})=>{const r=Array.isArray(e.verify)?e.verify.filter(e=>"string"==typeof e):[],o=(0,n.latestRow)(e,["verify","check"]),s=o?"met"===o.verdict?"passed":"unmet"===o.verdict?"failed":o.verdict:"not run yet"
3540
3540
  return`- [${(0,n.criterionShortKey)(String(e.id),t)}] ${r.length?`check now: ${r.map(e=>`\`${e.slice(0,120)}\``).join("; ")} (newest result: ${s})`:"no check of its own"}`})
3541
- return 0===r.length?"":`Recorded all the same, as the request reads now: your account on these criteria, and their checks as they stand:\n${r.join("\n")}\nOnly the completion was refused; say so if you tell the user.`}(t?.acceptanceCriteria,ne)}`}catch{}return j({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}if("sitting-held"===te.plan?.action)return P.info("completion held: the round stays open while the user is on its page",{requestId:s,until:te.plan.detail,look:ce,preview:he}),await(0,k.reopenOneTask)(C.getTaskClient(),s).then(()=>(0,I.clearActiveTaskCache)(),e=>P.warn("the round's one task could not be opened again; its worker opens one for its next edit",{requestId:s,error:(0,h.getErrorMessage)(e)})),j({success:!0}),{content:[{type:"text",text:[`The change is recorded on ${s}, and the round stays open: the user is on its page and may ask for more. Nothing is checked or completed yet. That happens once, for everything this round changed, when they go quiet, leave the page or press Complete, and you are told then.`,"Between changes they look at what this round made: a preview of your working copy when it serves a page, and the pictures and documents it changed, as committed. What they see must be current, so after every change run the build or the script that makes it.","When they ask for another change on this round, make it and call complete with `change`: one line saying what that change did. That records it under their words and loads what they are looking at again. Do not call merge. End your turn with that one line."].join("\n")}]}
3541
+ return 0===r.length?"":`Recorded all the same, as the request reads now: your account on these criteria, and their checks as they stand:\n${r.join("\n")}\nOnly the completion was refused; say so if you tell the user.`}(t?.acceptanceCriteria,ne)}`}catch{}return j({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}if("sitting-held"===te.plan?.action)return P.info("completion held: the round stays open while the user is on its page",{requestId:s,until:te.plan.detail,look:ce,preview:pe}),await(0,k.reopenOneTask)(C.getTaskClient(),s).then(()=>(0,I.clearActiveTaskCache)(),e=>P.warn("the round's one task could not be opened again; its worker opens one for its next edit",{requestId:s,error:(0,h.getErrorMessage)(e)})),j({success:!0}),{content:[{type:"text",text:[`The change is recorded on ${s}, and the round stays open: the user is on its page and may ask for more. Nothing is checked or completed yet. That happens once, for everything this round changed, when they go quiet, leave the page or press Complete, and you are told then.`,"Between changes they look at what this round made: a preview of your working copy when it serves a page, and the pictures and documents it changed, as committed. What they see must be current, so after every change run the build or the script that makes it.","When they ask for another change on this round, make it and call complete with `change`: one line saying what that change did. That records it under their words and loads what they are looking at again. Do not call merge. End your turn with that one line."].join("\n")}]}
3542
3542
  if(G&&!i)try{const e=await C.proxyGet(`/api/projects/${E.projectId}/requests/${encodeURIComponent(s)}/rounds`)
3543
3543
  V=function(e,t){const r=[]
3544
3544
  for(const t of Array.isArray(e)?e:[]){const e="string"==typeof t?.changed?t.changed.trim():""
3545
3545
  e&&!r.includes(e)&&r.push(e)}const n=(t??"").replace(/\s+/g," ").trim()
3546
- return n&&!r.includes(n)&&r.push(n),r.join("\n")}(((e?.data??e)?.rounds??[]).find(e=>e?.id===s)?.changes,O)||V}catch(e){P.debug("the round's changes could not be read for its summary; this change's line stands for it",{requestId:s,error:(0,h.getErrorMessage)(e)})}const pe=(0,x.showGiven)(U),fe=te.plan
3547
- await async function(e,t,r,n){try{const o=await e.getRequestClient().getRequest(t),s=function(e,t){return(Array.isArray(e)?e:[]).flatMap(e=>{if(!e?.id||!(0,$.hasBaseline)(e)||e.retired||e.standing&&e.waived)return[]
3546
+ return n&&!r.includes(n)&&r.push(n),r.join("\n")}(((e?.data??e)?.rounds??[]).find(e=>e?.id===s)?.changes,O)||V}catch(e){P.debug("the round's changes could not be read for its summary; this change's line stands for it",{requestId:s,error:(0,h.getErrorMessage)(e)})}const fe=(0,x.showGiven)(U),me=te.plan,ge="answer"===me?.action
3547
+ ge||await async function(e,t,r,n){try{const o=await e.getRequestClient().getRequest(t),s=function(e,t){return(Array.isArray(e)?e:[]).flatMap(e=>{if(!e?.id||!(0,$.hasBaseline)(e)||e.retired||e.standing&&e.waived)return[]
3548
3548
  const r="string"==typeof e.command?e.command.trim():""
3549
3549
  if(!r)return[]
3550
3550
  const n=Array.isArray(e.ledger)?e.ledger:[]
@@ -3552,35 +3552,36 @@ return t&&n.some(e=>"verify"===e?.source&&"string"==typeof e?.instrument&&e.inst
3552
3552
  if(0===s.length)return
3553
3553
  const i=await fetch(`${(0,f.getActionServerBaseUrl)()}/api/baseline-measure`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({requestId:t,baselines:s}),signal:AbortSignal.timeout(2e4)})
3554
3554
  n.info("baseline measurement started beside the sign-off check; the merge waits for it",{requestId:t,baselines:s.length,ok:i.ok})}catch(e){n.debug("baseline measurement could not start; the card says it was not measured",{requestId:t,error:(0,h.getErrorMessage)(e)})}}(C,s,J,P)
3555
- const me=fe&&pe.artifact?await C.getRequestClient().getRequest(s).then(e=>String(e?.title??"")).catch(()=>""):"",ge=fe?await(0,x.startShowing)({projectId:E.projectId,post:(e,t)=>C.proxyPost(e,t),log:P,sessionExternalId:K??void 0,assetThere:e=>(0,x.assetIsThere)(E.basePath,e),resultsOf:e=>C.proxyGet(`/api/projects/${E.projectId}/results?requestId=${encodeURIComponent(e)}`).then(e=>Array.isArray(e?.data)?e.data:Array.isArray(e)?e:[])},s,pe,me).catch(()=>""):""
3556
- if(ge&&P.info("showing started",{requestId:s,said:ge}),"review-submit"===fe?.action&&J&&X&&(X.reviewAcceptedSha=J),fe?.reviewChange&&ie&&X&&(X.afterReview={...ie,outcome:fe.reviewChange},"restarted"===fe.reviewChange&&(X.sinceReview=ie)),!fe)return j({success:!1,error:"plan_missing"}),{content:[{type:"text",text:`Server validation returned no completion plan for ${s} -- the remote is likely mid-deploy. Retry complete.`}],isError:!0}
3557
- const ye="testing"===fe.action||"human-review"===fe.action||"merge-cleared"===fe.action
3558
- if(ye&&te.testsSkipped&&(D||F&&F.length>0))try{const e=C.getToolRecordClient()
3559
- e&&await e.createToolRecord({projectId:E.projectId,requestId:s,type:"tests-skipped",metadata:{...D?{reason:D}:{},...F&&F.length>0?{skipTests:F}:{},testGate:te.gates.test,timestamp:(new Date).toISOString()}})}catch(e){P.warn("Failed to persist tests-skipped tool_record",{error:(0,h.getErrorMessage)(e)})}if(ye&&M&&M.length>0&&K){const e=C.getSessionMessageClient()
3555
+ const ye=me&&fe.artifact?await C.getRequestClient().getRequest(s).then(e=>String(e?.title??"")).catch(()=>""):"",we=me&&!ge?await(0,x.startShowing)({projectId:E.projectId,post:(e,t)=>C.proxyPost(e,t),log:P,sessionExternalId:K??void 0,assetThere:e=>(0,x.assetIsThere)(E.basePath,e),resultsOf:e=>C.proxyGet(`/api/projects/${E.projectId}/results?requestId=${encodeURIComponent(e)}`).then(e=>Array.isArray(e?.data)?e.data:Array.isArray(e)?e:[])},s,fe,ye).catch(()=>""):""
3556
+ if(we&&P.info("showing started",{requestId:s,said:we}),"review-submit"===me?.action&&J&&X&&(X.reviewAcceptedSha=J),me?.reviewChange&&ie&&X&&(X.afterReview={...ie,outcome:me.reviewChange},"restarted"===me.reviewChange&&(X.sinceReview=ie)),!me)return j({success:!1,error:"plan_missing"}),{content:[{type:"text",text:`Server validation returned no completion plan for ${s} -- the remote is likely mid-deploy. Retry complete.`}],isError:!0}
3557
+ const be="testing"===me.action||"human-review"===me.action||"merge-cleared"===me.action
3558
+ if(be&&te.testsSkipped&&(D||F&&F.length>0))try{const e=C.getToolRecordClient()
3559
+ e&&await e.createToolRecord({projectId:E.projectId,requestId:s,type:"tests-skipped",metadata:{...D?{reason:D}:{},...F&&F.length>0?{skipTests:F}:{},testGate:te.gates.test,timestamp:(new Date).toISOString()}})}catch(e){P.warn("Failed to persist tests-skipped tool_record",{error:(0,h.getErrorMessage)(e)})}if(be&&M&&M.length>0&&K){const e=C.getSessionMessageClient()
3560
3560
  if(e){let t=new Set
3561
3561
  try{const e=await C.proxyGet(`/api/projects/${E.projectId}/session-messages`,{requestId:s,messageType:"report",limit:200}),r=Array.isArray(e)?e:e?.data??[]
3562
3562
  t=new Set(r.filter(e=>(e?.content?.requestId??e?.content?.anchor?.id)===s).map(e=>String(e?.content?.summary??"")))}catch{}for(const r of M.slice(0,5)){const n=r.length>140?`${r.slice(0,137)}\u2026`:r
3563
3563
  if(!t.has(n))try{await e.createReport({fromSessionId:K,status:"success",summary:n,...r.length>140?{details:r}:{},attention:"fyi",requestId:s})}catch(e){P.warn("worthKnowing note failed (completion continues)",{error:(0,h.getErrorMessage)(e)})}}P.info("worthKnowing notes processed",{count:Math.min(M.length,5),requestId:s})}}if(B&&B.length>0&&K)for(const e of B.slice(0,2))try{const t=Array.isArray(e.files)&&e.files.length>0
3564
- await C.proxyPost(`/api/projects/${E.projectId}/guidance/propose`,{body:e.body,scope:t?"files":"project",...t?{pathAnchors:e.files}:{},...e.evidence?{evidence:e.evidence}:{},...e.userSaid?{userSaid:e.userSaid}:{},requestId:s,sessionExternalId:K}),P.info("guidance proposed at completion",{requestId:s})}catch(e){P.info("guidance at completion not proposed (completion continues)",{requestId:s,reason:(0,h.getErrorMessage)(e)})}const we=C.getRequestClient()
3565
- for(const t of fe.patches)try{const r=await we.updateRequest(s,{...t,completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3566
- e.refsSeen&&r?.namedRefs&&(e.refsSeen.namedRefs=r.namedRefs)}catch(e){return j({success:!1,error:"plan_patch_failed"}),{content:[{type:"text",text:`Failed to apply completion transition (${Object.keys(t).join(", ")}): ${(0,h.getErrorMessage)(e)}`}],isError:!0}}if(j({success:!0}),"review-escalated"===fe.action)return{content:[{type:"text",text:`Request ${s}: review stopped the work and it went to the user (out of review tries, or completed again unchanged). No further action from you; a human finalizes or sends back must_fix items.`}]}
3567
- if("review-start"===fe.action)return{content:[{type:"text",text:`Request ${s}: review started. Read-only reviewers are reading your diff. STOP here and wait: do NOT poll, sleep, or call tools to pass the time; each reviewer's report is delivered to you automatically and wakes you, so just end your turn between reports. When their reports arrive (a detailed handoff follows with the specifics), act on the findings, finish your tasks, and call complete again. If no reviewer finds anything, you are told the review was clean and the request went on with this completion: then do not complete again. After review passes, the server runs any remaining gates and messages you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that and don't merge until it tells you to.`}]}
3568
- if("review-submit"===fe.action)return{content:[{type:"text",text:`Request ${s}: review submitted. The server is evaluating it and will message you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that before acting. If a criterion is still unmet, the criteria reviewer takes another pass and reports back; address any must_fix and call complete again.`}]}
3569
- if("signoff-park"===fe.action)return{content:[{type:"text",text:`Request ${s}: review is complete. This request now awaits the user's sign-off in the UI -- stop here and do NOT call merge.`}]}
3570
- if("promise-hold"===fe.action){const e=fe.detail?` (${fe.detail})`:""
3571
- return{content:[{type:"text",text:`Request ${s}: your change touches the test behind a promise an earlier request made${e}. Only the user changes a promise's test: on the promise card they accept your test, send the work back to put the test back, or retire the promise. Stop here and end your turn; do not call complete or merge again. You are told their answer.`}]}}if("merge-cleared-after-review"===fe.action)return{content:[{type:"text",text:`Request ${s}: review is complete and all gates are clear. Call merge to finalize (do not call complete again).`}]}
3572
- if("testing"===fe.action){const e="human"===fe.testResolver?"A notification has been created asking the user to choose how to handle testing (auto-test, interactive-test, or skip). Stop here; you will receive a report when testing finishes.":"Tests are running automatically in the background. Stop here; each active test process will run and post its own report back to you."
3573
- return{content:[{type:"text",text:`Request ${s}: tests are now running. ${e}\n\n## When reports arrive\nEach test process reports separately: an individual passed report does NOT mean you are cleared.\n- When every process has passed, the server advances the remaining gates automatically: agent review may start (reviewers report their findings to you), the request may wait for sign-off from the user, or the request merges. With your account of every criterion on the record (criteriaComments in this call), the server merges it and tells you so; you call nothing. Only if you are told explicitly that you are "cleared to merge" do you call \`merge\`, with evidence for the criteria you had not accounted for.\n- **Failed**: fix the issues and call \`complete\` again.\n\nDo NOT call merge, finalize, or any other tool before that explicit instruction: stop here and wait.`}]}}if("delivery-review"===fe.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3574
- return{content:[{type:"text",text:`Request ${s} is handed to the DELIVERY review, which is the last gate on this project and resolves the sign-off.${e}\n\nStop here and do NOT call merge: the review finalizes the request, or comes back to you with what it found. End your turn with one short line; your completion summary is what the user reads, so do not write it out again.`}]}}if("human-review"===fe.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3575
- return{content:[{type:"text",text:`Request ${s} submitted for human review.${e}\n\nReview is human-only for this project: the user approves the merge in the UI. Do NOT call merge yourself.`}]}}let be,ve
3576
- try{be=await we.getRequest(s)}catch(e){ve=e}const ke=(0,v.kindProfile)(re??be?.type)
3577
- if("settle"===ke.finalize)return{content:[{type:"text",text:`Request ${s} is complete. A ${ke.label.toLowerCase()} request has no branch, so nothing merges: it closes on its own record now. Stop here and do not call merge.`}]}
3578
- if(void 0!==ve)return{content:[{type:"text",text:`Request ${s} is cleared to merge, but fetching its criteria failed: ${(0,h.getErrorMessage)(ve)}. Call merge with verification evidence for each acceptance criterion.`}]}
3579
- const Ie=be?.acceptanceCriteria||[]
3580
- if(!1===te?.gates?.review?.enabled&&(0,S.checksOff)(te)&&!1===te?.gates?.signoff?.enabled&&"merge"===ke.finalize&&(0===Ie.length||Array.isArray(N)&&N.length>0)){P.info("gates off and account recorded: merging in the same call",{requestId:s})
3564
+ await C.proxyPost(`/api/projects/${E.projectId}/guidance/propose`,{body:e.body,scope:t?"files":"project",...t?{pathAnchors:e.files}:{},...e.evidence?{evidence:e.evidence}:{},...e.userSaid?{userSaid:e.userSaid}:{},requestId:s,sessionExternalId:K}),P.info("guidance proposed at completion",{requestId:s})}catch(e){P.info("guidance at completion not proposed (completion continues)",{requestId:s,reason:(0,h.getErrorMessage)(e)})}const ve=C.getRequestClient()
3565
+ if("answer"===me.action){try{const t=await ve.updateRequest(s,{completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3566
+ e.refsSeen&&t?.namedRefs&&(e.refsSeen.namedRefs=t.namedRefs),await C.proxyPost(`/api/projects/${E.projectId}/requests/${s}/finalize-completion`,{summary:V,acceptanceEvidence:[{evidence:"This changed nothing: its branch holds no change and no record writes into the project."}],mergeResult:{mergeCommitHash:"unknown",cleanedUp:!1,method:"answer-only",diffStats:{additions:0,deletions:0,filesChanged:0}}})}catch(e){return j({success:!1,error:"answer_finish_failed"}),{content:[{type:"text",text:`Your reply on ${s} could not be recorded: ${(0,h.getErrorMessage)(e)}. Call complete again.`}],isError:!0}}return j({success:!0}),{content:[{type:"text",text:`Your summary is the reply to the user on ${s}, and it is with them now. Nothing in the project changed, so nothing is checked and nothing waits for a sign-off: it is finished. Stop here.`}]}}for(const t of me.patches)try{const r=await ve.updateRequest(s,{...t,completionSummary:V,completionFormat:"markdown",completionNotChecked:"string"==typeof H&&H.trim()?H.trim():null,cliOrigin:Y,...Z,...ee})
3567
+ e.refsSeen&&r?.namedRefs&&(e.refsSeen.namedRefs=r.namedRefs)}catch(e){return j({success:!1,error:"plan_patch_failed"}),{content:[{type:"text",text:`Failed to apply completion transition (${Object.keys(t).join(", ")}): ${(0,h.getErrorMessage)(e)}`}],isError:!0}}if(j({success:!0}),"review-escalated"===me.action)return{content:[{type:"text",text:`Request ${s}: review stopped the work and it went to the user (out of review tries, or completed again unchanged). No further action from you; a human finalizes or sends back must_fix items.`}]}
3568
+ if("review-start"===me.action)return{content:[{type:"text",text:`Request ${s}: review started. Read-only reviewers are reading your diff. STOP here and wait: do NOT poll, sleep, or call tools to pass the time; each reviewer's report is delivered to you automatically and wakes you, so just end your turn between reports. When their reports arrive (a detailed handoff follows with the specifics), act on the findings, finish your tasks, and call complete again. If no reviewer finds anything, you are told the review was clean and the request went on with this completion: then do not complete again. After review passes, the server runs any remaining gates and messages you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that and don't merge until it tells you to.`}]}
3569
+ if("review-submit"===me.action)return{content:[{type:"text",text:`Request ${s}: review submitted. The server is evaluating it and will message you the exact next step (re-run tests if your fixes changed code, await human sign-off, or merge) -- wait for that before acting. If a criterion is still unmet, the criteria reviewer takes another pass and reports back; address any must_fix and call complete again.`}]}
3570
+ if("signoff-park"===me.action)return{content:[{type:"text",text:`Request ${s}: review is complete. This request now awaits the user's sign-off in the UI -- stop here and do NOT call merge.`}]}
3571
+ if("promise-hold"===me.action){const e=me.detail?` (${me.detail})`:""
3572
+ return{content:[{type:"text",text:`Request ${s}: your change touches the test behind a promise an earlier request made${e}. Only the user changes a promise's test: on the promise card they accept your test, send the work back to put the test back, or retire the promise. Stop here and end your turn; do not call complete or merge again. You are told their answer.`}]}}if("merge-cleared-after-review"===me.action)return{content:[{type:"text",text:`Request ${s}: review is complete and all gates are clear. Call merge to finalize (do not call complete again).`}]}
3573
+ if("testing"===me.action){const e="human"===me.testResolver?"A notification has been created asking the user to choose how to handle testing (auto-test, interactive-test, or skip). Stop here; you will receive a report when testing finishes.":"Tests are running automatically in the background. Stop here; each active test process will run and post its own report back to you."
3574
+ return{content:[{type:"text",text:`Request ${s}: tests are now running. ${e}\n\n## When reports arrive\nEach test process reports separately: an individual passed report does NOT mean you are cleared.\n- When every process has passed, the server advances the remaining gates automatically: agent review may start (reviewers report their findings to you), the request may wait for sign-off from the user, or the request merges. With your account of every criterion on the record (criteriaComments in this call), the server merges it and tells you so; you call nothing. Only if you are told explicitly that you are "cleared to merge" do you call \`merge\`, with evidence for the criteria you had not accounted for.\n- **Failed**: fix the issues and call \`complete\` again.\n\nDo NOT call merge, finalize, or any other tool before that explicit instruction: stop here and wait.`}]}}if("delivery-review"===me.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3575
+ return{content:[{type:"text",text:`Request ${s} is handed to the DELIVERY review, which is the last gate on this project and resolves the sign-off.${e}\n\nStop here and do NOT call merge: the review finalizes the request, or comes back to you with what it found. End your turn with one short line; your completion summary is what the user reads, so do not write it out again.`}]}}if("human-review"===me.action){const e=te.testsSkipped&&D?`\n\n_Tests skipped: ${D}_`:""
3576
+ return{content:[{type:"text",text:`Request ${s} submitted for human review.${e}\n\nReview is human-only for this project: the user approves the merge in the UI. Do NOT call merge yourself.`}]}}let ke,Ie
3577
+ try{ke=await ve.getRequest(s)}catch(e){Ie=e}const $e=(0,v.kindProfile)(re??ke?.type)
3578
+ if("settle"===$e.finalize)return{content:[{type:"text",text:`Request ${s} is complete. A ${$e.label.toLowerCase()} request has no branch, so nothing merges: it closes on its own record now. Stop here and do not call merge.`}]}
3579
+ if(void 0!==Ie)return{content:[{type:"text",text:`Request ${s} is cleared to merge, but fetching its criteria failed: ${(0,h.getErrorMessage)(Ie)}. Call merge with verification evidence for each acceptance criterion.`}]}
3580
+ const xe=ke?.acceptanceCriteria||[]
3581
+ if(!1===te?.gates?.review?.enabled&&(0,S.checksOff)(te)&&!1===te?.gates?.signoff?.enabled&&"merge"===$e.finalize&&(0===xe.length||Array.isArray(N)&&N.length>0)){P.info("gates off and account recorded: merging in the same call",{requestId:s})
3581
3582
  const e=await(0,u.handleMergeRequest)({requestId:s,verifications:[]},E,C,q,T,R)
3582
- return e?.isError?e:{...e,content:[{type:"text",text:`Request ${s}: nothing gates this project (review, tests and sign-off are off) and your account per criterion is on the record, so it merged in this call.\n\n${e.content?.[0]?.text??""}`},...e.content?.slice(1)??[]]}}const $e=fe.skippedReason?`\n\n_Skipped re-running tests: ${fe.skippedReason}._\n`:"",xe=fe.noTestsAutoMerge?"\n\n_No test processes are configured for this project, so the test gate has nothing to run; this completion merges without tests._\n":""
3583
- return 0===Ie.length?{content:[{type:"text",text:`Request ${s} is ready. ${$e}${xe}No acceptance criteria defined: call merge directly.`}]}:{content:[{type:"text",text:`Request ${s}: all gates are clear.${$e}${xe}\n\n## Next Step: Verify & Merge\n\n${(0,p.formatVerifyInstructions)(Ie)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(t){let r="An unexpected error occurred",n=""
3583
+ return e?.isError?e:{...e,content:[{type:"text",text:`Request ${s}: nothing gates this project (review, tests and sign-off are off) and your account per criterion is on the record, so it merged in this call.\n\n${e.content?.[0]?.text??""}`},...e.content?.slice(1)??[]]}}const Se=me.skippedReason?`\n\n_Skipped re-running tests: ${me.skippedReason}._\n`:"",_e=me.noTestsAutoMerge?"\n\n_No test processes are configured for this project, so the test gate has nothing to run; this completion merges without tests._\n":""
3584
+ return 0===xe.length?{content:[{type:"text",text:`Request ${s} is ready. ${Se}${_e}No acceptance criteria defined: call merge directly.`}]}:{content:[{type:"text",text:`Request ${s}: all gates are clear.${Se}${_e}\n\n## Next Step: Verify & Merge\n\n${(0,p.formatVerifyInstructions)(xe)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(t){let r="An unexpected error occurred",n=""
3584
3585
  t instanceof s.ZodError?(r="Validation error",n=t.errors.map(e=>`${e.path.join(".")}: ${e.message}`).join(", ")):t instanceof Error?(r=t.message,n=t.stack||""):n=String(t),P.error("Complete request failed",{error:r,details:n})
3585
3586
  try{await(0,i.createFailureToolRecord)("complete-request",t,{error:r,details:n,requestId:e?.requestId},C.getToolRecordClient(),P,T,{requestId:e?.requestId,projectId:E.projectId,note:"Failed to complete request"})}catch{}return T.startTimer("tool_execution_time")({success:!1,error:t instanceof Error?t.name:"unknown"}),{content:[{type:"text",text:`Error: ${r}`}],isError:!0}}}
3586
3587
  const n=t(65454),o=t(59860),s=t(11569),i=t(18616),a=t(35510),c=t(82860),l=t(95122),d=t(7161),u=t(34306),h=t(58824),p=t(65454),f=t(79414),m=t(67071),g=t(92456),y=t(80331),w=t(63580),b=t(52232),v=t(87780),k=t(45391),I=t(43451),$=t(70715),x=t(42692),S=t(64721),_=new Set},32283(e,exports,t){exports.def=void 0
@@ -8204,7 +8205,8 @@ if(t.status===a.PollingStatus.POLLING)return null
8204
8205
  const r=this.authFlow.getPollingUrl(e),n=await fetch(r)
8205
8206
  if(n.ok){const e=await n.json()
8206
8207
  if(e.authenticated&&e.token){const t=this.authFlow.parseTokenResponse(e)
8207
- if(t)return await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),t}}return null}catch(e){return this.logger.error("Error checking authentication status",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,null}}async validateTokenWithRemoteServer(){this.logger.debug("Validating stored token with remote server")
8208
+ if(t)return await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),t}}return null}catch(e){return this.logger.error("Error checking authentication status",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,null}}async signInRefused(){try{const e=await this.getToken()
8209
+ return!!e&&401===(await fetch(`${this.remoteServerUrl}/api/auth/validate`,{method:"GET",headers:{Authorization:`Bearer ${e.token}`},signal:AbortSignal.timeout(1e4)})).status}catch{return!1}}forgetCachedSignIn(){this.invalidateCache()}async validateTokenWithRemoteServer(){this.logger.debug("Validating stored token with remote server")
8208
8210
  try{const e=await this.getToken()
8209
8211
  if(!e)return this.logger.debug("No token available for validation"),!1
8210
8212
  const t=`${this.remoteServerUrl}/auth/validate`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemylab",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "private": false,
5
5
  "description": "AlchemyLab: the agentic workbench. Work is a request, with criteria, gates and a receipt.",
6
6
  "author": "Testfire Software",