chainlesschain 0.166.96 → 0.166.98

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 (177) hide show
  1. package/README.md +27 -18
  2. package/package.json +3 -3
  3. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  4. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  5. package/src/assets/web-panel/assets/{AIOps-TNYT0Ehu.js → AIOps-DCIQFtF1.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-GAU5WRiJ.js → ActionButton-BxhHU3nE.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-CGBIObIC.js → Analytics-DdM_307O.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-oOSmcEm1.js → AppLayout-C43-kSrh.js} +4 -4
  9. package/src/assets/web-panel/assets/{Artifacts-CmEZTNjU.js → Artifacts-B2Vp2Am6.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-Dbt3E2nA.js → Audit-s-lYUfOp.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-D_BZmYk4.js → BackgroundAgents-DTE7Kzio.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-DgDOxdZF.js → Backup-9k1q4Mt6.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-Bo2pg8D_.js → BaseInput-DlpUtK5R.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-BF6Lb0W_.js → Chat-CR9S8Rmb.js} +5 -5
  15. package/src/assets/web-panel/assets/ChatBubbleRenderer-Xtgfw3-c.js +1 -0
  16. package/src/assets/web-panel/assets/{Checkbox-ZJM64PMU.js → Checkbox-DpFRu7Df.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-CCauMpRn.js → Codegen-BIl72E4Y.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-CA_MU4xw.js → Col-91tl_err.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-B5VQptTJ.js → Community-CswahO9-.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-C7Ehqru2.js → Compact-D9pfHmaM.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-Dyt6kfTg.js → Compliance-CXSZzAO9.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-B_yOOOHo.js → Cowork-CuT9RWTn.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-cbhAQANJ.js → Cron-B71aJWDV.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-BYC4ITZo.js → Crosschain-CcUuWyx8.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-Cc2Czj0c.js → DID-CtVVGOPL.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-B4VX9dth.js → Dashboard-CV7ZCYQq.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-g7e6T92p.js → Dropdown-DKHxwLgE.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-CzUK_NJA.js → EmailListRenderer-Bd03UIvv.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-ameoB_GI.js → EvolutionSettings-CTrG03B_.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DuehDwv2.js → FamilyGuardDashboard-DXS4bS6Q.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-DuMbIjYG.js → Federation-BODG2Szj.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-CS-om7RD.js → FormItemContext-D32ccUqD.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-CuKgo9Q0.js → GenericCardRenderer-ClsyrKvF.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-Bp6I9kxu.js → Git-DcM2yhbL.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-C_AzSOmj.js → Governance-BhUzM87n.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-C-qkoYD5.js → Inference-Dq1n0Ifg.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-D8Q4D_EN.js → KnowledgeGraph-dmmPwEks.js} +1 -1
  38. package/src/assets/web-panel/assets/Logs-CBSYrPmh.js +2 -0
  39. package/src/assets/web-panel/assets/{MarkdownRenderer-CaGz2EYV.js → MarkdownRenderer-CRoDI77y.js} +1 -1
  40. package/src/assets/web-panel/assets/{Marketplace-BWFjqLRM.js → Marketplace-Cfw7XLck.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-BJngUzks.js → McpTools-CNrZRy4n.js} +2 -2
  42. package/src/assets/web-panel/assets/{Memory-DcFAqj9b.js → Memory-BESjTxdd.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-CQjRXWWS.js → MobileBridge-Boyjo07i.js} +1 -1
  44. package/src/assets/web-panel/assets/MobileProjects-BmxmpTWz.js +1 -0
  45. package/src/assets/web-panel/assets/{Mtc-C_7mSz17.js → Mtc-CBkrD0Fq.js} +2 -2
  46. package/src/assets/web-panel/assets/{MtcAudit-DcYdxIWN.js → MtcAudit-BA7cAK8h.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-ypAr20wL.js → Multisig-m0RGzkKO.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-CJWFA8xg.js → NLProgramming-D_TgzifU.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-D1GhvZvR.js → Notes-Dr-Yr9LL.js} +4 -4
  50. package/src/assets/web-panel/assets/{NotificationSettings-CWOgdSHm.js → NotificationSettings-DGanpkqO.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-CE5Oqf07.js → OrderTableRenderer-D1FX50QY.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-wddxd4Ka.js → Organization-DRbPg-gs.js} +2 -2
  53. package/src/assets/web-panel/assets/{Overflow-Dczw5Ggs.js → Overflow-flEO37z6.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-Bmlos4fT.js → P2P-DqfqFbCW.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-DNp_WBr0.js → PdhVaultBrowser-Cmi5a5dW.js} +5 -5
  56. package/src/assets/web-panel/assets/{Permissions-tt7tio9B.js → Permissions-DBVRlvBW.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-C_ItcMUf.js → PersonalDataHub-gQqjPr9X.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-BS0NENVX.js → Pipeline-6HlifUc9.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-o9QNmXcZ.js → Privacy-bm_2-Zwg.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-g3r30nEt.js → ProjectInit-BJW3isuq.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-CQCKz8vR.js → ProjectSettings-DD3yolz7.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-DWH5cBmp.js → Projects-BF3GtWny.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-KGyPcaEb.js → Providers-CQA6WAK7.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-CFgEHopX.js → QrScannerModal-DOAwp5Xo.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-hLl0Nel4.js → QuickAsk-qeFXsAZT.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-BX6FCAMS.js → Recommend-zDWXwZN8.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-C5BLLEcs.js → RemoteSession-toe6Ip06.js} +3 -3
  68. package/src/assets/web-panel/assets/{Reputation-DVUhhjBy.js → Reputation-DRDi_Eqp.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-Bx3-cvc4.js → Row-Do2UbYkf.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-DA091bsm.js → RssFeed-B57C6_Sa.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-CJqXJFAx.js → Search-DfDyBpe9.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-BWZ5dHzy.js → Security-CulNxeAM.js} +3 -3
  73. package/src/assets/web-panel/assets/{Services-QhwMuZb3.js → Services-COfAYvs4.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-DgbULoTC.js → Skeleton-0fn0T146.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-cl7ldo6F.js → Skills-pPQgAhvJ.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-Cek1zXct.js → Sla-CIsRmePR.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-D6iXwMpA.js → SpeechSettings-Bn01d-8b.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-bC93x91L.js → SyncSettings-Cx_Znk7L.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-CcZOqgkI.js → Tasks-DvaskzpG.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-BTq2AoyQ.js → Templates-DmHCEiDO.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-D7qU02Di.js → Tenant-CqHyvnbW.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-YZpeH0oN.js → Terminal-DTt3yqWL.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-DDg43Omm.js → TimelineRenderer-BhkIxcR3.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-D-RO6fo4.js → Tokens-mhjYcBBP.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-TEnd7fo4.js → Trigger-CdlMQfwX.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-DVnK8TWT.js → Trust-Bzovg_Gw.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-B8FmpNyk.js → UkeySign-ph3EuYi7.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-DxIs_fZY.js → VideoEditing-Bo2B4VZE.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-BOyELv3w.js → Wallet-BQTKsSUT.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-CIHCpt3j.js → WebAuthn-nJxsXNHV.js} +4 -4
  91. package/src/assets/web-panel/assets/{WorkflowEditor-Bz7cskus.js → WorkflowEditor-CjH8g2N7.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-Dv8SddNl.js → chat-CkbNmnQD.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-BEV5nkv4.js → colors-BY9JcObR.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-9vwfkqFB.js → compact-item-Dzzq-d8n.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-ent1l9xX.js → createContext-DiJxxdTx.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-D502_Z3w.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-Q8eEU5e7.js → hasIn-DaXPOw3D.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DLQRUzgc.js → index-6Z6Z4UwN.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CdQo1l-5.js → index-7YVCjSqG.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-ByAsMed4.js → index-B31oMRmK.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CArObCCc.js → index-B4Sf1AMk.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DBdMxZA0.js → index-BGvIb1Sr.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-hfXZTN5I.js → index-BHeHyLRM.js} +3 -3
  104. package/src/assets/web-panel/assets/{index-CusIdZ6c.js → index-BQvtlYUd.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CfqytzM2.js → index-Bhsxh-rH.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-IjNq0ymK.js → index-BlWg1bRA.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DtCVUwNB.js → index-BqCHe05H.js} +1 -1
  108. package/src/assets/web-panel/assets/index-BrQ4nI4W.js +1 -0
  109. package/src/assets/web-panel/assets/{index-DjhTxtXx.js → index-BvgMt6Io.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-wlQxhwWL.js → index-BycyBM6g.js} +1 -1
  111. package/src/assets/web-panel/assets/index-C0_sewGO.js +1 -0
  112. package/src/assets/web-panel/assets/{index-ClayrGw1.js → index-C6XSCXeb.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-Bbxhm1Ul.js → index-CAzfu6k5.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BBTcn6Fs.js → index-CVblRqUN.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BUxM7YPq.js → index-CWLpEg34.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-Defz9gay.js → index-C_OMH_FT.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BCfGsk6N.js → index-CbOOm8I8.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Dx-mnFrM.js → index-CnLO1_yN.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CxvqZN65.js → index-CqOkm6kW.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-JdyMJF72.js → index-DDnqjZa2.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-6eOIwKrl.js → index-DObXhPhH.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-De1Gm9FM.js → index-DSqQyS9-.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-ChNGj01l.js → index-DWT9-E5b.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-FySnx-ic.js → index-D_Eoh740.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-D6oYsDxS.js → index-DaylJfw6.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D1zf7Wim.js → index-DbmHmeP-.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DeXt9bwV.js → index-Djeh6rAb.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-XSnRyYOQ.js → index-Dl8U-0hn.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-B7Gu0QHO.js → index-EiaWq1TH.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-bys1L9Zm.js → index-Igq-72Ep.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CAdPA5MQ.js → index-Jmlk_lDX.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Cn3XO8jc.js → index-LRZSVBxC.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-Zj25PNra.js → index-Uh9SjtgW.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-BSa4k_WD.js → index-cu1J4avY.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-qM_auh7p.js → index-dC2JACyJ.js} +1 -1
  136. package/src/assets/web-panel/assets/{index--G-igD6F.js → index-i9eu2Kir.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-e8NWdeA7.js → initDefaultProps-B0WuG3fa.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-Dqj2qiL6.js → motion-1r5YB22w.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-ucHeQCeV.js → move-CvtXWA_V.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-OY2ylE6m.js → mtc-parser-ChedmEE_.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-M4uSoAew.js → omit-DpEA3MP0.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-D2R8ck78.js → pickAttrs-BWgrUZF6.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-CkAkyODp.js → placementArrow-BWfo_VbI.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-D5Z1gXYW.js → responsiveObserve-CRft03Vk.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-DCLsPpEU.js → slide-l5LeXusH.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-COLrD1tR.js → statusUtils-CCEC0JR-.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-CyViVm6O.js → styleChecker-Bw5Gw_2w.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-qUsgJGGb.js → useFlexGapSupport-BAuxWB7K.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-BNGZrXAO.js → useFs-CxUP97Cw.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-CI8d0Z8T.js → usePersonalDataHub-BJDjT4Sy.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-DuM7m61_.js → vnode-BcCsFzIs.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-SdK0_dHD.js → zoom-MLmG09h6.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/commands/eval.js +79 -3
  155. package/src/commands/llm.js +40 -5
  156. package/src/data/changelog.json +26 -0
  157. package/src/lib/context-memory-kernel/message-adapter.js +41 -24
  158. package/src/lib/context-memory-kernel/segmented-memory-port.js +18 -0
  159. package/src/lib/eval/runner.js +22 -1
  160. package/src/lib/eval/verify01-contracts.js +106 -51
  161. package/src/lib/eval/verify01-execution.js +148 -166
  162. package/src/lib/eval/verify01-host-evidence.js +34 -2
  163. package/src/lib/eval/verify01-workspace.js +302 -0
  164. package/src/lib/execution-location-failure-site.js +18 -0
  165. package/src/lib/execution-location-target.js +10 -0
  166. package/src/lib/llm-connection-probe.js +147 -6
  167. package/src/lib/provider-http-error.js +30 -11
  168. package/src/lib/task-progress-tracker.js +1 -0
  169. package/src/runtime/agent-core.js +22 -0
  170. package/src/runtime/headless-runner.js +30 -20
  171. package/src/runtime/headless-stream.js +15 -10
  172. package/src/assets/web-panel/assets/ChatBubbleRenderer-BEmIX0R1.js +0 -1
  173. package/src/assets/web-panel/assets/Logs-BzkfZQQF.js +0 -2
  174. package/src/assets/web-panel/assets/MobileProjects-Cvg9bcvQ.js +0 -1
  175. package/src/assets/web-panel/assets/devWarning-DcHR2Rj6.js +0 -1
  176. package/src/assets/web-panel/assets/index-BZYMgiHf.js +0 -1
  177. package/src/assets/web-panel/assets/index-CnRInbAW.js +0 -1
@@ -0,0 +1,302 @@
1
+ /** Shared file boundaries and snapshots; no process broker or npm dependencies. */
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { createHash } from "node:crypto";
5
+ import { evalDigest } from "./evidence.js";
6
+ const MAX_BYTES = 16 * 1024 * 1024;
7
+ export const MAX_SNAPSHOT_BYTES = 512 * 1024 * 1024;
8
+ const MAX_DIFF_BYTES = 32 * 1024 * 1024;
9
+ const EMPTY_DELIVERABLE_DIGEST = evalDigest(Buffer.alloc(0));
10
+
11
+ export function requireValue(condition, message) {
12
+ if (!condition) throw new Error(message);
13
+ }
14
+
15
+ export function relativeFile(value) {
16
+ requireValue(
17
+ typeof value === "string" &&
18
+ value.length > 0 &&
19
+ !value.includes("\0") &&
20
+ !/[\\:*?<>|"]/u.test(value) &&
21
+ !value.startsWith("/") &&
22
+ value.split("/").every((part) => part && !/[. ]$/u.test(part)),
23
+ "review paths must be exact relative files",
24
+ );
25
+ return value;
26
+ }
27
+ export function readBytes(file) {
28
+ const descriptor = fs.openSync(file, "r");
29
+ try {
30
+ const before = fs.fstatSync(descriptor, { bigint: true });
31
+ requireValue(
32
+ before.isFile() && before.size <= BigInt(MAX_BYTES),
33
+ "input must be a regular file within 16 MiB",
34
+ );
35
+ const bytes = Buffer.alloc(Number(before.size) + 1);
36
+ let count = 0;
37
+ while (count < bytes.length) {
38
+ const size = fs.readSync(
39
+ descriptor,
40
+ bytes,
41
+ count,
42
+ bytes.length - count,
43
+ null,
44
+ );
45
+ if (!size) break;
46
+ count += size;
47
+ }
48
+ const after = fs.fstatSync(descriptor, { bigint: true });
49
+ requireValue(
50
+ count === Number(before.size) &&
51
+ ["dev", "ino", "size", "mtimeNs", "ctimeNs"].every(
52
+ (key) => before[key] === after[key],
53
+ ),
54
+ "input changed during read",
55
+ );
56
+ return bytes.subarray(0, count);
57
+ } finally {
58
+ fs.closeSync(descriptor);
59
+ }
60
+ }
61
+
62
+ export function canonicalDirectory(directory) {
63
+ const absolute = path.resolve(directory);
64
+ const canonical = (fs.realpathSync.native || fs.realpathSync)(absolute);
65
+ const same =
66
+ process.platform === "win32"
67
+ ? canonical.toLowerCase() === absolute.toLowerCase()
68
+ : canonical === absolute;
69
+ const stat = fs.lstatSync(absolute);
70
+ requireValue(
71
+ same && stat.isDirectory() && !stat.isSymbolicLink(),
72
+ "task directory must be canonical and unaliased",
73
+ );
74
+ return canonical;
75
+ }
76
+
77
+ /** Trusted preparation only: a seed contains no answer and never overwrites
78
+ * a project file. Existing source paths are not passed to this helper. */
79
+ export function seedVerify01Deliverables(directory, expectedFiles, budget) {
80
+ const root = canonicalDirectory(directory);
81
+ requireValue(
82
+ Array.isArray(expectedFiles) &&
83
+ expectedFiles.length > 0 &&
84
+ new Set(expectedFiles).size === expectedFiles.length,
85
+ "deliverable paths must be distinct",
86
+ );
87
+ expectedFiles.forEach(relativeFile);
88
+ const seeds = [];
89
+ for (const relative of expectedFiles) {
90
+ budget.remainingMs("deliverable-preparation");
91
+ let current = root;
92
+ for (const part of relative.split("/").slice(0, -1)) {
93
+ current = path.join(current, part);
94
+ within(root, current);
95
+ try {
96
+ fs.mkdirSync(current, { mode: 0o700 });
97
+ } catch (error) {
98
+ if (error.code !== "EEXIST") throw error;
99
+ }
100
+ canonicalDirectory(current);
101
+ }
102
+ const target = path.join(root, relative);
103
+ within(root, target);
104
+ const fd = fs.openSync(
105
+ target,
106
+ fs.constants.O_WRONLY |
107
+ fs.constants.O_CREAT |
108
+ fs.constants.O_EXCL |
109
+ (fs.constants.O_NOFOLLOW || 0),
110
+ 0o600,
111
+ );
112
+ try {
113
+ const stat = fs.fstatSync(fd);
114
+ requireValue(
115
+ stat.isFile() && stat.nlink === 1 && stat.size === 0,
116
+ "seed must be an empty unaliased regular file",
117
+ );
118
+ regularPath(root, relative);
119
+ const named = fs.lstatSync(target);
120
+ requireValue(
121
+ named.dev === stat.dev && named.ino === stat.ino,
122
+ "seed path changed identity during preparation",
123
+ );
124
+ canonicalDirectory(path.dirname(target));
125
+ seeds.push(
126
+ Object.freeze({
127
+ path: relative,
128
+ before: null,
129
+ origin: "trusted-empty-deliverable-preparation",
130
+ digest: EMPTY_DELIVERABLE_DIGEST,
131
+ bytes: 0,
132
+ requestedMode: 0o600,
133
+ mode: stat.mode & 0o777,
134
+ preparedAt: new Date().toISOString(),
135
+ }),
136
+ );
137
+ } finally {
138
+ fs.closeSync(fd);
139
+ }
140
+ }
141
+ return Object.freeze(seeds);
142
+ }
143
+
144
+ export function within(root, file) {
145
+ const relative = path.relative(root, file);
146
+ requireValue(
147
+ relative &&
148
+ relative !== ".." &&
149
+ !relative.startsWith(`..${path.sep}`) &&
150
+ !path.isAbsolute(relative),
151
+ "path escapes its declared root",
152
+ );
153
+ }
154
+
155
+ export function regularPath(root, relative) {
156
+ relativeFile(relative);
157
+ const file = path.join(root, relative);
158
+ within(root, file);
159
+ let current = root;
160
+ for (const segment of relative.split("/")) {
161
+ current = path.join(current, segment);
162
+ requireValue(
163
+ !fs.lstatSync(current).isSymbolicLink(),
164
+ "review/project paths must not traverse links",
165
+ );
166
+ }
167
+ requireValue(
168
+ fs.lstatSync(file).isFile(),
169
+ "review/project artifact must be a regular file",
170
+ );
171
+ return file;
172
+ }
173
+
174
+ export function snapshotVerify01Workspace(directory, budget, stage) {
175
+ const files = new Map();
176
+ let total = 0;
177
+ let dependencyBytes = 0;
178
+ let dependencyFiles = 0;
179
+ const dependencyHash = createHash("sha256");
180
+ const buffer = Buffer.alloc(64 * 1024);
181
+ const visit = (current) => {
182
+ for (const entry of fs
183
+ .readdirSync(current, { withFileTypes: true })
184
+ .sort((a, b) => a.name.localeCompare(b.name, "en"))) {
185
+ budget.remainingMs(stage);
186
+ const full = path.join(current, entry.name);
187
+ const relative = path.relative(directory, full).split(path.sep).join("/");
188
+ if (entry.isDirectory()) visit(full);
189
+ else {
190
+ requireValue(
191
+ entry.isFile() || entry.isSymbolicLink(),
192
+ "task snapshot contains an unsupported filesystem object",
193
+ );
194
+ // Preserve link identities without following them into another root.
195
+ const dependency = relative.split("/").includes("node_modules");
196
+ if (dependency && entry.isSymbolicLink()) {
197
+ // A dependency linked outside the isolated workspace cannot be
198
+ // fingerprinted by this capture contract; never silently omit it.
199
+ within(directory, fs.realpathSync(full));
200
+ }
201
+ let bytes = entry.isSymbolicLink()
202
+ ? Buffer.from(fs.readlinkSync(full))
203
+ : dependency
204
+ ? null
205
+ : readBytes(full);
206
+ let digest, size;
207
+ if (dependency && bytes === null) {
208
+ const hash = createHash("sha256");
209
+ const fd = fs.openSync(full, "r");
210
+ size = 0;
211
+ try {
212
+ let count;
213
+ while (
214
+ (count = fs.readSync(fd, buffer, 0, buffer.length, null)) > 0
215
+ ) {
216
+ budget.remainingMs(stage);
217
+ size += count;
218
+ requireValue(
219
+ dependencyBytes + size <= 16 * 1024 ** 3,
220
+ "dependency fingerprint exceeds 16 GiB",
221
+ );
222
+ hash.update(buffer.subarray(0, count));
223
+ }
224
+ } finally {
225
+ fs.closeSync(fd);
226
+ }
227
+ digest = `sha256:${hash.digest("hex")}`;
228
+ } else {
229
+ size = bytes.length;
230
+ digest = evalDigest(bytes);
231
+ }
232
+ if (dependency) {
233
+ dependencyBytes += size;
234
+ dependencyFiles++;
235
+ bytes = null;
236
+ } else total += size;
237
+ requireValue(
238
+ total <= MAX_SNAPSHOT_BYTES &&
239
+ files.size - dependencyFiles < 100000 &&
240
+ dependencyFiles <= 1000000,
241
+ "task snapshot exceeds its capture bound",
242
+ );
243
+ const value = {
244
+ type: entry.isSymbolicLink() ? "link" : "file",
245
+ mode: fs.lstatSync(full).mode & 0o777,
246
+ bytes,
247
+ size,
248
+ digest,
249
+ dependency,
250
+ };
251
+ files.set(relative, value);
252
+ if (dependency)
253
+ dependencyHash.update(
254
+ JSON.stringify([relative, value.type, value.mode, size, digest]) +
255
+ "\n",
256
+ );
257
+ }
258
+ }
259
+ };
260
+ visit(directory);
261
+ files.dependencyBoundary = {
262
+ contract:
263
+ "all node_modules files and link identities streamed with SHA-256; links never followed; dependency bodies omitted; every change rejected",
264
+ files: dependencyFiles,
265
+ bytes: dependencyBytes,
266
+ digest: `sha256:${dependencyHash.digest("hex")}`,
267
+ };
268
+ return files;
269
+ }
270
+
271
+ export function diffVerify01Workspace(before, after) {
272
+ const result = [];
273
+ let total = 0;
274
+ for (const file of [...new Set([...before.keys(), ...after.keys()])].sort()) {
275
+ const old = before.get(file),
276
+ next = after.get(file);
277
+ if (
278
+ old?.digest === next?.digest &&
279
+ old?.type === next?.type &&
280
+ old?.mode === next?.mode
281
+ )
282
+ continue;
283
+ total += (old?.bytes?.length || 0) + (next?.bytes?.length || 0);
284
+ requireValue(
285
+ total <= MAX_DIFF_BYTES,
286
+ "task diff exceeds 32 MiB; preserve workspace for independent inspection",
287
+ );
288
+ const describe = (value) =>
289
+ value
290
+ ? {
291
+ type: value.type,
292
+ mode: value.mode,
293
+ digest: value.digest,
294
+ bytes: value.size,
295
+ dependency: value.dependency,
296
+ bytesBase64: value.bytes?.toString("base64") ?? null,
297
+ }
298
+ : null;
299
+ result.push({ path: file, before: describe(old), after: describe(next) });
300
+ }
301
+ return result;
302
+ }
@@ -27,6 +27,24 @@ export function readExecutionLocationStorageFailure(stderr) {
27
27
  return match ? `${match[1]}${match[2] || ""}` : null;
28
28
  }
29
29
 
30
+ export function readExecutionLocationStorageLaunchFailure(stderr) {
31
+ const match = String(stderr || "")
32
+ .slice(0, MAX_DIAGNOSTIC_CHARS)
33
+ .match(
34
+ /\[windows-acl-launch:(inspect|repair|preflight):(spawn|timeout):(startup|initialize|traversal|lookup|repair-lock|repair-inspect|repair-write|verify):(EACCES|EPERM|ENOENT|ETIMEDOUT|EINVAL|ENOSYS|ENOMEM|EMFILE|ENFILE|ENOBUFS|EBUSY|UNKNOWN):(unknown|-?(?:0|[1-9][0-9]{0,4})):(spawnSync|spawn|unknown)\]/u,
35
+ );
36
+ if (!match) return null;
37
+ const [, operation, failureStage, progressStage, code, rawErrno, syscall] =
38
+ match;
39
+ const errno = rawErrno === "unknown" ? null : Number(rawErrno);
40
+ if (
41
+ (errno !== null && Math.abs(errno) > 65535) ||
42
+ (failureStage === "timeout") !== (code === "ETIMEDOUT")
43
+ )
44
+ return null;
45
+ return { operation, failureStage, progressStage, code, errno, syscall };
46
+ }
47
+
30
48
  export function executionLocationFailureSite(error) {
31
49
  const stack = String(error?.stack || "").slice(0, MAX_DIAGNOSTIC_CHARS);
32
50
  for (const frame of stack.split(/\r?\n/u).slice(1)) {
@@ -7,6 +7,7 @@ import { TextDecoder } from "node:util";
7
7
  import {
8
8
  readExecutionLocationFailureSite,
9
9
  readExecutionLocationStorageFailure,
10
+ readExecutionLocationStorageLaunchFailure,
10
11
  } from "./execution-location-failure-site.js";
11
12
  import {
12
13
  EXECUTION_LOCATION_TARGET_ATTESTATION_SCHEMA,
@@ -1039,6 +1040,10 @@ function targetProcessFailure(result) {
1039
1040
  error.failureCategory = failureCategory;
1040
1041
  if (failureSite) error.failureSite = failureSite;
1041
1042
  if (storageFailure) error.storageFailure = storageFailure;
1043
+ const storageLaunchFailure = readExecutionLocationStorageLaunchFailure(
1044
+ result.stderr,
1045
+ );
1046
+ if (storageLaunchFailure) error.storageLaunchFailure = storageLaunchFailure;
1042
1047
  return error;
1043
1048
  }
1044
1049
 
@@ -1108,6 +1113,11 @@ function runTargetCommand(profile, cliArgs, deps = {}, options = {}) {
1108
1113
  error.failureCategory = failureCategory;
1109
1114
  if (failureSite) error.failureSite = failureSite;
1110
1115
  if (storageFailure) error.storageFailure = storageFailure;
1116
+ const storageLaunchFailure = readExecutionLocationStorageLaunchFailure(
1117
+ result?.stderr,
1118
+ );
1119
+ if (storageLaunchFailure)
1120
+ error.storageLaunchFailure = storageLaunchFailure;
1111
1121
  throw error;
1112
1122
  }
1113
1123
  return options.interactive ? null : result.stdout;
@@ -1,13 +1,141 @@
1
1
  import { formatProviderResponseError } from "./provider-http-error.js";
2
+ import { estimateCost } from "./llm-pricing.js";
2
3
 
3
4
  // Reasoning models spend the same output allowance on thinking before the
4
5
  // final answer. A 16-token probe can therefore receive HTTP 200 with only
5
6
  // reasoning_content and finish_reason=length from an otherwise usable model.
6
7
  const PROBE_OUTPUT_TOKENS = 1024;
8
+ export const LLM_PROBE_SCHEMA = "chainlesschain.llm-connection-probe/v1";
9
+
10
+ const count = (value) => Number.isSafeInteger(value) && value >= 0;
11
+
12
+ /** Preserve missing/malformed usage as unknown, including cached prompt tokens. */
13
+ export function normalizeLlmProbeUsage(provider, data) {
14
+ if (!data || typeof data !== "object" || Array.isArray(data)) return null;
15
+ let usage;
16
+ if (provider === "ollama") {
17
+ usage = {
18
+ input_tokens: data.prompt_eval_count,
19
+ output_tokens: data.eval_count,
20
+ };
21
+ } else if (provider === "anthropic") {
22
+ usage = data.usage;
23
+ } else if (provider === "gemini") {
24
+ const raw = data.usageMetadata;
25
+ if (
26
+ !raw ||
27
+ !count(raw.candidatesTokenCount) ||
28
+ !count(raw.thoughtsTokenCount === undefined ? 0 : raw.thoughtsTokenCount)
29
+ )
30
+ return null;
31
+ const cached =
32
+ raw.cachedContentTokenCount === undefined
33
+ ? 0
34
+ : raw.cachedContentTokenCount;
35
+ if (
36
+ !count(raw.promptTokenCount) ||
37
+ !count(cached) ||
38
+ cached > raw.promptTokenCount
39
+ )
40
+ return null;
41
+ usage = {
42
+ input_tokens: raw.promptTokenCount - cached,
43
+ output_tokens: raw.candidatesTokenCount + (raw.thoughtsTokenCount ?? 0),
44
+ cache_read_input_tokens: cached,
45
+ };
46
+ } else {
47
+ const raw = data.usage;
48
+ if (!raw || !count(raw.prompt_tokens) || !count(raw.completion_tokens))
49
+ return null;
50
+ const detailed = raw.prompt_tokens_details?.cached_tokens;
51
+ const legacy = raw.prompt_cache_hit_tokens;
52
+ const cached =
53
+ detailed === undefined ? (legacy === undefined ? 0 : legacy) : detailed;
54
+ if (
55
+ !count(cached) ||
56
+ cached > raw.prompt_tokens ||
57
+ (detailed !== undefined && legacy !== undefined && detailed !== legacy)
58
+ )
59
+ return null;
60
+ usage = {
61
+ input_tokens: raw.prompt_tokens - cached,
62
+ output_tokens: raw.completion_tokens,
63
+ cache_read_input_tokens: cached,
64
+ };
65
+ }
66
+ if (!usage || typeof usage !== "object" || Array.isArray(usage)) return null;
67
+ const normalized = {
68
+ input_tokens: usage.input_tokens,
69
+ output_tokens: usage.output_tokens,
70
+ cache_read_input_tokens:
71
+ usage.cache_read_input_tokens === undefined
72
+ ? 0
73
+ : usage.cache_read_input_tokens,
74
+ cache_creation_input_tokens:
75
+ usage.cache_creation_input_tokens === undefined
76
+ ? 0
77
+ : usage.cache_creation_input_tokens,
78
+ };
79
+ return Object.values(normalized).every(count) ? normalized : null;
80
+ }
81
+
82
+ export function priceLlmProbeUsage(target, usage) {
83
+ if (
84
+ !usage ||
85
+ ![
86
+ usage.input_tokens,
87
+ usage.output_tokens,
88
+ usage.cache_read_input_tokens,
89
+ usage.cache_creation_input_tokens,
90
+ ].every(count)
91
+ )
92
+ return null;
93
+ const estimate = estimateCost({
94
+ provider: target.provider,
95
+ model: target.model,
96
+ inputTokens: usage.input_tokens,
97
+ outputTokens: usage.output_tokens,
98
+ cacheReadTokens: usage.cache_read_input_tokens,
99
+ cacheCreationTokens: usage.cache_creation_input_tokens,
100
+ });
101
+ return estimate.matched && Number.isFinite(estimate.totalCost)
102
+ ? estimate.totalCost
103
+ : null;
104
+ }
105
+
106
+ export function llmProbeReceipt(
107
+ target,
108
+ { ok = false, reply = null, usage = null } = {},
109
+ ) {
110
+ const normalizedUsage =
111
+ usage === null
112
+ ? null
113
+ : {
114
+ input_tokens: usage.input_tokens,
115
+ output_tokens: usage.output_tokens,
116
+ cache_read_input_tokens: usage.cache_read_input_tokens,
117
+ cache_creation_input_tokens: usage.cache_creation_input_tokens,
118
+ };
119
+ return {
120
+ schema: LLM_PROBE_SCHEMA,
121
+ ok,
122
+ provider: target.provider,
123
+ model: target.model,
124
+ reply:
125
+ target.apiKey && typeof reply === "string"
126
+ ? reply.replaceAll(target.apiKey, "[REDACTED]")
127
+ : reply,
128
+ usage: normalizedUsage,
129
+ totalCostUsd: priceLlmProbeUsage(target, normalizedUsage),
130
+ currency: "USD",
131
+ costBasis: "token-estimate",
132
+ billingVerified: false,
133
+ };
134
+ }
7
135
 
8
136
  export async function probeLlmConnection(
9
137
  target,
10
- { fetchImpl = fetch, timeoutMs = 20_000 } = {},
138
+ { fetchImpl = fetch, timeoutMs = 20_000, includeUsage = false } = {},
11
139
  ) {
12
140
  const base = target.baseUrl.replace(/\/+$/, "");
13
141
  const headers = { "Content-Type": "application/json" };
@@ -50,6 +178,7 @@ export async function probeLlmConnection(
50
178
  }
51
179
  const controller = new AbortController();
52
180
  const timer = setTimeout(() => controller.abort(), timeoutMs);
181
+ let usage = null;
53
182
  try {
54
183
  const response = await fetchImpl(url, {
55
184
  method: "POST",
@@ -60,9 +189,12 @@ export async function probeLlmConnection(
60
189
  });
61
190
  if (!response.ok)
62
191
  throw new Error(
63
- await formatProviderResponseError(target.provider, response),
192
+ await formatProviderResponseError(target.provider, response, {
193
+ secrets: [target.apiKey],
194
+ }),
64
195
  );
65
196
  const data = await response.json();
197
+ usage = normalizeLlmProbeUsage(target.provider, data);
66
198
  const text =
67
199
  target.provider === "ollama"
68
200
  ? data.response
@@ -91,11 +223,20 @@ export async function probeLlmConnection(
91
223
  "The endpoint returned no model text; check the protocol and model",
92
224
  );
93
225
  }
94
- return text.trim().slice(0, 100);
226
+ const reply = (
227
+ target.apiKey ? text.replaceAll(target.apiKey, "[REDACTED]") : text
228
+ )
229
+ .trim()
230
+ .slice(0, 100);
231
+ return includeUsage
232
+ ? llmProbeReceipt(target, { ok: true, reply, usage })
233
+ : reply;
95
234
  } catch (error) {
96
- if (controller.signal.aborted)
97
- throw new Error(`Connection test timed out after ${timeoutMs / 1000}s`);
98
- throw error;
235
+ const failure = controller.signal.aborted
236
+ ? new Error(`Connection test timed out after ${timeoutMs / 1000}s`)
237
+ : error;
238
+ if (includeUsage) failure.probe = llmProbeReceipt(target, { usage });
239
+ throw failure;
99
240
  } finally {
100
241
  clearTimeout(timer);
101
242
  }
@@ -3,9 +3,14 @@
3
3
  * Keep structured provider diagnostics while redacting credential-shaped text.
4
4
  */
5
5
 
6
- function safePart(value) {
6
+ function safePart(value, secrets = []) {
7
7
  if (value == null) return "";
8
- return String(value)
8
+ let text = String(value);
9
+ for (const secret of secrets) {
10
+ if (typeof secret === "string" && secret)
11
+ text = text.replaceAll(secret, "***");
12
+ }
13
+ return text
9
14
  .replace(/\s+/g, " ")
10
15
  .replace(/\b(Bearer\s+)[A-Za-z0-9._~+/-]+=*\b/gi, "$1***")
11
16
  .replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gi, "sk-***")
@@ -13,21 +18,24 @@ function safePart(value) {
13
18
  .slice(0, 400);
14
19
  }
15
20
 
16
- function errorDetail(payload) {
21
+ function errorDetail(payload, secrets) {
17
22
  if (payload == null) return { code: "", message: "" };
18
23
  const raw =
19
24
  typeof payload === "object" && payload.error != null
20
25
  ? payload.error
21
26
  : payload;
22
27
  if (typeof raw === "string") {
23
- return { code: "", message: safePart(raw) };
28
+ return { code: "", message: safePart(raw, secrets) };
24
29
  }
25
30
  if (!raw || typeof raw !== "object") {
26
- return { code: "", message: safePart(raw) };
31
+ return { code: "", message: safePart(raw, secrets) };
27
32
  }
28
33
  return {
29
- code: safePart(raw.code || raw.type),
30
- message: safePart(raw.message || raw.error_description || raw.detail),
34
+ code: safePart(raw.code || raw.type, secrets),
35
+ message: safePart(
36
+ raw.message || raw.error_description || raw.detail,
37
+ secrets,
38
+ ),
31
39
  };
32
40
  }
33
41
 
@@ -36,9 +44,14 @@ function errorDetail(payload) {
36
44
  * accounts and model-access denials. Preserve the safe code/message so clients
37
45
  * can show the real corrective action.
38
46
  */
39
- export function formatProviderHttpError(provider, status, payload = null) {
47
+ export function formatProviderHttpError(
48
+ provider,
49
+ status,
50
+ payload = null,
51
+ { secrets = [] } = {},
52
+ ) {
40
53
  const base = `${provider} API error: HTTP ${status}`;
41
- const detail = errorDetail(payload);
54
+ const detail = errorDetail(payload, secrets);
42
55
  const detailText = [detail.code, detail.message].filter(Boolean).join(": ");
43
56
  const detailSentence = detailText.replace(/[.!?]+$/, "");
44
57
  const classified = `${detail.code} ${detail.message}`.toLowerCase();
@@ -76,7 +89,11 @@ export function formatProviderHttpError(provider, status, payload = null) {
76
89
  return detailSentence ? `${base} — ${detailSentence}` : base;
77
90
  }
78
91
 
79
- export async function formatProviderResponseError(provider, response) {
92
+ export async function formatProviderResponseError(
93
+ provider,
94
+ response,
95
+ { secrets = [] } = {},
96
+ ) {
80
97
  let payload = null;
81
98
  try {
82
99
  const text = await response.text();
@@ -90,5 +107,7 @@ export async function formatProviderResponseError(provider, response) {
90
107
  } catch {
91
108
  // A broken/empty body still retains the HTTP status diagnosis.
92
109
  }
93
- return formatProviderHttpError(provider, response.status, payload);
110
+ return formatProviderHttpError(provider, response.status, payload, {
111
+ secrets,
112
+ });
94
113
  }
@@ -470,6 +470,7 @@ export class TaskProgressTracker {
470
470
  guidance:
471
471
  message +
472
472
  " For an implementation task, make the smallest justified, authorized change and validate it. " +
473
+ "If the user requested new or updated tests, actual test changes and focused validation remain required; reading tests or passing an existing baseline does not fulfill that request. Name the concrete missing fact before another read. " +
473
474
  "For a bug fix, state the observed failure, your leading root-cause hypothesis and the smallest test that can disprove it. Run that focused reproduction or diagnostic next; use its actual output to choose the next step. Do not keep reading adjacent files without naming the specific missing fact. A timeout alone does not establish that increasing the timeout is the fix. " +
474
475
  DIAGNOSTIC_WORKFLOW_GUIDANCE +
475
476
  " " +
@@ -15405,6 +15405,27 @@ export async function* agentLoop(messages, options) {
15405
15405
  }
15406
15406
  }
15407
15407
  const contextMemoryTrustedSystemIndexes = [];
15408
+ if (Number.isFinite(budget.limit)) {
15409
+ // consume() already charged this dispatch. The current request may still
15410
+ // act even when no further provider request remains. Rebuild this hint
15411
+ // after compaction and rejection-only turns; do not persist it in history.
15412
+ const furtherRequests = budget.remaining();
15413
+ // Keep the stable conversation prefix ahead of this changing counter.
15414
+ // The canonical planner protects the last conversational user bundle
15415
+ // even when trusted ephemeral system guidance follows it.
15416
+ callMessages = [
15417
+ ...callMessages,
15418
+ {
15419
+ role: "system",
15420
+ content:
15421
+ `Execution budget: this request plus ${furtherRequests} further model requests. ` +
15422
+ "For requested changes, reserve requests for implementation, focused validation, and repair or an accurate unfinished-work report. " +
15423
+ "Reading or an existing passing baseline does not deliver requested changes. " +
15424
+ "For research or monitoring, use the remaining requests for evidence and the requested answer; do not create files just to show activity.",
15425
+ },
15426
+ ];
15427
+ contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
15428
+ }
15408
15429
  if (prActionTask && !prInvestigationExhausted) {
15409
15430
  callMessages = [
15410
15431
  ...callMessages,
@@ -16304,6 +16325,7 @@ export async function* agentLoop(messages, options) {
16304
16325
  tool: toolName,
16305
16326
  result: earlyAuthorityDenial,
16306
16327
  error: earlyAuthorityDenial.error,
16328
+ execution_started: false,
16307
16329
  tool_use_id: call.id,
16308
16330
  turn_id: `${runId}:t${budget.consumed}`,
16309
16331
  permission_decision_id: decision?.id || null,