chainlesschain 0.166.77 → 0.166.78

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.
Files changed (222) hide show
  1. package/README.md +16 -7
  2. package/completions/_cc +1 -1
  3. package/completions/cc.bash +1 -1
  4. package/completions/cc.fish +1 -1
  5. package/completions/cc.ps1 +1 -1
  6. package/package.json +1 -1
  7. package/src/assets/linux-subreaper/linux-arm64/manifest.json +10 -0
  8. package/src/assets/linux-subreaper/linux-arm64/supervisor +0 -0
  9. package/src/assets/linux-subreaper/linux-x64/manifest.json +10 -0
  10. package/src/assets/linux-subreaper/linux-x64/supervisor +0 -0
  11. package/src/assets/web-panel/assets/{AIOps-CpiCBhRh.js → AIOps-DSyZEY2G.js} +1 -1
  12. package/src/assets/web-panel/assets/{ActionButton-CnU-Xvx-.js → ActionButton-DhNyZ577.js} +1 -1
  13. package/src/assets/web-panel/assets/{Analytics-BJW-CNtf.js → Analytics-HMMpxmyi.js} +3 -3
  14. package/src/assets/web-panel/assets/{AppLayout-UFQJL3G9.js → AppLayout-CwKMM5Ie.js} +5 -5
  15. package/src/assets/web-panel/assets/{Artifacts-Dr_IUDoY.js → Artifacts-CNzDmph7.js} +1 -1
  16. package/src/assets/web-panel/assets/{Audit-aglWo6rr.js → Audit-DxWpUW3V.js} +1 -1
  17. package/src/assets/web-panel/assets/{BackgroundAgents-Dm_TCiXC.js → BackgroundAgents-C1R2ST-P.js} +1 -1
  18. package/src/assets/web-panel/assets/{Backup-DUdX4-gA.js → Backup-B6biTaEV.js} +1 -1
  19. package/src/assets/web-panel/assets/{BaseInput-BTcLjy1o.js → BaseInput-CVnkD2Z5.js} +1 -1
  20. package/src/assets/web-panel/assets/{Chat-Bhy9qZrl.js → Chat-Dbewl4Je.js} +6 -6
  21. package/src/assets/web-panel/assets/{ChatBubbleRenderer-D0WrJQaQ.js → ChatBubbleRenderer-DVZ6SwC5.js} +1 -1
  22. package/src/assets/web-panel/assets/{Checkbox-CblrPa21.js → Checkbox-BqqiF1JE.js} +1 -1
  23. package/src/assets/web-panel/assets/{Codegen-SEAHzOlr.js → Codegen-BVMkGumc.js} +1 -1
  24. package/src/assets/web-panel/assets/{Col-DJz8iFOR.js → Col-DmiRHy96.js} +1 -1
  25. package/src/assets/web-panel/assets/{Community-RufKhcQt.js → Community-BDlpygqA.js} +1 -1
  26. package/src/assets/web-panel/assets/{Compact-Dlifx08U.js → Compact-B2NME_m-.js} +1 -1
  27. package/src/assets/web-panel/assets/{Compliance-DdhQWcHh.js → Compliance-BlzDLE-R.js} +1 -1
  28. package/src/assets/web-panel/assets/{Cowork-BLNn6oOm.js → Cowork-C8raPybB.js} +3 -3
  29. package/src/assets/web-panel/assets/{Cron-Dv-JWY2d.js → Cron-DA8Py0zP.js} +2 -2
  30. package/src/assets/web-panel/assets/{Crosschain-k7Pz7O-b.js → Crosschain-DU2XyHqB.js} +1 -1
  31. package/src/assets/web-panel/assets/{DID-C_10syUW.js → DID-Df098fT_.js} +2 -2
  32. package/src/assets/web-panel/assets/{Dashboard-CMyH6Szx.js → Dashboard-D1rT702x.js} +2 -2
  33. package/src/assets/web-panel/assets/{Dropdown-DjmD2Saa.js → Dropdown-BweXGo1O.js} +1 -1
  34. package/src/assets/web-panel/assets/{EmailListRenderer-36_IRUSo.js → EmailListRenderer-B9ShbgJH.js} +1 -1
  35. package/src/assets/web-panel/assets/EvolutionSettings-D75_iBoc.js +1 -0
  36. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DEgf9kyP.js → FamilyGuardDashboard-DrznZFVs.js} +1 -1
  37. package/src/assets/web-panel/assets/{Federation-DGO1wQls.js → Federation-DQZ2adIA.js} +1 -1
  38. package/src/assets/web-panel/assets/{FormItemContext-Doj1FmKW.js → FormItemContext-DN30Dowh.js} +1 -1
  39. package/src/assets/web-panel/assets/{GenericCardRenderer-GzOU27iT.js → GenericCardRenderer-DRdt0j1e.js} +1 -1
  40. package/src/assets/web-panel/assets/{Git-Dd7D1EDK.js → Git-wwRgStzk.js} +2 -2
  41. package/src/assets/web-panel/assets/{Governance-6IY8LcjI.js → Governance-CI4Uw0Nh.js} +1 -1
  42. package/src/assets/web-panel/assets/{Inference-BB9gl8q1.js → Inference-5TuE2AJI.js} +1 -1
  43. package/src/assets/web-panel/assets/{KnowledgeGraph-CeCed5wd.js → KnowledgeGraph-oXyvmFSR.js} +1 -1
  44. package/src/assets/web-panel/assets/{Logs-CYOeHuaI.js → Logs-ewudSWuv.js} +2 -2
  45. package/src/assets/web-panel/assets/{MarkdownRenderer-Bk8Zqc2R.js → MarkdownRenderer-Cz5nyufm.js} +1 -1
  46. package/src/assets/web-panel/assets/{Marketplace-D-_xgHgM.js → Marketplace-DcZeWFrs.js} +1 -1
  47. package/src/assets/web-panel/assets/{McpTools-NnaUTF5t.js → McpTools-BcV9p1RS.js} +3 -3
  48. package/src/assets/web-panel/assets/{Memory-CndN9pMt.js → Memory-CMhYvugt.js} +2 -2
  49. package/src/assets/web-panel/assets/{MobileBridge-BXblFmhY.js → MobileBridge-5RP2uwvT.js} +1 -1
  50. package/src/assets/web-panel/assets/{MobileProjects-CC26Dm2k.js → MobileProjects-BIuM9Ze4.js} +1 -1
  51. package/src/assets/web-panel/assets/{Mtc-BhaqWCiW.js → Mtc-DmBszTDe.js} +4 -4
  52. package/src/assets/web-panel/assets/{MtcAudit-D6fktM2w.js → MtcAudit-Czdp5ZGt.js} +5 -5
  53. package/src/assets/web-panel/assets/{Multisig-CFvahz7s.js → Multisig-DRWUuNr-.js} +3 -3
  54. package/src/assets/web-panel/assets/{NLProgramming-Co73Ivya.js → NLProgramming-IRQQN0-c.js} +1 -1
  55. package/src/assets/web-panel/assets/{Notes-B4g33L1o.js → Notes-CGhD1lW9.js} +4 -4
  56. package/src/assets/web-panel/assets/{NotificationSettings-lXd17EbN.js → NotificationSettings-BtyPgQAh.js} +1 -1
  57. package/src/assets/web-panel/assets/{OrderTableRenderer-BiOB0GIi.js → OrderTableRenderer-yUaqwCty.js} +1 -1
  58. package/src/assets/web-panel/assets/{Organization-JQ7_wQIA.js → Organization-C3kTVn5i.js} +4 -4
  59. package/src/assets/web-panel/assets/{Overflow-gwgJgozQ.js → Overflow-C2-0iZhq.js} +1 -1
  60. package/src/assets/web-panel/assets/{P2P-D9L_0gie.js → P2P-CISoEUxA.js} +2 -2
  61. package/src/assets/web-panel/assets/{PdhVaultBrowser-CbOPsFE9.js → PdhVaultBrowser-NfTVtvKQ.js} +5 -5
  62. package/src/assets/web-panel/assets/{Permissions-Cz42HNQf.js → Permissions-CfK0jJhm.js} +4 -4
  63. package/src/assets/web-panel/assets/{PersonalDataHub-DjorYtrF.js → PersonalDataHub-OsVxxh_j.js} +5 -5
  64. package/src/assets/web-panel/assets/{Pipeline-DyWPhmm5.js → Pipeline-DEmK_Ch2.js} +1 -1
  65. package/src/assets/web-panel/assets/{Privacy-DyfLMl2j.js → Privacy-D61s73b0.js} +1 -1
  66. package/src/assets/web-panel/assets/{ProjectInit-CyqDx1OE.js → ProjectInit-DkLF5gHb.js} +2 -2
  67. package/src/assets/web-panel/assets/{ProjectSettings-DsBw0Csy.js → ProjectSettings-BA7odTrI.js} +2 -2
  68. package/src/assets/web-panel/assets/{Projects-CRaSI25Z.js → Projects-CdI1GcAG.js} +1 -1
  69. package/src/assets/web-panel/assets/{Providers-CCI_klN-.js → Providers-D9BYyP1r.js} +1 -1
  70. package/src/assets/web-panel/assets/{QrScannerModal-DNsnlDdS.js → QrScannerModal-CXMItUDD.js} +1 -1
  71. package/src/assets/web-panel/assets/{QuickAsk-B9r2iaee.js → QuickAsk-8-tF9ffZ.js} +1 -1
  72. package/src/assets/web-panel/assets/{Recommend-BJDe03GR.js → Recommend-C2QGWOSi.js} +1 -1
  73. package/src/assets/web-panel/assets/{RemoteSession-J7JR3rRo.js → RemoteSession-B1M_v1lx.js} +3 -3
  74. package/src/assets/web-panel/assets/{Reputation-DR39AJeV.js → Reputation-D0WZHgv1.js} +1 -1
  75. package/src/assets/web-panel/assets/{Row-Dh77m3NZ.js → Row-D6nf9-c-.js} +1 -1
  76. package/src/assets/web-panel/assets/{RssFeed-BUdg28nJ.js → RssFeed-ClZ6M-mN.js} +3 -3
  77. package/src/assets/web-panel/assets/{Search-BNC7sGhj.js → Search-ZWkt8vuO.js} +1 -1
  78. package/src/assets/web-panel/assets/{Security-DISENGI7.js → Security-BUlQut2m.js} +4 -4
  79. package/src/assets/web-panel/assets/{Services-BBBGpJ1-.js → Services-Cd_3xJOc.js} +2 -2
  80. package/src/assets/web-panel/assets/{Skeleton-DMcIoIv2.js → Skeleton-C8e2-cHW.js} +1 -1
  81. package/src/assets/web-panel/assets/{Skills-QAyFbI3r.js → Skills-DucVRJp1.js} +1 -1
  82. package/src/assets/web-panel/assets/{Sla-CSg5wLH7.js → Sla-Csr5pUwI.js} +1 -1
  83. package/src/assets/web-panel/assets/{SpeechSettings-DMPxTc5x.js → SpeechSettings-CXvyaRAT.js} +1 -1
  84. package/src/assets/web-panel/assets/{SyncSettings-CPG7l30y.js → SyncSettings-KdsIcV5h.js} +2 -2
  85. package/src/assets/web-panel/assets/{Tasks-Y1kOVvVL.js → Tasks-B-eHmJm9.js} +1 -1
  86. package/src/assets/web-panel/assets/{Templates-jt9NagL0.js → Templates-BglVeaLK.js} +1 -1
  87. package/src/assets/web-panel/assets/{Tenant-DauuJICx.js → Tenant-BBbQ8qan.js} +1 -1
  88. package/src/assets/web-panel/assets/{Terminal-E9rnKeGq.js → Terminal-Ca_pCVBi.js} +2 -2
  89. package/src/assets/web-panel/assets/{TimelineRenderer-Cc7z2APG.js → TimelineRenderer-YD6XG_vZ.js} +1 -1
  90. package/src/assets/web-panel/assets/{Tokens-CV0UthRA.js → Tokens-2lRoeVli.js} +1 -1
  91. package/src/assets/web-panel/assets/{Trigger-BFcJJGfu.js → Trigger-C-3XNAU9.js} +1 -1
  92. package/src/assets/web-panel/assets/{Trust-BAydbNJA.js → Trust-k-1PxdLG.js} +1 -1
  93. package/src/assets/web-panel/assets/{UkeySign-DcOS6sqL.js → UkeySign-FG-qW646.js} +1 -1
  94. package/src/assets/web-panel/assets/{VideoEditing-BLHJZvif.js → VideoEditing-BNOe1cmd.js} +1 -1
  95. package/src/assets/web-panel/assets/{Wallet-4QFLKHwW.js → Wallet-D5C3i2Kw.js} +4 -4
  96. package/src/assets/web-panel/assets/{WebAuthn-BocEOOSj.js → WebAuthn-BOpztqd3.js} +5 -5
  97. package/src/assets/web-panel/assets/{WorkflowEditor-DCfF7D0B.js → WorkflowEditor-BpVrpUEv.js} +1 -1
  98. package/src/assets/web-panel/assets/{chat-CxvfsYGr.js → chat-DIuMHb38.js} +1 -1
  99. package/src/assets/web-panel/assets/{colors-KtQB9DmQ.js → colors-CTFJPyzQ.js} +1 -1
  100. package/src/assets/web-panel/assets/{compact-item-Dx4J6arN.js → compact-item-CONfmJcW.js} +1 -1
  101. package/src/assets/web-panel/assets/{createContext-Cq0olgzo.js → createContext-RkW5CRrz.js} +1 -1
  102. package/src/assets/web-panel/assets/devWarning-DaEBln_q.js +1 -0
  103. package/src/assets/web-panel/assets/{hasIn-Bf9-h3D-.js → hasIn-CW4XOjDC.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CK2U_AHi.js → index-7wMSBCU7.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DMR-keCL.js → index-Akmg1WdH.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-6dDDSCHD.js → index-B54qoVff.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CmQuG0fr.js → index-B8r2t0Ch.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-ClUfSChI.js → index-B9XoBoty.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-B3xfiItB.js → index-B9aS2VLu.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DQDR-_ai.js → index-BFs1Tznc.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DZWjYfWt.js → index-BKgaRT0b.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-nmyDOh_b.js → index-BM7bOUvu.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-B_8UcDan.js → index-BMg2JFmW.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-C9yaUHm9.js → index-BRZsPxNn.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Cz7f4Jaq.js → index-Bf19fKef.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CpO6DKuu.js → index-BkAbfBF-.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DFdEDvFn.js → index-CBjb2A5R.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-gt5N6VM_.js → index-CEZWQthY.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-0fi8DIVQ.js → index-CFGLf88d.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-hSzyoXri.js → index-CLUa68JH.js} +3 -3
  121. package/src/assets/web-panel/assets/{index-Cy865Hhq.js → index-CM2X25Er.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DDAe1UmZ.js → index-CX4T2uKN.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BMcC4cbj.js → index-CixqfdRk.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DsCdl2Od.js → index-CkRojEip.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DnU-dUWd.js → index-Cvmc3f25.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-Br1mDMfO.js → index-D-lpTPS8.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CaIclw-E.js → index-D59GbWCN.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DBRlZdZj.js → index-DAESljiJ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-B8WuPI-h.js → index-DDHUx4Yz.js} +1 -1
  130. package/src/assets/web-panel/assets/index-DG1mcYTa.js +1 -0
  131. package/src/assets/web-panel/assets/{index-D2BfSIrn.js → index-DP5pPedy.js} +1 -1
  132. package/src/assets/web-panel/assets/index-DRs5Pe8u.js +1 -0
  133. package/src/assets/web-panel/assets/{index-CqnggDos.js → index-DSlXL6Ju.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-_FIz-0tp.js → index-DWCJnn2O.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-BKtQyb2o.js → index-DWY7YwDu.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-DfrFNMvz.js → index-DZTwP364.js} +1 -1
  137. package/src/assets/web-panel/assets/{index-BHmdMKYl.js → index-DidrMvOx.js} +1 -1
  138. package/src/assets/web-panel/assets/{index-BO6XvO-C.js → index-Dj3K5kHs.js} +1 -1
  139. package/src/assets/web-panel/assets/{index-iE9tqEN5.js → index-YaeGscSw.js} +1 -1
  140. package/src/assets/web-panel/assets/{index-DI5bRqNG.js → index-YlMnFNOi.js} +1 -1
  141. package/src/assets/web-panel/assets/{index-Cfsn7N18.js → index-asWsB34i.js} +1 -1
  142. package/src/assets/web-panel/assets/{index-CeYP_kT9.js → index-gkjiFjQd.js} +1 -1
  143. package/src/assets/web-panel/assets/{initDefaultProps-DvzKJ6o5.js → initDefaultProps-BOr4igh3.js} +1 -1
  144. package/src/assets/web-panel/assets/{motion-D1yTvmxW.js → motion-CK469n2j.js} +1 -1
  145. package/src/assets/web-panel/assets/{move-DxtSIF8K.js → move-DzjudlYQ.js} +1 -1
  146. package/src/assets/web-panel/assets/{mtc-parser-BDsQgIHY.js → mtc-parser-BQaKUxC6.js} +1 -1
  147. package/src/assets/web-panel/assets/{omit-UVBJW8kh.js → omit-MciovCFD.js} +1 -1
  148. package/src/assets/web-panel/assets/{pickAttrs-D4QqtTyX.js → pickAttrs-DDPJ4zAz.js} +1 -1
  149. package/src/assets/web-panel/assets/{placementArrow-QXmu6vBf.js → placementArrow-Cznyb-jI.js} +1 -1
  150. package/src/assets/web-panel/assets/{responsiveObserve-D-PmXO9M.js → responsiveObserve-AJK3SLzJ.js} +1 -1
  151. package/src/assets/web-panel/assets/{slide-CKbGxEZJ.js → slide-CPQ28wu7.js} +1 -1
  152. package/src/assets/web-panel/assets/{statusUtils-BbgXPkXm.js → statusUtils-CFjzvqf_.js} +1 -1
  153. package/src/assets/web-panel/assets/{styleChecker-DOr9rk68.js → styleChecker-BPyFfTuR.js} +1 -1
  154. package/src/assets/web-panel/assets/{useFlexGapSupport-B2wO2r36.js → useFlexGapSupport-Dq7N6R05.js} +1 -1
  155. package/src/assets/web-panel/assets/{useFs-SeVGBK34.js → useFs-C3GS0uTc.js} +1 -1
  156. package/src/assets/web-panel/assets/{usePersonalDataHub-DUJBCxjD.js → usePersonalDataHub-BhgIVzP_.js} +1 -1
  157. package/src/assets/web-panel/assets/{vnode-CF4EYsig.js → vnode-4ZD9-MDr.js} +1 -1
  158. package/src/assets/web-panel/assets/{zoom-pRUs5pqI.js → zoom-Bx4MRVNW.js} +1 -1
  159. package/src/assets/web-panel/index.html +1 -1
  160. package/src/command-help-index.json +1 -1
  161. package/src/command-manifest.json +1 -1
  162. package/src/commands/checkpoint.js +42 -7
  163. package/src/commands/orchestrate.js +85 -25
  164. package/src/commands/session-location.js +5 -0
  165. package/src/commands/session-show.js +109 -1
  166. package/src/commands/session.js +26 -2
  167. package/src/commands/tokens.js +9 -4
  168. package/src/data/changelog.json +13 -0
  169. package/src/generated/cc-agent-protocol.schema.json +71 -0
  170. package/src/harness/jsonl-session-store.js +357 -114
  171. package/src/harness/mcp-client.js +44 -1
  172. package/src/lib/agent-router.js +35 -7
  173. package/src/lib/app-server/server.js +14 -0
  174. package/src/lib/background-agent-supervisor.js +14 -4
  175. package/src/lib/causal-observability.js +64 -1
  176. package/src/lib/checkpoint-summary-projection.js +98 -0
  177. package/src/lib/checkpoint-timeline-authority.js +15 -51
  178. package/src/lib/claude-code-bridge.js +302 -60
  179. package/src/lib/codex-app-server-adapter.js +161 -35
  180. package/src/lib/cost-budget.js +4 -0
  181. package/src/lib/doctor-checkup.js +31 -2
  182. package/src/lib/durable-security-store.js +6 -1
  183. package/src/lib/evolution/evolution-artifact-identity.js +21 -0
  184. package/src/lib/evolution/evolution-artifact-ports.js +5 -11
  185. package/src/lib/evolution/evolution-eval-cohort-receipt-reconciliation.js +389 -0
  186. package/src/lib/execution-location-failure-site.js +63 -0
  187. package/src/lib/execution-location-target.js +102 -8
  188. package/src/lib/external-agent-adapters.js +2 -0
  189. package/src/lib/image-file-boundary.js +154 -0
  190. package/src/lib/image-input.js +16 -3
  191. package/src/lib/llm-pricing.js +114 -8
  192. package/src/lib/mcp-call-ledger-store.js +7 -2
  193. package/src/lib/model-capabilities.js +21 -10
  194. package/src/lib/model-context-catalog.js +60 -1
  195. package/src/lib/openai-responses.js +7 -1
  196. package/src/lib/orchestrator.js +8 -2
  197. package/src/lib/process-execution-broker/index.js +93 -1
  198. package/src/lib/process-execution-broker/linux-subreaper-artifact.js +120 -0
  199. package/src/lib/process-execution-broker/linux-subreaper-helper.js +344 -0
  200. package/src/lib/process-execution-broker/linux-subreaper-process.js +326 -0
  201. package/src/lib/process-execution-broker/linux-subreaper-supervisor.c +360 -0
  202. package/src/lib/process-execution-broker/owned-posix-process-group-worker.mjs +131 -0
  203. package/src/lib/process-execution-broker/owned-posix-process-group.js +267 -0
  204. package/src/lib/process-execution-broker/process-ownership-journal.js +297 -0
  205. package/src/lib/process-execution-broker/process-ownership-quarantine.js +91 -0
  206. package/src/lib/runtime-usage-ledger.js +3 -0
  207. package/src/lib/secure-fs.js +158 -42
  208. package/src/lib/session-branch-history.js +240 -0
  209. package/src/lib/session-history-origins.js +285 -0
  210. package/src/lib/session-input-receipt.js +110 -0
  211. package/src/lib/session-resource-budget.js +8 -8
  212. package/src/lib/session-transcript-history.js +456 -0
  213. package/src/lib/session-transcript-page.js +164 -0
  214. package/src/lib/session-transcript-reference.js +38 -0
  215. package/src/lib/session-usage.js +8 -0
  216. package/src/lib/token-tracker.js +32 -54
  217. package/src/lib/usage-pricing-context.js +93 -0
  218. package/src/runtime/headless-stream.js +202 -4
  219. package/src/assets/web-panel/assets/EvolutionSettings-CmtU0XmM.js +0 -1
  220. package/src/assets/web-panel/assets/devWarning-CmgDNkoO.js +0 -1
  221. package/src/assets/web-panel/assets/index-BpIZ2S01.js +0 -1
  222. package/src/assets/web-panel/assets/index-C-VmKuyv.js +0 -1
@@ -0,0 +1,389 @@
1
+ /** Join a sealed admission inventory to presented final Eval receipts.
2
+ * Missing receipts stay unresolved; a caller-supplied set cannot prove global coverage.
3
+ */
4
+ import { createHash } from "node:crypto";
5
+ import { isProxy } from "node:util/types";
6
+ import {
7
+ resolveEvolutionEvalCohortEnrollment,
8
+ resolveEvolutionEvalCohortReconciliation,
9
+ } from "./evolution-eval-cohort-enrollment.js";
10
+ import {
11
+ computeEvolutionEvalContextDigest,
12
+ computeEvolutionEvalLaunchRequestDigest,
13
+ isEvolutionEvalReceiptVerifier,
14
+ verifyEvolutionEvalReceipt,
15
+ } from "./evolution-eval-gate.js";
16
+ import { verifyPmExplorationEffectAttemptCohort } from "./pm-exploration-benchmark.js";
17
+
18
+ export const EVOLUTION_EVAL_COHORT_RECEIPT_RECONCILIATION_SCHEMA =
19
+ "chainlesschain.evolution-eval-cohort-receipt-reconciliation/v1";
20
+ export const EVOLUTION_EVAL_COHORT_RECEIPT_RECONCILIATION_FAILED_CODE =
21
+ "CC_EVOLUTION_EVAL_COHORT_RECEIPT_RECONCILIATION_FAILED";
22
+ export const PM_EXPLORATION_ADMISSION_BOUND_COHORT_SCHEMA =
23
+ "chainlesschain.pm-exploration-admission-bound-cohort/v1";
24
+
25
+ function fail(message) {
26
+ const error = new Error(message);
27
+ error.code = EVOLUTION_EVAL_COHORT_RECEIPT_RECONCILIATION_FAILED_CODE;
28
+ throw error;
29
+ }
30
+
31
+ function snapshot(value, budget = { nodes: 0, chars: 0 }, depth = 0) {
32
+ if (++budget.nodes > 50_000 || depth > 50)
33
+ fail("cohort receipt evidence exceeds structural limits");
34
+ if (value === null || typeof value === "boolean") return value;
35
+ if (typeof value === "number" && Number.isFinite(value)) return value;
36
+ if (typeof value === "string") {
37
+ budget.chars += value.length;
38
+ if (budget.chars > 4_000_000)
39
+ fail("cohort receipt evidence exceeds size limit");
40
+ return value;
41
+ }
42
+ if (!value || typeof value !== "object" || isProxy(value))
43
+ fail("cohort receipt evidence must contain plain JSON data");
44
+ if (Array.isArray(value)) {
45
+ if (
46
+ Object.getPrototypeOf(value) !== Array.prototype ||
47
+ Reflect.ownKeys(value).length !== value.length + 1
48
+ )
49
+ fail("cohort receipt array must be dense own data");
50
+ return Array.from({ length: value.length }, (_, index) => {
51
+ const property = Object.getOwnPropertyDescriptor(value, String(index));
52
+ if (!property || !("value" in property))
53
+ fail("cohort receipt array must be own data");
54
+ return snapshot(property.value, budget, depth + 1);
55
+ });
56
+ }
57
+ if (![Object.prototype, null].includes(Object.getPrototypeOf(value)))
58
+ fail("cohort receipt evidence must be plain data");
59
+ return Object.fromEntries(
60
+ Reflect.ownKeys(value).map((key) => {
61
+ const property = Object.getOwnPropertyDescriptor(value, key);
62
+ if (
63
+ typeof key !== "string" ||
64
+ !property?.enumerable ||
65
+ !("value" in property)
66
+ )
67
+ fail("cohort receipt fields must be own data");
68
+ budget.chars += key.length;
69
+ if (budget.chars > 4_000_000)
70
+ fail("cohort receipt evidence exceeds size limit");
71
+ return [key, snapshot(property.value, budget, depth + 1)];
72
+ }),
73
+ );
74
+ }
75
+
76
+ function exact(value, keys, label) {
77
+ if (
78
+ !value ||
79
+ Array.isArray(value) ||
80
+ typeof value !== "object" ||
81
+ Reflect.ownKeys(value).length !== keys.length ||
82
+ keys.some((key) => !Object.hasOwn(value, key))
83
+ )
84
+ fail(`${label} must contain exactly its registered fields`);
85
+ return value;
86
+ }
87
+
88
+ function captureRecord(value, keys, label) {
89
+ if (
90
+ !value ||
91
+ Array.isArray(value) ||
92
+ typeof value !== "object" ||
93
+ isProxy(value) ||
94
+ ![Object.prototype, null].includes(Object.getPrototypeOf(value)) ||
95
+ Reflect.ownKeys(value).length !== keys.length
96
+ )
97
+ fail(`${label} must contain exactly its own data fields`);
98
+ return Object.fromEntries(
99
+ keys.map((key) => {
100
+ const property = Object.getOwnPropertyDescriptor(value, key);
101
+ if (!property?.enumerable || !("value" in property))
102
+ fail(`${label} must contain exactly its own data fields`);
103
+ return [key, property.value];
104
+ }),
105
+ );
106
+ }
107
+
108
+ function canonical(value) {
109
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
110
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
111
+ return `{${Object.keys(value)
112
+ .sort()
113
+ .map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
114
+ .join(",")}}`;
115
+ }
116
+
117
+ function hash(
118
+ value,
119
+ schema = EVOLUTION_EVAL_COHORT_RECEIPT_RECONCILIATION_SCHEMA,
120
+ ) {
121
+ return `sha256:${createHash("sha256")
122
+ .update(`${schema}\0${canonical(value)}`)
123
+ .digest("hex")}`;
124
+ }
125
+
126
+ function frozen(value) {
127
+ if (value && typeof value === "object") {
128
+ for (const child of Object.values(value)) frozen(child);
129
+ Object.freeze(value);
130
+ }
131
+ return value;
132
+ }
133
+
134
+ /** Re-audit the sealed admission set after signature checks. */
135
+ export async function reconcileEvolutionEvalCohortReceipts(
136
+ authority,
137
+ verifier,
138
+ input,
139
+ ) {
140
+ if (!isEvolutionEvalReceiptVerifier(verifier))
141
+ fail("a branded final Eval receipt verifier is required");
142
+ const source = exact(
143
+ snapshot(input),
144
+ ["cohortId", "slots"],
145
+ "cohort receipt source",
146
+ );
147
+ if (
148
+ typeof source.cohortId !== "string" ||
149
+ !Array.isArray(source.slots) ||
150
+ source.slots.length > 32
151
+ )
152
+ fail("cohort receipt slots are invalid");
153
+ const lookup = { cohortId: source.cohortId };
154
+ const enrollment = resolveEvolutionEvalCohortEnrollment(authority, lookup);
155
+ const sealed = await resolveEvolutionEvalCohortReconciliation(
156
+ authority,
157
+ lookup,
158
+ );
159
+ if (source.slots.length !== enrollment.evidence.slots.length)
160
+ fail("cohort receipt source must cover every enrolled slot");
161
+ const admitted = new Map(
162
+ sealed.inventory.admissions.map((entry) => [entry.slotId, entry]),
163
+ );
164
+ const slots = [];
165
+ let signedReceiptCount = 0;
166
+ let receiptUnavailableCount = 0;
167
+ for (const [index, item] of source.slots.entries()) {
168
+ const entry = exact(
169
+ item,
170
+ ["slotId", "launchRequest", "receipt", "receiptContext"],
171
+ "cohort receipt slot",
172
+ );
173
+ const registered = enrollment.evidence.slots[index];
174
+ if (entry.slotId !== registered.slotId)
175
+ fail("cohort receipt slots differ from enrolled order");
176
+ const admission = admitted.get(entry.slotId);
177
+ if (entry.receipt === null) {
178
+ if (entry.launchRequest !== null || entry.receiptContext !== null)
179
+ fail("missing receipt cannot carry a substituted source");
180
+ if (admission) receiptUnavailableCount += 1;
181
+ slots.push({
182
+ slotId: entry.slotId,
183
+ status: admission ? "receipt-unavailable" : "unadmitted",
184
+ admissionDigest: admission?.admissionDigest ?? null,
185
+ runId: admission?.runId ?? null,
186
+ receiptDigest: null,
187
+ decision: null,
188
+ });
189
+ continue;
190
+ }
191
+ if (!admission || !entry.launchRequest || !entry.receiptContext)
192
+ fail("signed receipt has no matching admitted slot or context");
193
+ const request = exact(
194
+ entry.launchRequest,
195
+ [
196
+ "suiteRef",
197
+ "candidateId",
198
+ "baselineId",
199
+ "targetEnvironmentRef",
200
+ "evaluationContext",
201
+ ],
202
+ "cohort launch request",
203
+ );
204
+ const context = exact(
205
+ entry.receiptContext,
206
+ [
207
+ "runId",
208
+ "runNonce",
209
+ "suiteDigest",
210
+ "policyDigest",
211
+ "evaluationAuthorityRoot",
212
+ "targetEnvironmentRef",
213
+ "evaluationContextDigest",
214
+ "candidateId",
215
+ "baselineId",
216
+ "environmentDigest",
217
+ "tenantId",
218
+ "provenanceAudience",
219
+ "trainerAuthority",
220
+ "trainerRevision",
221
+ ],
222
+ "cohort receipt context",
223
+ );
224
+ const run = exact(
225
+ request.evaluationContext,
226
+ ["planDigest", "targetMatrixRoot", "cellId", "runtimeId"],
227
+ "cohort evaluation context",
228
+ );
229
+ if (
230
+ computeEvolutionEvalLaunchRequestDigest(request) !==
231
+ admission.requestDigest ||
232
+ run.planDigest !== registered.evaluationPlanDigest ||
233
+ run.cellId !== entry.slotId ||
234
+ request.candidateId !== context.candidateId ||
235
+ request.baselineId !== context.baselineId ||
236
+ request.targetEnvironmentRef !== context.targetEnvironmentRef ||
237
+ context.runId !== admission.runId ||
238
+ context.runNonce !== admission.runNonce ||
239
+ context.tenantId !== enrollment.evidence.descriptor.tenantId ||
240
+ context.policyDigest !== registered.policyDigest ||
241
+ context.evaluationAuthorityRoot !== registered.evaluationAuthorityRoot ||
242
+ context.evaluationContextDigest !==
243
+ computeEvolutionEvalContextDigest({
244
+ ...run,
245
+ tenantId: context.tenantId,
246
+ targetEnvironmentRef: context.targetEnvironmentRef,
247
+ environmentDigest: context.environmentDigest,
248
+ candidateId: context.candidateId,
249
+ baselineId: context.baselineId,
250
+ suiteDigest: context.suiteDigest,
251
+ policyDigest: context.policyDigest,
252
+ evaluationAuthorityRoot: context.evaluationAuthorityRoot,
253
+ })
254
+ )
255
+ fail("signed receipt differs from admitted request or enrolled cell");
256
+ const verified = await verifyEvolutionEvalReceipt(
257
+ verifier,
258
+ entry.receipt,
259
+ context,
260
+ );
261
+ signedReceiptCount += 1;
262
+ slots.push({
263
+ slotId: entry.slotId,
264
+ status: "signed-receipt",
265
+ admissionDigest: admission.admissionDigest,
266
+ runId: admission.runId,
267
+ receiptDigest: verified.receiptDigest,
268
+ decision: verified.decision,
269
+ });
270
+ }
271
+ const finalSeal = await resolveEvolutionEvalCohortReconciliation(
272
+ authority,
273
+ lookup,
274
+ );
275
+ if (canonical(finalSeal) !== canonical(sealed))
276
+ fail("sealed Ledger inventory changed during receipt verification");
277
+ const core = {
278
+ schema: EVOLUTION_EVAL_COHORT_RECEIPT_RECONCILIATION_SCHEMA,
279
+ cohortId: source.cohortId,
280
+ enrollmentDigest: sealed.enrollmentDigest,
281
+ sealDigest: sealed.sealDigest,
282
+ admissionInventoryAuthenticated: true,
283
+ signedReceiptCount,
284
+ receiptUnavailableCount,
285
+ unadmittedSlotCount: sealed.inventory.unadmittedSlotIds.length,
286
+ slots,
287
+ presentedReceiptsAuthenticated: true,
288
+ receiptSetCompletenessAuthenticated: false,
289
+ executionCoverageAuthenticated: false,
290
+ cohortCompletenessAuthenticated: false,
291
+ promotionAuthority: false,
292
+ };
293
+ return frozen({ ...core, reconciliationDigest: hash(core) });
294
+ }
295
+
296
+ /** Bind the independently verified PM denominator to the signed admission/receipt census. */
297
+ export async function reconcilePmExplorationAdmissionBoundCohort(
298
+ authority,
299
+ verifier,
300
+ input,
301
+ ) {
302
+ if (!isEvolutionEvalReceiptVerifier(verifier))
303
+ fail("a branded final Eval receipt verifier is required");
304
+ const source = captureRecord(
305
+ input,
306
+ ["cohortId", "receiptSlots", "cohortSource", "cohort", "registration"],
307
+ "PM admission-bound cohort source",
308
+ );
309
+ const receiptSlots = snapshot(source.receiptSlots);
310
+ const registration = exact(
311
+ snapshot(source.registration),
312
+ ["cohortId", "planDigest", "slots"],
313
+ "PM cohort registration",
314
+ );
315
+ // This verifier snapshots its source and expected context before its first await.
316
+ const pm = await verifyPmExplorationEffectAttemptCohort(
317
+ verifier,
318
+ { source: source.cohortSource, cohort: source.cohort },
319
+ registration,
320
+ );
321
+ const joined = await reconcileEvolutionEvalCohortReceipts(
322
+ authority,
323
+ verifier,
324
+ { cohortId: source.cohortId, slots: receiptSlots },
325
+ );
326
+ const enrollment = resolveEvolutionEvalCohortEnrollment(authority, {
327
+ cohortId: source.cohortId,
328
+ });
329
+ if (
330
+ pm.cohortId !== source.cohortId ||
331
+ registration.cohortId !== source.cohortId ||
332
+ pm.planDigest !== enrollment.evidence.plan.planDigest ||
333
+ registration.planDigest !== pm.planDigest ||
334
+ pm.registeredSlotCount !== enrollment.evidence.manifest.slotIds.length ||
335
+ pm.perArmDenominator !==
336
+ enrollment.evidence.manifest.plannedTestObservationsPerArm ||
337
+ canonical(registration.slots.map((slot) => slot.slotId)) !==
338
+ canonical(enrollment.evidence.manifest.slotIds)
339
+ )
340
+ fail("PM denominator differs from signed cohort enrollment");
341
+ for (const [index, attempt] of pm.attempts.entries()) {
342
+ const admitted = joined.slots[index];
343
+ if (
344
+ attempt.slotId !== admitted.slotId ||
345
+ (admitted.status === "signed-receipt" &&
346
+ (attempt.kind === "receipt-unavailable" ||
347
+ attempt.runId !== admitted.runId ||
348
+ attempt.receiptDigest !== admitted.receiptDigest)) ||
349
+ (admitted.status !== "signed-receipt" &&
350
+ (attempt.kind !== "receipt-unavailable" ||
351
+ attempt.runId !== null ||
352
+ attempt.receiptDigest !== null))
353
+ )
354
+ fail("PM attempt differs from its sealed admission and final receipt");
355
+ }
356
+ if (
357
+ pm.authenticatedAttemptCount !== joined.signedReceiptCount ||
358
+ (pm.missingReceiptCount ?? 0) !==
359
+ joined.receiptUnavailableCount + joined.unadmittedSlotCount
360
+ )
361
+ fail("PM attempt counts differ from sealed admission inventory");
362
+ const core = {
363
+ schema: PM_EXPLORATION_ADMISSION_BOUND_COHORT_SCHEMA,
364
+ cohortId: source.cohortId,
365
+ planDigest: pm.planDigest,
366
+ enrollmentDigest: joined.enrollmentDigest,
367
+ sealDigest: joined.sealDigest,
368
+ receiptReconciliationDigest: joined.reconciliationDigest,
369
+ attemptCohortDigest: pm.cohortDigest,
370
+ registeredSlotCount: pm.registeredSlotCount,
371
+ signedReceiptCount: joined.signedReceiptCount,
372
+ admittedMissingReceiptCount: joined.receiptUnavailableCount,
373
+ unadmittedSlotCount: joined.unadmittedSlotCount,
374
+ perArmDenominator: pm.perArmDenominator,
375
+ baseline: pm.baseline,
376
+ candidate: pm.candidate,
377
+ admissionAndAttemptBindingAuthenticated: true,
378
+ receiptSetCompletenessAuthenticated: false,
379
+ executionCoverageAuthenticated: false,
380
+ cohortCompletenessAuthenticated: false,
381
+ reportAuthenticated: false,
382
+ requiresIndependentPilotApproval: true,
383
+ qualifiesForPromotion: false,
384
+ };
385
+ return frozen({
386
+ ...core,
387
+ bindingDigest: hash(core, PM_EXPLORATION_ADMISSION_BOUND_COHORT_SCHEMA),
388
+ });
389
+ }
@@ -0,0 +1,63 @@
1
+ // Diagnostic locations are public source labels, never target paths, stack
2
+ // text or error messages. They do not grant authority or trigger a retry.
3
+ const SOURCES = Object.freeze({
4
+ "commands/session-location.js": "session-location",
5
+ "harness/jsonl-session-store.js": "session-store",
6
+ "harness/session-index.js": "session-index",
7
+ "harness/transcript-integrity.js": "transcript-integrity",
8
+ "lib/secure-fs.js": "private-storage",
9
+ "lib/secure-file-identity.js": "file-identity",
10
+ "lib/session-anti-rollback-anchor.js": "session-anchor",
11
+ "lib/with-file-lock.js": "file-lock",
12
+ "lib/execution-location-local-supervisor.mjs": "local-supervisor",
13
+ "lib/execution-location-contract.js": "location-contract",
14
+ });
15
+ const LABELS = new Set(Object.values(SOURCES));
16
+ const PREFIX = "CC_EXECUTION_LOCATION_FAILURE_SITE=";
17
+ const MAX_DIAGNOSTIC_CHARS = 8192;
18
+
19
+ // PowerShell diagnostics are deliberately bounded to fixed native operation
20
+ // labels and HRESULTs; neither paths nor exception text cross the boundary.
21
+ export function readExecutionLocationStorageFailure(stderr) {
22
+ const match = String(stderr || "")
23
+ .slice(0, MAX_DIAGNOSTIC_CHARS)
24
+ .match(
25
+ /\[windows-acl:(initialize|traversal|lookup|repair-lock|repair-inspect|repair-write|verify|timeout(?:-(?:startup|initialize|traversal|lookup|repair-lock|repair-inspect|repair-write|verify))?|spawn|output)(:0x[0-9a-f]{8})?\]/u,
26
+ );
27
+ return match ? `${match[1]}${match[2] || ""}` : null;
28
+ }
29
+
30
+ export function executionLocationFailureSite(error) {
31
+ const stack = String(error?.stack || "").slice(0, MAX_DIAGNOSTIC_CHARS);
32
+ for (const frame of stack.split(/\r?\n/u).slice(1)) {
33
+ if (!/^\s+at /u.test(frame)) continue;
34
+ const normalized = frame.replaceAll("\\", "/");
35
+ for (const [source, label] of Object.entries(SOURCES)) {
36
+ const suffix = `/packages/cli/src/${source}:`;
37
+ const index = normalized.lastIndexOf(suffix);
38
+ if (index < 0) continue;
39
+ const position = normalized.slice(index + suffix.length);
40
+ const line = position.match(/^([1-9][0-9]{0,5}):[0-9]+\)?$/u)?.[1];
41
+ if (line) return `${label}:${line}`;
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+
47
+ export function formatExecutionLocationFailureSite(error) {
48
+ const site = executionLocationFailureSite(error);
49
+ return site === null ? "" : `${PREFIX}${site}\n`;
50
+ }
51
+
52
+ export function readExecutionLocationFailureSite(stderr) {
53
+ const text = String(stderr || "").slice(0, MAX_DIAGNOSTIC_CHARS);
54
+ for (const line of text.split(/\r?\n/u)) {
55
+ if (!line.startsWith(PREFIX)) continue;
56
+ const match = line
57
+ .slice(PREFIX.length)
58
+ .match(/^([a-z-]+):([1-9][0-9]{0,5})$/u);
59
+ if (match && LABELS.has(match[1])) return `${match[1]}:${match[2]}`;
60
+ }
61
+ // An uncaught supervisor exception already has a stack on stderr.
62
+ return executionLocationFailureSite({ stack: text });
63
+ }
@@ -4,6 +4,10 @@ import { tmpdir } from "node:os";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { TextDecoder } from "node:util";
7
+ import {
8
+ readExecutionLocationFailureSite,
9
+ readExecutionLocationStorageFailure,
10
+ } from "./execution-location-failure-site.js";
7
11
  import {
8
12
  EXECUTION_LOCATION_TARGET_ATTESTATION_SCHEMA,
9
13
  createExecutionLocationTargetAttestation,
@@ -18,7 +22,11 @@ import {
18
22
  import { canonicalJson } from "./scheduler-kernel/contract.js";
19
23
  import { executionBroker } from "./process-execution-broker/index.js";
20
24
  import { assertExecutionLocationRunnerLeaseAuthority } from "./execution-location-runner-lifecycle.js";
21
- import { ensurePrivateDirectory, repairPrivatePaths } from "./secure-fs.js";
25
+ import {
26
+ _resolveWindowsAclTimeout,
27
+ ensurePrivateDirectory,
28
+ repairPrivatePaths,
29
+ } from "./secure-fs.js";
22
30
  import { getSessionAntiRollbackDirectory } from "./session-anti-rollback-anchor.js";
23
31
  import {
24
32
  MAX_EXECUTION_LOCATION_RESULT_BUNDLE_BYTES,
@@ -657,6 +665,11 @@ function localTargetEnvironment(profile, lifecycleEnvironment) {
657
665
  // Windows. Keep all CLI state beneath a dedicated child directory.
658
666
  CHAINLESSCHAIN_HOME: path.join(profile.transport.home, ".chainlesschain"),
659
667
  CHAINLESSCHAIN_SECURITY_ANCHOR_HOME: profile.transport.securityHome,
668
+ // This numeric, bounded operation allowance is part of local storage
669
+ // configuration. Forward no other caller-specific environment or secrets.
670
+ CC_SECURE_FS_WINDOWS_ACL_TIMEOUT_MS: String(
671
+ _resolveWindowsAclTimeout(15_000),
672
+ ),
660
673
  FORCE_COLOR: "0",
661
674
  HOME: profile.transport.home,
662
675
  LOCALAPPDATA: path.join(profile.transport.home, "AppData", "Local"),
@@ -706,6 +719,7 @@ export function prepareLocalTargetState(profile, cliArgs, deps = {}) {
706
719
  anchorBase: profile.transport.securityHome,
707
720
  });
708
721
  const sessionDigest = createHash("sha256").update(sessionId).digest("hex");
722
+ const platform = deps.platform || process.platform;
709
723
  const directories = [
710
724
  stateHome,
711
725
  path.join(stateHome, "sessions"),
@@ -715,11 +729,19 @@ export function prepareLocalTargetState(profile, cliArgs, deps = {}) {
715
729
  path.join(antiRollbackDirectory, "namespace"),
716
730
  path.join(antiRollbackDirectory, "records"),
717
731
  path.join(antiRollbackDirectory, "records", sessionDigest.slice(0, 2)),
732
+ // Windows known-folder APIs can return an empty path for nonexistent
733
+ // isolated profile directories, making first-use caches relative to cwd.
734
+ ...(platform === "win32"
735
+ ? [
736
+ path.join(profile.transport.home, "AppData"),
737
+ path.join(profile.transport.home, "AppData", "Local"),
738
+ path.join(profile.transport.home, "AppData", "Roaming"),
739
+ ]
740
+ : []),
718
741
  ];
719
742
  const uniqueDirectories = [...new Set(directories)];
720
743
  const ensure = deps.ensurePrivateDirectory || ensurePrivateDirectory;
721
744
  const repair = deps.repairPrivatePaths || repairPrivatePaths;
722
- const platform = deps.platform || process.platform;
723
745
  for (const directory of uniqueDirectories) {
724
746
  ensure(
725
747
  directory,
@@ -961,6 +983,65 @@ function targetInvocation(profile, cliArgs, deps = {}, options = {}) {
961
983
  });
962
984
  }
963
985
 
986
+ // Target output can contain session text, paths, or credentials. Report only
987
+ // a fixed diagnostic category; this is never an authorization/retry decision.
988
+ function targetCommandFailureCategory(result) {
989
+ const stderr = String(result?.stderr || "").slice(0, MAX_PROBE_BYTES);
990
+ if (readExecutionLocationStorageFailure(stderr)) return "windows-acl";
991
+ const categories = [
992
+ ["stdin-empty", /session replica stdin is empty/u],
993
+ ["stdin-read-unavailable", /(?:EAGAIN|EINVAL)[^\r\n]*read/u],
994
+ ["stdin-identity", /local target stdin file (?:is invalid|changed)/u],
995
+ [
996
+ "target-facts-changed",
997
+ /target facts changed before location handoff append/u,
998
+ ],
999
+ ["filesystem-access", /\b(?:EACCES|EPERM)\b|Access is denied/iu],
1000
+ ["filesystem-missing", /\bENOENT\b/u],
1001
+ ["module-load", /\b(?:ERR_MODULE_NOT_FOUND|MODULE_NOT_FOUND)\b/u],
1002
+ [
1003
+ "file-identity",
1004
+ /(?:identity changed|pathname and descriptor identities differ|physical, non-symlink|single-link file)/u,
1005
+ ],
1006
+ [
1007
+ "storage-integrity",
1008
+ /(?:[Aa]nti-rollback|[Tt]ranscript digest|[Hh]ash chain|[Aa]nchor|[Rr]eplica)[^\r\n]*(?:invalid|mismatch|failed|conflict)/u,
1009
+ ],
1010
+ [
1011
+ "deployment-authority",
1012
+ /(?:authenticated evolution ingress|evolution deployment)/u,
1013
+ ],
1014
+ ["memory-limit", /heap out of memory|Reached heap limit/iu],
1015
+ ];
1016
+ return (
1017
+ categories.find(([, pattern]) => pattern.test(stderr))?.[0] || "unknown"
1018
+ );
1019
+ }
1020
+
1021
+ function targetProcessFailure(result) {
1022
+ // Native spawn errors include executable paths and argv. Preserve only fixed
1023
+ // categories and the same content-free diagnostics as a nonzero target exit.
1024
+ // A timeout is an unknown outcome: this function never retries the command.
1025
+ const categories = new Map([
1026
+ ["ETIMEDOUT", "process-timeout"],
1027
+ ["ENOBUFS", "process-output-limit"],
1028
+ ["ENOENT", "process-unavailable"],
1029
+ ["EACCES", "process-access"],
1030
+ ["EPERM", "process-access"],
1031
+ ]);
1032
+ const failureCategory = categories.get(result.error.code) || "process-spawn";
1033
+ const failureSite = readExecutionLocationFailureSite(result.stderr);
1034
+ const storageFailure = readExecutionLocationStorageFailure(result.stderr);
1035
+ const error = new Error(
1036
+ `target process failed (${failureCategory})${failureSite ? ` at ${failureSite}` : ""}${storageFailure ? ` [${storageFailure}]` : ""}`,
1037
+ );
1038
+ error.code = "CC_EXECUTION_LOCATION_TARGET_COMMAND_FAILED";
1039
+ error.failureCategory = failureCategory;
1040
+ if (failureSite) error.failureSite = failureSite;
1041
+ if (storageFailure) error.storageFailure = storageFailure;
1042
+ return error;
1043
+ }
1044
+
964
1045
  function runTargetCommand(profile, cliArgs, deps = {}, options = {}) {
965
1046
  const invocation = targetInvocation(profile, cliArgs, deps, options);
966
1047
  const spawnSync =
@@ -976,9 +1057,14 @@ function runTargetCommand(profile, cliArgs, deps = {}, options = {}) {
976
1057
  ) {
977
1058
  throw new Error("target command output boundary is invalid");
978
1059
  }
979
- const timeoutMs = Number(
980
- options.timeoutMs ?? DEFAULT_TARGET_COMMAND_TIMEOUT_MS,
981
- );
1060
+ // Hosted Windows Local targets can spend most of the generic 30-second
1061
+ // window on owner-only ACL checks before the CLI command runs. Keep the
1062
+ // existing bounded 120-second ceiling for this attested target platform.
1063
+ const defaultTimeoutMs =
1064
+ profile.target === "local" && profile.expected.platform === "win32"
1065
+ ? MAX_TARGET_COMMAND_TIMEOUT_MS
1066
+ : DEFAULT_TARGET_COMMAND_TIMEOUT_MS;
1067
+ const timeoutMs = Number(options.timeoutMs ?? defaultTimeoutMs);
982
1068
  if (
983
1069
  !Number.isSafeInteger(timeoutMs) ||
984
1070
  timeoutMs < 1 ||
@@ -1008,12 +1094,20 @@ function runTargetCommand(profile, cliArgs, deps = {}, options = {}) {
1008
1094
  ],
1009
1095
  ...(invocation.spawnOptions || {}),
1010
1096
  });
1011
- if (result?.error) throw result.error;
1097
+ if (result?.error) throw targetProcessFailure(result);
1012
1098
  if (!result || result.status !== 0) {
1099
+ const failureCategory = targetCommandFailureCategory(result);
1100
+ const failureSite = readExecutionLocationFailureSite(result?.stderr);
1101
+ const storageFailure = readExecutionLocationStorageFailure(
1102
+ result?.stderr,
1103
+ );
1013
1104
  const error = new Error(
1014
- `target command failed with status ${result?.status ?? "unknown"}`,
1105
+ `target command failed with status ${result?.status ?? "unknown"} (${failureCategory})${failureSite ? ` at ${failureSite}` : ""}${storageFailure ? ` [${storageFailure}]` : ""}`,
1015
1106
  );
1016
1107
  error.code = "CC_EXECUTION_LOCATION_TARGET_COMMAND_FAILED";
1108
+ error.failureCategory = failureCategory;
1109
+ if (failureSite) error.failureSite = failureSite;
1110
+ if (storageFailure) error.storageFailure = storageFailure;
1017
1111
  throw error;
1018
1112
  }
1019
1113
  return options.interactive ? null : result.stdout;
@@ -1187,7 +1281,7 @@ export function probeExecutionLocationTargetResourceLimit(
1187
1281
  } finally {
1188
1282
  invocation.cleanup?.();
1189
1283
  }
1190
- if (result?.error) throw result.error;
1284
+ if (result?.error) throw targetProcessFailure(result);
1191
1285
  const expectedMarker = `CC_EXECUTION_LOCATION_RESOURCE_PROBE_ARMED:${kind}`;
1192
1286
  const status = Number(result?.status);
1193
1287
  const signal = result?.signal == null ? null : String(result.signal);
@@ -15,6 +15,8 @@ export const EXTERNAL_AGENT_ERROR = Object.freeze({
15
15
  TIMEOUT: "EXTERNAL_AGENT_TIMEOUT",
16
16
  EXIT_NONZERO: "EXTERNAL_AGENT_EXIT_NONZERO",
17
17
  SPAWN_FAILED: "EXTERNAL_AGENT_SPAWN_FAILED",
18
+ CLEANUP_UNCONFIRMED: "EXTERNAL_AGENT_CLEANUP_UNCONFIRMED",
19
+ EXECUTION_BLOCKED: "EXTERNAL_AGENT_EXECUTION_BLOCKED",
18
20
  PROTOCOL_FAILED: "EXTERNAL_AGENT_PROTOCOL_FAILED",
19
21
  UNSUPPORTED_OPTION: "EXTERNAL_AGENT_UNSUPPORTED_OPTION",
20
22
  });