chainlesschain 0.166.126 → 0.166.128

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 (199) hide show
  1. package/README.md +31 -3
  2. package/package.json +1 -1
  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/.build-hash +1 -1
  6. package/src/assets/web-panel/assets/{AIOps-C6HzxpS_.js → AIOps-BmGA5zXX.js} +1 -1
  7. package/src/assets/web-panel/assets/{ActionButton-Ba2WP_mo.js → ActionButton-B7WXwoF0.js} +1 -1
  8. package/src/assets/web-panel/assets/{Analytics-MEZ-eSYO.js → Analytics-IvJG43B5.js} +3 -3
  9. package/src/assets/web-panel/assets/{AppLayout-B1F4dMJl.js → AppLayout-DWY017_e.js} +5 -5
  10. package/src/assets/web-panel/assets/Artifacts-BOyohM_-.js +1 -0
  11. package/src/assets/web-panel/assets/{Audit-GzrP6OYx.js → Audit-CD9sTnBN.js} +1 -1
  12. package/src/assets/web-panel/assets/{BackgroundAgents-PJ3RWIS5.js → BackgroundAgents-J6gg5z0U.js} +1 -1
  13. package/src/assets/web-panel/assets/{Backup-DV0wK73Y.js → Backup-D7ik3lse.js} +1 -1
  14. package/src/assets/web-panel/assets/{BaseInput-BqWPlsK1.js → BaseInput-MrDd5zcz.js} +1 -1
  15. package/src/assets/web-panel/assets/{Chat-D0yNPOid.js → Chat-DbxRqGiK.js} +5 -5
  16. package/src/assets/web-panel/assets/{ChatBubbleRenderer-D0De01yM.js → ChatBubbleRenderer-DbeJAwMg.js} +1 -1
  17. package/src/assets/web-panel/assets/{Checkbox-GOdS6Fpz.js → Checkbox-CditB77B.js} +1 -1
  18. package/src/assets/web-panel/assets/{Codegen-CcvPMAwP.js → Codegen-Ds0UZWZG.js} +1 -1
  19. package/src/assets/web-panel/assets/{Col-07yH3vgP.js → Col-CZlj1XI2.js} +1 -1
  20. package/src/assets/web-panel/assets/{Community-cZI0W7u_.js → Community-j4B2SoT6.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compact-BP6fwhXB.js → Compact-BuKQutaO.js} +1 -1
  22. package/src/assets/web-panel/assets/{Compliance-BvwQCjXA.js → Compliance-DAgDyS-p.js} +1 -1
  23. package/src/assets/web-panel/assets/{Cowork-yhhvyKZU.js → Cowork-DX2-I6V3.js} +3 -3
  24. package/src/assets/web-panel/assets/{Cron-Bpji2uez.js → Cron-dJpc-FxX.js} +2 -2
  25. package/src/assets/web-panel/assets/{Crosschain-BZ7XwkuS.js → Crosschain-7m8euM3v.js} +1 -1
  26. package/src/assets/web-panel/assets/{DID-BJ-Fw-Uk.js → DID-CLoYoCe1.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dashboard-3FbsaKoR.js → Dashboard-DR1rRMb7.js} +2 -2
  28. package/src/assets/web-panel/assets/{Dropdown-DP8yuWyM.js → Dropdown-BsKhCfvH.js} +1 -1
  29. package/src/assets/web-panel/assets/{EmailListRenderer-Co3i-4ca.js → EmailListRenderer-BAGexzJu.js} +1 -1
  30. package/src/assets/web-panel/assets/EvolutionSettings-BqYYmC01.js +1 -0
  31. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CPjecSCb.js → FamilyGuardDashboard-BIpueefy.js} +1 -1
  32. package/src/assets/web-panel/assets/{Federation-CJkZPulM.js → Federation-BluNep6d.js} +1 -1
  33. package/src/assets/web-panel/assets/{FormItemContext-CU0YWiAZ.js → FormItemContext-CerdM3am.js} +1 -1
  34. package/src/assets/web-panel/assets/{GenericCardRenderer-kTxvvpiU.js → GenericCardRenderer-DXh4tOjU.js} +1 -1
  35. package/src/assets/web-panel/assets/{Git-Cs6SFvMq.js → Git-CEE0cGmf.js} +2 -2
  36. package/src/assets/web-panel/assets/{Governance-CSs_8thn.js → Governance-Bc-XNDhM.js} +1 -1
  37. package/src/assets/web-panel/assets/{Inference-D7yCromD.js → Inference-CiBzXyZ-.js} +1 -1
  38. package/src/assets/web-panel/assets/{KnowledgeGraph-C6BcMDRm.js → KnowledgeGraph-CV2IiyuN.js} +1 -1
  39. package/src/assets/web-panel/assets/{Logs-Cz20G07I.js → Logs-fbQYKuSz.js} +2 -2
  40. package/src/assets/web-panel/assets/MarkdownRenderer-B73ZyMRI.js +1 -0
  41. package/src/assets/web-panel/assets/{Marketplace-BZIopTsG.js → Marketplace-C5utdpxZ.js} +1 -1
  42. package/src/assets/web-panel/assets/{McpTools-OHaHium7.js → McpTools-CPE4SaF3.js} +3 -3
  43. package/src/assets/web-panel/assets/{Memory-DBNBmoM9.js → Memory-DTFDszzk.js} +2 -2
  44. package/src/assets/web-panel/assets/{MobileBridge-BH-ajP-j.js → MobileBridge-DxqPmTzP.js} +1 -1
  45. package/src/assets/web-panel/assets/{MobileProjects-DwiFGqpp.js → MobileProjects-CwcK8l2y.js} +1 -1
  46. package/src/assets/web-panel/assets/{Mtc-BmT_VyZL.js → Mtc-DrjECLGO.js} +2 -2
  47. package/src/assets/web-panel/assets/{MtcAudit-D24wmjmR.js → MtcAudit-4IURCa-3.js} +5 -5
  48. package/src/assets/web-panel/assets/{Multisig-DwWj1F8f.js → Multisig-CggLV1Cp.js} +3 -3
  49. package/src/assets/web-panel/assets/{NLProgramming-DXBRBwhU.js → NLProgramming-DkOQJT73.js} +1 -1
  50. package/src/assets/web-panel/assets/{Notes-C1QG3x5c.js → Notes-Dodcva6s.js} +3 -3
  51. package/src/assets/web-panel/assets/{NotificationSettings-BnlSMFBJ.js → NotificationSettings-CQ3HeTs6.js} +1 -1
  52. package/src/assets/web-panel/assets/{OrderTableRenderer-uuW0wQc0.js → OrderTableRenderer-pT2nzmIO.js} +1 -1
  53. package/src/assets/web-panel/assets/{Organization-CXGC9RYr.js → Organization-B6HFsIfU.js} +4 -4
  54. package/src/assets/web-panel/assets/{Overflow-C3RxcBqQ.js → Overflow-G9dju55N.js} +1 -1
  55. package/src/assets/web-panel/assets/{P2P-DTh-AqFm.js → P2P-C1BCE155.js} +2 -2
  56. package/src/assets/web-panel/assets/{PdhVaultBrowser-IX0sEKne.js → PdhVaultBrowser-BFAxXn5D.js} +3 -3
  57. package/src/assets/web-panel/assets/{Permissions-CpcyEP_G.js → Permissions-DWg7cw9Q.js} +4 -4
  58. package/src/assets/web-panel/assets/{PersonalDataHub-I5zN_SIn.js → PersonalDataHub-BQxuOQOO.js} +3 -3
  59. package/src/assets/web-panel/assets/{Pipeline-CVg3gNFN.js → Pipeline-C3Gse9Ne.js} +1 -1
  60. package/src/assets/web-panel/assets/{Privacy-Dffk2pq9.js → Privacy-Dcsjx6Oi.js} +1 -1
  61. package/src/assets/web-panel/assets/{ProjectInit-B8Y3VsbN.js → ProjectInit-DeYlnXJQ.js} +2 -2
  62. package/src/assets/web-panel/assets/{ProjectSettings-Ds_4fCFG.js → ProjectSettings-D7kbZ_K7.js} +2 -2
  63. package/src/assets/web-panel/assets/{Projects-BlyQuiCs.js → Projects-C5m3NGzM.js} +1 -1
  64. package/src/assets/web-panel/assets/{Providers-CI9tKh8S.js → Providers-oT6jy83z.js} +1 -1
  65. package/src/assets/web-panel/assets/{QrScannerModal-DOrmL6X3.js → QrScannerModal-NZ11GEBa.js} +1 -1
  66. package/src/assets/web-panel/assets/{QuickAsk-CSSlopeF.js → QuickAsk-CtQU4Tx0.js} +1 -1
  67. package/src/assets/web-panel/assets/{Recommend-fKDWVJgw.js → Recommend-3CoXYu3O.js} +1 -1
  68. package/src/assets/web-panel/assets/{RemoteSession-BKlbq1C0.js → RemoteSession-C2d4LzBM.js} +3 -3
  69. package/src/assets/web-panel/assets/{Reputation-DhOFTKRG.js → Reputation-WZQHrGwl.js} +1 -1
  70. package/src/assets/web-panel/assets/{Row-ckVQk62z.js → Row-ChiqY7Hg.js} +1 -1
  71. package/src/assets/web-panel/assets/{RssFeed-CShivptZ.js → RssFeed-Cjwl2Kum.js} +2 -2
  72. package/src/assets/web-panel/assets/{Search-PJpI8T9h.js → Search-DRDMZxTF.js} +1 -1
  73. package/src/assets/web-panel/assets/{Security-CVQPej3p.js → Security-D0y4LlQ4.js} +3 -3
  74. package/src/assets/web-panel/assets/{Services-CWJj07ru.js → Services-ChpkqWm0.js} +2 -2
  75. package/src/assets/web-panel/assets/{Skeleton-CNxdd41V.js → Skeleton-D3WGZ8yO.js} +1 -1
  76. package/src/assets/web-panel/assets/{Skills-AD-xWT2V.js → Skills-Bv_7HaUW.js} +1 -1
  77. package/src/assets/web-panel/assets/{Sla-BuDuN1ak.js → Sla-crZMKyX0.js} +1 -1
  78. package/src/assets/web-panel/assets/{SpeechSettings-WYryugQK.js → SpeechSettings-ByWn5XDZ.js} +1 -1
  79. package/src/assets/web-panel/assets/{SyncSettings-Dxz8z_yO.js → SyncSettings--R55vxvj.js} +2 -2
  80. package/src/assets/web-panel/assets/{Tasks-BCQFGo6S.js → Tasks-BZA_Via_.js} +1 -1
  81. package/src/assets/web-panel/assets/{Templates-CNU1xhuV.js → Templates-9eJ9yY8Q.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tenant-CFsqv744.js → Tenant-CfWX2jqj.js} +1 -1
  83. package/src/assets/web-panel/assets/{Terminal--7FxkXMc.js → Terminal-CUXUF4kL.js} +2 -2
  84. package/src/assets/web-panel/assets/{TimelineRenderer-Cqtg4CN-.js → TimelineRenderer-77y9bkYN.js} +1 -1
  85. package/src/assets/web-panel/assets/{Tokens-DQD8oVJ3.js → Tokens-CvyrdLH6.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trigger-BujLIIRO.js → Trigger-MNRl_YNr.js} +1 -1
  87. package/src/assets/web-panel/assets/{Trust-_3yRNM57.js → Trust-BHOXK-Mp.js} +1 -1
  88. package/src/assets/web-panel/assets/{UkeySign-C_QKp9Ig.js → UkeySign-Bz1oZNyQ.js} +1 -1
  89. package/src/assets/web-panel/assets/{VideoEditing-BkgP1c6L.js → VideoEditing-DlqmXyZv.js} +1 -1
  90. package/src/assets/web-panel/assets/{Wallet-CTHaNBha.js → Wallet-Dg1rnqEG.js} +4 -4
  91. package/src/assets/web-panel/assets/{WebAuthn-CbXcDn_T.js → WebAuthn-DJtGeaOk.js} +4 -4
  92. package/src/assets/web-panel/assets/{WorkflowEditor-BUOyHiTN.js → WorkflowEditor-DJPubjX5.js} +1 -1
  93. package/src/assets/web-panel/assets/{chat-DTG5Geyv.js → chat-BWweDuIV.js} +1 -1
  94. package/src/assets/web-panel/assets/{colors-BAdqWSlv.js → colors-BX5ViADF.js} +1 -1
  95. package/src/assets/web-panel/assets/{compact-item-DYh7YdLa.js → compact-item-Df8MLbXp.js} +1 -1
  96. package/src/assets/web-panel/assets/{createContext-mPOA80GV.js → createContext-C0FDTwdV.js} +1 -1
  97. package/src/assets/web-panel/assets/devWarning-BgM5vq1s.js +1 -0
  98. package/src/assets/web-panel/assets/{hasIn-Gzp3HIXP.js → hasIn-PpL6GdNk.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CLuIQO9d.js → index-7VyVOEf7.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BL46pkYn.js → index-B3K1uZ7R.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CFXlLyEF.js → index-B4UxFB2N.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Diwevwx7.js → index-B8-pSyP7.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Brr8ALy2.js → index-B982oUKN.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CsgxUKpZ.js → index-BF0ERucU.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BjRl7Jhc.js → index-BMIEWinN.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-X1iyU-gh.js → index-BWSCphaT.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CYbMpkmP.js → index-BeFhy4BX.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CGQfiMVc.js → index-Beh1kLwx.js} +1 -1
  109. package/src/assets/web-panel/assets/index-Bl-HTXWn.js +1 -0
  110. package/src/assets/web-panel/assets/{index-CR3ZvuY6.js → index-C0PqPK-8.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CzkgWUAt.js → index-C2JU-gdS.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-z3FnuAKK.js → index-C8wl7Ica.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-og41WNLX.js → index-C9FOwTgX.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BQZVcznI.js → index-C9N1u8jV.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CqSb5LAk.js → index-Cf86RSQk.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DxpX3q8j.js → index-ChV82mzs.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CdleQSUU.js → index-Cj00JSqq.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-ByUjSWIg.js → index-Cm7vZvA3.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DbdMPF9D.js → index-CmMzB4C-.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-Ch0qsp2p.js → index-CxY_U5RT.js} +1 -1
  121. package/src/assets/web-panel/assets/index-Cxf0YfM5.js +1 -0
  122. package/src/assets/web-panel/assets/{index-BYE61P6D.js → index-D5Ei75Wt.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-OkiNUps8.js → index-DBzaRg4E.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BKYYncej.js → index-DFtzEEYe.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C52u0SKj.js → index-DGLbojjx.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D_65ERlZ.js → index-D_6XIMVV.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Byln7kVS.js → index-DddQd0_V.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CcZz24sL.js → index-DwZkBGXd.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-C5MHbkbK.js → index-DxJqyIP8.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CMScSzoi.js → index-Dy8K2laU.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BH067bfd.js → index-FAZH69my.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-y-TWtPEX.js → index-NdEUFm32.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DfsFQ-DX.js → index-P1ERNJla.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-CchNIYmQ.js → index-R0LQ3fgq.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-DCw8rGv8.js → index-UXM5vpt4.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-B1UsX4Hx.js → index-iif2A1eL.js} +1 -1
  137. package/src/assets/web-panel/assets/{index-C9uyUX6z.js → index-itNn6pW1.js} +1 -1
  138. package/src/assets/web-panel/assets/{initDefaultProps-DmksOjaL.js → initDefaultProps-DeMthvi4.js} +1 -1
  139. package/src/assets/web-panel/assets/{motion-Cb3y_Vsi.js → motion-_7kbkzE0.js} +1 -1
  140. package/src/assets/web-panel/assets/{move-DP-3qcfq.js → move-gCI04pLw.js} +1 -1
  141. package/src/assets/web-panel/assets/{mtc-parser-BCDUfUEO.js → mtc-parser-D5UWHv2U.js} +1 -1
  142. package/src/assets/web-panel/assets/{omit-MH-O2PY6.js → omit-CDCZcqeS.js} +1 -1
  143. package/src/assets/web-panel/assets/{pickAttrs-BaZORqPr.js → pickAttrs-DGMDLi3S.js} +1 -1
  144. package/src/assets/web-panel/assets/{placementArrow-Dkp_5tvw.js → placementArrow-C-3vC1Vh.js} +1 -1
  145. package/src/assets/web-panel/assets/{responsiveObserve-DBJSmMkS.js → responsiveObserve-vdoYucvi.js} +1 -1
  146. package/src/assets/web-panel/assets/{slide-Cc6qGIgj.js → slide-B62FhgyZ.js} +1 -1
  147. package/src/assets/web-panel/assets/{statusUtils-FundADw-.js → statusUtils-DCLlfnym.js} +1 -1
  148. package/src/assets/web-panel/assets/{styleChecker-qOO9jMdb.js → styleChecker-CGvQ4LRR.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFlexGapSupport-BYbRYwok.js → useFlexGapSupport-BqkGoKwe.js} +1 -1
  150. package/src/assets/web-panel/assets/{useFs-D6PqFBtt.js → useFs-Bkr_nU3q.js} +1 -1
  151. package/src/assets/web-panel/assets/{usePersonalDataHub-mJpur_zt.js → usePersonalDataHub-CYxMIUEq.js} +1 -1
  152. package/src/assets/web-panel/assets/{vnode-ZFVHKenK.js → vnode-sAbcY1FX.js} +1 -1
  153. package/src/assets/web-panel/assets/{zoom-Ca_KBv2o.js → zoom-Dm2pLrXi.js} +1 -1
  154. package/src/assets/web-panel/index.html +1 -1
  155. package/src/command-help-index.json +1 -1
  156. package/src/commands/agent.js +29 -0
  157. package/src/commands/ask.js +23 -23
  158. package/src/commands/chat.js +1 -5
  159. package/src/commands/session.js +92 -61
  160. package/src/commands/setup.js +35 -10
  161. package/src/commands/ui.js +18 -5
  162. package/src/constants.js +18 -89
  163. package/src/data/changelog.json +26 -0
  164. package/src/gateways/ws/action-protocol.js +22 -14
  165. package/src/gateways/ws/chat-intent-protocol.js +7 -3
  166. package/src/gateways/ws/llm-chat-protocol.js +9 -2
  167. package/src/gateways/ws/ws-server.js +24 -12
  168. package/src/lib/bm25-search.js +6 -3
  169. package/src/lib/chat-intent-service.js +28 -4
  170. package/src/lib/coding-task-guidance.js +6 -1
  171. package/src/lib/config-manager.js +49 -16
  172. package/src/lib/config-schema.js +5 -0
  173. package/src/lib/context-memory-kernel/memory-query-index.js +35 -17
  174. package/src/lib/evolution/evolution-deployment-config.js +48 -5
  175. package/src/lib/evolution/evolution-deployment-loader.js +26 -11
  176. package/src/lib/evolution/evolution-enabled.js +27 -0
  177. package/src/lib/evolution/governed-model-turn.js +4 -1
  178. package/src/lib/evolution/optional-ui-model-turn.js +26 -0
  179. package/src/lib/goal-check-evidence.js +159 -0
  180. package/src/lib/goal-condition-engine.js +24 -2
  181. package/src/lib/llm-connection-probe.js +48 -4
  182. package/src/lib/llm-onboarding-catalog.json +131 -0
  183. package/src/lib/paths.js +2 -2
  184. package/src/lib/skill-retrieval-router.js +2 -1
  185. package/src/lib/skill-search-tokenizer.js +143 -0
  186. package/src/repl/agent-repl.js +8 -4
  187. package/src/repl/chat-repl.js +15 -9
  188. package/src/runtime/agent-core.js +87 -7
  189. package/src/runtime/agent-runtime.js +18 -6
  190. package/src/runtime/headless-runner.js +138 -66
  191. package/src/runtime/headless-stream.js +1 -0
  192. package/src/runtime/mcp-tool-search-ranking.js +142 -0
  193. package/src/runtime/mcp-tool-search.js +198 -60
  194. package/src/assets/web-panel/assets/Artifacts-D50kNasl.js +0 -1
  195. package/src/assets/web-panel/assets/EvolutionSettings-BKWKDok5.js +0 -1
  196. package/src/assets/web-panel/assets/MarkdownRenderer-vialawkx.js +0 -1
  197. package/src/assets/web-panel/assets/devWarning-ChcomtaV.js +0 -1
  198. package/src/assets/web-panel/assets/index-CXxCC-4V.js +0 -1
  199. package/src/assets/web-panel/assets/index-CZYLUp6g.js +0 -1
@@ -1,6 +1,32 @@
1
1
  {
2
2
  "source": "CHANGELOG.md",
3
3
  "releases": [
4
+ {
5
+ "productVersion": null,
6
+ "cliVersion": "0.166.128",
7
+ "cliVersions": ["0.166.128"],
8
+ "date": "2026-10-27",
9
+ "title": "",
10
+ "sections": [
11
+ {
12
+ "heading": "Fixed - cc CLI 0.166.128: goal verification, tool discovery and memory queries (candidate, 2026-10-27)",
13
+ "body": "- Bind default goal evaluation to tool and artifact evidence, and stop automatic continuation when a reliable goal checkpoint cannot be saved.\n- Share new-connection model recommendations and protocol-aware probes across CLI and IDE integrations; retain existing model aliases and per-conversation model overrides.\n- Improve multilingual MCP and Skills descriptor discovery. Add an opt-in compact MCP provider catalog while retaining the full host execution ceiling, permission checks and revoked-schema handling.\n- Avoid unnecessary Memory posting unions when a narrower filter is already available. Preserve ordering, pagination, scope/sink filters, disk verification and generation-bound caches.\n- Add explicit headless `--review-changes` for a one-shot completion review after successful write/edit changes, with subsequent repairs inside the existing request and cost budgets. Suppress provisional text/thinking deltas and do not append review after incomplete usage. Default off; self-review is not independent task acceptance.\n- Retain published child package pins. Publish only through GitHub Actions OIDC after exact-source Linux, Windows and macOS CLI CI and Strict Sandbox pass; publish paired IDEs and clients only after upstream public readback.\n- Keep real task and billing acceptance separate from local synthetic benchmarks. Cumulative acceptance remains 32/45; NOT_PAID_READY / NOT_ADMITTED / HOLD remain."
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "productVersion": null,
19
+ "cliVersion": "0.166.127",
20
+ "cliVersions": ["0.166.127"],
21
+ "date": "2026-10-27",
22
+ "title": "",
23
+ "sections": [
24
+ {
25
+ "heading": "Added - cc CLI 0.166.127: optional self-evolution controls (2026-10-27)",
26
+ "body": "- Default fresh installations and older automatically generated local deployments to self-evolution off. Share the boolean `evolution.enabled` setting across CLI, cc ui, VS Code and JetBrains; explicit false overrides inherited deployment environment variables, while absent settings preserve manually selected deployments.\n- Enable and disable through configuration or deployment commands, initialize the local signed runtime on explicit enable, and retain deployment and trust history when disabled. Require a restart for running Agent sessions and reread the setting for new UI model requests.\n- Keep ordinary Agent, ask, chat, session resume and UI intent confirmation available while off. Retain strict signature and evidence checks for enabled deployments and prevent unrelated configuration writes from changing an absent Evolution choice.\n- Add shared configuration documentation and regression coverage. CLI 0.166.127 is public through OIDC after exact-source three-OS CLI CI and Strict Sandbox. Public Open VSX 0.37.165 and JetBrains 0.4.182 recommend .127; archive readback passed. Child dependency pins are unchanged. Microsoft Marketplace remains unpublished.\n- Publish mobile and PC v5.0.3.142 from frozen source c9881a2b71 after verified CLI and IDE releases. Five-platform builds, 22 public assets and three desktop updater metadata sets passed verification. No new live model-task acceptance: 32/45 accepted, 13 unfinished; NOT_PAID_READY / NOT_ADMITTED / HOLD remain.\n- Require exact-source Linux, Windows and macOS CLI CI and Strict Sandbox before GitHub Actions OIDC publication and public package readback. Automatic candidate promotion remains HOLD; this switch does not start a full RRSI campaign or claim new live model-task acceptance."
27
+ }
28
+ ]
29
+ },
4
30
  {
5
31
  "productVersion": null,
6
32
  "cliVersion": "0.166.126",
@@ -1,3 +1,5 @@
1
+ import { resolveServerEvolutionFactory } from "../../lib/evolution/optional-ui-model-turn.js";
2
+
1
3
  // Track running cowork tasks for cancellation
2
4
  const _runningTasks = new Map();
3
5
 
@@ -54,7 +56,7 @@ export async function handleCoworkTask(server, id, ws, message) {
54
56
  files,
55
57
  cwd: server.projectRoot || process.cwd(),
56
58
  llmOptions: {},
57
- evolutionCompositionFactory: server.evolutionCompositionFactory ?? null,
59
+ evolutionCompositionFactory: await resolveServerEvolutionFactory(server),
58
60
  signal: ac.signal,
59
61
  ...(message.mcpSessionId ? { mcpSessionId: message.mcpSessionId } : {}),
60
62
  ...(useParallel
@@ -205,8 +207,9 @@ export async function handleCoworkHistory(server, id, ws, message) {
205
207
 
206
208
  export async function handleCoworkTemplates(server, id, ws) {
207
209
  try {
208
- const { getTemplatesForUI } =
209
- await import("../../lib/cowork-task-templates.js");
210
+ const { getTemplatesForUI } = await import(
211
+ "../../lib/cowork-task-templates.js"
212
+ );
210
213
  const templates = getTemplatesForUI();
211
214
  server._send(ws, { id, type: "cowork:templates", templates });
212
215
  } catch (err) {
@@ -240,15 +243,16 @@ export async function handleOrchestrate(server, id, ws, message) {
240
243
  }
241
244
 
242
245
  try {
243
- const { Orchestrator, TASK_SOURCE } =
244
- await import("../../lib/orchestrator.js");
246
+ const { Orchestrator, TASK_SOURCE } = await import(
247
+ "../../lib/orchestrator.js"
248
+ );
245
249
 
246
250
  const orch = new Orchestrator({
247
251
  cwd: cwd || server.projectRoot || process.cwd(),
248
252
  maxParallel: Math.min(parseInt(agents, 10) || 3, 10),
249
253
  ciCommand: ci,
250
254
  agents: strategy ? { strategy } : undefined,
251
- evolutionCompositionFactory: server.evolutionCompositionFactory ?? null,
255
+ evolutionCompositionFactory: await resolveServerEvolutionFactory(server),
252
256
  verbose: false,
253
257
  });
254
258
 
@@ -389,8 +393,9 @@ async function _resolveWorkflowExecutionAuthority(server, sessionId) {
389
393
  }
390
394
  provider = descriptor.value;
391
395
  } else {
392
- ({ getVerifiedSessionExecutionLocationAuthority: provider } =
393
- await import("../../harness/jsonl-session-store.js"));
396
+ ({ getVerifiedSessionExecutionLocationAuthority: provider } = await import(
397
+ "../../harness/jsonl-session-store.js"
398
+ ));
394
399
  }
395
400
  if (typeof provider !== "function") {
396
401
  const error = new Error(
@@ -507,8 +512,9 @@ export async function handleWorkflowSave(server, id, ws, message) {
507
512
  );
508
513
  }
509
514
  try {
510
- const { getWorkflowRecord, validateWorkflow, saveWorkflow } =
511
- await import("../../lib/cowork-workflow.js");
515
+ const { getWorkflowRecord, validateWorkflow, saveWorkflow } = await import(
516
+ "../../lib/cowork-workflow.js"
517
+ );
512
518
  const result = validateWorkflow(workflow);
513
519
  if (!result.valid) {
514
520
  return _sendError(
@@ -595,8 +601,9 @@ export async function handleWorkflowRun(server, id, ws, message) {
595
601
  try {
596
602
  const { getWorkflowRecord, getWorkflowVersion, executeWorkflow } =
597
603
  await import("../../lib/cowork-workflow.js");
598
- const { executeDynamicWorkflowWithAdmission } =
599
- await import("../../lib/dynamic-workflow-facade.js");
604
+ const { executeDynamicWorkflowWithAdmission } = await import(
605
+ "../../lib/dynamic-workflow-facade.js"
606
+ );
600
607
  let workflowRunTask;
601
608
  if (Object.hasOwn(server, "workflowRunTask")) {
602
609
  const descriptor = Object.getOwnPropertyDescriptor(
@@ -608,8 +615,9 @@ export async function handleWorkflowRun(server, id, ws, message) {
608
615
  }
609
616
  workflowRunTask = descriptor.value;
610
617
  } else {
611
- ({ runCoworkTask: workflowRunTask } =
612
- await import("../../lib/cowork-task-runner.js"));
618
+ ({ runCoworkTask: workflowRunTask } = await import(
619
+ "../../lib/cowork-task-runner.js"
620
+ ));
613
621
  }
614
622
  if (typeof workflowRunTask !== "function") {
615
623
  throw new Error("Workflow task runner is unavailable");
@@ -17,6 +17,7 @@ import {
17
17
  classifyFollowupIntent,
18
18
  } from "../../lib/chat-intent-service.js";
19
19
  import { resolveLlmCreds } from "./llm-creds.js";
20
+ import { resolveServerEvolutionFactory } from "../../lib/evolution/optional-ui-model-turn.js";
20
21
 
21
22
  /**
22
23
  * Look up LLM creds for the intent flow.
@@ -60,7 +61,8 @@ export async function handleChatIntentUnderstand(server, id, ws, message) {
60
61
  contextMode: message.contextMode || "global",
61
62
  history,
62
63
  llmOptions,
63
- evolutionCompositionFactory: server.evolutionCompositionFactory ?? null,
64
+ evolutionCompositionFactory: await resolveServerEvolutionFactory(server),
65
+ prepareModelTurn: server.prepareUiModelTurn,
64
66
  });
65
67
  server._send(ws, {
66
68
  id,
@@ -118,7 +120,8 @@ export async function handleChatIntentUnderstandStream(
118
120
  contextMode: message.contextMode || "global",
119
121
  history,
120
122
  llmOptions,
121
- evolutionCompositionFactory: server.evolutionCompositionFactory ?? null,
123
+ evolutionCompositionFactory: await resolveServerEvolutionFactory(server),
124
+ prepareModelTurn: server.prepareUiModelTurn,
122
125
  })) {
123
126
  if (event.type === "token") {
124
127
  server._send(ws, {
@@ -171,7 +174,8 @@ export async function handleChatIntentClassifyFollowup(
171
174
  input,
172
175
  context: message.context || {},
173
176
  llmOptions,
174
- evolutionCompositionFactory: server.evolutionCompositionFactory ?? null,
177
+ evolutionCompositionFactory: await resolveServerEvolutionFactory(server),
178
+ prepareModelTurn: server.prepareUiModelTurn,
175
179
  });
176
180
  server._send(ws, {
177
181
  id,
@@ -180,7 +180,14 @@ export async function handleLlmChat(server, id, ws, message) {
180
180
  ws?.once?.("close", disconnect);
181
181
  try {
182
182
  const turn = await waitForChatPhase(
183
- prepareGovernedModelTurn(server.evolutionCompositionFactory ?? null, {
183
+ (
184
+ server.prepareUiModelTurn ||
185
+ ((context) =>
186
+ prepareGovernedModelTurn(
187
+ server.evolutionCompositionFactory ?? null,
188
+ context,
189
+ ))
190
+ )({
184
191
  mode: "ws-llm-chat",
185
192
  messages: message.messages,
186
193
  signal: controller.signal,
@@ -189,7 +196,7 @@ export async function handleLlmChat(server, id, ws, message) {
189
196
  "initialization",
190
197
  );
191
198
  const streamOptions = {
192
- requireCompletion: turn.governed,
199
+ requireCompletion: true,
193
200
  signal: controller.signal,
194
201
  };
195
202
  // Tell the browser the configured deadline even when waiting hints are
@@ -124,10 +124,7 @@ import {
124
124
  } from "./artifact-protocol.js";
125
125
  import { executionBroker } from "../../lib/process-execution-broker/index.js";
126
126
  import { collectWorkspacePluginBinSandboxPolicy } from "../../lib/plugin-runtime/bin.js";
127
- import {
128
- loadConfig,
129
- loadUserConfig,
130
- } from "../../lib/config-manager.js";
127
+ import { loadConfig, loadUserConfig } from "../../lib/config-manager.js";
131
128
 
132
129
  export const _deps = {
133
130
  spawn: (...args) => executionBroker.spawn(...args),
@@ -200,11 +197,9 @@ function boundedInteger(value, fallback, maximum = Number.MAX_SAFE_INTEGER) {
200
197
  }
201
198
 
202
199
  function loadCurrentLlmConfig() {
203
- const savedLlm =
204
- loadUserConfig({ failIfUnavailable: true }).llm || {};
200
+ const savedLlm = loadUserConfig({ failIfUnavailable: true }).llm || {};
205
201
  const resolvedLlm = loadConfig({ failIfUnavailable: true }).llm || {};
206
- const confirmedLlm =
207
- loadUserConfig({ failIfUnavailable: true }).llm || {};
202
+ const confirmedLlm = loadUserConfig({ failIfUnavailable: true }).llm || {};
208
203
  const provider =
209
204
  typeof savedLlm.provider === "string" && savedLlm.provider.trim()
210
205
  ? savedLlm.provider.trim()
@@ -378,6 +373,21 @@ export class ChainlessChainWSServer extends EventEmitter {
378
373
  }
379
374
  this.evolutionCompositionFactory =
380
375
  options.evolutionCompositionFactory || null;
376
+ if (
377
+ options.prepareUiModelTurn != null &&
378
+ typeof options.prepareUiModelTurn !== "function"
379
+ )
380
+ throw new TypeError("prepareUiModelTurn must be a function");
381
+ this.prepareUiModelTurn = options.prepareUiModelTurn || null;
382
+ if (
383
+ options.resolveEvolutionCompositionFactory != null &&
384
+ typeof options.resolveEvolutionCompositionFactory !== "function"
385
+ )
386
+ throw new TypeError(
387
+ "resolveEvolutionCompositionFactory must be a function",
388
+ );
389
+ this.resolveEvolutionCompositionFactory =
390
+ options.resolveEvolutionCompositionFactory || null;
381
391
  this.runtimeAdmissionDependencies =
382
392
  captureSkillRuntimeDependencies(options);
383
393
  this.skillOutcomeIndex =
@@ -827,8 +837,9 @@ export class ChainlessChainWSServer extends EventEmitter {
827
837
  /** Read the same static + scoped authority used by the Agent Core. */
828
838
  async _handlePermissionRulesGet(id, ws) {
829
839
  try {
830
- const { loadPermissionAuthority } =
831
- await import("../../lib/permission-authority.js");
840
+ const { loadPermissionAuthority } = await import(
841
+ "../../lib/permission-authority.js"
842
+ );
832
843
  const loaded = loadPermissionAuthority({ cwd: this.projectRoot });
833
844
  this._send(ws, {
834
845
  id,
@@ -1588,8 +1599,9 @@ export class ChainlessChainWSServer extends EventEmitter {
1588
1599
  /** @private — ping/pong heartbeat to detect dead connections */
1589
1600
  async _ensureTaskManager() {
1590
1601
  if (this._taskManager) return this._taskManager;
1591
- const { BackgroundTaskManager } =
1592
- await import("../../harness/background-task-manager.js");
1602
+ const { BackgroundTaskManager } = await import(
1603
+ "../../harness/background-task-manager.js"
1604
+ );
1593
1605
  this._taskManager = new BackgroundTaskManager({
1594
1606
  recoverOnStart: true,
1595
1607
  policyCwd: this.projectRoot,
@@ -129,11 +129,14 @@ export class BM25Search {
129
129
  * @param {number} [options.k1=1.5] - Term frequency saturation parameter
130
130
  * @param {number} [options.b=0.75] - Length normalization parameter
131
131
  * @param {string} [options.language="auto"] - Language for tokenization
132
+ * @param {function(string): string[]} [options.tokenizer] - Optional domain tokenizer
132
133
  */
133
134
  constructor(options = {}) {
134
135
  this.k1 = options.k1 || 1.5;
135
136
  this.b = options.b || 0.75;
136
137
  this.language = options.language || "auto";
138
+ this._tokenize =
139
+ options.tokenizer || ((text) => tokenize(text, this.language));
137
140
 
138
141
  // Index state
139
142
  this.documents = []; // Array of { id, tokens, originalDoc }
@@ -152,7 +155,7 @@ export class BM25Search {
152
155
 
153
156
  for (const doc of documents) {
154
157
  const text = [doc.title || "", doc.content || ""].join(" ");
155
- const tokens = tokenize(text, this.language);
158
+ const tokens = this._tokenize(text);
156
159
 
157
160
  this.documents.push({
158
161
  id: doc.id,
@@ -183,7 +186,7 @@ export class BM25Search {
183
186
  */
184
187
  addDocument(doc) {
185
188
  const text = [doc.title || "", doc.content || ""].join(" ");
186
- const tokens = tokenize(text, this.language);
189
+ const tokens = this._tokenize(text);
187
190
 
188
191
  this.documents.push({
189
192
  id: doc.id,
@@ -251,7 +254,7 @@ export class BM25Search {
251
254
 
252
255
  if (this.totalDocs === 0) return [];
253
256
 
254
- const queryTokens = tokenize(query, this.language);
257
+ const queryTokens = this._tokenize(query);
255
258
  if (queryTokens.length === 0) return [];
256
259
 
257
260
  const scores = [];
@@ -40,7 +40,13 @@ async function waitForIntentOperation(operation, signal) {
40
40
  }
41
41
  }
42
42
 
43
- async function* intentModelStream(messages, options, factory, mode) {
43
+ async function* intentModelStream(
44
+ messages,
45
+ options,
46
+ factory,
47
+ mode,
48
+ prepareModelTurn,
49
+ ) {
44
50
  const controller = new AbortController();
45
51
  const timeoutMs = resolveIntentTimeout(options);
46
52
  const timer =
@@ -57,7 +63,10 @@ async function* intentModelStream(messages, options, factory, mode) {
57
63
  let completed = false;
58
64
  try {
59
65
  const turn = await waitForIntentOperation(
60
- prepareGovernedModelTurn(factory, {
66
+ (
67
+ prepareModelTurn ||
68
+ ((context) => prepareGovernedModelTurn(factory, context))
69
+ )({
61
70
  mode,
62
71
  messages,
63
72
  signal: controller.signal,
@@ -87,13 +96,20 @@ async function* intentModelStream(messages, options, factory, mode) {
87
96
  }
88
97
  }
89
98
 
90
- async function intentModelText(messages, options, factory, mode) {
99
+ async function intentModelText(
100
+ messages,
101
+ options,
102
+ factory,
103
+ mode,
104
+ prepareModelTurn,
105
+ ) {
91
106
  let content = "";
92
107
  for await (const event of intentModelStream(
93
108
  messages,
94
109
  options,
95
110
  factory,
96
111
  mode,
112
+ prepareModelTurn,
97
113
  )) {
98
114
  if (event.type === "response-complete") content = event.content;
99
115
  }
@@ -213,6 +229,7 @@ export async function understandIntent({
213
229
  history,
214
230
  llmOptions,
215
231
  evolutionCompositionFactory = null,
232
+ prepareModelTurn,
216
233
  }) {
217
234
  if (!userInput || !userInput.trim()) {
218
235
  throw new Error("userInput required");
@@ -249,6 +266,7 @@ export async function understandIntent({
249
266
  },
250
267
  evolutionCompositionFactory,
251
268
  "intent-understand",
269
+ prepareModelTurn,
252
270
  );
253
271
 
254
272
  const jsonText = extractJson(fullContent);
@@ -297,6 +315,7 @@ export async function* understandIntentStream({
297
315
  history,
298
316
  llmOptions,
299
317
  evolutionCompositionFactory = null,
318
+ prepareModelTurn,
300
319
  }) {
301
320
  if (!userInput || !userInput.trim()) {
302
321
  throw new Error("userInput required");
@@ -321,7 +340,7 @@ export async function* understandIntentStream({
321
340
  let buffer = "";
322
341
  try {
323
342
  // Every model-backed intent stream uses an abortable per-call deadline and
324
- // authenticated composition; the rule-only path above stays local.
343
+ // host-selected Evolution policy; the rule-only path above stays local.
325
344
  for await (const event of intentModelStream(
326
345
  [
327
346
  { role: "system", content: systemPrompt },
@@ -330,6 +349,7 @@ export async function* understandIntentStream({
330
349
  { ...llmOptions, temperature: 0.3, maxTokens: 500 },
331
350
  evolutionCompositionFactory,
332
351
  "intent-understand-stream",
352
+ prepareModelTurn,
333
353
  )) {
334
354
  if (event.type === "response-token") {
335
355
  buffer += event.token;
@@ -575,6 +595,7 @@ async function llmBasedClassify(
575
595
  context,
576
596
  llmOptions,
577
597
  evolutionCompositionFactory,
598
+ prepareModelTurn,
578
599
  ) {
579
600
  const { systemPrompt, userPrompt } = buildFollowupPrompts(userInput, context);
580
601
  const fullContent = await intentModelText(
@@ -589,6 +610,7 @@ async function llmBasedClassify(
589
610
  },
590
611
  evolutionCompositionFactory,
591
612
  "intent-classify",
613
+ prepareModelTurn,
592
614
  );
593
615
  const jsonText = extractJson(fullContent);
594
616
  if (!jsonText) throw new Error("LLM response missing JSON");
@@ -618,6 +640,7 @@ export async function classifyFollowupIntent({
618
640
  context = {},
619
641
  llmOptions,
620
642
  evolutionCompositionFactory = null,
643
+ prepareModelTurn,
621
644
  }) {
622
645
  const startTime = Date.now();
623
646
  const ruleResult = ruleBasedClassify(input);
@@ -644,6 +667,7 @@ export async function classifyFollowupIntent({
644
667
  context,
645
668
  llmOptions,
646
669
  evolutionCompositionFactory,
670
+ prepareModelTurn,
647
671
  );
648
672
  return {
649
673
  ...llmResult,
@@ -3,7 +3,7 @@ export const CODING_TASK_QUALITY_GUIDANCE = `Coding task quality:
3
3
  - Read the actual implementation and its exported API before writing a caller or test. Check parameter order, return shapes, asynchronous lifecycle and fixture requirements against the source; an example in another directory can have different relative imports.
4
4
  - Keep progress explanations to one or two sentences. Once the relevant API and behavior are clear, make the next tool call; resolve a remaining uncertainty with a targeted read. Put implementation code directly in write/edit tool arguments instead of rehearsing the code or repeatedly analyzing the same source in ordinary assistant text.
5
5
  - Resolve each relative import from the destination file's directory. Read back the completed file and fix newDiagnostics from write/edit results before finishing. A successful write confirms persistence, not syntax, test execution or acceptance.
6
- - Regression tests need a working positive control and a negative control that exercises the requested behavior through the real production entry point. Assert observable effects; avoid mocks or alternate calls that bypass the behavior under test. Complete the current worker/request when testing cancellation and replacement.
6
+ - Before finishing a regression task, map each explicit acceptance requirement to a concrete fixture, production call path and observable assertion in the deliverable. Positive and negative controls must exercise the same requested behavior and differ in the intended condition. Resolve uncovered requirements with permitted tools, or report the specific gap. Avoid mocks or alternate calls that bypass the behavior under test. Complete the current worker/request when testing cancellation and replacement.
7
7
  - For boundary regressions, derive expected defaults, computed values and rejection rules from the implementation or the explicit requested contract. Inject mismatched, tampered or stale input through the real entry point while keeping other prerequisites valid; verify that the fixture reaches the intended check rather than failing during setup. Compare observable results with independent expected values or authoritative state, not a helper that merely recomputes the same result.
8
8
  - Trace rejection before asserting its aftermath: a request can be rejected before registration or persistence. Check whether state stays unchanged, a failed record is saved, or an event is emitted; do not assume every rejection creates a failed task. When testing attribution, verify independently recorded identities and provenance as well as message contents; identical text can still be attributed to the wrong source.
9
9
  - Use available execution tools for a focused check when permitted. When execution tools are unavailable, inspect imports, API contracts and fixtures using the available file tools, and clearly say that tests were not run. Never describe a read-back or static check as a passing test or end-to-end verification.
@@ -14,3 +14,8 @@ export const HERMETIC_CODING_SYSTEM_PROMPT = `You are a hermetic coding assistan
14
14
  ${CODING_TASK_QUALITY_GUIDANCE}
15
15
 
16
16
  Return a concise, evidence-based completion message within these tool limits.`;
17
+
18
+ /** Optional runtime follow-up; contains no task-specific acceptance information. */
19
+ export const CODING_CHANGE_REVIEW_PROMPT = `Runtime change review: the original user task, authorized scope, tools and remaining budgets still apply; this message grants no new permissions.
20
+ Before finishing, check the changed deliverable against each explicit requirement. For regression tests, identify the concrete fixture, actual production call path and observable assertion for each requirement. Confirm that positive and negative controls reach the intended behavior with valid prerequisites and differ in the intended condition. Similar field names and unrelated rejection paths do not establish coverage.
21
+ Use permitted tools to inspect and repair any gap. Run focused checks only when execution tools are available. If a requirement remains uncovered or a check cannot be run, report that specific limitation. This review is not evidence that tests or independent acceptance passed. Give a concise final answer when finished.`;
@@ -30,6 +30,16 @@ import {
30
30
  // `_deps.warn` to assert it fired.
31
31
  const _warnedConfigPaths = new Set();
32
32
  const _loadedSecretRefs = new Map();
33
+ const _implicitEvolutionDefaults = new WeakSet();
34
+
35
+ function trackImplicitEvolutionDefault(config, raw = {}) {
36
+ if (
37
+ raw.evolution?.enabled === undefined &&
38
+ config.evolution?.enabled === false
39
+ )
40
+ _implicitEvolutionDefaults.add(config.evolution);
41
+ return config;
42
+ }
33
43
  export const _deps = {
34
44
  createSecretStore: () => createSecretStore(),
35
45
  warn: (msg) => {
@@ -72,8 +82,11 @@ function assertNotSymbolicLink(target, label = "configuration path") {
72
82
  return stat;
73
83
  }
74
84
 
75
- function readConfigDocument({ failIfUnavailable = false } = {}) {
76
- const configPath = getConfigPath();
85
+ function readConfigDocument({
86
+ failIfUnavailable = false,
87
+ ...pathOptions
88
+ } = {}) {
89
+ const configPath = getConfigPath(pathOptions);
77
90
  if (!existsSync(configPath)) return {};
78
91
  try {
79
92
  assertNotSymbolicLink(configPath, "config.json");
@@ -182,9 +195,9 @@ function resolveSecretReferences(value, prefix = "", state = {}) {
182
195
  return value;
183
196
  }
184
197
 
185
- function restoreSecretReferences(config) {
198
+ function restoreSecretReferences(config, configPath = getConfigPath()) {
186
199
  const out = structuredClone(config);
187
- const prefix = `${getConfigPath()}\0`;
200
+ const prefix = `${configPath}\0`;
188
201
  for (const [cacheKey, saved] of _loadedSecretRefs) {
189
202
  if (!cacheKey.startsWith(prefix)) continue;
190
203
  const key = cacheKey.slice(prefix.length);
@@ -199,17 +212,21 @@ function restoreSecretReferences(config) {
199
212
  export function loadConfig({
200
213
  failIfUnavailable = false,
201
214
  resolveSecrets = true,
215
+ ...pathOptions
202
216
  } = {}) {
203
- const configPath = getConfigPath();
217
+ const configPath = getConfigPath(pathOptions);
204
218
  if (!existsSync(configPath)) {
205
- return { ...structuredClone(DEFAULT_CONFIG) };
219
+ return trackImplicitEvolutionDefault(structuredClone(DEFAULT_CONFIG));
206
220
  }
207
221
  try {
208
- const parsed = readConfigDocument({ failIfUnavailable });
222
+ const parsed = readConfigDocument({ ...pathOptions, failIfUnavailable });
209
223
  const effective = deepMerge(structuredClone(DEFAULT_CONFIG), parsed);
210
- return resolveSecrets
211
- ? resolveSecretReferences(effective, "", { configPath })
212
- : effective;
224
+ return trackImplicitEvolutionDefault(
225
+ resolveSecrets
226
+ ? resolveSecretReferences(effective, "", { configPath })
227
+ : effective,
228
+ parsed,
229
+ );
213
230
  } catch (err) {
214
231
  if (failIfUnavailable) {
215
232
  const error = new Error(
@@ -255,12 +272,12 @@ export function loadConfig({
255
272
  `Fix the JSON to restore them.${backupNote}\n`,
256
273
  );
257
274
  }
258
- return { ...structuredClone(DEFAULT_CONFIG) };
275
+ return trackImplicitEvolutionDefault(structuredClone(DEFAULT_CONFIG));
259
276
  }
260
277
  }
261
278
 
262
279
  export function saveConfig(config, options = {}) {
263
- const configPath = getConfigPath();
280
+ const configPath = getConfigPath(options);
264
281
  ensurePrivateDirectory(dirname(configPath), {
265
282
  applyWindowsAcl: true,
266
283
  failIfUnavailable: true,
@@ -276,7 +293,18 @@ export function saveConfig(config, options = {}) {
276
293
  const persisted =
277
294
  options.preserveSecretRefs === false
278
295
  ? structuredClone(config)
279
- : restoreSecretReferences(config);
296
+ : restoreSecretReferences(config, configPath);
297
+ // An inherited default must not become an explicit opt-out when unrelated
298
+ // settings are saved. Track the child object so top-level spreads preserve
299
+ // this distinction too; explicit writes via setConfigValue clear it.
300
+ if (
301
+ _implicitEvolutionDefaults.has(config.evolution) &&
302
+ persisted.evolution?.enabled === false
303
+ ) {
304
+ delete persisted.evolution.enabled;
305
+ if (Object.keys(persisted.evolution).length === 0)
306
+ delete persisted.evolution;
307
+ }
280
308
  assertSafeConfigObject(persisted);
281
309
  writeFileSync(tmp, JSON.stringify(persisted, null, 2) + "\n", {
282
310
  encoding: "utf-8",
@@ -390,7 +418,7 @@ export function setConfigValue(key, value, options = {}) {
390
418
  // `cc config set` invocations would otherwise each load, mutate, and write
391
419
  // back, silently losing one update. Configuration can carry credentials and
392
420
  // permission policy, so bounded lock failure must never write unlocked.
393
- const configPath = getConfigPath();
421
+ const configPath = getConfigPath(options);
394
422
  ensurePrivateDirectory(dirname(configPath), {
395
423
  applyWindowsAcl: true,
396
424
  failIfUnavailable: true,
@@ -398,9 +426,14 @@ export function setConfigValue(key, value, options = {}) {
398
426
  return withFileLock(
399
427
  configPath,
400
428
  () => {
401
- const config = loadConfig({ failIfUnavailable: true });
429
+ const config = loadConfig({
430
+ ...options,
431
+ failIfUnavailable: true,
432
+ });
402
433
  setNestedValue(config, key, parsedValue);
403
- saveConfig(config);
434
+ if (key === "evolution.enabled")
435
+ _implicitEvolutionDefaults.delete(config.evolution);
436
+ saveConfig(config, options);
404
437
  return config;
405
438
  },
406
439
  { failIfUnavailable: true },
@@ -22,6 +22,11 @@ const descriptor = (key, type, options = {}) => ({
22
22
  });
23
23
 
24
24
  const DESCRIPTORS = [
25
+ descriptor("evolution.enabled", "boolean", {
26
+ default: DEFAULT_CONFIG.evolution.enabled,
27
+ description:
28
+ "Enable optional self-evolution for new Agent sessions (off by default)",
29
+ }),
25
30
  descriptor("setupCompleted", "boolean", {
26
31
  default: DEFAULT_CONFIG.setupCompleted,
27
32
  description: "Whether initial CLI setup has completed",
@@ -125,31 +125,49 @@ export function matchesListQuery(row, query) {
125
125
  // before applying the remaining predicates; no full-record scan or top-k before
126
126
  // permission filtering. Recall uses these gates but retains kernel ranking.
127
127
  export function* selectQueryRows(index, query, after = null) {
128
- const candidates = [];
129
- const union = (field, keys) => {
128
+ let positions = null;
129
+ let shortest = index.rows.length;
130
+ const unions = [];
131
+ const consider = (posting) => {
132
+ if (posting.length < shortest) {
133
+ positions = posting;
134
+ shortest = posting.length;
135
+ }
136
+ };
137
+ const considerUnion = (field, keys) => {
130
138
  const lists = keys
131
139
  .map((key) => index.postings[field].get(key))
132
140
  .filter(Boolean);
133
- return lists.length < 2
134
- ? lists[0] || []
135
- : [...new Set(lists.flat())].sort((a, b) => a - b);
141
+ if (lists.length < 2) consider(lists[0] || []);
142
+ else unions.push(lists);
136
143
  };
137
144
  if (query.category)
138
- candidates.push(index.postings.category.get(query.category) || []);
145
+ consider(index.postings.category.get(query.category) || []);
139
146
  if (query.scopeAdmissions)
140
- candidates.push(
141
- union(
142
- "scope",
143
- query.scopeAdmissions.map((scope) =>
144
- scopeKey(scope.scope, scope.scopeId),
145
- ),
147
+ considerUnion(
148
+ "scope",
149
+ query.scopeAdmissions.map((scope) =>
150
+ scopeKey(scope.scope, scope.scopeId),
146
151
  ),
147
152
  );
148
- if (query.states) candidates.push(union("state", query.states));
149
- if (query.tags?.length) candidates.push(union("tag", query.tags));
150
- if (query.sink) candidates.push(union("sink", ["*", query.sink]));
151
- candidates.sort((a, b) => a.length - b.length);
152
- const positions = candidates[0];
153
+ if (query.states) considerUnion("state", query.states);
154
+ if (query.tags?.length) considerUnion("tag", query.tags);
155
+ if (query.sink) considerUnion("sink", ["*", query.sink]);
156
+ // A union cannot be shorter than its longest constituent. Inspect lengths
157
+ // before expanding broad permissions/tags when a selective posting exists.
158
+ // Stop building a union as soon as it cannot improve the current choice.
159
+ nextUnion: for (const lists of unions) {
160
+ if (shortest === 0) return;
161
+ if (lists.some((list) => list.length >= shortest)) continue;
162
+ const unique = new Set();
163
+ for (const list of lists) {
164
+ for (const position of list) {
165
+ unique.add(position);
166
+ if (unique.size >= shortest) continue nextUnion;
167
+ }
168
+ }
169
+ consider([...unique].sort((a, b) => a - b));
170
+ }
153
171
  const length = positions ? positions.length : index.rows.length;
154
172
  const rowAt = (offset) => index.rows[positions ? positions[offset] : offset];
155
173
  let start = 0;